Javascript / html5 drag n drop counting - javascript

Ok I have 7 colour block in which to drag 7 colour names. If the user get the correct colour name in the right colour block they receive a point. This is my code below but my count is not working when the user gets the correct answer. Can anyone help please, I know it is something stupid I'm not seeing.
function readDropZone() {
var score = document.getElementById('score');
score.innerHTML = 0;
var block = document.getElementById('colour-block').children;
for(var i = 0; i < block.length; ++i) {
var hitblock = block[i];
var dropzone = hitblock.lastElementChild;
if (dropzone.children.length > 0) {
var dropzoneId = dropzone.id;
var blockId = dropzone.firstElementChild.id;
var blockNo = dropzoneId.substring(dropzoneId.indexOf('-') + 1);
var dragNo = blockId.substring(blockId.indexOf('-') + 1);
if (dragNo == blockNo) {
score.innerHTML = parseInt(score.innerHTML) + 1;
}
}
if (parseInt(score.innerHTML) == 10) {
alert('Congratulations! You won the game!\nClick OK to restart.');
location.reload();
}
}
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
readDropZone();
const data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
#block-1, #block-2, #block-3, #block-4, #block-5, #block-6, #block-7 {
color: #fff;
width: 150px;
height: 35px;
border: 1px solid #aaaaaa;
text-align: center;
padding: 10px 0;
font-size: 1.25em;
}
#block-3 {
color: #000;
}
#colour-block {
float: left;
width: 50%;
}
#colour-name {
float: right;
line-height: 1.5em;
font-size: 1.25em;
font-weight: bold;
width: 50%;
clear: right;
cursor: move;
}
<h2>1. Drag and drop the names into the coloured blocks</h2>
<div id="colour-block">
<div id="block-1" class="block" style="background-color:red" ondrop="drop(event)" ondragover="allowDrop(event)" name="red"></div>
<div id="block-2" class="block" style="background-color:orangered" ondrop="drop(event)" ondragover="allowDrop(event)" name="orange" ></div>
<div id="block-3" class="block" style="background-color:yellow" ondrop="drop(event)" ondragover="allowDrop(event)" name="yellow"></div>
<div id="block-4" class="block" style="background-color:green" ondrop="drop(event)" ondragover="allowDrop(event)" name="green"></div>
<div id="block-5" class="block" style="background-color:skyblue" ondrop="drop(event)" ondragover="allowDrop(event)" name="blue"></div>
<div id="block-6" class="block" style="background-color:midnightblue" ondrop="drop(event)" ondragover="allowDrop(event)" name="indego"></div>
<div id="block-7" class="block" style="background-color:rgb(109, 92, 221)" ondrop="drop(event)" ondragover="allowDrop(event)" name="violet"></div>
</div>
<div id="colour-name">
<div id="drag-6" class="colour" draggable="true" ondragstart="drag(event)" name="indego">Indeagó</div>
<div id="drag-2" class="colour" draggable="true" ondragstart="drag(event)" name="orange">Oráiste</div>
<div id="drag-4" class="colour" draggable="true" ondragstart="drag(event)" name="green">Glas</div>
<div id="drag-3" class="colour" draggable="true" ondragstart="drag(event)" name="yellow">Buí</div>
<div id="drag-1" class="colour" draggable="true" ondragstart="drag(event)" name="red">Dearg</div>
<div id="drag-7" class="colour" draggable="true" ondragstart="drag(event)" name="violet">Corcairghorm</div>
<div id="drag-5" class="colour" draggable="true" ondragstart="drag(event)" name="blue">Gorm</div>
</div>
<div style="clear:both"></div>
<h1>Your score is <span id="score">0</span> out of 7</h1>
</div>

As several others have stated, your blockResults function is not being invoked. Once it is being invoked there are 2 errors that are preventing count from incrementing properly:
dropzone will never have children. You already check for the presense of children in this line: var dropzone = hitblock.lastElementChild; So I changed the if statement to just if (dropzone) {
The line var blockId = dropzone.firstElementChild.id; was a bit confusing to me as you are trying to get the id of the block but you are looking at the child's Id which is not present. I changed the line to var blockId = hitblock.id;
The counter begun incrementing after these two changes.

Related

append the element before and after on drop it

I'm trying to make a website that use drag and drop functionality to build a website. But I'm facing the problem that the element is not being append before another element like the code I have shown. please help me so it can drop the elements before and after a specific element not just at the end of all the elements.
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
#div1,
#div2 {
float: left;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<button draggable="true" ondragstart="drag(event)" id="drag1">button1</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">button2</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">button3</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">button4</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>
I'm using javascript.
That's actually quite tricky to achieve, you need to implement your own logic for inserting the element to the correct position in the list.
Here is an example where you can move items between divs and reorder items in the same div
(Note that I only implemented the logic for drag/drop items horizontally in a single line by using left offset, if you have multiple lines items list, you need to implement your own)
function allowDrop(ev) {
ev.preventDefault()
}
function drag(ev) {
ev.dataTransfer.setData('text', ev.target.id)
}
function drop(ev) {
ev.preventDefault()
var data = ev.dataTransfer.getData('text')
// ev.currentTarget is the div that the elements are dropped
const currentDragElementOffset = ev.clientX
const items = ev.currentTarget.children
//empty list, just append and return
if (items.length === 0) {
ev.currentTarget.appendChild(document.getElementById(data))
return
}
// non-empty list
for (let i = 0; i < items.length; i++) {
const item = items[i]
const {
left,
width
} = item.getBoundingClientRect()
// find the offset left from the center of the item
const currentElementLeftOffset = left + width / 2;
if (currentDragElementOffset < currentElementLeftOffset) {
ev.currentTarget.insertBefore(document.getElementById(data), item)
return
}
// found no insertion point, that means item was dragged to the end of the list
if (i === items.length - 1 && currentDragElementOffset > currentElementLeftOffset) {
ev.currentTarget.appendChild(document.getElementById(data))
}
}
}
#div1,
#div2 {
float: left;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<!DOCTYPE html>
<html>
<body>
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<button draggable="true" ondragstart="drag(event)" id="drag1">
button1
</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">
button2
</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">
button3
</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">
button4
</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>
Simply use the CSS property order.
The drop zones must have display: flex or display: inline-flex (see .zone in Example - CSS)
Each item that is draggable should have style="order: number " (see Example - JS)
Also, to avoid an item appending to another item, use event.currentTarget instead of event.target in the drop() function (see drop() in Example - JS). In the example, the repetitive parts in HTML have been streamlined (see Figure I):
Figure I
Original Post
Example
Attributes on each element in HTML
Attributes assigned to each element by .forEach()
Inline events on each element in HTML
Onevent properties bound to each element by .forEach()
Example
Details are commented
/*
Collect all .btn into a NodeList
Iterate through NodeList with .forEach()
Bind dragstart event to current <button>
Add inline style "order" with the value of current index
Add "draggable" attribute with the value of true
*/
document.querySelectorAll('.btn').forEach((b, i) => {
b.ondragstart = drag;
b.style.order = i;
b.setAttribute('draggable', true);
});
/*
Collect all .zone into a NodeList
Iterate through NodeList with .forEach()
Bind drop event to current <div>
Bind dragover event to current <div>
*/
document.querySelectorAll('.zone').forEach(z => {
z.ondrop = drop;
z.ondragover = allowDrop;
});
function allowDrop(e) {
e.preventDefault();
}
function drag(e) {
e.dataTransfer.setData("text", e.target.id);
}
function drop(e) {
e.preventDefault();
let data = e.dataTransfer.getData("text");
/*
Change e.target to e.currentTarget to prevent any <button>
appending onto another <button>. e.currentTarget will always
point to .zone
*/
e.currentTarget.append(document.getElementById(data));
}
.zone {
display: flex;
align-items: center;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
.btn {
margin: 0 10px;
cursor: move;
}
<h2>Drag and Drop</h2>
<p>Drag the buttons back and forth between the two div elements.</p>
<div class="zone">
<button id='b1' class='btn'>button1</button>
<button id='b2' class='btn'>button2</button>
<button id='b3' class='btn'>button3</button>
<button id='b4' class='btn'>button4</button>
</div>
<div class="zone"></div>
You should use .prepend() method for inserting element before the other element.
Element.prepend() method inserts a set of Node objects or string objects before the first child of the Element. String objects are inserted as equivalent Text nodes.
Here's a Working Code :
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.prepend(document.getElementById(data));
}
#div1,
#div2 {
float: left;
width: 500px;
height: 35px;
margin: 10px;
padding: 10px;
border: 1px solid black;
}
<h2>Drag and Drop</h2>
<p>Drag the image back and forth between the two div elements.</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)">
<button draggable="true" ondragstart="drag(event)" id="drag1">button1</button>
<button draggable="true" ondragstart="drag(event)" id="drag2">button2</button>
<button draggable="true" ondragstart="drag(event)" id="drag3">button3</button>
<button draggable="true" ondragstart="drag(event)" id="drag4">button4</button>
</div>
<div id="div2" ondrop="drop(event)" ondragover="allowDrop(event)">
</div>

How to set if..else statement in JS drag and drop

The result i want from the the below code is:
1. There are three text: Drag me!, Drag me2!, Drag me3!
2. One of the text will be drag to the last empty box
3. demo2 will display the text of the drop text
But what i have done will only display the "Drag me3!"
How can I done the 1, 2 & 3 by using if...else statement?
function dragStart(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
document.getElementById("demo").innerHTML = "Started to drag the p element";
}
function allowDrop(ev) {
ev.preventDefault();
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
ev.target.appendChild(document.getElementById(data));
document.getElementById("demo").innerHTML = "The p element was dropped";
var x = document.getElementById("dragtarget1").textContent;
var y = document.getElementById("dragtarget2").textContent;
var z = document.getElementById("dragtarget3").textContent;
document.getElementById("demo2").innerHTML = x;
document.getElementById("demo2").innerHTML = y;
document.getElementById("demo2").innerHTML = z;
}
.droptarget {
float: left;
width: 100px;
height: 35px;
margin: 15px;
padding: 10px;
border: 1px solid #aaaaaa;
}
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget1">Drag me!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget2">Drag me2!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)">
<p ondragstart="dragStart(event)" draggable="true" id="dragtarget3">Drag me3!</p>
</div>
<div class="droptarget" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<p style="clear:both;"><strong>Note:</strong> drag events are not supported in Internet Explorer 8 and earlier versions or Safari 5.1 and earlier versions.</p>
<p id="demo"></p>
<p id="demo2"></p>
The reason why you are seeing the behavior that you listed above is because of your line of code var x = document.getElementById("dragtarget").textContent;. What this code is doing is getting the text context of the element with that specific ID (dragtarget) and setting it to the inner HTML content of the id=demo2 every time. Instead of searching for a specific element with a specific ID, you need to use a more dynamic solution that looks in the event object received by the drop() function to determine what text to set in the demo2 element.

display next image on drop

I have three div boxes with id 10, 11, 12. I have an image array, on dropping an item box, the box element gets deleted, I make a call to function nextslide in the on-drop method which calls next slide to display.
On dropping the first element on any box with id 10, 11, 12 The box gets deleted, but displaying next image through nextslide() method doesn't work.
I want to display next image in an array on successfully dropping the first element.
How to achieve this?
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.id);
}
var x = document.get
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("Text");
alert(data);
var el = document.getElementById(data);
el.parentNode.removeChild(el); // deleting drag item
ev.target.style.backgroundColor = 'initial'; //[value indicate which box elemenet] bgcoclor none
nextslide();
}
var images = new Array();
images[0] = "https://picsum.photos/200/300/?random";
images[1] = "https://picsum.photos/200/300/?random";
images[2] = "https://picsum.photos/200/300/?random";
var currentpic = 0;
var lastpic = images.length - 1;
function nextslide() {
if (currentpic == lastpic) {
currentpic = 0;
document.getElementById('slide').src = images[currentpic];
} else {
currentpic++;
document.getElementById('slide').src = images[currentpic];
}
}
.box {
background-color: coral;
width: 20%;
height: 60px;
display: inline-block;
border-radius: 5px;
margin: -2px;
border-radius: 12%;
background-color: #00b300;
}
<div id="container">
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="10">
<p name="values"></p>
</div>
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="11">
<p name="values"></p>
</div>
<div class="box" ondrop="drop(event)" ondragover="allowDrop(event)" id="12">
<p name="values"></p>
</div>
</div>
<div class="box2" draggable="true" ondragstart="drag(event)" id="2">
<img src="https://picsum.photos/200/300/?random" draggable="true" id="slide" style="width:30px; height:100px; border-radius: 50%;" border="rounded" onclick="nextslide()" />
</div>

Draggable is not dragging

Somehow my draggables arn't dragging anymore into the placeholders.
I noticed it gives an error on the appendChild in the drop() function but when I alert in there I notice it doesn't even get that far.
var people = ['Sinan', 'Babette', 'Thomas', 'Yannick', 'Nick'];
$.each(people, function(key, val) {
$('#placeholders').append('<div class="dnd" data-id="' + val + '" ondrop="drop(event)" ondragover="testDiv(event, innerHTML)"></div>');
});
$('#seizeImg img').on('dragstart', function(event) {
drag(event);
});
function testDiv(ev, x) {
if (x.length > 0) {
return false;
} else {
allowDrop(ev);
return true;
}
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
var complete = false;
$.each('#seizeImg img', function(key, val) {
alert(key);
});
}
.dnd {
display: inline-block;
vertical-align: top;
width: 10%;
height: 160px;
padding: 10px;
border: 2px solid #B7E6E6;
background: rgba(51, 255, 102, 0.2);
}
#seizeImg img {
width: 10%;
height: 160px;
}
div.label {
height: 25px;
text-align: center;
border: none;
background: none;
}
div.buf {
background: rgba(255, 0, 0, 0.2);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="placeholders">
</div>
<br>
<br>
<div id="seizeImg">
<img id="Babette" src="img/Babette.jpg" draggable="true" ondrop="drop(event)" width="186" height="186">
<img id="Thomas" src="img/Thomas.jpg" draggable="true" ondrop="drop(event)" width="186" height="186">
<img id="Yannick" src="img/Yannick.jpg" draggable="true" ondrop="drop(event)" width="186" height="186">
<img id="Sinan" src="img/Sinan.jpg" ondrop="drop(event)" draggable="true" ondrop="drop(event)" width="186" height="186">
<img id="Nick" src="img/Nick.jpg" ondrop="drop(event)" draggable="true" ondrop="drop(event)" width="186" height="186">
</div>
I am assuming you are using jqueryUI with the drag and drop libraries installed. If you aren't that might make things a little easier for you.
you could make it work with:
$('#seizeImg img').draggable();
and if you wanted the drop to save data all you have to do is:
$('#placeholders').droppable({
accept: $('#seizeImg img'),
drop: function(){
//enter code here to take place whenever you drop something on it
// if you want to take a value from the object you are dropping on
// the droppable object just use:
var varID = (ui.draggable.attr("value");
}
});
Its a little more concise and jqueryUI takes out a lot of the guess work.
EDIT:
Unless you didn't include the code up top, you never call the actual jqueryUI draggable function. somewhere around
$(document).ready({function(){
// you have to include
$('seizeImg img').draggable({function(){
//add some more moving parts here if you need to
});
}
just setting draggable='true' in your HTML isn't the same thing.
The problem you are facing is caused by the lines below
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
You are trying to append an element that is not of Node type. That is happening because data is an empty string thus document.getElementById("") returns null which is not allowed to be passued to appendChild.

making a new div draggable, tried everything

Hello stackoverflow comunity.
I am working on some code that makes draggable resizeable divs. I have it working with the divs that are created originally, but the newly added divs arent becomming draggable.
Here is ALL my code:
<html>
<head>
<script>
var id = 4;
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
ev.target.appendChild(document.getElementById(ev.dataTransfer.getData("Text")));
}
function change(div)
{
var divw=parseInt(div.style.width);
var divh=parseInt(div.style.height);
var imgw=divw-10;
var imgh=divh-10;
div.children[0].style.width=imgw;
div.children[0].style.height=imgh;
div.style.border="dotted 3px grey";
}
function addimg()
{
var main = document.getElementById('main');
var div = document.createElement('div');
div.onmouseout = function() {this.style.border=0};
div.ondragstart = function() {drag(event)};
div.onmousemove = function() {change(this)};
div.setAttribute('draggable', true);
div.id = 'div'+id;
id+=1;
div.style.styleFloat = 'left';
div.style.cssFloat = 'left';
div.style.resize = 'both';
div.style.overflow = 'hidden';
div.style.height = '110px';
div.style.width = '110px';
div.innerHTML = '<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />';
main.appendChild(div);
}
</script>
</head>
<body>
<center>
<div ID="main" ondragover="event.preventDefault()" ondrop="drop(event)" style="width:900px; height:900px; border: dashed 1px lightgrey;" overflow="auto">
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML" style="resize:none; width: 100px; height: 100px"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
</center>
<button onclick="addimg()">add an image</button>
</body>
</html>
the issue is that the new divs aren't draggable.
P.S. if you use jquery, please explain it very detailed, i have no experience with it.
I m not sure what draggable function in this case is. Is it just dragging this newly added image to this element in top left ? After what that image disappear ?
If this is case, solution is very simple. In function addimage you have wrong line.Your line is:
div.ondragstart = function() {drag(event)};
And it should be
div.ondragstart = function(event) {drag(event)};
In this line you call function without setting event as argument, and you use it in function.
Hope it helps.
One solution is to use the same method used to create the <img> element, to create the <div>:
<html>
<head>
<script>
var id = 4;
function drag(ev) {
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev) {
ev.preventDefault();
document.getElementById('main')
.appendChild(document.getElementById(ev.dataTransfer.getData("Text")));
}
function change(div) {
var divw = parseInt(div.style.width);
var divh = parseInt(div.style.height);
var imgw = divw - 10;
var imgh = divh - 10;
div.children[0].style.width = imgw;
div.children[0].style.height = imgh;
div.style.border = "dotted 3px grey";
}
function addimg() {
var main = document.getElementById('main');
main.innerHTML += '<div id="div'+id+'" onmouseout="this.style.border=0" draggable="true" ' +
'ondragstart="drag(event)" onmousemove="change(this)" style="float:left; ' +
'resize:both; overflow:hidden; height: 110px; width:110px"></div>';
div = document.getElementById('div'+id);
div.innerHTML = '<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />';
id+=1;
}
</script>
</head>
<body>
<center>
<div ID="main" ondragover="event.preventDefault()" ondrop="drop(event)" style="width:900px; height:900px; border: dashed 1px lightgrey;" overflow="auto">
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML" style="resize:none; width: 100px; height: 100px"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3" style="float:left; resize:both; overflow:hidden; height: 110px; width:110px">
<img draggable="false" style="width: 100px; height: 100px" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
</center>
<button onclick="addimg()">add an image</button>
</body>
</html>
This should ensure the browser renders the new <div> element in the same way as the existing ones. In addition ensuring that elements are appended back to the main <div> element when they are dropped, will prevent them from disappearing when dropped onto of other elements, as previously.
Using Jquery
On the tip of using jquery, if we include the jquery.min.js library at the top of the file:
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
The change() function can be rewritten as:
function change(div) {
var $div = $(div);
$div.css('border','dotted 3px grey')
.children( ':first' )
.width( $div.width() - 10 )
.height( $div.height() - 10 );
}
This is somewhat shorter than the original. The first line converts the div parameter into a jquery object and stores it in the $div variable. The $ at the beginning of the variable name is just a convention, as the variable contains a jquery object. Caching the jquery object in this variable is more efficient than using $(div) 3 times in the change() function.
Calls to$div.width() and $div.height() perform the same action as the parseInt() calls in the original function. Jquery allows function calls to be 'chained', thus the first call on $div sets the border style and returns the same $div object. The .children() call returns the first child of $div (the <img> element) which then has it's width and height set using the corresponding methods.
It should be noted that jquery is generally thought to be easier to use, and offer good cross browser compatibility (which can be a real headache) rather than more efficient.
Moving style out of elements
We can move the common style attribute out of the individual elements into a separate section in the <head> of the html:
<style>
#main {
width:900px;
height:900px;
border: dashed 1px lightgrey;
overflow: auto;
}
.dragDiv {
float: left;
resize: both;
overflow: hidden;
height: 110px;
width: 110px;
}
.dragDiv img {
width: 100px;
height: 100px
}
.dragDiv textarea {
resize: none;
width: 100px;
height: 100px;
}
</style>
By giving the drag-able <div> elements the class dragDiv we reduce the amount of style duplication:
<div id="main" ondragover="event.preventDefault()" ondrop="drop(event)">
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div1">
<textarea onblur="this.nextElementSibling.innerHTML=this.innerHTML"></textarea>
<p style="background-color: blue"></p>
</div>
<div style="clear:both"></div>
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div2">
<img draggable="false" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
<div class="dragDiv" onmouseout="this.style.border=0" draggable="true" ondragstart="drag(event)" onmousemove="change(this)" id="div3">
<img draggable="false" src="https://www.google.com/images/srpr/logo11w.png" />
</div>
</div>
Is this something like what you are looking for? I'm happy to suggest more alterations, if required.
Jquery offers draggables - which use absolute positioning; resizables; and sortables - which offer similar 'snap on drop' behaviour as the code above. Although I don't suggest you use these instead, they might be good guides as to how you wish your code to behave.

Categories