Home > Web Front-end > JS Tutorial > JavaScript drag and drop effect code_javascript skills

JavaScript drag and drop effect code_javascript skills

WBOY
Release: 2016-05-16 18:57:40
Original
1031 people have browsed it

The prototype of this program was created when I was doing image cutting effects. At that time, I referred to several similar effects and learned a lot from muxrwc and BlueDestiny.
Although I feel good every time I sort it out, every once in a while I will find that somewhere can be improved, there is an error somewhere, and certain needs need to be realized, just like the knowledge I learned.
Considering that some people may only need a simple drag and drop, there is a simplified version of SimpleDrag for easy learning.
Effect Preview
ps: If you turn on ad filtering under maxthon, it is likely to be filtered out (I don’t know if there is any way to avoid it).
Program Description
[Program Principle]
Here we take SimpleDrag as an example to explain the basic principles.
First, a drag and drop object is required in the initialization program:

Copy the code The code is as follows:

this.Drag = $(drag);

There are also two parameters to record the coordinates of the mouse relative to the drag and drop object at the beginning:
Copy code The code is as follows:

this._x = this._y = 0;

There are also two event object functions Used to add removal events:
Copy code The code is as follows:

this._fM = BindAsEventListener (this, this.Move);
this._fS = Bind(this, this.Stop);

are the dragging program and the stop dragging program respectively.
The position of the drag-and-drop object must be absolute positioning:
Copy code The code is as follows:

this.Drag.style.position = "absolute";

Finally, bind the Start drag-and-drop program to the mousedown event of the drag-and-drop object:
addEventHandler(this.Drag, "mousedown ", BindAsEventListener(this, this.Start));
When the mouse is pressed on the drag-and-drop object, the Start program will be triggered. It is mainly used to prepare for dragging. Here, the coordinates of the mouse relative to the drag-and-drop object are recorded:
Copy code The code is as follows:

this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop;

And bind the _fM drag program and _fS stop drag program to the mousemove and mouseup events of the document respectively :
Copy code The code is as follows:

addEventHandler(document, "mousemove", this._fM );
addEventHandler(document, "mouseup", this._fS);

Note that the event must be bound to the document to ensure that the event is valid in the entire window document. If it is only bound to the drag and drop object, it is easy to drag too quickly and get out of touch.
When the mouse moves on the document, the Move program will be triggered. Here is the program to implement dragging.
The left and top values ​​that should be set for the drag and drop object can be obtained by the difference between the current coordinate value of the mouse and the relative coordinate value of the mouse when dragging started:
this.Drag.style.left = oEvent.clientX - this._x "px";
this.Drag.style.top = oEvent.clientY - this._y "px";
After finally releasing the mouse, the Stop program is triggered to end the drag and drop.
The main function here is to remove the events added to the document in the Start program:
removeEventHandler(document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this._fS );
Such a simple drag-and-drop program is ready. Let’s talk about other extensions and details.
【Drag and drop lock】
There are three types of locks, namely: horizontal lock (LockX), vertical lock (LockY), and complete lock (Lock).
This is relatively simple. To lock the horizontal and vertical directions, you only need to determine whether it is locked in Move and then set left and top. If it is fully locked, just return directly.
if(!this.LockX){ this.Drag.style.left = ; }
if(!this.LockY){ this.Drag.style.top = ; }
[Trigger object]
The trigger object is used to trigger the drag-and-drop program, which is set through the Handle attribute in the program. Sometimes the entire drag-and-drop object does not need to be used for triggering. In this case, the trigger object is needed.
After using the trigger object, the drag and drop object is still moved, but the trigger object is used to trigger the drag and drop (the general use is to put the trigger object into the drag and drop object).
ps: Another usage of the trigger object is to drag and drop multiple drag and drop objects with one trigger object at the same time by setting the same Handle.
【Range Limitation】
To set a range limit, you must first set Limit to true. There are two types of range restrictions, namely fixed range and container range restrictions, which are mainly set in the Move program.
The principle is that when the compared value exceeds the range, the values ​​to be set for left and top are corrected so that the drag and drop object can remain within the set range.
[Fixed Range Limit]
Container range limit is to specify the drag and drop range of the top, bottom, left, and right.
The meaning of each attribute is:
Top (mxTop): top limit;
Down (mxBottom): top offsetHeight limit;
Left (mxLeft): left limit;
Right (mxRight) :left offsetWidth limit.
If the range setting is incorrect, it may cause the up and down or left and right to exceed the range at the same time. There is a Repair program in the program to correct the range parameters.
The Repair program will be executed in the program initialization and Start program. Correct mxRight and mxBottom in the Repair program:
this.mxRight = Math.max(this.mxRight, this.mxLeft this.Drag.offsetWidth);
this.mxBottom = Math.max(this.mxBottom, this.mxTop this.Drag.offsetHeight);
where mxLeft offsetWidth and mxTop offsetHeight are the minimum range values ​​of mxRight and mxBottom respectively.
Correct the movement parameters according to the range parameters:
iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
iTop = Math.max(Math.min( iTop, mxBottom - this.Drag.offsetHeight), mxTop);
Take a larger value for the upper left side and a smaller value for the lower right side.
【Container scope limitation】
Container scope limitation means to limit the scope to one container_mxContainer.
It should be noted that the drag and drop object must be included in _mxContainer, because the program uses relative positioning to set the container range limit (if it is outside the container, absolute positioning must be used, which will be more troublesome). Also, the container space is larger than the drag-and-drop object, so there is no need to explain this.
The principle is similar to the fixed range limit, except that the range parameters are set according to the attributes of the container.
When a container is set, the Repair program will automatically set position to relative for relative positioning:
!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer .style.position = "relative");
ps: CurrentStyle is used to obtain the final style (see the final style section here for details).
Note that if the left and top of the drag-and-drop object are set before the program is executed but the container is not set to relative, shifting will occur when relative is automatically set, so the program will execute a Repair program during initialization to prevent this situation. Because offsetLeft and offsetTop must be obtained before setting relative to obtain the value correctly, Repair must be executed before setting _x and _y in the Start program.
Due to relative positioning, for the container scope, the upper, lower, left and right values ​​​​of the range parameters are 0, clientHeight, 0, clientWidth respectively.
clientWidth and clientHeight are the width and height of the visible part of the container (refer here for details).
为了容器范围能兼容固定范围的参数,程序中会获取容器范围和固定范围中范围更小的值:
Code
mxLeft = Math.max(mxLeft, 0);
mxTop = Math.max(mxTop, 0);
mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
mxBottom = Math.min(mxBottom, this._mxContainer.clientHeight);
因为设置相对定位的关系,容器_mxContainer设置过后一般不要取消或修改,否则很容易造成移位异常。
【鼠标捕获】
我在一个拖放实例中看到,即使鼠标移动到浏览器外面,拖放程序依然能够执行,仔细查看后发现是用了setCapture。
鼠标捕获(setCapture)是这个程序的重点,作用是将鼠标事件捕获到当前文档的指定的对象。这个对象会为当前应用程序或整个系统接收所有鼠标事件。
使用很简单:
this._Handle.setCapture();
setCapture捕获以下鼠标事件:onmousedown、onmouseup、onmousemove、onclick、ondblclick、onmouseover和onmouseout。
程序中主要是要捕获onmousemove和onmouseup事件。
msdn的介绍中还说到setCapture有一个bool参数,用来设置在容器内的鼠标事件是否都被容器捕获。
容器就是指调用setCapture的对象,大概意思就是:
参数为true时(默认)容器会捕获容器内所有对象的鼠标事件,即容器内的对象不会触发鼠标事件(跟容器外的对象一样);
参数为false时容器不会捕获容器内对象的鼠标事件,即容器内的对象可以正常地触发事件和取消冒泡。
而对于容器外的鼠标事件无论参数是什么都会被捕获,可以用下面这个简单的例子测试一下(ie):
Code


mouseover

<script>document.body.setCapture();</script>


这里的参数是true,一开始body会捕获所有鼠标事件,即使鼠标经过div也不会触发onmousemove事件。
换成false的话,div就可以捕获鼠标事件,就能触发div的onmousemove事件了。
拖放结束后还要使用releaseCapture释放鼠标,这个可以放在Stop程序中:
this._Handle.releaseCapture();
setCapture是ie的鼠标捕获方法,对于ff也有对应的captureEvents和releaseEvents方法。
但这两个方法只能由window来调用,而且muxrwc说这两个方法在DOM2里已经废弃了,在ff里已经没用了。
不过ff里貌似会自动设置取消鼠标捕获,但具体的情形就不清楚了,找不到一个比较详细的介绍,谁有这方面的资料记得告诉我啊。
下面都是我的猜测,ff的鼠标捕获相当于能自动设置和释放的document.body.setCapture(false)。
因为我测试下面的程序,发现ie和ff效果是差不多的:
ie:
Code



<script> <br>document.body.onmousedown=function(){this.setCapture(false)} <br>document.body.onmouseup=function(){this.releaseCapture()} <br>document.onmousemove=function(){aa.innerHTML+=1} <br></script>


ff:
Code



<script> <br>document.onmousemove=function(){aa.innerHTML =1} <br></script>


Unfortunately, without authoritative information reference, we can only guess. There are still many things that we still don’t understand and we will study them later.
Note that there is a bug in mouse capture under ff2. When there is no text content inside the drag-and-drop object and it is dragged and dropped outside the browser, the capture will fail.
Insert an empty text into the drag and drop object, such as This can be solved, but this bug has been fixed in ff3.
[Focus Lost]
Under normal circumstances, mouse capture can capture events normally, but if the focus of the browser window is lost, the capture will fail.
I have temporarily tested that the operations that can cause focus loss include switching windows (including alt tab), alert and popup and other pop-up forms.
When the focus is lost, the Stop program should be executed at the same time to end the drag and drop. However, when the focus is lost, the mouseup event cannot be captured, that is, _fS cannot be triggered.
Fortunately, IE has an onlosecapture event that will be triggered when the capture fails. For this situation, you can set it like this:
addEventHandler(this._Handle, "losecapture", this._fS);
and move it in the Stop program Except:
removeEventHandler(this._Handle, "losecapture", this._fS);
But ff does not have a similar method, but muxrwc finds a window.onblur event that replaces losecapture, so it can be set in the Start program:
addEventHandler(window, "blur", this._fS);
Remove in the Stop program:
removeEventHandler(window, "blur", this._fS);
That ie also has a window. Onblur event, using window.onblur instead of losecapture can save a piece of code.
Then I did some tests and found that basically any situation that triggers losecapture will trigger window.onblur at the same time, which seems to work.
So I modified the program to use window.onblur instead of losecapture, but something went wrong after testing. I found that if I use alt tab to switch to another window, dragging can continue, but the focus should have been lost by this time. .
So I eliminated the test and program code one by one, and found that if DTD is used, window.onblur will not be triggered until it gains focus again.
You can use the following code to test:

<script>window.onblur=function(){alert(1)}</script>
After switching to other programs, switch back again It will trigger window.onblur, and there are a few weird situations that I won’t mention. Anyway, using window.onblur in IE is not ideal.
[Cancel default action]
Drag-and-drop operations on text content, connections, and images in the selected state will trigger the system's default action. For example, dragging the mouse on an image in IE will become a prohibited operation state, which will cause This drag and drop procedure failed to execute.
However, after setCapture is set in IE, drag-and-drop operations and content selection with the mouse through the user interface will be prohibited.
It means that after setCapture, you cannot drag and drop and select the document content. Note that drag and drop here refers to the default action of the system. For example, ondragstart will not be triggered.
However, if the parameter of setCapture is false, the object in the container can still trigger events (see the mouse capture section for details), so the parameter of setCapture should be set to true or keep the default value.
The mouse capture of ff does not have this function, but it can be solved by using preventDefault to cancel the default action of the event:
oEvent.preventDefault();
ps: It is said that using preventDefault will cause mouseup loss, but I didn't find it in the test in ff3. If you find any mouseup loss, be sure to tell me.
【Clear Selection】
ie content selection will be prohibited after setting setCapture, but it will not clear the content that has been selected before setting, and content can also be selected through other methods after setting,
For example, use ctrl a to select content.
ps: onkeydown, onkeyup and onkeypress events will not be affected by mouse capture.
And ff can clear the original selected content when mousedown, but drag the mouse and ctrl a will still continue to select the content.
However, after canceling the system default action, this choice will not affect the drag and drop operation. The setting here is mainly for a better experience.
In the past, I used the method of disabling the selection of drag and drop objects to achieve the goal, that is, setting the onselectstart of the drag and drop object in IE to return false, and setting the style MozUserSelect (css:-moz-user-select) to none in FF.
但这种方法只能禁止拖放对象本身被选择,后来找到个更好的方法清除选择,不但不影响拖放对象的选择效果,还能对整个文档进行清除:
ie:document.selection.empty()
ff:window.getSelection().removeAllRanges()
为了防止在拖放过程中选择内容,所以把它放到Move程序中,下面是兼容的写法:
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
【margin】
还有一个情况,当拖放对象设置了margin,那么拖放的时候就会错位(给SimpleDrag的拖放对象设置margin就可以测试)。
原因是在Start程序设置_x和_y时是使用offset获取的,而这个值是包括margin的,所以在设置left和top之前要减去这个margin。
但如果在Start程序中就去掉margin那么在Move程序中设置范围限制时就会计算错误,
所以最好是在Start程序中获取值:
this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
在Move程序中设置值:
this.Drag.style.left = iLeft - this._marginLeft + "px";
this.Drag.style.top = iTop - this._marginTop + "px";
要注意margin要在范围修正之后再设置,否则会错位。
【透明背景bug】
在ie有一个透明背景bug(不知算不算bug),可以用下面的代码测试:
Code






点击div的背景会触发不了事件(点击边框或div里面的对象是可以触发的)。
到底什么时候会出现这个bug呢,再用下面的代码测试:
Code











测试代码中我把背景颜色(包括body)设成灰色,首先可以看出在蓝色div(测试对象)内只要触发点是在灰色上面,就能触发事件;相反,在其他不是背景的地方,即使是边框、图片,也不能触发事件。
就像是把灰色的背景的补到蓝色div上来,而且仅仅是背景能这样,多奇怪的设定啊。
这里要说明的是body比较特别,不管背景是不是透明,只要触发点是直接在body上就能触发事件。
我的结论是如果触发事件的对象背景是透明的,而事件的触发点不在对象内的元素上,也不是直接在body上,而且透明背景外没有非透明背景的话,那么事件触发就会失败。
这个结论写得不太好,因为我都不知改怎么表达这奇怪的设定,希望各位能明白。
ps:这里设置图片背景跟颜色背景效果是一样的。
那最好解决的方法就是给对象设一个非透明背景,但有时需求正好是要透明的,那怎么办呢?
首先想到的是加上背景色后设置完全透明,但这样连边框,容器内的对象等都完全透明了,不够好。
如果能保证触发点直接在body或非背景上也可以,如果这个也不能保证呢?
我想到的一个解决方法是在容器里面加一个层,覆盖整个容器,并设置背景色和完全透明:
Code
with(this._Handle.appendChild(document.createElement("div")).style){
width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)";
}
到这里又不得不说ie6的一个渲染bug,用下面的代码测试(ie6):
Code




<script>setTimeout("aa.style.height=200",0)</script>


Can be compared with ie7 As a result, it can be seen that although the height of the inner div is set to 100%, after the height of the outer div is modified, it is not filled for some reason.
If this div is a dragging object and suddenly half of it cannot be dragged, that will definitely not work.
Fortunately, BlueDestiny told me a solution. Set the overflow of the object to hidden, and the divs inside will be automatically filled again.
BlueDestiny said "The reason for this problem is because of the rendering problem of IE6. Through certain CSS properties, the DOM can be changed and rendered again."
This bug can also be solved with zoom. Anyway, it is to make the dom re-rendered. render.
When you find that this bug appears in the program, set the program optional parameter Transparent to true and such a layer will be automatically inserted.
Insert a little knowledge here. If you are careful, you will find that in the above test code, I set a background color for the html.
You can remove this background color and you will find that the background color will be set to the entire page. Although the body has always been used to set the background color of the page, but now you will have a doubt, the body is the part of the red box, why set it? The background color can be applied to the entire page, and setting the background color for html will display "normally".
The reason for this can be seen from the background section of the w3c standard of CSS21:
For HTML documents, however, we recommend that authors specify the background for the BODY element rather than the HTML element. For HTML documents whose root HTML element has computed values ​​of 'transparent' for 'background-color' and 'none' for 'background-image', user agents must instead use the computed value of those properties from that HTML element's first BODY element child when painting backgrounds for the canvas, and must not paint a background for that BODY element. Such backgrounds must also be anchored at the same point as they would be if they were painted only for the root element. This does not apply to XHTML documents.
我英It sucks, so just try to translate it:
For HTML documents, we recommend that authors (this is to browser producers) use the background of the BODY element instead of the HTML element. If the 'background-color' of the root element of the HTML document (HTML element) is 'transparent' and the 'background-image' is 'none' (these two happen to be the default values), then the HTML element is taken when setting the background The attribute value of the first BODY child element, and the background of that element is no longer rendered.
The last two sentences are hard to understand, but they are enough to explain the reason.
【iframe】
If there is an iframe embedded on the page, you should pay attention because there will be problems with mouse capture on the iframe.
For example, if you quickly move and drop on an iframe within a drag-and-drop container, or drag the mouse to an iframe outside the container, anyway, the mouse is on the iframe (note that there are no other elements separating it), problems will occur:
First of all, the capture is invalid. If the mouse is on the iframe, it cannot be dragged, but losecapture will not be triggered, let alone the blur of the window. This is the same in IE and FF;
Secondly, in IE If you rub the iframe a few more times, it may cause IE to die (for unknown reasons).
Here are a few methods I thought of:
Hide the iframe of the page, which is relatively simple, but some important information in the iframe may also be hidden, or cause the page layout to be misaligned, resulting in a poor user experience;
Cancel the drag and drop after moving the mouse to the iframe. It is not difficult, but the user experience is also not good;
Each iframe is covered with a transparent layer, which is very troublesome. The position and size of each iframe must be calculated;
Use a transparent layer to cover the entire page. It is recommended and relatively simple. This method is introduced below.
The overlay I made to imitate the LightBox content display effect can be applied here. First, instantiate a transparent overlay:
var ol = new OverLay({ Opacity: 0 });
Then Just add ol.Show() and ol.Close() in the onStart and onStop events to show and hide the overlay, so as long as drag and drop is not triggered in the iframe, there will be no problem.
If there are other better methods, please advise.
That’s it for the time being. I didn’t expect that a little drag and drop can bring so much knowledge.
We haven’t considered scrolling and other things yet. We will study them later if necessary.

Instructions for use
Only one parameter is required when instantiating, which is the drag and drop object:
new SimpleDrag("idDrag");
has the following optional parameters and attributes:
Attribute: Default value // Description
Handle: "", // Set the trigger object (use drag and drop object if not set)
Limit: false, // Whether to set range limit (when it is true, the following parameters are useful, Can be a negative number)
mxLeft:0,//Left limit
mxRight:9999,//Right limit
mxTop:0,//Top limit
mxBottom:9999,//Bottom limit
mxContainer:"",//Specify the limit within the container
LockX:false,//Whether to lock horizontal drag and drop
LockY:false,//Whether to lock vertical drag and drop
Lock:false, //Whether to lock
Transparent: false, //Whether to be transparent
onStart:function(){},//Execute when starting to move
onMove:function(){},//Execute when moving
onStop:function(){}//Executed when the movement ends
The attribute Drag is a drag and drop object. Transparent, Handle and mxContainer cannot be set after initialization.

Program Code
Code
Copy Code The code is as follows:

var isIE = (document.all) ? true : false;
var $ = function (id) {
return "string" == typeof id ? document.getElementById(id) : id;
};
var Class = {
create: function() {
return function() { this.initialize.apply(this, arguments); }
}
}
var Extend = function(destination, source) {
for (var property in source) {
destination[property] = source[property];
}
}
var Bind = function(object, fun) {
return function() {
return fun.apply(object, arguments);
}
}
var BindAsEventListener = function(object, fun) {
return function(event) {
return fun.call(object, (event || window.event));
}
}
var CurrentStyle = function(element){
return element.currentStyle || document.defaultView.getComputedStyle(element, null);
}
function addEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.addEventListener) {
oTarget.addEventListener(sEventType, fnHandler, false);
} else if (oTarget.attachEvent) {
oTarget.attachEvent("on" sEventType, fnHandler);
} else {
oTarget["on" sEventType] = fnHandler;
}
};
function removeEventHandler(oTarget, sEventType, fnHandler) {
if (oTarget.removeEventListener) {
oTarget.removeEventListener(sEventType, fnHandler, false);
} else if (oTarget.detachEvent) {
oTarget.detachEvent("on" sEventType, fnHandler);
} else {
oTarget["on" sEventType] = null;
}
};
//拖放程序
var Drag = Class.create();
Drag.prototype = {
//拖放对象
initialize: function(drag, options) {
this.Drag = $(drag);//拖放对象
this._x = this._y = 0;//记录鼠标相对拖放对象的位置
this._marginLeft = this._marginTop = 0;//记录margin
//事件对象(用于绑定移除事件)
this._fM = BindAsEventListener(this, this.Move);
this._fS = Bind(this, this.Stop);
this.SetOptions(options);
this.Limit = !!this.options.Limit;
this.mxLeft = parseInt(this.options.mxLeft);
this.mxRight = parseInt(this.options.mxRight);
this.mxTop = parseInt(this.options.mxTop);
this.mxBottom = parseInt(this.options.mxBottom);
this.LockX = !!this.options.LockX;
this.LockY = !!this.options.LockY;
this.Lock = !!this.options.Lock;
this.onStart = this.options.onStart;
this.onMove = this.options.onMove;
this.onStop = this.options.onStop;
this._Handle = $(this.options.Handle) || this.Drag;
this._mxContainer = $(this.options.mxContainer) || null;
this.Drag.style.position = "absolute";
//透明
if(isIE && !!this.options.Transparent){
//填充拖放对象
with(this._Handle.appendChild(document.createElement("div")).style){
width = height = "100%"; backgroundColor = "#fff"; filter = "alpha(opacity:0)";
}
}
//修正范围
this.Repair();
addEventHandler(this._Handle, "mousedown", BindAsEventListener(this, this.Start));
},
//设置默认属性
SetOptions: function(options) {
this.options = {//默认值
Handle: "",//设置触发对象(不设置则使用拖放对象)
Limit: false,//是否设置范围限制(为true时下面参数有用,可以是负数)
mxLeft: 0,//左边限制
mxRight: 9999,//右边限制
mxTop: 0,//上边限制
mxBottom: 9999,//下边限制
mxContainer: "",//指定限制在容器内
LockX: false,//是否锁定水平方向拖放
LockY: false,//是否锁定垂直方向拖放
Lock: false,//是否锁定
Transparent: false,//是否透明
onStart: function(){},//开始移动时执行
onMove: function(){},//移动时执行
onStop: function(){}//结束移动时执行
};
Extend(this.options, options || {});
},
//准备拖动
Start: function(oEvent) {
if(this.Lock){ return; }
this.Repair();
//记录鼠标相对拖放对象的位置
this._x = oEvent.clientX - this.Drag.offsetLeft;
this._y = oEvent.clientY - this.Drag.offsetTop;
//记录margin
this._marginLeft = parseInt(CurrentStyle(this.Drag).marginLeft) || 0;
this._marginTop = parseInt(CurrentStyle(this.Drag).marginTop) || 0;
//mousemove时移动 mouseup时停止
addEventHandler(document, "mousemove", this._fM);
addEventHandler(document, "mouseup", this._fS);
if(isIE){
//焦点丢失
addEventHandler(this._Handle, "losecapture", this._fS);
//设置鼠标捕获
this._Handle.setCapture();
}else{
//焦点丢失
addEventHandler(window, "blur", this._fS);
//阻止默认动作
oEvent.preventDefault();
};
//附加程序
this.onStart();
},
//Correction range
Repair: function() {
if(this.Limit){
//Correction error range parameter
this.mxRight = Math.max(this.mxRight , this.mxLeft this.Drag.offsetWidth);
this.mxBottom = Math.max(this.mxBottom, this.mxTop this.Drag.offsetHeight);
//If there is a container, the position must be set to relative. Relative positioning, and set
before getting offset!this._mxContainer || CurrentStyle(this._mxContainer).position == "relative" || (this._mxContainer.style.position = "relative");
}
},
//Drag
Move: function(oEvent) {
//Determine whether it is locked
if(this.Lock){ this.Stop(); return; } ;
//Clear selection
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
//Set movement parameters
var iLeft = oEvent.clientX - this._x, iTop = oEvent.clientY - this._y;
//Set range limit
if(this.Limit){
//Set range parameter
var mxLeft = this.mxLeft , mxRight = this.mxRight, mxTop = this.mxTop, mxBottom = this.mxBottom;
//If a container is set, correct the range parameter
if(!!this._mxContainer){
mxLeft = Math.max(mxLeft, 0);
mxTop = Math.max(mxTop, 0);
mxRight = Math.min(mxRight, this._mxContainer.clientWidth);
mxBottom = Math.min( mxBottom, this._mxContainer.clientHeight);
};
//Correct the movement parameters
iLeft = Math.max(Math.min(iLeft, mxRight - this.Drag.offsetWidth), mxLeft);
iTop = Math.max(Math.min(iTop, mxBottom - this.Drag.offsetHeight), mxTop);
}
//Set the position and correct margin
if(!this.LockX ){ this.Drag.style.left = iLeft - this._marginLeft "px"; }
if(!this.LockY){ this.Drag.style.top = iTop - this._marginTop "px"; }
//Additional program
this.onMove();
},
//Stop dragging
Stop: function() {
//Remove event
removeEventHandler( document, "mousemove", this._fM);
removeEventHandler(document, "mouseup", this._fS);
if(isIE){
removeEventHandler(this._Handle, "losecapture", this. _fS);
this._Handle.releaseCapture();
}else{
removeEventHandler(window, "blur", this._fS);
};
//Additional program
this.onStop();
}
};

Test code:
Code
Copy code The code is as follows:



< ;/div>









Drag and drop status: Not started
< ;script>
var drag = new Drag("idDrag", { mxContainer: "idContainer", Handle: "idHandle", Limit: true,
onStart: function(){ $("idShow").innerHTML = "Start drag and drop"; },
onMove: function(){ $("idShow").innerHTML = "left:" this.Drag.offsetLeft ";top:" this.Drag.offsetTop; },
onStop: function(){ $("idShow").innerHTML = "End drag and drop"; }
});
$("idReset").onclick = function(){
drag .Limit = true;
drag.mxLeft = drag.mxTop = 0;
drag.mxRight = drag.mxBottom = 9999;
drag.LockX = drag.LockY = drag.Lock = false;
}
$("idLock").onclick = function(){ drag.Lock = true; }
$("idLockX").onclick = function(){ drag.LockX = true; }
$("idLockY").onclick = function(){ drag.LockY = true; }
$("idLimit").onclick = function(){ drag.mxRight = drag.mxBottom = 200;drag.Limit = true; }
$("idLimitOff").onclick = function(){ drag.Limit = false; }


Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template