1. 程式人生 > >html自定義checkbox、radio、select —— checkbox、radio篇

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>。

 

接下來是為<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