Javascript drag-and-drop effect implementation code

Source: Internet
Author: User

There are many reasons for you to add the drag-and-drop feature to the page. The simplest reason is to reorganize data. For example, you may want users to reorganize a series of page elements and put an input or select component next to each element to represent their order, it is an alternative solution to allow drag and drop of elements in the group. Or you may want to have a navigation window that can be moved by users on your website. These are simple reasons for using the drag-and-drop function, because you can implement it!
The drag-and-drop effect on your web page is not very complex. First, we know the mouse position, and then we need to know when the user clicks an element, so that we know that we want to start dragging it, and finally we want to move this element.

Capture mouse movement
In the first step, we need to obtain the coordinates of the mouse. This function can be implemented through a function and assigned to document. onmousemove:

CodeCopy codeThe Code is as follows: document. onmousemove = mouseMove;
Function mouseMove (ev ){
Ev = ev | window. event;
Var mousePos = mouseCoords (ev );
}
Function mouseCoords (ev ){
If (ev. pageX | ev. pageY ){
Return {x: ev. pageX, y: ev. pageY };
}
Return {
X: ev. clientX + document. body. scrollLeft-document. body. clientLeft,
Y: ev. clientY + document. body. scrollTop-document. body. clientTop
};
}

First, we need to explain the event object. Whenever you move, click, or press a button, an event will happen. In IE, this event is global and stored in window. event. For Firefox and Its browsers, this event will be passed to any function pointing to this page action. Therefore, we make document. onmousemove point to the function that moves the mouse, and the function that moves the mouse gets the event object.
In the above Code, ev contains the event object in all browser environments. In Firefox, "| window. event" is ignored because it already contains events. In IE, the ev value is empty so that you need to set it to window. event.
In this article, we need to capture the coordinates of the mouse multiple times. Therefore, we have written a mouseCoords method, which has a parameter: event.
We will discuss again the differences between IE and other browsers. Firefox and other browsers use event. pageX and event. pageY to indicate the location of the mouse relative to the document. If you have a 500*500 window, And the mouse is in the middle of the window, the pageX and pageY values will be 250. If you scroll down the window to 500 pixels, The pageY value is 750.
On the contrary, Microsoft's IE uses event. clientX and event. clientY to indicate the position of the mouse relative to the window, rather than the current document. In the same example, if you place the cursor in the middle of the 500*500 window, the clientX and clientY values are both 250. If you scroll down the page, clientY will still be 250, because it is measured relative to the window, rather than the current document. Therefore, we should introduce the scrollLeft and scrollTop attributes of the document body area in the mouse position. Finally, the document in IE is not actually at (0, 0), and there is a small (usually 2 px) border around it, document. body. clientLeft and document. body. clientTop contains the Border width, so you need to introduce them in the mouse position.
Fortunately, we now have the mouseCoords function, so we don't have to worry about getting the mouse position.

Capture mouse clicks
Next, we must know when the mouse is clicked and when it is released. If we skip this step, as long as you move the mouse over these elements, it will produce the effect of dragging these elements, which is annoying and contrary to human intuition.
Here, there are two functions that can help us: onmousedown and onmouseup. Previously, we have directed document. onmousemove to a function. Therefore, we should logically point both document. onmousedown and document. onmouseup to the function. If we point document. onmousedown to a function, the function will execute text, images, tables, and so on by clicking any element. We only want the specific elements on the page to have the drag-and-drop function. Therefore, we can achieve this through the following methods:

CodeCopy codeThe Code is as follows: document. onmouseup = mouseUp;
Var dragObject = null;
Function makeClickable (object ){
Object. onmousedown = function (){
DragObject = this;
}
}
Function mouseUp (ev ){
DragObject = null;
}

We now have a variable dragObject that contains any elements you click. When you release the mouse, dragObject is set to null, so that when dragObject is not empty, we need to drag the operation.

Move Element
We now know how to capture mouse movement and click. What we need to do next is to move any element we want to drag. First, move an element to the desired position on the page. The position value of the element style table must be absolute, which means you can set its style. top or style. left: The measurement value is relative to the upper left corner of the page, because all our mouse moves are relative to the upper left corner of the page. This is usually the case.
Once we set item. style. position = 'absolute ', we need to change the top and left positions of the element to move it!

CodeCopy codeThe Code is as follows: document. onmousemove = mouseMove;
Document. onmouseup = mouseUp;
Var dragObject = null;
Var mouseOffset = null;
Function getMouseOffset (target, ev ){
Ev = ev | window. event;
Var docPos = getPosition (target );
Var mousePos = mouseCoords (ev );
Return {x: mousePos. x-docPos. x, y: mousePos. y-docPos. y };
}
Function getPosition (e ){
Var left = 0;
Var top = 0;
While (e. offsetParent ){
Left + = e. offsetLeft;
Top + = e. offsetTop;
E = e. offsetParent;
}
Left + = e. offsetLeft;
Top + = e. offsetTop;
Return {x: left, y: top };
}
Function mouseMove (ev ){
Ev = ev | window. event;
Var mousePos = mouseCoords (ev );
If (dragObject ){
DragObject. style. position = 'absolute ';
DragObject. style. top = mousePos. y-mouseOffset. y;
DragObject. style. left = mousePos. x-mouseOffset. x;
Return false;
}
}
Function mouseUp (){
DragObject = null;
}
Function makeDraggable (item ){
If (! Item) return;
Item. onmousedown = function (ev ){
DragObject = this;
MouseOffset = getMouseOffset (this, ev );
Return false;
}
}

You will notice that the Code is based on the previous example (refer to the previous article). Place them together and you will be able to move the elements at will.
When we click an element, another variable, mouseOffset, is stored. MouseOffset simply contains the position information of the clicked element. If we have a 20*20 PX image and click in the middle of the image, the mouseOffset should be {x: 10, y: 10 }. If we click the upper left corner of the image, the mouseOffset should be {x: 0, y: 0 }. We use it in the position information after the mouse moves. If we do not store this value, no matter where you click the element, the element will be the same as the mouse position.
The mouseOffset function uses another function getPosition. GetPosition is used to return the Coordinate Position of an element relative to the semi-EMT document. If we simply read item. offsetLeft or item. style. left, we get the position of the element relative to its parent element, rather than the document. In our script, all elements are relative to the document, so we need to do this.
To get the position of an element relative to the document, getPosition starts from its parent level and cyclically obtains its left and top values and accumulates them, in this way, we get the cumulative value of the elements we want from the top and left of the document.
When we get this information and move the mouse, mouseMove starts to run. First, we need to ensure that the value of item. style. position is absolute. Then, we move the element to any place and the mouse position minus the offset of the previously recorded mouse relative to the element. When the mouse is released, dragObject is set to null, And the mouseMove function does nothing.

Placement Element
We have handled this problem in the previous example. We just drag an element and put it down. Then, when we put down an element, there is usually another purpose. We take dragging the element to the garbage collection bin as an example, or we may want to align the element with a specific area on the page.
Unfortunately, we have entered a major problem here. Because the elements we are moving are always directly under our mouse, it is impossible to trigger operations on other elements on the page by mouseover, mousedown, mouseup, or mouse. If you move an element to the recycle bin, your mouse will move the element above it instead of the recycle bin.
So how should we deal with this problem? There are several solutions. The purpose of the previously mentioned mouseOffset is to ensure that the elements are always at the right position under the mouse. If you ignore this, the elements are always at the bottom right of the mouse, your mouse will not be hidden by the elements you are dragging, and we will not encounter any problems. But in fact, this is often not the case. We usually need to keep the elements below the mouse for the sake of beauty.
Another option is not to move the elements you are dragging. You can change the mouse style to tell the user that you are dragging an element until you place it somewhere. This solves our problem, but brings us the same problem as the previous solution: appearance.
Our final solution does not affect the elements you are moving or the elements (such as the recycle bin) at the moving end point ). Unfortunately, this is more difficult than the previous two solutions. What we will do is to get a set of targets we want to place. When the mouse is released, we manually check the position of the current mouse relative to each target, check whether the mouse is released on a target. If so, we know that we have placed the elements on our target.

CodeCopy codeThe Code is as follows :/*
All code from the previous example is needed with the exception
Of the mouseUp function which is replaced below
*/
Var dropTargets = [];
Function addDropTarget (dropTarget ){
DropTargets. push (dropTarget );
}
Function mouseUp (ev ){
Ev = ev | window. event;
Var mousePos = mouseCoords (ev );
For (var I = 0; I <dropTargets. length; I ++ ){
Var curTarget = dropTargets [I];
Var targPos = getPosition (curTarget );
Var targWidth = parseInt (curTarget. offsetWidth );
Var targHeight = parseInt (curTarget. offsetHeight );
If (
(MousePos. x> targPos. x )&&
(MousePos. <(targPos. x + targWidth ))&&
(MousePos. y> targPos. y )&&
(MousePos. y <(targPos. y + targHeight ))){
// DragObject was dropped onto curTarget!
}
}
DragObject = null;
}

In this example, when the mouse is released, we loop through each target that may place elements. If the mouse pointer is on the target, we have an event for placing elements, the mouse abscissa is greater than the left abscissa of the target element (mousePos. x> targPos. x), less than the horizontal coordinate (mousePos. x <(targPos. x + targWidth) to determine the Y coordinate. If all these values return true, our mouse is within the range of the target element.

Integrate all functions
Finally, we use all the code snippets to create a complete drag-and-drop function script. The first thing we need to do is DOM operations. If you are not familiar with this, you can read JavaScript Primer on DOM Manipulation.
The following code creates containers and container groups so that each element can be dragged in these containers, which is completed based on the second demo in this article. This code can be used to re-plan the order of elements, place the navigation window on the left or right side of the page, or add other functions you can think.
We will use pseudo-code to explain it step by step, and leave the real code to the reader through comments.
1. When the document is loaded for the first time, we create a DIV tag named dragHelper. When we start to move an element, dragHelper will become a hidden element and can be moved around. The actual elements are not dragged. They are only moved using insertBefore and appendChild. At the beginning, we hid dragHelper.
2. Create the mouseDown and mouseUp functions. At first, all these functions are assumed to record the state of the mouse button, so that the iMouseDown variable is true when the mouse is pressed, and false when the mouse is not pressed.
3. Create a global variable DragDrops and a function CreateDragContainer. DragDrops contains a group of associated containers. Any variable passed in CreateDragContainer (representing the container) is organized into a new set, allowing elements to move freely between these containers. Using setAttribute, The CreateDragContainer function also binds elements in each container.
4. Now our code knows the set where each element is located. Now let's look at the mouseMove function. The mouseMove function first sets a variable target, which indicates the target element under the mouse. If this element is in the Set (determined by getAttribute), continue the following operations:
. First, when necessary, we run a simple script to change the class attribute of the target element, which creates a flip effect.
. Then we check whether the mouse is clicked (because our code has been run here), if the event occurs:
4.2.1. Set the variable curTarget to the current element.
4.2.2. record the position of the element in the document so that it can be retrieved as needed.
4.2.3. Clone the current element to dragHelper so that we can move the hidden backup of the element.
4.2.4. Because we have a backup of the drag element in dragHelper, this element will always be under the mouse. We must remove the dragObj attribute to let the code know that dragObj is no longer in the collection.
4.2.5. We can quickly record the current position, width, and height of each element in the set. When an element is dragged for the first time, we only need to do this kind of work once. Otherwise, we must do it once or even several hundred times in a second whenever the mouse moves.
. If you do not click the mouse, either we have the same target element as before, or we do not have a target element. In either case, we will not do anything.
5. Now let's check the curTarget variable. CurTarget should contain only one dragged object, so if it exists, it indicates that we are dragging an element:
. Move the hidden DIV to the mouse. This element can be dragged like the one created before the article.
. Then we check whether the mouse exists in each container in the current collection.
5.2.1. If you move the mouse over a container, check each element in the container to see where the element we are dragging belongs.
5.2.2. Then we place the dragged element in front of another element in the container, or the last position of the container.
5.2.3. Finally, we confirm that the element is visible.
6. The rest is to capture the mouseUp event:
. First, hide dragHelper: it is no longer needed because we didn't drag anything.
. If the dragged element is visible, it already exists in any container to which it belongs, and all work has been completed.
. If the dragged element is invisible, place it back to its original location.

Related Article

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.