西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
軟件
軟件
文章
搜索

首頁編程開發(fā)javascript|JQuery → 基于jquery級聯(lián)的下拉插件

基于jquery級聯(lián)的下拉插件

相關(guān)軟件相關(guān)文章發(fā)表評論 來源:西西整理時間:2012/10/28 9:01:58字體大。A-A+

作者:佚名點(diǎn)擊:43次評論:2次標(biāo)簽: 下拉

  • 類型:濾鏡插件大。1.5M語言:英文 評分:6.6
  • 標(biāo)簽:
立即下載

/* 
 * 基于jquery級聯(lián)選擇
 * target: 下一級的jquery選擇器
 * urlOrData: ajax請求的url或用于刷選的Data
 * options: 配置
 */
(function($) {
    var defaultOptions = {
        after: null,
        before: null,
        usePost: false,
        defaultValue: null,
        filter: null,
        preValue: '-1',
        preText: '請選擇',
        groupSort: 'desc', 
        order: 'name asc',
        params: {},
        dataMap: {'text': 'text', 'value': 'value', 'group': 'group'}
    };
    var missGroup = '__MISS__';
    var dataToOption = function(data, op) {
        var d = [], vs = [], hasFilter = op.filter && $.isFunction(op.filter);
        $.each(data, function(i, v) {
            if(!hasFilter || (hasFilter && op.filter(v, i))) {
                if($.inArray(v[op.dataMap.value], vs) == -1) {
                    d.push($.extend({}, v));
                    vs.push(v[op.dataMap.value]);
                }
            }
        });
        if(op.order) {
            var sp = op.order.split(' '), col = sp[0], sort = sp[1].toLowerCase() == 'asc' ? 1 : -1;
            d.sort(function(a, b) {
                if(a[col] > b[col]) {
                    return sort;
                } else if(a[col] < b[col]) {
                    return -sort;
                } else {
                    return 0;
                }
            });
        }
        var ops = '', gps = groupData(mapData(d, op.dataMap));
        var createOption = function(items) {
            var _ops = '';
            if(!$.isArray(items)) {
                items = [items];
            }
            $.each(items, function(i, v) {
                _ops += '<option value="' + v['value'] + '">' + v['text'] + '</option>';
            });
            return _ops;
        };
        var createGroup = function(group, options) {
            return '<optgroup label="' + group + '"></optgroup>' + options;
        };
        if(op.preValue || op.preText) {
            ops += createOption({'value': op.preValue, 'text': op.preText});
        }
        if(gps[missGroup] != undefined) {
            ops += createOption(gps[missGroup]);
            delete gps[missGroup];
        }
        if(op.groupSort == 'desc') {
            gps['keys'].sort().reverse();
        } else if(op.groupSort == 'asc') {
            gps['keys'].sort()
        }
        $.each(gps['keys'], function(i, v) {
            ops += createGroup(v, createOption(gps[v]));
        });
        return ops;
    };
    var mapData = function(data, map) { 
        $.each(data, function(i, v) {
            $.each(map, function(j, k) {
                if(v[j] == undefined) {
                    data[i][j] = v[k] == undefined ? '' : v[k];
                    delete data[i][k];
                }
            });
        });
        return data;
    };
    var groupData = function(data) {
        var gps = {};
        gps['keys'] = [];
        var pushData = function(group, item) {
            if(gps[group] == undefined) {
                gps[group] = [];
            }
            gps[group].push(item);
        };
        var pushKey = function(key) {
            if($.inArray(key, gps['keys']) == -1) {
                gps['keys'].push(key);
            }
        };
        $.each(data, function(i, v) {
            if(v['group']) {
                pushKey(v['group']);
                pushData(v['group'], v);
            } else {
                pushData(missGroup, v);
            }
        });
        return gps;
    };
    $.fn.fillselect = function(urlOrData, options) {
        return this.each(function() {
            var $t = $(this), op, dataReadyCallback, ajaxXHR = null;
            op = $.extend(true, {}, defaultOptions, options);
            $t.data('fillselectOptions', op);
            if(op.before && $.isFunction(op.before)) {
                op.before.apply($t);
            }
            dataReadyCallback = function(data) {
                $t.html(dataToOption(data, op));
                if(op.defaultValue) {
                    $t.val(op.defaultValue);
                }
                if(op.after && $.isFunction(op.after)) {
                    op.after.apply($t);
                }
                $t.trigger('change');
            };
            if(typeof urlOrData == 'string') {
                if(ajaxXHR) {
                    ajaxXHR.abort();
                }
                ajaxXHR = $.ajax({
                    'url': urlOrData,
                    'type': op.usePost ? 'post' : 'get',
                    'data': op.params,
                    'dataType': 'json',
                    'success': function(data) {
                        ajaxXHR = null;
                        if(data.status == '200') {
                            dataReadyCallback(data.data || []);
                        }
                    },
                    'error': function() {
                        ajaxXHR = null;
                    }
                });
            } else {
                dataReadyCallback(urlOrData);
            }
        });
    };
    $.fn.chainselect = function(target, urlOrData, options) {
        return this.each(function() {
            $(this).bind('change', function() {
                var $t = $(this), op;
                op = $.extend(true, {}, defaultOptions , options);
                op.params[$t.attr('name') || $t.attr('id')] = $t.val();
                op.params['id'] = $t.val();
                if($t.val() != $t.data('fillselectOptions').preValue) {
                    $(target).fillselect(urlOrData, op);
                } else {
                    op.after = null;
                    $(target).fillselect([], op);
                }
            });
        });
    }
})(jQuery);

此段代碼實際上包含了兩個jq插件,第一個是fillselect用于填充select,支持data或url(ajax)的方式;第二個是chainselect用于級聯(lián)select。下面就詳細(xì)介紹一下這段代碼:

var defaultOptions = {
        after: null,
        before: null,
        usePost: false,
        defaultValue: null,
        filter: null,
        preValue: '-1',
        preText: '請選擇',
        groupSort: 'desc', 
        order: 'name asc',
        params: {},
        dataMap: {'text': 'text', 'value': 'value', 'group': 'group'}
    };

插件的默認(rèn)參數(shù)配置

after:select數(shù)據(jù)載入結(jié)束事件callback

before:數(shù)據(jù)載入前事件callback

usePost:ajax請求方式,默認(rèn)為GET

defaultValue:默認(rèn)選中的值

filter:數(shù)據(jù)過濾函數(shù),類似jq的grep方法,使用方式也是一樣的,第一個參數(shù)為value,第二個參數(shù)為key或index,當(dāng)返回值為false即過濾掉該條數(shù)據(jù),如:filter: function(v, i) { return v.count > 1; }過濾數(shù)據(jù)中count屬性小于1的數(shù)據(jù)

preValue,preText:初始o(jì)ption的值和文字

groupSort:分組optgroup排序方式

order:數(shù)據(jù)的排序方式,排序字段與方向空格隔開

params:隨ajax請求傳遞的參數(shù)

dataMap:數(shù)據(jù)屬性映射,目的提高插件對數(shù)據(jù)的自適應(yīng)性,如真實數(shù)據(jù)是name,id,year,則dataMap: { 'text': 'name', 'value': 'id', 'group': 'year' };如果不使用分組功能,只需保留text和value

missGroup:缺省分組名;

dataToOption:用于將數(shù)據(jù)轉(zhuǎn)換成option;

mapData:將數(shù)據(jù)轉(zhuǎn)成統(tǒng)一格式;

groupData:將數(shù)據(jù)分組;

這段實現(xiàn)邏輯略顯冗長,因為實際項目中的需求多變,這個可根據(jù)實際需求簡化一下代碼。

$.fn.fillselect在dataReadyCallback中觸發(fā)change事件主要目的是使此select的下一級生效;

$.fn.chainselect多了一個target參數(shù)用于指向下一級的jq選擇器。

那么現(xiàn)在來看下怎么使用,需求:廠牌brand->車款kind->車型model,ajax獲取的數(shù)據(jù)格式為{status: 200, data: [{id: 1, name: 'bmw'}, {id: 2, name: 'benz'}]};車型的數(shù)據(jù)需要根據(jù)year_name分組

<select name="brand" id="brand"></select>
<select name="kind" id="kind" disabled></select>
<select name="model" id="model" disabled></select>

    $('#brand').chainselect('#kind', '/request_url', {
            'dataMap': {'value': 'id', 'text': 'name'}, 
            'preValue': -1,
            'preText': '選擇/車款',
            'params': {'type': '_cache_kind'},
            'before': function() {
                this.attr('disabled', true);
            },
            'after': function() {
                this.removeAttr('disabled');
            },
            'defaultValue': lastKindId || -1
        });
        $('#kind').chainselect('#model', '/request_url', {
            'dataMap': {'value': 'myid', 'text': 'name', 'group': 'year_name'}, 
            'preValue': -1,
            'preText': '選擇/車型',
            'params': {'type': '_cache_model'},
            'filter': function(v, i) {
                return $.inArray(v.myid, myids) === -1;
            },
            'before': function() {
                this.attr('disabled', true);
            },
            'after': function() {
                this.removeAttr('disabled');
            }
        });
        $('#brand').fillselect('/request_url', {
            'dataMap': {'value': 'id', 'text': 'name'}, 
            'preValue': -1,
            'preText': '選擇/廠牌',
            'params': {'type': '_cache_brand'},
            'defaultValue': lastBrandId || -1
        });

    相關(guān)評論

    閱讀本文后您有什么感想? 已有人給出評價!

    • 8 喜歡喜歡
    • 3 頂
    • 1 難過難過
    • 5 囧
    • 3 圍觀圍觀
    • 2 無聊無聊

    熱門評論

    最新評論

    發(fā)表評論 查看所有評論(2)

    昵稱:
    表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
    字?jǐn)?shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)