原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-408713
原作者:我佛山人
![ContractedBlock.gif](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
/*
拖放类
演示: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);
}
});
拖放类
演示: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);
}
});