/** * 自定义下拉框 * @homepage http://www.sucaijiayuan.com */ var dropdownlist = (function($,undefined) { var staticvar = { themeidprefix: 'dropdownthemefor', themeid: 'dropdownthemefor#{id}', listid: 'dropdownoptionsfor#{id}', classdropdownlsit: 'mod-dropdownlist', classformitem: 'dropdown-select', classinput: 'dropdown-input', classicon: 'dropdown-icon', classoptions: 'dropdown-options', classfocusli: 'dropdown-options-focus', classlist : 'dropdown-list', classcustomscrollbar : 'custom-scroll-bar', classcustombox : 'dropdown-custombox', attroptionvalue: 'data-value', attrstylescols: 'data-cols', attrstyleswidth: 'data-width' }; var ids = []; /** * 创建随即字符串,作为dom节点的id * @return {string} */ var randomid = function() { while (true) { var id = ((new date()).gettime() + 'select' + math.floor(math.random() * 100000)).tostring(); if (!ids[id]) { ids[id] = true; return id; } } }; /** * 仿tangram 中的 t.string.format 方法 * @param str 目标字符串 * @param opts * @return {*} */ var format = function (str,opts) { source = str; var data = array.prototype.slice.call(arguments,1), tostring = object.prototype.tostring; if(data.length){ data = data.length == 1 ? (opts !== null && (/\[object array\]|\[object object\]/.test(tostring.call(opts))) ? opts : data) : data; return source.replace(/#\{(.+?)\}/g, function (match, key){ var replacer = data[key]; // chrome 下 typeof /a/ == 'function' if('[object function]' == tostring.call(replacer)){ replacer = replacer(key); } return ('undefined' == typeof replacer ? '' : replacer); }); } return source; }; /** * dropdownlist class * @param options * @constructor */ var ddlclass = function(){ }; ddlclass.prototype = { constructor:ddlclass, _addlistitem : function(opt){ var self = this; var new_option = $(''); new_option.attr(staticvar.attroptionvalue, opt.value); new_option.html(opt.text); new_option.attr('href','javascript:;'); var li = $('
  • '); new_option.click(function(event) { var value = $(this).attr(staticvar.attroptionvalue); self.select.val(value); self.select.trigger('change'); self.hide().listele.trigger('hide-list'); }); li.append(new_option); self.listul.append(li); return self; }, /** * 创建list * @private */ _list : function(){ var self = this; this.listid = format(staticvar.listid, {id: this.select.attr('id') || randomid()}); this.listele = $('
    ').attr('id',this.listid).addclass(staticvar.classlist).addclass(staticvar.classcustomscrollbar).hide(); this.listul = $('').appendto(this.listele); this.listbox = $('
    ').appendto(this.listele).addclass(staticvar.classcustombox); // 在列表底部增加一个额外的节点 if(this.configs.box){ this.listbox.append(this.configs.box); } var clickfunc = function(evt){ if(!$.contains(self.listele[0],evt.target)) { self.hide(); } }; this.listele.bind('show-list',function(){ $(document).bind('click', clickfunc); }); this.listele.bind('hide-list',function(){ $(document).unbind('click', clickfunc); }); var theoptions = this.select[0].options; $.each(theoptions,function(i,opt){ self._addlistitem(opt); }); this.listul.addclass(staticvar.classoptions); var resize = function() { $(window).unbind('resize',resize); settimeout(function() { var position = self.element.position(); self.listele.css({ 'left': position.left - 1, 'top': position.top + self.element[0].offsetheight }); $(window).resize(resize); }, 10); } $(window).resize(resize); self.listele.appendto(self.dropdownele); }, /** * 通过原生的select控件,创建自定义的下拉列表 * @return {*|jquery} */ _createfromselect : function() { this.select = $(this.configs.select); var themeid = format(staticvar.themeid, {id: this.select.attr('id')}), ddl = $('').attr({ id: themeid, 'href': 'javascript:;', 'class': staticvar.classformitem }), input = $('').attr({ 'class': staticvar.classinput }), icon = $('').attr({ 'class': staticvar.classicon }), elementclass = this.select.attr('class'); if (this.select[0].selectedindex>=0) { input.html('' + this.select[0].options[this.select[0].selectedindex].text + ''); } icon.html(' '); ddl.append(input).append(icon); if (elementclass) { $.each(elementclass.split(/\s+/),function(i,cls){ ddl.addclass(cls); }) } // 把原来的控件隐藏,插入新控件 this.select.hide(); this.dropdownele = $('
    ').append(ddl).insertafter(this.select) .addclass(staticvar.classdropdownlsit).addclass(this.configs.classname || ''); // 自定义宽度 var customizedwidth = this.select.attr(staticvar.attrstyleswidth) || ''; if (customizedwidth) { var pdl = parseint(input.css('padding-left'),10) || 0, pdr = parseint(input.css('padding-right'),10) || 0; input.css('width', parseint(customizedwidth, 10) - pdl - pdr - icon[0].offsetwidth - 3); } // 绑定事件 input.parent().click(function(event){ if($(this).attr('data-showwing') == 1){ self.hide(); }else{ self.show(); } event.preventdefault(); event.stoppropagation(); }); var self = this; this.select.change(function(event) { if (self.select[0].selectedindex>=0) { input.html('' + self.select[0].options[self.select[0].selectedindex].text + ''); } }); this.input = input; this.icon = icon; this.element = input.parent(); this._list(); return ddl; }, _init : function(configs) { this.configs = $.extend({ container : 'body' },configs || {}); var sel,attrs = {}; attrs.id = this.configs.attrs.id || randomid(); attrs['data-cols'] = this.configs.attrs.column || 8; if(this.configs.attrs.width) { attrs['data-width'] = this.configs.attrs.width; } // select控件通过js创建 if(this.configs.options){ if(this.configs.attrs.id) { attrs.id = this.configs.attrs.id; } attrs['data-cols'] = this.configs.attrs.column || 8; if(this.configs.attrs.width) { attrs['data-width'] = this.configs.attrs.width; } sel = $('').attr(attrs).hide().appendto($(this.configs.container)); var selectedindex, option; $.each(this.configs.options,function(i,opt){ option = new option(opt[0] || opt, opt[1] || opt[0] || opt); if (opt[2]) { option.selected = true; option.setattribute('selected', 'selected'); selectedindex = i; } sel[0].options.add(option); }); this.configs.select = sel; }else{ sel = this.configs.select.attr(attrs).hide(); if (!sel.is('select')) return; } $('#'+format(staticvar.themeid, {id: sel[0].id})).remove(); if (sel[0].options.length) this._createfromselect(sel).show(); return this; }, /** * 获取或设置 下拉框的值 * @param {string} value 需要给下拉框设定的内容 * @return {string/object} value有值时返回dropdownlist实例本身,否则返回下拉框的真实值 */ val : function(value){ if((value || '').length) { this.select.val(value).trigger('change'); return this; }else{ return this.select.val(); } }, change : function(){ if(arguments.length) { return this.select.change.apply(this.select,arguments); }else{ this.select.trigger('change'); return this; } }, show : function(){ var self = this; self.element.attr('data-showwing',1); var optionheight = parseint(self.configs.attrs.height,10) || 30; $('li a',self.listul).css({ 'height' : optionheight + 'px', 'line-height' : optionheight + 'px' }); // 自定义高度 var customizedcols = self.select.attr(staticvar.attrstylescols) || '10'; var lis = $('li',self.listul); var listheight = optionheight * math.min((parseint(customizedcols, 10)), lis.length); var parent = $('#' + format(staticvar.themeid,{id : self.select.attr('id')})); var position = parent.position(); var tmpstyles = { 'position': 'absolute', 'left': position.left , 'top': position.top + parent[0].offsetheight , 'width': parent[0].offsetwidth - (parseint(parent.css('border-left-width'),10) || 0) - (parseint(parent.css('border-right-width'),10) || 0), 'z-index': (parseint(self.select.parent().css('z-index'),10) || 0) + 10 }; self.listul.css({'height': listheight}); self.listele.css(tmpstyles).show().trigger('show-list'); var focusoption; $.each(lis,function(i,li){ if (self.select.val()==$('a',li).attr(staticvar.attroptionvalue)) { focusoption = li; return false; } }); if (focusoption) { settimeout(function() { $(focusoption).siblings('li').removeclass(staticvar.classfocusli).end().addclass(staticvar.classfocusli); focusoption.parentnode.scrolltop = focusoption.offsettop; },10); } return self; }, hide : function(){ this.element.attr('data-showwing',0); this.listele.hide().trigger('hide-list'); return this; }, add : function(option){ var opt = new option(option.text,option.value); this.select[0].options.add(opt); this._addlistitem(opt); return this; } }; /** * 根据配置创建自定义下拉框 * * @param {object} configs 创建下拉框所需要的配置项 * * @p-config {jq-elm} select 原生select控件的jquery对象,通过原生select创建时候必选 * * @p-config {jq-elm} container 自定义下拉框的父容器,通过json数据创建时候必选 * * @p-config {string} classname 自定义下拉框组件的class,所有和下拉框相关的节点,都受这个classname控制 * * @p-config {object} attrs 自定义下拉框的相关属性,参数可选 * @p-c-config {string} id 给自定义下拉框指定一个id,之后可以通过id进行dom操作 * @p-c-config {string} column 自定义下拉框中的option显示行数,默认显示10行 * @p-c-config {integer} width 自定义下拉框的宽度,字数超过会自动截断处理,默认:自适应 * @p-c-config {integer} height 自定义下拉框的高度,默认:30px * * @p-config {array} options 自定义下拉框需要显示的选项数据,对应select中的option * @p-c-item {array} 格式:[text,value,selected] * * @return {dropdownlist} 返回一个dropdownlist实例 */ var _create = function(configs) { return (new ddlclass())._init(configs); }; return { version : '1.3', create : _create }; })(jquery);