PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.11
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.11
2.0.13 2.0.12 2.0.11 2.0.10 2.0.9 trunk 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8
blockenberg / blocks / progress-bar / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.11, at blocks/progress-bar/frontend.js

200 lines 8.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function () {
2 'use strict';
3
4 function clampInt(value, min, max) {
5 var n = parseInt(value, 10);
6 if (isNaN(n)) n = 0;
7 return Math.max(min, Math.min(max, n));
8 }
9
10 function sanitizeColor(input, fallback) {
11 var v = String(input || '').trim();
12 // Allow only hex colors to avoid CSS injection via `background:`.
13 if (/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i.test(v)) {
14 return v;
15 }
16 return fallback;
17 }
18
19 function clearEl(el) {
20 while (el && el.firstChild) {
21 el.removeChild(el.firstChild);
22 }
23 }
24
25 // Lighten color helper
26 function lightenColor(hex, percent) {
27 var num = parseInt(hex.replace('#', ''), 16);
28 var r = Math.min(255, (num >> 16) + Math.round(255 * percent / 100));
29 var g = Math.min(255, ((num >> 8) & 0x00FF) + Math.round(255 * percent / 100));
30 var b = Math.min(255, (num & 0x0000FF) + Math.round(255 * percent / 100));
31 return '#' + (0x1000000 + (r << 16) + (g << 8) + b).toString(16).slice(1);
32 }
33
34 function initProgressBar(wrap) {
35 var itemsData = wrap.getAttribute('data-items');
36 var animate = wrap.getAttribute('data-animate') === '1';
37 var showLabels = wrap.getAttribute('data-show-labels') === '1';
38 var showPercentage = wrap.getAttribute('data-show-percentage') === '1';
39 var percentagePosition = wrap.getAttribute('data-percentage-position') || 'right';
40 var gradient = wrap.getAttribute('data-gradient') === '1';
41 var gradientAngle = clampInt(wrap.getAttribute('data-gradient-angle') || 90, 0, 360);
42 var glow = wrap.getAttribute('data-glow') === '1';
43 var stripes = wrap.classList.contains('bkbg-pb-striped');
44
45 if (!itemsData) return;
46
47 // Parse items
48 var items = itemsData.split(';;').map(function (item) {
49 var parts = item.split('|');
50 return {
51 label: parts[0] || '',
52 percentage: clampInt(parts[1], 0, 100),
53 color: sanitizeColor(parts[2], '#3b82f6')
54 };
55 });
56
57 var list = wrap.querySelector('.bkbg-pb-list');
58 if (!list) return;
59
60 clearEl(list);
61
62 items.forEach(function (item) {
63 // Build background style
64 var bgStyle = '';
65 var bgSize = '';
66 var lighterColor = lightenColor(item.color, 30);
67
68 if (stripes && gradient) {
69 var stripesBg = 'linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)';
70 bgStyle = stripesBg + ', linear-gradient(' + gradientAngle + 'deg, ' + item.color + ' 0%, ' + lighterColor + ' 50%, ' + item.color + ' 100%)';
71 bgSize = '40px 40px, 200% 100%';
72 } else if (stripes) {
73 var stripesBg = 'linear-gradient(45deg, rgba(255,255,255,0.15) 25%, transparent 25%, transparent 50%, rgba(255,255,255,0.15) 50%, rgba(255,255,255,0.15) 75%, transparent 75%, transparent)';
74 bgStyle = stripesBg + ', ' + item.color;
75 bgSize = '40px 40px, 100% 100%';
76 } else if (gradient) {
77 bgStyle = 'linear-gradient(' + gradientAngle + 'deg, ' + item.color + ' 0%, ' + lighterColor + ' 50%, ' + item.color + ' 100%)';
78 bgSize = '200% 100%';
79 } else {
80 bgStyle = item.color;
81 }
82
83 // Box shadow for glow
84 var boxShadow = '';
85 if (glow) {
86 boxShadow = 'box-shadow: 0 0 10px ' + item.color + ', 0 0 20px ' + item.color + '60;';
87 }
88
89 var itemEl = document.createElement('div');
90 itemEl.className = 'bkbg-pb-item';
91
92 // Header
93 if (showLabels || (showPercentage && percentagePosition === 'right')) {
94 var headerEl = document.createElement('div');
95 headerEl.className = 'bkbg-pb-header';
96 if (showLabels) {
97 var labelEl = document.createElement('span');
98 labelEl.className = 'bkbg-pb-label';
99 labelEl.textContent = item.label || '';
100 headerEl.appendChild(labelEl);
101 }
102 if (showPercentage && percentagePosition === 'right') {
103 var pctEl = document.createElement('span');
104 pctEl.className = 'bkbg-pb-percentage';
105 pctEl.textContent = item.percentage + '%';
106 headerEl.appendChild(pctEl);
107 }
108 itemEl.appendChild(headerEl);
109 }
110
111 // Above percentage
112 if (showPercentage && percentagePosition === 'above') {
113 var aboveWrap = document.createElement('div');
114 aboveWrap.className = 'bkbg-pb-above';
115
116 var abovePct = document.createElement('span');
117 abovePct.className = 'bkbg-pb-percentage-above';
118 abovePct.textContent = item.percentage + '%';
119 abovePct.style.left = (animate ? 0 : item.percentage) + '%';
120 aboveWrap.appendChild(abovePct);
121
122 itemEl.appendChild(aboveWrap);
123 }
124
125 // Track and bar
126 var trackEl = document.createElement('div');
127 trackEl.className = 'bkbg-pb-track';
128
129 var barEl = document.createElement('div');
130 barEl.className = 'bkbg-pb-bar';
131 barEl.style.width = (animate ? 0 : item.percentage) + '%';
132 barEl.style.background = bgStyle;
133 if (bgSize) {
134 barEl.style.backgroundSize = bgSize;
135 }
136 if (glow) {
137 barEl.style.boxShadow = '0 0 10px ' + item.color + ', 0 0 20px ' + item.color + '60';
138 }
139 barEl.setAttribute('data-percentage', String(item.percentage));
140 barEl.setAttribute('data-color', item.color);
141
142 if (showPercentage && percentagePosition === 'inside') {
143 var insidePct = document.createElement('span');
144 insidePct.className = 'bkbg-pb-percentage-inside';
145 insidePct.textContent = item.percentage + '%';
146 barEl.appendChild(insidePct);
147 }
148
149 trackEl.appendChild(barEl);
150 itemEl.appendChild(trackEl);
151
152 list.appendChild(itemEl);
153 });
154
155 // Animate if needed
156 if (animate) {
157 var observer = new IntersectionObserver(function (entries) {
158 entries.forEach(function (entry) {
159 if (entry.isIntersecting) {
160 wrap.classList.add('bkbg-pb-animated');
161
162 // Animate bars
163 var bars = wrap.querySelectorAll('.bkbg-pb-bar');
164 bars.forEach(function (bar) {
165 var percentage = bar.getAttribute('data-percentage');
166 bar.style.width = percentage + '%';
167 });
168
169 // Animate above percentages
170 var aboveEls = wrap.querySelectorAll('.bkbg-pb-percentage-above');
171 aboveEls.forEach(function (el) {
172 var text = el.textContent;
173 var percentage = parseInt(text, 10);
174 el.style.left = percentage + '%';
175 });
176
177 observer.unobserve(wrap);
178 }
179 });
180 }, { threshold: 0.2 });
181
182 observer.observe(wrap);
183 } else {
184 wrap.classList.add('bkbg-pb-animated');
185 }
186 }
187
188 function init() {
189 var progressBars = document.querySelectorAll('.bkbg-pb-wrap[data-items]');
190 progressBars.forEach(initProgressBar);
191 }
192
193 // Initialize
194 if (document.readyState === 'loading') {
195 document.addEventListener('DOMContentLoaded', init);
196 } else {
197 init();
198 }
199 })();
200