【鼠標(biāo)滾輪控制】
鼠標(biāo)滾輪控制,就是通過鼠標(biāo)滾輪滾動來控制滑塊的滑動。 首先ie綁定滾輪事件用的是mousewheel,ff用的是DOMMouseScroll,所以在WheelBind綁定鼠標(biāo)滾輪程序中是這樣設(shè)置的:
addEventHandler(o, isIE ? "mousewheel" : "DOMMouseScroll", BindAsEventListener(this, this.WheelCtrl));
接著看WheelCtrl鼠標(biāo)滾輪控制程序,通過event的detail屬性可以獲取鼠標(biāo)滾動的距離(值大小)和方向(正負(fù))。 利用它來設(shè)置要滑動的位置:
var i = this.WheelSpeed * e.detail; this.SetPos(this.Bar.offsetLeft + i, this.Bar.offsetTop + i);
但ie沒有detail,對應(yīng)的有wheelDelta,wheelDelta的數(shù)值剛好是detail的40倍,而且方向相反(正負(fù)相反),所以Event程序中是這樣給window.event添加detail的:
oEvent.detail = oEvent.wheelDelta / (-40);
為了防止觸發(fā)其他滾動條,這里用了preventDefault取消默認(rèn)動作。 注意不是用取消冒泡(貌似滾屏是事件的默認(rèn)動作)。
【方向鍵控制】
方向鍵控制,就是通過鍵盤的左右(上下)方向鍵來控制滑塊的滑動。 首先用KeyBind方向鍵綁定程序把KeyCtrl方向鍵控制程序綁定到對象的keydown事件中:
addEventHandler(o, "keydown", BindAsEventListener(this, this.KeyCtrl));
在KeyCtrl中,通過event的keyCode屬性獲取鍵盤的按鍵(左37、上38、右39、下40)并進(jìn)行相應(yīng)的操作:
switch (e.keyCode) { case 37 ://左 iLeft -= iWidth; break; case 38 ://上 iTop -= iHeight; break; case 39 ://右 iLeft += iWidth; break; case 40 ://下 iTop += iHeight; break; default : return;//不是方向按鍵返回 }
同樣為了防止觸發(fā)其他滾動條,也用了preventDefault取消默認(rèn)動作。
【focus和tabIndex】
在KeyBind程序中,除了綁定對象的keydown事件,還不夠的,可以在ff測試下面的代碼:
<div style="width:100px; height:100px; background-color:#CCC;" onkeydown="alert(1)"></div>
無論怎樣都觸發(fā)不了onkeydown事件(ie可以觸發(fā)),那就奇怪了,按照一般的思路應(yīng)該是可以的啊。 這個可以從w3c關(guān)于KeyboardEvent的部分中找到原因: Keyboard events are commonly directed at the element that has the focus. 大概就是說鍵盤按鍵事件一般指向能獲取焦點的元素,就是不能獲取焦點的元素就不能觸發(fā)鍵盤按鍵事件了。
難道div就不能獲取焦點?用下面的代碼測試(ff):
<div id="test" style="width:100px; height:100px; background-color:#CCC;" onfocus="alert(1)"></div> <script>document.getElementById("test").focus();</script>
還真的不行,那問題就在于怎么使div能獲取焦點了(當(dāng)然這個是轉(zhuǎn)了不少彎才想出來的)。
最后發(fā)現(xiàn)給元素設(shè)置tabIndex就能讓元素能獲取焦點了,如果不需要詳細(xì)了解的話下面可以略過。 首先看看w3c關(guān)于onfocus的部分: The onfocus event occurs when an element receives focus either by the pointing device or by tabbing navigation. This attribute may be used with the following elements: A, AREA, LABEL, INPUT, SELECT, TEXTAREA, and BUTTON. 當(dāng)元素通過指定(點擊)或tab導(dǎo)航(Tabbing navigation)獲得焦點,onfocus事件就會觸發(fā)。 該屬性會使用在以下元素(就是說默認(rèn)可以獲取焦點的元素):A, AREA, LABEL, INPUT, SELECT, TEXTAREA, and BUTTON. 測試下面的代碼:
<a href="#" onfocus="alert(1)" onkeydown="alert(2)">focus</a>
果然兩個事件都可以執(zhí)行。
接著看Tabbing navigation的部分: Those elements that do not support the tabindex attribute or support it and assign it a value of "0" are navigated next. These elements are navigated in the order they appear in the character stream. 這里看得不太明白,關(guān)鍵的意思是給元素設(shè)置tabindex為0就可以被導(dǎo)航到了(能獲取焦點了)。 測試下面的代碼(ff):
<div tabindex="0" style="width:100px; height:100px; background-color:#CCC;" onfocus="alert(1)" onkeydown="alert(2)"></div>
果然兩個事件都能觸發(fā)了。
不過w3c說得很模糊,msdn上倒是很清楚: An element can have focus if the tabIndex property is set to any valid negative or positive integer. Elements that receive focus can fire the onblur and onfocus events as of Internet Explorer 4.0, and the onkeydown, onkeypress, and onkeyup events as of Internet Explorer 5. 只要元素的tabIndex屬性設(shè)置成任何有效的整數(shù)那么該元素就能取得焦點。元素在取得焦點后就能觸發(fā)onblur,onfocus,onkeydown, onkeypress和onkeyup事件。
不同tabIndex值在tab order(Tabbing navigation)中的情況: Objects with a positive tabIndex are selected in increasing iIndex order and in source order to resolve duplicates. Objects with an tabIndex of zero are selected in source order. Objects with a negative tabIndex are omitted from the tabbing order. tabIndex值是正數(shù)的對象根據(jù)遞增的值順序和代碼中的位置順序來被選擇 tabIndex值是0的對象根據(jù)在代碼中的位置順序被選擇 tabIndex值是負(fù)數(shù)的對象會被忽略
這個不知道是否符合標(biāo)準(zhǔn),但貌似ff跟ie是一樣的(不同的地方后面會說)。 那么設(shè)置一個負(fù)的tabIndex值應(yīng)該是最理想的了。
ps:如果對ff的tabindex有興趣的話,推薦看看Test cases for tabindex bugs in Firefox,里面有更詳細(xì)更專業(yè)的分析。
那ie通過一開始的測試,是不是就說明不需要了呢?我們換一個元素測試:
<ul style="width:100px; height:100px; background-color:#CCC;" onfocus="alert(1)" onkeydown="alert(2)"></ul>
換成ul就又不能觸發(fā)事件了,怎么搞的。
再看看msdn,里面有一段: The following elements can have focus by default but are not tab stops. .略. applet, div, frameSet, span, table, td. 下面的元素默認(rèn)能獲取焦點但不能tab導(dǎo)航:applet, div, frameSet, span, table, td. 看來ie真是“為程序員著想”,但其他元素總不能漏了啊,還是全部都設(shè)置tabIndex好了。
終于回到程序上來,首先設(shè)置tabIndex:
o.tabIndex = -1;
ff元素獲得焦點后會出現(xiàn)一個虛線框,去掉會美觀一點:
isIE || (o.style.outline = "none");
ps:如果tabIndex設(shè)為0或以上的話ie也會出現(xiàn)虛線框。
綁定了keydown之后,點擊一下容器(獲取焦點)后就能用方向鍵控制方向了,但如果(沒有獲得焦點時)點擊滑塊,還是觸發(fā)不了事件。 因為滑塊在拖動效果中ie的鼠標(biāo)捕獲和ff的取消默認(rèn)動作導(dǎo)致容器不能獲得焦點,那手動設(shè)置可以嗎? 是可以的,ff中就是直接在滑塊的mousedown事件中執(zhí)行容器的focus方法獲得焦點。 ie本來也是可以的,但ie中當(dāng)對象執(zhí)行focus方法時,如果該對象有部分在滾動條外就會自動滾動到適當(dāng)?shù)奈恢茫ㄟ好點擊不會這樣)。 為了降低影響,程序中把滑塊也綁定了鍵盤控制,這樣點擊滑塊時只要執(zhí)行滑塊的focus方法獲得焦點就可以了:
var oFocus = isIE ? (this.KeyBind(this.Bar), this.Bar) : this.Container; addEventHandler(this.Bar, "mousedown", function(){ oFocus.focus(); });
ps:由于focus并不會冒泡(w3c標(biāo)準(zhǔn)),所以不用擔(dān)心滑塊的focus導(dǎo)致容器獲得焦點。 ps2:w3c的文檔還真是難讀,還是msdn的易懂。
出處:藍(lán)色理想
責(zé)任編輯:bluehearts
上一頁 仿Apple滑動條(拖動)產(chǎn)品展示效果 [3] 下一頁 仿Apple滑動條(拖動)產(chǎn)品展示效果 [5]
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|