Eventos de agarrar y soltar drag / drop
Para estos tipos de eventos es necesario crear áreas de actividad mediante estilos CSS y HTML. Sin embargo, los siguientes eventos solo funcionan con la interacción de puntero de mouse. Otros eventos sí admiten pantalla y acción táctil, como los touchEvents, contenidos en una API de Javascript.
Los siguientes eventos de acción con puntero de mouse solo funcionan como atributos de los elementos HTML.
En el código de abajo, un elemento HTML contiene un atributo ondragover
. Lo que significa que este elemento puede ser arrastrado por el puntero del mouse:
En HTML
<body>
<elementoHTML ondragover="true"...>
</body>
- ondrop:Activa evento cuando un elemento movible es seleccionado y soltado en el área destino.
- ondragover: Activa evento cuando una selección movible es arrastrado sobre el área destino.
- ondragstart: Activa evento cuando el usuario inicia el arrastre de un elemento movible.
- draggable: Booleano. True para activar selección de arrastre.
El siguiente ejemplo (solo para interacción con mouse) será comentado en sus partes:
En HTML
<!-- Elemento contenedor -->
<!-- ondrop="agarre()" permite
que se suelte y se agarre -->
<!-- Si quitamos evento ondrop
no se podrá soltar allí nada -->
<div class="rectang"
ondrop="agarre()"
ondragover="suelta()">
<!-- Elemento interno draggable.
Activo para drag. Activa función iniciaAgarre() -->
<!--Contiene eventos ondragstart y draggable -->
<!-- Contiene el id para estilos CSS -->
<div id="itemMovible"
ondragstart="iniciaAgarre()"
draggable="true">Mover</div>
</div>
<!-- Área destino. -->
<!-- Activa eventos ondrop y ondragover -->
<!-- Activa funciones agarre() y nDrop() -->
<div class="rectang"
ondrop="agarre()"
ondragover="suelta()"> 2 </div>
En Javascript
// Crea variable
let elementoDisparadorEvento;
function iniciaAgarre(){
/* Cuanto el evento se activa se guarda
en 'elementoDisparadorEvento' el elemento
que activó el evento */
elementoDisparadorEvento = event.target;
console.dir(elementoDisparadorEvento);
// Muestra: div#itemMovible
}
// Que es preventDefault??
function suelta(){
/* preventDefault() bloquea el NO
PERMITIR soltar un elemento desde HTML */
event.preventDefault();
}
function agarre(){
event.preventDefault();
/* Si el elemento disparador es clase rectang... */
if (event.target.className == "rectang"){
/* Al elemento disparador adjuntar el elemento disparador */
event.target.appendChild(elementoDisparadorEvento);
// Cambia color al soltarlo en área destino
document.getElementById("itemMovible").
style.backgroundColor="green";
// Cambia forma al soltarlo en área destino
document.getElementById("itemMovible").
style.borderRadius="50%";
}
}
En CSS
/* ESTILO CSS de ambas cajas */
.rectang{
height: 200px;
width: 200px;
padding: 20px;
margin: 0 50px;
display: inline-block;
border: 1px solid black;
background-color: ;
}
/* EstiloElemento movible */
#itemMovible{
width: 150px;
height: 150px;
background-color: orange;
borderRadius: 10px;
}
En otro ejemplo, el evento de arraste muestra un texto actualizado según el curso del evento:
En HTML
<!-- Elemento contenedor -->
<div class="areaDestino"
ondrop="soltar()"
ondragover="dejarSoltar()">
<!-- Arrastrable -->
<p ondragstart="iniciarArrastre()"
ondrag="arrastrando()"
draggable="true"
id="itemParaMover">X</p>
</div>
<!-- Sin este elemento no hay texto -->
<p id="demo"></p>
<div class="areaDestino"
ondrop="soltar()"
ondragover="dejarSoltar()"></div>
En Javascript
function iniciarArrastre() {
/* El método DataTransfer.setData()
establece los datos de arrastre.
- El primer argumento es el tipo de dato a
almacenar en el objeto drag.
- El segundo argumento representa
el dato a agregar al objeto drag. */
event.dataTransfer.setData("Text", event.target.id);
}
function arrastrando() {
document.getElementById("demo").innerHTML = "Elemento movido";
}
function dejarSoltar() {
// Permite que browser deje soltar elemento
event.preventDefault();
}
function soltar() {
// Permite que brows
event.preventDefault();
/* El objeto DataTransfer se utiliza
para contener los datos que se arrastran
durante una operación de arrastrar y colocar */
const data = event.dataTransfer.getData("Text");
event.target.appendChild(document.getElementById(data));
document.getElementById("demo").innerHTML = "Elemento soltado";
}
En CSS
/* Estilo area destino */
.areaDestino {
width: 100px;
height: 100px;
padding: 10px;
border: 1px solid black;
}
/* Estilo item movible */
#itemParaMover{
width: 80%;
height: 80%;
background-color: pink;
font-size: 40px;
margin: 0 0px;
}
- Método dataTransfer.setData(): establece los datos de arrastre. Por ejemplo, añade un id del elemento <p> hacia el objeto DataTransfer. Cuando el evento soltar se activa, se recupera el id y lo usamos para mover el elemento <p> hacia el área destino. - El primer argumento es el tipo de dato a almacenar en el objeto drag. - El segundo argumento representa el dato a agregar al objeto drag.
- Método DataTransfer.getData(): Recupera el string de un objeto drag pero retorna string vacio. Su argumento es un string que representa el dato a recuperar.
COMBINACIÓN DE EVENTOS DRAG -dragtarget,
drag / drop
Cuando las áreas de destino activan un evento cuando los eventos drag se activan:
En HTML
<!-- Contenedor -->
<div class="areaInicio">
<!-- Objeto movible con evento 'draggable' -->
<p draggable="true" id="objetoMovible">XXXXX</p>
</div>
<p>INICIA TODO</p>
<div class="areaInicio"></div>
<!-- Texto pendiente que se altera luego -->
<p id="pendiente"></p>
En Javascript
/* = = = = = RECORDAR = = = = =
event.target siempre obtiene los datos
del elemento a arrastrar */
/* Eventos activan */
document.addEventListener("dragstart", function( ) {
/* El método dataTransfer.setData() establece el tipo de datos
y el valor de los datos arrastrados */
event.dataTransfer.setData("Text", event.target.id);
/* Salida de texto al comenzar a arrastrar el elemento 'p' */
document.getElementById("pendiente").
innerHTML = "Inicia arrastre...";
/* Cambiar la opacidad del elemento arrastrable */
event.target.style.opacity = "0.8";
});
/* Mientras arrastra el elemento 'p',
cambie el color del texto de salida */
document.addEventListener("drag", function( ) {
document.getElementById("pendiente").style.color = "red";
});
/* Genere algo de texto cuando termine de arrastrar
el elemento p y restablezca la opacidad */
document.addEventListener("dragend", function( ) {
document.getElementById("pendiente").
innerHTML = "Finaliza arrastre...";
/* Toma el elemento arrastable */
event.target.style.opacity = "1";
/* Obtiene el elemento con el ID 'pendiente' y
accede al estilo de 'ancho' */
document.getElementById("pendiente").
style.width = "100px";
document.getElementById("pendiente").
style.heigth = "100px";
document.getElementById("pendiente").
style.backgroundColor = "red";
document.getElementById("pendiente").
style.color = "white";
});
/* Eventos disparados contra el objetivo de caída */
/* Cuando el elemento p arrastrable entre en el areaInicio,
cambie el estilo de borde del DIVS */
document.addEventListener("dragenter", function( ) {
if ( event.target.className == "areaInicio" ) {
event.target.style.border = "3px solid red";
}
});
/* De forma predeterminada, los datos/elementos no se
pueden quitar en otros elementos. Para permitir una
caída, debemos evitar el manejo predeterminado del
elemento */
document.addEventListener("dragover", function( ) {
event.preventDefault();
});
/* Cuando el elemento p arrastrable abandone el
areaInicio, restablezca el estilo de borde del DIVS */
document.addEventListener("dragleave", function( ) {
if ( event.target.className == "areaInicio" ) {
event.target.style.border = "";
}
});
/* On drop - Evitar el manejo predeterminado del
navegador de los datos (el valor predeterminado está
abierto como enlace en drop). Restablecer el color del
texto de salida y el color del borde del DIV. Obtenga los
datos arrastrados con el método dataTransfer.getData()
Los datos arrastrados son el identificador del elemento
arrastrado ("drag1"). Anexar el elemento arrastrado
al elemento de colocación */
document.addEventListener("drop", function( ) {
event.preventDefault();
if ( event.target.className == "areaInicio" ) {
document.getElementById("pendiente").style.color = "";
/* Estilo cuando se finalice drop */
event.target.style.border = "";
var data = event.dataTransfer.getData("Text");
event.target.appendChild(document.getElementById(data));
}
});
En CSS
/* Los dos recuadros tienen este estilo*/
.areaInicio {
width: 100px;
height: 120px;
padding: 5px;
border: 1px solid black;
}
#objetoMovible{
width: 90px;
height: 90px;
background-color: pink;
}
ANIMANDO ELEMENTOS
drag / drop
Para activar animaciones cuando se ejecuta una acción de click. En el ejemplo inferior se tiene un botón y un recuadro rojo. Al activar el botón se ejecuta la función 'moverCuadro(){}' que a su vez aloja una función 'setInterval( .. )' y que a su vez aloja una función de intervalo. Esta función 'setInterval()' obliga a ejecutar código cuando un lapso de tiempo ha ocurrido.
Explico aquí tres funciones útiles cuando deseamos controlar intervalos de tiempo: setInterval()
, setTimeout()
y clearInterval()
:
Función setInterval()
Itera un código dado dentro de la función, y define el rango de milisegundos que ese código será iterado.
En Consola
setInterval(() => console.log('holi Dudú'), 1000);
/* La palabra 'holi' será mostrada cada 5 segundos en consola */
// == OJO > Un salto a la línea de => hará que no funcione
Función setTimeout()
Ejecuta un código interno cuando ya ha transcurrido un lapso de milisegundos dados.
En Consola
setTimeout(() => {
console.log("Ya pasaron tres segundos");
}, 3000);
/* Se mostrará en consola 'Ya pasaron tres segundos'
luego de tres segundos */
Función clearInterval()
Es usado en complemento a setInterval()
. Cuando la función clearInterval()
es activada dentro de setInterval()
detiene la iteración de un código dado.
En Javascript
/* Conteo mostrará mensaje luego de 3 segundos */
var conteoOk = setInterval(() =>
console.log('holi Dudú'),
3000);
// Detener y mostrar luego de 6 segundos
setTimeout(() => { clearInterval(conteoOk);
console.log('Han pasado 3 segundos');
}, 6000);
- EN RESUMEN
setInterval()
..ejecuta código según un lapsosetTimeout()
..espera un lapso y ejecutaclearInterval()
..cancela código luego de un lapso dado en alguna de la funciones anteriores.
Otra combinación:
En Javascript
// Valor
var num = 1;
// Método que suma
function sumarOki()
{console.log (2 + num);
num++;
// Incrementa
}
/* Aloja un rango de intervalo,
y lo mostrará cada segundo */
var iterarOki = setInterval(sumarOki, 1000);
// === USANDO CLEAR-INTERVAL()
setTimeout(function() {
// Cancela intervalo
clearInterval(iterarOki);
console.log('Ya pasaron 5 segundos');
}, 5000);
Por otro lado, presentamos un ejercicio que combina las tres funciones es el siguiente:
En HTML
<!-- Se crea elemento boton --->
<button onclick="moverCuadro()"> Ir a la derecha </button>
<!-- Se crea elemento cuadro --->
<div id="cuadro"></div>
<p id="elemento"></p>
En Javascript
function moverCuadro(){
// Nueva variable 'b' aloja el elemento con ID 'cuadro'*/
let b = document.getElementById("cuadro");
/* variable vector 'x' dirige hacia adelante */
let x = 0;
/* variable vector 'm' dirige hacia abajo */
let m = 10;
setInterval(function() {
// Condicional. Si 'x' pasa de cero a 200...
if (x === 200){
// Limpiar duración de intervalo
clearInterval();
/* Pero si 'x' no pasa de 200. Es decir,
mientras el valor de 'x' sea menor a 200 */
} else {
// Incrementa el valor actual de 'x' en una unidad
x++;
/* OJO AQUÍ: Se apunta a la variable 'b',
se ingresa a las reglas de CSS,
se añade propiedad 'left'
Y SE ADJUNTA (NO SE SUMA)... */
b.style.left = x + "px";
/* Altera posición desde arriba,
incrementa dirección */
b.style.top = m++ + "px";
}
/* El intervalo debe durar 1 MILISEGUNDO.
Es decir, el cuadro se moverá cada milisegundo.
Si agregamos el valor de 1000 (un segundo,
entonces el cuadro se moverá cada segundo) */
}, 1);
}
En CSS
/* Todo 'div' tiene estas reglas */
div{
background-color: red;
width: 100px;
height: 100px;
/* Para que el elemento se coloque
en la esquina superior izquierda,
y permita reglas de posicionamiento top, left, etc... */
position: absolute;
}
En otras palabras, la estructura que se siguó para anidar las funciones fue:
En Javascript
function moverCuadro(){
// variables
/* document.getElementById... para apuntar
al elemento div que deseamos alterar */
setInterval(function() {
// condicional: siempre que el valor de 'x'
// NO SEA IGUAL a la una distancia en pixeles dada
if(/*condicion*/){
clearInterval();
} else {
// Incrementar 'x' y añadir un valor nuevo
// Apuntar a valores y agregarles pixel
}
}
}
REGISTRAR ACTIVIDAD DE LOS ELEMENTOS AL SER CLICKEADOS
pendiente...