原帖地址:http://space.flash8.net/space/?uid-18713-action-viewspace-itemid-409214
原作者:我佛山人
代码 // 拖放排序类 // 演示:http://demos.mootools.net/Sortables var Sortables = new Class({ // 继承自Events和Options,UI插件的特点 Implements: [Events, Options], options: { /* //排序事件 onSort: $empty, //开始事件 onStart: $empty, //完成事件 onComplete: $empty, */ snap: 4 , // 透明度 opacity: 1 , // 是否复制 clone: false , // 是否使用形变动画 revert: false , // 拖动句柄对象 handle: false , // 约束 constrain: false }, // 构造函数 initialize: function (lists, options) { // 设置配置参数 this .setOptions(options); this .elements = []; this .lists = []; this .idle = true ; // 列表项可以单个,也可以是符合 this .addLists($$($(lists) || lists)); // 如果不克隆副本,则不需要变形动画 if ( ! this .options.clone) this .options.revert = false ; // 如果指定变形动画效果 if ( this .options.revert) this .effect = new Fx.Morph( null , $merge({duration: 250 , link: ' cancel ' }, this .options.revert)); }, // 附加事件 attach: function () { this .addLists( this .lists); return this ; }, // 移除事件 detach: function () { this .lists = this .removeLists( this .lists); return this ; }, // 添加列表项 addItems: function () { // 给参数降维再遍历 Array.flatten(arguments).each( function (element) { // 加到数组 this .elements.push(element); // 将关联本列表项的start方法缓存 var start = element.retrieve( ' sortables:start ' , this .start.bindWithEvent( this , element)); // 如果指定拖动句柄,从当前列表项中获取,否则将当前列表项作为句柄 // 然后给句柄添加鼠标按下事件,触发start方法 ( this .options.handle ? element.getElement( this .options.handle) || element : element).addEvent( ' mousedown ' , start); }, this ); return this ; }, // 添加列表 addLists: function () { // 给参数降维再遍历 Array.flatten(arguments).each( function (list) { this .lists.push(list); // 添加当前列表下的项 this .addItems(list.getChildren()); }, this ); return this ; }, // 移除列表项 removeItems: function () { // 用于返回的数组 var elements = []; // 给参数降维再遍历 Array.flatten(arguments).each( function (element) { // 加到返回数组 elements.push(element); // 从数组中删除 this .elements.erase(element); // 取缓存中的事件绑定方法 var start = element.retrieve( ' sortables:start ' ); // 类似添加列表项时的判断,找到句柄后移除事件 ( this .options.handle ? element.getElement( this .options.handle) || element : element).removeEvent( ' mousedown ' , start); }, this ); // 返回移除的列表项集合 return $$(elements); }, // 移除列表 removeLists: function () { // 用于返回的数组 var lists = []; // 给参数降维再遍历 Array.flatten(arguments).each( function (list) { // 加到返回数组 lists.push(list); // 从数组中删除 this .lists.erase(list); // 移除当前列表的所有列表项,因为removeItems方法中自动给参数降维,所以可以直接传数组 this .removeItems(list.getChildren()); }, this ); // 返回移除的列表集合 return $$(lists); }, // 获取复制的对象 getClone: function (event, element) { // 如果指定不复制,返回新创建的div并插入到body if ( ! this .options.clone) return new Element( ' div ' ).inject(document.body); // 如果参数为函数,修改其调用的上下文指向并传送指定参数 if ($type( this .options.clone) == ' function ' ) return this .options.clone.call( this , event, element, this .list); // 剩下的是指定为复制的情况 // 复制当前列表项并修改其样式 return element.clone( true ).setStyles({ ' margin ' : ' 0px ' , ' position ' : ' absolute ' , ' visibility ' : ' hidden ' , ' width ' : element.getStyle( ' width ' ) }).inject( this .list).position(element.getPosition(element.offsetParent)); }, // 获取可放落的对象 getDroppables: function () { // 取当前列表下的所有列表项 var droppables = this .list.getChildren(); // 如果没有约束,则其它列表也作为可放落对象 if ( ! this .options.constrain) droppables = this .lists.concat(droppables).erase( this .list); // 从可放落对象集合中排除当前对象及其克隆 return droppables.erase( this .clone).erase( this .element); }, // 插入 insert: function (dragging, element) { // 指定插入位置 var where = ' inside ' ; if ( this .lists.contains(element)) { this .list = element; this .drag.droppables = this .getDroppables(); } else { where = this .element.getAllPrevious().contains(element) ? ' before ' : ' after ' ; } this .element.inject(element, where); this .fireEvent( ' onSort ' , [ this .element, this .clone]); }, // 开始操作 start: function (event, element) { // 如果当前非闲置状态,退出 if ( ! this .idle) return ; // 设置闲置状态标识 this .idle = false ; // 当前操作对象 this .element = element; // 获取当前透明度 this .opacity = element.get( ' opacity ' ); // 获取当前操作对象所在的列表对象 this .list = element.getParent(); // 获取当前操作对象的克隆对象 this .clone = this .getClone(event, element); // 创建拖放对象 this .drag = new Drag.Move( this .clone, { snap: this .options.snap, // 拖放范围,如果指定constrain参数为true才会取当前对象所在的列表对象 container: this .options.constrain && this .element.getParent(), // 获取可放落的对象 droppables: this .getDroppables(), // onSnap事件监听 onSnap: function () { // 停止事件冒泡及返回值 event.stop(); // 显示克隆对象 this .clone.setStyle( ' visibility ' , ' visible ' ); // 设置透明度 this .element.set( ' opacity ' , this .options.opacity || 0 ); // 触发onStart事件 this .fireEvent( ' onStart ' , [ this .element, this .clone]); }.bind( this ), // 拖动进入事件 onEnter: this .insert.bind( this ), // 取消拖动事件 onCancel: this .reset.bind( this ), // 拖动完成事件 onComplete: this .end.bind( this ) }); // 插入克隆对象到当前对象前面 this .clone.inject( this .element, ' before ' ); // 开始拖动 this .drag.start(event); }, // 结束拖动排序 end: function () { // 移除事件 this .drag.detach(); // 恢复透明度 this .element.set( ' opacity ' , this .opacity); // 如果使用形变动画(主要是外形尺寸和坐标位置上的) if ( this .effect) { // 获取尺寸 var dim = this .element.getStyles( ' width ' , ' height ' ); // 计算位置 var pos = this .clone.computePosition( this .element.getPosition( this .clone.offsetParent)); // 将当前克隆对象作为形变对象 this .effect.element = this .clone; // 开始动画效果 this .effect.start({ top: pos.top, left: pos.left, width: dim.width, height: dim.height, opacity: 0.25 // 动画完成后的后续操作 }).chain( this .reset.bind( this )); } else { // 后续操作 this .reset(); } }, // 重置 reset: function () { // 设置闲置状态标记 this .idle = true ; // 清除克隆对象 this .clone.destroy(); // 触发onComplete事件 this .fireEvent( ' onComplete ' , this .element); }, // 序列化 serialize: function () { // 使用Array.link处理参数 var params = Array.link(arguments, {modifier: Function.type, index: $defined}); // 遍历列表集 var serial = this .lists.map( function (list) { // 遍历各列表的列表项,如果参数中传有函数的引用,使用该函数处理列表项,否则默认返回id return list.getChildren().map(params.modifier || function (element) { // 取列表项的id return element.get( ' id ' ); }, this ); }, this ); // 参数中传送的索引值 var index = params.index; // 如果列表集中只有一项,则索引值为0 if ( this .lists.length == 1 ) index = 0 ; // 如果索引存在并且值在合法范围内,返回指定索引值列表的序列化结果,否则返回整个列表集的序列化结果 return $chk(index) && index >= 0 && index < this .lists.length ? serial[index] : serial; }});
转载于:https://www.cnblogs.com/maapaa/articles/mootools-s-44.html
相关资源:mootools-core-1.5.1