teclas teclado tecla retroceso pulsada eventos detectar combinacion javascript html css dom keyboard

retroceso - eventos del teclado javascript



cómo manejar las combinaciones de teclas javascript considerando un contexto de capa apilada? (3)

Digamos que tengo un <body> con un full modal abierto. Este modal se puede cerrar presionando la tecla [ESC] . Dentro de este modo full modal , el usuario puede abrir otro modal más pequeño, que también se puede cerrar presionando la tecla [ESC] . ¿Cómo se maneja la tecla [ESC] y se cierra la capa "superior", lo que impide que la pulsación de tecla se propague y cierre las otras capas que están escuchando la pulsación de tecla?

Estoy esperando una respuesta directa, usando preventDefault o algo similar ... No estoy considerando configurar algún tipo de servicio que haga muchos controles antes de decidir qué capa debe cerrarse. Para mí, esto debería funcionar como eventos de clics. , propagándose hacia arriba ¿Es esto factible?


No existe un .preventDefault() directo o algo de magia negra que evite bloquear el burbujeo de un detector de eventos a menos que vayas a crear un nuevo controlador cada vez que quieras adjuntar un detector de eventos específicamente para ese modal que no interfiera con los otros controladores .

En lugar de tener una variedad de controladores y muchos oyentes de eventos, ¿por qué no apilar los modales dentro de una matriz y luego destruirlos uno por uno?

Este es el código más corto que se me ocurre, vea los comentarios dentro del código para una explicación paso a paso.

// Global variable, we use this to store DOM objects. var modalStack = []; // My function to create/open my modals. function openModal() { var modalHTML = ''<div id="modal-''+modalStack.length+''" class="modal"><button onclick="openModal()">Open modal ''+(modalStack.length+1)+''</button></div>''; // I populate the modal with my stuff and assign it an ID containing the current stack size. document.body.insertAdjacentHTML( ''beforeend'', modalHTML ); // Add into the body modalStack.push( document.getElementById(''modal-''+modalStack.length) ); // And push my DOM object I just created into the array. } // My ESC event listener window.addEventListener(''keyup'', function(event) { var lastIndex = modalStack.length-1; // This gets the last element on the stack. if (event.keyCode == 27 && lastIndex >= 0) { var thisModal = modalStack[ lastIndex ]; // Just to make sense, I could''ve called the removeChild directly from the array. thisModal.parentNode.removeChild(thisModal); // Destroy the current element. modalStack.pop(); // Remove the associated last DOM object from the array. } }, false);

jsFiddle Demo


Podemos resolver esto utilizando la estructura de datos Stack , que se puede usar para mantener los estados de las ventanas modales que se crean y eliminan.

El modal más alto será el Top / Head de la pila, que se eliminará primero al escapar. A continuación se muestra una demostración simple de cómo esto puede implementarse.

Por último, no hay necesidad de un esfuerzo adicional para crear la implementación de la pila, JavaScript Array tiene incorporado pop método push y pop , y haremos uso de aquellos en la implementación a continuación.

var Modal = (function() { //Just to give different margins for each modal var BASE_MARGIN = 20; //STACK, in this array we will store all modals var modalStack = []; //Creates all DOM and attach it to document''s body function createModal() { var modal = document.createElement(''div''); modal.className = ''modal''; modal.style.margin = ((modalStack.length + 1) * BASE_MARGIN) + ''px''; var header = document.createElement(''div''); header.className = ''modalHeader''; header.innerHTML = ''Level-'' + (modalStack.length + 1); var close = document.createElement(''div''); close.className = ''closeModal''; close.innerHTML = ''X''; close.addEventListener("click", function() { var index = modalStack.indexOf(modal); for(var i = modalStack.length - 1; i >= index; i--) { var div = modalStack.pop(); //no need of i, because pop will always get the last element document.body.removeChild(div); } }); header.appendChild(close); var createModalButton = document.createElement(''button''); createModalButton.className = ''createButton''; createModalButton.addEventListener("click", createModal); createModalButton.innerHTML = "Create Modal"; modal.appendChild(header); modal.appendChild(createModalButton); document.body.appendChild(modal); modalStack.push(modal); } /** * Should be called on dom-loaded */ function initialize() { document.addEventListener("keyup", function(ev) { if (ev.keyCode == 27) { // escape key maps to keycode `27` var div = modalStack.pop(); document.body.removeChild(div); } }); } return { createModal : createModal, initialize: initialize } })();

div.modal { position: fixed; top: 0px; bottom: 0px; left: 0px; right: 0px; margin:20px; z-index = 100; background-color: #fff; border: 2px solid #333; } button.createButton { display: block; margin: auto; margin-top: 4px; } .modalHeader { background-color: lightsteelblue; border-bottom: 1px solid #555; color: white; padding: 6px 6px 6px 24px; } .closeModal { color: red; cursor: pointer; display: inline-block; float: right; margin-right: 14px; }

<html> <head> </head> <body onload="Modal.initialize();"> <!-- Initial button to create child modals --> <input style="margin:50px 200px" class="createButton" type="button" onclick="Modal.createModal();" value="Create Modal" /> </body> </html>

Como tenemos control sobre todas las ventanas modales, podemos cambiar la opacidad de otros modos o hacer que el modal modal se muestre / oculte según la creación o eliminación de una nueva ventana, como se muestra a continuación.

var Modal = (function() { //Just to give different margins for each modal var BASE_MARGIN = 20; //STACK, in this array we will store all modals var modalStack = []; //Creates all DOM and attach it to document''s body function createModal() { var modal = document.createElement(''div''); modal.className = ''modal''; modal.style.margin = ((modalStack.length + 1) * BASE_MARGIN) + ''px''; var header = document.createElement(''div''); header.className = ''modalHeader''; header.innerHTML = ''Level-'' + (modalStack.length + 1); var close = document.createElement(''div''); close.className = ''closeModal''; close.innerHTML = ''X''; close.addEventListener("click", function() { var index = modalStack.indexOf(modal); for(var i = modalStack.length - 1; i >= index; i--) { var div = modalStack.pop(); if(modalStack.length > 0) modalStack[modalStack.length - 1].style.display = ''block''; //no need of i, because pop will always get the last element document.body.removeChild(div); } }); header.appendChild(close); var createModalButton = document.createElement(''button''); createModalButton.className = ''createButton''; createModalButton.addEventListener("click", createModal); createModalButton.innerHTML = "Create Modal"; modal.appendChild(header); modal.appendChild(createModalButton); document.body.appendChild(modal); if(modalStack.length > 0) modalStack[modalStack.length - 1].style.display = ''none''; modalStack.push(modal); } /** * Should be called on dom-loaded */ function initialize() { document.addEventListener("keyup", function(ev) { if (ev.keyCode == 27) { // escape key maps to keycode `27` var div = modalStack.pop(); document.body.removeChild(div); if(modalStack.length > 0) modalStack[modalStack.length - 1].style.display = ''block''; } }); } return { createModal : createModal, initialize: initialize } })();

div.modal { position: fixed; top: 0px; bottom: 0px; left: 0px; right: 0px; margin:20px; z-index = 100; background-color: #fff; border: 2px solid #333; } button.createButton { display: block; margin: auto; margin-top: 4px; } .modalHeader { background-color: lightsteelblue; border-bottom: 1px solid #555; color: white; padding: 6px 6px 6px 24px; } .closeModal { color: red; cursor: pointer; display: inline-block; float: right; margin-right: 14px; }

<html> <head> </head> <body onload="Modal.initialize();"> <!-- Initial button to create child modals --> <input style="margin:50px 200px" class="createButton" type="button" onclick="Modal.createModal();" value="Create Modal" /> </body> </html>


La forma más fácil en que puedo pensar pf, usando solo JS:

function openModalOnTop(modalHtml) { $modalsContainer = document.getElementById("modalscontainer"); var modalContainerTemplate = document.createElement("div"); modalContainerTemplate.className = "modal"; modalContainerTemplate.innerHTML = modalHtml; $modalsContainer.appendChild(modalContainerTemplate); } function closeTopModal() { $modalsContainer = document.getElementById("modalscontainer"); $modalsContainer.lastChild.remove(); } window.addEventListener(''keyup'', function(event) { if (event.keyCode == 79) { console.log("open"); openModalOnTop("someHTMLHere"); } }, false); window.addEventListener(''keyup'', function(event) { if (event.keyCode == 27) { console.log("close"); closeTopModal(); } }, false);

.modal { position: fixed; top: 0; right: 0; bottom: 0; left: 0; background: rgba(0,0,0,0.2); }

<div id="modalscontainer"></div>

Abrir con la tecla o, cerrar con la tecla esc.