PageSourceSearch

https://eluno24.de/plugins/dzm_resources/frontend/js/dzmProgressbar.js?v=7.15.0&t=1789688781

js eluno24.de collected 2026-10-08 09:37:07 UTC 17,325 bytes, 475 lines download raw bytes

1class DZMProgressbar{
2    static Scan(){
3        let wrappers = document.querySelectorAll('[data-dzm-pb-wrapper]');
4        //console.log('SCAN', wrappers);
5        wrappers.forEach(w=>{
6            (new DZMProgressbar()).init(w);
7        });
8    }
9    constructor(selector = false) {
10
11        this.markElements = [];
12        this.marks = [];
13        this.goalWrapper = false
14        this.barColor = '#A9A29D'
15        this.progressColor = '#BFD037'
16        this.fillColor = '#ffffff'
17        this.showInfoText = true
18        this.unitBefore = false
19
20        this.offset = 0;
21        this.state = 0;
22        this.goal = 0;
23
24        this.nextGoal = 0;
25        this.prevGoal = 0;
26
27        this.wrapper = false;
28        this.barWrapper = false;
29        this.progressbar = false;
30        this.mode = 'all'; // all|single|next
31        this.showSpecialMark = true;
32        this.markPoints = {
33            min:false,
34            prev:false,
35            next:false,
36            special:false,
37            max:false,
38        }
39        this.infoTextWrapper = false;
40
41        this.selectors = {
42            wrapper:selector === false ? '[data-dzm-pb-wrapper]' : selector,
43            barWrapper:'.dzm-pb',
44            goalWrapper:"[data-dzm-pb-goal]",
45            marker:'[data-dzm-pb-marker]',
46            markerValue:'data-dzm-pb-marker',
47            markerType:'data-dzm-pb-marker-type',
48            progressbar:'[data-dzm-pb-progress]',
49            progressbarValue:'data-dzm-pb-progress',
50            localStorageProgressState:'dzmProgressState'+(selector === false ? '.dzm-pb' : selector),
51            localStorageLastGoal:'dzmLastGoal'+(selector === false ? '.dzm-pb' : selector),
52            infoTextWrapper:'[data-dzm-pb-info-text]',
53            setting:'[data-dzm-pb-setting]',
54            settings:{
55                mode:'dzmPbSettingsMode',
56                barColor:'dzmPbSettingsBarcolor',
57                progressColor:'dzmPbSettingsProgresscolor',
58                fillColor:'dzmPbSettingsFillcolor',
59                showSpecialMark:'dzmPbSettingsShowspecialmark',
60                showInfoText:'dzmPbSettingsShowinfotext',
61                unitBefore:'dzmPbSettingsUnitbefore',
62                strings:{
63                    outOf:'dzmPbSettingsStringsOutof',
64                    unit:'dzmPbSettingsStringsUnit',
65                    stateTextBefore:'dzmPbSettingsStringsStatetextbefore',
66                    stateTextAfter:'dzmPbSettingsStringsStatetextafter',
67                }
68
69            }
70        }
71
72        this.settings={
73            duration:1,
74            fps:60
75        }
76
77        this.strings = {
78            outOf:'von',
79            unit:'',
80            stateTextBefore:'',
81            stateTextAfter:'',
82        }
83    }
84
85    init(wrapper){
86        //console.warn('INIT PROGRESSBAR',this.selectors.wrapper)
87
88        // GET COMPONENTS
89        this.wrapper = wrapper
90        if(!this.wrapper){
91            console.log('no wrapper', this.selectors.wrapper)
92            return
93        }
94
95        // Eindeutiger Speicher-Key pro Bar. Frueher war der Key global ('dzmLastGoal.dzm-pb'),
96        // wodurch sich mehrere Bars und alte Warenkorbwerte gegenseitig ueberschrieben haben
97        // (Bar mal voll, mal leer, Flackern). Die Wrapper-ID (Portlet-UID bzw. statische ID)
98        // ist pro Bar stabil und eindeutig.
99        this.storageKey = 'dzmLastGoal_' + (this.wrapper.id || 'global');
100
101
102
103        this.barWrapper = this.wrapper.querySelector(this.selectors.barWrapper)
104        // SET WIDTH FOR INITIAL OPEN LOADING EFFECT
105        this.barWrapper.style.width = '100%';
106        // GET PROGRESSBAR COMPONENT AND MARKS
107        this.progressbar = this.wrapper.querySelector(this.selectors.progressbar)
108        this.markElements = this.wrapper.querySelectorAll(this.selectors.marker)
109        this.goalWrapper = this.wrapper.querySelector(this.selectors.goalWrapper)
110
111
112
113        // GET OPTIONS
114        let settings = this.wrapper.querySelector(this.selectors.setting);
115        this.mode = settings.dataset[this.selectors.settings.mode] || this.mode;
116        this.barColor = settings.dataset[this.selectors.settings.barColor] || this.barColor;
117        this.progressColor = settings.dataset[this.selectors.settings.progressColor] || this.progressColor;
118        this.fillColor = settings.dataset[this.selectors.settings.fillColor] || this.fillColor;
119        this.showSpecialMark = settings.dataset[this.selectors.settings.showSpecialMark] === 'true' || this.showSpecialMark;
120        this.showInfoText = settings.dataset[this.selectors.settings.showInfoText] === 'true' || this.showInfoText;
121        this.unitBefore = settings.dataset[this.selectors.settings.unitBefore] === 'true' || this.unitBefore;
122        this.strings.outOf = settings.dataset[this.selectors.settings.strings.outOf] || this.strings.outOf;
123        this.strings.unit = settings.dataset[this.selectors.settings.strings.unit] || this.strings.unit;
124        this.strings.stateTextBefore = settings.dataset[this.selectors.settings.strings.stateTextBefore] || this.strings.stateTextBefore;
125        this.strings.stateTextAfter = settings.dataset[this.selectors.settings.strings.stateTextAfter] || this.strings.stateTextAfter;
126
127
128        /*this.mode = options.mode || this.mode;
129        this.barColor = options.barColor || this.barColor;
130        this.progressColor = options.progressColor || this.progressColor;
131        this.fillColor = options.fillColor || this.fillColor;
132        this.showInfoText = 'showInfoText' in options ? options.showInfoText : this.showInfoText;
133        this.showSpecialMark = 'showSpecialMark' in options ? options.showSpecialMark : this.showSpecialMark;*/
134
135        if(this.showInfoText){
136            this.infoTextWrapper = this.wrapper.querySelector(this.selectors.infoTextWrapper)
137        }
138
139        /*this.strings = {
140            outOf:options.strings.outOf||this.strings.outOf,
141            unit:options.strings.unit||this.strings.unit,
142            stateTextBefore:options.strings.stateTextBefore||this.strings.stateTextBefore,
143            stateTextAfter:options.strings.stateTextAfter||this.strings.stateTextAfter,
144        };
145        this.unitBefore = options.strings.unitBefore||this.unitBefore,*/
146
147        // GET CURRENT TARGET VALUE BY ATTRIBUTE
148        this.goal = parseFloat(this.progressbar.getAttribute(this.selectors.progressbarValue));
149        this.state = this.goal;
150        if((this.state = localStorage.getItem(this.storageKey)) === null){
151            this.state =0
152            localStorage.setItem(this.storageKey, this.state);
153
154
155        }else{
156            // DEACTIVATE ANIMATION, SO IT IS NOT ANIMATING ALL THE TIME
157            this.barWrapper.classList.toggle('dzm-pb--no-animation',true)
158        }
159        this.state = parseFloat(this.state)
160
161
162
163
164        this.markElements.forEach(marker=>{
165            let markerValue = parseFloat(marker.getAttribute(this.selectors.markerValue));
166            let markerType = marker.getAttribute(this.selectors.markerType);
167            let newMark = {
168                value:markerValue,
169                type: markerType,
170                mark:marker,
171                description:marker.dataset.dzmPbMarkerDescription
172            }
173            this.marks.push(newMark)
174
175
176        })
177
178
179        this.marks.sort((a, b) => a.value - b.value);
180
181        this.setupMarkPoints();
182
183
184
185        this.setMarks()
186
187
188        let statePercent = this.nextGoal > 0
189            ? (this.state - this.prevGoal) * 100 / (this.nextGoal - this.prevGoal === 0 ? 1 : this.nextGoal - this.prevGoal)
190            : 0;
191        this.progressbar.style.width =statePercent + '%';
192
193        // VIEW THE PROGRESS BAR
194        this.barWrapper.style.opacity = '1';
195        // ACTIVATE ANIMATIONS
196        setTimeout(()=>{
197            this.barWrapper.classList.toggle('dzm-pb--no-animation',false)
198        },1)
199
200        window.progressBar = this
201        this.setProgress( this.goal)
202    }
203    setGoalString(){
204        if(!this.goalWrapper && !this.infoTextWrapper)
205            return;
206        let set = false;
207        this.marks.forEach(mark=>{
208            if((mark.value > this.goal || mark.isMax) && !set){
209                if(this.goalWrapper){
210                    this.goalWrapper.innerText = Math.min(this.goal,this.marks[this.markPoints.max].value).toFixed(2) + ' '+this.strings.outOf+' ' +mark.value.toFixed(2)
211                }
212                if(this.showInfoText && mark.value-this.goal > 0){
213                    let infoText = '';
214                    infoText = this.strings.stateTextBefore+ ' ';
215                    if(this.unitBefore){
216                        infoText += this.strings.unit + ' ' + (mark.value-this.goal).toFixed(2) + ' ';
217                    }else{
218                        infoText += (mark.value-this.goal).toFixed(2) + ' ' + this.strings.unit + ' ';
219                    }
220                    infoText += mark.description + ' ' + this.strings.stateTextAfter;
221
222                    this.infoTextWrapper.innerText = infoText;
223                }else{
224                    this.infoTextWrapper.innerText = '';
225
226                }
227                set = true
228            }
229
230        })
231    }
232
233    setProgress( target=0){
234
235        // Kein gueltiges Ziel (z.B. einziger Marker mit Schwelle 0) -> Bar leer lassen statt
236        // durch die "=== 0 ? 1"-Division eine explodierende Breite zu erzeugen.
237        if(this.nextGoal <= 0){
238            this.progressbar.style.width = '0%';
239            return;
240        }
241
242        // CALC THE DIFF PERCENTAGE OF TARGET FROM SAVEDPROGRESS, BUT MAX 100%
243
244        let statePercent = (this.state - this.prevGoal) * 100 / (this.nextGoal - this.prevGoal === 0 ? 1 : this.nextGoal - this.prevGoal)
245
246        let targetPercent = ((Math.min(target,this.nextGoal) - this.prevGoal) * 100 / ((this.nextGoal - this.prevGoal === 0 ? 1 : this.nextGoal - this.prevGoal))) - statePercent;
247
248
249
250
251        let time = 0;
252        let interval = setInterval(()=>{
253            time += 1 / this.settings.fps;
254            // Animation nach Ablauf der Dauer sauber beenden. Frueher wurde per Float-Gleichheit
255            // (currentProgress === targetPercent+statePercent) terminiert -> durch Rundungsfehler
256            // konnte das Intervall ueberschiessen oder gar nicht stoppen.
257            let finished = time >= this.settings.duration;
258            let progress = this.easeInOutQuad(time * 100 / this.settings.duration, time, 0, targetPercent, this.settings.duration);
259            let currentProgress = finished ? (statePercent + targetPercent) : (statePercent + progress);
260
261            this.progressbar.style.width =currentProgress + '%';
262            this.marks.forEach(mark=>{
263                let markPercentValue = (mark.value-this.prevGoal) * 100 / (this.nextGoal-this.prevGoal);
264
265                this.toggleDone(mark.mark,markPercentValue <= currentProgress)
266            })
267
268            if (finished) {
269
270                clearInterval(interval);
271                this.state = Math.min(target,this.nextGoal)
272                localStorage.setItem(this.storageKey, this.state);
273
274
275
276                if(this.mode !== 'all' && (
277                    (this.markPoints.next !== false && this.markPoints.next !== this.markPoints.max  )
278                    || (this.markPoints.prev !== false && target <= this.marks[this.markPoints.prev].value))){
279                    this.checkNextGoales(currentProgress, target)
280                }
281            }
282        }, 1000 / this.settings.fps);
283
284
285    }
286
287    toggleDone(mark,on = true){
288        mark.classList.toggle('done', on)
289        if(on){
290            mark.firstElementChild.style.backgroundColor = this.progressColor;
291        }else{
292            mark.firstElementChild.style.backgroundColor = this.barColor;
293        }
294    }
295
296    checkNextGoales(currentProgress,target){
297
298
299        let lastNextGoal = this.nextGoal;
300        let lastPrevGoal = this.prevGoal;
301
302
303        this.setupMarkPoints()
304        this.setMarks()
305
306        if(lastNextGoal === this.nextGoal && lastPrevGoal === this.prevGoal)
307            return;
308        let statePercent = (this.state - this.prevGoal) * 100 / (this.nextGoal - this.prevGoal === 0 ? 1 : this.nextGoal - this.prevGoal)
309        this.progressbar.style.width =statePercent + '%';
310
311
312
313        this.setProgress(target)
314
315
316
317    }
318
319    setupMarkPoints(){
320        this.marks.forEach(mark=>{
321            mark.isMin = false;
322            mark.isMax = false;
323            mark.isPrev = false;
324            mark.isSpecial = false;
325            mark.isNext = false;
326            this.markPoints.min = false;
327            this.markPoints.max = false;
328            this.markPoints.prev = false;
329            this.markPoints.next = false;
330            this.markPoints.special = false;
331        })
332        this.marks.forEach((mark,i)=>{
333            if(i===0){
334                this.markPoints.min = i;
335                mark.isMin = true;
336            }
337            if(i === this.marks.length - 1){
338                this.markPoints.max = i;
339                mark.isMax = true;
340            }
341
342            if(mark.type === 'special'){
343                this.markPoints.special = i;
344                mark.isSpecial = true;
345            }
346
347            if(mark.value <= this.state && !mark.isMax){
348                this.markPoints.prev = i;
349                mark.isPrev = true;
350                if(i>0){
351                    this.marks[i-1].isPrev = false
352                }
353            }
354
355            if(mark.value > this.state && this.markPoints.next === false){
356                this.markPoints.next = i;
357                mark.isNext = true;
358            }
359        })
360
361        if(this.mode === 'all'){
362            this.nextGoal = this.marks[this.markPoints.max].value
363            this.prevGoal = 0;
364        }else if(this.mode === 'next'){
365            if(this.markPoints.next !== false){
366                if(this.showSpecialMark && ((this.markPoints.special !== false && this.marks[this.markPoints.special].value > this.marks[this.markPoints.next].value)
367
368                )){
369                    this.nextGoal = this.marks[this.markPoints.special].value;
370                }else{
371                    this.nextGoal = this.marks[this.markPoints.next].value;
372                }
373            }else{
374                this.nextGoal = this.marks[this.markPoints.max].value;
375            }
376
377            this.prevGoal = 0;
378        }else if(this.mode ==='single'){
379            if(this.markPoints.next !== false){
380                if(this.showSpecialMark && this.markPoints.special !== false && this.marks[this.markPoints.special].value > this.marks[this.markPoints.next].value){
381                    this.nextGoal = this.marks[this.markPoints.special].value;
382                }else{
383                    this.nextGoal = this.marks[this.markPoints.next].value;
384                }
385            }else{
386                this.nextGoal = this.marks[this.markPoints.max].value;
387            }
388            if(this.markPoints.prev !== false){
389                this.prevGoal = this.marks[this.markPoints.prev].value;
390            }else{
391                this.prevGoal = 0;
392            }
393
394        }
395
396
397
398    }
399
400    setMarks(){
401
402        this.marks.forEach((mark,i)=>{
403            let position = 0;
404            mark.mark.style.zIndex = 'unset';
405            switch (this.mode){
406                case 'all':
407                    position = mark.value * 100 / this.nextGoal
408                    mark.mark.style.left = position + '%';
409                    this.toggleDone(mark.mark,mark.value <= this.state)
410                    break;
411                case 'next':
412                    position = mark.value * 100 / this.nextGoal
413
414                    console.log(mark);
415                    mark.mark.style.left = position + '%';
416                    this.toggleDone(mark.mark,mark.value <= this.state)
417                    if(mark.value > this.state){
418                        if (mark.isNext || (this.showSpecialMark && mark.isSpecial) || (this.showSpecialMark && mark.value <= this.marks[this.markPoints.special].value)) {
419
420
421                        }else{
422                            mark.mark.style.zIndex = '-1';
423                        }
424                    }
425
426                    break;
427                case 'single':
428                    if(mark.isMax){
429                        position = 100;
430                    }else{
431
432                    position = Math.max(0,(mark.value - this.prevGoal) * 100 / (this.nextGoal - this.prevGoal))
433                    }
434
435                    mark.mark.style.left = position + '%';
436                    this.toggleDone(mark.mark,mark.value <= this.state)
437                    if(mark.value > this.state){
438                        if (mark.isNext || (this.showSpecialMark && mark.isSpecial) || (this.showSpecialMark && mark.value <= this.marks[this.markPoints.special].value)) {
439
440
441                        }else{
442                            mark.mark.style.zIndex = '-1';
443                        }
444                    }
445
446
447            }
448
449        })
450
451        this.setGoalString()
452
453    }
454
455    easeInOutQuad(x, t, b, c, d) {
456        if ((t /= d / 2) < 1) {
457            return c / 2 * Math.pow(t, 4) + b;
458        } else {
459            let adjustedT = t - 2;
460            return -c / 2 * (Math.pow(adjustedT, 4) - 2) + b;
461        }
462    }
463
464
465
466}
467
468dzm.dispatcher.listen([
469    dzm.events.DOM.contentLoaded,
470    dzm.events.quickbuy.addedToCart,
471    dzm.events.sidebar.cartLoaded,
472],()=>{
473    DZMProgressbar.Scan();
474})
475

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.