html自定義checkbox、radio、select —— checkbox、radio篇


前些日子,所在公司項目的UI做了大改,前端全部改用 Bootstrap 框架,Bootstrap的優缺點在此就不詳述了,網上一大堆相關資料。

前端的設計就交給我和另一個同事[LV,大學同班同學,畢業后在同一家公司同一個部門同一個項目組共事,現在他離職跑去創業了,小小懷念一下他],由於我們都是不喜歡 html 自帶的 checkbox、radio、select 的樣式,所以就決定自己來寫一套基於 Bootstrap 的樣式。

 

對於 checkbox/radio,首先我們想到的就是用圖片來替換掉現有的點擊框,我會一點PS,所以圖片就交給我了:

 從左到右分別是:unchecked: { normal, hover, active/focus}; checked: { normal, hover, active/focus}; disabled: { unchecked, checked }

針對這些 Icon,寫好對應的樣式。由於 Bootstrap 自帶的 Icon 寬、高都為 14px,我們也用同樣的大小,並且參照 Bootstrap Icon 命名:icon-sfa[項目名縮寫]-checkbox / icon-sfa-radio

寫代碼的中途,我曾想過直接用樣式來控制UI,不使用圖片,如 Google 的登錄。但后來放棄了,原因是坑爹的 IE8-,完全不支持。

替換現有的樣式並不難,無非就是將原有的點擊框隱藏起來,用圖片來代替現有的位置。

難的是事件的響應!

 

我們是在原有系統UI的基礎上,進行UI的替換的。所以原有頁面會有許多的JS代碼,而我們最不想碰的就是這些JS代碼。所以對於事件的響應,我們可真是絞盡腦汁了,特別是對 select 改寫(在下一篇將會詳述)。

 

替換樣式:

<label>
    <i>
    <input type="checkbox">
    text
</label>

 

大致結構就是這樣,其中<i>用來顯示自定義 Icon,其他照舊。

為<label>添加 hover、mousedown、mouseup 事件,分別用來處理對應的UI顯示;

為<input>添加隱藏樣式:{ opacity: 0, position: 'relative', left: -99999 },使用 "opacity" 不使用 "display" 的原因,依舊是坑爹的 IE。由於我們需要為<input>添加 change 事件來改變UI顯示,但是如果使用 "display",在 IE8- 下是無法促發 change 事件的。

我們甚至想過直接為<label>添加 click 事件,但是均會有沖突。為了兼容各個瀏覽器內核,嘗試了許多方法后,最終選擇使用 "opacity",目前經過測試,IE、chrome、ff 下是可以正確使用的。

至於使用 "position" 和 "left",是因為在 IE 下,會有這么一個惡心的虛線框 ,只能選擇把它遠遠的移走。"position" 的值為 "relative" 而不是 "absolute",是因為原先<input>的位置,包括大小要預留着給<i>。

(今天在寫 demo 時發現,是由於 "bootstrap.extension.css" 里對 <i> margin-left 進行了設置,導致值為 "absolute" 時出現位置偏差,在此改過。應為 "absolute",且刪除 "bootstrap.extension.css" 中的設置,demo 已更新)

接下來是為<input>添加 change 事件,根據當前<input> checked 的值,改變顯示的UI。這里需要注意的是,radio 是以 name 的值來進行分組的,即幾個 name 的值相同的 radio <input>將會組成一組,而每一組最多只能有一個 radio 選中。

最后,為<input>定義一個用於 form reset 的方法,用於當重置表單時,重新初始化顯示的UI。

 

貼上主體JS:

// Transform Checkbox / Radio
$.fn.transformInput = function () {
    return this.each(function () {
        var $input = $(this);
        if ($input.data('transformed')) { return; }

        var _defaultChecked = false;
        var $label = _getLabel($input);
        var $icon = $('<i>', { 'class': $input.is('input:checkbox') ? 'icon-sfa-checkbox' : 'icon-sfa-radio' })
            .insertBefore($input);
        $input.attr('checked') && $icon.addClass('checked') && (_defaultChecked = true);
        $input.attr('disabled') && $icon.addClass('disabled');

        $label
            .hover(function () { $icon.addClass('hover'); return $label; }, function () { $icon.removeClass('hover').removeClass('active'); return $label; })
            .mousedown(function (event) { if (event.which == 1) { $icon.addClass('active'); } return $label; })
            .mouseup(function (event) { $icon.removeClass('active'); return $label; });
        $input
            .data({ transformed: true })
            .css({ opacity: 0, position: 'relative', left: -99999 })
            .change(function () {
                if (!$input.attr('disabled')) {
                    if ($input.is('input:radio')) {
                        var _name = $input.attr('name');
                        if (_name != undefined && _name != '') {
                            $('input[name="' + _name + '"]', this.form).not($input).attr({ checked: false }).transformResetStatus();
                        }
                        $input.attr({ checked: true });
                    }
                    $input.transformResetStatus();
                }

                return $input;
            })
            .on({
                transformReset: function () {
                    $input.attr({ checked: _defaultChecked }).transformResetStatus();
                }
            });
    });
};

里面有一些方法這里就不貼出來了,將在下一篇《html自定義checkbox、radio、select —— select篇》一起將代碼上傳。

 

看看在流瀏覽器中的效果:

 


 

下一篇《html自定義checkbox、radio、select —— select篇》在周5下班前貼出,將附上 checkbox、radio、select 的demo


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM