PageSourceSearch

https://www.sausewind-shop.com/templates/NIUplus/js/niu-app/niu.loadMore.js?v=7.15.1

js sausewind-shop.com collected 2026-09-24 11:39:53 UTC 12,622 bytes, 389 lines download raw bytes

1import NiuBase from "niu-base";
2
3class NiuLoadMore extends NiuBase{
4    static Selectors = {
5        wrapper:()=>{return'[data-niu-load-more]'},
6        maxPages:'[data-niu-load-more-max-pages]',
7        productsCount:'[data-niu-load-more-products-count]',
8        productsShown:'[data-niu-load-more-products-shown]',
9        productsOffset:'[data-niu-load-more-products-offset]',
10        currentPage:'[data-niu-load-more-current-page]',
11        currentProductsText:'[data-niu-load-more-current-products-text]',
12        maxProductsText:'[data-niu-load-more-max-products-text]',
13        progressBar:'[data-niu-load-more-progress-bar]',
14        btn:'[data-niu-load-more-btn]',
15        btnText:'[data-niu-load-more-btn-text]',
16        btnSpinner:'[data-niu-load-more-btn-spinner]',
17        prevBtn:'[data-niu-load-prev-btn]',
18        prevBtnText:'[data-niu-load-prev-btn-text]',
19        prevBtnSpinner:'[data-niu-load-prev-btn-spinner]',
20        next:'[data-niu-load-more-next]',
21        prev:'[data-niu-load-more-prev]',
22        current:'[data-niu-load-more-current]',
23
24
25
26        pages:'[data-niu-load-more-pages]',
27
28        elements:'.niu-box',
29        targetList:'product-list'
30
31    }
32
33    constructor(wrapper) {
34        super(wrapper);
35        this.currentPage;
36        this.maxPages;
37        this.productsCount;
38        this.productsShown;
39        this.percentageShown;
40        this.productsOffset;
41
42        this.productsPerPage;
43
44        this.maxProductsText;
45        this.currentProductsText;
46        this.progressBar;
47        this.btn;
48        this.btnText;
49        this.btnSpinner;
50
51        this.prevBtn;
52        this.prevBtnText;
53        this.prevBtnSpinner;
54
55        this.nextPageURL;
56        this.prevPageURL;
57        this.currentPageURL;
58
59        this.targetList;
60
61        this.pages=[];
62
63        this.itemsStack = [];
64
65        this.loading = false;
66        this.loadingPrev = false;
67    }
68    setError(msg){
69        this.wrapper.classList.add('d-none');
70        console.error(msg)
71
72    }
73    init(){
74        /*console.log('init load ore')*/
75        if(!this.wrapper.querySelector(NiuLoadMore.Selectors.current))
76            return;
77        this.currentPage = parseInt(this.wrapper.dataset[NiuBase.select(NiuLoadMore.Selectors.currentPage)]);
78        this.maxPages = parseInt(this.wrapper.dataset[NiuBase.select(NiuLoadMore.Selectors.maxPages)]);
79
80        if(this.currentPage<this.maxPages){
81            this.wrapper.classList.remove('d-none')
82        }
83
84        this.targetList = document.getElementById(NiuLoadMore.Selectors.targetList);
85        if(!this.targetList){
86            this.setError('no targetlist')
87            return;
88        }
89        this.nextPageURL = this.wrapper.querySelector(NiuLoadMore.Selectors.next).dataset.niuLoadMoreNext;
90        this.prevPageURL = this.wrapper.querySelector(NiuLoadMore.Selectors.prev).dataset.niuLoadMorePrev;
91        this.currentPageURL = this.wrapper.querySelector(NiuLoadMore.Selectors.current).dataset.niuLoadMoreCurrent;
92
93        this.productsCount = parseInt(this.wrapper.dataset[NiuBase.select(NiuLoadMore.Selectors.productsCount)]);
94        this.productsShown = parseInt(this.wrapper.dataset[NiuBase.select(NiuLoadMore.Selectors.productsShown)]);
95        this.productsOffset = parseInt(this.wrapper.dataset[NiuBase.select(NiuLoadMore.Selectors.productsOffset)]);
96        this.productsPerPage = this.productsShown - this.productsOffset + 1;
97
98        this.maxProductsText = this.wrapper.querySelector(NiuLoadMore.Selectors.maxProductsText)
99        this.currentProductsText = this.wrapper.querySelector(NiuLoadMore.Selectors.currentProductsText)
100        this.progressBar = this.wrapper.querySelector(NiuLoadMore.Selectors.progressBar)
101
102
103
104        this.btn = this.wrapper.querySelector(NiuLoadMore.Selectors.btn)
105        this.btnText = this.wrapper.querySelector(NiuLoadMore.Selectors.btnText)
106        this.btnSpinner = this.wrapper.querySelector(NiuLoadMore.Selectors.btnSpinner)
107
108        this.setStatus()
109        this.wrapper.querySelectorAll(NiuLoadMore.Selectors.pages).forEach(p=>{
110            this.pages.push(p.dataset[NiuBase.select(NiuLoadMore.Selectors.pages)])
111        })
112
113
114        this.btn.addEventListener('click',()=>{
115            this.loadMore()
116        });
117
118
119        this.prevBtn = document.querySelector(NiuLoadMore.Selectors.prevBtn)
120        if(this.prevBtn){
121            this.prevBtnText = this.prevBtn.querySelector(NiuLoadMore.Selectors.prevBtnText)
122            this.prevBtnSpinner = this.prevBtn.querySelector(NiuLoadMore.Selectors.prevBtnSpinner)
123
124            this.prevBtn.addEventListener('click',()=>{
125                this.loadPrev();
126            })
127        }
128
129        this.loadMore();
130
131    }
132
133    triggerLoading(){
134        this.loading = !this.loading;
135        if(this.loading){
136            this.btn.disabled = true;
137            this.btnText.classList.add('d-none')
138            this.btnSpinner.classList.remove('d-none')
139        }else{
140            this.btnText.classList.remove('d-none')
141            this.btnSpinner.classList.add('d-none')
142            this.btn.disabled = false;
143        }
144    }
145
146    triggerPrevLoading(){
147        this.loadingPrev = !this.loadingPrev;
148        if(this.loadingPrev){
149            this.prevBtn.disabled = true;
150            this.prevBtnText.classList.add('d-none')
151            this.prevBtnSpinner.classList.remove('d-none')
152        }else{
153            this.prevBtnText.classList.remove('d-none')
154            this.prevBtnSpinner.classList.add('d-none')
155            this.prevBtn.disabled = false;
156        }
157    }
158
159    getColumnsCount(){
160        let cs = window.getComputedStyle(this.targetList);
161        return cs.getPropertyValue('grid-template-columns').split(" ").length;
162    }
163    getEmptySlots(){
164        let columnCount = this.getColumnsCount()
165
166        let items = this.targetList.querySelectorAll(NiuLoadMore.Selectors.elements);
167        let itemsSpace = 0;
168        items.forEach(item=>{
169            let cs = window.getComputedStyle(item);
170            let colSpan = cs.getPropertyValue('grid-column-start').split(" ");
171            if(colSpan.length > 1){
172                itemsSpace += parseInt(colSpan[1]);
173            }else{
174                itemsSpace++;
175            }
176            /*console.log(cs.getPropertyValue('grid-column-start'))*/
177        })
178        let itemsInLastRow = itemsSpace % columnCount;
179
180        return itemsInLastRow === 0 ? 0 : columnCount - itemsInLastRow;
181    }
182
183    fillUp(){
184        let emptySlots = this.getEmptySlots();
185        let i = 0;
186        while(emptySlots > 0 && this.itemsStack.length > 0){
187            emptySlots--;
188            this.pushItem(this.itemsStack.shift(),i)
189
190            i++;
191        }
192    }
193
194    emptyStack(){
195        let i = 0;
196        let columnsCount = this.getColumnsCount();
197        let currentFilled = columnsCount;
198        while(this.itemsStack.length > 0){
199            if(currentFilled === columnsCount && this.itemsStack.length < columnsCount && this.productsCount-this.productsShown > columnsCount){
200                break;
201            }
202
203            this.pushItem(this.itemsStack.shift(),i)
204
205
206            if(currentFilled === columnsCount){
207                currentFilled = 1;
208            }else{
209                currentFilled++;
210            }
211
212            i++;
213
214        }
215    }
216
217    pushItem(element,i){
218        element.classList.remove('niu-sub-ani','animate__faster')
219        element.classList.add('animate__animated', 'animate__fadeInUp');
220
221
222        element.style.animationDelay = `${ i * 0.1}s`;
223
224
225        element.style.animationDuration = '0.3s';
226        this.productsShown++;
227        this.setStatus()
228        this.targetList.appendChild(element);
229    }
230
231    setStatus(){
232        this.percentageShown = this.productsShown * 100 / this.productsCount;
233
234
235        this.maxProductsText.innerText = this.productsCount;
236        this.currentProductsText.innerText = this.productsShown;
237        this.progressBar.style.width = (this.percentageShown)+'%';
238        if(this.productsShown >= this.productsCount){
239            this.btn.classList.add('d-none')
240        }
241    }
242
243    loadMore(){
244        if(this.loading){
245            /*console.log('LoadMoreBtn: Mach ma nich so schnell hier...')*/
246            return;
247        }
248        /*console.log('loadMore')*/
249        this.emptyStack()
250        /*if(this.currentPage+1 > this.pages.length){
251            if(this.itemsStack.length > 0){
252                this.fillUp()
253            }
254            this.dispatch(dzm.events.productList.updated)
255            return;
256        }*/
257        this.triggerLoading()
258
259        const controller = new AbortController();
260
261        const timeout = setTimeout(()=>{
262            controller.abort();
263            const link = document.createElement('a');
264            link.href = this.pages[this.currentPage]; // Ziel-URL
265            link.innerText = this.btnText.innerText;
266            link.className = this.btn.className; // übernimmt CSS-Klassen vom Button
267            this.btn.replaceWith(link);
268
269
270        },10000);
271        if(this.currentPage > 1){
272            history.pushState({}, "", this.currentPageURL);
273        }
274        if(this.nextPageURL === ""){
275            this.triggerLoading()
276            return;
277        }
278        fetch(this.nextPageURL+'?isAjax',{signal:controller.signal})
279            .then(res=> {
280                clearTimeout(timeout);
281                return res.text()
282        })
283            .then(result=>{
284
285            this.currentPage++;
286
287
288            const tempContainer = document.createElement('div');
289            tempContainer.innerHTML = result;
290            const elements = tempContainer.querySelectorAll(NiuLoadMore.Selectors.elements);
291            const next = tempContainer.querySelector(NiuLoadMore.Selectors.next).dataset.niuLoadMoreNext;
292
293            /*console.log('next',next);*/
294            this.currentPageURL = this.nextPageURL;
295            this.nextPageURL = next;
296
297
298
299            elements.forEach((element) => {
300                if(!element.classList.contains('niu-disturber'))
301                    this.itemsStack.push(element)
302
303            });
304
305        }).catch(err=>{
306            console.error('loadMore error', err)
307        }).finally(()=>{
308            this.triggerLoading()
309            this.fillUp()
310            this.dispatch(dzm.events.productList.updated)
311        })
312    }
313
314
315    loadPrev(){
316        /*console.log(this.prevPageURL)*/
317        if(this.loadingPrev){
318            /*console.log('LoadPrevBtn: Mach ma nich so schnell hier...')*/
319            return;
320        }
321        /*console.log('loadPrev')*/
322        /*if(this.currentPage+1 > this.pages.length){
323            if(this.itemsStack.length > 0){
324                this.fillUp()
325            }
326            this.dispatch(dzm.events.productList.updated)
327            return;
328        }*/
329        this.triggerPrevLoading()
330
331        const controller = new AbortController();
332
333        const timeout = setTimeout(()=>{
334            controller.abort();
335            const link = document.createElement('a');
336            link.href = this.prevPageURL // Ziel-URL
337            link.innerText = this.prevBtnText.innerText;
338            link.className = this.prevBtn.className; // übernimmt CSS-Klassen vom Button
339            this.prevBtn.replaceWith(link);
340
341
342        },10000);
343        history.pushState({}, "", this.prevPageURL);
344
345
346        fetch(this.prevPageURL+'?isAjax',{signal:controller.signal})
347            .then(res=> {
348                clearTimeout(timeout);
349                return res.text()
350            })
351            .then(result=>{
352
353                //this.currentPage++;
354
355
356                const tempContainer = document.createElement('div');
357                tempContainer.innerHTML = result;
358                const elements = [...tempContainer.querySelectorAll(NiuLoadMore.Selectors.elements)].reverse();
359                const prev = tempContainer.querySelector(NiuLoadMore.Selectors.prev).dataset.niuLoadMorePrev;
360                /*console.log('prev',prev);*/
361                this.prevPageURL = prev;
362                if(this.prevPageURL === ""){
363                    this.prevBtn.classList.add('d-none')
364                }
365
366                elements.forEach((element) => {
367                        element.classList.remove('niu-sub-ani','animate__faster','animate__animated', 'animate__fadeInUp')
368
369                        this.targetList.prepend(element);
370
371
372
373                });
374
375            }).catch(err=>{
376            console.error('loadPrev error', err)
377        }).finally(()=>{
378            this.triggerPrevLoading()
379            this.dispatch(dzm.events.productList.updated)
380        })
381    }
382}
383
384
385NiuBase.listenTo([
386    dzm.events.controller.initialized
387],()=>{
388    NiuLoadMore.Scan();
389})

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.