.window.getSelection && window.getSelection().removeAllRanges();你博客写的是清除选择,我感觉挺模糊。 
  但我如果不加这句话,在ff下一甩鼠标就丢失事件了,请你详细解释下。 这个是为了兼容FF的3.你的理解有点错误

解决方案 »

  1.   

    chinmo 我知道是兼容ff的  但他的具体作用我还不理解
    对于我3的理解 正确的我不知道应该是怎样 请指点 
      

  2.   

    再回chinmo兄 我印象里好像想要用offset定位 那么div必须得是绝对定位的吧
      

  3.   

    1.鼠标还可能跑到浏览器外!
    2.由于需要释放选择,或者说是清除,如果是用阻止默认动作就会在某些操作的时候导致mouseup丢失.所以这里选择了window.getSelection && window.getSelection().removeAllRanges();
      

  4.   

    lz那个跟我那个差很远啊
    尤其是move的部分
    给我那个例子你参考吧
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
     <head>
      <title> New Document </title>
      <meta name="Generator" content="EditPlus">
      <style>
      #oContent{
        border: 3px solid #000033;
        height: 400px;
        width: 200px;
    position:relative;
      }
      #oDiv{
        width: 40px;
        height: 40px;
        background-color:#993333;
        z-index: 100;
        position: absolute;  }
      </style>
      <script language="JavaScript">
      <!--
        var $ = function(id){
            return 'string' == typeof id ? document.getElementById(id) : id;
        }    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 isIE = (document.all) ? true : false;    var Class = {
            create : function(){
                return function(){
                    this.initialize.apply(this, arguments);
                }
            }
        }    Object.extend = function(distination, source){
            for(var property in source){
                distination[property] = source[property];
            }
            return distination;
        }//拖放程序
    var Drag = Class.create();
    Drag.prototype = {
      //拖放对象,触发对象
      initialize: function(obj, drag, options) {
        var oThis = this;

    this._obj = $(obj);//拖放对象
    this.Drag = $(drag);//触发对象
    this._x = this._y = 0;//记录鼠标相对拖放对象的位置
    //事件对象(用于移除事件)
    this._fM = function(e){ oThis.Move(window.event || e); }
    this._fS = function(){ oThis.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.mxContainer = this.options.mxContainer;

    this.onMove = this.options.onMove;
    this.Lock = !!this.options.Lock;

    this._obj.style.position = "absolute";
    addEventHandler(this.Drag, "mousedown", function(e){ oThis.Start(window.event || e); });
      },
      //设置默认属性
      SetOptions: function(options) {
        this.options = {//默认值
    Limit: false,//是否设置限制(为true时下面参数有用,可以是负数)
    mxLeft: 0,//左边限制
    mxRight: 0,//右边限制
    mxTop: 0,//上边限制
    mxBottom: 0,//下边限制
    mxContainer: null,//指定限制在容器内
    onMove: function(){},//移动时执行
    Lock: false//是否锁定
        };
        Object.extend(this.options, options || {});
      },
      //准备拖动
      Start: function(oEvent) {
    if(this.Lock){ return; }
    //记录鼠标相对拖放对象的位置
    this._x = oEvent.clientX - this._obj.offsetLeft;
    this._y = oEvent.clientY - this._obj.offsetTop;
    //mousemove时移动 mouseup时停止
    addEventHandler(document, "mousemove", this._fM);
    addEventHandler(document, "mouseup", this._fS);
    //使鼠标移到窗口外也能释放
    if(isIE){
    addEventHandler(this.Drag, "losecapture", this._fS);
    this.Drag.setCapture();
    }else{
    addEventHandler(window, "blur", this._fS);
    }
      },
      //拖动
      Move: function(oEvent) {
    //判断是否锁定
    if(this.Lock){ this.Stop(); return; }
    //清除选择(ie设置捕获后默认带这个)
    window.getSelection && window.getSelection().removeAllRanges();
    //当前鼠标位置减去相对拖放对象的位置得到offset位置
    var iLeft = oEvent.clientX - this._x, iTop = oEvent.clientY - this._y;
    //设置范围限制
    if(this.Limit){
    //如果设置了容器,因为容器大小可能会变化所以每次都要设
    if(!!this.mxContainer){
    this.mxLeft = this.mxTop = 0;
    this.mxRight = this.mxContainer.clientWidth;
    this.mxBottom = this.mxContainer.clientHeight;
    }
    //获取超出长度
    var iRight = iLeft + this._obj.offsetWidth - this.mxRight, iBottom = iTop + this._obj.offsetHeight - this.mxBottom;
    //这里是先设置右边下边再设置左边上边,可能会不准确
    if(iRight > 0) iLeft -= iRight;
    if(iBottom > 0) iTop -= iBottom;
    if(this.mxLeft > iLeft) iLeft = this.mxLeft;
    if(this.mxTop > iTop) iTop = this.mxTop;
    }
    //设置位置
    //由于offset是把margin也算进去的所以要减去
    this._obj.style.left = iLeft - (parseInt(this._obj.currentStyle.marginLeft) || 0) + "px";
    this._obj.style.top = iTop - (parseInt(this._obj.currentStyle.marginTop) || 0) + "px";
    //附加程序
    this.onMove();
      },
      //停止拖动
      Stop: function() {
    //移除事件
    removeEventHandler(document, "mousemove", this._fM);
    removeEventHandler(document, "mouseup", this._fS);
    if(isIE){
    removeEventHandler(this.Drag, "losecapture", this._fS);
    this.Drag.releaseCapture();
    }else{
    removeEventHandler(window, "blur", this._fS);
    }
      }
    };
        
      //-->
      </script>
     </head> <body>
     <div id="oContent">
     <div id="oDiv"></div>
     </div>
     <script>
      new Drag("oDiv","oDiv",{Limit : true, mxContainer: $("oContent")});
     </script>
     </body>
    </html>
      

  5.   

    定位才有可能和position属性扯上关系如果只是取值,就和position属性没有什么关系了
      

  6.   

    谢谢你的程序,不好意思其实看完之后 大部分思路我还是懂 但我认为还是那几个细节就是限制范围判断this.mxLeft = this.mxTop = 0;为什么是0??
      

  7.   

    我来一次总的:1.addEventHandler(this.oDrag, "mousedown", function(e){oThis.mouseDown(e || window.event)})的时候 
      为什么不能直接addEventHandler(this.oDrag, "mousedown", this.mouseDown),此时this指向哪? 
    答:这里要清楚你的鼠标可能出了浏览器之外
    2.window.getSelection && window.getSelection().removeAllRanges();你博客写的是清除选择,我感觉挺模糊。 
      但我如果不加这句话,在ff下一甩鼠标就丢失事件了,请你详细解释下。 
    答:因为你拖放的时候有一个选择的,这里是清楚选择,这么写是为了兼容FF.如果是用阻止默认动作就会在某些操作的时候导致mouseup丢失,所以引用了这个
    3.关于范围限制,我看你的最大范围,最小范围默认都是0,为什么是这样?我的理解是: 
      最大右范围 = 容器的offsetLeft + offsetWidth; 
      最小左范围 = 容器的offsetLeft 
      最大下范围 = 容器的offsetTop + offsetHeight; 
      最小上范围 = 容器的offsetTop 
      所以我就写了我那块限制范围的代码,但没有实现我想要的。 
    答:他这个是范围限制,你最多不是都距离到0吗?当然你也可以为负的!设置为0是防止出现滚动条
    4.要想用offset取位置是不是容器div和拖拽div的position属性都应该是absolute? 
    答:取值和position属性没有关系,只有定位的时候才有关系
      

  8.   

    因为这里
      #oContent{
        border: 3px solid #000033;
        height: 400px;
        width: 200px;
        position:relative;
      }注意是position:relative;不是absolute
    那么里面的drag的left和top就是相对oContent来说的了
    明白?
      

  9.   

    谢谢chinmo兄的回复,但我写几点疑问
    1.我想addEventHandler事件绑定是mousedown而且我是绑定在拖拽div上,所以是与浏览器外无关的吧,只要是直接this.mouseDown,this的
      引用发生了改变,会抛错2.3.我在想为什么是0,想想offset取位置是不是相对父控件的?比如我那拖拽div取位置是相对容器div所以是0就可以?4.恩,那就是我的意思,但我想问下relative和absolute具体是什么区别?明天加分结贴
      

  10.   

    谢谢cloud刚才的回复,relative和absolute理解错了我!
      

  11.   

    清除选择的作用是
    例如drag里面有一个字a
    你用光标选择了这个a(例如全选)
    如果没有清除选择然后拖动drag里面的a
    lz可以试试
      

  12.   

    刚才的程序漏了
    if(!isIE){
    HTMLElement.prototype.__defineGetter__("currentStyle", function () {
    return this.ownerDocument.defaultView.getComputedStyle(this, null);
    });
    }有这个ff中才正常
      

  13.   


    1.3.晕,不是说了吗?这个数字不是死的,你可以自己定啊!你定什么范围他就只能到那范围!到0的话是他可以与他相对的父对象或者当前位置可以边重叠4.position:absolute;他的意思是绝对定位,他是参照浏览器的左上角,配合TOP、RIGHT、BOTTOM、LEFT(下面简称TRBL)进行定位,在没有设定TRBL,默认依据父级的做标原始点为原始点。如果设定TRBL并且父级没有设定position属性,那么当前的absolute则以浏览器左上角为原始点进行定位,位置将由TRBL决定。怎么样才能让他的提示在标题下面呢!那就需要相对定义标题(父级)==Relative,CSS中的写法是:position:relative    他的意思是绝对相对定位,他是参照父级的原始点为原始点,无父级则以BODY的原始点为原始点,配合TRBL进行定位,当父级内有padding等CSS属性时,当前级的原始点则参照父级内容区的原始点进行定位。这样我们就可以对于这个例题总结一句话:用了position:absolute;他的父级标签就一定要用position:relative; absolute的英文意思是绝对的意思,实际上是针对父级元素元素定位,如果父级元素没有position:relative|absolute,则追至再上一个父级元素,直至相对于文档的左上角定位,按照我们中国人的理解观念,这个其实是相对定位,是脱离文档流的。用了abolute属性,原有float属性将失效;
    relative的英文意思是相对的意思,实际上是相对于对象当前位置的定位。而且是不脱离文档流的,就算用top、lef、bottom、right或margin将其移动位置,它也会在原来的文档流中占有自己实际大小的一块位置。absolute是相对于父对象定位,relative是相对于当前位置定位*/
      

  14.   

    还有cloud兄  你给我的代码ff似乎不行
      

  15.   

    哦 
    window.getSelection && window.getSelection().removeAllRanges(); 作用看出来了  不然有字就把字拖出来啦
      

  16.   

    看了下cloud的程序也是,就是当你限定范围后,当鼠标移动到范围之外 还可以拖动 ,这样应不应该考虑?
      

  17.   

    cloud你可以把我的第一个问题解释下么?
      

  18.   


    个人觉得只要drag的移动还在范围内就ok
    而且感觉这样更炫
      

  19.   

    哈哈  有道理 帮我解答下第一个问题还有就是我把 window.getSelection && window.getSelection().removeAllRanges();
    放在mousedown里了  感觉没有什么意外 你说放在mousedown里有道理么?还有我没考虑边框 好像没感觉异常
    <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
    <html>
     <head>
      <title> New Document </title>
      <meta name="Generator" content="EditPlus">
      <style>
      #oContent{
    border: 3px solid #000033;
    height: 400px;
    width: 200px;
    position:relative;
      }
      #oDiv{
    width: 40px;
    height: 40px;
    background-color:#993333;
    z-index: 100;
    position: absolute;  }
      </style>
      <script language="JavaScript">
      <!--
    var $ = function(id){
    return 'string' == typeof id ? document.getElementById(id) : id;
    } 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 isIE = (document.all) ? true : false; var Class = {
    create : function(){
    return function(){
    this.initialize.apply(this, arguments);
    }
    }
    } Object.extend = function(distination, source){
    for(var property in source){
    distination[property] = source[property];
    }
    return distination;
    } var Drag = Class.create();
    Drag.prototype = {
    initialize : function(idContent, idDrag, options){
    var oThis = this;
    this._fM = function(e){oThis.mouseMove(e || window.event)};
    this._fU = function(e){oThis.mouseUp(e || window.event)};
    this._x = 0;this.y = 0;
    this.oDrag = $(idDrag);this.oContent = $(idContent);
    this.setOptions(options);
    addEventHandler(this.oDrag, "mousedown", function(e){oThis.mouseDown(e || window.event)})
    }, setOptions : function(options){
    this.options = {
    Limit : true //true: 限制范围 ,false: 不限制范围
    };
    Object.extend(this.options, options || {});
    }, mouseDown : function(oEvent){
    this._x = oEvent.clientX - this.oDrag.offsetLeft;
    this._y = oEvent.clientY - this.oDrag.offsetTop;
    if(isIE){
    addEventHandler(this.oDrag, "losecapture", this._fU);
    this.oDrag.setCapture();
    }else{
    window.getSelection && window.getSelection().removeAllRanges();
    }
    addEventHandler(document, "mousemove",this._fM);
    addEventHandler(document, "mouseup",this._fU);
    }, mouseMove : function(oEvent){
    var iLeft = oEvent.clientX - this._x;
    var iTop = oEvent.clientY - this._y;
    // 限制范围时候的坐标判断
    if(this.options.Limit){
    var iMaxLeft = iMaxTop = 0;
    var iMaxRight = this.oContent.clientWidth;
    var iMaxBottom = this.oContent.clientHeight;
    var bLock = false; // 获取超出长度
    var iRight = this.oDrag.offsetWidth + iLeft - iMaxRight;
    var iBottom = this.oDrag.offsetHeight + iTop - iMaxBottom; if(iRight > 0){iLeft -= iRight; bLock = true;}
    if(iBottom > 0){iTop -= iBottom; bLock = true;}
    if(iMaxLeft > iLeft) {iLeft = iMaxLeft; bLock = true;}
    if(iMaxTop > iTop){iTop = iMaxTop; bLock = true;}
    /* if(bLock){
    removeEventHandler(document, "mousemove",this._fM );
    removeEventHandler(document, "mouseup",this._fU );
    }*/
    // 不限制范围的坐标判断
    }
    this.oDrag.style.left = iLeft;
    this.oDrag.style.top = iTop; }, mouseUp : function(oEvent){
    if(isIE){
    removeEventHandler(this.oDrag, "losecapture", this._fU);
    this.oDrag.releaseCapture();
    }
    removeEventHandler(document, "mousemove",this._fM );
    removeEventHandler(document, "mouseup",this._fU );
    }
    }

      //-->
      </script>
     </head> <body>
     <div id="oContent">
     <div id="oDiv">drag</div>
     </div>
     <script>
      new Drag("oContent","oDiv",{limit : true});
     </script>
     </body>
    </html>
      

  20.   

    1.addEventHandler(this.oDrag, "mousedown", function(e){oThis.mouseDown(e || window.event)})的时候 
      为什么不能直接addEventHandler(this.oDrag, "mousedown", this.mouseDown),此时this指向哪? 这个就跟this的使用有关了
    可以参考JavaScript中this关键字使用方法详解的用DOM方式在事件处理函数中使用this关键字部分(这篇文章不错,值得看看)意思就是在使用addEventListener绑定事件后
    事件里面的this已经是window对象了
    所以用了个oThis
      

  21.   

    还有就是我把 window.getSelection && window.getSelection().removeAllRanges(); 
    放在mousedown里了  感觉没有什么意外 你说放在mousedown里有道理么?还有我没考虑边框 好像没感觉异常 因为move的时候也是可以ctrl+a全选的
    所以最好move的时候也释放掉,这样就万无一失了
      

  22.   

    恩  ok了 谢谢chinmo,cloud回复今天不能加分,先一人50,明天再给clou兄追加100