You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
426 lines
10 KiB
Plaintext
426 lines
10 KiB
Plaintext
11 months ago
|
/**
|
||
|
* combobox - jQuery EasyUI
|
||
|
*
|
||
|
* Licensed under the GPL terms
|
||
|
* To use it on other terms please contact us
|
||
|
*
|
||
|
* Copyright(c) 2009-2012 stworthy [ stworthy@gmail.com ]
|
||
|
*
|
||
|
* Dependencies:
|
||
|
* combo
|
||
|
*
|
||
|
*/
|
||
|
(function($){
|
||
|
/**
|
||
|
* scroll panel to display the specified item
|
||
|
*/
|
||
|
function scrollTo(target, value){
|
||
|
var panel = $(target).combo('panel');
|
||
|
var item = panel.find('div.combobox-item[value="' + value + '"]');
|
||
|
if (item.length){
|
||
|
if (item.position().top <= 0){
|
||
|
var h = panel.scrollTop() + item.position().top;
|
||
|
panel.scrollTop(h);
|
||
|
} else if (item.position().top + item.outerHeight() > panel.height()){
|
||
|
var h = panel.scrollTop() + item.position().top + item.outerHeight() - panel.height();
|
||
|
panel.scrollTop(h);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* select previous item
|
||
|
*/
|
||
|
function selectPrev(target){
|
||
|
var panel = $(target).combo('panel');
|
||
|
var values = $(target).combo('getValues');
|
||
|
var item = panel.find('div.combobox-item[value="' + values.pop() + '"]');
|
||
|
if (item.length){
|
||
|
var prev = item.prev(':visible');
|
||
|
if (prev.length){
|
||
|
item = prev;
|
||
|
}
|
||
|
} else {
|
||
|
item = panel.find('div.combobox-item:visible:last');
|
||
|
}
|
||
|
var value = item.attr('value');
|
||
|
select(target, value);
|
||
|
// setValues(target, [value]);
|
||
|
scrollTo(target, value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* select next item
|
||
|
*/
|
||
|
function selectNext(target){
|
||
|
var panel = $(target).combo('panel');
|
||
|
var values = $(target).combo('getValues');
|
||
|
var item = panel.find('div.combobox-item[value="' + values.pop() + '"]');
|
||
|
if (item.length){
|
||
|
var next = item.next(':visible');
|
||
|
if (next.length){
|
||
|
item = next;
|
||
|
}
|
||
|
} else {
|
||
|
item = panel.find('div.combobox-item:visible:first');
|
||
|
}
|
||
|
var value = item.attr('value');
|
||
|
select(target, value);
|
||
|
// setValues(target, [value]);
|
||
|
scrollTo(target, value);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* select the specified value
|
||
|
*/
|
||
|
function select(target, value){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
var data = $.data(target, 'combobox').data;
|
||
|
|
||
|
if (opts.multiple){
|
||
|
var values = $(target).combo('getValues');
|
||
|
for(var i=0; i<values.length; i++){
|
||
|
if (values[i] == value) return;
|
||
|
}
|
||
|
values.push(value);
|
||
|
setValues(target, values);
|
||
|
} else {
|
||
|
setValues(target, [value]);
|
||
|
}
|
||
|
|
||
|
for(var i=0; i<data.length; i++){
|
||
|
if (data[i][opts.valueField] == value){
|
||
|
opts.onSelect.call(target, data[i]);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* unselect the specified value
|
||
|
*/
|
||
|
function unselect(target, value){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
var data = $.data(target, 'combobox').data;
|
||
|
var values = $(target).combo('getValues');
|
||
|
for(var i=0; i<values.length; i++){
|
||
|
if (values[i] == value){
|
||
|
values.splice(i, 1);
|
||
|
setValues(target, values);
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
for(var i=0; i<data.length; i++){
|
||
|
if (data[i][opts.valueField] == value){
|
||
|
opts.onUnselect.call(target, data[i]);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* set values
|
||
|
*/
|
||
|
function setValues(target, values, remainText){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
var data = $.data(target, 'combobox').data;
|
||
|
var panel = $(target).combo('panel');
|
||
|
|
||
|
panel.find('div.combobox-item-selected').removeClass('combobox-item-selected');
|
||
|
var vv = [], ss = [];
|
||
|
for(var i=0; i<values.length; i++){
|
||
|
var v = values[i];
|
||
|
var s = v;
|
||
|
for(var j=0; j<data.length; j++){
|
||
|
if (data[j][opts.valueField] == v){
|
||
|
s = data[j][opts.textField];
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
vv.push(v);
|
||
|
ss.push(s);
|
||
|
panel.find('div.combobox-item[value="' + v + '"]').addClass('combobox-item-selected');
|
||
|
}
|
||
|
|
||
|
$(target).combo('setValues', vv);
|
||
|
if (!remainText){
|
||
|
$(target).combo('setText', ss.join(opts.separator));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
function transformData(target){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
var data = [];
|
||
|
$('>option', target).each(function(){
|
||
|
var item = {};
|
||
|
item[opts.valueField] = $(this).attr('value')!=undefined ? $(this).attr('value') : $(this).html();
|
||
|
item[opts.textField] = $(this).html();
|
||
|
item['selected'] = $(this).attr('selected');
|
||
|
data.push(item);
|
||
|
});
|
||
|
return data;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* load data, the old list items will be removed.
|
||
|
*/
|
||
|
function loadData(target, data, remainText){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
var panel = $(target).combo('panel');
|
||
|
|
||
|
$.data(target, 'combobox').data = data;
|
||
|
|
||
|
var selected = $(target).combobox('getValues');
|
||
|
panel.empty(); // clear old data
|
||
|
for(var i=0; i<data.length; i++){
|
||
|
var v = data[i][opts.valueField];
|
||
|
var s = data[i][opts.textField];
|
||
|
var item = $('<div class="combobox-item"></div>').appendTo(panel);
|
||
|
item.attr('value', v);
|
||
|
if (opts.formatter){
|
||
|
item.html(opts.formatter.call(target, data[i]));
|
||
|
} else {
|
||
|
item.html(s);
|
||
|
}
|
||
|
if (data[i]['selected']){
|
||
|
(function(){
|
||
|
for(var i=0; i<selected.length; i++){
|
||
|
if (v == selected[i]) return;
|
||
|
}
|
||
|
selected.push(v);
|
||
|
})();
|
||
|
}
|
||
|
}
|
||
|
if (opts.multiple){
|
||
|
setValues(target, selected, remainText);
|
||
|
} else {
|
||
|
if (selected.length){
|
||
|
setValues(target, [selected[selected.length-1]], remainText);
|
||
|
} else {
|
||
|
setValues(target, [], remainText);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
opts.onLoadSuccess.call(target, data);
|
||
|
|
||
|
$('.combobox-item', panel).hover(
|
||
|
function(){$(this).addClass('combobox-item-hover');},
|
||
|
function(){$(this).removeClass('combobox-item-hover');}
|
||
|
).click(function(){
|
||
|
var item = $(this);
|
||
|
if (opts.multiple){
|
||
|
if (item.hasClass('combobox-item-selected')){
|
||
|
unselect(target, item.attr('value'));
|
||
|
} else {
|
||
|
select(target, item.attr('value'));
|
||
|
}
|
||
|
} else {
|
||
|
select(target, item.attr('value'));
|
||
|
$(target).combo('hidePanel');
|
||
|
}
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* request remote data if the url property is setted.
|
||
|
*/
|
||
|
function request(target, url, param, remainText){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
if (url){
|
||
|
opts.url = url;
|
||
|
}
|
||
|
// if (!opts.url) return;
|
||
|
param = param || {};
|
||
|
|
||
|
if (opts.onBeforeLoad.call(target, param) == false) return;
|
||
|
|
||
|
opts.loader.call(target, param, function(data){
|
||
|
loadData(target, data, remainText);
|
||
|
}, function(){
|
||
|
opts.onLoadError.apply(this, arguments);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* do the query action
|
||
|
*/
|
||
|
function doQuery(target, q){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
|
||
|
if (opts.multiple && !q){
|
||
|
setValues(target, [], true);
|
||
|
} else {
|
||
|
setValues(target, [q], true);
|
||
|
}
|
||
|
|
||
|
if (opts.mode == 'remote'){
|
||
|
request(target, null, {q:q}, true);
|
||
|
} else {
|
||
|
var panel = $(target).combo('panel');
|
||
|
panel.find('div.combobox-item').hide();
|
||
|
var data = $.data(target, 'combobox').data;
|
||
|
for(var i=0; i<data.length; i++){
|
||
|
if (opts.filter.call(target, q, data[i])){
|
||
|
var v = data[i][opts.valueField];
|
||
|
var s = data[i][opts.textField];
|
||
|
var item = panel.find('div.combobox-item[value="' + v + '"]');
|
||
|
item.show();
|
||
|
if (s == q){
|
||
|
setValues(target, [v], true);
|
||
|
item.addClass('combobox-item-selected');
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* create the component
|
||
|
*/
|
||
|
function create(target){
|
||
|
var opts = $.data(target, 'combobox').options;
|
||
|
$(target).addClass('combobox-f');
|
||
|
$(target).combo($.extend({}, opts, {
|
||
|
onShowPanel: function(){
|
||
|
$(target).combo('panel').find('div.combobox-item').show();
|
||
|
scrollTo(target, $(target).combobox('getValue'));
|
||
|
opts.onShowPanel.call(target);
|
||
|
}
|
||
|
}));
|
||
|
}
|
||
|
|
||
|
$.fn.combobox = function(options, param){
|
||
|
if (typeof options == 'string'){
|
||
|
var method = $.fn.combobox.methods[options];
|
||
|
if (method){
|
||
|
return method(this, param);
|
||
|
} else {
|
||
|
return this.combo(options, param);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
options = options || {};
|
||
|
return this.each(function(){
|
||
|
var state = $.data(this, 'combobox');
|
||
|
if (state){
|
||
|
$.extend(state.options, options);
|
||
|
create(this);
|
||
|
} else {
|
||
|
state = $.data(this, 'combobox', {
|
||
|
options: $.extend({}, $.fn.combobox.defaults, $.fn.combobox.parseOptions(this), options)
|
||
|
});
|
||
|
create(this);
|
||
|
loadData(this, transformData(this));
|
||
|
}
|
||
|
if (state.options.data){
|
||
|
loadData(this, state.options.data);
|
||
|
}
|
||
|
request(this);
|
||
|
});
|
||
|
};
|
||
|
|
||
|
|
||
|
$.fn.combobox.methods = {
|
||
|
options: function(jq){
|
||
|
return $.data(jq[0], 'combobox').options;
|
||
|
},
|
||
|
getData: function(jq){
|
||
|
return $.data(jq[0], 'combobox').data;
|
||
|
},
|
||
|
setValues: function(jq, values){
|
||
|
return jq.each(function(){
|
||
|
setValues(this, values);
|
||
|
});
|
||
|
},
|
||
|
setValue: function(jq, value){
|
||
|
return jq.each(function(){
|
||
|
setValues(this, [value]);
|
||
|
});
|
||
|
},
|
||
|
clear: function(jq){
|
||
|
return jq.each(function(){
|
||
|
$(this).combo('clear');
|
||
|
var panel = $(this).combo('panel');
|
||
|
panel.find('div.combobox-item-selected').removeClass('combobox-item-selected');
|
||
|
});
|
||
|
},
|
||
|
loadData: function(jq, data){
|
||
|
return jq.each(function(){
|
||
|
loadData(this, data);
|
||
|
});
|
||
|
},
|
||
|
reload: function(jq, url){
|
||
|
return jq.each(function(){
|
||
|
request(this, url);
|
||
|
});
|
||
|
},
|
||
|
select: function(jq, value){
|
||
|
return jq.each(function(){
|
||
|
select(this, value);
|
||
|
});
|
||
|
},
|
||
|
unselect: function(jq, value){
|
||
|
return jq.each(function(){
|
||
|
unselect(this, value);
|
||
|
});
|
||
|
}
|
||
|
};
|
||
|
|
||
|
$.fn.combobox.parseOptions = function(target){
|
||
|
var t = $(target);
|
||
|
return $.extend({}, $.fn.combo.parseOptions(target), $.parser.parseOptions(target,[
|
||
|
'valueField','textField','mode','method','url'
|
||
|
]));
|
||
|
};
|
||
|
|
||
|
$.fn.combobox.defaults = $.extend({}, $.fn.combo.defaults, {
|
||
|
valueField: 'value',
|
||
|
textField: 'text',
|
||
|
mode: 'local', // or 'remote'
|
||
|
method: 'post',
|
||
|
url: null,
|
||
|
data: null,
|
||
|
|
||
|
keyHandler: {
|
||
|
up: function(){selectPrev(this);},
|
||
|
down: function(){selectNext(this);},
|
||
|
enter: function(){
|
||
|
var values = $(this).combobox('getValues');
|
||
|
$(this).combobox('setValues', values);
|
||
|
$(this).combobox('hidePanel');
|
||
|
},
|
||
|
query: function(q){doQuery(this, q);}
|
||
|
},
|
||
|
filter: function(q, row){
|
||
|
var opts = $(this).combobox('options');
|
||
|
return row[opts.textField].indexOf(q) == 0;
|
||
|
},
|
||
|
formatter: function(row){
|
||
|
var opts = $(this).combobox('options');
|
||
|
return row[opts.textField];
|
||
|
},
|
||
|
loader: function(param, success, error){
|
||
|
var opts = $(this).combobox('options');
|
||
|
if (!opts.url) return false;
|
||
|
$.ajax({
|
||
|
type: opts.method,
|
||
|
url: opts.url,
|
||
|
data: param,
|
||
|
dataType: 'json',
|
||
|
success: function(data){
|
||
|
success(data);
|
||
|
},
|
||
|
error: function(){
|
||
|
error.apply(this, arguments);
|
||
|
}
|
||
|
});
|
||
|
},
|
||
|
|
||
|
onBeforeLoad: function(param){},
|
||
|
onLoadSuccess: function(){},
|
||
|
onLoadError: function(){},
|
||
|
onSelect: function(record){},
|
||
|
onUnselect: function(record){}
|
||
|
});
|
||
|
})(jQuery);
|