duduromeroa.com

#Javascript, #DOMJs, #webinteractiva, #Interfaces, #duduromeroa, #Guayaquil

Javascript

Programación para web con Javascript,API DOM 5: event.preventDefault(), event.target, event.dataTransfer.setData(), setInterval(), setTimeout(), clearInterval()


George Póyla, matemático. Resolver problemas de diseño. www.duduromeroa.com

Por Eduardo J. Romero Andrade
| Guayaquil

Contacto duduromeroa@gmail.com



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;
}

xxxx
xxxx

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 lapso
  • setTimeout()..espera un lapso y ejecuta
  • clearInterval()..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...


BIBLIOGRAFÍA:
    3ra edición. 2018. Marijn Haverbeke. No starch press.
    [2] MDN Web Docs, Javascript. Mozilla Foundation.
    David Flanagan (2020). Editorial O'Reilly.
    Ved Antani, Stoyan Stefanov (2017). Packt Publishing.
    Editorial Packt.
    Information and Computation. Elsevier.
    ACM SIGCSE