/**
* 自定义下拉框
* @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);