自訂 form 的 valueChange 事件

此篇文章最近更新時間為2011-01-27 05:32:58 目前共有1篇留言

關於作者 - JosephJ

任職於 Faria。喜好戶外運動、2008 年 5 月完成「跑步環島」。對於新技術跟程式碼有著強烈的偏執狂。

不一致的 blur/change 事件,導致想自訂 valueChange 事件

前一篇文章「表單 Radio Button 點選,在不同瀏覽器所觸發的事件與順序」讓我覺得要將表單驗證統一綁在 onblur 或 onchange 事件有其困難性... 但自訂一個 form 的 valueChange 事件、也就是在任一欄位值有改變時被觸發、且可取得改變前後的值與物件,應該就可以滿足我想在 change 被觸發時去做表單驗證的想法了。

valueChange 如何實作

基本的思路就是在 form 節點綁上所有可取得的事件,例如 click, blur, focus, keyup, keypress, keydown, change, paste 等。將所有欄位當前的值撈出來成為 QueryString 的格式比對,若有不同就會觸發此自訂事件,此事件的 Event Handler 可以取得改變前後的值、欄位 name、被影響欄位的集合等。

valueChange 如何使用

請先在你的頁面載入 yui3 的 library、並載入我寫的 form-util.js,接著這樣用:
YUI().use("form-util", function () {
    var form = Y.one("#form-1");
    Y.FormUtil.set(form);
    form.on("valueChange", function (e) {
        Y.log(e.target); // 有被影響的節點,在 radio 的情況會有兩個
        Y.log(e.prevValue); // 此欄位先前的值
        Y.log(e.targetName); // 此欄位的名稱
    });
});

所以我們就可以 switch (targetName) 去過濾、有哪些欄位是當值有改變時就做表單驗證的。

範例頁面,請試著改變表單的內容、觀看原始碼。

相關的好用 Function

var form = Y.one("#form-1");
Y.FormUtil.set(form);
form.item("username").val(); // 取得 input[name=username] 的值。
form.item("password"); // 取得 input[name=password] 的值,不用 val 方法也行。
form.item("description"); // 取得 textarea[name=description] 的值。
form.item("categories").val("5"); // 設定 select[name=categories] 到 value=5 的 option。
form.getValue("username"); 
form.setValue("categories", "5");
form.getState(); // 以 querystring 的方式取得所有欄位的值。
Y.FormUtil.getValue(form, "username"); // Static 
Y.FormUtil.getValue(form, "password"); // Static

實作過程有趣之 1 - 在 YUI 的 Node 上綁 Custom Event

只有做過 Y.on() 這樣 Static 型態的 Custom Event,不過其實 YUI 也可以針對 Node 做 Custom Event:

Y.augment(node, Y.EventTarget);
node.publish("valueChange");

並且在適當的時間點去 fire 即可:

node.fire("valueChange"[, 要傳給使用的資料]);

雖然還是可以用 Y.on("valueChange") 來取得事件,但 node.on("valueChange") 這種方式還是直覺且好記多了 :D

實作過程有趣之 2 - 設定 Function 回傳的預設值

可以使用 form.item("username").val 設定或取得某個欄位的值,但我也希望可以用 form.item("username") 來取得值,困難的地方在於 val 函式是 item 函式執行後所產生字屬性,如何在沒呼叫到 val 時就回傳 getter 的值哩?該這就得利用到 constructore 的 toString()。壞處是每次跑這段程式都得去 new,Performance 不佳,但使用起來比較有親和力,是我覺得是很有趣的作法 :D

function Item(name){
    if (!(this instanceof Item)) {
        return new Item(name);
    }
    this.name = name;
    this.toString = function () {
        return getValue.call(this, node, name);
    };
    this.val = function (value) {
        if (arguments.length) {
            return setValue.call(this, node, this.name, value);
        } else {
            return getValue.call(this, node, this.name);
        }
    };
}
node.item = Item;


Comments

  1. 你好請教 2011-01-30 05:53:02
    你好 在網路搜尋奇摩無障礙的資料連到這你這邊來 有看到你之前寫的一篇相關文章
    http://www.wretch.cc/blog/taiwanydn/12398182

    因為我是唸特殊教育的學生 正在做視障者使用奇摩網站的無障礙問題
    看到你有歸納一些問題 不知可以跟您請教比較詳細的資訊嗎?
暱稱: 必填。
Email: 非必填。若填寫為不公開欄位,僅供站長參考聯繫。
內容: 必填。限 255 個字元以內。
驗證碼:
送出

Facebook Comment