PageSourceSearch

https://kutahyaporselen.com/theme/v5/js/general.js?v=1790853806

js kutahyaporselen.com collected 2026-10-01 12:37:10 UTC 272,409 bytes, 7,042 lines download raw bytes

1/**
2 * serviceWorker
3
4if ('serviceWorker' in navigator) {
5    window.addEventListener('load', () => {
6        navigator.serviceWorker.register('/sw.js').then(res => {}, err => {});
7    });
8}
9
10/**
11 * pwa
12
13const Pwa = () => {
14    if (localStorage.getItem('install-pwa') == 'true') return;
15
16    let event, pwa, install, close;
17
18    const remove = item => {
19        item.remove();
20        localStorage.setItem('install-pwa', true);
21    };
22
23    const created = () => {
24        pwa = document.createElement('div');
25        pwa.id = 'pwa-install-popup';
26        pwa.innerHTML = `
27        <div class="pwa-inner p-1 bg-white border-round">
28            <div class="pwa-title">Uygulamayı Yükle</div>
29            <div class="d-flex align-items-center">
30                <div class="pwa-icon mr-1">
31                    <img src="/theme/v5/images/pwa/48x48.png">
32                </div>
33                <div class="pwa-text">
34                    <div>T-Soft</div>
35                    <span>mangox.1ticaret.com</span>
36                </div>
37            </div>
38            <div class="pwa-buttons">
39                <button class="btn btn-primary mr-1" id="pwa-install">Yükle</button>
40                <button class="btn btn-light" id="pwa-close">İptal</button>
41            </div>
42        </div>`;
43        document.body.append(pwa);
44
45        install = pwa.querySelector('#pwa-install');
46        close = pwa.querySelector('#pwa-close');
47
48        install.addEventListener("click", () => {
49            event.prompt();
50            event.userChoice.then( result => {
51                result.outcome === 'accepted' ? pwa.remove() : remove(pwa);
52            });
53        });
54
55        close.addEventListener("click", () => {
56            remove(pwa);
57        });
58    };
59
60    window.addEventListener("beforeinstallprompt", e => {
61        e.preventDefault();
62        event = e;
63        if (localStorage.getItem('install-pwa') != 'true') created();
64    });
65};
66
67/**
68 * Flatpickr localize
69 */
70var appendContent, autoCart, diff, elementHeight, elementOffsetTop, menu, windowHeight;
71window.flatpickr.localize({
72    weekdays: {
73        shorthand: [TLANG.sun || "Paz", TLANG.mon || "Pzt", TLANG.tues || "Sal", TLANG.wed || "Çar", TLANG.thurs || "Per", TLANG.fri || "Cum", TLANG.sat || "Cmt"],
74        longhand: [TLANG.sunday || "Pazar", TLANG.monday || "Pazartesi", TLANG.tuesday || "Salı", TLANG.wednesday || "Çarşamba", TLANG.thursday || "Perşembe", TLANG.friday || "Cuma", TLANG.saturday || "Cumartesi"],
75    },
76    months: {
77        shorthand: [TLANG.jan || "Oca", TLANG.feb || "Şub", TLANG.mar || "Mar", TLANG.apr || "Nis", TLANG.may || "May", TLANG.jun || "Haz", TLANG.jul || "Tem", TLANG.aug || "Ağu", TLANG.sep || "Eyl", TLANG.oct || "Eki", TLANG.nov || "Kas", TLANG.dec || "Ara" ],
78        longhand: [
79            TLANG.january || "Ocak", TLANG.february || "Şubat", TLANG.march || "Mart", TLANG.april || "Nisan", TLANG.may || "Mayıs", TLANG.june || "Haziran", TLANG.july || "Temmuz", TLANG.august || "Ağustos", TLANG.september || "Eylül", TLANG.october || "Ekim",  TLANG.november || "Kasım", TLANG.december || "Aralık"],
80    },
81    firstDayOfWeek: 1,
82    ordinal: () => ".",
83    rangeSeparator: " - ",
84    weekAbbreviation: TLANG.wk || "Hf",
85    scrollTitle: TLANG.swipe_to_increase || "Artırmak için kaydırın",
86    toggleTitle: TLANG.on_off || "Aç/Kapa",
87    amPM: [TLANG.am || "ÖÖ", TLANG.pm || "ÖS"],
88    time_24hr: true,
89});
90
91/*
92  TSOFT JavaScript Library v1
93  https://tsoft.com.tr/
94*/
95const fn = {},
96      doc = document ? document : window.document,
97      indexOf = [].indexOf,
98      toString = {}.toString,
99      hasOwn = {}.hasOwnProperty,
100      fnToString = hasOwn.toString;
101
102const mouseClickEvents = { down: 'mousedown', up: 'mouseup' };
103const mouseHoverEvents = ('onmouseleave' in document) ? [ 'mouseenter', 'mouseleave'] : [ 'mouseover', 'mouseout' ];
104
105const isFunction = function isFunction(obj) {
106    return typeof obj === "function" && typeof obj.nodeType !== "number";
107};
108
109const isWindow = function isWindow(obj) {
110    return obj != null && obj === obj.window;
111};
112
113const getUrlParam = function(key = '', url = document.location) {
114    if (key == '') return;
115    url = new URL(url);
116    const params = url.searchParams;
117    return params.get(key);
118}
119
120const setUrlParam = function(key = '', value = '' , url = document.location) {
121    if (key == '') return;
122    url = new URL(url);
123    const params = url.searchParams;
124    params.set(key, value);
125    return url;
126}
127
128const deleteUrlParam = function(key = '', url = document.location) {
129    if (key == '') return;
130    url = new URL(url);
131    const params = url.searchParams;
132    params.delete(key);
133    return url;
134}
135
136const LocalApi = {
137    get: (key, def = false) => {
138        try {
139            const obj = JSON.parse(localStorage.getItem(key));
140            let now = new Date().getTime();
141            if(Number.isNaN(obj.timeout) || obj.timeout < 1000000000) {
142                obj.timeout = 1000000000;
143            } else if (obj.timeout < 9000000000) {
144                obj.timeout = obj.timeout * 1000;
145            }
146            if (obj.timeout && obj.timeout < now) {
147                return def;
148            }
149            return typeof obj.value !== 'undefined' ? obj.value : def;
150        } catch (ex) {
151            return def;
152        }
153    },
154    set: (key, val, timeout) => {
155        if(key === 'v5token') {
156            try {
157                timeout = Number.parseInt(timeout) > 0 ? timeout : 365 * 24 * 3600;
158                let obj = { value: val, timeout: timeout * 1000};
159                localStorage.setItem(key, JSON.stringify(obj));
160                return true;
161            } catch (ex) {
162                return false;
163            }
164        } else {
165            try {
166                timeout = Number.parseInt(timeout) > 0 ? timeout : 365 * 24 * 3600;
167                let obj = { value: val, timeout: new Date().getTime() + (1000 * timeout) };
168                localStorage.setItem(key, JSON.stringify(obj));
169                return true;
170            } catch (ex) {
171                return false;
172            }
173        }
174
175    },
176    remove: key => {
177        try {
178            localStorage.removeItem(key);
179            return true;
180        } catch (ex) {
181            return false;
182        }
183    }
184};
185
186/**
187 * Axios setting localize
188 */
189
190axios.defaults.headers.common['Accept-Language'] = LANGUAGE || 'tr';
191axios.interceptors.request.use(
192    async (config) => {
193        const token = bearerToken();
194        if (token) config.headers.Authorization = `Bearer ${token}`;
195        return config;
196    },
197    (error) => {
198        return Promise.reject(error);
199    }
200);
201axios.interceptors.response.use(
202    response => response,
203    error => {
204        const errorResponse = error.response;
205        if (!errorResponse) return;
206
207        const errorStatus = errorResponse.status || '';
208        const errorCode = errorResponse.data?.errorCode || '';
209        const errorUrl = errorResponse.config?.url || '';
210        const errorMessage = errorResponse.data?.message || '';
211
212        if(([403].includes(errorStatus) || [401].includes(errorCode)) && !errorResponse.data?.data[0]?.password_change) {
213            if (errorUrl.indexOf(getEndpoint('LOGIN')) > -1) {
214                T.notify({
215                    text: errorMessage,
216                    className: 'danger',
217                    duration: 5000,
218                    stopOnFocus: true
219                });
220                return;
221            }
222        }
223        return Promise.reject(errorResponse);
224    }
225);
226
227const tokenPadeId = document.getElementById('link_table_id').value;
228const bearerToken = function(){
229    const tokenExpControl = JSON.parse(localStorage.getItem('v5token'));
230    if (!tokenExpControl) return;
231
232    if(tokenExpControl.timeout && (Number.isNaN(tokenExpControl.timeout) || tokenExpControl.timeout < 1000000000)) {
233        tokenExpControl.timeout = 1000000000;
234    } else if (tokenExpControl.timeout < 9000000000) {
235        tokenExpControl.timeout = tokenExpControl.timeout * 1000;
236    }
237    axios.defaults.headers.common['Authorization'] = `Bearer ${tokenExpControl.value}`;
238    if(((Math.floor(tokenExpControl.timeout - new Date().getTime())/1000)/60) < 10) {
239        fetch(getEndpoint('LOGIN'), {
240            method: 'POST',
241            cache: 'no-cache',
242            headers: {
243                'Content-Type': 'application/json',
244                'Authorization': `Bearer ${tokenExpControl.value}`
245            },
246            referrerPolicy: 'no-referrer',
247            body: JSON.stringify({
248                refresh: 1
249            })
250        }).then(response => {return response.json(); }).then(result => {
251            let obj = { value: result.data[0].bearer, timeout: result.data[0].exp_at };
252            LocalApi.remove('v5token');
253            localStorage.setItem('v5token', JSON.stringify(obj));
254        }).catch((e) => {
255            if(e.status === 403 || e.status === 401 || e.status === 500) {
256                axios.get('/srv/service/customer/logout').then(() => {
257                    LocalApi.remove('v5token');
258                    window.location.href = '/';
259                });
260            }
261        });
262    }
263    return tokenExpControl.value;
264};
265
266if (LocalApi.get('v5token') !== false) {
267    if (MEMBER_INFO.ID == 0) {
268        if (tokenPadeId == '91') bearerToken();
269    } else {
270        bearerToken();
271    }
272}
273
274const LoginPageTracking = {
275    Callback: {},
276    callbackArray: []
277};
278const SignPageTracking = {
279    Callback: () => {}
280};
281const QuickViewObj = {
282    callback: {
283    open: []
284    }
285};
286
287const scrollBehavior = function(href = null, height) {
288    const top = height != null && typeof height == 'number' ? height : 0;
289    const element = typeof href == 'object' && href != null ? href : (href != null ? document.querySelector(href) : null);
290    if (element == null) return;
291
292    let elementRect = element.getBoundingClientRect();
293    let bodyRect = document.body.getBoundingClientRect();
294
295    let topRelativeToBody = elementRect.top - bodyRect.top - top;
296
297    scroll({
298        top: topRelativeToBody,
299        behavior: "smooth"
300    });
301}
302
303const scrollToElm = function(el, height = null) {
304    T(el).trigger('click');
305    scrollBehavior(el, height);
306}
307
308let googleTokenClient;
309
310let multiCart = false,
311    multiCartItem = null;
312
313function toType(obj) {
314    let class2type = {};
315
316    if (obj == null) {
317        return obj + "";
318    }
319
320    return typeof obj === "object" || typeof obj === "function" ?
321        class2type[toString.call(obj)] || "object" :
322        typeof obj;
323}
324
325function isArrayLike(obj) {
326    let length = !!obj && "length" in obj && obj.length,
327        type = toType(obj);
328
329    if (isFunction(obj) || isWindow(obj)) {
330        return false;
331    }
332
333    return type === "array" || length === 0 ||
334        typeof length === "number" && length > 0 && (length - 1) in obj;
335}
336
337function transitionCtrl(element, handler) {
338    const transitionEndEvent = 'webkitTransition' in document.body.style ? 'webkitTransitionEnd' : 'transitionend',
339        supportTransition = 'webkitTransition' in document.body.style || 'transition' in document.body.style,
340        transitionDuration = 'webkitTransition' in document.body.style ? 'webkitTransitionDuration' : 'transitionDuration';
341
342    function getDuration(element) {
343        let duration = supportTransition ? window.getComputedStyle(element)[transitionDuration] : 0;
344        duration = Number.parseFloat(duration);
345        duration = typeof duration === 'number' && !Number.isNaN(Number(duration)) ? duration * 1000 : 0;
346        return duration;
347    }
348
349    let called = 0,
350        duration = getDuration(element);
351
352    duration ? T(element).one(transitionEndEvent, function(e) {!called && handler(e), called = 1; }) :
353        setTimeout(function() {!called && handler(), called = 1; }, 17);
354}
355
356function evalScripts(content) {
357    content = content.replaceAll(/\s+/g, ' ');
358    let startRegex = "<\s*script.*?>";
359    let finishRegex = "<\s*\/\s*script\s*>";
360    let mainRegex = new RegExp(startRegex + ".*?" + finishRegex, "ig");
361    let res = content.match(mainRegex) || [];
362
363    let i=0;
364    let myscript = '';
365    let callbackArr = [];
366
367    for(i=0;i<res.length; i++){
368        myscript = res[i].replace(new RegExp(startRegex, "ig"), "").replace(new RegExp(finishRegex, "ig"), "");
369        callbackArr.push(myscript);
370    }
371
372    for(i=0;i<callbackArr.length; i++){
373        try{
374            eval(callbackArr[i]);
375        }catch(ex){
376            console.log(ex);
377        }
378    };
379}
380
381function evalScriptsAppend(content, id) {
382    content = content.replaceAll(/\s+/g, ' ');
383    let startRegex = "<\s*script.*?>";
384    let finishRegex = "<\s*\/\s*script\s*>";
385    let mainRegex = new RegExp(startRegex + ".*?" + finishRegex, "ig");
386    let res = content.match(mainRegex) || [];
387
388    for (let i=0; i<res.length; i++) {
389        if (T(`#${id}-${i}`).length > 0) T(`#${id}-${i}`)[0].remove();
390        try{
391            const parser = new DOMParser();
392            const doc = parser.parseFromString(res[i], 'text/html');
393            const src = doc.querySelector('script').getAttribute('src');
394
395            const script = document.createElement('script');
396            script.id = `${id}-${i}`;
397            if (src != undefined) script.src = src;
398            script.innerHTML = doc.querySelector('script').innerHTML || '';
399            document.body.appendChild(script);
400        }catch(ex){
401            console.log(ex);
402        }
403    }
404    if (res.length > 0) return true;
405};
406
407function addToCompare(element = null, pageId = '', parentId = '') {
408    if (element == null) return;
409
410    const productId = element.dataset.id;
411    if (!productId) return;
412
413    let status;
414    const localCompare = LocalApi.get('compareProducts') || [];
415    const isActive = Array.from(localCompare).find(x => x == productId) || false;
416
417    if (!isActive && localCompare.length == 4) {
418        status = 3;
419    } else {
420        if (isActive) {
421            status = 2;
422        } else {
423            localCompare.push(productId);
424            LocalApi.set('compareProducts', localCompare);
425            T(`.add-to-compare-btn[data-id="${productId}"]`).addClass('active');
426            status = 1;
427        }
428    }
429
430    loadSubFolder({
431        pageId: pageId || 2,
432        blockParentId: parentId || 1003,
433        subFolder: 'compare',
434        params: {
435            product: localCompare.join('-'),
436            status: status
437        },
438        success:  function(loadRes){
439            T.modal({
440                id: 'product-compare-list-popup',
441                width: '1170px',
442                html: loadRes,
443                close: true
444            });
445        }
446    });
447}
448
449function compareSelectedProducts(pageId = '', parentId = '') {
450    if (pageId == '' || parentId == '') 
451        return;
452
453    const elems = LocalApi.get('compareProducts') || [];
454    if (elems.length == 0 || elems.length == 1 || elems.length > 4) {
455        let message;
456
457        if (elems.length == 0) {
458            message = TLANG.no_comparison_products || 'Ürün seçimi yapılmadığı için karşılaştırılamamaktadır';
459        } else if (elems.length == 1) {
460            message = TLANG.least_compare_warning || 'Karşılaştırmak için en az 2 ürün seçmelisiniz';
461        } else if (elems.length > 4) {
462            message = TLANG.most_compare_warning || 'Karşılaştırmak için en fazla 4 ürün seçmelisiniz';
463        }
464
465        T.notify({
466            text: message,
467            className: 'danger product-compare-failed-notify',
468            duration: 1800,
469        });
470
471        return;
472    }
473
474    loadSubFolder({
475        pageId: pageId,
476        blockParentId: parentId,
477        subFolder: 'compare',
478        params: {
479            product: elems.join('-'),
480        },
481        success:  function(loadRes){
482            T.modal({
483                id: 'product-compare-list-popup',
484                width: '1170px',
485                html: loadRes,
486                close: true
487            });
488        }
489    });
490}
491
492function compareSet() {
493    const localCompare = LocalApi.get('compareProducts') || [];
494    if (localCompare.length == 0) return;
495
496    const compareBtns = T('.add-to-compare-btn');
497    if (compareBtns.length == 0) return;
498
499    Array.from(compareBtns).forEach(item => {
500        const id = item.dataset.id;
501        const isCompareId = Array.from(localCompare).find(x => x == id);
502        isCompareId ? T(item).addClass('active') : T(item).removeClass('active');
503    });
504}
505
506function TSOFT(arr) {
507    let self = this;
508    for (let i = 0; i < arr.length; i += 1) {
509        self[i] = arr[i];
510    }
511    self.length = arr.length;
512    return this;
513}
514
515function tInitFn(fn) {
516    try { fn(); } catch (e) {
517        console.error(((TLANG.function_not_found || "Fonksiyon bulunamadı: ") + ' ' + e));
518    }
519}
520
521fn.TSOFT = function(dom, selector) {
522    return new TSOFT(dom, selector);
523};
524
525fn.init = function(selector, context) {
526    let arr = [];
527    let i = 0;
528    if (selector && !context) {
529        if (selector instanceof TSOFT) {
530            return selector;
531        }
532    }
533    if (selector) {
534        if (typeof selector === 'string') {
535            let els;
536            let tempParent;
537            let html = selector.trim();
538            if (html.indexOf('<') >= 0 && html.indexOf('>') >= 0) {
539                let toCreate = 'div';
540                if (html.indexOf('<li') === 0) { toCreate = 'ul'; }
541                if (html.indexOf('<tr') === 0) { toCreate = 'tbody'; }
542                if (html.indexOf('<td') === 0 || html.indexOf('<th') === 0) { toCreate = 'tr'; }
543                if (html.indexOf('<tbody') === 0) { toCreate = 'table'; }
544                if (html.indexOf('<option') === 0) { toCreate = 'select'; }
545                tempParent = doc.createElement(toCreate);
546                tempParent.innerHTML = html;
547                for (i = 0; i < tempParent.childNodes.length; i += 1) {
548                    arr.push(tempParent.childNodes[i]);
549                }
550            } else {
551                if (!context && selector[0] === '#' && !selector.match(/[ .<>:~]/)) {
552                    els = [doc.getElementById(selector.trim().split('#')[1])];
553                } else {
554                    els = (context || doc).querySelectorAll(selector.trim());
555                }
556                for (i = 0; i < els.length; i += 1) {
557                    if (els[i]) { arr.push(els[i]); }
558                }
559            }
560        } else if (selector.nodeType || selector === window || selector === doc) {
561            arr.push(selector);
562        } else if (selector.length > 0 && selector[0].nodeType) {
563            for (i = 0; i < selector.length; i += 1) {
564                arr.push(selector[i]);
565            }
566        }
567    }
568    return new TSOFT(arr);
569};
570
571TSOFT.prototype = {
572    addClass: function(cls) {
573        cls = cls.split(' ');
574        for (let i = 0; i < this.length; i++) {
575            this[i].classList.add(...cls);
576        }
577    },
578    removeClass: function(cls) {
579        cls = cls.split(' ');
580        for (let i = 0; i < this.length; i++) {
581            this[i].classList.remove(...cls);
582        }
583    },
584    toggleClass: function(cls) {
585        cls = cls.split(' ');
586        for (let i = 0; i < this.length; i++) {
587            cls.map(c => {
588                this[i].classList.toggle(c);
589            });
590        }
591    },
592    hasClass: function(cls) {
593        return this[0].classList['contains'](cls);
594    },
595    index: function() {
596        return [...this[0].parentElement.children].indexOf(this[0]);
597    },
598    on: function(event, handler) {
599        for (let i = 0; i < this.length; i++) {
600            this[i].addEventListener(event, handler, false);
601        }
602    },
603    off: function(event, handler) {
604        for (let i = 0; i < this.length; i++) {
605            this[i].removeEventListener(event, handler, false);
606        }
607    },
608    one: function(event, handler = function(){}) {
609        for (let i = 0; i < this.length; i++) {
610            this[i].addEventListener(event, handler, {once: true});
611        }
612    },
613    trigger: function(value) {
614        for (let i = 0; i < this.length; i++) {
615            let event = '';
616            const el = this || data;
617
618            if(document.createEvent) {
619                event = document.createEvent("HTMLEvents");
620                event.initEvent(value, true, true);
621                event.eventName = value;
622                this[i].dispatchEvent(event, {'bubbles': true});
623            } else {
624                event = document.createEventObject();
625                event.eventName = value;
626                event.eventType = value;
627                this[i].fireEvent("on" + event.eventType, event);
628            }
629        }
630    },
631    html: function(value = null) {
632        if (value == null) {
633            return this[0].innerHTML;
634        }
635        for (let i = 0; i < this.length; i++) {
636            this[i].innerHTML = value;
637        }
638    },
639    text: function(value = null) {
640        if (value == null) {
641            return this[0].innerText;
642        }
643        for (let i = 0; i < this.length; i++) {
644            this[i].textContent = value;
645        }
646    },
647    height: function(value = '') {
648        if (!value) {
649            const all = [];
650            for (let i = 0; i < this.length; i++) {
651                all.push(this[i].clientHeight);
652            }
653            return all;
654        } else {
655            for (let i = 0; i < this.length; i++) {
656                this[i].style.height = Number.parseInt(value) > 0 ? `${value}px` : value;
657            }
658        }
659    },
660    show: function(display = null) {
661        for (let i = 0; i < this.length; i++) {
662            if (display != null) {
663                this[i].style.display = display;
664            } else {
665                this[i].style.display = 'block';
666            }
667        }
668    },
669    hide: function() {
670        for (let i = 0; i < this.length; i++) {
671            this[i].style.display = 'none';
672        }
673    },
674    attr: function(name, value = null) {
675        if (value == null) {
676            return this[0].getAttribute(name);
677        }
678        if (name && value) {
679            for (let i = 0; i < this.length; i++) {
680                this[i].setAttribute(name, value);
681            }
682        }
683    }
684};
685
686const T = function(sel, ctx) {
687    return fn.init(sel, ctx);
688};
689
690T.extend = function() {
691    let options, name, src, copy, copyIsArray, clone,
692        target = arguments[0] || {},
693        i = 1,
694        length = arguments.length,
695        deep = false;
696
697    if (typeof target === "boolean") {
698        deep = target;
699        target = arguments[i] || {};
700        i++;
701    }
702
703    if (typeof target !== "object" && !isFunction(target)) {
704        target = {};
705    }
706
707    if (i === length) {
708        target = this;
709        i--;
710    }
711
712    for (; i < length; i++) {
713        if ((options = arguments[i]) != null) {
714            for (name in options) {
715                copy = options[name];
716                if (name === "__proto__" || target === copy) {
717                    continue;
718                }
719
720                if (deep && copy && (T.isPlainObject(copy) ||
721                        (copyIsArray = Array.isArray(copy)))) {
722                    src = target[name];
723
724                    if (copyIsArray && !Array.isArray(src)) {
725                        clone = [];
726                    } else if (!copyIsArray && !T.isPlainObject(src)) {
727                        clone = {};
728                    } else {
729                        clone = src;
730                    }
731
732                    copyIsArray = false;
733                    target[name] = T.extend(deep, clone, copy);
734                } else if (copy !== undefined) {
735                    target[name] = copy;
736                }
737            }
738        }
739    }
740
741    return target;
742};
743
744T.extend({
745    ready: (callback) => {
746        /* dom loaded */
747        if (doc.readyState != 'loading') {
748            callback();
749        }
750        /* modern browsers */
751        else if (doc.addEventListener) {
752            doc.addEventListener('DOMContentLoaded', callback);
753        }
754        /* IE <= 8 */
755        else {
756            doc.attachEvent('onreadystatechange', function() {
757                if (doc.readyState == 'complete')
758                    callback();
759            });
760        }
761    },
762    isPlainObject: function(obj) {
763        let proto, Ctor;
764        if (!obj || toString.call(obj) !== "[object Object]") {
765            return false;
766        }
767
768        proto = getProto(obj);
769
770        if (!proto) {
771            return true;
772        }
773
774        Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
775        return typeof Ctor === "function" && fnToString.call(Ctor) === ObjectFunctionString;
776    },
777    isEmptyObject: function(obj) {
778        let name;
779
780        for (name in obj) {
781            return false;
782        }
783        return true;
784    },
785    each: function(obj, callback) {
786        let length, i = 0;
787
788        if (isArrayLike(obj)) {
789            length = obj.length;
790            for (; i < length; i++) {
791                if (callback.call(obj[i], i, obj[i]) === false) {
792                    break;
793                }
794            }
795        } else {
796            for (i in obj) {
797                if (callback.call(obj[i], i, obj[i]) === false) {
798                    break;
799                }
800            }
801        }
802
803        return obj;
804    },
805    inArray: function(elem, arr, i) {
806        return arr == null ? -1 : indexOf.call(arr, elem, i);
807    },
808    wrap: function(toWrap, wrapper, className = '') {
809        wrapper = wrapper || document.createElement('div');
810
811        if (className != '')
812            wrapper.classList.add(className);
813
814        toWrap.parentNode.insertBefore(wrapper, toWrap);
815        return wrapper.appendChild(toWrap);
816    },
817    setCookie: function(cookieName, cookieValue, exdays) {
818        let d = new Date();
819        d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
820        let expires = 'expires=' + d.toUTCString();
821        document.cookie = cookieName + '=' + cookieValue + ';' + expires + ';path=/';
822    },
823    getCookie: function(cookieName) {
824        let name = cookieName + '=';
825        let decodedCookie = decodeURIComponent(document.cookie);
826        let ca = decodedCookie.split(';');
827        for (let i = 0; i < ca.length; i++) {
828            let c = ca[i];
829            while (c.charAt(0) == ' ') {
830                c = c.substring(1);
831            }
832            if (c.indexOf(name) == 0) {
833                return c.substring(name.length, c.length);
834            }
835        }
836        return '';
837    },
838    browser: function() {
839        const brwoser = navigator.userAgent;
840        if (brwoser.indexOf('Firefox') > -1) {
841            return 'Mozilla Firefox';
842        } else if (brwoser.indexOf('Opera') > -1 || brwoser.indexOf('OPR') > -1) {
843            return 'Opera';
844        } else if (brwoser.indexOf('Trident') > -1) {
845            return 'Microsoft Internet Explorer';
846        } else if (brwoser.indexOf('Edge') > -1) {
847            return 'Microsoft Edge';
848        } else if (brwoser.indexOf('Chrome') > -1) {
849            return 'Google Chrome';
850        } else if (brwoser.indexOf('Safari') > -1) {
851            return 'Apple Safari';
852        } else {
853            return 'unknown';
854        }
855    },
856    isMobile: function() {
857        if ((/Android|webOS|iPhone|iPad|iPod|BlackBerry|Windows Phone/i.test(navigator.userAgent)) && window.innerWidth < 768) {
858            return true;
859        } else {
860            return false;
861        }
862    },
863    getLink: function(param, value, link) {
864        let re = new RegExp('[\?\&]' + param + '=', 'g');
865        let url = link || window.location.href;
866        if (re.test(url)) {
867            re = new RegExp('([\?\&]' + param + '=)(.*?)&', 'g');
868            if (re.test(url)) {
869                url = url.replace(re, '$1' + value + '&');
870            } else {
871                re = new RegExp('([\?\&]' + param + '=)(.*?)$', 'g');
872                url = url.replace(re, '$1' + value);
873            }
874        } else if (/\?/g.test(url)) {
875            url += '&' + param + '=' + value;
876        } else {
877            url += '?' + param + '=' + value;
878        }
879        if (value === '') {
880            re = new RegExp('([\?\&])' + param + '=[^?&]*&?', 'g');
881            url = url.replace(re, '$1');
882        }
883        url = url.replaceAll(/[?&]$/g, '');
884        if (param !== 'pg') url = url.replaceAll(/(\?|\&)pg=\d+/ig, "$1pg=1");
885        if (param !== 'ps') url = url.replaceAll(/(\?|\&)ps=\d+/ig, "$1ps=1");
886        return url;
887    },
888    accordion: function(element) {
889        let self = this,
890            accBody = null;
891
892        function openAction(collapseElement) {
893            T(collapseElement).addClass('show');
894        }
895
896        function closeAction(collapseElement) {
897            T(collapseElement).removeClass('show');
898        }
899
900        self.toggle = function(e) {
901            if (e && e.target.tagName === 'A') { e.preventDefault(); }
902            const accWrapper = element.closest('.accordion-wrapper');
903            if (accWrapper) {
904                const items = Array.from(accWrapper.querySelectorAll('[data-toggle="accordion"]'));
905                items.forEach(item => {
906                    if (element == item) return;
907                    const itemBody = document.querySelector(item.getAttribute('data-target') || item.getAttribute('href')) || item.nextElementSibling;
908                    if (itemBody) closeAction(itemBody);
909                    T(item).removeClass('active');
910                });
911            }
912            if (T(element).hasClass('active')) { self.hide(); } else { self.show(); }
913        };
914
915        self.hide = function() {
916            closeAction(accBody);
917            T(element).removeClass('active');
918        };
919
920        self.show = function() {
921            openAction(accBody);
922            T(element).addClass('active');
923        };
924
925        tInitFn(function() {
926            if (element.Accordion == 1) return;
927            accBody = document.querySelector(element.getAttribute('data-target') || element.getAttribute('href')) || element.nextElementSibling;
928
929            if(element.getAttribute('data-mobile') == 'true') { accBody.setAttribute('data-mobile', 'true'); }
930            if(element.getAttribute('data-mobile') == 'true' && !T.isMobile()) { return; }
931
932            if (T(element).hasClass('active')) { accBody.classList.add('show'); }
933            if (!element.Accordion) { T(element).on('click', self.toggle); }
934
935            self.element = element;
936            element.Accordion = 1;
937        });
938
939        return;
940        },
941    dropdown: function(element) {
942        let self = this,
943            parent;
944
945        function preventEmptyAnchor(anchor) {
946            (anchor.href && anchor.href.slice(-1) === '#' || anchor.parentNode && anchor.parentNode.href &&
947                anchor.parentNode.href.slice(-1) === '#') && this.preventDefault();
948        }
949
950        function toggleDismiss() {
951            if (element.open)
952                T(document).on('click', dismissHandler);
953            else
954                T(document).off('click', dismissHandler);
955        }
956
957        function dismissHandler(e) {
958            let eventTarget = e.target;
959
960            if (['A', 'BUTTON'].includes(eventTarget.nodeName)) {
961                self.hide(eventTarget);
962            } else if (!element.contains(eventTarget) && parent.contains(eventTarget)) {
963                return;
964            }
965
966            self.hide(eventTarget);
967            preventEmptyAnchor.call(e, eventTarget);
968        }
969
970        function clickHandler(e) {
971            self.show();
972            preventEmptyAnchor.call(e, e.target);
973        }
974
975        self.show = function() {
976            parent.classList.add('show');
977            element.open = true;
978            T(element).off('click', clickHandler);
979            setTimeout(function() {
980                toggleDismiss();
981            }, 1);
982        };
983
984        self.hide = function(eventTarget) {
985            parent.classList.remove('show');
986            element.open = false;
987            toggleDismiss();
988            setTimeout(function() {
989                element.Dropdown && T(element).on('click', clickHandler);
990                if (typeof element.dataset.callback === 'string' && typeof window[element.dataset.callback] === 'function') {
991                    window[element.dataset.callback](element, eventTarget);
992                }
993            }, 1);
994        };
995
996        tInitFn(function() {
997            if (element.Dropdown == 1) return;
998            parent = element.parentNode;
999            menu = parent.querySelector('.dropdown-menu');
1000            if (!element.open) {
1001                T(element).on('click', clickHandler);
1002            }
1003            element.open = false;
1004            self.element = element;
1005            element.Dropdown = 1;
1006        });
1007    },
1008    tab: function(element) {
1009        const self = this;
1010        let next, activeTab, nextContent, activeContent, tabs, property;
1011
1012        function setActiveTab(next) {
1013            activeTab = tabs.getElementsByClassName('active')[0];
1014            if (!activeTab) {
1015                console.warn(`activeTab element undefined`);
1016                return;
1017            }
1018            activeContent = document.querySelector(activeTab.querySelector('a').getAttribute('href'));
1019            if (!activeContent) {
1020                console.warn(`activeContent element undefined`);
1021                return;
1022            }
1023            T(activeTab).removeClass('active');
1024            T(next.parentNode).addClass('active');
1025            triggerHide();
1026        }
1027
1028        function triggerHide() {
1029            T(nextContent).addClass('active');
1030            T(activeContent).removeClass('active');
1031        }
1032
1033        function clickHandler(e) {
1034            e.preventDefault();
1035            next = e.currentTarget;
1036            self.show();
1037        }
1038
1039        self.show = function() {
1040            next = next || element;
1041            nextContent = document.querySelector(next.getAttribute('href'));
1042            appendContent = document.querySelector(next.dataset.content) || document.querySelector(next.getAttribute('href'));
1043            property = next.dataset.property;
1044            if (!T(next.parentNode).hasClass('active') || T(next.parentNode).hasClass('load')) {
1045                if((next.dataset.href || '').trim() != '' && !T(next.parentNode).hasClass('loaded')) {
1046                    T(nextContent).addClass('is-loading');
1047                    let url = next.dataset.href;
1048                    if (!element.dataset?.endpoint == 'base') url = getEndpoint('', next.dataset.href);
1049
1050                    axios.get(url).then(response => {
1051                        appendContent.innerHTML = property ? response.data[property] : response.data;
1052
1053                        T(next.parentNode).addClass('loaded');
1054                        T(next.parentNode).removeClass('load');
1055                        T(nextContent).removeClass('is-loading');
1056
1057                        if(typeof window[next.dataset.callback] == 'function'){
1058                            window[next.dataset.callback](next, nextContent, appendContent);
1059                        }
1060
1061                        evalScripts(appendContent.innerHTML);
1062                        try {
1063                            favouriteProducts.set();
1064                            compareSet();
1065                        } catch (error) {}
1066                    }).catch(error => console.log(`Tab content not loaded => ${error}`));
1067                }
1068            }
1069            if (!T(next.parentNode).hasClass('active')) setActiveTab(next);
1070        };
1071
1072        tInitFn(function() {
1073            if (element.Tab == 1) return;
1074            tabs = element.closest('.tab-nav');
1075            T(element).on('click', clickHandler);
1076            self.element = element;
1077            element.Tab = 1;
1078        });
1079    },
1080    placeholder: {
1081        createPlaceholder: function(element) {
1082            const parentNode = element.parentNode;
1083            const isRequired = element.required || T(element).hasClass('required') || String(element.getAttribute('data-validate')).includes('required');
1084            const span = (parentNode.querySelector('.input-placeholder')) ? parentNode.querySelector('.input-placeholder') : document.createElement('span');
1085            span.className = "input-placeholder" + (element.value != '' ? ' focused' : '');
1086
1087            let text = element.getAttribute('data-placeholder') || element.getAttribute('placeholder');
1088            if (text == null) return false;
1089
1090            text += isRequired ? '<span class="input-placeholder-required fw-bold text-danger">*</span>' : '';
1091
1092            span.innerHTML = text;
1093
1094            return span;
1095        },
1096        show: function(e) {
1097            const parentNode = e.parentNode;
1098            T(e).removeClass('form-control-placeholder-hidden');
1099            T(parentNode.querySelector('.input-placeholder')).addClass('focused');
1100        },
1101        hide: function(e) {
1102            const parentNode = e.parentNode;
1103            if (e.value === '') T(parentNode.querySelector('.input-placeholder')).removeClass('focused');
1104        },
1105        visible: function(e) {
1106            T(e).addClass('form-control-placeholder-hidden');
1107        },
1108        reset: function(element) {
1109            if (element && element.Reset != 1) return;
1110
1111            if (element) {
1112                if (element.value === '') {
1113                    T.placeholder.hide(element);
1114                    T.placeholder.visible(element);
1115                } else {
1116                    T.placeholder.show(element);
1117                }
1118            }
1119
1120            const selectItem = T('.form-control-placeholder[data-toggle="placeholder"]');
1121            if (selectItem.length > 0) {
1122                Array.from(selectItem).forEach(item => {
1123                    if (item.value === '') {
1124                        T.placeholder.hide(item);
1125                        T.placeholder.visible(item);
1126                    } else {
1127                        T.placeholder.show(item);
1128                    }
1129                });
1130            }
1131        },
1132        init: function(element = null) {
1133            if (element.Placeholder == 1 || T.placeholder.createPlaceholder(element) == false) return;
1134
1135            setTimeout(() => {
1136                element.parentNode.insertBefore(T.placeholder.createPlaceholder(element), element.nextSibling);
1137                T(element.parentNode).addClass('position-relative');
1138                T(element).addClass('loaded form-control-placeholder');
1139                element.Reset = 1;
1140
1141                if (element.tagName == 'SELECT') {
1142                    T(element).on('change', () => {
1143                        T.placeholder.reset(element);
1144                    });
1145                } else {
1146
1147                    T(element).on('paste', () => {
1148                        setTimeout(() => {
1149                            if (element.value !== '') T.placeholder.show(element);
1150                        }, 11);
1151                    });
1152
1153                    T(element).on('input', () => {
1154                        if (element.value !== '') T.placeholder.show(element);
1155                    });
1156
1157                    T(element).on('blur', () => {
1158                        T.placeholder.reset(element);
1159                    });
1160                }
1161
1162                T.placeholder.reset(element);
1163
1164                element = element;
1165                element.Placeholder = 1;
1166            }, 250);
1167        },
1168    },
1169    notify: function(options) {
1170        const self = this;
1171        let defaults = {
1172            text: "",
1173            stopOnFocus: false,
1174            duration: 6000,
1175            gravity: "top", /* top || bottom */
1176            position: 'right', /* left || right */
1177            className: '', /* default : success || danger */
1178            iconClass : '',
1179        };
1180        const nameRule = {
1181            wrapId: 'tsoft-notify-' + defaults.gravity + '-' + defaults.position,
1182            wrapClass: 'tsoft-notify-wrapper notify-' + defaults.gravity + ' notify-' + defaults.position,
1183            notify: 'notify-item'
1184        };
1185
1186        /*Extend options*/
1187        if (typeof options === 'object') {
1188            defaults = T.extend(defaults, options);
1189        }
1190
1191        self.createWrap = function() {
1192            let notifyWrapEl = document.querySelector(`.tsoft-notify-wrapper.notify-${defaults.gravity}.notify-${defaults.position}`);
1193            if (notifyWrapEl == null) {
1194                notifyWrapEl = document.createElement('div');
1195                notifyWrapEl.id = nameRule.wrapId;
1196                notifyWrapEl.className = nameRule.wrapClass;
1197                document.body.appendChild(notifyWrapEl);
1198            }
1199
1200            return notifyWrapEl;
1201        }
1202
1203        self.build = function() {
1204            let myNotify = document.createElement('div');
1205            myNotify.className = nameRule.notify + ' ' + defaults.className + ' fade-in';
1206            myNotify.innerHTML = `<div class="notify-text">${defaults.text}</div>`;
1207
1208            if (defaults.iconClass) {
1209                const iconEl = document.createElement('span');
1210                iconEl.className = 'notify-icon';
1211                iconEl.innerHTML = `<i class="${defaults.iconClass}"></i>`;
1212                myNotify.prepend(iconEl);
1213            }
1214
1215            const closeEl = document.createElement('span');
1216            closeEl.className = 'notify-close';
1217            closeEl.innerHTML = '<i class="ti-close"></i>';
1218
1219            closeEl.addEventListener('click', function(event) {
1220                event.stopPropagation();
1221                self.removeEl(myNotify);
1222                window.clearTimeout(myNotify.timeOutValue);
1223            }.bind(this));
1224
1225            myNotify.appendChild(closeEl);
1226
1227            if (defaults.duration > 0) {
1228                myNotify.timeOutValue = window.setTimeout(function() {
1229                        this.removeEl(myNotify);
1230                    }.bind(this),
1231                    defaults.duration
1232                );
1233            }
1234
1235            if (defaults.stopOnFocus && defaults.duration > 0) {
1236                /* Stop duration */
1237                myNotify.addEventListener('mouseover', event => {
1238                    window.clearTimeout(myNotify.timeOutValue);
1239                });
1240
1241                /* Add back the timeout */
1242                myNotify.addEventListener('mouseleave', event => {
1243                    myNotify.timeOutValue = window.setTimeout(e => {
1244                        self.removeEl(myNotify);
1245                    }, defaults.duration);
1246                });
1247            }
1248
1249            return myNotify;
1250        }
1251
1252        self.removeEl = function(el) {
1253            const wrapper = document.querySelector('#' + nameRule.wrapId);
1254            if (wrapper.querySelectorAll('.' + nameRule.notify).length > 1) {
1255                wrapper.removeChild(el);
1256            } else {
1257                document.body.removeChild(wrapper);
1258            }
1259        }
1260
1261        tInitFn(function() {
1262            const wrapper = self.createWrap();
1263            wrapper.appendChild(self.build());
1264        });
1265    },
1266    mask: function(element, validate, regex, max = null) {
1267        const self = this;
1268        if (typeof element == 'string') element = T(element);
1269        if (!element) return;
1270
1271        Array.from(element).forEach(item => {
1272            validate = item.dataset.type ? item.dataset.type : validate;
1273            regex = item.dataset.mask ? item.dataset.mask : regex;
1274
1275            if (!validate)
1276                return;
1277
1278            function run(event) {
1279                let re;
1280                switch (validate) {
1281                    case 'string':
1282                        re = /[^\p{L}\s\-]/gu;
1283                        break;
1284                    case 'number':
1285                        re = /[^0-9]/g;
1286                        break;
1287                    case 'price':
1288                        re = /[^0-9.,]/g;
1289                        break;
1290                    case 'password' :
1291                        re = /^\s+|\s+$/;
1292                        break;
1293                    case 'email' :
1294                        re = /^\s+|(?:^|\s|,|;|!|:|-|\.|\?)[ğçşüöı]/g;
1295                        break;
1296                    case 'custom' :
1297                        if (regex) re = new RegExp(`[${regex}]`,"g");
1298                        break;
1299                    default:
1300                        console.log(validate + ', undefined mask...');
1301                }
1302
1303                if (event.type == 'paste') {
1304                    setTimeout(() => {
1305                        const value = event?.target?.value || null;
1306                        if (!re || value == null) return;
1307                        if (re.test(String(value))) event.target.value = event.target.value.replace(re, '');
1308                    }, 10);
1309                } else if (event.type == 'keypress') {
1310                    let value = event.target.value;
1311                    if (event.target.closest('.t-phone-masked')) value = event.target.value.replaceAll(/\D+/g, '');
1312                    if (max != null && value.length >= max) event.preventDefault();
1313                    if (re && re.test(String(event.key))) event.preventDefault();
1314
1315                }
1316            }
1317
1318            tInitFn(function() {
1319                if (item.Mask == 1) return;
1320
1321                T(item).on('paste', (event) => {
1322                    run(event);
1323                });
1324
1325                T(item).on('keypress', (event) => {
1326                    run(event);
1327                });
1328
1329                self.item = item;
1330                item.Mask = 1;
1331            });
1332        });
1333
1334            return;
1335        },
1336    zoomImage: function(element, options) {
1337        if (T.isMobile()) return;
1338
1339        if (element == '' || T(element).length < 1)
1340            return console.log('zoom image undefined');
1341
1342        if (!element.dataset.image)
1343            return console.log('zoom image "data-image" undefined');
1344
1345        const self = this;
1346        let lens, image, result, maxSize, control = 0;
1347
1348        const defaults = T.extend({
1349            target: element.dataset.target || '#product-right',
1350            type: 'zoom', /* zoom or magnifier */
1351            width: element.dataset.width || element.clientWidth,
1352            height: element.dataset.height || element.clientHeight,
1353        }, options);
1354
1355        function zoomPos() {
1356            if (T(defaults.target).length < 1) return;
1357
1358            const targetEl = T(defaults.target)[0].getBoundingClientRect();;
1359            let top = targetEl.top;
1360            if (document.body.scrollTop > targetEl.top || document.documentElement.scrollTop > targetEl.top) {
1361                const fark = document.documentElement.scrollTop - top;
1362                if (fark > 0) top = top + fark;
1363            } else {
1364                top = targetEl.top;
1365            }
1366            return top;
1367        }
1368
1369        function createZoom() {
1370            element = T(element)[0];
1371
1372            lens = document.createElement('div');
1373            lens.className = 't-zoom-lens';
1374            element.parentElement.classList.add('t-zoom-image');
1375            element.parentElement.style.height = `${element.height + 1}px`;
1376            element.parentElement.insertBefore(lens, element);
1377
1378            lens.addEventListener('mousemove', zoomEnable);
1379            element.addEventListener('mousemove', zoomEnable);
1380            lens.addEventListener('touchmove', zoomEnable);
1381            element.addEventListener('touchmove', zoomEnable);
1382        }
1383
1384        function createImg() {
1385            if (T(defaults.target).length < 1) return; 
1386            const targetEl = T(defaults.target)[0];
1387
1388            control = 1;
1389            result = document.createElement('div');
1390            result.className = 't-zoom-result';
1391            result.style.backgroundImage = "url('" + image.src + "')";
1392            result.style.position = "absolute";
1393            result.style.pointerEvents = "none";
1394            document.body.appendChild(result);
1395
1396            result.style.width = `${defaults.width}px`;
1397            result.style.height = `${defaults.height}px`;
1398            result.style.top = `${zoomPos()}px`;
1399            result.style.left = LANGUAGE == 'ar' ? `${targetEl.offsetLeft + targetEl.clientWidth - defaults.width}px` : `${targetEl.offsetLeft}px`;
1400
1401            window.onscroll = () => {
1402                result.style.top = `${zoomPos()}px`;
1403            };
1404
1405            image.onload = function() {
1406                result.style.backgroundSize = `${image.width}px ${image.height}px`;
1407            }
1408        }
1409
1410        function zoomEnable(e) {
1411            lens.style.height = `${element.height / (image.height / defaults.height)}px`;
1412            lens.style.width = `${element.width / (image.width / defaults.width)}px`;
1413
1414            let pos, x, y;
1415            e.preventDefault();
1416            pos = getCursorPos(e);
1417            x = pos.x - (lens.offsetWidth / 2);
1418            y = pos.y - (lens.offsetHeight / 2);
1419
1420            if (pos.x <= 0) {
1421                return;
1422            } else if (control == 0) {
1423                createImg();
1424            }
1425
1426            if (x > element.width - lens.offsetWidth) {x = element.width - lens.offsetWidth;}
1427            if (x < 0) {x = 0;}
1428
1429            if (y > element.height - lens.offsetHeight) {y = element.height - lens.offsetHeight;}
1430            if (y < 0) {y = 0;}
1431            lens.style.left = x + "px";
1432            lens.style.top = y + "px";
1433
1434            const bgPosX = x * (defaults.width / lens.offsetWidth),
1435                  bgPosY = y * (defaults.height / lens.offsetHeight);
1436
1437            result.style.backgroundPosition = `-${bgPosX}px -${bgPosY}px`;
1438        }
1439
1440        function getCursorPos(e) {
1441            let a, x = 0, y = 0;
1442            e = e || window.event;
1443            a = element.getBoundingClientRect();
1444            x = e.pageX - a.left;
1445            y = e.pageY - a.top;
1446            x = x - window.pageXOffset;
1447            y = y - window.pageYOffset;
1448            return { x: x, y: y };
1449        }
1450
1451        function destroy() {
1452            T('.t-zoom-image').removeClass('t-zoom-image');
1453            element.parentElement.style.height = '';
1454            if(lens) element.parentNode.removeChild(lens);
1455            if (control == 1) {
1456                document.body.removeChild(result);
1457            }
1458            control = 0;
1459        }
1460
1461        tInitFn(function() {
1462            if (element.zoomImage == 1) return;
1463
1464            element.parentNode.addEventListener('mouseenter', e => {
1465                if (element.active != 1) {
1466                    image = new Image();
1467                    image.src = element.dataset.image;
1468                    maxSize = element.width + (element.width * .2);
1469
1470                    image.onload = function() {
1471                        if (image.width > maxSize) {
1472                            element.active = 1;
1473                            createZoom();
1474                        }
1475                    }
1476                } else {
1477                    createZoom();
1478                }
1479            });
1480            element.parentNode.addEventListener("mouseleave", destroy);
1481
1482            self.element = element;
1483            element.zoomImage = 1;
1484        });
1485    },
1486    modal: function(element, options) {
1487        T.modal.instance = T.modal.instance || {};
1488        T.modal.counter = T.modal.counter || 0;
1489        T.modal.close = T.modal.close || null;
1490
1491        const defaults = T.extend({
1492            id: '',
1493            class: '',
1494            width: '',
1495            height: '',
1496            title: '',
1497            html: '',
1498            close: false,
1499            autoClose: 0,
1500            disableClose: false,
1501            openCallback: () => {},
1502            closeCallback: () => {},
1503            buttons: [
1504                /* {text: '', href: '', class: '', event: function() {}, }, */
1505            ],
1506        }, (element.nodeName == undefined ? arguments[0] : options));
1507
1508        function createModal() {
1509            const modal = document.createElement('div');
1510            const modalBackdrop = document.createElement('div');
1511            const modalContent = document.createElement('div');
1512
1513            T.modal.counter++;
1514            if (defaults.id.trim() == '') {
1515                defaults.id = 'popup' + T.modal.counter;
1516            }
1517            modal.id = defaults.id;
1518
1519            if (T('.t-modal-wrapper').length > 0) {
1520                modal.className = `t-modal-wrapper fade-in modal-level-${T.modal.counter} ${defaults.class}`;
1521            } else {
1522                modal.className = 't-modal-wrapper fade-in ' + defaults.class;
1523            }
1524
1525            modal.classList.add(THEME_FOLDER);
1526
1527            const modalContainer = document.createElement('div');
1528            modalContainer.classList.add('t-modal-container');
1529
1530            if (defaults.width.trim() != '') {
1531                modalContent.style.width = defaults.width;
1532            }
1533
1534            if (defaults.height.trim() != '') {
1535                modalContent.style.height = defaults.height;
1536            }
1537
1538            modalBackdrop.className = 't-modal-backdrop';
1539            modalBackdrop.addEventListener('click', (event) => {
1540                closeModal(modal);
1541            });
1542            modalContainer.appendChild(modalBackdrop);
1543
1544            modalContent.className = 't-modal-content';
1545            modalContent.innerHTML = defaults.title + defaults.html;
1546
1547            if (defaults.buttons.length > 0) {
1548                const modalButtons = document.createElement('div');
1549                modalButtons.className = 'd-flex justify-content-end gap-1 mt-1 t-modal-buttons';
1550                defaults.buttons.forEach(btn => {
1551                    const button = document.createElement('a');
1552                    button.className = btn.class || '';
1553                    button.innerHTML = btn.text || '';
1554                    button.href = btn.href || 'javascript:void(0)';
1555                    if (btn.event) {
1556                        button.addEventListener('click', () => {
1557                            try {
1558                                btn.event();
1559                            } catch (error) {
1560                                console.error('Button event error:', error);
1561                            }
1562                        });
1563                    }
1564                    modalButtons.append(button);
1565                });
1566                modalContent.append(modalButtons);
1567            }
1568
1569            if(defaults.close === true) {
1570                const closeEl = document.createElement('span');
1571                closeEl.className = 't-modal-close';
1572                closeEl.id = 't-modal-close-' + T.modal.counter;
1573                closeEl.innerHTML = '<i class="ti-close"></i>';
1574                closeEl.addEventListener('click', () => {
1575                    closeModal(modal);
1576                });
1577                modalContainer.appendChild(closeEl);
1578            }
1579
1580            if (defaults.autoClose > 0) {
1581                setTimeout(() => {
1582                    closeModal(modal);
1583                }, defaults.autoClose);
1584            }
1585
1586            T.modal.close = () => {
1587                closeModal(modal);
1588            };
1589
1590            modal.appendChild(modalContainer);
1591            modalContainer.appendChild(modalContent);
1592
1593            setTimeout(() => {
1594                Array.from(modal.querySelectorAll('[data-action="destroy"]')).forEac
1594h(destroyEl => {
1595                    destroyEl.addEventListener('click', e => {
1596                        e.preventDefault();
1597                        e.stopPropagation();
1598                        closeModal(modal);
1599                    });
1600                });
1601            }, 150);
1602
1603            defaults.openCallback?.();
1604            return modal;
1605        }
1606
1607        function closeModal(modal) {
1608            if (defaults.disableClose == true) return;
1609            if (document.getElementById(modal.id) == null) return;
1610            document.body.removeChild(modal);
1611            T.modal.counter--;
1612
1613            defaults.closeCallback?.();
1614
1615            if(T.modal.counter == 0) {
1616                T('html').removeClass('is-active-modal');
1617            }
1618        }
1619
1620        tInitFn(function() {
1621            T('html').addClass('is-active-modal');
1622            document.body.appendChild(createModal());
1623            evalScripts(document.querySelector('.t-modal-wrapper:last-child').innerHTML);
1624        });
1625    },
1626    popupWin: function(element) {
1627        const self = this;
1628
1629        const openPopup = function() {
1630            const width = element.dataset.width ? element.dataset.width : 570;
1631            const elId  = element.dataset.id ? element.dataset.id : `popupwin-${T.popupWin.counter}`;
1632            const url = element.dataset.url || element.getAttribute('href');
1633
1634            if(url == 'undefined' || url == '') {
1635                return;
1636            }
1637
1638            axios.get(url).then(response => {
1639                const result = response.data;
1640                T.modal({
1641                    id: elId,
1642                    width: width > 0 ? `${width}px` : 'auto',
1643                    html: (typeof result == 'object' && element.dataset.property && result[element.dataset.property]) ? result[element.dataset.property] : result,
1644                    close: true
1645                });
1646                T.buttonLock.unlock();
1647            }).catch(error => console.warn(`Popupwin error => ${error}`));
1648        }
1649
1650        tInitFn(function() {
1651            if(element.Popupwin == 1) return;
1652
1653            T.popupWin.counter = T.popupWin.counter || 0;
1654            T.popupWin.counter++;
1655
1656            T(element).on('click', function(e) {
1657                e.preventDefault();
1658                T.buttonLock.dom = element;
1659                T.buttonLock.lock();
1660                openPopup();
1661            });
1662
1663            self.element = element;
1664            element.Popupwin = 1;
1665        });
1666    },
1667    tooltip: function(element, options = {}) {
1668        const self = this,
1669              dataset = element.dataset,
1670              titleString = element.getAttribute('title') || dataset.title;
1671
1672        let tooltip = null;
1673
1674        const defaults = {
1675            placement: options.placement ? options.placement : (dataset.placement ? dataset.placement : 'top'),
1676            container: element.closest('.t-modal-wrapper') ? element.closest('.t-modal-wrapper') : document.body,
1677            /* delay: options.delay ? options.delay : 200, */
1678        };
1679
1680        function createTooltip(){
1681            tooltip = document.createElement('div');
1682            let arrow = document.createElement('div'),
1683                tooltipInner = document.createElement('div');
1684
1685            T(tooltip).addClass('t-tooltip fade-in');
1686            T(arrow).addClass('arrow');
1687            T(tooltipInner).addClass('tooltip-inner');
1688            tooltipInner.innerHTML = titleString;
1689            tooltip.appendChild(arrow);
1690            tooltip.appendChild(tooltipInner);
1691            defaults.container.appendChild(tooltip);
1692        }
1693
1694        function destroyTooltip(){
1695            tooltip.remove();
1696            delete element.Tooltip;
1697        }
1698
1699        function stylePos(){
1700            if (!element) return;
1701            if (!tooltip) return;
1702
1703            const rect = element.getBoundingClientRect(),
1704                  leftPosition = rect.left + (element.offsetWidth/2),
1705                  topPosition = rect.top + (defaults.container === document.body ? window.pageYOffset : defaults.container.offsetTop + defaults.container.scrollTop) - tooltip.offsetHeight;
1706
1707            tooltip.style.top = topPosition + 'px';
1708            tooltip.style.left = leftPosition + 'px';
1709            tooltip.style.right = 'auto';
1710        }
1711
1712        function toggleEvents() {
1713            T(element).on(mouseHoverEvents[0], self.show);
1714            T(element).on(mouseHoverEvents[1], self.hide);
1715            T(element).on('click', self.hide);
1716        }
1717
1718        self.show = function () {
1719            createTooltip();
1720            stylePos();
1721        }
1722
1723        self.hide = function () {
1724            destroyTooltip();
1725        }
1726
1727        tInitFn(function() {
1728            if (element.Tooltip == 1) return;
1729            if (!titleString) return;
1730
1731            if (!element.Tooltip) {
1732                toggleEvents();
1733            }
1734
1735            self.element = element;
1736            element.Tooltip = 1;
1737        });
1738    },
1739    popConfirm: function(element) {
1740        let popWrapper = null;
1741
1742        const eventBtn = (btn, callback = null) => {
1743            const opt = element.dataset;
1744
1745            if (typeof callback === 'string' && typeof window[callback] === 'function') {
1746                T.buttonLock.dom = T(btn)[0];
1747                T.buttonLock.lock();
1748                if (opt.loading) T(btn).addClass('is-loading');
1749                else T(popWrapper)[0].remove();
1750
1751                window[callback](element, btn);
1752                setTimeout(() => {
1753                    if (opt.loading) T(btn).removeClass('is-loading');
1754                    T(popWrapper)[0].remove();
1755                    window.onresize = '';
1756                    T.buttonLock.unlock();
1757                }, 500);
1758            } else {
1759                T(popWrapper)[0].remove();
1760            }
1761        }
1762
1763        function show() {
1764            if (T(popWrapper).length > 0) T(popWrapper)[0].remove();
1765            createPopConfirm(element);
1766            element.open = true;
1767            toggleDismiss();
1768        }
1769
1770        function toggleDismiss() {
1771            if (element.open == true) {
1772                T(document).on('click', dismissHandler);
1773                window.onresize = windowSize;
1774            } else {
1775                T(document).off('click', dismissHandler);
1776            }
1777        }
1778
1779        function dismissHandler(e) {
1780            if (T('.t-popconfirm').length > 0) {
1781                let eventTarget = e.target;
1782
1783                const tagNames = document.querySelector('.t-popconfirm').getElementsByTagName("*");
1784                const tag = Array.from(tagNames).find(el => el == eventTarget);
1785
1786                if (tag || e.target.closest('[data-toggle="popconfirm"]') == element) {
1787                    return;
1788                } else {
1789                    T(popWrapper)[0].remove();
1790                    window.onresize = '';
1791                }
1792            } else {
1793                element.open = false;
1794                toggleDismiss();
1795            }
1796        }
1797
1798        function createPopConfirm(element) {
1799            const opt = element.dataset;
1800
1801            popWrapper = document.createElement('div');
1802                  T(popWrapper).addClass('t-popconfirm fade-in');
1803
1804            const popInner = document.createElement('div');
1805                  T(popInner).addClass('t-popconfirm-inner');
1806
1807            if (opt.title) {
1808                const title = document.createElement('div');
1809                      T(title).addClass('t-popconfirm-message');
1810                      T(title).html(`<div class="t-confirm-title">${opt.title}</div>`);
1811
1812                if (opt.icon) {
1813                    const icon = document.createElement('div');
1814                          T(icon).addClass('t-popconfirm-icon');
1815                          T(icon).html(`<i class="${opt.icon}"></i>`);
1816                    title.prepend(icon);
1817                }
1818
1819                popInner.prepend(title);
1820            }
1821
1822            if (opt.confirm || opt.cancel) {
1823                const buttons = document.createElement('div');
1824                      T(buttons).addClass('t-popconfirm-buttons');
1825
1826                if (opt.confirm) {
1827                    const confirm = document.createElement('button');
1828                          T(confirm).addClass('btn btn-primary t-popconfirm-confirm-btn');
1829                          T(confirm).text(opt.confirm);
1830                    buttons.append(confirm);
1831
1832                    T(confirm).on('click', () => {
1833                        eventBtn(confirm, element.dataset.callback);
1834                    });
1835                }
1836
1837                if (opt.cancel) {
1838                    const cancel = document.createElement('button');
1839                          T(cancel).addClass('btn btn-light t-popconfirm-cancel-btn');
1840                          T(cancel).text(opt.cancel);
1841                    buttons.prepend(cancel);
1842
1843                    T(cancel).on('click', () => {
1844                        eventBtn(cancel, element.dataset.cancelcallback)
1845                    });
1846                }
1847                popInner.append(buttons);
1848            }
1849
1850            popWrapper.append(popInner);
1851            document.body.appendChild(popWrapper);
1852            stylePos(element, popWrapper);
1853        }
1854
1855        function stylePos(element, popWrapper){
1856            if (!element || !popWrapper) return;
1857
1858            const rect = element.getBoundingClientRect();
1859            let posY, posX;
1860
1861            if (rect.left + popWrapper.offsetWidth > window.innerWidth || (window.innerWidth - rect.right + popWrapper.offsetWidth) > window.innerWidth) {
1862                if (rect.left > (window.innerWidth - rect.right)) {
1863                    posY = rect.top + window.pageYOffset - popWrapper.offsetHeight + (element.offsetHeight/2);
1864                    posX = rect.right - popWrapper.offsetWidth - element.offsetWidth;
1865
1866                    T(popWrapper).removeClass('popconfirm-left');
1867                    T(popWrapper).addClass('popconfirm-right');
1868                } else {
1869                    posY = rect.top + window.pageYOffset - popWrapper.offsetHeight + (element.offsetHeight/2);
1870                    posX = rect.left + element.offsetWidth;
1871                    T(popWrapper).removeClass('popconfirm-right');
1872                    T(popWrapper).addClass('popconfirm-left');
1873                }
1874            } else {
1875                posY = rect.top + window.pageYOffset - popWrapper.offsetHeight;
1876                posX = rect.left + (element.offsetWidth/2);
1877                T(popWrapper).removeClass('popconfirm-right popconfirm-right');
1878            }
1879
1880            if (posX < 1) {
1881                popWrapper.style.width = `${rect.left}px`;
1882                popWrapper.style.left = 0;
1883                posY = rect.top + window.pageYOffset - popWrapper.offsetHeight + (element.offsetHeight/2);
1884            } else {
1885                popWrapper.style.left = `${posX}px`;
1886            }
1887
1888            popWrapper.style.top = `${posY}px`;
1889        }
1890
1891        function windowSize() {
1892            stylePos(element, popWrapper);
1893        }
1894
1895        tInitFn(function() {
1896            if (element.popConfirm == 1) return;
1897
1898            if (!element.open) {
1899                T(element).on('click', show);
1900            }
1901
1902            element.open = false;
1903            self.element = element;
1904            element.popConfirm = 1;
1905        });
1906
1907    },
1908    drawer: function(element) {
1909        const self = this;
1910        const drawer = T(element.getAttribute('href'));
1911        if(drawer.length < 1) {
1912            T(element).addClass('d-none');
1913            return;
1914        }
1915
1916        const overlay = T(`.drawer-overlay[data-rel="${element.getAttribute('href').replace('#', '')}"]`);
1917        const subCloseEl = T(element.getAttribute('href') + ` .sub-drawer-close[data-rel="${element.getAttribute('href').replace('#', '')}"]`);
1918        const closeEl = T(element.getAttribute('href') + ' .drawer-close');
1919        const settings = drawer[0].dataset || {};
1920
1921        self.show = function () {
1922            T(element).addClass('active');
1923            drawer.addClass('animated active');
1924            overlay.addClass('active');
1925            document.body.classList.add(`body-${element.getAttribute('href').replace('#', '')}`);
1926            document.body.style.overflow = 'hidden';
1927            if (settings.display == 'push') {
1928                document.body.classList.add(`drawer-${settings.position}-active`, 'drawer-animated');
1929            }
1930            transitionCtrl(drawer[0], function() {
1931                drawer.removeClass('animated');
1932                if (typeof settings.callback === 'string' && typeof window[settings.callback] === 'function') {
1933                    window[settings.callback]();
1934                }
1935            });
1936        }
1937
1938        self.hide = function () {
1939            T(element).removeClass('active');
1940            drawer.addClass('animated');
1941            drawer.removeClass('active');
1942            if (settings.display == 'push') {
1943                document.body.classList.remove(`drawer-${settings.position}-active`);
1944            }
1945            transitionCtrl(T(drawer)[0], function() {
1946                drawer.removeClass('animated');
1947                overlay.removeClass('active');
1948                if (T('.drawer-overlay.active').length == 0) document.body.style.overflow = null;
1949                document.body.classList.remove(`body-${element.getAttribute('href').replace('#', '')}`);
1950                if (settings.display == 'push') {
1951                    document.body.classList.remove('drawer-animated');
1952                }
1953            });
1954        }
1955
1956        tInitFn(function() {
1957            if(element.Drawer == 1
1958               || (element.tagName != 'A' && !element.href && drawer.length < 1)
1959               || (settings.platform == 'mobile' && !T.isMobile())) {
1960                return;
1961            }
1962
1963            if (closeEl != null) {
1964                drawer.addClass('closable-active');
1965            }
1966
1967            T(element).on('click', function(e) {
1968                e.preventDefault();
1969                if (T(element).hasClass('active')) {
1970                    self.hide();
1971                } else {
1972                    self.show();
1973                }
1974            });
1975
1976            overlay.on('click', function(e) {
1977                e.preventDefault();
1978                self.hide();
1979                if (drawer[0].querySelectorAll('.sub-drawer-close').length > 0) T(drawer[0].querySelectorAll('.sub-drawer-close')).trigger('click');
1980            });
1981
1982            closeEl.on('click', function(e) {
1983                e.preventDefault();
1984                self.hide();
1985                if (drawer[0].querySelectorAll('.sub-drawer-close').length > 0) T(drawer[0].querySelectorAll('.sub-drawer-close')).trigger('click');
1986            });
1987
1988            subCloseEl.on('click', function(e) {
1989                e.preventDefault();
1990                self.hide();
1991            });
1992
1993            self.element = element;
1994            element.Drawer = 1;
1995        });
1996    },
1997    checkValidity: function(form) {
1998        if(!form) { return; }
1999
2000        let self = this;
2001        let success = 1;
2002        const classNames = {
2003            'input': 'error-input',
2004            'errorEl': 'error-input-msg'
2005        };
2006        const validateTool = [
2007            'required',
2008            'email',
2009            'phone'
2010        ];
2011
2012        self.trim = (s) => {
2013            return s.replace(/^\s+|\s+$/, '');
2014        }
2015
2016        self.validateRequired = (input) => {
2017            if (self.trim(input.value) == '') {
2018                insertError(input, TLANG.form_required || "Bu alan boş bırakılamaz");
2019            }
2020        }
2021
2022        self.validatePhone = (phone) => {
2023            if (phone.value.replaceAll(/\D/g, '').length < Number(phone.dataset.pattern || 12)) {
2024                insertError(phone, TLANG.form_required || "Bu alan boş bırakılamaz");
2025            }
2026        }
2027
2028        self.validateEmail = (email) => {
2029            const re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
2030
2031            if (email.value == '') {
2032                return;
2033            }
2034
2035            if (!re.test(String(email.value).toLowerCase())) {
2036                insertError(email, TLANG.not_email_format || "Email formatına uygun değil");
2037            }
2038        }
2039
2040        const insertError = (el, msg) => {
2041            const errorEl = document.createElement('div');
2042            errorEl.className = classNames.errorEl;
2043            errorEl.innerHTML = msg;
2044
2045            if (el.closest('.input-group') && el.closest('.input-group').querySelector('.input-group-append')) {
2046                errorEl.style.right = (el.closest('.input-group').querySelector('.input-group-append').clientWidth + 6) + 'px';
2047            }
2048
2049            let otherItem = null;
2050            if (el.closest('.city-input-container')) {
2051                otherItem = el.closest('.city-input-container').parentNode.querySelector('.city-select-container select');
2052            } else if (el.closest('.town-input-container')) {
2053                otherItem = el.closest('.town-input-container').parentNode.querySelector('.town-select-container select');
2054            } else if (el.closest('.district-input-container')) {
2055                otherItem = el.closest('.district-input-container').parentNode.querySelector('.district-select-container select');
2056            }
2057
2058            T(el).addClass(classNames.input);
2059            T(el.parentNode).addClass('position-relative');
2060            el.parentNode.insertBefore(errorEl, el.parentNode.lastElementChild.nextSibling);
2061
2062            if (otherItem != null && otherItem.parentNode) {
2063                let otherErrorEl = errorEl.cloneNode(true);
2064                T(otherItem).addClass(classNames.input);
2065                T(otherItem.parentNode).addClass(classNames.input);
2066                otherItem.parentNode.insertBefore(otherErrorEl, otherItem.parentNode.lastElementChild.nextSibling);
2067                T(otherItem).on('focus', () => {
2068                    T(otherItem).removeClass(classNames.input);
2069                    otherErrorEl.remove();
2070                });
2071            }
2072
2073            T(el).on('focus', () => {
2074                T(el).removeClass(classNames.input);
2075                errorEl.remove();
2076            });
2077            success = 0;
2078        }
2079
2080        const clearInputs = () => {
2081            const inputs = Array.from(form.querySelectorAll(`.${classNames.input}`));
2082            if (inputs.length == 0) return;
2083            inputs.forEach(el => {
2084                el.classList.remove(classNames.input);
2085                if (el.parentNode.querySelector(`.${classNames.errorEl}`)) el.parentNode.querySelector(`.${classNames.errorEl}`).remove();
2086            });
2087        }
2088
2089        clearInputs();
2090        Array.from(form.elements).forEach(el => {
2091            let validate = el.getAttribute('data-validate');
2092            if(validate != null) {
2093                validate = validate.split(',');
2094                for (let i = 0; i < validate.length; i++) {
2095                    const element = validate[i];
2096                    if(validateTool.find(x => x == element)) {
2097                        const nameCapitalized = element.charAt(0).toUpperCase() + element.slice(1);
2098                        const fonk = `validate${nameCapitalized}`;
2099                        if(!T(el).hasClass(classNames.input)) {
2100                            self[fonk](el);
2101                        }
2102                    }
2103                }
2104            }
2105        });
2106
2107        return success;
2108    },
2109    qty: function(qty) {
2110        const self = this;
2111
2112        const input = qty.querySelector('input[type="number"]');
2113        const decreaseBtn = qty.querySelector('span.ti-minus');
2114        const increaseBtn = qty.querySelector('span.ti-plus');
2115        const multiItem = T('.product-multiple-item');
2116        let inputOldCount;
2117
2118        self.calculate = function(inc, decimal) {
2119            let oldCount = Number.parseFloat(input.value);
2120            let count = oldCount;
2121
2122            if (inc != 'INPUT') {
2123                let minCount = input.min || 1;
2124                let maxCount = input.max;
2125                count += inc;
2126                if (minCount > count || (maxCount != '' && count > maxCount)) {
2127                    return;
2128                }
2129            } else {
2130                oldCount = inputOldCount;
2131            }
2132
2133            if (!Number.isInteger(count)) count = Number.parseFloat(count.toFixed(decimal));
2134            input.value = count;
2135
2136            if (qty.dataset.multiple && multiItem.length > 0) {
2137                self.multiple(count);
2138            }
2139
2140            const cb = qty.dataset.callback;
2141            if (typeof cb !== 'undefined' && typeof window[cb] === 'function' && (count != oldCount)) {
2142                window[cb](count, oldCount, qty, inc);
2143            }
2144        }
2145
2146        self.multiple = function(qtyCount) {
2147            for (let i = 0; i < multiItem.length; i++) {
2148                if (T('#multiple-price').length > 0) T('#multiple-price')[0].remove();
2149                T(multiItem).removeClass('active');
2150                const item = multiItem[i];
2151
2152                if (item.dataset.min <= qtyCount && item.dataset.max >= qtyCount) {
2153                    T(item).addClass('active');
2154                    if (document.querySelector('.product-multiple-scroll')) document.querySelector('.product-multiple-scroll').scrollTo(item.offsetLeft, 0);
2155
2156                    if (item.closest('#product-multiple-discount').querySelector('.product-multiple-title')) {
2157                        const selector = item.closest('#product-right');
2158                        if (selector == null) return;
2159
2160                        let product = null;
2161                        if (selector.querySelectorAll('.product-price').length) product = T(selector.querySelectorAll('.product-price'));
2162                        if (selector.querySelectorAll('.product-price-not-vat').length) product = T(selector.querySelectorAll('.product-price-not-vat'));
2163
2164                        const price = T(product).attr('data-price') || T(product).text() || 0,
2165                              parse = T.priceToFloat(price);
2166
2167                        const productCurrency = PRODUCT_DATA ? PRODUCT_DATA[0].currency_target : CURRENCY;
2168                        const unitPrice = parse - (parse * item.dataset.percent / 100);
2169                        const multiPrice = T.format((unitPrice) * input.value) + ' ' + productCurrency;
2170                        const element = document.createElement('span');
2171                              element.id = 'multiple-price';
2172                              element.innerHTML = `<div>${multiPrice}</div><div class="multiple-unit-price">${input.value} x ${T.format(unitPrice)} ${productCurrency}</div>`
2173
2174                        item.closest('#product-multiple-discount').querySelector('.product-multiple-title').append(element);
2175                    }
2176                    return;
2177                }
2178            }
2179        }
2180
2181        if (qty.dataset.multiple && multiItem.length > 0) {
2182            multiItem.on('click', (e) => {
2183                let item = e.target.classList['contains']('product-multiple-item') ? e.target : e.target.closest('.product-multiple-item');
2184                input.value = item.dataset.min <= 0 ? 1 : item.dataset.min;
2185                self.calculate('INPUT');
2186            });
2187        }
2188
2189        tInitFn(function() {
2190            if (qty.Qty == 1) return;
2191
2192            const increment = qty.dataset.increment ? qty.dataset.increment : input.step || '1';
2193            const decimal = increment.indexOf('.') > -1 ? increment.replaceAll(/^.*?\./g, '').trim().length : 0;
2194
2195            T(decreaseBtn).on('click', () => self.calculate(increment ? Number.parseFloat(`-${increment}`) : -1, decimal));
2196            T(increaseBtn).on('click', () => self.calculate(increment ? Number.parseFloat(increment) : 1, decimal));
2197
2198            input.addEventListener('focus', () => inputOldCount = Number.parseFloat(input.value));
2199            input.addEventListener('blur', () => self.calculate('INPUT', decimal));
2200
2201            self.qty = qty;
2202            qty.Qty = 1;
2203        });
2204
2205    },
2206    loginForm: function (element) {
2207        const self = this;
2208
2209        self.submit = function(form, submitButton) {
2210            if(!T.checkValidity(form)) {
2211                T.buttonLock.unlock();
2212                return;
2213            }
2214
2215            let loginType = 'email';
2216            const prefix = form.dataset.prefix || '';
2217            const vendor = form.dataset.vendor || 0;
2218            const cb = form.dataset.callback || 'rastgelebirfonksionadi';
2219            const selectedLoginType = (prefix != '') ? (document.getElementById(prefix + 'login-type') != null ? document.getElementById(prefix + 'login-type') : document.getElementById('login-type')) : null;
2220
2221            if (selectedLoginType != null) {
2222                loginType = selectedLoginType.querySelector('li.active').dataset.type;
2223            }
2224
2225            if (form.dataset.vendorcode == "1") {
2226                loginType = 'vendor-code';
2227            }
2228
2229            memberLogin({
2230                type: loginType,
2231                prefix: prefix,
2232                vendor: vendor,
2233                callback: typeof window[cb] === 'function' ? window[cb] : function(){},
2234                submitter: submitButton,
2235                form: form
2236            });
2237        };
2238
2239        tInitFn(function() {
2240            if (1 == element.loginForm)
2241                return;
2242
2243            const prefix = element.dataset.prefix || '';
2244            const email = element.querySelector(`#${prefix}email`);
2245            const phone = element.querySelector(`#${prefix}phone`);
2246            const rememberMe = element.querySelector(`#${prefix}remember`);
2247
2248            if (email) {
2249                const emailVal = T.getCookie('email');
2250                if (emailVal) email.value = emailVal;
2251            }
2252            if (phone) {
2253                const phoneVal = T.getCookie('phone');
2254                if (phoneVal) phone.value = phoneVal;
2255            }
2256            if (rememberMe) {
2257                const rememberVal = T.getCookie('rememberMe');
2258                if (rememberVal) rememberMe.checked = true;
2259            }
2260
2261            T(element).on('submit', e => {
2262                e.preventDefault();
2263                e.stopPropagation();
2264                T.buttonLock.dom = e.submitter;
2265                T.buttonLock.lock();
2266                self.submit(e.target, e.submitter);
2267            });
2268
2269            self.loginForm = element;
2270            element.loginForm = 1;
2271        });
2272    },
2273    otpLogin: function (element) {
2274        const self = this;
2275
2276        const modalOtp = function(receiver, ttl) {
2277            loadSubFolder({
2278                pageId: 5,
2279                blockParentId: 1006,
2280                subFolder: 'otp',
2281                params: {
2282                    receiver: receiver,
2283                    ttl: ttl
2284                },
2285                success:  function(loadRes){
2286                    T.modal({
2287                        id: 'otp-login-popup',
2288                        html: loadRes,
2289                        close: true,
2290                        width: '480px'
2291                    });
2292                }
2293            });
2294        }
2295
2296        self.submit = async function(form) {
2297            if(!T.checkValidity(form)) {
2298                T.buttonLock.unlock();
2299                return;
2300            }
2301
2302            const formData = new FormData(form);
2303            const channel = form.dataset.otpChannel || '';
2304            let otp = formData.get('otp').trim();
2305            if (channel === 'sms') otp = otp.replaceAll(/\D/g, '');
2306
2307            try {
2308                const response = await axios.post(getEndpoint('OTP_REQUEST', encodeURIComponent(otp))
2308);
2309                const result = response.data;
2310                if(result.status == 1) {
2311                    modalOtp(otp, result.ttl || 60);
2312                } else if (result.ttl) {
2313                    modalOtp(otp, result.ttl || 60);
2314                    return;
2315                }
2316
2317                const message = result.statusText;
2318                const field = form.querySelector(`input[name="${result.field}"]`);
2319                if (message) {
2320                    if (field) {
2321                        popoverAlert.show(
2322                            field, 
2323                            message, 
2324                            3000, 
2325                            `btn ${(result.status === true) ? 'btn-success' : 'btn-danger'} text-left`,
2326                            false
2327                        );
2328                    } else {
2329                        T.notify({
2330                            text: message,
2331                            className: result.status == 1 ? 'success' : 'danger',
2332                            duration: 1800,
2333                        });
2334                    }
2335                }
2336            } catch (error) {
2337                console.error(error);
2338            } finally {
2339                T.buttonLock.unlock();
2340            }
2341        }
2342
2343        tInitFn(function() {
2344            if(element.otpLogin == 1) return;
2345
2346            T(element).on('submit', e => {
2347                e.preventDefault();
2348                e.stopPropagation();
2349                T.buttonLock.dom = e.submitter;
2350                T.buttonLock.lock();
2351                self.submit(e.target);
2352            });
2353
2354            self.otpLogin = element;
2355            element.otpLogin = 1;
2356        });
2357    },
2358    setLanguage: {
2359        set: function(element) {
2360            let language = (element.nodeName == 'SELECT' ? element.value : element.dataset.language) || '';
2361            if(language == '') return;
2362
2363            const link_type = T('#link_type')[0],
2364                  link_table_id = T('#link_table_id')[0];
2365
2366            let link = link_type ? `/${link_type.value}` : '';
2367                link += link_table_id ? `/${link_table_id.value}` : '';
2368
2369            axios.get(`/srv/service/language/change/${language}${link}`).then(response => {
2370                const result = response.data;
2371                if(result.success == 1) {
2372                    if (result.link == '') {
2373                        (link_table_id && link_table_id.value == 1) ? window.location.href = '/' : window.location.reload();
2374                    } else {
2375                        window.location.href = '/' + result.link;
2376                    }
2377                }
2378            }).catch(error => console.warn(`Set language error => ${error}`));
2379        },
2380        init: function(element) {
2381            const self = this;
2382            let event = 'click';
2383
2384            if(element.Language == 1) return;
2385            if (element.nodeName == 'SELECT') event = 'change';
2386
2387            T(element).on(event, () => {
2388                T.setLanguage.set(element)
2389            });
2390
2391            self.element = element;
2392            element.Language = 1;
2393        }
2394    },
2395    setCurrency: {
2396        set: function(element, reload = true) {
2397            let currency = (element.nodeName == 'SELECT' ? element.value : element.dataset.currency) || '';
2398            if(currency == '') return;
2399
2400            axios.get(`/srv/shopping/shopping/set-currency/${currency}`).then(response => {
2401                if(response.data == 1) {
2402                    if (reload == true) window.location.reload();
2403                }
2404            }).catch(error => console.warn(`Set currency error => ${error}`));
2405        },
2406        init: function(element) {
2407            const self = this;
2408            let event = 'click';
2409
2410            if(element.Currency == 1) return;
2411            if (element.nodeName == 'SELECT') event = 'change';
2412
2413            T(element).on(event, () => {
2414                T.setCurrency.set(element)
2415            });
2416
2417            self.element = element;
2418            element.Currency = 1;
2419        }
2420    },
2421    vat: function(p, vat) {
2422        if (p > 0 && p <= 0.0000001) {
2423            return 0;
2424        }
2425        let priceParam = Number.isNaN(Number(p)) ? 0.0 : Number.parseFloat(p);
2426        let vatParam = Number.isNaN(Number(vat)) > 0 ? 0 : Number.parseInt(vat);
2427        priceParam = priceParam * (100 + vatParam) / 100;
2428        return T.format(priceParam);
2429    },
2430    format: function(p, d) {
2431        let decimals = typeof d != 'undefined' ? d : typeof DECIMAL_LENGTH !== 'undefined' ? DECIMAL_LENGTH : 2;
2432        let n = !Number.isFinite(Number(+p)) ? 0 : +p,
2433            prec = !Number.isFinite(Number(+decimals)) ? 2 : Math.abs(decimals),
2434            sep = (typeof SEP_THO === 'undefined') ? '.' : SEP_THO,
2435            dec = (typeof SEP_DEC === 'undefined') ? ',' : SEP_DEC,
2436            toFixedFix = function(n, prec) {
2437                const k = Math.pow(10, prec);
2438                return '' + Math.round(n * k) / k;
2439            };
2440        let s = '';
2441
2442        s = (prec ? toFixedFix(n, prec) : '' + Math.round(n)).split('.');
2443        if (s[0].length > 3) {
2444            s[0] = s[0].replaceAll(/\B(?=(?:\d{3})+(?!\d))/g, sep);
2445        }
2446        if ((s[1] || '').length < prec) {
2447            s[1] = s[1] || '';
2448            s[1] += new Array(prec - s[1].length + 1).join('0');
2449        }
2450        return s.join(dec);
2451    },
2452    priceToFloat: function(p) {
2453        if (!p) return false;
2454        p = String(p);
2455        let price = '';
2456        if (SEP_THO === ',') {
2457            price = Number.parseFloat(p.replaceAll(',', ''));
2458        } else if (SEP_DEC == ",") {
2459            price = Number.parseFloat(p.replaceAll('.', '').replace(',', '.'));
2460        } else {
2461            price = Number.parseFloat(p);
2462        }
2463        return price;
2464    },
2465    timeConverter: function(UNIX_timestamp = 0, format = 'd.m.y') {
2466        let time = Number.parseInt(UNIX_timestamp);
2467        if(Number.isNaN(time) || time < 1000000000) {
2468            time = 1000000000;
2469        } else if (time < 9000000000) {
2470            time = time * 1000;
2471        }
2472
2473        const pad  = s => (s < 10) ? '0' + s : s;
2474        const date = new Date(time);
2475
2476        format = format.replaceAll(/y+/ig, date.getFullYear());
2477        format = format.replaceAll(/d+/ig, pad(date.getDate()));
2478        format = format.replaceAll(/m+/ig, pad(date.getMonth() + 1));
2479        format = format.replaceAll(/h+/ig, pad(date.getHours()));
2480        format = format.replaceAll(/i+/ig, pad(date.getMinutes()));
2481        format = format.replaceAll(/s+/ig, pad(date.getSeconds()));
2482
2483        return format;
2484    },
2485    affix: function(element) {
2486        if(T.isMobile()) return;
2487        let self = this,
2488          detectDirect = 0,
2489          tempMarginTop = 0,
2490          topDistance = element.dataset.top || Number(Number(T(`header [data-toggle="sticky"]:not([data-mobile="true"])`).height()) + 10) || 0,
2491          bottomDistance = element.dataset.bottom || 0,
2492          parentElement = document.querySelector(element.dataset.parent) || element.parentElement ||  null,
2493          marginElement = T(parentElement.querySelector(`.affix-margin`))[0];
2494          elementHeight = T(element).height(),
2495          windowHeight = window.innerHeight,
2496          diff = windowHeight - elementHeight,
2497
2498          tInitFn(function() {
2499            if (element == null || element.Sticky == 1 || parentElement == null ) return;
2500
2501            T(element).addClass('position-sticky');
2502            T(parentElement).addClass('position-relative');
2503
2504            if(diff > 0){
2505                element.setAttribute("style", `top:${topDistance}px`);
2506                return;
2507            }
2508
2509            if(!marginElement){
2510                marginElement = document.createElement("div");
2511                marginElement.classList.add("affix-margin");
2512                element.parentNode.insertBefore(marginElement,element);
2513            }
2514
2515            document.addEventListener("scroll", (e) => {
2516                topDistance = element.dataset.top || Number(Number(T(`header [data-toggle="sticky"]:not([data-mobile="true"])`).height()) + 10) || 0,
2517                elementOffsetTop = element.offsetTop;
2518                if (detectDirect < window.pageYOffset) {
2519                    if (elementOffsetTop <= tempMarginTop) { tempMarginTop = elementOffsetTop;}
2520                    element.setAttribute("style", `top:${diff-bottomDistance}px; bottom:auto`);
2521                } else {
2522                    if (elementOffsetTop >= tempMarginTop) { tempMarginTop = elementOffsetTop;}                   
2523                    element.setAttribute("style", `bottom:${diff-topDistance}px; top:auto`);
2524                }
2525                marginElement.style = `margin-top:${tempMarginTop}px`;
2526                detectDirect = window.pageYOffset;
2527            });
2528
2529            self.affix = element;
2530            element.affix = 1;
2531        });
2532    },
2533    sticky: function(element) {
2534        const self = this,
2535              elementHeight = element.offsetHeight,
2536              parentElement = document.querySelector(element.dataset.parent) || null,
2537              elementTop = Number(parentElement.offsetTop),
2538              className = element.dataset.class || 'sticky',
2539              topScroll = Number(element.dataset.scroll || 0),
2540              elementDirect = element.dataset.direction || false,
2541              mobile = element.dataset.mobile || false;
2542
2543        let detectDirect = 0
2544        const direction = () => {
2545            if (elementDirect == false) return;
2546
2547            if (detectDirect < window.pageYOffset) {
2548                T(element).removeClass(`${className}-direction`);
2549            } else if (detectDirect > window.pageYOffset) {
2550                T(element).addClass(`${className}-direction`);
2551            }
2552            detectDirect = window.pageYOffset;
2553        };
2554
2555        tInitFn(function() {
2556            if (element == null || element.Sticky == 1 || parentElement == null) return;
2557
2558            if (mobile == 'true') {
2559                if (!T.isMobile()) return;
2560            }
2561
2562            window.addEventListener('scroll', () => {
2563                if (window.pageYOffset > (topScroll + elementTop)) {
2564                    parentElement.style.paddingTop = `${elementHeight}px`;
2565                    T(parentElement).addClass(`${className}-wrapper`);
2566                    T(element).addClass(className);
2567                    window[String(element.dataset.callback)]?.('active');
2568                    direction();
2569                } else {
2570                    parentElement.style.paddingTop = null;
2571                    T(parentElement).removeClass(`${className}-wrapper`);
2572                    T(element).removeClass(className);
2573                    window[String(element.dataset.callback)]?.('passive');
2574                }
2575            });
2576
2577            self.sticky = element;
2578            element.Sticky = 1;
2579        });
2580    },
2581    buttonLock: {
2582        dom: null,
2583        text: '',
2584        tmp: '',
2585        lock: function() {
2586            const self = this;
2587            if (self.dom == null) 
2588                return;
2589
2590            self.dom.setAttribute('disabled', true);
2591
2592            if (self.dom.nodeName == 'INPUT') {
2593                self.tmp = self.dom.value;
2594                self.text.trim() ? self.dom.value = self.text : '';
2595            } 
2596            else {
2597                self.tmp = self.dom.innerHTML;
2598                self.text.trim() ? self.dom.innerHTML = self.text : '';
2599            }
2600        },
2601        unlock: function() {
2602            const self = this;
2603            if (self.dom == null) 
2604                return;
2605
2606            self.dom.removeAttribute('disabled');
2607
2608            if (self.dom.nodeName == 'INPUT') { self.dom.value = self.tmp; }
2609            else { self.dom.innerHTML = self.tmp; }
2610        }
2611    },
2612    inputFile: function(element) {
2613        const self = this;
2614        const label = element.id ? T(`label[for="${element.id}"]`)[0] : element.nextElementSibling;
2615        const defaultVal = label.querySelector('span').innerHTML || element.placeholder || TLANG.choose_file || 'Dosya Seçiniz';
2616        const changeFile = e => {
2617            const input = e.target;
2618            const fileName = (input.files && input.files.length > 1) ? `${input.files.length} ${TLANG.file || 'Dosya'}` : input.value.split('\\').pop();
2619            label.querySelector('span').innerHTML = fileName || defaultVal;
2620        }
2621        tInitFn(function() {
2622            if(element == null || element.inputFile == 1) 
2623                return;
2624
2625            element.addEventListener('change', changeFile);
2626            element.style.display = 'none';
2627
2628            self.inputFile = element;
2629            element.inputFile = 1;
2630        });
2631    },
2632    equalHeight: function(element) {
2633        const self = this;
2634        const wrapper = typeof element != 'string' ? T(element)[0] : null;
2635        const dom = wrapper == null ? T(element) : T(element.querySelectorAll(`${element.dataset.selector}`));
2636        const selectors = dom.length ? dom : null;
2637
2638        const equalHeightFn = function() {
2639            setTimeout(function() {
2640                selectors.height('auto');
2641                const maxHeight = Math.max(...selectors.height());
2642                selectors.height(maxHeight);
2643                selectors.addClass('height-equalized');
2644            }, 100);
2645        };
2646
2647        tInitFn(function() {
2648            if(selectors == null || element == null) return;
2649            equalHeightFn();
2650            self.equalHeight = element;
2651            element.equalHeight = 1;
2652        });
2653    },
2654    signInGoogleAuth: function(element) {
2655        tInitFn(function() {
2656            if(element.SocialGoogle == 1) return;
2657
2658            T(element).on('click', () => {
2659                googleTokenClientFn();
2660            });
2661
2662            element.SocialGoogle = 1;
2663        });
2664    },
2665    productListLayout: function(element) {
2666        const self = this;
2667        let layout = '';
2668        let event = 'click';
2669        const changeLayout = () => {
2670            layout = (element.nodeName == 'SELECT' ? element.value : element.dataset.layout) || '';
2671            if(layout == '') return;
2672
2673            T.setCookie('selected_layout', layout, 365);
2674            location.reload();
2675        }
2676
2677        tInitFn(function() {
2678            if(element.Layout == 1) return;
2679
2680            if (element.nodeName == 'SELECT') {
2681                event = 'change';
2682            }
2683
2684            T(element).on(event, changeLayout);
2685
2686            self.element = element;
2687            element.Layout = 1;
2688        });
2689    },
2690    shareButton: function(element) {
2691        tInitFn(function() {
2692            if(element.ShareButton == 1) return;
2693
2694            T(element).on('click', () => {
2695                const platform = element.dataset.platform;
2696                const image = element.dataset.image ? (element.dataset.image.startsWith('http') ? element.dataset.image : window.location.origin + element.dataset.image) : '';
2697                const title = element.dataset.title;
2698                const url = window.location.origin + window.location.pathname;
2699
2700                switch(platform) {
2701                    case 'facebook':
2702                        window.open(`https://www.facebook.com/sharer/sharer.php?u=${url}`, '_blank', 'width=600,height=400');
2703                        break;
2704                    case 'twitter':
2705                        window.open(`https://x.com/share?url=${url}&text=${title}`, '_blank', 'width=600,height=400');
2706                        break;
2707                    case 'pinterest':
2708                        window.open(`http://pinterest.com/pin/create/button/?url=${url}&media=${image}&description=${title}`, '_blank', 'width=600,height=400');
2709                        break;
2710                    case 'whatsapp':
2711                        window.open(`https://wa.me/?text=${url} - ${title}`, '_blank', 'width=600,height=400');
2712                        break;
2713                    case 'linkedin':
2714                        window.open(`https://www.linkedin.com/sharing/share-offsite?url=${url}&title=${title}`, '_blank', 'width=600,height=400');
2715                        break;
2716                    default:
2717                        break;
2718                }
2719            });
2720
2721            element.ShareButton = 1;
2722        });
2723    },
2724});
2725
2726const formLoader = options => {
2727    const opt = {
2728        selector: 'form:last',
2729        url: '',
2730        data: null,
2731        callback: function() {}
2732    };
2733
2734    for (let i in options) {
2735        opt[i] = options[i];
2736    }
2737
2738    const fillFormFields = (result) => {
2739        const form = document.querySelector(opt.selector);
2740        for (const key in result) {
2741            const value = result[key];
2742
2743            if (value == null) continue;
2744            if (form == null) return;
2745
2746            const input = form.querySelector(`[name="${key}"]`);
2747
2748            if(input != null) {
2749                if (input.type === 'radio' || input.type === 'checkbox') {
2750                    const inputsRadio = form.querySelectorAll(`[name="${key}"]`);
2751                    Array.from(inputsRadio).forEach(item => {
2752                        (value == item.value || Number.parseInt(value) === 1) ? item.checked = value : '';
2753
2754                        });
2755                } else if(input.value === '' || typeof input.value === "undefined") {
2756                    input.value = value;
2757                }
2758            }
2759        }
2760
2761        opt.callback(result);
2762        return;
2763    };
2764
2765    if (String(opt.url).trim() == '' && opt.data !== null) {
2766        fillFormFields(opt.data);
2767        return;
2768    }
2769
2770    if (String(opt.url).trim() == '') return;
2771
2772    axios.get(opt.url).then(response => {
2773        const result = typeof response.data == 'object' && response.data != '' ? response.data : response;
2774        fillFormFields(result);
2775    }).catch(error => {
2776        console.warn(`FormLoader Error => ${error}`);
2777    });
2778}
2779
2780const taxLoader = options => {
2781    const self = this;
2782    if (LANGUAGE != 'tr') return;
2783    const opt = {
2784        selector: '',
2785        limit: 15,
2786        start: 0,
2787    };
2788
2789    for (let i in options) {
2790        opt[i] = options[i];
2791    }
2792
2793    const element = T(opt.selector)[0];
2794    if (!element) return;
2795
2796    const loadTax = (taxData, taxUl, limit) => {
2797        for (let i=opt.start; i<limit; i++) {
2798            const taxItem = document.createElement('li');
2799                  taxItem.className = 't-tax-list-item';
2800                  taxItem.dataset.value = taxData[i];
2801                  taxItem.innerText = taxData[i];
2802
2803            T(taxItem).on('click', item => {
2804                element.value = item.target.dataset.value;
2805                if (element.parentNode.querySelector('.input-placeholder')) {
2806                    element.parentNode.querySelector('.input-placeholder').classList.add('focused');
2807                }
2808            });
2809            taxUl.append(taxItem);
2810        }
2811        opt.start = limit;
2812    };
2813
2814    axios.get(getEndpoint('TAX_OFFICE_LIST')).then(response => {
2815        const data = response.data;
2816        if ((data !== null || typeof data !== 'undefined')) {
2817            const taxData = data.toString().split("\n"),
2818                  collator = new Intl.Collator(undefined, { numeric: true, sensitivity: 'base' });
2819                  taxData.sort(collator.compare);
2820
2821            element.setAttribute('readonly', 'readonly');
2822            element.classList.add('t-tax-form');
2823            element.parentNode.classList.add('t-tax-office');
2824
2825            const taxHtml = document.createElement('div');
2826                  taxHtml.className = 't-tax-list p-1';
2827                  taxHtml.style.display = 'none';
2828
2829            const taxUl = document.createElement('ul');
2830                  taxUl.className = 'w-100 list-style-none t-tax-list-ul';
2831
2832            const taxSearch = document.createElement('input');
2833                  taxSearch.type = 'search';
2834                  taxSearch.className = 'w-100 form-control form-control-sm no-cancel mb-1 t-tax-search';
2835                  taxSearch.placeholder = TLANG.search || 'Ara';
2836
2837            taxSearch.addEventListener('keyup', event => {
2838                const value = event.target.value,
2839                      searchString = String(value).toLocaleUpperCase('tr-TR'),
2840                      items = taxUl.querySelectorAll('.t-tax-list-item');
2841
2842                if (searchString != '' && searchString.length >= 2) {
2843                    opt.limit = taxData.length;
2844                    loadTax(taxData, taxUl, opt.limit);
2845                    Array.from(items).forEach(li => {
2846                        if(String(li.dataset.value).toLocaleUpperCase('tr-TR').indexOf(searchString) > -1) {
2847                            li.classList.remove('d-none');
2848                        } else {
2849                            li.classList.add('d-none');
2850                        }
2851                    });
2852                } else {
2853                    Array.from(items).forEach(li => {
2854                        li.classList.remove('d-none');
2855                    });
2856                }
2857            });
2858
2859            let count = 1;
2860            taxUl.addEventListener('scroll', () => {
2861                if (taxUl.scrollTop + taxUl.clientHeight >= taxUl.scrollHeight - 1) {
2862                    count ++;
2863                    if (count * opt.limit >= taxData.length) {
2864                        opt.limit = taxData.length;
2865                        loadTax(taxData, taxUl, opt.limit);
2866                        return;
2867                    } else {
2868                        loadTax(taxData, taxUl, (count * opt.limit));
2869                    }
2870                }
2871            });
2872            loadTax(taxData, taxUl, opt.limit);
2873
2874            const taxItem = document.createElement('li');
2875                    taxItem.classList.add('t-tax-list-item');
2876
2877            taxHtml.append(taxSearch);
2878            taxHtml.append(taxUl);
2879            element.parentNode.insertBefore(taxHtml, element);
2880
2881            element.addEventListener('click', () => {
2882                taxHtml.classList.add('show');
2883                taxHtml.style.display = 'block';
2884            });
2885
2886            element.addEventListener('focus', () => {
2887                taxHtml.classList.add('show');
2888                taxHtml.style.display = 'block';
2889            });
2890        }
2891    });
2892
2893    document.addEventListener('click', e => {
2894        let taxDom = e.target.nodeName == 'I' ? e.target.parentElement : e.target;
2895        if (!taxDom.classList.contains('t-tax-form') && !e.target.classList.contains('t-tax-search') && document.querySelectorAll('.t-tax-list.show').length) {
2896            document.querySelector('.t-tax-list').style.display = 'none';
2897            document.querySelector('.t-tax-list.show').classList.remove('show');
2898        }
2899    });
2900}
2901
2902const regionLoader = options => {
2903    const self = this;
2904
2905    const opt = {
2906        country: { selector: '.country:last', value: '' },
2907        city: { selector: '', value: '' },
2908        town: { selector: '', value: '' },
2909        district: { selector: '', value: '' },
2910        countryLimit: true
2911    };
2912
2913    for (let i in options) {
2914        opt[i] = options[i];
2915    }
2916
2917    opt.country.value = opt.country.value || '';
2918    opt.city.value = opt.city.value || '';
2919    opt.town.value = opt.town.value || '';
2920    opt.district.value = opt.district.value || '';
2921
2922    let lastTownParent = null;
2923    let lastDistrictParent = null;
2924
2925    const getInput = input => T(`input[name="${input}"]`).length > 0 ? T(`input[name="${input}"]`)[0] : null;
2926    const hasSelect = selector => selector && T(selector).length > 0;
2927    const getSelect = selector => hasSelect(selector) ? T(selector)[0] : null;
2928
2929    const clearSelectOptions = selector => {
2930        if (!hasSelect(selector)) return;
2931        Array.prototype.forEach.call(T(`${selector} > option:not(:first-child)`), node => {
2932            node.parentNode.removeChild(node);
2933        });
2934    }
2935
2936    const showInput = input => {
2937        const el = getInput(input);
2938        if (el) el.parentNode.classList.remove('d-none');
2939    }
2940
2941    const hideSelect = selector => {
2942        const el = getSelect(selector);
2943        if (!el) return;
2944        el.parentNode.classList.add('d-none');
2945        if (el.dataset.validate) el.dataset.validate = '';
2946    }
2947
2948    const showSelect = selector => {
2949        const el = getSelect(selector);
2950        if (!el) return;
2951        el.parentNode.classList.remove('d-none');
2952    }
2953
2954    const isValueEqual = (left, right) => `${left}`.trim() === `${right}`.trim();
2955
2956    const setInputDisabled = (input, disabled) => {
2957        const el = getInput(input);
2958        if (!el) return;
2959        if (disabled) {
2960            el.setAttribute('disabled', 'disabled');
2961        } else {
2962            el.removeAttribute('disabled');
2963        }
2964    }
2965
2966    const setSelectDisabled = (selector, disabled) => {
2967        const el = getSelect(selector);
2968        if (!el) return;
2969        if (disabled) {
2970            el.setAttribute('disabled', 'disabled');
2971        } else {
2972            el.removeAttribute('disabled');
2973        }
2974    }
2975
2976    const setSelectValue = (selector, value) => {
2977        const selectEl = getSelect(selector);
2978        if (!selectEl) return false;
2979        if (value === undefined || value === null || value === '') return false;
2980        const targetValue = `${value}`.trim();
2981        for (let i = 0; i < selectEl.options.length; i++) {
2982            if (`${selectEl.options[i].value}`.trim() === targetValue) {
2983                selectEl.value = selectEl.options[i].value;
2984                return true;
2985            }
2986        }
2987        return false;
2988    }
2989
2990    const matchSelectValueByText = (selector, text) => {
2991        const selectEl = getSelect(selector);
2992        if (!selectEl || !text) return '';
2993        const targetText = `${text}`.trim();
2994        for (let i = 0; i < selectEl.options.length; i++) {
2995            if (`${selectEl.options[i].text}`.trim() === targetText) {
2996                selectEl.value = selectEl.options[i].value;
2997                return selectEl.options[i].value;
2998            }
2999        }
3000        return '';
3001    }
3002
3003    const resolveSelectedValue = (selector, rawValue) => {
3004        if (setSelectValue(selector, rawValue)) return rawValue;
3005        const asText = matchSelectValueByText(selector, rawValue);
3006        if (asText) return asText;
3007        return '';
3008    }
3009
3010    const useInputFallback = (input, selector, { disableInput = false } = {}) => {
3011        showInput(input);
3012        setInputDisabled(input, disableInput);
3013        if (!hasSelect(selector)) return;
3014        clearSelectOptions(selector);
3015        const selectEl = getSelect(selector);
3016        if (selectEl) selectEl.value = '';
3017        setSelectDisabled(selector, true);
3018        hideSelect(selector);
3019    }
3020
3021    const clearTownInputs = () => {
3022        opt.town.value = '';
3023        opt.district.value = '';
3024        const townInput = getInput('town');
3025        const districtInput = getInput('district');
3026        if (townInput) townInput.value = '';
3027        if (districtInput) districtInput.value = '';
3028    }
3029
3030    const clearDistrictInputs = () => {
3031        opt.district.value = '';
3032        const districtInput = getInput('district');
3033        if (districtInput) districtInput.value = '';
3034    }
3035
3036    const loadCountries = () => {
3037        axios.get(getEndpoint('REGION_COUNTRIES')).then(response => {
3038            const data = response.data;
3039            data.countries = data.countries.map((country) => {
3040                return {
3041                    code: country.code,
3042                    name: country.title,
3043                    pattern : country.pattern
3044                }
3045            });
3046            if (data.countries.length == 1) {
3047                opt.country.value = data.countries[0].code;
3048            }
3049
3050            if (T(opt.country.selector).length < 1) {
3051                if (opt.country.selector == '') {
3052                    loadCities(data.selected || MEMBER_INFO.COUNTRY || 'TR');
3053                }
3054                return false;
3055            }
3056
3057            if (opt.country.value === '') {
3058                opt.country.value = data.selected || MEMBER_INFO.COUNTRY || 'TR';
3059            }
3060
3061            Array.prototype.forEach.call(T(`${opt.country.selector} > option:not(:first-child)`), node => {
3062                node.parentNode.removeChild(node);
3063            });
3064
3065            data.countries.forEach(country => {
3066                let option = document.createElement('option');
3067                option.value = country.code;
3068                option.innerHTML = country.name;
3069                if(country.code == opt.country.value) {
3070                    option.selected = true;
3071                }
3072                document.querySelector(opt.country.selector).appendChild(option);
3073            });
3074
3075            T(opt.country.selector).trigger('change');
3076        }).catch(error => {
3077            console.warn(`Country Loaded Error => ${error}`);
3078            return;
3079        });
3080    }
3081
3082    const loadCities = (parentCode = 'TR') => {
3083        const flagInputs = document.querySelectorAll('[data-flag-masked]');
3084        Array.from(flagInputs).forEach(item => {
3085            if (item.value != '') return;
3086
3087            if (item.dataset.key != parentCode) {
3088                try {
3089                    tFlag.changePhoneMask(null, item, parentCode);
3090                } catch (error) {
3091                }
3092            }
3093
3094            });
3095
3096        if (T(opt.city.selector).length < 1) {
3097            useInputFallback('city', opt.city.selector);
3098            useInputFallback('town', opt.town.selector);
3099            useInputFallback('district', opt.district.selector);
3100            return false;
3101        }
3102
3103        axios.get(getEndpoint('REGION_CITIES', parentCode)).then(response => {
3104            const data = response.data.cities;
3105
3106            if (data.length < 1) {
3107                useInputFallback('city', opt.city.selector);
3108                useInputFallback('town', opt.town.selector);
3109                useInputFallback('district', opt.district.selector);
3110                return;
3111            }
3112
3113            setInputDisabled('town', true);
3114            setInputDisabled('district', true);
3115            setSelectDisabled(opt.city.selector, false);
3116
3117            const cityInput = getInput('city');
3118            if (cityInput) cityInput.parentNode.classList.add('d-none');
3119            showSelect(opt.city.selector);
3120
3121            if(T('[name="province"]').length > 0) {
3122                const smallCode = parentCode.toLowerCase();
3123                if (['us', 'cn', 'de', 'ru', 'gb', 'in', 'es'].includes(smallCode)) {
3124                    T('[name="province"]')[0].closest('.popover-wrapper:first').classList.add('d-none');
3125                } else {
3126                    T('[name="province"]')[0].closest('.popover-wrapper:first').classList.remove('d-none');
3127                }
3128            }
3129
3130            clearSelectOptions(opt.city.selector);
3131
3132            data.forEach(city => {
3133                let option = document.createElement('option');
3134                option.value = city.code;
3135                option.innerHTML = city.title;
3136                option.selected = isValueEqual(opt.city.value, city.code);
3137                document.querySelector(opt.city.selector).appendChild(option);
3138            });
3139
3140            opt.city.value = resolveSelectedValue(opt.city.selector, opt.city.value);
3141            T(opt.city.selector).trigger('change');
3142        }).catch(() => {
3143            useInputFallback('city', opt.city.selector);
3144            useInputFallback('town', opt.town.selector);
3145            useInputFallback('district', opt.district.selector);
3146        });
3147    }
3148
3149    const loadTowns = parentCode => {
3150        if (!parentCode) {
3151            clearTownInputs();
3152            const hasCityOptions = hasSelect(opt.city.selector) && T(`${opt.city.selector} > option:not(:first-child)`).length > 0;
3153            useInputFallback('town', opt.town.selector, { disableInput: hasCityOptions });
3154            useInputFallback('district', opt.district.selector, { disableInput: hasCityOptions });
3155            return false;
3156        } else {
3157            setInputDisabled('town', false);
3158            setSelectDisabled(opt.town.selector, false);
3159        }
3160
3161        if (lastTownParent !== null && parentCode !== lastTownParent) {
3162            clearTownInputs();
3163        }
3164        lastTownParent = parentCode;
3165        lastDistrictParent = null;
3166
3167        if (T(opt.town.selector).length < 1) {
3168            useInputFallback('town', opt.town.selector);
3169            useInputFallback('district', opt.district.selector);
3170            return false;
3171        }
3172
3173        axios.get(getEndpoint('REGION_TOWN', parentCode)).then(response => {
3174            let data = response.data.towns;
3175
3176            if (data.length < 1) {
3177                useInputFallback('town', opt.town.selector);
3178                useInputFallback('district', opt.district.selector);
3179                return;
3180            }
3181
3182            data = data.sort((a, b) => a.title.localeCompare(b.title));
3183
3184            const townInput = getInput('town');
3185            if (townInput) townInput.parentNode.classList.add('d-none');
3186            showSelect(opt.town.selector);
3187
3188            clearSelectOptions(opt.town.selector);
3189
3190            data.forEach(town => {
3191                let option = document.createElement('option');
3192                option.value = town.code;
3193                option.innerHTML = town.title;
3194                option.selected = isValueEqual(opt.town.value, town.code);
3195                document.querySelector(opt.town.selector).appendChild(option);
3196            });
3197
3198            opt.town.value = resolveSelectedValue(opt.town.selector, opt.town.value);
3199            if (!opt.town.value) {
3200                setInputDisabled('district', true);
3201            }
3202            T(opt.town.selector).trigger('change');
3203        }).catch(() => {
3204            useInputFallback('town', opt.town.selector);
3205            useInputFallback('district', opt.district.selector);
3206        });
3207    }
3208
3209    const loadDistricts = parentCode => {
3210        if (!parentCode) {
3211            clearDistrictInputs();
3212            const hasTownOptions = hasSelect(opt.town.selector) && T(`${opt.town.selector} > option:not(:first-child)`).length > 0;
3213            useInputFallback('district', opt.district.selector, { disableInput: hasTownOptions });
3214            return false;
3215        } else {
3216            setInputDisabled('district', false);
3217            setSelectDisabled(opt.district.selector, false);
3218        }
3219
3220        if (lastDistrictParent !== null && parentCode !== lastDistrictParent) {
3221            clearDistrictInputs();
3222        }
3223        lastDistrictParent = parentCode;
3224
3225        if (T(opt.district.selector).length < 1) {
3226            useInputFallback('district', opt.district.selector);
3227            return false;
3228        }
3229
3230        axios.get(getEndpoint('REGION_DISTRICTS', parentCode)).then(response => {
3231            let data = response.data.districts;
3232
3233            if (data.length < 1) {
3234                useInputFallback('district', opt.district.selector);
3235                return;
3236            }
3237
3238            data = data.sort((a, b) => a.title.localeCompare(b.title));
3239
3240            clearSelectOptions(opt.district.selector);
3241
3242            data.forEach(district => {
3243                let option = document.createElement('option');
3244                option.value = district.code;
3245                option.dataset.postacode = district.postalcode || '';
3246                option.innerHTML = district.title;
3247                option.selected = opt.district.value == district.code;
3248                document.querySelector(opt.district.selector).appendChild(option);
3249            });
3250
3251            if (T(`${opt.district.selector} > option[value="${opt.district.value}"]`).length > 0) {
3252                T(opt.district.selector)[0].value = opt.district.value;
3253                T(opt.district.selector).trigger('change');
3254            }
3255            const districtInput = getInput('district');
3256            if (districtInput) districtInput.parentNode.classList.add('d-none');
3257            showSelect(opt.district.selector);
3258        }).catch(() => {
3259            useInputFallback('district', opt.district.selector);
3260        });
3261    }
3262
3263    T(opt.country.selector).on('change', e => {
3264        loadCities(e.target.value);
3265    });
3266
3267    T(opt.city.selector).on('change', e => {
3268        loadTowns(e.target.value);
3269        if (T('[name="city"]').length > 0 && T(opt.city.selector)[0].name != 'city' && T(opt.city.selector)[0].value != '') {
3270            T('[name="city"]')[0].value = T(opt.city.selector)[0].options[T(opt.city.selector)[0].options.selectedIndex].text;
3271        }
3272    });
3273
3274    T(opt.town.selector).on('change', e => {
3275        loadDistricts(e.target.value);
3276        if (T('[name="town"]').length > 0 && T(opt.town.selector)[0].name != 'town' && T(opt.city.selector)[0].value != '') {
3277            T('[name="town"]')[0].value = T(opt.town.selector)[0].options[T(opt.town.selector)[0].options.selectedIndex].text;
3278        }
3279    });
3280
3281    T(opt.district.selector).on('change', e => {
3282        if (T('[name="district"]').length > 0 && T(opt.district.selector)[0].name != 'district' && T(opt.city.selector)[0].value != '') {
3283            T('[name="district"]')[0].value = T(opt.district.selector)[0].options[T(opt.district.selector)[0].options.selectedIndex].text;
3284            const postacode = T(opt.district.selector)[0].options[T(opt.district.selector)[0].options.selectedIndex].dataset.postacode || '';
3285            if (T('[name="post_code"]').length > 0) T('[name="post_code"]')[0].value = postacode;
3286        }
3287    });
3288
3289    loadCountries();
3290}
3291
3292const tsRegion = options => {
3293    const self = this;
3294
3295    const opt = {
3296        container: '.regions',
3297        countryLimit: 1,
3298        storeLimit: 0,
3299        regionLimit: null,
3300        country: {
3301            container: '.country-container',
3302            select: '.country-select',
3303            value: '',
3304            caption: ''
3305        },
3306        state: {
3307            container: '.state-container',
3308            select: '.state-select',
3309            selectContainer: '.state-select-container',
3310            input: '.state-input',
3311            inputContainer: '.state-input-container',
3312            value: '',
3313            caption: ''
3314        },
3315        city: {
3316            container: '.city-container',
3317            select: '.city-select',
3318            selectContainer: '.city-select-container',
3319            input: '.city-input',
3320            inputContainer: '.city-input-container',
3321            value: '',
3322            caption: ''
3323        },
3324        town: {
3325            container: '.town-container',
3326            select: '.town-select',
3327            selectContainer: '.town-select-container',
3328            input: '.town-input',
3329            inputContainer: '.town-input-container',
3330            value: '',
3331            caption: ''
3332        },
3333        district: {
3334            container: '.district-container',
3335            select: '.district-select',
3336            selectContainer: '.district-select-container',
3337            input: '.district-input',
3338            inputContainer: '.district-input-container',
3339            value: '',
3340            caption: ''
3341        }
3342    };
3343
3344    if (typeof options == "object") {
3345        for (let i in options) {
3346            if (typeof options[i] == "object") {
3347                for (let j in options[i]) {
3348                    opt[i][j] = options[i][j];
3349                }
3350            } else {
3351                opt[i] = options[i];
3352            }
3353        }
3354    }
3355
3356    const c = opt;
3357    const l = {
3358        country: [],
3359        state: [],
3360        city: [],
3361        town: [],
3362        district: []
3363    };
3364
3365    const v = {
3366        country: opt.country.value || "",
3367        state: opt.state.value || "",
3368        city: opt.city.value || "",
3369        town: opt.town.value || "",
3370        district: opt.district.value || ""
3371    };
3372
3373    const vc = {
3374        country: opt.country.caption || "",
3375        state: opt.state.caption || "",
3376        city: opt.city.caption || "",
3377        town: opt.town.caption || "",
3378        district: opt.district.caption || ""
3379    };
3380    const mapSTypes = {
3381        country: 'U',
3382        state: 'E',
3383        city: 'S',
3384        town: 'I',
3385        district: 'M'
3386    };
3387
3388    const getInputEl = what => T(`${c.container} ${c[what].input}`).length ? T(`${c.container} ${c[what].input}`)[0] : null;
3389    const getSelectEl = what => T(`${c.container} ${c[what].select}`).length ? T(`${c.container} ${c[what].select}`)[0] : null;
3390    const setInputDisabled = (what, disabled) => {
3391        const el = getInputEl(what);
3392        if (!el) return;
3393        el.disabled = !!disabled;
3394        if (disabled) {
3395            el.setAttribute('disabled', 'disabled');
3396        } else {
3397            el.removeAttribute('disabled');
3398        }
3399    };
3400    const setSelectDisabled = (what, disabled) => {
3401        const el = getSelectEl(what);
3402        if (!el) return;
3403        el.disabled = !!disabled;
3404        if (disabled) {
3405            el.setAttribute('disabled', 'disabled');
3406        } else {
3407            el.removeAttribute('disabled');
3408        }
3409    };
3410    const getInputDisabledState = what => {
3411        const country = getCountry(v.country) || {};
3412        const needsState = !!country.has_state && l.state.length > 0;
3413        const cityDisabled = needsState && !v.state;
3414        const townDisabled = (l.city.length > 0 && !v.city) || cityDisabled;
3415
3416        switch (what) {
3417            case 'city':
3418                return cityDisabled;
3419            case 'town':
3420                return townDisabled;
3421            case 'district':
3422                return (l.town.length > 0 && !v.town) || townDisabled;
3423            default:
3424                return false;
3425        }
3426    };
3427    const applyDisabledRules = () => {
3428        if (l.city.length === 0) setInputDisabled('city', getInputDisabledState('city'));
3429        if (l.town.length === 0) setInputDisabled('town', getInputDisabledState('town'));
3430        if (l.district.length === 0) setInputDisabled('district', getInputDisabledState('district'));
3431    };
3432
3433    const getCountry = (code) => {
3434        for (let i in l.country) {
3435            if (l.country[i].code == code) {
3436                const item = l.country[i];
3437                item.has_state = item.has_state == 1;
3438                return item;
3439            }
3440        }
3441    };
3442
3443    const loadCountries = function() {
3444        const rf = (result) => {
3445            if (result.countries) {
3446                if(opt.countryLimit){
3447                    result.countries = result.countries.filter(function(item){
3448                        return !MEMBER_INFO.E_COUNTRY || item.code == MEMBER_INFO.E_COUNTRY
3449                    });
3450                }
3451                l.country = result.countries;
3452                let ob = T(`${c.container} ${c.country.select}`),
3453                      cExists = false;
3454
3455                if (ob.length) {
3456                    result.countries.forEach(item => {
3457                        let option = document.createElement('option');
3458                        option.value = item.code;
3459                        option.innerHTML = item.title;
3460                        ob[0].appendChild(option);
3461                        if (item.code == v.country) { cExists = true; }
3462                    });
3463                }
3464
3465                if (v.country == "" || !cExists) {
3466                    if (result.countries && result.countries.length && result.countries.length == 1) {
3467                        v.country = result.countries[0].code;
3468                    } else if (result.selected && getCountry(result.selected)) {
3469                        v.country = result.selected;
3470                    } else if (getCountry("TR")) {
3471                        v.country = "TR";
3472                    } else if (result.countries.length > 0) {
3473                        v.country = result.countries[0].code;
3474                    }
3475                }
3476                if (ob.length) {
3477                    ob[0].value = v.country;
3478                    T.placeholder.reset(ob[0]);
3479                }
3480                loadStates();
3481            } else { 
3482
3483            }
3484        };
3485        axios.get(getEndpoint('COUNTRY', '1?lang='+LANGUAGE+'&country='+(MEMBER_INFO.COUNTRY || 'TR'))).then(res => {
3486            const data = res.data;
3487            rf(data);
3488        });
3489    };
3490
3491    const _loadRegion = (what, parent) => {
3492        _reset(what);
3493        const rf = (result) => {
3494            const items = result && result.data ? result.data : [];
3495            l[what] = items;
3496            _render(what, items);
3497        };
3498        if (!parent) {
3499            rf();
3500        } else {
3501            const data = { storeLimit: opt.storeLimit };
3502            switch (what) {
3503                case 'country':
3504                    break;
3505                case 'state':
3506                    data.U = v.country;
3507                    break;
3508                case 'city':
3509                    data.U = v.country;
3510                    data.E = v.state;
3511                    break;
3512                case 'town':
3513                    data.U = v.country;
3514                    data.E = v.state;
3515                    data.S = v.city;
3516                    break;
3517                case 'district':
3518                    data.U = v.country;
3519                    data.E = v.state;
3520                    data.S = v.city;
3521                    data.I = v.town;
3522                    break;
3523            }
3524
3525            let formData = new FormData();
3526            for (let key in data) {
3527                formData.append(key, data[key]);
3528            }
3529
3530            let lmt = opt.regionLimit != null ? opt.regionLimit : (opt.countryLimit ? "1" : "0");
3531            axios.post(getEndpoint('REGION', `${mapSTypes[what]}/${parent}/${lmt}`), formData).then(res => {
3532                const data = res.data;
3533                rf(data);
3534            });
3535        }
3536        return;
3537    };
3538
3539    const loadStates = () => {
3540        const flagInputs = document.querySelectorAll('[data-flag-masked]');
3541        Array.from(flagInputs).forEach(item => {
3542            if (item.value != '') return;
3543
3544            if (item.dataset.key != v.country) {
3545                try {
3546                    tFlag.changePhoneMask(null, item, v.country);
3547                } catch (error) {
3548                }
3549            }
3550
3551            });
3552
3553        T(`${c.container} ${c.state.container}`).hide();
3554        _reset("state");
3555        let item = getCountry(v.country) || {};
3556        if (!item.has_state) {
3557            loadCities();
3558            return;
3559        }
3560        T(`${c.container} ${c.state.container}`).show();
3561        _loadRegion("state", v.country);
3562    };
3563
3564    const loadCities = () => {
3565        let item = getCountry(v.country) || {};
3566        let pc = item.has_state ? v.state : v.country;
3567        _loadRegion("city", pc);
3568    };
3569
3570    const loadTowns = () => {
3571        _loadRegion("town", v.city);
3572    };
3573
3574    const loadDistricts = () => {
3575        _loadRegion("district", v.town);
3576    };
3577
3578    const _render = (what, data) => {
3579        if (data.length == 0) {
3580            T(`${c.container} ${c[what].selectContainer}`).hide();
3581            T(`${c.container} ${c[what].inputContainer}`).show();
3582            if (T(`${c.container} ${c[what].input}`).length) {
3583                T(`${c.container} ${c[what].input}`)[0].value = vc[what];
3584                T.placeholder.reset(T(`${c.container} ${c[what].input}`)[0]);
3585            }
3586            setInputDisabled(what, getInputDisabledState(what));
3587            setSelectDisabled(what, true);
3588            applyDisabledRules();
3589        } else {
3590            T(`${c.container} ${c[what].selectContainer}`).show();
3591            T(`${c.container} ${c[what].inputContainer}`).hide();
3592            if (T(`${c.container} ${c[what].input}`).length) {
3593                T(`${c.container} ${c[what].input}`)[0].value = '';
3594            }
3595            setInputDisabled(what, true);
3596            setSelectDisabled(what, false);
3597
3598            const ob = T(`${c.container} ${c[what].select}`);
3599
3600            if (!ob.length) return;
3601
3602            const rCodes = [];
3603
3604            ob.html("<option value=''>" + ob[0].getAttribute('placeholder') + "</option>");
3605
3606            data.forEach(item => {
3607                let option = document.createElement('option');
3608                option.value = item.code;
3609                if (what == 'district') option.dataset.postacode = item.postalcode || '';
3610                option.innerHTML = item.title;
3611                ob[0].appendChild(option);
3612                rCodes.push(item.code);
3613            });
3614
3615            if (rCodes.indexOf(v[what]) == -1) {
3616                v[what] = '';
3617                switch (what) {
3618                    case 'state':
3619                        v.city = '';
3620                        v.town = '';
3621                        v.district = '';
3622                        break;
3623                    case 'city':
3624                        v.town = '';
3625                        v.district = '';
3626                        break;
3627                    case 'town':
3628                        v.district = '';
3629                        break;
3630                }
3631                if (rCodes.length == 1) {
3632                    ob[0].value = rCodes[0];
3633                    T(ob).trigger('change');
3634                    return;
3635                }
3636            } else {
3637                ob[0].value = v[what];
3638            }
3639            T.placeholder.reset(ob[0]);
3640        }
3641        /* after render */
3642        switch (what) {
3643            case 'state':
3644                loadCities();
3645                break;
3646            case 'city':
3647                loadTowns();
3648                break;
3649            case 'town':
3650                loadDistricts();
3651                break;
3652        }
3653        applyDisabledRules();
3654    };
3655
3656    const _reset = (type) => {
3657        let obs = {},
3658            $typeIdx = 0,
3659            $totalIdx = 4;
3660        obs[1] = c.state;
3661        obs[2] = c.city;
3662        obs[3] = c.town;
3663        obs[4] = c.district;
3664
3665        switch (type) {
3666            case 'state':
3667                $typeIdx = 1;
3668                break;
3669            case 'city':
3670                $typeIdx = 2;
3671                break;
3672            case 'town':
3673                $typeIdx = 3;
3674                break;
3675            case 'district':
3676                $typeIdx = 4;
3677                break;
3678        }
3679
3680        for (let i = $typeIdx; i <= $totalIdx; i++) {
3681            T(`${c.container} ${obs[i].select}`).html('');
3682            if (T(`${c.container} ${obs[i].input}`).length) T(`${c.container} ${obs[i].input}`)[0].value = '';
3683            T(`${c.container} ${obs[i].selectContainer}`).hide();
3684            T(`${c.container} ${obs[i].inputContainer}`).show();
3685            if (i === 1) l.state = [];
3686            if (i === 2) l.city = [];
3687            if (i === 3) l.town = [];
3688            if (i === 4) l.district = [];
3689        }
3690        applyDisabledRules();
3691    };
3692
3693    const _listener = () => {
3694        const rs = ["state", "city", "town", "district"];
3695        T(`${c.container} ${c.country.select}`).on('change', el => {
3696            const _this = el.target;
3697            if (_this.dataset.value == _this.value) {
3698                return;
3699            }
3700            _this.dataset.value = _this.value;
3701
3702            v.country = el.target.value;
3703            for (i = 0; i < rs.length; i++) {
3704                vc[rs[i]] = '';
3705                v[rs[i]] = '';
3706            }
3707            loadStates();
3708        });
3709        T(`${c.container} ${c.state.select}`).on('change', el => {
3710            const _this = el.target;
3711            if (_this.dataset.value == _this.value) {
3712                return;
3713            }
3714            _this.dataset.value = _this.value;
3715
3716            v.state = el.target.value;
3717            for (i = 1; i < rs.length; i++) {
3718                vc[rs[i]] = '';
3719                v[rs[i]] = '';
3720            }
3721            loadCities();
3722        });
3723        T(`${c.container} ${c.city.select}`).on('change', el => {
3724            const _this = el.target;
3725            if (_this.dataset.value == _this.value) {
3726                return;
3727            }
3728            _this.dataset.value = _this.value;
3729
3730            v.city = el.target.value;
3731            for (i = 2; i < rs.length; i++) {
3732                vc[rs[i]] = '';
3733                v[rs[i]] = '';
3734            }
3735            loadTowns();
3736        });
3737        T(`${c.container} ${c.town.select}`).on('change', el => {
3738            const _this = el.target;
3739            if (_this.dataset.value == _this.value) {
3740                return;
3741            }
3742            _this.dataset.value = _this.value;
3743
3744            v.town = el.target.value;
3745            for (i = 3; i < rs.length; i++) {
3746                vc[rs[i]] = '';
3747                v[rs[i]] = '';
3748            }
3749            loadDistricts();
3750        });
3751        T(`${c.container} ${c.district.select}`).on('change', el => {
3752            const _this = el.target;
3753            if (_this.dataset.value == _this.value) {
3754                return;
3755            }
3756            _this.dataset.value = _this.value;
3757
3758            v.district = el.target.value;
3759
3760            const postacode = T(`${c.container} ${c.district.select}`)[0].options[T(`${c.container} ${c.district.select}`)[0].options.selectedIndex].dataset.postacode || '';
3761            if (T('[name="post_code"]').length > 0) T('[name="post_code"]')[0].value = postacode;
3762        });
3763
3764        T(`${c.container} ${c.state.input}`).on('keyup', el => {
3765            vc.state = el.target.value;
3766        });
3767        T(`${c.container} ${c.city.input}`).on('keyup', el => {
3768            vc.city = el.target.value;
3769        });
3770        T(`${c.container} ${c.town.input}`).on('keyup', el => {
3771            vc.town = el.target.value;
3772        });
3773        T(`${c.container} ${c.district.input}`).on('keyup', el => {
3774            vc.district = el.target.value;
3775        });
3776    };
3777
3778    _listener();
3779    loadCountries();
3780}
3781
3782const loadSubFolder = function(options){
3783    if(!options.pageId && !blockParentId && !subFolder) {
3784        return;
3785    }
3786
3787    const defOptions = {
3788        pageId : options.pageId || 0, 
3789        blockParentId: options.blockParentId || 0,
3790        subFolder: options.subFolder || "",
3791        params:  options.params || {},
3792        success :  options.success || function(){}
3793    }
3794
3795    const params = {};
3796    for(let key in defOptions.params){
3797        params[key] = defOptions.params[key];
3798    }
3799
3800    const url = `/srv/service/content-v5/sub-folder/${defOptions.pageId}/${defOptions.blockParentId}/${defOptions.subFolder}`;
3801    axios.get(url, {params: params}).then(response => {
3802        defOptions.success(response.data);
3803    }).catch(error => {
3804        console.error(`Sub folder load error => ${error}`);
3805    });
3806}
3807
3808const Cart = {
3809    callback: {
3810        update: null,
3811        updateAll: null,
3812        delete: null,
3813        deleteAll: null,
3814        load: [],
3815        add: [],
3816    },
3817    storageKey : 'Cart',
3818    update: function(sessIndex, count, callback) {
3819        axios.get(`/srv/service/cart/update-item/${sessIndex}/${count}`).then(response => {
3820            const res = response.data;
3821            if (typeof mobileApp !== 'undefined') {
3822                try {
3823                    mobileApp.changedCartCount(res.totalQuantity);
3824                } catch (err) {}
3825            }
3826            if (typeof webkit !== 'undefined') {
3827                try {
3828                    webkit.messageHandlers.callbackHandler.postMessage(res.totalQuantity);
3829                } catch (err) {}
3830            }
3831            Cart.setStorage('update',res,sessIndex);
3832
3833            for(let i=0; i < callbacks.cart.update.length; i++){
3834                if(typeof callbacks.cart.update[i] === 'function'){
3835                    try {
3836                        callbacks.cart.update[i]?.(res);
3837                    } catch (error) { console.log(`Cart Update Callback Error => ${error}`); }
3838                }
3839            }
3840
3841            if (typeof callback === 'function') {
3842                callback(res);
3843                if (typeof Cart.callback.update === 'function') {
3844                    Cart.callback.update(res);
3845                }
3846            } else {
3847                T.modal({
3848                    width: '400px',
3849                    html: res.statusText
3850                });
3851                setTimeout(function() {
3852                    window.location.reload();
3853                }, 2500);
3854            }
3855        }).catch(error => console.warn(`Error cart update => ${error}`));
3856    },
3857    updateAll: function(countList, callback) {
3858        const param = typeof countList === 'object' ? countList.join('-') : countList;
3859        axios.get(`/srv/service/cart/update/${param}`).then(response => {
3860            const res = response.data;
3861            if (typeof mobileApp !== 'undefined') {
3862                try {
3863                    mobileApp.changedCartCount(res.totalQuantity);
3864                } catch (err) {}
3865            }
3866            if (typeof webkit !== 'undefined') {
3867                try {
3868                    webkit.messageHandlers.callbackHandler.postMessage(res.totalQuantity);
3869                } catch (err) {}
3870            }
3871
3872            for(let i=0; i < callbacks.cart.updateAll.length; i++){
3873                if(typeof callbacks.cart.updateAll[i] === 'function'){
3874                    try {
3875                        callbacks.cart.updateAll[i]?.(res);
3876                    } catch (error) { console.log(`Cart UpdateAll Callback Error => ${error}`); }
3877                }
3878            }
3879
3880            if (typeof callback === 'function') {
3881                callback(res);
3882                if (typeof Cart.callback.updateAll === 'function') {
3883                    Cart.callback.updateAll(res);
3884                }
3885            } else {
3886                window.location.reload();
3887            }
3888        }).catch(error => console.warn(`Error cart updateAll => ${error}`));
3889    },
3890    delete: function(sessIndex, callback) {
3891        axios.get(`/srv/service/cart/delete/${sessIndex}`).then(response => {
3892            const res = response.data;
3893            if (typeof mobileApp !== 'undefined') {
3894                try {
3895                    mobileApp.changedCartCount(res.totalQuantity);
3896                } catch (err) {}
3897            }
3898            if (typeof webkit !== 'undefined') {
3899                try {
3900                    webkit.messageHandlers.callbackHandler.postMessage(res.totalQuantity);
3901                } catch (err) {}
3902            }
3903
3904            Cart.setStorage('delete',response,sessIndex);
3905
3906            for(let i=0; i < callbacks.cart.delete.length; i++){
3907                if(typeof callbacks.cart.delete[i] === 'function'){
3908                    try {
3909                        callbacks.cart.delete[i]?.(res);
3910                    } catch (error) { console.log(`Cart Delete Callback Error => ${error}`); }
3911                }
3912            }
3913
3914            if (typeof callback === 'function') {
3915                callback(res);
3916                if (typeof Cart.callback.delete === 'function') {
3917                    Cart.callback.delete(res);
3918                }
3919            } else if (typeof window[callback] === 'function') {
3920                window[callback](res);
3921                if (typeof Cart.callback.delete === 'function') {
3922                    Cart.callback.delete(res);
3923                }
3924            } else {
3925                window.location.reload();
3926            }
3927        }).catch(error => console.warn(`Error cart delete => ${error}`));
3928    },
3929    deleteAll: function(callback) {
3930        axios.get(`/srv/service/cart/delete-all`).then(response => {
3931            const res = response.data;
3932            if (typeof mobileApp !== 'undefined') {
3933                try {
3934                    mobileApp.changedCartCount(0);
3935                } catch (err) {}
3936            }
3937            if (typeof webkit !== 'undefined') {
3938                try {
3939                    webkit.messageHandlers.callbackHandler.postMessage(0);
3940                } catch (err) {}
3941            }
3942
3943            Cart.setStorage('deleteAll');
3944
3945            for(let i=0; i < callbacks.cart.deleteAll.length; i++){
3946                if(typeof callbacks.cart.deleteAll[i] === 'function'){
3947                    try {
3948                        callbacks.cart.deleteAll[i]?.(res);
3949                    } catch (error) { console.log(`Cart DeleteAll Callback Error => ${error}`); }
3950                }
3951            }
3952
3953            if (typeof Cart.callback.deleteAll === 'function') {
3954                Cart.callback.deleteAll(res);
3955            }
3956            if (typeof callback === 'function') {
3957                callback(res);
3958            } else {
3959                setTimeout(function() {
3960                    window.location.reload();
3961                }, 750);
3962            }
3963        }).catch(error => console.warn(`Error cart deleteAll => ${error}`));
3964    },
3965    setStorage : function(action,response,index){
3966        if(typeof window.localStorage === 'undefined'){
3967            return false;
3968        }
3969        let storage = window.localStorage.getItem(Cart.storageKey);
3970        if(storage === null){
3971            storage = {  summary : {   },    items : []  };
3972        }else{
3973            storage = JSON.parse(storage);
3974        }
3975
3976        switch(action) {
3977            case 'update':
3978            case 'add':
3979                if(response.cartProducts === null){
3980                    return false;
3981                }
3982                storage.items = response.cartProducts;
3983                storage.summary = { total : response.totalPrice};
3984                break;
3985
3986            case 'delete':
3987                if (storage && storage.items) {
3988                    if(storage.items.length === 0){
3989                        return false;
3990                    }
3991                    storage.items.splice(index,1);
3992                    storage.summary.total = response.priceCart;
3993                    break;
3994                }
3995
3996            case 'deleteAll':
3997                storage.items  = [];
3998                storage.summary = { total : 0};
3999                break;
4000        }
4001
4002        window.localStorage.setItem(Cart.storageKey,JSON.stringify(storage));
4003        return true;
4004    },
4005    getStorage : function(){
4006        let storage = window.localStorage.getItem(Cart.storageKey);
4007        if(storage === null){
4008            storage = [];
4009        }else{
4010            storage = JSON.parse(storage);
4011        }
4012        return storage;
4013    }
4014}
4015
4016const OrderCallback = {
4017    address: [],
4018    payment: [],
4019    paymentChange: [],
4020    approve: [],
4021}
4022
4023const addToSelectionProducts = function() {
4024    const inputs = T('input.multiple-ids-cart:checked');
4025
4026    if(inputs.length < 1) {
4027        T.notify({
4028            text: TLANG.no_products_selected || 'Seçili ürün bulunmamaktadır',
4029            className: 'danger',
4030            duration: 1800,
4031        });
4032        return;
4033    }
4034
4035    const pids = [], 
4036          variants = [],
4037          counts = [];
4038
4039    Array.from(inputs).forEach(input => {
4040        const id = input.value;
4041        const variant = T(`#subPro${input.dataset.target}`);
4042        const p_count = T(`#ProductCount${input.dataset.target}`);
4043        pids.push(id);
4044        variants.push(variant.length > 0 ? variant[0].value : 0);
4045        counts.push(p_count.length > 0 ? p_count[0].value : 1);
4046    });
4047
4048    if (pids.length < 1) return;
4049    multiCart = true;
4050    addToCart(pids, variants, counts);
4051};
4052
4053const destroySelectionProducts = function() {
4054    const inputs = T('input.multiple-ids-cart:checked') || [];
4055    Array.from(inputs).forEach(input => {
4056        input.checked = false;
4057    });
4058};
4059
4060const addToCart = function(options) {
4061    const personalizationPid = [];
4062    let opt = {
4063        productId: 0,
4064        variantId: 0,
4065        quantity: 0,
4066        buyNow: 0,
4067        redirect: PAGE_LINK.CART,
4068        relatedProductId: '',
4069        relatedProductIds: [],
4070        multi: 0,
4071        beforeHtml: '',
4072        afterHtml: '',
4073        callbackFn: null,
4074        openModal: true
4075    };
4076    if (opt.redirect == 'order') opt.redirect = PAGE_LINK.ORDER;
4077
4078    if (typeof options === 'object' && typeof options.productId !== 'undefined') {
4079        for (let i in options) {
4080            opt[i] = options[i];
4081        }
4082    } else if (arguments.length > 1) {
4083        let i = 0;
4084        for (let key in opt) {
4085            if (i >= arguments.length) {
4086                break;
4087            }
4088            opt[key] = arguments[i];
4089            i++;
4090        }
4091    }
4092
4093    const post = new FormData();
4094    /**
4095     * Product id(s) append
4096    */
4097    if(Array.isArray(opt.productId) && opt.productId.length > 0) {
4098        opt.productId.forEach(item => {
4099            post.append('productId[]', item);
4100            personalizationPid.push(item);
4101        });
4102    } else {
4103        post.append('productId', opt.productId);
4104        personalizationPid.push(opt.productId);
4105    }
4106    /**
4107     * Variant id(s) append
4108    */
4109    if(Array.isArray(opt.variantId) && opt.variantId.length > 0) {
4110        opt.variantId.forEach(item => {
4111            post.append('variantId[]', item);
4112        });
4113    } else {
4114        post.append('variantId', opt.variantId);
4115    }
4116    /**
4117     * Quantity value(s) append
4118    */
4119    if(Array.isArray(opt.quantity) && opt.quantity.length > 0) {
4120        opt.quantity.forEach(item => {
4121            post.append('quantity[]', item);
4122        });
4123    } else {
4124        post.append('quantity', opt.quantity);
4125    }
4126    /**
4127     * Related Product id(s) append
4128    */
4129    const paramRelatedProductId = getUrlParam('relatedProductId');
4130    if (paramRelatedProductId) {
4131        const paramRelatedProductIdArray = paramRelatedProductId.split('-');
4132        const paramRelatedId = paramRelatedProductIdArray[0];
4133        const paramProductId = paramRelatedProductIdArray[1];
4134        if(paramRelatedId && paramProductId && (paramProductId == opt.productId)) {
4135            opt.relatedProductId = paramRelatedId;
4136        }
4137    }
4138
4139    if(Array.isArray(opt.relatedProductId) && opt.relatedProductId.length > 0) {
4140        opt.relatedProductId.forEach(item => {
4141            post.append('relatedProductId[]', item);
4142        });
4143    } else {
4144        post.append('relatedProductId', opt.relatedProductId);
4145    }
4146    /** 
4147     * subscribe id append
4148    */
4149
4150    if (typeof opt.productId != 'object' && T(`input#product-subscribe-${opt.productId}:checked`).length > 0) {
4151        const subscribe = T(`input#product-subscribe-${opt.productId}:checked`).length == 1 ? 1 : 0;
4152        const subscribeFrequency = subscribe == 1 ? T(`#product-subscribe-frequency-${opt.productId}`)[0].value : '';
4153        post.append('subscribe', subscribe);
4154        post.append('subscribeFrequency', subscribeFrequency);
4155    }
4156    /**
4157     * product note
4158     */
4159    if(T(`#order-note-${opt.productId}`).length > 0 && T(`#order-note-${opt.productId}`)[0].value != '') {
4160        post.append('orderNotes', T(`#order-note-${opt.productId}`)[0].value);
4161    }
4162    /*
4163    multi: opt.multi
4164    */
4165
4166    /**
4167     * personalization
4168     */
4169
4170    let validateStatus = true;
4171    if (typeof PERSONALIZATION != 'undefined') {
4172        if (opt.productId == PERSONALIZATION.product) {
4173            PERSONALIZATION.validate();
4174            if (PERSONALIZATION.validateStatus == false) {
4175                return false;
4176            }
4177            const data = PERSONALIZATION.formData;
4178            for (let key in data) {
4179                post.append(key, data[key]);
4180            }
4181        } else {
4182            personalizationPid.forEach(pid => {
4183                if (PERSONALIZATION[pid]) {
4184                    PERSONALIZATION[pid].validate();
4185                    validateStatus = PERSONALIZATION[pid].validateStatus;
4186
4187                    let data = {};
4188                    for (let key in PERSONALIZATION[pid].formData) {
4189                        data[key] = PERSONALIZATION[pid].formData[key];
4190                    }
4191                    post.append(`formData[${pid}]`, JSON.stringify(data));
4192                }
4193
4194                });
4195        }
4196    }
4197    if (validateStatus == false) return;
4198
4199    /**
4200     * CSRF_TOKEN
4201     */
4202     post.append('csrfToken', CART_CSRF_TOKEN);
4203
4204    axios.post('/srv/service/cart/add-to-cart', post).then(result => {
4205        const res = result.data;
4206        if (res.status > 0 || (Array.isArray(res) && res[0].status > 0)) {
4207            window['CART_COUNT'] = Array.isArray(res) ? res[res.length - 1].totalQuantity : res.totalQuantity;
4208            T('.cart-soft-count').text(CART_COUNT);
4209
4210            window['CART_TOTAL'] = Array.isArray(res) ? res[res.length - 1].totalPrice : res.totalPrice;
4211            T('.cart-soft-price').text(CART_TOTAL);
4212
4213            Cart.setStorage('add',res);
4214
4215            for(let i=0; i < callbacks.cart.add.length; i++){
4216                if(typeof callbacks.cart.add[i] === 'function'){
4217                    try {
4218                        callbacks.cart.add[i]?.(res);
4219                    } catch (error) { console.log(`Cart Add Callback Error => ${error}`); }
4220                }
4221            }
4222
4223            for (let i = 0; i < Cart.callback.add.length; i++) {
4224                if (typeof Cart.callback.add[i] === 'function') {
4225                    try {
4226                        Cart.callback.add[i]?.(res);
4227                    } catch (error) { console.warn(`Shopping basket adding Callback error => ${error}`) }
4228                }
4229            }
4230
4231            /* callback just running */
4232            if (typeof opt.callbackFn === 'string' && typeof window[opt.callbackFn] === 'function') {
4233                try {
4234                    return window[opt.callbackFn]?.(res);
4235                } catch (error) { console.warn(`Shopping basket adding Callback error => ${error}`) }
4236            }
4237        }
4238
4239        if(multiCart) {
4240            const errorMessage = [];
4241            for(let i=0; i<res.length; i++) {
4242                const that = res[i];
4243                if(that.status < 1) {
4244                    errorMessage.push(that);
4245                }
4246                else {
4247                    multiCartItem = that;
4248                }
4249            }
4250
4251            if (multiCartItem != null) {
4252                switch (multiCartItem.status) {
4253                    case 1:
4254                        autoCart = false;
4255                        multiCart = false;
4256                        if (opt.buyNow == 0) {
4257                            openModal();
4258                        } else {
4259                            window.location.href = '/' + opt.redirect;
4260                        }
4261                        destroySelectionProducts();
4262                        break;
4263                    case 2:
4264                        autoCart = false;
4265                        window.location.href = multiCartItem.url;
4266                        break;
4267                    case 3:
4268                        autoCart = false;
4269                        multiCart = false;
4270                        if (opt.buyNow == 0) {
4271                            openModal();
4272                        } else {
4273                            window.location.href = '/' + opt.redirect;
4274                        }
4275                        destroySelectionProducts();
4276                        break;
4277                }
4278                multiCartItem = null;
4279            }
4280            if (errorMessage.length > 0) {
4281                let errorHtml = '';
4282                errorMessage.forEach(msg => {
4283                    if (msg.url && msg.title) {
4284                        errorHtml += `<p class="text-body">${msg.statusText} : <a href="/${msg.url}" class="text-danger text-underline" target="_blank">${msg.title}</a></p>`;
4285                    } else {
4286                        errorHtml += `<p class="text-body">${msg.statusText}</p>`;
4287                    }
4288                });
4289                setTimeout(() => {
4290                    T.notify({
4291                        text: errorHtml,
4292                        className: 'danger',
4293                        stopOnFocus : true,
4294                        duration: 2400,
4295                    });
4296                }, 500);
4297            }
4298        } else {
4299            switch (res.status) {
4300                case -1: /* varyant selection error */
4301                    for(let i=0; i < callbacks.cart.error.length; i++){
4302                        if(typeof callbacks.cart.error[i] === 'function'){
4303                            try {
4304                                callbacks.cart.error[i]?.(res);
4305                            } catch (error) { console.log(`Cart Error Callback Error => ${error}`); }
4306                        }
4307                    }
4308
4309                    if (res.url != '') {
4310                        if (PAGE_TYPE === 'product') {
4311                            if (document.getElementById('link_table_id').value == opt.productId) {
4312                                T.notify({
4313                                    text: res.statusText,
4314                                    className: 'danger',
4315                                    stopOnFocus : true,
4316                                    duration: 2400,
4317                                });
4318                                return false;
4319                            } else {
4320                                window.location.href = '/' + res.url;
4321                                return false;
4322                            }
4323                        } else {
4324                            window.location.href = '/' + res.url;
4325                            return false;
4326                        }
4327                    } else {
4328                        let errorHtml = '';
4329                        if (res.url || res.title) {
4330                            errorHtml += `<p class="text-body">${res.statusText} : <a href="/${res.url}" class="text-danger text-underline" target="_blank">${res.title}</a></p>`;
4331                        } else {
4332                            errorHtml += `<p class="text-body">${res.statusText}</p>`;
4333                        }
4334                        T.notify({
4335                            text: errorHtml,
4336                            className: 'danger',
4337                            stopOnFocus : true,
4338                            duration: 2400,
4339                        });
4340                    }
4341                    break;
4342                case 0:
4343                    if (res.personalization_error && PAGE_TYPE !== 'product' && res.url) {
4344                        window.location.href = '/' + res.url;
4345                        return false;
4346                    }
4347                    T.notify({
4348                        text: res.statusText || TLANG.no_product_add || 'Ürün sepetinize eklenemedi',
4349                        className: 'danger',
4350                        stopOnFocus : true,
4351                        duration: 2400,
4352                    });
4353                    break;
4354                case -2:
4355                    T.notify({
4356                        text: res.statusText,
4357                        className: 'danger',
4358                        stopOnFocus : true,
4359                        duration: 2400,
4360                    });
4361                    loadSubFolder({
4362                        pageId: 85,
4363                        blockParentId: 1110,
4364                        subFolder: 'set-store',
4365                        params : opt,
4366                        success:  function(loadRes){
4367                            T.modal({
4368                                html: loadRes,
4369                                width: '580px',
4370                                close: true
4371                            });
4372                        }
4373                    });
4374                    break;
4375                case 1:
4376                    if (opt.buyNow == 0) {
4377                    } else {
4378                        window.location.href = '/' + opt.redirect;
4379                    }
4380                    break;
4381                case 2:
4382                    window.location.href = res.url;
4383                    break;
4384                case 3:
4385                    if (opt.buyNow == 0) {
4386                        openModal();
4387                    } else {
4388                        window.location.href = '/' + opt.redirect;
4389                    }
4390                    break;
4391                case 4: 
4392                    if (opt.buyNow == 0) {
4393                        T.notify({
4394                            text: `<div>${res.statusText}</div><a href="/${PAGE_LINK.CART}" class="fw-semibold underline">${TLANG.go_to_cart || 'Sepete git'}</a>`,
4395                            className: 'success',
4396                            duration: 5000,
4397                        });
4398                    } else {
4399                        window.location.href = '/' + opt.redirect;
4400                    }
4401                default:
4402                    break;
4403            }
4404        }
4405    }).catch(error => { console.warn(`Shopping basket adding error => ${error}`) });
4406
4407    const openModal = () => {
4408        if (!opt.openModal) return;
4409        let cartRelatedProductId = opt.relatedProductId;
4410        if (opt.relatedProductIds && opt.relatedProductIds.length > 0) {
4411            cartRelatedProductId = opt.relatedProductIds.join(',');
4412        }
4413        loadSubFolder({
4414            pageId: 30,
4415            blockParentId: 1054,
4416            subFolder: 'popup-cart',
4417            params: {
4418                product: (Array.isArray(opt.productId) && opt.productId.length > 0) ? opt.productId.join('-') : opt.productId,
4419                variantId: (Array.isArray(opt.variantId) && opt.variantId.length > 0) ? opt.variantId.join('-') : opt.variantId || 0,
4420                multi : (Array.isArray(opt.productId) && opt.productId.length > 0) ? true : false,
4421                relatedProductId : cartRelatedProductId
4422            },
4423            success: function(loadRes){
4424                if(document.getElementById('modal-popup-cart') != null) {
4425                    let popupContent = document.getElementById('modal-popup-cart').querySelector('.t-modal-content');
4426                    popupContent.innerHTML = loadRes;
4427                    evalScripts(popupContent.innerHTML);
4428                } else {
4429                    T.modal({
4430                        id: 'modal-popup-cart',
4431                        width: '570px',
4432                        html: loadRes,
4433                        close: true
4434                    });
4435                }
4436                if (PAGE_ID == 30 && cartVue && typeof cartVue.load == 'function') cartVue.load();
4437            }
4438        });
4439    }
4440};
4441
4442const popoverAlert = {
4443    show: function(item, message, duration = 3000, classes = '', scrollable = true, type = 'inline', hideAll = true) {
4444        if (item == null) return;
4445
4446        if (hideAll) popoverAlert.hideAll();
4447
4448        const popoverWrapper = item.closest('.popover-wrapper');
4449        if(popoverWrapper == null) return;
4450        if(popoverWrapper.querySelector('.popover-item') != null) return;
4451
4452        const inlineWarning = classes !== '' && classes !== 'undefined' && type == 'inline' && message.trim().length < 51;
4453        const pop = document.createElement('span');
4454        pop.className = `popover-item fade-in ${classes.indexOf('success') > -1 ? 'success' : ''} ${inlineWarning ? type : ''}`;
4455        pop.innerHTML = message;
4456
4457        let explodeClass = inlineWarning ? classes.replaceAll('btn-danger', 'btn-outline-danger').replaceAll('btn-success', 'btn-outline-success').replace('no-radius', '') : classes;
4458        explodeClass = explodeClass.split(' ').filter(e => e.trim() != '');
4459
4460        if(inlineWarning) {
4461            item.classList.add(...explodeClass);
4462            if (popoverWrapper.classList.contains('input-group') && popoverWrapper.querySelector('.input-group-append')) {
4463                pop.style.right = (popoverWrapper.querySelector('.input-group-append').clientWidth + 6) + 'px';
4464            }
4465        } else {
4466            pop.classList.add(...explodeClass);
4467        }
4468
4469        popoverWrapper.appendChild(pop);
4470        if(scrollable === true) {
4471            if (T('html').hasClass('is-active-modal')) {
4472                const position = popoverWrapper.offsetTop - popoverWrapper.closest('.t-modal-content').offsetTop + popoverWrapper.closest('.t-modal-content').scrollTop;
4473                popoverWrapper.closest('.t-modal-container').scrollTo({
4474                     top: position - 140,
4475                     behavior: 'smooth'
4476                });
4477            } else {
4478                scroll({
4479                    top: popoverWrapper.offsetTop - 200,
4480                    behavior: "smooth"
4481                });
4482            }
4483        }
4484
4485        if(duration !== false) {
4486            setTimeout(function () {
4487                popoverAlert.hide(pop, explodeClass);
4488                item.classList.remove(...explodeClass);
4489            }, duration + 250);
4490        }
4491
4492        T(item).on('focus', () => {
4493            popoverAlert.hide(pop, explodeClass);
4494            item.classList.remove(...explodeClass);
4495        });
4496
4497    },
4498    hide: function(item, removeClass) {
4499        if (!item.closest('.popover-wrapper')) return;
4500        const input = item.closest('.popover-wrapper').querySelector('input:not(.t-search-input)');
4501        if (input != null && removeClass) {
4502            input.classList.remove(...removeClass);
4503        }
4504        item.closest('.popover-wrapper').removeChild(item);
4505    },
4506    hideAll: function() {
4507        Array.from(document.querySelectorAll('.popover-item')).forEac
4507h(item => {
4508            popoverAlert.hide(item);
4509        });
4510    }
4511};
4512
4513const memberLogin = function (options) {
4514    const self = this;
4515    let opt = {
4516        type: 'email',
4517        prefix: '',
4518        vendor: 0,
4519        callback: function() {
4520        },
4521        submitter: null,
4522        form: null
4523    };
4524
4525    for (let i in options) {
4526        opt[i] = options[i];
4527    }
4528
4529    opt.email = opt.prefix + 'email';
4530    opt.phone = opt.prefix + 'phone';
4531    opt.password = opt.prefix + 'password';
4532    opt.remember = opt.prefix + 'remember';
4533    opt.redirect = opt.prefix + 'redirect';
4534    opt.security_code = opt.prefix + 'security_code';
4535    opt.prefix = opt.prefix === '' ? 'deneme' : opt.prefix;
4536
4537    const data = new FormData();
4538    if (opt.type == 'phone') {
4539        data.append('username', document.getElementById(opt.phone).value.replaceAll(/\D/g, ''));
4540        data.append('type', opt.type);
4541    } else {
4542        data.append('username', document.getElementById(opt.email).value);
4543    }
4544
4545    if (opt.vendor == '1') data.append('vendor', 1);
4546
4547    data.append('password', document.getElementById(opt.password).value);
4548    data.append('rememberMe', document.getElementById(opt.remember) != null && document.getElementById(opt.remember).checked ? 1 : 0);
4549    if (document.getElementById(opt.redirect) != null) data.append('redirect', document.getElementById(opt.redirect).value);
4550    if (document.getElementById(opt.security_code) != null) {
4551        const seccode = document.getElementById(opt.security_code);
4552        let limit = seccode.dataset.limit = Number.parseInt(seccode.dataset.limit) || 0;
4553
4554        if (limit < 1) data.append('security_code', seccode.value);
4555
4556        limit = Math.max(0, limit - 1);
4557        seccode.dataset.limit = limit;
4558
4559        if (limit < 1) seccode.parentNode.classList.remove('d-none');
4560        if (document.querySelectorAll('[name="g-recaptcha-response"]')[0] && typeof document.querySelectorAll('[name="g-recaptcha-response"]')[0].value !== 'undefined') data.set('security_code', document.querySelectorAll('[name="g-recaptcha-response"]')[0].value);
4561    }
4562
4563    let httpsUri = '//' + window.location.host;
4564    let postUrl = httpsUri + getEndpoint('LOGIN');
4565
4566    const changePassword = async function() {
4567        loadSubFolder({
4568            pageId: 6,
4569            blockParentId: 1008,
4570            subFolder: 'change-password',
4571            success: async function(loadRes){
4572                await T.modal({
4573                    id: 'modal-change-password',
4574                    width: '480px',
4575                    html: loadRes,
4576                    close: true,
4577                });
4578
4579                const changePasswordForm = document.querySelector('[data-toggle="change-password"]');
4580                if (changePasswordForm) {
4581                    changePasswordForm.addEventListener('submit', async e => {
4582                        e.preventDefault();
4583                        e.stopPropagation();
4584
4585                        const form = e.target;
4586                        const formData = new FormData(form);
4587
4588                        if (!T.checkValidity(form)) return;
4589
4590                        formData.append('type', opt.type);
4591                        formData.append('username', data.get('username'));
4592                        formData.append('password_old', data.get('password'));
4593                        formData.append('redirect', data.get('redirect'));
4594
4595                        const recaptchaResponse = formData.get('g-recaptcha-response');
4596                        if (recaptchaResponse != null && typeof grecaptcha !== 'undefined') formData.set('security_code', recaptchaResponse);
4597
4598                        T.buttonLock.dom = form.submitter;
4599                        T.buttonLock.lock();
4600
4601                        await axios.post(getEndpoint('CUSTOMER_CHANGE_PASSWORD'), formData).then(response => {
4602                            const res = response.data;
4603                            if (res.status) {
4604                                const element = form.querySelector(`[name="password_new"]`);
4605                                if (element) {
4606                                    popoverAlert.show(
4607                                        element,
4608                                        res.message,
4609                                        5000,
4610                                        `btn btn-success text-left`,
4611                                        true,
4612                                        '',
4613                                    );
4614                                }
4615
4616                                setTimeout(() => {
4617                                    window.location.href = res.page?.url || '/';
4618                                }, 1500);
4619                            }
4620                        }).catch(error => {
4621                            const grecaptchaEl = form.querySelector('.g-recaptcha');
4622                            if (grecaptchaEl && recaptchaResponse != null) grecaptchaReset(grecaptchaEl);
4623
4624                            const captchaImg = form.querySelector('.captcha-img');
4625                            if (captchaImg) {
4626                                const captcha = form.querySelector('[name="security_code"]');
4627                                if (captcha) captcha.value = '';
4628                                captchaImg.src = `/SecCode.php?${new Date().getTime()}`;
4629                            }
4630
4631                            let msg;
4632                            if (error.response) {
4633                                msg = error.response.data.data[0];
4634                            } else if (error.request) {
4635                                msg = JSON.parse(error.request.response).data[0];
4636                            }
4637                            if (!msg) return;
4638
4639                            const element = form.querySelector(`[name="${msg.key}"]`);
4640                            if (!element) return;
4641
4642                            popoverAlert.show(
4643                                element,
4644                                msg.statusText,
4645                                10000,
4646                                `btn btn-danger no-radius text-left`,
4647                                true,
4648                                msg.key == '',
4649                            );
4650                        });
4651
4652                        T.buttonLock.unlock();
4653                    });
4654                }
4655            }
4656        });
4657    }
4658
4659    axios.post(postUrl, data).then((response) => {
4660        const result = response.data;
4661
4662        opt.callback(result, options);
4663
4664        let obj = { value: result.data[0].bearer, timeout: result.data[0].exp_at };
4665        localStorage.setItem('v5token', JSON.stringify(obj));
4666
4667        if (result.status) {
4668            for(let i=0; i < callbacks.customer.login.length; i++){
4669                if(typeof callbacks.customer.login[i] === 'function'){
4670                    try {
4671                        callbacks.customer.login[i]?.(result);
4672                    } catch (error) { console.log(`Customer Login Callback Error => ${error}`); }
4673                }
4674            }
4675
4676            if (typeof LoginPageTracking !== 'undefined') {
4677                if(typeof LoginPageTracking.Callback === 'function'){
4678                    try {
4679                        LoginPageTracking.Callback(result);
4680                    } catch (error) { console.log(error); }
4681                }
4682                for(let i = 0; i < LoginPageTracking.callbackArray.length; i++){
4683                    if(typeof LoginPageTracking.callbackArray[i] === 'function'){
4684                        try {
4685                            LoginPageTracking.callbackArray[i]?.(result);
4686                        } catch (error) { console.log(error); }
4687                    }
4688                }
4689            }
4690        }
4691
4692        T.buttonLock.unlock();
4693    }).catch(error => {
4694        if (error.response) {
4695            opt.callback(error.response.data, options);
4696        } else if (error.request) {
4697            const response = JSON.parse(error.request.response);
4698            if (response?.data[0]?.captcha_active) {
4699                const securityCode = document.getElementById(opt.security_code);
4700                if (securityCode) {
4701                    securityCode.parentNode.classList.remove('d-none');
4702                    securityCode.focus();
4703                } else {
4704                    loadSubFolder({
4705                        pageId: 5,
4706                        blockParentId: 1006,
4707                        subFolder: 'captcha',
4708                        params: {
4709                            type: response?.data[0]?.captcha_type,
4710                            prefix: opt.prefix
4711                        },
4712                        success: function(loadRes){
4713                            const password = document.getElementById(opt.password);
4714                            if (password) {
4715                                const passowordWrapper = password.closest('.input-group');
4716                                if (passowordWrapper) {
4717                                    passowordWrapper.insertAdjacentHTML('afterend', loadRes);
4718                                } else {
4719                                    password.parentNode.insertAdjacentHTML('afterend', loadRes);
4720                                }
4721                                evalScripts(loadRes);
4722                                const securityCode = document.getElementById(opt.security_code);
4723                                if (securityCode) securityCode.focus();
4724                            }
4725                        }
4726                    });
4727                }
4728            }
4729            if (response?.data[0]?.password_change) {
4730                changePassword();
4731                T.buttonLock.unlock();
4732                return;
4733            }
4734            opt.callback(response, options);
4735            if (typeof loginCaptcha !== 'undefined') {
4736                try {
4737                    loginCaptcha.forEach(item => item.refreshCode());
4738                } catch (error) {
4739                    console.error(`Login Captcha Refresh Code Error => ${error}`);
4740                }
4741            }
4742        }
4743        T.buttonLock.unlock();
4744    });
4745}
4746
4747const subscribe = {
4748    change: function(el) {
4749        const selector = el.closest('#product-right');
4750        if (selector == null) return;
4751
4752        let productPrice = null,
4753        productNotDiscounted = null;
4754
4755        if (selector.querySelectorAll('.product-price').length) productPrice = T(selector.querySelectorAll('.product-price'));
4756        if (selector.querySelectorAll('.product-price-not-vat').length) productPrice = T(selector.querySelectorAll('.product-price-not-vat'));
4757
4758        if (selector.querySelectorAll('.product-price-not-discounted').length) productNotDiscounted = T(selector.querySelectorAll('.product-price-not-discounted'));
4759        if (selector.querySelectorAll('.product-price-not-discounted-not-vat').length) productNotDiscounted = T(selector.querySelectorAll('.product-price-not-discounted-not-vat'));
4760
4761        if (productPrice == null) return;
4762
4763        const price = T(productPrice).attr('data-price') || T(productPrice).text() || 0;
4764        const parsePrice = T.priceToFloat(price);
4765        T(productPrice).attr('data-price', price);
4766
4767        const notDiscounted = productNotDiscounted != null ? T(productNotDiscounted).attr('data-price') || T(productNotDiscounted).text() || 0 : null;
4768        let parseNotDiscounted = notDiscounted != null ? T.priceToFloat(notDiscounted) : null;
4769        if (productNotDiscounted != null) T(productNotDiscounted).attr('data-price', notDiscounted);
4770
4771        const subsDiscount = el.checked == true ? el.dataset.discount || 0 : 0;
4772
4773        T(productPrice).text(T.format(parsePrice - (parsePrice * subsDiscount / 100)));
4774        if (productNotDiscounted != null) T(productNotDiscounted).text(T.format(parseNotDiscounted - (parseNotDiscounted * subsDiscount / 100)));
4775    },
4776    init: function(el = null) {
4777        if (el == null || el.Subscribe == 1) return;
4778
4779        el.addEventListener('change', () => {
4780            subscribe.change(el);
4781        });
4782
4783        self.sticky = el;
4784        el.Subscribe = 1;
4785    },
4786};
4787
4788const selectVaryant = {
4789    set: {
4790        price: function(self, data, element) {
4791            const selector = self.closest(self.dataset.wrapper) || self.closest('.product-item') || self.closest('#product-right');
4792            if (selector != null && data) {
4793                if (self.closest('#product-detail')) {
4794                    PRODUCT_DATA[0].subproduct_code = data.WS_CODE;
4795                    PRODUCT_DATA[0].subproduct_id = data.ID;
4796                }
4797
4798                const vPrice = Number.parseFloat(data.PRICE);
4799                const vNotDiscounted = Number.parseFloat(data.PRICE_NOT_DISCOUNTED);
4800                let vDiscountPercent = (((vPrice - vNotDiscounted) / vNotDiscounted) * 100);
4801                const mop = (1 + data.MONEY_ORDER_PERCENT / 100) * vPrice;
4802
4803                T(selector.querySelectorAll('.money-order-price')).text(T.vat(mop, data.VAT));
4804                T(selector.querySelectorAll('.money-order-price-not-vat')).text(T.format(mop));
4805
4806                T(selector.querySelectorAll('.product-price')).text(T.vat(vPrice, data.VAT));
4807                T(selector.querySelectorAll('.product-price-not-vat')).text(T.format(vPrice));
4808
4809                T(selector.querySelectorAll('.product-price-not-discounted')).text(T.vat(vNotDiscounted, data.VAT));
4810                T(selector.querySelectorAll('.product-price-not-discounted-not-vat')).text(T.format(vNotDiscounted));
4811
4812                if (selector.querySelectorAll('.product-price').length) {
4813                    T(selector.querySelectorAll('.product-price')).attr('data-price', T.vat(vPrice, data.VAT));
4814                    T(selector.querySelectorAll('.product-price')).attr('data-default-price', data.PRICE);
4815                }
4816                if (selector.querySelectorAll('.product-price-not-vat').length) {
4817                    T(selector.querySelectorAll('.product-price-not-vat')).attr('data-price', T.format(vPrice));
4818                    T(selector.querySelectorAll('.product-price-not-vat')).attr('data-default-price', data.PRICE);
4819                }
4820                if (selector.querySelectorAll('.product-price-not-discounted').length) {
4821                    T(selector.querySelectorAll('.product-price-not-discounted')).attr('data-price', T.vat(vNotDiscounted, data.VAT));
4822                    T(selector.querySelectorAll('.product-price-not-discounted')).attr('data-default-price', data.PRICE);
4823                }
4824                if (selector.querySelectorAll('.product-price-not-discounted-not-vat').length) {
4825                    T(selector.querySelectorAll('.product-price-not-discounted-not-vat')).attr('data-price', T.format(vNotDiscounted));
4826                    T(selector.querySelectorAll('.product-price-not-discounted-not-vat')).attr('data-default-price', data.PRICE);
4827                }
4828
4829                if (vDiscountPercent < 0) vDiscountPercent = vDiscountPercent * -1;
4830
4831                if (vDiscountPercent <= 0) {
4832                    T(selector.querySelectorAll('.discounted-badge')).addClass('d-none');
4833                    T(selector.querySelectorAll('.product-discounted-price')).addClass('d-none');
4834                } else {
4835                    T(selector.querySelectorAll('.product-discounted-price')).removeClass('d-none');
4836                    T(selector.querySelectorAll('.discounted-badge')).removeClass('d-none');
4837                    T(selector.querySelectorAll('.product-discount')).text(vDiscountPercent.toFixed());
4838                }
4839
4840                if (typeof PERSONALIZATION != 'undefined') {
4841                    if (PERSONALIZATION[self.dataset.pid]) {
4842                        PERSONALIZATION[self.dataset.pid].price();
4843                    } else if (PERSONALIZATION.price) {
4844                        PERSONALIZATION.price();
4845                    }
4846                }
4847
4848                const changeSubs = selector.querySelector('[data-toggle="subscribe"]');
4849                if (changeSubs) subscribe.change(changeSubs);
4850
4851                if (data.CODE == '') {
4852                    const supplier_code = T('#product-supplier-code');
4853                    if (supplier_code.length > 0) {
4854                        T(selector.querySelector('#product-code')).show();
4855                        T(selector.querySelector('#product-code #supplier-product-code')).text(supplier_code[0].value);
4856                    } else {
4857                        T(selector.querySelector('#product-code')).hide();
4858                    }
4859                } else {
4860                    T(selector.querySelector('#product-code')).show();
4861                    T(selector.querySelector('#product-code #supplier-product-code')).text(data.CODE ? data.CODE : '');
4862                }
4863
4864                if (data.BARCODE == '') {
4865                    const barcode = T('#barcode-product-code');
4866                    if (barcode.length > 0) {
4867                        T(selector.querySelector('#product-barcode')).show();
4868                        T(selector.querySelector('#product-barcode #barcode-product-code')).text(barcode[0].value);
4869                    } else {
4870                        T(selector.querySelector('#product-barcode')).hide();
4871                    }
4872                } else {
4873                    T(selector.querySelector('#product-barcode')).show();
4874                    T(selector.querySelector('#product-barcode #barcode-product-code')).text(data.BARCODE ? data.BARCODE : '');
4875                }
4876
4877                if (data.CASH_POINT_AMOUNT) {
4878                    T(selector.querySelector('#product-cash-amount')).text(T.format(data.CASH_POINT_AMOUNT));
4879                    T(selector.querySelector('#product-cash-amount')).attr('data-price', data.CASH_POINT_AMOUNT);
4880                }
4881                if (data.CASH_POINT) {
4882                    T(selector.querySelector('#product-cash-point')).text(data.CASH_POINT);
4883                    T(selector.querySelector('#product-cash-point')).attr('data-point', data.CASH_POINT);
4884                }
4885            }
4886
4887            window[element.dataset.callback]?.(element, self, data);
4888        },
4889        stock: function(el, status) {
4890            const selector = el.closest('.product-item') || el.closest('#product-right') || el.closest(el.dataset.wrapper);
4891            if (selector == null) return;
4892
4893            if (typeof cnf_negative_stock !== 'undefined' && cnf_negative_stock == 1) status = true;
4894
4895            if (status) {
4896                T(selector.querySelectorAll('.out-of-stock')).addClass('d-none');
4897                T(selector.querySelectorAll('.in-stock-available')).show();
4898                T(selector.querySelectorAll('.out-stock-available')).addClass('d-none');
4899            } else {
4900                T(selector.querySelectorAll('.out-of-stock')).removeClass('d-none');
4901                T(selector.querySelectorAll('.in-stock-available')).hide();
4902                T(selector.querySelectorAll('.out-stock-available')).removeClass('d-none');
4903            }
4904        },
4905        buttonLink: function(self, proId, data) {
4906            const selector = self.closest(self.dataset.wrapper) || self.closest('.product-item') || self.closest('#product-detail') || self.closest('#product-right');
4907            if (selector == null) return;
4908
4909            Array.from(T(selector.querySelectorAll('[data-type="price"], [data-type="shoplist"], [data-type="stock"], [data-type="installment"], [data-type="store"]'))).forEach(item => {
4910                let dataType;
4911                if (item.dataset.url) {
4912                    dataType = item.dataset.url;
4913                } else if (item.dataset.href) {
4914                    dataType = item.dataset.href;
4915                } else {
4916                    dataType = item.href;
4917                }
4918                let link = dataType.split('?');
4919                link[1] = link[1] || "";
4920
4921                let params = new URLSearchParams(link[1]);
4922
4923                params.set('product', proId);
4924                params.set('variant', data.ID);
4925
4926                if (dataType.includes('isHtml')) {
4927                    params.set('isHtml', '1');
4928                }
4929
4930                link[1] = params.toString();
4931
4932                let joinedLink = link.join('?').replaceAll(/\/\?\&/ig,'&');
4933                if (item.dataset.url) {
4934                    item.dataset.url = joinedLink;
4935                } else if (item.dataset.href) {
4936                    item.dataset.href = joinedLink;
4937                } else {
4938                    item.href = joinedLink;
4939                }
4940
4941                if (item.dataset.type == 'installment') {
4942                    if (T(item.parentNode).hasClass('loaded')) {
4943                        T(item.parentNode).removeClass('loaded');
4944                        T(item.parentNode).addClass('load');
4945                    }
4946                    if (T(item.parentNode).hasClass('active')) {
4947                        T(item).trigger('click');
4948                    }
4949                }
4950            });
4951        },
4952    },
4953    init: function(element = null) {
4954        if(element == null || element.Variant) return;
4955
4956        let event = 'click';
4957        if(element.nodeName == 'SELECT') event = 'change';
4958
4959        const variantWrapper = element.closest('.variant-wrapper');
4960        const subOne = variantWrapper?.querySelector('.sub-one');
4961        const subTwo = variantWrapper?.querySelector('.sub-two');
4962        const variantSub = element.closest('.sub-one') ? subOne : subTwo;
4963        const variantOtherSub = variantSub == subOne ? subTwo : subOne;
4964        const variantItem = (element.nodeName === 'SELECT') ? element.options[element.selectedIndex] : element;
4965
4966        element.addEventListener(event, async function(e) {
4967            let self = this;
4968            if(element.nodeName == 'A')
4969                e.preventDefault();
4970
4971            if(element.nodeName == 'SELECT')
4972                self = element.options[self.options.selectedIndex];
4973
4974            const subId = self.dataset.id;
4975            const subProId = self.dataset.target;
4976            const proId = self.dataset.pid;
4977
4978            if ((self.value === '' || self.value === '0') && element.subpro && element.nodeName == 'SELECT') {
4979                T(element.subpro)[0].value = '0';
4980                element.querySelectorAll('option').forEach(option => {
4981                    option.classList.remove('selected');
4982                });
4983                T(self).addClass('selected');
4984                selectVaryant.set.stock(self, true);
4985                return;
4986            }
4987
4988            if (!subId || !subProId || !proId) return;
4989            element.subpro = '#subPro' + subProId;
4990
4991            const variantWrapper = self.closest('.variant-wrapper');
4992            const subEl = self.closest('.sub-one') == null ? self.closest('.sub-two') : self.closest('.sub-one');
4993            if (!subEl) return;
4994            const otherSubEl = T(subEl).hasClass('sub-one') == true ? '.sub-two' : '.sub-one';
4995
4996            let variantData = [];
4997
4998            const defaultSelect = function() {
4999                if (subOne && subTwo && variantSub == subOne && variantSub.oneClick != 1 && self.classList.contains('selected')) {
5000                    variantSub.oneClick = 1;
5001
5002                    const activeElement = variantOtherSub.querySelector('.selected');
5003                    if (!activeElement) return;
5004
5005                    const isElementPassive = activeElement.classList.contains('passive') || activeElement.classList.contains('not-sub');
5006                    const otherElements = variantOtherSub.querySelectorAll('[data-toggle="variant"]:not(select), select[data-toggle="variant"] option[data-id]');
5007                    const otherNotActive = variantOtherSub.querySelectorAll('.passive, .not-sub');
5008
5009                    if (isElementPassive && otherNotActive.length != otherElements.length) {
5010                        let stats = 0;
5011                        Array.from(otherElements).forEach(item => {
5012                            item.classList.remove('selected');
5013                            if (stats) return;
5014
5015                            if (!(item.classList.contains('passive') || item.classList.contains('not-sub')) && item.dataset.type) {
5016                                stats = 1;
5017                                item.classList.add('selected');
5018
5019                                const select = variantOtherSub.querySelector('select[data-toggle="variant"]');
5020                                if (select && item.value !== '0') {
5021                                    select.value = item.value;
5022                                    T(select).trigger('change');
5023                                } else {
5024                                    T(item).trigger('click');
5025                                }
5026                            }
5027                        });
5028                    } else {
5029                        setTimeout(() => {
5030                            const select = variantOtherSub.querySelector('select[data-toggle="variant"]');
5031                            if (select && activeElement.value !== '0') {
5032                                select.value = activeElement.value;
5033                                T(select).trigger('change');
5034                            } else {
5035                                T(activeElement).trigger('click');
5036                            }
5037                        }, 1);
5038                    }
5039                }
5040            }
5041
5042            const notAjax = async () => {
5043                const data = {
5044                    'ADDITIONAL_INFO': self.dataset.additional || '',
5045                    'ID': self.dataset.subproductId,
5046                    'TYPE_ID': self.dataset.id,
5047                    'TYPE': self.dataset.type,
5048                    'CODE': self.dataset.code,
5049                    'TYPE_COLOR_CODE': self.dataset.colorCode,
5050                    'PRICE': self.dataset.price,
5051                    'STOCK': self.dataset.stock,
5052                    'IN_STOCK': self.dataset.instock,
5053                    'BARCODE': self.dataset.barcode,
5054                    'MONEY_ORDER_PERCENT': self.dataset.mop,
5055                    'VAT': self.dataset.vat,
5056                    'PRICE_NOT_DISCOUNTED': self.dataset.notDiscounted,
5057                    'WS_CODE': self.dataset.wscode,
5058                    'WEIGHT': self.dataset.weight,
5059                    'CASH_POINT': self.dataset.cashPoint,
5060                    'CASH_POINT_AMOUNT': self.dataset.cashPointAmount,
5061                };
5062
5063                selectVaryant.set.price(self, data, element);
5064                selectVaryant.set.stock(self, data.STOCK > 0);
5065                selectVaryant.set.buttonLink(self, proId, data);
5066                T('#subPro' + subProId)[0].value = data.ID;
5067                defaultSelect();
5068            }
5069
5070            if (variantWrapper.querySelector(otherSubEl)) {
5071                const subOneLenght = variantWrapper.querySelector('.sub-one').querySelectorAll('[data-toggle="variant"]:not(select), select[data-toggle="variant"] option[data-id]');
5072                if (subOneLenght.length == 1) {
5073                    if (T(subEl).hasClass('sub-two')) {
5074                        notAjax();
5075                    } else {
5076                        setTimeout(() => {
5077                            defaultSelect();
5078                        }, 1);
5079                    }
5080                } else {
5081                    const getList = T(subEl).hasClass('sub-one') ? 'get-variant2-list' : 'get-variant1-list';
5082                    axios.get(getEndpoint('VARIANT', `${getList}/${proId}/${subId}`)).then(res => {
5083                        const data = res.data.VARIANT2_LIST ?? res.data.VARIANT1_LIST;
5084                        const variantArray = variantWrapper.querySelector(otherSubEl).querySelectorAll('[data-toggle="variant"]:not(select), select[data-toggle="variant"] option');
5085
5086                        Array.from(variantArray).forEach(el => {
5087                            if(el.value == '0' || el.value == '') return;
5088
5089                            if (T(subEl).hasClass('sub-one')) {
5090                                T(el).addClass('d-none');
5091                                T(el).addClass('passive not-sub');
5092                            }
5093
5094                            if (el['name'] == null) el['name'] = T(el).text();
5095                            const subData = Array.from(data).find(x => x.TYPE_ID == el.dataset.id);
5096                            if (subData) {
5097                                if (subData.STOCK > 0) {
5098                                    T(el).removeClass('passive');
5099                                    if (el.nodeName == 'OPTION') {
5100                                        T(el).text(el.name);
5101                                        el.removeAttribute('disabled');
5102                                    }
5103                                } else {
5104                                    if (el.nodeName == 'OPTION') {
5105                                        T(el).text(`${el.name} (${TLANG.out_of_stock || 'Tükendi'})`);
5106                                        if (el.closest('.product-item')) {
5107                                            if (el.closest('.sub-two')) el.setAttribute('disabled', 'disabled');
5108                                        }
5109                                    }
5110                                }
5111                                T(el).removeClass('d-none not-sub');
5112                            }
5113                        });
5114
5115                        const otherSelected = variantWrapper.querySelector(otherSubEl).querySelector('.selected');
5116                        if (otherSelected != null && (otherSelected.value === '0' || otherSelected.value === '')) return;
5117
5118                        if (otherSelected != null) {
5119                            if (T(otherSelected).hasClass('d-none')) T(otherSelected).removeClass('selected');
5120                            const subId = otherSelected.dataset.id;
5121                            variantData = Array.from(data).find(x => x.TYPE_ID == subId);
5122                            const variantId = variantData ? variantData.ID : '0';
5123                            selectVaryant.set.price(self, variantData, element);
5124                            selectVaryant.set.buttonLink(self, proId, variantData);
5125                            if (T(self).hasClass('not-sub')) {
5126                                selectVaryant.set.stock(self, true);
5127                            } else {
5128                                selectVaryant.set.stock(self, !T(self).hasClass('passive'));
5129                            }
5130                            T('#subPro' + subProId)[0].value = variantId;
5131                        } else {
5132                            window[element.dataset.callback]?.(element, self, data);
5133                        }
5134
5135                        defaultSelect();
5136                    });
5137                }
5138            } else {
5139                notAjax();
5140            }
5141
5142            T(subEl.querySelectorAll('[data-toggle="variant"]:not(select)')).removeClass('selected');
5143            T(subEl.querySelectorAll('select[data-toggle="variant"] option')).removeClass('selected');
5144            if (!T(self).hasClass('d-none')) T(self).addClass('selected');
5145        });
5146
5147        if (typeof selectVariantCallback === 'function' && PAGE_TYPE === 'product' && typeof PRODUCT_DATA === 'object' && PRODUCT_DATA[0]?.id && !selectVariantCallback.ready) {
5148            selectVariantCallback.ready = 1;
5149            const getVariantId = getUrlParam('variant');
5150            try {
5151                const subOne = document.querySelector('.sub-one');
5152                const subTwo = document.querySelector('.sub-two');
5153                selectVariantCallback(PRODUCT_DATA, getVariantId, subOne, subTwo);
5154            } catch (error) { }
5155        }
5156
5157        const isOnylSub = (variantOtherSub && variantSub === subOne) || (subOne && !subTwo || subTwo && !subOne);
5158        const isElementActive = variantItem.classList.contains('selected');
5159        const isElementPassive = variantItem.classList.contains('passive') || variantItem.classList.contains('not-sub');
5160        const otherElements = variantSub.querySelectorAll('[data-toggle="variant"]:not(select), select[data-toggle="variant"] option[data-id]');
5161        const otherNotActive = variantSub.querySelectorAll('.passive, .not-sub');
5162        const subOneLenght = subOne?.querySelectorAll('[data-toggle="variant"]:not(select), select[data-toggle="variant"] option[data-id]');
5163
5164        if (isOnylSub && isElementActive) {
5165            if (!variantOtherSub && isElementActive && isElementPassive && otherNotActive.length != otherElements.length) {
5166                let stats = 0;
5167                Array.from(otherElements).forEach(item => {
5168                    item.classList.remove('selected');
5169                    if (stats) return;
5170
5171                    if (!(item.classList.contains('passive') || item.classList.contains('not-sub')) && item.dataset.type) {
5172                        stats = 1;
5173                        item.classList.add('selected');
5174                        const select = variantSub.querySelector('select[data-toggle="variant"]');
5175                        setTimeout(() => {
5176                            if (select && item.value !== '0') {
5177                                select.value = item.value;
5178                                T(select).trigger('change');
5179                            } else {
5180                                T(item).trigger('click');
5181                            }
5182                        }, 1);
5183                    }
5184                });
5185            } else {
5186                T(element).trigger(event);
5187            }
5188        } else if (variantSub === subOne && subOneLenght?.length == 1) {
5189            T(element).trigger(event);
5190        }
5191
5192        if (!variantOtherSub || (variantOtherSub && subOneLenght?.length == 1 && variantSub == subTwo)) {
5193            if (element.nodeName == 'SELECT') {
5194                Array.from(element.options).forEach(option => {
5195                    const stock = Number(option.dataset.stock);
5196                    if (option['name'] == null) option['name'] = T(option).text();
5197                    if (stock <= 0) {
5198                        T(option).text(`${option.name} (${TLANG.out_of_stock || 'Tükendi'})`);
5199                        if (option.closest('.product-item')) option.setAttribute('disabled', 'disabled');
5200                    } else {
5201                        T(option).text(option.name);
5202                        option.removeAttribute('disabled');
5203                    }
5204                });
5205            }
5206        }
5207
5208        element.Variant = element;
5209    }
5210};
5211
5212const snapScroll = {
5213    init: function(element = null) {
5214        if(element == null || element.Snap) return;
5215        element.style.opacity = 0;
5216        let count = 0;
5217        const snapItem = element.querySelectorAll('.snap-item');
5218        snapItem[0].classList.add('snap-item-active');
5219
5220        const scroll = element.querySelector('.snap-scroll');
5221        const btnPrev = element.querySelector('.snap-prev');
5222        const btnNext = element.querySelector('.snap-next');
5223
5224        T(btnPrev).on('click', () => {
5225            count--;
5226            if (count <= 0) count = 0;
5227
5228            element.querySelector('.snap-item-active').classList.remove('snap-item-active');
5229            snapItem[count].classList.add('snap-item-active');
5230            scroll.scrollBy(-element.querySelector('.snap-item-active').offsetWidth, 0);
5231        });
5232
5233        T(btnNext).on('click', () => {
5234            count++;
5235            if (count >= snapItem.length) count = snapItem.length - 1;
5236
5237            element.querySelector('.snap-item-active').classList.remove('snap-item-active');
5238            snapItem[count].classList.add('snap-item-active');
5239            scroll.scrollBy(element.querySelector('.snap-item-active').offsetWidth, 0);
5240        });
5241
5242        setTimeout(() => {
5243            if (scroll.clientWidth < element.clientWidth) {
5244                T(btnPrev).addClass('d-none');
5245                T(btnNext).addClass('d-none');
5246            } else {
5247                T(scroll).addClass('overflow-x-auto overflow-y-hidden');
5248            }
5249            scroll.scrollTo(0, 0);
5250            element.style.opacity = null;
5251        }, 250);
5252
5253        element.Snap = element;
5254    }
5255};
5256
5257const favouriteProducts = {
5258    STORAGE_KEY: "favorite_products",
5259    SESSION_KEY: "favorites_fetched",
5260    SESSION_SERVER: "server_favorites",
5261    LIST_API_URL: "/srv/service/profile/get-shopping-list",
5262    ADD_API_URL: "/srv/service/profile/add-to-fav-list",
5263    REMOVE_API_URL: "/srv/service/profile/delete-shopping-products-by-product-id",
5264    updateTimeout: null,
5265    debounceTimeout: null,
5266    maxChanges: 10,
5267    syncFavorites: false,
5268    ids: [],
5269    async add(ids = null) {
5270        if (MEMBER_INFO.ID <= 0) {
5271            favouriteProducts.login();
5272            return;
5273        }
5274
5275        let isSingle = false;
5276
5277        if (ids == null) ids = [];
5278        if (!Array.isArray(ids)) {
5279            ids = [ids];
5280            isSingle = true;
5281        }
5282        if (ids.length === 0) return;
5283
5284        let favorites = this.getFavorites();
5285        let changed = false;
5286        const callback = this.callback;
5287
5288        ids.forEach(productId => {
5289            if (isSingle) {
5290                if (favorites.includes(productId)) {
5291                    favorites.splice(favorites.indexOf(productId), 1);
5292                    callback(productId, 'remove');
5293                    changed = true;
5294                } else {
5295                    favorites.push(productId);
5296                    callback(productId, 'add');
5297                    changed = true;
5298                }
5299            } else {
5300                if (!favorites.includes(productId)) {
5301                    favorites.push(productId);
5302                    callback(productId, 'add');
5303                    changed = true;
5304                }
5305            }
5306        });
5307
5308        if (changed) {
5309            await this.setFavorites(favorites);
5310            await this.sendUpdates(true);
5311            this.set();
5312        }
5313    },
5314    remove(ids = null) {
5315        if (ids == null) return;
5316        if (!Array.isArray(ids)) {
5317            ids = [ids];
5318        }
5319        let favorites = this.getFavorites();
5320        const callback = this.callback;
5321        ids.forEach(productId => {
5322            if (favorites.includes(productId)) {
5323                favorites.splice(favorites.indexOf(productId), 1);
5324                callback(productId, 'remove');
5325            }
5326        });
5327        this.setFavorites(favorites);
5328        this.sendUpdates();
5329        this.set();
5330    },
5331    counter() {
5332        sessionStorage.removeItem(this.SESSION_KEY);
5333        this.fetchFavorites();
5334    },
5335    getFavorites() {
5336        return JSON.parse(localStorage.getItem(this.STORAGE_KEY)) || [];
5337    },
5338    async setFavorites(favorites) {
5339        localStorage.setItem(this.STORAGE_KEY, JSON.stringify(favorites));
5340        T('.customer-favorites-count, .tsoft-favourite-count').text(favorites.length || 0);
5341    },
5342    fetchFavorites() {
5343        if (MEMBER_INFO.ID <= 0) {
5344            localStorage.removeItem(this.STORAGE_KEY);
5345            sessionStorage.removeItem(this.SESSION_KEY);
5346            sessionStorage.removeItem(this.SESSION_SERVER);
5347            return;
5348        }
5349
5350        if (sessionStorage.getItem(this.SESSION_KEY) && localStorage.getItem(this.STORAGE_KEY)) {
5351            this.sendUpdates();
5352            return;
5353        };
5354
5355        axios.get(this.LIST_API_URL)
5356            .then(response => {
5357                let data = response.data;
5358                let apiFavorites = data?.CATEGORIES?.[0]?.PRODUCTS?.map(p => p.ID) || [];
5359
5360                this.setFavorites(apiFavorites);
5361                sessionStorage.setItem(this.SESSION_SERVER, JSON.stringify(apiFavorites));
5362                sessionStorage.setItem(this.SESSION_KEY, "true");
5363
5364                this.sendUpdates(false, apiFavorites);
5365                this.set();
5366            })
5367            .catch(error => {
5368                console.error("API hatası:", error);
5369            });
5370    },
5371    async set() {
5372        const favorites = this.getFavorites();
5373        T('.customer-favorites-count, .tsoft-favourite-count').text(favorites.length || 0);
5374        const allFavButtons = document.querySelectorAll('.add-favourite-btn[data-id]');
5375
5376        allFavButtons.forEach(btn => {
5377            btn.classList.remove('fav-added');
5378        });
5379
5380        favorites.forEach(productId => {
5381            const favButtons = document.querySelectorAll(`.add-favourite-btn[data-id="${productId}"]`);
5382            favButtons.forEach(btn => {
5383                btn.classList.add('fav-added');
5384            });
5385        });
5386    },
5387    toggleFavorite(productId) {
5388        let favorites = this.getFavorites();
5389        const index = favorites.indexOf(productId);
5390
5391        const favButtons = document.querySelectorAll(`[data-id="${productId}"]`);
5392
5393        if (index === -1) {
5394            favorites.push(productId);
5395            favButtons.forEach(btn => {
5396                btn.classList.add('fav-added');
5397            });
5398            this.callback(productId, 'add');
5399        } else {
5400            favorites.splice(index, 1);
5401            favButtons.forEach(btn => {
5402                btn.classList.remove('fav-added');
5403            });
5404            this.callback(productId, 'remove');
5405        }
5406
5407        this.setFavorites(favorites);
5408        this.scheduleUpdate();
5409    },
5410    debounceToggleFavorite(productId) {
5411        clearTimeout(this.debounceTimeout);
5412        this.debounceTimeout = setTimeout(() => {
5413            if (MEMBER_INFO.ID <= 0) {
5414                favouriteProducts.login();
5415                return;
5416            }
5417
5418            if (!localStorage.getItem(this.STORAGE_KEY)) {
5419                this.fetchFavorites().then(() => {
5420                    this.toggleFavorite(productId);
5421                });
5422                return;
5423            }
5424
5425            this.toggleFavorite(productId);
5426        }, 500);
5427    },
5428    async scheduleUpdate() {
5429        if (this.updateTimeout) clearTimeout(this.updateTimeout);
5430
5431        let storedFavorites = this.getFavorites();
5432        let serverFavorites = JSON.parse(sessionStorage.getItem(this.SESSION_SERVER)
5432) || [];
5433
5434        let toAdd = storedFavorites.filter(id => !serverFavorites.includes(id));
5435        let toRemove = serverFavorites.filter(id => !storedFavorites.includes(id));
5436
5437        if (toAdd.length + toRemove.length > this.maxChanges) {
5438            this.sendUpdates();
5439            return;
5440        }
5441
5442        this.updateTimeout = setTimeout(() => {
5443            this.sendUpdates();
5444        }, 60000);
5445    },
5446    sendUpdates(message = false, localFavorites = []) {
5447        if (this.syncFavorites) return;
5448        this.syncFavorites = true;
5449
5450        let storedFavorites = localFavorites.length > 0 ? localFavorites : this.getFavorites();
5451        let serverFavorites = JSON.parse(sessionStorage.getItem(this.SESSION_SERVER)) || [];
5452
5453        let toAdd = storedFavorites.filter(id => !serverFavorites.includes(id));
5454        let toRemove = serverFavorites.filter(id => !storedFavorites.includes(id));
5455
5456        let sent = true;
5457
5458        const sendSync = async (url, data, isAdd = true) => {
5459            try {
5460                if (message) {
5461                    try {
5462                        let response = await axios.post(url, data);
5463                        const result = response.data;
5464
5465                        if (result?.status) {
5466                            if (result?.data?.length > 1) {
5467                                let message = '';
5468                                const not_added_product = [];
5469
5470                                result.data.map(item => {
5471                                    if (item.status) {
5472                                        message += `<div class="d-flex align-items-center mb-1"><i class="ti-check text-primary mr-1"></i> ${item.product.name}</div>`;
5473                                    } else {
5474                                        if (not_added_product.indexOf(item.statusText) === -1) not_added_product.push(item.statusText);
5475                                    }
5476                                });
5477
5478                                if (not_added_product.length > 0) message += `<div class="text-gray mt-1 py-1 border-top border-light">${not_added_product.join('<br>')}</div>`;
5479
5480                                T.modal({
5481                                    html: `<div class="block-title mb-1">${TLANG.favorited_products || 'Favoriye Eklenen Ürünler'}</div>${message}`,
5482                                    width: '480px'
5483                                });
5484                            } else {
5485                                T.notify({
5486                                    text: isAdd ? TLANG.added_to_favorites || 'Ürün favorilerinize eklendi' : TLANG.removed_from_favorites || 'Ürün favorilerinizden çıkarıldı',
5487                                    className: isAdd ? 'success add-favourite-added-notify' : 'danger add-favourite-removed-notify',
5488                                    duration: 2500,
5489                                    iconClass : isAdd ? 'ti-thumbs-up' : 'ti-trash',
5490                                });
5491                            }
5492                        } else {
5493                            const not_added_product = [];
5494                            result.data.map(item => {
5495                                if (not_added_product.indexOf(item.statusText) === -1) not_added_product.push(item.statusText);
5496                            });
5497
5498                            if (not_added_product.length > 0) {
5499                                T.modal({
5500                                    html: `<div class="text-gray py-1">${not_added_product.join('<br>')}</div>`,
5501                                    width: '480px'
5502                                });
5503                            }
5504                        }
5505
5506                        return result.status;
5507                    } catch (error) {
5508                        console.error("Veri gönderme hatası:", error);
5509                        return false;
5510                    }
5511                } else if (navigator.sendBeacon) {
5512                    return navigator.sendBeacon(url, data);
5513                } else {
5514                    const xhr = new XMLHttpRequest();
5515                    xhr.open('POST', url, false);
5516                    try {
5517                        xhr.send(data);
5518                        return xhr.status === 200;
5519                    } catch (error) {
5520                        console.error("Veri gönderme hatası:", error);
5521                        return false;
5522                    }
5523                }
5524            } catch (error) {
5525                console.error("sendSync işlemi sırasında hata:", error);
5526                return false;
5527            }
5528        };
5529
5530        const processUpdates = async () => {
5531            try {
5532                if (toAdd.length > 0) {
5533                    const body = new FormData();
5534                    toAdd.forEach(id => {
5535                        body.append('ids[]', id + '-0');
5536                    });
5537                    body.append('fetch', true);
5538                    body.append('cat_id', 1);
5539                    const addResult = await sendSync(this.ADD_API_URL, body, true);
5540                    sent = sent && addResult;
5541                }
5542
5543                if (toRemove.length > 0) {
5544                    const body = new FormData();
5545                    toRemove.forEach(id => {
5546                        body.append('products[]', id);
5547                    });
5548                    const removeResult = await sendSync(this.REMOVE_API_URL, body, false);
5549                    sent = sent && removeResult;
5550                }
5551
5552                if (sent) {
5553                    sessionStorage.setItem(this.SESSION_SERVER, JSON.stringify(storedFavorites));
5554                    if (localFavorites.length > 0) {
5555                        this.setFavorites(localFavorites);
5556                        this.set();
5557                    }
5558                }
5559            } catch (error) {
5560                console.error("Favori güncellemesi sırasında hata:", error);
5561            } finally {
5562                // İşlem başarılı veya başarısız olsa da kilidi kaldır
5563                this.syncFavorites = false;
5564            }
5565        };
5566
5567        processUpdates();
5568    },
5569    handleOnline() {
5570        this.sendUpdates();
5571    },
5572    handlePageLeave() {
5573        this.sendUpdates();
5574    },
5575    click: function(element) {
5576        if (element.clickFavBtn == 1) return;
5577        element.addEventListener('click', () => {
5578            let productId = element.getAttribute("data-id");
5579            if (productId) favouriteProducts.debounceToggleFavorite(productId);
5580        });
5581        element.clickFavBtn = 1;
5582    },
5583    login: function() {
5584        loadSubFolder({
5585            pageId: 5,
5586            blockParentId: 1006,
5587            subFolder: 'popup-login',
5588            success:  function(loadRes){
5589                T.modal({
5590                    id: 'popup-login',
5591                    html: loadRes,
5592                    close: true
5593                });
5594            }
5595        });
5596    },
5597    callback: function(id, type) {
5598        const product = Array.from(PRODUCT_DATA).find(p => p.id == id);
5599        if (product) {
5600            const returnData = [{
5601                data: {
5602                    code: product.code,
5603                    id: product.id,
5604                    name: product.name,
5605                    currency: product.currency,
5606                    category_id: product.category_id,
5607                    category_name: product.category,
5608                    category_path: product.category_path,
5609                    brand: product.brand,
5610                    price: product.total_sale_price
5611                },
5612                status: 1
5613            }];
5614
5615            if (type == 'add') {
5616                for(let i=0; i < callbacks.product.wishList.add.length; i++){
5617                    if(typeof callbacks.product.wishList.add[i] === 'function'){
5618                        try {
5619                            callbacks.product.wishList.add[i]?.(returnData);
5620                        } catch (error) { console.log(`Product Wishlist Add Callback Error => ${error}`); }
5621                    }
5622                }
5623
5624                for(let i=0; i < callbacks.product.favourite.add.length; i++){
5625                    if(typeof callbacks.product.favourite.add[i] === 'function'){
5626                        try {
5627                            callbacks.product.favourite.add[i]?.(id);
5628                        } catch (error) { console.log(`Products Favourite Add Callback Error => ${error}`); }
5629                    }
5630                }
5631            } else {
5632                for(let i=0; i < callbacks.product.wishList.remove.length; i++){
5633                    if(typeof callbacks.product.wishList.remove[i] === 'function'){
5634                        try {
5635                            callbacks.product.wishList.remove[i]?.(returnData);
5636                        } catch (error) { console.log(`Product Wishlist Remove Callback Error => ${error}`); }
5637                    }
5638                }
5639
5640                for(let i=0; i < callbacks.product.favourite.remove.length; i++){
5641                    if(typeof callbacks.product.favourite.remove[i] === 'function'){
5642                        try {
5643                            callbacks.product.favourite.remove[i]?.(id);
5644                        } catch (error) { console.log(`Products Favourite Remove Callback Error => ${error}`); }
5645                    }
5646                }
5647            }
5648        }
5649    },
5650    init() {
5651        this.fetchFavorites();
5652        this.set();
5653
5654        if (MEMBER_INFO.ID > 0) {
5655            window.addEventListener("online", () => this.handleOnline());
5656
5657            const boundHandlePageLeave = this.handlePageLeave.bind(this);
5658
5659            window.addEventListener("beforeunload", boundHandlePageLeave);
5660            window.addEventListener("unload", boundHandlePageLeave);
5661            window.addEventListener("pagehide", boundHandlePageLeave);
5662            window.addEventListener("visibilitychange", () => {
5663                if (document.visibilityState === 'hidden') {
5664                    boundHandlePageLeave();
5665                }
5666            });
5667        }
5668    }
5669};
5670
5671const countDown = {
5672    init: function(count = null) {
5673        let timer = count.dataset.timer;
5674            timer = timer.split(',');
5675            timer = new Date(timer[0], timer[1]-1, timer[2], timer[3], timer[4], timer[5]);
5676            countDown.get(count, timer);
5677    },
5678    get: function(element, timer) {
5679        const x = setInterval(function() {
5680            const now = new Date();
5681            const countDate = new Date(timer);
5682            const amount = Date.parse(countDate) - Date.parse(now);
5683            delete now;
5684            if (amount < 0) {
5685                clearInterval(x);
5686                return;
5687            }
5688            const days = Math.floor(amount / (1000 * 60 * 60 * 24)),
5689                  hours = Math.floor((amount % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)),
5690                  minutes = Math.floor((amount % (1000 * 60 * 60)) / (1000 * 60)),
5691                  seconds = Math.floor((amount % (1000 * 60)) / 1000);
5692
5693            const formattedHours = hours < 10 ? '0' + hours : hours,
5694                  formattedMinutes = minutes < 10 ? '0' + minutes : minutes,
5695                  formattedSeconds = seconds < 10 ? '0' + seconds : seconds;
5696
5697            if (element.querySelector('.day .timer-text')) element.querySelector('.day .timer-text').innerHTML = days;
5698            if (element.querySelector('.hour .timer-text')) element.querySelector('.hour .timer-text').innerHTML = formattedHours;
5699            if (element.querySelector('.minute .timer-text')) element.querySelector('.minute .timer-text').innerHTML = formattedMinutes;
5700            if (element.querySelector('.second .timer-text')) element.querySelector('.second .timer-text').innerHTML = formattedSeconds;
5701        }, 1000);
5702    }
5703};
5704
5705const passwordStrengthControl = function() {
5706    if (Number(MEMBER_INFO.ID) < 1) return;
5707    if(typeof MEMBER_INFO.PASSWORD_STRENGTH == 'undefined') return;
5708    if (Number(MEMBER_INFO.PASSWORD_STRENGTH) > 6) return;
5709
5710    loadSubFolder({
5711        pageId: 6,
5712        blockParentId: 1008,
5713        subFolder: 'update-password',
5714        params:  {},
5715        success:  function(loadRes){
5716            T.modal({
5717                id: 'modal-update-password',
5718                width: '570px',
5719                html: loadRes,
5720                close: false
5721            });
5722        }
5723    });
5724};
5725
5726const mobileAppFn = function() {
5727    const element = document.querySelector('[data-toggle="mobile-app"]');
5728    if (element && T.isMobile() && PAGE_ID == 1) {
5729
5730        if (T.getCookie('mobileApp') == 1) {
5731            element.remove();
5732            return;
5733        } else {
5734            element.classList.remove('d-none');
5735        }
5736
5737        const downloadBtn = element.querySelector('[data-toggle="mobile-app-download"]');
5738        const closeBtn = element.querySelector('[data-toggle="mobile-app-close"]');
5739
5740        const MobileAppRedirect = element.querySelector('[name="MobileAppRedirect"]')?.value || '',
5741            AppMarketLink = element.querySelector('[name="AppMarketLink"]')?.value || '',
5742            OpenAppLink = element.querySelector('[name="OpenAppLink"]')?.value || '';
5743
5744        let storeUrl;
5745        if (MobileAppRedirect == 'ios') {
5746            storeUrl = `https://itunes.apple.com/app/id${AppMarketLink}`;
5747        } else if (MobileAppRedirect == 'android') {
5748            storeUrl = `market://details?id=${AppMarketLink}`;
5749        }
5750        if (!storeUrl) return;
5751
5752        const meta = document.createElement('meta');
5753        meta.name = 'apple-itunes-app';
5754        meta.content = `app-id=${AppMarketLink}, affiliate-data=myAffiliateData, app-argument=${OpenAppLink}://`;
5755        document.head.append(meta);
5756
5757        if (downloadBtn) {
5758            downloadBtn.addEventListener('click', e => {
5759                setTimeout(() => {
5760                    document.location.href = storeUrl;
5761                }, 2000);
5762                document.location.href = `${OpenAppLink}://`;
5763            });
5764        }
5765
5766        if (closeBtn) {
5767            closeBtn.addEventListener('click', e => {
5768                element.remove();
5769                T.setCookie('mobileApp', 1);
5770            });
5771        }
5772    }
5773}
5774
5775const catalog = function(element) {
5776    if (T.isMobile()) return;
5777
5778    if(element == null || element.catalog) return;
5779
5780    const productItem = element.closest('.product-item');
5781    if (!productItem) {
5782        console.warn('catalog warn: productItem undefined');
5783        return;
5784    };
5785
5786    const productId = element.dataset.product;
5787    if (!productId) {
5788        console.warn('getCatalog warn: productId (catalog.dataset.product) undefined');
5789        return;
5790    };
5791
5792    const modelId = element.dataset.model;
5793    if (!modelId) {
5794        console.warn('getCatalog warn: modelId (catalog.dataset.model) undefined');
5795        return;
5796    };
5797
5798    const isCatalogActive = element.querySelector('[data-toggle="is-catalog-active"]');
5799    if (!isCatalogActive?.value) return;
5800
5801    let hoverTimeout;
5802    element.addEventListener('mouseenter', () => {
5803        if (element.classList.contains('catalog-loaded') || element.catalogApp) return;
5804
5805        hoverTimeout = setTimeout(async () => {
5806            productItem.classList.add('catalog-opacity');
5807            element.classList.add('pointer-events-none');
5808
5809            element['catalogApp'] = Vue.createApp({
5810                data() {
5811                    return {
5812                        ATTRIBUTES: [],
5813                    }
5814                },
5815                methods: {
5816                    async getAttribute(product_id = null, product = true) {
5817                        if (product_id == null) return;
5818                        const self = this;
5819
5820                        if (element[`PRODUCT_ATTRIBUTES_${product_id}`]) {
5821                            self.ATTRIBUTES = JSON.parse(JSON.stringify(element[`PRODUCT_ATTRIBUTES_${product_id}`]));
5822                            Array.from(self.ATTRIBUTES).forEach(item => {
5823                                const selectedOption = item.OPTIONS.find(opt => opt.SELECTED === true);
5824                                if (selectedOption) {
5825                                    item['SELECT_ID'] = selectedOption.ID;
5826                                    item['SELECT_NAME'] = selectedOption.NAME;
5827                                    if (self.ATTRIBUTES.CATALOG_VIEW == 'select') item['SELECT_SEARCH'] = item['SELECT_NAME'];
5828                                }
5829                            });
5830                        } else {
5831                            const formData = new FormData();
5832                            formData.append('product_id', product_id);
5833                            formData.append('with_image', '1');
5834
5835                            try {
5836                                await axios.post(getEndpoint('CATALOG_ATTRIBUTES'), formData).then(response => {
5837                                    if (!response.data?.length) {
5838                                        console.warn('productCardCatalog warn: CATALOG_ATTRIBUTES length');
5839                                        return;
5840                                    };
5841                                    self.ATTRIBUTES = response.data;
5842
5843                                    Array.from(self.ATTRIBUTES).forEac
5843h(item => {
5844                                        item.OPTIONS = item.OPTIONS.filter(opt => opt.PRODUCT_ID != null);
5845                                        const selectedOption = item.OPTIONS.find(opt => opt.SELECTED === true);
5846                                        if (selectedOption) {
5847                                            item['SELECT_ID'] = selectedOption.ID;
5848                                            item['SELECT_NAME'] = selectedOption.NAME;
5849                                            if (item.CATALOG_VIEW == 'select') item['SELECT_SEARCH'] = item['SELECT_NAME'];
5850                                        }
5851                                    });
5852                                    element[`PRODUCT_ATTRIBUTES_${product_id}`] = JSON.parse(JSON.stringify(self.ATTRIBUTES));
5853                                    return;
5854                                });
5855                            } catch (error) {
5856                                console.warn(`CATALOG_ATTRIBUTES error => ${error}`);
5857                            }
5858                        }
5859
5860                        if (product == null) {
5861                            element.ATTRIBUTES = JSON.parse(JSON.stringify(self.ATTRIBUTES));
5862                            self.getProductProperties();
5863                        }
5864
5865                        setTimeout(() => {
5866                            self.slideAttribute();
5867                        }, 50);
5868
5869                        productItem.classList.remove('catalog-opacity');
5870                        element.classList.remove('pointer-events-none');
5871                        element.classList.add('catalog-loaded');
5872                    },
5873                    setAttribute(attribute = null, option = null) {
5874                        const self = this;
5875
5876                        if (option.target?.value) option = Array.from(attribute.OPTIONS).find(x => x.ID == option.target.value);
5877                        if (attribute == null || option == null) return;
5878                        if (attribute['SELECT_ID'] == option.ID) return;
5879
5880                        Array.from(attribute.OPTIONS).map(x => x.SELECTED = x.ID == option.ID ? true : false);
5881                        attribute['SELECT_ID'] = option.ID;
5882                        attribute['SELECT_NAME'] = option.NAME;
5883                        if (attribute.CATALOG_VIEW == 'select') {
5884                            attribute['SELECT_SEARCH'] = attribute['SELECT_NAME'];
5885                            attribute.IS_OPEN = false;
5886                            Array.from(attribute.OPTIONS).forEach(item => {
5887                                item['HIDDEN'] = false;
5888                            });
5889                        }
5890
5891                        element.ATTRIBUTES = JSON.parse(JSON.stringify(self.ATTRIBUTES));
5892
5893                        self.getProductProperties(option);
5894                        return;
5895                    },
5896                    async getProductProperties(option = null) {
5897                        const self = this;
5898                        let catalogProductId = '';
5899
5900                        const formData = new FormData();
5901                        formData.append('model_id', modelId);
5902                        Array.from(self.ATTRIBUTES).forEach((item, index) => {
5903                            if (item.SELECT_ID) {
5904                                catalogProductId += `${item.GROUP_ID}_${item.SELECT_ID}`;
5905                                formData.append(`attribute[${index}][id]`, item.GROUP_ID);
5906                                formData.append(`attribute[${index}][option_id]`, item.SELECT_ID);
5907                            }
5908                        });
5909
5910                        if (element[`PRODUCT_DATA_${catalogProductId}`]) {
5911                            const PRODUCT = element[`PRODUCT_DATA_${catalogProductId}`];
5912                            await self.setProductData(PRODUCT);
5913                            await self.getAttribute(PRODUCT.ID);
5914                            return;
5915                        }
5916
5917                        try {
5918                            productItem.classList.add('catalog-opacity');
5919                            element.classList.add('pointer-events-none');
5920
5921                            await axios.post(getEndpoint('CATALOG_GET_PRODUCT'), formData).then(async response => {
5922                                if (response?.data?.length) {
5923                                    const PRODUCT = response.data[0];
5924                                    if (PRODUCT?.ID) {
5925                                        element[`PRODUCT_DATA_${catalogProductId}`] = PRODUCT;
5926                                        await self.setProductData(PRODUCT);
5927                                        await self.getAttribute(PRODUCT.ID);
5928                                    } else {
5929                                        await self.getAttribute(option.PRODUCT_ID, null);
5930                                    }
5931                                }
5932                            });
5933                        } catch (error) {
5934                            console.warn(`CATALOG_GET_PRODUCT error => ${error}`);
5935                        } finally {
5936                            productItem.classList.remove('catalog-opacity');
5937                            element.classList.remove('pointer-events-none');
5938                        }
5939                    },
5940                    async setProductData(P = null) {
5941                        if (P == null) return;
5942
5943                        productItem.dataset.id = P.ID;
5944                        const productItemData = productItem.querySelectorAll(`
5945                            [data-toggle="product-title"], 
5946                            [data-toggle="product-url"], 
5947                            [data-toggle="product-id"], 
5948                            .product-price, .product-price-not-vat, 
5949                            .product-price-not-discounted, .product-price-not-discounted-not-vat, 
5950                            .product-discount`
5951                        );
5952
5953                        Array.from(productItemData).forEach(item => {
5954                            if (item.dataset.toggle == 'product-title') item.innerText = P.TITLE;
5955                            if (item.dataset.toggle == 'product-url') item.href = P.URL;
5956                            if (item.dataset.toggle == 'product-id') item.value = P.ID;
5957
5958                            if (item.classList.contains('product-price')) item.innerText = T.vat(P.PRICE_SELL, P.VAT);
5959                            if (item.classList.contains('product-price-not-vat')) item.innerText = T.format(P.PRICE_SELL);
5960                            if (item.classList.contains('product-price-not-discounte')) item.innerText = T.vat(P.PRICE_NOT_DISCOUNTED, P.VAT);
5961                            if (item.classList.contains('product-price-not-discounted-not-vat')) item.innerText = T.format(P.PRICE_NOT_DISCOUNTED);
5962                            if (item.classList.contains('product-discount')) item.innerText = P.DISCOUNT_PERCENT;
5963                        });
5964
5965                        const discountItems = productItem.querySelectorAll('.discounted-badge, .product-discounted-price');
5966                        Array.from(discountItems).forEach(item => {
5967                            if (P.IS_DISPLAY_DISCOUNTED_ACTIVE && P.DISCOUNT_PERCENT > 0) {
5968                                item.classList.remove('d-none');
5969                            } else {
5970                                item.classList.add('d-none');
5971                            }
5972                        });
5973
5974                        const productItemImages = productItem.querySelectorAll('[data-toggle="product-image"]');
5975                        if (productItemImages?.length) {
5976                            for (let i = 0; i < productItemImages.length; i++ ) {
5977                                if (productItemImages[i].nodeName == 'SOURCE') {
5978                                    productItemImages[i].srcset = P.IMAGE_LIST[i]?.MEDIUM || P.IMAGE_LIST[0]?.MEDIUM || '';
5979                                } else {
5980                                    productItemImages[i].src = P.IMAGE_LIST[i]?.MEDIUM || P.IMAGE_LIST[0]?.MEDIUM || '';
5981                                }
5982                            }
5983                        }
5984                        return;
5985                    },
5986                    async slideAttribute() {
5987                        const catalogSliders = element.querySelectorAll('.swiper-container');
5988                        Array.from(catalogSliders).forEach(item => {
5989                            if (item.slider == 1) {
5990                                item['swiperData'] .update()
5991                                return;
5992                            }
5993
5994                            const nextEl = item.querySelector('.swiper-button-next');
5995                            const prevEl = item.querySelector('.swiper-button-prev');
5996
5997                            item['swiperData'] = new Swiper(item, {
5998                                slidesPerView: 'auto',
5999                                spaceBetween: 5,
6000                                watchOverflow: true,
6001                                navigation: {
6002                                    nextEl: nextEl,
6003                                    prevEl: prevEl
6004                                },
6005                            });
6006
6007                            item.slider = 1;
6008                        });
6009                    },
6010                    open(attribute) {
6011                        attribute['SELECT_SEARCH'] = '';
6012                        attribute.IS_OPEN = true;
6013                    },
6014                    search(attribute) {
6015                        Array.from(attribute.OPTIONS).forEach(item => {
6016                            if (item.NAME.toLowerCase().includes(attribute.SELECT_SEARCH.toLowerCase())) {
6017                                item['HIDDEN'] = false;
6018                            } else {
6019                                item['HIDDEN'] = true;
6020                            }
6021                        });
6022                    },
6023                    async close(attribute) {
6024                        attribute['SELECT_SEARCH'] = attribute['SELECT_NAME'];
6025                        setTimeout(() => {
6026                            Array.from(attribute.OPTIONS).forEac
6026h(item => {
6027                                item['HIDDEN'] = false;
6028                            });
6029
6030                            attribute.IS_OPEN = false;
6031                        }, 500);
6032                    },
6033                    parentClass(el) {
6034                        let currentElement = el;
6035
6036                        while (currentElement && currentElement?.dataset?.toggle != 'product') {
6037                            currentElement.classList.add('catalog-parent-element');
6038                            currentElement = currentElement.parentElement;
6039                        }
6040                    }
6041                },
6042                async mounted() {
6043                    const self = this;
6044                    self.parentClass(element);
6045
6046                    await self.getAttribute(productId);
6047                    element.classList.add('catalog-first-loaded');
6048
6049                    setTimeout(() => {
6050                        element.classList.remove('catalog-first-loaded');
6051                    }, 1500);
6052                }
6053            }).mount(element);
6054        }, 250);
6055
6056        return;
6057        });
6058
6059    element.addEventListener('mouseleave', () => {
6060        if (element.classList.contains('catalog-loaded')) return;
6061        clearTimeout(hoverTimeout);
6062    });
6063
6064    element.catalog = element;
6065};
6066
6067const catalogApp = {
6068    ATTRIBUTES: [],
6069    items: {},
6070    data: {},
6071    requestManager: {
6072        currentRequests: new Map(),
6073        async makeRequest(key, requestFn) {
6074            if (this.currentRequests.has(key)) {
6075                this.currentRequests.get(key).abort();
6076            }
6077            const controller = new AbortController();
6078            this.currentRequests.set(key, controller);
6079
6080            try {
6081                const result = await requestFn(controller.signal);
6082                this.currentRequests.delete(key);
6083                return result;
6084            } catch (error) {
6085                if (error.name === 'AbortError') {
6086                    console.log('Request cancelled');
6087                    return null;
6088                }
6089                throw error;
6090            }
6091        }
6092    },
6093    cacheManager: {
6094        maxItems: 100,
6095        cache: new Map(),
6096        set(key, value) {
6097            if (this.cache.size >= this.maxItems) {
6098                const firstKey = this.cache.keys().next().value;
6099                this.cache.delete(firstKey);
6100            }
6101            this.cache.set(key, value);
6102        },
6103        get(key) {
6104            return this.cache.get(key);
6105        },
6106        clear() {
6107            this.cache.clear();
6108        }
6109    },
6110    errorHandler: {
6111        handle(error, context) {
6112            console.error(`${context}: ${error.message}`);
6113            const userMessages = {
6114                'CATALOG_ATTRIBUTES': 'Ürün özellikleri yüklenirken bir hata oluştu',
6115                'CATALOG_GET_PRODUCT': 'Ürün bilgileri alınırken bir hata oluştu',
6116                'PAGE_LOAD': 'Sayfa yüklenirken bir hata oluştu'
6117            };
6118
6119            const message = userMessages[context] || 'Bir hata oluştu';
6120            this.showError(message);
6121        },
6122        showError(message) {
6123            const event = new CustomEvent('show-error', { detail: message });
6124            window.dispatchEvent(event);
6125        }
6126    },
6127    deepClone: (obj) => {
6128        try {
6129            return window.structuredClone ? structuredClone(obj) : JSON.parse(JSON.stringify(obj));
6130        } catch (error) {
6131            return JSON.parse(JSON.stringify(obj));
6132        }
6133    },
6134    init: async function() {
6135        const productCatalogs = document.querySelectorAll('[data-toggle="product-catalog"]');
6136        [...productCatalogs].forEach(productCatalog => {
6137            if (productCatalog.component) return;
6138
6139            const { product: productId, model: modelId } = productCatalog.dataset;
6140
6141            if (!productId || !modelId) {
6142                catalogApp.errorHandler.handle(new Error('Missing required data'), 'INIT');
6143                return;
6144            }
6145
6146            catalogApp.items[productId] = Vue.createApp({
6147                data() {
6148                    return {
6149                        ATTRIBUTES: [],
6150                        loading: false
6151                    }
6152                },
6153                methods: {
6154                    async getAttribute(product_id = null, product = true) {
6155                        if (!product_id) return;
6156                        const self = this;
6157
6158                        const cachedData = catalogApp.cacheManager.get(`PRODUCT_ATTRIBUTES_${product_id}`);
6159                        if (cachedData) {
6160                            this.processAttributes(cachedData);
6161                        } else {
6162                            await this.fetchAttributes(product_id);
6163                        }
6164
6165                        if (product == null) {
6166                            catalogApp.ATTRIBUTES = catalogApp.deepClone(self.ATTRIBUTES);
6167                            self.getProductProperties();
6168                        }
6169                        this.updateLoadingState(false);
6170                    },
6171
6172                    async fetchAttributes(product_id) {
6173                        const formData = new FormData();
6174                        formData.append('product_id', product_id);
6175                        formData.append('with_image', '1');
6176
6177                        try {
6178                            const response = await catalogApp.requestManager.makeRequest
6178(
6179                                'attributes',
6180                                async (signal) => {
6181                                    return await axios.post(getEndpoint('CATALOG_ATTRIBUTES'), formData, { signal });
6182                                }
6183                            );
6184
6185                            if (!response?.data?.length) {
6186                                catalogApp.errorHandler.handle(new Error('No data received'), 'CATALOG_ATTRIBUTES');
6187                                return;
6188                            }
6189
6190                            this.processAttributes(response.data);
6191                            catalogApp.cacheManager.set(`PRODUCT_ATTRIBUTES_${product_id}`, catalogApp.deepClone(this.ATTRIBUTES));
6192                        } catch (error) {
6193                            catalogApp.errorHandler.handle(error, 'CATALOG_ATTRIBUTES');
6194                        }
6195                    },
6196
6197                    processAttributes(attributes) {
6198                        this.ATTRIBUTES = catalogApp.deepClone(attributes);
6199                        this.ATTRIBUTES.forEach(item => {
6200                            item.OPTIONS = item.OPTIONS.filter(opt => opt.PRODUCT_ID != null);
6201                            const selectedOption = item.OPTIONS.find(opt => opt.SELECTED === true);
6202                            if (selectedOption) {
6203                                item.SELECT_ID = selectedOption.ID;
6204                                item.SELECT_NAME = selectedOption.NAME;
6205                                if (item.CATALOG_VIEW === 'select') {
6206                                    item.SELECT_SEARCH = item.SELECT_NAME;
6207                                }
6208                            }
6209                        });
6210                    },
6211
6212                    async setAttribute(attribute = null, option = null) {
6213                        if (!attribute || !option) return;
6214
6215                        if (this.setAttributeTimeout) {
6216                            clearTimeout(this.setAttributeTimeout);
6217                        }
6218
6219                        this.setAttributeTimeout = setTimeout(async () => {
6220                            if (option.target?.value) {
6221                                option = attribute.OPTIONS.find(x => x.ID == option.target.value);
6222                            }
6223                            if (attribute.SELECT_ID === option.ID) return;
6224
6225                            attribute.OPTIONS.forEach(x => x.SELECTED = x.ID === option.ID);
6226                            attribute.SELECT_ID = option.ID;
6227                            attribute.SELECT_NAME = option.NAME;
6228
6229                            if (attribute.CATALOG_VIEW === 'select') {
6230                                attribute.SELECT_SEARCH = attribute.SELECT_NAME;
6231                                attribute.IS_OPEN = false;
6232                                attribute.OPTIONS.forEach(item => item.HIDDEN = false);
6233                            }
6234
6235                            catalogApp.ATTRIBUTES = catalogApp.deepClone(this.ATTRIBUTES);
6236                            await this.getProductProperties(option);
6237                        }, 300);
6238                    },
6239
6240                    async getProductProperties(option = null) {
6241                        let catalogProductId = '';
6242                        const formData = new FormData();
6243                        formData.append('model_id', modelId);
6244
6245                        this.ATTRIBUTES.forEach((item, index) => {
6246                            if (item.SELECT_ID) {
6247                                catalogProductId += `${item.GROUP_ID}_${item.SELECT_ID}`;
6248                                formData.append(`attribute[${index}][id]`, item.GROUP_ID);
6249                                formData.append(`attribute[${index}][option_id]`, item.SELECT_ID);
6250                            }
6251                        });
6252
6253                        if (catalogApp.cacheManager.get(`PRODUCT_DATA_${catalogProductId}`)) {
6254                            const PRODUCT = catalogApp.cacheManager.get(`PRODUCT_DATA_${catalogProductId}`);
6255                            await this.setProductData(PRODUCT);
6256                            return;
6257                        }
6258
6259                        try {
6260                            this.setLoadingState();
6261                            const response = await catalogApp.requestManager.makeRequest
6261(
6262                                'product',
6263                                async (signal) => {
6264                                    return await axios.post(getEndpoint('CATALOG_GET_PRODUCT'), formData, { signal });
6265                                }
6266                            );
6267
6268                            if (response?.data?.length) {
6269                                const PRODUCT = response.data[0];
6270                                if (PRODUCT?.ID) {
6271                                    catalogApp.cacheManager.set(`PRODUCT_DATA_${catalogProductId}`, PRODUCT);
6272                                    await this.getAttribute(PRODUCT.ID);
6273                                    await this.setProductData(PRODUCT);
6274                                } else {
6275                                    await this.getAttribute(option.PRODUCT_ID, null);
6276                                }
6277                            }
6278                        } catch (error) {
6279                            catalogApp.errorHandler.handle(error, 'CATALOG_GET_PRODUCT');
6280                        } finally {
6281                            this.removeLoadingState();
6282                        }
6283                    },
6284
6285                    updateLoadingState(isLoading) {
6286                        const element = document.querySelector('.folder-product-detail');
6287                        if (!element) return;
6288
6289                        if (isLoading) {
6290                            element.classList.add('catalog-opacity', 'pointer-events-none');
6291                        } else {
6292                            element.classList.remove('catalog-opacity', 'pointer-events-none');
6293                        }
6294                        this.loading = isLoading;
6295                    },
6296
6297                    setLoadingState() {
6298                        this.updateLoadingState(true);
6299                    },
6300
6301                    removeLoadingState() {
6302                        this.updateLoadingState(false);
6303                    },
6304
6305                    validateUrl(url) {
6306                        try {
6307                            new URL(url, window.location.origin);
6308                            return true;
6309                        } catch {
6310                            return false;
6311                        }
6312                    },
6313
6314                    async setProductData(PRODUCT = null) {
6315                        if (!PRODUCT) return;
6316
6317                        const url = '/' + PRODUCT.URL;
6318                        if (!this.validateUrl(url)) {
6319                            catalogApp.errorHandler.handle(new Error('Invalid URL'), 'PAGE_LOAD');
6320                            return;
6321                        }
6322
6323                        if (!catalogApp.cacheManager.get(`PAGE_DATA_${PRODUCT.ID}`)) {
6324                            this.setLoadingState();
6325                            window.pushstateloaded = true;
6326
6327                            if (window.history && window.history.pushState) {
6328                                try {
6329                                    const response = await axios.get(url);
6330                                    catalogApp.cacheManager.set(`PAGE_DATA_${PRODUCT.ID}`, response.data);
6331                                } catch (error) {
6332                                    catalogApp.errorHandler.handle(error, 'PAGE_LOAD');
6333                                    window.location.href = url;
6334                                    return;
6335                                }
6336                            } else {
6337                                window.location.href = url;
6338                                return;
6339                            }
6340                        }
6341
6342                        const PAGE_DATA = catalogApp.cacheManager.get(`PAGE_DATA_${PRODUCT.ID}`);
6343                        if (!PAGE_DATA) return;
6344
6345                        const parser = new DOMParser();
6346                        const htmlDoc = parser.parseFromString(PAGE_DATA, 'text/html');
6347                        const newProductDetail = htmlDoc?.querySelector('.folder-product-detail');
6348                        const productDetail = document.querySelector('.folder-product-detail');
6349
6350                        if (productDetail && newProductDetail) {
6351                            productDetail.innerHTML = newProductDetail.innerHTML;
6352                            await window.history.replaceState('catalog', null, url);
6353
6354                            initComponents();
6355                            const blockId = productDetail.dataset.id;
6356                            if (typeof BLOCKS == 'object') {
6357                                const BLOCK = Array.from(BLOCKS).find(x => x.ID == blockId);
6358                                BLOCK_FN[BLOCK.ID](BLOCK, BLOCK.SETTING);
6359                            }
6360
6361                            const callback = productCatalog.dataset.callback;
6362                            window[callback]?.(productCatalog, PAGE_DATA);
6363
6364                            this.removeLoadingState();
6365                        } else {
6366                            window.location.href = url;
6367                        }
6368                    },
6369
6370                    open(attribute) {
6371                        attribute.SELECT_SEARCH = '';
6372                        attribute.IS_OPEN = true;
6373                    },
6374
6375                    search(attribute) {
6376                        const searchTerm = attribute.SELECT_SEARCH.toLowerCase();
6377                        attribute.OPTIONS.forEach(item => {
6378                            item.HIDDEN = !item.NAME.toLowerCase().includes(searchTerm);
6379                        });
6380                    },
6381
6382                    async close(attribute) {
6383                        attribute.SELECT_SEARCH = attribute.SELECT_NAME;
6384                        setTimeout(() => {
6385                            attribute.OPTIONS.forEach(item => item.HIDDEN = false);
6386                            attribute.IS_OPEN = false;
6387                        }, 500);
6388                    },
6389
6390                    parentClass(element) {
6391                        while (element && !element.classList.contains('folder-product-detail')) {
6392                            element.classList.add('catalog-parent-element');
6393                            element = element.parentElement;
6394                        }
6395                    }
6396                },
6397                async mounted() {
6398                    try {
6399                        document.body.classList.add('is-loading');
6400                        const cachedAttributes = catalogApp.cacheManager.get(`PRODUCT_ATTRIBUTES_${productId}`);
6401
6402                        if (cachedAttributes) {
6403                            this.ATTRIBUTES = catalogApp.deepClone(cachedAttributes);
6404                        } else if (catalogApp.ATTRIBUTES.length) {
6405                            this.ATTRIBUTES = catalogApp.deepClone(catalogApp.ATTRIBUTES);
6406                        } else {
6407                            await this.getAttribute(productId);
6408                        }
6409
6410                        this.parentClass(productCatalog);
6411                    } catch (error) {
6412                        catalogApp.errorHandler.handle(error, 'MOUNT');
6413                    } finally {
6414                        document.body.classList.remove('is-loading');
6415                    }
6416                }
6417            }).mount(productCatalog);
6418
6419            productCatalog.component = 1;
6420        });
6421    }
6422};
6423catalogApp.init();
6424
6425const setupImageTracking = {
6426    SETUP_IMAGE_TIMEOUT: 7000,
6427    isSvg(src) {
6428        if (!src) return true;
6429        return (
6430            src.endsWith('.svg') ||
6431            src.includes('.svg?') ||
6432            src.startsWith('data:image/svg')
6433        );
6434    },
6435    triggerFallback(img, src) {
6436        if (img.dataset.fallbackProcessed) return;
6437        img.dataset.fallbackProcessed = 'true';
6438
6439        const fallbackSrc = src.replace(/(?:https?:)?\/\/[^/]+/i, `${location.protocol}//${location.hostname}`);
6440
6441        if (img.dataset.src) {
6442            img.dataset.src = fallbackSrc;
6443            setTimeout(() => {
6444                if (img.src != fallbackSrc) img.src = fallbackSrc;
6445            }, 100);
6446        } else {
6447            img.src = fallbackSrc;
6448        }
6449
6450        const imgPicture = img.closest('picture');
6451        if (imgPicture) {
6452            const imgSource = imgPicture.querySelector('source');
6453            if (imgSource) {
6454                const srcset = imgSource.srcset;
6455                const fallbackSrcset = srcset.replace(/(?:https?:)?\/\/[^/]+/i, `${location.protocol}//${location.hostname}`);
6456                imgSource.srcset = fallbackSrcset;
6457            }
6458        }
6459    },
6460    trackImage(img, src) {
6461        if (window.location.hostname === 'local.tsoft.biz') return;
6462        if (!src || !src.includes('witcdn.') || setupImageTracking.isSvg(src)) return;
6463
6464        const timer = setTimeout(() => {
6465            if (!img.complete || img.naturalWidth === 0) {
6466                setupImageTracking.triggerFallback(img, src);
6467            }
6468        }, setupImageTracking.SETUP_IMAGE_TIMEOUT);
6469
6470        img.addEventListener('load', () => {
6471            if (img.naturalWidth === 0) {
6472                setupImageTracking.triggerFallback(img, src);
6473            }
6474            clearTimeout(timer);
6475        }, { once: true });
6476
6477        img.addEventListener('error', () => {
6478            setupImageTracking.triggerFallback(img, src);
6479            clearTimeout(timer);
6480        }, { once: true });
6481
6482        if (img.complete && img.naturalWidth === 0) {
6483            clearTimeout(timer);
6484            setupImageTracking.triggerFallback(img, src);
6485        }
6486    },
6487    init() {
6488        document.querySelectorAll('img').forEach(img => {
6489            const src = img.src;
6490            const dataSrc = img.dataset.src;
6491
6492            if (dataSrc || img.classList.contains('lazyload')) return;
6493            setupImageTracking.trackImage(img, src);
6494        });
6495    }
6496};
6497
6498const imageTrackingObserver = new MutationObserver(mutations => {
6499    mutations.forEach(mutation => {
6500        mutation.addedNodes.forEach(node => {
6501            if (node.nodeType === 1) {
6502                if (node.tagName === 'IMG') {
6503                    const src = node.src;
6504                    const dataSrc = node.dataset.src;
6505                    if (!dataSrc && !node.classList.contains('lazyload')) {
6506                        setupImageTracking.trackImage(node, src);
6507                    }
6508                }
6509                const imgs = node.querySelectorAll && node.querySelectorAll('img');
6510                if (imgs) {
6511                    imgs.forEach(img => {
6512                        const src = img.src;
6513                        const dataSrc = img.dataset.src;
6514                        if (!dataSrc && !img.classList.contains('lazyload')) {
6515                            setupImageTracking.trackImage(img, src);
6516                        }
6517                    });
6518                }
6519            }
6520        });
6521    });
6522});
6523
6524imageTrackingObserver.observe(document.body, {
6525    childList: true,
6526    subtree: true
6527});
6528
6529document.addEventListener('lazyloaded', e => {
6530    const img = e.target;
6531    if (!img || img.tagName !== 'IMG') return;
6532
6533    const src = img.dataset.src;
6534    setTimeout(() => {
6535        setupImageTracking.trackImage(img, src);
6536    }, 100);
6537});
6538
6539const initComponents = () => {
6540    catalogApp.init();
6541    setupImageTracking.init();
6542
6543    let tsoftComponents = {
6544        Dropdown: [T.dropdown, '[data-toggle*="dropdown"]'],
6545        Tab: [T.tab, '[data-toggle*="tab"]'],
6546        Accordion: [T.accordion, '[data-toggle*="accordion"]'],
6547        Placeholder: [T.placeholder.init, '[data-toggle*="placeholder"]'],
6548        Mask: [T.mask, '[data-toggle*="mask"]'],
6549        Zoom: [T.zoomImage, '[data-toggle*="zoom-image"]'],
6550        Modal: [T.modal, '[data-toggle*="modal"]'],
6551        Tooltip: [T.tooltip, '[data-toggle*="tooltip"]'],
6552        Drawer: [T.drawer, '[data-toggle*="drawer"]'],
6553        Qty: [T.qty, '[data-toggle*="qty"]'],
6554        Login: [T.loginForm, '[data-toggle*="login-form"]'],
6555        OtpLogin: [T.otpLogin, '[data-toggle*="otp-login"]'],
6556        PhoneMask: [tFlag.init, '[data-flag-masked]'],
6557        Language: [T.setLanguage.init, '[data-toggle*="language"]'],
6558        Currency: [T.setCurrency.init, '[data-toggle*="currency"]'],
6559        Variant: [selectVaryant.init, '[data-toggle*="variant"]'],
6560        Catalog: [catalog, '[data-toggle*="product-item-catalog"]'],
6561        Popupwin: [T.popupWin, '.popupwin'],
6562        Affix: [T.affix, '[data-toggle*="affix"]'],
6563        Sticky: [T.sticky, '[data-toggle*="sticky"]'],
6564        InputFile: [T.inputFile, '[data-toggle*="input-file"]'],
6565        EqualHeight: [T.equalHeight, '[data-toggle*="equalHeight"]'],
6566        Subscribe: [subscribe.init, '[data-toggle*="subscribe"]'],
6567        AddFavBtn: [favouriteProducts.click, '.add-favourite-btn'],
6568        PopConfirm: [T.popConfirm, '[data-toggle*="popconfirm"]'],
6569        CountDown: [countDown.init, '[data-toggle*="count-down"]'],
6570        SnapScroll: [snapScroll.init, '[data-toggle*="snap-scroll"]'],
6571        SocialGoogle:[T.signInGoogleAuth, '[data-toggle*="signin-google"]'],
6572        ProductListLayout: [T.productListLayout, '[data-toogle="layaout"]'],
6573        ShareButton: [T.shareButton, '[data-toggle*="share"]'],
6574    };
6575
6576    let initializeDataAPI = function(Constructor, collection) {
6577        Array.from(collection).map(function(x) { return new Constructor(x); });
6578    };
6579
6580    for (let component in tsoftComponents) {
6581        let selectors = tsoftComponents[component][1].split(/\s+/);
6582        let elements = [];
6583
6584        selectors.forEach(selector => {
6585            let selectedElements = document.querySelectorAll(selector.trim());
6586            elements = elements.concat(Array.from(selectedElements));
6587        });
6588
6589        initializeDataAPI(tsoftComponents[component][0], elements);
6590    }
6591
6592    T.mask('input[type="password"]', 'password');
6593    T.mask('input[type="email"]', 'email');
6594    T.mask('input[name="name"], input[name="surname"], input[name="fullname"], input[name="firstname"], input[name="lastname"]', 'string');
6595
6596    T('a[href*="authentication/social-login"]').on('click', (e) => {
6597        e.preventDefault();
6598
6599        if(getUrlParam('type', e.target.href) == 'apple') {
6600            axios.get(e.target.href).then(response => {
6601                window.location.href = response.data.data[0];
6602            });
6603        }
6604    });
6605
6606};
6607
6608const lazyControl = (wrapper) => {
6609    if (!wrapper || typeof wrapper !== 'object') return;
6610
6611    const observer = new IntersectionObserver((entries) => {
6612        entries.forEach(entry => {
6613            if (entry.isIntersecting) {
6614                const swiper = entry.target.querySelector('.swiper-wrapper');
6615                if (swiper && !swiper.lazyItem) {
6616                    loadImagesProgressively(swiper);
6617                    swiper.lazyItem = 1;
6618                }
6619                observer.unobserve(entry.target);
6620            }
6621        });
6622    }, {
6623        threshold: 0.1
6624    });
6625
6626    observer.observe(wrapper);
6627};
6628
6629const loadImagesProgressively = (container, batchSize = 3) => {
6630    const lazyImages = container.querySelectorAll('[loading="lazy"]:not(.lazyloaded)');
6631    if (!lazyImages.length) return;
6632
6633    const loadBatch = (startIndex) => {
6634        const batch = Array.from(lazyImages).slice(startIndex, startIndex + batchSize);
6635        if (!batch.length) return;
6636
6637        batch.forEach(img => {
6638            img.classList.add('lazyloaded');
6639            img.dataset.priority = 'true';
6640            img.setAttribute('loading', 'eager');
6641            lazySizes.loader.unveil(img);
6642        });
6643
6644        setTimeout(() => {
6645            loadBatch(startIndex + batchSize);
6646        }, 100);
6647    };
6648
6649    loadBatch(0);
6650    lazySizes.autoSizer.checkElems();
6651};
6652
6653const kvkkCallback = [];
6654const memberKvkkControl = () => {
6655    if (typeof ADMIN_USER_FULLNAME != 'undefined' && ADMIN_USER_FULLNAME.trim() != '') return;
6656
6657    if (MEMBER_INFO.ID > 0 && MEMBER_INFO.KVKK != 1 && SETTINGS.KVKK_REQUIRED == 1) {
6658        axios.get('/srv/service/content-v5/sub-folder/6/1008/notifications').then(response => {
6659            const data = response.data;
6660            T.modal({
6661                id: 'notifications-popup',
6662                html: data,
6663                width: '480px',
6664                close : true,
6665                closeCallback() {
6666                    if (PAGE_TYPE == 'order' || PAGE_TYPE == 'address' || PAGE_TYPE == 'payment') window.location.reload();
6667                }
6668            });
6669        });
6670    }
6671};
6672
6673const activationControl = () => {
6674    const activationType = getUrlParam('activation');
6675    if (activationType) {
6676        switch (activationType) {
6677            case 'newsletter':
6678                const token = getUrlParam('token');
6679                axios.post('/srv/service/guest/activateSubscription/' + token).then(response => {
6680                    const data = response.data;
6681                    if (data.status === 1) {
6682                        T.modal({
6683                            id: 'activation-newsletter',
6684                            html: data.statusText,
6685                            width: '580px',
6686                            close : true,
6687                        });
6688
6689                        setTimeout(function (){
6690                            for(let i=0; i < callbacks.customer.subscribe.length; i++){
6691                                if(typeof callbacks.customer.subscribe[i] === 'function'){
6692                                    try {
6693                                        callbacks.customer.subscribe[i]?.(data);
6694                                    } catch (error) { console.log(`Customer Other Callback Error => ${error}`); }
6695                                }
6696                            }
6697                        }, 500);
6698
6699                    }
6700                });
6701                break;
6702            case 'membership':
6703                const memberId = getUrlParam('id'),
6704                      memberToken = getUrlParam('token');
6705                axios.post('/srv/service/customer/activateMembership/' + memberId + '/' + memberToken).then(response => {
6706                    const data = response.data;
6707                    if (data.status) {
6708                        T.modal({
6709                            id: 'activation-membership',
6710                            html: `<a href="/srv/service/content-v5/sub-folder/5/1006/popup-login" class="popupwin">${TLANG.activation_membership_success || 'Üyeliğiniz başarıyla aktifleştirilmiştir, giriş yapmak için <b>tıklayınız</b>'}</a>`,
6711                            width: 'auto',
6712                            close : true,
6713                        });
6714                        initComponents();
6715                        history.pushState('', '', '/');
6716                    }
6717                });
6718                break;
6719            case 'facebook':
6720                axios.get('/srv/service/content-v5/sub-folder/6/1008/facebook-email').then(response => {
6721                    const data = response.data;
6722                    T.modal({
6723                        id: 'activation-facebook-email',
6724                        html: data,
6725                        width: '400px',
6726                        close : true,
6727                    });
6728                });
6729                break;
6730            case 'facebookphone':
6731                axios.get('/srv/service/content-v5/sub-folder/6/1008/facebook-phone').then(response => {
6732                    const data = response.data;
6733                    T.modal({
6734                        id: 'activation-facebook-phone',
6735                        html: data,
6736                        width: '400px',
6737                        close : true,
6738                    });
6739                });
6740                break;
6741            case 'twitter':
6742                axios.get('/srv/service/content-v5/sub-folder/6/1008/twitter-email').then(response => {
6743                    const data = response.data;
6744                    T.modal({
6745                        id: 'activation-twitter-email',
6746                        html: data,
6747                        width: '400px',
6748                        close : true,
6749                    });
6750                });
6751                break;
6752            case 'googlephone':
6753                axios.get('/srv/service/content-v5/sub-folder/6/1008/google-phone').then(response => {
6754                    const data = response.data;
6755                    T.modal({
6756                        id: 'activation-google-phone',
6757                        html: data,
6758                        width: '400px',
6759                        close : true,
6760                    });
6761                });
6762                break;
6763            case 'social':
6764                axios.get('/srv/service/content-v5/sub-folder/6/1008/social').then(response => {
6765                    const data = response.data;
6766                    T.modal({
6767                        id: 'activation-social',
6768                        html: data,
6769                        width: '400px',
6770                        close : true,
6771                    });
6772                });
6773                break;
6774        }
6775    }
6776
6777    const activationTypeError = getUrlParam('error');
6778    if (activationTypeError && PAGE_ID == '5' && MEMBER_INFO.ID < 1) {
6779        switch (activationTypeError) {
6780            case 'mail_already_registered':
6781                T.modal({
6782                    html: `<div class="p-1" style="font-size: 14px">${TLANG.login_mail_error || 'Bu e-posta adresiyle kayıt yapılmıştır. Lütfen giriş yapınız.'}</div>`,
6783                    width: '435px',
6784                    close: true
6785                });
6786                const mailUrl = new URL(window.location.href);
6787                mailUrl.searchParams.delete('error');
6788                window.history.replaceState({}, '', mailUrl);
6789                break;
6790            case 'phone_already_registered':
6791                T.modal({
6792                    html: `<div class="p-1" style="font-size: 14px">${TLANG.login_phone_error || 'Bu telefon numarasıyla kayıt yapılmıştır. Lütfen giriş yapınız.'}</div>`,
6793                    width: '435px',
6794                    close: true
6795                });
6796                const phoneUrl = new URL(window.location.href);
6797                phoneUrl.searchParams.delete('error');
6798                window.history.replaceState({}, '', phoneUrl);
6799                break;
6800        }
6801    }
6802
6803    const multiShoppingToken = getUrlParam('TmultiShoppingCart');
6804    if (multiShoppingToken) {
6805        const parts = multiShoppingToken.split('.');
6806        if (parts.length === 3) {
6807            const base64 = parts[1].replace(/-/g, '+').replace(/_/g, '/');
6808            const padded = base64 + '='.repeat((4 - base64.length % 4) % 4);
6809            const payload = JSON.parse(atob(padded));
6810
6811            if (payload.length == 0) return;
6812        
6813            const cartOpt = {
6814                productId: [],
6815                variantId: [],
6816                quantity: [],
6817                buyNow: 1,
6818                redirect: 'order'
6819            };
6820        
6821            const formData = new FormData();
6822            Array.from(payload).forEach(product => {
6823                formData.append('ws_codes[]', product.supplierProductCode);
6824            });
6825
6826            document.body.classList.add('is-loading');
6827            axios.post(getEndpoint('GET_PRODUCT_BY_WS_CODES'), formData).then(response => {
6828                const data = response.data.data;
6829                if (!data?.length) return;
6830
6831                Array.from(data).forEach(item => {
6832                    cartOpt.productId.push(item.id);
6833
6834                    const product = payload.find(i => i.supplierProductCode == item.ws_code);
6835                    if (product) {
6836                        cartOpt.quantity.push(product.quantity || 1);
6837                        cartOpt.variantId.push(item.variant_id || 0);
6838                    }
6839                });
6840
6841                if (cartOpt.productId.length) {
6842                    multiCart = true;
6843                    addToCart(cartOpt);
6844                }
6845            }).catch(error => {
6846                console.warn(`GET_PRODUCT_BY_WS_CODES error => ${error}`);
6847            }).finally(() => {
6848                document.body.classList.remove('is-loading');
6849            });
6850        }
6851    }
6852};
6853
6854const referererStorage = {
6855    api: '',
6856    hasLocal: 'localStorage' in window && window['localStorage'] !== null,
6857    hasQueryString: function() {
6858        let ref = document.referrer || "";
6859        if (ref == '') {
6860            return false;
6861        }
6862        let a = document.createElement('a');
6863        a.href = ref;
6864        let q = '';
6865        let queryString = a.search;
6866        let pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
6867        for (let i = 0; i < pairs.length; i++) {
6868            let pair = pairs[i].split('=');
6869            if (pair[0] == 'q') {
6870                q = pair[1];
6871            }
6872        }
6873        return q != '';
6874    },
6875    addItemStorage: async function() {
6876        let cReferrer = localStorage.getItem('cReferrer');
6877        let items = [];
6878        if (cReferrer !== null) {
6879            let obj = {};
6880            try {
6881                obj = JSON.parse(cReferrer);
6882            } catch (err) {
6883                obj = {};
6884            }
6885            if (typeof obj.schedule != "undefined" && Date.now() < obj.schedule && !this.hasQueryString()) {
6886                return;
6887            }
6888            items = obj.items || [];
6889        }
6890
6891        try {
6892            if (!this.api) {
6893                const response = await axios.get('/srv/service/guest/ip');
6894                this.api = response.data;
6895            }
6896        } catch (error) {
6897            console.warn(`GET_IP error => ${error}`);
6898        }
6899        items.push({ time: Number.parseInt(Date.now() / 1000), uri: document.referrer, page: window.location.href, ip: this.api });
6900        this.setItems(items);
6901    },
6902    getObj: function() {
6903        let cReferrer = null;
6904        let cReferrerObj = {};
6905        if (this.hasLocal) {
6906            cReferrer = localStorage.getItem('cReferrer');
6907        } else {
6908            try {
6909                cReferrer = T.getCookie('cReferrer');
6910            } catch (err) {}
6911        }
6912        try {
6913            cReferrerObj = JSON.parse(cReferrer);
6914        } catch (err) {}
6915        return cReferrerObj;
6916    },
6917    getItems: function() {
6918        return this.getObj().items || [];
6919    },
6920    setItems: function(items) {
6921        let obj = {
6922            schedule: Date.now() + (24 * 60 * 60 * 1000),
6923            items: items || []
6924        };
6925        this.save(obj);
6926    },
6927    save: function(sObj) {
6928        if (this.hasLocal) {
6929            this.saveStorage(sObj);
6930        } else {
6931            this.saveCookie(sObj);
6932        }
6933    },
6934    saveStorage: function(sObj) {
6935        localStorage.setItem('cReferrer', JSON.stringify(sObj));
6936    },
6937    saveCookie: function(sObj) {
6938        try {
6939            T.setCookie('cReferrer', JSON.stringify(sObj), { path: '/', expires: 30 });
6940        } catch (err) {}
6941    }
6942};
6943
6944const grecaptchaReset = function(element = null) {
6945    if (typeof grecaptcha == 'undefined') return;
6946    const recaptchas = document.querySelectorAll('.g-recaptcha');
6947
6948    if (element) {
6949        const elementIndex = Array.from(recaptchas).indexOf(element);
6950        if (elementIndex > -1) grecaptcha.reset(elementIndex);
6951    } else {
6952        Array.from(recaptchas).forEach((_, index) => {
6953            grecaptcha.reset(index);
6954
6955            });
6956    }
6957}
6958
6959const googleTokenClientFn = () => {
6960    if (typeof googleTokenClient != 'undefined') {
6961        googleTokenClient.requestAccessToken();
6962        return;
6963    }
6964
6965    if (typeof google !== 'undefined') {
6966        try {
6967            googleTokenClient = google.accounts.oauth2.initTokenClient({
6968                client_id: GOOGLE_CLIENT_ID,
6969                scope: 'openid email profile',
6970                callback: (response) => {
6971                    if (response.access_token) {
6972                        location.href = location.origin + `/srv/service/social/google/login?code=${response.access_token}`;
6973                    } else {
6974                        console.warn('Google Sign-In error:', response);
6975                    }
6976                },
6977            });
6978            googleTokenClient.requestAccessToken();
6979        } catch (error) {
6980            googleTokenClient = undefined;
6981            console.warn('Google Sign-In error:', error);
6982        }
6983    }
6984}
6985
6986T.ready(() => {
6987    const productPoint = document.querySelector('#product-point');
6988    if (productPoint?.value) T('.product-cash-amount').html(T.format(productPoint.value, 2));
6989
6990    T('.product-item').on('click', e => {
6991        const element = e.target;
6992        const productItem = element.closest('.product-item');
6993        const productLink = element.closest('a');
6994        if (!productLink) return;
6995
6996        let hrefValue = productLink.getAttribute('href');
6997        if (!hrefValue || hrefValue == '#') return;
6998
6999        if (!hrefValue.startsWith('http://') && !hrefValue.startsWith('https://')) {
7000            hrefValue = `${window.location.origin}${hrefValue}`;
7001        }
7002
7003        try {
7004            const url = new URL(hrefValue);
7005            const productIndex = Array.from(document.querySelectorAll('.product-item')).indexOf(productItem);
7006            for (let i = 0; i < callbacks.product.click.length; i++) {
7007                if (typeof callbacks.product.click[i] === 'function') {
7008                    try {
7009                        callbacks.product.click[i]?.(productIndex, productItem);
7010                    } catch (error) {
7011                        console.warn(`Product Click Callback Error => ${error}`);
7012                    }
7013                }
7014            }
7015        } catch (error) {
7016            console.warn('Invalid URL:', hrefValue); 
7017        }
7018    });
7019
7020    T('.logout').on('click', e => {
7021        e.preventDefault();
7022        axios.get('/srv/service/customer/logout').then(() => {
7023            LocalApi.remove('v5token');
7024            window.location.href = '/';
7025        });
7026    });
7027
7028    T('.cart-soft-count').text(CART_COUNT);
7029    T('.cart-soft-price').text(CART_TOTAL);
7030
7031    favouriteProducts.init();
7032    compareSet();
7033    mobileAppFn();
7034
7035    passwordStrengthControl();
7036    memberKvkkControl();
7037    activationControl();
7038    referererStorage.addItemStorage();
7039    /* Pwa(); */
7040});
7041
7042document.body ? initComponents() : T(document).one('DOMContentLoaded', initComponents);

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.