Битрикс автоматическое определение города на php
Последние записи
Данный материал не является исчерпывающим руководством. Код поставляется бесплатно и "как есть". Используйте его на свой страх и риск
У MaxMind есть хорошая инструкция по использованию их баз данных: maxmind-db/reader. Ознакомьтесь с ней или продолжайте читать мой опыт внедрения.
Скачать бесплатные базы MaxMind можно здесь: GeoLite2 Free Downloadable Databases (требуется регистрация аккаунта)
Скачанную базу данных GeoLite2-City.mmdb
положите в любую удобную папку, например, в /local/libs/maxmind/
Для чтения баз данных MaxMind для php требуется специальная "читалка". Переходим в консоль ssh
под root
аккаунтом и ставим MaxMind DB Reader
yum install php-maxminddb
Если вы получили ошибку, то можно воспользоваться командой
apt install libmaxminddb-dev
Будем считать, что composer
уже подключен на вашем проекте. Переходим в консоль и ставим
php composer.phar require maxmind-db/reader:~1.0
composer require geoip2/geoip2
Кроссбраузерная форма выбора города пользователя
В init.php
добавляем
require($_SERVER['DOCUMENT_ROOT'].'/local/libs/init/geolocationMaxMInd.php');
Листинг файла geolocationMaxMInd.php
//Смело избавляйтесь от доп. параметров (REGION_ID, REGION_NAME) они нужны в очень редких случаях
require $_SERVER['DOCUMENT_ROOT'].'/vendor/autoload.php';
use GeoIp2\Database\Reader;
AddEventHandler("main", "OnPageStart", "OnPageStart");
function OnPageStart(){
global $CITY; //Определяем глобальную переменную на сайте куда запишем полученную информацию
if(!CModule::IncludeModule("sale")) // не смогли подключить модуль
return;
//Я разделил куки с геолокацией на 3 отдельных (для удобства), вы можете использовать любой формат записи
if(!$_COOKIE['geoCity'] || !$_COOKIE['geoRegion'] || !$_COOKIE['geoID']){//Если не определены все 3 куки, то определяем через MaxMind
$reader = new Reader($_SERVER['DOCUMENT_ROOT'].'/local/libs/maxmind/GeoLite2-City.mmdb');//Говорим ридеру откуда читать базу данных
$ip = \Bitrix\Main\Service\GeoIp\Manager::getRealIp(); //Получаем ip стандартными методами Битрикс
$record = $reader->city($ip); //Получаем массив данных по айпи
$CITY = array(
'REGION_NAME' => $record->mostSpecificSubdivision->names['ru'],//определяем область
'CITY_NAME'=> $record->city->names['ru'],//определяем город
);
$location = getLocationByName(CITY['CITY_NAME']);
$CITY['CITY_ID'] = $location['ID'];
$CITY['REGION_ID'] = $location['REGION_ID'];
//Устанавливаем массив с городом по умолчанию на случай, если город не найден
if(!$CITY['CITY_NAME']){
$CITY = array(
'REGION_NAME' => 'Московская область',
'CITY_NAME'=> 'Москва',
'CITY_ID'=> '84',
);
}
//Устанавливаем куки
setcookie("geoCity", $CITY['CITY_NAME'], time()+60*60*24*30*12*2, "/");
setcookie("geoRegion", $CITY['REGION_NAME'], time()+60*60*24*30*12*2, "/");
setcookie("geoID", $CITY['CITY_ID'], time()+60*60*24*30*12*2, "/");
setcookie("geoRegionID", $CITY['REGION_ID'], time()+60*60*24*30*12*2, "/");
}else{
//Поскольку куки найдены, то заполняем массив данными из них
$CITY = array(
'REGION_NAME' => $_COOKIE['geoRegion'],
'CITY_NAME'=> $_COOKIE['geoCity'],
'CITY_ID'=> $_COOKIE['geoID'],
'REGION_ID'=> $_COOKIE['geoRegionID'],
);
}
if($_COOKIE['changeRegionID']=='Y' && $_COOKIE['CITY_NAME']!='Москва'){//В моем случае у Москвы регионы не было
setcookie("changeRegionID", null, -1, "/");
$location = getLocationByName(CITY['CITY_NAME']);
$CITY['REGION_ID'] = location['REGION_ID'];
setcookie("geoRegionID", $CITY['REGION_ID'], time()+60*60*24*30*12*2, "/");
}
}
function getLocationByName($name){
//Ищем совпадение найденного города в местоположениях Битрикс
$db_vars = CSaleLocation::GetList(
array(
"SORT" => "ASC",
"COUNTRY_NAME_LANG" => "ASC",
"CITY_NAME_LANG" => "ASC"
),
array("LID" => LANGUAGE_ID,'CITY_NAME' =>name),
false,
false,
array()
);
return $db_vars->Fetch();
}
В header.php
добавляем вызов формы
<a class="js-select-city" href="javascript:void(0);" data-city="Москва" data-region="Московская область" data-id="216" data-code="0000073738">Москва</a>
В footer.php
выводим форму
<div class="topOuter absCenter">
<div class="topInner">
<div class="topWindowClose"><svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 52 52" style="enable-background:new 0 0 52 52;" xml:space="preserve"><g><path d="M26,0C11.664,0,0,11.663,0,26s11.664,26,26,26s26-11.663,26-26S40.336,0,26,0z M26,50C12.767,50,2,39.233,2,26 S12.767,2,26,2s24,10.767,24,24S39.233,50,26,50z"/><path d="M35.707,16.293c-0.391-0.391-1.023-0.391-1.414,0L26,24.586l-8.293-8.293c-0.391-0.391-1.023-0.391-1.414,0 s-0.391,1.023,0,1.414L24.586,26l-8.293,8.293c-0.391,0.391-0.391,1.023,0,1.414C16.488,35.902,16.744,36,17,36 s0.512-0.098,0.707-0.293L26,27.414l8.293,8.293C34.488,35.902,34.744,36,35,36s0.512-0.098,0.707-0.293 c0.391-0.391,0.391-1.023,0-1.414L27.414,26l8.293-8.293C36.098,17.316,36.098,16.684,35.707,16.293z"/></g></svg></div>
<h3>Выбор города:</h3>
<?= bitrix_sessid_post() ?>
<?
global $CITY;
if(CModule::IncludeModule("sale"))
{
CSaleLocation::proxySaleAjaxLocationsComponent(
array(
"AJAX_CALL" => "Y",
'CITY_OUT_LOCATION' => 'Y',
'COUNTRY_INPUT_NAME' => 'RUSSIA_COUNTRY',
'CITY_INPUT_NAME' => "ORDER_PROP_CITY",
//'LOCATION_VALUE' => $CITY['CITY_ID'], //5
"ONCITYCHANGE" => "",
"INDEX_ON " => "N",
),
array(),
'search',
true,
'popup-location-block-wrapper'
);
}
?>
<h4>или выберите из списка:</h4>
<hr />
<div class="row citiesQuick">
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Москва'){?>active<?}?>" data-title="Москва" data-region="Московская область" data-id="84" data-code="0000073738" title="Москва">Москва</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Санкт-Петербург'){?>active<?}?>" data-title="Санкт-Петербург" data-region="Ленинградская область" data-id="85" data-code="0000103664" title="Санкт-Петербург">Санкт-Петербург</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Балашиха'){?>active<?}?>" data-title="Балашиха" data-region="Московская область" data-id="87" data-code="0000033889" title="Балашиха">Балашиха</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Воронеж'){?>active<?}?>" data-title="Воронеж" data-region="Воронежская область" data-id="740" data-code="0000293598" title="Воронеж">Воронеж</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Екатеринбург'){?>active<?}?>" data-title="Екатеринбург" data-region="Свердловская область" data-id="2203" data-code="0000812044" title="Екатеринбург">Екатеринбург</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Казань'){?>active<?}?>" data-title="Казань" data-region="Республика Татарстан" data-id="1558" data-code="0000550426" title="Казань">Казань</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Королёв'){?>active<?}?>" data-title="Королёв" data-region="Московская область" data-id="91" data-code="0000030318" title="Королёв">Королёв</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Красногорск'){?>active<?}?>" data-title="Красногорск" data-region="Московская область" data-id="142" data-code="0000044453" title="Красногорск">Красногорск</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Краснодар'){?>active<?}?>" data-title="Краснодар" data-region="Краснодарский край" data-id="1132" data-code="0000386590" title="Краснодар">Краснодар</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Люберцы'){?>active<?}?>" data-title="Люберцы" data-region="Московская область" data-id="149" data-code="0000046203" title="Люберцы">Люберцы</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Мытищи'){?>active<?}?>" data-title="Мытищи" data-region="Московская область" data-id="153" data-code="0000049473" title="Мытищи">Мытищи</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Нижний Новгород'){?>active<?}?>" data-title="Нижний Новгород" data-region="Нижегородская область" data-id="1698" data-code="0000600317" title="Нижний Новгород">Нижний Новгород</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Новосибирск'){?>active<?}?>" data-title="Новосибирск" data-region="Новосибирская область" data-id="2614" data-code="0000949228" title="Новосибирск">Новосибирск</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Одинцово'){?>active<?}?>" data-title="Одинцово" data-region="Московская область" data-id="166" data-code="0000054606" title="Одинцово">Одинцово</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Пермь'){?>active<?}?>" data-title="Пермь" data-region="Пермский край" data-id="1869" data-code="0000670178" title="Пермь">Пермь</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Подольск'){?>active<?}?>" data-title="Подольск" data-region="Московская область" data-id="109" data-code="0000032609" title="Подольск">Подольск</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Пушкин'){?>active<?}?>" data-title="Пушкин" data-region="Ленинградская область" data-id="3139" data-code="0000107443" title="Пушкин">Пушкин</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Ростов-на-Дону'){?>active<?}?>" data-title="Ростов-на-Дону" data-region="Ростовская область" data-id="1248" data-code="0000445112" title="Ростов-на-Дону">Ростов-на-Дону</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Самара'){?>active<?}?>" data-title="Самара" data-region="Самарская область" data-id="1831" data-code="0000650509" title="Самара">Самара</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Сочи'){?>active<?}?>" data-title="Сочи" data-region="Краснодарский край" data-id="1137" data-code="0000394020" title="Сочи">Сочи</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Химки'){?>active<?}?>" data-title="Химки" data-region="Московская область" data-id="111" data-code="0000033097" title="Химки">Химки</a></div>
<div class="col-xs-4"><a href="#" class="cityQuick <?if($CITY['CITY_NAME']=='Челябинск'){?>active<?}?>" data-title="Челябинск" data-region="Челябинская область" data-id="2354" data-code="0000854968" title="Челябинск">Челябинск</a></div>
</div>
</div>
</div>
Записываем стили формы в template_styles.css
.absCenter { display: -webkit-box; display: -moz-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-align: center; -moz-box-align: center; -ms-flex-align: center; -webkit-align-items: center; align-items: center; -webkit-box-pack: center; -moz-box-pack: center; -ms-flex-pack: center; -webkit-justify-content: center; justify-content: center; text-align: center; flex-direction: column}
.topOuter{background-color: rgba(0,0,0,0.5);position: fixed;top:0;left:0;width:100%;height:100%;z-index: 1000;display: none}
.topInner {background-color: #fff;padding:40px 40px;border-radius: 10px;position: relative;min-width: 320px;max-width:700px;-webkit-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.2); -moz-box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.2); box-shadow: 0px 5px 10px 0px rgba(0,0,0,0.2);text-align: left;max-height: 500px;overflow-y: auto;width: 100%}
.topInner h2{font-family: Gotham-Pro-Bold,"HelveticaNeueCyr", "PT Sans", sans-serif;font-size: 24px; font-weight: 600;line-height: 32px;margin-bottom:14px;text-align: left}
.topInner .formClose{position: absolute;right: 0;top:0;background-color: #E31D23;border-radius: 50%;width: 28px;height:28px; -webkit-transform: translate(50%,-50%); -moz-transform: translate(50%,-50%); -ms-transform: translate(50%,-50%); -o-transform: translate(50%,-50%); transform: translate(50%,-50%);cursor:pointer}
.topInner .formClose .svgBox{margin-top:3px;}
.topInner .formClose svg{width: 8px;height:8px;fill:#fff;stroke:#fff;}
.topInner .formClose:hover{background-color: #d21a20}
.topInner h3{text-align: left;text-transform: uppercase;font-weight:600;border-bottom:1px solid #12472f;padding-bottom:10px;}
.topInner h4{text-align: left;font-weight:600;font-size: 14px;margin-top:20px;margin-bottom:15px}
#autocomplete{margin-bottom: 20px;font-size: 14px;}
.cityQuick {font-weight:400;font-size: 14px;color: #202020}
.cityQuick.active {font-weight:600;}
.cityQuick:hover {color:#d6000a;}
.citiesQuick.row{padding:0 15px;/*margin:0;background: #f7f7f7;border: 1px solid #E5E5E5;*/}
.topWindowClose {position: absolute;top:8px;right:8px;width: 52px;height:52px;cursor: pointer}
.topOuter .topWindowClose {top:12px;right:12px;width: 28px;height:28px;}
.topWindowClose svg{fill:#383838}
.topWindowClose:hover svg {fill:#888888;}
.topWindowTitle {color:#a00200;font-family:Ubuntu, Arial, Helvetica, sans-serif;font-size:64px;font-weight: 600;margin-top: 60px}
.topWindowTitle span{font-size:130px;position: relative;bottom: -15px;}
.topWindowTitle span:after{position: absolute;top:10px;right:-8px;content: '';background-image: url('/upload/stock/shapka.png');width: 65px;height:37px;}
.topWindowText {margin-top: 35px;margin-left:0;margin-right:0;}
.topWindowText p{margin-bottom: 14px;text-align: left;color: #1d1a1a;font-family:Ubuntu, Arial, Helvetica, sans-serif;font-size:14px;font-weight: 400;line-height: 19px;padding:0 20px 0 40px;}
.topWindowText p span{font-weight: 600}
.topWindowClose svg {-moz-transition: all 0.5s;-webkit-transition: all 0.5s;-o-transition: all 0.5s;-ms-transition: all 0.5s}
/* Geolocation autocomplete */
.autocomplete-suggestions { border: 1px solid #999; background: #FFF; overflow: auto; }
.autocomplete-suggestion { padding: 2px 5px; white-space: nowrap; overflow: hidden;cursor: pointer}
.autocomplete-selected { background: #F0F0F0; }
.autocomplete-suggestions strong { font-weight: normal; color: #3399FF; }
.autocomplete-group { padding: 2px 5px; }
.autocomplete-group strong { display: block; border-bottom: 1px solid #000; }
.topInner .bx-sls .bx-ui-sls-pane{max-height: 200px;}
.topInner .bx-sls .bx-ui-sls-fake, .topInner .bx-sls .bx-ui-sls-route{height: 25px;}
.topInner .bx-sls .dropdown-item-text span{color:#3399ff}
.topInner .bx-sls .dropdown-item-text{color:#888888}
.topInner .bx-sls .bx-ui-sls-variants .bx-ui-sls-variant:hover,.topInner .bx-sls .bx-ui-sls-variant-active{background-color: #f7f7f7;}
.topInner .location-block-wrapper .bx-sls .dropdown-icon{top:13px;body .newHeader .newPhoneWrap}
.citiesQuick {display: flex;flex-wrap: wrap;}
.citiesQuick > div{flex-grow: 1;width: 33%;}
.topInner .bx-sls .bx-ui-sls-fake, .topInner .bx-sls .bx-ui-sls-route{min-height: 25px}
.topInner .bx-sls .dropdown-icon{top: 5px}
.topInner .bx-sls .dropdown-fade2white{top: 0;height: 25px;}
.topInner .bx-sls .dropdown-item-text{font-size: 1.4rem;line-height: 2rem;font-weight: 400;margin-bottom: 10px;color: #202020}
.topInner .bx-sls .dropdown-item-text:hover{color: #d6000a}
.topInner .bx-sls .bx-ui-sls-variants .bx-ui-sls-variant, .topInner .bx-sls .bx-ui-sls-error{padding: 0}
.topInner .bx-sls .dropdown-item{margin: 0}
.topInner .bx-ui-sls-error > div{display: none}
@media all and (max-width: 600px) {
.topInner {min-width: calc(320px - 80px);max-width: calc(320px - 80px);width: 100%;}
.citiesQuick .col-xs-4{-ms-flex-preferred-size: 100%;flex-basis: 100%;max-width: 100%;}
body .newHeader .cityChoice .row,body .newHeader .cityChoice{margin-top:0;}
body .newHeader .newPhoneBlock{position: absolute;top:20px}
body .newHeader .newPhoneWrap{top:0 !important;}
body .newHeader .logo_wrapp {margin-bottom: 0}
body .newHeader .cityChoice .row {margin-top:0 !important;}
.cityWrap {min-height: 30px;position: relative;padding-left: 15px !important;}
body .newHeader .cityChoice {bottom:0;position: absolute;bottom:0;}
}
@media all and (max-width: 400px) {
/*body .newHeader .cityPodpis{display: none}
body .newHeader .cityName {margin-left: 0 !important;}*/
}
В основной скрипт шаблона, например, main.js
добавляем
function closeForm(){
$('.topOuter').removeClass('active').fadeOut(600,function(){});
}
function showForm(){
$('.topOuter').css("display", "flex").addClass('active').hide().fadeIn(600);
}
function setCity(city, region, id, code,geoRegionID) {
var date = new Date();
var days = 365;//3 // <--- нужное количество дней
var hours = 24;//24 // <--- нужное количество часов
var minutes = 60;//60 // <--- нужное количество минут
var seconds = 60; // <--- нужное количество секунд
date.setTime(date.getTime() + (days * hours * minutes * seconds * 1000));
$.cookie("geoCity", city, {expires: date, path: '/'});
$.cookie("geoRegion", region, {expires: date, path: '/'});
$.cookie("changeRegionID", 'Y', {expires: date, path: '/'});
$.cookie("geoID", id, {expires: date, path: '/'});
$.cookie("BITRIX_SM_CITY_NAME", city, {expires: date, path: '/'});
$.cookie("BITRIX_SM_CITY_ID", id, {expires: date, path: '/'});
$.cookie("BITRIX_SM_REGION_NAME", region, {expires: date, path: '/'});
$('.js-cityChoose').html(city);
$('.cityQuick').removeClass('active');
$(".cityQuick[data-title='" + city + "']").addClass('active');
//Если мы на странице оформления заказа
if ($('#bx-soa-order-form').length) {
//Вызов смены города в старом шаблоне
//BX.saleOrderAjax.changeLoc(id);
$('.dropdown-field').val(code).fadeOut(0);
$('.bx-ui-sls-fake').val(code).fadeOut(0);
//Вызов смены города в новом шаблоне
BX.Sale.OrderAjaxComponent.params.newCity=code;
BX.Sale.OrderAjaxComponent.locations[id];
BX.Sale.OrderAjaxComponent.editFadeRegionBlock(true);
BX.Sale.OrderAjaxComponent.sendRequest();
}
location.reload();
closeForm();
}
function IsJsonString(str) {
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
$(document).ready(function(){
$('body').on('click', '.topOuter', function (e) {
if ($('.topOuter').has(e.target).length === 0) {//Отслеживаем клик именно по элементу
closeForm();
}
});
$('body').on('click touch', '.topWindowClose', function (e) {
closeForm();
});
$('body').on('click touch', '.cityQuick', function (e) {
e.preventDefault();
var city = $(this).text();
if(city !== $('.cityName').text()){
setCity(city,$(this).attr('data-region'),$(this).attr('data-id'),$(this).attr('data-code'));
}else{
closeForm();
}
closeForm();
});
$('body').on('click touch', '.js-cityChoose', function (e) {
e.preventDefault();
showForm();
});
$('body').on('click', '.topInner .bx-ui-sls-variant', function (e) {
var el = $(this).find('.dataLocation'),
data = {'AJAX': 'Y', 'sessid':$("#sessid").val(), 'DATA': {'CODE':el.attr('data-code'),'ID':el.attr('data-id')}};
$.ajax({
type: 'post',
url: '/local/ajax/setCity.php',
data: data,
//dataType: 'json',
success: function (data) {
if(IsJsonString(data)){
data=$.parseJSON(data);
setCity(data.CITY,data.REGION,data.ID,data.REGION_ID);
}
}
});
});
$(document).keydown(function (e) {
if (e.keyCode === 27) {//Esc
var popup = $('.topOuter:visible');
if (popup) {
closeForm(popup);
return false;
}
}
});
});
function changeCity(){
var el = $('.topInner .bx-ui-sls-variant-active').find('.dataLocation'),
data = {'AJAX': 'Y', 'sessid':$("#sessid").val(), 'DATA': {'CODE':el.attr('data-code'),'ID':el.attr('data-id')}};
$.ajax({
type: 'post',
url: '/local/ajax/setCity.php',
data: data,
//dataType: 'json',
success: function (data) {
console.log(data);
if(IsJsonString(data)){
data=$.parseJSON(data);
setCity(data.CITY,data.REGION,data.ID,data.CODE,data.REGION_ID);
}
}
});
}
/*!
* jQuery Cookie Plugin v1.4.1
* https://github.com/carhartl/jquery-cookie
*
* Copyright 2006, 2014 Klaus Hartl
* Released under the MIT license
*/
(function (factory) {
if (typeof define === 'function' && define.amd) {
// AMD (Register as an anonymous module)
define(['jquery'], factory);
} else if (typeof exports === 'object') {
// Node/CommonJS
module.exports = factory(require('jquery'));
} else {
// Browser globals
factory(jQuery);
}
}(function ($) {
var pluses = /\+/g;
function encode(s) {
return config.raw ? s : encodeURIComponent(s);
}
function decode(s) {
return config.raw ? s : decodeURIComponent(s);
}
function stringifyCookieValue(value) {
return encode(config.json ? JSON.stringify(value) : String(value));
}
function parseCookieValue(s) {
if (s.indexOf('"') === 0) {
// This is a quoted cookie as according to RFC2068, unescape...
s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
}
try {
// Replace server-side written pluses with spaces.
// If we can't decode the cookie, ignore it, it's unusable.
// If we can't parse the cookie, ignore it, it's unusable.
s = decodeURIComponent(s.replace(pluses, ' '));
return config.json ? JSON.parse(s) : s;
} catch(e) {}
}
function read(s, converter) {
var value = config.raw ? s : parseCookieValue(s);
return $.isFunction(converter) ? converter(value) : value;
}
var config = $.cookie = function (key, value, options) {
// Write
if (arguments.length > 1 && !$.isFunction(value)) {
options = $.extend({}, config.defaults, options);
if (typeof options.expires === 'number') {
var days = options.expires, t = options.expires = new Date();
t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
}
return (document.cookie = [
encode(key), '=', stringifyCookieValue(value),
options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
options.path ? '; path=' + options.path : '',
options.domain ? '; domain=' + options.domain : '',
options.secure ? '; secure' : ''
].join(''));
}
// Read
var result = key ? undefined : {},
// To prevent the for loop in the first place assign an empty array
// in case there are no cookies at all. Also prevents odd result when
// calling $.cookie().
cookies = document.cookie ? document.cookie.split('; ') : [],
i = 0,
l = cookies.length;
for (; i < l; i++) {
var parts = cookies[i].split('='),
name = decode(parts.shift()),
cookie = parts.join('=');
if (key === name) {
// If second argument (value) is a function it's a converter...
result = read(cookie, value);
break;
}
// Prevent storing a cookie that we couldn't decode.
if (!key && (cookie = read(cookie)) !== undefined) {
result[name] = cookie;
}
}
return result;
};
config.defaults = {};
$.removeCookie = function (key, options) {
// Must not alter options, thus extending a fresh object...
$.cookie(key, '', $.extend({}, options, { expires: -1 }));
return !$.cookie(key);
};
}));
Листинг файла setCity.php
require($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");
use Bitrix\Sale\Location\LocationTable;
if (check_bitrix_sessid() && $_SERVER["REQUEST_METHOD"] == "POST") {
$parameters = array();
$parameters['filter']['=CODE'] = $_POST['DATA']['CODE'];
$parameters['filter']['NAME.LANGUAGE_ID'] = "ru";
$parameters['limit'] = 1;
$parameters['select'] = array('LNAME' => 'NAME.NAME', '*');
$item = Bitrix\Sale\Location\LocationTable::getList( $parameters )->fetch();
if(strlen( $item[ 'LNAME' ] ) > 0)
{
$city = $item['LNAME'];
$id = $item['ID'];
$code = $item['CODE'];
$regionID = $item['REGION_ID'];
if($item['DEPTH_LEVEL']>=5){
$item = \Bitrix\Sale\Location\LocationTable::getById($item['PARENT_ID'])->fetch();
}
if($item['DEPTH_LEVEL']=4){
$item = \Bitrix\Sale\Location\LocationTable::getById($item['PARENT_ID'])->fetch();
}
$parameters['filter']['=CODE'] = $item['CODE'];
$arVal = Bitrix\Sale\Location\LocationTable::getList( $parameters )->fetch();
if ( $arVal && strlen( $arVal[ 'LNAME' ] ) > 0 )
{
$region = $arVal['LNAME'];
}
echo json_encode(array('CITY'=>$city, 'REGION'=>$region, 'ID'=>$id, 'CODE'=>$code, 'REGION_ID'=>$regionID));
}else{
return false;
}
}
Правим файл \bitrix\js\sale\core_ui_etc.js
Вызов функции BX.util.wrapSubstring = function(haystack, chunks, wrapTagName, escapeParts){
(~404ст) меняем на
BX.util.wrapSubstring = function(haystack, chunks, wrapTagName, escapeParts, full = false){
Так же меняем строку
return haystack.replace(/#A#/g, '<'+wrapTagName+'>').replace(/#B#/g, '</'+wrapTagName+'>'); (~444ст)
на
if(full){
return haystack.replace(/#A#/g, '<'+wrapTagName+' class="dataLocation newFilLCode" data-code="'+full.CODE+'" data-type="'+full.TYPE_ID+'" data-id="'+full.VALUE+'">').replace(/#B#/g, '</'+wrapTagName+'>');
}else{
return haystack.replace(/#A#/g, '<'+wrapTagName+'>').replace(/#B#/g, '</'+wrapTagName+'>');
}
В файле bitrix\components\bitrix\sale.location.selector.search\templates\.default\script.js
меняем строчку (~71ст)
itemData['=display_wrapped'] = BX.util.wrapSubstring(itemData.DISPLAY+itemData.PATH, chunks, this.opts.wrapTagName, true, itemData);
на
itemData['=display_wrapped'] = BX.util.wrapSubstring(itemData.DISPLAY+itemData.PATH, chunks, this.opts.wrapTagName, true, itemData);
Выглядит форма примерно так
Автоматическая подгрузка города пользователя в поле выбора местоположения в sale.order.ajax
Добавляем в init.php
код:
\Bitrix\Main\EventManager::getInstance()->addEventHandlerCompatible(
'sale',
'OnSaleComponentOrderProperties',
'SaleOrderEvents::fillLocation'
);
class SaleOrderEvents{
function fillLocation(&$arUserResult, $request, &$arParams, &$arResult)
{
$registry = \Bitrix\Sale\Registry::getInstance(\Bitrix\Sale\Registry::REGISTRY_TYPE_ORDER);
$orderClassName = $registry->getOrderClassName();
$order = $orderClassName::create(\Bitrix\Main\Application::getInstance()->getContext()->getSite());
$propertyCollection = $order->getPropertyCollection();
foreach ($propertyCollection as $property){
if ($property->isUtil())
continue;
$arProperty = $property->getProperty();
if(
$arProperty['TYPE'] === 'LOCATION'
&& array_key_exists($arProperty['ID'],$arUserResult["ORDER_PROP"])
&& !$request->getPost("ORDER_PROP_".$arProperty['ID'])
&& (
!is_array($arOrder=$request->getPost("order"))
|| !$arOrder["ORDER_PROP_".$arProperty['ID']]
)
) {
global $CITY;
//Получаем код местоположения по его айди
$arLocs = CSaleLocation::GetByID($CITY['ID'], LANGUAGE_ID);
$arUserResult["ORDER_PROP"][$arProperty['ID']] = $arLocs['CODE'];
}
}
}
}
Смена города "на лету"
Вешаем обработчик на объект для которого заранее зададим поля data-city, data-region, data-id, data-code
. Например так:
<a class="js-select-city" href="javascript:void(0);" data-city="Москва" data-region="Московская область" data-id="216" data-code="0000073738">Москва</a>
Тогда javascript для смены города будет выглядеть так:
$('.js-select-city').click(function(){
var el = $(this);
//Запоминаем город
setCity(el.attr('data-city'),el.attr('data-region'),el.attr('data-id'),el.attr('data-code'));
});
function setCity(city, region, id, code) {
var date = new Date(),
days = 365,//3 // <--- нужное количество дней
hours = 24,//24 // <--- нужное количество часов
minutes = 60,//60 // <--- нужное количество минут
seconds = 60; // <--- нужное количество секунд
date.setTime(date.getTime() + (days * hours * minutes * seconds * 1000));
//Устанавливаем куки
$.cookie("geoCity", city, {expires: date, path: '/'});
$.cookie("geoRegion", region, {expires: date, path: '/'});
$.cookie("geoID", id, {expires: date, path: '/'});
//Если мы на странице оформления заказа
if ($('#bx-soa-order-form').length) {
//Вызов смены города в старом шаблоне
//BX.saleOrderAjax.changeLoc(id);
$('.dropdown-field').val(code).fadeOut(0);
$('.bx-ui-sls-fake').val(code).fadeOut(0);
//Вызов смены города в новом шаблоне
BX.Sale.OrderAjaxComponent.params.newCity=code;
BX.Sale.OrderAjaxComponent.locations[id];
BX.Sale.OrderAjaxComponent.editFadeRegionBlock(true);
BX.Sale.OrderAjaxComponent.sendRequest();
}
}
Получение списка местоположений
Учтите, что Id городов в местоположениях Битрикс у нас будут отличаться
Получить перечень городов и их id в Битрикс можно например так:
Bitrix\Main\Loader::includeModule('sale');
$db_vars = CSaleLocation::GetList(
array(
"SORT" => "ASC",
"COUNTRY_NAME_LANG" => "ASC",
"CITY_NAME_LANG" => "ASC"
),
array("LID" => LANGUAGE_ID),
false,
false,
array()
);
while ($location = $db_vars->Fetch()):
echo $location["CITY_NAME"] .' - '. $location["ID"].'
';
print_r(CSaleLocation::GetByID($location["ID"]));
endwhile;
Комментарии