PageSourceSearch

https://www.luxentu.de/templates/NIUplus/js/niu-app/niu.quickBuy.js?v=7.14.0

js luxentu.de collected 2026-10-08 11:01:57 UTC 15,116 bytes, 398 lines download raw bytes

1import NiuBase from "niu-base";
2
3class NiuQuickBuy extends NiuBase{
4    static Selectors = {
5        wrapper:(id='')=>{return'[data-niu-sidebar-quickbuy'+(id!==''?'='+id:'')+']'},
6        wrapperType:'[data-niu-sidebar-content]',
7        productKey:'[data-niu-sidebar-productpreview-trigger]',
8        type:'[data-niu-sidebar-productpreview-type]',
9        currentProduct:"[data-niu-sidebar-currentproduct]",
10
11        variation: "[data-niu-variation]",
12        variationType:"[data-niu-variation-type]",
13        productPreviewImage:"[data-niu-sidebar-productpreview-image]",
14        productPreviewPrice:"[data-niu-sidebar-productpreview-price]",
15        productCheckoutContainer:"[data-niu-sidebar-productpreview-checkout-container]",
16        productPreviewBasket:"[data-niu-sidebar-productpreview-checkout]",
17        productVariationTitle:'[data-niu-sidebar-productpreview-variation-title]',
18        productCheckoutTitle:'[data-niu-sidebar-productpreview-checkout-title]',
19        variationContainer:"[data-niu-sidebar-variation-container]",
20        variationItem: "[data-niu-variation-item]",
21        qtyInput: "[data-niu-sidebar-productpreview-checkout-qtyinput]",
22        qtyUp:"[data-niu-sidebar-productpreview-checkout-qtyupbutton]",
23        qtyDown:"[data-niu-sidebar-productpreview-checkout-qtydownbutton]",
24        pluginSlot:"[data-niu-sidebar-plugin-slot]"
25
26    }
27
28    constructor(wrapper) {
29        super(wrapper);
30        this.type = wrapper.dataset[NiuBase.select(NiuQuickBuy.Selectors.wrapperType)]
31        this.sidebarId = wrapper.dataset[NiuBase.select(NiuQuickBuy.Selectors.wrapper())];
32        this.product = false;
33        this.productId = '';
34        this.variations = {};
35        this.cartButton = "";
36        this.priceWrapper = "";
37        this.productImageContainer = "";
38        this.productPriceContainer = "";
39        this.productCheckoutContainer = "";
40        this.productCheckoutBasket = "";
41        this.productVariationContainer = "";
42        this.productVariationTitle = "";
43        this.productCheckoutTitle = "";
44        this.qtyInput = "";
45        this.qtyUpBtn = "";
46        this.qtyDownBtn = "";
47    }
48
49    init(){
50        super.init();
51        this.register();
52    }
53
54    async getQuickBuyProduct(trigger){
55        if(!trigger.dataset || !trigger.dataset[NiuBase.select(NiuQuickBuy.Selectors.productKey)]){
56            this.postError('No productKey in trigger');
57            return;
58        }
59
60        this.dispatch(dzm.events.sidebar.startLoading);
61
62        const productKey = trigger.dataset[NiuBase.select(NiuQuickBuy.Selectors.productKey)];
63
64        const body = {
65            kArtikel:productKey
66        };
67        const endpoint = `${niu.controller.basicData.shopUrl}?niuapi=true&jtl_token=${niu.controller.basicData.jtlToken}&request_type=getProductPreview`;
68
69        let res = await fetch(
70            endpoint,{
71                method:'POST',
72                body:JSON.stringify(body)
73            });
74        const contentType = res.headers.get('content-type')
75
76        let result;
77        if(contentType && contentType.includes('application/json')){
78            result = await res.json()
79            //console.warn('RESULT', result)
80        }else{
81            result = await res.text()
82            this.postError(result);
83            return
84        }
85
86
87        if(result.data && result.data !== ''){
88            this.wrapper.innerHTML = result.data;
89            this.initCurrentProduct(true);
90            this.dispatch(dzm.events.quickbuy.loaded)
91
92        }else{
93            this.postError('unknown template error')
94        }
95
96        this.dispatch(dzm.events.sidebar.stopLoading)
97
98    }
99
100    async getQuickViewProduct(trigger){
101        if(!trigger.dataset || !trigger.dataset[NiuBase.select(NiuQuickBuy.Selectors.productKey)]){
102            this.postError('No productKey in trigger');
103            return;
104        }
105
106        this.dispatch(dzm.events.sidebar.startLoading);
107
108        const productKey = trigger.dataset[NiuBase.select(NiuQuickBuy.Selectors.productKey)];
109
110        const body = {
111            kArtikel:productKey
112        };
113        const endpoint = `${niu.controller.basicData.shopUrl}?niuapi=true&jtl_token=${niu.controller.basicData.jtlToken}&request_type=getProductQuickView`;
114
115        let res = await fetch(
116            endpoint,{
117                method:'POST',
118                body:JSON.stringify(body)
119            });
120        const contentType = res.headers.get('content-type')
121
122        let result;
123        if(contentType && contentType.includes('application/json')){
124            result = await res.json()
125            //console.warn('RESULT', result)
126        }else{
127            result = await res.text()
128            this.postError(result);
129            return
130        }
131
132
133        if(result.data && result.data !== ''){
134            this.wrapper.innerHTML = result.data;
135            this.dispatch(dzm.events.quickView.loaded, trigger)
136        }else{
137            this.postError('unknown template error')
138        }
139
140        this.dispatch(dzm.events.sidebar.stopLoading)
141
142    }
143
144    initCurrentProduct(first = false){
145        this.product = this.wrapper.querySelector(NiuQuickBuy.Selectors.currentProduct);
146        this.productId = this.product.dataset[NiuBase.select(NiuQuickBuy.Selectors.currentProduct)];
147        this.productImageContainer = this.product.querySelector(NiuQuickBuy.Selectors.productPreviewImage)
148        this.productPriceContainer = this.product.querySelector(NiuQuickBuy.Selectors.productPreviewPrice)
149        this.productCheckoutBasket = this.product.querySelector(NiuQuickBuy.Selectors.productPreviewBasket)
150        this.productCheckoutContainer = this.product.querySelector(NiuQuickBuy.Selectors.productCheckoutContainer)
151        this.productVariationContainer = this.product.querySelector(NiuQuickBuy.Selectors.variationContainer)
152        this.productVariationTitle = this.product.querySelector(NiuQuickBuy.Selectors.productVariationTitle)
153        this.productCheckoutTitle = this.product.querySelector(NiuQuickBuy.Selectors.productCheckoutTitle)
154        // Slot fuer Beitraege von Zusatzplugins - optional, nicht jede Sidebar hat ihn
155        this.pluginSlot = this.product.querySelector(NiuQuickBuy.Selectors.pluginSlot)
156
157        this.getAllVariations();
158
159        if(first){
160            this.initQtyBtns()
161            //this is just a trick to trigger first time a variation selection, so if there is only one choice, it should load the child with this option
162            this.variationSelected(null,null,'SELECTBOX').then(result =>{
163                return result
164            })
165        }
166
167    }
168
169    getAllVariations(){
170        const variations = this.product.querySelectorAll(NiuQuickBuy.Selectors.variation)
171        variations.forEach(v =>{
172            const variation = v.dataset[NiuBase.select(NiuQuickBuy.Selectors.variation)]
173            const variationType = v.dataset[NiuBase.select(NiuQuickBuy.Selectors.variationType)]
174
175            this.variations['v'+variation] = v
176            this.variations['v'+variation].variationType = variationType
177            this.variations['v'+variation].variationItems = { }
178            const variationItems = v.querySelectorAll(NiuQuickBuy.Selectors.variationItem)
179            if(variationType === 'SELECTBOX'){
180                v.addEventListener('change',async (e)=>{
181
182                    await this.variationSelected(e,null,variationType)
183                })
184            }
185            variationItems.forEach(vi=>{
186                const variationItem = vi.dataset[NiuBase.select(NiuQuickBuy.Selectors.variationItem)];
187                if(variationItem){
188                    this.variations['v'+variation].variationItems['vi'+variationItem.split(':')[1]] = vi
189
190                }
191                if(variationType !== 'SELECTBOX'){
192                    vi.addEventListener('click',async (e)=>{
193
194                        await this.variationSelected(e,vi,variationType)
195                    })
196                }
197
198            })
199        })
200    }
201
202    initQtyBtns(){
203        this.qtyInput = this.product.querySelector(NiuQuickBuy.Selectors.qtyInput)
204        this.qtyUpBtn = this.product.querySelector(NiuQuickBuy.Selectors.qtyUp)
205        if(this.qtyUpBtn){
206            this.qtyUpBtn.addEventListener('click',(e)=>{
207                this.updateQty(e,'up')
208            })
209        }
210
211        this.qtyDownBtn = this.product.querySelector(NiuQuickBuy.Selectors.qtyDown)
212        if(this.qtyDownBtn){
213            this.qtyDownBtn.addEventListener('click',(e)=>{
214                this.updateQty(e,'down')
215            })
216        }
217    }
218
219    updateQty(e,type){
220        let step = 1
221        if(this.qtyInput.step === 'any'){
222            if(type === 'up'){
223                this.qtyInput.value++;
224            }else{
225                this.qtyInput.value--;
226            }
227
228        }else{
229            if(type === 'up'){
230                this.qtyInput.stepUp();
231            }else{
232                this.qtyInput.stepDown();
233            }
234        }
235
236    }
237
238    async variationSelected(e,vi,type){
239        let body = {}
240        body.kArtikel = this.productId
241        body.selectedVariations = {}
242
243
244
245
246
247
248        if(type !== 'SELECTBOX'){
249            vi.checked = true
250        }
251
252        Object.values(this.variations).forEach(vg=>{
253            const variationType = vg.dataset[NiuBase.select(NiuQuickBuy.Selectors.variationType)]
254
255            if(variationType === 'SELECTBOX' && vg.selectedOptions && vg.selectedOptions.length > 0){
256
257                const variationItem = vg.selectedOptions[0].dataset[NiuBase.select(NiuQuickBuy.Selectors.variationItem)]
258                if(variationItem){
259                    let variationSelection = variationItem.split(':')
260                    body.selectedVariations[variationSelection[0]] = variationSelection[1]
261                }
262
263            }else{
264                Object.values(vg.variationItems).forEach(vi=>{
265                    const variationItem = vi.dataset[NiuBase.select(NiuQuickBuy.Selectors.variationItem)]
266                    // Pessimistische Vormarkierung: Alle Varianten gelten als nicht
267                    // waehlbar, bis die Antwort unten sagt, welche moeglich sind.
268                    // 'not-in-stock' und nicht 'sold-out' - der Kern trifft dieselbe
269                    // Unterscheidung (jtl.article.js:1592: notExists -> not-in-stock,
270                    // sonst sold-out). Hier geht es immer um "gibt es in dieser
271                    // Kombination nicht", nie um echten Ausverkauf.
272                    vi.parentElement.classList.add('swatches-not-in-stock')
273                    if(vi.checked){
274                        vi.parentElement.classList.add('active')
275                        let variationSelection = variationItem.split(':')
276                        body.selectedVariations[variationSelection[0]] = variationSelection[1]
277                    }else{
278                        vi.parentElement.classList.remove('active')
279                    }
280
281                    //vi.disabled = true
282
283                })
284            }
285
286
287        })
288
289
290
291
292        const endpoint = `${niu.controller.basicData.shopUrl}?niuapi=true&jtl_token=${niu.controller.basicData.jtlToken}&request_type=variationSelected`;
293
294        let res = await fetch(endpoint,{
295            method:'POST',
296            body:JSON.stringify(body)
297        })
298
299        const contentType = res.headers.get('content-type')
300        let result;
301        if(contentType && contentType.includes('application/json')){
302            result = await res.json()
303            //console.log(result)
304        }else{
305            result = await res.text();
306            //console.error(result)
307            return;
308        }
309
310        //window.response = result
311
312        if('data' in result && 'childProductImage' in result.data && 'childProductPrice' in result.data && 'childProductBasket' in result.data){
313            this.productImageContainer.innerHTML = result.data.childProductImage;
314            this.productPriceContainer.innerHTML = result.data.childProductPrice;
315            this.productCheckoutBasket.innerHTML = result.data.childProductBasket;
316            this.productVariationContainer.innerHTML = result.data.childProductVariations;
317            this.productCheckoutTitle.innerHTML = result.data.childProductTitle;
318            if(this.pluginSlot && 'childProductPluginSlot' in result.data){
319                this.pluginSlot.innerHTML = result.data.childProductPluginSlot;
320            }
321            if(this.productVariationTitle){
322                this.productVariationTitle.innerHTML = result.data.childProductVariationTitleBox;
323            }
324            this.initCurrentProduct();
325            this.initQtyBtns();
326
327            //(NiuTemplateController.getInstance()).reInitScripts(constants.scriptSets.io);
328            console.log('REAL SELECTION')
329            this.dispatch(dzm.events.quickbuy.variationSelected)
330
331
332        }
333
334        Object.entries(result.data.possibleVariations).forEach((v)=>{
335
336            v[1].forEach(val=>{
337                this.variations['v'+v[0]].variationItems['vi'+val].parentElement.classList.remove('swatches-not-in-stock')
338                //this.variations['v'+v[0]].variationItems['vi'+val].disabled = false
339            })
340        })
341
342        if(result.data.hasInvalidSelection){
343            document.querySelector('[data-niu-sidebar-currentproduct-variationwarning]')?.classList.remove('d-none');
344        }else{
345            document.querySelector('[data-niu-sidebar-currentproduct-variationwarning]')?.classList.add('d-none');
346
347        }
348
349        //Needed for custom select box
350        $.evo.article().variationRefreshAll();
351    }
352
353    postError(message){
354        this.wrapper.innerHTML = '<div class="container"><strong>Ups...da ist etwas schief gelaufen</strong></div>'
355        console.error(message);
356        this.dispatch(dzm.events.sidebar.stopLoading)
357    }
358
359    register(){
360        if(this.type === 'quickBuy'){
361            NiuBase.listenTo([
362                dzm.events.quickbuy.triggered
363            ],async (data)=>{
364                if('content' in data && (data.content === 'quickBuy')){
365                    if('trigger' in data && data.trigger !== null){
366                            console.log('FIRE GETQUICKBUYPRODUCT')
367                            await this.getQuickBuyProduct(data.trigger);
368                    }else{
369                        console.error('No trigger element in data')
370                    }
371                }
372
373            });
374        }else if(this.type === 'quickView'){
375
376            NiuBase.listenTo([
377                dzm.events.quickView.triggered
378            ],async (data)=>{
379                if('content' in data && (data.content === 'quickView')){
380                    if('trigger' in data && data.trigger !== null){
381                            await this.getQuickViewProduct(data.trigger);
382                    }else{
383                        console.error('No trigger element in data')
384                    }
385                }
386
387            });
388        }else{
389            console.error('⚠️ unknown type for quickbuy sidebar', this.type, this)
390        }
391    }
392}
393
394NiuBase.listenTo([
395    dzm.events.controller.initialized
396],()=>{
397    NiuQuickBuy.Scan();
398})

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.