( function($){

        $.fn.suggester = function(options) {

            /**
             * For later IE6 hacks...
             */
            var isIE6 = /msie|MSIE 6/.test(navigator.userAgent);

            /**
             * Suggester input objects
             */
            var suggesterInputFirst = undefined;
            var suggesterInputSecond = undefined;

            /**
             * For situation when suggester shouldn show up
             */
            var suggesterShowUp = true;

            /**
             * Is set to first or second every time user changes input. In one-input suggester, only first matters.
             */
            var suggesterInput = 'first';

            /**
             * Containers for user selected location codes
             */
            var suggesterFirstLandCode = undefined;
            var suggesterFirstLocCode = undefined;
            var suggesterFirstGroupCode = undefined;
            var suggesterSecondLandCode = undefined;
            var suggesterSecondLocCode = undefined;
            var suggesterSecondGroupCode = undefined;

            /**
             * test
             */
            var suggesterSelectedItem = undefined;

            /**
             * Position of actualy used suggester. (set while input is focused)
             */
            var suggesterPosition = {'top':'0', 'left':'0'};

            /**
             * Width of actualy used suggester. (the same as input)
             */
            var suggesterWidth = '0';

            /**
             * If suggester is reading asynchronous data, this value is true to prevent reading data too often
             */
            var suggesterOnRoute = false;

            /**
             * Used to query suggester requests. If user change suggester phrase to fast,
             * it should update suggester content automaticaly without need of key pressing.
             */
            var suggesterRequestQuery = undefined;

            /**
             * Container for user written suggestion to compare with new one onChange
             */
            var lastPhrase = '';

            /**
             * Container for very actual phrase.
             */
            var actualPhrase = '';

            /**
             * Phrase which the request is send for. if suggest phrase was changed, lastResponseData should be updated.
             * This is the base phrase, 3 letters long. (may differ by setting the letters2activate)
             */
            var lastResponsePhrase = undefined;

            /**
             * Responded data to use in suggesting process.
             */
            var lastResponseData = undefined;

            /**
             * Suggester default settings
             */
            var defaults = {

                /**
                 * Suggester server-side url
                 */
                requestUrl:'/proxy.php?pickup=',

                /**
                 * Suggester validation url
                 */
                 validationUrl: undefined,

                /**
                 * Suggester request timeout in seconds
                 */
                requestTimeout: 5,

                 /**
                  * Minimum number of letters needed to activate suggester
                  */
                letters2activate: 3,

                /**
                 * If set to true, removes white chars from user phrase internaly (no changes to visual representation)
                 */
                trimPhrase: true,

                /**
                 * Sets focus on designated suggester input after page finishes to load.
                 */
                focusOn: false,

                /**
                 * Width (in pixels) of suggesters list. Set to 0 to make suggester auto-determinate the value.
                 */
                width: 0,

                /**
                 * Height (in pixels) of suggester list. 
                 */
                height: 200,

                /**
                 * Width offset to shrink/enlarge suggester list after auto-determining the width. may be subzero.
                 */
                widthOffset: 0,

                /**
                 * Top offset to change suggester position after auto-determining the y-pos. may be subzero.
                 */
                topOffset: 0,

                /**
                 * Shows and hides suggester list with effect.
                 */
                suggesterFade: false,

                /**
                 * Enable to override dropoff location whenever pickup location was chosen
                 */
                dropoffOverride: true,

                /**
                 * If true, json response data will be cleared from any illegal characters
                 */
                clearResponseData: false,

                /**
                 * If true, suggester input fields will have browser default autocomplete set to off
                 */
                disableAutocomplete: true,

                /**
                 * If true, suggester list will disapear on Escape key pressed.
                 */
                hideOnEsc: true,

                /**
                 * TODO: If true, suggester will ask on every change of phrase (not only on 3 letter long phrase)
                 */
                askAlways: true,

                /**
                 * Set input field names.
                 */
                input_loc_name: 'loc_name',
                input_loc_code: 'loc_code',
                input_land_name: 'land',
                input_land_code: 'land_code',
                input_group_code: 'v_group',

                /**
                 * Set hidden input name and id values.
                 */
                pickup_loc_name: 'suggester_pickup',
                pickup_loc_code: 'suggester_first_loc_code',
                pickup_land_name: 'suggester_first_land_name',
                pickup_land_code: 'suggester_first_land_code',
                pickup_group_code: 'suggester_first_group_code',

                dropoff_loc_name: 'suggester_dropoff',
                dropoff_loc_code: 'suggester_second_loc_code',
                dropoff_land_name: 'suggester_second_land_name',
                dropoff_land_code: 'suggester_second_land_code',
                dropoff_group_code: 'suggester_second_group_code',

                /**
                 * Submit button selector. If set, suggester will try to do the validation and call callbackOnSubmit function afterwards.
                 */
                submitButton: undefined,

                /**
                 * Callback on enter.
                 */
                callbackOnEnter: function(){},

                /**
                 * Callback on submit.
                 */
                callbackOnSubmit: function(){},


                /******************************************
                 * Filters - optionaly shows/hides some information in list on special demand.
                 * (for eg. hotels doesn't need country caption)
                 *****************************************/

                /**
                * Turn on/off showing of country caption in suggester list.
                */
                filterShowCaption: true,

                /**
                 * Adds embos to part of suggested text
                 */
                filterShowEmboss: true,

                /**
                 * Hide aliases if they have the same name as location.
                 */
                filterHideEqualAlias: true,

                /**
                 * Turn on/off showing loc_code, even if code.length != 3
                 **/
                filterAlwaysShowLocCode: false
            };

            /**
             * Initial setup
             */
            var options = $.extend(defaults, options);

            /**
             * It checks if user clicked outside suggester list and hides suggester then
             */
            var blurize = function(event){
                hideSuggester();
            };

            /**
             * Blocks enter from submiting the form.
             * @param {Object} event
             */
            var onEnter = function(event){
                if ( event.keyCode == 13 ) {
                    // if something in both was selected, set hidden value and submit form.
                    // if just one input was filled, set the same as in other one to it.
                    var id = $("#suggester_list").find(".selected").attr("id");
                    if (id) {
                        var selected = returnSelectedInfo(id);
                        setSuggesterVars(selected[options.input_land_code], selected[options.input_loc_code], selected[options.input_loc_name], selected[options.input_land_name], selected[options.input_group_code]);
                        hideSuggester();
                        if (suggesterInput == 'first'){
                            $(suggesterInputSecond).focus();
							
                        }
                    } else {
                        //var tabindex = $().attr("tabindex");
                        if (suggesterInput == 'first'){
                            // console.debug("enter on first: " + lastPhrase);
                            var tabindex = $(suggesterInputFirst).attr("tabindex");
                            if ( tabindex > 0 && lastPhrase.length == options.letters2activate){
                                //d("onEnter input first");
                                var phrase = $(suggesterInputFirst).val();
                                if ( lastResponseData != undefined ){
                                    if (lastResponseData.length > 0) {
                                        if (lastPhrase.toLowerCase() == lastResponseData[0][options.input_loc_code].toLowerCase()){
                                            setSuggesterVars ( lastResponseData[0][options.input_land_code], lastResponseData[0][options.input_loc_code], lastResponseData[0][options.input_loc_name], lastResponseData[0][options.input_land_name], lastResponseData[0][options.input_group_code]);
                                            suggesterShowUp = false;
                                            hideSuggester();
                                            suggesterInput = 'second';
                                            tabindex++;
                                            //$(suggesterInputFirst).parents().find("form").find("input[tabindex="+tabindex+"]").select();
                                            $(suggesterInputSecond).select();
											
											
                                        }
                                    }
                                } else {
                                    return false;
                                }
                            }
                        } else {
                            if (suggesterInput == 'second'){
                                //console.debug("enter on second: " + lastPhrase);
                                var phrase = $(suggesterInputSecond).attr("value");
                                if (phrase.length == options.letters2activate){
                                    if ( lastResponseData != undefined ){
                                        if (lastResponseData.length > 0) {
                                            if (phrase.toLowerCase() == lastResponseData[0][options.input_loc_code].toLowerCase()){
                                                setSuggesterVars ( lastResponseData[0][options.input_land_code], lastResponseData[0][options.input_loc_code], lastResponseData[0][options.input_loc_name], lastResponseData[0][options.input_land_name], lastResponseData[0][options.input_land_code], lastResponseData[0][options.input_group_code]);
                                                suggesterShowUp = false;
                                                hideSuggester();
													
                                            }
                                        }
                                    } else {
                                        return false;
                                    }
                                }
                                if (phrase.length > options.letters2activate){
                                    validate();
                                    //options.callbackOnEnter();
                                    //$(suggesterInputSecond).parents().find("form").submit();
                                } else {
                                    return false;
                                }
                            }
                        }
                    }
                    event.preventDefault();
					
                    return false; // TODO: finish onEnter
			
                }
            };

            /**
             * Key listener to determine suggesters next step AKA inside router
             */
            var keyListener = function(event)
            {
                // hide suggester on ESC
                if (event.keyCode == 27 && options.hideOnEsc) {
                    hideSuggester();
                    return false;
                }

                if ( event.keyCode == 9 ){
                    hideSuggester();
					
                    return;
                }

                // change suggester after any change
                //if (actualInputValue != lastPhrase && lastResponseData != undefined && !suggesterOnRoute) {
                if ( ( $("#suggester_list").length > 0 ) && !suggesterOnRoute) {
                    // on key up
                    if (event.keyCode == 38) {
                        suggesterCursorUp();
                        return false;
                    }

                    // on key down
                    if (event.keyCode == 40) {
                        suggesterCursorDown();
                        return false;
                    }
                }

                if ( ( event.keyCode >= 65 && event.keyCode <= 90 ) || event.keyCode == 8 || event.keyCode == 40) {
                // get actual user written string from input
                var actualInputValue = $(this).val();

                // clean remembered vars for actualy changed input
                cleanSuggesterVars(suggesterInput);

//              mirror("lastPhrase", actualInputValue);
//              mirror("lastResponseData", lastResponseData);
//              mirror("lastResponsePhrase", lastResponsePhrase);
//              mirror("suggesterOnRoute", suggesterOnRoute);

                // TODO: removed for now.
                //if (defaults.trimPhrase) actualInputValue = jQuery.trim(actualInputValue);

                if ( actualInputValue.length >= options.letters2activate )
                {
                    $(this).addClass('suggester_active');

                    var actualDataPhrase = actualInputValue.substr(0, options.letters2activate).toLowerCase();
//                  if (lastResponsePhrase != undefined) {
                    var lastDataPhrase = lastResponsePhrase;
//                  }

                    // update suggester data if phrase was changed
                    if (actualDataPhrase !== lastDataPhrase)
                    {
                        // update suggester data (load from server)
                        updateSuggesterData(actualDataPhrase);

                        // remember actual 3L phrase
                        lastResponsePhrase = actualDataPhrase;
                    } else {
                        // show suggester without refreshing data
                        showSuggester(actualInputValue);
                    }
                } else {
                    $(this).removeClass('suggester_active');

                    //if ( actualInputValue.length < defaults.letters2activate)
                    hideSuggester();
                }
                // remember as last used phrase (whole word)
                lastPhrase = actualInputValue;
                }
                if (!suggesterOnRoute) {
                    suggesterShowUp = true;
                }
            };

            var jumpUp = function(){
                var selected  = $("#suggester_list").find(".selected");
                var st = 0;
                if (selected.length == 1){
                    if (isNaN(selected.position().top)) {
                        st = 0;
                    } else {
                        st = selected.position().top;
                    }
                }
                var sl = $("#suggester_list").scrollTop();
                if ((st + sl) <= $("#suggester_list").scrollTop()) {
                    $("#suggester_list").scrollTop(st + sl); 
                } else {
                    //$("#suggester_list").scrollTop(0); 
                }
            };

            var jumpDown = function(){
                var selected  = $("#suggester_list").find(".selected");
                var st = 0;
                if (selected.length == 1){
                    if (isNaN(selected.position().top)) {
                        st = 0;
                    } else {
                        st = selected.position().top;
                    }
                }
                var sl = $("#suggester_list").scrollTop();
                if ((st + sl) >= $("#suggester_list").scrollTop()) {
                   $("#suggester_list").scrollTop(st + sl); 
                } else {
                    //$("#suggester_list").scrollTop(0); 

                }
            };

            var suggesterCursorUp = function() {
                var choices = $("#suggester_list").find('.choice');
                var selected  = $("#suggester_list").find(".selected");
                var index = $(choices).index($(selected));

                if (index < 0) {
                    $("#suggester_list > .choice:last").addClass('selected');
                } else {
                    $(selected).removeClass('selected');
                    $(choices).eq(index - 1).addClass('selected');
					
                }
                jumpUp();
            };

            var suggesterCursorDown = function()
            {
                var choices = $("#suggester_list").find('.choice');
                var selected  = $("#suggester_list").find(".selected");
                var index = $(choices).index($(selected));

                if (index < 0){
                    $("#suggester_list > .choice:first").addClass('selected');
                } else {
                    if ((index + 1) < $(choices).length){
                        $(selected).removeClass('selected');
                        $(choices).eq(index + 1).addClass('selected');
                    } else {
                        $(selected).removeClass('selected');
                        $("#suggester_list > .choice:first").addClass('selected');
                    }
                }
                jumpDown();
            };

            /**
             * Sends request and returns response from designated url
             */
            var updateSuggesterData = function(phrase){
                var rqUrl = options.requestUrl + encodeURI(phrase);

                // set suggesterOnRoute to not request while requesting already
                if (!suggesterOnRoute) {
                    suggesterOnRoute = true;

                    if(suggesterInput == 'first'){
                        $('#suggester_pickup_progress').show();
                    } else if (suggesterInput == 'second'){
                        $('#suggester_dropoff_progress').show();
                    }
                    $.ajax({
                        url: rqUrl,
                        timeout: (options.requestTimeout * 1000),
                        dataType: "text",
                        data: 'phrase='+phrase,
                        type: 'POST',
                        success: function(response){

                            // if data is obsolete, do request for newest.
                            if (suggesterRequestQuery) {
                                temp = suggesterRequestQuery;
                                //mirror('suggesterRequestQuery', suggesterRequestQuery);
                                resetSuggesterQuery();
                                suggesterOnRoute = false;
                                updateSuggesterData(temp);
                                showSuggester(phrase);
                            }

                            // remove some junk from response
                            var text = response.replace(/createRPCDone/g, "");
                            //var text = response;

                            // validate text to be realy JSON
                            if (options.clearResponseData) {
                                text = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test(text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')');
                            }

                            // update stored suggests
                            lastResponseData = eval( text );

                            suggesterOnRoute = false;

                            showSuggester(lastPhrase);
                            suggesterShowUp = true;
                        },
                        error: function(response){
                            suggesterOnRoute = false;
                            resetSuggesterQuery();
                        },
                        complete: function(response){
                            if(suggesterInput == 'first'){
                                $('#suggester_pickup_progress').hide();
							
                            } else if (suggesterInput == 'second'){
                                $('#suggester_dropoff_progress').hide();
								
                            }
                        }
                    });
                } else {
                    // add request to query for further send
                    querySuggesterRequest(phrase);
						
                }
            };

            /**
             * Adds phrase to query for further use
             * @param {Object} phase
             */
            var querySuggesterRequest = function(phrase)
            {
                suggesterRequestQuery = phrase;
            };

            /**
             * Resets suggester request query
             */
            var resetSuggesterQuery = function()
            {
                suggesterRequestQuery = undefined;
            };

            /**
             * Returns location data for designated location code
             * @param {Object} code
             */
            var returnSelectedInfo = function(code)
            {
                for (i in lastResponseData){
                    // one place from list
                    if (lastResponseData[i][options.input_loc_code] == code) {
                        return lastResponseData[i];
                    }
                }
                return false;
            };

            /**
             * Set focus on first suggester input
             */
            var setStartFocus = function()
            {
                if (options.focusOn.length > 0) $(options.focusOn).focus();
            };

            /**
             * Puts prepared html list under input box
             */
            var showSuggester = function(phrase)
            {
                if(suggesterShowUp){

                // prepare suggests
                var choices_counter = prepareSuggests(phrase);

                //$("#suggester_list").css('height', '20px');

                // show suggests
                //$("#suggester_list").slideDown('normal'); //css('display', 'block');

                if (choices_counter > 0) {
                    setSuggesterPosition();
                    $("#suggester_list").css('left', suggesterPosition.left);
                    $("#suggester_list").css('top', suggesterPosition.top);
                    
                    // deamn IE6
                    if (isIE6 === true && choices_counter > 12){
                        $("#suggester_list").css('width', (suggesterWidth-17));
                    } else {
                        $("#suggester_list").css('width', suggesterWidth);
                    }

                    if (options.suggesterFade){
                        $("#suggester_list").show();
                    } else {
                        $("#suggester_list").show();
                    }

                    // ;( IE6 SUCKS!
                    if (isIE6 === true) {
                        var suggesterHeight = $("#suggester_list").height();
                        //$('#suggester_list_back').remove();
                        suggesterWidth = (parseInt(suggesterWidth) + 1) + 'px';
                        $("#suggester_list_back").css('left', suggesterPosition.left).css('top', suggesterPosition.top).css('width', suggesterWidth).css('height', suggesterHeight).css('display', 'block');
                    }

                    // reset suggester list position
                    //setSuggesterPosition();
                    $("#"+suggesterInput+"_suggester_list > .choice:first").each(function(){
                        $(this).addClass('selected');
							
											
                    });

                    // bind mouseOver and mouseClick to suggester list
                    $("#suggester_list > .choice").hover( function(){
                        // remove hidden part - reset suggesterSelectedLocation
                        //cleanSuggesterVars(suggesterInput); - commented @ yanoo 2009 10 13
                        // remove visual part - .selected class from .choice div
                        $("#suggester_list").removeClass('selected');
                        $(this).addClass('selected');
						
                    }, function(){
                        $(this).removeClass('selected');
					
						
                    });

                    // set item click
                    $("#suggester_list .choice").bind('click', function(){
                        // TODO: later on it has to be changed to function which sets all needed hidden variables

                        var selected = returnSelectedInfo($(this).attr('id'));
						
                        //if (typeof selected == 'object') {
                        setSuggesterVars(selected[options.input_land_code], selected[options.input_loc_code], selected.loc_name, selected[options.input_land_name], selected[options.input_group_code]);
                            //setSuggesterPhrase();
                             hideSuggester();
						    	$('#desApt_suggest_layer').hide();
								$('#desApt_suggest_val').show();
								$('#desApt_suggest_val').html($('#suggester_dropoff').val());

                        // jump to second suggester field after chosing in first
                        if (suggesterInput == 'first'){
                            $(suggesterInputSecond).focus();
							//alert('test');
		                        $('#depApt_suggest_layer').hide();
								$('#depApt_suggest_val').show();
								$('#depApt_suggest_val').html($('#suggester_pickup').val());
								$('#desApt_suggest_layer').hide();
								$('#desApt_suggest_val').show();
								$('#desApt_suggest_link').hide();
								$('#desApt_suggest_val').html($('#suggester_dropoff').val());
									
								
								
                        }

                        //}
                    });
                } else {
                    if (isIE6 === true) hideSuggester();
					
                }
              }
            };

            var prepareSuggests = function(phrase){

                var choices_counter = 0;

                //var phrase = lastResponsePhrase;
                //var data = lastResponseData;

                // create suggester list if it not exists
                if ($("#suggester_list").length == 0) {
                    //suggesterInputFirst.after('<div id="suggester_list"></div>');
                    //if ($("#endPage")){
                        //$('#endPage').before('<div class="suggester_list" id="suggester_list"></div>');
//                    } else {
                        $('body').append('<div class="suggester_list" id="suggester_list"></div>');
//                    }
                }

                // reset suggester list content
                $("#suggester_list").html('');
                var suggester_list_html = '';

                // container to store last country code
                var lastCountryCode = "";
                var lastCountryName = "";
                var lastLocationCode = "";
                var lastGroupCode = "";

                var firstCountryCode = "";
                var firstCountryName = "";
                var firstLocationCode = "";
                var firstGroupCode = "";

                // parse every element in suggester data to retrieve items (locations) to show
                for (i in lastResponseData) {

                    // relocate data in row (for different data sources)

                    // do not show location when phrase is longer than 3 (IATA) and begin of phrase is the same as location code.
                    if (phrase.length > 3 && phrase.substr(0,3).toUpperCase() === lastResponseData[i][options.input_loc_code] && i == 0)
                    {
                        continue;
                    }

                    // remember first location code
                    if (i == 0){
                        firstCountryCode = lastResponseData[i][options.input_land_code];
                        firstCountryName = lastResponseData[i][options.input_land_name];
                        firstLocationCode = lastResponseData[i][options.input_loc_code];
                        firstGroupCode = lastResponseData[i][options.input_group_code];
                    }

                    // sometimes return data has empty fields, dunno why
                    if ( lastResponseData[i].loc_name == undefined) {
                        continue;
                    }

                    var location_name = lastResponseData[i].loc_name;
                    var location_code = lastResponseData[i][options.input_loc_code];
                    var location_alias = lastResponseData[i][options.input_group_code];

                    var rgx = new RegExp(phrase, 'gi');

                    var name_niddle = location_name.match(rgx);
                    var code_niddle = location_code.match(rgx);
                    var alias_niddle = location_alias.match(rgx);

                    if (name_niddle != null || code_niddle != null || alias_niddle != null) {

                        /* FILTER filterNameNoWrap */
                        //location_name = location_name.replace(/\s/, '&nbsp;');

                        /* FILTER filterShowEmboss */
                        if (options.filterShowEmboss && false) { //FIXME: remove false
                            if (name_niddle)  {
                                location_name = location_name.replace(rgx, '<span class="emboss">' + name_niddle + '</span>');
                            }
                            if (code_niddle) {
                                location_code = location_code.replace(rgx, '<span class="emboss">' + code_niddle + '</span>');
                            }
                            if (alias_niddle) {
                                location_alias = location_alias.replace(rgx, '<span class="emboss">' + alias_niddle + '</span>');
                            }
                        }

                        /* FILTER filterShowCaption */
                        if (options.filterShowCaption) {

                            // add country strip if it is different as last one

                            //  if (lastCountryCode !== lastResponseData[i].land_code && i != 0 &&  ){
                            //if (lastCountryCode != lastResponseData[i][options.input_land_code]) {
                            if (lastCountryCode != lastResponseData[i][options.input_land_code] || lastCountryName != lastResponseData[i][options.input_land_name]) {
                                // hide caption for phrase when location name and location iata are the same
                                //if ( ! ( phrase.length == 3 &&  ( phrase.substr(0, 3).toUpperCase() == lastResponseData[i].loc_code || phrase.substr(0,3).toUpperCase() == lastResponseData[i].loc_name.toUpperCase() ) ) )
                                if ( ! ( i == 0 && phrase.length == 3 && ( lastPhrase.substr(0, 3).toUpperCase() == lastResponseData[i][options.input_loc_code] || phrase.substr(0,3).toUpperCase() == lastResponseData[i][options.input_loc_name].toUpperCase())))
                                {
                                    //$("#suggester_list").append('<div class="caption"><span>' + lastResponseData[i][options.input_land_name] + '</span></div>');
                                    suggester_list_html += '<div class="caption"><span>' + lastResponseData[i][options.input_land_name] + '</span></div>';
                                }
                                choices_counter++; // increment for further comparation
                            }
                            lastCountryCode = lastResponseData[i][options.input_land_code];
                            lastCountryName = lastResponseData[i][options.input_land_name];
                        }

                        // create list of accepted locations to show
                        var choice = '<div class="choice" id="' + lastResponseData[i][options.input_loc_code] + '" title="' + lastResponseData[i][options.input_loc_name] + '"><span class="name">' + location_name + '</span>';
                        // add location code only if this is IATA (3 letters)
                        if (lastResponseData[i][options.input_loc_code].length == 3 || options.filterAlwaysShowLocCode ) {
                            choice += '<span class="code">' + location_code + '</span>';
                        }
                        // add alias only if it is different than location name
                        if (lastResponseData[i][options.input_loc_name] != lastResponseData[i][options.input_group_code]) {
                            choice += '<span class="alias">' + location_alias + '</span>';
                        }
                        choice += '</div>';

                        // check for earlier loc_code in array and don't show the same one

                        if ( i == 0 && lastResponseData[1] != undefined){
                            if ( lastResponseData[0][options.input_loc_code] != lastResponseData[1][options.input_loc_code] ) {
                                //$("#suggester_list").append(choice);
                                suggester_list_html += choice;
                            }
                        } else {
                            //$("#suggester_list").append(choice);
                            suggester_list_html += choice;
                        }
                        choices_counter++;
                    }
                }
                $("#suggester_list").append(suggester_list_html);
                if ( !isNaN(choices_counter) && choices_counter > 12){
                    $("#suggester_list").css('overflow', 'visible').css('overflow-y', 'scroll').css('height', options.height + 'px').css('width', '100px');
                    // FIXME: set width of suggester list
                } else {
                    $("#suggester_list").css('overflow-y', 'auto').css('height', 'auto');
                }
                return choices_counter;
            };

            /**
             * This function creates (if lack of) hidden input add fill it with user
             * settings like the information that user chose from suggester or not.
             * @param {Object} variable
             */
            var setSuggesterVars = function(land_code, loc_code, loc_name, land_name, group_code){
                switch (suggesterInput){
                    case 'first' :  {
                        setSuggesterVarsFirst(land_code, loc_code, loc_name, land_name, group_code);
                        var dropoffOverride = options.dropoffOverride;
                        if (checkInputNotSet('second') && dropoffOverride) {
                            setSuggesterVarsSecond(land_code, loc_code, loc_name, land_name, group_code);
                        }
                        break;
                    }
                    case 'second' : {
                        setSuggesterVarsSecond(land_code, loc_code, loc_name, land_name, group_code);
                        if (checkInputNotSet('first')) {
                            setSuggesterVarsFirst(land_code, loc_code, loc_name, land_name, group_code);
                        }
                        break;
                    }
                }
            };

            /**
             * Check if another input was already set
             * @param {Object} input
             */
            var checkInputNotSet = function(input){
                switch(input){
                    case 'first': {
                        return ( suggesterFirstLandCode && suggesterFirstLocCode ) ? false : true;
                        break;
                    }
                    case 'second': {
                        return ( suggesterSecondLandCode && suggesterSecondLocCode ) ? false : true;
                        break;
                    }
                }
            };

            /**
             * Set all values to first suggester input
             * @param {Object} land_code
             * @param {Object} loc_code
             * @param {Object} loc_name
             * @param {Object} land_name
             * @param {Object} group_code
             */
            var setSuggesterVarsFirst = function(land_code, loc_code, loc_name, land_name, group_code){
                // if there is no input for variables yet, create one and put there actual user settings
                if ($('input#'+options.pickup_land_code).length == 0) {
                    $('.suggester').filter('.first').after('<input type="hidden" id="'+options.pickup_land_code+'" name="'+options.pickup_land_code+'" value="" />');
                }
                if ($('input#'+options.pickup_land_name).length == 0) {
                    $('.suggester').filter('.first').after('<input type="hidden" id="'+options.pickup_land_name+'" name="'+options.pickup_land_name+'" value="" />');
                }
                if ($('input#'+options.pickup_loc_code).length == 0) {
                    $('.suggester').filter('.first').after('<input type="hidden" id="'+options.pickup_loc_code+'" name="'+options.pickup_loc_code+'" value="" />');
                }
                if ($('input#'+options.pickup_group_code).length == 0) {
                    $('.suggester').filter('.first').after('<input type="hidden" id="'+options.pickup_group_code+'" name="'+options.pickup_group_code+'" value="" />');
                }
                suggesterFirstLandCode = land_code;
                suggesterFirstLandName = land_name;
                suggesterFirstLocCode = loc_code;
                suggesterFirstGroupCode = group_code;
                $("input#"+options.pickup_land_code).val(land_code);
                $("input#"+options.pickup_land_name).val(land_name);
                $("input#"+options.pickup_loc_code).val(loc_code);
                $("input#"+options.pickup_group_code).val(group_code);
                setSuggesterPhrase(loc_name, 'first');
            };

            /**
             * Set all values to second suggester input
             * @param {Object} land_code
             * @param {Object} loc_code
             * @param {Object} loc_name
             */
            var setSuggesterVarsSecond = function(land_code, loc_code, loc_name, land_name, group_code){
                if ($('input#'+options.dropoff_land_code).length == 0) {
                    $('.suggester').filter('.second').after('<input type="hidden" id="'+options.dropoff_land_code+'" name="'+options.dropoff_land_code+'" value="" />');
                }
                if ($('input#'+options.dropoff_land_name).length == 0) {
                    $('.suggester').filter('.second').after('<input type="hidden" id="'+options.dropoff_land_name+'" name="'+options.dropoff_land_name+'" value="" />');
                }
                if ($('input#'+options.dropoff_loc_code).length == 0) {
                    $('.suggester').filter('.second').after('<input type="hidden" id="'+options.dropoff_loc_code+'" name="'+options.dropoff_loc_code+'" value="" />');
                }
                if ($('input#'+options.dropoff_group_code).length == 0) {
                    $('.suggester').filter('.first').after('<input type="hidden" id="'+options.dropoff_group_code+'" name="'+options.dropoff_group_code+'" value="" />');
                }
                suggesterSecondLandCode = land_code;
                suggesterSecondLandName = land_name;
                suggesterSecondLocCode = loc_code;
                suggesterSecondGroupCode = group_code;
                $("input#"+options.dropoff_land_code).val(land_code);
                $("input#"+options.dropoff_land_name).val(land_name);
                $("input#"+options.dropoff_loc_code).val(loc_code);
                $("input#"+options.dropoff_group_code).val(group_code);
                setSuggesterPhrase(loc_name, 'second');
            };

            /**
             * Cleans user chosen location
             * @param {Object} input
             */
            var cleanSuggesterVars = function(input)
            {
                switch(input){
                    case 'first': {
                            suggesterFirstLandCode = undefined;
                            suggesterFirstLandName = undefined;
                            suggesterFirstLocCode = undefined;
                            suggesterFirstGroupCode = undefined;
                            $('#'+options.pickup_land_code).val('');
                            $('#'+options.pickup_land_name).val('');
                            $('#'+options.pickup_loc_code).val('');
                            $('#'+options.pickup_group_code).val('');
                        break;
                    }
                    case 'second': {
                            suggesterSecondLandCode = undefined;
                            suggesterSecondLandName = undefined;
                            suggesterSecondLocCode = undefined;
                            suggesterSecondGroupCode = undefined;
                            $('#'+options.dropoff_land_code).val('');
                            $('#'+options.dropoff_land_name).val('');
                            $('#'+options.dropoff_loc_code).val('');
                            $('#'+options.dropoff_group_code).val('');
                        break;
                    }
                }
            };

            /**
             * Fills actual suggester input with designated phrase
             */
            var setSuggesterPhrase = function(phrase, input)
            {
                var which = (input) ? input : suggesterInput;
                switch (which) {
                    case 'first': { $(suggesterInputFirst).val(phrase); break; }
                    case 'second': { $(suggesterInputSecond).val(phrase); break; }
                }
            };

            /**
             * Hide suggester
             */
            var hideSuggester = function()
            {
                if (options.suggesterFade){
                    $("#suggester_list").show("normal", function(){
                        $(this).remove();
                    });
                } else {
                //$("#suggester_list").slideUp("fast", function(){
                    $("#suggester_list").remove();
                //});
                }
                if (isIE6 === true) {
                    hideIFrameBG();
                }
            };

            /**
             * Sets position of suggester list
             */
            var setSuggesterPosition = function(){
                if (suggesterInput == 'first') {
                     suggesterPosition = $(suggesterInputFirst).offset();
                     suggesterWidth = (options.width > 0) ? options.width : $(suggesterInputFirst).innerWidth();
                     suggesterWidth += options.widthOffset;

                     suggesterPosition.top += suggesterInputFirst.outerHeight();
                     suggesterPosition.top += options.topOffset;

                     suggesterPosition.left += parseInt($(suggesterInputFirst).css('borderLeftWidth'));
                } else {
                     suggesterPosition = $(suggesterInputSecond).offset();
                     suggesterWidth = (options.width > 0) ? options.width : $(suggesterInputSecond).innerWidth();
                     suggesterWidth += options.widthOffset;

                     suggesterPosition.top += suggesterInputSecond.outerHeight();
                     suggesterPosition.top += options.topOffset;

                     suggesterPosition.left += parseInt($(suggesterInputSecond).css('borderLeftWidth'));
                }
           };

            var createIFrameBG = function(){
                if ( $("#suggester_list_back").length == 0 ){
                    var iframe = '<iframe src="" id="suggester_list_back" frameborder="no" style="border:0; z-index:10; background-color: rgb(255, 255, 255) none repeat scroll 0% 0%; visibility: visible; position: absolute; left: -100px; top: -100px; width: 10px; height: 10px; display: none;"></iframe>';
                    $('body').append(iframe);
                }
            };

            var hideIFrameBG = function(){
                $("#suggester_list_back").css('width', '10px').css('height', '10px').css('left', '-100px').css('top', '-100px');
            }

            /**
             *
             */
            var setFocus = function()
            {
                suggesterInput = ($(this).hasClass('second') ) ? 'second' : 'first';
                //setSuggesterPosition();
                // TODO: set keyup event here to trigger suggester preparation and show off
                //showSuggester($(this).val());
                //$(this).keyup();

//              mirror('suggesterInput', suggesterInput);
//              mirror('suggesterPosition', suggesterPosition.left+'x'+suggesterPosition.top);
            };

            var validate = function(){
                // get params to validate
                var pickup_phrase = ($("#suggester_pickup").val() || '');
                var dropoff_phrase = ($("#suggester_dropoff").val() || '');

                var pckloc = ($("#suggester_first_loc_code").val() || '');
                var drploc = ($("#suggester_second_loc_code").val() || '');

                var pcklnd = ($("#suggester_first_land_code").val() || '');
                var drplnd = ($("#suggester_second_land_code").val() || '');
                // send params to validator

                $.ajax({
                    url: options.validationUrl,
                    dataType: "json",
                    type: "POST",
                    data: ({ pickup_phrase: pickup_phrase, dropoff_phrase: dropoff_phrase, pckloc: pckloc, drploc: drploc, pcklnd: pcklnd, drplnd: drplnd }),
                    success: function(msg){
                        options.callbackOnSubmit(msg);
                        // show suggester list if message != OK
                        if (msg.message != 'OK'){
                            if (msg.pickup.loc_code == '' || msg.dropoff.loc_code == '') {
                                suggesterInput = 'first';
                                updateSuggesterData(pickup_phrase);
                                showSuggester(pickup_phrase);
                            }
                        }
                    }
                });
            }

            /**
             * Mirrors value to designated place onscreen.
             * @param {Object} key
             * @param {Object} value
            var mirror = function(key, value)
            {
                var k = "#"+key;
                $(k).html(key +": "+value);
            };*/

            /**
             * Main loop
             */
            return this.each(function(){

                    if (isIE6 === true){
                        createIFrameBG();
                    }

                    if ( options.disableAutocomplete ){
                        $(this).attr("autocomplete", "off");
                    }

                    if (options.submitButton){
                        $(options.submitButton).bind('click', validate);
                    }

                    // Bind callback to onEnter
                    $(this).bind('keypress', onEnter);

                    // Bind callback to every key pressed (UP)
                    $(this).bind('keyup', keyListener);

                    // hide suggester when somebody click someware outside the suggester list
                    $("html").bind('click', blurize);
		

                    // Set suggester inputs as first and second and remember them as objects inside
                    if (suggesterInputFirst)
                    {
                        $(this).attr("name", options.dropoff_loc_name);
                        suggesterInputSecond = $(this);
                        $(suggesterInputSecond).addClass("second");
                    } else {
                        $(this).attr("name", options.pickup_loc_name);
                        suggesterInputFirst = $(this);
                        $(suggesterInputFirst).addClass("first");
                    }

                    $(this).bind('focus', setFocus);
                    //$(this).bind('blur', hideSuggester);
				
                    /**
                     * Set focus on chosen (first) input in form if its selector is set
                     */
                    setStartFocus();
            });
        };
})(jQuery);

