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 / book-review / frontend.js

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

270 lines 13.2 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 halfStarHTML(color) {
5 return '<span style="position:relative;display:inline-block;color:#d1d5db;line-height:1;">�
6 <span style="position:absolute;left:0;top:0;width:50%;overflow:hidden;color:' + color + ';">�
7 </span></span>';
8 }
9
10 function starsHTML(rating, max, color) {
11 var full = Math.floor(rating);
12 var half = rating - full >= 0.5;
13 var empty = max - full - (half ? 1 : 0);
14 var out = '';
15 var i;
16 for (i = 0; i < full; i++) out += '<span style="color:' + color + '">�
17 </span>';
18 if (half) out += halfStarHTML(color);
19 for (i = 0; i < empty; i++) out += '<span style="color:#d1d5db">�
20 </span>';
21 return out;
22 }
23
24 function esc(str) {
25 return String(str || '')
26 .replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
27 }
28
29 function typoCssVarsForEl(typo, prefix, el) {
30 if (!typo) return;
31 if (typo.family) el.style.setProperty(prefix + 'font-family', "'" + typo.family + "', sans-serif");
32 if (typo.weight) el.style.setProperty(prefix + 'font-weight', typo.weight);
33 if (typo.transform) el.style.setProperty(prefix + 'text-transform', typo.transform);
34 if (typo.style) el.style.setProperty(prefix + 'font-style', typo.style);
35 if (typo.decoration) el.style.setProperty(prefix + 'text-decoration', typo.decoration);
36 var su = typo.sizeUnit || 'px';
37 if (typo.sizeDesktop !== '' && typo.sizeDesktop != null) el.style.setProperty(prefix + 'font-size-d', typo.sizeDesktop + su);
38 if (typo.sizeTablet !== '' && typo.sizeTablet != null) el.style.setProperty(prefix + 'font-size-t', typo.sizeTablet + su);
39 if (typo.sizeMobile !== '' && typo.sizeMobile != null) el.style.setProperty(prefix + 'font-size-m', typo.sizeMobile + su);
40 var lhu = typo.lineHeightUnit || '';
41 if (typo.lineHeightDesktop !== '' && typo.lineHeightDesktop != null) el.style.setProperty(prefix + 'line-height-d', typo.lineHeightDesktop + lhu);
42 if (typo.lineHeightTablet !== '' && typo.lineHeightTablet != null) el.style.setProperty(prefix + 'line-height-t', typo.lineHeightTablet + lhu);
43 if (typo.lineHeightMobile !== '' && typo.lineHeightMobile != null) el.style.setProperty(prefix + 'line-height-m', typo.lineHeightMobile + lhu);
44 var lsu = typo.letterSpacingUnit || 'px';
45 if (typo.letterSpacingDesktop !== '' && typo.letterSpacingDesktop != null) el.style.setProperty(prefix + 'letter-spacing-d', typo.letterSpacingDesktop + lsu);
46 if (typo.letterSpacingTablet !== '' && typo.letterSpacingTablet != null) el.style.setProperty(prefix + 'letter-spacing-t', typo.letterSpacingTablet + lsu);
47 if (typo.letterSpacingMobile !== '' && typo.letterSpacingMobile != null) el.style.setProperty(prefix + 'letter-spacing-m', typo.letterSpacingMobile + lsu);
48 var wsu = typo.wordSpacingUnit || 'px';
49 if (typo.wordSpacingDesktop !== '' && typo.wordSpacingDesktop != null) el.style.setProperty(prefix + 'word-spacing-d', typo.wordSpacingDesktop + wsu);
50 if (typo.wordSpacingTablet !== '' && typo.wordSpacingTablet != null) el.style.setProperty(prefix + 'word-spacing-t', typo.wordSpacingTablet + wsu);
51 if (typo.wordSpacingMobile !== '' && typo.wordSpacingMobile != null) el.style.setProperty(prefix + 'word-spacing-m', typo.wordSpacingMobile + wsu);
52 }
53
54 function buildApp(app) {
55 var opts = {};
56 try { opts = JSON.parse(app.getAttribute('data-opts') || '{}'); } catch (e) {}
57
58 var cRadius = (opts.cardRadius || 16) + 'px';
59 var bRadius = (opts.btnRadius || 8) + 'px';
60 var maxW = (opts.maxWidth || 860) + 'px';
61 var covW = (opts.coverWidth || 160) + 'px';
62 var titleSz = (opts.titleSize || 24) + 'px';
63 var bodySz = (opts.bodySize || 15) + 'px';
64 var starClr = opts.starColor || '#f59e0b';
65 var rating = opts.rating || 4;
66 var maxRat = opts.maxRating || 5;
67
68 /* ── Card ── */
69 var card = document.createElement('div');
70 card.className = 'bkbg-br-card';
71 card.style.cssText = [
72 'border:1px solid ' + (opts.borderColor || '#e5e7eb'),
73 'border-radius:' + cRadius,
74 'overflow:hidden',
75 'background:' + (opts.cardBg || '#ffffff'),
76 'max-width:' + maxW,
77 'margin:0 auto',
78 ].join(';');
79
80 /* ── Header ── */
81 var header = document.createElement('div');
82 header.className = 'bkbg-br-header';
83 header.style.cssText = 'background:' + (opts.headerBg || '#f5f3ff') + ';padding:28px;display:flex;gap:24px;align-items:flex-start;flex-wrap:wrap';
84
85 /* Cover */
86 if (opts.coverUrl) {
87 var img = document.createElement('img');
88 img.src = opts.coverUrl;
89 img.alt = opts.coverAlt || opts.bookTitle || '';
90 img.className = 'bkbg-br-cover';
91 img.style.cssText = 'width:' + covW + ';border-radius:8px;display:block;object-fit:cover;flex-shrink:0';
92 header.appendChild(img);
93 } else {
94 var placeholder = document.createElement('div');
95 placeholder.className = 'bkbg-br-cover-placeholder';
96 placeholder.style.cssText = 'width:' + covW + ';border-radius:8px;background:#e5e7eb;display:flex;align-items:center;justify-content:center;min-height:220px;font-size:48px;flex-shrink:0';
97 placeholder.textContent = '📖';
98 header.appendChild(placeholder);
99 }
100
101 /* Meta */
102 var meta = document.createElement('div');
103 meta.className = 'bkbg-br-meta';
104 meta.style.cssText = 'flex:1;min-width:0';
105
106 var titleEl = document.createElement('h2');
107 titleEl.className = 'bkbg-br-title';
108 titleEl.style.cssText = 'color:' + (opts.titleColor || '#1e1b4b') + ';margin:0 0 4px;';
109 titleEl.textContent = opts.bookTitle || '';
110 meta.appendChild(titleEl);
111
112 var authorEl = document.createElement('div');
113 authorEl.className = 'bkbg-br-author';
114 authorEl.style.cssText = 'color:' + (opts.authorColor || '#6c3fb5') + ';font-weight:600;font-size:15px;margin-bottom:12px';
115 authorEl.textContent = opts.bookAuthor || '';
116 meta.appendChild(authorEl);
117
118 /* Rating */
119 var ratingRow = document.createElement('div');
120 ratingRow.className = 'bkbg-br-rating-row';
121 ratingRow.style.cssText = 'display:flex;align-items:center;gap:10px;margin-bottom:16px;flex-wrap:wrap';
122
123 var starsSpan = document.createElement('span');
124 starsSpan.className = 'bkbg-br-stars';
125 starsSpan.style.cssText = 'letter-spacing:2px;font-size:22px;line-height:1';
126 starsSpan.innerHTML = starsHTML(rating, maxRat, starClr);
127 ratingRow.appendChild(starsSpan);
128
129 var ratingLbl = document.createElement('span');
130 ratingLbl.className = 'bkbg-br-rating-label';
131 ratingLbl.style.cssText = 'font-size:14px;color:#6b7280';
132 ratingLbl.textContent = rating + ' / ' + maxRat + (opts.ratingLabel ? '' + opts.ratingLabel : '');
133 ratingRow.appendChild(ratingLbl);
134 meta.appendChild(ratingRow);
135
136 /* Details */
137 if (opts.showDetails !== false) {
138 var det = document.createElement('div');
139 var rows = [
140 ['Genre', opts.genre],
141 ['Publisher', opts.publisher],
142 ['Year', opts.publishYear],
143 ['Pages', opts.pages],
144 ['ISBN', opts.isbn],
145 ];
146 rows.forEach(function (r) {
147 if (!r[1]) return;
148 var row = document.createElement('div');
149 row.className = 'bkbg-br-detail-row';
150 row.innerHTML = '<span class="bkbg-br-detail-label" style="color:' + (opts.detailLabelClr || '#9ca3af') + '">' + esc(r[0]) + ':</span>' +
151 '<span class="bkbg-br-detail-val" style="color:' + (opts.bodyColor || '#374151') + '">' + esc(r[1]) + '</span>';
152 det.appendChild(row);
153 });
154 meta.appendChild(det);
155 }
156
157 header.appendChild(meta);
158 card.appendChild(header);
159
160 /* ── Body ── */
161 var body = document.createElement('div');
162 body.className = 'bkbg-br-body';
163 body.style.cssText = 'padding:24px 28px;background:' + (opts.cardBg || '#ffffff');
164
165 /* Summary */
166 if (opts.summary) {
167 var sumHead = document.createElement('p');
168 sumHead.className = 'bkbg-br-section-title';
169 sumHead.style.color = opts.titleColor || '#1e1b4b';
170 sumHead.textContent = 'Review Summary';
171 var sumText = document.createElement('div');
172 sumText.className = 'bkbg-br-summary';
173 sumText.style.cssText = 'color:' + (opts.bodyColor || '#374151') + ';margin-bottom:20px';
174 sumText.innerHTML = opts.summary;
175 body.appendChild(sumHead);
176 body.appendChild(sumText);
177 }
178
179 /* Pros / Cons */
180 var pros = opts.pros || [];
181 var cons = opts.cons || [];
182 var hasPros = opts.showPros !== false && pros.length > 0;
183 var hasCons = opts.showCons !== false && cons.length > 0;
184
185 if (hasPros || hasCons) {
186 var pcGrid = document.createElement('div');
187 pcGrid.className = 'bkbg-br-proscons';
188 pcGrid.style.cssText = 'display:grid;grid-template-columns:' + (hasPros && hasCons ? '1fr 1fr' : '1fr') + ';gap:20px;margin-bottom:20px';
189
190 function makeList(items, color, icon, label) {
191 var col = document.createElement('div');
192 var lh = document.createElement('div');
193 lh.className = 'bkbg-br-list-head';
194 lh.style.cssText = 'font-weight:700;font-size:14px;margin-bottom:8px;color:' + color;
195 lh.textContent = icon + ' ' + label;
196 col.appendChild(lh);
197 var ul = document.createElement('ul');
198 ul.className = 'bkbg-br-list';
199 items.forEach(function (item) {
200 var li = document.createElement('li');
201 li.style.cssText = 'display:flex;gap:8px;align-items:flex-start;margin-bottom:6px;color:' + (opts.bodyColor || '#374151');
202 li.innerHTML = '<span class="bkbg-br-list-icon" style="color:' + color + ';font-weight:700;flex-shrink:0;margin-top:1px">' + icon + '</span>' +
203 '<span>' + esc(item) + '</span>';
204 ul.appendChild(li);
205 });
206 col.appendChild(ul);
207 return col;
208 }
209
210 if (hasPros) pcGrid.appendChild(makeList(pros, opts.prosColor || '#15803d', '', 'Pros'));
211 if (hasCons) pcGrid.appendChild(makeList(cons, opts.consColor || '#b91c1c', '', 'Cons'));
212 body.appendChild(pcGrid);
213 }
214
215 /* Button */
216 if (opts.showBtn !== false && opts.btnText) {
217 var btn = document.createElement('a');
218 btn.className = 'bkbg-br-btn';
219 btn.href = opts.btnUrl || '#';
220 btn.target = opts.btnTarget !== false ? '_blank' : '_self';
221 btn.rel = opts.btnTarget !== false ? 'noopener noreferrer' : '';
222 btn.textContent = opts.btnText;
223 btn.style.cssText = [
224 'display:inline-block',
225 'background:' + (opts.btnBg || '#6c3fb5'),
226 'color:' + (opts.btnColor || '#ffffff'),
227 'border-radius:' + bRadius,
228 'padding:12px 32px',
229 'font-weight:700',
230 'font-size:15px',
231 'text-decoration:none',
232 ].join(';');
233 body.appendChild(btn);
234 }
235
236 card.appendChild(body);
237 app.innerHTML = '';
238 app.appendChild(card);
239
240 typoCssVarsForEl(opts.typoTitle, '--bkbg-br-title-', app);
241 typoCssVarsForEl(opts.typoBody, '--bkbg-br-body-', app);
242
243 /* Schema.org JSON-LD */
244 if (opts.showSchema !== false) {
245 var schema = {
246 '@context': 'https://schema.org',
247 '@type': 'Review',
248 'reviewRating': { '@type': 'Rating', 'ratingValue': String(opts.rating || 4), 'bestRating': String(opts.maxRating || 5) },
249 'itemReviewed': {
250 '@type': 'Book',
251 'name': opts.bookTitle || '',
252 'author': { '@type': 'Person', 'name': opts.bookAuthor || '' },
253 'publisher': opts.publisher ? { '@type': 'Organization', 'name': opts.publisher } : undefined,
254 'datePublished': opts.publishYear || undefined,
255 'numberOfPages': opts.pages || undefined,
256 'isbn': opts.isbn || undefined,
257 'image': opts.coverUrl || undefined,
258 },
259 'reviewBody': opts.summary || undefined,
260 };
261 var script = document.createElement('script');
262 script.type = 'application/ld+json';
263 script.textContent = JSON.stringify(schema);
264 app.appendChild(script);
265 }
266 }
267
268 document.querySelectorAll('.bkbg-br-app').forEach(buildApp);
269 })();
270