zoukankan      html  css  js  c++  java
  • 兼容所有浏览器的拖拽交互

    目录:

    1. 用H5方法实现拖拽交互
    2. 自定义事件
    3. 自定义拖拽事件
    4. 实现兼容所有浏览器的拖拽交互

    跟着教程用H5实现了一个简单的拖拽,左右两个白盒子是容器,两边的红盒子可以任意拖拽。

    满足以下两个要求:

    • 被拖起来的盒子变成黄色,并且在原容器中消失,跟随鼠标移动。
    • 被拖拽的盒子进入容器时,容器会变颜色,离开时恢复原来的颜色。
    • 拖拽释放后,添加到准确的位置。

    HTML+CSS为:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>拖动</title>
    </head>
    <style>
        body{
            background-color: #ccc;
        }
        .container {
            width: 200px;
            height: 800px;
            background-color: #fff;
            border: 1px solid #000;
            margin: 50px;
            float: left;
        }
        .box {
            width: 200px;
            height: 80px;
            background-color: #f00;
            border: 1px solid #000;
        }
        .light {
            background-color: #f9f;
        }
        .move {
            background-color: #ffff73;
        }
        .hide {
            display: none;
        }
    </style>
    <body>
    <div class="wrap">
        <div class="container">
            <div class="box">1</div>
            <div class="box">2</div>
            <div class="box">3</div>
            <div class="box">4</div>
        </div><!--container结束-->
        <div class="container">
            <div class="box">5</div>
            <div class="box">6</div>
            <div class="box">7</div>
        </div><!--container结束-->
    </div><!--wrap结束-->

           <script type="text/javascript" src="js/util.js"></script> 

         <script type="text/javascript" src="js/dragAnddrop.js"></script>
    </body>
    </html>

    (util.js中是一些平时经常会用到的方法,像下面会出现的$.on( )用于接受一个选择器,然后在其表示的节点上绑定事件。$.getElements( )负责选出符合接收到的选择器的所有元素。)

    看教程之前,我的代码大致是这样的:

    window.onload=function(){
        var boxes=getElements(".box");
        //设置拖动目标可以被拖动
        each(me.box,function(item,index){
            item.draggable=true;
        });
        //获取拖动目标,并为其添加样式
        $.on(".wrap","dragstart",function(e){
            var e=e||window.event,
                target=e.target||e.srcElement;
            if (hasClass(target,"box")) {
                e.dataTransfer.setData("text/plain",".move");
            }
        });
            //其他功能
    }

    然后我看到了教程中这样的代码:

    (function () {
        var dnd = {
          // 初始化
          init: function () {
            var me = this;
            me.src = document.querySelector('#demo1-src');
            me.panelList = document.querySelector('.panel-list');
    
            // 为拖拽源监听dragstart,设置关联数据
            me.src.addEventListener('dragstart', me.onDragStart, false);
    
            //省略
          onDragStart: function (e) {
            e.dataTransfer.setData('text/plain', 'demo1-src');
          },
          //省略
        dnd.init();
      }());

    顿时觉得自己写了一坨屎。不过还好,终于见识到了传说中的面向对象。

    在用H5实现拖拽交互的过程中,我遇到一个问题:

    为drop添加事件处理程序的时候,要用appendChild方法将被拖拽的盒子添加到容器中去,那么要怎么获取到被拖拽的元素呢?

    我先想到可以在dragstart事件处理程序中把被拖拽的元素保存在一个变量里,然后再drop的事件处理程序访问它。但是很遗憾,并不能访问到。想一想,这是因为变量被声明之后的值是undefined,他在dragstart事件处理程序中被赋值,结束之后这个值就已经失效了,所以drop的事件处理程序中访问到的变量值是undefined。

    然后我想到了,在事件处理程序中想要获得信息,可以通过传入的事件对象,想到这里,之前看的云里雾里的dataTransfer对象就派上用场了。可以在dragstart事件处理程序中将为被拖拽的对象添加的class通过setData()方法传递给drop,这样就可以获取到他了。

    最终写好的代码如下:

    window.onload=function(){
        var dragdrop={
            //初始化
            init:function(){
                var me=this;
                me.box=getElements(".box");
                //设置拖动目标可以被拖动
                each(me.box,function(item,index){
                    item.draggable=true;
                });
                //获取拖动目标,并为其添加样式
                $.on(".wrap","dragstart",me.dragStart);
                //让拖动目标在拖起来的时候在原容器中消失
                $.on(".wrap","drag",me.Drag);
                //松开的时候恢复原状
                $.on(".wrap","dragend",me.dragEnd);
                //监听放置目标的dragenter事件,添加视觉效果
                $.on(".wrap","dragenter",me.dragEnter);
                //设置放置目标
                $.on(".wrap","dragover",me.prevent);
                //取消视觉效果
                $.on(".wrap","dragleave",me.dragLeave);
                //在拖放目标上处理
                $.on(".wrap","drop",me.dragDrop);
            },
            dragStart:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"box")) {
                    e.dataTransfer.setData("text/plain",".move");
                    addClass(target,"move");
                }
            },
            Drag:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"box")) {
                    addClass(target,"hide");
                }
            },
            dragEnd:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"box")) {
                    removeClass(target,"hide");
                    removeClass(target,"move");
                }
            },
            dragEnter:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"container")) {
                    addClass(target,"light");
                }
            },
            prevent:function(e){
                $.prevent(e);
            },
            dragLeave:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"container")) {
                    removeClass(target,"light");
                }
            },
            dragDrop:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"container")) {
                    var dragging=$(e.dataTransfer.getData("text/plain"));
                    removeClass(dragging,"move");
                    removeClass(target,"light");
                    target.appendChild(dragging);
                }
            },
        }
        dragdrop.init();
    }

    虽然还没有很深刻的体会到这种面向对象写法的好处,但还是模仿着写了。

    接下来就要开始照顾不支持H5的宝宝们了。

    一开始就被一系列的问题卡住,他怎么动起来?什么时候让他动起来?怎么让他跟着鼠标走?他怎么回去?怎么给它绑定事件处理程序?

    前两个问题还能勉强想出来,当鼠标按下的时候,可以给他设置position:absolute让他动起来,然后让他的left和top和mousedown事件的鼠标坐标相同就可以了。

    后几个问题就真的束手无策了。

    在《JavaScript高级程序设计》中找到答案,发现这件事情真的没那么简单。

    最本质的,要深刻地理解事件是怎么回事。

    事件是一种叫做观察者的设计模式,这是一种创建松散耦合代码的技术。对象可以发布事件,用来表示在该对象生命周期中某个有趣的时刻到了。然后其他对象可以观察该对象,等待这些有趣的时刻到来并通过运行代码来响应。

    意思就是说,事件是一个对象发出的信号,他邀请别人一起来庆祝他重要的时刻,不管有没有人愿意来,他都可以发出信号。

    那么,他要怎样发出信号呢? 通过 函数调用 很容易就可以实现对象之间的通信。

    有行为就需要有管理机制,得到一个名字,检测其对应的函数,执行函数。所以就需要一个对象来进行管理。

    函数的调用需要一些代码,需要函数名。所以这个对象中应该保存着函数名表示事件类型,还要保存该类型相应的代码,所以他还需要一个个方法为其添加事件类型和处理函数,还要有一个让函数中的代码执行的方法,这个方法读取函数名,然后执行这个函数名对应的代码。可以添加就要可以删除,所以还需要一个负责删除处理程序的方法。

    所以,这个对象应该长这样:

    {

    事件类型和他的代码们:

    {type1:[fun1,fun2...]

      type2:[fun1,fun2,..]

      .....}

    接待员:为对象添加type和相应fun。

    执行官:接收一个type执行相应代码。

    清理员:接收一个type和他想删除的fun,为其删掉这个fun。

    }

     用JavaScript实现就长下面这样:

    function eventTarget(){
        this.handlers={};
    }
    
    eventTarget.prototype={
        constructor:eventTarget,
        addHandler:function(type,handler){
            if (typeof this.handlers[type]=="undefined") {
                this.handlers[type]=[];
            }
            this.handlers[type].push(handler);
        },
    
        fire:function(e){
            var handlers=this.handlers[e.type]
            if (isArray(handlers)) {
                for (var i = 0,len = handlers.length;i<len; i++) {
                    handlers[i](e);
                }
            }
        },
    
        removeHandler:function(type,handler){
            if (isArray(this.handlers[type])) {
                removeItem(this.handlers[type],handler);
            }
        },
    };

    用这种构造函数+原型的方式,就是为了自定义的事件可以继承他的方法,并拥有自己的事件类型。

    有了这个完美的事件管理机制,就可以自定义拖拽事件对象了。

    按照H5的思路,他应该可以触发这6种事件:dragstart、drag、dragend、dragenter、dragleave和drop。

    首先,他如何触发dragstart?什么时候应该触发dragstart?

    拖拽的本质就是,鼠标在一个元素上按下不松开,挪动鼠标,放到另一个地方,松开。

    听起来好像很熟悉,就是我们熟悉的mousedown、mousemove和mouseup嘛。

    所以,当元素上发生mousedown的时候,就触发dragstart事件,移动的时候触发drag,移动到目标元素里面的时候触发dragenter,移出去的时候触发dragleave,松开的时候要是在目标元素里面就触发drop,然后触发dragend(因为不在里面的话要回到原位)。

    如果要绑定事件的话,就要知道绑定在哪里,因为事先不知道要被绑定的元素,所以绑定在document上,让每个DOM对象都有机会成为被拖拽的和放置目标。然后指定筛选条件,在指定的满足条件的对象上面触发事件。

    那么,如何指定被拖拽对象和放置目标呢?

    还是模仿H5,他通过设置draggable属性和阻止浏览器默认行为,我们也可以通过添加一个自定义属性或者类名,来判别目标对象。

    想明白这些之后,就可以开始写处理程序了,解决了重重问题之后,最后的对象是这样的:

    //自定义拖动事件(和HTML的class属性耦合)
    var DragDrop=function(){
        var dragdrop=new eventTarget(),
            dragging=null,  
            x=0,y=0,
            border_r,border_l,border_top,border_btm,
            left,right,top,bottom;
        
        function handle(e){
            var e=e||window.event,
                target=e.target||e.srcElement,
                drops=getElements(".dropable");  //问题1
            switch(e.type){
                case "mousedown":
                    if (hasClass(target,"draggable")) {
                        dragging=target;
                        x=e.clientX-target.offsetLeft;
                        y=e.clientY-target.offsetTop;
                        dragdrop.fire({
                            type:"dragstart",
                            target:dragging,
                            x:e.clientX,
                            y:e.clientY
                        });
                    }
                    break;
                case "mousemove":
                    if (dragging!==null) {
                        dragging.style.left=e.clientX-x+"px";
                        dragging.style.top=e.clientY-y+"px";
                        dragdrop.fire({
                            type:"drag",
                            target:dragging,
                            x:e.clientX,
                            y:e.clientY
                        });
                        if (drops[0]) {
                            for (var i = 0; i < drops.length; i++) {
                            border_l=dragging.offsetLeft;
                            border_r=parseInt(getCSS(dragging,"width"))+border_l;  //问题2
                            border_top=dragging.offsetTop;
                            border_btm=parseInt(getCSS(dragging,"height"))+border_top;
                            left=drops[i].offsetLeft;
                            right=parseInt(getCSS(drops[i],"width"))+left;
                            top=drops[i].offsetTop;
                            bottom=parseInt(getCSS(drops[i],"height"))+top;
                            if(border_r>left&&border_l<right&&border_top<bottom&&border_btm>top){
                                dragdrop.fire({
                                    type:"dragenter",
                                    target:drops[i]
                                });
                                }else{
                                    dragdrop.fire({
                                        type:"dragleave",
                                        target:drops[i]
                                    });
                                }
                            }
                        }
                    }
                    break;
                case "mouseup":
                    if (drops[0]&&dragging) {
                        for (var i = 0; i < drops.length; i++) {
                            dragWidth=parseInt(getCSS(dragging,"width"));
                            border_r=dragWidth+dragging.offsetLeft;
                            border_l=dragging.offsetLeft;
                            left=drops[i].offsetLeft;
                            right=drops[i].offsetLeft+parseInt(getCSS(drops[i],"width"));
                            if(border_r>left&&border_l<right&&border_top<bottom&&border_btm>top){  //问题3
                                dragdrop.fire({
                                    type:"drop",
                                    target:drops[i],
                                    dragging:dragging
                                });
                            break;
                            }
                        }
                    }
                    dragdrop.fire({
                        type:"dragend",
                        target:dragging,
                        x:e.clientX,
                        y:e.clientY
                    });
                    dragging=null;
                    break;
            }
        };
        dragdrop.enable=function(){
            $.add(document,"mousedown",handle);
            $.add(document,"mousemove",handle);
            $.add(document,"mouseup",handle);
        };
        dragdrop.disable=function(){
            $.remove(document,"mousedown",handle);
            $.remove(document,"mousemove",handle);
            $.remove(document,"mouseup",handle);
        };
        return dragdrop;
    }

    问题1:

    最开始的时候,我是不知道该怎么将被拖拽对象和目标对象分开的,我一直想,当感受到拖拽的时候就让事件的target变成被拖拽的元素,当感受到有东西改过来时让事件的target变成目标对象,当我尝试着把dragenter事件让mouseenter来触发时,失望的发现,鼠标上拖着东西的时候是无法触发mouseenter的。

    然后我想到,既然只能获得被拖拽的对象,也没有想mousedown那样的事件可以来获取放置目标,那就换个思路。通过class来获取,毕竟在我心中class是个万能的东西。所以我的逻辑就是,获取到所有class=droppable的对象,判断他们是否被拖动元素覆盖,是的话就触发dragenter,不是的话就触发dragleave。(这也就导致了问题3。)

    问题2:

    我想到的判断拖拽元素是否在目标元素上方的方法是,看被拖动元素是否有两条边线在目标元素之内。这就需要获取拖拽元素和目标元素的width。

    而用node.style.width获取不到。查了一下发现,这个方法只能获取到写在标签里面的样式。想要获取CSS中的样式,需要用DOM2级样式中定义的document.defaultView.getComputerStyle()和IE的obj.currentStyle。所以就写了一个getCSS方法,代码如下:

    //获得元素的CSS样式
    function getCSS(ele,name){
        if (ele) {
            return document.defaultView.getComputedStyle?
                document.defaultView.getComputedStyle(ele,null)[name]:ele.currentStyle[name];
        }
    }

    问题3:

    由于我上面判断目标对象的逻辑,被拖拽的元素会更容易drop进第一个带有droppable的容器里面。这个问题还有待解决。

    定义好拖拽事件对象之后,就可以为其绑定处理程序了。

    这时候就体现出之前面向对象写法的好处了:①他将所有事件处理函数都变成对象自身的方法,减少了很多游离再全局中的变量。②这些方法只有他自己能调用,外部不需要知道这里会发生什么,只需要知道他能做这些事情就够了。

    这样的写法,让一切变得非常井然有序,逻辑清晰。

    因为他们处理的方法是不同的,所以事件处理程序中的执行代码会有些差异,需要判断一下,不然会有冲突。

    到这里,已经可以实现我想要的功能了,而且还没有发现什么重大的问题。所以暂时先写成这个样子啦。

    虽然一直很嫌弃不支持新方法的浏览器,尤其是IE。但是这次要好好的感谢一下他,让我更深刻的了解了事件,并且让我见识到了JavaScript如此强大的函数,它可以创造无限可能。

    完整代码(https://github.com/mamengyi/Baidu/tree/master/2015_Spring/task0002/%E6%8B%96%E6%8B%BD%E4%BA%A4%E4%BA%92)

    //自定义事件
    function eventTarget(){
        this.handlers={};
    }
    
    eventTarget.prototype={
        constructor:eventTarget,
        addHandler:function(type,handler){
            if (typeof this.handlers[type]=="undefined") {
                this.handlers[type]=[];
            }
            this.handlers[type].push(handler);
        },
    
        fire:function(e){
            var handlers=this.handlers[e.type]
            if (isArray(handlers)) {
                for (var i = 0,len = handlers.length;i<len; i++) {
                    handlers[i](e);
                }
            }
        },
    
        removeHandler:function(type,handler){
            if (isArray(this.handlers[type])) {
                removeItem(this.handlers[type],handler);
            }
        },
    };
    
    
    //自定义拖动事件(和HTML的class属性耦合)
    var DragDrop=function(){
        var dragdrop=new eventTarget(),
            dragging=null,
            x=0,y=0,
            border_r,border_l,border_top,border_btm,
            left,right,top,bottom;
        
        function handle(e){
            var e=e||window.event,
                target=e.target||e.srcElement,
                drops=getElements(".dropable");
            switch(e.type){
                case "mousedown":
                    if (hasClass(target,"draggable")) {
                        dragging=target;
                        x=e.clientX-target.offsetLeft;
                        y=e.clientY-target.offsetTop;
                        dragdrop.fire({
                            type:"dragstart",
                            target:dragging,
                            x:e.clientX,
                            y:e.clientY
                        });
                    }
                    break;
                case "mousemove":
                    if (dragging!==null) {
                        dragging.style.left=e.clientX-x+"px";
                        dragging.style.top=e.clientY-y+"px";
                        dragdrop.fire({
                            type:"drag",
                            target:dragging,
                            x:e.clientX,
                            y:e.clientY
                        });
                        if (drops[0]) {
                            for (var i = 0; i < drops.length; i++) {
                            border_l=dragging.offsetLeft;
                            border_r=parseInt(getCSS(dragging,"width"))+border_l;
                            border_top=dragging.offsetTop;
                            border_btm=parseInt(getCSS(dragging,"height"))+border_top;
                            left=drops[i].offsetLeft;
                            right=parseInt(getCSS(drops[i],"width"))+left;
                            top=drops[i].offsetTop;
                            bottom=parseInt(getCSS(drops[i],"height"))+top;
                            if(border_r>left&&border_l<right&&border_top<bottom&&border_btm>top){
                                dragdrop.fire({
                                    type:"dragenter",
                                    target:drops[i]
                                });
                                }else{
                                    dragdrop.fire({
                                        type:"dragleave",
                                        target:drops[i]
                                    });
                                }
                            }
                        }
                    }
                    break;
                case "mouseup":
                    if (drops[0]&&dragging) {
                        for (var i = 0; i < drops.length; i++) {
                            dragWidth=parseInt(getCSS(dragging,"width"));
                            border_r=dragWidth+dragging.offsetLeft;
                            border_l=dragging.offsetLeft;
                            left=drops[i].offsetLeft;
                            right=drops[i].offsetLeft+parseInt(getCSS(drops[i],"width"));
                            if(border_r>left&&border_l<right&&border_top<bottom&&border_btm>top){  //会更容易drop进第一个盒子里。
                                dragdrop.fire({
                                    type:"drop",
                                    target:drops[i],
                                    dragging:dragging
                                });
                            break;
                            }
                        }
                    }
                    dragdrop.fire({
                        type:"dragend",
                        target:dragging,
                        x:e.clientX,
                        y:e.clientY
                    });
                    dragging=null;
                    break;
            }
        };
        dragdrop.enable=function(){
            $.add(document,"mousedown",handle);
            $.add(document,"mousemove",handle);
            $.add(document,"mouseup",handle);
        };
        dragdrop.disable=function(){
            $.remove(document,"mousedown",handle);
            $.remove(document,"mousemove",handle);
            $.remove(document,"mouseup",handle);
        };
        return dragdrop;
    }
    
    
    
    //拖动
    window.onload=function(){
        var dragdrop={
            //初始化
            inith5:function(){
                var me=this;
                me.box=getElements(".box");
                //设置拖动目标可以被拖动
                each(me.box,function(item,index){
                    item.draggable=true;
                });
                //获取拖动目标,并为其添加样式
                $.on(".wrap","dragstart",me.dragStart);
                //让拖动目标在拖起来的时候在原容器中消失
                $.on(".wrap","drag",me.Drag);
                //松开的时候恢复原状
                $.on(".wrap","dragend",me.dragEnd);
                //监听放置目标的dragenter事件,添加视觉效果
                $.on(".wrap","dragenter",me.dragEnter);
                //设置放置目标
                $.on(".wrap","dragover",me.prevent);
                //取消视觉效果
                $.on(".wrap","dragleave",me.dragLeave);
                //在拖放目标上处理
                $.on(".wrap","drop",me.dragDrop);
            },
            init:function(){
                var me=this,
                    dragevent=new DragDrop();
                dragevent.enable();
                //设置拖动目标可以被拖动
                me.box=getElements(".box");
                each(me.box,function(item,index){
                    addClass(item,"draggable");
                });
                //获取拖动目标,并为其添加样式
                dragevent.addHandler("dragstart",me.dragStart);
                //松开的时候恢复原状
                dragevent.addHandler("dragend",me.dragEnd);
                //监听放置目标的dragenter事件,添加视觉效果
                dragevent.addHandler("dragenter",me.dragEnter);
                //设置放置目标
                me.container=getElements(".container");
                each(me.container,function(item,index){
                    addClass(item,"dropable");
                });
                //取消视觉效果
                dragevent.addHandler("dragleave",me.dragLeave);
                //在拖放目标上处理
                dragevent.addHandler("drop",me.dragDrop);
            },
            dragStart:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"box")) {
                    if (e.dataTransfer) {
                        e.dataTransfer.setData("text/plain",".move");
                        addClass(target,"move");
                    }else{
                        addClass(target,"moving");
                    }
                }
            },
            Drag:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (e.dataTransfer&&hasClass(target,"box")) {
                    addClass(target,"hide");
                }
            },
            dragEnd:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (e.dataTransfer&&hasClass(target,"box")) {
                    removeClass(target,"hide");
                    removeClass(target,"move");
                }else{
                    removeClass(target,"moving");
                }
            },
            dragEnter:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"container")) {
                    addClass(target,"light");
                }
            },
            prevent:function(e){
                $.prevent(e);
            },
            dragLeave:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (hasClass(target,"container")) {
                    removeClass(target,"light");
                }
            },
            dragDrop:function(e){
                var e=e||window.event,
                    target=e.target||e.srcElement;
                if (e.dataTransfer&&hasClass(target,"container")) {
                    var dragging=$(e.dataTransfer.getData("text/plain"));
                    removeClass(dragging,"move");
                    removeClass(target,"light");
                    target.appendChild(dragging);
                }else if (e.dragging) {
                    var lights=getElements(".light"),
                        len=lights.length;
                    for (var i = 0; i < len; i++) {
                        removeClass(lights[0],"light"); //注意这里是一个NodeList
                    }
                    removeClass(e.dragging,"moving");
                    target.appendChild(e.dragging);
                }
            },
        }
        if(supportDrag()){
            dragdrop.inith5();
        }else{
            dragdrop.init();
        }
    }

    util:

    //对数组(类数组对象)的每项都执行fn(item,index)
    function each(arr,fn){
        for(var i = 0 , len = arr.length ; i<len ; i++){
            fn(arr[i],i);
        }
    }
    //DOM元素选择器
    function getElements(selector){
        //类选择器,返回全部项
        if(/.((?:[wu00c0-uFFFF-]|\.)+)/.test(selector)){
            if(document.getElementsByClassName){
                return document.getElementsByClassName(selector.slice(1,selector.length));
            }
            var nodes = document.all ? document.all : document.getElementsByTagName('*');
            var arr=[];//用来保存符合的className;    
            for(var i=0;i<nodes.length;i++){
                if(hasClass(nodes[i],selector.slice(1,selector.length))){
                    arr.push(nodes[i]);
                }
            }
            return arr;
        }
    
        //ID选择器
        if(/#((?:[wu00c0-uFFFF-]|\.)+)/.test(selector)){
            return document.getElementById(selector.slice(1,selector.length));
        }
    
    
        //tag选择器
        if(/^((?:[wu00c0-uFFFF-]|\.)+)/.test(selector)){
            return document.getElementsByTagName(selector);
        }
    
        //属性选择器
        if(/^[[A-Za-z0-9_-S]+]$/.test(selector)){
            selector = selector.slice(1,selector.length-1);
            var eles = document.getElementsByTagName("*");
            selector = selector.split("=");
            var att = selector[0];
            var value = selector[1];
            var arr = []; 
            if (value) {
                for (var i = 0; i < eles.length; i++) {
                    if(eles[i].getAttribute(att)==value){
                       arr.push(eles[i]);
                    } 
                }
            }else{
                for (var i = 0; i < eles.length; i++) {
                    if(eles[i].getAttribute(att)){
                        arr.push(eles[i]);
                    } 
                }
            }
            return arr;
        }
    }
    function $(selector){
        var all=selector.split(/s+/);
        var result = [],rooot=[document];
        for (var i = 0; i < all.length; i++) {
            var type=all[i][0];
            switch(type){
            //ID
            case "#" :
                for (var j = 0; j < rooot.length; j++) {
                    var ele=rooot[j].getElementById(all[i].slice(1));
                    if (ele) {
                        result.push(ele);
                    }
                }
                break;
            
            //class
            case ".":
                for (var j = 0; j < rooot.length; j++) {
                    if (document.getElementsByClassName) {
                        var eles=rooot[j].getElementsByClassName(all[i].slice(1));
                        if (eles) {
                            result=result.concat(Array.prototype.slice.call(eles));
                        }
                    }else{
                        var arr = rooot[j].getElementsByTagName("*");
                        for (var i = 0; i < arr.length; i++) {
                            if (hasClass(arr[i], className)) {
                                result.push(arr[i]);
                            }
                        }
                    }
                }
                break;
            //属性
            case "[":
                var att = all[i].slice(1,all[i].length-1).split("=");
                var key = att[0],value=att[1];
                for (var j = 0; j < rooot.length; j++) {
                    var eles=rooot[j].getElementsByTagName("*");
                    for (var i = 0; i < eles.length; i++) {
                        if (value) {
                            for (var i = 0; i < eles.length; i++) {
                                if(eles[i].getAttribute(key)==value){
                                    result.push(eles[i]);
                                }
                            }
                        }else{
                            for (var i = 0; i < eles.length; i++) {
                                if(eles[i].getAttribute(key)){
                                    result.push(eles[i]);
                                }
                            }
                        }
                    }
                }
                break;
            //tag
            default:
                for (var j = 0; j < rooot.length; j++) {
                    eles=rooot[j].getElementsByTagName(all[i]);
                    if (eles) {
                        result=result.concat(Array.prototype.slice.call(eles));
                    }
                }
            }
            rooot=result;
            result=[];   
        }
        return rooot[0];
    }
    //检查ele是否有className
    function hasClass(ele,className){
        if (ele&&ele.className) {
            var classes=ele.className.split(/s+/);//这里必须要切成数组之后再判断
            if(classes.indexOf(className)!=-1){
                return true;
            } 
        }
        return false;
    }
    
    // 为element增加一个样式名为newClassName的新样式
    function addClass(ele,newClass){
        if (!hasClass(ele,newClass)) {
            ele.className=ele.className?[ele.className,newClass].join(" "):newClass;
        }
    }
    
    // 移除element中的样式oldClassName
    function removeClass(ele,oldClass){
        if (hasClass(ele,oldClass)) {
            var arr = ele.className.split(/s+/);
            for (var i = 0; i < arr.length; i++) {
                if(arr[i]===oldClass){
                    arr.splice(i,1);
                    break;
                }
            }
            ele.className=arr.join(" ");
        }
    }
    //获得元素的CSS样式
    function getCSS(ele,name){
        if (ele) {
            return document.defaultView.getComputedStyle?
                document.defaultView.getComputedStyle(ele,null)[name]:ele.currentStyle[name];
        }
    }
    //添加事件
    function addEvent(selector,event,listener){
        var ele=$(selector);
        if(ele.addEventListener){
            ele.addEventListener(event,listener,false);
        }else{
            ele.attachEvent("on"+event,listener);
        }
    }
    //添加事件(给节点)
    function addEventToNode(ele,event,listener){
        if(ele.addEventListener){
            ele.addEventListener(event,listener,false);
        }else{
            ele.attachEvent("on"+event,listener);
        }
    }
    //移除事件
    function removeEvent(selector,event,listener){
        var ele=$(selector);
        if(ele.removeEventListener){
            ele.removeEventListener(event,listener,false);
        }else{
            ele.detachEvent("on"+event,listener);
        }
    }
    function removeNodeEvent(ele,event,listener){
        if(ele.removeEventListener){
            ele.removeEventListener(event,listener,false);
        }else{
            ele.detachEvent("on"+event,listener);
        }
    }

    //阻止浏览器默认行为
    function preventDefault(e){
    if (e&&e.preventDefault) {
    e.preventDefault();
    }else{
    e.returnValue=false;
    }
    return false;
    }
    $.prevent=preventDefault;

    $.on = addEvent;
    $.add = addEventToNode;
    $.un = removeEvent;
    $.remove=removeNodeEvent;

    //判断是否支持ondrag事件

    function supportDrag(){ 
        var div = document.createElement('div'); 
        return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div); 
    }

    参考:

    教程:http://qiudeqing.com/html5/2015/05/17/drag-and-drop.html

  • 相关阅读:
    Win8系统 Python安装
    一些安卓开源框架整理
    Android 媒体键监听以及模拟媒体键盘的实现 demo
    android View 自动 GONE 问题
    Android 定时器TimerTask 简单使用
    关于Android studio 相对 eclipse 优点
    Java序列化与反序列化
    android shape的使用 边框
    Android Studio 修改 包名 package name
    Android WebView Long Press长按保存图片到手机
  • 原文地址:https://www.cnblogs.com/LiveWithIt/p/5906692.html
Copyright © 2011-2022 走看看