One, JS drag-and-drop plug-in principle
What is the common drag-and-drop operation? The whole process has a few steps:
1, click the dragged element
2, hold down the mouse, move the mouse
3, drag and drop elements to a certain position, release the mouse
The process here involves three DOM events: Onmousedown,onmousemove,onmouseup. So the basic idea of drag-and-drop is:
1, click the dragged element to trigger onmousedown
(1) To set the drag of the current element to true, indicating that you can drag
(2) to record the coordinates of the current mouse x,y
(3) record the coordinates of the current element x,y
2, move the mouse trigger onmousemove
(1) to determine whether the element can be dragged, if it is, enter step 2, or return directly
(2) If the element can be dragged, set the coordinates of the element
The x coordinate of the
element = The horizontal distance of the mouse movement + element original X coordinate = mouse now x coordinate-mouse before the X coordinate + element original X coordinate
element's Y coordinate = mouse movement transverse distance + element original Y coordinate = mouse now sit on y Superscript-Mouse y-coordinate + element original y-coordinate
3, release mouse trigger OnMouseUp
(1) Set mouse drag state to False
Two, the most basic effect based on the principle
Before implementing the basic effect, there are a few things to note:
1, the element wants to be dragged, and its Postion property must be relative or absolute
2, Getting the coordinates of the mouse through Event.clientx and Event.clienty
3, onmousemove is bound to the document element rather than dragging the element itself, which resolves the problem of delay or stop movement caused by quick drag
The
code is as follows:
Var dragobj = document.getelementbyid ("test");
dragobj.style.left = "0px";
dragobj.style.top = "0px";
var mousex, mousey, objx, objy;
var dragging = false; dragobj.onmousedown = function (event) { event = event | |
window.event;
dragging = true;
dragObj.style.position = "relative";
mouseX = event.clientX;
mouseY = event.clientY;
objx = parseint (DragObj.style.left);
objy = parseint (DragObj.style.top); } document.onmousemove = function (event) { event = event | |
window.event; if (dragging) { Dragobj.style.left&nbsP;= parseint (EVENT.CLIENTX - MOUSEX + OBJX) + "px"; dragobj.style.top = parseint (event.clientY -
 MOUSEY + OBJY) + "px";    &NBSP} document.onmouseup = function () {
dragging = false; }
Third, Code abstraction and optimization
The above code to make plug-ins, to abstract them out, the basic structure is as follows:
; (Function (window, undefined) {
function Drag (ele) {}
window. Drag = Drag;
}) (window, undefined);
The code is wrapped with a self executing anonymous function, internally defining the drag method and exposing it to the global, directly calling drag, and passing in the dragged element.
First, the simple encapsulation of some common methods:
; (function (window, undefined) { var dom = { //Binding Event on: function (Node, eventname, handler) { if (node.addeventlistener) {
node.addeventlistener (Eventname, handler); } else {
node.attachevent ("on" + eventname, handler); } }, //gets the style of the element getStyle: function node, stylename) { var
realstyle = null; if (window.getComputedStyle) {
Realstyle = window.getcomputedstyle (Node, null) [stylename]; } else if (node.currentstyle) { realstyle = node.currentstyle[
StyleName]; } return realStyle;
       &NBSP}, //gets the style of the setting element setCss: function (node, css) {
for (VAR KEY IN CSS) { node.style[key
] = css[key]; }
} }; window.
drag = drag; }) (window, undefined);
in a drag-and-drop operation, there are two objects: the dragged object and the mouse object, we define the following two objects and their corresponding actions:
First drag the object, it contains an element node and drag before the coordinates x and y:
Function dragelement (node) { this.node = node;//dragged element node
this.x = 0;//drag before the x-coordinate this.y = 0;//drag before the y-coordinate} dragelement.prototype = { constructor: dragelement, init: function () { This.setelecss ({ left: ) Dom.getstyle (node, "left"), "Top": dom.getstyle (node, "top")  )
.setxy (Node.style.left, node.style.top);    &NBSP}, //set the current coordinates setxy: function (x, y) { This.x = parseint (x) | |
0; this.y = parseint (y) | |
0;
return this;    &NBSP}, //set the style of the element node setelecss: function (CSS) { dom.setcss (THIS.NODE, CSS)
return this;    &NBSP}}
Another object is the mouse, which contains the x and Y coordinates:
function Mouse () {
this.x = 0;
This.y = 0;
}
Mouse.prototype.setXY = function (x, y) {
this.x = parseint (x);
This.y = parseint (y);
}
This is the two objects defined in the drag-and-drop operation.
If a page can have multiple drag-and-drop elements, what should be noted:
1, each element corresponding to a Drag object instance
2, each page can only have a drag in the element
To do this, we define a single object to save the associated configuration:
var draggableconfig = {
zindex:1,
draggingobj:null,
mouse:new Mouse ()
};
has three properties in this object:
(1) ZIndex: The ZIndex property used to assign to a drag object, when two drag objects overlap, causing the current drag-and-drop object to be blocked, and setting the ZIndex to appear at the top level
(2) Draggingobj: Saves the object being dragged, removing the previous variable used to determine whether it can be dragged, and by draggingobj to determine whether the current can be dragged and the corresponding drag object
(3) Mouse: A unique mouse object that holds information such as the coordinates of the current mouse
Finally binds the Onmousedown,onmouseover,onmouseout event, consolidating the preceding code as follows:
; (function (window, undefined) { var dom = { //Binding Event on: function (Node, eventname, handler) { if (Node.addeventlistener) { node.addeventlistener (eventName,
handler); } else { node.attachevent ("On" + eventName,
handler); } }
, //gets the style of the element getstyle: function (node, stylename) {
var realStyle = null; if (WindOw.getcomputedstyle) { realStyle =
window.getComputedStyle (Node, null) [stylename]; } else if (node.currentstyle) {
realstyle = node.currentstyle[stylename]; }
return realStyle; }, //gets the style of the settings element setcss: function (NODE, CSS) { for (var key in css) {
node.style[key] = css[key];
} }
}; //#region Drag element class function dragelement (node) {
this.node = node; this.x =
0; this.y =
0; } dragelement.prototype = { constructor: dragelement, init: function () { this.setelecss ({ "Left": dom.getstyle (node, "left"), ' top ': dom.getstyle (node, "top")                 &NBSP})
.setxy (Node.style.left, node.style.top);   &NBSP}, setXY: function (x, y) { this.x = parseint (x) | |
0; this.y = parseint (y) | |
0;
return this;                &NBSP}, setelecss: function (CSS) { dom.setcsS (THIS.NODE, CSS);
return this; } } //#endregion // #region Mouse Element function mouse () { this.x
= 0; this.y =
0; } mouse.prototype.setxy = function (x, y) {
this.x = parseint (x); this.y =
parseint (y); } //#endregion //drag and drop configuration var draggableconfig = { zindex: 1, draggingobj: null, mouse: new mouse () }; function drag (ele) { this.ele =
ele; function MouseDown (event) { var ele = event.target | |
event.srcElement;
draggableconfig.mouse.setxy (Event.clientx, event.clienty); draggableconfig.draggingobj = new dRagelement (ele); draggableconfig.draggingobj .setxy (ele.style.left, Ele.style.top) .setelecss ({ "ZIndex": draggableconfig.zindex++, "position": "relative" }); } ele.onselectstart = function () { //prevents text in the object from being selected
return false; } dom.on (ele, "
MouseDown ", mousedown); } &nbsP; dom.on (document, "MouseMove", function (event) { if (draggableconfig.draggingobj) { var mouse = Draggableconfig.mouse, draggingObj =
Draggableconfig.draggingobj; draggingobj.setelecss ({ "Left": parseint (Event.clientx - mouse.x + d raggingobj.x) + "px", "Top": parseint (Event.clienty  - MOUSE.Y + DRAGGINGOBJ.Y) + "px"
}); }          &NBSP}) dom.on (document, "MouseUp", function (event) { draggableconfig.draggingobj
= null;            &NBSP}) &nbsP;window.
drag = drag;        &NBSP}) (window, undefined);
Call method: Drag (document.getElementById ("obj"));
Note that in order to prevent text from being selected in the dragged element, return false through the Onselectstart event handler to handle the problem.
Iv. Expansion: Effective drag-and-drop elements
Some of our common drag-and-drop effects are likely to be this:
The top of the frame is able to drag and drop operation, the content area is not dragged, how to achieve this effect:
First, optimize the drag-and-drop element object as follows, adding a target element target, which means the dragged object, in the login box above, is the entire login window.
The drag element that is logged and set coordinates is the target element, but it is not a valid part of the entire part that is dragged. We add Class draggable in the HTML structure for the dragged active area to effectively drag regions:
<div id= "obj1" class= "dialog" style= "position:relative;left:50px" >
<div class= "header draggable" >< c2/> Drag effective elements
</div>
<div class= "Content" >
drag Objects 1
</div>
&L T;/div>
Then modify the drag method as follows:
Function drag (ele) { var dragNode = (Ele.queryselector (". Draggable ") | |
ele); dom.on (dragnode, "MouseDown", function (event) { var dragelement = draggableconfig.dragelement = new
dragelement (ele); draggableconfig.mouse.setxy (Event.clientX, event.clientY)
; draggableconfig.dragelement .setxy (dragelement.target.style.left, DragElement.target.style.top) Settargetcss ({ "ZIndex": draggableconfig.zindex++, "position": "relative"
}); &NBSP;&NBSP;&NBSP;&NBSP}). On (dragnode, "MouseOver", function () {
dom.setcss (this, draggablestyle.dragging); &NBSP;&NBSP;&NBSP;&NBSP}). On (dragnode, "Mouseout", function () {
dom.setcss (This, draggablestyle.defaults);
}); }
The main modification of
is that the node that is bound MouseDown becomes a valid element that contains the Draggable class, and the entire element is a valid element if it does not contain draggable.
V, performance tuning and summarization
Because onmousemove is calling, there are some performance issues that we can delay by settimout to bind onmousemove events. The improved move function is the following
Function move (event) { if (draggableconfig.dragelement) { var mouse = draggableconfig.mouse,
dragElement = draggableConfig.dragElement; dragelement.settargetcss ({ "Left": parseint (event.clientx - mouse.x + Dragelement.x) + "px", "top": parseint (EVENT.CLIENTY&NBSP;-&NBSP;MOUSE.Y&NBSP;+&NBSP;DRAGELEMENT.Y) + "px"
});
dom.off (document, "MouseMove", move); settimeout (function () { &Nbsp; dom.on (document, "MouseMove", move);
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;},&NBSP;25); &NBSP;&NBSP;&NBSP;&NBSP}}
Summary:
The implementation of the entire drag-and-drop plug-in is actually very simple, mainly to pay attention to some of the
1, the realization of the idea: the element drag position change is equal to the mouse change distance, the key is to get the mouse changes and elements of the original coordinates
2, settimeout to delay loading of onmousemove events to provide performance
six, jquery plug-ins
Simply encapsulate it as a jquery plug-in, primarily by replacing the associated Dom method with the JQuery method to manipulate the
; (function ($, window, undefined) { //#region Drag element class function dragelement (node) {
this.target = node; node.onselectstart = function () { //prevents text in the object from being selected
return false; } dragelement.prototype = { constructor: Dragelement, setXY: function (x, y) { this.x = parseint (x) | |
0; &Nbsp; this.y = parseint (y) | |
0;
return this; }, settargetcss : function (CSS) { $ (
this.target). css (CSS);
return this;
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}  } //#endregion //#region Mouse element function mouse () {
this.x = 0;
this.y = 0; &NBSP;&NBSP;&NBSP;&NBSP} Mouse.prototype.setXY = function (X, y) { this.x = parseint (x);
this.y = parseint (y); &NBSP;&NBSP;&NBSP;&NBSP} //#endregion //Drag and drop configuration
var draggableconfig = { zindex: 1, dragelement: null,
mouse: new mouse () }; var draggablestyle = {
dragging: { cursor: "Move" }, defaults: { cursor: "Default" &NBSP;&NBSP;&NBSP;&NBSP} var $document = $ (document); function drag ($ele) { var
$dragNode = $ele. Find (". draggable"); $dragNode = $dragNode. length > 0
$dragNode : $ele;
$dragNode. On ({ "MouseDown": function (Event ) { var
dragelement = draggableconfig.dragelement = new dragelement ($ele. Get (0));
DraggableConfig.mouse.setXY (Event.clientx, event.clienty); Draggableconfig.dragelement .setxy (dragelement.target.style.left, DragElement.target.style.top) .settargetcss ({ "ZIndex": draggableconfig.zindex++, "position": "relative" })
; }, "MouseOver": function () { $ (This)
. CSS (draggablestyle.dragging); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}, "Mouseout": function () {
$ (this). CSS (draggablestyle.defaults); } &NBSP;&NBSP})  } function move (event) { if (draggableconfig.dragelement) { var mouse = draggableconfig.mouse, &NBsp; dragelement
= draggableconfig.dragelement; dragelement.settargetcss ({ "Left": parseint ( Event.clientx - mouse.x + dragelement.x) + "px", "Top": parseint (event.clienty - &NBSP;MOUSE.Y&NBSP;+&NBSP;DRAGELEMENT.Y) + "px"
});
$document. Off ("MouseMove", move);
settimeout (function () { $document. On ("MouseMove", move);
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;},&NBSP;25); &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}  } $document. On ({ "MouseMove": move, "MouseUp": function () {
draggableConfig.dragElement = null;
} }); $.fn.drag = function (options) {
drag (this); &NBSP;&NBSP;&NBSP;&NBSP}}) (jquery, window, undefined)
jquery Drag-and-drop plug-ins
has always been very confusing to the location of JS get elements: A client, an offset, a scroll.
plus the major browsers are not compatible, alas, make the elder brother Dizzy.
and many page effects use these locations. You have to practice, you have to remember.
Let's say this simple drag-and-drop plug-in based on jquery. &NBSP
By convention, let's talk about the principle of drag-and-drop, and the steps of doing this:
What is drag? See the name to know: is to drag a dongdong to drag. Put it on our dom and change its position.
It has only two difficulties: 1, how to know is in tow? 2, how to know where to drag, dragged to where?
In fact, this is not difficult, after all, both are the basis of things, the key is skilled.
into JS, we have a drag-and-drop effect, roughly the following steps:
1, let elements capture events (in general, nothing more than MouseDown, MouseMove, MouseUp)
2, when MouseDown, The tag starts dragging, and gets the position of the element and mouse.
3, in the MouseMove, constantly get the new location of the mouse, and through the corresponding location algorithm, to reposition the element position.
4, in the MouseUp, the end of drag ... And then the cycle.
In the middle, a place to note: The dragged element needs to be positioned at least relative or absolute, otherwise the drag will not be effective.
OK, no more, no code, no truth. The corresponding explanation is in it:
<! 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 "> <head> <meta http-equiv= "Content-type" content= "Text/html; charset=utf-8"/> <title >Jeremy - DragDrop Test !</title> <meta name= "keywords" content= "JavaScript Free Drag class" /> <script type= "Text/javascript" src= "Jquery-1.4.2.min.js" > </script> <script type= "Text/javascript" > (function ($) { $.extend ({ //get mouse Current coordinates mousecoords:function (EV) { if (ev.pageX | | ev.pagey) { return {x: Ev.pagex,&nbsP;y:ev.pagey};} return { x:ev.clientx + document.body.scrollleft - document.body.clientleft , y:ev.clientY + Document.body.scrolltop - document.body.clienttop
};
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP}, //get style value getstyle:function (obj,styleName) { return Obj.currentstyle ? obj.currentstyle[stylename] : document.defaultview.getcomputedstyle (obj
, null) [StyleName]; return obj.currentstyle ? obj.currentstyle[stylename] :
Document.defaultView.getComputedStyle (Obj,null). GetPropertyValue (StyleName); } &NBSP}); // element Drag plug-in $. Fn.dragdrop = function (options) {
var opts = $.extend ({},$.fn.dragdrop.defaults,options); return this.each (function () { //whether you are dragging var bDraging = false; //Moving elements &NBSP;&NBSP;&NBSp; var
moveele = $ (this);
//click which element to trigger the move. //this element needs to be a child element of the moved element (such as a caption, etc.) var focuele = opts.focuele ? $ (
Opts.focuele,moveele) : moveEle ; if (!focuele | | focuele.length<=0) { alert (' focuEle is not found! the element must be a child of '
+this.id); return
False } // initdiffx| The distance between the mouse and the origin of the moved element when the y : is initially // movex| When y : move, the moved element locates position (new mouse position and initdiffx| Y's difference)
// if a callback function in move is defined, the object will pass in the callback function as a parameter. &NBSP;&NBSP;VAR&NBSP;DRAGPARAMS&NBSP;=&NBSP;{INITDIFFX: ', Initdiffy: ', MoveX: ', Movey: '}; //are moved elements, you need to set the positioning style, otherwise the drag effect will not work.
moveele.css ({' position ': ' absolute ', ' left ': ' 0 ', ' top ': ' 0 '}); When //clicks, record mouse position //dom Writing:
getElementById (' * * * '). Onmousedown= function (event); focuele.bind (' MouseDown ', function (e) { //Mark starts moving bdraging = true; //Change Mouse Shape
&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;MOVEELE.CSS ({' cursor ': ' Move '}); //capture Events. (This usage, also has the advantage, is prevents the movement too quickly causes the mouse to run outside the moved element) if (Moveele.get (0). setCapture) { moveele.get (0). SetCapture (); } //(actually the distance of the mouse's current position relative to the origin of the moved element) // dom: (ev.clientx + Document.body.scrollleft - document.body.clientleft) - document.getelementbyid (' * * *).
Style.left; dragparams.initdiffx = $.mousecoords (E).
X - moveele.position (). Left;
Dragparams.initdiffy = $.mousecoords (E). Y - moveele.position (). Top; }); //Mobile Process focuele.bind (' MouseMove ', function (e) { if (bdraging) { //the new position of the element being moved, in fact the difference between the current mouse position and the original position
//actually, the new position of the moved element can also be directly the mouse position, which can also manifest drag, but the position of the element is not accurate.
Dragparams.movex = $.mousecoords (e) .x - dragparams.initdiffx;
dragparams.movey = $.mousecoords (e) .y - dragparams.initdiffy;
//whether to restrict movement in a region. //fixarea format: [x axis minimum value, X-axis maximum, y-axis minimum, y-axis maximum] if ( Opts.fixarea) &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBsp; { if (dragparams.movex<opts.fixarea[0]) { dragparams.movex=opts.fixarea[0] }
if (Dragparams.movex>opts.fixarea[1]) { &NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;&NBSP;DRAGPARAMS.MOVEX=OPTS.FIXAREA[1] }
if (Dragparams.movey<opts.fixarea[2]) { DRAGPARAMS.MOVEY=OPTS.FIXAREA[2] } if (Dragparams.movey>opts.fixarea[3] ) { DRAGPARAMS.MOVEY=OPTS.FIXAREA[3] } } //Move direction: can be unqualified, vertical, level. if (opts.dragDirection== ' All ') { //dom: document.getelementbyid (' * * *). Style.left = ' ***px '; moveele.css ({' Left ':d ragparams.movex, ' top ':
Dragparams.movey}); } else if (opts.dragdirection== ' vertical ') {
Moveele.css ({' Top ':d Ragparams.movey}); } else if (opts.dragdirection== ' horizontal ') {&NBSP;&NBsp;
moveele.css ({' Left ':d Ragparams.movex}); } //If there is a callback if (Opts.callback) { //Dragparams as a parameter pass
opts.callback.call (Opts.callback,dragparams);
} }
}); //when mouse is bouncing, mark to cancel move focuele.bind (' MouseUp ', function (e) {
bDraging=false; moveele.css ({' CUrsor ': ' Default '}); if (MoveEle.get (0). releasecapture) {
moveele.get (0). ReleaseCapture (); }
});
});
}; //Default configuration $.fn.dragdrop.defaults = { focuEle:null, //Click which element to start dragging, can be empty.
is not empty, a child element of the element being dragged is required. callback:null,
//the callback that is triggered when dragging. dragdirection: ' All ', //drag direction: [' All ', ' vertical ', ' horizontal '] fixarea:null //restrict which area to drag and provide [Minx,maxx,miny,maxy] in array form
};
(jQuery); // test $ (function () {//qualified region, with callback function. $ (' #dragDiv '). DragDrop ({fixarea:[0,$ (' #dragContainer '). Width () -50,0,$ (' #dragContainer '). Height () -50],callback:function (params) { $ (' #span1 '). Text (' X: '
+params.movex+ ' y: ' +params.movey);
}}); Default Settings $ (' #dragDiv1 '). DragDrop ();
}); </script> </head> <body> <div id= "Dragcontainer" style= "Position:relative;left :10px;top:10px;border:1px dashed blue;width:500px;height:500px; " > <div id= "dragdiv" style= "background-color:blue;height:50px;width:50px;" > </div> <div id= "dragDiv1" style= "border:1px solid red;height:50px;width:50px;" > </div> </div> <span id= "Span1" ></span></body> </html>