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 / interactive-poll / frontend.js

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

143 lines 4.6 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 var LS_PREFIX = 'bkip_vote_';
5
6 function getStoredData(instanceId) {
7 try {
8 var raw = localStorage.getItem(LS_PREFIX + instanceId);
9 return raw ? JSON.parse(raw) : null;
10 } catch (e) {
11 return null;
12 }
13 }
14
15 function storeData(instanceId, data) {
16 try {
17 localStorage.setItem(LS_PREFIX + instanceId, JSON.stringify(data));
18 } catch (e) {}
19 }
20
21 function calcTotals(votes) {
22 return votes.reduce(function (a, b) { return a + b; }, 0);
23 }
24
25 function renderResults(wrap, votes, animate) {
26 var total = calcTotals(votes);
27 var fills = wrap.querySelectorAll('.bkip-bar-fill');
28 var pcts = wrap.querySelectorAll('.bkip-result-pct');
29 var totalNum = wrap.querySelector('.bkip-total-num');
30
31 fills.forEach(function (fill, i) {
32 var pct = total > 0 ? Math.round((votes[i] / total) * 100) : 0;
33
34 if (!animate) {
35 fill.style.transition = 'none';
36 }
37
38 // Trigger transition by setting width after a tiny delay
39 setTimeout(function () {
40 fill.style.width = pct + '%';
41 }, animate ? 50 : 0);
42
43 if (pcts[i]) pcts[i].textContent = pct + '%';
44 });
45
46 if (totalNum) totalNum.textContent = total;
47 }
48
49 function showResults(wrap) {
50 var votesEl = wrap.querySelector('.bkip-votes');
51 var resultsEl = wrap.querySelector('.bkip-results');
52 if (votesEl) votesEl.classList.add('bkip-hidden');
53 if (resultsEl) resultsEl.classList.add('bkip-visible');
54 }
55
56 function showVotes(wrap) {
57 var votesEl = wrap.querySelector('.bkip-votes');
58 var resultsEl = wrap.querySelector('.bkip-results');
59 if (votesEl) votesEl.classList.remove('bkip-hidden');
60 if (resultsEl) resultsEl.classList.remove('bkip-visible');
61 }
62
63 function initPoll(wrap) {
64 var instanceId = wrap.dataset.instance;
65 var allowRevote = wrap.dataset.allowRevote !== 'false';
66 var showBefore = wrap.dataset.showBefore === 'true';
67 var animate = wrap.dataset.animate !== 'false';
68
69 if (!instanceId) return;
70
71 // Load option data from embedded JSON
72 var dataScript = wrap.querySelector('.bkip-data');
73 var baseOptions;
74 try {
75 baseOptions = JSON.parse(dataScript ? dataScript.textContent : '[]');
76 } catch (e) {
77 baseOptions = [];
78 }
79
80 // Initialise votes array from localStorage or base
81 var stored = getStoredData(instanceId);
82 var votes = stored ? stored.votes : baseOptions.map(function (o) { return o.votes || 0; });
83 var voted = stored ? stored.voted : false;
84
85 // Initial render
86 if (showBefore || voted) {
87 renderResults(wrap, votes, false);
88 if (voted) showResults(wrap);
89 }
90
91 // Vote buttons
92 var btns = Array.prototype.slice.call(wrap.querySelectorAll('.bkip-option-btn'));
93 btns.forEach(function (btn) {
94 btn.addEventListener('click', function () {
95 if (voted && !allowRevote) return;
96
97 var idx = parseInt(btn.dataset.index, 10);
98 if (isNaN(idx) || idx < 0 || idx >= votes.length) return;
99
100 // If revote: subtract previous vote
101 if (voted && stored && typeof stored.lastVote === 'number') {
102 votes[stored.lastVote] = Math.max(0, votes[stored.lastVote] - 1);
103 }
104
105 votes[idx] = (votes[idx] || 0) + 1;
106 voted = true;
107
108 var newStored = { votes: votes, voted: true, lastVote: idx };
109 storeData(instanceId, newStored);
110 stored = newStored;
111
112 renderResults(wrap, votes, animate);
113 showResults(wrap);
114 });
115 });
116
117 // Revote button
118 var revoteBtn = wrap.querySelector('.bkip-revote');
119 if (revoteBtn) {
120 if (!allowRevote) {
121 revoteBtn.style.display = 'none';
122 }
123 revoteBtn.addEventListener('click', function () {
124 if (!allowRevote) return;
125 voted = false;
126 showVotes(wrap);
127 });
128 }
129 }
130
131 function init() {
132 var polls = document.querySelectorAll('.bkip-wrap[data-instance]');
133 polls.forEach(initPoll);
134 }
135
136 if (document.readyState === 'loading') {
137 document.addEventListener('DOMContentLoaded', init);
138 } else {
139 init();
140 }
141
142 }());
143