Javascript 为什么在此脚本中可以将鼠标从拖动区域中拉出?
使用David Flanagan提供的简单JS脚本使我的bookmarklet可拖动 我注意到,我可以在“向下键”期间将指针从拖动条上移开,弹出窗口可能会也可能不会跟随指针,或者突然捕捉到指针 Firefox8和Firefox9的总体体验并不令人印象深刻。XP上的IE8按设计工作 它是为bookmarklet设计的,所以我不能使用jQuery或YUI这样的框架 问题:如何提高鼠标向下/拖动的粘性,以便使用普通JS在mousedown和mousemove上保持窗口与鼠标的连接 另外,请帮助我使getLeft和getTop在IE/Chrome和Fx中工作,以便弹出窗口仅限于视口 (谢谢techfoobar)Javascript 为什么在此脚本中可以将鼠标从拖动区域中拉出?,javascript,mouseevent,drag,gecko,Javascript,Mouseevent,Drag,Gecko,使用David Flanagan提供的简单JS脚本使我的bookmarklet可拖动 我注意到,我可以在“向下键”期间将指针从拖动条上移开,弹出窗口可能会也可能不会跟随指针,或者突然捕捉到指针 Firefox8和Firefox9的总体体验并不令人印象深刻。XP上的IE8按设计工作 它是为bookmarklet设计的,所以我不能使用jQuery或YUI这样的框架 问题:如何提高鼠标向下/拖动的粘性,以便使用普通JS在mousedown和mousemove上保持窗口与鼠标的连接 另外,请帮助我使ge
函数getTop(顶部){
//if(console)console.log('y:'+top+':'+document.body.clientHeight);
if(top=(document.body.clientHeight-40))返回document.body.clientHeight-40;
返回顶部;
}
函数getLeft(左){
//if(console)console.log('x:'+left+':'+document.body.clientWidth);
if(left=(document.body.clientWidth-500))返回document.body.clientWidth-500;
左转;
}
//这段代码来自《JavaScript:权威指南》第6版(ISBN#978-0596805524)。David Flanagan版权所有2011。
函数getScrollOffsets(w){
w=w | |窗;
if(w.pageXOffset!=null)返回{x:w.pageXOffset,y:w.pageYOffset};
var d=w.文件;
如果(document.compatMode==“CSS1Compat”)
返回{x:d.documentElement.scrollLeft,y:d.documentElement.scrollTop};
返回{x:d.body.scrollLeft,y:d.body.scrollTop};
}
函数zDrag(elementToDrag,event){var scroll=getScrollOffsets();
var startX=event.clientX+scroll.x;
var startY=event.clientY+scroll.y;
var origX=elementToDrag.offsetLeft;
变量origY=元素todrag.offsetTop;
var deltaX=startX-origX;
var deltaY=恒星-恒星;
如果(document.addEventListener){
document.addEventListener(“mousemove”,moveHandler,true);
document.addEventListener(“mouseup”,upHandler,true);
}
如果(文件附件){
elementToDrag.setCapture();
elementToDrag.attachEvent(“onmousemove”,moveHandler);
elementToDrag.attachEvent(“onmouseup”,upHandler);
elementToDrag.attachEvent(“onlosecapture”,upHandler);
}
if(event.stopPropagation)event.stopPropagation();
else event.cancelBubble=true;
if(event.preventDefault)event.preventDefault();
else event.returnValue=false;
函数moveHandler(e){
如果(!e)e=window.event;
var scroll=getScrollOffsets();
elementToDrag.style.left=getLeft(e.clientX+scroll.x-deltaX,true)+“px”;
elementToDrag.style.top=getTop(e.clientY+scroll.y-deltaY,true)+“px”;
如果(e.stopPropagation)e.stopPropagation();
否则e.cancelBubble=true;
};
函数upHandler(e){
如果(!e)e=window.event;
如果(document.removeEventListener){
document.removeEventListener(“mouseup”,upHandler,true);
removeEventListener(“mousemove”,moveHandler,true);
}
如果(document.detachEvent){
elementToDrag.detachEvent(“onlosecapture”,upHandler);
elementToDrag.detachEvent(“onmouseup”,upHandler);
elementToDrag.detachEvent(“onmousemove”,moveHandler);
elementToDrag.releaseCapture();
}
如果(e.stopPropagation)e.stopPropagation();
否则e.cancelBubble=true;
};
}
//端阻力代码
主要问题是iframe。当鼠标指针进入时,表示您对所有已注册事件说再见。用div替换iframe,Firefox中的情况应该会有所改进。IE似乎只是更新显示速度更快;鼠标指针永远没有机会进入IE中的iframe。这应该考虑粘性问题
我可以从您的演示站点上看到,当鼠标位于内部iframe上时,我们会遇到粘性问题。这是因为内部iframe不会将事件冒泡到处理zDrag的mousemove事件的根文档元素
我通过附加一个覆盖div(不可见但在那里)解决了这个问题,该div占据了根文档的整个区域,从而有效地防止内部iframe获得mousemove。由于这个overlay div是我们的根文档元素的直接后代,所以它正确地弹出mousemove事件
更改包括用于获取文档高度(从)的附加方法,以及用于添加/显示/隐藏覆盖div的zDrag方法的更改
function getDocHeight() {
var D = document;
return Math.max(
Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
Math.max(D.body.clientHeight, D.documentElement.clientHeight)
);
}
function zDrag(elementToDrag, event) {
var scroll = getScrollOffsets();
// create/show overlay - over the inner iframe and everything else
var div = document.getElementById('overlay');
if(div==null) {
div = document.createElement('div');
div.id = 'overlay';
div.style.position = 'absolute';
div.style.left = '0px';
div.style.top = '0px';
div.style.width = '100%';
div.style.height = getDocHeight()+'px';
div.style.zIndex = 99999;
div.style.cursor = 'move';
var bodyTag = document.getElementsByTagName("body")[0];
bodyTag.appendChild(div);
}
else {
div.style.display = 'block';
}
var startX = event.clientX + scroll.x;
var startY = event.clientY + scroll.y;
var origX = elementToDrag.offsetLeft;
var origY = elementToDrag.offsetTop;
var deltaX = startX - origX;
var deltaY = startY - origY;
if (document.addEventListener) {
document.addEventListener("mousemove", moveHandler, true);
document.addEventListener("mouseup", upHandler, true);
}
else if (document.attachEvent) {
/*elementToDrag.setCapture();
elementToDrag.attachEvent("onmousemove", moveHandler);
elementToDrag.attachEvent("onmouseup", upHandler);
elementToDrag.attachEvent("onlosecapture", upHandler);*/
// attach the events to the document element, to ensure we dont 'miss' any move events.
document.setCapture();
document.attachEvent("onmousemove", moveHandler);
document.attachEvent("onmouseup", upHandler);
document.attachEvent("onlosecapture", upHandler);
}
if (event.stopPropagation) event.stopPropagation();
else event.cancelBubble = true;
if (event.preventDefault) event.preventDefault();
else event.returnValue = false;
function moveHandler(e) {
if (!e) e = window.event;
var scroll = getScrollOffsets();
elementToDrag.style.left = getLeft(e.clientX + scroll.x - deltaX,true) + "px";
elementToDrag.style.top = getTop(e.clientY + scroll.y - deltaY,true) + "px";
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
};
function upHandler(e) {
// dragging is over. hide the overlay.
document.getElementById('overlay').style.display = 'none';
if (!e) e = window.event;
if (document.removeEventListener) {
document.removeEventListener("mouseup", upHandler, true);
document.removeEventListener("mousemove", moveHandler, true);
}
else if (document.detachEvent) {
/*elementToDrag.detachEvent("onlosecapture", upHandler);
elementToDrag.detachEvent("onmouseup", upHandler);
elementToDrag.detachEvent("onmousemove", moveHandler);
elementToDrag.releaseCapture();*/
document.detachEvent("onlosecapture", upHandler);
document.detachEvent("onmouseup", upHandler);
document.detachEvent("onmousemove", moveHandler);
document.releaseCapture();
}
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
};
}
编辑-用于限制视口内的拖动
现在,它将限制拖动到视口内部(即浏览器窗口内部宽度和高度)。更改包括a)一个额外的跨浏览器函数,用于获取窗口内部宽度和高度(from);b)更改moveHandler()方法(在zDrag方法内部),以检查和强制执行限制
function getWindowSize() {
var winW = 630, winH = 460;
if (document.body && document.body.offsetWidth) {
winW = document.body.offsetWidth;
winH = document.body.offsetHeight;
}
if (document.compatMode=='CSS1Compat' && document.documentElement && document.documentElement.offsetWidth ) {
winW = document.documentElement.offsetWidth;
winH = document.documentElement.offsetHeight;
}
if (window.innerWidth && window.innerHeight) {
winW = window.innerWidth;
winH = window.innerHeight;
}
return {width: winW, height: winH};
}
在zDrag()中,将当前的moveHandler替换为:
function moveHandler(e) {
if (!e) e = window.event;
var scroll = getScrollOffsets();
var newLeft = getLeft(e.clientX + scroll.x - deltaX,true);
if(newLeft + elementToDrag.offsetWidth > winDim.width) {
newLeft = winDim.width - elementToDrag.offsetWidth;
}
elementToDrag.style.left = newLeft + "px";
var newTop = getTop(e.clientY + scroll.y - deltaY,true);
if(newTop + elementToDrag.offsetHeight > winDim.height) {
newTop = winDim.height - elementToDrag.offsetHeight;
}
elementToDrag.style.top = newTop + "px";
if (e.stopPropagation) e.stopPropagation();
else e.cancelBubble = true;
};
编辑-winDim变量
winDim是存储视口尺寸的变量。它在移动处理程序中用于检查移动对象是否在视口中。我将其保留在外部,以避免在每次移动事件中重新计算窗口尺寸,从而降低性能
var winDim = null;
function zDrag(...) {
if(winDim == null) winDim = getWindowSize
// ... rest of the code in zDrag ...
}
因此,您的问题仅适用于Firefox,或者..?可能是IE以外的其他浏览器。IE8工作良好。请使您的代码更具可读性。但鼠标指针不应该有机会进入iframe,因为我在div上执行鼠标向下操作,这应该会将鼠标向下的点粘到指针上。我必须用一个iframe来解释zindex的理由,嗯?我们把iframe放在里面,但是用div覆盖它。非常有趣。谢谢你,我来测试一下。当我看到“overlay”时,我想-哦,不,这将停止与iframe的交互,但是如果在拖动停止时隐藏/删除它,它当然会起作用
var winDim = null;
function zDrag(...) {
if(winDim == null) winDim = getWindowSize
// ... rest of the code in zDrag ...
}