Примеры автодополнения

Плагин Autocomplete для jQuery позволяет пользователям быстро находить и выбирать значения из предварительно заполненного списка по мере ввода, используя поиск и фильтрацию.
Примеры использования: https://jqueryui.com/autocomplete/
Подробное описание: https://api.jqueryui.com/autocomplete/
В этой статье будут приведены примеры того, как можно настроить автодополнение ввода населенных пунктов и муниципальных образований, используя связку плагина jQuery Autocomplete и сервис api.geotree.ru.

Пример 1.

Пример с минимальной функциональностью: выполняется поиск всех объектов, соответствующих запросу.
Показать исходный код с комментариями
Открыть пример на отдельной странице
<!doctype html>
<html>
<head>
  <title>GeoTree example 1</title>
  <!-- Подключаем библиотеки jQuery и jQuery UI -->
  <script src="https://files.geotree.ru/jquery/jquery-1.12.4.js"></script>
  <script src="https://files.geotree.ru/jquery/ui/1.12.1/jquery-ui.js"></script>
  <link rel="stylesheet" href="https://files.geotree.ru/jquery/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
    .ui-autocomplete-loading {
      background: white url("https://files.geotree.ru/jquery/ui/images/ui-anim_basic_16x16.gif") right center no-repeat;
    }
  </style>
  <script>
  $(function() {
    //Добавляем автодополнение к текстовому полю с идентификатором "geotree_example_1"
    $("#geotree_example_1").autocomplete({
      //При поиске к указанному адресу будет добавляться "&term=введенный текст..."
      source: "https://api.geotree.ru/search.php?",
      minLength: 0, //Минимальное количество символов, которое пользователь должен ввести перед выполнением поиска
      delay: 0, //Задержка в миллисекундах между нажатием клавиши и выполнением поиска
      select: function( event, ui ) {//Событие срабатывает при выборе элемента в меню
	    //Выбранный элемент выведем в консоль и в блок #result_1
        console.log(ui.item);
        $("#result_1").html(JSON.stringify(ui.item));
      }
	})
    .on("focus", function() { //при получении фокуса будет выполняться поиск, даже если поле пустое
		$(this).autocomplete( 'search', $(this).val());
	});
  });
  </script>
</head>
<body>
  <!-- Блок с полем для ввода -->
  <div class="ui-widget">
	<input id="geotree_example_1" style="width: 100%;" placeholder="Начните ввод текста">
  </div>
  <!-- Блок для отображения информации по выбранному элементу -->
  <div id="result_1" style="background-color: #e0e0e0; word-wrap: break-word; margin: 5px; padding: 5px;"></div>
</body>
</html>

Пример 2.

Поиск любых объектов, при этом сначала будут отображаться объекты Алтаского края (код ОКТМО 01), городского округа Горноалтайск Республики Алтай (84701) и Майминского района Республики Алтай (код 84615). При выборе элемента будет выполен разбор объекта.
Показать исходный код с комментариями
Открыть пример на отдельной странице
<!doctype html>
<html>
<head>
  <title>GeoTree example 2</title>
  <script src="https://files.geotree.ru/jquery/jquery-1.12.4.js"></script>
  <script src="https://files.geotree.ru/jquery/ui/1.12.1/jquery-ui.js"></script>
  <link rel="stylesheet" href="https://files.geotree.ru/jquery/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
    .ui-autocomplete-loading {
      background: white url("https://files.geotree.ru/jquery/ui/images/ui-anim_basic_16x16.gif") right center no-repeat;
    }
  </style>
  <script>
  $(function() {
    $("#geotree_example_2").autocomplete({
      source: "https://api.geotree.ru/search.php?oktmo_priority=01,84701,84615",
      minLength: 0,
      delay: 0,
      select: function(event, ui) {
        var info=oktmo_info(ui.item);
        $("#result_2").html(info);
      }
	})
    .on("focus", function() {
		$(this).autocomplete( 'search', $(this).val());
	});
  });
  
  // Расшифровка параметра oktmo_type (устанавливается на основе кода ОКТМО)
  var oktmo_types={
    "гфз" : "город федерального значения",
    "суб" : "субъект РФ",
    "вт" : "внутригородская территория",
    "мр" : "муниципальный район",
    "мо" : "муниципальный округ",
    "го" : "городской округ",
    "гп" : "городское поселение",
    "сп" : "сельское поселение",
    "вр" : "внутригородской район",
    "мс" : "межселенная территория",
    "г" : "город",
    "пгт" : "пгт",
    "снп" : "сельский населенный пункт"
  }
  
  //Функция, генерирующая текст с инфомрацией о выбранном объекте
  function oktmo_info( obj ) {
    console.log(obj);
    var info=row(obj);
    for(var i=obj.parent_level; i>=1; i--) {
      info+=row(obj.parents["level_"+i]);
    } 
    return info;
  }
  
  //Функция, генерирующая текст с инфомрацией о каждом уровне объека
  function row(record) {
    var text="уровень "+record["level"]+": <strong>"+record.name_display+"</strong>";
    if ("center_level" in record) {
      text+=" (центр уровня "+record["center_level"]+")";
    }
    text+=", ОКМТО: "+record.oktmo+", тип: "+oktmo_types[record.oktmo_type]+"<br>";
    return text;
  }
  </script>
</head>
<body>
  <div class="ui-widget">
	<input id="geotree_example_2" style="width: 100%;" placeholder="Начните ввод текста">
  </div>
  <!-- Блок для отображения информации по выбранному элементу -->
  <div id="result_2" style="background-color: #e0e0e0; word-wrap: break-word; margin: 5px; padding: 5px;"></div>
</body>
</html>

Пример 3.

Поиск населенных пунктов с сортировкой по расстоянию от центра Новосибирска в радиусе 50 км. Остальные населенные пункт тоже будут отображены в списке, но будут расположены ниже и отсортированы по умолчанию. Элементы списка генерируются налету и состоят из наименования, списка вышестоящих объектов, расстояния до объекта от указанной точки.
Показать исходный код с комментариями
Открыть пример на отдельной странице
<!doctype html>
<html>
<head>
  <title>GeoTree example 3</title>
  <script src="https://files.geotree.ru/jquery/jquery-1.12.4.js"></script>
  <script src="https://files.geotree.ru/jquery/ui/1.12.1/jquery-ui.js"></script>
  <link rel="stylesheet" href="https://files.geotree.ru/jquery/ui/1.12.1/themes/base/jquery-ui.css">
  <style>
    .ui-autocomplete-loading {
      background: white url("https://files.geotree.ru/jquery/ui/images/ui-anim_basic_16x16.gif") right center no-repeat;
    }
  </style>
  <script>
  $(function() {
    //Добавляем автодополнение к #geotree_example_3
    $("#geotree_example_3").autocomplete({
      //в параметрах lon и lat указываем геоточку,
	  //в distance_sort - расстояние, в пределах которого объекты будут отсортированы по расстоянию
      source: "https://api.geotree.ru/search.php?level=4&lon=82.92&lat=55.03&distance_sort=50",
      minLength: 0,
      delay: 0,
      select: function( event, ui ) {
        console.log(ui.item);
        $("#result_3").html(JSON.stringify(ui.item));
      }
	})
    .on("focus", function() {
		$(this).autocomplete( 'search', $(this).val());
	})
	//Метод, управляющий созданием элементов списка
	.autocomplete( "instance" )._renderItem = function( ul, item ) {
      return $( "<li>" )
        .append( item_html(item) )
        .appendTo( ul );
    };
  });
  //Функция, генерирующая html-код элемента списка
  function item_html (item) {
    var label = item["name_display"];//наименование объекта
    var desc=""; //описание объекта
	//информация о субъекте РФ (уровень 1)
    if (item["level"] > 1) {
      desc=item["parents"]["level_1"]["name_display"];
    } else if (item["oktmo_type"]=="гфз") {
      desc="город федерального значения";
    }
	//информация об уровне 2 (район, городской или муниципальном округ, территория города федерального значения)
    if (item["level"] > 2 &&
	  //не будем указывать наименование районов/округов для их центров,
	  //если наименования центра и района/округа совпадают и у центра нет тёзки в этом же районе/округе
	  //пример: для города Иркутска не будет указано, что он находится в городском округе Иркутск
      !(item["name_without_type"]==item["parents"]["level_2"]["name_without_type"] && item["center_level"] <= 2 && item["unique_display"] < 2)
    ) {
      desc+=", "+item["parents"]["level_2"]["name_display"];
    }
   //Наименование сельского или городского поселения будет указано только в том случае,
   //если у населенного пункта есть тёзки в этом же районе/городском округе
   //Пример: в Татарском районе Новосибирской области есть две деревни "Рождественка":
   //в Увальском сельсовете и в Северотатарском сельсовете
   if (item["level"] > 3 && item["unique_display"] > 2 && ("level_3" in item["parents"])) {
      label+=" ("+item["parents"]["level_3"]["name_display"]+")";
    }
    item["value"]=item["name_display"]; //значение, которое будет отображено в текстовом поле после выбора элемента
    desc+=" <i>"+distance_show(item["distance"])+"</i>"; //информация о расстоянии до объекта
	return "<div><strong>" + label + "</strong><br><span style='color: #808080'>" + desc + "</span></div>";
  }
  
  //Функция distance_show преобразует расстояние в метрах для удобного отображения:
  //Пример: вместо "3212345 метров" будет отображено "3.2 тыс.км"
  function distance_show(m) {
    if (m==0) {
      return "";
    }
    if (m<1000) {
      return "("+m+" м)";
    }
    if (m<10000) {
      return "("+(Math.round(m/100)/10)+" км)";
    }
    if (m<1000000) {
      return "("+(Math.round(m/1000))+" км)";
    }
    return "("+(Math.round(m/100000)/10)+" тыс.км)";
  }
  </script>
</head>
<body>
  <div class="ui-widget">
	<input id="geotree_example_3" style="width: 100%;" placeholder="Начните ввод текста">
  </div>
  <!-- Блок для отображения информации по выбранному элементу -->
  <div id="result_3" style="background-color: #e0e0e0; word-wrap: break-word; margin: 5px; padding: 5px;"></div>
</body>
</html>