[转帖]Mootools源码分析-40 -- Drag.Move

原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-408713

原作者:我佛山人

 

代码
/*
拖放类
演示:http://demos.mootools.net/Drag.Absolutely
http://demos.mootools.net/Drag.Cart
http://demos.mootools.net/DragDrop
*/
Drag.Move 
= new Class({

    
//继承自Drag类
    Extends: Drag,

    options: {
    
//可以用于放落的对象数组
        droppables: [],
        
//限制拖动范围的容器
        container: false
    },

    
//构造函数
    initialize: function(element, options)    {
        
//调用父类同名方法
        arguments.callee.parent(element, options);
        
//获取可以用于放落的对象集合
        this.droppables = $$(this.options.droppables);
        
this.container = $(this.options.container);
        
if (this.container && $type(this.container) != 'element')    this.container = $(this.container.getDocument().body);
        element 
= this.element;

        
//获取当前定位方式
        var current = element.getStyle('position');
        
//如果为默认的静态定位,改为绝对定位
        var position = (current != 'static'? current : 'absolute';
        
//获取坐标
        if (element.getStyle('left'== 'auto' || element.getStyle('top'== 'auto') element.position(element.getPosition(element.offsetParent));

        
//设置定位方式,确保可element拖动
        element.setStyle('position', position);

        
//添加onStart事件监听,用addEvent的第三个参数指定为内部事件,可免于被移除
        this.addEvent('onStart'function()    {
            
this.checkDroppables();
        }, 
true);
    },

    
//开始拖动,将覆盖父类Drag的同名方法
    start: function(event)    {
        
//如果指定容器
        if (this.container)    {
            
var el = this.element, cont = this.container, ccoo = cont.getCoordinates(el.offsetParent), cps = {}, ems = {};

            
//取padding和margin在四个方向上的值
            ['top''right''bottom''left'].each(function(pad)    {
                cps[pad] 
= cont.getStyle('padding-' + pad).toInt();
                ems[pad] 
= el.getStyle('margin-' + pad).toInt();
            }, 
this);

            
//得到真实尺寸
            var width = el.offsetWidth + ems.left + ems.right, height = el.offsetHeight + ems.top + ems.bottom;
            
//计算出拖动限制的上下限值
            var x = [ccoo.left + cps.left, ccoo.right - cps.right - width];
            
var y = [ccoo.top + cps.top, ccoo.bottom - cps.bottom - height];

            
this.options.limit = {x: x, y: y};
        }
        arguments.callee.parent(event);
    },

    
//碰撞检查,原理是检查鼠标位置是否在对象内部
    checkAgainst: function(el)    {
        
//取指定对象的坐标及尺寸值
        el = el.getCoordinates();
        
//取当前鼠标位置
        var now = this.mouse.now;
        
//判断鼠标是否在对象范围内
        return (now.x > el.left && now.x < el.right && now.y < el.bottom && now.y > el.top);
    },

    
//可放落检查
    checkDroppables: function()    {
        
//先根据碰撞检查过滤可放落对象数组,再取最后一个
        var ōvered = this.droppables.filter(this.checkAgainst, this).getLast();
        
//如果当前可放落的对象不同于上次的
        if (this.overed != overed)    {
            
//如果上次可放落对象存在,触发onLeave离开事件
            if (this.overed) this.fireEvent('onLeave', [this.element, this.overed]);
            
//如果存在当前可放落对象
            if (overed)    {
                
//更新
                this.overed = overed;
                
//触发onEnter进入事件
                this.fireEvent('onEnter', [this.element, overed]);
            }    
else    {
                
//置空
                this.overed = null;
            }
        }
    },

    
//拖动,将覆盖父类同名方法
    drag: function(event)    {
        
//调用父类同名方法
        arguments.callee.parent(event);
        
//如果可放落对象数组不为空,在每次移动时检查碰撞
        if (this.droppables.length)    this.checkDroppables();
    },

    
//停止拖动,将覆盖父类同名方法
    stop: function(event)    {
        
//在松开鼠标时再次检查碰撞
        this.checkDroppables();
        
//触发onDrop放落事件
        this.fireEvent('onDrop', [this.element, this.overed]);
        
//置空
        this.overed = null;
        
//调用父类同名方法
        return arguments.callee.parent(event);
    }
});

//根据Drag.Move对Element的扩展实现
Element.implement({
    
//使对象可拖放化
    makeDraggable: function(options)    {
        
return new Drag.Move(this, options);
    }
});

 

posted @ 2009-12-01 11:16  webgis松鼠  阅读(323)  评论(0编辑  收藏  举报