Mootools Sortables插件BUG修正 | 影の域

影の域

关注web前端,追逐html5脚步,体会code人生

Mootools Sortables插件BUG修正

| 4,198 点击

      前阵子新版专辑管理项目开发中碰到比较郁闷的问题,经测试最终决定给Sortables打个小补丁。

      由于对选择状态的文本内容、连接和图片等进行拖放操作会触发系统的默认动作,例如ie中拖动图片鼠标会变成禁止操作状态,这样会导致这个拖放程序执行失败,所以Mootools 的Drag基类配置里其实有preventDefault配置项来给使用者解决此类问题,默认值为false,需要处理时设置为true即可。

      然而郁闷的是,开发时才发现,Sortables类里内部创建的Drag.Move实例却只能使用preventDefault的默认值,因为Sortables没有给出配置项用来设置内部(this.drag)这个DragMove实例的preventDefault参数项。无奈之下,只能打补丁了。

      另打补丁期间又发现另一个问题,甚是郁闷。Sortables的start方法仅判断是否空闲进而决定是否真正执行。而实际项目需求有时需要屏蔽鼠标右键(带来的问题很多),而看了办法发现,找到的唯一办法仍旧是打补丁。

      最终,打上2处补丁后,世界清静了。。。

源代码:

var Sortables = new Class({

 Implements: [Events, Options],

 options: {/*
      onSort: $empty(element, clone),
     onStart: $empty(element, clone),
     onComplete: $empty(element),*/
     snap: 4,
     opacity: 1,
     clone: false,
     revert: false,
     handle: false,
     constrain: false
 },

……

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,
       container: this.options.constrain && this.element.getParent(),
       droppables: this.getDroppables(),
       onSnap: function(){
           event.stop();
           this.clone.setStyle('visibility', 'visible');
           this.element.set('opacity', this.options.opacity || 0);
           this.fireEvent('start', [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);
 },

……

补丁后:

var Sortables = new Class({

 Implements: [Events, Options],

 options: {/*
      onSort: $empty(element, clone),
     onStart: $empty(element, clone),
     onComplete: $empty(element),*/
     snap: 4,
     opacity: 1,
     clone: false,
     revert: false,
     handle: false,
     constrain: false,
     rightClickAble: false,  // add by myself
     preventDefault:false   // add by myself
 },

……

start: function(event, element){
    if (!this.idle || (!this.options.rightClickAble && event.rightClick)) return;  // modified by myself
    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,
       container: this.options.constrain && this.element.getParent(),
       droppables: this.getDroppables(),
       preventDefault:!!this.options.preventDefault,  // add by myself
       onSnap: function(){
           event.stop();
           this.clone.setStyle('visibility', 'visible');
           this.element.set('opacity', this.options.opacity || 0);
           this.fireEvent('start', [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);
 },

……