1(function($) { 2 'use strict'; 3 4 var configuredShopId = window.PROSKTR && window.PROSKTR.shop 5 ? window.PROSKTR.shop.id 6 : ''; 7 var adapterConstructor = configuredShopId === 'PRO' 8 ? window.ProShopsMapAdapter 9 : window.ymapsShopsMapAdatderNew; 10 if ( configuredShopId === 'BBNG' ) { 11 adapterConstructor = window.ProShopsMapAdapter; 12 } 13 14 if ( 15 !$ 16 || !$.map 17 || !$.map.shopsMap 18 || typeof adapterConstructor !== 'function' 19 ) { 20 return; 21 } 22 23 var adapterPrototype = adapterConstructor.prototype; 24 25 function getRequestSignature(values) { 26 values = values || {}; 27 var keys = [ 28 'city', 29 'zone_id', 30 'country', 31 'shop_id', 32 'pvzResourcesFlag', 33 'price', 34 'weight', 35 'product_group', 36 'noPostamat', 37 'free_shipping', 38 'full_prepay_discount_delivery', 39 'fitting', 40 'typesToFitting', 41 'hideButtons', 42 'dateSendActual' 43 ]; 44 var signature = {}; 45 46 for ( var i = 0; i < keys.length; i++ ) { 47 signature[keys[i]] = typeof values[keys[i]] === 'undefined' ? null : values[keys[i]]; 48 } 49 if ( typeof signature.city === 'string' ) { 50 signature.city = signature.city.toLowerCase(); 51 } 52 return JSON.stringify(signature); 53 } 54 55 function isCoffeeShop() { 56 return !!( 57 window.PROSKTR 58 && window.PROSKTR.shop 59 && ['COFFEE', 'SOVA', 'COAL'].indexOf(window.PROSKTR.shop.id) !== -1 60 ); 61 } 62 63 function isIridatoShop() { 64 return !!( 65 window.PROSKTR 66 && window.PROSKTR.shop 67 && window.PROSKTR.shop.id === 'IRIDATO' 68 ); 69 } 70 71 function isTimeShop() { 72 return !!( 73 window.PROSKTR 74 && window.PROSKTR.shop 75 && window.PROSKTR.shop.id === 'TIME' 76 ); 77 } 78 79 function isTwoXuShop() { 80 return !!( 81 window.PROSKTR 82 && window.PROSKTR.shop 83 && window.PROSKTR.shop.id === '2XU' 84 ); 85 } 86 87 function isBackShop() { 88 return !!( 89 window.PROSKTR 90 && window.PROSKTR.shop 91 && window.PROSKTR.shop.id === 'BACK' 92 ); 93 } 94 95 function isProShop() { 96 return !!( 97 window.PROSKTR 98 && window.PROSKTR.shop 99 && window.PROSKTR.shop.id === 'PRO' 100 ); 101 } 102 103 function isBillabongShop() { 104 return !!( 105 window.PROSKTR 106 && window.PROSKTR.shop 107 && window.PROSKTR.shop.id === 'BBNG' 108 ); 109 } 110 111 function usesResilientInitialMapLoading() { 112 if ( isBillabongShop() ) { 113 return true; 114 } 115 return isCoffeeShop() 116 || isIridatoShop() 117 || isTimeShop() 118 || isLoveShop() 119 || isTwoXuShop() 120 || isBackShop() 121 || isProShop(); 122 } 123 124 function usesLiveMapOpenerContext() { 125 return usesResilientInitialMapLoading(); 126 } 127 128 function ensureBackMapCityOption(widget, city) { 129 if ( !widget || !widget.citySelect || !widget.citySelect.is('select') || typeof city !== 'string' ) { 130 return; 131 } 132 var cityText = $.trim(city); 133 var cityValue = cityText.toLowerCase(); 134 if ( !cityValue ) { 135 return; 136 } 137 var option = widget.citySelect.find('option').filter(function() { 138 return String($(this).val() || '').toLowerCase() === cityValue; 139 }).first(); 140 if ( !option.length ) { 141 option = $('<option>').val(cityValue).text(cityText).appendTo(widget.citySelect); 142 } 143 widget.citySelect.val(option.val()); 144 } 145 146 function isLoveShop() { 147 return !!( 148 window.PROSKTR 149 && window.PROSKTR.shop 150 && window.PROSKTR.shop.id === 'LOVE' 151 ); 152 } 153 154 function enableLovePointPrefetch(adapter) { 155 var events = adapter 156 && adapter.objectManager 157 && adapter.objectManager.objects 158 && adapter.objectManager.objects.events; 159 if ( 160 !isLoveShop() 161 || !adapter 162 || !adapter.shopsMap 163 || typeof adapter.shopsMap.prefetchPointDetails !== 'function' 164 || !events 165 || adapter._lovePointPrefetchEvents === events 166 ) { 167 return; 168 } 169 170 adapter._lovePointPrefetchEvents = events; 171 var prefetchTimer = null; 172 var prefetchPointId = null; 173 var prefetch = function(pointId) { 174 adapter.shopsMap.prefetchPointDetails(pointId); 175 }; 176 var schedulePrefetch = function(event) { 177 var pointId = event.get('objectId'); 178 window.clearTimeout(prefetchTimer); 179 prefetchPointId = pointId; 180 prefetchTimer = window.setTimeout(function() { 181 prefetch(pointId); 182 }, 60); 183 }; 184 var startPrefetch = function(event) { 185 window.clearTimeout(prefetchTimer); 186 prefetch(event.get('objectId')); 187 }; 188 189 events.add('mouseenter', schedulePrefetch); 190 events.add(['mousedown', 'touchstart'], startPrefetch); 191 events.add('mouseleave', function(event) { 192 if ( prefetchPointId === event.get('objectId') ) { 193 window.clearTimeout(prefetchTimer); 194 prefetchPointId = null; 195 } 196 }); 197 } 198 199 function usesDefaultPointDetailsErrorUi(widget) { 200 return !widget.options || typeof widget.options.pointLoadingEndEvent !== 'function'; 201 } 202 203 function ensureCoffeeMapFilter(adapter) { 204 if ( 205 !isCoffeeShop() 206 || !adapter 207 || !adapter.map 208 || !adapter.objectManager 209 || !window.ymaps 210 ) { 211 return; 212 } 213 214 var points = adapter.objectManager.objects.getAll(); 215 var available = { 216 cod: false,
217 round_the_clock: false, 218 cdek: false, 219 yandexgo: false, 220 fivepost: false, 221 boxberry: false 222 }; 223 var labels = { 224 cod: 'ÐплаÑа пÑи полÑÑении', 225 round_the_clock: '24 ÑаÑа', 226 cdek: 'СÐÐÐ', 227 yandexgo: 'ЯндекÑ', 228 fivepost: 'ÐÑÑÑÑоÑка (5Post)', 229 boxberry: 'BoxBerry' 230 }; 231 232 for ( var i = 0; i < points.length; i++ ) { 233 var properties = points[i].properties || {}; 234 available.cod = available.cod || !!properties.cod || !!properties.pay_card || !!properties.point_cash; 235 available.round_the_clock = available.round_the_clock || !!properties.round_the_clock; 236 if ( typeof available[properties.delivery] !== 'undefined' ) { 237 available[properties.delivery] = true; 238 } 239 } 240 241 var filterOrder = ['cod', 'round_the_clock', 'cdek', 'yandexgo', 'fivepost', 'boxberry']; 242 var listBoxItems = []; 243 for ( var j = 0; j < filterOrder.length; j++ ) { 244 var filterValue = filterOrder[j]; 245 if ( !available[filterValue] ) { 246 continue; 247 } 248 listBoxItems.push(new ymaps.control.ListBoxItem({ 249 data: { 250 content: labels[filterValue], 251 filterValue: filterValue 252 }, 253 state: { 254 selected: false 255 } 256 })); 257 } 258 259 if ( adapter.listBoxControl ) { 260 adapter.map.controls.remove(adapter.listBoxControl); 261 } 262 if ( !listBoxItems.length ) { 263 adapter.listBoxControl = null; 264 return; 265 } 266 267 var reduceFilters = function(filters, filter) { 268 filters[filter.data.get('filterValue')] = filter.isSelected(); 269 return filters; 270 }; 271 adapter.listBoxControl = new ymaps.control.ListBox({ 272 data: { 273 content: 'ФилÑÑÑ', 274 title: 'ФилÑÑÑ' 275 }, 276 items: listBoxItems, 277 state: { 278 expanded: false, 279 filters: listBoxItems.reduce(reduceFilters, {}) 280 } 281 }); 282 adapter.map.controls.add(adapter.listBoxControl); 283 284 adapter.listBoxControl.events.add(['select', 'deselect'], function(event) { 285 var listBoxItem = event.get('target'); 286 var filters = ymaps.util.extend({}, adapter.listBoxControl.state.get('filters')); 287 filters[listBoxItem.data.get('filterValue')] = listBoxItem.isSelected(); 288 adapter.listBoxControl.state.set('filters', filters); 289 }); 290 291 var filterMonitor = new ymaps.Monitor(adapter.listBoxControl.state); 292 filterMonitor.add('filters', function(filters) { 293 adapter.objectManager.setFilter(function(object) { 294 var properties = object.properties || {}; 295 if ( filters.cod && !(properties.cod || properties.pay_card || properties.point_cash) ) { 296 return false; 297 } 298 if ( filters.round_the_clock && !properties.round_the_clock ) { 299 return false; 300 } 301 302 var selectedDeliveries = []; 303 var deliveryFilters = ['cdek', 'yandexgo', 'fivepost', 'boxberry']; 304 for ( var k = 0; k < deliveryFilters.length; k++ ) { 305 if ( filters[deliveryFilters[k]] ) { 306 selectedDeliveries.push(deliveryFilters[k]); 307 } 308 } 309 return !selectedDeliveries.length || selectedDeliveries.indexOf(properties.delivery) !== -1; 310 }); 311 }); 312 } 313 314 function showPointLoading(widget, pointId) { 315 var checkedWrapper = $('.store-item-checked', widget.element); 316 $('.store-page__list', widget.element).addClass('d-none'); 317 checkedWrapper 318 .data('loading-point-id', String(pointId)) 319 .addClass('is-loading') 320 .removeAttr('hidden') 321 .removeClass('d-none hidden') 322 .show(); 323 } 324 325 function hidePointLoading(widget, pointId, hideWrapper) { 326 var checkedWrapper = $('.store-item-checked', widget.element); 327 if ( 328 typeof pointId !== 'undefined' 329 && checkedWrapper.data('loading-point-id') !== String(pointId) 330 ) { 331 return; 332 } 333 checkedWrapper.removeClass('is-loading').removeData('loading-point-id'); 334 if ( hideWrapper ) { 335 checkedWrapper.addClass('d-none'); 336 } 337 } 338 339 function clearPointDetailsError(widget) { 340 $('.store-item-checked', widget.element) 341 .removeClass('has-load-error') 342 .find('.store-load-error') 343 .remove(); 344 } 345 346 function showPointDetailsError(widget, pointId, loadError) { 347 var checkedWrapper = $('.store-item-checked', widget.element); 348 var message = loadError === 'timeout' 349 ? '\u0421\u0435\u0440\u0432\u0435\u0440 \u043e\u0442\u0432\u0435\u0447\u0430\u0435\u0442 \u0434\u043e\u043b\u044c\u0448\u0435 \u043e\u0431\u044b\u0447\u043d\u043e\u0433\u043e. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.' 350 : '\u041f\u0440\u043e\u0432\u0435\u0440\u044c\u0442\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u0435 \u0438 \u043f\u043e\u043f\u0440\u043e\u0431\u0443\u0439\u0442\u0435 \u0435\u0449\u0451 \u0440\u0430\u0437.'; 351 var error = $('<div/>', { 352 'class': 'store-load-error', 353 'role': 'alert' 354 }); 355 356 hidePointLoading(widget, pointId, false); 357 clearPointDetailsError(widget); 358 $('<strong/>').text('\u041d\u0435 \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u0442\u044c \u043f\u0443\u043d\u043a\u0442 \u0432\u044b\u0434\u0430\u0447\u0438').appendTo(error); 359 $('<span/>').text(message).appendTo(error); 360 $('<button/>', { 361 'type': 'button', 362 'class': 'btn js-default-pvz-details-retry', 363 'data-point-id': pointId, 364 'text': '\u041f\u043e\u0432\u0442\u043e\u0440\u0438\u0442\u044c' 365 }).appendTo(error); 366 checkedWrapper 367 .addClass('has-load-error') 368 .removeAttr('hidden') 369 .removeClass('d-none hidden') 370 .show()
371 .append(error); 372 } 373 374 function resetPointDetailsRetry(widget, pointId) { 375 var key = String(pointId); 376 widget._backPointRetryAttempts = widget._backPointRetryAttempts || {}; 377 widget._backPointRetryTimers = widget._backPointRetryTimers || {}; 378 if ( widget._backPointRetryTimers[key] ) { 379 window.clearTimeout(widget._backPointRetryTimers[key]); 380 delete widget._backPointRetryTimers[key]; 381 } 382 delete widget._backPointRetryAttempts[key]; 383 } 384 385 function retryPointDetails(widget, pointId, feature, loadError) { 386 if ( !usesDefaultPointDetailsErrorUi(widget) || loadError === 'abort' ) { 387 return false; 388 } 389 390 var key = String(pointId); 391 widget._backPointRetryAttempts = widget._backPointRetryAttempts || {}; 392 widget._backPointRetryTimers = widget._backPointRetryTimers || {}; 393 if ( (widget._backPointRetryAttempts[key] || 0) >= 1 ) { 394 return false; 395 } 396 397 widget._backPointRetryAttempts[key] = (widget._backPointRetryAttempts[key] || 0) + 1; 398 widget._backPointRetryTimers[key] = window.setTimeout(function() { 399 delete widget._backPointRetryTimers[key]; 400 if ( 401 String(widget._backActivePointId) === key 402 && !widget._backPointDetails[pointId] 403 && !widget._backPointRequests[pointId] 404 ) { 405 widget._loadBackPointDetails(pointId, widget.map.getPointById(pointId) || feature); 406 return; 407 } 408 resetPointDetailsRetry(widget, pointId); 409 }, 300); 410 return true; 411 } 412 413 function resetBackPointSelection(widget) { 414 widget._backActivePointId = null; 415 widget._backSelectedPointId = null; 416 var pointRequests = widget._backPointRequests || {}; 417 for ( var pointId in pointRequests ) { 418 if ( Object.prototype.hasOwnProperty.call(pointRequests, pointId) 419 && pointRequests[pointId] 420 && typeof pointRequests[pointId].abort === 'function' ) { 421 pointRequests[pointId].abort(); 422 } 423 } 424 var retryTimers = widget._backPointRetryTimers || {}; 425 for ( var retryPointId in retryTimers ) { 426 if ( Object.prototype.hasOwnProperty.call(retryTimers, retryPointId) ) { 427 window.clearTimeout(retryTimers[retryPointId]); 428 } 429 } 430 widget._backPointRequests = {}; 431 widget._backPointRetryAttempts = {}; 432 widget._backPointRetryTimers = {}; 433 434 var objectBalloon = widget.map 435 && widget.map.objectManager 436 && widget.map.objectManager.objects 437 && widget.map.objectManager.objects.balloon; 438 if ( objectBalloon && typeof objectBalloon.close === 'function' ) { 439 objectBalloon.close(); 440 } 441 hidePointLoading(widget, undefined, true); 442 clearPointDetailsError(widget); 443 $('.store-item-checked', widget.element) 444 .stop(true, true) 445 .removeClass('is-loading has-load-error') 446 .removeData('loading-point-id') 447 .addClass('d-none') 448 .hide(); 449 if ( widget.element && typeof widget.element.trigger === 'function' ) { 450 widget.element.trigger('backShopsMapSelectionReset'); 451 } 452 } 453 454 $.widget('map.shopsMap', $.map.shopsMap, { 455 options: { 456 pointDetailsTimeout: 15000, 457 initialRequestTimeout: 20000 458 }, 459 _getCitiesList: function() { 460 ensureBackMapCityOption(this, this.options.city); 461 return $.Deferred().resolve().promise(); 462 }, 463 _getMetroByCity: function() { 464 return false; 465 }, 466 _getBackRequestSignature: function(values) { 467 return getRequestSignature($.extend({}, this.getPointsValues || {}, values || {})); 468 }, 469 canReuseBackMap: function(options) { 470 return !!this._backInitialLoaded 471 && this._backRequestSignature === this._getBackRequestSignature(options); 472 }, 473 refreshBackViewport: function() { 474 if ( this.map && typeof this.map.fitToViewport === 'function' ) { 475 this.map.fitToViewport(); 476 } 477 }, 478 reloadBackMap: function(options) { 479 var previousSignature = this._getBackRequestSignature(); 480 var keys = [ 481 'city', 482 'zone_id', 483 'country', 484 'shop_id', 485 'pvzResourcesFlag', 486 'price', 487 'weight', 488 'product_group', 489 'noPostamat', 490 'free_shipping', 491 'full_prepay_discount_delivery', 492 'fitting', 493 'typesToFitting', 494 'dateSendActual' 495 ]; 496 options = options || {}; 497 ensureBackMapCityOption(this, options.city); 498 for ( var i = 0; i < keys.length; i++ ) { 499 if ( typeof options[keys[i]] !== 'undefined' ) { 500 this.options[keys[i]] = options[keys[i]]; 501 this.getPointsValues[keys[i]] = options[keys[i]]; 502 } 503 } 504 if ( previousSignature !== this._getBackRequestSignature() ) { 505 this._backInitialRetryCount = 0; 506 } 507 this.getPoints(); 508 }, 509 _setOptions: function(options) { 510 var refreshProMap = isProShop() && !!this._backRequestSignature; 511 if ( isBillabongShop() && this._backRequestSignature ) { 512 refreshProMap = true; 513 } 514 var sameProMapRequest = refreshProMap 515 && this._backRequestSignature === this._getBackRequestSignature(options); 516 if ( refreshProMap ) { 517 resetBackPointSelection(this); 518 } 519 if ( options ) { 520 ensureBackMapCityOption(this, options.city); 521 } 522 var result = this._super(options); 523 if ( refreshProMap ) { 524 if ( sameProMapRequest && this._backInitialLoaded ) { 525 var widget = this; 526 setTimeout(function() { 527 widget.refreshBackViewport(); 528 hideCoffeeMapLoading(); 529 }, 0); 530 } else if ( !this._backInitialRequest ) { 531 this.reloadBackMap(options); 532 } 533 } 534 return result; 535 }, 536 getPoints: function() { 537 resetBackPointSelection(this); 538 if ( this.element && this.element[0] ) { 539 this.element[0].backShopsMapWidget = this; 540 } 541 if ( usesResilientInitialMapLoading() ) { 542 prepareCoffeeMapLoading(); 543 } 544 this._backInitialRequestGeneration = (this._backInitialRequestGeneration || 0) + 1; 545 var requestGeneration = this._backInitialRequestGeneration; 546 clearTimeout(this._backBoundsTimer); 547 clearTimeout(this._backInitialRetryTimer); 548 if ( this._backInitialRequest ) { 549 this._backInitialRequest.abort(); 550 } 551 if ( this._backBoundsRequest ) { 552 this._backBoundsRequest.abort(); 553 } 554 555 this._clear(); 556 this.pointListDiv.addClass('ajax-loading'); 557 this._backLoadedPointIds = {}; 558 this._backPointDetails = {}; 559 this._backPointRequests = {}; 560 this._backInitialLoaded = false;
561 this._backLastBoundsKey = null; 562 this._backBoundsLoadQueued = false; 563 this._backLoadedBoundsKeys = {}; 564 this._backRequestSignature = this._getBackRequestSignature(); 565 this.element.removeData('back-map-loaded'); 566 if ( this.mapLoading ) { 567 this.mapLoading.addClass('loading'); 568 } 569 570 var data = $.extend({}, this.getPointsValues, {backGeoJson: 1}); 571 var initialRequest = $.ajax({ 572 url: this.options.pointsSourceUrl, 573 method: 'POST', 574 dataType: this.options.dataType, 575 context: this, 576 timeout: this.options.initialRequestTimeout, 577 data: data 578 }).done(function(msg) { 579 if ( this._backInitialRequestGeneration !== requestGeneration ) { 580 return; 581 } 582 if ( !msg || !msg.geoJson || !msg.mapCenter ) { 583 this._backInitialRequestFailed = true; 584 return; 585 } 586 this.pointListDiv.removeClass('ajax-loading'); 587 this._registerBackGeoJson(msg.geoJson); 588 this.map.addGeoJson(msg.geoJson, false); 589 var initialBoundsKey = this._getBackBoundsKey(msg.bounds); 590 if ( initialBoundsKey ) { 591 this._backLoadedBoundsKeys[initialBoundsKey] = true; 592 } 593 this.distanceFrom = msg.mapCenter; 594 this.map.setMapCenter(msg.mapCenter, this.options.startMapZoom || 10); 595 this._backInitialLoaded = true; 596 this.element.data('back-map-loaded', true); 597 this._toggleFiltrs(); 598 this.putPoints(); 599 if ( (isProShop() || isBillabongShop()) && msg.selectedPoint ) { 600 this._restoreProSelectedPoint(msg.selectedPoint); 601 } 602 this.options.pointsDrawed(this.element); 603 this._scheduleVisibleBackPointsLoad(); 604 if ( usesResilientInitialMapLoading() ) { 605 this._backInitialRetryCount = 0; 606 waitForCoffeeMapRender(this, requestGeneration); 607 } 608 }).fail(function(xhr, status) { 609 if ( 610 this._backInitialRequestGeneration !== requestGeneration 611 || status === 'abort' 612 ) { 613 return; 614 } 615 this._backInitialRequestFailed = true; 616 }).always(function() { 617 if ( this._backInitialRequestGeneration !== requestGeneration ) { 618 return; 619 } 620 this.pointListDiv.removeClass('ajax-loading'); 621 if ( this._backInitialRequest === initialRequest ) { 622 this._backInitialRequest = null; 623 } 624 if ( !this._backInitialRequestFailed ) { 625 return; 626 } 627 628 this._backInitialRequestFailed = false; 629 if ( !usesResilientInitialMapLoading() ) { 630 if ( this.mapLoading ) { 631 this.mapLoading.removeClass('loading'); 632 } 633 return; 634 } 635 636 this._backInitialRetryCount = (this._backInitialRetryCount || 0) + 1; 637 if ( this._backInitialRetryCount > 3 ) { 638 showCoffeeMapRetry(this, 'Ðе ÑдалоÑÑ Ð·Ð°Ð³ÑÑзиÑÑ ÐºÐ°ÑÑÑ.<br>ÐажмиÑе, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð²ÑоÑиÑÑ'); 639 return; 640 } 641 setCoffeeMapLoadingText('ÐагÑÑзка каÑÑÑ Ð·Ð°Ð½Ñла болÑÑе вÑемени.<br>ÐовÑоÑÑем запÑоÑ...'); 642 643 var widget = this; 644 var delay = Math.min(400 * this._backInitialRetryCount, 1600); 645 this._backInitialRetryTimer = setTimeout(function() { 646 if ( widget._backInitialRequestGeneration === requestGeneration ) { 647 widget.getPoints(); 648 } 649 }, delay); 650 }); 651 this._backInitialRequest = initialRequest; 652 }, 653 _registerBackGeoJson: function(geoJson) { 654 if ( !geoJson || !geoJson.features ) { 655 return; 656 } 657 this.availableFiltrs = this.availableFiltrs || {}; 658 this.availableFiltrs.filtr = this.availableFiltrs.filtr || {}; 659 this.availableFiltrs.filtr_delivery = this.availableFiltrs.filtr_delivery || {}; 660 var filterNames = ['cod', 'pay_card', 'round_the_clock', 'primerka', 'free_cost']; 661 for ( var filterIndex = 0; filterIndex < filterNames.length; filterIndex++ ) { 662 this.availableFiltrs.filtr[filterNames[filterIndex]] = this.availableFiltrs.filtr[filterNames[filterIndex]] || {}; 663 } 664 for ( var i = 0; i < geoJson.features.length; i++ ) { 665 var feature = geoJson.features[i]; 666 var point = feature.properties; 667 this._backLoadedPointIds[feature.id] = true; 668 this.availableFiltrs.filtr.cod[point.cod ? 1 : 0] = true; 669 this.availableFiltrs.filtr.pay_card[point.pay_card ? 1 : 0] = true; 670 this.availableFiltrs.filtr.round_the_clock[point.round_the_clock ? 1 : 0] = true; 671 this.availableFiltrs.filtr.primerka[point.primerka ? 1 : 0] = true; 672 this.availableFiltrs.filtr.free_cost[point.free_cost ? 1 : 0] = true; 673 this.availableFiltrs.filtr_delivery[point.delivery] = true; 674 } 675 }, 676 _scheduleVisibleBackPointsLoad: function() { 677 var widget = this; 678 clearTimeout(this._backBoundsTimer); 679 this._backBoundsTimer = setTimeout(function() { 680 widget._loadVisibleBackPoints(); 681 }, 250); 682 },
683 _getBackBoundsKey: function(bounds) { 684 if ( !bounds || bounds.length !== 2 ) { 685 return ''; 686 } 687 var step = 0.02; 688 return JSON.stringify([ 689 [ 690 Math.floor((bounds[0][0] + 1e-9) / step) * step, 691 Math.floor((bounds[0][1] + 1e-9) / step) * step 692 ], 693 [ 694 Math.ceil((bounds[1][0] - 1e-9) / step) * step, 695 Math.ceil((bounds[1][1] - 1e-9) / step) * step 696 ] 697 ]); 698 }, 699 _loadVisibleBackPoints: function() { 700 if ( !this._backInitialLoaded ) { 701 return; 702 } 703 var bounds = this.map.getBounds(); 704 if ( !bounds || bounds.length !== 2 ) { 705 return; 706 } 707 var boundsKey = this._getBackBoundsKey(bounds); 708 if ( boundsKey === this._backLastBoundsKey || this._backLoadedBoundsKeys[boundsKey] ) { 709 return; 710 } 711 if ( this._backBoundsRequest ) { 712 this._backBoundsLoadQueued = true; 713 return; 714 } 715 716 this._backLastBoundsKey = boundsKey; 717 this._backLoadedBoundsKeys[boundsKey] = true; 718 this._backBoundsLoadQueued = false; 719 var data = $.extend({}, this.getPointsValues, { 720 backGeoJson: 1, 721 bounds: JSON.stringify(bounds) 722 }); 723 this._backBoundsRequest = $.ajax({ 724 url: this.options.pointsSourceUrl, 725 method: 'POST', 726 dataType: this.options.dataType, 727 context: this, 728 global: false, 729 data: data 730 }).done(function(msg) { 731 if ( !msg.geoJson || !msg.geoJson.features ) { 732 return; 733 } 734 msg.geoJson.features = msg.geoJson.features.filter(function(feature) { 735 return !this._backLoadedPointIds[feature.id]; 736 }, this); 737 if ( msg.geoJson.features.length ) { 738 this._registerBackGeoJson(msg.geoJson); 739 this.map.addGeoJson(msg.geoJson, true); 740 this._toggleItemsByFiltrs(); 741 } 742 }).fail(function() { 743 this._backLastBoundsKey = null; 744 delete this._backLoadedBoundsKeys[boundsKey]; 745 }).always(function() { 746 this._backBoundsRequest = null; 747 if ( this._backBoundsLoadQueued ) { 748 this._backBoundsLoadQueued = false; 749 this._scheduleVisibleBackPointsLoad(); 750 } 751 }); 752 }, 753 pointClickEvent: function(id) { 754 var feature = this.map.getPointById(id); 755 if ( !feature ) { 756 return; 757 } 758 if ( usesDefaultPointDetailsErrorUi(this) ) { 759 var checkedWrapper = $('.store-item-checked', this.element); 760 if ( checkedWrapper.hasClass('has-load-error') ) { 761 resetPointDetailsRetry(this, id); 762 } 763 clearPointDetailsError(this); 764 } 765 this._backActivePointId = id; 766 if ( this._backPointDetails[id] ) { 767 if ( usesDefaultPointDetailsErrorUi(this) ) { 768 resetPointDetailsRetry(this, id); 769 } 770 this._emitBackPointClick(this._backPointDetails[id], feature.geometry.coordinates); 771 return; 772 } 773 774 if ( typeof this.options.pointLoadingEvent === 'function' ) { 775 this.options.pointLoadingEvent.apply(this.element, [id, feature.geometry.coordinates]); 776 } else { 777 showPointLoading(this, id); 778 } 779 if ( this._backPointRequests[id] ) { 780 return; 781 } 782 this._loadBackPointDetails(id, feature); 783 }, 784 prefetchPointDetails: function(id) { 785 if ( this._backPointDetails[id] || this._backPointRequests[id] ) { 786 return; 787 } 788 var feature = this.map.getPointById(id); 789 if ( !feature ) { 790 return; 791 } 792 this._loadBackPointDetails(id, feature); 793 }, 794 _loadBackPointDetails: function(id, feature) { 795 796 var pointLoaded = false; 797 var loadError = 'error'; 798 var data = $.extend({}, this.getPointsValues, { 799 pointId: id, 800 backGeoJson: 1 801 }); 802 this._backPointRequests[id] = $.ajax({ 803 url: '/ajax_shopsMap.php?action=getPointDetails', 804 method: 'POST', 805 dataType: this.options.dataType, 806 context: this, 807 global: false, 808 timeout: this.options.pointDetailsTimeout, 809 data: data 810 }).done(function(msg) { 811 if ( !msg.point ) { 812 loadError = 'empty'; 813 return; 814 } 815 pointLoaded = true; 816 if ( usesDefaultPointDetailsErrorUi(this) ) { 817 resetPointDetailsRetry(this, id); 818 clearPointDetailsError(this); 819 } 820 var properties = this._buildBackPointProperties(msg.point, feature.properties); 821 this._backPointDetails[id] = properties; 822 if ( this._backActivePointId === id ) { 823 this._emitBackPointClick(properties, feature.geometry.coordinates); 824 } 825 }).fail(function(jqXHR, textStatus) { 826 loadError = textStatus || 'error'; 827 }).always(function() { 828 delete this._backPointRequests[id]; 829 if ( !pointLoaded && this._backActivePointId === id ) { 830 if ( retryPointDetails(this, id, feature, loadError) ) { 831 return; 832 } 833 if ( typeof this.options.pointLoadingEndEvent === 'function' ) { 834 this.options.pointLoadingEndEvent.apply(this.element, [id, loadError]); 835 } else if ( usesDefaultPointDetailsErrorUi(this) ) { 836 showPointDetailsError(this, id, loadError); 837 } else { 838 hidePointLoading(this, id, true); 839 } 840 } 841 }); 842 }, 843 _buildBackPointProperties: function(point, baseProperties) { 844 var pointCost = parseFloat(point.cost) || 0; 845 var startPrice = point.price_info && point.price_info.start_price 846 ? parseFloat(point.price_info.start_price) || 0 847 : 0; 848 var displayCost = pointCost; 849 if ( 850 window.PROSKTR 851 && PROSKTR.shop 852 && PROSKTR.shop.id === 'LOVE' 853 && displayCost === 0 854 && startPrice > 0 855 ) { 856 displayCost = startPrice; 857 } 858 return $.extend({}, baseProperties, { 859 title: point.title, 860 delivery: point.point_resourse, 861 round_the_clock: point.round_the_clock, 862 point_cash: point.point_cash, 863 pay_card: point.pay_card, 864 primerka: point.primerka > 0, 865 free_cost: point.cost == 0 || point.fullPrepayFreeDelivery ? 1 : 0, 866 cod: point.pay_card > 0 || point.point_cash > 0, 867 point_metro: point.point_metro, 868 pointId: point.point_id, 869 point_ident: point.point_ident, 870 point_city: point.point_city, 871 dates: point.dates, 872 delivery_name: point.delivery_name, 873 schedule: point.schedule, 874 address: point.point_address, 875 cost: point.cost, 876 display_cost: displayCost, 877 pvz_iml_date: point.select && point.select.length ? point.select[0].id : '', 878 storage_days: point.storage_days, 879 fitting: point.showFitting, 880 details_loaded: true 881 }); 882 }, 883 _restoreProSelectedPoint: function(point) { 884 var pointId = point && parseInt(point.point_id, 10); 885 var feature = pointId ? this.map.getPointById(pointId) : null; 886 if ( !feature ) { 887 return; 888 } 889 var properties = this._buildBackPointProperties(point, feature.properties); 890 this._backPointDetails[pointId] = properties; 891 this._backSelectedPointId = pointId; 892 this._backActivePointId = pointId; 893 if ( typeof this.map.openPoint === 'function' ) { 894 this.map.openPoint(pointId); 895 } 896 this._emitBackPointClick(properties, feature.geometry.coordinates); 897 }, 898 _emitBackPointClick: function(properties, coordinates) { 899 hidePointLoading(this); 900 if ( usesLiveMapOpenerContext() ) { 901 $('.store-item-checked', this.element) 902 .stop(true, true) 903 .removeAttr('hidden') 904 .removeClass('d-none hidden') 905 .show(); 906 } 907 this.options.pointClickEvent.apply(this.element, [properties, coordinates]); 908 }, 909 _createItem: function(point, pointId) { 910 this.availableFiltrs.filtr.cod[point.pay_card || point.point_cash] = true; 911 this.availableFiltrs.filtr.pay_card[point.pay_card] = true; 912 this.availableFiltrs.filtr.round_the_clock[point.round_the_clock] = true; 913 this.availableFiltrs.filtr.primerka[point.primerka] = true; 914 this.availableFiltrs.filtr.free_cost[point.cost == 0 || point.fullPrepayFreeDelivery] = true; 915 this.availableFiltrs.filtr_delivery[point.point_resourse] = true; 916 this.map.addPoint(point, pointId); 917 }, 918 _groupList: function(setCenter) { 919 var deferred = $.Deferred(); 920 if ( typeof setCenter === 'undefined' ) { 921 deferred.resolve(); 922 return deferred; 923 } 924 925 var points = this.map.getPoints(); 926 var maxDistances = [1000, 3000, 10000, Infinity]; 927 var maxDistance = maxDistances[Math.min(setCenter, maxDistances.length - 1)]; 928 var latitudes = [this.distanceFrom[0]]; 929 var longitudes = [this.distanceFrom[1]]; 930 931 for ( var i = 0; i < points.length; i++ ) { 932 var coordinates = this.map.getPointCoordinates(points[i]); 933 if ( this.map.getDistance(coordinates, this.distanceFrom) < maxDistance ) { 934 latitudes.push(coordinates[0]); 935 longitudes.push(coordinates[1]); 936 } 937 } 938 939 this._setMapCenter( 940 [ 941 [Math.min.apply(null, latitudes), Math.min.apply(null, longitudes)], 942 [Math.max.apply(null, latitudes), Math.max.apply(null, longitudes)] 943 ], 944 [ 945 latitudes.reduce(function(a, b) { return a + b; }) / latitudes.length, 946 longitudes.reduce(function(a, b) { return a + b; }) / longitudes.length 947 ] 948 ).done(function() { 949 deferred.resolve(); 950 }); 951 return deferred; 952 } 953 }); 954 955 if ( !adapterPrototype.optimizedViewportLoading ) { 956 var originalInit = adapterPrototype.init; 957 adapterPrototype.init = function(options) { 958 originalInit.apply(this, arguments); 959 enableLovePointPrefetch(this); 960 if ( !this.iconContentLayout && window.ymaps && ymaps.templateLayoutFactory ) { 961 this.iconContentLayout = ymaps.templateLayoutFactory.createClass( 962 '<div class="map-mark"><div class="map-mark-label">$[properties.delivery_name]<br>$[properties.cost_label]</div></div>' 963 ); 964 } 965 var adapter = this; 966 if ( this.map && this.map.events ) { 967 this.map.events.add('actionend', function() { 968 if ( 969 adapter.shopsMap 970 && typeof adapter.shopsMap._scheduleVisibleBackPointsLoad === 'function' 971 ) { 972 adapter.shopsMap._scheduleVisibleBackPointsLoad(); 973 } 974 }); 975 } 976 }; 977 adapterPrototype.optimizedViewportLoading = true; 978 } 979 980 adapterPrototype.addGeoJson = function(geoJson, append) { 981 if ( !geoJson || !geoJson.features ) { 982 return; 983 } 984 for ( var i = 0;
984 i < geoJson.features.length; i++ ) { 985 var pointOptions = { 986 iconLayout: this.hidePointLabels ? 'default#image' : 'default#imageWithContent', 987 draggable: false, 988 hideIconOnBallon: false, 989 iconImageHref: this.iDomain + this.iconsPoint.src, 990 iconImageSize: this.iconsPoint.size, 991 iconImageOffset: this.iconsPoint.offset 992 }; 993 if ( !this.hidePointLabels ) { 994 pointOptions.iconContentLayout = this.iconContentLayout; 995 } 996 geoJson.features[i].options = pointOptions; 997 } 998 if ( append ) { 999 this.objectManager.add(geoJson); 1000 if ( typeof this.refreshFilterControl === 'function' ) { 1001 this.refreshFilterControl(); 1002 } 1003 return; 1004 } 1005 this.pointsInfo = geoJson; 1006 this.addPoints(); 1007 }; 1008 adapterPrototype.getBounds = function() { 1009 return this.map.getBounds(); 1010 }; 1011 adapterPrototype.fitToViewport = function() { 1012 if ( this.map && this.map.container ) { 1013 this.map.container.fitToViewport(); 1014 } 1015 }; 1016 adapterPrototype.getPointById = function(id) { 1017 return this.objectManager.objects.getById(id); 1018 }; 1019 1020 if ( !adapterPrototype.optimizedRemoveAllPatched && typeof adapterPrototype.addPoints === 'function' ) { 1021 var originalAddPoints = adapterPrototype.addPoints; 1022 adapterPrototype.addPoints = function() { 1023 var events = this.listBoxControl && this.listBoxControl.events; 1024 if ( events && typeof events.removeAll !== 'function' ) { 1025 events.removeAll = function() { 1026 return this; 1027 }; 1028 } 1029 var result = originalAddPoints.apply(this, arguments); 1030 ensureCoffeeMapFilter(this); 1031 return result; 1032 }; 1033 adapterPrototype.optimizedRemoveAllPatched = true; 1034 } 1035 1036 function getWidget() { 1037 var popup = document.getElementById('map-popup'); 1038 return popup && ( 1039 popup.backShopsMapWidget 1040 || $('#map-popup').data('map-shopsMap') 1041 || $('#map-popup').data('shopsMap') 1042 ); 1043 } 1044 1045 function isMagnificMapPopup() { 1046 return $('#map-popup').hasClass('popupWindow') 1047 && $.magnificPopup 1048 && typeof $.magnificPopup.open === 'function'; 1049 } 1050 1051 function showMapPopup() { 1052 if ( isMagnificMapPopup() ) { 1053 $.magnificPopup.open({ 1054 items: { 1055 src: '#map-popup', 1056 type: 'inline' 1057 } 1058 }); 1059 return; 1060 } 1061 $('#map-popup').modal('show'); 1062 } 1063 1064 function prepareCoffeeMapLoading() { 1065 if ( !usesResilientInitialMapLoading() ) { 1066 return; 1067 } 1068 1069 var popup = $('#map-popup'); 1070 var mapHolder = popup.find('.map-holder').first(); 1071 var mapLoading = popup.find('#mapLoading'); 1072 1073 if ( isCoffeeShop() && mapHolder.length && mapLoading.length && !mapLoading.parent().is(mapHolder) ) { 1074 mapLoading.prependTo(mapHolder); 1075 } 1076 if ( isProShop() ) { 1077 mapLoading.find('.loader-text').text('\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u043f\u0443\u043d\u043a\u0442\u043e\u0432 \u0432\u044b\u0434\u0430\u0447\u0438'); 1078 } 1079 mapLoading 1080 .removeClass('retry-ready') 1081 .addClass('loading back-initial-loading'); 1082 } 1083 1084 function hideCoffeeMapLoading() { 1085 if ( usesResilientInitialMapLoading() ) { 1086 $('#map-popup #mapLoading').removeClass('loading back-initial-loading'); 1087 } 1088 } 1089 1090 function setCoffeeMapLoadingText(text) { 1091 if ( !usesResilientInitialMapLoading() ) { 1092 return; 1093 } 1094 $('#map-popup #mapLoading .loader-text').html(text); 1095 } 1096 1097 function showCoffeeMapRetry(widget, text) { 1098 if ( !usesResilientInitialMapLoading() ) { 1099 return; 1100 } 1101 var mapLoading = $('#map-popup #mapLoading'); 1102 mapLoading 1103 .data('retry-widget', widget) 1104 .addClass('loading back-initial-loading retry-ready'); 1105 setCoffeeMapLoadingText(text); 1106 } 1107 1108 function waitForCoffeeMapRender(widget, requestGeneration, attempt) { 1109 if ( !usesResilientInitialMapLoading() || widget._backInitialRequestGeneration !== requestGeneration ) { 1110 return; 1111 } 1112 1113 attempt = attempt || 0; 1114 var mapRendered = widget._backInitialLoaded 1115 && $('#map-popup #map-canvas').find('[class*="ymaps-"]').length > 0; 1116 1117 if ( mapRendered ) { 1118 widget.refreshBackViewport(); 1119 hideCoffeeMapLoading(); 1120 return; 1121 } 1122 1123 if ( attempt < 80 ) { 1124 setTimeout(function() { 1125 waitForCoffeeMapRender(widget, requestGeneration, attempt + 1); 1126 }, 50); 1127 return; 1128 } 1129 1130 showCoffeeMapRetry(widget, 'Ðе ÑдалоÑÑ Ð¾ÑобÑазиÑÑ ÐºÐ°ÑÑÑ.<br>ÐажмиÑе, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð²ÑоÑиÑÑ'); 1131 } 1132 1133 function refreshVisibleMap() { 1134 var widget = getWidget(); 1135 if ( widget && widget._backInitialLoaded ) { 1136 setTimeout(function() { 1137 widget.refreshBackViewport(); 1138 }, 0); 1139 } 1140 } 1141 1142 document.addEventListener('click', function(event) { 1143 var target = event.target.closest ? event.target.closest('.shops_map_call') : null; 1144 if ( !target ) { 1145 return; 1146 } 1147 prepareCoffeeMapLoading(); 1148 // PRO uses the legacy Helius popup. Let its delegated handler keep the 1149 // active delivery row and apply callback in sync; _setOptions above takes 1150 // care of reusing or reloading the optimized map on subsequent opens. 1151 if ( isProShop() ) { 1152 var proWidget = getWidget(); 1153 if ( proWidget ) { 1154 resetBackPointSelection(proWidget); 1155 } 1156 return; 1157 } 1158 // Billabong keeps its own modal-holder opener and live delivery-row 1159 // callback. The shared bridge still handles reuse and reload in _setOptions. 1160 if ( isBillabongShop() ) { 1161 var billabongWidget = getWidget(); 1162 if ( billabongWidget ) { 1163 resetBackPointSelection(billabongWidget); 1164 } 1165 return; 1166 } 1167 var widget = getWidget(); 1168 if ( !widget ) { 1169 return; 1170 } 1171 1172 event.preventDefault(); 1173 event.stopPropagation(); 1174 if ( typeof event.stopImmediatePropagation === 'function' ) { 1175 event.stopImmediatePropagation(); 1176 } 1177 1178 var options = $(target).data('map-options') || {}; 1179 if ( usesLiveMapOpenerContext() ) { 1180 $('#delivery .shops_map_call').removeClass('opened'); 1181 } 1182 $(target).removeClass('disabled').addClass('opened'); 1183 showMapPopup(); 1184 if ( widget.canReuseBackMap(options) ) { 1185 setTimeout(function() { 1186 widget.refreshBackViewport(); 1187 hideCoffeeMapLoading(); 1188 }, 0); 1189 } else { 1190 widget.reloadBackMap(options); 1191 } 1192 }, true); 1193 1194 $('#map-popup').on('shown.bs.modal.optimizedShopsMap', refreshVisibleMap); 1195 $(document).on('click.optimizedShopsMap', '#map-popup #mapLoading.retry-ready', function() { 1196 var widget = $(this).data('retry-widget') || getWidget(); 1197 if ( !widget ) { 1198 return; 1199 } 1200 widget._backInitialRetryCount = 0; 1201 widget.getPoints(); 1202 }); 1203 $(document) 1204 .off('click.optimizedShopsMapPointRetry', '#map-popup .js-default-pvz-details-retry') 1205 .on('click.optimizedShopsMapPointRetry', '#map-popup .js-default-pvz-details-retry', function(event) { 1206 var widget = getWidget(); 1207 var pointId = $(this).data('point-id'); 1208 1209 event.preventDefault(); 1210 event.stopPropagation(); 1211 if ( !widget || typeof pointId === 'undefined' ) { 1212 return; 1213 } 1214 resetPointDetailsRetry(widget, pointId); 1215 clearPointDetailsError(widget); 1216 widget.pointClickEvent(pointId); 1217 }); 1218 $(document).on('mfpOpen.optimizedShopsMap', function() { 1219 if ( $.magnificPopup.instance && $.magnificPopup.instance.content ) { 1220 var content = $.magnificPopup.instance.content; 1221 if ( !content.is('#map-popup') && !content.find('#map-popup').length ) { 1222 return; 1223 } 1224 } 1225 refreshVisibleMap(); 1226 }); 1227})(window.jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.