/* By Bo Ericsson, https://www.linkedin.com/in/boeric00/ */ /* eslint-disable func-names, wrap-iife, no-plusplus, no-param-reassign, no-bitwise */ // Id generator (a demo of iife, generator function, and closure) // Outer iife to define the getId function, which returns an ever increasing integer // with each call const getId = (() => { // Inner iife to run the generator function which returns 'id', a generator object const id = (function* () { let i = 0; while (true) { yield i++; } })(); // The 'id' generator is locked inside the outer iife's closure return () => id.next().value; })(); // Returns an array of specified size with values incrementing from 0 function range(length) { const array = []; for (let i = 0; i < length; i++) { array.push(i); } return array; } // Zone colors (used to pick colors for the object generated in each zone) const zoneColors = ['blue', 'green', 'orange', 'darkred']; // Obtain references to the four zones const zones = document.querySelectorAll('.zone'); // Drag handlers let source; // Contains a reference to the item being dragged // Triggers when an item starts being dragged function ondragstart(evt) { // Add the 'dragging' class from the item being moved this.classList.add('dragging'); // Save a reference to the item being dragged source = this; evt.dataTransfer.effectAllowed = 'move'; } function ondragover(evt) { evt.preventDefault(); } function ondragenter(evt) { if (evt.target.classList.contains('zone')) { // Add the 'droppable' class of the zone element evt.target.classList.add('droppable'); } evt.preventDefault(); } function ondragleave(evt) { if (evt.target.classList.contains('zone')) { // Remove the 'droppable' class of the zone element evt.target.classList.remove('droppable'); } } function ondrop(evt) { // Remove the 'dragging' class from the item being moved source.classList.remove('dragging'); if (evt.target.classList.contains('zone')) { // Remove the 'droppable' class of the zone element evt.target.classList.remove('droppable'); // Move the item evt.target.appendChild(source); } evt.preventDefault(); } // Create items zones.forEach((zone, zoneIdx) => { // Add handlers for the zone's drag events zone.ondragenter = ondragenter; zone.ondragover = ondragover; zone.ondragleave = ondragleave; zone.ondrop = ondrop; // Determine items to create in this zone (min 1, max 7) const items = ~~(Math.random() * 7) + 1; range(items).forEach((idx) => { // Create the element const elem = document.createElement('div'); // Generate the text for the element const text = `${zoneIdx}-${idx}`; elem.innerHTML = text; // Determine type (circle or square randomly) const type = Math.random() > 0.5 ? 'circle' : 'square'; elem.className = `item ${type} color-${zoneColors[zoneIdx]}`; // Set the element id (not necessary but demos, when inspected, // that items actually move, not just the innerHTML) elem.id = getId(); // Enable dragging elem.draggable = true; // Handler to kickstart the dragging process elem.ondragstart = ondragstart; // Append the item to the zone zone.appendChild(elem); }); });