move div by drag etc.

D

DL

Rumor has it that some implementation of HTML5's drag and drop is very
clumsy. Let's ignore that for now.

Say, we have we have 5 or 6 DIV (s) in a page or 5 or 6 or more TD in
a TR, what might be an elegant way to drag the DIV (s) or TD (s) to re-
arrange the DIV (s) or TD (s)?

Then, maybe, we could consider to drag a DIV to a trash bin for
removal as well ...

Primarily browsers to be supported at this point is IE7 and FF3.5.

Thanks.
 
G

Garrett Smith

DL said:
Rumor has it that some implementation of HTML5's drag and drop is very
clumsy. Let's ignore that for now.

OK. It would be worthwhile to hear some discussion the shortcomings. We
can proceed without, that, though.
Say, we have we have 5 or 6 DIV (s) in a page or 5 or 6 or more TD in
a TR, what might be an elegant way to drag the DIV (s) or TD (s) to re-
arrange the DIV (s) or TD (s)?

DIV can have left/top style value applied. TD cannot.

A general approach is:
Add a callback for mousedown on document.
Add a callback for mousemove on document
Add a callback for mouseup on document.

mousedown: if the element the user clicked or one of its ancestors is
something that can be dragged, set the activeDragObject to that.

mousemove:
1) if there is no activeDragObject, return.
2) move the activeDragObject by the difference from where mousedown
occurred and the cursor position. The cursor position
is e.pageX[1] or (e.clientX[2] + scroll offsets[3][4]).

mouseup: set activeDragObject = null.

That is basically the idea to use. IFRAMEs can make things harder.

A general outline might look like:-

function mousedownHandler(ev) {
var target = getEventTarget(ev),
draggable = findDraggableAncestor(target);
if(draggable) {
activeDragObject = draggable;
}
}

function mousemoveHandler(ev) {
if(!activeDragObject) return;
var coords = getEventCoords(ev),
ePageX = eventCoords.x, ePageY = eventCoords.y,
distX = ePageX - mousedownX,
distY = ePageY - mousedownY;
}

function mouseupHandler(ev) {
activeDragObject = null;
}

function findDraggableAncestor(target) {
var closestAncestor = document.body;
for(var x = target; x !== closestAncestor; x = x.parentNode) {
if(matchesDragCriteria(x)) {
return x;
}
return null;
}

function getEventCoords(ev) {
var coords = { x : 0, y : 0 };
// find e.pageX/e.pageY or
// (e.clientX/e.clientY + scroll offsets);

return coords;
}
Then, maybe, we could consider to drag a DIV to a trash bin for
removal as well ...

Is the trash bin on the same page?
Primarily browsers to be supported at this point is IE7 and FF3.5.

Why so limited? There is no reason this could not work in older versions
of Firefox, Opera, versions of Webkit. iPhone, too, with very little
extra work.

Blackberry - I need to investigate further, for latest touch screens.
Palm Pre - I think it is not possible.

[1]https://developer.mozilla.org/En/DOM/Event.pageX
[2]http://msdn.microsoft.com/en-us/library/ms533567(VS.85).aspx
[3]http://msdn.microsoft.com/en-us/library/ms534617(VS.85).aspx
[4]https://developer.mozilla.org/en/DOM/window.pageXOffset
 
D

Don84

DL said:
Rumor has it that some implementation of HTML5's drag and drop is very
clumsy.  Let's ignore that for now.

OK. It would be worthwhile to hear some discussion the shortcomings. We
can proceed without, that, though.
Say, we have we have 5 or 6 DIV (s) in a page or 5 or 6 or more TD in
a TR, what might be an elegant way to drag the DIV (s) or TD (s) to re-
arrange the DIV (s) or TD (s)?

DIV can have left/top style value applied. TD cannot.

A general approach is:
   Add a callback for mousedown on document.
   Add a callback for mousemove on document
   Add a callback for mouseup on document.

mousedown: if the element the user clicked or one of its ancestors is
something that can be dragged, set the activeDragObject to that.

mousemove:
1) if there is no activeDragObject, return.
2) move the activeDragObject by the difference from where mousedown
occurred and the cursor position. The cursor position
is e.pageX[1] or (e.clientX[2] + scroll offsets[3][4]).

mouseup: set activeDragObject = null.

That is basically the idea to use. IFRAMEs can make things harder.

A general outline might look like:-

function mousedownHandler(ev) {
   var target = getEventTarget(ev),
       draggable = findDraggableAncestor(target);
   if(draggable) {
     activeDragObject = draggable;
   }

}

function mousemoveHandler(ev) {
   if(!activeDragObject) return;
   var coords = getEventCoords(ev),
       ePageX = eventCoords.x, ePageY = eventCoords.y,
       distX = ePageX - mousedownX,
       distY = ePageY - mousedownY;

}

function mouseupHandler(ev) {
  activeDragObject = null;

}

function findDraggableAncestor(target) {
   var closestAncestor = document.body;
   for(var x = target; x !== closestAncestor; x = x.parentNode) {
     if(matchesDragCriteria(x)) {
       return x;
     }
   return null;

}

function getEventCoords(ev) {
   var coords = { x : 0, y : 0 };
   // find e.pageX/e.pageY or
   // (e.clientX/e.clientY + scroll offsets);

   return coords;

}
Then, maybe, we could consider to drag a DIV to a trash bin for
removal as well ...

Is the trash bin on the same page?
Primarily browsers to be supported at this point is IE7 and FF3.5.

Why so limited? There is no reason this could not work in older versions
of Firefox, Opera, versions of Webkit. iPhone, too, with very little
extra work.

Blackberry - I need to investigate further, for latest touch screens.
Palm Pre - I think it is not possible.

[1]https://developer.mozilla.org/En/DOM/Event.pageX
[2]http://msdn.microsoft.com/en-us/library/ms533567(VS.85).aspx
[3]http://msdn.microsoft.com/en-us/library/ms534617(VS.85).aspx
[4]https://developer.mozilla.org/en/DOM/window.pageXOffset

Excellent. Before I start to "play" with it, let me say, sorry I
haven't clearly stated that all the actions would take place on the
same page, but I guess the vars of your sample code of ePageX and
ePageY can be anything really, or ePageX and ePageY won't hurt
neither, yes?

Also, on
"
Add a callback for mousedown on document.
Add a callback for mousemove on document
"
would it be like <div id="div1" onmousedown="jsdoDownFN();"
onmousemove="jsdoMoveFN();" .../> ?
Is that what you meant by "callback"?

Many thanks.
 
G

Garrett Smith

Don84 said:
DL said:
Rumor has it that some implementation of HTML5's drag and drop is very
clumsy. Let's ignore that for now.
OK. It would be worthwhile to hear some discussion the shortcomings. We
can proceed without, that, though.
Say, we have we have 5 or 6 DIV (s) in a page or 5 or 6 or more TD in
a TR, what might be an elegant way to drag the DIV (s) or TD (s) to re-
arrange the DIV (s) or TD (s)?
DIV can have left/top style value applied. TD cannot.

A general approach is:
Add a callback for mousedown on document.
Add a callback for mousemove on document
Add a callback for mouseup on document.

mousedown: if the element the user clicked or one of its ancestors is
something that can be dragged, set the activeDragObject to that.

mousemove:
1) if there is no activeDragObject, return.
2) move the activeDragObject by the difference from where mousedown
occurred and the cursor position. The cursor position
is e.pageX[1] or (e.clientX[2] + scroll offsets[3][4]).

mouseup: set activeDragObject = null.

That is basically the idea to use. IFRAMEs can make things harder.

A general outline might look like:-

function mousedownHandler(ev) {
var target = getEventTarget(ev),
draggable = findDraggableAncestor(target);
if(draggable) {
activeDragObject = draggable;
}

}

function mousemoveHandler(ev) {
if(!activeDragObject) return;
var coords = getEventCoords(ev),
ePageX = eventCoords.x, ePageY = eventCoords.y,
distX = ePageX - mousedownX,
distY = ePageY - mousedownY;

}

function mouseupHandler(ev) {
activeDragObject = null;

}

function findDraggableAncestor(target) {
var closestAncestor = document.body;
for(var x = target; x !== closestAncestor; x = x.parentNode) {
if(matchesDragCriteria(x)) {
return x;
}
return null;

}

function getEventCoords(ev) {
var coords = { x : 0, y : 0 };
// find e.pageX/e.pageY or
// (e.clientX/e.clientY + scroll offsets);

return coords;

}
Then, maybe, we could consider to drag a DIV to a trash bin for
removal as well ...
Is the trash bin on the same page?
Primarily browsers to be supported at this point is IE7 and FF3.5.
Why so limited? There is no reason this could not work in older versions
of Firefox, Opera, versions of Webkit. iPhone, too, with very little
extra work.

Blackberry - I need to investigate further, for latest touch screens.
Palm Pre - I think it is not possible.

[1]https://developer.mozilla.org/En/DOM/Event.pageX
[2]http://msdn.microsoft.com/en-us/library/ms533567(VS.85).aspx
[3]http://msdn.microsoft.com/en-us/library/ms534617(VS.85).aspx
[4]https://developer.mozilla.org/en/DOM/window.pageXOffset

(It would be good if you could reply inline-style, trimming/removing
signatures or other things that don't matter anymore)
Excellent. Before I start to "play" with it, let me say, sorry I
haven't clearly stated that all the actions would take place on the
same page, but I guess the vars of your sample code of ePageX and
ePageY can be anything really, or ePageX and ePageY won't hurt
neither, yes?

First let me say that the example is non-functional. It was given to
outline the process of drag 'n drop.

In mousemomveHandlerm variables ePageX and ePageY represent the current
cursor position. In mousemove, the activeDragObject will move left by
the amount the cursor has moved. That is: (ePageX - mousedownX).

So, if the mousedown event happened at {x:10, y:10}, we can say that
mousedownX = 10.

When mousemove fires, say for example, the cursor happens to be at
(x:20, y:30}, the difference in |x| is (20 - 10). This means the div
new position will add 10 (10px) to the current position.

TO avoid re-parsing the style properties of the draggable object, an
object can be used to represent the div. THe object can have x and y
properties that get updated a moveToX and moveToY methods. This can be
added after you get a basic, working example.
Also, on
"
Add a callback for mousedown on document.
Add a callback for mousemove on document
"
would it be like <div id="div1" onmousedown="jsdoDownFN();"
onmousemove="jsdoMoveFN();" .../> ?
Is that what you meant by "callback"?

No, the events are added on document.

document.onmousedown = mousedownHandler;

function mousedownHandler(ev) {
var target = getEventTarget(ev);
// ...
}

Function getEventTarget will find the ev.target or event.srcElement,
depending on the browser event model.

If that target is something that the program is interested in dragging,
set the activeDragObject to that.
 
D

Don84

...
....

Function getEventTarget will find the ev.target or event.srcElement,
depending on the browser event model.

If that target is something that the program is interested in dragging,
set the activeDragObject to that.

It looks like I didn't know how to implement the getEventTarget
function properly. The code below is not working. The getEventTarget
function is at the bottom.

Many thanks.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>"flowing" objects </title>
<script type="text/javascript">
function addDot() {
var div = document.createElement("div");
if (div)
{

div.style.position = "absolute";
div.style.left = "100";
div.style.top = "150";
div.style.width = "20px";
div.style.height = "20px";
div.style.backgroundColor = "red";

document.body.appendChild(div);

}
}

// drap and drop to move DIV, credit of Garrett Smith

function mousedownHandler(ev) {
var target = getEventTarget(ev),draggable = findDraggableAncestor
(target);
if(draggable) {
activeDragObject = draggable;
}
}
document.onmousedown = mousedownHandler;

function mousemoveHandler(ev) {
if(!activeDragObject) return;
var coords = getEventCoords(ev), ePageX = eventCoords.x, ePageY =
eventCoords.y,
distX = ePageX - mousedownX,
distY = ePageY - mousedownY;
}
document.onmousemove = mousemoveHandler;

function mouseupHandler(ev) {
activeDragObject = null;
}
document.onmouseup = mouseupHandler;

function findDraggableAncestor(target) {
var closestAncestor = document.body;
for(var x = target; x !== closestAncestor; x = x.parentNode) {
if(matchesDragCriteria(x)) {
return x;
}
return null;
}

function getEventCoords(ev) {
// var coords = { x : 0, y : 0 };
var coords = { x : 100, y : 150 };
// find e.pageX/e.pageY or
// (e.clientX/e.clientY + scroll offsets);
return coords;
}

function getEventTarget(ev) {
var ev.target = div;
// var target = div;
activeDragObject = div;
}

</script>

</head>
<body onload="addDot()">
<!--h1>Multi-dimensional view of data sets</h1-->
</body>
</html>
 
D

Don84

It looks like I didn't know how to implement the getEventTarget
function properly.  The code below is not working.  The getEventTarget
function is at the bottom.
....

Silly me, the functions are not fired... hang on for a sec.
 
D

Don84

...

Silly me, the functions are not fired... hang on for a sec.

This is the new code that separate the drag and drop js code into a
separate file and use a reference to it from the calling HTML file.

The html code:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>move objects </title>
<script type="text/javascript" src="drag_n_drop.js"></script>
</head>

<body>
<div id="test1" style="left:200;top:200;width:50;height:100">Hey me
here</div>
<div id="test2" style="left:300;top:300;width:50;height:100">Hey she
there</div>
</body>
</html>

// the drag_n_drop.js file
// other functions stay put (the way as your wrote)
// the two questionable functions
function getEventCoords(ev) {
// var coords = { x : 0, y : 0 };
var coords = { x : 200, y : 200 };
/* if the above code is the initial value and correct then what
about the div id of "test2"
how do we make that div dragable as well? and what if we have more?
hope I'm wrong and your default to 0 for both x and y is correct
*/

// find e.pageX/e.pageY or
// (e.clientX/e.clientY + scroll offsets);
return coords;
}

function getEventTarget(ev) {
var ev.target = div;
// attempt to make generic, so that all div (s) are dragable
// but not working, I don't know what I'm doing ...
// var target = "test1";
activeDragObject = div;
}

Many thanks.
 
G

Garrett Smith

Don84 said:
It looks like I didn't know how to implement the getEventTarget
function properly. The code below is not working.

It was posted as a non-functional outline.

The getEventTarget
function is at the bottom.

My comments are inline.
Many thanks.

You're welcome.
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://
www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

XHTML is not going to offer an advantage.

With HTML 4 you can remove the extra attributes.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>"flowing" objects </title>
<script type="text/javascript">
function addDot() {
var div = document.createElement("div");
if (div)
{
div.className = "mySpecialClass";

css:
..mySpecialClass {
position: absolute;
/* [...] */
}

}

// drap and drop to move DIV, credit of Garrett Smith

Thanks, but you can remove that. Everyone who is reading this knows that
I'm trying to help. I am not writing the code. I am providing an
outline to try to answer your question.

You are going be the one who writes the actual code.

The outline does not address complications that may arise (iframes),
potentially desirable features (whatever they may be), or optimizations
(mousemove throttle).


Based on what you have, you will need to write:
1) getEventTarget
2) getEventCoords
3) matchesDragCriteria

I explain (1) below. (2) is trickier. (3) defines what is draggable.
function mousedownHandler(ev) {
var target = getEventTarget(ev),draggable = findDraggableAncestor
(target);
if(draggable) {
activeDragObject = draggable;
}
}
document.onmousedown = mousedownHandler;

function mousemoveHandler(ev) {
if(!activeDragObject) return;
var coords = getEventCoords(ev), ePageX = eventCoords.x, ePageY =
eventCoords.y,
distX = ePageX - mousedownX,
distY = ePageY - mousedownY;
}
document.onmousemove = mousemoveHandler;

function mouseupHandler(ev) {
activeDragObject = null;
}
document.onmouseup = mouseupHandler;

// if the element the user clicked or one of its ancestors is
// something that can be dragged.
function findDraggableAncestor(target) {
var closestAncestor = document.body;
for(var x = target; x !== closestAncestor; x = x.parentNode) {

// This function is not defined.
if(matchesDragCriteria(x)) {
return x;
}
return null;
}

// Change this function to decide what can be dragged.
function matchesDragCriteria(el) {
// Function "hasClass" is not defined.
return hasClass(el, "mySpecialClass");
}

// This function needs to be fixed to return the actual event coords,
// right now it just returns {x:100, y:150}. You need the actual coords.
function getEventCoords(ev) {
// var coords = { x : 0, y : 0 };
var coords = { x : 100, y : 150 };
// find e.pageX/e.pageY or
// (e.clientX/e.clientY + scroll offsets);
return coords;
}

function getEventTarget(ev) {
var ev.target = div;

No, that should return an HTMLElement. Something like:-
ev = ev || event;
return ev.target || event.srcElement;

[snip rest of code]
 
D

Don84

This is a quick update. I also did some more research for it, and
very anxious to get the basics working first and then figure out
exactly how it works, and yes, have achieved that, very exciting...
thank you so much for getting me started on the right path, will
update if you don't mind.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,085
Messages
2,570,597
Members
47,218
Latest member
GracieDebo

Latest Threads

Top