script.aculo.usを読み解く

第11回 dragdrop.js (前編)

この記事を読むのに必要な時間:およそ 8.5 分

0167:  deactivate: function() {
0168:    this.activeDraggable = null;
0169:  },
0170:  

167~170行目のdeactivateは,現在ドラッグ中の要素を示すactiveDraggableをnullにする関数です。

0171:  updateDrag: function(event) {
0172:    if(!this.activeDraggable) return;
0173:    var pointer = [Event.pointerX(event), Event.pointerY(event)];
0174:    // Mozilla-based browsers fire successive mousemove events with
0175:    // the same coordinates, prevent needless redrawing (moz bug?)
0176:    if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
0177:    this._lastPointer = pointer;
0178:    
0179:    this.activeDraggable.updateDrag(event, pointer);
0180:  },
0181:  

171~181行目のupdateDragは,documentオブジェクトのmousemoveイベントハンドラです。ドラッグ中の処理をする関数です。

176行目で,前回のマウスポインタの位置と比べて変化があったときに,次の処理に進みます。

179行目で,現在ドラッグ中の要素のupdateDragメソッドを呼びます。

0182:  endDrag: function(event) {
0183:    if(this._timeout) { 
0184:      clearTimeout(this._timeout); 
0185:      this._timeout = null; 
0186:    }
0187:    if(!this.activeDraggable) return;
0188:    this._lastPointer = null;
0189:    this.activeDraggable.endDrag(event);
0190:    this.activeDraggable = null;
0191:  },
0192:  

182~192行目のendDragは,documentオブジェクトのmouseupイベントハンドラです。ドラッグ終了時の処理をする関数です。

189行目で,ドラッグしていた要素のendDragメソッドを呼びます。さらに状態をリセットします。

0193:  keyPress: function(event) {
0194:    if(this.activeDraggable)
0195:      this.activeDraggable.keyPress(event);
0196:  },
0197:  

193~197行目のkeyPressは,documentオブジェクトのkeyPressイベントハンドラです。ドラッグ中の要素のkeyPressメソッドを呼びます。デフォルトでは,これはEscキーのときドラッグをキャンセルする処理につながります。

0198:  addObserver: function(observer) {
0199:    this.observers.push(observer);
0200:    this._cacheObserverCallbacks();
0201:  },
0202:  

198~202行目のaddObserverは,引数にSortableObserverのインスタンスをとります。ドラッグ可能要素全体についてのフックをobservers配列に追加する関数です。

200行目で,_cacheObserverCallbacksを呼んで,フックの数を常に記憶しておきます。

0203:  removeObserver: function(element) {  // element instead of observer fixes mem leaks
0204:    this.observers = this.observers.reject( function(o) { return o.element==element });
0205:    this._cacheObserverCallbacks();
0206:  },
0207:  

203~207行目のremoveObserverは,引数にドラッグ可能要素をとります。observers配列からこの要素にからんだフックをすべて削除する関数です。

203行目のコメントで,フックでなく要素を中心に考えることでメモリリークを防げる旨が書かれています。

205行目で,_cacheObserverCallbacksを呼んで,フックの数を常に記憶しておきます。

0208:  notify: function(eventName, draggable, event) {  // 'onStart', 'onEnd', 'onDrag'
0209:    if(this[eventName+'Count'] > 0)
0210:      this.observers.each( function(o) {
0211:        if(o[eventName]) o[eventName](eventName, draggable, event);
0212:      });
0213:    if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
0214:  },
0215:  

208~215行目のnotifyは,引数にイベント名('onStart'か'onEnd'か'onDrag')と,ドラッグ可能要素と,イベント情報をとります。イベント名に該当するフックを呼ぶ関数です。

209行目で,observers配列の線形探索を何度もしなくてすむように,_cacheObserverCallbacksで,フックの数を常に記憶してあったのが役に立ちます。

210行目で,observers配列からイベント名に該当するフックを呼びます。

213行目で,さらに,ドラッグ可能要素の該当するフックを呼びます。

0216:  _cacheObserverCallbacks: function() {
0217:    ['onStart','onEnd','onDrag'].each( function(eventName) {
0218:      Draggables[eventName+'Count'] = Draggables.observers.select(
0219:        function(o) { return o[eventName]; }
0220:      ).length;
0221:    });
0222:  }
0223:}
0224:
0225:/*--------------------------------------------------------------------------*/
0226:

216~226行目の_cacheObserverCallbacksは,observers配列のなかのSortableObserverのインスタンスのフックの数を常に記憶するための関数です。

217行目で,フックの数を,それぞれonStartCount,onEndCount,onDragCountプロパティに保存します。

著者プロフィール

源馬照明(げんまてるあき)

名古屋大学大学院多元数理科学研究科1年。学部生のときにSchemeの素晴らしさを知ったのをきっかけに,関数型言語の世界へ。JavaScriptに,ブラウザからすぐに試せる関数型言語としての魅力と将来性を感じている。

ブログ:Gemmaの日記