text: ﻿/**
   * jQuery EasyUI 1.4.5
   * 
   * Copyright (c) 2009-2016 www.jeasyui.com. All rights reserved.
   *
   * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
   * To use it on other terms please contact us: info@jeasyui.com
   *
   */
  /**
   * combobox - jQuery EasyUI
   * 
   * Dependencies:
   *   combo
   * 
   */
  (function($){
  	function getRowIndex(target, value){
  		var state = $.data(target, 'combobox');
  		return $.easyui.indexOfArray(state.data, state.options.valueField, value);
  	}
  	
  	/**
  	 * scroll panel to display the specified item
  	 */
  	function scrollTo(target, value){
  		var opts = $.data(target, 'combobox').options;
  		var panel = $(target).combo('panel');
  		var item = opts.finder.getEl(target, 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);
  			}
  		}
  		panel.triggerHandler('scroll');	// trigger the group sticking
  	}
  	
  	function nav(target, dir){
  		var opts = $.data(target, 'combobox').options;
  		var panel = $(target).combobox('panel');
  		var item = panel.children('div.combobox-item-hover');
  		if (!item.length){
  			item = panel.children('div.combobox-item-selected');
  		}
  		item.removeClass('combobox-item-hover');
  		var firstSelector = 'div.combobox-item:visible:not(.combobox-item-disabled):first';
  		var lastSelector = 'div.combobox-item:visible:not(.combobox-item-disabled):last';
  		if (!item.length){
  			item = panel.children(dir=='next' ? firstSelector : lastSelector);
  		} else {
  			if (dir == 'next'){
  				item = item.nextAll(firstSelector);
  				if (!item.length){
  					item = panel.children(firstSelector);
  				}
  			} else {
  				item = item.prevAll(firstSelector);
  				if (!item.length){
  					item = panel.children(lastSelector);
  				}
  			}
  		}
  		if (item.length){
  			item.addClass('combobox-item-hover');
  			var row = opts.finder.getRow(target, item);
  			if (row){
  				$(target).combobox('scrollTo', row[opts.valueField]);
  				if (opts.selectOnNavigation){
  					select(target, row[opts.valueField]);
  				}
  			}
  		}
  	}
  	
  	/**
  	 * select the specified value
  	 */
  	function select(target, value, remainText){
  		var opts = $.data(target, 'combobox').options;
  		var values = $(target).combo('getValues');
  		if ($.inArray(value+'', values) == -1){
  			if (opts.multiple){
  				values.push(value);
  			} else {
  				values = [value];
  			}
  			setValues(target, values, remainText);
  			opts.onSelect.call(target, opts.finder.getRow(target, value));
  		}
  	}
  	
  	/**
  	 * unselect the specified value
  	 */
  	function unselect(target, value){
  		var opts = $.data(target, 'combobox').options;
  		var values = $(target).combo('getValues');
  		var index = $.inArray(value+'', values);
  		if (index >= 0){
  			values.splice(index, 1);
  			setValues(target, values);
  			opts.onUnselect.call(target, opts.finder.getRow(target, value));
  		}
  	}
  	
  	/**
  	 * set values
  	 */
  	function setValues(target, values, remainText){
  		var opts = $.data(target, 'combobox').options;
  		var panel = $(target).combo('panel');
  		
  		if (!$.isArray(values)){
  			values = values.split(opts.separator);
  		}
  		if (!opts.multiple){
  			values = values.length ? [values[0]] : [''];
  		}
  		panel.find('div.combobox-item-selected').removeClass('combobox-item-selected');
  		var theRow = null;
  		var vv = [], ss = [];
  		for(var i=0; i<values.length; i++){
  			var v = values[i];
  			var s = v;
  			opts.finder.getEl(target, v).addClass('combobox-item-selected');
  			var row = opts.finder.getRow(target, v);
  			if (row){
  				s = row[opts.textField];
  				theRow = row;
  			}
  			vv.push(v);
  			ss.push(s);
  		}
  
  		if (!remainText){
  			$(target).combo('setText', ss.join(opts.separator));
  		}
  		if (opts.showItemIcon){
  			var tb = $(target).combobox('textbox');
  			tb.removeClass('textbox-bgicon ' + opts.textboxIconCls);
  			if (theRow && theRow.iconCls){
  				tb.addClass('textbox-bgicon ' + theRow.iconCls);
  				opts.textboxIconCls = theRow.iconCls;
  			}
  		}
  		$(target).combo('setValues', vv);
  		panel.triggerHandler('scroll');	// trigger the group sticking
  	}
  	
  	/**
  	 * load data, the old list items will be removed.
  	 */
  	function loadData(target, data, remainText){
  		var state = $.data(target, 'combobox');
  		var opts = state.options;
  		state.data = opts.loadFilter.call(target, data);
  
  		opts.view.render.call(opts.view, target, $(target).combo('panel'), state.data);		
  
  		var vv = $(target).combobox('getValues');
  		$.easyui.forEach(state.data, false, function(row){
  			if (row['selected']){
  				$.easyui.addArrayItem(vv, row[opts.valueField]+'');
  			}
  		});
  		if (opts.multiple){
  			setValues(target, vv, remainText);
  		} else {
  			setValues(target, vv.length ? [vv[vv.length-1]] : [], remainText);
  		}
  		
  		opts.onLoadSuccess.call(target, data);
  	}
  	
  	/**
  	 * 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;
  		}
  		param = $.extend({}, opts.queryParams, param||{});
  //		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 state = $.data(target, 'combobox');
  		var opts = state.options;
  		
  		var qq = opts.multiple ? q.split(opts.separator) : [q];
  		if (opts.mode == 'remote'){
  			_setValues(qq);
  			request(target, null, {q:q}, true);
  		} else {
  			var panel = $(target).combo('panel');
  			panel.find('div.combobox-item-selected,div.combobox-item-hover').removeClass('combobox-item-selected combobox-item-hover');
  			panel.find('div.combobox-item,div.combobox-group').hide();
  			var data = state.data;
  			var vv = [];
  			$.map(qq, function(q){
  				q = $.trim(q);
  				var value = q;
  				var group = undefined;
  				for(var i=0; i<data.length; i++){
  					var row = data[i];
  					if (opts.filter.call(target, q, row)){
  						var v = row[opts.valueField];
  						var s = row[opts.textField];
  						var g = row[opts.groupField];
  						var item = opts.finder.getEl(target, v).show();
  						if (s.toLowerCase() == q.toLowerCase()){
  							value = v;
  							select(target, v, true);
  						}
  						if (opts.groupField && group != g){
  							opts.finder.getGroupEl(target, g).show();
  							group = g;
  						}
  					}
  				}
  				vv.push(value);
  			});
  			_setValues(vv);
  		}
  		function _setValues(vv){
  			setValues(target, opts.multiple ? (q?vv:[]) : vv, true);
  		}
  	}
  	
  	function doEnter(target){
  		var t = $(target);
  		var opts = t.combobox('options');
  		var panel = t.combobox('panel');
  		var item = panel.children('div.combobox-item-hover');
  		if (item.length){
  			var row = opts.finder.getRow(target, item);
  			var value = row[opts.valueField];
  			if (opts.multiple){
  				if (item.hasClass('combobox-item-selected')){
  					t.combobox('unselect', value);
  				} else {
  					t.combobox('select', value);
  				}
  			} else {
  				t.combobox('select', value);
  			}
  		}
  		var vv = [];
  		$.map(t.combobox('getValues'), function(v){
  			if (getRowIndex(target, v) >= 0){
  				vv.push(v);
  			}
  		});
  		t.combobox('setValues', vv);
  		if (!opts.multiple){
  			t.combobox('hidePanel');
  		}
  	}
  	
  	/**
  	 * create the component
  	 */
  	function create(target){
  		var state = $.data(target, 'combobox');
  		var opts = state.options;
  		
  		$(target).addClass('combobox-f');
  		$(target).combo($.extend({}, opts, {
  			onShowPanel: function(){
  				$(this).combo('panel').find('div.combobox-item:hidden,div.combobox-group:hidden').show();
  				setValues(this, $(this).combobox('getValues'), true);
  				$(this).combobox('scrollTo', $(this).combobox('getValue'));
  				opts.onShowPanel.call(this);
  			}
  		}));
  		
  		$(target).combo('panel').unbind().bind('mouseover', function(e){
  			$(this).children('div.combobox-item-hover').removeClass('combobox-item-hover');
  			var item = $(e.target).closest('div.combobox-item');
  			if (!item.hasClass('combobox-item-disabled')){
  				item.addClass('combobox-item-hover');
  			}
  			e.stopPropagation();
  		}).bind('mouseout', function(e){
  			$(e.target).closest('div.combobox-item').removeClass('combobox-item-hover');
  			e.stopPropagation();
  		}).bind('click', function(e){
  			var comboTarget = $(this).panel('options').comboTarget;
  			var item = $(e.target).closest('div.combobox-item');
  			if (!item.length || item.hasClass('combobox-item-disabled')){return}
  			var row = opts.finder.getRow(comboTarget, item);
  			if (!row){return}
  			var value = row[opts.valueField];
  			if (opts.multiple){
  				if (item.hasClass('combobox-item-selected')){
  					unselect(comboTarget, value);
  				} else {
  					select(comboTarget, value);
  				}
  			} else {
  				select(comboTarget, value);
  				$(comboTarget).combo('hidePanel');
  			}
  			e.stopPropagation();
  		}).bind('scroll', function(){
  			if (opts.groupPosition == 'sticky'){
  				var comboTarget = $(this).panel('options').comboTarget;
  				var stick = $(this).children('.combobox-stick');
  				if (!stick.length){
  					stick = $('<div class="combobox-stick"></div>').appendTo(this);
  				}
  				stick.hide();
  				$(this).children('.combobox-group:visible').each(function(){
  					var g = $(this);
  					var groupData = opts.finder.getGroup(comboTarget, g);
  					var rowData = state.data[groupData.startIndex + groupData.count - 1];
  					var last = opts.finder.getEl(comboTarget, rowData[opts.valueField]);
  					if (g.position().top < 0 && last.position().top > 0){
  						stick.show().html(g.html());
  						return false;
  					}
  				});
  			}
  		});
  	}
  	
  	$.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);
  			} else {
  				state = $.data(this, 'combobox', {
  					options: $.extend({}, $.fn.combobox.defaults, $.fn.combobox.parseOptions(this), options),
  					data: []
  				});
  			}
  			create(this);
  			if (state.options.data){
  				loadData(this, state.options.data);
  			} else {
  				var data = $.fn.combobox.parseData(this);
  				if (data.length){
  					loadData(this, data);
  				}
  			}
  			request(this);
  		});
  	};
  	
  	
  	$.fn.combobox.methods = {
  		options: function(jq){
  			var copts = jq.combo('options');
  			return $.extend($.data(jq[0], 'combobox').options, {
  				width: copts.width,
  				height: copts.height,
  				originalValue: copts.originalValue,
  				disabled: copts.disabled,
  				readonly: copts.readonly
  			});
  		},
  		cloneFrom: function(jq, from){
  			return jq.each(function(){
  				$(this).combo('cloneFrom', from);
  				$.data(this, 'combobox', $(from).data('combobox'));
  				$(this).addClass('combobox-f').attr('comboboxName', $(this).attr('textboxName'));
  			});
  		},
  		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, $.isArray(value)?value:[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');
  			});
  		},
  		reset: function(jq){
  			return jq.each(function(){
  				var opts = $(this).combobox('options');
  				if (opts.multiple){
  					$(this).combobox('setValues', opts.originalValue);
  				} else {
  					$(this).combobox('setValue', opts.originalValue);
  				}
  			});
  		},
  		loadData: function(jq, data){
  			return jq.each(function(){
  				loadData(this, data);
  			});
  		},
  		reload: function(jq, url){
  			return jq.each(function(){
  				if (typeof url == 'string'){
  					request(this, url);
  				} else {
  					if (url){
  						var opts = $(this).combobox('options');
  						opts.queryParams = url;
  					}
  					request(this);
  				}
  			});
  		},
  		select: function(jq, value){
  			return jq.each(function(){
  				select(this, value);
  			});
  		},
  		unselect: function(jq, value){
  			return jq.each(function(){
  				unselect(this, value);
  			});
  		},
  		scrollTo: function(jq, value){
  			return jq.each(function(){
  				scrollTo(this, value);
  			});
  		}
  	};
  	
  	$.fn.combobox.parseOptions = function(target){
  		var t = $(target);
  		return $.extend({}, $.fn.combo.parseOptions(target), $.parser.parseOptions(target,[
  			'valueField','textField','groupField','groupPosition','mode','method','url',{showItemIcon:'boolean'}
  		]));
  	};
  	
  	$.fn.combobox.parseData = function(target){
  		var data = [];
  		var opts = $(target).combobox('options');
  		$(target).children().each(function(){
  			if (this.tagName.toLowerCase() == 'optgroup'){
  				var group = $(this).attr('label');
  				$(this).children().each(function(){
  					_parseItem(this, group);
  				});
  			} else {
  				_parseItem(this);
  			}
  		});
  		return data;
  		
  		function _parseItem(el, group){
  			var t = $(el);
  			var row = {};
  			row[opts.valueField] = t.attr('value')!=undefined ? t.attr('value') : t.text();
  			row[opts.textField] = t.text();
  			row['selected'] = t.is(':selected');
  			row['disabled'] = t.is(':disabled');
  			if (group){
  				opts.groupField = opts.groupField || 'group';
  				row[opts.groupField] = group;
  			}
  			data.push(row);
  		}
  	};
  
  	var COMBOBOX_SERNO = 0;
  	var defaultView = {
  		render: function(target, container, data){
  			var state = $.data(target, 'combobox');
  			var opts = state.options;
  
  			COMBOBOX_SERNO++;
  			state.itemIdPrefix = '_easyui_combobox_i' + COMBOBOX_SERNO;
  			state.groupIdPrefix = '_easyui_combobox_g' + COMBOBOX_SERNO;		
  			state.groups = [];
  			
  			var dd = [];
  			var group = undefined;
  			for(var i=0; i<data.length; i++){
  				var row = data[i];
  				var v = row[opts.valueField]+'';
  				var s = row[opts.textField];
  				var g = row[opts.groupField];
  				
  				if (g){
  					if (group != g){
  						group = g;
  						state.groups.push({
  							value: g,
  							startIndex: i,
  							count: 1
  						});
  						dd.push('<div id="' + (state.groupIdPrefix+'_'+(state.groups.length-1)) + '" class="combobox-group">');
  						dd.push(opts.groupFormatter ? opts.groupFormatter.call(target, g) : g);
  						dd.push('</div>');
  					} else {
  						state.groups[state.groups.length-1].count++;
  					}
  				} else {
  					group = undefined;
  				}
  				
  				var cls = 'combobox-item' + (row.disabled ? ' combobox-item-disabled' : '') + (g ? ' combobox-gitem' : '');
  				dd.push('<div id="' + (state.itemIdPrefix+'_'+i) + '" class="' + cls + '">');
  				if (opts.showItemIcon && row.iconCls){
  					dd.push('<span class="combobox-icon ' + row.iconCls + '"></span>');
  				}
  				dd.push(opts.formatter ? opts.formatter.call(target, row) : s);
  				dd.push('</div>');
  			}
  			$(container).html(dd.join(''));
  		}
  	};
  	
  	$.fn.combobox.defaults = $.extend({}, $.fn.combo.defaults, {
  		valueField: 'value',
  		textField: 'text',
  		groupPosition: 'static',	// or 'sticky'
  		groupField: null,
  		groupFormatter: function(group){return group;},
  		mode: 'local',	// or 'remote'
  		method: 'post',
  		url: null,
  		data: null,
  		queryParams: {},
  		showItemIcon: false,
  		view: defaultView,
  		
  		keyHandler: {
  			up: function(e){nav(this,'prev');e.preventDefault()},
  			down: function(e){nav(this,'next');e.preventDefault()},
  			left: function(e){},
  			right: function(e){},
  			enter: function(e){doEnter(this)},
  			query: function(q,e){doQuery(this, q)}
  		},
  		filter: function(q, row){
  			var opts = $(this).combobox('options');
  			return row[opts.textField].toLowerCase().indexOf(q.toLowerCase()) >= 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);
  				}
  			});
  		},
  		loadFilter: function(data){
  			return data;
  		},
  		finder:{
  			getEl:function(target, value){
  				var index = getRowIndex(target, value);
  				var id = $.data(target, 'combobox').itemIdPrefix + '_' + index;
  				return $('#'+id);
  			},
  			getGroupEl:function(target, gvalue){
  				var state = $.data(target, 'combobox');
  				var index = $.easyui.indexOfArray(state.groups, 'value', gvalue);
  				var id = state.groupIdPrefix + '_' + index;
  				return $('#'+id);
  			},
  			getGroup:function(target, p){
  				var state = $.data(target, 'combobox');
  				var index = p.attr('id').substr(state.groupIdPrefix.length+1);
  				return state.groups[parseInt(index)];
  			},
  			getRow:function(target, p){
  				var state = $.data(target, 'combobox');
  				var index = (p instanceof $) ? p.attr('id').substr(state.itemIdPrefix.length+1) : getRowIndex(target, p);
  				return state.data[parseInt(index)];
  			}
  		},
  		
  		onBeforeLoad: function(param){},
  		onLoadSuccess: function(){},
  		onLoadError: function(){},
  		onSelect: function(record){},
  		onUnselect: function(record){}
  	});
  })(jQuery);
  