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


上一篇《html自定義checkbox、radio、select —— checkbox、radio篇》介紹了我們是怎么將 html 自帶的 checkbox、radio 改成我們自定義的UI的,現在來說說怎么將 html 自帶的 select 改成我們自定義的UI(由於時間關系,我們只完成了單選部分的轉換,而多選部分的轉換沒做,后續會找個時間補上)。

 

select 跟 checkbox、radio 方法大致相同。在 Bootstrap 中,有一個"按鈕式下拉菜單"的組件,我們是在這個基礎上進行修改的。

效果:

        

 

結構大致是:

<div>
    <button>
    <ul>
</div>
<select>

 

其中,<div>包住的就是展示出來的UI,<button>是正常情況下顯示的,<ul>是各個選項,<select>是隱藏的。

 

首先,<button>使用 Bootstrap 中 "btn dropdown-toggle" 樣式,並為其添加<span>、<i>標簽用來顯示文字和下拉的圖標,我們有對部分 ".dropdown-" 相關的樣式做了擴展和改寫。

var $button = $('<button>', { type: 'button', 'class': 'btn dropdown-toggle', 'data-toggle': 'dropdown' })
    .append($('<span>', { 'class': 'text-left pull-left' }))
    .append($('<i>', { 'class': 'caret pull-right' }))
    .click(function () {
        $button.dropdown();
        return $button;
    });

接着,將<select>中的各個選項加進<ul>中,使用<a>保存 value 和 text,並添加 click 事件。

var $selectALink;
var _addOption = function ($option, inGroup) {
    var $aLink = $('<a>', { href: 'javascript:void(0)', 'data-value': $option.val(), html: $option.html() === '' ? '&nbsp;' : $option.html() })
        .click(function () {
            if (!$aLink.data('disabled')) {
                _setSelectValue($wrapper, $aLink);
                $ul.scrollTop($aLink[0].offsetTop - 1);

                $select.trigger('change');

                if ($.validator)
                    $select.valid();
            }

            return $aLink;
        });
    inGroup && $aLink.addClass('groupopt');
    $option.attr('disabled') && $aLink.addClass('disabled').data({ disabled: true });
    $option.attr('selected') && ($selectALink = $aLink);

    $ul.append($('<li>').append($aLink));
}

var $ul = $('<ul>', { 'class': 'dropdown-menu' });
$select
    .children()
    .each(function () {
        var $obj = $(this);
        if ($obj.is('optgroup')) {
            $ul.append(
                $('<li>').append(
                    $('<label>', { 'class': 'optgroup', html: $obj.attr('label') })
                )
            );
            $('option', $obj).each(function () {
                _addOption($(this), true);
            });
        } else if ($obj.is('option')) {
            _addOption($obj);
        }
    });

然后將<button>、<ul>裝進<div>中,隱藏<select>,設置初始值,再做一些調整,就可以看到這種效果了:

 

對於我們來說,做麻煩的就是當使用 JQ 控制顯示隱藏(hide()、show())的時候,修改的<select>也要跟着變化。說以我們只能重寫 JQ 的 hide()、show() 方法。

首先對 <select> 添加對應處理方法:

$select
    .addClass('hide')
    .data({ transformed: true })
    .on({
        hide: function () {
            $wrapper.hide();
            _setSelectStatus($select);
        },
        show: function () {
            $wrapper.show();
            _setSelectStatus($select);
        },
        transformReset: function () {
            $('option', $select).not(_$defaultSelected.attr({ selected: true })).attr({ selected: false });
            $select.transformResetStatus();
        }
    });

同 checkbox、radio,transformReset() 方法也是用於表單重置的。

接着,重寫 JQ 的 hide()、show() 方法,而我們的目的是新方法僅對 <select> 有效,而其他標簽依舊使用舊方法,所以:

var _oldhide = $.fn.hide;
var _oldshow = $.fn.show;
$.fn.hide = function (speed, callback) {
    if (this.is('select') && this.data('transformed')) {
        this.trigger('hide');
    } else {
        _oldhide.apply(this, arguments);
    }
    return this;
};
$.fn.show = function (speed, callback) {
    if (this.is('select') && this.data('transformed')) {
        this.trigger('show');
    } else {
        _oldshow.apply(this, arguments);
    }
    return this;
};

至此,整個改造過程大體完成,測試也能通過。

 

但是后來又有問題了,就是用 JQ 改變 checkbox、radio、select 的值的時候,顯示的東西不會隨着變。

嘗試了很多方法,想實現自動同步的效果,但是都失敗了了。后來,我們只能在代碼里,手動同步了,即在修改后,再調用一個方法來同步:

$.fn.transformResetStatus = function () {
    return this.each(function () {
        var $obj = $(this);
        if ($obj.is('input')) {
            $obj.data('transformed') && _setInputStatus($obj);
        } else if ($obj.is('select')) {
            $obj.data('transformed') && _setSelectStatus($obj);
        }
    });
};

 

好了,3個標簽的改造已經完成了。大家可以試試 Demo,在 IE8、9、chrome、ff 上測試通過,其他沒測過。

demo 可能寫得不夠好,插件也可能存在一些問題我還沒發現的,請發現任何問題都跟我說一下,謝謝各位!

 


另:要請教各位怎么把文件放在網盤上,然后直接 copy 出文件路徑,今天試過115、百度、騰訊的,都不能直接 copy,都是只能引到另一個頁面下載。

 


免責聲明!

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



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