Draggable Elements element Drag function to implement code _JAVASCRIPT skills

Source: Internet
Author: User
Of course, we can study the source of JS library, you can also try to invent the wheel, the process is still very interesting ... Below I will implement the next page element drag and drop function
Let's start with implementation now, starting with the top-level approach, which is used to initialize a drag object, and the method's declaration is as follows
function Dragobject (CFG)
Here's the CFG we use an object to pass in, sort of like ExtJS. Configuration Properties
Copy Code code as follows:

var dragobj = new Dragobject ({
El: ' Exampleb ',
Attachel: ' Examplebhandle ',
Lowerbound:new Position (0, 0),//position represents a point, there are attributes x,y the following details
Upperbound:new Position (500, 500),
Startcallback:.,//Start dragging when the callback is triggered here are omitted
Movecallback: ...,//The callback triggered during the drag process
Endcallback: ...,//drag end Trigger callback
Attachlater: ...//whether to start the monitoring of the drag-and-drop event immediately
});

The configuration parameter El can be the ID of a specific element, or it can be directly a DOM object Attachel is an example of the handle element, drag it to drag the element, lowerbound and upperbound are used to limit the drag range, are position objects, About the encapsulation and function of this object we will analyze the following, not anxious ha:, if not, there is no restriction on the scope of the drag. Startcallback, Movecallback, endcallback are all callback functions, Attachlater true or false. If you are not very clear on the following analysis, I think you will be clear soon.
Here's how to write the position code as follows:
Copy Code code as follows:

function Position (x, y) {
This. x = x;
Thix. y = y;
}
Position.prototype = {
Constructor:position,
Add:function (val) {
var newpos = new Position (this. X, this. Y);
if (val) {
Newpos.x = val. X
Newpos.y = val. Y
}
return newpos;
},
Subtract:function (val) {
var newpos = new Position (this. X, this. Y);
if (val) {
Newpos.x-= val. X
Newpos.y-= val. Y
}
return newpos;
},
Min:function (val) {
var newpos = new Position (this. X, this. Y);
if (val) {
Newpos.x = this. X > val. X? Val. X:this. X
Newpos.y = this. Y > val. Y? Val. Y:this. Y
return newpos;
}
return newpos;
},
Max:function (val) {
var newpos = new Position (this. X, this. Y);
if (val) {
Newpos.x = this. X < Val. X? Val. X:this. X
Newpos.y = this. Y < Val. Y? Val. Y:this. Y
return newpos;
}
return newpos;
},
Bound:function (lower, Upper) {
var newpos = This.max (lower);
return Newpos.min (upper);
},
Check:function () {
var newpos = new Position (this. X, this. Y);
if (isNaN (newpos.x))
newpos.x = 0;
if (isNaN (NEWPOS.Y))
Newpos.y = 0;
return newpos;
},
Apply:function (EL) {
if (typeof el = = ' string ')
El = document.getElementById (EL);
if (!el) return;
El.style.left = this. X + ' px ';
El.style.top = this. Y + ' px ';
}
};

A simple encapsulation of a coordinate point that holds two values: x, y coordinates. We can use the add and Substract methods to perform + operations and-operations with other coordinates, returning a computed new coordinate point. The Min and Max functions, as the name suggests, are used to compare to other coordinate points and return smaller and larger values. The bound method returns a coordinate point within a bounded range. The check method is used to ensure that the value of the property x, Y is a numeric type, otherwise 0 is placed. The final apply method is to apply the attribute x,y to the element style.left and top. Then I took out most of the rest of the code and looked at it 1.1 more:
Copy Code code as follows:

function Dragobject (CFG) {
var el = Cfg.el,
Attachel = Cfg.attachel,
Lowerbound = Cfg.lowerbound,
Upperbound = Cfg.upperbound,
Startcallback = Cfg.startcallback,
Movecallback = Cfg.movecallback,
Endcallback = Cfg.endcallback,
Attachlater = Cfg.attachlater;
if (typeof el = = ' string ')
El = document.getElementById (EL);
if (!el) return;
if (lowerbound!= undefined && upperbound!= undefined) {
var temppos = lowerbound.min (upperbound);
Upperbound = Lowerbound.max (upperbound);
Lowerbound = Temppos;
}
var cursorstartpos,
Elementstartpos,
dragging = False,
Listening = False,
disposed = false;
function DragStart (EVENTOBJ) {
if (dragging | |!listening | | disposed) return;
dragging = true;
if (Startcallback)
Startcallback (EVENTOBJ, EL);
Cursorstartpos = Absolutecursorposition (EVENTOBJ);
Elementstartpos = new Position (parseint (GetStyle (El, ' left ')), parseint (GetStyle (el, ' top '));
Elementstartpos = Elementstartpos.check ();
Hookevent (document, ' MouseMove ', Draggo);
Hookevent (document, ' MouseUp ', dragstophook);
return CancelEvent (EVENTOBJ);
}
function Draggo (e) {
if (!dragging | | disposed) return;
var newpos = absolutecursorposition (e);
Newpos = Newpos.add (Elementstartpos)
. Subtract (Cursorstartpos)
. Bound (lowerbound, upperbound);
Newpos.apply (EL);
if (Movecallback)
Movecallback (Newpos, EL);
return CancelEvent (e);
}
function Dragstophook (e) {
DragStop ();
return CancelEvent (e);
}
function DragStop () {
if (!dragging | | disposed) return;
Unhookevent (document, ' MouseMove ', Draggo);
Unhookevent (document, ' MouseUp ', dragstophook);
Cursorstartpos = null;
Elementstartpos = null;
if (Endcallback)
Endcallback (EL);
dragging = false;
}
this.startlistening = function () {
if (Listening | | disposed) return;
listening = true;
Hookevent (Attachel, ' MouseDown ', dragstart);
};
this.stoplistening = function (stopcurrentdragging) {
if (!listening | | disposed)
Return
Unhookevent (Attachel, ' MouseDown ', dragstart);
listening = false;
if (stopcurrentdragging && dragging)
DragStop ();
};
This.dispose = function () {
if (disposed) return;
This.stoplistening (TRUE);
el = null;
Attachel = null;
Lowerbound = null;
Upperbound = null;
Startcallback = null;
Movecallback = null;
Endcallback = null;
disposed = true;
};
this.isdragging = function () {
return dragging;
};
this.islistening = function () {
return listening;
};
this.isdisposed = function () {
return disposed;
};
if (typeof Attachel = = ' String ')
Attachel = document.getElementById (Attachel);
If it is not configured, or if the DOM object is not found, use the El
if (!attachel) Attachel = El;
if (!attachlater)
This.startlistening ();
}

Some of them do not give the method, in the downward analysis of the process, will be given ....
We first use the CFG to make El and Attachel point to the actual Dom object, or El instead if the Attachel is not configured or the corresponding element is not found. We also set up some variables to use in the drag. Cursorstartpos is used to save the mouse's coordinate point when the mouse is pressed to start dragging. Elementstartpos is used to save the starting point at which elements start dragging. Dragging, listening, disposed are some state variables. Listening: refers to whether the drag object is listening for drag-and-drop start events. Dragging: Whether the element is being dragged. Disposed:drag object is cleared and can no longer be dragged.
At the end of the code, we see that if Attachlater is not true, then call Startlistening, which is a public method defined in drag object, let's look at its implementation
Copy Code code as follows:

this.startlistening = function () {
if (Listening | | disposed) return;
listening = true;
Hookevent (Attachel, ' MouseDown ', dragstart);
};

The first two lines is to make a judgment, if you have begun to drag and drop events to monitor or clean up, nothing to do direct return. Otherwise, the listening state is set to true, indicating that we started listening, associating the DragStart function with the Attachel MouseDown event. Here's a hookevent function, and we'll look at it like this:
Copy Code code as follows:

function Hookevent (EL, EventName, callback) {
if (typeof el = = ' string ')
El = document.getElementById (EL);
if (!el) return;
if (El.addeventlistener)
El.addeventlistener (EventName, callback, false);
else if (el.attachevent)
El.attachevent (' on ' + EventName, callback);
}

In fact, there is nothing, that is, the interception of element events to do a cross-browser package, the same unhookevent method is as follows
Copy Code code as follows:

function Unhookevent (EL, EventName, callback) {
if (typeof el = = ' string ')
El = document.getElementById (EL);
if (!el) return;
if (El.removeeventlistener)
El.removeeventlistener (EventName, callback, false);
else if (el.detachevent)
El.detachevent (' on ' + EventName, callback);
}

Then let's look at the implementation of the DragStart function, which is a private function of drag object
Copy Code code as follows:

function DragStart (EVENTOBJ) {
if (dragging | |!listening | | disposed) return;
dragging = true;
if (Startcallback)
Startcallback (EVENTOBJ, EL);
Cursorstartpos = Absolutecursorposition (EVENTOBJ);
Elementstartpos = new Position (parseint (GetStyle (El, ' left ')), parseint (GetStyle (el, ' top '));
Elementstartpos = Elementstartpos.check ();
Hookevent (document, ' MouseMove ', Draggo);
Hookevent (document, ' MouseUp ', dragstophook);
return CancelEvent (EVENTOBJ);
}

This function is called when the DOM object referred to by Attachel captures the MouseDown event. First we determine the drag object in a suitable drag-and-drop state, if the drag is in progress, or not in the monitoring of drag-and-drop events, or have handled the "funeral", then do nothing. If all is OK, we set the dragging state to true and then "started", and if startcallback is defined, we call it down to MouseDown event and El as parameters. Then we locate the absolute position of the mouse and save it in the Cursorstartpos. Then get the drag-and-drop element's current top, left, encapsulated as a position object saved to the Elementstartpos. For the sake of insurance, we check whether the property is legal in the Elementstartpos. Look at the two hookevent calls, one is the MouseMove event, which means that the Draggo function is being dragging. One is the MouseUp event, which represents the end of the drag, and calls the Dragstophook function. You may ask why events are tied to the document, not to the elements being dragged, such as El or Attachel. Because, given the direct binding of events to elements, It is possible that some delay in the browser will affect the effect, so directly bind the event to the document. If it is not very understanding, perhaps the impact is not small: P .... Look at the CancelEvent in the last sentence (EVENTOBJ)
Copy Code code as follows:

function CancelEvent (e) {
E = e? E:window.event;
if (e.stoppropagation)
E.stoppropagation ();
if (E.preventdefault)
E.preventdefault ();
E.cancelbubble = true;
E.returnvalue = false;
return false;
}

Used to stop bubbling, to block the default event, which can be understood as security considerations .... In DragStart some methods need to introduce, first look at Absolutecursorposition, and then look at GetStyle
Copy Code code as follows:

function Absolutecursorposition (e) {
E = e? E:window.event;
var x = e.clientx + (document.documentelement | | document.body). scrollleft;
var y = e.clienty + (document.documentelement | | document.body). scrolltop;
return new Position (x, y);
}

This method is only used to obtain the mouse in the browser absolute position, the scroll bar to consider the line
Copy Code code as follows:

function GetStyle (El, property) {
if (typeof el = = ' string ')
El = document.getElementById (EL);
if (!el | |!property) return;
var value = El.style[property];
if (!value) {
if (Document.defaultview && document.defaultView.getComputedStyle) {
var css = Document.defaultView.getComputedStyle (EL, null);
Value = CSS? Css.getpropertyvalue (property): null;
else if (El.currentstyle) {
Value = El.currentstyle[property];
}
}
return value = = ' Auto '? ': value;
}

The GetStyle method is used to get the CSS property value of the element so that regardless of whether your style is written inline or defined in CSS, we can get the correct value, of course we just get the top of the element, left property. Here's how to really handle drag and drop work Draggo
Copy Code code as follows:

function Draggo (e) {
if (!dragging | | disposed) return;
var newpos = absolutecursorposition (e);
Newpos = Newpos.add (Elementstartpos)
. Subtract (Cursorstartpos)
. Bound (lowerbound, upperbound);
Newpos.apply (EL);
if (Movecallback)
Movecallback (Newpos, EL);
return CancelEvent (e);
}

This method is not complicated, like any other method, we first look at the status of the next, if not in the drag or have been cleaned, then do nothing. If all goes well, we use the current position of the mouse, the initial position of the element, the initial position of the mouse, and the limited range (if configured Upperbound, lowerbound) to compute a result point, By using the Apply method we assign the calculated coordinates to element style.top and Style.left, so that the drag element determines its position. If you configure the Movecallback, then call the next, finally a cancelevent ... The new coordinate operation here is similar to the operation of jquery, because each method of the Position object returns a position to the image ... there's another way in DragStart Dragstophook
Copy Code code as follows:

function Dragstophook (e) {
DragStop ();
return CancelEvent (e);
}
function DragStop () {
if (!dragging | | disposed) return;
Unhookevent (document, ' MouseMove ', Draggo);
Unhookevent (document, ' MouseUp ', dragstophook);
Cursorstartpos = null;
Elementstartpos = null;
if (Endcallback)
Endcallback (EL);
dragging = false;
}

The key to look at the DragStop method, the same first judge the state, all OK, we remove the binding MouseMove and MouseUp, and the Cursorstartpos and Elementstartpos values released, a drag-and-drop end. If Endcallback is configured, it is called, and the dragging state is set to false ... Finally, the public method that is used is given
Copy Code code as follows:

this.stoplistening = function (stopcurrentdragging) {
if (!listening | | disposed)
Return
Unhookevent (Attachel, ' MouseDown ', dragstart);
listening = false;
if (stopcurrentdragging && dragging)
DragStop ();
};
This.dispose = function () {
if (disposed) return;
This.stoplistening (TRUE);
el = null;
Attachel = null;
Lowerbound = null;
Upperbound = null;
Startcallback = null;
Movecallback = null;
Endcallback = null;
disposed = true;
};
this.isdragging = function () {
return dragging;
};
this.islistening = function () {
return listening;
};
this.isdisposed = function () {
return disposed;
};

Stoplistening removes the Listener drag MouseDown event, sets the listener state listening to false, and here is a parameter stopcurrentdragging known as the name. Dispose method for some processing work, if you do not want to let drag object can be dragged, then call the dispose of it, as the following three small methods isdragging, islistening, isdisposed a look will know, Returns the associated state. Finally to the source of the next zipper download point I welcome Park friends Message, Exchange!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.