Делаем форму для ввода адреса

от автора

Сегодня, в день релиза нового jQuery плагина для сервиса КЛАДР в облаке, я хочу показать как можно быстро сделать форму для ввода адреса с автодополнением и валидацией.


Для нетерпеливых: исходный код формы можно посмотреть на гитхабе. Для запуска примера вам достаточно скачать его в zip и открыть страницу с примером в браузере.

Несколько слов о плагине и реализованных фичах:

  • Мы избавились от использования jquery.ui.autocomplete. Теперь плагин суммарно весит 13 Кбайт и не требует никаких дополнительных библиотек, кроме непосредственно jQuery.
  • Плагин теперь состоит из 2 отдельных частей: библиотеки для выполнения запросов к сервису (гитхаб) и собственно самого плагина для автодополнения (гитхаб). Это даёт возможность в случае необходимости использовать их отдельно.
  • В плагине для автодополнения мы постарались реализовать весь необходимый функционал: проверку корректности введенного адреса, ajax-крутилку.

Теперь после небольшого резюме нововведений предлагаю вернуться к форме. Начнём с подключения необходимых библиотек.

<link href="../jquery.kladr.min.css" rel="stylesheet"> <link href="css/example5.css" rel="stylesheet">  <script src="js/lib/jquery-1.10.2.min.js" type="text/javascript"></script> <script src="../jquery.kladr.min.js" type="text/javascript"></script> <script src="js/example5.js" type="text/javascript"></script> 

Так как целью данного поста является не стилевое оформление форм сразу приведу код html и css

HTML

<!DOCTYPE html> <html>     <head>         <meta http-equiv="content-type" content="text/html; charset=utf-8">         <title>Форма для ввода адреса</title>          <link href="../jquery.kladr.min.css" rel="stylesheet">         <link href="css/example5.css" rel="stylesheet">          <script src="js/lib/jquery-1.10.2.min.js" type="text/javascript"></script>         <script src="../jquery.kladr.min.js" type="text/javascript"></script>         <script src="js/example5.js" type="text/javascript"></script>     </head>     <body>         <form>             <div class="field">                 <label>Регион</label>                 <input type="text" name="region">             </div>             <div class="field">                 <label>Район</label>                 <input type="text" name="district">             </div>             <div class="field">                 <label>Город</label>                 <input type="text" name="city">             </div>             <div class="field">                 <label>Улица</label>                 <input type="text" name="street">             </div>             <div class="field">                 <label>Дом</label>                 <input type="text" name="building">             </div>             <div class="tooltip" style="display: none;"><b></b><span></span></div>         </form>     </body> </html> 

CSS

body, input {     color: #555;     font-size: 13px;     font-family: Helvetica, Arial, sans-serif; } form {     width: 300px;     margin: 40px auto 0;     padding: 20px 20px 10px;     border-radius: 5px;     border: 1px solid #e1e1e8;     background-color: #f7f7f9;     box-shadow: rgba(0,0,0,0.075) 2px 3px 7px; } input, button {     outline: none; } .field label {     display: inline-block;     width: 80px;     vertical-align: middle; } .field {     margin-bottom: 10px;     padding: 0; } .field input {     height: 2em;     min-width: 196px;     border-radius: 3px;     border: 1px solid #d3d3d3;     box-shadow: inset 0 1px 1px rgba(0,0,0,0.1);     padding: 0 7px;     color: #666; } .tooltip {     position: absolute;     top: 16px;     left: 360px;     width: 220px;     color: #b94a48;     padding: 8px 10px;     border-radius: 5px;     border: 1px solid #eed3d7;     background-color: #f2dede;     opacity: 0.8; } .tooltip b {     position: absolute;     display: block;     left: -14px;     width: 0;     height: 0;     color: transparent;     border: 7px solid;     border-right-color: #f2dede; } #kladr_autocomplete ul {     border-radius: 4px;     border-color: #d3d3d3;     padding: 0;     background-color: #fff; } #kladr_autocomplete li {     padding: 6px 8px;     border: none;     border-bottom: 1px solid #ededed;     background-color: transparent; } #kladr_autocomplete ul .active {     border: none;     border-bottom: 1px solid  #f0f0f0;     background-color: #f0f0f0;     margin-top: -1px;     padding-top: 7px; } #kladr_autocomplete ul li:first-child.active {     padding-top: 6px;     margin-top: 0; } #kladr_autocomplete li strong {     color: #5499BB; } #kladr_autocomplete .spinner {     background-image: url("../img/spinner.png");     width: 16px;     height: 16px; } 

В итоге у нас получается вот такая вот форма.

Осталось сделать автодополнение с валидацией.
Открываем example5.js.
Сохраняем токен, ключ и объекты, которыми будем манипулировать в виде переменных.

$(function() {     var token = '51dfe5d42fb2b43e3300006e';     var key   = '86a2c2a06f1b2451a87d05512cc2c3edfdf41969';      var region   = $('[name="region"]');     var district = $('[name="district"]');     var city     = $('[name="city"]');     var street   = $('[name="street"]');     var building = $('[name="building"]'); }); 

Теперь чтобы подключить автодополнение из сервиса, нам в простейшем варианте нужно написать следующее.

region.kladr({     token: token,     key: key,     type: $.kladr.type.region });  district.kladr({     token: token,     key: key,     type: $.kladr.type.district });  city.kladr({     token: token,     key: key,     type: $.kladr.type.city });  street.kladr({     token: token,     key: key,     type: $.kladr.type.street });  building.kladr({     token: token,     key: key,     type: $.kladr.type.building }); 

Для того чтобы автодополнение районов выполнялось из выбранного региона и т.д. задаём родительский объект для нижестоящих полей при выборе элемента в списке.

region.kladr({     select: function(obj) {         region.parent().find('label').text(obj.type);         district.kladr('parentType', $.kladr.type.region);         district.kladr('parentId', obj.id);         city.kladr('parentType', $.kladr.type.region);         city.kladr('parentId', obj.id);     } });  district.kladr({     select: function(obj) {         district.parent().find('label').text(obj.type);         city.kladr('parentType', $.kladr.type.district);         city.kladr('parentId', obj.id);     } });  city.kladr({     select: function(obj) {         city.parent().find('label').text(obj.type);         street.kladr('parentType', $.kladr.type.city);         street.kladr('parentId', obj.id);         building.kladr('parentType', $.kladr.type.city);         building.kladr('parentId', obj.id);     } });  street.kladr({     select: function(obj) {         street.parent().find('label').text(obj.type);         building.kladr('parentType', $.kladr.type.street);         building.kladr('parentId', obj.id);     } });  building.kladr({     select: function(obj) {         building.parent().find('label').text(obj.type);     } }); 

Сделаем проверку введенных данных (на случай если пользователь не будет выбирать название в списке, а введёт его вручную).

var tooltip  = $('.tooltip');  var ShowError = function(input, message){     tooltip.find('span').text(message);      var inputOffset = input.offset();     var inputWidth  = input.outerWidth();     var inputHeight = input.outerHeight();      var tooltipHeight = tooltip.outerHeight();      tooltip.css({         left: (inputOffset.left + inputWidth + 10) + 'px',         top: (inputOffset.top + (inputHeight - tooltipHeight)/2 - 1) + 'px'     });      tooltip.show(); };  region.kladr({     verify: true,     check: function(obj) {         if(obj){             region.parent().find('label').text(obj.type);             district.kladr('parentType', $.kladr.type.region);             district.kladr('parentId', obj.id);             city.kladr('parentType', $.kladr.type.region);             city.kladr('parentId', obj.id);         } else {             ShowError(region, 'Неверно введено название региона');         }     } });  district.kladr({     verify: true,     check: function(obj) {         if(obj){             district.parent().find('label').text(obj.type);             city.kladr('parentType', $.kladr.type.district);             city.kladr('parentId', obj.id);         } else {             ShowError(district, 'Неверно введено название района');         }     } });  city.kladr({     verify: true,     check: function(obj) {         if(obj){             city.parent().find('label').text(obj.type);             street.kladr('parentType', $.kladr.type.city);             street.kladr('parentId', obj.id);             building.kladr('parentType', $.kladr.type.city);             building.kladr('parentId', obj.id);         } else {             ShowError(city, 'Неверно введено название населённого пункта');         }     } });  street.kladr({     verify: true,     check: function(obj) {         if(obj){             street.parent().find('label').text(obj.type);             building.kladr('parentType', $.kladr.type.street);             building.kladr('parentId', obj.id);         } else {             ShowError(street, 'Неверно введено название улицы');         }     } }); 

Ну и последний штрих: сделаем чтобы пункты в списке автодополнения регионов и районов форматировались в стиле «Московская обл.»

var LabelFormat = function( obj, query ){     var label = '';      var name = obj.name.toLowerCase();     query = query.toLowerCase();      var start = name.indexOf(query);     start = start > 0 ? start : 0;      if(query.length < obj.name.length){         label += obj.name.substr(0, start);         label += '<strong>' + obj.name.substr(start, query.length) + '</strong>';         label += obj.name.substr(start+query.length, obj.name.length-query.length-start);     } else {         label += '<strong>' + obj.name + '</strong>';     }      if(obj.typeShort){         label += ' ' + obj.typeShort + '.';     }      return label; };  region.kladr({     labelFormat: LabelFormat, });  district.kladr({     labelFormat: LabelFormat, }); 

Вот и всё =)
Буду рад вашим вопросам и комментариям

Весь JS код

$(function() {     var token = '51dfe5d42fb2b43e3300006e';     var key   = '86a2c2a06f1b2451a87d05512cc2c3edfdf41969';      var region   = $('[name="region"]');     var district = $('[name="district"]');     var city     = $('[name="city"]');     var street   = $('[name="street"]');     var building = $('[name="building"]');      var tooltip  = $('.tooltip');      var LabelFormat = function( obj, query ){         var label = '';          var name = obj.name.toLowerCase();         query = query.toLowerCase();          var start = name.indexOf(query);         start = start > 0 ? start : 0;          if(query.length < obj.name.length){             label += obj.name.substr(0, start);             label += '<strong>' + obj.name.substr(start, query.length) + '</strong>';             label += obj.name.substr(start+query.length, obj.name.length-query.length-start);         } else {             label += '<strong>' + obj.name + '</strong>';         }          if(obj.typeShort){             label += ' ' + obj.typeShort + '.';         }          return label;     };      var ShowError = function(input, message){         tooltip.find('span').text(message);          var inputOffset = input.offset();         var inputWidth  = input.outerWidth();         var inputHeight = input.outerHeight();          var tooltipHeight = tooltip.outerHeight();          tooltip.css({             left: (inputOffset.left + inputWidth + 10) + 'px',             top: (inputOffset.top + (inputHeight - tooltipHeight)/2 - 1) + 'px'         });          tooltip.show();     };      region.kladr({         token: token,         key: key,         type: $.kladr.type.region,         labelFormat: LabelFormat,         verify: true,         select: function(obj) {             region.parent().find('label').text(obj.type);             district.kladr('parentType', $.kladr.type.region);             district.kladr('parentId', obj.id);             city.kladr('parentType', $.kladr.type.region);             city.kladr('parentId', obj.id);         },         check: function(obj) {             if(obj){                 region.parent().find('label').text(obj.type);                 district.kladr('parentType', $.kladr.type.region);                 district.kladr('parentId', obj.id);                 city.kladr('parentType', $.kladr.type.region);                 city.kladr('parentId', obj.id);             } else {                 ShowError(region, 'Неверно введено название региона');             }         }     });      district.kladr({         token: token,         key: key,         type: $.kladr.type.district,         labelFormat: LabelFormat,         verify: true,         select: function(obj) {             district.parent().find('label').text(obj.type);             city.kladr('parentType', $.kladr.type.district);             city.kladr('parentId', obj.id);         },         check: function(obj) {             if(obj){                 district.parent().find('label').text(obj.type);                 city.kladr('parentType', $.kladr.type.district);                 city.kladr('parentId', obj.id);             } else {                 ShowError(district, 'Неверно введено название района');             }         }     });      city.kladr({         token: token,         key: key,         type: $.kladr.type.city,         verify: true,         select: function(obj) {             city.parent().find('label').text(obj.type);             street.kladr('parentType', $.kladr.type.city);             street.kladr('parentId', obj.id);             building.kladr('parentType', $.kladr.type.city);             building.kladr('parentId', obj.id);         },         check: function(obj) {             if(obj){                 city.parent().find('label').text(obj.type);                 street.kladr('parentType', $.kladr.type.city);                 street.kladr('parentId', obj.id);                 building.kladr('parentType', $.kladr.type.city);                 building.kladr('parentId', obj.id);             } else {                 ShowError(city, 'Неверно введено название населённого пункта');             }         }     });      street.kladr({         token: token,         key: key,         type: $.kladr.type.street,         select: function(obj) {             street.parent().find('label').text(obj.type);             building.kladr('parentType', $.kladr.type.street);             building.kladr('parentId', obj.id);         },         check: function(obj) {             if(obj){                 street.parent().find('label').text(obj.type);                 building.kladr('parentType', $.kladr.type.street);                 building.kladr('parentId', obj.id);             } else {                 ShowError(street, 'Неверно введено название улицы');             }         }     });      building.kladr({         token: token,         key: key,         type: $.kladr.type.building,         select: function(obj) {             building.parent().find('label').text(obj.type);         }     }); }); 

ссылка на оригинал статьи http://habrahabr.ru/post/194018/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *