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