Sunday, May 12, 2024
 Popular · Latest · Hot · Upcoming
67
rated 0 times [  72] [ 5]  / answers: 1 / hits: 20328  / 14 Years ago, sun, february 27, 2011, 12:00:00

I'm making a Drag and Drop JavaScript engine. I learned how to set a bounding box as the parent element. However, now I wish to set the bounding box to any parent of any parent, or as the entire page (bound-less).



Right now my Javascript Engine looks like:



// JavaScript Document

var dragObj;

document.addEventListener(mousedown, down, false);

function down(event) {
if(~event.target.className.search(/drag/)) {
dragObj = makeObj(event.target);
dragObj.element.style.zIndex=100;
document.addEventListener(mousemove, freeMovement, false);
}
}

function freeMovement(event) {

if (typeof(dragObj.element.mouseup) == undefined)
document.addEventListener(mouseup, drop, false);
//Prevents redundantly adding the same event handler repeatedly

dragObj.element.style.left = Math.max(0, Math.min(event.clientX - dragObj.posX, dragObj.boundX)) + px;
dragObj.element.style.top = Math.max(0, Math.min(event.clientY - dragObj.posY, dragObj.boundY)) + px;
}

function drop() {
dragObj.element.style.zIndex=1;

document.removeEventListener(mousemove, freeMovement, false);
document.removeEventListener(mouseup, drop, false);
//alert(DEBUG_DROP);
}

function makeBoundlessObj(e) {
var obj = new Object();
obj.element = e;

obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

obj.posX = event.clientX - e.offsetLeft;
obj.posY = event.clientY - e.offsetTop;

return obj;
}

function makeObj(e) {
obj = new Object();
obj.element = e;

obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

obj.posX = event.clientX - e.offsetLeft;
obj.posY = event.clientY - e.offsetTop;

var curleft = curtop = 0;
if (e.offsetParent) {
do {
curleft += e.offsetLeft;
curtop += e.offsetTop;
//alert(e.id + : + e.innerHTML);
if(~e.className.search(/bound/)) {
obj.boundX = curleft - obj.element.offsetLeft;
obj.boundY = curtop - obj.element.offsetTop;
return obj;
}

} while (e = e.offsetParent);
}

return obj;
}

function findPos(obj) { // Donated by `lwburk` on StackOverflow
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
return { x: curleft, y: curtop };
}
}


My CSS is as follows:



@charset utf-8;
/* CSS Document */


* {
padding: 0px;
margin: 0px;
}

.drag {
position: absolute;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
}

.bound {
position: relative;
}

.square {
width: 100px;
height: 100px;
background: red;
cursor:move;
}

#center {
width: 500px;
height: 300px;
margin: auto;
margin-top: 50px;
background-color:#ccc;
text-align: center;
border-radius: 25px;
-moz-border-radius: 25px;
}

#box {
background-color: #FF3;
height: 278px;
border-radius: 0 0 25px 25px;
-moz-border-radius: 0 0 25px 25px;
opacity: 0.5;
}


And my HTML is pretty clean:



<div id=center>
<h1>Hello World! <hr /></h1>
<div id=box class=bound>
<p class=drag square> One </p>
<p class=drag square> Two </p>
</div>
</div>


I've attempted to make the proper functions multiple times. I'll give one that I've made which doesn't work, and I'll list why:




  1. If it doesn't have bounds, I set the default bounds as the parent element (because I don't know how to set bounds as the entire page)


  2. If one of the parent elements IS a bound, then I am not setting the bound coordinates correctly (again, I don't know how)




Oh, and I set the bounds while I create the drag_object.



JavaScript creation function:



function makeObj(e) {
var obj = new Object();
obj.element = e;

obj.boundX = e.parentNode.offsetWidth - e.offsetWidth;
obj.boundY = e.parentNode.offsetHeight - e.offsetHeight;

obj.posX = event.clientX - e.offsetLeft;
obj.posY = event.clientY - e.offsetTop;

var curleft = curtop = 0;
if (e.offsetParent) {
do {
curleft += e.offsetLeft;
curtop += e.offsetTop;
//alert(e.id + : + e.innerHTML);
if(~e.className.search(/bound/)) {
obj.boundX = curleft - obj.element.offsetLeft;
obj.boundY = curtop - obj.element.offsetTop;
return obj;
}

} while (e = e.offsetParent);
}

return obj;
}


What is the correct math for setting the bounding box and why? Can I get rid of the position: relative in the .bound class? Can I make .drag class not position: absolute? I know all of these things will probably greatly affect how the bounding function is written. If I had to choose between having the .drag class or the .bound class not need a certain type of position, I would choose that the .bound class be set to any kind of positioning.



Thank you all for reading and helping! It means a lot to me; I'm a full time (boarding) high school student with very little free time =/



EDIT:



I should note that I'm on my tenth day of learning Javascript- or fifteenth-hour depending on how you look at it, and I would like to learn the language before I start using libraries like jQuery. This engine is an academic exercise I've made for myself for the sake of knowledge and learning the language =]


More From » html

 Answers
20

The first thing I noticed is that you didn't have a minimum boundary. You'll need that in order to enforce the upper AND lower bound.



What is the correct math for setting the bounding box and why?



First thing is that dragObj needs to account for both boundaries (applies to position: absolute):



// parentNode is our bounding box
// the minimum boundary is based on the top left corner of our container
obj.minBoundX = e.parentNode.offsetLeft;
obj.minBoundY = e.parentNode.offsetTop;

// the maximum is the bottom right corner of the container
// or.. the top left (x,y) + the height and width (h,y) - the size of the square
obj.maxBoundX = obj.minBoundX + e.parentNode.offsetWidth - e.offsetWidth;
obj.maxBoundY = obj.minBoundY + e.parentNode.offsetHeight - e.offsetHeight;


Enforcing the boundaries is a simple update to freeMovement:



dragObj.element.style.left = Math.max(dragObj.minBoundX, Math.min(event.clientX - dragObj.posX, dragObj.maxBoundX)) + px;
dragObj.element.style.top = Math.max(dragObj.minBoundY, Math.min(event.clientY - dragObj.posY, dragObj.maxBoundY)) + px;


Can I get rid of the position: relative in the .bound class? Yup.



Can I make .drag class not position: absolute? Yup. You'll just want to change your positions to be relative and your calculations to account for this. For example, your minimum bound will now be 0.



// parentNode is our bounding box
// the minimum boundary is based on the top left corner of our container
obj.minBoundX = 0;
obj.minBoundY = 0;


Here is the JSFiddle for the position:absolute version: http://jsfiddle.net/feWcQ/ (works with Firefox 4). I also added two tiny boxes that show your boundaries. Hopefully my answer helps you!


[#93557] Friday, February 25, 2011, 14 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
nora

Total Points: 248
Total Questions: 111
Total Answers: 97

Location: India
Member since Wed, Aug 4, 2021
3 Years ago
;