/*!
 * Auto Complete 5.0
 * November 22, 2009
 * Corey Hart @ http://www.codenothing.com
 */ 
(function ($, undefined) {
    // Expose autoComplete to the jQuery chain
    $.fn.autoComplete = function () {
        // Force array of arguments
        var args = Slice.call(arguments),
			self = this,
			first = args.shift(),
			isMethod = (typeof first === 'string');

        // Deep namespacing is not supported in jQuery, a mistake I made in v4.1
        if (isMethod) first = first.replace('.', '-');

        // Allow for passing array of arguments, or multiple arguments
        // Eg: .autoComplete('trigger', [arg1, arg2, arg3...]) or .autoComplete('trigger', arg1, arg2, arg3...)
        // Mainly to allow for .autoComplete('trigger', arguments) to work
        // Note*: button.supply passes an array as the first param, so check against that first
        args = first === 'button-supply' || first === 'direct-supply' ? $.isArray(args[0]) && $.isArray(args[0][0]) ? args[0] : args :
			args[1] === undefined && $.isArray(args[0]) ? args[0] : args;


        // Autocomplete special triggers
        return isMethod ?
        // The only chain breaking operation is option, which gets passed back the
        // settings/value it requested, otherwise trigger the event and don't break the chain!
			$(self)[first === 'option' && args.length < 2 ? 'triggerHandler' : 'trigger']('autoComplete.' + first, args) :

        // Allow passing a jquery event special object {from $.Event()}
			first && first[$.expando] ? $(self).trigger(first, args) :

        // Initiate the autocomplete (Only takes a single argument, the options object)
			AutoCompleteFunction.call(self, first);
    };

    // bgiframe is needed to fix z-index problem for IE6 users.
    $.fn.bgiframe = $.fn.bgiframe ? $.fn.bgiframe : $.fn.bgIframe ? $.fn.bgIframe : function () {
        // For applications that don't have bgiframe plugin installed, create a useless 
        // function that doesn't break the chain
        return this;
    };

    // The expando won't get attached to the jQuery object until 1.4 release(or so it seems in the nightlies)
    // To get the expando, we must create an event through jQuery, and filter it out.
    $.expando = $.expando !== undefined ? $.expando : (function () {
        var event = $.Event('keyup'), i;
        for (i in event)
            if (i.indexOf('jQuery') === 0)
                return i;
        // Use the event's timestamp on instances where 
        // expando isn't attached to the event object
        // (is it ever not?)
        return 'jQuery' + event.timeStamp;
    })();

    // Current timestamp
    function now() {
        return (new Date).getTime();
    }



    // Internals
    var 
    // Munging
	TRUE = true,
	FALSE = false,

    // Copy of the slice prototype
	Slice = Array.prototype.slice,

    // Attach global aspects to jQuery itself
	AutoComplete = $.autoComplete = {
	    // Index Counter
	    counter: 0,

	    // Attach length of stack to object
	    length: 0,

	    // Storage of elements
	    stack: {},

	    // Storage order of uid's
	    order: [],

	    // Global access to elements in use
	    hasFocus: FALSE,

	    // Callback methods for getting focus element
	    getFocus: function () {
	        return this.order[0] ? this.stack[this.order[0]] : undefined;
	    },
	    getPrevious: function () {
	        // Removing elements cause some indexs on the order stack
	        // to become undefined, so loop until one is found
	        for (var i = 1, l = this.order.length; i < l; i++)
	            if (this.order[i])
	                return this.stack[this.order[i]];
	        // If none are found, return undefined
	        return undefined;
	    },

	    // Attempts to remove element from the stack
	    remove: function (i) {
	        for (var k = 0, l = this.order.length; k < l; k++)
	            if (this.order[k] === i)
	                this.order[k] = undefined;
	        this.stack[i] = undefined;
	        this.length--;
	        delete this.stack[i];
	    },

	    // Returns full stack in jQuery form
	    getAll: function () {
	        for (var i = 0, l = this.counter, stack = []; i < l; i++)
	            if (this.stack[i])
	                stack.push(this.stack[i]);
	        return $(stack);
	    },

	    defaults: {
	        // To smooth upgrade process to 5.0, set backwardsCompatible to true
	        backwardsCompatible: FALSE,
	        // Server Script Path
	        ajax: 'ajax.php',
	        ajaxCache: $.ajaxSettings.cache,
	        // Data Configuration
	        dataSupply: [],
	        dataFn: undefined,
	        dataName: 'Id',
	        // Drop List CSS
	        list: 'auto-complete-list',
	        rollover: 'auto-complete-list-rollover',
	        hiddenValue: undefined,
	        width: undefined, // Defined as inputs width when extended (can be overridden with this global/options/meta)
	        striped: undefined,
	        maxHeight: undefined,
	        newList: FALSE,
	        // Post Data
	        postVar: 'value',
	        postData: {},
	        // Limitations
	        minChars: 3,
	        maxItems: -1,
	        maxRequests: 0,
	        requestType: 'POST',
	        // Input
	        inputControl: undefined,
	        autoFill: FALSE,
	        nonInput: undefined,
	        multiple: FALSE,
	        multipleSeparator: ' ',
	        // Events
	        onBlur: undefined,
	        onFocus: undefined,
	        onHide: undefined,
	        onLoad: undefined,
	        onMaxRequest: function () { },
	        onRollover: undefined,
	        onSelect:
            function (something, dataContainer) { // Esta funcion es un hack para validar que la ciudad escrita es una ciudad valida
               
                if ("#" + this.id == inputCiudadOrigen)
                    $(hiddenTextoCiudadOrigen).val(dataContainer.data.Nombre)
                else if ("#" + this.id == inputCiudadDestino)
                    $(hiddenTextoCiudadDestino).val(dataContainer.data.Nombre)
            },
	        onShow: undefined,
	        onSubmit: function () { return TRUE; },
	        spinner: undefined,
	        preventEnterSubmit: TRUE,
	        delay: 0,
	        // Caching Options
	        useCache: TRUE,
	        cacheLimit: 50
	    }
	},

    // Autocomplete function
	AutoCompleteFunction = function (options) {
	    return this.each(function () {
	        var 
	        // Cache a copy of the input element
			self = this,
	        // Cache Input Object
			$input = $(self).attr('autocomplete', 'off'),
	        // autoComplete enabled/disabled
			Active = TRUE,
	        // Track every event triggered
			LastEvent = {},
	        // String of current input value
			inputval = '',
	        // Place holder for all list elements
			$elems = { length: 0 },
	        // Place holder for the list element in focus
			$li,
	        // View and heights for scrolling
			view, ulHeight, liHeight, liPerView,
	        // Harcoded value for ul visiblity
			ulOpen = FALSE,
	        // Timer for delay
			timeid,
	        // Ajax requests holder
			xhr,
	        // li element in focus during key up/down, and its data
			liFocus = -1, liData,
	        // For multiple selections
			separator,

	        // Index of current input
			inputIndex = (function () { AutoComplete.length++; return ++AutoComplete.counter; })(),
	        // Number of requests made
			requests = 0,
	        // Internal Per Input Cache
			cache = {
			    length: 0,
			    val: undefined,
			    list: {}
			},

	        // Merge defaults with passed options and metadata options
			settings = $.extend(
				{ width: $input.outerWidth() },
				AutoComplete.defaults,
				options || {},
				$.metadata ? $input.metadata() : {}
			),

	        // Create the drop list (Use an existing one if possible)
			$ul = !settings.newList && $('ul.' + settings.list)[0] ?
				$('ul.' + settings.list).eq(0).bgiframe().data('autoComplete', TRUE) :
				$('<ul/>').appendTo('body').addClass(settings.list).bgiframe().hide().data('ac-selfmade', TRUE).data('autoComplete', TRUE),

	        // Attach document click to force blur event
			$doc = $(document).bind('click.autoComplete-' + inputIndex, function (event) {
			    var $elem;
			    // Make sure input is active and list is open
			    if (Active && ulOpen &&
			    // Double check the event timestamps to ensure there isn't
			    // a delayed reaction from a button
					(!LastEvent || event.timeStamp - LastEvent.timeStamp > 200) &&
			    // Check the target after all other checks are passed (less processing)
					($elem = $(event.target)).closest('ul').data('ac-input-index') !== inputIndex &&
			    // Also ensure that the input it's being clicked on either
					$elem.data('ac-input-index') !== inputIndex) {
			        $ul.hide(event);
			        // We want to trigger all blur events, so don't
			        // pass special autoComplete flags here through the
			        // trigger function
			        $input.blur();
			    }
			    LastEvent = event;
			});

	        // Attach special fn's to ul
	        newUl();
	        // Upper case requestType now instead of on every call
	        settings.requestType = settings.requestType.toUpperCase();
	        // Set separator to local variable for munging
	        separator = settings.multiple ? settings.multipleSeparator : undefined;
	        // Add input to stack
	        AutoComplete.stack[inputIndex] = self;

	        /**
	        * Input Central
	        */
	        // Show autocomplete has been initialized on this element
	        $input.data('autoComplete', TRUE)
	        // Attach input index and initial settings
			.data('ac-input-index', inputIndex)
	        // autoComplete Activity
			.data('ac-active', Active)
	        // Attach settings to initail and current states
			.data('ac-initial-settings', $.extend(TRUE, {}, settings)).data('ac-settings', settings)
	        // Central autoComplete specific function
	        // Opera uses keypress as it has problems with keydown
			.bind(window.opera ? 'keypress.autoComplete' : 'keydown.autoComplete', function (event) {

			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Track last event and store code for munging
			    var key = (LastEvent = event).keyCode, enter = FALSE;

			    // Tab Key
			    if (key == 9 && ulOpen) {
			        select(event);
			    }
			    // Enter Key
			    else if (key == 13 && $li) {
			        // IE needs keydown to return false on 'enter' so the element doesn't
			        // lose focus. The problem with returning false is that it prevents bubbling,
			        // and most importantly, form submission. To allow for most flexibility,
			        // preventEnterSubmit is used along with activity of drop down UL list to
			        // determine whether focus is on the drop list or is just on the input.
			        //
			        // Furthermore, preventEnterSubmit will now be defaulted to true, so as
			        // to affect as few implementations as possible, and the ones that need
			        // form submission on 'enter' can just set this flag to false for it to
			        // work as needed.
			        enter = settings.preventEnterSubmit && ulOpen ? FALSE : TRUE;
			        select(event);
			    }
			    // Up Arrow
			    else if (key == 38) {
			        if (liFocus > 0) {
			            liFocus--;
			            up(event);
			        } else {
			            liFocus = -1;
			            $input.val(inputval);
			            $ul.hide(event);
			        }
			    }
			    // Down Arrow
			    else if (key == 40) {
			        if (liFocus < $elems.length - 1) {
			            liFocus++;
			            down(event);
			        }
			    }

			    // Page Up
			    else if (key == 33) {
			        if (liFocus > 0) {
			            liFocus -= liPerView;
			            if (liFocus < 0) liFocus = 0;
			            up(event);
			        }
			    }
			    // Page Down
			    else if (key == 34) {
			        if (liFocus < $elems.length - 1) {
			            liFocus += liPerView;
			            if (liFocus > $elems.length - 1) liFocus = $elems.length - 1;
			            down(event);
			        }
			    }
			    // Check for non input values defined by user
			    else if (settings.nonInput && $.inArray(key, settings.nonInput)) {
			        $ul.html('').hide(event);
			    }
			    // Everything else is considered possible input, so
			    // return before keyup prevention flag is set
			    else {
			        return TRUE;
			    }

			    // Prevent autoComplete keyup event's from triggering by
			    // attaching a flag to the last event
			    LastEvent[$.expando + '_autoComplete_keydown'] = TRUE;
			    return enter;
			})
	        // Run a keydown event to specifically catch the tab key
			.bind('keyup.autoComplete', function (event) {
			    // If autoComplete has been disabled or keyup prevention 
			    // flag has be set, prevent input events
			    if (!Active || LastEvent[$.expando + '_autoComplete_keydown']) return TRUE;

			    /**
			    * If no special operations were run on keydown,
			    * allow for regular text searching
			    */
			    inputval = $input.val();
			    var key = (LastEvent = event).keyCode,
					val = separator ? inputval.split(separator).pop() : inputval;
			    // Still check to make sure 'enter' wasn't pressed
			    if (key != 13) {
			        // Caching key value
			        cache.val = settings.inputControl === undefined ? val :
						settings.inputControl.apply(self, settings.backwardsCompatible ?
							[val, key, $ul, event] : [event, { val: val, key: key, ul: $ul}]);
			        // Only send request if character length passes
			        if (cache.val.length >= settings.minChars)
			            sendRequest(event, settings, cache, (key == 8 || key == 32));
			        // Remove list on backspace of small string
			        else if (key == 8)
			            $ul.html('').hide(event);
			    }
			})
	        // Bind specific Blur Actions
			.bind('blur.autoComplete', function (event) {
			    // If autoComplete has been disabled or the drop list
			    // is still open, prevent input events
			    if (!Active || ulOpen) return TRUE;
			    // Store event
			    LastEvent = event;
			    $input.data('ac-hasFocus', FALSE);
			    liFocus = -1;
			    // Only push undefined index onto order stack
			    // if not already there (incase multiple blur events occur)
			    if (AutoComplete.order[0] !== undefined)
			        AutoComplete.order.unshift(undefined);
			    // Expose focus
			    AutoComplete.hasFocus = FALSE;
			    $ul.hide(event);
			    // Trigger blur callback last
			    if (settings.onBlur) settings.onBlur.apply(self, settings.backwardsCompatible ?
					[inputval, $ul, event] : [event, { val: inputval, ul: $ul}]);
			})
	        // Bind specific focus actions
			.bind('focus.autoComplete', function (event, flag) {
			    // If autoComplete has been disabled but not destoyed, just return true 
			    if (!Active ||
			    // Prevent inner focus events if caused by autoComplete inner functionality
					(AutoComplete.focus === inputIndex && flag === $.expando + '_autoComplete') ||
			    // Because IE triggers focus AND closes the drop list before form submission,
			    // prevent inner function focus functionality & pass on the select flag
					LastEvent[$.expando + '_autoComplete_enter'])
			        return TRUE;
			    // Store event
			    LastEvent = event;
			    // If ul is not associated with current input, clear it
			    if (inputIndex != $ul.data('ac-input-index'))
			        $ul.html('').hide(event);
			    // Store focus into input
			    $input.data('ac-hasFocus', TRUE);
			    // Overwrite undefined index pushed on by the blur event
			    if (AutoComplete.order[0] === undefined) {
			        if (AutoComplete.order[1] === inputIndex)
			            AutoComplete.order.shift();
			        else
			            AutoComplete.order[0] = inputIndex;
			    }
			    // Only push another uid if it's not the current one
			    else if (AutoComplete.order[0] != inputIndex && AutoComplete.order[1] != inputIndex)
			        AutoComplete.order.unshift(inputIndex);
			    // Keep the order array to within the global cacheLimit size
			    if (AutoComplete.order.length > AutoComplete.defaults.cacheLimit)
			        AutoComplete.order.pop();
			    // Expose focus
			    AutoComplete.hasFocus = TRUE;
			    // Trigger focus callback last
			    if (settings.onFocus) settings.onFocus.apply(self, settings.backwardsCompatible ? [$ul, event] : [event, { ul: $ul}]);
			})

	        /**
	        * Autocomplete Methods
	        * -Extensions off autoComplete event
	        */
	        // Allows for change of settings at any point
			.bind('autoComplete.settings', function (event, newSettings) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Give access to current settings and cache
			    if ($.isFunction(newSettings)) {
			        var ret = newSettings.apply(self, settings.backwardsCompatible ?
						[settings, cache, $ul, event] : [event, { settings: settings, cache: cache, ul: $ul}]);
			        // Allow for extending of settings/cache based off function return values
			        if ($.isArray(ret) && ret[0] !== undefined) {
			            settings = $.extend(TRUE, {}, settings, ret[0] || settings);
			            cache = $.extend(TRUE, {}, cache, ret[1] || cache);
			        }
			    } else {
			        // Extend deep so settings are kept
			        settings = $.extend(TRUE, {}, settings, newSettings || {});
			    }
			    // Upper case requestType now instead of on every call
			    settings.requestType = settings.requestType.toUpperCase();
			    // Reassign local separator
			    separator = settings.multiple ? settings.multipleSeparator : undefined;
			    // Restablish current settings onto the inputs data
			    $input.data('ac-settings', settings);
			    // Change the drop down if user want's a differen't class attached
			    $ul = !settings.newList && $ul.hasClass(settings.list) ? $ul :
					!settings.newList && $('ul.' + settings.list)[0] ? $('ul.' + settings.list).bgiframe().data('autoComplete', TRUE) :
					$('<ul/>').appendTo('body').addClass(settings.list).bgiframe().hide()
						.data('ac-selfmade', TRUE).data('autoComplete', TRUE);
			    // Attach special ul fn's
			    newUl();
			    // Return & Store event
			    return LastEvent = event;
			})
	        // Clears the Cache & requests (requests can be blocked on request)
			.bind('autoComplete.flush', function (event, cacheOnly) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    cache = { length: 0, val: undefined, list: {} };
			    if (!cacheOnly) requests = 0;
			    // Store & return event
			    return LastEvent = event;
			})
	        // External button trigger for ajax requests
			.bind('autoComplete.button-ajax', function (event, postData, cacheName) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Store event
			    LastEvent = event;
			    // Refocus the input box and pass flag to prevent inner focus events
			    $input.trigger('focus', [$.expando + '_autoComplete']);
			    // Allow for just passing the cache name
			    if (typeof postData === 'string') {
			        cacheName = postData;
			        postData = {};
			    }
			    // If no cache name is given, supply a non-common word
			    cache.val = cacheName || 'NON_404_<>!@$^&';
			    // Timer is done within sendRequest
			    return sendRequest(
					event,
					$.extend(TRUE, {}, settings, { maxItems: -1, postData: postData || {} }),
					cache
				);
			})
	        // External button trigger for supplied data
			.bind('autoComplete.button-supply', function (event, data, cacheName) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Store event
			    LastEvent = event;
			    // Refocus the input box and pass flag to prevent inner focus events
			    $input.trigger('focus', [$.expando + '_autoComplete']);
			    // Allow for just passing of cacheName
			    if (typeof data === 'string') {
			        cacheName = data;
			        data = undefined;
			    }
			    // If no cache name is given, supply a non-common word
			    cache.val = cacheName || 'NON_404_SUPPLY_<>!@$^&';
			    // If no data is supplied, use data in settings
			    data = $.isArray(data) && data.length ? data : settings.dataSupply;
			    // Timer done within sendRequest
			    return sendRequest(
					event,
					$.extend(TRUE, {}, settings, { maxItems: -1, dataSupply: data, dataFn: function () { return TRUE; } }),
					cache
				);
			})
	        // Supply list directly into the result function
			.bind('autoComplete.direct-supply', function (event, data, cacheName) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Store event
			    LastEvent = event;
			    // Refocus the input box and pass flag to prevent inner focus events
			    $input.trigger('focus', [$.expando + '_autoComplete']);
			    // Allow for just passing of cacheName
			    if (typeof data === 'string') {
			        cacheName = data;
			        data = undefined;
			    }
			    // If no cache name is given, supply a non-common word
			    cache.val = cacheName || 'NON_404_SUPPLY_<>!@$^&';
			    // If no data is supplied, use data in settings
			    data = $.isArray(data) && data.length ? data : settings.dataSupply;
			    // Load the results directly into the results function
			    // bypassing error checks (Only do)
			    return loadResults(
					event,
					data,
					$.extend(TRUE, {}, settings, { maxItems: -1, dataSupply: data, dataFn: function () { return TRUE; } }),
					cache
				);
			})
	        // Triggering autocomplete programatically
			.bind('autoComplete.search', function (event, value) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    cache.val = value || '';
			    // Timer done within sendRequest
			    return sendRequest(LastEvent = event, settings, cache);
			})
	        // Add jquery-ui like option access
			.bind('autoComplete.option', function (event) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Store event
			    LastEvent = event;
			    var args = Slice.call(arguments), length = args.length;
			    return length == 3 ? (function () { settings[args[1]] = args[2]; $input.data('ac-settings', settings); return args[2]; })() :
					length == 2 ? (function () {
					    switch (args[1]) {
					        case 'ul': return $ul;
					        case 'cache': return cache;
					        case 'xhr': return xhr;
					        case 'input': return $input;
					        default: return settings[args[1]] || undefined;
					    }
					})() :
					settings;
			})
	        // Add enabling event (only applicable after disable)
			.bind('autoComplete.enable', function (event) {
			    $input.data('ac-active', Active = TRUE);
			    // Store & return event
			    return LastEvent = event;
			})
	        // Add disable event
			.bind('autoComplete.disable', function (event) {
			    // Store event
			    $input.data('ac-active', Active = FALSE);
			    $ul.html('').hide(event);
			    // Store & return event
			    return LastEvent = event;
			})
	        // Add a destruction function
			.bind('autoComplete.destroy', function (event) {
			    // Break down the input
			    $input
			    // Remove all autoComplete Specific Data
					.removeData('autoComplete')
					.removeData('ac-input-index')
					.removeData('ac-initial-settings')
					.removeData('ac-settings')
					.removeData('ac-active')
			    // Remove all autoComplete specific events
					.unbind('.autoComplete')
			    // jQuery requires every namespace attached to
			    // a made up event to be removed separately
					.unbind('autoComplete.' + [
							'settings',
							'flush',
							'button-ajax',
							'button-supply',
							'direct-supply',
							'search',
							'option',
							'enable',
							'disable',
							'destroy'
						].join(' autoComplete.'))
			    // Unbind the form submission event
					.parents('form').eq(0).unbind('submit.autoComplete-' + inputIndex);
			    // Remove document click event
			    $doc.unbind('click.autoComplete-' + inputIndex);
			    // Remove from stack
			    AutoComplete.remove(inputIndex);
			    // Disable Activity
			    Active = FALSE;
			    // Clean the UL
			    var list = $ul.html('').hide(event).data('ac-inputs'), i;
			    list[inputIndex] = undefined;
			    for (i in list)
			        if (list[i] === TRUE)
			            return LastEvent = event;
			    // Remove the element from the DOM if self created no other input is using it
			    if ($ul.data('ac-selfmade') === TRUE) $ul.remove();
			    // Store & return event
			    return LastEvent = event;
			})

	        // Back to normal events
	        // Prevent form submission if defined in settings
			.parents('form').eq(0).bind('submit.autoComplete-' + inputIndex, function (event) {
			    // If autoComplete has been disabled, prevent input events
			    if (!Active) return TRUE;
			    // Because IE triggers focus AND closes the drop list before form submission, store the flag if any
			    var flag = LastEvent[$.expando + '_autoComplete_enter'] || FALSE;
			    // Store event
			    LastEvent = event;
			    return settings.preventEnterSubmit ?
					(ulOpen || flag) ? FALSE : settings.onSubmit.call(self, event, { form: this, ul: $ul }) :
					settings.onSubmit.call(self, event, { form: this, ul: $ul });
			});

	        // Ajax/Cache Request
	        function sendRequest(event, settings, cache, backSpace, timeout) {
	            // Pass spinner enabler
	            if (settings.spinner) settings.spinner.call(self, event, { active: TRUE, ul: $ul });
	            // Centralize the timer request
	            if (timeid) timeid = clearTimeout(timeid);
	            // Call send request again with timeout flag if on delay
	            if (settings.delay > 0 && timeout === undefined) return timeid = setTimeout(function () {
	                sendRequest(event, settings, cache, backSpace, TRUE);
	                timeid = clearTimeout(timeid);
	            }, settings.delay);

	            // Abort previous request incase it's still running
	            if (xhr) xhr.abort();

	            // Load from cache if possible
	            if (settings.useCache && cache.list[cache.val])
	                return loadResults(event, cache.list[cache.val], settings, cache, backSpace);

	            // Use user supplied data when defined
	            if (settings.dataSupply.length)
	                return userSuppliedData(event, settings, cache, backSpace);

	            // Check Max requests first before sending request
	            if (settings.maxRequests && ++requests >= settings.maxRequests) {
	                $ul.html('').hide(event);
	                if (settings.spinner) settings.spinner.call(self, event, { active: FALSE, ul: $ul });
	                return requests > settings.maxRequests ?
						FALSE : settings.onMaxRequest.apply(self, settings.backwardsCompatible ?
								[cache.val, $ul, event, inputval] : [event, { search: cache.val, val: inputval, ul: $ul}]);
	            }

	            // Send request server side
	            settings.postData[settings.postVar] = cache.val
	            // Switched to base ajax request to remove list on errors
	            return xhr = $.ajax({
	                type: settings.requestType,
	                url: settings.ajax,
	                data: settings.postData,
	                dataType: 'json',
	                cache: settings.ajaxCache,
	                success: function (list) {
	                    loadResults(event, list, settings, cache, backSpace);
	                },
	                error: function () {
	                    $ul.html('').hide(event);
	                    if (settings.spinner) settings.spinner.call(self, event, { active: FALSE, ul: $ul });
	                }
	            });
	        }

	        // Parse User Supplied Data
	        function userSuppliedData(event, settings, cache, backSpace) {
	            var list = [], // Result list
					args = [], // Backwards Compatibility
					fn = $.isFunction(settings.dataFn), // User supplied function
					regex = fn ? undefined : new RegExp('^' + cache.val, 'i'), // Only compile regex if needed
					k = 0, entry, i = 0, l = settings.dataSupply.length; // Looping vars

	            // Loop through each entry and find matches
	            for (; i < l; i++) {
	                entry = settings.dataSupply[i];
	                // Force object
	                entry = typeof entry === 'object' && entry.value ? entry : { value: entry };
	                // Setup arguments for dataFn in a backwards compatible way if needed
	                args = settings.backwardsCompatible ?
						[cache.val, entry.value, list, i, settings.dataSupply, $ul, event] :
						[event, { val: cache.val, entry: entry.value, list: list, i: i, supply: settings.dataSupply, ul: $ul}];
	                // If user supplied function, use that, otherwise test with default regex
	                if ((fn && settings.dataFn.apply(self, args)) || (!fn && entry.value.match(regex))) {
	                    // Reduce browser load by breaking on limit if it exists
	                    if (settings.maxItems > -1 && ++k > settings.maxItems)
	                        break;
	                    list.push(entry);
	                }
	            }
	            // Use normal load functionality
	            return loadResults(event, list, settings, cache, backSpace);
	        }

	        // Key element Selection
	        function select(event) {
	            // Ensure the select function only gets fired when list of open
	            if (ulOpen) {
	                if (settings.onSelect) settings.onSelect.apply(self, settings.backwardsCompatible ?
						[liData, $li, $ul, event] : [event, { data: liData, li: $li, ul: $ul}]);
	                autoFill(undefined);
	                //inputval = $input.val();
	                Seleccionar();
	                // Because IE triggers focus AND closes the drop list before form submission
	                // attach a flag on 'enter' selection
	                if (LastEvent.type == 'keydown') LastEvent[$.expando + '_autoComplete_enter'] = TRUE;
	            }
	            $ul.hide(event);
	            return $li;
	        }

	        function Seleccionar() {
	            liData = $li.data(settings.dataName);
	            var li = liData.Id ? liData : liData.value;
	            $(settings.hiddenValue).val(li.Id);
	            $input.val(li.Nombre);
	        }

	        // Key direction up
	        function up(event) {
	            if ($li) $li.removeClass(settings.rollover);
	            $ul.show(event);
	            $li = $elems.eq(liFocus).addClass(settings.rollover);
	            liData = $li.data(settings.dataName);
	            if (!$li.length || !liData) return FALSE;
	            var nombre = liData.value ? liData.value.Nombre : liData.Nombre;
	            autoFill(nombre || '');
	            if (settings.onRollover) settings.onRollover.apply(self, settings.backwardsCompatible ?
					[liData, $li, $ul, event] : [event, { data: liData, li: $li, ul: $ul}]);
	            // Scrolling
	            var v = liFocus * liHeight;
	            if (v < view - ulHeight) {
	                view = v + ulHeight
	                $ul.scrollTop(v);
	            }
	            return $li;
	        }

	        // Key direction down
	        function down(event) {
	            if ($li) $li.removeClass(settings.rollover);
	            $ul.show(event);
	            $li = $elems.eq(liFocus).addClass(settings.rollover);
	            liData = $li.data(settings.dataName);
	            if (!$li.length || !liData) return FALSE;
	            var nombre = liData.value ? liData.value.Nombre : liData.Nombre;
	            autoFill(nombre || '');
	            // Scrolling
	            var v = (liFocus + 1) * liHeight;
	            if (v > view)
	                $ul.scrollTop((view = v) - ulHeight);
	            // Callback
	            if (settings.onRollover) settings.onRollover.apply(self, settings.backwardsCompatible ?
					[liData, $li, $ul, event] : [event, { data: liData, li: $li, ul: $ul}]);
	            return $li;
	        }

	        // Attach new show/hide functionality to only the
	        // ul object (so not to infect all of jQuery)
	        function newUl() {
	            if (!$ul[$.expando + '_autoComplete']) {
	                // Make a copy of the old show/hide
	                var hide = $ul.hide, show = $ul.show;
	                $ul.hide = function (event, speed, callback) {
	                    if (settings.onHide && ulOpen) {
	                        settings.onHide.call(self, event, { ul: $ul });
	                        LastEvent[$.expando + '_autoComplete_hide'] = TRUE;
	                    }
	                    ulOpen = FALSE;
	                    return hide.call($ul, speed, callback);
	                };
	                $ul.show = function (event, speed, callback) {
	                    if (settings.onShow && !ulOpen) settings.onShow.call(self, event, { ul: $ul });
	                    ulOpen = TRUE;
	                    return show.call($ul, speed, callback);
	                };
	                // A flag must be attached to the $ul cached object
	                $ul[$.expando + '_autoComplete'] = TRUE;
	            }
	            var list = $ul.data('ac-inputs') || {};
	            list[inputIndex] = TRUE;
	            return $ul.data('ac-inputs', list);
	        }

	        // Auto-fill the input
	        // Credit to Jörn Zaefferer @ http://bassistance.de/jquery-plugins/jquery-plugin-autocomplete/
	        // and http://www.pengoworks.com/workshop/jquery/autocomplete.htm for this functionality
	        function autoFill(val) {
	            // Set starting and ending points based on values
	            if (val === undefined) {
	                var start, end; start = end = $input.val().length;
	            } else {
	                if (separator) val = inputval.substr(0, inputval.length - inputval.split(separator).pop().length) + val + separator;
	                var start = inputval.length, end = val.length;
	                $input.val(val);
	            }

	            // Create selection if allowed
	            if (!settings.autoFill || start > end) {
	                return FALSE;
	            }
	            else if (self.createTextRange) {
	                var range = self.createTextRange();
	                if (val === undefined) {
	                    range.move('character', start);
	                    range.select();
	                } else {
	                    range.collapse(TRUE);
	                    range.moveStart("character", start);
	                    range.moveEnd("character", end);
	                    range.select();
	                }
	            }
	            else if (self.setSelectionRange) {
	                self.setSelectionRange(start, end);
	            }
	            else if (self.selectionStart) {
	                self.selectionStart = start;
	                self.selectionEnd = end;
	            }
	            return TRUE;
	        }

	        // List Functionality
	        function loadResults(event, list, settings, cache, backSpace) {
	            var cadBuscada = list.CadenaBuscada ? list.CadenaBuscada : cache.val;
	            list = list.ListaResultados ? list.ListaResultados : list;
	            // Allow another level of result handling
	            if (settings.onLoad) list = settings.onLoad.call(self, event, { list: list, settings: settings, cache: cache, ul: $ul });
	            // Pass spinner killer as wait time is done in javascript processing
	            if (settings.spinner) settings.spinner.call(self, event, { active: FALSE, ul: $ul });
	            // Store results into the cache if allowed
	            if (settings.useCache && cache.list[cache.val] === undefined) {
	                cache.length++;
	                cache.list[cache.val] = list;
	                // Clear cache if necessary
	                if (cache.length > settings.cacheLimit) {
	                    cache.list = {};
	                    cache.length = 0;
	                }
	            }

	            // Ensure there is a list
	            if (!list || list.length < 1)
	                return $ul.html('').hide(event);

	            // Refocus list element
	            liFocus = -1;

	            // Initialize Vars together (save bytes)
	            var offset = $input.offset(), // Input position
				    container = [], // Container for list elements
				    aci = 0, k = 0, i = 0, even = FALSE, length = list.length; // Loop Items

	            // Push items onto container
	            for (; i < length; i++) {
	                nombre = list[i].Nombre ? list[i].Nombre : list[i].value.Nombre;
	                if (nombre) {
	                    if (settings.maxItems > -1 && ++aci > settings.maxItems)
	                        break;
	                    container.push(
							settings.striped && even ? '<li class="' + settings.striped + '">' : '<li>', FormatName(cadBuscada, nombre), '</li>'
						);
	                    even = !even;
	                }
	            }

	            // Load items into list
	            $elems = $ul.html(container.join('')).children('li');
	            for (length = $elems.length; k < length; k++) {
	                $.data($elems[k], settings.dataName, list[k]);
	                $.data($elems[k], 'ac-index', k);
	            }


	            // Autofill input with first entry
	            if (settings.autoFill && !backSpace) {
	                liFocus = 0;
	                liData = list[0];
	                autoFill(liData.value || '');
	                $li = $elems.eq(0).addClass(settings.rollover);
	            }

	            // Clear off old events and attach new ones
	            $ul.unbind('.autoComplete')
	            // Attach input index in focus
				.data('ac-input-index', inputIndex)
	            // Remove focus elements hover class
				.bind('mouseout.autoComplete', function () {
				    $li.removeClass(settings.rollover);
				})
	            // Mouseover using event delegation
				.bind('mouseover.autoComplete', function (event) {
				    $li = $(event.target).closest('li');
				    // Ensure 'li' mouseover
				    if ($li.length < 1) return FALSE;
				    // Remove hover class from last rollover
				    $elems.filter('.' + settings.rollover).removeClass(settings.rollover);
				    liFocus = $li.addClass(settings.rollover).data('ac-index');
				    liData = $li.data(settings.dataName);
				    if (settings.onRollover) settings.onRollover.apply(self, settings.backwardsCompatible ?
						[liData, $li, $ul, event] : [event, { data: liData, li: $li, ul: $ul}]);
				})
	            // Click event using target from mouseover
				.bind('click.autoComplete', function (event) {
				    // Refocus the input box and pass flag to prevent inner focus events
				    $input.trigger('focus', [$.expando + '_autoComplete']);

				    liData = $li.data(settings.dataName);
				    // Check against separator for input value
				    $input.val(inputval = separator ?
						inputval.substr(0, inputval.length - inputval.split(separator).pop().length) + liData.Nombre + separator :
						liData.Nombre ? liData.Nombre : liData.value.Nombre
					);
				    $ul.hide(event);
				    autoFill(undefined);
				    Seleccionar();
				    if (settings.onSelect) settings.onSelect.apply(self, settings.backwardsCompatible ?
						[liData, $li, $ul, event] : [event, { data: liData, li: $li, ul: $ul}]);
				})
	            // Reposition list
				.css({
				    top: offset.top + $input.outerHeight(),
				    left: offset.left,
				    width: settings.width
				})
	            // Scroll to the top
				.scrollTop(0);

	            // If Max Height specified, control it
	            if (settings.maxHeight) $ul.css({
	                height: liHeight * $elems.length > settings.maxHeight ? settings.maxHeight : 'auto',
	                overflow: 'auto'
	            });

	            // Apply list height to view for inital value,
	            // and show the list now so no jerkiness from css
	            // changes are shown to the user
	            ulHeight = $ul.show(event).outerHeight();
	            view = ulHeight;
	            // Log li height for less computation
	            liHeight = $elems.eq(0).outerHeight();
	            // Number of elements per viewport
	            liPerView = Math.floor(view / liHeight);

	            // Include amount of time it took
	            // to load the list
	            LastEvent.timeStamp = now();

	            // Every function needs to return something
	            return $ul;
	        }
	    });
	};
})(jQuery);

function FormatName(_search, _name) {
    search = _search.toLowerCase().removeAccents();
    name = _name.toLowerCase().removeAccents();
    //    return name;
    var posStart = name.indexOf(search);
    if (posStart < 0) return _name;
    var longitud = search.length;
    var finalName = _name.substr(0, posStart);
    finalName += "<span style=\"font-weight:bold\">" + _name.toString().substr(posStart, longitud) + "</span>";
    var carToEnd = name.length - posStart - longitud;
    if (carToEnd > 0)
        finalName += _name.toString().substr(posStart + longitud, name.length - posStart - longitud);
    return finalName;
}

String.prototype.removeAccents = function() {
    var __r = {
        'À': 'A', '�?': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Á': 'A', 'Æ': 'E',
        'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E',
        'Í': 'I', '�?': 'I', 'Î': 'I', '�?': 'I',
        'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Ö': 'O',
        'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U',
        'Ñ': 'N'
    };

    return this.replace(/[À�?ÂÃÄÅÁÆÈÉÊËÍ�?Î�?ÒÓÔÖÙÚÛÜÑ]/gi, function(m) {
        var ret = __r[m.toUpperCase()];

        if (m === m.toLowerCase())
            ret = ret.toLowerCase();

        return ret;
    });
};

