﻿function SetupAgenciesFinder(_clientID, url_localsHandler, url_namesHandler, _noResultsResource, controlID, txtName, txtLocation, txtAMI, txtAPEMIP, btnSearch) {
    $('#' + controlID).SetupAgencyFinder({
        maxResults: 6,
        clientID: _clientID,
        databaseHandler_URLs: {
            agencyLocals: url_localsHandler,
            agencyNames: url_namesHandler
        },
        noResultsResource: _noResultsResource,
        txtName: txtName,
        txtLocation: txtLocation
    });
   
   var txtCity = "#" + _clientID + "_" + txtLocation;
   var txtName = "#" +_clientID + "_" + txtName;
   var txtAmi = "#" + _clientID + "_" + txtAMI;
   var txtApemip = "#" + _clientID + "_" + txtAPEMIP;
   var btnSearch = "#" + _clientID + "_" + btnSearch;
   var $textboxCity = $(txtCity),
                $textboxName = $(txtName),
                $textboxAmi = $(txtAmi),
                $textboxApemip = $(txtApemip),
                $buttonSearch = $(btnSearch);
                
   $buttonSearch.click(function() {
          
        var local = $textboxCity.val();
        var name = $textboxName.val();
        var ami = $textboxAmi.val();
        var apemip = $textboxApemip.val();

        if (local == "" && name == "" && ami=="" && apemip=="")
            return false;
    });
    
    if (window.devicePixelRatio == 1) {
        $("#dSearchAgencies").css("margin-top", "11px !important");
    };
}

(function($) {
    $.fn.SetupAgencyFinder = function(pluginSettings) {

        var defaultSettings = {
            parameter: 'parameter_value',
            databaseHandler_URLs: {
                agencyLocals: 'App_Handlers/Agencies/locals.ashx',
                agencyNames: 'App_Handlers/Agencies/names.ashx'
            },
            queryDelay: 250, 		// milisegundos
            requestTimeout: 5000, 	//milisegundos
            mininumChars: 3, 	// valor tido em conta apenas para o primeiro request de localizações.
            maxResults: 6,
            currentItem_class: 'current',
            clientID: '',
            txtName: '',
            txtLocation: ''
        };
        var $settings = $.extend(defaultSettings, pluginSettings);

        return this.each(function() {



            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // INDEX

            // DECLARATIONS
            // INIT
            // TEXT INPUT
            // SUGGESTIONS
            // ============================================================================================
            // ============================================================================================
            // ============================================================================================


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ DECLARATIONS

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================
            var txtCity = "#" + $settings.clientID + "_" + $settings.txtLocation;
            var txtName = "#" + $settings.clientID + "_" + $settings.txtName;


            var $textboxCity = $(txtCity),
                $textboxName = $(txtName),
                $localSuggestionsDiv = $('#dLocalSuggestions', $(this)),
                $nameSuggestionsDiv = $('#dNameSuggestions', $(this)),
				$localLoader = $('.localLoader', $(this)),
                $nameLoader = $('.nameLoader', $(this));

            var _delayID = -1;
            var _keyboard = { left: 37, up: 38, right: 39, down: 40, enter: 13, escape: 27, backspace: 8 };

            var currentIndex = -1;


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ INIT

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ TEXT INPUT

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // ----------------------------------------------------------------------
            // > Ao escrever na caixa de texto, solicito à BD os dados adequados
            $textboxCity.keyup(function(event) {

                // 1. obter os tokens introduzidso na textboxs
                var localToken = $textboxCity.val();
                var nameToken = $textboxName.val();

                // 2. apenas invocar a base de dados se: for um caracter válido + houverem caracteres suficientes
                if (IsIgnoredKey(event.keyCode) == false) {
                    if (HasEnoughChars(localToken) == true) {

                        // 2.1. apresentar o loader
                        $localLoader.show();

                        // 2.2. garantir que só são feitos pedidos à BD de x em x segundos

                        // 2.2.1. apagar possiveis timeouts a decorrer
                        if (_delayID != -1) {
                            clearTimeout(_delayID);
                        }

                        // 2.2.2 criar novo timeout
                        _delayID = setTimeout(function() {
                            RequestSuggestions(localToken, nameToken, $settings.databaseHandler_URLs.agencyLocals, true);
                        }, $settings.queryDelay);

                    }
                    else {

                        // 2.3. apaga as sugestões
                        ClearSuggestions($localSuggestionsDiv);
                    }
                }

            });

            $textboxName.keyup(function(event) {

                // 1. obter os tokens introduzidos nas textboxs
                var nameToken = $textboxName.val();
                var localToken = $textboxCity.val();

                // 2. apenas invocar a base de dados se: for um caracter válido + houverem caracteres suficientes
                if (IsIgnoredKey(event.keyCode) == false) {
                    if (HasEnoughChars(nameToken) == true) {

                        // 2.1. apresentar o loader
                        $nameLoader.show();

                        // 2.2. garantir que só são feitos pedidos à BD de x em x segundos

                        // 2.2.1. apagar possiveis timeouts a decorrer
                        if (_delayID != -1) {
                            clearTimeout(_delayID);
                        }

                        // 2.2.2 criar novo timeout
                        _delayID = setTimeout(function() {
                            RequestSuggestions(localToken, nameToken, $settings.databaseHandler_URLs.agencyNames, false);
                        }, $settings.queryDelay);

                    }
                    else {

                        // 2.3. apaga as sugestões
                        ClearSuggestions($nameSuggestionsDiv);
                    }
                }

            });
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > evita que um clique em cima da caixa de texto, faça desaparecer as sugestões
            $textboxCity.click(function(event) {
                ClearSuggestions($nameSuggestionsDiv);
                event.stopPropagation();
            });
            $textboxName.click(function(event) {
                ClearSuggestions($localSuggestionsDiv);
                event.stopPropagation();
            });
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > verifica se existem caracteres suficientes para iniciar uma pesquisa
            function HasEnoughChars(token) {
                
                // 1. Se já houver valores numa das textbox
                if ($textboxCity.val().length >= $settings.mininumChars || $textboxName.val().length >= $settings.mininumChars) {
                    // 1.1. ...basta existir apenas um caracter
                    return (token.length >= 1);
                } else {
                    // 1.2. ...é necessário pelo menos $settings.mininumChars caracteres
                    return (token.length >= $settings.mininumChars);
                }

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > verifica se determinada tecla pressionada deve ser considerada para solicitar dados à BD
            function IsIgnoredKey(nKeyCode) {
                if ((nKeyCode == 9) || (nKeyCode == 13) || // tab, enter
    			        (nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl
    			        (nKeyCode >= 18 && nKeyCode <= 20) || // alt, pause/break,caps lock
    			        (nKeyCode == 27) || // esc
    			        (nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end
                /*(nKeyCode >= 36 && nKeyCode <= 38) || // home,left,up
                (nKeyCode == 40) || // down*/
    			        (nKeyCode >= 36 && nKeyCode <= 40) || // home,left,up, right, down
    			        (nKeyCode >= 44 && nKeyCode <= 45) || // print screen,insert
    			        (nKeyCode == 224) || // print screen,insert
    			        (nKeyCode == 229) // Bug 2041973: Korean XP fires 2 keyup events, the key and 229
    			    ) {
                    return true;
                }
                return false;
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            function CloseBecauseError($textbox) {

                // 1. Limpar a textbox
                $textbox.val('');
                $textbox.attr('readonly', 'true');
                $textbox.blur();


            }
            // ----------------------------------------------------------------------


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ SUGGESTIONS

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================


            // ----------------------------------------------------------------------
            // > Pedido de sugestões à BD
            function RequestSuggestions(_localToken, _nameToken, _url, isLocal) {

                var $textbox;
                var token = "";
                var $loader;
                //Se é um local, utilizar a textboxCity
                if (isLocal) {
                    $textboxName.attr("disabled", "disabled");
                    $textbox = $textboxCity;
                    $loader = $localLoader;
                    token = _localToken;
                }
                else {//Se não, utilizar a textboxName
                    $textboxCity.attr("disabled", "disabled");
                    $textbox = $textboxName;
                    $loader = $nameLoader;
                    token = _nameToken;
                }
                // 0. faço o pedido assincrono ao handler
                $.ajax({
                    type: 'GET',
                    timeout: $settings.requestTimeout,
                    url: _url,
                    processData: true,
                    data: {
                        locationToken: encodeURI(_localToken),
                        nameToken: encodeURI(_nameToken),
                        maxResults: $settings.maxResults
                    },
                    dataType: 'json',
                    error: function(request, status, error) {

                        $textboxCity.attr("disabled", "");
                        $textboxName.attr("disabled", "");
                        // 1.1. apresento o erro
                        //alert('Error: ' + status);

                        // 1.2. escondo o loader
                        $loader.hide();

                    },
                    success: function(data) {
                        $textboxCity.attr("disabled", "");
                        $textboxName.attr("disabled", "");

                        // 2.1. carrego as sugestões
                        DisplaySuggestions(data.suggestions, token, isLocal);

                        // 2.2. escondo o loader
                        $localLoader.hide();
                        $nameLoader.hide();

                    }
                });

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Apresento as sugestões, lista de DIVs
            function DisplaySuggestions(suggestions, locationToken, isLocal) {

                // 1. Apago as sugestões que possam existir na lista
                var $suggestionsDiv;
                var $textbox;
                if (isLocal) {
                    $suggestionsDiv = $localSuggestionsDiv;
                    $textbox = $textboxCity;
                }
                else {
                    $suggestionsDiv = $nameSuggestionsDiv;
                    $textbox = $textboxName;
                }
                ClearSuggestions($suggestionsDiv);

                // 2. Se existirem sugestões a apresentar
                if (suggestions.length > 0) {

                    // 2.1 para cada uma delas
                    $.each(suggestions, function(index, results) {

                        // 2.1.1. construo a descrição a apresentar por cada sugestão, Se fizer match com a outra caixa de texto, irá ser apresentada essa informação(icone)
                        var line = results.description;


                        //if (results.match == 1) { line += ' <span class="match"></span>'; }
                        // 2.1.2. construo o objecto (sugestão) a ser adicionado à lista de sugestões
                        var linkTemplate = $('<a href="#">' + line + '</a>');

                        // 2.1.3. anexo-lhe os dados (JSON) relativos à informação que ele representa
                        linkTemplate.data('resultItemInfo', results);

                        // 2.1.4. anexo-lhe o indice da lista respectivo
                        linkTemplate.data('itemIndex', index);

                        // 2.1.5. preparo o efeito de hovering no objecto
                        linkTemplate.hover(
                            function() {

                                // 2.1.5.1. ao passar o rato por cima devo marcar o objecto como seleccionado
                                currentIndex = $(this).data("itemIndex");
                                SetSelected(currentIndex, $suggestionsDiv);
                                $textbox.blur();

                            }, function() {

                                // 2.1.5.2. ao retirar o rato de cima devo desmarcá-lo como objecto seleccionado
                                linkTemplate.removeClass($settings.currentItem_class);
                                currentIndex = -1;
                                $textbox.blur();
                            }
                        );

                        // 2.1.6. preparo o click no objecto
                        linkTemplate.click(function(event) {

                            // 2.1.6.1. chamo a função de selecção de item
                            PickValue(results, isLocal);

                            // 2.1.6.2. evito a propagação do evento
                            event.stopPropagation();
                            return false;
                        });

                        // 2.1.7. sublinho a existencia do token especificado em cada sugestão
                        linkTemplate.highlight(locationToken);

                        // 2.1.8. adiciono o objecto ao div de sugestões
                        $suggestionsDiv.append(linkTemplate);

                    });
  
                }
                else {
                    //Display none suggestions
                    var noSuggestionsFeedback = $settings.noResultsResource;

                    // 2.1.2. construo o objecto de informação da não existencia de sugestoes
                    var template = $('<a href="#">' + noSuggestionsFeedback + '</a>');
                    template.click(function(event) {
                        event.stopPropagation();
                        return false;
                    });

                    $suggestionsDiv.append(template);

                }
             

                $('body').one('click', function() {
                    ClearSuggestions($suggestionsDiv);
                });

                // 2.3. depois de preparado, mostro o div de sugestões se a caixa de texto ainda tiver o numero mínimo de caracteres
                if (HasEnoughChars($textbox.val())) {
                    $suggestionsDiv.show();
                }
                else {
                    ClearSuggestions($suggestionsDiv);
                }

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Limpa todas as sugestões activas
            function ClearSuggestions($suggestionsDiv) {

                // 1. escondo o div com as sugestões
                $suggestionsDiv.hide();

                // 2. apago o seu conteudo, para na próxima vez que for apresentado, não levar com valores obsoletos
                $suggestionsDiv.children().remove();
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Limpa a textbox
            function ClearTextbox($textbox) {

                // 1. retiro o focus da textbox, pois só assim consigo alterar o seu valor
                $textbox.blur();
                // 2. reset ao valor da textbox
                $textbox.val('');

                // 3. volto a atribuir o focus à textbox
                $textbox.focus();
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Para cada tecla 
            $(document).keydown(function(e) {

                BindKeyPress(e, true, $localSuggestionsDiv, $textboxCity);
                BindKeyPress(e, false, $nameSuggestionsDiv, $textboxName);

            });
            // ----------------------------------------------------------------------

            function BindKeyPress(e, isLocal, $suggestionsDiv, $textbox) {
                var pressed = false;
                var $loader;
                if (isLocal) { $loader = $localLoader; }
                else { $loader = $nameLoader; }
                // 1. Se estão a ser apresentadas sugestoes
                if ($suggestionsDiv.is(':visible')) {

                    switch (e.keyCode) {

                        // up arrow                                              
                        case _keyboard.up:
                            if ($loader.is(':visible')) return false;
                            Navigate('up', $suggestionsDiv, $textbox);
                            pressed = true;
                            break;

                        // down arrow                                              
                        case _keyboard.down:
                            if ($loader.is(':visible')) return false;
                            Navigate('down', $suggestionsDiv, $textbox);
                            pressed = true;
                            break;

                        // enter key                                              
                        case _keyboard.enter:
                            if ($loader.is(':visible')) return false;

                            // 1. Get location info JSON object
                            var results = $suggestionsDiv.children('a').eq(currentIndex).data('resultItemInfo');

                            // 2. Pick Location
                            if (results != undefined)
                            { PickValue(results, isLocal); }
                            pressed = true;
                            break;

                        // escape key                                              
                        case _keyboard.escape:
                            ClearSuggestions($suggestionsDiv);
                            pressed = true;
                            break;

                    }

                }

                if (pressed)
                    return false;
            }

            // ----------------------------------------------------------------------
            function Navigate(direction, $suggestionsDiv, $textbox) {

                if ($suggestionsDiv.children('a').filter('.' + $settings.currentItem_class).size() == 0) {
                    currentIndex = -1;
                }

                if (direction == 'up' && currentIndex != -1) {
                    if (currentIndex != 0) {
                        currentIndex--;
                    }
                    else {
                        $suggestionsDiv.children('a').removeClass($settings.currentItem_class);
                        $textbox.focus();
                        currentIndex = -1;
                        return;
                    }
                } else if (direction == 'down') {
                    if (currentIndex != $suggestionsDiv.children('a').size() - 1) {
                        currentIndex++;
                    }
                }

                SetSelected(currentIndex, $suggestionsDiv);

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            function SetSelected(itemIndex, $suggestionsDiv) {
                if (itemIndex >= 0) {
                    $suggestionsDiv.children('a').removeClass($settings.currentItem_class);
                    $suggestionsDiv.children('a').eq(itemIndex).addClass($settings.currentItem_class);
                }
            };
            // ----------------------------------------------------------------------


            // ============================================================================================
            // ============================================================================================

            // ============================================================================================
            // ============================================================================================


            // ----------------------------------------------------------------------
            function PickValue(result, isLocal) {

                var $textbox;
                var $suggestionsDiv;
                if (isLocal) {
                    $textbox = $textboxCity;
                    $suggestionsDiv = $localSuggestionsDiv;
                }
                else {
                    $textbox = $textboxName;
                    $suggestionsDiv = $nameSuggestionsDiv;
                }

                // 0. Limpar nodes existentes
                $textbox.val();
                // 1. attach de toda a informação relativa à sugestão
                $textbox.data('resultItemInfo', result);

                var line = '';
                // 1. Atribuo a descrição à textbix
                if (result.description != "") {
                    line = result.description;
                }

                $textbox.val(line);
                // 1.2. Apagar sugestões
                ClearSuggestions($suggestionsDiv);

            };
            // ----------------------------------------------------------------------



        });

    };
})(jQuery);

/* @ AUXILIAR PLUGINS
==================================================================== */

// ------------------------------------------------
(function($) {
    $.fn.highlight = function(pat) {
        function innerHighlight(node, pat) {
            var skip = 0;
            if (node.nodeType == 3) {
                var pos = node.data.toUpperCase().indexOf(pat);
                if (pos >= 0) {
                    var spannode = document.createElement('span');
                    spannode.className = 'highlight';
                    var middlebit = node.splitText(pos);
                    var endbit = middlebit.splitText(pat.length);
                    var middleclone = middlebit.cloneNode(true);
                    spannode.appendChild(middleclone);
                    middlebit.parentNode.replaceChild(spannode, middlebit);
                    skip = 1;
                }
            }
            else if (node.nodeType == 1 && node.childNodes && !/(script|style)/i.test(node.tagName)) {
                for (var i = 0; i < node.childNodes.length; ++i) {
                    i += innerHighlight(node.childNodes[i], pat);
                }
            }
            return skip;
        }
        return this.each(function() {
            innerHighlight(this, pat.toUpperCase());
        });
    };
})(jQuery);
// ------------------------------------------------







function SetupAgenciesNameFinder(_clientID, url_namesHandler, _noResultsResource, controlID, txtName) {
    $('#' + controlID).SetupAgencyNameFinder({
        maxResults: 6,
        clientID: _clientID,
        databaseHandler_URLs: {
            agencyNames: url_namesHandler
        },
        noResultsResource: _noResultsResource,
        txtName: txtName
    });
   
    var txtName = "#" +_clientID + "_" + txtName;

    var $textboxName = $(txtName);
    if (window.devicePixelRatio == 1) {
        $("#dSearchAgencies").css("margin-top", "11px !important");
    };
}

(function($) {
    $.fn.SetupAgencyNameFinder = function(pluginSettings) {

        var defaultSettings = {
            parameter: 'parameter_value',
            databaseHandler_URLs: {
                agencyNames: 'App_Handlers/Agencies/names.ashx'
            },
            queryDelay: 250, 		// milisegundos
            requestTimeout: 5000, 	//milisegundos
            mininumChars: 3, 	// valor tido em conta apenas para o primeiro request de localizações.
            maxResults: 6,
            currentItem_class: 'current',
            clientID: '',
            txtName: ''
        };
        var $settings = $.extend(defaultSettings, pluginSettings);

        return this.each(function() {



            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // INDEX

            // DECLARATIONS
            // INIT
            // TEXT INPUT
            // SUGGESTIONS
            // ============================================================================================
            // ============================================================================================
            // ============================================================================================


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ DECLARATIONS

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================
            var txtName = "#" + $settings.clientID + "_" + $settings.txtName;


            var $textboxName = $(txtName),
                $nameSuggestionsDiv = $('#dNameSuggestions', $(this)),
                $nameLoader = $('.nameLoader', $(this));

            var _delayID = -1;
            var _keyboard = { left: 37, up: 38, right: 39, down: 40, enter: 13, escape: 27, backspace: 8 };

            var currentIndex = -1;


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ INIT

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ TEXT INPUT

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // ----------------------------------------------------------------------
            // > Ao escrever na caixa de texto, solicito à BD os dados adequados
             $textboxName.keyup(function(event) {

                // 1. obter os tokens introduzidos nas textboxs
                var nameToken = $textboxName.val();

                // 2. apenas invocar a base de dados se: for um caracter válido + houverem caracteres suficientes
                if (IsIgnoredKey(event.keyCode) == false) {
                    if (HasEnoughChars(nameToken) == true) {

                        // 2.1. apresentar o loader
                        $nameLoader.show();

                        // 2.2. garantir que só são feitos pedidos à BD de x em x segundos

                        // 2.2.1. apagar possiveis timeouts a decorrer
                        if (_delayID != -1) {
                            clearTimeout(_delayID);
                        }

                        // 2.2.2 criar novo timeout
                        _delayID = setTimeout(function() {
                            RequestSuggestions(nameToken, $settings.databaseHandler_URLs.agencyNames, false);
                        }, $settings.queryDelay);

                    }
                    else {

                        // 2.3. apaga as sugestões
                        ClearSuggestions($nameSuggestionsDiv);
                    }
                }

            });
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > evita que um clique em cima da caixa de texto, faça desaparecer as sugestões
            $textboxName.click(function(event) {
                event.stopPropagation();
            });
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > verifica se existem caracteres suficientes para iniciar uma pesquisa
            function HasEnoughChars(token) {
                // 1.. ...é necessário pelo menos $settings.mininumChars caracteres
                return (token.length >= $settings.mininumChars);
             };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > verifica se determinada tecla pressionada deve ser considerada para solicitar dados à BD
            function IsIgnoredKey(nKeyCode) {
                if ((nKeyCode == 9) || (nKeyCode == 13) || // tab, enter
    			        (nKeyCode == 16) || (nKeyCode == 17) || // shift, ctl
    			        (nKeyCode >= 18 && nKeyCode <= 20) || // alt, pause/break,caps lock
    			        (nKeyCode == 27) || // esc
    			        (nKeyCode >= 33 && nKeyCode <= 35) || // page up,page down,end
                /*(nKeyCode >= 36 && nKeyCode <= 38) || // home,left,up
                (nKeyCode == 40) || // down*/
    			        (nKeyCode >= 36 && nKeyCode <= 40) || // home,left,up, right, down
    			        (nKeyCode >= 44 && nKeyCode <= 45) || // print screen,insert
    			        (nKeyCode == 224) || // print screen,insert
    			        (nKeyCode == 229) // Bug 2041973: Korean XP fires 2 keyup events, the key and 229
    			    ) {
                    return true;
                }
                return false;
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            function CloseBecauseError($textbox) {

                // 1. Limpar a textbox
                $textbox.val('');
                $textbox.attr('readonly', 'true');
                $textbox.blur();


            }
            // ----------------------------------------------------------------------


            // ============================================================================================
            // ============================================================================================
            // ============================================================================================

            // @@ SUGGESTIONS

            // ============================================================================================
            // ============================================================================================
            // ============================================================================================


            // ----------------------------------------------------------------------
            // > Pedido de sugestões à BD
            function RequestSuggestions( _nameToken, _url, isLocal) {

                var $textbox;
                var token = "";
                var $loader;
                //Se é um local, utilizar a textboxCity
                $textbox = $textboxName;
                $loader = $nameLoader;
                token = _nameToken;
              
                // 0. faço o pedido assincrono ao handler
                $.ajax({
                    type: 'GET',
                    timeout: $settings.requestTimeout,
                    url: _url,
                    processData: true,
                    data: {
                        locationToken: '',
                        nameToken: encodeURI(_nameToken),
                        maxResults: $settings.maxResults
                    },
                    dataType: 'json',
                    error: function(request, status, error) {

                        $textboxName.attr("disabled", "");
                        // 1.1. apresento o erro
                        //alert('Error: ' + status);

                        // 1.2. escondo o loader
                        $loader.hide();

                    },
                    success: function(data) {
                        $textboxName.attr("disabled", "");

                        // 2.1. carrego as sugestões
                        DisplaySuggestions(data.suggestions, token, isLocal);

                        // 2.2. escondo o loader
                        $nameLoader.hide();

                    }
                });

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Apresento as sugestões, lista de DIVs
            function DisplaySuggestions(suggestions, locationToken, isLocal) {

                // 1. Apago as sugestões que possam existir na lista
                var $suggestionsDiv;
                var $textbox;
           
                $suggestionsDiv = $nameSuggestionsDiv;
                $textbox = $textboxName;
                ClearSuggestions($suggestionsDiv);

                // 2. Se existirem sugestões a apresentar
                if (suggestions.length > 0) {

                    // 2.1 para cada uma delas
                    $.each(suggestions, function(index, results) {

                        // 2.1.1. construo a descrição a apresentar por cada sugestão, Se fizer match com a outra caixa de texto, irá ser apresentada essa informação(icone)
                        var line = results.description;


                        //if (results.match == 1) { line += ' <span class="match"></span>'; }
                        // 2.1.2. construo o objecto (sugestão) a ser adicionado à lista de sugestões
                        var linkTemplate = $('<a href="#">' + line + '</a>');

                        // 2.1.3. anexo-lhe os dados (JSON) relativos à informação que ele representa
                        linkTemplate.data('resultItemInfo', results);

                        // 2.1.4. anexo-lhe o indice da lista respectivo
                        linkTemplate.data('itemIndex', index);

                        // 2.1.5. preparo o efeito de hovering no objecto
                        linkTemplate.hover(
                            function() {

                                // 2.1.5.1. ao passar o rato por cima devo marcar o objecto como seleccionado
                                currentIndex = $(this).data("itemIndex");
                                SetSelected(currentIndex, $suggestionsDiv);
                                $textbox.blur();

                            }, function() {

                                // 2.1.5.2. ao retirar o rato de cima devo desmarcá-lo como objecto seleccionado
                                linkTemplate.removeClass($settings.currentItem_class);
                                currentIndex = -1;
                                $textbox.blur();
                            }
                        );

                        // 2.1.6. preparo o click no objecto
                        linkTemplate.click(function(event) {

                            // 2.1.6.1. chamo a função de selecção de item
                            PickValue(results, isLocal);

                            // 2.1.6.2. evito a propagação do evento
                            event.stopPropagation();
                            return false;
                        });

                        // 2.1.7. sublinho a existencia do token especificado em cada sugestão
                        linkTemplate.highlight(locationToken);

                        // 2.1.8. adiciono o objecto ao div de sugestões
                        $suggestionsDiv.append(linkTemplate);

                    });
  
                }
                else {
                    //Display none suggestions
                    var noSuggestionsFeedback = $settings.noResultsResource;

                    // 2.1.2. construo o objecto de informação da não existencia de sugestoes
                    var template = $('<a href="#">' + noSuggestionsFeedback + '</a>');
                    template.click(function(event) {
                        event.stopPropagation();
                        return false;
                    });

                    $suggestionsDiv.append(template);

                }
             

                $('body').one('click', function() {
                    ClearSuggestions($suggestionsDiv);
                });

                // 2.3. depois de preparado, mostro o div de sugestões se a caixa de texto ainda tiver o numero mínimo de caracteres
                if (HasEnoughChars($textbox.val())) {
                    $suggestionsDiv.show();
                }
                else {
                    ClearSuggestions($suggestionsDiv);
                }

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Limpa todas as sugestões activas
            function ClearSuggestions($suggestionsDiv) {

                // 1. escondo o div com as sugestões
                $suggestionsDiv.hide();

                // 2. apago o seu conteudo, para na próxima vez que for apresentado, não levar com valores obsoletos
                $suggestionsDiv.children().remove();
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Limpa a textbox
            function ClearTextbox($textbox) {

                // 1. retiro o focus da textbox, pois só assim consigo alterar o seu valor
                $textbox.blur();
                // 2. reset ao valor da textbox
                $textbox.val('');

                // 3. volto a atribuir o focus à textbox
                $textbox.focus();
            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            // > Para cada tecla 
            $(document).keydown(function(e) {

                BindKeyPress(e, false, $nameSuggestionsDiv, $textboxName);

            });
            // ----------------------------------------------------------------------

            function BindKeyPress(e, isLocal, $suggestionsDiv, $textbox) {
                var pressed = false;
                var $loader;
                $loader = $nameLoader; 
                // 1. Se estão a ser apresentadas sugestoes
                if ($suggestionsDiv.is(':visible')) {

                    switch (e.keyCode) {

                        // up arrow                                              
                        case _keyboard.up:
                            if ($loader.is(':visible')) return false;
                            Navigate('up', $suggestionsDiv, $textbox);
                            pressed = true;
                            break;

                        // down arrow                                              
                        case _keyboard.down:
                            if ($loader.is(':visible')) return false;
                            Navigate('down', $suggestionsDiv, $textbox);
                            pressed = true;
                            break;

                        // enter key                                              
                        case _keyboard.enter:
                            if ($loader.is(':visible')) return false;

                            // 1. Get location info JSON object
                            var results = $suggestionsDiv.children('a').eq(currentIndex).data('resultItemInfo');

                            // 2. Pick Location
                            if (results != undefined)
                            { PickValue(results, isLocal); }
                            pressed = true;
                            break;

                        // escape key                                              
                        case _keyboard.escape:
                            ClearSuggestions($suggestionsDiv);
                            pressed = true;
                            break;

                    }

                }

                if (pressed)
                    return false;
            }

            // ----------------------------------------------------------------------
            function Navigate(direction, $suggestionsDiv, $textbox) {

                if ($suggestionsDiv.children('a').filter('.' + $settings.currentItem_class).size() == 0) {
                    currentIndex = -1;
                }

                if (direction == 'up' && currentIndex != -1) {
                    if (currentIndex != 0) {
                        currentIndex--;
                    }
                    else {
                        $suggestionsDiv.children('a').removeClass($settings.currentItem_class);
                        $textbox.focus();
                        currentIndex = -1;
                        return;
                    }
                } else if (direction == 'down') {
                    if (currentIndex != $suggestionsDiv.children('a').size() - 1) {
                        currentIndex++;
                    }
                }

                SetSelected(currentIndex, $suggestionsDiv);

            };
            // ----------------------------------------------------------------------

            // ----------------------------------------------------------------------
            function SetSelected(itemIndex, $suggestionsDiv) {
                if (itemIndex >= 0) {
                    $suggestionsDiv.children('a').removeClass($settings.currentItem_class);
                    $suggestionsDiv.children('a').eq(itemIndex).addClass($settings.currentItem_class);
                }
            };
            // ----------------------------------------------------------------------


            // ============================================================================================
            // ============================================================================================

            // ============================================================================================
            // ============================================================================================


            // ----------------------------------------------------------------------
            function PickValue(result, isLocal) {

                var $textbox;
                var $suggestionsDiv;
                
                $textbox = $textboxName;
                $suggestionsDiv = $nameSuggestionsDiv;
                
                // 0. Limpar nodes existentes
                $textbox.val();
                // 1. attach de toda a informação relativa à sugestão
                $textbox.data('resultItemInfo', result);

                var line = '';
                // 1. Atribuo a descrição à textbix
                if (result.description != "") {
                    line = result.description;
                }

                $textbox.val(line);
                // 1.2. Apagar sugestões
                ClearSuggestions($suggestionsDiv);

            };
            // ----------------------------------------------------------------------



        });

    };
})(jQuery);


