templates/Map/page.html.twig line 1

Open in your IDE?
  1. {% extends 'grid.html.twig' %}
  2. {% block mainContainer %}
  3.    {# {{ form(form) }}#}
  4.     <div id="map_form"></div>
  5.     <img src="{{ asset('/static/preloader.gif') }}" id="preloader" style="display: none;" />
  6.     <div id="map"
  7.          data-city-uri-idenity="{{ cityUriIdentity }}"
  8.          data-city-latitude="{{ cityLatitude }}"
  9.          data-city-longitude="{{ cityLongitude }}"
  10.          style="width:100%; height:500px;"></div>
  11. {% endblock %}
  12. {% block javascripts %}
  13.     <script src="{{ asset('bundles/fosjsrouting/js/router.min.js') }}"></script>
  14.     <script src="{{ path('fos_js_routing_js', { callback: 'fos.Router.setData' }) }}"></script>
  15.     <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
  16.     <script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU" type="text/javascript"></script>
  17.     <script type="text/javascript">
  18.         ;var RoutingDecorator = {
  19.             generate: function (name, params) {
  20.                 const orig_name = name;
  21.                 try {
  22.                     Routing.getRoute(name)
  23.                 } catch(error) {
  24.                     name = name + '.' + '{{ app.request.locale }}';
  25.                     try {
  26.                         Routing.getRoute(name)
  27.                     } catch(error) {
  28.                         name = orig_name;
  29.                     }
  30.                 }
  31.                 return Routing.generate(name, params);
  32.             }
  33.         };
  34.         ;(function () {
  35.             document.addEventListener('DOMContentLoaded', _ => {
  36.                 var avatarPath = '{{ asset('', 'profile_media_avatar') }}';
  37.                 var photoPath = '{{ asset('', 'profile_media') }}';
  38.                 var thumbPath = '{{ asset('', 'saloon_media_thumb') }}';
  39.                 var mapContainer = document.querySelector('#map');
  40.                 var preloader = document.querySelector('#preloader');
  41.                 var cityUriIdentity = mapContainer.getAttribute('data-city-uri-idenity');
  42.                 var cityLatitude = mapContainer.getAttribute('data-city-latitude');
  43.                 var cityLongitude = mapContainer.getAttribute('data-city-longitude');
  44.                 var formName = 'filter_map_form';
  45.                 var multipleCities = {{ multipleCities }};
  46.                 var routesUrl = '/js/fos_js_routes{{ multipleCities ? '_city_prefixed' }}.json';
  47.                 loadRoutes();
  48.                 var myMap, clusterer;
  49.                 ymaps.ready(function () {
  50.                     myMap = new ymaps.Map('map', {
  51.                             center: [cityLatitude, cityLongitude],
  52.                             zoom: 9,
  53.                             behaviors: ['default', 'scrollZoom']
  54.                         }, {
  55.                             searchControlProvider: 'yandex#search'
  56.                         });
  57.                     clusterer = new ymaps.Clusterer({
  58.                             preset: 'islands#invertedVioletClusterIcons',//Через кластеризатор можно указать только стили кластеров,стили для меток нужно назначать каждой метке отдельно.
  59.                             groupByCoordinates: false,//Ставим true, если хотим кластеризовать только точки с одинаковыми координатами.
  60.                             //Опции кластеров указываем в кластеризаторе с префиксом "cluster".
  61.                             clusterDisableClickZoom: true,
  62.                             clusterHideIconOnBalloonOpen: false,
  63.                             geoObjectHideIconOnBalloonOpen: false
  64.                     });
  65.                     // Можно менять опции кластеризатора после создания.
  66.                     clusterer.options.set({
  67.                         gridSize: 80,
  68.                         clusterDisableClickZoom: true
  69.                     });
  70.                     loadForm();
  71.                 });
  72.                 function loadRoutes() {
  73.                     $.ajax({
  74.                         url:routesUrl,
  75.                         dataType: "json",
  76.                         async: false,
  77.                         success: function (routes) {
  78.                             Routing.setRoutingData(routes);
  79.                         },
  80.                         error: function (xhr, ajaxOptions, thrownError) {}
  81.                     });
  82.                 }
  83.                 function setFormSubmitListener() {
  84.                     document.querySelector("form[name="+formName+"]").addEventListener('submit', function(e){
  85.                         e.preventDefault();
  86.                         if(!clusterer)
  87.                             return;
  88.                         filterData();
  89.                         return false;
  90.                     });
  91.                 }
  92.                 function loadForm() {
  93.                     fetch('{{ path('map.form', {city: cityUriIdentity}) }}', {
  94.                         mode: "cors",
  95.                         importance: "low",
  96.                         method: "POST",
  97.                         headers: {
  98.                             "Content-Type": "application/x-www-form-urlencoded",
  99.                             "X-Requested-With": "XMLHttpRequest"
  100.                         },
  101.                     }).then(response => {
  102.                         if (response.status < 300) {
  103.                             return response.text();
  104.                         } else {
  105.                             console.warn("🤔");
  106.                             return null;
  107.                         }
  108.                     }).then(response => {
  109.                         document.querySelector('#map_form').innerHTML = response;
  110.                         filterData();
  111.                         setFormSubmitListener();
  112.                     });
  113.                 }
  114.                 function filterData() {
  115.                     preloader.style.display = 'block';
  116.                     var data = {};
  117.                     $("form[name="+formName+"]").serializeArray().forEach((object)=>{
  118.                         //"подгоняем" данные под формат, ожидаемый формой при сабмите
  119.                         var fieldName = object.name.toString().replace(formName + '[', '').replace(']', '');
  120.                         var clearFieldName = fieldName.substr(0, fieldName.indexOf('['));
  121.                         if(~fieldName.indexOf('[]')) {
  122.                             checkArrayIsInFormObject(clearFieldName, data);
  123.                             data[clearFieldName].push(object.value);
  124.                         } else if(~fieldName.indexOf('[m')) {
  125.                             if(!object.value)
  126.                                 return;
  127.                             checkObjectIsInFormObject(clearFieldName, data);
  128.                             if(~fieldName.indexOf('[min]'))
  129.                                 data[clearFieldName]['min'] = object.value;
  130.                             if(~fieldName.indexOf('[max]'))
  131.                                 data[clearFieldName]['max'] = object.value;
  132.                         } else {
  133.                             data[fieldName] = object.value;
  134.                         }
  135.                     });
  136.                     $.ajax({
  137.                         url:'{{ path('map.filter', {city:cityUriIdentity}) }}',
  138.                         type: "POST",
  139.                         dataType: "json",
  140.                         data: {
  141.                             "form": JSON.stringify(data),
  142.                         },
  143.                         async: true,
  144.                         success: function (return_data) {
  145.                             // console.log(return_data);
  146.                             getDetailsData({
  147.                                 data: return_data,
  148.                                 callback: (points) => updateMap(points)
  149.                             })
  150.                             preloader.style.display = 'none';
  151.                         },
  152.                         error: function (xhr, ajaxOptions, thrownError) {}
  153.                     });
  154.                 }
  155.                 function checkArrayIsInFormObject(name, formObject) {
  156.                     if(false == formObject.hasOwnProperty(name))
  157.                         formObject[name] = [];
  158.                 }
  159.                 function checkObjectIsInFormObject(name, formObject) {
  160.                     if(false == formObject.hasOwnProperty(name))
  161.                         formObject[name] = {};
  162.                 }
  163.                 function getDetailsData({data, callback}) {
  164.                     const profilesRawData = data.profiles || [];
  165.                     const saloonsRawData = data.saloons || [];
  166.                     const profilesAllId = profilesRawData.map(_data => _data[0]).flat();
  167.                     const saloonsAllId = saloonsRawData.map(_data => _data[0]).flat();
  168.                     const profileArray = Array.isArray(profilesAllId) ? profilesAllId : [];
  169.                     const saloonIdArray = Array.isArray(saloonsAllId) ? saloonsAllId : [];
  170.                     const requestBody = {};
  171.                     requestBody.profiles = profileArray;
  172.                     requestBody.saloons = saloonIdArray;
  173.                     fetch('{{ path('map.detail', {city:cityUriIdentity}) }}', {
  174.                         method: "POST",
  175.                         headers: {
  176.                             'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
  177.                             'X-Requested-With': 'XMLHttpRequest',
  178.                         },
  179.                         body: new URLSearchParams(requestBody).toString()
  180.                     })
  181.                     .then(response => response.json())
  182.                     .then(data => {
  183.                         const { profiles, saloons } = data;
  184.                         callback({ profiles, saloons });
  185.                     })
  186.                     .catch(error => console.error(error));
  187.                     {# $.ajax({
  188.                         url:'{{ path('map.detail', {city:cityUriIdentity}) }}',
  189.                         type: "POST",
  190.                         dataType: "json",
  191.                         data: {
  192.                             "profiles": profileArray.toString(),
  193.                             "saloons": saloonIdArray.toString(),
  194.                         },
  195.                         async: true,
  196.                         success: function (return_data) {
  197.                             console.log(return_data);
  198.                         },
  199.                         error: function (xhr, ajaxOptions, thrownError) {}
  200.                     }); #}
  201.                 }
  202.                 function updateMap(points) {
  203.                     clusterer.removeAll();
  204.                     if (!points || (points.profiles.length == 0 && points.saloons.length == 0)) return
  205.                     const mergedPoints = [...points.profiles, ...points.saloons];
  206.                     var getImgUrl = function(path, imgType) {
  207.                         if(path[0] == '/')
  208.                             return path;
  209.                             console.log(imgType)
  210.                             console.log(photoPath)
  211.                             console.log(thumbPath)
  212.                         var assetPackagePath = '';
  213.                         if(imgType == 'avatar')
  214.                             assetPackagePath = avatarPath;
  215.                         else if(imgType == 'photo')
  216.                             assetPackagePath = photoPath; // /media/profiles/vp/rd/vprdP4ShlKUpkOB.jpg
  217.                         else if(imgType == 'thumb')
  218.                             assetPackagePath = thumbPath; // /media/saloons/thumb///.jpg
  219.                         return `${assetPackagePath}${path.slice(0, 2).toLowerCase()}/${path.slice(2, 4).toLowerCase()}/${path}.jpg`;
  220.                     };
  221.                     var getPointData = function (point) {
  222.                         const isProfile = point[0] == 1;
  223.                         const isSaloon = point[0] == 2;
  224.                         let url = '';
  225.                         const uri = point[3];
  226.                         if(isProfile) {
  227.                             url = RoutingDecorator.generate(
  228.                                 'profile_preview.page',
  229.                                 multipleCities ? {city: cityUriIdentity, profile: uri} : {profile: uri}
  230.                             );
  231.                         } else if(isSaloon) {
  232.                             url = RoutingDecorator.generate(
  233.                                 'saloon_preview.page',
  234.                                 multipleCities ? {city: cityUriIdentity, saloon: uri} : {saloon: uri}
  235.                             );
  236.                         }
  237.                         var processProfileShowsUrl = '{{ path('map.increment_profile_shows', multipleCities ? {city:cityUriIdentity} : {}) }}';
  238.                         return {
  239.                             balloonContentHeader: '',
  240.                             balloonContentBody: '<p><img src="' + getImgUrl(point[5], isProfile ? 'avatar' : 'thumb') + '" width="100" /></p>' + '<font size=3><b><a target="_blank" href="' + url + '">Профиль</a></b></font>'
  241.                                 + '<img style="display:none;" width="0" height="0" src="' + processProfileShowsUrl + '?id=' + (isProfile ? point[9] : null)+'" />', //не убирать, функционально важно
  242.                             balloonContentFooter: '<font size=1>' + point[8] + ',' + point[9] + ',' + point[10] + '</strong>',
  243.                             clusterCaption: '<strong>' + (isSaloon ? 'Салон ' : '') + point[4] + '</strong>'
  244.                         };
  245.                     };
  246.                     var getPointOptions = function (index, type) {
  247.                         return {
  248.                             preset: type == 'profile' ? 'islands#violetIcon' : 'islands#redIcon'
  249.                         };
  250.                     };
  251.                     var geoObjects = [];
  252.                     for(var i = 0, len = mergedPoints.length; i < len; i++) {
  253.                         const _point = mergedPoints[i];
  254.                         geoObjects[i] = new ymaps.Placemark([_point[1], _point[2]], getPointData(_point), getPointOptions(i, _point[0] == 1));
  255.                     }
  256.                     //В кластеризатор можно добавить javascript-массив меток (не геоколлекцию) или одну метку.
  257.                     clusterer.add(geoObjects);
  258.                     myMap.geoObjects.add(clusterer);
  259.                     // Спозиционируем карту так, чтобы на ней были видны все объекты.
  260.                     myMap.setBounds(clusterer.getBounds(), {
  261.                         checkZoomRange: true
  262.                     });
  263.                 }
  264.             });
  265.         })();
  266.     </script>
  267. {% endblock %}