﻿/*
 * jQuery UI Autocomplete 1.7.2
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Autocomplete
 *
 * Depends:
 *	ui.core.js
 */

(function($) { 

$.extend($.ui, { autocomplete: { version: "1.7.2" } });

var PROP_NAME = 'autocomplete';

function Autocomplete() {
	this._mainDivId = 'ui-autocomplete-div';
	this._currPage = 1;
	this._totalPages = 1;

	this.regional = [];
	this.regional[''] = {
		defaultText:"输入中文/拼音或↑↓选择.",
		queryText:"<span>{0}</span> ,按拼音排序",
		notFoundText:"对不起, 找不到: <span>{0}</span>",
		pageText :"←→翻页, 共<span>{0}</span>项, 共<span>{1}</span>页"
	};
	this._defaults = {
		//Config
		remoteData: null,
		localData: null,
		dataFormat: null,
		itemFormat: null,
		dataFilter: null,
		pageSize: 10,
		timeout: 6000,
		defaultClientSort: true,
		clientSort: true,
		clientCache: false,
		asyncCache: false,
		fixedInput: true,

		//Event
		onBeforShow: null,
		onShow: null,
		onClose: null,
		onSelect: null
	};

	$.extend(this._defaults, this.regional['']);
	this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-autocomplete ui-widget ui-widget-content ui-helper-clearfix ui-corner-all ui-helper-hidden-accessible"></div>');
}

$.extend(Autocomplete.prototype, {
	markerClassName: 'hasAutocomplete',

	/* Debug logging (if enabled). */
	log: function () {
		if (this.debug)
			console.log.apply('', arguments);
	},

	_get: function(inst, name) {
		return inst.settings[name] !== undefined ?
			inst.settings[name] : this._defaults[name];
	},

	_newInst: function(target) {
		var id = target[0].id.replace(/([:\[\]\.])/g, '\\\\$1'); // escape jQuery meta chars
		return {
			id: id, 
			input: target,
			queryText: 'empty',
			data: [],
			filterData: [],
			dpDiv: this.dpDiv
		};
	},

	_getInst: function(target) {
		try {
			return $.data(target, PROP_NAME);
		}
		catch (err) {
			throw 'Missing instance data for this autocomplete';
		}
	},

	_attachAutocomplete: function(target, settings) {

		var nodeName = target.nodeName.toLowerCase();

		if (!target.id)
			target.id = 'dp' + (++this.uuid);
		var inst = this._newInst($(target));
		inst.settings = $.extend({}, settings || {});
		if (nodeName == 'input' || nodeName == 'textarea') {
			var $input = $(inst.input).attr("autocomplete", "off");
			this._connectAutocomplete(target, inst);
		}
	},

	/* Attach the date picker to an input field. */
	_connectAutocomplete: function(target, inst) {
		var input = $(target);
		inst.append = $([]);
		inst.trigger = $([]);
		if (input.hasClass(this.markerClassName))
			return;


		input.focus(this._asyncAutocomplete);
		input.click(this._asyncAutocomplete);

		input.addClass(this.markerClassName).keydown(this._doKeyDown).keyup(this._doKeyUp).
			bind("setValue.autocomplete", function(event, key, value) {
				inst.settings[key] = value;
			}).bind("getValue.autocomplete", function(event, key) {
				return this._get(inst, key);
			});
		$.data(target, PROP_NAME, inst);
	},
	
	_asyncAutocomplete: function(input) {
		input = input.target || input;
		var inst = $.autocomplete._getInst(input);
		var queryText = encodeURIComponent($(input).val());
		
		var onBeforeShow = $.autocomplete._get(inst, 'onBeforeShow');
		var beforeShowReturnValue = true;
		if (onBeforeShow)
			beforeShowReturnValue = onBeforeShow.apply((inst.input ? inst.input[0] : null),
				[(inst.input ? inst.input.val() : ''), inst]);
		if(beforeShowReturnValue===false)
			return;

		if ($.autocomplete._animing)
			return;
		else if($.autocomplete._lastInput == input && $.autocomplete._autocompleteShowing && queryText==inst.queryText) // already here
			return;
		else if($.autocomplete._lastInput != input)
			$.autocomplete._hideAutocomplete(null, '');
		

		inst.queryText = queryText;
		var remoteData = $.autocomplete._get(inst, 'remoteData');
		var localData = $.autocomplete._get(inst, 'localData');

		if(remoteData!=null) {
			var url = typeof remoteData == 'string'?remoteData+queryText
				:remoteData.apply(input, [queryText, inst]);
			var timeout = $.autocomplete._get(inst, 'timeout');
			var asyncCache = $.autocomplete._get(inst, 'asyncCache');
			var clientCache = $.autocomplete._get(inst, 'clientCache');
			var dataFormat = $.autocomplete._get(inst, 'dataFormat');
			if(clientCache && $.isArray(inst.data) && inst.data.length>0) {
				
				$.autocomplete._showAutocomplete.call($.autocomplete, input);
				return;
			}

			$.ajax({
				type: "GET",
				url: url,
				data: "",
				dataType: "text",
				timeout: timeout,
				cache: asyncCache,
				success: function(msg){
					var data = dataFormat==null?$.autocomplete._dataFormat(input, msg):dataFormat(input, msg);
					inst.filterData = inst.data = data;
					
					$.autocomplete._showAutocomplete.call($.autocomplete, input);
				},
				error: function(textStatus, errorThrown) {
					//alert('服务器忙,请重试...');
				}
			});
		}else if(localData!=null) {
			var data = $.isArray(localData)?localData:($.isFunction(localData)?localData.call(input, [queryText, inst]):[]);
			if(typeof data == 'string')
				data = dataFormat==null?$.autocomplete._dataFormat(input, _localData):dataFormat(input, _localData);
			inst.filterData = inst.data = data;
			$.autocomplete._showAutocomplete.call($.autocomplete, input);
		}
	},

	_showAutocomplete: function(input) {
		
		$.autocomplete._currPage = 1;
		var inst = $.autocomplete._getInst(input);
		
		if (!$.autocomplete._pos) { // position below input
			$.autocomplete._pos = $.autocomplete._findPos(input);
			$.autocomplete._pos[1] += input.offsetHeight; // add the height
		}
		var isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css('position') == 'fixed';
			return !isFixed;
		});
		if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
			$.autocomplete._pos[0] -= document.documentElement.scrollLeft;
			$.autocomplete._pos[1] -= document.documentElement.scrollTop;
		}
		var offset = {left: $.autocomplete._pos[0], top: $.autocomplete._pos[1]};
		$.autocomplete._pos = null;
		inst.rangeStart = null;
		// determine sizing offscreen
		inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
		$.autocomplete._updateAutocomplete(inst);
		// fix width for dynamic number of date pickers
		// and adjust position before showing
		offset = $.autocomplete._checkOffset(inst, offset, isFixed);
		inst.dpDiv.css({position: isFixed ? 'fixed' : 'absolute', display: 'none',
			left: offset.left + 'px', top: offset.top + 'px'});
		
		var showAnim = $.autocomplete._get(inst, 'showAnim') || 'show';
		var duration = $.autocomplete._get(inst, 'duration') || ($.autocomplete._autocompleteShowing?'':'normal');
		
		var postProcess = function() {
			$.autocomplete._animing = false;
			$.autocomplete._autocompleteShowing = true;
			if ($.browser.msie && parseInt($.browser.version,10) < 7) // fix IE < 7 select problems
				$('iframe.ui-autocomplete-cover').css({width: inst.dpDiv.width() + 4,
					height: inst.dpDiv.height() + 4});

			var onShow = $.autocomplete._get(inst, 'onShow');
			if (onShow)
				onShow.apply((inst.input ? inst.input[0] : null),
					[(inst.input ? inst.input.val() : ''), inst]);
		};
		$.autocomplete._animing = true;
		if ($.effects && $.effects[showAnim])
			inst.dpDiv.show(showAnim, $.autocomplete._get(inst, 'showOptions'), duration, postProcess);
		else
			inst.dpDiv[showAnim](duration, postProcess);
		if (duration == '')
			postProcess();
		if (inst.input[0].type != 'hidden')
			inst.input[0].focus();
		$.autocomplete._lastInput = input;
		$.autocomplete._curInst = inst;

	},

	/* Generate the date picker content. */
	_updateAutocomplete: function(inst) {
		var dims = {width: inst.dpDiv.width() + 4,
			height: inst.dpDiv.height() + 4};
		var self = this;
		inst.dpDiv.empty().append(this._generateHTML(inst))
			.find('iframe.ui-autocomplete-cover').
				css({width: dims.width, height: dims.height}).show()
			.end()
			.find('.ui-autocomplete-page a').click(function(event) {
				var _goto = $(this).attr('goto');
				
				$.autocomplete._currPage = _goto;
				$.autocomplete._updateAutocomplete(inst);
				return false;
			}).end()
			.find('.ui-autocomplete-list a').click(function(event) {
				/*$('.ui-autocomplete-selected').removeClass('ui-autocomplete-selected');
				inst.selectedItem = $(this);
				$(inst.selectedItem).addClass('ui-autocomplete-selected');
				*/
				var _index = $(this).attr('index');
				$.autocomplete._selectItem(inst, _index);
				return false;
			}).end()
			.click(function(event) {
				if (inst.input && inst.input[0].type != 'hidden' && inst == $.autocomplete._curInst)
					$(inst.input[0]).focus();
				return false;
			});
		
		if (inst.input && inst.input[0].type != 'hidden' && inst == $.autocomplete._curInst)
			$(inst.input[0]).focus();

		//selectedItem
		inst.selectedItem = null;//$(inst.dpDiv).find('.ui-autocomplete-selected');
	},

	_generateHTML: function(inst) {
		
		var itemFormat = $.autocomplete._get(inst, 'itemFormat');
		var pagesize = $.autocomplete._get(inst, 'pageSize') || 15;
		var dataFilter = $.autocomplete._get(inst, 'dataFilter');
		var data = dataFilter==null?this._dataFilter(inst):dataFilter(inst);
		$.autocomplete._totalPages = Math.ceil(data.length/pagesize);

		var _defaultText = $.autocomplete._get(inst, 'defaultText');
		var _queryText = $.autocomplete._get(inst, 'queryText');
		var _notFoundText = $.autocomplete._get(inst, 'notFoundText');
		var _pageText = $.autocomplete._get(inst, 'pageText');

		var html = '<div class="ui-autocomplete-message">';
		if(inst.input.val()=='') {
			html += _defaultText;
		}else if(!data || data.length<=0){
			html += this._textFormat(_notFoundText, decodeURIComponent(inst.queryText));
		}else if(inst.input.val()!=''){
			html += this._textFormat(_queryText, decodeURIComponent(inst.queryText));
		}
		html += '</div>';
		html += '<div class="ui-autocomplete-list">';

		if($.isArray(data))
		{
			var isFirst = true;
			
			var loop = -1;
			for(var i=0; i<data.length; i++)
			{
				if (++loop < pagesize * ($.autocomplete._currPage - 1)) {
					continue;
				}
				if (pagesize * $.autocomplete._currPage <= loop) {
					break;
				}
				var itemHTML = itemFormat==null?this._itemFormat(data[i]):itemFormat(data[i]);
				html += '<a href="#" index="'+i+'" class="ui-autocomplete-item'+(isFirst?' ui-autocomplete-selected':'')+'">'+itemHTML+'</a>';
				isFirst = false;
			}
		}
		html += '</div>';
		html += '<div class="ui-autocomplete-page">';
		var _goto = 1;
		if ($.autocomplete._totalPages > 1) {
			if ($.autocomplete._currPage > 1) {
				_goto = parseInt($.autocomplete._currPage, 10) - 1;
				html += '<a href="#" class="ui-autocomplete-arrowl" goto="'+_goto+'">&lt;-</a>';
			}
			var startPage = Math.max($.autocomplete._currPage - 2, 1);
			var endPage = Math.min($.autocomplete._totalPages, startPage + 4);
			for ( var i = startPage; i <= endPage; i++) {
				html += '<a href="#" class="ui-autocomplete-arrowr'+((i == $.autocomplete._currPage)?' ui-autocomplete-page-current':'')+'" goto="'+i+'">'+i+'</a>';
			}

			if ($.autocomplete._currPage != $.autocomplete._totalPages) {
				_goto = parseInt($.autocomplete._currPage, 10) + 1;
				html += '<a href="#" class="ui-autocomplete-arrowr" goto="'+_goto+'">-&gt;</a>';
			}
		}

		html += '<div>';
		html += this._textFormat(_pageText, data.length, $.autocomplete._totalPages);
		html += '</div>';

		html += '</div>';
		html += ($.browser.msie && parseInt($.browser.version,10) < 7?
			'<iframe src="javascript:false;" class="ui-autocomplete-cover" frameborder="0"></iframe>' : '');
		return html;
	},

	/* Check positioning to remain on screen. */
	_checkOffset: function(inst, offset, isFixed) {
		var dpWidth = inst.dpDiv.outerWidth();
		var dpHeight = inst.dpDiv.outerHeight();
		var inputWidth = inst.input ? inst.input.outerWidth() : 0;
		var inputHeight = inst.input ? inst.input.outerHeight() : 0;
		var viewWidth = (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) + $(document).scrollLeft();
		var viewHeight = (window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight) + $(document).scrollTop();
		//fixed scrollbar width
		var scrollBarWidth = $(document).scrollTop()>0?18:0;
		offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
		offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
		offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

		// now check if autocomplete is showing outside window viewport - move to a better place if so.
		
		offset.left -= (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ? Math.abs(offset.left + dpWidth - viewWidth + scrollBarWidth) : 0;
		offset.top -= (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ? Math.abs(offset.top + dpHeight + inputHeight*2 - viewHeight) : 0;

		return offset;
	},

	/* Find an object's position on the screen. */
	_findPos: function(obj) {
		while (obj && (obj.type == 'hidden' || obj.nodeType != 1)) {
			obj = obj.nextSibling;
		}
		var position = $(obj).offset();
		return [position.left, position.top];
	},
	
	_doKeyDown: function(event) {
		if($.autocomplete._animing)return false;

		var inst = $.autocomplete._getInst(event.target);
		var handled = true;
		inst._keyEvent = true;

		if ($.autocomplete._autocompleteShowing) {
			if(!inst.selectedItem) {
				inst.selectedItem = $(inst.dpDiv).find('.ui-autocomplete-selected');
			}
			
			switch(event.keyCode) {
				case 38: //up
					if($(inst.selectedItem).prev().length) {
						$(inst.selectedItem).removeClass('ui-autocomplete-selected');
						inst.selectedItem = inst.selectedItem.prev();
						$(inst.selectedItem).addClass('ui-autocomplete-selected');
					}else if($.autocomplete._currPage>1) {
						$.autocomplete._currPage--;
						$.autocomplete._updateAutocomplete(inst);
					}
					break;
				case 40: //down
					if($(inst.selectedItem).next().length) {
						$(inst.selectedItem).removeClass('ui-autocomplete-selected');
						inst.selectedItem = inst.selectedItem.next();
						$(inst.selectedItem).addClass('ui-autocomplete-selected');
					}else if($.autocomplete._currPage<$.autocomplete._totalPages) {
						$.autocomplete._currPage++;
						$.autocomplete._updateAutocomplete(inst);
					}

					break;
				case 33:  //left
				case 37:  //left
				case 109: //left
				case 188: //left
				case 219: //left
					if($.autocomplete._currPage>1) {
						$.autocomplete._currPage--;
						$.autocomplete._updateAutocomplete(inst);
					}

					break;
				case 34:  //right
				case 39:  //right
				case 61:  //right
				case 190: //right
				case 221: //right
					if($.autocomplete._currPage<$.autocomplete._totalPages) {
						$.autocomplete._currPage++;
						$.autocomplete._updateAutocomplete(inst);
					}

					break;
				case  9: //tab
				case 13: //enter
					var _index = $(inst.selectedItem).attr('index');
					$.autocomplete._selectItem(inst, _index);
					handled = false;
					break;
				
				
				case 27://esc
					$.autocomplete._hideAutocomplete(null, '');
					break;

				default: 
					handled = false;

					break;
			}
		}else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
			$.autocomplete._showAutocomplete(this);
		else {
			handled = false;
		}
		if (handled) {
			event.preventDefault();
			event.stopPropagation();
		}
	},
	
	_doKeyUp: function(event) {
		var keyCode = '|' + event.keyCode + '|';
		if ('|38|40|33|37|109|188|219|34|39|61|190|221|13|'.indexOf(keyCode) == -1) {
			if($.autocomplete._keyUpTimer) {
				clearTimeout($.autocomplete._keyUpTimer);
			}
			$.autocomplete._keyUpTimer = setTimeout(function() {
				$.autocomplete._currPage = 1;
				$.autocomplete._asyncAutocomplete(event);
			}, 100);
		}
	},

	_selectItem : function(inst, index, hide) {
		hide = hide===false?false:true;
		
		var selectedData = inst.filterData[index]?inst.filterData[index]:[];
		inst.input.val(selectedData[1]);

		var onSelect = this._get(inst, 'onSelect');
		if (onSelect)
			onSelect.apply((inst.input ? inst.input[0] : null),
				[selectedData, inst]);
		if(hide)
			this._hideAutocomplete(null, 'normal', true);
	},

	_dataFilter : function(inst) {
		var clientCache = $.autocomplete._get(inst, 'clientCache');
		var localData = $.autocomplete._get(inst, 'localData');
		var data = inst.data;
		var filterData = [];

		if((!clientCache && localData==null) ||  inst.queryText=='') 
		{
			filterData = inst.filterData = data;

		}else{

			if($.isArray(data) && data.length > 0) {
				for(var i=0; i<data.length; i++)
				{
					var regex = new RegExp(inst.queryText.toUpperCase());
					var regexText = encodeURIComponent(data[i].join("").toUpperCase());
					if(regex.test(regexText)) 
					{
						filterData.push(data[i]);
					}
				}
			}
			inst.filterData = filterData;
		}
		return filterData;
	},
	
	_itemFormat : function(item) {
		
		return '<span>' + item[1] + '</span>' + item[0];
	},
	
	_dataFormat : function(input, data) {
		data = data.replace(/<[^>]+>/g, '').replace(/(^\s*)|(\s*$)/g, "");
		var splitData = data.split('@');
		var returnValue = [];
		for ( var key in splitData) {
			if (splitData[key]) {
				returnValue.push(splitData[key].split('|'));
			}
		}
		
		var val = $(input).val();
		var inst = $.autocomplete._getInst(input);
		var defaultClientSort = $.autocomplete._get(inst, 'defaultClientSort');
		var clientSort = $.autocomplete._get(inst, 'clientSort');
		if((val == '' && defaultClientSort)
			|| (val != '' && clientSort) ) {

			var fn = function(param1, param2) {
				return $.autocomplete._dataCompare.call($.autocomplete, param1, param2);
			};
			returnValue.sort(fn);
		}

		return returnValue;
	},

	
	_dataCompare : function(param1, param2) {
		param1 = param1[0];
		param2 = param2[0];
		if (typeof param1 == "string" && typeof param2 == "string") {
			return param1.localeCompare(param2);
		}
		if (typeof param1 == "number" && typeof param2 == "string") {
			return -1;
		}
		if (typeof param1 == "string" && typeof param2 == "number") {
			return 1;
		}
		if (typeof param1 == "number" && typeof param2 == "number") {
			if (param1 > param2)
				return 1;
			if (param1 == param2)
				return 0;
			if (param1 < param2)
				return -1;
		}
	},

	_hideAutocomplete: function(input, duration) {
		var inst = this._curInst;

		if (!inst || (input && inst != $.data(input, PROP_NAME)))
			return;
		//alert([1, this._autocompleteShowing].join(": "));

        if (this._autocompleteShowing) {
			//alert([2, this._autocompleteShowing].join(": "));
            var fixedInput = $.autocomplete._get(inst, 'fixedInput');
            if (fixedInput && inst.input.val() != '' && arguments.length < 3) {
				var _index = $(inst.dpDiv).find('.ui-autocomplete-selected').attr('index');
				$.autocomplete._selectItem(inst, _index, false);
			}
			//alert([3, this._autocompleteShowing].join(": "));

			duration = (duration != null && duration!='' ? duration : '');
			var showAnim = $.autocomplete._get(inst, 'showAnim') || 'show';

			var postProcess = function() {
				var onClose = $.autocomplete._get(inst, 'onClose');
				if (onClose)
					onClose.apply((inst.input ? inst.input[0] : null),
						[(inst.input ? inst.input.val() : ''), inst]);
			};
			var method = (duration == '' ? 'hide' : (showAnim == 'slideDown' ? 'slideUp' :
					(showAnim == 'fadeIn' ? 'fadeOut' : 'hide')));
			//alert([duration, method]);
			//if (duration != '' && $.effects && $.effects[showAnim])
			//	inst.dpDiv.hide(showAnim, $.autocomplete._get(inst, 'showOptions'),
			//		duration, postProcess);
			//else
				inst.dpDiv[method](duration, postProcess);
			
			this._autocompleteShowing = false;
			try{this._lastInput.blur();}catch(e){}
			this._lastInput = null;
		}
		this._curInst = null;
		
	},

	/* Close date picker if clicked elsewhere. */
	_checkExternalClick: function(event) {
		if (!$.autocomplete._curInst)
			return;
		var $target = $(event.target);
		if (($target.parents('#' + $.autocomplete._mainDivId).length == 0) &&
				!$target.hasClass($.autocomplete.markerClassName) &&
				$.autocomplete._autocompleteShowing)
			$.autocomplete._hideAutocomplete(null, '');
	},
	_textFormat : function(format){
		var args = $.makeArray(arguments).slice(1);
		return format.replace(/\{(\d+)\}/g, function(m, i){
			return args[i];
		});
	}
});

$.fn.autocomplete = function(options){

	if (!$.autocomplete.initialized) {
		$(document).mousedown($.autocomplete._checkExternalClick).
			find('body').append($.autocomplete.dpDiv);
		$.autocomplete.initialized = true;
	}

	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
		return $.autocomplete['_' + options + 'Autocomplete'].
			apply($.autocomplete, [this[0]].concat(otherArgs));
	return this.each(function() {
		typeof options == 'string' ?
			$.autocomplete['_' + options + 'Autocomplete'].
				apply($.autocomplete, [this].concat(otherArgs)) :
			$.autocomplete._attachAutocomplete(this, options);
	});
};

$.autocomplete = new Autocomplete();
$.autocomplete.initialized = false;
$.autocomplete.uuid = new Date().getTime();
$.autocomplete.version = "1.7.2";

window.DP_jQuery = $;

})(jQuery);
