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:
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)
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 =]