UPDATE:(回顧一下,小提琴和獎金)JavaScript的:如何模擬變化事件在Internet Explorer(代表團)
這個問題還沒有得到太多的關注,所以我要去花一些代表就可以了。我知道我的答案和問題往往過於冗長。這就是爲什麼我繼續設立this fiddle,這一點,在我看來,我目前不必使用到接近沸騰change
事件樣的代碼體面的表現。我試圖解決幾個問題:
pseudo-change
事件不會觸發select元素,除非它失去焦點。在某些情況下,應在選擇新值時重定向客戶端。我如何實現這一目標?- 的處理程序被調用這兩個標籤被點擊時,以及複選框自己。本身就是你所期望的,但由於事件冒泡,它(AFAIK)無法確定哪個元素被點擊。 IE的事件對象沒有
realTarget
屬性。 - 如果通過單擊標籤改變
checked
-state在IE複選框的,一切都很好(儘管它需要一些討厭的解決方法),而是直接點擊複選框時,調用處理程序,但選中狀態保持不變,直到我再次點擊。然後值改變,但處理程序不被調用。 - 當我切換到不同的選項卡,然後再返回,處理程序被調用多次。如果檢查狀態實際發生了變化,則爲三次,如果直接單擊checbox,則只有一次。
任何可以幫助我解決上述問題的信息都將不勝感激。請,我不會忘記添加一個jQuery標記,我喜歡純JS,所以我正在尋找一個純JS的答案。
我有一個網頁上有超過250個選擇元素和20〜30個複選框。我也必須跟蹤用戶的行爲,並採取適當的行動。因此,我很自然地委派變革事件,而不是增加數百名聽衆,恕我直言。
當然,IE -company政策:IE8必須是當我需要它supported-不會觸發onchange事件。所以我試圖僞造一個onchange事件。到目前爲止,我所做的工作除了一件讓我真正感到困惑的事情外,還有相當好的工作。
我使用onfocusin
和onfocusout
來註冊事件。在某些情況下,當用戶從select元素中選擇一個新值時,腳本應該立即響應。然而,只要選擇沒有失去焦點,這將不會發生。
這就是我想出迄今:
i = document.getElementById('content');
if (!i.addEventListener)
{
i.attachEvent('onfocusin',(function(self)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
switch (target.tagName.toLowerCase())
{
case 'input':
if (target.getAttribute('type') !== 'checkbox')
{
return true;
}
return changeDelegator.apply(self,[e]);//(as is
case 'select':
self.attachEvent('onfocusout',(function(self,current)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
if (target !== current)
{
return;
}
self.detachEvent('onfocusout',arguments.callee);//(remove closure
return changeDelegator.apply(self,[e]);
}
})(self,target));
default: return;
}
}
})(i));//(fake change event, buggy
}
else
{//(to put things into perspective: all major browsers:
i.addEventListener('change',changeDelegator,false);
}
我試着安裝了onfocusin
處理器內的另一個事件監聽器,綁定到onclick
事件。它發射了任何選擇重點ATM的onfocusout
事件。唯一的問題是,99.9%的用戶會點擊一個選擇,因此focusin
事件也會觸發onclick。
爲了避開這一點,我創建了封閉,並接受當前選擇,對焦和它的原始值,將其作爲參數。但有些用戶做使用他們的鍵盤,並且這些用戶經常選項卡到下一個選擇框而不更改值。每次綁定一個新的onclick聽衆...我相信有HAS比檢查所有e.type
和分開處理它們更容易。
只是作爲一個例子:有一個額外的onclick
監聽器代碼:所有代碼都是一樣的第一個片段,所以我只粘貼case 'select':
塊
case 'select':
self.attachEvent('onfocusout',(function(self,current)
{
return function(e)
{
e = e || window.event;//(IE...
var target = e.target || e.srcElement;
if (!(target === current))
{
return;
}
self.detachEvent('onfocusout',arguments.callee);//(remove closure
return changeDelegator.apply(self,[e]);
};
})(self,target));
self.attachEvent('onclick',(function(self,current,oldVal)
{
return function(e)
{
e = e || window.event;
var target = e.target || e.srcElement;
if (target.tagName.toLowerCase() === 'option')
{
while(target.tagName.toLowerCase() !== 'select')
{
target = target.parentNode;
}
}
if (target !== current)
{//focus lost, onfocusout triggered anyway:
self.detachEvent('onclick',arguments.callee);
return;
}
var val = target.options[target.selectedIndex].innerHTML;//works best in all browsers
if (oldVal !== target.options[target.selectedIndex].innerHTML)
{
self.detachEvent('onclick',arguments.callee);
return target.fireEvent('onfocusout');
}
};
})(self,target,target.options[target.selectedIndex].innerHTML));
default: return;
1.是的,我確定:IE8觸發更改事件,但它不會冒泡。這是[已知問題](http://stackoverflow.com/questions/5146784/make-form-elements-onchange-bubble-in-internet-explorer) 2.在兩種情況下調用更改處理程序,那不是問題。然而,當點擊標籤時,處理程序在檢查狀態發生變化後被調用,而直接點擊複選框後,檢查狀態即將改變。所以如果'target.checked === true',它剛剛被檢查過,還是會被取消選中?沒有辦法說。用盡字符 –
3.添加模糊和焦點會導致IE崩潰:請注意,由於「onchange」不冒泡,因此我使用「onfocusin」和「onfocusout」事件。如果處理程序模糊不清並重點關注,它會繼續不斷地調用它自己。 4.處理程序的意思是:嚴格地說'changeDelegator'只是一個函數,但我在處理程序的上下文中調用了一個函數('changeDelegator。 apply(this,[e]);'),所以我認爲它是實際處理程序的擴展/延續。我知道,當選項卡爲_revived_時,'focusin'會被觸發,但對於由委託人函數處理的每個事件,它都會被觸發。字符.... –
我最後的意思是簡單的:我點擊一個複選框(處理程序被觸發,但是選中狀態不會改變!),如果我再次點擊該複選框,那麼處理程序isn沒有打電話,但檢查的狀態都改變了。如果我沒有再次單擊它,但切換標籤並再次返回,'focusin'事件顯示_not_不會被調用,我點擊一次該複選框。真奇怪。在性能方面:有一個主要的區別,尤其是當在V8上不運行它時更是如此。將它附加到整個頁面上的每個元素將加起來爲333(只計數它們)elems!字符... –