/**
 * @include  "d:/www/_common/js/js_common.js"
 * @include  "d:/www/_common/js/ajaqs_sender.js"
 * @include  "d:/www/_common/js/events.js"
 */

/**
 * @class
 * 
 * @type suggester_class
 */
var oSGST = new suggester_class();

/**
 * @class
 * класс-саггестер
 */
function suggester_class()
{
	/**
	 * массив в котором хранится ответ сервера
	 * @type Array
	 */
  	var aAnswerItems = [];

	/**
	 * URL сценария PHP, который возвращает подсказки для ключевого слова
	 * @type String
	 */
 	var cResponseURL = "";

	/**
	 * завершение URL'а, который возвращает подсказки для ключевого слова
	 * @type String
	 * */
	var cResponseURLEnd = '';

	/**
	 * ключевое слово, которым был инициирован запрос HTTP
	 * @type String
	 */
	var cHTTPRequestKeyword = "";

	/**
	 * последнее ключевое слово, для которого были получены подсказки
	 * @type String
	 */
	var cUserKeyword = "";

	/**
	 * количество принятых подсказок для ключевого слова
	 * @type Number
	 */
	var nCount = 0;

	/**
	 * максимальное число отображаемых символов в подсказке
	 * @type Number	
	 */
	var nMaxLen = 30;

	/**
	 * признак того, что нажимались курсорные клавиши "вверх" или "вниз", 
	 * когда последний раз возникало событие KEYUP
	 * @type Boolean
	 */
	var isKeyUpDownPressed = false;

	/**
	 * последняя подсказка, которая была использована для автодополнения
	 * @type String
	 */
	var cAutoCompletedKeyword = "";

	/**
	 * признак того, что для заданного ключевого слова был получен 
	 * не пустой список подсказок
	 * @type Boolean
	 */
	var hasResults = false;

	/**
	 * идентификатор, использовавшийся для операции отмены с помощью метода clearTimeout
	 * @type Number
	 */
	var nTimeoutId = -1;

	/**
	 * позиция текущей выбранной подсказки (клавишами или мышкой)
	 * @type Number
	 */
	var nPos = -1;

	/**
	 * @private
	 * буферный объект, который содержит принятые подсказки для различных ключевых слов
	 * @type Object
	 */
	var sgst_Cache = {};

	/**
	 * минимальная позиция видимых подсказок
	 * @type Number
	 */
	var nMinVisPos = 0;

	/**
	 * максимальная позиция видимых подсказок
	 * @type Number
	 */
	var nMaxVisPos = 9;

	/**
	 * @type boolean
	 * если имеет значение TRUE - выводятся подробные сообщения об ошибках
	 * @type Boolean
	 * */
	var lDebugMode = true;

	/**
	 * текст, который выводится, когда подсказок нет
	 * @type String
	 */
	var cNotFoundMSG = 'Нет улиц начинающихся с';

	/**
	 * ссылка на функцию, которая будет выполнена после выбора элемента пользователем
	 * @type function
	 */
	var fJSAction = null;

	/**
	 * ссылка на функцию, которая будет формировать текст подсказки
	 * если не задана - используется стандартная
	 * в качестве параметра получает объект для текущей подсказки
	 * @type function
	 */
	var fMakeItemName = null;
	
	/**
	 * список полей через запятую
	 * @type String
	 */
	var aFields = '';

	/**
	 * флаг, если TRUE - значит к подсказкамх есть TITLE
	 * @type Boolean
	 */
	var lTitleNeed = false;

	/**
	 * ID объекта keyword - в нем юзер набирает ключевое слово
	 * @type String
	 */
	var cKeywordID = 'txtKeyword';

	/**
	 * ID элемента в который будет осуществляеться переход после выбора элемента
	 * @type String
	 */
	var cAutoFocusID = '';
	
	/**
	 * ссылка на объект keyword - в нем юзер набирает ключевое слово
	 * @type HTMLInputElement
	 */
	var oKeyword = null;

	/**
	 * ID объекта suggest - в нем идут подсказки
	 * @type String
	 * */
	var cSuggestID = 'streets_suggest';

	/**
	 * ссылка на объект suggest - в нем идут подсказки
	 * @type HTMLElement
	 */
	var oSuggest = null;

	/**
	 * ID объекта scroll - он занимается скроллингом списка подсказок
	 * @type String
	 */
	var cScrollID = 'streets_scroll';

	/**
	 * ID UL-элемента
	 * @type String
	 */
	var cListID = 'streets_list';

	/**
	 * ссылка на объект scroll - он занимается сколлингом списка подсказок
	 * @type HTMLElement
	 */
	var oScroll = null;

	/**
	 * на сколько скроллить список при нажатии клавиш "вверх" и "вниз"
	 * @type Number
	 */
	var nScrollSize = 18;

	/**
	 * имя CSS класса, которым подсвечивается активная подсказка
	 * @type String
	 */
	var cHLClass = "highlightrow";

	/**
	 * имя префикса для ID элементов списка
	 * @type String
	 */
	var cLiPrefix = 'tr';

	/**
	 * имя префикса для ID ссылок в списке
	 * @type String
	 */
	var cAPrefix = 'a';

	/**
	 * поиск начнется только если длина слова не меньше этого значения
	 * @type Number
	 */
	var nMinLenRun = 2;

	/**
	 * поиск начнется только если длина слова не больше этого значения
	 * @type Number
	 */
	var nMaxLenRun = 4;

	/**
	 * подготовка заггестера к работе 
	 *  
	 * @param {init_obj/Object} toInit - объект с параметрами для запуска 
	 * @param {Boolean} tlFocus - если TRUE, то при запуске автофокус в поле ввода саггестера 
	 * @param {Boolean} tlClear - если TRUE, то при запускеполе ввода саггестера очищается
	 * @return void
	 */
	this.run = function(toInit, tlFocus, tlClear)
	{
		cKeywordID = toInit.KeywordID;
		cSuggestID = toInit.SuggestID;
		cScrollID  = toInit.ScrollID;
		cListID    = toInit.ListID;

		cHLClass   = toInit.HLClass;
		cLiPrefix  = toInit.LiPrefix;
		cAPrefix   = toInit.APrefix;

		oKeyword = id(cKeywordID);
		oSuggest = id(cSuggestID);
		oScroll  = id(cScrollID);

	    if (! oScroll)
	    {
	        oScroll = dce('div');
	        oScroll.id = cScrollID;

	        oSuggest = dce('div');
	        oSuggest.id = cSuggestID;

	        oScroll.appendChild(oSuggest);
	        oKeyword.parentNode.appendChild(oScroll);

	        oSuggest = id(cSuggestID);
	        oScroll  = id(cScrollID);
	    }

        if (! oKeyword) { alert('Указан несуществующий элемент - ' + cKeywordID); return false; }
	    if (! oScroll) { alert('Указан несуществующий элемент - ' + cScrollID); return false; }

		nMinLenRun = toInit.MinLenRun;
		nMaxLenRun = toInit.MaxLenRun;

		cNotFoundMSG = toInit.NotFoundMSG;
		cResponseURL = toInit.ResponseURL;

		cAutoFocusID = toInit.AutoFocusID;

		if (toInit.JSAction) fJSAction = toInit.JSAction;
		if (toInit.MakeItemName) fMakeItemName = toInit.MakeItemName;

		//	подгоняем ширину контейнера в котором будут подсказки под ширину поля ввода
		oScroll.style.width = parseInt(oKeyword.clientWidth - 10) + 'px';

		oKeyword.setAttribute("autocomplete", "off");  // отключить функцию автодополнения браузера
		oKeyword.onkeyup = _HandleKeyUp;
		oKeyword.readOnly = false;

		if (tlClear) oKeyword.value = "";    // очистить поле ввода ключевого слова и установить на него фокус ввода
		if (tlFocus) oKeyword.focus();

		setTimeout(function() { _CheckForChanges() }, 500);
	}

	/**
	 * периодически проверяет, изменилось ли ключевое слово
	 *
	 * @return void
	 */
	function _CheckForChanges()
	{
		var lcKeyword = oKeyword.value;   // получить ключевое слово
		if (lcKeyword == "")   // проверить - есть ли что-нибудь в поле ввода
		{
			_Hide();  				// скрыть список с подсказками
			cUserKeyword = "";		// сбросить ключевое слово
			cHTTPRequestKeyword = "";
		}

		setTimeout(function() { _CheckForChanges() }, 500);

		// проверить было ли изменено ключевое слово
		if (lcKeyword!=''  &&  (cUserKeyword!=lcKeyword  &&  lcKeyword.length >= nMinLenRun 
		    &&   lcKeyword.length <= nMaxLenRun)  &&  (cAutoCompletedKeyword != lcKeyword) 
		    && (!isKeyUpDownPressed))
		{
			_GetSuggestions(lcKeyword);    //  обновить список подсказок
			oKeyword.readOnly = true;
		}
	}

	/**
	 * @private
	 * инициирует запрос HTTP для получения подсказок к текущему ключевому слову
	 *
	 * @param {String} lcKeyWord - строчка которую будем спрашивать у сервера
	 * @return void
	 */
	function _GetSuggestions(lcKeyWord)
	{
		if(lcKeyWord !=""  &&  !isKeyUpDownPressed)
		{
			if(oAjax.xmlHTTP)
			{
				/* если объект XMLHttpRequest не занят обработкой предыдущего запроса... */
				if (oAjax.xmlHTTP.readyState==4  ||  oAjax.xmlHTTP.readyState==0)
				{
					cHTTPRequestKeyword = lcKeyWord;
					cUserKeyword = lcKeyWord;
					oAjax.start(cResponseURL, _UpdateSuggestions, cKeywordID, true);
				}
				else    // если объект XMLHttpRequest занят...
						/**
						 * @tga
						 * может забить и не ставить в очередь?
						 */
				{
					cUserKeyword = lcKeyWord;  // сохранить ключевое слово, введенное пользователем
					if(nTimeoutId != -1) clearTimeout(nTimeoutId); // сбросить все ранее уствновленные таймауты
					nTimeoutId = setTimeout(function() { _GetSuggestions(cUserKeyword) }, 500);
				}
			}
		}
	}

	/**
	 * @private
	 * обрабатывает ответ сервера (oAjax - вызывает ее)
	 * 
	 * @return void
	 */
	function _UpdateSuggestions()
	{
		// ошибка сервера?
	    if (!oAjax.responseObj) { alert(oAjax.responseText); return false; }

	    if (oAjax.responseObj.result != 'Error')
	    {
	        if (oAjax.responseObj.result == 'Ok')  // проверить найдена ли хоть одна подсказка по нашему запросу
	            _getItemsFromCSV(); // извлечь имена подсказок в виде массива (а также их ID)

	        if (cHTTPRequestKeyword == cUserKeyword)   //  определить - это ли слово ищет юзер
	            _DisplayResults(cHTTPRequestKeyword);  // отобразить массив результатов
	    }
	    else alert(oAjax.responseObj.error);

	    oKeyword.onkeyup = _HandleKeyUp;
	    oKeyword.readOnly = false;
	    return true;
	}

	/**
	 * получает ответ из CSV и загружает его в массив
	 * 
	 * @param {String} tcCSV - строка которую разберем и превратим в массив
	 * @return {Array} - массив с названиями элементов
	  */
	function _getItemsFromCSV(tcCSV)
	{
	    var laCSV = oAjax.responseObj.rows.split('|');
	    aFields = oAjax.responseObj.fields.split(';');

	    lTitleNeed = (oAjax.responseObj.fields.indexOf('title')) ? true : false;

	    aAnswerItems = new Array();

	    for (var i=0; i < laCSV.length; i++)
	    {
	        var laCur = laCSV[i].split(';');

	        aAnswerItems[i] = new Object();

	        for (var j=0; j < aFields.length; j++)
	        {
	            var lcF = aFields[j];
	            aAnswerItems[i][lcF] = laCur[j];
	        }
	    }

	    nCount = laCSV.length;
	}

	/**
	 * @private
	 * заполняет список подсказками
	 *
	 * @param {String} tcKeyWord - слово по которому искали
	 * @return void
	 */
	function _DisplayResults(tcKeyWord)
	{
	    if (nCount == 0)   // если массив результатов пуст - вывести вообщение
	    {
	    	var loDiv = dce('p');

	        //  если сервер дал мессадж о том что ничего не найдено - показываем его
	        if (oAjax.responseObj.message  &&  oAjax.responseObj.message!='') loDiv.innerHTML = oAjax.responseObj.message;
	        //  иначен показываем свой
	        else loDiv.innerHTML = cNotFoundMSG +" <strong>" + tcKeyWord + "</strong>";
	        hasResults = false;     //  установить флаг, что ничего не было найдено
	    }

	    else    //  вывести результаты
	    {
	    	var loDiv = dce('ul');
	    	loDiv.id = cListID;

	        nPos = -1;						// сбросить индекс выбранной подсказки
	        isKeyUpDownPressed = false;	// сбросить признак нажатия на клавишу "вверх" или "вниз"
	        hasResults = true;				// установить флаг, что для данного ключевого слова имеются результаты

	        // обойти результаты в цикле и сгенерировать список результатов в формате HTML
	        for (var i=0; i < nCount; i++)
	        {
	            loDiv.appendChild(_makeSuggestItem(i));
	        }
	    }

	    oScroll.scrollTop = 0;      // прокрутить в начало списка
	    oSuggest.appendChild(loDiv);
	    oScroll.style.display = "block";

	    if (nCount > 0) _AutocompleteKeyword();     // если результаты были получены, дополняем ключевое слово
	}
	
	/**
	 * @private
	 * создает элемент списка с подсказкой
	 * 
	 * @param {Number} tnPos - положение подсказки в списке
	 * @return {HTMLLIElement} - элемент-списка
	 */
	function _makeSuggestItem(tnPos)
	{
		var lcHelpText = (fMakeItemName) ? fMakeItemName.call(this, aAnswerItems[tnPos]) : _GetItemName(tnPos);     // получить имя подсказки

		var loLI = dce('li');
		loLI.id = cLiPrefix + tnPos;
		loLI.onmouseover = _sgst_MouseOver;
		loLI.onmouseout  = _sgst_MouseOut;

		var loA = dce('a');
		loA.id = cAPrefix +tnPos;
		loA.href = 'javascript:fe();';

		if (fJSAction) loA.onclick = fJSAction;
		else loA.onclick = _sgst_AutoClick;
		loA.innerHTML = _makeItemName(lcHelpText);

		loLI.appendChild(loA);

		return loLI;
	}

	/**
	 * возвращает текст подсказки по ее позиции в массиве
	 *
	 * @param {Number} tnPos - позиция в массиве подсказок
	 * @return {String} - текст подсказки
	 */
	function _GetItemName(tnPos)
	{
	    var lcRet = aAnswerItems[tnPos].name;
	    if (aAnswerItems[tnPos].title)
	    	lcRet = lcRet +' /'+ aAnswerItems[tnPos].title +'/';
 
	    return lcRet;
	}

	/**
	 * @private
	 * выделяет полужирным текст подсказки который совпадает с введенным текстом
	 * 
	 * @param {String} tcHelpText - текст подсказки
	 * @return {String} - текст подсказки с выделением
	 */
	function _makeItemName(tcHelpText)
	{
        if (tcHelpText.length <= nMaxLen)
        {
            // выделить жирным шрифтом часть подсказки, которая совпадает с ключевым словом
            var lcRet = '<strong>' + tcHelpText.substring(0, cHTTPRequestKeyword.length) + '</strong>';
            lcRet += tcHelpText.substring(cHTTPRequestKeyword.length, tcHelpText.length);
        }
        else	//	еще никогда не было
        {
            // проверить, не превышает ли длина ключевого слова максимального количества символов, которые могут быть отображены 
            if(cHTTPRequestKeyword.length < nMaxLen)
            {
              // выделить жирным шрифтом часть подсказки, которая совпадает с ключевым словом 
                var lcRet = '<strong>' + tcHelpText.substring(0, cHTTPRequestKeyword.length) + '</strong>';
                lcRet += tcHelpText.substring(cHTTPRequestKeyword.length, nMaxLen);
            }
            else var lcRet = '<strong>' + tcHelpText + '</strong>';	// выделить жирным всю подсказку
        }

        return lcRet;
	}

	/**
	 * обрабатывает событие нажатия на клавиши
	 *
	 * @param {Event} e  - ссылка на событие
	 * @return void
	 */
	function _HandleKeyUp(e)
	{
	    e = (e) ? e : window.event;    // получить ссылку на событие
	    var target = (!e.target) ? e.srcElement : e.target; // получить ссылку на приемник события
	    if (target.nodeType == 3) target = target.parentNode;

	    // получить код символа нажатой клавиши
	    var code = (e.charCode) ? e.charCode : ((e.keyCode) ? e.keyCode : ((e.which) ? e.which : 0));
	
	    if (e.type == "keyup")  // убедиться, что получено событие KEYUP
	    {
	        isKeyUpDownPressed = false;
	        // проверить, нажата ли клавиша, которая нас интересует
	        if ((code < 13 && code != 8) || (code >=14 && code < 32) || (code >= 33 && code <= 46 && code != 38 && code != 40) || (code >= 112 && code <= 123))
	        {
	            // просто игнорировать клавиши, которые нас не интересуют
	        }
	        else
	        {
	            if (code == 13)  // если нажата клавиша Enter, перейти на страницу с описанием текущей функции
	            {
	                if(nPos >= 0)   // проверить, выбрана ли какая-нибудь подсказка
	                {
	                	if (fJSAction) fJSAction.call(this, e);
	                	else _sgst_AutoSelect(nPos, aAnswerItems[nPos].id);

	                    isKeyUpDownPressed = true;
	                }
	            }

	            if (code == 40) //  если нажата клавиша "вниз", перейти к следующей подсказке
	            {
	                var newTR = id(cLiPrefix + (++ nPos));
	                var oldTR = id(cLiPrefix + (-- nPos));

	                if (nPos>=0  &&  nPos < (nCount - 1)) oldTR.className = ""; // снять выделение с прежней подсказки

	                if (nPos < (nCount - 1))  // выделить новую подсказку и обновить ключевое слово
	                {
	                    newTR.className = cHLClass;
	                    nPos++;
	                }

	                isKeyUpDownPressed = true;
	
	                if (nPos > nMaxVisPos)   // прокрутить вниз, если подсказка за пределами окна
	                {
	                    oScroll.scrollTop += nScrollSize;
	                    nMaxVisPos++;
	                    nMinVisPos++;
	                }
	            }

	            if (code == 38)    // если была нажата клавиша "вверх", перейти к предыдущей подсказке
	            {
	                var newTR = id(sgst_LiPrefix + (--sgst_Pos));
	                var oldTR = id(sgst_LiPrefix + (++sgst_Pos));

	                if (nPos>=0 && nPos <= nCount - 1) oldTR.className = "";    // снять выделение с прежней подсказки

	                if (nPos > 0)    //  выделить новую подсказку и обновить ключевое слово
	                {
	                    newTR.className = cHLClass;
	                    nPos--;
	                    if (nPos < nMinVisPos)  //  прокрутить вверх, если подсказка за пределами окна
	                    {
	                        oScroll.scrollTop -= nScrollSize;
	                        nMaxVisPos--;
	                        nMinVisPos--;
	                    }
	                }
	                if (nPos == 0) nPos--;
	                isKeyUpDownPressed = true;
	            }
	        }

	        if (isKeyUpDownPressed)
	        {
	            //  если нажималась нужная нам кнопка - предотвращаем дальнейшие действия
	            stopDefault(e);
	            stopBubble(e);
	        }
	    }
	}

	/**
	 * @private
	 * выполняется автоматом (если не указано что-то иное)
	 *
	 * @param {Number} tnPos - позиция выбранной подсказки в массиве подсказок возвращенных сервером
	 * @param {Number} tnID - числовой ID выбранного объекта
	 */
	function _sgst_AutoSelect(tnPos, tnID)
	{
	    try
	    {
	    	var lcName = aAnswerItems[tnPos].name;
	        if (lcName  &&  lcName!='') oKeyword.value = aAnswerItems[tnPos].name;    //  пишем подсказку в текстовое поле
	    }
	    catch (e) {};	//	пустой обработчик исключения

	    var loIDField = id(cKeywordID + 'ID');  //  пытаемся найти скрытое поле, в которое нужно записать ID подсказки
	    if (loIDField) loIDField.value= tnID;       //  если такое поле нашли - записываем туда ID подсказки

	    oKeyword.onkeyup = null;

	    if (cAutoFocusID  &&  cAutoFocusID!='')
	    {
	    	var loAuto = id(cAutoFocusID)
	    	if (loAuto) loAuto.focus();
	    }

	    _Hide();

	    return false;
	}

	/**
	 * @private
	 * если не задана другая функция, то эта будет обрабатывать 
	 * клик мышкой по подсказке
	 * 
	 * @param {Event} e - ссылка на объект-событие
	 * @return {Boolean} - всегда FALSE
	 */
	function _sgst_AutoClick(e)
	{
		e = e || window.event;
		var loLink = e.target || e.srcElement;

		while(loLink.tagName != 'LI') loLink = loLink.parentNode;

		nPos = parseInt(loLink.id.replace(cLiPrefix, ''));

		var lnItemID = aAnswerItems[nPos].id;

		_sgst_AutoSelect(nPos, lnItemID);

        stopDefault(e);
        stopBubble(e);
		return false;
	}

	/**
	 * снимает выделение со всех подсказок
	 *
	 * @return void
	 */
	function _DeselectAll()
	{
		for (var i=0; i < nCount; i++) id(cLiPrefix + i).className = "";
	}

	/**
	 * @private
	 * обрабатывает перемещение указателя мыши по списку подсказок
	 *
	 * @param {Event} e - ссылка на объект-событие
	 * @return void
	 */
	function _sgst_MouseOver(e)
	{
		_DeselectAll();

		e = e || window.event;
    	var oTr = e.target || e.srcElement;
    	while(oTr.tagName != 'LI') oTr = oTr.parentNode;

		oTr.className = cHLClass;
		nPos = oTr.id.substring(cLiPrefix.length, oTr.id.length);
	}

	/**
	 * @private
	 * обрабатывает выход указателя мыши за пределы списка с подсказками
	 *
	 * @param {Event} e - ссылка на объект-событие
	 * @return void
	 */
	function _sgst_MouseOut(e)
	{
		e = e || window.event;
    	var oTr = e.target || e.srcElement;
    	while(oTr.tagName != 'LI') oTr = oTr.parentNode;

		oTr.className = "";
		nPos = -1;
	}

	/**
	 * скрывает слой, содержащий подсказки
	 *
	 * @return void
	 */
	function _Hide()
	{
		if (oScroll) oScroll.style.display = "none";
	}

	/**
	 * @private
	 * suggester_class::selectRange() - выделяет диапазон в текстовом элементе, ссылка на который передается в качестве аргумента
	 *
	 * @param HTMLobject oText - объект-текст
	 * @param integer start - начало выделения
	 * @param integer length - длина выделения
	 * @return void
	 */
	function _SelectRange(oText, start, length)
	{
	  // проверить тип браузера IE или FF
		if (oText.createTextRange)
		{
			//  IE
			var oRange = oText.createTextRange();
			oRange.moveStart("character", start);
			oRange.moveEnd("character", length - oText.value.length);
			oRange.select();
		}
		else    // FF
		{
			if (oText.setSelectionRange) oText.setSelectionRange(start, length);
		}
		oText.focus();
	}

	/**
	 * дополняет введенное слово
	 * 
	 * @return void
	 */
	function _AutocompleteKeyword()
	{
		nPos = 0;     // сбросить позицию выделенной подсказки
		_DeselectAll();      // снять выделение со всех подсказок
		id(cLiPrefix + "0").className = cHLClass;     //  подсветить выбранную подсказку
		_SelectRange(oKeyword, cHTTPRequestKeyword.length, oKeyword.value.length);        // выделить часть, которая была дополнена
		cAutoCompletedKeyword = oKeyword.value;        // запомнить полное ключевое слово вместе с дополненной частью
	}
/**
 * конец класса
 */
}

/**
 * @type class
 * пример объекта, который передается методу suggester_class::Run()
 */
var init_obj =
{
	KeywordID : '',
	SuggestID : '',
	ScrollID : '',
	ListID : '',
	AutoFocusID: '',
	HLClass : '',
	LiPrefix : '',
	APrefix : '',
	MinLenRun : 2,
	MaxLenRun : 5,
	NotFoundMSG : 'Нет объектов начинающихся с ',
	ResponseURL : '',
	JSAction : null,
	MakeItemName: null
};

/**
 * @deprecated
 * пример функции обрабатывающие клик на подскаке в саггестере
 * 
 * @param {Event} e - ссылка на объект событие
 * @return {Boolean} - всегда FALSE
 */
function __sgst_test_clicker(e)
{
	e = e || window.event;
	var loLink = e.target || e.srcElement;
	alert(loLink.innerHTML + '\n' + loLink.id);
	return false;
}


/**
 * @deprecated
 * пример функции формирующей текст подсказки
 * можно передавать анонимную функцию 
 *
 * @param {Object} toI - объект с подсказками
 * @return {String} - текст подсказки
 */
function makeCityName(toI)
{
   	return toI.name + ' ('+ toI.title +')';
}
