script.aculo.usを読み解く

第11回 dragdrop.js (前編)

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

0111:  fire: function(event, element) {
0112:    if(!this.last_active) return;
0113:    Position.prepare();
0114:
0115:    if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
0116:      if (this.last_active.onDrop) {
0117:        this.last_active.onDrop(element, this.last_active.element, event); 
0118:        return true; 
0119:      }
0120:  },
0121:

111~121行目のfireは,引数にイベント情報と,ドラッグした要素をとります。ドラッグ終了直後に呼ばれる関数です。

113行目で,Position.prepareを呼んで,スクロール位置の調整をします。

115行目で,このドロップを受けつけるかをisAffected関数でチェックします。

116行目で,もしonDropフックがあれば呼びます。

0122:  reset: function() {
0123:    if(this.last_active)
0124:      this.deactivate(this.last_active);
0125:  }
0126:}
0127:

122~127行目のresetは,deactivate関数を呼んで,現在ドラッグが上空にあるドロップ先であるlast_activeの状態を,元に戻す関数です。

Draggables

ドラッグ可能要素の全体を管理するためのクラスです。以下で,このクラスに登場するプロパティの意味について解説します。

drags
Draggableクラスのインスタンスをすべて保持する配列です。
observers
SortableObserverクラスのインスタンスが入る配列です。
onStartCount,onEndCount,onDragCount
observers配列にあるフックの数を記憶するためのプロパティです。フックの追加,削除のたびに_cacheObserverCallbacksで更新します。
activeDraggable
現在ドラッグ中の要素を示します。マウスイベントで常に更新します。
_lastPointer
前回のマウスポインタの位置です。前回のマウスイベントと比べてポインタの位置に変化があったときだけ処理を行うために必要です。
_lastScrollPointer
前回のスクロール位置です。
_timeout
activate関数で処理を指定時間遅延するためのタイマです。

それではコードを見ていきましょう。

0128:var Draggables = {
0129:  drags: [],
0130:  observers: [],
0131:  

129,130行目のdrags,observersは上述の通りです。

0132:  register: function(draggable) {
0133:    if(this.drags.length == 0) {
0134:      this.eventMouseUp   = this.endDrag.bindAsEventListener(this);
0135:      this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
0136:      this.eventKeypress  = this.keyPress.bindAsEventListener(this);
0137:      
0138:      Event.observe(document, "mouseup", this.eventMouseUp);
0139:      Event.observe(document, "mousemove", this.eventMouseMove);
0140:      Event.observe(document, "keypress", this.eventKeypress);
0141:    }
0142:    this.drags.push(draggable);
0143:  },
0144:  

132~144行目のregisterは,引数にドラッグ可能要素をとります。drags配列に,ドラッグ可能要素を登録する関数です。

133~141行目で,もしこれが初めての登録ならば,documentオブジェクトに各種のイベントハンドラを設定します。

142行目で,drags配列に要素を追加します。

0145:  unregister: function(draggable) {
0146:    this.drags = this.drags.reject(function(d) { return d==draggable });
0147:    if(this.drags.length == 0) {
0148:      Event.stopObserving(document, "mouseup", this.eventMouseUp);
0149:      Event.stopObserving(document, "mousemove", this.eventMouseMove);
0150:      Event.stopObserving(document, "keypress", this.eventKeypress);
0151:    }
0152:  },
0153:  

145~153行目のunregisterは,引数にドラッグ可能要素をとります。このクラスのdrags配列から,ドラッグ可能要素を削除する関数です。

147~151行目で,もしこれが最終の削除ならば,documentオブジェクトからイベントハンドラを解除します。

0154:  activate: function(draggable) {
0155:    if(draggable.options.delay) { 
0156:      this._timeout = setTimeout(function() { 
0157:        Draggables._timeout = null; 
0158:        window.focus(); 
0159:        Draggables.activeDraggable = draggable; 
0160:      }.bind(this), draggable.options.delay); 
0161:    } else {
0162:      window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
0163:      this.activeDraggable = draggable;
0164:    }
0165:  },
0166:  

154~166行目のactivateは,引数にドラッグ可能要素をとります。現在ドラッグ中の要素を示すactiveDraggableを設定する関数です。指定した時間,処理を遅延する機能があります。

155~160行目で,ドラッグ可能要素のoptions.delayで指定した時間,タイマで処理を遅延します。

158,162行目で,キーボードイベントを受けつけるため,window.focusでフォーカスを持ちます。

159,163行目で,現在ドラッグ中の要素を示すactiveDraggableを更新します。

著者プロフィール

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

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

ブログ:Gemmaの日記