IE's AutoComplete feature doesn't trigger onchange event is a well-known "by-design" behaviour:

Using AutoComplete in HTML Forms
To determine when a user updates the content of a field from the AutoComplete dialog box, use the onpropertychange event, rather than the onchange event, because the onchange event does not fire.

I have ever found some fixes (example 1, 2) developed by community before. Today, when I managed to put them into my project, I found something interesting.

As using jQuery 1.4+, if I set change() event on a <input type="text" />, it will be triggered as well as the event declared by onchange="..." when IE AutoComplete.  In the other word, jQuery 1.4 solved the "onchange not triggered" issue of IE AutoComplete.

After tracing the code roughly, I found jQuery uses some new mechanism: beforeactive event to store the original value in .data("_chage_data"), compares it with current value in focusout event, if not equal, then trigger the onchange event...  I guess that's why it can detect the value change when using IE AutoComplete.

So, using jQuery 1.4+, you can solved the well-known "No OnChange Event When IE AutoComplete" issue easily!

Here is my simple test case.  When jQuery 1.3.2 is included, no change event will be fired when using IE AutoComplete to fill t1, t2 value.   After changing the link to jQuery 1.4.2, you will find AutoComplete on t1 can trigger both "T1 JS change" and "T1 jQuery change" now.

<%@ Page Language="C#" AutoEventWireup="true" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script type='text/javascript' 
src='http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.js'></script>
<!--  <script type='text/javascript' 
src='http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.js'></script> -->
    <script type="text/javascript">
        function output(msg) {
            var disp = document.getElementById("disp");
            disp.innerHTML += "<li>" + msg;
        }
        $(function() {
            //if you set change event on #t1 with jQuery 1.4.2,
            //the onchange event will be triggered when using AutoComplete
            $("#t1").change(function() {
                output("T1 jQuery change");
            });
        });
    </script>
</head>
<body>
<form method="post">
T1: <input type="text" id="t1" name="t1" onchange="output('T1 JS change');"/><br />
T2: <input type="text" id="t2" name="t2" onchange="output('T2 JS change');" /><br />
<input type="submit" value="Submit" />
</form>
<div id="disp"></div>
</body>
</html>

【中文摘要】

上回試著要用autocomplete="off"法解決IE自動完成時onchange事件不會被觸發的老問題,不過如同91在回饋裡所言--要關閉使用者慣用的自動完成功能,就得向User解釋這個難以啟齒的技術鳥問題。萬一不幸遇上"角頭級"的使用者,哪可能耐著性子聽你說什麼IE自動完成、onchange這些鬼東西,只怕會換來一句--"onchange是三小,恁爸只聽過回家吃自己,沒聽過onchange啦!"... 想到這個畫面,我忽然不寒而慄,決定花時間研究一下怎麼讓AutoComplete也觸發change事件。

開了個小專案寫了jQuery做測試,卻發現一件有趣的事。AutoComplete竟會觸發onchange事件~~~ 是我眼花了還是腦筋不清楚? 明明上回驗證過,像鐵一般的事實這回怎麼來了個急轉彎? 在做了一堆測試比對後,總算釐清一件事實:

使用jQuery 1.4設定<input type="text">的change()事件後,使用IE AutoComplete也會觸發onchange事件!!

我做了一個簡單的測試案例(程式碼在上方)來驗證這點: 首先使用jQuery-1.3.2,用IE自動完成填入t1, t2的資料,並不會觸發onchange事件;改用jQuery-1.4.2後,再以自動完成為t1, t2填入資料, 這回有加掛jQuery chnage()事件的t1會觸發用jQuery及用onchange="..."宣告的事件,而t2則不會。

粗略地追了一下程式碼,發現jQuery-1.4在change事件觸發機制上做了改良: 在beforeactive事件時會將原值存在.data("_chage_data")、在focusout事件中會用它跟現值比對,不一致時則觸發change事件。這跟我原本想出的解法差不多,而jQuery在核心中已實踐了類似的邏輯,應該就是無形中修好"AutoComplete不觸發OnChange事件"問題的原因。

總之,不費吹灰之力就修好這個惱人的問題,有賺到的感覺,哈!!


Comments

# by demo

真的是賺到,自動完成我不怕你啦!!

# by 91

真是太棒了 :D

# by jain

感恩,本來打算照您的例子硬寫了~~~

# by jain

黑暗大小,目前我們在實作jquery時有問題請教一下: 在「gridview」中加入「checkbox」,是否有方法在點選「checkbox 」時就得知該列的某欄資料?

# by jain

抱歉,手誤,打錯版主名稱~~~

# by Jeffrey

to jain, 某欄的資料如果有顯示在<TD>中,可以用$(this).closest("tr").children("td:eq(n)").text()的方式取得;若要參照的欄位值沒有呈現在UI上的,我習慣的做法是設法把它變成tr的Attribute,或是一樣用<td>放置欄位值,再用CSS把它們藏起來。

Post a comment