Drag and Drop data not being retained in dataTransfer object - javascript

I am trying to implement a simple drag and drop, but for some reason the data I'm storing in the dataTransfer object is not being retained. Here is my code:
function drag(ev) {
var checker_id = ev.target.id;
var checker_slot = ev.target.getAttribute('data-slot');
console.log(`Starting drag with ${checker_id} from slot ${checker_slot}`);
ev.originalEvent.dataTransfer.setData("checker-id", ev.target.id);
ev.originalEvent.dataTransfer.setData("checker-slot", ev.target.getAttribute('data-slot'));
var stored_id = ev.originalEvent.dataTransfer.getData("checker-id");
var stored_slot = ev.originalEvent.dataTransfer.getData("checker-slot");
console.log(`Just stored checker ${stored_id} from slot ${stored_slot}`);
}
function drag_over(ev) {
console.log(`Drag_over event data: ${ev.originalEvent.dataTransfer.types}`);
var checker_id = ev.originalEvent.dataTransfer.getData("checker-id");
var checker_slot = ev.originalEvent.dataTransfer.getData("checker-slot");
console.log(`Drag_over with checker ${checker_id} from slot ${checker_slot}`);
}
$("#checker-1").on('dragstart', drag);
$("#slot-2").on('dragover', drag_over);
.slot {
width: 100px;
height: 100px;
margin: 100px;
border: 2px solid black;
}
.checker {
width: 50px;
height: 50px;
background: blue;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js" integrity="sha256-hlKLmzaRlE8SCJC1Kw8zoUbU8BxA+8kR3gseuKfMjxA=" crossorigin="anonymous"></script>
<div class="slot" id="slot-1">
<div class="checker" id="checker-1" data-slot="slot-1" draggable="true">
</div>
<div class="slot" id="slot-2"></div>
I would expect the output to the console to be the following:
Starting drag with checker-1 from slot slot-1
Just stored checker checker-1 from slot slot-1
Drag_over event data: checker-id,checker-slot
Drag_over with checker checker-1 from slot slot-1
Instead, the last log statement is:
Drag_over with checker from slot
For some reason, it's retaining the keys I store in the dataTransfer object but not the values. I can't figure out what I'm doing wrong.

I noticed you were missing a DIV close tag. This corrected code appears to work:
function drag(ev) {
var checker_id = ev.target.id;
var checker_slot = ev.target.getAttribute('data-slot');
console.log(`Starting drag with ${checker_id} from slot ${checker_slot}`);
ev.originalEvent.dataTransfer.setData("checker-id", ev.target.id);
ev.originalEvent.dataTransfer.setData("checker-slot", ev.target.getAttribute('data-slot'));
var stored_id = ev.originalEvent.dataTransfer.getData("checker-id");
var stored_slot = ev.originalEvent.dataTransfer.getData("checker-slot");
console.log(`Just stored checker ${stored_id} from slot ${stored_slot}`);
}
function drag_over(ev) {
console.log(`Drag_over event data: ${ev.originalEvent.dataTransfer.types}`);
var checker_id = ev.originalEvent.dataTransfer.getData("checker-id");
var checker_slot = ev.originalEvent.dataTransfer.getData("checker-slot");
console.log(`Drag_over with checker ${checker_id} from slot ${checker_slot}`);
}
$("#checker-1").on('dragstart', drag);
$("#slot-2").on('dragover', drag_over);
.slot {
width: 100px;
height: 100px;
margin: 100px;
border: 2px solid black;
}
.checker {
width: 50px;
height: 50px;
background: blue;
}
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.min.js" integrity="sha256-hlKLmzaRlE8SCJC1Kw8zoUbU8BxA+8kR3gseuKfMjxA=" crossorigin="anonymous"></script>
<div class="slot" id="slot-1">
<div class="checker" id="checker-1" data-slot="slot-1" draggable="true">
</div>
</div>
<div class="slot" id="slot-2"></div>
You might also consider the following.
$(function() {
$(".checker").draggable();
$(".slot").droppable({
accept: ".checker",
drop: function(event, ui) {
ui.draggable.appendTo(this).attr("style", "");
console.log("Got " + ui.draggable.attr("id"));
}
});
});
.slot {
width: 100px;
height: 100px;
margin: 100px;
border: 2px solid black;
}
.checker {
width: 50px;
height: 50px;
background: blue;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.13.0/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.6.0.js"></script>
<script src="https://code.jquery.com/ui/1.13.0/jquery-ui.js"></script>
<div class="slot" id="slot-1">
<div class="checker" id="checker-1" data-slot="slot-1" draggable="true">
</div>
</div>
<div class="slot" id="slot-2"></div>

Related

Check if DOM elements are present inside a DIV then run functions assigned to those elements in order

i'm trying to develop a game using html, css and js. At the moment I'm focusing on manipulating DOM elements without using the canvas tag. My idea is to create a pseudo graphical programming language, similar to the Blockly environment. So far I have inserted 3 clickable elements inside #toolbox that create their copies in #workspace.
Now, I am trying to assign functions to the elements present in #workspace, which once pressed the Run button are executed in order of appearance, so as to create a queue of commands that is able to move the pink square inside #output_section.
Therefore I cannot understand how to write the function that is able to verify the presence of the elements and then be able to perform the different functions assigned to these elements.
Any ideas? :D
I'm using Jquery 3.3.1
function addRed() {
var redWorkspace = document.createElement("DIV");
redWorkspace.className = "remove-block block red";
document.getElementById("workspace").appendChild(redWorkspace);
};
function addBlue() {
var blueWorkspace = document.createElement("DIV");
blueWorkspace.className = "remove-block block blue";
document.getElementById("workspace").appendChild(blueWorkspace);
};
function addGreen() {
var greenWorkspace = document.createElement("DIV");
greenWorkspace.className = "remove-block block green";
document.getElementById("workspace").appendChild(greenWorkspace);
};
$("#clear_workspace").click(function () {
$("#workspace").empty();
});
$(document).on("click", ".remove-block", function () {
$(this).closest("div").remove();
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
bottom: 0;
right: 0;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<html>
<body>
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div onclick="addRed()" class="block red">Left</div>
<div onclick="addBlue()" class="block blue">Up</div>
<div onclick="addGreen()" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>
</body>
</html>
Completely untested but run button does something along the lines of:
$("#run_workspace").click(function() {
$("#workspace .block").each(function(elem) {
if (elem.hasClass("red")) {
moveObjectLeft();
} else if (elem.hasClass("green")) {
moveObjectRight();
} else if (elem.hasClass("blue")) {
moveObjectUp();
}
});
});
Commonly, it's a good idea to store all required information in arrays and objects, and use HTML only to display your data.
Also, if you are already using jQuery - use it for all 100%)
Made some improvements:
let mobs = {
pinky: {
node: $('#moving_square'),
coors: { top: 400, left: 400 },
step: 30,
moveQueue: [],
// moveTimeout ???
},
}; // storing here all created objects, that must move.
/* Each [moveQueue] array will store the chain of moves, like ["up", "up", "left"]
You can take each "key-word" of move, and get required function buy that key,
from the 'move' object */
let move = { // Think about how to simlify this object and functions. It's possible!)
left: function (obj) {
let left = obj.coors.left = (obj.coors.left - obj.step);
obj.node.css('left', left + 'px');
},
up: function (obj) {
let top = obj.coors.top = (obj.coors.top - obj.step);
obj.node.css('top', top + 'px');
},
right: function (obj) {
let left = obj.coors.left = (obj.coors.left + obj.step);
obj.node.css('left', left + 'px');
}
};
let stepTimeout = 1000;
let running = false;
let timeouts = {}; // store all running timeouts here,
// and clear everything with for( key in obj ) loop, if required
$('#toolbox .block').on('click', function () {
let color = $(this).attr('data-color');
let workBlock = '<div class="remove-block block ' + color + '"></div>';
$('#workspace').append(workBlock);
mobs.pinky.moveQueue.push( $(this).text().toLowerCase() ); // .attr('data-direction');
// instead of pinky - any other currently selected object
// $(this).text().toLowerCase() — must be "left", "up", "right"
});
$('#run_workspace').on('click', function () {
running = true;
runCode();
function runCode() {
for (let obj in mobs) { // mobile objects may be multiple
// Inside the loop, obj == mobs each key name. Here it's == "pinky"
let i = 0;
let pinky = mobs[obj];
localRun();
function localRun() {
let direction = pinky.moveQueue[i]; // getting direction key by array index.
move[direction](pinky); // calling the required function from storage.
if (pinky.moveQueue[++i] && running ) {
// self-calling again, if moveQueue has next element.
// At the same time increasing i by +1 ( ++i )
timeouts[obj] = setTimeout(localRun, stepTimeout);
}
}
}
}
});
$("#clear_workspace").click(function () {
$("#workspace").empty();
});
$('#workspace').on("click", ".remove-block", function () {
$(this).closest("div").remove();
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
top: 400px;
left: 400px;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div data-color="red" class="block red">Left</div>
<div data-color="blue" class="block blue">Up</div>
<div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>
But... jQuery was used only for clicks... Translation to JS:
let mobs = {
pinky: {
node: document.getElementById('moving_square'),
coors: { top: 400, left: 400 },
step: 30,
moveQueue: [],
},
};
let move = {
left: function (obj) {
let left = obj.coors.left = (obj.coors.left - obj.step);
obj.node.style.left = left + 'px';
},
up: function (obj) {
let top = obj.coors.top = (obj.coors.top - obj.step);
obj.node.style.top = top + 'px';
},
right: function (obj) {
let left = obj.coors.left = (obj.coors.left + obj.step);
obj.node.style.left = left + 'px';
}
};
let stepTimeout = 1000;
let running = false;
let timeouts = {};
let blocks = document.querySelectorAll('#toolbox .block');
let workSpace = document.getElementById('workspace');
blocks.forEach(function(block){
block.addEventListener('click', function(){
let color = this.dataset.color;
let workBlock = '<div class="remove-block block ' + color + '"></div>';
workSpace.insertAdjacentHTML('beforeend', workBlock);
mobs.pinky.moveQueue.push( this.textContent.toLowerCase() );
});
});
document.getElementById('run_workspace').addEventListener('click', function () {
running = true;
runCode();
function runCode() {
for (let obj in mobs) { // mobile objects may be multiple
// Inside the loop, obj == mobs each key name. Here it's == "pinky"
let i = 0;
let pinky = mobs[obj];
localRun();
function localRun() {
let direction = pinky.moveQueue[i]; // getting direction key by array index.
move[direction](pinky); // calling the required function from storage.
if (pinky.moveQueue[++i] && running ) {
// self-calling again, if moveQueue has next element.
// At the same time increasing i by +1 ( ++i )
timeouts[obj] = setTimeout(localRun, stepTimeout);
}
}
}
}
});
document.getElementById("clear_workspace").addEventListener('click', function () {
workSpace.textContent = "";
});
workSpace.addEventListener('click', function (e) {
if( e.target.classList.contains('remove-block') ){
e.target.remove();
}
});
html,
body {
margin: 0;
padding: 0;
}
#workspace {
display: flex;
height: 100px;
padding: 10px;
background: black;
}
#toolbox {
display: flex;
padding: 10px;
width: 300px;
}
#output_section {
height: 500px;
width: 500px;
border: solid black;
margin: 10px;
position: relative;
}
#moving_square {
position: absolute;
top: 400px;
left: 400px;
width: 100px;
height: 100px;
background: pink;
}
.block {
height: 100px;
width: 100px;
}
.red {
background: red;
}
.blue {
background: cyan;
}
.green {
background: green;
}
.grey {
background: #ccc;
}
<div id="workspace"></div>
<div id="workspace-menu">
<button id="run_workspace">Run</button>
<button id="clear_workspace">Clear</button>
</div>
<div id="toolbox" class="grey">
<div data-color="red" class="block red">Left</div>
<div data-color="blue" class="block blue">Up</div>
<div data-color="green" class="block green">Right</div>
</div>
<div id="output_section">
<div id="moving_square"></div>
</div>

Making clone to swap to html elements with hammer.js

I'm trying to make swap between two divs, I mean, change one by other preserving events and everything.
Both have hammer events to detect swipe. When I make a swap elements in my project, they lost hammer events, but preserve other events like click.
To illustrate the behaviour I made this:
$(document).ready(function(){
$("#obj2").each(function(){
var $this = $(this);
var h = new Hammer(this);
h.get("swipe").set({ direction: Hammer.DIRECTION_ALL, threshold: 1, velocity:0.1 });
h.on("swipe",function(ev){
$this.text(ev.angle.toFixed(2));
});
});
$("#obj1").click(function(){
alert("this works");
});
$("#makeClone").click(function(){
$("#obj2").text("3. swipe again :(");
var aux = $("#obj2").clone(true);
$("#container2").html($("#container1").clone(true));
$("#container1").html(aux);
});
});
div.obj,#makeClone{
display:inline-block;
box-sizing:border-box;
width:300px;
height:150px;
text-align:center;
border-radius:10px;
background:#f44336;
font:18px/150px "Lato";
color:white;
margin-bottom:5px;
cursor:pointer;
}
#obj2{
background:#4caf50;
}
#makeClone{
background:#666;
height:50px;
font:12px/50px "hack";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://raw.githubusercontent.com/hammerjs/jquery.hammer.js/master/jquery.hammer.js"></script>
<div id="container1">
<div id="obj1" class="obj">click</div>
</div>
<div id="container2">
<div id="obj2" class="obj">1.swipe on me!</div>
</div>
<br><br>
<div id="makeClone">2.change with clone</div>
Do not clone your objects. Use .append instead of .html.
$(document).ready(function() {
$("#obj2").each(function() {
var $this = $(this);
var h = new Hammer(this);
h.get("swipe").set({
direction: Hammer.DIRECTION_ALL,
threshold: 1,
velocity: 0.1
});
h.on("swipe", function(ev) {
$this.text(ev.angle.toFixed(2));
});
});
$("#obj1").click(function() {
alert("this works");
});
$("#makeClone").click(function() {
$("#obj2").text("3. swipe again :(");
var d1 = $("#container1>div");
var d2 = $("#container2>div");
$("#container2").append(d1);
$("#container1").append(d2);
});
});
div.obj,
#makeClone {
display: inline-block;
box-sizing: border-box;
width: 300px;
height: 150px;
text-align: center;
border-radius: 10px;
background: #f44336;
font: 18px/150px "Lato";
color: white;
margin-bottom: 5px;
cursor: pointer;
}
#obj2 {
background: #4caf50;
}
#makeClone {
background: #666;
height: 50px;
font: 12px/50px "hack";
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/hammer.js/2.0.8/hammer.min.js"></script>
<script src="https://raw.githubusercontent.com/hammerjs/jquery.hammer.js/master/jquery.hammer.js"></script>
<div id="container1">
<div id="obj1" class="obj">click</div>
</div>
<div id="container2">
<div id="obj2" class="obj">1.swipe on me!</div>
</div>
<br><br>
<div id="makeClone">2.change with clone</div>

change event is not fired on Microsoft Edge on first click

I am trying to implement drag and drop and browse files. I have a <div> with id #box and trying to trigger <input type="file" id="imageUpload" /> on click event of that <div>. The following code is working fine on Mozilla Firefox and Google Chrome but having problem on Microsoft Edge.
$(document).off().on('click', '#box', function () {
$('#imageUpload').trigger('click');
$('#imageUpload').off().on('change', function () {
var imageLoader = document.getElementById('imageUpload');
selectedFiles = imageLoader.files;
imageBrowseUploader(selectedFiles);
});
});
#box {
border: 1px dotted #0B85A1;
width: 100%;
height: 150px;
color: #92AAB0;
text-align: center;
font-weight: 500;
}
#imageUpload {
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="box">
<b>Drag and drop or click here</b> to upload your image.
</div>
<input type="file" id="imageUpload" />
Here is the working Demo with minor changes! (As you can see)
$(document).ready(function(){
$(document).on('click', '#box', function () {
//debugger;
$('#imageUpload').trigger('click');
});
$(document).on('change', function () {
debugger;
var imageLoader = document.getElementById('imageUpload');
selectedFiles = imageLoader.files[0].name;
imageBrowseUploader(selectedFiles);
});
});
function imageBrowseUploader(selectedFiles)
{
alert(selectedFiles);
}
#box {
border: 1px dotted #0B85A1;
width: 100%;
height: 150px;
color: #92AAB0;
text-align: center;
font-weight: 500;
}
#imageUpload {
visibility: hidden;
}
<html>
<head>
<!-- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
</head>
<body>
<div id="box">
<b>Drag and drop or click here</b> to upload your image.
</div>
<input type="file" id="imageUpload" />
</body>
</html>
Hope this will works for you! thank you :)
I would put the on change outside the click function, like this:
$(document).ready(function(){
$(document).off().on('click', '#box', function () {
$('#imageUpload').trigger('click');
});
$('#imageUpload').off().on('change', function () {
var imageLoader = document.getElementById('imageUpload');
selectedFiles = imageLoader.files;
imageBrowseUploader(selectedFiles);
});
});
#box {
border: 1px dotted #0B85A1;
width: 100%;
height: 150px;
color: #92AAB0;
text-align: center;
font-weight: 500;
}
#imageUpload {
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="box">
<b>Drag and drop or click here</b> to upload your image.
</div>
<input type="file" id="imageUpload" />
$(document).off().on('click', '#box', function () {
$('#imageUpload').trigger('click');
$('#imageUpload').off().on('change', function () {
var imageLoader = document.getElementById('imageUpload');
selectedFiles = imageLoader.files;
imageBrowseUploader(selectedFiles);
});
});
#box {
border: 1px dotted #0B85A1;
width: 100%;
height: 150px;
color: #92AAB0;
text-align: center;
font-weight: 500;
}
#imageUpload {
visibility: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id="box">
<b>Drag and drop or click here</b> to upload your image.
</div>
<input type="file" id="imageUpload" />
Your above function contains event inside event.Please don't do that and initialize your change function inside document.ready function()

Fade out animation with JQuery

I have the following code that attempts to demonstrate and animate a dequeuing procedure of an aircraft takeoff queue.
For every takeoff (or dequeue) which happens after 5 seconds, a box is supposed to fade out until all have faded out after the takeoff queue is empty.
My problem is how do i link each plane dequeue to a box such that for every dequeue a box fades out?
Here is the code snipet
function airport() {
this.takeoff_queue = ["KQA", "ERJ", "TOM", "DHL", "ETH"];
this.landing_queue = ["RWA", "KLM", "PAN", "FLY540", "JAMBO"];
console.log('DEPARTING', this.landing_queue, 'ARRIVING', this.takeoff_queue);
}
var departure = new airport();
var takeoff_interval = setInterval(function depart() {
$("#box1").fadeOut();
if (departure.takeoff_queue.length != 0) {
departure.takeoff_queue.shift()
$("#box1").fadeOut();
console.log('DEPARTING', departure.takeoff_queue);
} else {
clearInterval(takeoff_interval);
console.log('TAKEOFFS COMPLETE');
}
}, 5000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h3>SIMPLE SIMULATED TAKEOFF</h3>
<div id="box1" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box2" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box3" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box4" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box5" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
If this is a wrong approach kindly explain it to me.
How about associating each element with some data such as its destination in this case, and look for the element based on that
function airport() {
this.takeoff_queue = ["KQA", "ERJ", "TOM", "DHL", "ETH"];
this.landing_queue = ["RWA", "KLM", "PAN", "FLY540", "JAMBO"];
console.log('DEPARTING', this.landing_queue, 'ARRIVING', this.takeoff_queue);
}
var departure = new airport();
var takeoff_interval = setInterval(function depart() {
if (departure.takeoff_queue.length != 0) {
var dest = departure.takeoff_queue.shift()
$("[data-dest='" + dest + "']").fadeOut();
console.log('DEPARTING', departure.takeoff_queue);
} else {
clearInterval(takeoff_interval);
console.log('TAKEOFFS COMPLETE');
}
}, 5000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h3>SIMPLE SIMULATED TAKEOFF</h3>
<div id="box1" style="width: 20px; height: 20px; background:black;float:left;margin:10px" data-dest="KQA"></div>
<div id="box2" style="width: 20px; height: 20px; background:black;float:left;margin:10px" data-dest="ERJ"></div>
<div id="box3" style="width: 20px; height: 20px; background:black;float:left;margin:10px" data-dest="TOM"></div>
<div id="box4" style="width: 20px; height: 20px; background:black;float:left;margin:10px" data-dest="DHL"></div>
<div id="box5" style="width: 20px; height: 20px; background:black;float:left;margin:10px" data-dest="ETH"></div>
Within your setInterval call, you're continually fading #div1 which only should be faded once. I believe what you're after is $("div:visible:first").fadeOut();:
var takeoff_interval = setInterval(function depart() {
if (departure.takeoff_queue.length != 0) {
departure.takeoff_queue.shift()
$("div:visible:first").fadeOut();
console.log('DEPARTING', departure.takeoff_queue);
} else {
clearInterval(takeoff_interval);
console.log('TAKEOFFS COMPLETE');
}
}, 5000);
jsFiddle example
Try utilizing .queue()
function airport() {
this.takeoff_queue = ["KQA", "ERJ", "TOM", "DHL", "ETH"];
this.landing_queue = ["RWA", "KLM", "PAN", "FLY540", "JAMBO"];
console.log('DEPARTING', this.landing_queue, 'ARRIVING', this.takeoff_queue);
}
var departure = new airport();
$(document).queue("q", $.map(departure.takeoff_queue, function(val, key) {
// add `class` `departure.takeoff_queue` value to `div`
$("div[id^=box]").eq(key).addClass(val);
return function(next) {
// select `div` by `departure.takeoff_queue` value `class`
$("div[class="+val+"]").delay(5000).fadeOut(0, function() {
console.log("DEPARTING:" + this.className);
next()
})
}
})).dequeue("q").promise("q").done(function() {
console.log("TAKEOFFS COMPLETE")
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h3>SIMPLE SIMULATED TAKEOFF</h3>
<div id="box1" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box2" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box3" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box4" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>
<div id="box5" style="width: 20px; height: 20px; background:black;float:left;margin:10px"></div>

Polymer drag-drop event object property contains parent srcElement

I'm building a simple one page app using Polymer. I have created a custom element that contains the Polymer-drag-drop demo. The action of dragging and creating a div works fine, the event object's relatedTarget property holds a reference to the correct drop div. The problem is the srcElement and target property both hold references to the shadowRoot parent polymer element, in this case "workspace-drop".
EDIT:
Logging event.currentTarget on fire also contains a reference to the parentDiv holding the colored children. <div flex horizontal style="border: 1px dotted silver;">
Code is as follows (pretty much the demo but in a polymer element):
<link rel="import" href="/components/polymer/polymer.html">
<script src="/components/webcomponentsjs/webcomponents.js">
</script>
<link rel="import" href="/components/core-drag-drop/core-drag-drop.html">
<polymer-element name="workspace-drop">
<template>
<style>
html {
font-family: 'Helvetica Neue', 'Roboto', 'Arial', sans-serif;
}
body {
height: 100vh;
margin: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.box {
display: inline-block;
width: 100px;
height: 100px;
margin: 16px;
}
.dropped {
position: absolute;
border: 1px solid black;
width: 5px;
height: 5px;
}
</style>
<div flex horizontal style="border: 1px dotted silver;">
<core-drag-drop></core-drag-drop>
<div class="box" style="background-color: lightblue;" draggable="false"></div>
<div class="box" style="background-color: orange;" draggable="false"></div>
<div class="box" style="background-color: lightgreen;" draggable="false"></div>
<div id="hello">Hello World</div>
</div>
<div id="drop" hash="test" class="box" style="border: 3px solid silver; position: relative; width: 300px; height: 300px;" draggable="false"></div>
</template>
<script>
(function(){
addEventListener('drag-start', function(e) {
var dragInfo = e.detail;
// flaw #2: e vs dragInfo.event
console.log(e.detail);
var color = dragInfo.event.target.style.backgroundColor;
dragInfo.avatar.style.cssText = 'border: 3px solid ' + color + '; width: 32px; height: 32px; border-radius: 32px; background-color: whitesmoke';
dragInfo.drag = function() {};
dragInfo.drop = drop;
});
//
function drop(dragInfo) {
var color = dragInfo.avatar.style.borderColor;
var dropTarget = dragInfo.event.relatedTarget;
if (color && dropTarget.id === 'drop') {
var f = dragInfo.framed;
var d = document.createElement('div');
d.className = 'dropped';
d.style.left = f.x - 4 + 'px';
d.style.top = f.y - 4 + 'px';
d.style.backgroundColor = color;
dropTarget.appendChild(d);
dropTarget.style.backgroundColor = color;
}
}
Polymer({
ready: function(){
}
});
})();
</script>
</polymer-element>
Any assistance is appreciated!
Figured it out. It is related to this question.
When loggin an event object, currentTarget is null, but when logging event.currentTarget it logs a value. Why is that?
Logging the event after the drag action has completed returns a reference to the object in its completed state. Logging the specific event.target property on drag-start gave reference to the correct object, on start.

Categories

Resources