PageSourceSearch

https://www.unionmart.ru/bitrix/templates/design2025/components/bi…/order_ajax.js?1788290063335535

js unionmart.ru collected 2026-10-01 12:39:21 UTC 335,535 bytes, 7,739 lines download raw bytes

1BX.namespace('BX.Sale.OrderAjaxComponent');
2
3(function () {
4    'use strict';
5
6    /**
7     * Show empty default property value to multiple properties without default values
8     */
9    if (BX.Sale && BX.Sale.Input && BX.Sale.Input.Utils) {
10        BX.Sale.Input.Utils.asMultiple = function (value) {
11            if (value === undefined || value === null || value === '') {
12                return [];
13            } else if (value.constructor === Array) {
14                var i = 0, length = value.length, val;
15
16                for (; i < length;) {
17                    val = value[i];
18
19                    if (val === undefined || val === null || val === '') {
20                        value.splice(i, 1);
21                        --length;
22                    } else {
23                        ++i;
24                    }
25                }
26
27                return value.length ? value : [''];
28            } else {
29                return [value];
30            }
31        };
32    }
33
34    BX.Sale.OrderAjaxComponent = {
35
36        initializePrimaryFields: function () {
37            this.BXFormPosting = false;
38            this.regionBlockNotEmpty = false;
39            this.locationsInitialized = false;
40            this.locations = {};
41            this.cleanLocations = {};
42            this.locationsTemplate = '';
43            this.pickUpMapFocused = false;
44            this.options = {};
45            this.activeSectionId = '';
46            this.firstLoad = true;
47            this.initialized = {};
48            this.mapsReady = false;
49            this.lastSelectedDelivery = 0;
50            this.deliveryLocationInfo = {};
51            this.deliveryPagination = {};
52            this.deliveryCachedInfo = [];
53            this.paySystemPagination = {};
54            this.validation = {};
55            this.hasErrorSection = {};
56            this.pickUpPagination = {};
57            this.timeOut = {};
58            this.isMobile = BX.browser.IsMobile();
59            this.isHttps = window.location.protocol === "https:";
60            this.orderSaveAllowed = false;
61            this.socServiceHiddenNode = false;
62        },
63
64        /**
65         * Initialization of sale.order.ajax component js
66         */
67        init: function (parameters) {
68            this.initializePrimaryFields();
69
70            this.result = parameters.result || {};
71            this.prepareLocations(parameters.locations);
72            this.params = parameters.params || {};
73            this.signedParamsString = parameters.signedParamsString || '';
74            this.siteId = parameters.siteID || '';
75            this.ajaxUrl = parameters.ajaxUrl || '';
76            this.templateFolder = parameters.templateFolder || '';
77            this.imgFolder = parameters.imgFolder || '';
78            this.defaultBasketItemLogo = this.templateFolder + "/images/product_logo.png";
79            this.defaultStoreLogo = this.templateFolder + "/images/pickup_logo.png";
80            this.defaultDeliveryLogo = this.templateFolder + "/images/delivery_logo.png";
81            this.defaultPaySystemLogo = this.templateFolder + "/images/pay_system_logo.png";
82
83            this.orderBlockNode = BX(parameters.orderBlockId);
84            this.totalBlockNode = BX(parameters.totalBlockId);
85            this.mobileTotalBlockNode = BX(parameters.totalBlockId + '-mobile');
86            this.savedFilesBlockNode = BX('bx-soa-saved-files');
87            this.orderSaveBlockNode = BX('bx-soa-orderSave');
88            this.mainErrorsNode = BX('bx-soa-main-notifications');
89
90            this.authBlockNode = BX(parameters.authBlockId);
91            this.authHiddenBlockNode = BX(parameters.authBlockId + '-hidden');
92            this.basketBlockNode = BX(parameters.basketBlockId);
93            this.basketHiddenBlockNode = BX(parameters.basketBlockId + '-hidden');
94            this.regionBlockNode = BX(parameters.regionBlockId);
95            this.regionHiddenBlockNode = BX(parameters.regionBlockId + '-hidden');
96            this.paySystemBlockNode = BX(parameters.paySystemBlockId);
97            this.paySystemHiddenBlockNode = BX(parameters.paySystemBlockId + '-hidden');
98            this.deliveryBlockNode = BX(parameters.deliveryBlockId);
99            this.deliveryHiddenBlockNode = BX(parameters.deliveryBlockId + '-hidden');
100            this.pickUpBlockNode = BX(parameters.pickUpBlockId);
101            this.pickUpHiddenBlockNode = BX(parameters.pickUpBlockId + '-hidden');
102            this.propsBlockNode = BX(parameters.propsBlockId);
103            this.propsHiddenBlockNode = BX(parameters.propsBlockId + '-hidden');
104
105            if (this.result.SHOW_AUTH) {
106                this.authBlockNode.style.display = '';
107                BX.addClass(this.authBlockNode, 'bx-active');
108                this.authGenerateUser = this.result.AUTH.new_user_registration_email_confirmation !== 'Y' && this.result.AUTH.new_user_phone_required !== 'Y';
109            }
110
111            if (this.totalBlockNode) {
112                this.totalInfoBlockNode = this.totalBlockNode.querySelector('.bx-soa-cart-total');
113                this.totalInfoBlockDataNode = this.totalBlockNode.querySelector('.bx-soa-cart-total-data');
114                this.totalGhostBlockNode = this.totalBlockNode.querySelector('.bx-soa-cart-total-ghost');
115            }
116
117            this.options.deliveriesPerPage = parseInt(parameters.params.DELIVERIES_PER_PAGE);
118            this.options.paySystemsPerPage = parseInt(parameters.params.PAY_SYSTEMS_PER_PAGE);
119            this.options.pickUpsPerPage = parseInt(parameters.params.PICKUPS_PER_PAGE);
120
121            this.options.showWarnings = !!parameters.showWarnings;
122            this.options.propertyValidation = !!parameters.propertyValidation;
123            this.options.priceDiffWithLastTime = false;
124
125            this.options.pickUpMap = parameters.pickUpMap;
126            this.options.propertyMap = parameters.propertyMap;
127
128            this.options.totalPriceChanged = false;
129
130            if (!this.result.IS_AUTHORIZED || typeof this.result.LAST_ORDER_DATA.FAIL !== 'undefined')
131                this.initFirstSection();
132
133            BX.addClass(this.basketBlockNode, 'bx-selected');
134
135            this.initOptions();
136            this.editOrder();
137            this.bindEvents();
138
139            this.orderBlockNode.removeAttribute('style');
140            this.basketBlockScrollCheck();
141
142            if (this.params.USE_ENHANCED_ECOMMERCE === 'Y') {
143                this.setAnalyticsDataLayer('checkout');
144            }
145
146            if (this.params.USER_CONSENT === 'Y') {
147                this.initUserConsent();
148            }
149        },
150
151        /**
152         * Send ajax request with order data and executes callback by action
153         */
154        sendRequest: function (action, actionData) {
155            var form;
156
157            if (!this.startLoader())
158                return;
159
160            this.firstLoad = false;
161
162            action = BX.type.isNotEmptyString(action) ? action : 'refreshOrderAjax';
163
164            if (action === 'saveOrderAjax') {
165                form = BX('bx-soa-order-form');
166                if (form) {
167                    form.querySelector('input[type=hidden][name=sessid]').value = BX.bitrix_sessid();
168                }
169
170                BX.ajax.submitAjax(
171                    BX('bx-soa-order-form'),
172                    {
173                        url: this.ajaxUrl,
174                        method: 'POST',
175                        dataType: 'json',
176                        data: {
177                            via_ajax: 'Y',
178                            action: 'saveOrderAjax',
179                            sessid: BX.bitrix_sessid(),
180                            SITE_ID: this.siteId,
181                            signedParamsString: this.signedParamsString
182                        },
183                        onsuccess: BX.proxy(this.saveOrderWithJson, this),
184                        onfailure: BX.proxy(this.handleNotRedirected, this)
185                    }
186                );
187            } else {
188                BX.ajax({
189                    method: 'POST',
190                    dataType: 'json',
191                    url: this.ajaxUrl,
192                    data: this.getData(action, actionData),
193                    onsuccess: BX.delegate(function (result) {
194                        if (result.redirect && result.redirect.length)
195                            document.location.href = result.redirect;
196
197                        this.saveFiles();
198                        switch (action) {
199                            case 'refreshOrderAjax':
200                                this.refreshOrder(result);
201                                break;
202                            case 'confirmSmsCode':
203                            case 'showAuthForm':
204                                this.firstLoad = true;
205                                this.refreshOrder(result);
206                                break;
207                            case 'enterCoupon':
208                                if (result && result.order) {
209                                    this.deliveryCachedInfo = [];
210                                    this.refreshOrder(result);
211                                    BX.Sale.BasketComponent.sendRequest("refreshAjax", {onlyBasketRefresh: true});
212                                } else {
213                                    this.addCoupon(result);
214                                }
215
216                                break;
217                            case 'removeCoupon':
218                                if (result && result.order) {
219                                    this.deliveryCachedInfo = [];
220                                    this.refreshOrder(result);
221                                    BX.Sale.BasketComponent.sendRequest("refreshAjax", {onlyBasketRefresh: true});
222                                } else {
223                                    this.removeCoupon(result);
224                                }
225
226                                break;
227                        }
228                        BX.cleanNode(this.savedFilesBlockNode);
229                        this.endLoader();
230                    }, this),
231                    onfailure: BX.delegate(function () {
232                        this.endLoader();
233                    }, this)
234                });
235            }
236        },
237
238        getData: function (action, actionData) {
239            var data = {
240                order: this.getAllFormData(),
241                sessid: BX.bitrix_sessid(),
242                via_ajax: 'Y',
243                SITE_ID: this.siteId,
244                signedParamsString: this.signedParamsString
245            };
246
247            data[this.params.ACTION_VARIABLE] = action;
248
249            if (action === 'enterCoupon' || action === 'removeCoupon')
250                data.coupon = actionData;
251
252            return data;
253        },
254
255        getAllFormData: function () {
256            var form = BX('bx-soa-order-form'),
257                prepared = BX.ajax.prepareForm(form),
258                i;
259
260            for (i in prepared.data) {
261                if (prepared.data.hasOwnProperty(i) && i == '') {
262                    delete prepared.data[i];
263                }
264            }
265
266            return !!prepared && prepared.data ? prepared.data : {};
267        },
268
269        /**
270         * Refreshes order via json data from ajax request
271         */
272        refreshOrder: function (result) {
273            if (result.error) {
274                this.showError(this.mainErrorsNode, result.error);
275                this.animateScrollTo(this.mainErrorsNode, 800, 20);
276            } else if (result.order.SHOW_AUTH) {
277                var animation;
278
279                if (
280                    (result.order.OK_MESSAGE && result.order.OK_MESSAGE.length)
281                    || (result.order.SMS_AUTH && result.order.SMS_AUTH.TYPE === 'OK')
282                ) {
283                    animation = 'bx-step-good';
284                } else {
285                    animation = 'bx-step-bad';
286                }
287
288                this.addAnimationEffect(this.authBlockNode, animation);
289                BX.merge(this.result, result.order);
290                this.editAuthBlock();
291                this.showAuthBlock();
292                this.showErrors(result.order.ERROR, false);
293                this.animateScrollTo(this.authBlockNode);
294            } else {
295                this.isPriceChanged(result);
296
297                if (this.activeSectionId !== this.deliveryBlockNode.id)
298                    this.deliveryCachedInfo = [];
299
300                this.result = result.order;
301                this.prepareLocations(result.locations);
302                this.locationsInitialized = false;
303                this.maxWaitTimeExpired = false;
304                this.pickUpMapFocused = false;
305                this.deliveryLocationInfo = {};
306
307                this.initialized = {};
308
309                this.initOptions();
310                this.editOrder();
311                this.mapsReady && this.initMaps();
312                BX.saleOrderAjax && BX.saleOrderAjax.initDeferredControl();
313            }
314
315            return true;
316        },
317
318        saveOrderWithJson: function (result) {
319            var redirected = false;
320
321            if (result && result.order) {
322                result = result.order;
323
324                if (result.REDIRECT_URL) {
325                    if (this.params.USE_ENHANCED_ECOMMERCE === 'Y') {
326                        this.setAnalyticsDataLayer('purchase', result.ID);
327                    }
328
329                    (window.b24order = window.b24order || []).push({id: result.ID, sum: this.result.TOTAL.ORDER_PRICE});
330
331                    redirected = true;
332                    location.href = result.REDIRECT_URL;
333                } else if (result.SHOW_AUTH) {
334                    this.result.SHOW_AUTH = result.SHOW_AUTH;
335                    this.result.AUTH = result.AUTH;
336                    this.result.SMS_AUTH = result.SMS_AUTH;
337
338                    this.editAuthBlock();
339                    this.showAuthBlock();
340                    this.animateScrollTo(this.authBlockNode);
341                } else {
342                    this.showErrors(result.ERROR, true, true);
343                }
344            }
345
346            if (!redirected) {
347                this.handleNotRedirected();
348            }
349        },
350
351        handleNotRedirected: function () {
352            this.endLoader();
353            this.disallowOrderSave();
354        },
355
356        /**
357         * Showing loader image with overlay.
358         */
359        startLoader: function () {
360            if (this.BXFormPosting === true)
361                return false;
362
363            this.BXFormPosting = true;
364
365            if (!this.loadingScreen) {
366                this.loadingScreen = new BX.PopupWindow('loading_screen', null, {
367                    overlay: {backgroundColor: 'white', opacity: 1},
368                    events: {
369                        onAfterPopupShow: BX.delegate(function () {
370                            BX.cleanNode(this.loadingScreen.popupContainer);
371                            BX.removeClass(this.loadingScreen.popupContainer, 'popup-window');
372                            this.loadingScreen.popupContainer.appendChild(
373                                BX.create('IMG', {props: {src: this.imgFolder + '/loader.gif'}})
374                            );
375                            this.loadingScreen.popupContainer.removeAttribute('style');
376                            this.loadingScreen.popupContainer.style.display = 'block';
377                        }, this)
378                    }
379                });
380                BX.addClass(this.loadingScreen.overlay.element, 'bx-step-opacity');
381            }
382
383            this.loadingScreen.overlay.element.style.opacity = '0';
384            this.loadingScreen.show();
385            this.loadingScreen.overlay.element.style.opacity = '0.6';
386
387            return true;
388        },
389
390        /**
391         * Hiding loader image with overlay.
392         */
393        endLoader: function () {
394            this.BXFormPosting = false;
395
396            if (this.loadingScreen && this.loadingScreen.isShown()) {
397                this.loadingScreen.close();
398            }
399        },
400
401        htmlspecialcharsEx: function (str) {
402            return str.replace(/&amp;/g, '&amp;amp;')
403                .replace(/&lt;/g, '&amp;lt;').replace(/&gt;/g, '&amp;gt;')
404                .replace(/&quot;/g, '&amp;quot;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
405        },
406
407        saveFiles: function () {
408            if (this.result.ORDER_PROP && this.result.ORDER_PROP.properties) {
409                var props = this.result.ORDER_PROP.properties, i, prop;
410                for (i = 0; i < props.length; i++) {
411                    if (props[i].TYPE == 'FILE') {
412                        prop = this.orderBlockNode.querySelector('div[data-property-id-row="' + props[i].ID + '"]');
413                        if (prop)
414                            this.savedFilesBlockNode.appendChild(prop);
415                    }
416                }
417            }
418        },
419
420        /**
421         * Animating scroll to certain node
422         */
423        animateScrollTo: function (node, duration, shiftToTop) {
424            if (!node)
425                return;
426
427            var scrollTop = BX.GetWindowScrollPos().scrollTop,
428                orderBlockPos = BX.pos(this.orderBlockNode),
429                ghostTop = BX.pos(node).top - (this.isMobile ? 50 : 0);
430
431            if (shiftToTop)
432                ghostTop -= parseInt(shiftToTop);
433
434            if (ghostTop + window.innerHeight > orderBlockPos.bottom)
435                ghostTop = orderBlockPos.bottom - window.innerHeight + 17;
436
437            new BX.easing({
438                duration: duration || 800,
439                start: {scroll: scrollTop},
440                finish: {scroll: ghostTop},
441                transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
442                step: BX.delegate(function (state) {
443                    window.scrollTo(0, state.scroll);
444                }, this)
445            }).animate();
446        },
447
448        checkKeyPress: function (event) {
449            if (event.keyCode == 13) {
450                var target = event.target || event.srcElement,
451                    send = target.getAttribute('data-send'),
452                    nextAttr, next;
453
454                if (!send) {
455                    nextAttr = target.getAttribute('data-next');
456                    if (nextAttr) {
457                        next = this.orderBlockNode.querySelector('input[name=' + nextAttr + ']');
458                        next && next.focus();
459                    }
460
461                    return BX.PreventDefault(event);
462                }
463            }
464        },
465
466        getSizeString: function (maxSize, len) {
467            var gbDivider = 1024 * 1024 * 1024,
468                mbDivider = 1024 * 1024,
469                kbDivider = 1024,
470                str;
471
472            maxSize = parseInt(maxSize);
473            len = parseInt(len);
474
475            if (maxSize >
475 gbDivider)
476                str = parseFloat(maxSize / gbDivider).toFixed(len) + ' Gb';
477            else if (maxSize > mbDivider)
478                str = parseFloat(maxSize / mbDivider).toFixed(len) + ' Mb';
479            else if (maxSize > kbDivider)
480                str = parseFloat(maxSize / kbDivider).toFixed(len) + ' Kb';
481            else
482                str = maxSize + ' B';
483
484            return str;
485        },
486
487        getFileAccepts: function (accepts) {
488            var arr = [],
489                arAccepts = accepts.split(','),
490                i, currentAccept;
491
492            var mimeTypesMap = {
493                json: 'application/json',
494                javascript: 'application/javascript',
495                'octet-stream': 'application/octet-stream',
496                ogg: 'application/ogg',
497                pdf: 'application/pdf',
498                zip: 'application/zip',
499                gzip: 'application/gzip',
500                aac: 'audio/aac',
501                mp3: 'audio/mpeg',
502                gif: 'image/gif',
503                jpeg: 'image/jpeg',
504                png: 'image/png',
505                svg: 'image/svg+xml',
506                tiff: 'image/tiff',
507                css: 'text/css',
508                csv: 'text/csv',
509                html: 'text/html',
510                plain: 'text/plain',
511                php: 'text/php',
512                xml: 'text/xml',
513                mpeg: 'video/mpeg',
514                mp4: 'video/mp4',
515                quicktime: 'video/quicktime',
516                flv: 'video/x-flv',
517                doc: 'application/msword',
518                docx: 'application/msword',
519                xls: 'application/vnd.ms-excel',
520                xlsx: 'application/vnd.ms-excel'
521            };
522
523            for (i = 0; i < arAccepts.length; i++) {
524                currentAccept = BX.util.trim(arAccepts[i]);
525                currentAccept = mimeTypesMap[currentAccept] || currentAccept;
526                arr.push(currentAccept);
527            }
528
529            return arr.join(',');
530        },
531
532        uniqueText: function (text, separator) {
533            var phrases, i, output = [];
534
535            text = text || '';
536            separator = separator || '<br>';
537
538            phrases = text.split(separator);
539            phrases = BX.util.array_unique(phrases);
540
541            for (i = 0; i < phrases.length; i++) {
542                if (phrases[i] == '')
543                    continue;
544
545                output.push(BX.util.trim(phrases[i]));
546            }
547
548            return output.join(separator);
549        },
550
551        getImageSources: function (item, key) {
552            if (!item || !key || !item[key])
553                return false;
554
555            return {
556                src_1x: item[key + '_SRC'],
557                src_2x: item[key + '_SRC_2X'],
558                src_orig: item[key + '_SRC_ORIGINAL']
559            };
560        },
561
562        getErrorContainer: function (node) {
563            if (!node)
564                return;
565
566            node.appendChild(
567                BX.create('DIV', {props: {className: 'alert alert-danger'}, style: {display: 'none'}})
568            );
569        },
570
571        showError: function (node, msg, border) {
572            if (BX.type.isArray(msg))
573                msg = msg.join('<br>');
574
575            var errorContainer = node.querySelector('.alert.alert-danger'), animate;
576            if (errorContainer && msg.length) {
577                BX.cleanNode(errorContainer);
578                errorContainer.appendChild(BX.create('DIV', {html: msg}));
579
580                animate = !this.hasErrorSection[node.id];
581                if (animate) {
582                    errorContainer.style.opacity = 0;
583                    errorContainer.style.display = '';
584                    new BX.easing({
585                        duration: 300,
586                        start: {opacity: 0},
587                        finish: {opacity: 100},
588                        transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
589                        step: function (state) {
590                            errorContainer.style.opacity = state.opacity / 100;
591                        },
592                        complete: function () {
593                            errorContainer.removeAttribute('style');
594                        }
595                    }).animate();
596                } else
597                    errorContainer.style.display = '';
598
599                if (!!border)
600                    BX.addClass(node, 'bx-step-error');
601            }
602        },
603
604        showErrors: function (errors, scroll, showAll) {
605            var errorNodes = this.orderBlockNode.querySelectorAll('div.alert.alert-danger'),
606                section, k, blockErrors;
607
608            for (k = 0; k < errorNodes.length; k++) {
609                section = BX.findParent(errorNodes[k], {className: 'bx-soa-section'});
610                BX.removeClass(section, 'bx-step-error');
611                errorNodes[k].style.display = 'none';
612                BX.cleanNode(errorNodes[k]);
613            }
614
615            if (!errors || BX.util.object_keys(errors).length < 1)
616                return;
617
618            for (k in errors) {
619                if (!errors.hasOwnProperty(k))
620                    continue;
621
622                blockErrors = errors[k];
623                switch (k.toUpperCase()) {
624                    case 'MAIN':
625                        this.showError(this.mainErrorsNode, blockErrors);
626                        this.animateScrollTo(this.mainErrorsNode, 800, 20);
627                        scroll = false;
628                        break;
629                    case 'AUTH':
630                        if (this.authBlockNode.style.display == 'none') {
631                            this.showError(this.mainErrorsNode, blockErrors, true);
632                            this.animateScrollTo(this.mainErrorsNode, 800, 20);
633                            scroll = false;
634                        } else
635                            this.showError(this.authBlockNode, blockErrors, true);
636                        break;
637                    case 'REGION':
638                        if (showAll || this.regionBlockNode.getAttribute('data-visited') === 'true') {
639                            this.showError(this.regionBlockNode, blockErrors, true);
640                            this.showError(this.regionHiddenBlockNode, blockErrors);
641                        }
642                        break;
643                    case 'DELIVERY':
644                        if (showAll || this.deliveryBlockNode.getAttribute('data-visited') === 'true') {
645                            this.showError(this.deliveryBlockNode, blockErrors, true);
646                            this.showError(this.deliveryHiddenBlockNode, blockErrors);
647                        }
648                        break;
649                    case 'PAY_SYSTEM':
650                        if (showAll || this.paySystemBlockNode.getAttribute('data-visited') === 'true') {
651                            this.showError(this.paySystemBlockNode, blockErrors, true);
652                            this.showError(this.paySystemHiddenBlockNode, blockErrors);
653                        }
654                        break;
655                    case 'PROPERTY':
656                        if (showAll || this.propsBlockNode.getAttribute('data-visited') === 'true') {
657                            this.showError(this.propsBlockNode, blockErrors, true);
658                            this.showError(this.propsHiddenBlockNode, blockErrors);
659                        }
660                        break;
661                }
662            }
663
664            !!scroll && this.scrollToError();
665        },
666
667        showBlockErrors: function (node) {
668            var errorNode = node.querySelector('div.alert.alert-danger'),
669                hiddenNode, errors;
670
671            if (!errorNode)
672                return;
673
674            BX.removeClass(node, 'bx-step-error');
675            errorNode.style.display = 'none';
676            BX.cleanNode(errorNode);
677
678            switch (node.id) {
679                case this.regionBlockNode.id:
680                    hiddenNode = this.regionHiddenBlockNode;
681                    errors = this.result.ERROR.REGION;
682                    break;
683                case this.deliveryBlockNode.id:
684                    hiddenNode = this.deliveryHiddenBlockNode;
685                    errors = this.result.ERROR.DELIVERY;
686                    break;
687                case this.paySystemBlockNode.id:
688                    hiddenNode = this.paySystemHiddenBlockNode;
689                    errors = this.result.ERROR.PAY_SYSTEM;
690                    break;
691                case this.propsBlockNode.id:
692                    hiddenNode = this.propsHiddenBlockNode;
693                    errors = this.result.ERROR.PROPERTY;
694                    break;
695            }
696
697            if (errors && BX.util.object_keys(errors).length) {
698                this.showError(node, errors, true);
699                this.showError(hiddenNode, errors);
700            }
701        },
702
703        checkNotifications: function () {
704            var informer = this.mainErrorsNode.querySelector('[data-type="informer"]'),
705                success, sections, className, text, scrollTop, informerPos;
706
707            if (informer) {
708                if (this.firstLoad && this.result.IS_AUTHORIZED && typeof this.result.LAST_ORDER_DATA.FAIL === 'undefined') {
709                    sections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active');
710                    success = sections.length && sections[sections.length - 1].getAttribute('data-visited') == 'true';
711                    className = success ? 'success' : 'warning';
712                    text = (success ? this.params.MESS_SUCCESS_PRELOAD_TEXT : this.params.MESS_FAIL_PRELOAD_TEXT).split('#ORDER_BUTTON#').join(this.params.MESS_ORDER);
713
714                    informer.appendChild(
715                        BX.create('DIV', {
716                            children: [
717                                BX.create('DIV', {
718                                    style: {position: 'relative', paddingLeft: '48px'},
719                                    children: [
720                                        BX.create('DIV', {props: {className: 'icon-' + className}}),
721                                        BX.create('DIV', {html: text})
722                                    ]
723                                })
724                            ]
725                        })
726                    );
727                    BX.addClass(informer, 'alert alert-' + className);
728                    informer.style.display = '';
729                } else if (BX.hasClass(informer, 'alert')) {
730                    scrollTop = BX.GetWindowScrollPos().scrollTop;
731                    informerPos = BX.pos(informer);
732                }
733            }
734        },
735
736        /**
737         * Returns status of preloaded data from back-end for certain block
738         */
739        checkPreload: function (node) {
740            var status;
741
742            switch (node.id) {
743                case this.regionBlockNode.id:
744                    status = this.result.LAST_ORDER_DATA && this.result.LAST_ORDER_DATA.PERSON_TYPE;
745                    break;
746                case this.paySystemBlockNode.id:
747                    status = this.result.LAST_ORDER_DATA && this.result.LAST_ORDER_DATA.PAY_SYSTEM;
748                    break;
749                case this.deliveryBlockNode.id:
750                    status = this.result.LAST_ORDER_DATA && this.result.LAST_ORDER_DATA.DELIVERY;
751                    break;
752                case this.pickUpBlockNode.id:
753                    status = this.result.LAST_ORDER_DATA && this.result.LAST_ORDER_DATA.PICK_UP;
754                    break;
755                default:
756                    status = true;
757            }
758
759            return status;
760        },
761
762        checkBlockErrors: function (node) {
763            var hiddenNode, errorNode, showError, showWarning, errorTooltips, i;
764
765            if (hiddenNode = BX(node.id + '-hidden')) {
766                errorNode = hiddenNode.querySelector('div.alert.alert-danger');
767                showError = errorNode && errorNode.style.display != 'none';
768                showWarning = hiddenNode.querySelector('div.alert.alert-warning.alert-show');
769
770                if (!showError) {
771                    errorTooltips = hiddenNode.querySelectorAll('div.tooltip');
772                    for (i = 0; i < errorTooltips.length; i++) {
773                        if (errorTooltips[i].getAttribute('data-state') == 'opened') {
774                            showError = true;
775                            break;
776                        }
777                    }
778                }
779            }
780
781            if (showError)
782                BX.addClass(node, 'bx-step-error');
783            else if (showWarning)
784                BX.addClass(node, 'bx-step-warning');
785            else
786                BX.removeClass(node, 'bx-step-error bx-step-warning');
787
788            return !showError;
789        },
790
791        scrollToError: function () {
792            var sections = this.orderBlockNode.querySelectorAll('div.bx-soa-section.bx-active'),
793                i, errorNode;
794
795            for (i in sections) {
796                if (sections.hasOwnProperty(i)) {
797                    errorNode = sections[i].querySelector('.alert.alert-danger');
798                    if (errorNode && errorNode.style.display != 'none') {
799                        this.animateScrollTo(sections[i]);
800                        break;
801                    }
802                }
803            }
804        },
805
806        showWarnings: function () {
807            var sections = this.orderBlockNode.querySelectorAll('div.bx-soa-section.bx-active'),
808                currentDelivery = this.getSelectedDelivery(),
809                k, warningString;
810
811            for (k = 0; k < sections.length; k++) {
812                BX.removeClass(sections[k], 'bx-step-warning');
813
814                if (sections[k].getAttribute('data-visited') == 'false')
815                    BX.removeClass(sections[k], 'bx-step-completed');
816            }
817
818            if (currentDelivery && currentDelivery.CALCULATE_ERRORS) {
819                BX.addClass(this.deliveryBlockNode, 'bx-step-warning');
820
821                warningString = '<strong>' + this.params.MESS_DELIVERY_CALC_ERROR_TITLE + '</strong>';
822                if (this.params.MESS_DELIVERY_CALC_ERROR_TEXT.length)
823                    warningString += '<br><small>' + this.params.MESS_DELIVERY_CALC_ERROR_TEXT + '</small>';
824
825                this.showBlockWarning(this.deliveryBlockNode, warningString);
826                this.showBlockWarning(this.deliveryHiddenBlockNode, warningString);
827
828                if (this.activeSectionId != this.deliveryBlockNode.id) {
829                    BX.addClass(this.deliveryBlockNode, 'bx-step-completed');
830                    BX.bind(this.deliveryBlockNode.querySelector('.alert.alert-warning'), 'click', BX.proxy(this.showByClick, this));
831                }
832            } else if (BX.hasClass(this.deliveryBlockNode, 'bx-step-warning') && this.activeSectionId != this.deliveryBlockNode.id) {
833                BX.removeClass(this.deliveryBlockNode, 'bx-step-warning');
834            }
835
836            if (!this.result.WARNING || !this.options.showWarnings)
837                return;
838
839            for (k in this.result.WARNING) {
840                if (this.result.WARNING.hasOwnProperty(k)) {
841                    switch (k.toUpperCase()) {
842                        case 'DELIVERY':
843                            if (this.deliveryBlockNode.getAttribute('data-visited') === 'true') {
844                                this.showBlockWarning(this.deliveryBlockNode, this.result.WARNING[k], true);
845                                this.showBlockWarning(this.deliveryHiddenBlockNode, this.result.WARNING[k], true);
846                            }
847
848                            break;
849                        case 'PAY_SYSTEM':
850                            if (this.paySystemBlockNode.getAttribute('data-visited') === 'true') {
851                                this.showBlockWarning(this.paySystemBlockNode, this.result.WARNING[k], true);
852                                this.showBlockWarning(this.paySystemHiddenBlockNode, this.result.WARNING[k], true);
853                            }
854
855                            break;
856                    }
857                }
858            }
859        },
860
861        notifyAboutWarnings: function (node) {
862            if (!BX.type.isDomNode(node))
863                return;
864
865            switch (node.id) {
866                case this.deliveryBlockNode.id:
867                    this.showBlockWarning(this.deliveryBlockNode, this.result.WARNING.DELIVERY, true);
868                    break;
869                case this.paySystemBlockNode.id:
870                    this.showBlockWarning(this.paySystemBlockNode, this.result.WARNING.PAY_SYSTEM, true);
871                    break;
872            }
873        },
874
875        showBlockWarning: function (node, warnings, hide) {
876            var errorNode = node.querySelector('.alert.alert-danger'),
877                warnStr = '',
878                i, warningNode, existedWarningNodes;
879
880            if (errorNode) {
881                if (BX.type.isString(warnings)) {
882                    warnStr = warnings;
883                } else {
884                    for (i in warnings) {
885                        if (warnings.hasOwnProperty(i) && warnings[i]) {
886                            warnStr += warnings[i] + '<br>';
887                        }
888                    }
889                }
890
891                if (!warnStr) {
892                    return;
893                }
894
895                existedWarningNodes = node.querySelectorAll('.alert.alert-warning');
896                for (i in existedWarningNodes) {
897                    if (existedWarningNodes.hasOwnProperty(i) && BX.type.isDomNode(existedWarningNodes[i])
897) {
898                        if (existedWarningNodes[i].innerHTML.indexOf(warnStr) !== -1) {
899                            return;
900                        }
901                    }
902                }
903
904                warningNode = BX.create('DIV', {
905                    props: {className: 'alert alert-warning' + (!!hide ? ' alert-hide' : ' alert-show')},
906                    html: warnStr
907                });
908                BX.prepend(warningNode, errorNode.parentNode);
909                BX.addClass(node, 'bx-step-warning');
910            }
911        },
912
913        showPagination: function (entity, node) {
914            if (!node || !entity)
915                return;
916
917            var pagination, navigation = [], i,
918                pageCounter, active, paginationNode;
919
920            switch (entity) {
921                case 'delivery':
922                    pagination = this.deliveryPagination;
923                    break;
924                case 'paySystem':
925                    pagination = this.paySystemPagination;
926                    break;
927                case 'pickUp':
928                    pagination = this.pickUpPagination;
929                    break;
930            }
931
932            if (pagination.pages.length > 1) {
933                navigation.push(
934                    BX.create('LI', {
935                        attrs: {
936                            'data-action': 'prev',
937                            'data-entity': entity
938                        },
939                        props: {className: 'bx-pag-prev'},
940                        html: pagination.pageNumber == 1
941                            ? '<span>' + this.params.MESS_NAV_BACK + '</span>'
942                            : '<a href=""><span>' + this.params.MESS_NAV_BACK + '</span></a>',
943                        events: {click: BX.proxy(this.doPagination, this)}
944                    })
945                );
946                for (i = 0; i < pagination.pages.length; i++) {
947                    pageCounter = parseInt(i) + 1;
948                    active = pageCounter == pagination.pageNumber ? 'bx-active' : '';
949
950                    navigation.push(
951                        BX.create('LI', {
952                            attrs: {
953                                'data-action': pageCounter,
954                                'data-entity': entity
955                            },
956                            props: {className: active},
957                            html: '<a href=""><span>' + pageCounter + '</span></a>',
958                            events: {click: BX.proxy(this.doPagination, this)}
959                        })
960                    );
961                }
962
963                navigation.push(
964                    BX.create('LI', {
965                        attrs: {
966                            'data-action': 'next',
967                            'data-entity': entity
968                        },
969                        props: {className: 'bx-pag-next'},
970                        html: pagination.pageNumber == pagination.pages.length
971                            ? '<span>' + this.params.MESS_NAV_FORWARD + '</span>'
972                            : '<a href=""><span>' + this.params.MESS_NAV_FORWARD + '</span></a>',
973                        events: {click: BX.proxy(this.doPagination, this)}
974                    })
975                );
976
977                paginationNode = BX.create('DIV', {
978                    props: {className: 'bx-pagination'},
979                    children: [
980                        BX.create('DIV', {
981                            props: {className: 'bx-pagination-container'},
982                            children: [BX.create('UL', {children: navigation})]
983                        })
984                    ]
985                });
986
987                node.appendChild(BX.create('DIV', {style: {clear: 'both'}}));
988                node.appendChild(paginationNode);
989            }
990        },
991
992        doPagination: function (e) {
993            var target = e.target || e.srcElement,
994                node = target.tagName == 'LI' ? target : BX.findParent(target, {tagName: 'LI'}),
995                page = node.getAttribute('data-action'),
996                entity = node.getAttribute('data-entity'),
997                pageNum;
998
999            if (BX.hasClass(node, 'bx-active'))
1000                return BX.PreventDefault(e);
1001
1002            if (page == 'prev' || page == 'next') {
1003                pageNum = parseInt(BX.findParent(node).querySelector('.bx-active').getAttribute('data-action'));
1004                page = page == 'next' ? ++pageNum : --pageNum;
1005            }
1006
1007            if (entity == 'delivery')
1008                this.showDeliveryItemsPage(page);
1009            else if (entity == 'paySystem')
1010                this.showPaySystemItemsPage(page);
1011            else if (entity == 'pickUp')
1012                this.showPickUpItemsPage(page);
1013
1014            return BX.PreventDefault(e);
1015        },
1016
1017        showDeliveryItemsPage: function (page) {
1018            this.getCurrentPageItems('delivery', page);
1019
1020            var selectedDelivery = this.getSelectedDelivery(), hidden,
1021                deliveryItemsContainer, k, deliveryItemNode;
1022
1023            if (selectedDelivery && selectedDelivery.ID) {
1024                hidden = this.deliveryBlockNode.querySelector('input[type=hidden][name=DELIVERY_ID]');
1025                if (!hidden) {
1026                    hidden = BX.create('INPUT', {
1027                        props: {
1028                            type: 'hidden',
1029                            name: 'DELIVERY_ID',
1030                            value: selectedDelivery.ID
1031                        }
1032                    })
1033                }
1034            }
1035
1036            deliveryItemsContainer = this.deliveryBlockNode.querySelector('.bx-soa-pp-item-container');
1037            BX.cleanNode(deliveryItemsContainer);
1038
1039            if (BX.type.isDomNode(hidden))
1040                BX.prepend(hidden, BX.findParent(deliveryItemsContainer));
1041
1042            for (k = 0; k < this.deliveryPagination.currentPage.length; k++) {
1043                deliveryItemNode = this.createDeliveryItem(this.deliveryPagination.currentPage[k]);
1044                deliveryItemsContainer.appendChild(deliveryItemNode);
1045            }
1046
1047            this.showPagination('delivery', deliveryItemsContainer);
1048        },
1049
1050        showPaySystemItemsPage: function (page) {
1051            this.getCurrentPageItems('paySystem', page);
1052
1053            var selectedPaySystem = this.getSelectedPaySystem(), hidden,
1054                paySystemItemsContainer, k, paySystemItemNode;
1055
1056            if (selectedPaySystem && selectedPaySystem.ID) {
1057                hidden = this.paySystemBlockNode.querySelector('input[type=hidden][name=PAY_SYSTEM_ID]');
1058                if (!hidden) {
1059                    hidden = BX.create('INPUT', {
1060                        props: {
1061                            type: 'hidden',
1062                            name: 'PAY_SYSTEM_ID',
1063                            value: selectedPaySystem.ID
1064                        }
1065                    })
1066                }
1067            }
1068
1069            paySystemItemsContainer = this.paySystemBlockNode.querySelector('.bx-soa-pp-item-container');
1070            BX.cleanNode(paySystemItemsContainer);
1071
1072            if (BX.type.isDomNode(hidden))
1073                BX.prepend(hidden, BX.findParent(paySystemItemsContainer));
1074
1075            for (k = 0; k < this.paySystemPagination.currentPage.length; k++) {
1076                paySystemItemNode = this.createPaySystemItem(this.paySystemPagination.currentPage[k]);
1077                paySystemItemsContainer.appendChild(paySystemItemNode);
1078            }
1079
1080            this.showPagination('paySystem', paySystemItemsContainer);
1081        },
1082
1083        showPickUpItemsPage: function (page) {
1084            this.getCurrentPageItems('pickUp', page);
1085            this.editPickUpList(false);
1086        },
1087
1088        getCurrentPageItems: function (entity, page) {
1089            if (!entity || typeof page === 'undefined')
1090                return;
1091
1092            var pagination, perPage;
1093
1094            switch (entity) {
1095                case 'delivery':
1096                    pagination = this.deliveryPagination;
1097                    perPage = this.options.deliveriesPerPage;
1098                    break;
1099                case 'paySystem':
1100                    pagination = this.paySystemPagination;
1101                    perPage = this.options.paySystemsPerPage;
1102                    break;
1103                case 'pickUp':
1104                    pagination = this.pickUpPagination;
1105                    perPage = this.options.pickUpsPerPage;
1106                    break;
1107            }
1108
1109            if (pagination && perPage > 0) {
1110                if (page <= 0 || page > pagination.pages.length)
1111                    return;
1112
1113                pagination.pageNumber = page;
1114                pagination.currentPage = pagination.pages.slice(pagination.pageNumber - 1, pagination.pageNumber)[0];
1115            }
1116        },
1117
1118        initPropsListForLocation: function () {
1119            if (BX.saleOrderAjax && this.result.ORDER_PROP && this.result.ORDER_PROP.properties) {
1120                var i, k, curProp, attrObj;
1121
1122                BX.saleOrderAjax.cleanUp();
1123
1124                for (i = 0; i < this.result.ORDER_PROP.properties.length; i++) {
1125                    curProp = this.result.ORDER_PROP.properties[i];
1126
1127                    if (curProp.TYPE == 'LOCATION' && curProp.MULTIPLE == 'Y' && curProp.IS_LOCATION != 'Y') {
1128                        for (k = 0; k < this.locations[curProp.ID].length; k++) {
1129                            BX.saleOrderAjax.addPropertyDesc({
1130                                id: curProp.ID + '_' + k,
1131                                attributes: {
1132                                    id: curProp.ID + '_' + k,
1133                                    type: curProp.TYPE,
1134                                    valueSource: curProp.SOURCE == 'DEFAULT' ? 'default' : 'form'
1135                                }
1136                            });
1137                        }
1138                    } else {
1139                        attrObj = {
1140                            id: curProp.ID,
1141                            type: curProp.TYPE,
1142                            valueSource: curProp.SOURCE == 'DEFAULT' ? 'default' : 'form'
1143                        };
1144
1145                        if (!this.deliveryLocationInfo.city && parseInt(curProp.INPUT_FIELD_LOCATION) > 0) {
1146                            attrObj.altLocationPropId = parseInt(curProp.INPUT_FIELD_LOCATION);
1147                            this.deliveryLocationInfo.city = curProp.INPUT_FIELD_LOCATION;
1148                        }
1149
1150                        if (!this.deliveryLocationInfo.loc && curProp.IS_LOCATION == 'Y')
1151                            this.deliveryLocationInfo.loc = curProp.ID;
1152
1153                        if (!this.deliveryLocationInfo.zip && curProp.IS_ZIP == 'Y') {
1154                            attrObj.isZip = true;
1155                            this.deliveryLocationInfo.zip = curProp.ID;
1156                        }
1157
1158                        BX.saleOrderAjax.addPropertyDesc({
1159                            id: curProp.ID,
1160                            attributes: attrObj
1161                        });
1162                    }
1163                }
1164            }
1165        },
1166
1167        /**
1168         * Binds main events for scrolling/resizing
1169         */
1170        bindEvents: function () {
1171            BX.bind(this.orderSaveBlockNode.querySelector('[data-save-button]'), 'click', BX.proxy(this.clickOrderSaveAction, this));
1172            BX.bind(window, 'scroll', BX.proxy(this.totalBlockScrollCheck, this));
1173            BX.bind(window, 'resize', BX.throttle(function () {
1174                this.totalBlockResizeCheck();
1175                this.alignBasketColumns();
1176                this.basketBlockScrollCheck();
1177                this.mapsReady && this.resizeMapContainers();
1178            }, 50, this));
1179            BX.addCustomEvent('onDeliveryExtraServiceValueChange', BX.proxy(this.sendRequest, this));
1180        },
1181
1182        initFirstSection: function () {
1183            var firstSection = this.orderBlockNode.querySelector('.bx-soa-section.bx-active');
1184            if (this.basketBlockNode && firstSection.id != this.basketBlockNode.id) {
1185                BX.addClass(firstSection, 'bx-selected');
1186            }
1187            this.activeSectionId = firstSection.id;
1188        },
1189
1190        initOptions: function () {
1191            var headers, i, total;
1192
1193            this.initPropsListForLocation();
1194
1195            this.propertyCollection = new BX.Sale.PropertyCollection(BX.merge({publicMode: true}, this.result.ORDER_PROP));
1196            this.fadedPropertyCollection = new BX.Sale.PropertyCollection(BX.merge({publicMode: true}, this.result.ORDER_PROP));
1197
1198            if (this.options.propertyValidation)
1199                this.initValidation();
1200
1201            this.initPagination();
1202
1203            this.options.showPreviewPicInBasket = false;
1204            this.options.showDetailPicInBasket = false;
1205            this.options.showPropsInBasket = false;
1206            this.options.showPriceNotesInBasket = false;
1207
1208            if (this.result.GRID && this.result.GRID.HEADERS) {
1209                headers = this.result.GRID.HEADERS;
1210                for (i = 0; i < headers.length; i++) {
1211                    if (headers[i].id === 'PREVIEW_PICTURE')
1212                        this.options.showPreviewPicInBasket = true;
1213
1214                    if (headers[i].id === 'DETAIL_PICTURE')
1215                        this.options.showDetailPicInBasket = true;
1216
1217                    if (headers[i].id === 'PROPS')
1218                        this.options.showPropsInBasket = true;
1219
1220                    if (headers[i].id === 'NOTES')
1221                        this.options.showPriceNotesInBasket = true;
1222                }
1223            }
1224
1225            if (this.result.TOTAL) {
1226                total = this.result.TOTAL;
1227                this.options.showOrderWeight = total.ORDER_WEIGHT && parseFloat(total.ORDER_WEIGHT) > 0;
1228                this.options.showPriceWithoutDiscount = parseFloat(total.ORDER_PRICE) < parseFloat(total.PRICE_WITHOUT_DISCOUNT_VALUE);
1229                this.options.showDiscountPrice = total.DISCOUNT_PRICE && parseFloat(total.DISCOUNT_PRICE) > 0;
1230                this.options.showTaxList = total.TAX_LIST && total.TAX_LIST.length;
1231                this.options.showPayedFromInnerBudget = total.PAYED_FROM_ACCOUNT_FORMATED && total.PAYED_FROM_ACCOUNT_FORMATED.length;
1232            }
1233        },
1234
1235        reachGoal: function (goal, section) {
1236            var counter = this.params.YM_GOALS_COUNTER || '',
1237                useGoals = this.params.USE_YM_GOALS == 'Y' && typeof window['yaCounter' + counter] !== 'undefined',
1238                goalId;
1239
1240            if (useGoals) {
1241                goalId = this.getGoalId(goal, section);
1242                window['yaCounter' + counter].reachGoal(goalId);
1243            }
1244        },
1245
1246        getGoalId: function (goal, section) {
1247            if (!goal)
1248                return '';
1249
1250            if (goal == 'initialization')
1251                return this.params.YM_GOALS_INITIALIZE;
1252
1253            if (goal == 'order')
1254                return this.params.YM_GOALS_SAVE_ORDER;
1255
1256            var goalId = '',
1257                isEdit = goal == 'edit';
1258
1259            if (!section || !section.id)
1260                return '';
1261
1262            switch (section.id) {
1263                case this.basketBlockNode.id:
1264                    goalId = isEdit ? this.params.YM_GOALS_EDIT_BASKET : this.params.YM_GOALS_NEXT_BASKET;
1265                    break;
1266                case this.regionBlockNode.id:
1267                    goalId = isEdit ? this.params.YM_GOALS_EDIT_REGION : this.params.YM_GOALS_NEXT_REGION;
1268                    break;
1269                case this.paySystemBlockNode.id:
1270                    goalId = isEdit ? this.params.YM_GOALS_EDIT_PAY_SYSTEM : this.params.YM_GOALS_NEXT_PAY_SYSTEM;
1271                    break;
1272                case this.deliveryBlockNode.id:
1273                    goalId = isEdit ? this.params.YM_GOALS_EDIT_DELIVERY : this.params.YM_GOALS_NEXT_DELIVERY;
1274                    break;
1275                case this.pickUpBlockNode.id:
1276                    goalId = isEdit ? this.params.YM_GOALS_EDIT_PICKUP : this.params.YM_GOALS_NEXT_PICKUP;
1277                    break;
1278                case this.propsBlockNode.id:
1279                    goalId = isEdit ? this.params.YM_GOALS_EDIT_PROPERTIES : this.params.YM_GOALS_NEXT_PROPERTIES;
1280                    break;
1281            }
1282
1283            return goalId;
1284        },
1285
1286        isPriceChanged: function (result) {
1287            var priceBefore = this.result.TOTAL.ORDER_TOTAL_LEFT_TO_PAY === null || this.result.TOTAL.ORDER_TOTAL_LEFT_TO_PAY === ''
1288                    ? this.result.TOTAL.ORDER_TOTAL_PRICE
1289                    : this.result.TOTAL.ORDER_TOTAL_LEFT_TO_PAY,
1290                priceAfter = result.order.TOTAL.ORDER_TOTAL_LEFT_TO_PAY === null ? result.order.TOTAL.ORDER_TOTAL_PRICE : result.order.TOTAL.ORDER_TOTAL_LEFT_TO_PAY;
1291
1292            this.options.totalPriceChanged = parseFloat(priceBefore) != parseFloat(priceAfter);
1293        },
1294
1295        initValidation: function () {
1296            if (!this.result.ORDER_PROP || !this.result.ORDER_PROP.properties)
1297                return;
1298
1299            var properties = this.result.ORDER_PROP.properties,
1300                obj = {}, i;
1301
1302            for (i in properties) {
1303                if (properties.hasOwnProperty(i))
1304                    obj[properties[i].ID] = properties[i];
1305            }
1306
1307            this.validation.properties = obj;
1308        },
1309
1310        initPagination: function () {
1311            var arReserve, pages, arPages, i;
1312
1313            if (this.result.DELIVERY) {
1314                this.result.DELIVERY = this.getDeliverySortedArray(this.result.DELIVERY);
1315
1316                if (this.options.deliveriesPerPage > 0 && this.result.DELIVERY.length > this.options.deliveriesPerPage) {
1317                    arReserve = this.result.DELIVERY.slice();
1318                    pages = Math.ceil(arReserve.length / this.options.deliveriesPerPage);
1319                    arPages = [];
1320
1321                    for (i = 0; i < pages; i++) {
1322                        arPages.push(arReserve.splice(0, this.options.deliveriesPerPage));
1323                    }
1324                    this.deliveryPagination.pages = arPages;
1325
1326                    for (i = 0; i < this.result.DELIVERY.length; i++) {
1327                        if (this.result.DELIVERY[i].CHECKED == 'Y') {
1328                            this.deliveryPagination.pageNumber = Math.ceil(++i / this.options.deliveriesPerPage);
1329                            break;
1330                        }
1331                    }
1332
1333                    this.deliveryPagination.pageNumber = this.deliveryPagination.pageNumber || 1;
1334                    this.deliveryPagination.currentPage = arPages.slice(this.deliveryPagination.pageNumber - 1, this.deliveryPagination.pageNumber)[0];
1335                    this.deliveryPagination.show = true
1336                } else {
1337                    this.deliveryPagination.pageNumber = 1;
1338                    this.deliveryPagination.currentPage = this.result.DELIVERY;
1339                    this.deliveryPagination.show = false;
1340                }
1341            }
1342
1343            if (this.result.PAY_SYSTEM) {
1344                if (this.options.paySystemsPerPage > 0 && this.result.PAY_SYSTEM.length > this.options.paySystemsPerPage) {
1345                    arReserve = this.result.PAY_SYSTEM.slice();
1346                    pages = Math.ceil(arReserve.length / this.options.paySystemsPerPage);
1347                    arPages = [];
1348
1349                    for (i = 0; i < pages; i++) {
1350                        arPages.push(arReserve.splice(0, this.options.paySystemsPerPage));
1351                    }
1352                    this.paySystemPagination.pages = arPages;
1353
1354                    for (i = 0; i < this.result.PAY_SYSTEM.length; i++) {
1355                        if (this.result.PAY_SYSTEM[i].CHECKED == 'Y') {
1356                            this.paySystemPagination.pageNumber = Math.ceil(++i / this.options.paySystemsPerPage);
1357                            break;
1358                        }
1359                    }
1360
1361                    this.paySystemPagination.pageNumber = this.paySystemPagination.pageNumber || 1;
1362                    this.paySystemPagination.currentPage = arPages.slice(this.paySystemPagination.pageNumber - 1, this.paySystemPagination.pageNumber)[0];
1363                    this.paySystemPagination.show = true
1364                } else {
1365                    this.paySystemPagination.pageNumber = 1;
1366                    this.paySystemPagination.currentPage = this.result.PAY_SYSTEM;
1367                    this.paySystemPagination.show = false;
1368                }
1369            }
1370        },
1371
1372        initPickUpPagination: function () {
1373            var usePickUpPagination = false,
1374                usePickUp = false,
1375                stores, i = 0,
1376                arReserve, pages, arPages;
1377
1378            if (this.options.pickUpsPerPage >= 0 && this.result.DELIVERY) {
1379                for (i = 0; i < this.result.DELIVERY.length; i++) {
1380                    if (this.result.DELIVERY[i].CHECKED === 'Y' && this.result.DELIVERY[i].STORE_MAIN) {
1381                        usePickUp = this.result.DELIVERY[i].STORE_MAIN.length > 0;
1382                        usePickUpPagination = this.result.DELIVERY[i].STORE_MAIN.length > this.options.pickUpsPerPage;
1383                        if (usePickUp)
1384                            stores = this.getPickUpInfoArray(this.result.DELIVERY[i].STORE_MAIN);
1385                        break;
1386                    }
1387                }
1388            }
1389
1390            if (usePickUp) {
1391                if (this.options.pickUpsPerPage > 0 && usePickUpPagination) {
1392                    arReserve = stores.slice();
1393                    pages = Math.ceil(arReserve.length / this.options.pickUpsPerPage);
1394                    arPages = [];
1395
1396                    for (i = 0; i < pages; i++)
1397                        arPages.push(arReserve.splice(0, this.options.pickUpsPerPage));
1398
1399                    this.pickUpPagination.pages = arPages;
1400
1401                    for (i = 0; i < stores.length; i++) {
1402                        if (!this.result.BUYER_STORE || stores[i].ID == this.result.BUYER_STORE) {
1403                            this.pickUpPagination.pageNumber = Math.
1403ceil(++i / this.options.pickUpsPerPage);
1404                            break;
1405                        }
1406                    }
1407
1408                    if (!this.pickUpPagination.pageNumber)
1409                        this.pickUpPagination.pageNumber = 1;
1410
1411                    this.pickUpPagination.currentPage = arPages.slice(this.pickUpPagination.pageNumber - 1, this.pickUpPagination.pageNumber)[0];
1412                    this.pickUpPagination.show = true
1413                } else {
1414                    this.pickUpPagination.pageNumber = 1;
1415                    this.pickUpPagination.currentPage = stores;
1416                    this.pickUpPagination.show = false;
1417                }
1418            }
1419        },
1420
1421        prepareLocations: function (locations) {
1422            this.locations = {};
1423            this.cleanLocations = {};
1424
1425            var temporaryLocations,
1426                i, k, output;
1427
1428            if (BX.util.object_keys(locations).length) {
1429                for (i in locations) {
1430                    if (!locations.hasOwnProperty(i))
1431                        continue;
1432
1433                    this.locationsTemplate = locations[i].template || '';
1434                    temporaryLocations = [];
1435                    output = locations[i].output;
1436
1437                    if (output.clean) {
1438                        this.cleanLocations[i] = BX.processHTML(output.clean, false);
1439                        delete output.clean;
1440                    }
1441
1442                    for (k in output) {
1443                        if (output.hasOwnProperty(k)) {
1444                            temporaryLocations.push({
1445                                output: BX.processHTML(output[k], false),
1446                                showAlt: locations[i].showAlt,
1447                                lastValue: locations[i].lastValue,
1448                                coordinates: locations[i].coordinates || false
1449                            });
1450                        }
1451                    }
1452
1453                    this.locations[i] = temporaryLocations;
1454                }
1455            }
1456        },
1457
1458        locationsCompletion: function () {
1459            var i, locationNode, clearButton, inputStep, inputSearch,
1460                arProperty, data, section;
1461
1462            this.locationsInitialized = true;
1463            this.fixLocationsStyle(this.regionBlockNode, this.regionHiddenBlockNode);
1464            this.fixLocationsStyle(this.propsBlockNode, this.propsHiddenBlockNode);
1465
1466            for (i in this.locations) {
1467                if (!this.locations.hasOwnProperty(i))
1468                    continue;
1469
1470                locationNode = this.orderBlockNode.querySelector('div[data-property-id-row="' + i + '"]');
1471                if (!locationNode)
1472                    continue;
1473
1474                clearButton = locationNode.querySelector('div.bx-ui-sls-clear');
1475                inputStep = locationNode.querySelector('div.bx-ui-slst-pool');
1476                inputSearch = locationNode.querySelector('input.bx-ui-sls-fake[type=text]');
1477
1478                locationNode.removeAttribute('style');
1479                this.bindValidation(i, locationNode);
1480                if (clearButton) {
1481                    BX.bind(clearButton, 'click', function (e) {
1482                        var target = e.target || e.srcElement,
1483                            parent = BX.findParent(target, {tagName: 'DIV', className: 'tanais-form-group'}),
1484                            locationInput;
1485
1486                        if (parent)
1487                            locationInput = parent.querySelector('input.bx-ui-sls-fake[type=text]');
1488
1489                        if (locationInput)
1490                            BX.fireEvent(locationInput, 'keyup');
1491                    });
1492                }
1493
1494                if (!this.firstLoad && this.options.propertyValidation) {
1495                    if (inputStep) {
1496                        arProperty = this.validation.properties[i];
1497                        data = this.getValidationData(arProperty, locationNode);
1498                        section = BX.findParent(locationNode, {className: 'bx-soa-section'});
1499
1500                        if (section && section.getAttribute('data-visited') == 'true')
1501                            this.isValidProperty(data);
1502                    }
1503
1504                    if (inputSearch)
1505                        BX.fireEvent(inputSearch, 'keyup');
1506                }
1507            }
1508
1509            if (this.firstLoad && this.result.IS_AUTHORIZED && typeof this.result.LAST_ORDER_DATA.FAIL === 'undefined') {
1510                this.showActualBlock();
1511            } else if (!this.result.SHOW_AUTH) {
1512                this.changeVisibleContent();
1513            }
1514
1515            this.checkNotifications();
1516        },
1517
1518        fixLocationsStyle: function (section, hiddenSection) {
1519            if (!section || !hiddenSection)
1520                return;
1521
1522            var regionActive = this.activeSectionId == section.id ? section : hiddenSection,
1523                locationSearchInputs, locationStepInputs, i;
1524
1525            locationSearchInputs = regionActive.querySelectorAll('div.bx-sls div.dropdown-block.bx-ui-sls-input-block');
1526            locationStepInputs = regionActive.querySelectorAll('div.bx-slst div.dropdown-block.bx-ui-slst-input-block');
1527
1528            if (locationSearchInputs.length)
1529                for (i = 0; i < locationSearchInputs.length; i++)
1530                    BX.addClass(locationSearchInputs[i], 'tanais-form-control');
1531
1532            if (locationStepInputs.length)
1533                for (i = 0; i < locationStepInputs.length; i++)
1534                    BX.addClass(locationStepInputs[i], 'tanais-form-control');
1535        },
1536
1537        /**
1538         * Order saving action with validation. Doesn't send request while have errors
1539         */
1540        clickOrderSaveAction: function (event) {
1541            if (this.isValidForm()) {
1542                this.allowOrderSave();
1543
1544                if (this.params.USER_CONSENT === 'Y' && BX.UserConsent) {
1545                    BX.onCustomEvent('bx-soa-order-save', []);
1546                } else {
1547                    this.doSaveAction();
1548                }
1549            }
1550
1551            return BX.PreventDefault(event);
1552        },
1553
1554        doSaveAction: function () {
1555            if (this.isOrderSaveAllowed()) {
1556                this.reachGoal('order');
1557                this.sendRequest('saveOrderAjax');
1558            }
1559        },
1560
1561        /**
1562         * Hiding current block node and showing next available block node
1563         */
1564        clickNextAction: function (event) {
1565            var target = event.target || event.srcElement,
1566                actionSection = BX.findParent(target, {className: "bx-active"}),
1567                section = this.getNextSection(actionSection),
1568                allSections, titleNode, editStep;
1569
1570            this.reachGoal('next', actionSection);
1571
1572            if (
1573                (!this.result.IS_AUTHORIZED || typeof this.result.LAST_ORDER_DATA.FAIL !== 'undefined')
1574                && section.next.getAttribute('data-visited') == 'false'
1575            ) {
1576                titleNode = section.next.querySelector('.bx-soa-section-title-container');
1577                BX.bind(titleNode, 'click', BX.proxy(this.showByClick, this));
1578                editStep = section.next.querySelector('.bx-soa-editstep');
1579                if (editStep)
1580                    editStep.style.display = '';
1581
1582                allSections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active');
1583                if (section.next.id == allSections[allSections.length - 1].id)
1584                    this.switchOrderSaveButtons(true);
1585            }
1586
1587            this.fade(actionSection, section.next);
1588            this.show(section.next);
1589
1590            return BX.PreventDefault(event);
1591        },
1592
1593        /**
1594         * Hiding current block node and showing previous available block node
1595         */
1596        clickPrevAction: function (event) {
1597            var target = event.target || event.srcElement,
1598                actionSection = BX.findParent(target, {className: "bx-active"}),
1599                section = this.getPrevSection(actionSection);
1600
1601            this.fade(actionSection);
1602            this.show(section.next);
1603            this.animateScrollTo(section.next, 800);
1604            return BX.PreventDefault(event);
1605        },
1606
1607        /**
1608         * Showing authentication block node
1609         */
1610        showAuthBlock: function () {
1611            var showNode = this.authBlockNode,
1612                fadeNode = BX(this.activeSectionId);
1613
1614            if (!showNode || BX.hasClass(showNode, 'bx-selected'))
1615                return;
1616
1617            fadeNode && this.fade(fadeNode);
1618            this.show(showNode);
1619        },
1620
1621        /**
1622         * Hiding authentication block node
1623         */
1624        closeAuthBlock: function () {
1625            var actionSection = this.authBlockNode,
1626                nextSection = this.getNextSection(actionSection).next;
1627
1628            this.fade(actionSection);
1629            BX.cleanNode(BX(nextSection.id + '-hidden'));
1630            this.show(nextSection);
1631        },
1632
1633        /**
1634         * Checks possibility to skip section
1635         */
1636        shouldSkipSection: function (section) {
1637            var skip = false;
1638
1639            if (this.params.SKIP_USELESS_BLOCK === 'Y') {
1640                if (section.id === this.pickUpBlockNode.id) {
1641                    var delivery = this.getSelectedDelivery();
1642                    if (delivery) {
1643                        skip = this.getPickUpInfoArray(delivery.STORE).length === 1;
1644                    }
1645                }
1646
1647                if (section.id === this.deliveryBlockNode.id) {
1648                    skip = this.result.DELIVERY && this.result.DELIVERY.length === 1
1649                        && this.result.DELIVERY[0].EXTRA_SERVICES.length === 0
1650                        && !this.result.DELIVERY[0].CALCULATE_ERRORS;
1651                }
1652
1653                if (section.id === this.paySystemBlockNode.id) {
1654                    skip = this.result.PAY_SYSTEM && this.result.PAY_SYSTEM.length === 1 && this.result.PAY_FROM_ACCOUNT !== 'Y';
1655                }
1656            }
1657
1658            return skip;
1659        },
1660
1661        /**
1662         * Returns next available block node (node skipped while have one pay system, delivery or pick up)
1663         */
1664        getNextSection: function (actionSection, skippedSection) {
1665            if (!this.orderBlockNode || !actionSection)
1666                return {};
1667
1668            var allSections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'),
1669                nextSection, i;
1670
1671            for (i = 0; i < allSections.length; i++) {
1672                if (allSections[i].id === actionSection.id && allSections[i + 1]) {
1673                    nextSection = allSections[i + 1];
1674
1675                    if (this.shouldSkipSection(nextSection)) {
1676                        this.markSectionAsCompleted(nextSection);
1677
1678                        return this.getNextSection(nextSection, nextSection);
1679                    }
1680
1681                    return {
1682                        prev: actionSection,
1683                        next: nextSection,
1684                        skip: skippedSection
1685                    };
1686                }
1687            }
1688
1689            return {next: actionSection};
1690        },
1691
1692        markSectionAsCompleted: function (section) {
1693            var titleNode;
1694
1695            if (
1696                (!this.result.IS_AUTHORIZED || typeof this.result.LAST_ORDER_DATA.FAIL !== 'undefined')
1697                && section.getAttribute('data-visited') === 'false'
1698            ) {
1699                this.changeVisibleSection(section, true);
1700            }
1701
1702            section.setAttribute('data-visited', 'true');
1703            BX.addClass(section, 'bx-step-completed');
1704            BX.remove(section.querySelector('.alert.alert-warning.alert-hide'));
1705            this.checkBlockErrors(section);
1706        },
1707
1708        /**
1709         * Returns previous available block node (node skipped while have one pay system, delivery or pick up)
1710         */
1711        getPrevSection: function (actionSection) {
1712            if (!this.orderBlockNode || !actionSection)
1713                return {};
1714
1715            var allSections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'),
1716                prevSection, i;
1717
1718            for (i = 0; i < allSections.length; i++) {
1719                if (allSections[i].id === actionSection.id && allSections[i - 1]) {
1720                    prevSection = allSections[i - 1];
1721
1722                    if (this.shouldSkipSection(prevSection)) {
1723                        this.markSectionAsCompleted(prevSection);
1724
1725                        return this.getPrevSection(prevSection);
1726                    }
1727
1728                    return {
1729                        prev: actionSection,
1730                        next: prevSection
1731                    };
1732                }
1733            }
1734
1735            return {next: actionSection};
1736        },
1737
1738        addAnimationEffect: function (node, className, timeout) {
1739            if (!node || !className)
1740                return;
1741
1742            if (this.timeOut[node.id]) {
1743                clearTimeout(this.timeOut[node.id].timer);
1744                BX.removeClass(node, this.timeOut[node.id].className);
1745            }
1746
1747            setTimeout(function () {
1748                BX.addClass(node, className)
1749            }, 10);
1750            this.timeOut[node.id] = {
1751                className: className,
1752                timer: setTimeout(
1753                    BX.delegate(function () {
1754                        BX.removeClass(node, className);
1755                        delete this.timeOut[node.id];
1756                    }, this),
1757                    timeout || 5000)
1758            };
1759        },
1760
1761        /**
1762         * Replacing current active block node with generated fade block node
1763         */
1764        fade: function (node, nextSection) {
1765            if (!node || !node.id || this.activeSectionId != node.id)
1766                return;
1767
1768            this.hasErrorSection[node.id] = false;
1769
1770            var objHeightOrig = node.offsetHeight,
1771                objHeight;
1772
1773            switch (node.id) {
1774                case this.authBlockNode.id:
1775                    this.authBlockNode.style.display = 'none';
1776                    BX.removeClass(this.authBlockNode, 'bx-active');
1777                    break;
1778                case this.basketBlockNode.id:
1779                    this.editFadeBasketBlock();
1780                    break;
1781                case this.regionBlockNode.id:
1782                    this.editFadeRegionBlock();
1783                    break;
1784                case this.paySystemBlockNode.id:
1785                    BX.remove(this.paySystemBlockNode.querySelector('.alert.alert-warning.alert-hide'));
1786                    this.editFadePaySystemBlock();
1787                    break;
1788                case this.deliveryBlockNode.id:
1789                    BX.remove(this.deliveryBlockNode.querySelector('.alert.alert-warning.alert-hide'));
1790                    this.editFadeDeliveryBlock();
1791                    break;
1792                case this.pickUpBlockNode.id:
1793                    this.editFadePickUpBlock();
1794                    break;
1795                case this.propsBlockNode.id:
1796                    this.editFadePropsBlock();
1797                    break;
1798            }
1799
1800            BX.addClass(node, 'bx-step-completed');
1801            BX.removeClass(node, 'bx-selected');
1802
1803            objHeight = node.offsetHeight;
1804            node.style.height = objHeightOrig + 'px';
1805
1806            // calculations of scrolling animation
1807            if (nextSection) {
1808                var windowScrollTop = BX.GetWindowScrollPos().scrollTop,
1809                    orderPos = BX.pos(this.orderBlockNode),
1810                    nodePos = BX.pos(node),
1811                    diff, scrollTo, nextSectionHeightBefore, nextSectionHeightAfter, nextSectionHidden, offset;
1812
1813                nextSectionHidden = BX(nextSection.id + '-hidden');
1814                nextSectionHidden.style.left = '-10000';
1815                nextSectionHidden.style.position = 'absolute';
1816                this.orderBlockNode.appendChild(nextSectionHidden);
1817                nextSectionHeightBefore = nextSection.offsetHeight;
1818                nextSectionHeightAfter = nextSectionHidden.offsetHeight + 57;
1819                BX(node.id + '-hidden').parentNode.appendChild(nextSectionHidden);
1820                nextSectionHidden.removeAttribute('style');
1821
1822                diff = objHeight + nextSectionHeightAfter - objHeightOrig - nextSectionHeightBefore;
1823
1824                offset = window.innerHeight - orderPos.height - diff;
1825                if (offset > 0)
1826                    scrollTo = orderPos.top - offset / 2;
1827                else {
1828                    if (nodePos.top > windowScrollTop)
1829                        scrollTo = nodePos.top;
1830                    else
1831                        scrollTo = nodePos.bottom + 6 - objHeightOrig + objHeight;
1832
1833                    if (scrollTo + window.innerHeight > orderPos.bottom + 25 + diff)
1834                        scrollTo = orderPos.bottom + 25 + diff - window.innerHeight;
1835                }
1836
1837                scrollTo -= this.isMobile ? 50 : 0;
1838            }
1839
1840            new BX.easing({
1841                duration: nextSection ? 800 : 600,
1842                start: {height: objHeightOrig, scrollTop: windowScrollTop},
1843                finish: {height: objHeight, scrollTop: scrollTo},
1844                transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
1845                step: function (state) {
1846                    node.style.height = state.height + "px";
1847                    if (nextSection)
1848                        window.scrollTo(0, state.scrollTop);
1849                },
1850                complete: function () {
1851                    node.style.height = '';
1852                }
1853            }).animate();
1854
1855            this.checkBlockErrors(node);
1856        },
1857
1858        /**
1859         * Showing active data in certain block node
1860         */
1861        show: function (node) {
1862            if (!node || !node.id || this.activeSectionId == node.id)
1863                return;
1864
1865            this.activeSectionId = node.id;
1866            BX.removeClass(node, 'bx-step-error bx-step-warning');
1867
1868            switch (node.id) {
1869                case this.authBlockNode.id:
1870                    this.authBlockNode.style.display = '';
1871                    BX.addClass(this.authBlockNode, 'bx-active');
1872                    break;
1873                case this.regionBlockNode.id:
1874                    this.editActiveRegionBlock(true);
1875                    break;
1876                case this.deliveryBlockNode.id:
1877                    this.editActiveDeliveryBlock(true);
1878                    break;
1879                case this.paySystemBlockNode.id:
1880                    this.editActivePaySystemBlock(true);
1881                    break;
1882                case this.pickUpBlockNode.id:
1883                    this.editActivePickUpBlock(true);
1884                    break;
1885                case this.propsBlockNode.id:
1886                    this.editActivePropsBlock(true);
1887                    break;
1888            }
1889
1890            if (this.basketBlockNode && node.id == this.basketBlockNode.id) {
1891                this.editActiveBasketBlock(true);
1892                this.alignBasketColumns();
1893            }
1894
1895            if (node.getAttribute('data-visited') === 'false') {
1896                this.showBlockErrors(node);
1897                this.notifyAboutWarnings(node);
1898            }
1899
1900            node.setAttribute('data-visited', 'true');
1901            BX.addClass(node, 'bx-selected');
1902            BX.removeClass(node, 'bx-step-completed');
1903        },
1904
1905        showByClick: function (event) {
1906            var target = event.target || event.srcElement,
1907                showNode = BX.findParent(target, {className: "bx-active"}),
1908                // fadeNode = BX(this.activeSectionId),
1909                scrollTop = BX.GetWindowScrollPos().scrollTop;
1910
1911            if (!showNode || BX.hasClass(showNode, 'bx-selected'))
1912                return BX.PreventDefault(event);
1913
1914            this.reachGoal('edit', showNode);
1915
1916            // fadeNode && this.fade(fadeNode);
1917            this.show(showNode);
1918
1919            setTimeout(BX.delegate(function () {
1920                if (BX.pos(showNode).top < scrollTop)
1921                    this.animateScrollTo(showNode, 300);
1922            }, this), 320);
1923
1924            return BX.PreventDefault(event);
1925        },
1926
1927        /**
1928         * Checks each active block from top to bottom for errors (showing first block with errors or last block)
1929         */
1930        showActualBlock: function () {
1931            var allSections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'),
1932                i = 0;
1933
1934            while (allSections[i]) {
1935                if (allSections[i].id === this.regionBlockNode.id)
1936                    this.isValidRegionBlock();
1937
1938                if (allSections[i].id === this.propsBlockNode.id)
1939                    this.isValidPropertiesBlock();
1940
1941                if (!this.checkBlockErrors(allSections[i]) || !this.checkPreload(allSections[i])) {
1942                    if (this.activeSectionId !== allSections[i].id) {
1943                        BX(this.activeSectionId) && this.fade(BX(this.activeSectionId));
1944                        this.show(allSections[i]);
1945                    }
1946
1947                    break;
1948                }
1949
1950                BX.addClass(allSections[i], 'bx-step-completed');
1951                allSections[i].setAttribute('data-visited', 'true');
1952                i++;
1953            }
1954        },
1955
1956        /**
1957         * Returns footer node with navigation buttons
1958         */
1959        getBlockFooter: function (node) {
1960            var sections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'),
1961                firstSection = sections[0],
1962                lastSection = sections[sections.length - 1],
1963                currentSection = BX.findParent(node, {className: "bx-soa-section"}),
1964                isLastNode = false,
1965                buttons = [];
1966
1967            if (currentSection && currentSection.id.indexOf(firstSection.id) == '-1') {
1968                buttons.push(
1969                    BX.create('A', {
1970                        props: {
1971                            href: 'javascript:void(0)',
1972                            className: 'pull-left btn btn-default btn-md'
1973                        },
1974                        html: this.params.MESS_BACK,
1975                        events: {
1976                            click: BX.proxy(this.clickPrevAction, this)
1977                        }
1978                    })
1979                );
1980            }
1981
1982            if (currentSection && currentSection.id.indexOf(lastSection.id) != '-1')
1983                isLastNode = true;
1984
1985            if (!isLastNode) {
1986                buttons.push(
1987                    BX.create('A', {
1988                        props: {href: 'javascript:void(0)', className: 'pull-right btn btn-default btn-md'},
1989                        html: this.params.MESS_FURTHER,
1990                        events: {click: BX.proxy(this.clickNextAction, this)}
1991                    })
1992                );
1993            }
1994
1995            /*node.appendChild(
1996				BX.create('DIV', {
1997					props: {className: 'row bx-soa-more'},
1998					children: [
1999						BX.create('DIV', {
2000							props: {className: 'bx-soa-more-btn'},
2001							children: buttons
2002						})
2003					]
2004				})
2005			);*/
2006        },
2007
2008        getNewContainer: function (notFluid) {
2009            return BX.create('DIV', {props: {className: 'bx-soa-section-content' + (!!notFluid ? '' : ' container-fluid')}});
2010        },
2011
2012        /**
2013         * Showing/hiding order save buttons
2014         */
2015        switchOrderSaveButtons: function (state) {
2016            var orderSaveNode = this.orderSaveBlockNode,
2017                totalButton = this.totalBlockNode.querySelector('.bx-soa-cart-total-button-container'),
2018                mobileButton = this.mobileTotalBlockNode.querySelector('.bx-soa-cart-total-button-container'),
2019                lastState = this.orderSaveBlockNode.style.display == '';
2020
2021            if (lastState != state) {
2022                if (state) {
2023                    orderSaveNode.style.opacity = 0;
2024                    orderSaveNode.style.display = '';
2025                    if (totalButton) {
2026                        totalButton.style.opacity = 0;
2027                        totalButton.style.display = '';
2028                    }
2029                    if (mobileButton) {
2030                        mobileButton.style.opacity = 0;
2031                        mobileButton.style.display = '';
2032                    }
2033
2034                    new BX.easing({
2035                        duration: 500,
2036                        start: {opacity: 0},
2037                        finish: {opacity: 100},
2038                        transition: BX.easing.transitions.linear,
2039                        step: function (state) {
2040                            orderSaveNode.style.opacity = state.opacity / 100;
2041                            if (totalButton)
2042                                totalButton.style.opacity = state.opacity / 100;
2043                            if (mobileButton)
2044                                mobileButton.style.opacity = state.opacity / 100;
2045                        },
2046                        complete: function () {
2047                            orderSaveNode.removeAttribute('style');
2048                            totalButton && totalButton.removeAttribute('style');
2049                            mobileButton && mobileButton.removeAttribute('style');
2050                        }
2051                    }).animate();
2052                } else {
2053                    orderSaveNode.style.display = 'none';
2054                    if (totalButton)
2055                        totalButton.setAttribute('style', 'display: none !important');
2056                    if (mobileButton)
2057                        mobileButton.setAttribute('style', 'display: none !important');
2058                }
2059            }
2060        },
2061
2062        /**
2063         * Returns true if current section or next sections had already visited
2064         */
2065        shouldBeSectionVisible: function (sections, currentPosition) {
2066            var state = false, editStepNode;
2067
2068            if (!sections || !sections.length)
2069                return state;
2070
2071            for (; currentPosition < sections.length; currentPosition++) {
2072                if (sections[currentPosition].getAttribute('data-visited') == 'true') {
2073                    state = true;
2074                    break;
2075                }
2076
2077                if (!this.firstLoad) {
2078                    editStepNode = sections[currentPosition].querySelector('.bx-soa-editstep');
2079                    if (editStepNode && editStepNode.style.display !== 'none') {
2080                        state = true;
2081                        break;
2082                    }
2083                }
2084            }
2085
2086            return state;
2087        },
2088
2089        /**
2090         * Showing/hiding blocks content if user authorized/unauthorized
2091         */
2092        changeVisibleContent: function () {
2093            var sections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'),
2094                i, state;
2095
2096            var orderDataLoaded = !!this.result.IS_AUTHORIZED && this.params.USE_PRELOAD === 'Y' && this.result.LAST_ORDER_DATA.FAIL !== true,
2097                skipFlag = true;
2098
2099            for (i = 0; i < sections.length; i++) {
2100                state = this.firstLoad && orderDataLoaded;
2101                state = state || this.shouldBeSectionVisible(sections, i);
2102
2103                this.changeVisibleSection(sections[i], state);
2104
2105                if (this.firstLoad && skipFlag) {
2106                    if (
2107                        state
2108                        && sections[i + 1]
2109                        && this.checkBlockErrors(sections[i])
2110                        && (
2111                            (orderDataLoaded && this.checkPreload(sections[i]))
2112                            || (!orderDataLoaded && this.shouldSkipSection(sections[i]))
2113                        )
2114                    ) {
2115                        this.fade(sections[i]);
2116                        this.markSectionAsCompleted(sections[i]);
2117                        this.show(sections[i + 1]);
2118                    } else {
2119                        skipFlag = false;
2120                    }
2121                }
2122            }
2123        },
2124
2125        changeVisibleSection: function (section, state) {
2126            var titleNode, content, editStep;
2127
2128            if (this.basketBlockNode && section.id !== this.basketBlockNode.id) {
2129                content = section.querySelector('.bx-soa-section-content');
2130                if (content)
2131                    content.style.display = state ? '' : 'none';
2132            }
2133        },
2134
2135        /**
2136         * Edit order block nodes with this.result/this.params data
2137         */
2138        editOrder: function () {
2139            if (!this.orderBlockNode || !this.result)
2140                return;
2141
2142            if (this.result.DELIVERY.length > 0) {
2143                BX.addClass(this.deliveryBlockNode, 'bx-active');
2144                this.deliveryBlockNode.removeAttribute('style');
2145            } else {
2146                BX.removeClass(this.deliveryBlockNode, 'bx-active');
2147                this.deliveryBlockNode.style.display = 'none';
2148            }
2149
2150            this.orderSaveBlockNode.style.display = this.result.SHOW_AUTH ? 'none' : '';
2151            this.mobileTotalBlockNode.style.display = this.result.SHOW_AUTH ? 
2151'none' : '';
2152
2153            this.checkPickUpShow();
2154
2155            var sections = this.orderBlockNode.querySelectorAll('.bx-soa-section.bx-active'), i;
2156            for (i in sections) {
2157                if (sections.hasOwnProperty(i)) {
2158                    this.editSection(sections[i]);
2159                }
2160            }
2161
2162            this.editTotalBlock();
2163            this.totalBlockFixFont();
2164
2165            this.showErrors(this.result.ERROR, false);
2166            this.showWarnings();
2167        },
2168
2169        /**
2170         * Edit certain block node
2171         */
2172        editSection: function (section) {
2173            if (!section || !section.id)
2174                return;
2175
2176            if (this.result.SHOW_AUTH && section.id != this.authBlockNode.id && (this.basketBlockNode && section.id != this.basketBlockNode.id))
2177                section.style.display = 'none';
2178            else if (section.id != this.pickUpBlockNode.id)
2179                section.style.display = '';
2180
2181            var active = true,
2182                titleNode = section.querySelector('.bx-soa-section-title-container'),
2183                editButton, errorContainer;
2184
2185            errorContainer = section.querySelector('.alert.alert-danger');
2186            this.hasErrorSection[section.id] = errorContainer && errorContainer.style.display != 'none';
2187
2188            switch (section.id) {
2189                case this.authBlockNode.id:
2190                    this.editAuthBlock();
2191                    break;
2192                case this.regionBlockNode.id:
2193                    this.editRegionBlock(active);
2194                    break;
2195                case this.paySystemBlockNode.id:
2196                    this.editPaySystemBlock(active);
2197                    break;
2198                case this.deliveryBlockNode.id:
2199                    this.editDeliveryBlock(active);
2200                    break;
2201                case this.pickUpBlockNode.id:
2202                    this.editPickUpBlock(active);
2203                    break;
2204                case this.propsBlockNode.id:
2205                    this.editPropsBlock(active);
2206                    break;
2207            }
2208
2209            if (this.basketBlockNode && section.id == this.basketBlockNode.id) {
2210                this.editBasketBlock(active);
2211            }
2212
2213            if (active)
2214                section.setAttribute('data-visited', 'true');
2215        },
2216
2217        editAuthBlock: function () {
2218            if (!this.authBlockNode)
2219                return;
2220
2221            var authContent = this.authBlockNode.querySelector('.bx-soa-section-content'),
2222                regContent, okMessageNode;
2223
2224            if (BX.hasClass(authContent, 'reg')) {
2225                regContent = authContent;
2226                authContent = BX.firstChild(this.authHiddenBlockNode);
2227            } else
2228                regContent = BX.firstChild(this.authHiddenBlockNode);
2229
2230            BX.cleanNode(authContent);
2231            BX.cleanNode(regContent);
2232
2233            if (this.result.SHOW_AUTH) {
2234                this.getErrorContainer(authContent);
2235                this.editAuthorizeForm(authContent);
2236                this.editSocialContent(authContent);
2237                this.getAuthReference(authContent);
2238
2239                this.getErrorContainer(regContent);
2240                this.editRegistrationForm(regContent);
2241                this.getAuthReference(regContent);
2242            } else {
2243                BX.onCustomEvent('OnBasketChange');
2244                this.closeAuthBlock();
2245            }
2246
2247            if (this.result.OK_MESSAGE && this.result.OK_MESSAGE.length) {
2248                this.toggleAuthForm({target: this.authBlockNode.querySelector('input[type=submit]')});
2249                okMessageNode = BX.create('DIV', {
2250                    props: {className: 'alert alert-success'},
2251                    text: this.result.OK_MESSAGE.join()
2252                });
2253                this.result.OK_MESSAGE = '';
2254                BX.prepend(okMessageNode, this.authBlockNode.querySelector('.bx-soa-section-content'));
2255            }
2256        },
2257
2258        editAuthorizeForm: function (authContent) {
2259            var login, password, remember, button, authFormNode;
2260
2261            login = this.createAuthFormInputContainer(
2262                BX.message('STOF_LOGIN'),
2263                BX.create('INPUT', {
2264                    attrs: {'data-next': 'USER_PASSWORD'},
2265                    props: {
2266                        name: 'USER_LOGIN',
2267                        type: 'text',
2268                        value: this.result.AUTH.USER_LOGIN,
2269                        maxlength: "30"
2270                    },
2271                    events: {keypress: BX.proxy(this.checkKeyPress, this)}
2272                })
2273            );
2274            password = this.createAuthFormInputContainer(
2275                BX.message('STOF_PASSWORD'),
2276                BX.create('INPUT', {
2277                    attrs: {'data-send': true},
2278                    props: {
2279                        name: 'USER_PASSWORD',
2280                        type: 'password',
2281                        value: '',
2282                        maxlength: "30"
2283                    },
2284                    events: {keypress: BX.proxy(this.checkKeyPress, this)}
2285                })
2286            );
2287            remember = BX.create('DIV', {
2288                props: {className: 'bx-authform-formgroup-container'},
2289                children: [
2290                    BX.create('DIV', {
2291                        props: {className: 'checkbox'},
2292                        children: [
2293                            BX.create('LABEL', {
2294                                props: {className: 'bx-filter-param-label'},
2295                                children: [
2296                                    BX.create('INPUT', {
2297                                        props: {
2298                                            type: 'checkbox',
2299                                            name: 'USER_REMEMBER',
2300                                            value: 'Y'
2301                                        }
2302                                    }),
2303                                    BX.create('SPAN', {
2304                                        props: {className: 'bx-filter-param-text'},
2305                                        text: BX.message('STOF_REMEMBER')
2306                                    })
2307                                ]
2308                            })
2309                        ]
2310                    })
2311                ]
2312            });
2313            button = BX.create('DIV', {
2314                props: {className: 'bx-authform-formgroup-container'},
2315                children: [
2316                    BX.create('INPUT', {
2317                        props: {
2318                            id: 'do_authorize',
2319                            type: 'hidden',
2320                            name: 'do_authorize',
2321                            value: 'N'
2322                        }
2323                    }),
2324                    BX.create('INPUT', {
2325                        props: {
2326                            type: 'submit',
2327                            className: 'btn btn-default',
2328                            value: BX.message('STOF_ENTER')
2329                        },
2330                        events: {
2331                            click: BX.delegate(function (e) {
2332                                BX('do_authorize').value = 'Y';
2333                                this.sendRequest('showAuthForm');
2334                                return BX.PreventDefault(e);
2335                            }, this)
2336                        }
2337                    })
2338                ]
2339            });
2340            authFormNode = BX.create('DIV', {
2341                props: {className: 'bx-authform'},
2342                children: [
2343                    BX.create('H3', {props: {className: 'bx-title'}, text: BX.message('STOF_AUTH_REQUEST')}),
2344                    login,
2345                    password,
2346                    remember,
2347                    button,
2348                    BX.create('A', {
2349                        props: {
2350                            href: this.params.PATH_TO_AUTH + '?forgot_password=yes&back_url=' + encodeURIComponent(document.location.href)
2351                        },
2352                        text: BX.message('STOF_FORGET_PASSWORD')
2353                    })
2354                ]
2355            });
2356
2357            authContent.appendChild(BX.create('DIV', {children: [authFormNode]}));
2358        },
2359
2360        createAuthFormInputContainer: function (labelText, inputNode, required) {
2361            var labelHtml = '';
2362
2363            if (required)
2364                labelHtml += '<span class="bx-authform-starrequired">*</span>';
2365
2366            labelHtml += labelText;
2367
2368            return BX.create('DIV', {
2369                props: {className: 'bx-authform-formgroup-container'},
2370                children: [
2371                    BX.create('DIV', {props: {className: 'bx-authform-label-container'}, html: labelHtml}),
2372                    BX.create('DIV', {props: {className: 'bx-authform-input-container'}, children: [inputNode]})
2373                ]
2374            });
2375        },
2376
2377        activatePhoneAuth: function () {
2378            if (!this.result.SMS_AUTH)
2379                return;
2380
2381            new BX.PhoneAuth({
2382                containerId: 'bx_register_resend',
2383                errorContainerId: 'bx_register_error',
2384                interval: 60,
2385                data: {
2386                    signedData: this.result.SMS_AUTH.SIGNED_DATA
2387                },
2388                onError: function (response) {
2389                    var errorDiv = BX('bx_register_error');
2390                    var errorNode = BX.findChildByClassName(errorDiv, 'errortext');
2391                    errorNode.innerHTML = '';
2392
2393                    for (var i = 0; i < response.errors.length; i++) {
2394                        errorNode.innerHTML = errorNode.innerHTML + BX.util.htmlspecialchars(response.errors[i].message) + '<br>';
2395                    }
2396
2397                    errorDiv.style.display = '';
2398                }
2399            });
2400        },
2401
2402        editRegistrationForm: function (authContent) {
2403            if (!this.result.AUTH)
2404                return;
2405
2406            var authFormNodes = [];
2407            var showSmsConfirm = this.result.SMS_AUTH && this.result.SMS_AUTH.TYPE === 'OK';
2408
2409            if (showSmsConfirm) {
2410                authFormNodes.push(BX.create('DIV', {
2411                    props: {className: 'alert alert-success'},
2412                    text: BX.message('STOF_REG_SMS_REQUEST')
2413                }));
2414                authFormNodes.push(BX.create('INPUT', {
2415                    props: {
2416                        type: 'hidden',
2417                        name: 'SIGNED_DATA',
2418                        value: this.result.SMS_AUTH.SIGNED_DATA || ''
2419                    }
2420                }));
2421                authFormNodes.push(this.createAuthFormInputContainer(
2422                    BX.message('STOF_SMS_CODE'),
2423                    BX.create('INPUT', {
2424                        attrs: {'data-send': true},
2425                        props: {
2426                            name: 'SMS_CODE',
2427                            type: 'text',
2428                            size: 40,
2429                            value: ''
2430                        },
2431                        events: {keypress: BX.proxy(this.checkKeyPress, this)}
2432                    }),
2433                    true
2434                ));
2435                authFormNodes.push(BX.create('DIV', {
2436                    props: {className: 'bx-authform-formgroup-container'},
2437                    children: [
2438                        BX.create('INPUT', {
2439                            props: {
2440                                name: 'code_submit_button',
2441                                type: 'submit',
2442                                className: 'btn btn-default',
2443                                value: BX.message('STOF_SEND')
2444                            },
2445                            events: {
2446                                click: BX.delegate(function (e) {
2447                                    this.sendRequest('confirmSmsCode');
2448                                    return BX.PreventDefault(e);
2449                                }, this)
2450                            }
2451                        })
2452                    ]
2453                }));
2454                authFormNodes.push(BX.create('DIV', {
2455                    props: {className: 'bx-authform-formgroup-container'},
2456                    children: [
2457                        BX.create('DIV', {
2458                            props: {id: 'bx_register_error'},
2459                            style: {display: 'none'}
2460                        }),
2461                        BX.create('DIV', {
2462                            props: {id: 'bx_register_resend'}
2463                        })
2464                    ]
2465                }));
2466            } else {
2467                authFormNodes.push(BX.create('H3', {
2468                    props: {className: 'bx-title'},
2469                    text: BX.message('STOF_REG_REQUEST')
2470                }));
2471                authFormNodes.push(this.createAuthFormInputContainer(
2472                    BX.message('STOF_NAME'),
2473                    BX.create('INPUT', {
2474                        attrs: {'data-next': 'NEW_LAST_NAME'},
2475                        props: {
2476                            name: 'NEW_NAME',
2477                            type: 'text',
2478                            size: 40,
2479                            value: this.result.AUTH.NEW_NAME || ''
2480                        },
2481                        events: {keypress: BX.proxy(this.checkKeyPress, this)}
2482                    }),
2483                    true
2484                ));
2485                authFormNodes.push(this.createAuthFormInputContainer(
2486                    BX.message('STOF_LASTNAME'),
2487                    BX.create('INPUT', {
2488                        attrs: {'data-next': 'NEW_EMAIL'},
2489                        props: {
2490                            name: 'NEW_LAST_NAME',
2491                            type: 'text',
2492                            size: 40,
2493                            value: this.result.AUTH.NEW_LAST_NAME || ''
2494                        },
2495                        events: {keypress: BX.proxy(this.checkKeyPress, this)}
2496                    }),
2497                    true
2498                ));
2499                authFormNodes.push(this.createAuthFormInputContainer(
2500                    BX.message('STOF_EMAIL'),
2501                    BX.create('INPUT', {
2502                        attrs: {'data-next': 'PHONE_NUMBER'},
2503                        props: {
2504                            name: 'NEW_EMAIL',
2505                            type: 'text',
2506                            size: 40,
2507                            value: this.result.AUTH.NEW_EMAIL || ''
2508                        },
2509                        events: {keypress: BX.proxy(this.checkKeyPress, this)}
2510                    }),
2511                    this.result.AUTH.new_user_email_required == 'Y'
2512                ));
2513
2514                if (this.result.AUTH.new_user_phone_auth === 'Y') {
2515                    authFormNodes.push(this.createAuthFormInputContainer(
2516                        BX.message('STOF_PHONE'),
2517                        BX.create('INPUT', {
2518                            attrs: {'data-next': 'captcha_word'},
2519                            props: {
2520                                name: 'PHONE_NUMBER',
2521                                type: 'text',
2522                                size: 40,
2523                                value: this.result.AUTH.PHONE_NUMBER || ''
2524                            },
2525                            events: {keypress: BX.proxy(this.checkKeyPress, this)}
2526                        }),
2527                        this.result.AUTH.new_user_phone_required === 'Y'
2528                    ));
2529                }
2530
2531                if (this.authGenerateUser) {
2532                    authFormNodes.push(
2533                        BX.create('LABEL', {
2534                            props: {for: 'NEW_GENERATE_N'},
2535                            children: [
2536                                BX.create('INPUT', {
2537                                    attrs: {checked: !this.authGenerateUser},
2538                                    props: {
2539                                        id: 'NEW_GENERATE_N',
2540                                        type: 'radio',
2541                                        name: 'NEW_GENERATE',
2542                                        value: 'N'
2543                                    }
2544                                }),
2545                                BX.message('STOF_MY_PASSWORD')
2546                            ],
2547                            events: {
2548                                change: BX.delegate(function () {
2549                                    var generated = this.authBlockNode.querySelector('.generated');
2550                                    generated.style.display = '';
2551                                    this.authGenerateUser = false;
2552                                }, this)
2553                            }
2554                        })
2555                    );
2556                    authFormNodes.push(BX.create('BR'));
2557                    authFormNodes.push(
2558                        BX.create('LABEL', {
2559                            props: {for: 'NEW_GENERATE_Y'},
2560                            children: [
2561                                BX.create('INPUT', {
2562                                    attrs: {checked: this.authGenerateUser},
2563                                    props: {
2564                                        id: 'NEW_GENERATE_Y',
2565                                        type: 'radio',
2566                                        name: 'NEW_GENERATE',
2567                                        value: 'Y'
2568                                    }
2569                                }),
2570                                BX.message('STOF_SYS_PASSWORD')
2571                            ],
2572                            events: {
2573                                change: BX.delegate(function () {
2574                                    var generated = this.authBlockNode.querySelector('.generated');
2575                                    generated.style.display = 'none';
2576                                    this.authGenerateUser = true;
2577                                }, this)
2578                            }
2579                        })
2580                    );
2581                }
2582
2583                authFormNodes.push(
2584                    BX.create('DIV', {
2585                        props: {className: 'generated'},
2586                        style: {display: this.authGenerateUser ? 'none' : ''},
2587                        children: [
2588                            this.createAuthFormInputContainer(
2589                                BX.message('STOF_LOGIN'),
2590                                BX.create('INPUT', {
2591                                    props: {
2592                                        name: 'NEW_LOGIN',
2593                                        type: 'text',
2594                                        size: 30,
2595                                        value: this.result.AUTH.NEW_LOGIN || ''
2596                                    },
2597                                    events: {
2598                                        keypress: BX.proxy(this.checkKeyPress, this)
2599                                    }
2600                                }),
2601                                true
2602                            ),
2603                            this.createAuthFormInputContainer(
2604                                BX.message('STOF_PASSWORD'),
2605                                BX.create('INPUT', {
2606                                    props: {
2607                                        name: 'NEW_PASSWORD',
2608                                        type: 'password',
2609                                        size: 30
2610                                    },
2611                                    events: {
2612                                        keypress: BX.proxy(this.checkKeyPress, this)
2613                                    }
2614                                }),
2615                                true
2616                            ),
2617                            this.createAuthFormInputContainer(
2618                                BX.message('STOF_RE_PASSWORD'),
2619                                BX.create('INPUT', {
2620                                    props: {
2621                                        name: 'NEW_PASSWORD_CONFIRM',
2622                                        type: 'password',
2623                                        size: 30
2624                                    },
2625                                    events: {
2626                                        keypress: BX.proxy(this.checkKeyPress, this)
2627                                    }
2628                                }),
2629                                true
2630                            )
2631                        ]
2632                    })
2633                );
2634
2635                if (this.result.AUTH.captcha_registration == 'Y') {
2636                    authFormNodes.push(BX.create('DIV', {
2637                        props: {className: 'bx-authform-formgroup-container'},
2638                        children: [
2639                            BX.create('DIV', {
2640                                props: {className: 'bx-authform-label-container'},
2641                                children: [
2642                                    BX.create('SPAN', {props: {className: 'bx-authform-starrequired'}, text: '*'}),
2643                                    BX.message('CAPTCHA_REGF_PROMT'),
2644                                    BX.create('DIV', {
2645                                        props: {className: 'bx-captcha'},
2646                                        children: [
2647                                            BX.create('INPUT', {
2648                                                props: {
2649                                                    name: 'captcha_sid',
2650                                                    type: 'hidden',
2651                                                    value: this.result.AUTH.capCode || ''
2652                                                }
2653                                            }),
2654                                            BX.create('IMG', {
2655                                                props: {
2656                                                    src: '/bitrix/tools/captcha.php?captcha_sid=' + this.result.AUTH.capCode,
2657                                                    alt: ''
2658                                                }
2659                                            })
2660                                        ]
2661                                    })
2662                                ]
2663                            }),
2664                            BX.create('DIV', {
2665                                props: {className: 'bx-authform-input-container'},
2666                                children: [
2667                                    BX.create('INPUT', {
2668                                        attrs: {'data-send': true},
2669                                        props: {
2670                                            name: 'captcha_word',
2671                                            type: 'text',
2672                                            size: '30',
2673                                            maxlength: '50',
2674                                            value: ''
2675                                        },
2676                                        events: {keypress: BX.proxy(this.checkKeyPress, this)}
2677                                    })
2678                                ]
2679                            })
2680                        ]
2681                    }));
2682                }
2683                authFormNodes.push(
2684                    BX.create('DIV', {
2685                        props: {className: 'bx-authform-formgroup-container'},
2686                        children: [
2687                            BX.create('INPUT', {
2688                                props: {
2689                                    id: 'do_register',
2690                                    name: 'do_register',
2691                                    type: 'hidden',
2692                                    value: 'N'
2693                                }
2694                            }),
2695                            BX.create('INPUT', {
2696                                props: {
2697                                    type: 'submit',
2698                                    className: 'btn btn-default',
2699                                    value: BX.message('STOF_REGISTER')
2700                                },
2701                                events: {
2702                                    click: BX.delegate(function (e) {
2703                                        BX('do_register').value = 'Y';
2704                                        this.sendRequest('showAuthForm');
2705                                        return BX.PreventDefault(e);
2706                                    }, this)
2707                                }
2708                            }),
2709                            BX.create('A', {
2710                                props: {className: 'btn btn-link', href: ''},
2711                                text: BX.message('STOF_DO_AUTHORIZE'),
2712                                events: {
2713                                    click: BX.delegate(function (e) {
2714                                        this.toggleAuthForm(e);
2715                                        return BX.PreventDefault(e);
2716                                    }, this)
2717                                }
2718                            })
2719                        ]
2720                    })
2721                );
2722            }
2723
2724            authContent.appendChild(
2725                BX.create('DIV', {
2726                    children: [BX.create('DIV', {props: {className: 'bx-authform'}, children: authFormNodes})]
2727                })
2728            );
2729
2730            if (showSmsConfirm) {
2731                this.activatePhoneAuth();
2732            }
2733        },
2734
2735        editSocialContent: function (authContent) {
2736            if (!BX('bx-soa-soc-auth-services'))
2737                return;
2738
2739            var nodes = [];
2740
2741            if (this.socServiceHiddenNode === false) {
2742                var socServiceHiddenNode = BX('bx-soa-soc-auth-services').querySelector('.bx-authform-social');
2743
2744                if (BX.type.isDomNode(socServiceHiddenNode)) {
2745                    this.socServiceHiddenNode = socServiceHiddenNode.innerHTML;
2746                    BX.remove(socServiceHiddenNode);
2747                }
2748            }
2749
2750            if (this.socServiceHiddenNode) {
2751                nodes.push(BX.create('DIV', {
2752                    props: {className: 'bx-authform-social'},
2753                    html: '<h3 class="bx-title">' + BX.message('SOA_DO_SOC_SERV') + '</h3>' + this.socServiceHiddenNode
2754                }));
2755                nodes.push(BX.create('hr', {props: {className: 'bxe-light'}}));
2756            }
2757
2758            if (this.result.AUTH.new_user_registration === 'Y') {
2759                nodes.push(BX.create('DIV', {
2760                    props: {className: 'bx-soa-reg-block'},
2761                    children: [
2762                        BX.create('P', {html: this.params.MESS_REGISTRATION_REFERENCE}),
2763                        BX.create('A', {
2764                            props: {className: 'btn btn-default'},
2765                            text: BX.message('STOF_DO_REGISTER'),
2766                            events: {
2767                                click: BX.delegate(function (e) {
2768                                    this.toggleAuthForm(e);
2769                                    return BX.PreventDefault(e);
2770                                }, this)
2771                            }
2772                        })
2773                    ]
2774                }));
2775            }
2776
2777            authContent.appendChild(BX.create('DIV', {children: nodes}));
2778        },
2779
2780        getAuthReference: function (authContent) {
2781            authContent.appendChild(
2782                BX.create('DIV', {
2783                    children: [
2784                        BX.create('DIV', {
2785                            props: {className: 'bx-soa-reference'},
2786                            children: [
2787                                this.params.MESS_AUTH_REFERENCE_1,
2788                                BX.create('BR'),
2789                                this.params.MESS_AUTH_REFERENCE_2,
2790                                BX.create('BR'),
2791                                this.params.MESS_AUTH_REFERENCE_3
2792                            ]
2793                        })
2794                    ]
2795                })
2796            );
2797        },
2798
2799        toggleAuthForm: function (event) {
2800            if (!event)
2801                return;
2802
2803            var target = event.target || event.srcElement,
2804                section = BX.findParent(target, {className: 'bx-soa-section'}),
2805                container = BX.findParent(target, {className: 'bx-soa-section-content'}),
2806                insertContainer = BX.firstChild(this.authHiddenBlockNode);
2807
2808            new BX.easing({
2809                duration: 100,
2810                start: {opacity: 100},
2811                finish: {opacity: 0},
2812                transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
2813                step: function (state) {
2814                    container.style.opacity = state.opacity / 100;
2815                }
2816            }).animate();
2817
2818            this.authHiddenBlockNode.appendChild(container);
2819            BX.cleanNode(section);
2820            section.appendChild(
2821                BX.create('DIV', {
2822                    props: {className: 'bx-soa-section-title-container'},
2823                    children: [
2824                        BX.create('h2', {
2825                            props: {className: 'bx-soa-section-title'},
2826                            html: BX.hasClass(insertContainer, 'reg') ? this.params.MESS_REG_BLOCK_NAME : this.params.MESS_AUTH_BLOCK_NAME
2827                        })
2828                    ]
2829                })
2830            );
2831            insertContainer.style.opacity = 0;
2832            section.appendChild(insertContainer);
2833
2834            setTimeout(function () {
2835                new BX.easing({
2836                    duration: 100,
2837                    start: {opacity: 0},
2838                    finish: {opacity: 100},
2839                    transition: BX.easing.makeEaseOut(BX.easing.transitions.quart),
2840                    step: function (state) {
2841                        insertContainer.style.opacity = state.opacity / 100;
2842                    },
2843                    complete: function () {
2844                        insertContainer.style.height = '';
2845                        insertContainer.style.opacity = '';
2846                    }
2847                }).animate();
2848            }, 110);
2849
2850            this.animateScrollTo(section);
2851        },
2852
2853        alignBasketColumns: function () {
2854            if (!this.basketBlockNode)
2855                return;
2856
2857            var i = 0, k, columns = 0, columnNodes,
2858                windowSize = BX.GetWindowInnerSize(),
2859                basketRows, percent;
2860
2861            if (windowSize.innerWidth > 580 && windowSize.innerWidth < 992) {
2862                basketRows = this.basketBlockNode.querySelectorAll('.bx-soa-basket-info');
2863                percent = 100;
2864
2865                if (basketRows.length) {
2866                    columnNodes = basketRows[0].querySelectorAll('.bx-soa-item-properties');
2867
2868                    if (columnNodes.length && columnNodes[0].style.width != '')
2869                        return;
2870
2871                    columns = columnNodes.length;
2872                    if (columns > 0) {
2873                        columns = columns > 4 ? 4 : columns;
2874                        percent = parseInt(percent / columns);
2875                        for (; i < basketRows.length; i++) {
2876                            columnNodes = basketRows[i].querySelectorAll('.bx-soa-item-properties')
2877                            for (k = 0; k < columnNodes.length; k++) {
2878                                columnNodes[k].style.width = percent + '%';
2879                            }
2880                        }
2881                    }
2882                }
2883            } else {
2884                columnNodes = this.basketBlockNode.querySelectorAll('.bx-soa-item-properties');
2885
2886                if (columnNodes.length && columnNodes[0].style.width == '')
2887                    return;
2888
2889                for (; i < columnNodes.length; i++) {
2890                    columnNodes[i].style.width = '';
2891                }
2892            }
2893        },
2894
2895        editBasketBlock: function (active) {
2896            if (!this.basketBlockNode || !this.basketHiddenBlockNode || !this.result.GRID)
2897                return;
2898
2899            BX.remove(BX.lastChild(this.basketBlockNode));
2900            BX.remove(BX.lastChild(this.basketHiddenBlockNode));
2901
2902            this.editActiveBasketBlock(active);
2903            this.editFadeBasketBlock(active);
2904
2905            this.initialized.basket = true;
2906        },
2907
2908        editActiveBasketBlock: function (activeNodeMode) {
2909            var node = !!activeNodeMode ? this.basketBlockNode : this.basketHiddenBlockNode,
2910                basketContent, basketTable;
2911
2912            if (this.initialized.basket) {
2913                this.basketHiddenBlockNode.appendChild(BX.lastChild(node));
2914                node.appendChild(BX.firstChild(this.basketHiddenBlockNode));
2915            } else {
2916                basketContent = node.querySelector('.bx-soa-section-content');
2917                basketTable = BX.create('DIV', {props: {className: 'bx-soa-item-table'}});
2918
2919                if (!basketContent) {
2920                    basketContent = this.getNewContainer();
2921                    node.appendChild(basketContent);
2922                } else {
2923                    BX.cleanNode(basketContent);
2924                }
2925
2926                this.editBasketItems(basketTable, true);
2927
2928                basketContent.appendChild(
2929                    BX.create('DIV', {
2930                        props: {className: 'bx-soa-table-fade'},
2931                        children: [
2932                            BX.create('DIV', {
2933                                style: {overflowX: 'auto', overflowY: 'hidden'},
2934                                children: [basketTable]
2935                            })
2936                        ]
2937                    })
2938                );
2939
2940                if (this.params.SHOW_COUPONS_BASKET === 'Y') {
2941                    this.editCoupons(basketContent);
2942                }
2943
2944                this.getBlockFooter(basketContent);
2945
2946                BX.bind(
2947                    basketContent.querySelector('div.bx-soa-table-fade').firstChild,
2948                    'scroll',
2949                    BX.proxy(this.basketBlockScrollCheckEvent, this)
2950                );
2951            }
2952
2953            this.alignBasketColumns();
2954        },
2955
2956        editFadeBasketBlock: function (activeNodeMode) {
2957            var node = !!activeNodeMode ? this.basketHiddenBlockNode : this.basketBlockNode,
2958                newContent, basketTable;
2959
2960            if (!this.initialized.basket) {
2961                newContent = this.getNewContainer();
2962                basketTable = BX.create('DIV', {props: {className: 'bx-soa-item-table'}});
2963
2964                this.editBasketItems(basketTable, false);
2965
2966                newContent.appendChild(
2967                    BX.create('DIV', {
2968                        props: {className: 'bx-soa-table-fade'},
2969                        children: [
2970                            BX.create('DIV', {
2971                                style: {overflowX: 'auto', overflowY: 'hidden'},
2972                                children: [basketTable]
2973                            })
2974                        ]
2975                    })
2976                );
2977
2978                if (this.params.SHOW_COUPONS_BASKET === 'Y') {
2979                    this.editCouponsFade(newContent);
2980                }
2981
2982                node.appendChild(newContent);
2983                this.alignBasketColumns();
2984                this.basketBlockScrollCheck();
2985
2986                BX.bind(
2987                    this.basketBlockNode.querySelector('div.bx-soa-table-fade').firstChild,
2988                    'scroll',
2989                    BX.proxy(this.basketBlockScrollCheckEvent, this)
2990                );
2991            }
2992
2993            this.alignBasketColumns();
2994        },
2995
2996        editBasketItems: function (basketItemsNode, active) {
2997            if (!this.result.GRID.ROWS)
2998                return;
2999
3000            var index = 0, i;
3001
3002            if (this.params.SHOW_BASKET_HEADERS === 'Y') {
3003                this.editBasketItemsHeader(basketItemsNode);
3004            }
3005
3006            for (i in this.result.GRID.ROWS) {
3007                if (this.result.GRID.ROWS.hasOwnProperty(i)) {
3008                    this.createBasketItem(basketItemsNode, this.result.GRID.ROWS[i], index++, !!active);
3009                }
3010            }
3011        },
3012
3013        editBasketItemsHeader: function (basketItemsNode) {
3014            if (!basketItemsNode)
3015                return;
3016
3017            var headers = [
3018                    BX.create('DIV', {
3019                        props: {className: 'bx-soa-item-td'},
3020                        style: {paddingBottom: '5px'},
3021                        children: [
3022                            BX.create('DIV', {
3023                                props: {className: 'bx-soa-item-td-title'},
3024                                text: BX.message('SOA_SUM_NAME')
3025                            })
3026                        ]
3027                    })
3028                ],
3029                toRight = false, column, basketColumnIndex = 0, i;
3030
3031            for (i = 0; i < this.result.GRID.HEADERS.length; i++) {
3032                column = this.result.GRID.HEADERS[i];
3033
3034                if (column.id === 'NAME' || column.id === 'PREVIEW_PICTURE' || column.id === 'PROPS' || column.id === 'NOTES')
3035                    continue;
3036
3037                if (column.id === 'DETAIL_PICTURE' && !this.options.showPreviewPicInBasket)
3038                    continue;
3039
3040                toRight = BX.util.in_array(column.id, ["QUANTITY", "PRICE_FORMATED", "DISCOUNT_PRICE_PERCENT_FORMATED", "SUM"]);
3041                headers.push(
3042                    BX.create('DIV', {
3043                        props: {className: 'bx-soa-item-td bx-soa-item-properties' + (toRight ? ' bx-text-right' : '')},
3044                        style: {paddingBottom: '5px'},
3045                        children: [
3046                            BX.create('DIV', {
3047                                props: {className: 'bx-soa-item-td-title'},
3048                                text: column.name
3049                            })
3050                        ]
3051                    })
3052                );
3053
3054                ++basketColumnIndex;
3055                if (basketColumnIndex == 4 && this.result.GRID.HEADERS[i + 1]) {
3056                    headers.push(BX.create('DIV', {props: {className: 'bx-soa-item-nth-4p1'}}));
3057                    basketColumnIndex = 0;
3058                }
3059            }
3060
3061            basketItemsNode.appendChild(
3062                BX.create('DIV', {
3063                    props: {className: 'bx-soa-item-tr'},
3064                    children: headers
3065                })
3066            );
3067        },
3068
3069        createBasketItem: function (basketItemsNode, item, index, active) {
3070            var mainColumns = [],
3071                otherColumns = [],
3072                hiddenColumns = [],
3073                currentColumn, basketColumnIndex = 0,
3074                i, tr, cols;
3075
3076            if (this.options.showPreviewPicInBasket || this.options.showDetailPicInBasket)
3077                mainColumns.push(this.createBasketItemImg(item.data));
3078
3079            mainColumns.push(this.createBasketItemContent(item.data));
3080
3081            for (i = 0; i < this.result.GRID.HEADERS.length; i++) {
3082                currentColumn = this.result.GRID.HEADERS[i];
3083
3084                if (currentColumn.id === 'NAME' || currentColumn.id === 'PREVIEW_PICTURE' || currentColumn.id === 'PROPS' || currentColumn.id === 'NOTES')
3085                    continue;
3086
3087                if (currentColumn.id === 'DETAIL_PICTURE' && !this.options.showPreviewPicInBasket)
3088                    continue;
3089
3090                otherColumns.push(this.createBasketItemColumn(currentColumn, item, active));
3091
3092                ++basketColumnIndex;
3093                if (basketColumnIndex == 4 && this.result.GRID.HEADERS[i + 1]) {
3094                    otherColumns.push(BX.create('DIV', {props: {className: 'bx-soa-item-nth-4p1'}}));
3095                    basketColumnIndex = 0;
3096                }
3097            }
3098
3099            if (active) {
3100                for (i = 0; i < this.result.GRID.HEADERS_HIDDEN.length; i++) {
3101                    tr = this.createBasketItemHiddenColumn(this.result.GRID.HEADERS_HIDDEN[i], item);
3102                    if (BX.type.isArray(tr))
3103                        hiddenColumns = hiddenColumns.concat(tr);
3104                    else if (tr)
3105                        hiddenColumns.push(tr);
3106                }
3107            }
3108
3109            cols = [
3110                BX.create('DIV', {
3111                    props: {className: 'bx-soa-item-td'},
3112                    style: {minWidth: '300px'},
3113                    children: [
3114                        BX.create('DIV', {
3115                            props: {className: 'bx-soa-item-block'},
3116                            children: mainColumns
3117                        })
3118                    ]
3119                })
3120            ].concat(otherColumns);
3121
3122            basketItemsNode.appendChild(
3123                BX.create('DIV', {
3124                    props: {className: 'bx-soa-item-tr bx-soa-basket-info' + (index == 0 ? ' bx-soa-item-tr-first' : '')},
3125                    children: cols
3126                })
3127            );
3128
3129            if (hiddenColumns.length) {
3130                basketItemsNode.appendChild(
3131                    BX.create('DIV', {
3132                        props: {className: 'bx-soa-item-tr bx-soa-item-info-container'},
3133                        children: [
3134                            BX.create('DIV', {
3135                                props: {className: 'bx-soa-item-td'},
3136                                children: [
3137                                    BX.create('A', {
3138                                        props: {href: '', className: 'bx-soa-info-s
3138hower'},
3139                                        html: this.params.MESS_ADDITIONAL_PROPS,
3140                                        events: {
3141                                            click: BX.proxy(this.showAdditionalProperties, this)
3142                                        }
3143                                    }),
3144                                    BX.create('DIV', {
3145                                        props: {className: 'bx-soa-item-info-block'},
3146                                        children: [
3147                                            BX.create('TABLE', {
3148                                                props: {className: 'bx-soa-info-block'},
3149                                                children: hiddenColumns
3150                                            })
3151                                        ]
3152                                    })
3153                                ]
3154                            })
3155                        ]
3156                    })
3157                );
3158            }
3159        },
3160
3161        showAdditionalProperties: function (event) {
3162            var target = event.target || event.srcElement,
3163                infoContainer = target.nextSibling,
3164                parentContainer = BX.findParent(target, {className: 'bx-soa-item-tr bx-soa-item-info-container'}),
3165                parentHeight = parentContainer.offsetHeight;
3166
3167            if (BX.hasClass(infoContainer, 'bx-active')) {
3168                new BX.easing({
3169                    duration: 300,
3170                    start: {opacity: 100, height: parentHeight},
3171                    finish: {opacity: 0, height: 35},
3172                    transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
3173                    step: function (state) {
3174                        infoContainer.style.opacity = state.opacity / 100;
3175                        infoContainer.style.height = state.height + 'px';
3176                        parentContainer.style.height = state.height + 'px';
3177                    },
3178                    complete: function () {
3179                        BX.removeClass(infoContainer, 'bx-active');
3180                        infoContainer.removeAttribute("style");
3181                        parentContainer.removeAttribute("style");
3182                    }
3183                }).animate();
3184            } else {
3185                infoContainer.style.opacity = 0;
3186                BX.addClass(infoContainer, 'bx-active');
3187                var height = infoContainer.offsetHeight + parentHeight;
3188                BX.removeClass(infoContainer, 'bx-active');
3189                infoContainer.style.paddingTop = '10px';
3190
3191                new BX.easing({
3192                    duration: 300,
3193                    start: {opacity: 0, height: parentHeight},
3194                    finish: {opacity: 100, height: height},
3195                    transition: BX.easing.makeEaseOut(BX.easing.transitions.quad),
3196                    step: function (state) {
3197                        infoContainer.style.opacity = state.opacity / 100;
3198                        infoContainer.style.height = state.height + 'px';
3199                        parentContainer.style.height = state.height + 'px';
3200                    },
3201                    complete: function () {
3202                        BX.addClass(infoContainer, 'bx-active');
3203                        infoContainer.removeAttribute("style");
3204                    }
3205                }).animate();
3206            }
3207
3208            return BX.PreventDefault(event);
3209        },
3210
3211        createBasketItemImg: function (data) {
3212            if (!data)
3213                return;
3214
3215            var logoNode, logotype;
3216
3217            logoNode = BX.create('DIV', {props: {className: 'bx-soa-item-imgcontainer'}});
3218
3219            if (data.PREVIEW_PICTURE_SRC && data.PREVIEW_PICTURE_SRC.length)
3220                logotype = this.getImageSources(data, 'PREVIEW_PICTURE');
3221            else if (data.DETAIL_PICTURE_SRC && data.DETAIL_PICTURE_SRC.length)
3222                logotype = this.getImageSources(data, 'DETAIL_PICTURE');
3223
3224            if (logotype && logotype.src_2x) {
3225                logoNode.setAttribute('style',
3226                    'background-image: url("' + logotype.src_1x + '");' +
3227                    'background-image: -webkit-image-set(url(' + logotype.src_1x + ') 1x, url(' + logotype.src_2x + ') 2x)'
3228                );
3229            } else {
3230                logotype = logotype && logotype.src_1x || this.defaultBasketItemLogo;
3231                logoNode.setAttribute('style', 'background-image: url("' + logotype + '");');
3232            }
3233
3234            if (this.params.HIDE_DETAIL_PAGE_URL !== 'Y' && data.DETAIL_PAGE_URL && data.DETAIL_PAGE_URL.length) {
3235                logoNode = BX.create('A', {
3236                    props: {href: data.DETAIL_PAGE_URL},
3237                    children: [logoNode]
3238                });
3239            }
3240
3241            return BX.create('DIV', {
3242                props: {className: 'bx-soa-item-img-block'},
3243                children: [logoNode]
3244            });
3245        },
3246
3247        createBasketItemContent: function (data) {
3248            var itemName = data.NAME || '',
3249                titleHtml = this.htmlspecialcharsEx(itemName),
3250                props = data.PROPS || [],
3251                propsNodes = [];
3252
3253            if (this.params.HIDE_DETAIL_PAGE_URL !== 'Y' && data.DETAIL_PAGE_URL && data.DETAIL_PAGE_URL.length) {
3254                titleHtml = '<a href="' + data.DETAIL_PAGE_URL + '">' + titleHtml + '</a>';
3255            }
3256
3257            if (this.options.showPropsInBasket && props.length) {
3258                for (var i in props) {
3259                    if (props.hasOwnProperty(i)) {
3260                        var name = props[i].NAME || '',
3261                            value = props[i].VALUE || '';
3262
3263                        propsNodes.push(
3264                            BX.create('DIV', {
3265                                props: {className: 'bx-soa-item-td-title'},
3266                                style: {textAlign: 'left'},
3267                                text: name
3268                            })
3269                        );
3270                        propsNodes.push(
3271                            BX.create('DIV', {
3272                                props: {className: 'bx-soa-item-td-text'},
3273                                style: {textAlign: 'left'},
3274                                text: value
3275                            })
3276                        );
3277                    }
3278                }
3279            }
3280
3281            return BX.create('DIV', {
3282                props: {className: 'bx-soa-item-content'},
3283                children: propsNodes.length ? [
3284                    BX.create('DIV', {props: {className: 'bx-soa-item-title'}, html: titleHtml}),
3285                    BX.create('DIV', {props: {className: 'bx-scu-container'}, children: propsNodes})
3286                ] : [
3287                    BX.create('DIV', {props: {className: 'bx-soa-item-title'}, html: titleHtml})
3288                ]
3289            });
3290        },
3291
3292        createBasketItemColumn: function (column, allData, active) {
3293            if (!column || !allData)
3294                return;
3295
3296            var data = allData.columns[column.id] ? allData.columns : allData.data,
3297                toRight = BX.util.in_array(column.id, ["QUANTITY", "PRICE_FORMATED", "DISCOUNT_PRICE_PERCENT_FORMATED", "SUM"]),
3298                textNode = BX.create('DIV', {props: {className: 'bx-soa-item-td-text'}}
3298),
3299                logotype, img;
3300
3301            if (column.id === 'PRICE_FORMATED') {
3302                textNode.appendChild(BX.create('STRONG', {props: {className: 'bx-price'}, html: data.PRICE_FORMATED}));
3303                if (parseFloat(data.DISCOUNT_PRICE) > 0) {
3304                    textNode.appendChild(BX.create('BR'));
3305                    textNode.appendChild(BX.create('STRONG', {
3306                        props: {className: 'bx-price-old'},
3307                        html: data.BASE_PRICE_FORMATED
3308                    }));
3309                }
3310
3311                if (this.options.showPriceNotesInBasket && active) {
3312                    textNode.appendChild(BX.create('BR'));
3313                    textNode.appendChild(BX.create('SMALL', {text: data.NOTES}));
3314                }
3315            } else if (column.id === 'SUM') {
3316                textNode.appendChild(BX.create('STRONG', {props: {className: 'bx-price all'}, html: data.SUM}));
3317                if (parseFloat(data.DISCOUNT_PRICE) > 0) {
3318                    textNode.appendChild(BX.create('BR'));
3319                    textNode.appendChild(BX.create('STRONG', {
3320                        props: {className: 'bx-price-old'},
3321                        html: data.SUM_BASE_FORMATED
3322                    }));
3323                }
3324            } else if (column.id === 'DISCOUNT') {
3325                textNode.appendChild(BX.create('STRONG', {
3326                    props: {className: 'bx-price'},
3327                    text: data.DISCOUNT_PRICE_PERCENT_FORMATED
3328                }));
3329            } else if (column.id === 'DETAIL_PICTURE') {
3330                logotype = this.getImageSources(allData.data, column.id),
3331                    img = BX.create('IMG', {props: {src: logotype && logotype.src_1x || this.defaultBasketItemLogo}});
3332
3333                if (logotype && logotype.src_1x && logotype.src_orig) {
3334                    BX.bind(img, 'click', BX.delegate(function (e) {
3335                        this.popupShow(e, logotype.src_orig);
3336                    }, this));
3337                }
3338
3339                textNode.appendChild(img);
3340            } else if (BX.util.in_array(column.id, ["QUANTITY", "WEIGHT_FORMATED", "DISCOUNT_PRICE_PERCENT_FORMATED"])) {
3341                textNode.appendChild(BX.create('SPAN', {html: data[column.id]}));
3342            } else if (column.id === 'PREVIEW_TEXT') {
3343                if (data['PREVIEW_TEXT_TYPE'] === 'html') {
3344                    textNode.appendChild(BX.create('SPAN', {html: data['PREVIEW_TEXT'] || ''}));
3345                } else {
3346                    textNode.appendChild(BX.create('SPAN', {text: data['PREVIEW_TEXT'] || ''}));
3347                }
3348            } else {
3349                var columnData = data[column.id], val = [];
3350                if (BX.type.isArray(columnData)) {
3351                    for (var i in columnData) {
3352                        if (columnData.hasOwnProperty(i)) {
3353                            if (columnData[i].type == 'image')
3354                                val.push(this.getImageContainer(columnData[i].value, columnData[i].source));
3355                            else if (columnData[i].type == 'linked') {
3356                                textNode.appendChild(BX.create('SPAN', {html: columnData[i].value_format}));
3357                                textNode.appendChild(BX.create('BR'));
3358                            } else if (columnData[i].value) {
3359                                textNode.appendChild(BX.create('SPAN', {html: columnData[i].value}));
3360                                textNode.appendChild(BX.create('BR'));
3361                            }
3362                        }
3363                    }
3364
3365                    if (val.length) {
3366                        textNode.appendChild(
3367                            BX.create('DIV', {
3368                                props: {className: 'bx-scu-list'},
3369                                children: [BX.create('UL', {props: {className: 'bx-scu-itemlist'}, children: val})]
3370                            })
3371                        );
3372                    }
3373                } else if (columnData) {
3374                    textNode.appendChild(BX.create('SPAN', {html: BX.util.htmlspecialchars(columnData)}));
3375                }
3376            }
3377
3378            return BX.create('DIV', {
3379                props: {className: 'bx-soa-item-td bx-soa-item-properties' + (toRight ? ' bx-text-right' : '')},
3380                children: [
3381                    BX.create('DIV', {
3382                        props: {className: 'bx-soa-item-td-title'},
3383                        text: column.name
3384                    }),
3385                    textNode
3386                ]
3387            });
3388        },
3389
3390        createBasketItemHiddenColumn: function (column, allData) {
3391            if (!column || !allData)
3392                return;
3393
3394            var data = allData.columns[column.id] ? allData.columns : allData.data,
3395                textNode = BX.create('TD', {props: {className: 'bx-soa-info-text'}}
3395),
3396                logotype, img, i;
3397
3398            if (column.id === 'PROPS') {
3399                var propsNodes = [], props = allData.data.PROPS;
3400                if (props && props.length) {
3401                    for (i in props) {
3402                        if (props.hasOwnProperty(i)) {
3403                            var name = props[i].NAME || '',
3404                                value = props[i].VALUE || '';
3405
3406                            if (value.length == 0)
3407                                continue;
3408
3409                            propsNodes.push(
3410                                BX.create('TR', {
3411                                    props: {className: 'bx-soa-info-line'},
3412                                    children: [
3413                                        BX.create('TD', {props: {className: 'bx-soa-info-title'}, text: name + ':'}),
3414                                        BX.create('TD', {
3415                                            props: {className: 'bx-soa-info-text'},
3416                                            html: BX.util.htmlspecialchars(value)
3417                                        })
3418                                    ]
3419                                })
3420                            );
3421                        }
3422                    }
3423
3424                    return propsNodes;
3425                } else return;
3426            } else if (column.id === 'PRICE_FORMATED') {
3427                textNode.appendChild(BX.create('STRONG', {props: {className: 'bx-price'}, html: data.PRICE_FORMATED}));
3428                if (parseFloat(data.DISCOUNT_PRICE) > 0) {
3429                    textNode.appendChild(BX.create('BR'));
3430                    textNode.appendChild(BX.create('STRONG', {
3431                        props: {className: 'bx-price-old'},
3432                        html: data.BASE_PRICE_FORMATED
3433                    }));
3434                }
3435            } else if (column.id === 'SUM')
3436                textNode.appendChild(BX.create('STRONG', {props: {className: 'bx-price all'}, text: data.SUM}));
3437            else if (column.id === 'DISCOUNT')
3438                textNode.appendChild(BX.create('STRONG', {
3439                    props: {className: 'bx-price'},
3440                    text: data.DISCOUNT_PRICE_PERCENT_FORMATED
3441                }));
3442            else if (column.id === 'DETAIL_PICTURE' || column.id === 'PREVIEW_PICTURE') {
3443                logotype = this.getImageSources(allData.data, column.id),
3444                    img = BX.create('IMG', {
3445                        props: {src: logotype && logotype.src_1x || this.defaultBasketItemLogo},
3446                        style: {maxWidth: '50%'}
3447                    });
3448
3449                if (logotype && logotype.src_1x && logotype.src_orig) {
3450                    BX.bind(img, 'click', BX.delegate(function (e) {
3451                        this.popupShow(e, logotype.src_orig);
3452                    }, this));
3453                }
3454
3455                textNode.appendChild(img);
3456            } else if (BX.util.in_array(column.id, ["QUANTITY", "WEIGHT_FORMATED", "DISCOUNT_PRICE_PERCENT_FORMATED"])) {
3457                textNode.appendChild(BX.create('SPAN', {html: data[column.id]}));
3458            } else if (column.id === 'PREVIEW_TEXT') {
3459                if (data['PREVIEW_TEXT_TYPE'] === 'html') {
3460                    textNode.appendChild(BX.create('SPAN', {html: data['PREVIEW_TEXT'] || ''}));
3461                } else {
3462                    textNode.appendChild(BX.create('SPAN', {text: data['PREVIEW_TEXT'] || ''}));
3463                }
3464            } else {
3465                var columnData = data[column.id], val = [];
3466                if (BX.type.isArray(columnData)) {
3467                    for (i in columnData) {
3468                        if (columnData.hasOwnProperty(i)) {
3469                            if (columnData[i].type == 'image')
3470                                val.push(this.getImageContainer(columnData[i].value, columnData[i].source));
3471                            else if (columnData[i].type == 'linked') {
3472                                textNode.appendChild(BX.create('SPAN', {html: columnData[i].value_format}));
3473                                textNode.appendChild(BX.create('BR'));
3474                            } else if (columnData[i].value) {
3475                                textNode.appendChild(BX.create('SPAN', {html: columnData[i].value}));
3476                                textNode.appendChild(BX.create('BR'));
3477                            } else return;
3478                        }
3479                    }
3480
3481                    if (val.length) {
3482                        textNode.appendChild(
3483                            BX.create('DIV', {
3484                                props: {className: 'bx-scu-list'},
3485                                children: [BX.create('UL', {props: {className: 'bx-scu-itemlist'}, children: val})]
3486                            })
3487                        );
3488                    }
3489
3490                } else if (columnData) {
3491                    textNode.appendChild(BX.create('SPAN', {html: BX.util.htmlspecialchars(columnData)}));
3492                } else {
3493                    return;
3494                }
3495            }
3496
3497            return BX.create('TR', {
3498                props: {className: 'bx-soa-info-line'},
3499                children: [
3500                    BX.create('TD', {
3501                        props: {className: 'bx-soa-info-title'},
3502                        text: column.name + ':'
3503                    }),
3504                    textNode
3505                ]
3506            });
3507        },
3508
3509        popupShow: function (e, url, source) {
3510            if (this.popup)
3511                this.popup.destroy();
3512
3513            var that = this;
3514            this.popup = new BX.PopupWindow('bx-soa-image-popup', null, {
3515                lightShadow: true,
3516                offsetTop: 0,
3517                offsetLeft: 0,
3518                closeIcon: {top: '3px', right: '10px'},
3519                autoHide: true,
3520                bindOptions: {position: "bottom"},
3521                closeByEsc: true,
3522                zIndex: 100,
3523                events: {
3524                    onPopupShow: function () {
3525                        BX.create("IMG", {
3526                            props: {src: source || url},
3527                            events: {
3528                                load: function () {
3529                                    var content = BX('bx-soa-image-popup-content');
3530                                    if (content) {
3531                                        var windowSize = BX.GetWindowInnerSize(),
3532                                            ratio = this.isMobile ? 0.5 : 0.9,
3533                                            contentHeight, contentWidth;
3534
3535                                        BX.cleanNode(content);
3536                                        content.appendChild(this);
3537
3538                                        contentHeight = content.offsetHeight;
3539                                        contentWidth = content.offsetWidth;
3540
3541                                        if (contentHeight >
3541 windowSize.innerHeight * ratio) {
3542                                            content.style.height = windowSize.innerHeight * ratio + 'px';
3543                                            content.style.width = contentWidth * (windowSize.innerHeight * ratio / contentHeight) + 'px';
3544                                            contentHeight = content.offsetHeight;
3545                                            contentWidth = content.offsetWidth;
3546                                        }
3547
3548                                        if (contentWidth > windowSize.innerWidth * ratio) {
3549                                            content.style.width = windowSize.innerWidth * ratio + 'px';
3550                                            content.style.height = contentHeight * (windowSize.innerWidth * ratio / contentWidth) + 'px';
3551                                        }
3552
3553                                        content.style.height = content.offsetHeight + 'px';
3554                                        content.style.width = content.offsetWidth + 'px';
3555
3556                                        that.popup.adjustPosition();
3557                                    }
3558                                }
3559                            }
3560                        });
3561                    },
3562                    onPopupClose: function () {
3563                        this.destroy();
3564                    }
3565                },
3566                content: BX.create('DIV', {
3567                    props: {id: 'bx-soa-image-popup-content'},
3568                    children: [BX.create('IMG', {props: {src: this.imgFolder + "/loader.gif"}})]
3569                })
3570            });
3571            this.popup.show();
3572        },
3573
3574        getImageContainer: function (link, source) {
3575            return BX.create('LI', {
3576                props: {className: 'bx-img-item'},
3577                children: [
3578                    BX.create('DIV', {
3579                        props: {className: 'bx-scu-itemColorBlock'},
3580                        children: [
3581                            BX.create('DIV', {
3582                                props: {className: 'bx-img-itemColor'},
3583                                style: {backgroundImage: 'url(' + link + ')'}
3584                            })
3585                        ],
3586                        events: {
3587                            click: BX.delegate(function (e) {
3588                                this.popupShow(e, link, source)
3589                            }, this)
3590                        }
3591                    })
3592                ]
3593            });
3594        },
3595
3596        getCouponChangeEvent: function () {
3597            return BX.delegate(function (event) {
3598                var newCoupon = BX.getEventTarget(event);
3599                if (newCoupon && newCoupon.value) {
3600                    this.sendRequest('enterCoupon', newCoupon.value);
3601                    newCoupon.value = '';
3602                }
3603            }, this);
3604        },
3605
3606        editCoupons: function (basketItemsNode) {
3607            var couponsList = this.getCouponsList(true),
3608                couponsLabel = this.getCouponsLabel(true),
3609                couponsBlock = BX.create('DIV', {
3610                    props: {className: 'bx-soa-coupon-block'},
3611                    children: [
3612                        BX.create('DIV', {
3613                            props: {className: 'bx-soa-coupon-input'},
3614                            children: [
3615                                BX.create('INPUT', {
3616                                    props: {
3617                                        className: 'tanais-form-control bx-ios-fix',
3618                                        type: 'text'
3619                                    },
3620                                    events: {
3621                                        change: this.getCouponChangeEvent()
3622                                    }
3623                                }),
3624                                BX.create("SPAN", {
3625                                    props: {
3626                                        className: 'bx-soa-coupon-btn'
3627                                    }
3628                                })
3629                            ]
3630                        }),
3631                        BX.create('SPAN', {props: {className: 'bx-soa-coupon-item'}, children: couponsList})
3632                    ]
3633                });
3634
3635            basketItemsNode.appendChild(
3636                BX.create('DIV', {
3637                    props: {className: 'bx-soa-coupon'},
3638                    children: [
3639                        couponsLabel,
3640                        couponsBlock
3641                    ]
3642                })
3643            );
3644        },
3645
3646        editCouponsFade: function (basketItemsNode) {
3647            if (this.result.COUPON_LIST.length < 1)
3648                return;
3649
3650            var couponsList = this.getCouponsList(false),
3651                couponsLabel, couponsBlock;
3652
3653            if (couponsList.length) {
3654                couponsLabel = this.getCouponsLabel(false);
3655                couponsBlock = BX.create('DIV', {
3656                    props: {className: 'bx-soa-coupon-block'},
3657                    children: [
3658                        BX.create('DIV', {
3659                            props: {className: 'bx-soa-coupon-list'},
3660                            children: [
3661                                BX.create('DIV', {
3662                                    props: {className: 'bx-soa-coupon-item'},
3663                                    children: [couponsLabel].concat(couponsList)
3664                                })
3665                            ]
3666                        })
3667                    ]
3668                });
3669
3670                basketItemsNode.appendChild(
3671                    BX.create('DIV', {
3672                        props: {className: 'bx-soa-coupon bx-soa-coupon-item-fixed'},
3673                        children: [couponsBlock]
3674                    })
3675                );
3676            }
3677        },
3678
3679        getCouponsList: function (active) {
3680            var couponsList = [], i;
3681
3682            for (i = 0; i < this.result.COUPON_LIST.length; i++) {
3683                if (active || (!active && this.result.COUPON_LIST[i].JS_STATUS == 'APPLIED')) {
3684                    couponsList.push(this.getCouponNode({
3685                        text: this.result.COUPON_LIST[i].COUPON,
3686                        desc: this.result.COUPON_LIST[i].JS_CHECK_CODE,
3687                        status: this.result.COUPON_LIST[i].JS_STATUS
3688                    }, active));
3689                }
3690            }
3691
3692            return couponsList;
3693        },
3694
3695        getCouponNode: function (coupon, active) {
3696            var couponName = BX.util.htmlspecialchars(coupon.text) || '',
3697                couponDesc = coupon.desc && coupon.desc.length
3698                    ? coupon.desc.charAt(0).toUpperCase() + coupon.desc.slice(1)
3699                    : BX.message('SOA_NOT_FOUND'),
3700                couponStatus = coupon.status || 'BAD',
3701                couponItem, tooltip;
3702
3703            switch (couponStatus.toUpperCase()) {
3704                case 'ENTERED':
3705                    couponItem = 'used';
3706                    tooltip = 'warning';
3707                    break;
3708                case 'BAD':
3709                    couponItem = tooltip = 'danger';
3710                    break;
3711                default:
3712                    couponItem = tooltip = 'success';
3713            }
3714
3715            return BX.create('STRONG', {
3716                attrs: {
3717                    'data-coupon': couponName,
3718                    className: 'bx-soa-coupon-item-' + couponItem
3719                },
3720                children: active ? [
3721                    couponName || '',
3722                    BX.create('SPAN', {
3723                        props: {className: 'bx-soa-coupon-remove'},
3724                        events: {
3725                            click: BX.delegate(function (e) {
3726                                var target = e.target || e.srcElement,
3727                                    coupon = BX.findParent(target, {tagName: 'STRONG'});
3728
3729                                if (coupon && coupon.getAttribute('data-coupon')) {
3730                                    this.sendRequest('removeCoupon', coupon.getAttribute('data-coupon'))
3731                                }
3732                            }, this)
3733                        }
3734                    })
3735                ] : [couponName]
3736            });
3737        },
3738
3739        getCouponsLabel: function (active) {
3740            return BX.create('DIV', {
3741                props: {className: 'bx-soa-coupon-label'},
3742                children: active
3743                    ? [BX.create('LABEL', {html: this.params.MESS_USE_COUPON + ':'})]
3744                    : [this.params.MESS_COUPON + ':']
3745            });
3746        },
3747
3748        addCoupon: function (coupon) {
3749            var couponListNodes = this.orderBlockNode.querySelectorAll('.bx-soa-coupon:not(.bx-soa-coupon-item-fixed) .bx-soa-coupon-item');
3750
3751            for (var i = 0; i < couponListNodes.length; i++) {
3752                if (couponListNodes[i].querySelector('[data-coupon="' + BX.util.htmlspecialchars(coupon) + '"]'))
3753                    break;
3754
3755                couponListNodes[i].appendChild(this.getCouponNode({text: coupon}, true, 'bx-soa-coupon-item-danger'));
3756            }
3757        },
3758
3759        removeCoupon: function (coupon) {
3760            var couponNodes = this.orderBlockNode.querySelectorAll('[data-coupon="' + BX.util.htmlspecialchars(coupon) + '"]'),
3761                i;
3762
3763            for (i in couponNodes) {
3764                if (couponNodes.hasOwnProperty(i)) {
3765                    BX.remove(couponNodes[i]);
3766                }
3767            }
3768        },
3769
3770        editRegionBlock: function (active) {
3771            if (!this.regionBlockNode || !this.regionHiddenBlockNode || !this.result.PERSON_TYPE)
3772                return;
3773
3774            if (active) {
3775                this.editActiveRegionBlock(true);
3776                !this.regionBlockNotEmpty && this.editFadeRegionBlock();
3777            } else
3778                this.editFadeRegionBlock();
3779
3780            this.initialized.region = true;
3781        },
3782
3783        editActiveRegionBlock: function (activeNodeMode) {
3784            var node = activeNodeMode ? this.regionBlockNode : this.regionHiddenBlockNode,
3785                regionContent, regionNode, regionNodeCol;
3786
3787            if (this.initialized.region) {
3788                BX.remove(BX.lastChild(node));
3789                node.appendChild(BX.firstChild(this.regionHiddenBlockNode));
3790            } else {
3791                regionContent = node.querySelector('.bx-soa-section-content');
3792                if (!regionContent) {
3793                    regionContent = this.getNewContainer();
3794                    node.appendChild(regionContent);
3795                } else
3796                    BX.cleanNode(regionContent);
3797
3798                this.getErrorContainer(regionContent);
3799
3800                regionNode = BX.create('DIV', {props: {className: 'bx_soa_location'}});
3801                regionNodeCol = BX.create('DIV', {});
3802
3803                this.getPersonTypeControl(regionNodeCol);
3804
3805                this.getProfilesControl(regionNodeCol);
3806
3807                this.getDeliveryLocationInput(regionNodeCol);
3808
3809                if (!this.result.SHOW_AUTH) {
3810                    if (this.regionBlockNotEmpty) {
3811                        BX.addClass(this.regionBlockNode, 'bx-active');
3812                        this.regionBlockNode.style.display = '';
3813                    } else {
3814                        BX.removeClass(this.regionBlockNode, 'bx-active');
3815                        this.regionBlockNode.style.display = 'none';
3816
3817                        if (!this.result.IS_AUTHORIZED || typeof this.result.LAST_ORDER_DATA.FAIL !== 'undefined')
3818                            this.initFirstSection();
3819                    }
3820                }
3821
3822                regionNode.appendChild(regionNodeCol);
3823                regionContent.appendChild(regionNode);
3824                this.getBlockFooter(regionContent);
3825            }
3826        },
3827
3828        editFadeRegionBlock: function () {
3829            var regionContent = this.regionBlockNode.querySelector('.bx-soa-section-content'), newContent;
3830
3831            if (this.initialized.region) {
3832                this.regionHiddenBlockNode.appendChild(regionContent);
3833            } else {
3834                this.editActiveRegionBlock(false);
3835                BX.remove(BX.lastChild(this.regionBlockNode));
3836            }
3837
3838            newContent = this.getNewContainer(true);
3839            this.regionBlockNode.appendChild(newContent);
3840            this.editFadeRegionContent(newContent);
3841        },
3842
3843        editFadeRegionContent: function (node) {
3844            if (!node || !this.locationsInitialized)
3845                return;
3846
3847            var selectedPersonType = this.getSelectedPersonType(),
3848                errorNode = this.regionHiddenBlockNode.querySelector('.alert.alert-danger'),
3849                addedHtml = '', props = [], locationProperty,
3850                input, zipValue = '', zipProperty,
3851                fadeParamName, i, k, locationString, validRegionErrors;
3852
3853            BX.cleanNode(node);
3854
3855            if (errorNode)
3856                node.appendChild(errorNode.cloneNode(true));
3857
3858            if (selectedPersonType && selectedPersonType.NAME && this.result.PERSON_TYPE.length > 1) {
3859                addedHtml += '<strong>' + this.params.MESS_PERSON_TYPE + ':</strong> '
3860                    + BX.util.htmlspecialchars(selectedPersonType.NAME) + '<br>';
3861            }
3862
3863            if (selectedPersonType) {
3864                fadeParamName = 'PROPS_FADE_LIST_' + selectedPersonType.ID;
3865                props = this.params[fadeParamName] || [];
3866            }
3867
3868            for (i in this.result.ORDER_PROP.properties) {
3869                if (this.result.ORDER_PROP.properties.hasOwnProperty(i)) {
3870                    if (this.result.ORDER_PROP.properties[i].IS_LOCATION == 'Y'
3871                        && this.result.ORDER_PROP.properties[i].ID == this.deliveryLocationInfo.loc) {
3872                        locationProperty = this.result.ORDER_PROP.properties[i];
3873                    } else if (this.result.ORDER_PROP.properties[i].IS_ZIP == 'Y'
3874                        && this.result.ORDER_PROP.properties[i].ID == this.deliveryLocationInfo.zip) {
3875                        zipProperty = this.result.ORDER_PROP.properties[i];
3876                        for (k = 0; k < props.length; k++) {
3877                            if (props[k] == zipProperty.ID) {
3878                                input = BX('zipProperty');
3879                                zipValue = input && input.value && input.value.length ? input.value : BX.message('SOA_NOT_SPECIFIED');
3880                                break;
3881                            }
3882                        }
3883                    }
3884                }
3885            }
3886
3887            locationString = this.getLocationString(this.regionHiddenBlockNode);
3888            if (locationProperty && locationString.length)
3889                addedHtml += '<strong>' + BX.util.htmlspecialchars(locationProperty.NAME) + ':</strong> '
3890                    + BX.util.htmlspecialchars(locationString) + '<br>';
3891
3892            if (zipProperty && zipValue.length)
3893                addedHtml += '<strong>' + BX.util.htmlspecialchars(zipProperty.NAME) + ':</strong> '
3894                    + BX.util.htmlspecialchars(zipValue);
3895
3896            node.innerHTML += addedHtml;
3897
3898            if (this.regionBlockNode.getAttribute('data-visited') == 'true') {
3899                validRegionErrors = this.isValidRegionBlock();
3900
3901                if (validRegionErrors.length) {
3902                    BX.addClass(this.regionBlockNode, 'bx-step-error');
3903                    this.showError(this.regionBlockNode, validRegionErrors);
3904                } else
3905                    BX.removeClass(this.regionBlockNode, 'bx-step-error');
3906            }
3907
3908            BX.bind(node.querySelector('.alert.alert-danger'), 'click', BX.proxy(this.showByClick, this));
3909            BX.bind(node.querySelector('.alert.alert-warning'), 'click', BX.proxy(this.showByClick, this));
3910        },
3911
3912        getSelectedPersonType: function () {
3913            var personTypeInput, currentPersonType, personTypeId, i,
3914                personTypeLength = this.result.PERSON_TYPE.length;
3915
3916            if (personTypeLength == 1) {
3917                personTypeInput = this.regionBlockNode.querySelector('input[type=hidden][name=PERSON_TYPE]');
3918                if (!personTypeInput)
3919                    personTypeInput = this.regionHiddenBlockNode.querySelector('input[type=hidden][name=PERSON_TYPE]');
3920            } else if (personTypeLength == 2) {
3921                personTypeInput = this.regionBlockNode.querySelector('input[type=radio][name=PERSON_TYPE]:checked');
3922                if (!personTypeInput)
3923                    personTypeInput = this.regionHiddenBlockNode.querySelector('input[type=radio][name=PERSON_TYPE]:checked');
3924            } else {
3925                personTypeInput = this.regionBlockNode.querySelector('select[name=PERSON_TYPE] > option:checked');
3926                if (!personTypeInput)
3927                    personTypeInput = this.regionHiddenBlockNode.querySelector('select[name=PERSON_TYPE] > option:checked');
3928            }
3929
3930            if (personTypeInput) {
3931                personTypeId = personTypeInput.value;
3932
3933                for (i in this.result.PERSON_TYPE) {
3934                    if (this.result.PERSON_TYPE[i].ID == personTypeId) {
3935                        currentPersonType = this.result.PERSON_TYPE[i];
3936                        break;
3937                    }
3938                }
3939            }
3940
3941            return currentPersonType;
3942        },
3943
3944        getDeliveryLocationInput: function (node) {
3945            var currentProperty, locationId, altId, location, k, altProperty,
3946                labelHtml, currentLocation, insertedLoc,
3947                labelTextHtml, label, input, altNode;
3948
3949            for (k in this.result.ORDER_PROP.properties) {
3950                if (this.result.ORDER_PROP.properties.hasOwnProperty(k)) {
3951                    currentProperty = this.result.ORDER_PROP.properties[k];
3952                    if (currentProperty.IS_LOCATION == 'Y') {
3953                        locationId = currentProperty.ID;
3954                        altId = parseInt(currentProperty.INPUT_FIELD_LOCATION);
3955                        break;
3956                    }
3957                }
3958            }
3959
3960            location = this.locations[locationId];
3961            if (location && location[0] && location[0].output) {
3962                this.regionBlockNotEmpty = true;
3963
3964                labelHtml = '<label class="bx-soa-custom-label" for="soa-property-' + parseInt(locationId) + '">'
3965                    + (currentProperty.REQUIRED == 'Y' ? '<span class="bx-authform-starrequired">*</span> ' : '')
3966                    + BX.util.htmlspecialchars(currentProperty.NAME)
3967                    + (currentProperty.DESCRIPTION.length ? ' <small>(' + BX.util.htmlspecialchars(currentProperty.DESCRIPTION) + ')</small>' : '')
3968                    + '</label>';
3969
3970                currentLocation = location[0].output;
3971                insertedLoc = BX.create('DIV', {
3972                    attrs: {'data-property-id-row': locationId},
3973                    props: {className: 'tanais-form-group bx-soa-location-input-container'},
3974                    style: {visibility: 'hidden'},
3975                    html: labelHtml + currentLocation.HTML
3976                });
3977                node.appendChild(insertedLoc);
3978                node.appendChild(BX.create('INPUT', {
3979                    props: {
3980                        type: 'hidden',
3981                        name: 'RECENT_DELIVERY_VALUE',
3982                        value: location[0].lastValue
3983                    }
3984                }));
3985
3986                for (k in currentLocation.SCRIPT)
3987                    if (currentLocation.SCRIPT.hasOwnProperty(k))
3988                        BX.evalGlobal(currentLocation.SCRIPT[k].JS);
3989            }
3990
3991            if (location && location[0] && location[0].showAlt && altId > 0) {
3992                for (k in this.result.ORDER_PROP.properties) {
3993                    if (parseInt(this.result.ORDER_PROP.properties[k].ID) == altId) {
3994                        altProperty = this.result.ORDER_PROP.properties[k];
3995                        break;
3996                    }
3997                }
3998            }
3999
4000            if (altProperty) {
4001                altNode = BX.create('DIV', {
4002                    attrs: {'data-property-id-row': altProperty.ID},
4003                    props: {className: "tanais-form-group bx-soa-location-input-container"}
4004                });
4005
4006                labelTextHtml = altProperty.REQUIRED == 'Y' ? '<span class="bx-authform-starrequired">*</span> ' : '';
4007                labelTextHtml += BX.util.htmlspecialchars(altProperty.NAME);
4008
4009                label = BX.create('LABEL', {
4010                    attrs: {for: 'altProperty'},
4011                    props: {className: 'bx-soa-custom-label'},
4012                    html: labelTextHtml
4013                });
4014
4015                input = BX.create('INPUT', {
4016                    props: {
4017                        id: 'altProperty',
4018                        type: 'text',
4019                        placeholder: altProperty.DESCRIPTION,
4020                        autocomplete: 'city',
4021                        className: 'tanais-form-control bx-soa-customer-input bx-ios-fix',
4022                        name: 'ORDER_PROP_' + altProperty.ID,
4023                        value: altProperty.VALUE
4024                    }
4025                });
4026
4027                altNode.appendChild(label);
4028                altNode.appendChild(input);
4029                node.appendChild(altNode);
4030
4031                this.bindValidation(altProperty.ID, altNode);
4032            }
4033
4034            this.getZipLocationInput(node);
4035
4036            /*if (location && location[0])
4037			{
4038				node.appendChild(
4039					BX.create('DIV', {
4040						props: {className: 'bx-soa-reference'},
4041						html: this.params.MESS_REGION_REFERENCE
4042					})
4043				);
4044			}*/
4045        },
4046
4047        getLocationString: function (node) {
4048            if (!node)
4049                return '';
4050
4051            var locationInputNode = node.querySelector('.bx-ui-sls-route'),
4052                locationString = '',
4053                locationSteps, i, altLoc;
4054
4055            if (locationInputNode && locationInputNode.value && locationInputNode.value.length)
4056                locationString = locationInputNode.value;
4057            else {
4058                locationSteps = node.querySelectorAll('.bx-ui-combobox-fake.bx-combobox-fake-as-input');
4059                for (i = locationSteps.length; i--;) {
4060                    if (locationSteps[i].innerHTML.indexOf('...') >= 0)
4061                        continue;
4062
4063                    if (locationSteps[i].innerHTML.indexOf('---') >= 0) {
4064                        altLoc = BX('altProperty');
4065                        if (altLoc && altLoc.value.length)
4066                            locationString += altLoc.value;
4067
4068                        continue;
4069                    }
4070
4071                    if (locationString.length)
4072                        locationString += ', ';
4073
4074                    locationString += locationSteps[i].innerHTML;
4075                }
4076
4077                if (locationString.length == 0)
4078                    locationString = BX.message('SOA_NOT_SPECIFIED');
4079            }
4080
4081            return locationString;
4082        },
4083
4084        getZipLocationInput: function (node) {
4085            var zipProperty, i, propsItemNode, labelTextHtml, label, input;
4086
4087            for (i in this.result.ORDER_PROP.properties) {
4088                if (this.result.ORDER_PROP.properties.hasOwnProperty(i) && this.result.ORDER_PROP.properties[i].IS_ZIP == 'Y') {
4089                    zipProperty = this.result.ORDER_PROP.properties[i];
4090                    break;
4091                }
4092            }
4093
4094            if (zipProperty) {
4095                this.regionBlockNotEmpty = true;
4096
4097                propsItemNode = BX.create('DIV', {props: {className: "tanais-form-group bx-soa-location-input-container"}});
4098                propsItemNode.setAttribute('data-property-id-row', zipProperty.ID);
4099
4100                labelTextHtml = zipProperty.REQUIRED == 'Y' ? '<span class="bx-authform-starrequired">*</span> ' : '';
4101                labelTextHtml += BX.util.htmlspecialchars(zipProperty.NAME);
4102
4103                label = BX.create('LABEL', {
4104                    attrs: {'for': 'zipProperty'},
4105                    props: {className: 'bx-soa-custom-label'},
4106                    html: labelTextHtml
4107                });
4108                input = BX.create('INPUT', {
4109                    props: {
4110                        id: 'zipProperty',
4111                        type: 'text',
4112                        placeholder: zipProperty.DESCRIPTION,
4113                        autocomplete: 'zip',
4114                        className: 'tanais-form-control bx-soa-customer-input bx-ios-fix',
4115                        name: 'ORDER_PROP_' + zipProperty.ID,
4116                        value: zipProperty.VALUE
4117                    }
4118                });
4119
4120                propsItemNode.appendChild(label);
4121                propsItemNode.appendChild(input);
4122                node.appendChild(propsItemNode);
4123                node.appendChild(
4124                    BX.create('input', {
4125                        props: {
4126                            id: 'ZIP_PROPERTY_CHANGED',
4127                            name: 'ZIP_PROPERTY_CHANGED',
4128                            type: 'hidden',
4129                            value: this.result.ZIP_PROPERTY_CHANGED || 'N'
4130                        }
4131                    })
4132                );
4133
4134                this.bindValidation(zipProperty.ID, propsItemNode);
4135            }
4136        },
4137
4138        getPersonTypeSortedArray: function (objPersonType) {
4139            var personTypes = [], k;
4140
4141            for (k in objPersonType) {
4142                if (objPersonType.hasOwnProperty(k)) {
4143                    personTypes.push(objPersonType[k]);
4144                }
4145            }
4146
4147            return personTypes.sort(function (a, b) {
4148                return parseInt(a.SORT) - parseInt(b.SORT)
4149            });
4150        },
4151
4152        getPersonTypeControl: function (node) {
4153            if (!this.result.PERSON_TYPE)
4154                return;
4155
4156            this.result.PERSON_TYPE = this.getPersonTypeSortedArray(this.result.PERSON_TYPE);
4157
4158            var personTypesCount = this.result.PERSON_TYPE.length,
4159                currentType, oldPersonTypeId, i,
4160                input, options = [], label, delimiter = false;
4161
4162            if (personTypesCount > 1) {
4163                input = BX.create('DIV', {
4164                    props: {className: 'tanais-form-group person-type'},
4165                });
4166                node.appendChild(input);
4167                node = input;
4168            }
4169
4170            if (personTypesCount > 2) {
4171                for (i in this.result.PERSON_TYPE) {
4172                    if (this.result.PERSON_TYPE.hasOwnProperty(i)) {
4173                        currentType = this.result.PERSON_TYPE[i];
4174                        options.push(BX.create('OPTION', {
4175                            props: {
4176                                value: currentType.ID,
4177                                selected: currentType.CHECKED == 'Y'
4178                            },
4179                            text: currentType.NAME
4180                        }));
4181
4182                        if (currentType.CHECKED == 'Y')
4183                            oldPersonTypeId = currentType.ID;
4184                    }
4185
4186                }
4187                node.appendChild(BX.create('SELECT', {
4188                    props: {name: 'PERSON_TYPE', className: 'tanais-form-control'},
4189                    children: options,
4190                    events: {change: BX.proxy(this.sendRequest, this)}
4191                }));
4192
4193                this.regionBlockNotEmpty = true;
4194            } else if (personTypesCount == 2) {
4195                for (i in this.result.PERSON_TYPE) {
4196                    if (this.result.PERSON_TYPE.hasOwnProperty(i)) {
4197                        currentType = this.result.PERSON_TYPE[i];
4198                        label = BX.create('LABEL', {
4199                            children: [
4200                                BX.create('INPUT', {
4201                                    attrs: {checked: currentType.CHECKED == 'Y'},
4202                                    props: {type: 'radio', name: 'PERSON_TYPE', value: currentType.ID}
4203                                }),
4204                                BX.util.htmlspecialchars(currentType.NAME)
4205                            ],
4206                            events: {change: BX.proxy(this.sendRequest, this)}
4207                        });
4208
4209                        node.appendChild(
4210                            BX.create('DIV', {
4211                                props: {
4212                                    className: 'tanais-radio-inline' + (currentType.CHECKED == 'Y' ? " checked" : "")
4213                                },
4214                                children: [label]
4215                            })
4216                        );
4217
4218                        delimiter = true;
4219
4220                        if (currentType.CHECKED == 'Y')
4221                            oldPersonTypeId = currentType.ID;
4222                    }
4223                }
4224
4225                this.regionBlockNotEmpty = true;
4226            } else {
4227                for (i in this.result.PERSON_TYPE)
4228                    if (this.result.PERSON_TYPE.hasOwnProperty(i))
4229                        node.appendChild(BX.create('INPUT', {
4230                            props: {
4231                                type: 'hidden',
4232                                name: 'PERSON_TYPE',
4233                                value: this.result.PERSON_TYPE[i].ID
4234                            }
4235                        }));
4236            }
4237
4238            if (oldPersonTypeId) {
4239                node.appendChild(
4240                    BX.create('INPUT', {
4241                        props: {
4242                            type: 'hidden',
4243                            name: 'PERSON_TYPE_OLD',
4244                            value: oldPersonTypeId
4245
4246                        }
4247                    })
4248                );
4249            }
4250        },
4251
4252        getProfilesControl: function (node) {
4253            var profilesLength = BX.util.object_keys(this.result.USER_PROFILES).length,
4254                i, label, options = [],
4255                profileChangeInput, input;
4256
4257            if (profilesLength) {
4258                if (
4259                    this.params.ALLOW_USER_PROFILES === 'Y'
4260                    && (profilesLength > 1 || this.params.ALLOW_NEW_PROFILE === 'Y')
4261                ) {
4262                    this.regionBlockNotEmpty = true;
4263
4264                    label = BX.create('LABEL', {
4265                        props: {className: 'bx-soa-custom-label'},
4266                        html: this.params.MESS_SELECT_PROFILE
4267                    });
4268
4269                    for (i in this.result.USER_PROFILES) {
4270                        if (this.result.USER_PROFILES.hasOwnProperty(i)) {
4271                            options.unshift(
4272                                BX.create('OPTION', {
4273                                    props: {
4274                                        value: this.result.USER_PROFILES[i].ID,
4275                                        selected: this.result.USER_PROFILES[i].CHECKED === 'Y'
4276                                    },
4277                                    html: this.result.USER_PROFILES[i].NAME
4278                                })
4279                            );
4280                        }
4281                    }
4282
4283                    if (this.params.ALLOW_NEW_PROFILE === 'Y') {
4284                        options.unshift(BX.create('OPTION', {
4285                            props: {value: 0},
4286                            text: BX.message('SOA_PROP_NEW_PROFILE')
4287                        }));
4288                    }
4289
4290                    profileChangeInput = BX.create('INPUT', {
4291                        props: {
4292                            type: 'hidden',
4293                            value: 'N',
4294                            id: 'profile_change',
4295                            name: 'profile_change'
4296                        }
4297                    });
4298                    input = BX.create('SELECT', {
4299                        props: {className: 'tanais-form-control', name: 'PROFILE_ID'},
4300                        children: options,
4301                        events: {
4302                            change: BX.delegate(function () {
4303                                BX('profile_change').value = 'Y';
4304                                this.sendRequest();
4305                            }, this)
4306                        }
4307                    });
4308
4309                    node.appendChild(
4310                        BX.create('DIV', {
4311                            props: {className: 'tanais-form-group bx-soa-location-input-container'},
4312                            children: [label, profileChangeInput, input]
4313                        })
4314                    );
4315                } else {
4316                    for (i in this.result.USER_PROFILES) {
4317                        if (
4318                            this.result.USER_PROFILES.hasOwnProperty(i)
4319                            && this.result.USER_PROFILES[i].CHECKED === 'Y'
4320                        ) {
4321                            node.appendChild(
4322                                BX.create('INPUT', {
4323                                    props: {
4324                                        name: 'PROFILE_ID',
4325                                        type: 'hidden',
4326                                        value: this.result.USER_PROFILES[i].ID
4327                                    }
4328                                })
4329                            );
4330                        }
4331                    }
4332                }
4333            }
4334        },
4335
4336        editPaySystemBlock: function (active) {
4337            if (!this.paySystemBlockNode || !this.paySystemHiddenBlockNode || !this.result.PAY_SYSTEM)
4338                return;
4339
4340            if (active)
4341                this.editActivePaySystemBlock(true);
4342            else
4343                this.editFadePaySystemBlock();
4344
4345            this.initialized.paySystem = true;
4346        },
4347
4348        editActivePaySystemBlock: function (activeNodeMode) {
4349            var node = activeNodeMode ? this.paySystemBlockNode : this.paySystemHiddenBlockNode,
4350                paySystemContent, paySystemNode;
4351
4352            if (this.initialized.paySystem) {
4353                BX.remove(BX.lastChild(node));
4354                node.appendChild(BX.firstChild(this.paySystemHiddenBlockNode));
4355            } else {
4356                paySystemContent = node.querySelector('.bx-soa-section-content');
4357                if (!paySystemContent) {
4358                    paySystemContent = this.getNewContainer();
4359                    node.appendChild(paySystemContent);
4360                } else
4361                    BX.cleanNode(paySystemContent);
4362
4363                this.getErrorContainer(paySystemContent);
4364                paySystemNode = BX.create('DIV', {props: {className: 'bx-soa-pp'}});
4365                this.editPaySystemItems(paySystemNode);
4366                paySystemContent.appendChild(paySystemNode);
4367
4368                if (this.params.SHOW_COUPONS_PAY_SYSTEM == 'Y')
4369                    this.editCoupons(paySystemContent);
4370
4371                this.getBlockFooter(paySystemContent);
4372            }
4373        },
4374
4375        editFadePaySystemBlock: function () {
4376            var paySystemContent = this.paySystemBlockNode.querySelector('.bx-soa-section-content'), newContent;
4377
4378            if (this.initialized.paySystem) {
4379                this.paySystemHiddenBlockNode.appendChild(paySystemContent);
4380            } else {
4381                this.editActivePaySystemBlock(false);
4382                BX.remove(BX.lastChild(this.paySystemBlockNode));
4383            }
4384
4385            newContent = this.getNewContainer(true);
4386            this.paySystemBlockNode.appendChild(newContent);
4387
4388            this.editFadePaySystemContent(newContent);
4389
4390            if (this.params.SHOW_COUPONS_PAY_SYSTEM == 'Y')
4391                this.editCouponsFade(newContent);
4392        },
4393
4394        editPaySystemItems: function (paySystemNode) {
4395            if (!this.result.PAY_SYSTEM || this.result.PAY_SYSTEM.length <= 0)
4396                return;
4397
4398            var paySystemItemsContainer = BX.create('DIV', {props: {className: 'bx-soa-pp-item-container'}}),
4399                paySystemItemNode, i;
4400
4401            for (i = 0; i < this.paySystemPagination.currentPage.length; i++) {
4402                paySystemItemNode = this.createPaySystemItem(this.paySystemPagination.currentPage[i]);
4403                paySystemItemsContainer.appendChild(paySystemItemNode);
4404            }
4405
4406            if (this.paySystemPagination.show)
4407                this.showPagination('paySystem', paySystemItemsContainer);
4408
4409            paySystemNode.appendChild(paySystemItemsContainer);
4410        },
4411
4412        createPaySystemItem: function (item) {
4413            var checked = item.CHECKED == 'Y',
4414                paySystemId = parseInt(item.ID),
4415                title, label, itemNode;
4416
4417            label = BX.create('DIV', {
4418                props: {className: 'bx-soa-pp-company-graf-container'},
4419                children: [
4420                    BX.create('INPUT', {
4421                        props: {
4422                            id: 'ID_PAY_SYSTEM_ID_' + paySystemId,
4423                            name: 'PAY_SYSTEM_ID',
4424                            type: 'checkbox',
4425                            className: 'bx-soa-pp-company-checkbox',
4426                            value: paySystemId,
4427                            checked: checked
4428                        }
4429                    }),
4430                    BX.create('SPAN', {
4431                        props: {
4432                            className: 'style-checkbox'
4433                        }
4434                    })
4435                ]
4436            });
4437
4438            if (this.params.SHOW_PAY_SYSTEM_LIST_NAMES == 'Y') {
4439                title = BX.create('DIV', {props: {className: 'bx-soa-pp-company-smalltitle'}, text: item.NAME});
4440            }
4441
4442            itemNode = BX.create('DIV', {
4443                props: {className: 'bx-soa-pp-company'},
4444                children: [
4445                    label,
4446                    title,
4447                    BX.create('DIV', {
4448                        props: {className: 'bx-soa-pp-company-smalldescr'},
4449                        html: item.DESCRIPTION
4450                    })
4451                ],
4452                events: {
4453                    click: BX.proxy(this.selectPaySystem, this)
4454                }
4455            });
4456
4457            if (checked)
4458                BX.addClass(itemNode, 'bx-selected');
4459
4460            return itemNode;
4461        },
4462
4463        getInnerPaySystem: function () {
4464            if (!this.result.CURRENT_BUDGET_FORMATED || !this.result.PAY_CURRENT_ACCOUNT || !this.result.INNER_PAY_SYSTEM)
4465                return;
4466
4467            var accountOnly = this.params.ONLY_FULL_PAY_FROM_ACCOUNT && (this.params.ONLY_FULL_PAY_FROM_ACCOUNT == 'Y'),
4468                isSelected = this.result.PAY_CURRENT_ACCOUNT && (this.result.PAY_CURRENT_ACCOUNT == 'Y'),
4469                paySystem = this.result.INNER_PAY_SYSTEM,
4470                logotype, logoNode, subTitle, label, title, hiddenInput, htmlString, innerPsDesc;
4471
4472            if (this.params.SHOW_PAY_SYSTEM_INFO_NAME == 'Y') {
4473                subTitle = BX.create('DIV', {
4474                    props: {className: 'bx-soa-pp-company-subTitle'},
4475                    text: paySystem.NAME
4476                });
4477            }
4478
4479            logoNode = BX.create('DIV', {props: {className: 'bx-soa-pp-company-image'}});
4480            logotype = this.getImageSources(paySystem, 'LOGOTIP');
4481            if (logotype && logotype.src_2x) {
4482                logoNode.setAttribute('style',
4483                    'background-image: url(' + logotype.src_1x + ');' +
4484                    'background-image: -webkit-image-set(url(' + logotype.src_1x + ') 1x, url(' + logotype.src_2x + ') 2x)'
4485                );
4486            } else {
4487                logotype = logotype && logotype.src_1x || this.defaultPaySystemLogo;
4488                logoNode.setAttribute('style', 'background-image: url(' + logotype + ');');
4489            }
4490
4491            label = BX.create('DIV', {
4492                props: {className: 'bx-soa-pp-company-logo'},
4493                children: [
4494                    BX.create('DIV', {
4495                        props: {className: 'bx-soa-pp-company-graf-container'},
4496                        children: [
4497                            BX.create('INPUT', {
4498                                props: {
4499                                    type: 'checkbox',
4500                                    className: 'bx-soa-pp-company-checkbox',
4501                                    name: 'PAY_CURRENT_ACCOUNT',
4502                                    value: 'Y',
4503                                    checked: isSelected
4504                                }
4505                            }),
4506                            logoNode
4507                        ],
4508                        events: {
4509                            click: BX.proxy(this.selectPaySystem, this)
4510                        }
4511                    })
4512                ]
4513            });
4514
4515            if (paySystem.DESCRIPTION && paySystem.DESCRIPTION.length) {
4516                title = BX.create('DIV', {
4517                    props: {className: 'bx-soa-pp-company-block'},
4518                    children: [BX.create('DIV', {
4519                        props: {className: 'bx-soa-pp-company-desc'},
4520                        html: paySystem.DESCRIPTION
4521                    })]
4522                });
4523            }
4524
4525            hiddenInput = BX.create('INPUT', {
4526                props: {
4527                    type: 'hidden',
4528                    name: 'PAY_CURRENT_ACCOUNT',
4529                    value: 'N'
4530                }
4531            });
4532
4533            htmlString = this.params.MESS_INNER_PS_BALANCE + ' <b class="wsnw">' + this.result.CURRENT_BUDGET_FORMATED
4534                + '</b><br>
4534' + (accountOnly ? BX.message('SOA_PAY_ACCOUNT3') : '');
4535            innerPsDesc = BX.create('DIV', {props: {className: 'bx-soa-pp-company-desc'}, html: htmlString});
4536
4537            return BX.create('DIV', {
4538                props: {className: 'bx-soa-pp-inner-ps' + (isSelected ? ' bx-selected' : '')},
4539                children: [hiddenInput, subTitle, label, title, innerPsDesc]
4540            });
4541        },
4542
4543        editFadePaySystemContent: function (node) {
4544            var selectedPaySystem = this.getSelectedPaySystem(),
4545                errorNode = this.paySystemHiddenBlockNode.querySelector('div.alert.alert-danger'),
4546                warningNode = this.paySystemHiddenBlockNode.querySelector('div.alert.alert-warning.alert-show'),
4547                addedHtml = '', logotype, imgSrc;
4548
4549            if (errorNode)
4550                node.appendChild(errorNode.cloneNode(true));
4551            else
4552                this.getErrorContainer(node);
4553
4554            if (warningNode && warningNode.innerHTML)
4555                node.appendChild(warningNode.cloneNode(true));
4556
4557            if (this.isSelectedInnerPayment()) {
4558                logotype = this.getImageSources(this.result.INNER_PAY_SYSTEM, 'LOGOTIP');
4559                imgSrc = logotype && logotype.src_1x || this.defaultPaySystemLogo;
4560
4561                addedHtml += '<div class="bx-soa-pp-company-selected">';
4562                addedHtml += '<img src="' + imgSrc + '" style="height:18px;" alt="">';
4563                addedHtml += '<strong>' + this.result.INNER_PAY_SYSTEM.NAME + '</strong><br>';
4564                addedHtml += '</div>';
4565            }
4566
4567            if (selectedPaySystem && selectedPaySystem.NAME) {
4568                logotype = this.getImageSources(selectedPaySystem, 'PSA_LOGOTIP');
4569                imgSrc = logotype && logotype.src_1x || this.defaultPaySystemLogo;
4570
4571                addedHtml += '<div class="bx-soa-pp-company-selected">';
4572                addedHtml += '<img src="' + imgSrc + '" style="height:18px;" alt="">';
4573                addedHtml += '<strong>' + BX.util.htmlspecialchars(selectedPaySystem.NAME) + '</strong>';
4574                addedHtml += '</div>';
4575            }
4576
4577            if (!addedHtml.length)
4578                addedHtml = '<strong>' + BX.message('SOA_PS_SELECT_ERROR') + '</strong>';
4579
4580            node.innerHTML += addedHtml;
4581
4582            node.appendChild(BX.create('DIV', {style: {clear: 'both'}}));
4583            BX.bind(node.querySelector('.alert.alert-danger'), 'click', BX.proxy(this.showByClick, this));
4584            BX.bind(node.querySelector('.alert.alert-warning'), 'click', BX.proxy(this.showByClick, this));
4585        },
4586
4587        getSelectedPaySystem: function () {
4588            var paySystemCheckbox = this.paySystemBlockNode.querySelector('input[type=checkbox][name=PAY_SYSTEM_ID]:checked'),
4589                currentPaySystem = null, paySystemId, i;
4590
4591            if (!paySystemCheckbox)
4592                paySystemCheckbox = this.paySystemHiddenBlockNode.querySelector('input[type=checkbox][name=PAY_SYSTEM_ID]:checked');
4593
4594            if (!paySystemCheckbox)
4595                paySystemCheckbox = this.paySystemHiddenBlockNode.querySelector('input[type=hidden][name=PAY_SYSTEM_ID]');
4596
4597            if (paySystemCheckbox) {
4598                paySystemId = paySystemCheckbox.value;
4599
4600                for (i = 0; i < this.result.PAY_SYSTEM.length; i++) {
4601                    if (this.result.PAY_SYSTEM[i].ID == paySystemId) {
4602                        currentPaySystem = this.result.PAY_SYSTEM[i];
4603                        break;
4604                    }
4605                }
4606            }
4607
4608            return currentPaySystem;
4609        },
4610
4611        isSelectedInnerPayment: function () {
4612            var innerPaySystemCheckbox = this.paySystemBlockNode.querySelector('input[type=checkbox][name=PAY_CURRENT_ACCOUNT]');
4613
4614            if (!innerPaySystemCheckbox)
4615                innerPaySystemCheckbox = this.paySystemHiddenBlockNode.querySelector('input[type=checkbox][name=PAY_CURRENT_ACCOUNT]');
4616
4617            return innerPaySystemCheckbox && innerPaySystemCheckbox.checked;
4618        },
4619
4620        selectPaySystem: function (event) {
4621            if (!this.orderBlockNode || !event)
4622                return;
4623
4624            var target = event.target || event.srcElement,
4625                innerPaySystemSection = this.paySystemBlockNode.querySelector('div.bx-soa-pp-inner-ps'),
4626                innerPaySystemCheckbox = this.paySystemBlockNode.querySelector('input[type=checkbox][name=PAY_CURRENT_ACCOUNT]'),
4627                fullPayFromInnerPaySystem = this.result.TOTAL && parseFloat(this.result.TOTAL.ORDER_TOTAL_LEFT_TO_PAY) === 0;
4628
4629            var innerPsAction = BX.hasClass(target, 'bx-soa-pp-inner-ps') ? target : BX.findParent(target, {className: 'bx-soa-pp-inner-ps'}),
4630                actionSection = BX.hasClass(target, 'bx-soa-pp-company') ? target : BX.findParent(target, {className: 'bx-soa-pp-company'}),
4631                actionInput, selectedSection;
4632
4633            if (innerPsAction) {
4634                if (target.nodeName == 'INPUT')
4635                    innerPaySystemCheckbox.checked = !innerPaySystemCheckbox.checked;
4636
4637                if (innerPaySystemCheckbox.checked) {
4638                    BX.removeClass(innerPaySystemSection, 'bx-selected');
4639                    innerPaySystemCheckbox.checked = false;
4640                } else {
4641                    BX.addClass(innerPaySystemSection, 'bx-selected');
4642                    innerPaySystemCheckbox.checked = true;
4643                }
4644            } else if (actionSection) {
4645                if (BX.hasClass(actionSection, 'bx-selected')) {
4646                    if (target.nodeName == "A") {
4647                        return;
4648                    }
4649                    return BX.PreventDefault(event);
4650                }
4651
4652                if (innerPaySystemCheckbox && innerPaySystemCheckbox.checked && fullPayFromInnerPaySystem) {
4653                    BX.addClass(actionSection, 'bx-selected');
4654                    actionInput = actionSection.querySelector('input[type=checkbox]');
4655                    actionInput.checked = true;
4656                    BX.removeClass(innerPaySystemSection, 'bx-selected');
4657                    innerPaySystemCheckbox.checked = false;
4658                } else {
4659                    selectedSection = this.paySystemBlockNode.querySelector('.bx-soa-pp-company.bx-selected');
4660                    BX.addClass(actionSection, 'bx-selected');
4661                    actionInput = actionSection.querySelector('input[type=checkbox]');
4662                    actionInput.checked = true;
4663
4664                    if (selectedSection) {
4665                        BX.removeClass(selectedSection, 'bx-selected');
4666                        selectedSection.querySelector('input[type=checkbox]').checked = false;
4667                    }
4668                }
4669            }
4670
4671            this.sendRequest();
4672        },
4673
4674        editDeliveryBlock: function (active) {
4675            if (!this.deliveryBlockNode || !this.deliveryHiddenBlockNode || !this.result.DELIVERY)
4676                return;
4677
4678            if (active)
4679                this.editActiveDeliveryBlock(true);
4680            else
4681                this.editFadeDeliveryBlock();
4682
4683            this.checkPickUpShow();
4684
4685            this.initialized.delivery = true;
4686        },
4687
4688        editActiveDeliveryBlock: function (activeNodeMode) {
4689            var node = activeNodeMode ? this.deliveryBlockNode : this.deliveryHiddenBlockNode,
4690                deliveryContent, deliveryNode;
4691
4692            if (!this.initialized.delivery) {
4693                deliveryContent = node.querySelector('.bx-soa-section-content');
4694                if (!deliveryContent) {
4695                    deliveryContent = this.getNewContainer();
4696                    node.appendChild(deliveryContent);
4697                } else
4698                    BX.cleanNode(deliveryContent);
4699
4700                this.getErrorContainer(deliveryContent);
4701
4702                deliveryNode = BX.create('DIV', {props: {className: 'bx-soa-pp'}});
4703                this.editDeliveryItems(deliveryNode);
4704                deliveryContent.appendChild(deliveryNode);
4705                this.editDeliveryInfo(deliveryNode);
4706
4707                if (this.params.SHOW_COUPONS_DELIVERY == 'Y')
4708                    this.editCoupons(deliveryContent);
4709
4710                this.getBlockFooter(deliveryContent);
4711            }
4712        },
4713
4714        editDeliveryItems: function (deliveryNode) {
4715            if (!this.result.DELIVERY || this.result.DELIVERY.length <= 0)
4716                return;
4717
4718            var deliveryItemsContainer = BX.create('DIV', {props: {className: 'bx-soa-pp-item-container'}}),
4719                deliveryItemNode, k;
4720
4721            for (k = 0; k < this.deliveryPagination.currentPage.length; k++) {
4722                deliveryItemNode = this.createDeliveryItem(this.deliveryPagination.currentPage[k]);
4723                deliveryItemsContainer.appendChild(deliveryItemNode);
4724            }
4725
4726            if (this.deliveryPagination.show)
4727                this.showPagination('delivery', deliveryItemsContainer);
4728
4729            deliveryNode.appendChild(deliveryItemsContainer);
4730        },
4731
4732        editDeliveryInfo: function (deliveryNode) {
4733            if (!this.result.DELIVERY)
4734                return;
4735
4736            var deliveryInfoContainer = BX.create('DIV', {props: {className: 'bx-soa-pp-desc-container'}}),
4737                currentDelivery, title, period,
4738                infoList, extraServices, extraServicesNode;
4739
4740            var isShowDeliveryInfo = false;
4741            var issetPeriod = false;
4742
4743            BX.cleanNode(deliveryInfoContainer);
4744            currentDelivery = this.getSelectedDelivery();
4745
4746            title = BX.create('DIV', {
4747                props: {className: 'bx-soa-pp-company-block'},
4748                children: [
4749                    currentDelivery.CALCULATE_DESCRIPTION
4750                        ? (isShowDeliveryInfo = true) && BX.create('DIV', {
4751                        props: {className: 'bx-soa-pp-company-desc'},
4752                        html: currentDelivery.CALCULATE_DESCRIPTION
4753                    })
4754                        : null
4755                ]
4756            });
4757
4758            if (currentDelivery.PERIOD_TEXT && currentDelivery.PERIOD_TEXT.length) {
4759                period = BX.create('LI', {
4760                    children: [
4761                        BX.create('DIV', {
4762                            props: {className: 'bx-soa-pp-list-termin'},
4763                            html: this.params.MESS_PERIOD + ':'
4764                        }),
4765                        BX.create('DIV', {
4766                            props: {className: 'bx-soa-pp-list-description'},
4767                            html: currentDelivery.PERIOD_TEXT
4768                        })
4769                    ]
4770                });
4771
4772                isShowDeliveryInfo = issetPeriod = true;
4773            }
4774
4775            infoList = !issetPeriod ? null : BX.create('UL', {
4776                props: {className: 'bx-soa-pp-list'},
4777                children: [period]
4778            });
4779            extraServices = this.getDeliveryExtraServices(currentDelivery);
4780
4781            if (extraServices.length) {
4782                extraServicesNode = BX.create('DIV', {
4783                    props: {className: 'bx-soa-pp-company-block'},
4784                    children: extraServices
4785                });
4786                isShowDeliveryInfo = true;
4787            }
4788
4789            if (isShowDeliveryInfo) {
4790                deliveryInfoContainer.appendChild(
4791                    BX.create('DIV', {
4792                        props: {className: 'bx-soa-pp-company'},
4793                        children: [title, extraServicesNode, infoList]
4794                    })
4795                );
4796
4797                deliveryNode.appendChild(deliveryInfoContainer);
4798
4799                BX("bx_soa_item_delivery_id_" + currentDelivery.ID).appendChild(deliveryInfoContainer);
4800            }
4801
4802            if (this.params.DELIVERY_NO_AJAX != 'Y')
4803                this.deliveryCachedInfo[currentDelivery.ID] = currentDelivery;
4804        },
4805
4806        getDeliveryPriceNodes: function (delivery) {
4807            var priceNodesArray;
4808
4809            if (typeof delivery.DELIVERY_DISCOUNT_PRICE !== 'undefined'
4810                && parseFloat(delivery.DELIVERY_DISCOUNT_PRICE) != parseFloat(delivery.PRICE)) {
4811                if (parseFloat(delivery.DELIVERY_DISCOUNT_PRICE) > parseFloat(delivery.PRICE))
4812                    priceNodesArray = [delivery.DELIVERY_DISCOUNT_PRICE_FORMATED];
4813                else
4814                    priceNodesArray = [
4815                        delivery.DELIVERY_DISCOUNT_PRICE_FORMATED,
4816                        BX.create('BR'),
4817                        BX.create('SPAN', {props: {className: 'bx-price-old'}, html: delivery.PRICE_FORMATED})
4818                    ];
4819            } else {
4820                priceNodesArray = [delivery.PRICE_FORMATED];
4821            }
4822
4823            return priceNodesArray;
4824        },
4825
4826        getDeliveryExtraServices: function (delivery) {
4827            var extraServices = [],
4828                i, currentService, serviceNode, serviceName, input;
4829
4830            for (i in delivery.EXTRA_SERVICES) {
4831                if (!delivery.EXTRA_SERVICES.hasOwnProperty(i))
4832                    continue;
4833
4834                currentService = delivery.EXTRA_SERVICES[i];
4835
4836                if (!currentService.canUserEditValue)
4837                    continue;
4838
4839                if (currentService.editControl.indexOf('this.checked') == -1) {
4840                    serviceName = BX.create('LABEL', {
4841                        html: BX.util.htmlspecialchars(currentService.name)
4842                            + (currentService.price ? ' (' + currentService.priceFormatted + ')' : '')
4843                    });
4844
4845                    serviceNode = BX.create('DIV', {
4846                        props: {className: 'tanais-form-group bx-soa-pp-field'},
4847                        html: currentService.editControl
4848                            + (currentService.description && currentService.description.length
4849                                ? '<div class="bx-soa-service-small">' + BX.util.htmlspecialchars(currentService.description) + '</div>'
4850                                : '')
4851                    });
4852
4853                    BX.prepend(serviceName, serviceNode);
4854                    input = serviceNode.querySelector('input[type=text]');
4855                    if (!input)
4856                        input = serviceNode.querySelector('select');
4857
4858                    if (input)
4859                        BX.addClass(input, 'tanais-form-control');
4860                } else {
4861                    serviceNode = BX.create('DIV', {
4862                        props: {className: 'checkbox'},
4863                        children: [
4864                            BX.create('LABEL', {
4865                                html: currentService.editControl + BX.util.htmlspecialchars(currentService.name)
4866                                    + (currentService.price ? ' (' + currentService.priceFormatted + ')' : '')
4867                                    + (currentService.description && currentService.description.length
4868                                        ? '<div class="bx-soa-service-small">' + BX.util.htmlspecialchars(currentService.description) + '</div>'
4869                                        : '')
4870                            })
4871                        ]
4872                    });
4873                }
4874
4875                extraServices.push(serviceNode);
4876            }
4877
4878            return extraServices;
4879        },
4880
4881        editFadeDeliveryBlock: function () {
4882            var deliveryContent = this.deliveryBlockNode.querySelector('.bx-soa-section-content'), newContent;
4883
4884            if (!this.initialized.delivery) {
4885                this.editActiveDeliveryBlock(false);
4886                BX.remove(BX.lastChild(this.deliveryBlockNode));
4887            }
4888
4889            newContent = this.getNewContainer(true);
4890            this.deliveryBlockNode.appendChild(newContent);
4891
4892            this.editFadeDeliveryContent(newContent);
4893
4894            if (this.params.SHOW_COUPONS_DELIVERY == 'Y')
4895                this.editCouponsFade(newContent);
4896        },
4897
4898        createDeliveryItem: function (item) {
4899            var checked = item.CHECKED == 'Y',
4900                deliveryId = parseInt(item.ID),
4901                labelNodes = [
4902                    BX.create('INPUT', {
4903                        props: {
4904                            id: 'ID_DELIVERY_ID_' + deliveryId,
4905                            name: 'DELIVERY_ID',
4906                            type: 'checkbox',
4907                            className: 'bx-soa-pp-company-checkbox',
4908                            value: deliveryId,
4909                            checked: checked
4910                        }
4911                    }),
4912                    BX.create('SPAN', {
4913                        props: {
4914                            className: 'style-checkbox'
4915                        }
4916                    })
4917                ],
4918                deliveryCached = this.deliveryCachedInfo[deliveryId],
4919                logotype, label, title, itemNode, logoNode;
4920
4921            if (this.params.SHOW_DELIVERY_LIST_NAMES == 'Y') {
4922                labelNodes.push(
4923                    BX.create('DIV', {
4924                        props: {className: 'bx-soa-pp-company-smalltitle'},
4925                        children: [
4926                            BX.create("SPAN", {
4927                                text: this.params.SHOW_DELIVERY_PARENT_NAMES != 'N' ? item.NAME : item.OWN_NAME
4928                            })
4929                        ]
4930                    })
4931                );
4932            }
4933
4934            var hasDeliveryCost = false;
4935
4936            if (item.PRICE >= 0 || typeof item.DELIVERY_DISCOUNT_PRICE !== 'undefined') {
4937                var actualPrice = typeof item.DELIVERY_DISCOUNT_PRICE !== 'undefined' ?
4938                    (item.DELIVERY_DISCOUNT_PRICE > 0 ? item.DELIVERY_DISCOUNT_PRICE_FORMATED : this.params.MESS_PRICE_FREE) :
4939                    (item.PRICE > 0 ? item.PRICE_FORMATED : this.params.MESS_PRICE_FREE);
4940
4941                labelNodes.push(
4942                    BX.create('DIV', {
4943                        props: {className: 'bx-soa-pp-delivery-cost'},
4944                        html: actualPrice
4945                    })
4946                );
4947
4948                hasDeliveryCost = true;
4949            } else if (deliveryCached && (deliveryCached.PRICE >= 0 || typeof deliveryCached.DELIVERY_DISCOUNT_PRICE !== 'undefined')) {
4950                var actualPrice = typeof deliveryCached.DELIVERY_DISCOUNT_PRICE !== 'undefined' ?
4951                    (deliveryCached.DELIVERY_DISCOUNT_PRICE > 0 ? deliveryCached.DELIVERY_DISCOUNT_PRICE_FORMATED : this.params.MESS_PRICE_FREE) :
4952                    (deliveryCached.PRICE > 0 ? deliveryCached.PRICE_FORMATED : this.params.MESS_PRICE_FREE);
4953
4954                labelNodes.push(
4955                    BX.create('DIV', {
4956                        props: {className: 'bx-soa-pp-delivery-cost'},
4957                        html: actualPrice
4958                    })
4959                );
4960
4961                hasDeliveryCost = true;
4962            }
4963
4964            label = BX.create('DIV', {
4965                props: {
4966                    className: 'bx-soa-pp-company-graf-container' + (hasDeliveryCost ? ' has-delivery-cost' : '')
4967                        + (item.CALCULATE_ERRORS || deliveryCached && deliveryCached.CALCULATE_ERRORS ? ' bx-bd-waring' : '')
4968                },
4969                children: labelNodes
4970            });
4971
4972            itemNode = BX.create('DIV', {
4973                props: {
4974                    id: 'bx_soa_item_delivery_id_' + deliveryId,
4975                    className: 'bx-soa-pp-company'
4976                },
4977                children: [
4978                    BX.create('DIV', {
4979                        props: {
4980                            className: 'bx-soa-pp-company-inner-block'
4981                        },
4982                        children: [
4983                            label,
4984                            BX.create('DIV', {
4985                                props: {className: 'bx-soa-pp-company-smalldescr' + (checked ? ' bx-soa-pp-company-desc' : '')},
4986                                html: item.DESCRIPTION
4987                            })
4988                        ],
4989                        events: {click: BX.proxy(this.selectDelivery, this)}
4990                    })
4991                ]
4992            });
4993
4994            checked && BX.addClass(itemNode, 'bx-selected');
4995
4996            if (checked && this.result.LAST_ORDER_DATA.PICK_UP)
4997                this.lastSelectedDelivery = deliveryId;
4998
4999            return itemNode;
5000        },
5001
5002        editFadeDeliveryContent: function (node) {
5003            var selectedDelivery = this.getSelectedDelivery(),
5004                name = this.params.SHOW_DELIVERY_PARENT_NAMES != 'N' ? selectedDelivery.NAME : selectedDelivery.OWN_NAME,
5005                errorNode = this.deliveryHiddenBlockNode.querySelector('div.alert.alert-danger'),
5006                warningNode = this.deliveryHiddenBlockNode.querySelector('div.alert.alert-warning.alert-show'),
5007                extraService, logotype, imgSrc, arNodes, i;
5008
5009            if (errorNode && errorNode.innerHTML)
5010                node.appendChild(errorNode.cloneNode(true));
5011            else
5012                this.getErrorContainer(node);
5013
5014            if (warningNode && warningNode.innerHTML)
5015                node.appendChild(warningNode.cloneNode(true));
5016
5017            if (selectedDelivery && selectedDelivery.NAME) {
5018                logotype = this.getImageSources(selectedDelivery, 'LOGOTIP');
5019                imgSrc = logotype && logotype.src_1x || this.defaultDeliveryLogo;
5020                arNodes = [
5021                    BX.create('IMG', {props: {src: imgSrc, alt: ''}, style: {height: '18px'}}),
5022                    BX.create('STRONG', {text: name})
5023                ];
5024
5025                if (this.params.DELIVERY_FADE_EXTRA_SERVICES == 'Y' && BX.util.object_keys(selectedDelivery.EXTRA_SERVICES).length) {
5026                    arNodes.push(BX.create('BR'));
5027
5028                    for (i in selectedDelivery.EXTRA_SERVICES) {
5029                        if (selectedDelivery.EXTRA_SERVICES.hasOwnProperty(i)) {
5030                            extraService = selectedDelivery.EXTRA_SERVICES[i];
5031                            if (extraService.value && extraService.value != 'N' && extraService.canUserEditValue) {
5032                                arNodes.push(BX.create('BR'));
5033                                arNodes.push(BX.create('STRONG', {text: extraService.name + ': '}));
5034                                arNodes.push(extraService.viewControl);
5035                            }
5036                        }
5037                    }
5038                }
5039
5040                node.appendChild(
5041                    BX.create('DIV', {
5042                        props: {className: 'bx-soa-pp-company-selected'},
5043                        children: arNodes
5044                    })
5045                );
5046                node.appendChild(
5047                    BX.create('DIV', {
5048                        props: {className: 'bx-soa-pp-price'},
5049                        children: this.getDeliveryPriceNodes(selectedDelivery)
5050                    })
5051                );
5052            } else
5053                node.appendChild(BX.create('STRONG', {text: BX.message('SOA_DELIVERY_SELECT_ERROR')}));
5054
5055            node.appendChild(BX.create('DIV', {style: {clear: 'both'}}));
5056            BX.bind(node.querySelector('.alert.alert-danger'), 'click', BX.proxy(this.showByClick, this));
5057            BX.bind(node.querySelector('.alert.alert-warning'), 'click', BX.proxy(this.showByClick, this));
5058        },
5059
5060        selectDelivery: function (event) {
5061            if (!this.orderBlockNode)
5062                return;
5063
5064            var target = event.target || event.srcElement,
5065                actionSection = BX.hasClass(target, 'bx-soa-pp-company') ? target : BX.findParent(target, {className: 'bx-soa-pp-company'}),
5066                selectedSection = this.deliveryBlockNode.querySelector('.bx-soa-pp-company.bx-selected'),
5067                actionInput, selectedInput;
5068
5069            if (BX.hasClass(actionSection, 'bx-selected')) {
5070                if (target.nodeName == "A") {
5071                    return;
5072                }
5073                return BX.PreventDefault(event);
5074            }
5075
5076            if (actionSection) {
5077                actionInput = actionSection.querySelector('input[type=checkbox]');
5078                BX.addClass(actionSection, 'bx-selected');
5079                actionInput.checked = true;
5080            }
5081            if (selectedSection) {
5082                selectedInput = selectedSection.querySelector('input[type=checkbox]');
5083                BX.removeClass(selectedSection, 'bx-selected');
5084                selectedInput.checked = false;
5085            }
5086
5087            this.sendRequest();
5088        },
5089
5090        getSelectedDelivery: function () {
5091            var deliveryCheckbox = this.deliveryBlockNode.querySelector('input[type=checkbox][name=DELIVERY_ID]:checked'),
5092                currentDelivery = false,
5093                deliveryId, i;
5094
5095            if (!deliveryCheckbox)
5096                deliveryCheckbox = this.deliveryHiddenBlockNode.querySelector('input[type=checkbox][name=DELIVERY_ID]:checked');
5097
5098            if (!deliveryCheckbox)
5099                deliveryCheckbox = this.deliveryHiddenBlockNode.querySelector('input[type=hidden][name=DELIVERY_ID]');
5100
5101            if (deliveryCheckbox) {
5102                deliveryId = deliveryCheckbox.value;
5103
5104                for (i in this.result.DELIVERY) {
5105                    if (this.result.DELIVERY[i].ID == deliveryId) {
5106                        currentDelivery = this.result.DELIVERY[i];
5107                        break;
5108                    }
5109                }
5110            }
5111
5112            return currentDelivery;
5113        },
5114
5115        activatePickUp: function (deliveryName) {
5116            if (!this.pickUpBlockNode || !this.pickUpHiddenBlockNode)
5117                return;
5118
5119            this.pickUpBlockNode.style.display = '';
5120            this.pickUpBlockNode.querySelector('h2.bx-soa-section-title .bx-soa-section-title-text').innerHTML =
5121                '<span class="bx-soa-section-title-count"></span>' + BX.util.htmlspecialchars(deliveryName);
5122
5123            if (BX.hasClass(this.pickUpBlockNode, 'bx-active'))
5124                return;
5125
5126            BX.addClass(this.pickUpBlockNode, 'bx-active');
5127            this.pickUpBlockNode.style.display = '';
5128        },
5129
5130        deactivatePickUp: function () {
5131            if (!this.pickUpBlockNode || !this.pickUpHiddenBlockNode)
5132                return;
5133
5134            if (!BX.hasClass(this.pickUpBlockNode, 'bx-active'))
5135                return;
5136
5137            BX.removeClass(this.pickUpBlockNode, 'bx-active');
5138            this.pickUpBlockNode.style.display = 'none';
5139        },
5140
5141        editPickUpBlock: function (active) {
5142            if (!this.pickUpBlockNode || !this.pickUpHiddenBlockNode || !BX.hasClass(this.pickUpBlockNode, 'bx-active') || !this.result.DELIVERY)
5143                return;
5144
5145            this.initialized.pickup = false;
5146
5147            if (active)
5148                this.editActivePickUpBlock(true);
5149            else
5150                this.editFadePickUpBlock();
5151
5152            this.initialized.pickup = true;
5153        },
5154
5155        editActivePickUpBlock: function (activeNodeMode) {
5156            var node = activeNodeMode ? this.pickUpBlockNode : this.pickUpHiddenBlockNode,
5157                pickUpContent, pickUpContentCol;
5158
5159            if (this.initialized.pickup) {
5160                if (
5161                    this.params.SHOW_NEAREST_PICKUP === 'Y'
5162                    && this.maps
5163                    && !this.maps.maxWaitTimeExpired
5164                ) {
5165                    this.maps.maxWaitTimeExpired = true;
5166                    this.initPickUpPagination();
5167                    this.editPickUpList(true);
5168                    this.pickUpFinalAction();
5169                }
5170
5171                if (this.maps && !this.pickUpMapFocused) {
5172                    this.pickUpMapFocused = true;
5173                    setTimeout(BX.proxy(this.maps.pickUpMapFocusWaiter, this.maps), 200);
5174                }
5175            } else {
5176                pickUpContent = node.querySelector('.bx-soa-section-content');
5177                if (!pickUpContent) {
5178                    pickUpContent = this.getNewContainer();
5179                    node.appendChild(pickUpContent);
5180                }
5181                BX.cleanNode(pickUpContent);
5182
5183                pickUpContentCol = BX.create('DIV', {});
5184                this.editPickUpMap(pickUpContentCol);
5185                this.editPickUpLoader(pickUpContentCol);
5186
5187                pickUpContent.appendChild(
5188                    BX.create('DIV', {
5189                        props: {className: 'bx_soa_pickup'},
5190                        children: [pickUpContentCol]
5191                    })
5192                );
5193
5194                if (this.params.SHOW_PICKUP_MAP != 'Y' || this.params.SHOW_NEAREST_PICKUP != 'Y') {
5195                    this.initPickUpPagination();
5196                    this.editPickUpList(true);
5197                    this.pickUpFinalAction();
5198                }
5199
5200                this.getBlockFooter(pickUpContent);
5201            }
5202        },
5203
5204        editFadePickUpBlock: function () {
5205            var pickUpContent = this.pickUpBlockNode.querySelector('.bx-soa-section-content'), newContent;
5206
5207            if (this.initialized.pickup) {
5208                this.pickUpHiddenBlockNode.appendChild(pickUpContent);
5209            } else {
5210                this.editActivePickUpBlock(false);
5211                BX.remove(BX.lastChild(this.pickUpBlockNode));
5212            }
5213
5214            newContent = this.getNewContainer();
5215            this.pickUpBlockNode.appendChild(newContent);
5216
5217            this.editFadePickUpContent(newContent);
5218        },
5219
5220        editFadePickUpContent: function (pickUpContainer) {
5221        },
5222
5223        getPickUpInfoArray: function (storeIds) {
5224            if (!storeIds || storeIds.length <= 0)
5225                return [];
5226
5227            var arr = [], i;
5228
5229            for (i = 0; i < storeIds.length; i++)
5230                if (this.result.STORE_LIST[storeIds[i]])
5231                    arr.push(this.result.STORE_LIST[storeIds[i]]);
5232
5233            return arr;
5234        },
5235
5236        getSelectedPickUp: function () {
5237            var pickUpInput = BX('BUYER_STORE'),
5238                currentPickUp, pickUpId,
5239                allStoresList = this.result.STORE_LIST,
5240                stores, i;
5241
5242            if (pickUpInput) {
5243                pickUpId = pickUpInput.value;
5244                currentPickUp = allStoresList[pickUpId];
5245
5246                if (!currentPickUp) {
5247                    stores = this.getSelectedDelivery().STORE;
5248                    if (stores) {
5249                        for (i in stores) {
5250                            if (stores.hasOwnProperty(i)) {
5251                                currentPickUp = allStoresList[stores[i]];
5252                                pickUpInput.setAttribute('value', stores[i]);
5253                                break;
5254                            }
5255                        }
5256                    }
5257                }
5258            }
5259
5260            return currentPickUp;
5261        },
5262
5263        /**
5264         * Checking delivery for pick ups. Displaying/hiding pick up block node.
5265         */
5266        checkPickUpShow: function () {
5267            var currentDelivery = this.getSelectedDelivery(), name, stores;
5268
5269            if (currentDelivery && currentDelivery.STORE && currentDelivery.STORE.length)
5270                stores = this.getPickUpInfoArray(currentDelivery.STORE);
5271
5272            if (stores && stores.length) {
5273                name = this.params.SHOW_DELIVERY_PARENT_NAMES != 'N' ? currentDelivery.NAME : currentDelivery.OWN_NAME;
5274                currentDelivery.STORE_MAIN = currentDelivery.STORE;
5275                this.activatePickUp(name);
5276                this.editSection(this.pickUpBlockNode);
5277            } else {
5278                this.deactivatePickUp();
5279            }
5280        },
5281
5282        geoLocationSuccessCallback: function (result) {
5283            var activeStores,
5284                currentDelivery = this.getSelectedDelivery();
5285
5286            if (currentDelivery && currentDelivery.STORE) {
5287                activeStores = this.getPickUpInfoArray(currentDelivery.STORE);
5288            }
5289
5290            if (activeStores && activeStores.length >= this.options.pickUpMap.minToShowNearestBlock) {
5291                this.editPickUpRecommendList(result.geoObjects.get(0));
5292            }
5293
5294            this.initPickUpPagination();
5295            this.editPickUpList(true);
5296            this.pickUpFinalAction();
5297        },
5298
5299        geoLocationFailCallback: function () {
5300            this.initPickUpPagination();
5301            this.editPickUpList(true);
5302            this.pickUpFinalAction();
5303        },
5304
5305        initMaps: function () {
5306            this.maps = BX.Sale.OrderAjaxComponent.Maps.init(this);
5307            if (this.maps) {
5308                this.mapsReady = true;
5309                this.resizeMapContainers();
5310
5311                if (this.params.SHOW_PICKUP_MAP === 'Y' && BX('pickUpMap')) {
5312                    var currentDelivery = this.getSelectedDelivery();
5313                    if (currentDelivery && currentDelivery.STORE && currentDelivery.STORE.length) {
5314                        var activeStores = this.getPickUpInfoArray(currentDelivery.STORE);
5315                    }
5316
5317                    if (activeStores && activeStores.length) {
5318                        var selected = this.getSelectedPickUp();
5319                        this.maps.initializePickUpMap(selected);
5320
5321                        if (this.params.SHOW_NEAREST_PICKUP === 'Y') {
5322                            this.maps.showNearestPickups(BX.proxy(this.geoLocationSuccessCallback, this), BX.proxy(this.geoLocationFailCallback, this));
5323                        }
5324
5325                        this.maps.buildBalloons(activeStores);
5326                    }
5327                }
5328
5329                if (this.params.SHOW_MAP_IN_PROPS === 'Y' && BX('propsMap')) {
5330                    var propsMapData = this.getPropertyMapData();
5331                    this.maps.initializePropsMap(propsMapData);
5332                }
5333            }
5334        },
5335
5336        getPropertyMapData: function () {
5337            var currentProperty, locationId, k;
5338            var data = this.options.propertyMap.defaultMapPosition;
5339
5340            for (k in this.result.ORDER_PROP.properties) {
5341                if (this.result.ORDER_PROP.properties.hasOwnProperty(k)) {
5342                    currentProperty = this.result.ORDER_PROP.properties[k];
5343                    if (currentProperty.IS_LOCATION == 'Y') {
5344                        locationId = currentProperty.ID;
5345                        break;
5346                    }
5347                }
5348            }
5349
5350            if (this.locations[locationId] && this.locations[locationId][0] && this.locations[locationId][0].coordinates) {
5351                currentProperty = this.locations[locationId][0].coordinates;
5352
5353                var long = parseFloat(currentProperty.LONGITUDE),
5354                    lat = parseFloat(currentProperty.LATITUDE);
5355
5356                if (!isNaN(long) && !isNaN(lat) && long != 0 && lat != 0) {
5357                    data.lon = long;
5358                    data.lat = lat;
5359                }
5360            }
5361
5362            return data;
5363        },
5364
5365        resizeMapContainers: function () {
5366            var pickUpMapContainer = BX('pickUpMap'),
5367                propertyMapContainer = BX('propsMap'),
5368                resizeBy = this.propsBlockNode,
5369                width, height;
5370
5371            if (resizeBy && (pickUpMapContainer || propertyMapContainer)) {
5372                width = resizeBy.clientWidth;
5373                height = parseInt(width / 16 * 9);
5374
5375                if (this.params.SHOW_PICKUP_MAP === 'Y' && pickUpMapContainer) {
5376                    pickUpMapContainer.style.height = height + 'px';
5377                }
5378
5379                if (this.params.SHOW_MAP_IN_PROPS === 'Y' && propertyMapContainer) {
5380                    propertyMapContainer.style.height = height + 'px';
5381                }
5382            }
5383        },
5384
5385        editPickUpMap: function (pickUpContent) {
5386            pickUpContent.appendChild(BX.create('DIV', {
5387                props: {id: 'pickUpMap'},
5388                style: {width: '100%', marginBottom: '10px'}
5389            }));
5390        },
5391
5392        editPickUpLoader: function (pickUpContent) {
5393            pickUpContent.appendChild(
5394                BX.create('DIV', {
5395                    props: {id: 'pickUpLoader', className: 'text-center'},
5396                    children: [BX.create('IMG', {props: {src: this.imgFolder + '/loader.gif'}})]
5397                })
5398            );
5399        },
5400
5401        editPickUpList: function (isNew) {
5402            if (!this.pickUpPagination.currentPage || !this.pickUpPagination.currentPage.length)
5403                return;
5404
5405            BX.remove(BX('pickUpLoader'));
5406
5407            var pickUpList = BX.create('DIV', {props: {className: 'bx-soa-pickup-list main'}}),
5408                buyerStoreInput = BX('BUYER_STORE'),
5409                selectedStore,
5410                container, i, found = false,
5411                recommendList, selectedDelivery, currentStore, storeNode;
5412
5413            if (buyerStoreInput)
5414                selectedStore = buyerStoreInput.value;
5415
5416            recommendList = this.pickUpBlockNode.querySelector('.bx-soa-pickup-list.recommend');
5417            if (!recommendList)
5418                recommendList = this.pickUpHiddenBlockNode.querySelector('.bx-soa-pickup-list.recommend');
5419
5420            if (!recommendList || !recommendList.querySelector('.bx-soa-pickup-list-item.bx-selected')) {
5421                selectedDelivery = this.getSelectedDelivery();
5422                if (selectedDelivery && selectedDelivery.STORE) {
5423                    for (i = 0; i < selectedDelivery.STORE.length; i++)
5424                        if (selectedDelivery.STORE[i] == selectedStore)
5425                            found = true;
5426                }
5427            } else
5428                found = true;
5429
5430            for (i = 0; i < this.pickUpPagination.currentPage.length; i++) {
5431                currentStore = this.pickUpPagination.currentPage[i];
5432
5433                if (currentStore.ID == selectedStore || parseInt(selectedStore) == 0 || !found) {
5434                    selectedStore = buyerStoreInput.value = currentStore.ID;
5435                    found = true;
5436                }
5437
5438                storeNode = this.createPickUpItem(currentStore, {selected: currentStore.ID == selectedStore});
5439                pickUpList.appendChild(storeNode);
5440            }
5441
5442            if (!!isNew) {
5443                container = this.pickUpHiddenBlockNode.querySelector('.bx_soa_pickup>div');
5444                if (!container)
5445                    container = this.pickUpBlockNode.querySelector('.bx_soa_pickup>div');
5446
5447                container.appendChild(
5448                    BX.create('DIV', {
5449                        props: {className: 'bx-soa-pickup-subTitle'},
5450                        html: this.params.MESS_PICKUP_LIST
5451                    })
5452                );
5453                container.appendChild(pickUpList);
5454            } else {
5455                container = this.pickUpBlockNode.querySelector('.bx-soa-pickup-list.main');
5456                BX.insertAfter(pickUpList, container);
5457                BX.remove(container);
5458            }
5459
5460            this.pickUpPagination.show && this.showPagination('pickUp', pickUpList);
5461        },
5462
5463        pickUpFinalAction: function () {
5464            var selectedDelivery = this.getSelectedDelivery(),
5465                deliveryChanged;
5466
5467            if (selectedDelivery) {
5468                deliveryChanged = this.lastSelectedDelivery !== parseInt(selectedDelivery.ID);
5469                this.lastSelectedDelivery = parseInt(selectedDelivery.ID);
5470            }
5471
5472            if (deliveryChanged && this.pickUpBlockNode.id !== this.activeSectionId) {
5473                if (this.pickUpBlockNode.id !== this.activeSectionId) {
5474                    this.editFadePickUpContent(BX.lastChild(this.pickUpBlockNode));
5475                }
5476
5477                BX.removeClass(this.pickUpBlockNode, 'bx-step-completed');
5478            }
5479
5480            this.maps && this.maps.pickUpFinalAction();
5481        },
5482
5483        getStoreInfoHtml: function (currentStore) {
5484            var html = '';
5485
5486            if (currentStore.ADDRESS)
5487                html += BX.message('SOA_PICKUP_ADDRESS') + ': ' + BX.util.htmlspecialchars(currentStore.ADDRESS) + '<br>';
5488
5489            if (currentStore.PHONE)
5490                html += BX.message('SOA_PICKUP_PHONE') + ': ' + BX.util.htmlspecialchars(currentStore.PHONE) + '<br>';
5491
5492            if (currentStore.SCHEDULE)
5493                html += BX.message('SOA_PICKUP_WORK') + ': ' + BX.util.htmlspecialchars(currentStore.SCHEDULE) + '<br>';
5494
5495            if (currentStore.DESCRIPTION)
5496                html += BX.message('SOA_PICKUP_DESC') + ': ' + BX.util.htmlspecialchars(currentStore.DESCRIPTION) + '<br>';
5497
5498            return html;
5499        },
5500
5501        createPickUpItem: function (currentStore, options) {
5502            options = options || {};
5503
5504            var imgClassName = 'bx-soa-pickup-l-item-detail',
5505                buttonClassName = 'bx-soa-pickup-l-item-btn',
5506                logoNode, logotype, html, storeNode, imgSrc;
5507
5508            if (this.params.SHOW_STORES_IMAGES === 'Y') {
5509                logotype = this.getImageSources(currentStore, 'IMAGE_ID');
5510                imgSrc = logotype && logotype.src_1x || this.defaultStoreLogo;
5511                logoNode = BX.create('IMG', {
5512                    props: {
5513                        src: imgSrc,
5514                        className: 'bx-soa-pickup-l-item-img'
5515                    },
5516                    events: {
5517                        click: BX.delegate(function (e) {
5518                            this.popupShow(e, logotype && logotype.src_orig || imgSrc);
5519                        }, this)
5520                    }
5521                });
5522            } else {
5523                imgClassName += ' no-image';
5524                buttonClassName += ' no-image';
5525            }
5526
5527            html = this.getStoreInfoHtml(currentStore);
5528            storeNode = BX.create('DIV', {
5529                props: {className: 'bx-soa-pickup-list-item', id: 'store-' + currentStore.ID},
5530                children: [
5531                    BX.create('DIV', {
5532                        props: {className: 'bx-soa-pickup-l-item-adress'},
5533                        children: options.distance ? [
5534                            BX.util.htmlspecialchars(currentStore.ADDRESS),
5535                            ' ( ~' + options.distance + ' ' + BX.message('SOA_DISTANCE_KM') + ' ) '
5536                        ] : [BX.util.htmlspecialchars(currentStore.ADDRESS)]
5537                    }),
5538                    BX.create('DIV', {
5539                        props: {className: imgClassName},
5540                        children: [
5541                            logoNode,
5542                            BX.create('DIV', {
5543                                props: {className: 'bx-soa-pickup-l-item-name'},
5544                                text: currentStore.TITLE
5545                            }),
5546                            BX.create('DIV', {props: {className: 'bx-soa-pickup-l-item-desc'}, html: html})
5547                        ]
5548                    }),
5549                    BX.create('DIV', {
5550                        props: {className: buttonClassName},
5551                        children: [
5552                            BX.create('A', {
5553                                props: {href: 'javascript:void(0);', className: 'btn btn-default'},
5554                                html: this.params.MESS_SELECT_PICKUP,
5555                                events: {
5556                                    click: BX.delegate(function (event) {
5557                                        this.selectStore(event);
5558                                        this.clickNextAction(event)
5559                                    }, this)
5560                                }
5561                            })
5562                        ]
5563                    })
5564                ],
5565                events: {
5566                    click: BX.proxy(this.selectStore, this)
5567                }
5568            });
5569
5570            if (options.selected)
5571                BX.addClass(storeNode, 'bx-selected');
5572
5573            return storeNode;
5574        },
5575
5576        editPickUpRecommendList: function (geoLocation) {
5577            if (!this.maps || !this.maps.canUseRecommendList() || !geoLocation) {
5578                return;
5579            }
5580
5581            BX.remove(BX('pickUpLoader'));
5582
5583            var recommendList = BX.create('DIV', {props: {className: 'bx-soa-pickup-list recommend'}}),
5584                buyerStoreInput = BX('BUYER_STORE'),
5585                selectedDelivery = this.getSelectedDelivery();
5586
5587            var i, currentStore, currentStoreId, distance, storeNode, container;
5588
5589            var recommendedStoreIds = this.maps.getRecommendedStoreIds(geoLocation);
5590            for (i = 0; i < recommendedStoreIds.length; i++) {
5591                currentStoreId = recommendedStoreIds[i];
5592                currentStore = this.getPickUpInfoArray([currentStoreId])[0];
5593
5594                if (i === 0 && parseInt(selectedDelivery.ID) !== this.lastSelectedDelivery) {
5595                    buyerStoreInput.value = parseInt(currentStoreId);
5596                }
5597
5598                distance = this.maps.getDistance(geoLocation, currentStoreId);
5599                storeNode = this.createPickUpItem(currentStore, {
5600                    selected: buyerStoreInput.value === currentStoreId,
5601                    distance: distance
5602                });
5603                recommendList.appendChild(storeNode);
5604
5605                if (selectedDelivery.STORE_MAIN) {
5606                    selectedDelivery.STORE_MAIN.splice(selectedDelivery.STORE_MAIN.indexOf(currentStoreId), 1);
5607                }
5608            }
5609
5610            container = this.pickUpHiddenBlockNode.querySelector('.bx_soa_pickup>div');
5611            if (!container) {
5612                container = this.pickUpBlockNode.querySelector('.bx_soa_pickup>div');
5613            }
5614
5615            container.appendChild(
5616                BX.create('DIV', {
5617                    props: {className: 'bx-soa-pickup-subTitle'},
5618                    html: this.params.MESS_NEAREST_PICKUP_LIST
5619                })
5620            );
5621            container.appendChild(recommendList);
5622        },
5623
5624        selectStore: function (event) {
5625            var storeItem,
5626                storeInput = BX('BUYER_STORE'),
5627                selectedPickUp, storeItemId, i, k, page,
5628                target, h1, h2;
5629
5630            if (BX.type.isString(event)) {
5631                storeItem = BX('store-' + event);
5632                if (!storeItem) {
5633                    for (i = 0; i < this.pickUpPagination.pages.length; i++) {
5634                        page = this.pickUpPagination.pages[i];
5635                        for (k = 0; k < page.length; k++) {
5636                            if (page[k].ID == event) {
5637                                this.showPickUpItemsPage(++i);
5638                                break;
5639                            }
5640                        }
5641                    }
5642                    storeItem = BX('store-' + event);
5643                }
5644            } else {
5645                target = event.target || event.srcElement;
5646                storeItem = BX.hasClass(target, 'bx-soa-pickup-list-item')
5647                    ? target
5648                    : BX.findParent(target, {className: 'bx-soa-pickup-list-item'});
5649            }
5650
5651            if (storeItem && storeInput) {
5652                if (BX.hasClass(storeItem, 'bx-selected'))
5653                    return;
5654
5655                selectedPickUp = this.pickUpBlockNode.querySelector('.bx-selected');
5656                storeItemId = storeItem.id.substr('store-'.length);
5657
5658                BX.removeClass(selectedPickUp, 'bx-selected');
5659
5660                h1 = storeItem.clientHeight;
5661                storeItem.style.overflow = 'hidden';
5662                BX.addClass(storeItem, 'bx-selected');
5663                h2 = storeItem.clientHeight;
5664                storeItem.style.height = h1 + 'px';
5665
5666                new BX.easing({
5667                    duration: 300,
5668                    start: {height: h1, opacity: 0},
5669                    finish: {height: h2, opacity: 100},
5670                    transition: BX.easing.transitions.quad,
5671                    step: function (state) {
5672                        storeItem.style.height = state.height + "px";
5673                    },
5674                    complete: function () {
5675                        storeItem.removeAttribute('style');
5676                    }
5677                }).animate();
5678
5679                storeInput.setAttribute('value', storeItemId);
5680                this.maps && this.maps.selectBalloon(storeItemId);
5681            }
5682        },
5683
5684        getDeliverySortedArray: function (objDelivery) {
5685            var deliveries = [],
5686                delivery_sort = this.params.ORDER_DELIVERY_SORT,
5687                problemDeliveries = [],
5688                sortFunc = function (a, b) {
5689                    var sort = parseInt(a.SORT) - parseInt(b.SORT);
5690                    if (sort === 0) {
5691                        return a.OWN_NAME.toLowerCase() > b.OWN_NAME.toLowerCase()
5692                            ? 1
5693                            : (a.OWN_NAME.toLowerCase() < b.OWN_NAME.toLowerCase() ? -1 : 0);
5694                    } else {
5695                        return sort;
5696                    }
5697                },
5698                sortFuncByPrice = function (a, b) {
5699                    var sort;
5700                    if (delivery_sort == "PRICE_DESC")
5701                        sort = parseInt(b.PRICE) - parseInt(a.PRICE);
5702                    else
5703                        sort = parseInt(a.PRICE) - parseInt(b.PRICE);
5704                    if (sort === 0) {
5705                        return a.OWN_NAME.toLowerCase() > b.OWN_NAME.toLowerCase()
5706                            ? 1
5707                            : (a.OWN_NAME.toLowerCase() < b.OWN_NAME.toLowerCase() ? -1 : 0);
5708                    } else {
5709                        return sort;
5710                    }
5711                },
5712                k;
5713
5714            for (k in objDelivery) {
5715                if (objDelivery.hasOwnProperty(k)) {
5716                    if (this.params.SHOW_NOT_CALCULATED_DELIVERIES === 'L' && objDelivery[k].CALCULATE_ERRORS) {
5717                        problemDeliveries.push(objDelivery[k]);
5718                    } else {
5719                        deliveries.push(objDelivery[k]);
5720                    }
5721                }
5722            }
5723
5724            deliveries.sort(
5725                this.params.DELIVERY_NO_AJAX == "Y" ?
5726                    (delivery_sort !== "SORT" ? sortFuncByPrice : sortFunc) : sortFunc
5727            );
5728            problemDeliveries.sort(sortFunc);
5729
5730            return deliveries.concat(problemDeliveries);
5731        },
5732
5733        editPropsBlock: function (active) {
5734            if (!this.propsBlockNode || !this.propsHiddenBlockNode || !this.result.ORDER_PROP)
5735                return;
5736
5737            if (active)
5738                this.editActivePropsBlock(true);
5739            else
5740                this.editFadePropsBlock();
5741
5742            this.initialized.props = true;
5743        },
5744
5745        editActivePropsBlock: function (activeNodeMode) {
5746            var node = activeNodeMode ? this.propsBlockNode : this.propsHiddenBlockNode,
5747                propsContent, propsNode, selectedDelivery, showPropM
5747ap = false, i, validationErrors;
5748
5749            if (this.initialized.props) {
5750                this.maps && setTimeout(BX.proxy(this.maps.propsMapFocusWaiter, this.maps), 200);
5751            } else {
5752                propsContent = node.querySelector('.bx-soa-section-content');
5753                if (!propsContent) {
5754                    propsContent = this.getNewContainer();
5755                    node.appendChild(propsContent);
5756                } else
5757                    BX.cleanNode(propsContent);
5758
5759                this.getErrorContainer(propsContent);
5760
5761                propsNode = BX.create('DIV', {});
5762                selectedDelivery = this.getSelectedDelivery();
5763
5764                if (
5765                    selectedDelivery && this.params.SHOW_MAP_IN_PROPS === 'Y'
5766                    && this.params.SHOW_MAP_FOR_DELIVERIES && this.params.SHOW_MAP_FOR_DELIVERIES.length
5767                ) {
5768                    for (i = 0; i < this.params.SHOW_MAP_FOR_DELIVERIES.length; i++) {
5769                        if (parseInt(selectedDelivery.ID) === parseInt(this.params.SHOW_MAP_FOR_DELIVERIES[i])) {
5770                            showPropMap = true;
5771                            break;
5772                        }
5773                    }
5774                }
5775
5776                this.editPropsItems(propsNode);
5777                showPropMap && this.editPropsMap(propsNode);
5778
5779                if (this.params.HIDE_ORDER_DESCRIPTION !== 'Y') {
5780                    this.editPropsComment(propsNode);
5781                }
5782
5783                propsContent.appendChild(propsNode);
5784                this.getBlockFooter(propsContent);
5785            }
5786        },
5787
5788        editFadePropsBlock: function () {
5789            var propsContent = this.propsBlockNode.querySelector('.bx-soa-section-content'), newContent;
5790
5791            if (this.initialized.props) {
5792                this.propsHiddenBlockNode.appendChild(propsContent);
5793            } else {
5794                this.editActivePropsBlock(false);
5795                BX.remove(BX.lastChild(this.propsBlockNode));
5796            }
5797
5798            newContent = this.getNewContainer();
5799            this.propsBlockNode.appendChild(newContent);
5800
5801            this.editFadePropsContent(newContent);
5802        },
5803
5804        editFadePropsContent: function (node) {
5805            if (!node || !this.locationsInitialized)
5806                return;
5807
5808            var errorNode = this.propsHiddenBlockNode.querySelector('.alert'),
5809                personType = this.getSelectedPersonType(),
5810                fadeParamName, props,
5811                group, property, groupIterator, propsIterator, i, validPropsErrors;
5812
5813            BX.cleanNode(node);
5814
5815            if (errorNode)
5816                node.appendChild(errorNode.cloneNode(true));
5817
5818            if (personType) {
5819                fadeParamName = 'PROPS_FADE_LIST_' + personType.ID;
5820                props = this.params[fadeParamName];
5821            }
5822
5823            if (!props || props.length === 0) {
5824                node.innerHTML += '<strong>' + BX.message('SOA_ORDER_PROPS') + '</strong>';
5825            } else {
5826                groupIterator = this.fadedPropertyCollection.getGroupIterator();
5827                while (group = groupIterator()) {
5828                    propsIterator = group.getIterator();
5829                    while (property = propsIterator()) {
5830                        for (i = 0; i < props.length; i++)
5831                            if (props[i] == property.getId() && property.getSettings()['IS_ZIP'] != 'Y')
5832                                this.getPropertyRowNode(property, node, true);
5833                    }
5834                }
5835            }
5836
5837            if (this.propsBlockNode.getAttribute('data-visited') === 'true') {
5838                validPropsErrors = this.isValidPropertiesBlock();
5839                if (validPropsErrors.length)
5840                    this.showError(this.propsBlockNode, validPropsErrors);
5841            }
5842
5843            BX.bind(node.querySelector('.alert.alert-danger'), 'click', BX.proxy(this.showByClick, this));
5844            BX.bind(node.querySelector('.alert.alert-warning'), 'click', BX.proxy(this.showByClick, this));
5845        },
5846
5847        editPropsItems: function (propsNode) {
5848            if (!this.result.ORDER_PROP || !this.propertyCollection)
5849                return;
5850
5851            var propsItemsContainer = BX.create('DIV', {props: {className: 'bx-soa-customer'}}),
5852                group, property, groupIterator = this.propertyCollection.getGroupIterator(), propsIterator;
5853
5854            if (!propsItemsContainer)
5855                propsItemsContainer = this.propsBlockNode.querySelector('.bx-soa-customer');
5856
5857            while (group = groupIterator()) {
5858                propsIterator = group.getIterator();
5859                while (property = propsIterator()) {
5860                    if (
5861                        this.deliveryLocationInfo.loc == property.getId()
5862                        || this.deliveryLocationInfo.zip == property.getId()
5863                        || this.deliveryLocationInfo.city == property.getId()
5864                    )
5865                        continue;
5866
5867                    this.getPropertyRowNode(property, propsItemsContainer, false);
5868                }
5869            }
5870
5871            propsNode.appendChild(propsItemsContainer);
5872        },
5873
5874        getPropertyRowNode: function (property, propsItemsContainer, disabled) {
5875            var propsItemNode = BX.create('DIV'),
5876                textHtml = '',
5877                propertyType = property.getType() || '',
5878                propertyDesc = property.getDescription() || '',
5879                label;
5880
5881            if (disabled) {
5882                propsItemNode.innerHTML = '<strong>' + BX.util.htmlspecialchars(property.getName()) + ':</strong> ';
5883            } else {
5884                BX.addClass(propsItemNode, "tanais-form-group bx-soa-customer-field");
5885
5886                if (property.isRequired())
5887                    textHtml += '<span class="bx-authform-starrequired">*</span> ';
5888
5889                textHtml += BX.util.htmlspecialchars(property.getName());
5890                if (propertyDesc.length && propertyType != 'STRING' && propertyType != 'NUMBER' && propertyType != 'DATE')
5891                    textHtml += ' <small>(' + BX.util.htmlspecialchars(propertyDesc) + ')</small>';
5892
5893                label = BX.create('LABEL', {
5894                    attrs: {'for': 'soa-property-' + property.getId()},
5895                    props: {className: 'bx-soa-custom-label'},
5896                    html: textHtml
5897                });
5898                propsItemNode.setAttribute('data-property-id-row', property.getId());
5899                propsItemNode.appendChild(label);
5900            }
5901
5902            switch (propertyType) {
5903                case 'LOCATION':
5904                    this.insertLocationProperty(property, propsItemNode, disabled);
5905                    break;
5906                case 'DATE':
5907                    this.insertDateProperty(property, propsItemNode, disabled);
5908                    break;
5909                case 'FILE':
5910                    this.insertFileProperty(property, propsItemNode, disabled);
5911                    break;
5912                case 'STRING':
5913                    this.insertStringProperty(property, propsItemNode, disabled);
5914                    break;
5915                case 'ENUM':
5916                    this.insertEnumProperty(property, propsItemNode, disabled);
5917                    break;
5918                case 'Y/N':
5919                    this.insertYNProperty(property, propsItemNode, disabled);
5920                    break;
5921                case 'NUMBER':
5922                    this.insertNumberProperty(property, propsItemNode, disabled);
5923            }
5924
5925            propsItemsContainer.appendChild(propsItemNode);
5926        },
5927
5928        insertLocationProperty: function (property, propsItemNode, disabled) {
5929            var propRow, propNodes, locationString, currentLocation, insertedLoc, propContainer, i, k, values = [];
5930
5931            if (property.getId() in this.locations) {
5932                if (disabled) {
5933                    propRow = this.propsHiddenBlockNode.querySelector('[data-property-id-row="' + property.getId() + '"]');
5934                    if (propRow) {
5935                        propNodes = propRow.querySelectorAll('div.bx-soa-loc');
5936                        for (i = 0; i < propNodes.length; i++) {
5937                            locationString = this.getLocationString(propNodes[i]);
5938                            values.push(locationString.length ? BX.util.htmlspecialchars(locationString) : BX.message('SOA_NOT_SELECTED'));
5939                        }
5940                    }
5941                    propsItemNode.innerHTML += values.join('<br>');
5942                } else {
5943                    propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
5944                    propRow = this.locations[property.getId()];
5945                    for (i = 0; i < propRow.length; i++) {
5946                        currentLocation = propRow[i] ? propRow[i].output : {};
5947                        insertedLoc = BX.create('DIV', {props: {className: 'bx-soa-loc'}, html: currentLocation.HTML});
5948
5949                        if (property.isMultiple())
5950                            insertedLoc.style.marginBottom = this.locationsTemplate == 'search' ? '5px' : '20px';
5951
5952                        propContainer.appendChild(insertedLoc);
5953
5954                        for (k in currentLocation.SCRIPT) {
5955                            if (currentLocation.SCRIPT.hasOwnProperty(k))
5956                                BX.evalGlobal(currentLocation.SCRIPT[k].JS);
5957                        }
5958                    }
5959
5960                    if (property.isMultiple()) {
5961                        propContainer.appendChild(
5962                            BX.create('DIV', {
5963                                attrs: {'data-prop-id': property.getId()},
5964                                props: {className: 'btn btn-default'},
5965                                text: BX.message('ADD_DEFAULT'),
5966                                events: {
5967                                    click: BX.proxy(this.addLocationProperty, this)
5968                                }
5969                            })
5970                        );
5971                    }
5972
5973                    propsItemNode.appendChild(propContainer);
5974                }
5975            }
5976        },
5977
5978        addLocationProperty: function (e) {
5979            var target = e.target || e.srcElement,
5980                propId = target.getAttribute('data-prop-id'),
5981                lastProp = BX.previousSibling(target),
5982                insertedLoc, k, input, index = 0,
5983                prefix = 'sls-',
5984                randomStr = BX.util.getRandomString(5);
5985
5986            if (BX.hasClass(lastProp, 'bx-soa-loc')) {
5987                if (this.locationsTemplate == 'search') {
5988                    input = lastProp.querySelector('input[type=text][class=dropdown-field]');
5989                    if (input)
5990                        index = parseInt(input.name.substring(input.name.indexOf('[') + 1, input.name.indexOf(']'))) + 1;
5991                } else {
5992                    input = lastProp.querySelectorAll('input[type=hidden]');
5993                    if (input.length) {
5994                        input = input[input.length - 1];
5995                        index = parseInt(input.name.substring(input.name.indexOf('[') + 1, input.name.indexOf(']'))) + 1;
5996                    }
5997                }
5998            }
5999
6000            if (this.cleanLocations[propId]) {
6001                insertedLoc = BX.create('DIV', {
6002                    props: {className: 'bx-soa-loc'},
6003                    style: {marginBottom: this.locationsTemplate == 'search' ? '5px' : '20px'},
6004                    html: this.cleanLocations[propId].HTML.split('#key#').join(index).replace(/sls-\d{5}/g, prefix + randomStr)
6005                });
6006                target.parentNode.insertBefore(insertedLoc, target);
6007
6008                BX.saleOrderAjax.addPropertyDesc({
6009                    id: propId + '_' + index,
6010                    attributes: {
6011                        id: propId + '_' + index,
6012                        type: 'LOCATION',
6013                        valueSource: 'form'
6014                    }
6015                });
6016
6017
6018                for (k in this.cleanLocations[propId].SCRIPT)
6019                    if (this.cleanLocations[propId].SCRIPT.hasOwnProperty(k))
6020                        BX.evalGlobal(this.cleanLocations[propId].SCRIPT[k].JS.split('_key__').join('_' + index).replace(/sls-\d{5}/g, prefix + randomStr));
6021
6022                BX.saleOrderAjax.initDeferredControl();
6023            }
6024        },
6025
6026        insertDateProperty: function (property, propsItemNode, disabled) {
6027            var prop, dateInputs, values, i,
6028                propContainer, inputText;
6029
6030            if (disabled) {
6031                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6032                if (prop) {
6033                    values = [];
6034                    dateInputs = prop.querySelectorAll('input[type=text]');
6035
6036                    for (i = 0; i < dateInputs.length; i++)
6037                        if (dateInputs[i].value && dateInputs[i].value.length)
6038                            values.push(dateInputs[i].value);
6039
6040                    propsItemNode.innerHTML += this.valuesToString(values);
6041                }
6042            } else {
6043                propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6044                property.appendTo(propContainer);
6045                propsItemNode.appendChild(propContainer);
6046                inputText = propContainer.querySelectorAll('input[type=text]');
6047
6048                for (i = 0; i < inputText.length; i++)
6049                    this.alterDateProperty(property.getSettings(), inputText[i]);
6050
6051                this.alterProperty(property.getSettings(), propContainer);
6052                this.bindValidation(property.getId(), propContainer);
6053            }
6054        },
6055
6056        insertFileProperty: function (property, propsItemNode, disabled) {
6057            var prop, fileLinks, values, i, html,
6058                saved, propContainer;
6059
6060            if (disabled) {
6061                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6062                if (prop) {
6063                    values = [];
6064                    fileLinks = prop.querySelectorAll('a');
6065
6066                    for (i = 0; i < fileLinks.length; i++) {
6067                        html = fileLinks[i].innerHTML;
6068                        if (html.length)
6069                            values.push(html);
6070                    }
6071
6072                    propsItemNode.innerHTML += this.valuesToString(values);
6073                }
6074            } else {
6075                saved = this.savedFilesBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6076                if (saved)
6077                    propContainer = saved.querySelector('div.soa-property-container');
6078
6079                if (propContainer)
6080                    propsItemNode.appendChild(propContainer);
6081                else {
6082                    propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6083                    property.appendTo(propContainer);
6084                    propsItemNode.appendChild(propContainer);
6085                    this.alterProperty(property.getSettings(), propContainer);
6086                }
6087            }
6088        },
6089
6090        insertStringProperty: function (property, propsItemNode, disabled) {
6091            var prop, inputs, values, i, propContainer;
6092
6093            if (disabled) {
6094                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6095                if (prop) {
6096                    values = [];
6097                    inputs = prop.querySelectorAll('input[type=text]');
6098                    if (inputs.length == 0)
6099                        inputs = prop.querySelectorAll('textarea');
6100
6101                    if (inputs.length) {
6102                        for (i = 0; i < inputs.length; i++) {
6103                            if (inputs[i].value.length)
6104                                values.push(inputs[i].value);
6105                        }
6106                    }
6107
6108                    propsItemNode.innerHTML += this.valuesToString(values);
6109                }
6110            } else {
6111                propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6112                property.appendTo(propContainer);
6113
6114                var propSettings = property.getSettings();
6115
6116                if (
6117                    this.params.USE_LEGAL_ENTITY_AUTOLOAD_DATA == "Y" &&
6118                    this.params.AUTOLOAD_LEGAL_INN.length > 0 &&
6119                    this.params.AUTOLOAD_LEGAL_INN == propSettings["CODE"]
6120                ) {
6121                    BX.addClass(propContainer, "has-soa-action-button");
6122
6123                    propContainer.appendChild(
6124                        BX.create('A', {
6125                            props: {
6126                                className: 'btn btn-default js-inn-autoload-btn' // Класс кнопки
6127                            },
6128                            html: this.params.MESS_AUTOLOAD_LEGAL_INN_BTN,
6129                            events: {
6130                                click: BX.proxy(this.autoLoadLegalDataByINN, this) // Привязка события
6131                            }
6132                        })
6133                    );
6134                }
6135
6136                if (
6137                    this.params.USE_COMPANY_AUTOCOMPLETE == "Y" &&
6138                    this.params.AUTOLOAD_LEGAL_COMPANY.length > 0 &&
6139                    this.params.AUTOLOAD_LEGAL_COMPANY == propSettings["CODE"]
6140                ) {
6141                    BX.addClass(propContainer, "has-soa-company-suggest");
6142
6143                    propContainer.appendChild(
6144                        BX.create('SPAN', {
6145                            props: {
6146                                className: 'soa-suggests-company-container'
6147                            },
6148                            children: [
6149                                BX.create('SPAN', {
6150                                    props: {
6151                                        className: 'soa-suggests-company-block'
6152                                    }
6153                                })
6154                            ]
6155                        })
6156                    );
6157
6158                    property.addEvent("input", this.autocompleteCompany);
6159                    property.addEvent("blur", function (e) {
6160                        $(this).next(".soa-suggests-company-container").fadeOut();
6161                    });
6162                    property.addEvent("focus", function (e) {
6163                        var _sc = $(this).next(".soa-suggests-company-container");
6164                        var _scb = _sc.find(".soa-suggests-company-block");
6165                        if (_scb.length > 0 && _scb.html() !== "") {
6166                            _sc.fadeIn();
6167                        }
6168                    });
6169                }
6170
6171                if (
6172                    this.params.USE_ADDR_AUTOCOMPLATE == "Y" &&
6173                    this.params.AUTOCOMPLATE_ADDR.length > 0 &&
6174                    this.params.AUTOCOMPLATE_ADDR == propSettings["CODE"]
6175                ) {
6176                    BX.addClass(propContainer, "has-soa-address-suggest");
6177
6178                    propContainer.appendChild(
6179                        BX.create('SPAN', {
6180                            props: {
6181                                className: 'soa-suggests-container'
6182                            },
6183                            children: [
6184                                BX.create('SPAN', {
6185                                    props: {
6186                                        className: 'soa-suggests-block'
6187                                    }
6188                                })
6189                            ]
6190                        })
6191                    );
6192
6193                    property.addEvent("input", this.autocompleteAddr);
6194                    property.addEvent("blur", function (e) {
6195                        $(this).next(".soa-suggests-container").fadeOut();
6196                    });
6197                    property.addEvent("focus", function (e) {
6198                        var _sc = $(this).next(".soa-suggests-container");
6199                        var _scb = _sc.find(".soa-suggests-block");
6200                        if (_scb.length > 0 && _scb.html() !== "") {
6201                            _sc.fadeIn();
6202                        }
6203                    });
6204                }
6205
6206                propsItemNode.appendChild(propContainer);
6207
6208                this.alterProperty(property.getSettings(), propContainer);
6209                this.bindValidation(property.getId(), propContainer);
6210            }
6211        },
6212
6213        insertEnumProperty: function (property, propsItemNode, disabled) {
6214            var prop, inputs, values, i, propContainer;
6215
6216            if (disabled) {
6217                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6218                if (prop) {
6219                    values = [];
6220                    inputs = prop.querySelectorAll('input[type=radio]');
6221                    if (inputs.length) {
6222                        for (i = 0; i < inputs.length; i++) {
6223                            if (inputs[i].checked)
6224                                values.push(inputs[i].nextSibling.nodeValue);
6225                        }
6226                    }
6227                    inputs = prop.querySelectorAll('option');
6228                    if (inputs.length) {
6229                        for (i = 0; i < inputs.length; i++) {
6230                            if (inputs[i].selected)
6231                                values.push(inputs[i].innerHTML);
6232                        }
6233                    }
6234
6235                    propsItemNode.innerHTML += this.valuesToString(values);
6236                }
6237            } else {
6238                propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6239                property.appendTo(propContainer);
6240                propsItemNode.appendChild(propContainer);
6241                this.bindValidation(property.getId(), propContainer);
6242            }
6243        },
6244
6245        insertYNProperty: function (property, propsItemNode, disabled) {
6246            var prop, inputs, values, i, propContainer;
6247
6248            if (disabled) {
6249                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6250                if (prop) {
6251                    values = [];
6252                    inputs = prop.querySelectorAll('input[type=checkbox]');
6253
6254                    for (i = 0; i < inputs.length; i += 2)
6255                        values.push(inputs[i].checked ? BX.message('SOA_YES') : BX.message('SOA_NO'));
6256
6257                    propsItemNode.innerHTML += this.valuesToString(values);
6258                }
6259            } else {
6260                propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6261                property.appendTo(propContainer);
6262                propsItemNode.appendChild(propContainer);
6263                this.alterProperty(property.getSettings(), propContainer);
6264                this.bindValidation(property.getId(), propContainer);
6265            }
6266        },
6267
6268        insertNumberProperty: function (property, propsItemNode, disabled) {
6269            var prop, inputs, values, i, propContainer;
6270
6271            if (disabled) {
6272                prop = this.propsHiddenBlockNode.querySelector('div[data-property-id-row="' + property.getId() + '"]');
6273                if (prop) {
6274                    values = [];
6275                    inputs = prop.querySelectorAll('input[type=text]');
6276
6277                    for (i = 0; i < inputs.length; i++)
6278                        if (inputs[i].value.length)
6279                            values.push(inputs[i].value);
6280
6281                    propsItemNode.innerHTML += this.valuesToString(values);
6282                }
6283            } else {
6284                propContainer = BX.create('DIV', {props: {className: 'soa-property-container'}});
6285                property.appendTo(propContainer);
6286                propsItemNode.appendChild(propContainer);
6287                this.alterProperty(property.getSettings(), propContainer);
6288                this.bindValidation(property.getId(), propContainer);
6289            }
6290        },
6291
6292        valuesToString: function (values) {
6293            var str = values.join(', ');
6294
6295            return str.length ? BX.util.htmlspecialchars(str) : BX.message('SOA_NOT_SELECTED');
6296        },
6297
6298        alterProperty: function (settings, propContainer) {
6299            var divs = BX.findChildren(propContainer, {tagName: 'DIV'}),
6300                i, textNode, inputs, del, add,
6301                fileInputs, accepts, fileTitles;
6302
6303            if (divs && divs.length) {
6304                for (i = 0; i < divs.length; i++) {
6305                    divs[i].style.margin = '5px 0';
6306                }
6307            }
6308
6309            textNode = propContainer.querySelector('input[type=text]');
6310            if (!textNode)
6311                textNode = propContainer.querySelector('textarea');
6312
6313            if (textNode) {
6314                textNode.id = 'soa-property-' + settings.ID;
6315                if (settings.IS_ADDRESS == 'Y')
6316                    textNode.setAttribute('autocomplete', 'new-password');
6317                if (settings.IS_EMAIL == 'Y')
6318                    textNode.setAttribute('autocomplete', 'email');
6319                if (settings.IS_PAYER == 'Y')
6320                    textNode.setAttribute('autocomplete', 'name');
6321                if (settings.IS_PHONE == 'Y') {
6322                    textNode.setAttribute('autocomplete', 'tel');
6323                    $(textNode).mask(this.params.PHONE_INPUT_MASK);
6324                }
6325
6326                if (settings.PATTERN && settings.PATTERN.length) {
6327                    textNode.removeAttribute('pattern');
6328                }
6329            }
6330
6331            inputs = propContainer.querySelectorAll('input[type=text]');
6332            for (i = 0; i < inputs.length; i++) {
6333                inputs[i].placeholder = settings.DESCRIPTION;
6334                BX.addClass(inputs[i], 'tanais-form-control bx-soa-customer-input bx-ios-fix');
6335            }
6336
6337            inputs = propContainer.querySelectorAll('select');
6338            for (i = 0; i < inputs.length; i++)
6339                BX.addClass(inputs[i], 'tanais-form-control');
6340
6341            inputs = propContainer.querySelectorAll('textarea');
6342            for (i = 0; i < inputs.length; i++) {
6343                inputs[i].placeholder = settings.DESCRIPTION;
6344                BX.addClass(inputs[i], 'tanais-form-control bx-ios-fix');
6345            }
6346
6347            del = propContainer.querySelectorAll('label');
6348            for (i = 0; i < del.length; i++)
6349                BX.remove(del[i]);
6350
6351            if (settings.TYPE == 'FILE') {
6352                if (settings.ACCEPT && settings.ACCEPT.length) {
6353                    fileInputs = propContainer.querySelectorAll('input[type=file]');
6354                    accepts = this.getFileAccepts(settings.ACCEPT);
6355                    for (i = 0; i < fileInputs.length; i++)
6356                        fileInputs[i].setAttribute('accept', accepts);
6357                }
6358
6359                fileTitles = propContainer.querySelectorAll('a');
6360                for (i = 0; i < fileTitles.length; i++) {
6361                    BX.bind(fileTitles[i], 'click', function (e) {
6362                        var target = e.target || e.srcElement,
6363                            fileInput = target && target.nextSibling && target.nextSibling.nextSibling;
6364
6365                        if (fileInput)
6366                            BX.fireEvent(fileInput, 'change');
6367                    });
6368                }
6369            }
6370
6371            add = propContainer.querySelectorAll('input[type=button]');
6372            for (i = 0; i < add.length; i++) {
6373                BX.addClass(add[i], 'btn btn-default');
6374
6375                if (settings.MULTIPLE == 'Y' && i == add.length - 1)
6376                    continue;
6377
6378                if (settings.TYPE == 'FILE') {
6379                    BX.prepend(add[i], add[i].parentNode);
6380                    add[i].style.marginRight = '10px';
6381                }
6382            }
6383
6384            if (add.length) {
6385                add = add[add.length - 1];
6386                BX.bind(add, 'click', BX.delegate(function (e) {
6387                    var target = e.target || e.srcElement,
6388                        targetContainer = BX.findParent(target, {tagName: 'div', className: 'soa-property-container'}),
6389                        del = targetContainer.querySelector('label'),
6390                        add = targetContainer.querySelectorAll('input[type=button]'),
6391                        textInputs = targetContainer.querySelectorAll('input[type=text]'),
6392                        textAreas = targetContainer.querySelectorAll('textarea'),
6393                        divs = BX.findChildren(targetContainer, {tagName: 'DIV'});
6394
6395                    var i, fileTitles, fileInputs, accepts;
6396
6397                    if (divs && divs.length) {
6398                        for (i = 0; i < divs.length; i++) {
6399                            divs[i].style.margin = '5px 0';
6400                        }
6401                    }
6402
6403                    this.bindValidation(settings.ID, targetContainer);
6404
6405                    if (add.length && add[add.length - 2]) {
6406                        BX.prepend(add[add.length - 2], add[add.length - 2].parentNode);
6407                        add[add.length - 2].style.marginRight = '10px';
6408                        BX.addClass(add[add.length - 2], 'btn btn-default');
6409                    }
6410
6411                    del && BX.remove(del);
6412                    if (textInputs.length) {
6413                        textInputs[textInputs.length - 1].placeholder = settings.DESCRIPTION;
6414                        BX.addClass(textInputs[textInputs.length - 1], 'tanais-form-control bx-soa-customer-input bx-ios-fix');
6415                        if (settings.TYPE == 'DATE')
6416                            this.alterDateProperty(settings, textInputs[textInputs.length - 1]);
6417
6418                        if (settings.PATTERN && settings.PATTERN.length)
6419                            textInputs[textInputs.length - 1].removeAttribute('pattern');
6420                    }
6421
6422                    if (textAreas.length) {
6423                        textAreas[textAreas.length - 1].placeholder = settings.DESCRIPTION;
6424                        BX.addClass(textAreas[textAreas.length - 1], 'tanais-form-control bx-ios-fix');
6425                    }
6426
6427                    if (settings.TYPE == 'FILE') {
6428                        if (settings.ACCEPT && settings.ACCEPT.length) {
6429                            fileInputs = propContainer.querySelectorAll('input[type=file]');
6430                            accepts = this.getFileAccepts(settings.ACCEPT);
6431                            for (i = 0; i < fileInputs.length; i++)
6432                                fileInputs[i].setAttribute('accept', accepts);
6433                        }
6434
6435                        fileTitles = targetContainer.querySelectorAll('a');
6436                        BX.bind(fileTitles[fileTitles.length - 1], 'click', function (e) {
6437                            var target = e.target || e.srcElement,
6438                                fileInput = target && target.nextSibling && target.nextSibling.nextSibling;
6439
6440                            if (fileInput)
6441                                setTimeout(function () {
6442                                    BX.fireEvent(fileInput, 'change');
6443                                }, 10);
6444                        });
6445                    }
6446                }, this));
6447            }
6448        },
6449
6450        alterDateProperty: function (settings, inputText) {
6451            var parentNode = BX.findParent(inputText, {tagName: 'DIV'}),
6452                addon;
6453
6454            BX.addClass(parentNode, 'input-group');
6455            addon = BX.create('DIV', {
6456                props: {className: 'input-group-addon'},
6457                children: [BX.create('I', {props: {className: 'bx-calendar'}})]
6458            });
6459            BX.insertAfter(addon, inputText);
6460            BX.remove(parentNode.querySelector('input[type=button]'));
6461            BX.bind(addon, 'click', BX.delegate(function (e) {
6462                var target = e.target || e.srcElement,
6463                    parentNode = BX.findParent(target, {tagName: 'DIV', className: 'input-group'});
6464
6465                BX.calendar({
6466                    node: parentNode.querySelector('.input-group-addon'),
6467                    field: parentNode.querySelector('input[type=text]').name,
6468                    form: '',
6469                    bTime: settings.TIME == 'Y',
6470                    bHideTime: false
6471                });
6472            }, this));
6473        },
6474
6475        isValidForm: function () {
6476            if (!this.options.propertyValidation)
6477                return true;
6478
6479            var regionErrors = this.isValidRegionBlock(),
6480                propsErrors = this.isValidPropertiesBlock(),
6481                navigated = false, tooltips, i;
6482
6483            if (regionErrors.length) {
6484                navigated = true;
6485                this.animateScrollTo(this.regionBlockNode, 800, 50);
6486            }
6487
6488            if (propsErrors.length && !navigated) {
6489                if (this.activeSectionId == this.propsBlockNode.id) {
6490                    tooltips = this.propsBlockNode.querySelectorAll('div.tooltip');
6491                    for (i = 0; i < tooltips.length; i++) {
6492                        if (tooltips[i].getAttribute('data-state') == 'opened') {
6493                            this.animateScrollTo(BX.findParent(tooltips[i], {className: 'tanais-form-group bx-soa-customer-field'}), 800, 50);
6494                            break;
6495                        }
6496                    }
6497                } else
6498                    this.animateScrollTo(this.propsBlockNode, 800, 50);
6499            }
6500
6501            if (regionErrors.length) {
6502                this.showError(this.regionBlockNode, regionErrors);
6503                BX.addClass(this.regionBlockNode, 'bx-step-error');
6504            }
6505
6506            if (propsErrors.length) {
6507                if (this.activeSectionId !== this.propsBlockNode.id)
6508                    this.showError(this.propsBlockNode, propsErrors);
6509
6510                BX.addClass(this.propsBlockNode, 'bx-step-error');
6511            }
6512
6513            return !(regionErrors.length + propsErrors.length);
6514        },
6515
6516        isValidRegionBlock: function () {
6517            if (!this.options.propertyValidation)
6518                return [];
6519
6520            var regionProps = this.orderBlockNode.querySelectorAll('.bx-soa-location-input-container[data-
6520property-id-row]'),
6521                regionErrors = [],
6522                id, arProperty, data, i;
6523
6524            for (i = 0; i < regionProps.length; i++) {
6525                id = regionProps[i].getAttribute('data-property-id-row');
6526                arProperty = this.validation.properties[id];
6527                data = this.getValidationData(arProperty, regionProps[i]);
6528
6529                regionErrors = regionErrors.concat(this.isValidProperty(data, true));
6530            }
6531
6532            return regionErrors;
6533        },
6534
6535        isValidPropertiesBlock: function (excludeLocation) {
6536            if (!this.options.propertyValidation)
6537                return [];
6538
6539            var props = this.orderBlockNode.querySelectorAll('.bx-soa-customer-field[data-property-id-row]'),
6540                propsErrors = [],
6541                id, propContainer, arProperty, data, i;
6542
6543            for (i = 0; i < props.length; i++) {
6544                id = props[i].getAttribute('data-property-id-row');
6545
6546                if (!!excludeLocation && this.locations[id])
6547                    continue;
6548
6549                propContainer = props[i].querySelector('.soa-property-container');
6550                if (propContainer) {
6551                    arProperty = this.validation.properties[id];
6552                    data = this.getValidationData(arProperty, propContainer);
6553                    propsErrors = propsErrors.concat(this.isValidProperty(data, true));
6554                }
6555            }
6556
6557            return propsErrors;
6558        },
6559
6560        isValidProperty: function (data, fieldName) {
6561            var propErrors = [], inputErrors, i;
6562
6563            if (!data || !data.inputs)
6564                return propErrors;
6565
6566            for (i = 0; i < data.inputs.length; i++) {
6567                inputErrors = data.func(data.inputs[i], !!fieldName);
6568                if (inputErrors.length)
6569                    propErrors[i] = inputErrors.join('<br>');
6570            }
6571
6572            this.showValidationResult(data.inputs, propErrors);
6573
6574            return propErrors;
6575        },
6576
6577        bindValidation: function (id, propContainer) {
6578            if (!this.validation.properties || !this.validation.properties[id])
6579                return;
6580
6581            var arProperty = this.validation.properties[id],
6582                data = this.getValidationData(arProperty, propContainer),
6583                i, k;
6584
6585            if (data && data.inputs && data.action) {
6586                for (i = 0; i < data.inputs.length; i++) {
6587                    if (BX.type.isElementNode(data.inputs[i]))
6588                        BX.bind(data.inputs[i], data.action, BX.delegate(function () {
6589                            this.isValidProperty(data);
6590                        }, this));
6591                    else
6592                        for (k = 0; k < data.inputs[i].length; k++)
6593                            BX.bind(data.inputs[i][k], data.action, BX.delegate(function () {
6594                                this.isValidProperty(data);
6595                            }, this));
6596                }
6597            }
6598        },
6599
6600        getValidationData: function (arProperty, propContainer) {
6601            if (!arProperty || !propContainer)
6602                return;
6603
6604            var data = {}, inputs;
6605
6606            switch (arProperty.TYPE) {
6607                case 'STRING':
6608                    data.action = 'change';
6609                    data.func = BX.delegate(function (input, fieldName) {
6610                        return this.validateString(input, arProperty, fieldName);
6611                    }, this);
6612
6613                    inputs = propContainer.querySelectorAll('input[type=text]');
6614                    if (inputs.length) {
6615                        data.inputs = inputs;
6616                        break;
6617                    }
6618                    inputs = propContainer.querySelectorAll('textarea');
6619                    if (inputs.length)
6620                        data.inputs = inputs;
6621                    break;
6622                case 'LOCATION':
6623                    data.func = BX.delegate(function (input, fieldName) {
6624                        return this.validateLocation(input, arProperty, fieldName);
6625                    }, this);
6626
6627                    inputs = propContainer.querySelectorAll('input.bx-ui-sls-fake[type=text]');
6628                    if (inputs.length) {
6629                        data.inputs = inputs;
6630                        data.action = 'keyup';
6631                        break;
6632                    }
6633                    inputs = propContainer.querySelectorAll('div.bx-ui-slst-pool');
6634                    if (inputs.length) {
6635                        data.inputs = inputs;
6636                    }
6637                    break;
6638                case 'Y/N':
6639                    data.inputs = propContainer.querySelectorAll('input[type=checkbox]');
6640                    data.action = 'change';
6641                    data.func = BX.delegate(function (input, fieldName) {
6642                        return this.validateCheckbox(input, arProperty, fieldName);
6643                    }, this);
6644                    break;
6645                case 'NUMBER':
6646                    data.inputs = propContainer.querySelectorAll('input[type=text]');
6647                    data.action = 'blur';
6648                    data.func = BX.delegate(function (input, fieldName) {
6649                        return this.validateNumber(input, arProperty, fieldName);
6650                    }, this);
6651                    break;
6652                case 'ENUM':
6653                    inputs = propContainer.querySelectorAll('input[type=radio]');
6654                    if (!inputs.length)
6655                        inputs = propContainer.querySelectorAll('input[type=checkbox]');
6656
6657                    if (inputs.length) {
6658                        data.inputs = [inputs];
6659                        data.action = 'change';
6660                        data.func = BX.delegate(function (input, fieldName) {
6661                            return this.validateEnum(input, arProperty, fieldName);
6662                        }, this);
6663                        break;
6664                    }
6665
6666                    inputs = propContainer.querySelectorAll('option');
6667                    if (inputs.length) {
6668                        data.inputs = [inputs];
6669                        data.action = 'click';
6670                        data.func = BX.delegate(function (input, fieldName) {
6671                            return this.validateSelect(input, arProperty, fieldName);
6672                        }, this);
6673                    }
6674                    break;
6675                case 'FILE':
6676                    data.inputs = propContainer.querySelectorAll('input[type=file]');
6677                    data.action = 'change';
6678                    data.func = BX.delegate(function (input, fieldName) {
6679                        return this.validateFile(input, arProperty, fieldName);
6680                    }, this);
6681                    break;
6682                case 'DATE':
6683                    data.inputs = propContainer.querySelectorAll('input[type=text]');
6684                    data.action = 'change';
6685                    data.func = BX.delegate(function (input, fieldName) {
6686                        return this.validateDate(input, arProperty, fieldName);
6687                    }, this);
6688                    break;
6689            }
6690
6691            return data;
6692        },
6693
6694        showErrorTooltip: function (tooltipId, targetNode, text) {
6695            if (!tooltipId || !targetNode || !text)
6696                return;
6697
6698            var tooltip = BX('tooltip-' + tooltipId),
6699                tooltipInner, quickLocation;
6700
6701            text = this.uniqueText(text, '<br>');
6702
6703            if (tooltip) {
6704                tooltipInner = tooltip.querySelector('div.tooltip-inner');
6705            } else {
6706                tooltipInner = BX.create('DIV', {props: {className: 'tooltip-inner'}});
6707                tooltip = BX.create('DIV', {
6708                    props: {
6709                        id: 'tooltip-' + tooltipId,
6710                        className: 'bx-soa-tooltip bx-soa-tooltip-static bx-soa-tooltip-danger tooltip top'
6711                    },
6712                    children: [
6713                        BX.create('DIV', {props: {className: 'tooltip-arrow'}}),
6714                        tooltipInner
6715                    ]
6716                });
6717
6718                quickLocation = targetNode.parentNode.querySelector('div.quick-locations');
6719                if (quickLocation)
6720                    targetNode = quickLocation;
6721
6722                BX.insertAfter(tooltip, targetNode);
6723            }
6724
6725            tooltipInner.innerHTML = text;
6726
6727            if (tooltip.getAttribute('data-state') != 'opened') {
6728                tooltip.setAttribute('data-state', 'opened');
6729                tooltip.style.opacity = 0;
6730                tooltip.style.display = 'block';
6731
6732                new BX.easing({
6733                    duration: 150,
6734                    start: {opacity: 0},
6735                    finish: {opacity: 100},
6736                    transition: BX.easing.transitions.quad,
6737                    step: function (state) {
6738                        tooltip.style.opacity = state.opacity / 100;
6739                    }
6740                }).animate();
6741            }
6742        },
6743
6744        closeErrorTooltip: function (tooltipId) {
6745            var tooltip = BX('tooltip-' + tooltipId);
6746            if (tooltip) {
6747                tooltip.setAttribute('data-state', 'closed');
6748
6749                new BX.easing({
6750                    duration: 150,
6751                    start: {opacity: 100},
6752                    finish: {opacity: 0},
6753                    transition: BX.easing.transitions.quad,
6754                    step: function (state) {
6755                        tooltip.style.opacity = state.opacity / 100;
6756                    },
6757                    complete: function () {
6758                        tooltip.style.display = 'none';
6759                    }
6760                }).animate();
6761            }
6762        },
6763
6764        showValidationResult: function (inputs, errors) {
6765            if (!inputs || !inputs.length || !errors)
6766                return;
6767
6768            var input0 = BX.type.isElementNode(inputs[0]) ? inputs[0] : inputs[0][0],
6769                formGroup = BX.findParent(input0, {tagName: 'DIV', className: 'tanais-form-group'}),
6770                label = formGroup.querySelector('label'),
6771                tooltipId, inputDiv, i;
6772
6773            if (label)
6774                tooltipId = label.getAttribute('for');
6775
6776            for (i = 0; i < inputs.length; i++) {
6777                inputDiv = BX.findParent(inputs[i], {tagName: 'DIV', className: 'tanais-form-group'});
6778                if (errors[i] && errors[i].length)
6779                    BX.addClass(inputDiv, 'has-error');
6780                else
6781                    BX.removeClass(inputDiv, 'has-error');
6782            }
6783
6784            if (errors.length)
6785                this.showErrorTooltip(tooltipId, label, errors.join('<br>'));
6786            else
6787                this.closeErrorTooltip(tooltipId);
6788        },
6789
6790        validateString: function (input, arProperty, fieldName) {
6791            if (!input || !arProperty)
6792                return [];
6793
6794            var value = input.value,
6795                errors = [],
6796                name = BX.util.htmlspecialchars(arProperty.NAME),
6797                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + name + '"' : BX.message('SOA_FIELD'),
6798                re;
6799
6800            if (arProperty.MULTIPLE === 'Y')
6801                return errors;
6802
6803            if (arProperty.REQUIRED === 'Y' && value.length === 0)
6804                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6805
6806            if (value.length) {
6807                if (arProperty.MINLENGTH && arProperty.MINLENGTH > value.length)
6808                    errors.push(BX.message('SOA_MIN_LENGTH') + ' "' + name + '" ' + BX.message('SOA_LESS') + ' ' + arProperty.MINLENGTH + ' ' + BX.message('SOA_SYMBOLS'));
6809
6810                if (arProperty.MAXLENGTH && arProperty.MAXLENGTH < value.length)
6811                    errors.push(BX.message('SOA_MAX_LENGTH') + ' "' + name + '" ' + BX.message('SOA_MORE') + ' ' + arProperty.MAXLENGTH + ' ' + BX.message('SOA_SYMBOLS'));
6812
6813                if (arProperty.IS_EMAIL === 'Y') {
6814                    input.value = value = BX.util.trim(value);
6815                    if (value.length) {
6816                        re = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;
6817                        if (!re.test(value)) {
6818                            errors.push(BX.message('SOA_INVALID_EMAIL'));
6819                        }
6820                    }
6821                }
6822
6823                if (value.length > 0 && arProperty.PATTERN && arProperty.PATTERN.length) {
6824                    re = new RegExp(arProperty.PATTERN);
6825                    if (!re.test(value))
6826                        errors.push(field + ' ' + BX.message('SOA_INVALID_PATTERN'));
6827                }
6828            }
6829
6830            return errors;
6831        },
6832
6833        validateLocation: function (input, arProperty, fieldName) {
6834            if (!input || !arProperty)
6835                return [];
6836
6837            var parent = BX.findParent(input, {tagName: 'DIV', className: 'tanais-form-group'}),
6838                value = this.getLocationString(parent),
6839                errors = [],
6840                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + BX.util.htmlspecialchars(arProperty.NAME) + '"' : BX.message('SOA_FIELD');
6841
6842            if (arProperty.MULTIPLE == 'Y' && arProperty.IS_LOCATION !== 'Y')
6843                return errors;
6844
6845            if (arProperty.REQUIRED == 'Y' && (value.length == 0 || value == BX.message('SOA_NOT_SPECIFIED')))
6846                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6847
6848            return errors;
6849        },
6850
6851        validateCheckbox: function (input, arProperty, fieldName) {
6852            if (!input || !arProperty)
6853                return [];
6854
6855            var errors = [],
6856                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + BX.util.htmlspecialchars(arProperty.NAME) + '"' : BX.message('SOA_FIELD');
6857
6858            if (arProperty.MULTIPLE == 'Y')
6859                return errors;
6860
6861            if (arProperty.REQUIRED == 'Y' && !input.checked)
6862                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6863
6864            return errors;
6865        },
6866
6867        validateNumber: function (input, arProperty, fieldName) {
6868            if (!input || !arProperty)
6869                return [];
6870
6871            var value = input.value,
6872                errors = [],
6873                name = BX.util.htmlspecialchars(arProperty.NAME),
6874                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + name + '"' : BX.message('SOA_FIELD'),
6875                num, del;
6876
6877            if (arProperty.MULTIPLE == 'Y')
6878                return errors;
6879
6880            if (arProperty.REQUIRED == 'Y' && value.length == 0)
6881                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6882
6883            if (value.length) {
6884                if (!/[0-9]|\./.test(value))
6885                    errors.push(field + ' ' + BX.message('SOA_NOT_NUMERIC'));
6886
6887                if (arProperty.MIN && parseFloat(arProperty.MIN) > parseFloat(value))
6888                    errors.push(BX.message('SOA_MIN_VALUE') + ' "' + name + '" ' + parseFloat(arProperty.MIN));
6889
6890                if (arProperty.MAX && parseFloat(arProperty.MAX) < parseFloat(value))
6891                    errors.push(BX.message('SOA_MAX_VALUE') + ' "' + name + '" ' + parseFloat(arProperty.MAX));
6892
6893                if (arProperty.STEP && parseFloat(arProperty.STEP) > 0) {
6894                    num = Math.abs(parseFloat(value) - (arProperty.MIN && parseFloat(arProperty.MIN) > 0 ? parseFloat(arProperty.MIN) : 0));
6895                    del = (num / parseFloat(arProperty.STEP)).toPrecision(12);
6896                    if (del != parseInt(del))
6897                        errors.push(field + ' ' + BX.message('SOA_NUM_STEP') + ' ' + arProperty.STEP);
6898                }
6899            }
6900
6901            return errors;
6902        },
6903
6904        validateEnum: function (inputs, arProperty, fieldName) {
6905            if (!inputs || !arProperty)
6906                return [];
6907
6908            var values = [], errors = [], i,
6909                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + BX.util.htmlspecialchars(arProperty.NAME) + '"' : BX.message('SOA_FIELD');
6910
6911            if (arProperty.MULTIPLE == 'Y')
6912                return errors;
6913
6914            for (i = 0; i < inputs.length; i++)
6915                if (inputs[i].checked || inputs[i].selected)
6916                    values.push(i);
6917
6918            if (arProperty.REQUIRED == 'Y' && values.length == 0)
6919                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6920
6921            return errors;
6922        },
6923
6924        validateSelect: function (inputs, arProperty, fieldName) {
6925            if (!inputs || !arProperty)
6926                return [];
6927
6928            var values = [], errors = [], i,
6929                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + BX.util.htmlspecialchars(arProperty.NAME) + '"' : BX.message('SOA_FIELD');
6930
6931            if (arProperty.MULTIPLE == 'Y')
6932                return errors;
6933
6934            for (i = 0; i < inputs.length; i++)
6935                if (inputs[i].selected)
6936                    values.push(i);
6937
6938            if (arProperty.REQUIRED == 'Y' && values.length == 0)
6939                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6940
6941            return errors;
6942        },
6943
6944        validateFile: function (inputs, arProperty, fieldName) {
6945            if (!inputs || !arProperty)
6946                return [];
6947
6948            var errors = [], i,
6949                files = inputs.files || [],
6950                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + BX.util.htmlspecialchars(arProperty.NAME) + '"' : BX.message('SOA_FIELD'),
6951                defaultValue = inputs.previousSibling.value,
6952                file, fileName, splittedName, fileExtension;
6953
6954            if (arProperty.MULTIPLE == 'Y')
6955                return errors;
6956
6957            if (
6958                arProperty.REQUIRED == 'Y' && files.length == 0 && defaultValue == ''
6959                && (!arProperty.DEFAULT_VALUE || !arProperty.DEFAULT_VALUE.length)
6960            ) {
6961                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6962            } else {
6963                for (i = 0; i < files.length; i++) {
6964                    file = files[i];
6965                    fileName = BX.util.htmlspecialchars(file.name);
6966                    splittedName = file.name.split('.');
6967                    fileExtension = splittedName.length > 1 ? splittedName[splittedName.length - 1].toLowerCase() : '';
6968
6969                    if (arProperty.ACCEPT.length > 0 && (fileExtension.length == 0 || arProperty.ACCEPT.indexOf(fileExtension) == '-1'))
6970                        errors.push(BX.message('SOA_BAD_EXTENSION') + ' "' + fileName + '" (' + BX.util.htmlspecialchars(arProperty.ACCEPT) + ')');
6971
6972                    if (file.size > parseInt(arProperty.MAXSIZE))
6973                        errors.push(BX.message('SOA_MAX_SIZE') + ' "' + fileName + '" (' + this.getSizeString(arProperty.MAXSIZE, 1) + ')');
6974                }
6975            }
6976
6977            return errors;
6978        },
6979
6980        validateDate: function (input, arProperty, fieldName) {
6981            if (!input || !arProperty)
6982                return [];
6983
6984            var value = input.value,
6985                errors = [],
6986                name = BX.util.htmlspecialchars(arProperty.NAME),
6987                field = !!fieldName ? BX.message('SOA_FIELD') + ' "' + name + '"' : BX.message('SOA_FIELD');
6988
6989            if (arProperty.MULTIPLE == 'Y')
6990                return errors;
6991
6992            if (arProperty.REQUIRED == 'Y' && value.length == 0)
6993                errors.push(field + ' ' + BX.message('SOA_REQUIRED'));
6994
6995            return errors;
6996        },
6997
6998        editPropsMap: function (propsNode) {
6999            var propsMapContainer = BX.create('DIV', {style: {marginBottom: '10px'}}),
7000                map = BX.create('DIV', {props: {id: 'propsMap'}, style: {width: '100%'}});
7001
7002            propsMapContainer.appendChild(map);
7003            propsNode.appendChild(propsMapContainer);
7004        },
7005
7006        editPropsComment: function (propsNode) {
7007            var propsCommentContainer, label, input, div;
7008
7009            propsCommentContainer = BX.create('DIV', {});
7010            label = BX.create('LABEL', {
7011                attrs: {for: 'orderDescription'},
7012                props: {className: 'bx-soa-customer-label'},
7013                html: this.params.MESS_ORDER_DESC
7014            });
7015            input = BX.create('TEXTAREA', {
7016                props: {
7017                    id: 'orderDescription',
7018                    cols: '4',
7019                    className: 'tanais-form-control bx-soa-customer-textarea bx-ios-fix tanais-textarea',
7020                    name: 'ORDER_DESCRIPTION'
7021                },
7022                text: this.result.ORDER_DESCRIPTION ? this.result.ORDER_DESCRIPTION : ''
7023            });
7024            div = BX.create('DIV', {
7025                props: {className: 'tanais-form-group bx-soa-customer-field'},
7026                children: [label, input]
7027            });
7028
7029            propsCommentContainer.appendChild(div);
7030            propsNode.appendChild(propsCommentContainer);
7031        },
7032
7033        declOfNum(n, titles) {
7034            return titles[(n % 10 === 1 && n % 100 !== 11) ? 0 : n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 10 || n % 100 >= 20) ? 1 : 2]
7035        },
7036
7037        editTotalBlock: function () {
7038            if (!this.totalInfoBlockDataNode || !this.result.TOTAL)
7039                return;
7040
7041            var total = this.result.TOTAL,
7042                priceHtml, params = {},
7043                discText, valFormatted, i,
7044                curDelivery, deliveryError, deliveryValue,
7045                showOrderButton = this.params.SHOW_TOTAL_ORDER_BUTTON === 'Y';
7046
7047            BX.cleanNode(this.totalInfoBlockDataNode);
7048
7049            if (parseFloat(total.ORDER_PRICE) === 0) {
7050                priceHtml = this.params.MESS_PRICE_FREE;
7051                params.free = true;
7052            } else {
7053                priceHtml = total.ORDER_PRICE_FORMATED;
7054            }
7055
7056            if (this.options.showPriceWithoutDiscount) {
7057                priceHtml = '<span class="bx-price-old">' +
7058                    total.PRICE_WITHOUT_DISCOUNT + '</span><br>
7058' + '<span class="with-discount-value">' + priceHtml + '</span>';
7059            }
7060
7061            this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(total.BASKET_POSITIONS + this.declOfNum(total.BASKET_POSITIONS, [' товар', ' товара', ' товаров']), priceHtml, params));
7062
7063            if (this.options.showOrderWeight) {
7064                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_WEIGHT_SUM'), total.ORDER_WEIGHT_FORMATED));
7065            }
7066
7067            if (this.options.showTaxList) {
7068                for (i = 0; i < total.TAX_LIST.length; i++) {
7069                    valFormatted = total.TAX_LIST[i].VALUE_MONEY_FORMATED || '';
7070                    this.totalInfoBlockDataNode.appendChild(
7071                        this.createTotalUnit(
7072                            total.TAX_LIST[i].NAME + (!!total.TAX_LIST[i].VALUE_FORMATED ? ' ' + total.TAX_LIST[i].VALUE_FORMATED : '') + ':',
7073                            valFormatted
7074                        )
7075                    );
7076                }
7077            }
7078
7079            params = {};
7080            curDelivery = this.getSelectedDelivery();
7081            deliveryError = curDelivery && curDelivery.CALCULATE_ERRORS && curDelivery.CALCULATE_ERRORS.length;
7082
7083            if (deliveryError) {
7084                deliveryValue = BX.message('SOA_NOT_CALCULATED');
7085                params.error = deliveryError;
7086            } else {
7087                if (parseFloat(total.DELIVERY_PRICE) === 0) {
7088                    deliveryValue = this.params.MESS_PRICE_FREE;
7089                    params.free = true;
7090                } else {
7091                    deliveryValue = total.DELIVERY_PRICE_FORMATED;
7092                }
7093
7094                if (
7095                    curDelivery && typeof curDelivery.DELIVERY_DISCOUNT_PRICE !== 'undefined'
7096                    && parseFloat(curDelivery.PRICE) > parseFloat(curDelivery.DELIVERY_DISCOUNT_PRICE)
7097                ) {
7098                    deliveryValue = '<span class="bx-price-old">' + curDelivery.PRICE_FORMATED + '</span><br>' + '<span class="with-discount-value">' + deliveryValue + '</span>';
7099                }
7100            }
7101
7102            if (this.result.DELIVERY.length) {
7103                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_DELIVERY'), deliveryValue, params));
7104            }
7105
7106            if (this.options.showDiscountPrice) {
7107                discText = this.params.MESS_ECONOMY;
7108                if (total.DISCOUNT_PERCENT_FORMATED && parseFloat(total.DISCOUNT_PERCENT_FORMATED) > 0)
7109                    discText += total.DISCOUNT_PERCENT_FORMATED;
7110
7111                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(discText + ':', total.DISCOUNT_PRICE_FORMATED, {highlighted: true}));
7112            }
7113
7114            if (this.options.showPayedFromInnerBudget) {
7115                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_IT'), total.ORDER_TOTAL_PRICE_FORMATED));
7116                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_PAYED'), total.PAYED_FROM_ACCOUNT_FORMATED));
7117                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_LEFT_TO_PAY'), total.ORDER_TOTAL_LEFT_TO_PAY_FORMATED, {total: true}));
7118            } else {
7119                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_SUM_IT'), total.ORDER_TOTAL_PRICE_FORMATED, {total: true}));
7120            }
7121
7122            if (parseFloat(total.PAY_SYSTEM_PRICE) >= 0 && this.result.DELIVERY.length) {
7123                this.totalInfoBlockDataNode.appendChild(this.createTotalUnit(BX.message('SOA_PAYSYSTEM_PRICE'), '~' + total.PAY_SYSTEM_PRICE_FORMATTED));
7124            }
7125
7126            var couponContainer = BX.create('DIV', {
7127                props: {
7128                    className: 'bx-total-coupon-container'
7129                }
7130            });
7131
7132            if (this.params.SHOW_COUPONS == 'Y') {
7133                this.editCoupons(couponContainer);
7134            }
7135
7136            this.totalInfoBlockDataNode.appendChild(couponContainer);
7137
7138            if (!this.result.SHOW_AUTH) {
7139                var _children = [
7140                    BX.create('A', {
7141                        props: {
7142                            href: 'javascript:void(0)',
7143                            className: 'btn btn-default btn-order-save'
7144                        },
7145                        html: this.params.MESS_ORDER,
7146                        events: {
7147                            click: BX.proxy(this.clickOrderSaveAction, this)
7148                        }
7149                    })
7150                ];
7151
7152                if (this.params.USE_BUY_ONE_CLICK == "Y") {
7153                    _children.push(
7154                        BX.create('A', {
7155                            props: {
7156                                href: 'javascript:void(0)',
7157                                className: 'btn btn-outline-primary btn-order-one-click'
7158                            },
7159                            html: this.params.MESS_TOTAL_BLOCK_BUY_ONE_CLICK_BTN,
7160                            events: {
7161                                click: BX.proxy(this.buyOneClickFormShow, this)
7162                            }
7163                        })
7164                    );
7165                }
7166
7167                this.totalInfoBlockDataNode.appendChild(
7168                    BX.create('DIV', {
7169                        props: {className: 'bx-soa-cart-total-button-container'},
7170                        children: _children
7171                    })
7172                );
7173            }
7174
7175            this.editMobileTotalBlock();
7176        },
7177
7178        editMobileTotalBlock: function () {
7179            BX.cleanNode(this.mobileTotalBlockNode);
7180            this.mobileTotalBlockNode.appendChild(this.totalInfoBlockNode.cloneNode(true));
7181            BX.bind(this.mobileTotalBlockNode.querySelector('a.bx-soa-price-not-calc'), 'click', BX.delegate(function () {
7182                this.animateScrollTo(this.deliveryBlockNode);
7183            }, this));
7184            BX.bind(this.mobileTotalBlockNode.querySelector('a.btn-order-save'), 'click', BX.proxy(this.clickOrderSaveAction, this));
7185
7186            if (this.params.USE_BUY_ONE_CLICK == "Y") {
7187                BX.bind(this.mobileTotalBlockNode.querySelector('.bx-soa-cart-total .btn-order-one-click'), 'click', BX.proxy(this.buyOneClickFormShow, this));
7188            }
7189
7190            BX.bind(
7191                this.mobileTotalBlockNode.querySelector(".bx-soa-coupon-input input[type='text']"),
7192                'change',
7193                this.getCouponChangeEvent()
7194            );
7195        },
7196
7197        createTotalUnit: function (name, value, params) {
7198            var totalValue, className = 'bx-soa-cart-total-line';
7199
7200            name = name || '';
7201            value = value || '';
7202            params = params || {};
7203
7204            if (params.error) {
7205                totalValue = [BX.create('A', {
7206                    props: {className: 'bx-soa-price-not-calc'},
7207                    html: value,
7208                    events: {
7209                        click: BX.delegate(function () {
7210                            this.animateScrollTo(this.deliveryBlockNode);
7211                        }, this)
7212                    }
7213                })];
7214            } else if (params.free) {
7215                totalValue = [BX.create('SPAN', {
7216                    props: {className: 'bx-soa-price-free'},
7217                    html: value
7218                })];
7219            } else {
7220                totalValue = [value];
7221            }
7222
7223            if (params.total) {
7224                className += ' bx-soa-cart-total-line-total';
7225            }
7226
7227            if (params.highlighted) {
7228                className += ' bx-soa-cart-total-line-highlighted';
7229            }
7230
7231            return BX.create('DIV', {
7232                props: {className: className},
7233                children: [
7234                    BX.create('SPAN', {props: {className: 'bx-soa-cart-t'}, text: name}),
7235                    BX.create('SPAN', {
7236                        props: {
7237                            className: 'bx-soa-cart-d' + (!!params.total && this.options.totalPriceChanged ? ' bx-soa-changeCostSign' : '')
7238                        },
7239                        children: totalValue
7240                    })
7241                ]
7242            });
7243        },
7244
7245        basketBlockScrollCheckEvent: function (e) {
7246            var target = e.target || e.srcElement,
7247                scrollLeft = target.scrollLeft,
7248                scrollRight = target.scrollWidth - (scrollLeft + target.clientWidth),
7249                parent = target.parentNode;
7250
7251            if (scrollLeft == 0)
7252                BX.removeClass(parent, 'bx-soa-table-fade-left');
7253            else
7254                BX.addClass(parent, 'bx-soa-table-fade-left');
7255
7256            if (scrollRight == 0)
7257                BX.removeClass(parent, 'bx-soa-table-fade-right');
7258            else
7259                BX.addClass(parent, 'bx-soa-table-fade-right');
7260        },
7261
7262        basketBlockScrollCheck: function () {
7263            var scrollableNodes = this.orderBlockNode.querySelectorAll('div.bx-soa-table-fade'),
7264                parentNode, parentWidth, tableNode, tableWidth,
7265                i, scrollNode, scrollLeft, scrollRight, scrollable = false;
7266
7267            for (i = 0; i < scrollableNodes.length; i++) {
7268                parentNode = scrollableNodes[i];
7269                tableNode = parentNode.querySelector('div.bx-soa-item-table');
7270                parentWidth = parentNode.clientWidth;
7271                tableWidth = tableNode.clientWidth || 0;
7272                scrollable = scrollable || tableWidth > parentWidth;
7273
7274                if (scrollable) {
7275                    scrollNode = BX.firstChild(parentNode);
7276                    scrollLeft = scrollNode.scrollLeft;
7277                    scrollRight = scrollNode.scrollWidth - (scrollLeft + scrollNode.clientWidth);
7278
7279                    if (scrollLeft == 0)
7280                        BX.removeClass(parentNode, 'bx-soa-table-fade-left');
7281                    else
7282                        BX.addClass(parentNode, 'bx-soa-table-fade-left');
7283
7284                    if (scrollRight == 0)
7285                        BX.removeClass(parentNode, 'bx-soa-table-fade-right');
7286                    else
7287                        BX.addClass(parentNode, 'bx-soa-table-fade-right');
7288
7289                    if (scrollLeft == 0 && scrollRight == 0)
7290                        BX.addClass(parentNode, 'bx-soa-table-fade-right');
7291                } else
7292                    BX.removeClass(parentNode, 'bx-soa-table-fade-left bx-soa-table-fade-right');
7293            }
7294        },
7295
7296        totalBlockScrollCheck: function () {
7297            if (!this.totalInfoBlockNode || !this.totalGhostBlockNode)
7298                return;
7299
7300            var scrollTop = BX.GetWindowScrollPos().scrollTop,
7301                ghostTop = BX.pos(this.totalGhostBlockNode).top,
7302                ghostBottom = BX.pos(this.orderBlockNode).bottom,
7303                width;
7304
7305            if (ghostBottom - this.totalBlockNode.offsetHeight < scrollTop + 20)
7306                BX.addClass(this.totalInfoBlockNode, 'bx-soa-cart-total-bottom');
7307            else
7308                BX.removeClass(this.totalInfoBlockNode, 'bx-soa-cart-total-bottom');
7309
7310            if (scrollTop > ghostTop && !BX.hasClass(this.totalInfoBlockNode, 'bx-soa-cart-total-fixed')) {
7311                width = this.totalInfoBlockNode.offsetWidth;
7312                BX.addClass(this.totalInfoBlockNode, 'bx-soa-cart-total-fixed');
7313                this.totalGhostBlockNode.style.paddingTop = this.totalInfoBlockNode.offsetHeight + 'px';
7314                this.totalInfoBlockNode.style.width = width + 'px';
7315            } else if (scrollTop < ghostTop && BX.hasClass(this.totalInfoBlockNode, 'bx-soa-cart-total-fixed')) {
7316                BX.removeClass(this.totalInfoBlockNode, 'bx-soa-cart-total-fixed');
7317                this.totalGhostBlockNode.style.paddingTop = 0;
7318                this.totalInfoBlockNode.style.width = '';
7319            }
7320        },
7321
7322        totalBlockResizeCheck: function () {
7323            if (!this.totalInfoBlockNode || !this.totalGhostBlockNode)
7324                return;
7325
7326            if (BX.hasClass(this.totalInfoBlockNode, 'bx-soa-cart-total-fixed'))
7327                this.totalInfoBlockNode.style.width = this.totalGhostBlockNode.offsetWidth + 'px';
7328        },
7329
7330        totalBlockFixFont: function () {
7331            var totalNode = this.totalInfoBlockNode.querySelector('.bx-soa-cart-total-line.bx-soa-cart-total-line-total'),
7332                buttonNode, target, objList = [];
7333
7334            if (totalNode) {
7335                target = BX.lastChild(totalNode);
7336                objList.push({
7337                    node: target,
7338                    maxFontSize: 28,
7339                    smallestValue: false,
7340                    scaleBy: target.parentNode
7341                });
7342            }
7343
7344            if (objList.length)
7345                BX.FixFontSize.init({objList: objList, onAdaptiveResize: true});
7346        },
7347
7348        setAnalyticsDataLayer: function (action, id) {
7349            if (!this.params.DATA_LAYER_NAME)
7350                return;
7351
7352            var info, i;
7353            var products = [],
7354                dataVariant, item;
7355
7356            for (i in this.result.GRID.ROWS) {
7357                if (this.result.GRID.ROWS.hasOwnProperty(i)) {
7358                    item = this.result.GRID.ROWS[i];
7359                    dataVariant = [];
7360
7361                    for (i = 0; i < item.data.PROPS.length; i++) {
7362                        dataVariant.push(item.data.PROPS[i].VALUE);
7363                    }
7364
7365                    products.push({
7366                        'id': item.data.PRODUCT_ID,
7367                        'name': item.data.NAME,
7368                        'price': item.data.PRICE,
7369                        'brand': (item.data[this.params.BRAND_PROPERTY + '_VALUE'] || '').split(', ').join('/'),
7370                        'variant': dataVariant.join('/'),
7371                        'quantity': item.data.QUANTITY
7372                    });
7373                }
7374            }
7375
7376            switch (action) {
7377                case 'checkout':
7378                    info = {
7379                        'event': 'checkout',
7380                        'ecommerce': {
7381                            'checkout': {
7382                                'products': products
7383                            }
7384                        }
7385                    };
7386                    break;
7387                case 'purchase':
7388                    info = {
7389                        'event': 'purchase',
7390                        'ecommerce': {
7391                            'purchase': {
7392                                'actionField': {
7393                                    'id': id,
7394                                    'revenue': this.result.TOTAL.ORDER_TOTAL_PRICE,
7395                                    'tax': this.result.TOTAL.TAX_PRICE,
7396                                    'shipping': this.result.TOTAL.DELIVERY_PRICE
7397                                },
7398                                'products': products
7399                            }
7400                        }
7401                    };
7402                    break;
7403            }
7404
7405            window[this.params.DATA_LAYER_NAME] = window[this.params.DATA_LAYER_NAME] || [];
7406            window[this.params.DATA_LAYER_NAME].push(info);
7407        },
7408
7409        isOrderSaveAllowed: function () {
7410            return this.orderSaveAllowed === true;
7411        },
7412
7413        allowOrderSave: function () {
7414            this.orderSaveAllowed = true;
7415        },
7416
7417        disallowOrderSave: function () {
7418            this.orderSaveAllowed = false;
7419        },
7420
7421        initUserConsent: function () {
7422            BX.ready(BX.delegate(function () {
7423                var control = BX.UserConsent && BX.UserConsent.load(this.orderBlockNode);
7424                if (control) {
7425                    BX.addCustomEvent(control, BX.UserConsent.events.save, BX.proxy(this.doSaveAction, this));
7426                    BX.addCustomEvent(control, BX.UserConsent.events.refused, BX.proxy(this.disallowOrderSave, this));
7427                }
7428            }, this));
7429        },
7430
7431        buyOneClickFormHide: function () {
7432            $(".bx-soa-cart-total-data").addClass("animate__fadeInBlock").show();
7433            $(".bx-soa-cart-total-form").removeClass("animate__fadeInBlock").hide();
7434        },
7435
7436        buyOneClickFormShow: function () {
7437            $(".bx-soa-cart-total-data").removeClass("animate__fadeInBlock").hide();
7438            $(".bx-soa-cart-total-form").addClass("animate__fadeInBlock").show();
7439        },
7440
7441        buyOneClickFormSend: function (btn) {
7442            var oneClickForm = $(btn).closest(".bx-soa-cart-total-form");
7443            var msgBox = oneClickForm.find(".bx-soa-cart-total-form-message-box");
7444            var requiredInputs = oneClickForm.find(":required");
7445            var _this = this;
7446
7447            var isValidForm = true;
7448
7449            requiredInputs.each(function () {
7450                if ($(this).val().length < 2) {
7451                    $(this).addClass("error");
7452                    isValidForm = false;
7453                } else {
7454                    if ($(this).is(".error")) {
7455                        $(this).removeClass("error");
7456                    }
7457                }
7458            });
7459
7460            var fields = {
7461                "full_name": oneClickForm.find("[name='full_name']").val(),
7462                "phone": oneClickForm.find("[name='phone']").val(),
7463                "email": oneClickForm.find("[name='email']").val(),
7464                "sessid": BX.bitrix_sessid()
7465            };
7466
7467            var comment = oneClickForm.find("[name='comment']");
7468            var captcha_code = oneClickForm.find("[name='captcha_code']");
7469            var captcha_word = oneClickForm.find("[name='captcha_word']");
7470
7471            if (comment.length > 0) {
7472                fields["comment"] = comment.val();
7473            }
7474
7475            if (captcha_code.length > 0) {
7476                fields["captcha_code"] = captcha_code.val();
7477                fields["captcha_word"] = captcha_word.val();
7478            }
7479
7480            if (isValidForm) {
7481                this.startLoader();
7482
7483                $.post(
7484                    this.templateFolder + "/ajax/one_click_order_ajax.php",
7485                    fields,
7486                    function (result) {
7487                        if (result.success) {
7488                            window.location.href = _this.params.CURRENT_PAGE + "?ORDER_ID=" + result.data.ORDER_ID;
7489                        } else {
7490                            msgBox.addClass("error").html("");
7491
7492                            if (result.errors.length < 1) {
7493                                result.errors.push(_this.params.MESS_TOTAL_BLOCK_BUY_ONE_CLICK_FORM_UNKNOWN_ERROR);
7494                            }
7495
7496                            result.errors.forEach(function (item) {
7497                                msgBox.append("<p>" + item + "</p>");
7498                            });
7499                        }
7500
7501                        setTimeout(function () {
7502                            BX.Sale.OrderAjaxComponent.endLoader();
7503                        }, 400);
7504                    },
7505                    "json"
7506                );
7507            }
7508        },
7509
7510        autoLoadLegalDataByINN: function (btn) {
7511            if (
7512                this.params.USE_LEGAL_ENTITY_AUTOLOAD_DATA == "Y" &&
7513                this.params.AUTOLOAD_LEGAL_INN.length > 0
7514            ) {
7515                var inn = document.querySelector(
7516                    ".tanais-order #soa-property-" +
7517                    this.getOrderPropertyIdByCode(this.params.AUTOLOAD_LEGAL_INN)
7518                );
7519
7520                if (inn !== null && inn.value.length > 0) {
7521                    this.startLoader();
7522
7523                    $.post(
7524                        this.templateFolder + "/ajax/get_data_for_legal_inn_ajax.php",
7525                        {
7526                            "inn": inn.value,
7527                            "sessid": BX.bitrix_sessid()
7528                        },
7529                        function (result) {
7530                            var orderAjaxComponent = BX.Sale.OrderAjaxComponent;
7531
7532                            var kpp = document.querySelector(
7533                                ".tanais-order #soa-property-" +
7534                                orderAjaxComponent.getOrderPropertyIdByCode(
7535                                    orderAjaxComponent.params.AUTOLOAD_LEGAL_KPP
7536                                )
7537                            );
7538
7539                            var companyAddr = document.querySelector(
7540                                ".tanais-order #soa-property-" +
7541                                orderAjaxComponent.getOrderPropertyIdByCode(
7542                                    orderAjaxComponent.params.AUTOLOAD_LEGAL_COMPANY_ADDR
7543                                )
7544                            );
7545
7546                            var company = document.querySelector(
7547                                ".tanais-order #soa-property-" +
7548                                orderAjaxComponent.getOrderPropertyIdByCode(
7549                                    orderAjaxComponent.params.AUTOLOAD_LEGAL_COMPANY
7550                                )
7551                            );
7552
7553                            if (result.success) {
7554                                var resultData = result.data;
7555
7556                                if (kpp !== null && (typeof resultData.data.kpp !== "undefined")) {
7557                                    kpp.value = resultData.data.kpp;
7558                                }
7559
7560                                if (companyAddr !== null && (typeof resultData.data.address.value !== "undefined")) {
7561                                    companyAddr.value = resultData.data.address.value;
7562                                }
7563
7564                                if (company !== null && (typeof resultData.value !== "undefined")) {
7565                                    company.value = resultData.value;
7566                                }
7567                            } else {
7568                                if (kpp !== null) kpp.value = "";
7569                                if (companyAddr !== null) companyAddr.value = "";
7570                                if (company !== null) company.value = "";
7571
7572                                console.log(result.errors);
7573                            }
7574
7575                            setTimeout(function () {
7576                                orderAjaxComponent.endLoader();
7577                            }, 400);
7578                        },
7579                        "json"
7580                    );
7581                }
7582
7583            }
7584        },
7585
7586        autocompleteCompany: function () {
7587            var _this = this;
7588            var inputValue = _this.value;
7589            var orderComponent = BX.Sale.OrderAjaxComponent;
7590
7591            if (inputValue.trim().length > 1) {
7592                $.post(
7593                    orderComponent.templateFolder + "/ajax/get_data_for_suggest_ajax.php",
7594                    {
7595                        "company_name": inputValue,
7596                        "sessid": BX.bitrix_sessid()
7597                    },
7598                    function (result) {
7599                        if (result.success) {
7600                            var items = result.data.map(function (item) {
7601                                return $('<span>')
7602                                    .text(item.value)
7603                                    .attr('data-inn', item.data.inn);
7604                            });
7605
7606                            $(_this).next(".soa-suggests-company-container")
7607                                .fadeIn()
7608                                .find(".soa-suggests-company-block")
7609                                .empty()
7610                                .append(items)
7611                                .find("span")
7612                                .on("click", function () {
7613                                    var selected = $(this);
7614                                    var inn = selected.attr('data-inn');
7615
7616                                    var innField = document.querySelector(
7617                                        ".tanais-order #soa-property-" +
7618                                        orderComponent.getOrderPropertyIdByCode(
7619                                            orderComponent.params.AUTOLOAD_LEGAL_INN
7620                                        )
7621                                    );
7622
7623                                    if (innField) {
7624                                        innField.value = inn;
7625                                        orderComponent.autoLoadLegalDataByINN();
7626                                    }
7627
7628                                    $(this).closest(".soa-suggests-company-block").html("");
7629                                    $(this).closest(".soa-suggests-company-container").fadeOut();
7630                                });
7631                        } else {
7632                            console.log(result.errors);
7633                        }
7634                    },
7635                    "json"
7636                );
7637            }
7638        },
7639
7640        autocompleteAddr: function () {
7641            var _this = this;
7642            var inputValue = _this.value;
7643            var numericValue = inputValue.replace(/\D/g, ''); // Оставляем только цифры
7644
7645            // Проверяем, находится ли поле внутри контейнера ИНН
7646            var isINNField = $(_this).closest('.has-soa-action-button').length > 0;
7647
7648            if (isINNField) {
7649                // Для поля ИНН: проверяем ровно 10 цифр
7650                if (numericValue.length === 10) {
7651                    // Находим кнопку и триггерим клик
7652                    var $button = $(_this).closest('.has-soa-action-button').find('.js-inn-autoload-btn');
7653                    if ($button.length) {
7654                        $button.trigger('click'); // Триггерим событие click
7655                    } else {
7656                        console.error('Кнопка для автозагрузки ИНН не найдена');
7657                    }
7658                }
7659            } else {
7660                // Для адреса: оригинальная логика (длина > 1)
7661                if (inputValue.trim().length > 1) {
7662                    $.post(
7663                        BX.Sale.OrderAjaxComponent.templateFolder + "/ajax/get_addr_suggest.php",
7664                        {
7665                            "addr": inputValue,
7666                            "sessid": BX.bitrix_sessid()
7667                        },
7668                        function (result) {
7669                            if (result.success) {
7670                                var items = result.data.map(function (item) {
7671                                    return "<span>" + item.value + "</span>";
7672                                });
7673                                $(_this).next(".soa-suggests-container")
7674                                    .fadeIn()
7675                                    .find(".soa-suggests-block")
7676                                    .html(items.join(""))
7677                                    .find("span")
7678                                    .on("click", function () {
7679                                        _this.value = $(this).text();
7680                                        $(this).closest(".soa-suggests-block").html("");
7681                                        $(this).closest(".soa-suggests-container").fadeOut();
7682                                    });
7683                            } else {
7684                                console.log(result.errors);
7685                            }
7686                        },
7687                        "json"
7688                    );
7689                }
7690            }
7691        },
7692
7693        getOrderPropertyIdByCode: function (code) {
7694            for (var i = 0; i < this.result.ORDER_PROP.properties.length; i++) {
7695                if (this.result.ORDER_PROP.properties[i]["CODE"] == code) {
7696                    return this.result.ORDER_PROP.properties[i]["ID"];
7697                }
7698            }
7699
7700            return 0;
7701        }
7702    };
7703})();
7704
7705$(function () {
7706
7707    if (typeof BX.Sale.OrderAjaxComponent.params !== "undefined") {
7708        $(".tanais-order .bx-soa-cart-total-form [autocomplete='tel']").mask(
7709            BX.Sale.OrderAjaxComponent.params.PHONE_INPUT_MASK
7710        );
7711    }
7712
7713    // Находим статический родительский элемент (например, контейнер корзин
7713ы)
7714    var cartContainer = document.querySelector('#bx-soa-properties'); // Укажите правильный селектор
7715
7716    if (cartContainer) {
7717        // Делегирование события input для поля ИНН
7718        cartContainer.addEventListener('input', function (event) {
7719            var target = event.target;
7720            if (target.matches('.has-soa-action-button input[type="text"]')) {
7721                var inputValue = target.value.replace(/\D/g, ''); // Оставляем только цифры
7722                if (inputValue.length === 10) {
7723                    var button = target.closest('.has-soa-action-button').querySelector('.js-inn-autoload-btn');
7724                    if (button) {
7725                        button.click(); // Триггерим клик по кнопке
7726                    }
7727                }
7728            }
7729        });
7730
7731        // Делегирование события click для кнопки
7732        cartContainer.addEventListener('click', function (event) {
7733            var target = event.target;
7734            if (target.matches('.js-inn-autoload-btn')) {
7735                autoLoadLegalDataByINN.call(target);
7736            }
7737        });
7738    }
7739});

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.