script.aculo.usを読み解く

第7回 slider.js

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

0190:  setSpan: function(span, range) {
0191:    if (this.isVertical()) {
0192:      span.style.top = this.translateToPx(range.start);
0193:      span.style.height = this.translateToPx(range.end - range.start + this.range.start);
0194:    } else {
0195:      span.style.left = this.translateToPx(range.start);
0196:      span.style.width = this.translateToPx(range.end - range.start + this.range.start);
0197:    }
0198:  },

190~198行目の,setSpanは,実際にスパンのCSSを書き換える関数です。引数に,書き換える要素と,そのスパンの範囲をとります。

191行目で,スライダーが垂直なら,CSSのtopとheightを書き換えます。topにはスパンの始点を,heightにはスパンの幅を,それぞれtranslateToPxでCSSの値に直して代入します。

194行目で,スライダーが水平なら,CSSのleftとwidthを書き換えます。leftにはスパンの始点を,widthにはスパンの幅を,それぞれtranslateToPxでCSSの値に直して代入します。

0199:  updateStyles: function() {
0200:    this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
0201:    Element.addClassName(this.activeHandle, 'selected');
0202:  },

199~202行目の,updateStylesは,選択中のハンドルのクラス名に'selected'を加える関数です。setValueでハンドルを動かしたときや,startDragでドラッグを始めたときに,この関数が呼ばれます。

200行目で,一度,全てのハンドルのクラス名から'selected'を除きます。

201行目で,改めて,選択中のハンドルのクラス名に'selected'を加えます。

0203:  startDrag: function(event) {
0204:    if (Event.isLeftClick(event)) {
0205:      if (!this.disabled){
0206:        this.active = true;
0207:        
0208:        var handle = Event.element(event);
0209:        var pointer  = [Event.pointerX(event), Event.pointerY(event)];
0210:        var track = handle;
0211:        if (track==this.track) {
0212:          var offsets  = Position.cumulativeOffset(this.track); 
0213:          this.event = event;
0214:          this.setValue(this.translateToValue( 
0215:           (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
0216:          ));
0217:          var offsets  = Position.cumulativeOffset(this.activeHandle);
0218:          this.offsetX = (pointer[0] - offsets[0]);
0219:          this.offsetY = (pointer[1] - offsets[1]);
0220:        } else {
0221:          // find the handle (prevents issues with Safari)
0222:          while((this.handles.indexOf(handle) == -1) && handle.parentNode) 
0223:            handle = handle.parentNode;
0224:            
0225:          if (this.handles.indexOf(handle)!=-1) {
0226:            this.activeHandle    = handle;
0227:            this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
0228:            this.updateStyles();
0229:            
0230:            var offsets  = Position.cumulativeOffset(this.activeHandle);
0231:            this.offsetX = (pointer[0] - offsets[0]);
0232:            this.offsetY = (pointer[1] - offsets[1]);
0233:          }
0234:        }
0235:      }
0236:      Event.stop(event);
0237:    }
0238:  },

203~238行目の,startDragは,ドラッグを開始する関数です。この関数は,⁠トラックとハンドルの)mousedownイベントのリスナです。

205行目で,disabledフラグがtrueのときは,ドラッグを開始しません。

206行目で,ドラッグが開始したことを示すactiveフラグをtrueにします。

208行目で,イベントの発生源を取得します。

209行目で,マウスポインタの位置を取得して[x,y]の配列にします。

211行目で,もしイベントの発生源がトラックなら,以下の処理を行います。

212行目で,Prototype.jsのcumulativeOffsetメソッドで,ドキュメント基点からのオフセットを取得します。

214行目で,トラック要素の左上を基点にマウスポインタの位置を計算して,前述のtranslateToValueでスライダーの値を求めます。ここでハンドルの幅の半分を補正します。これでハンドルの中央部分がポインタの真下にきます。このsetValueを呼ぶときに,ハンドルのインデックスを指定していないので,現在選択中の(つまり最近に動かしていた)ハンドルが動きます。

217行目で,選択中のハンドルのオフセットを取得します。

218,219行目で,ポインタ位置と,選択中のハンドルのオフセットのずれ具合を保存しておきます。ドラッグしたときに,このずれを保ちながらハンドルが動くようにするためです。

画像

220行目で,もしイベントの発生源がトラックでなければ,以下でそれに最も近いハンドルを探しだします。

222行目で,whileループで,該当するハンドルが見つかるまで,親要素をたどります。

225行目で,それで実際にハンドルが見つかれば,以下の処理をします。

226,227行目で,それを選択中のハンドルとします。

228行目で,updateStylesを呼んで,選択中のハンドルのクラス名に'selected'を加えます。

230~232行目で,ここでもやはり,ポインタ位置と,選択中のハンドルのオフセットのずれ具合を保存しておきます。

著者プロフィール

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

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

ブログ:Gemmaの日記

コメント

コメントの記入