PluginProbe
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor / 2.0.7
Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor v2.0.7
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 / neon-text / frontend.js

frontend.js in Blockenberg — 600+ Advanced Gutenberg Blocks & AI Agent for WordPress Block Editor 2.0.7, at blocks/neon-text/frontend.js

167 lines 6.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 document.addEventListener('DOMContentLoaded', function () {
2 document.querySelectorAll('.bkbg-nt-app').forEach(function (root) {
3 var opts = JSON.parse(root.dataset.opts || '{}');
4 initNeonText(root, opts);
5 });
6 });
7
8 var _typoKeys = {
9 family:'font-family', weight:'font-weight', style:'font-style',
10 decoration:'text-decoration', transform:'text-transform',
11 sizeDesktop:'font-size-d', sizeTablet:'font-size-t', sizeMobile:'font-size-m',
12 lineHeightDesktop:'line-height-d', lineHeightTablet:'line-height-t', lineHeightMobile:'line-height-m',
13 letterSpacingDesktop:'letter-spacing-d', letterSpacingTablet:'letter-spacing-t', letterSpacingMobile:'letter-spacing-m',
14 wordSpacingDesktop:'word-spacing-d', wordSpacingTablet:'word-spacing-t', wordSpacingMobile:'word-spacing-m'
15 };
16 function typoCssVarsForEl(el, obj, prefix) {
17 if (!obj || typeof obj !== 'object') return;
18 Object.keys(_typoKeys).forEach(function (k) {
19 var v = obj[k];
20 if (v === undefined || v === '' || v === null) return;
21 if (k === 'sizeDesktop' || k === 'sizeTablet' || k === 'sizeMobile') v = v + (obj.sizeUnit || 'px');
22 else if (k === 'lineHeightDesktop' || k === 'lineHeightTablet' || k === 'lineHeightMobile') v = v + (obj.lineHeightUnit || '');
23 else if (k === 'letterSpacingDesktop' || k === 'letterSpacingTablet' || k === 'letterSpacingMobile') v = v + (obj.letterSpacingUnit || 'px');
24 else if (k === 'wordSpacingDesktop' || k === 'wordSpacingTablet' || k === 'wordSpacingMobile') v = v + (obj.wordSpacingUnit || 'px');
25 el.style.setProperty(prefix + _typoKeys[k], String(v));
26 });
27 }
28
29 function buildNeonShadow(a, boost) {
30 var tube = a.tubeColor || '#00d4ff';
31 var glow = a.glowColor || '#00d4ff';
32 var second = a.secondGlow || '#0055ff';
33 var int = (a.glowIntensity || 3) * (boost || 1);
34 var spread = a.glowSpread || 40;
35
36 return [
37 '0 0 ' + Math.round(spread * 0.1) + 'px ' + tube,
38 '0 0 ' + Math.round(spread * 0.3) + 'px ' + tube,
39 '0 0 ' + Math.round(spread * 0.6 * int) + 'px ' + glow,
40 '0 0 ' + Math.round(spread * 1.0 * int) + 'px ' + glow,
41 '0 0 ' + Math.round(spread * 2.0 * int) + 'px ' + second,
42 '0 0 ' + Math.round(spread * 3.0 * int) + 'px ' + second,
43 ].join(', ');
44 }
45
46 function initNeonText(root, a) {
47 var Tag = a.tag || 'h2';
48 var text = a.text || 'NEON SIGN';
49 var shadow = buildNeonShadow(a);
50
51 /* wrap */
52 var wrap = document.createElement('div');
53 wrap.className = 'bkbg-nt-wrap';
54 wrap.style.cssText = [
55 'background:' + (a.backgroundColor || '#0a0a12'),
56 'padding:' + (a.paddingV || 64) + 'px ' + (a.paddingH || 48) + 'px',
57 'border-radius:' + (a.borderRadius || 16) + 'px',
58 'text-align:' + (a.textAlign || 'center'),
59 'position:relative',
60 'overflow:hidden',
61 ].join(';');
62
63 /* sign border */
64 if (a.showBorderSign) {
65 var border = document.createElement('div');
66 border.className = 'bkbg-nt-border-sign';
67 var br = Math.max(0, (a.borderRadius || 16) - 6);
68 border.style.cssText = [
69 'inset:12px',
70 'border-color:' + (a.borderSignColor || '#ff0080'),
71 'border-radius:' + br + 'px',
72 'box-shadow:0 0 12px ' + (a.borderSignColor || '#ff0080') + ',inset 0 0 12px ' + (a.borderSignColor || '#ff0080') + '22',
73 ].join(';');
74 wrap.appendChild(border);
75 }
76
77 /* scanlines */
78 if (a.showScanlines) {
79 var scanDiv = document.createElement('div');
80 scanDiv.className = 'bkbg-nt-scanlines';
81 wrap.appendChild(scanDiv);
82 }
83
84 /* text element */
85 var textEl = document.createElement(Tag);
86 textEl.className = 'bkbg-nt-text';
87
88 var baseTs = [
89 'color:' + (a.tubeColor || '#00d4ff'),
90 'text-shadow:' + shadow,
91 'margin:0',
92 'display:block',
93 'cursor:default',
94 'position:relative',
95 'z-index:2',
96 ].join(';');
97
98 /* flicker mode */
99 var flickerMode = a.flickerMode || 'soft';
100 if (flickerMode === 'soft') textEl.classList.add('bkbg-nt-flicker-soft');
101 if (flickerMode === 'classic') textEl.classList.add('bkbg-nt-flicker-classic');
102
103 textEl.style.cssText = baseTs;
104
105 /* broken flicker: wrap a single character in a span */
106 if (flickerMode === 'broken') {
107 var chars = text.split('');
108 var letterIdx = a.flickerLetter >= 0 && a.flickerLetter < chars.length
109 ? a.flickerLetter
110 : Math.floor(Math.random() * chars.length);
111 textEl.innerHTML = chars.map(function (ch, i) {
112 if (ch === ' ') return '<span>&nbsp;</span>';
113 if (i === letterIdx) {
114 return '<span class="bkbg-nt-broken-letter" style="text-shadow:' + shadow + '">' + ch + '</span>';
115 }
116 return '<span>' + ch + '</span>';
117 }).join('');
118 } else {
119 textEl.textContent = text;
120 }
121
122 wrap.appendChild(textEl);
123
124 /* subtitle */
125 if (a.showSubText && a.subText) {
126 var subEl = document.createElement('p');
127 subEl.className = 'bkbg-nt-sub';
128 var subShadow = buildNeonShadow(a, 0.6);
129 subEl.style.cssText = [
130 'color:' + (a.tubeColor || '#00d4ff'),
131 'text-shadow:' + subShadow,
132 'position:relative',
133 'z-index:2',
134 ].join(';');
135 subEl.textContent = a.subText;
136 wrap.appendChild(subEl);
137 }
138
139 /* glow floor */
140 if (a.showGlowFloor) {
141 var floor = document.createElement('div');
142 floor.className = 'bkbg-nt-floor';
143 floor.style.cssText = 'background:radial-gradient(ellipse at center,' + (a.glowColor || '#00d4ff') + '55 0%,transparent 70%);';
144 wrap.appendChild(floor);
145 }
146
147 root.appendChild(wrap);
148
149 /* Typography CSS vars */
150 typoCssVarsForEl(root.parentNode, a.headingTypo, '--bkbg-nt-hd-');
151 typoCssVarsForEl(root.parentNode, a.subtitleTypo, '--bkbg-nt-sb-');
152
153 /* broken: re-randomize letter occasionally for realism */
154 if (flickerMode === 'broken' && a.flickerLetter < 0) {
155 setInterval(function () {
156 var oldLetter = wrap.querySelector('.bkbg-nt-broken-letter');
157 if (!oldLetter) return;
158 var spans = Array.from(textEl.querySelectorAll('span'));
159 var noneEmpty = spans.filter(function (s) { return s.textContent.trim(); });
160 if (!noneEmpty.length) return;
161 oldLetter.classList.remove('bkbg-nt-broken-letter');
162 var pick = noneEmpty[Math.floor(Math.random() * noneEmpty.length)];
163 pick.classList.add('bkbg-nt-broken-letter');
164 }, 4000 + Math.random() * 4000);
165 }
166 }
167