PluginProbe
VikBooking Hotel Booking Engine & PMS / trunk
VikBooking Hotel Booking Engine & PMS vtrunk
1.8.15 1.8.14 1.8.13 1.8.12 1.8.11 1.8.10 1.8.9 1.8.6 1.8.7 1.8.8 trunk 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 All 36 releases
vikbooking / admin / resources / js / gutenberg-tools.js

gutenberg-tools.js in VikBooking Hotel Booking Engine & PMS trunk, at admin/resources/js/gutenberg-tools.js

520 lines 12.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 (function(wp) {
2 'use strict';
3
4 /**
5 * Creates a control element according to the provided field data.
6 *
7 * @param object field The field structure.
8 * @param object props The block properties object.
9 *
10 * @return mixed A react control.
11 */
12 window.vboCreateControlElement = (field, props) => {
13 let fieldControl;
14
15 switch (field.layout) {
16 case 'html.form.fields.list':
17 fieldControl = field.class === 'btn-group btn-group-yesno'
18 ? new VBOWidgetBlockFieldCheckbox(field)
19 : new VBOWidgetBlockFieldList(field);
20 break;
21
22 case 'html.form.fields.groupedlist':
23 fieldControl = new VBOWidgetBlockFieldGroupedList(field);
24 break;
25
26 case 'html.form.fields.textarea':
27 fieldControl = new VBOWidgetBlockFieldTextarea(field);
28 break;
29
30 case 'html.form.fields.media':
31 fieldControl = new VBOWidgetBlockFieldMedia(field);
32 break;
33
34 case 'html.form.fields.number':
35 // Do not use NUMBER field yet because this control is experimental
36 // and might be subject to drastic and breaking changes
37 // fieldControl = new VBOWidgetBlockFieldNumber(field);
38 break;
39 }
40
41 if (!fieldControl) {
42 switch (field.type) {
43 case 'color':
44 fieldControl = new VBOWidgetBlockFieldColor(field);
45 break;
46
47 case 'editor':
48 fieldControl = new VBOWidgetBlockFieldTextarea(field);
49 break;
50
51 case 'html':
52 fieldControl = new VBOWidgetBlockFieldHtml(field);
53 break;
54
55 default:
56 // type not supported, use a text field
57 fieldControl = new VBOWidgetBlockFieldText(field);
58 }
59 }
60
61 return fieldControl.createElement(props);
62 }
63
64 /**
65 * Abstract field control.
66 */
67 const VBOWidgetBlockField = class VBOWidgetBlockField {
68 constructor(data) {
69 for (let key in data) {
70 if (data.hasOwnProperty(key)) {
71 this[key] = data[key];
72 }
73 }
74 }
75
76 shouldDisplay(props) {
77 if (!this.showon) {
78 return true;
79 }
80
81 // detect the conditions glue
82 let glue = this.showon.match(/\[OR\]/i) ? 'or' : 'and';
83
84 // extract all the conditions
85 let conditions = this.showon.split(/\[AND\]|\[OR\]/i);
86
87 let verified = false;
88
89 for (let condition of conditions) {
90 // extract the attribute [1], the comparator [2] and the comparison value [3]
91 let chunks = condition.match(/^([a-z0-9_\[\]]+)([!:]+)(.*$)$/i);
92
93 if (!chunks) {
94 // invalid condition
95 continue;
96 }
97
98 let fieldName = chunks[1];
99 let comparator = chunks[2];
100 let match = (chunks[3] === null || chunks[3] === undefined ? '' : chunks[3]).split(/\s*,\s*/);
101
102 if (!props.attributes.hasOwnProperty(fieldName)) {
103 // field not found
104 continue;
105 }
106
107 // validate condition
108 switch (comparator) {
109 case ':':
110 verified = match.indexOf(props.attributes[fieldName].toString()) !== -1;
111 break;
112
113 case '!:':
114 verified = match.indexOf(props.attributes[fieldName].toString()) === -1;
115 break;
116 }
117
118 if (!verified && glue === 'and') {
119 // all the conditions must be verified
120 return false;
121 }
122
123 if (verified && glue === 'or') {
124 // at least a condition can be verified
125 return true;
126 }
127 }
128
129 return verified;
130 }
131
132 createElement(props) {
133 if (this.shouldDisplay(props)) {
134 return this.buildElement(props);
135 }
136
137 return null;
138 }
139
140 buildElement(props) {
141 return null;
142 }
143 }
144
145 /**
146 * Text control field renderer.
147 *
148 * @see wp.components.TextControl
149 * @link https://developer.wordpress.org/block-editor/reference-guides/components/text-control/
150 */
151 const VBOWidgetBlockFieldText = class VBOWidgetBlockFieldText extends VBOWidgetBlockField {
152 buildElement(props) {
153 return wp.element.createElement(
154 wp.components.TextControl,
155 {
156 label: this.label,
157 help: this.description,
158 value: props.attributes[this.name],
159 placeholder: this.hint,
160 onChange: (value) => {
161 let attrs = {};
162 attrs[this.name] = value;
163
164 props.setAttributes(attrs);
165 },
166 __nextHasNoMarginBottom: true,
167 __next40pxDefaultSize: true,
168 }
169 );
170 }
171 }
172
173 /**
174 * Textarea control field renderer.
175 *
176 * @see wp.components.TextareaControl
177 * @link https://developer.wordpress.org/block-editor/reference-guides/components/text-control/
178 */
179 const VBOWidgetBlockFieldTextarea = class VBOWidgetBlockFieldTextarea extends VBOWidgetBlockField {
180 buildElement(props) {
181 return wp.element.createElement(
182 wp.components.TextareaControl,
183 {
184 label: this.label,
185 help: this.description,
186 value: props.attributes[this.name],
187 placeholder: this.hint,
188 onChange: (value) => {
189 let attrs = {};
190 attrs[this.name] = value;
191
192 props.setAttributes(attrs);
193 },
194 __nextHasNoMarginBottom: true,
195 __next40pxDefaultSize: true,
196 }
197 );
198 }
199 }
200
201 /**
202 * Number control field renderer.
203 *
204 * @see wp.components.NumberControl
205 * @link https://developer.wordpress.org/block-editor/reference-guides/components/number-control/
206 */
207 const VBOWidgetBlockFieldNumber = class VBOWidgetBlockFieldNumber extends VBOWidgetBlockField {
208 buildElement(props) {
209 return wp.element.createElement(
210 wp.components.__experimentalNumberControl,
211 {
212 label: this.label,
213 help: this.description,
214 value: props.attributes[this.name],
215 min: this.min !== 'undefined' ? this.min : Number.NEGATIVE_INFINITY,
216 max: this.max !== 'undefined' ? this.max : Number.POSITIVE_INFINITY,
217 step: this.step !== 'undefined' ? this.step : 'any',
218 onChange: (value) => {
219 let attrs = {};
220 attrs[this.name] = value;
221
222 props.setAttributes(attrs);
223 },
224 __nextHasNoMarginBottom: true,
225 __next40pxDefaultSize: true,
226 }
227 );
228 }
229 }
230
231 /**
232 * Color control field renderer.
233 *
234 * @see wp.components.ColorPicker
235 * @link https://developer.wordpress.org/block-editor/reference-guides/components/color-picker/
236 */
237 const VBOWidgetBlockFieldColor = class VBOWidgetBlockFieldColor extends VBOWidgetBlockField {
238 buildElement(props) {
239 return wp.element.createElement(
240 wp.components.BaseControl,
241 {
242 label: this.label,
243 help: this.description,
244 children: wp.element.createElement(
245 wp.components.ColorPicker,
246 {
247 color: props.attributes[this.name],
248 enableAlpha: true,
249 copyFormat: 'hex',
250 onChange: (value) => {
251 let attrs = {};
252 attrs[this.name] = value;
253
254 props.setAttributes(attrs);
255 }
256 }
257 ),
258 __nextHasNoMarginBottom: true,
259 __next40pxDefaultSize: true,
260 }
261 );
262 }
263 }
264
265 /**
266 * Checkbox control field renderer.
267 *
268 * @see wp.components.ToggleControl
269 * @link https://developer.wordpress.org/block-editor/reference-guides/components/toggle-control/
270 */
271 const VBOWidgetBlockFieldCheckbox = class VBOWidgetBlockFieldCheckbox extends VBOWidgetBlockField {
272 buildElement(props) {
273 return wp.element.createElement(
274 wp.components.ToggleControl,
275 {
276 label: this.label,
277 help: this.description,
278 checked: parseInt(props.attributes[this.name]) ? true : false,
279 onChange: (value) => {
280 let attrs = {};
281 attrs[this.name] = value ? 1 : 0;
282
283 props.setAttributes(attrs);
284 },
285 __nextHasNoMarginBottom: true,
286 __next40pxDefaultSize: true,
287 }
288 );
289 }
290 }
291
292 /**
293 * List control field renderer.
294 *
295 * @see wp.components.SelectControl
296 * @link https://developer.wordpress.org/block-editor/reference-guides/components/select-control/
297 */
298 const VBOWidgetBlockFieldList = class VBOWidgetBlockFieldList extends VBOWidgetBlockField {
299 buildElement(props) {
300 return wp.element.createElement(
301 wp.components.SelectControl,
302 {
303 label: this.label,
304 help: this.description,
305 value: props.attributes[this.name],
306 options: this.options,
307 multiple: this.multiple ? true : false,
308 onChange: (value) => {
309 let attrs = {};
310 attrs[this.name] = value;
311
312 props.setAttributes(attrs);
313 },
314 __nextHasNoMarginBottom: true,
315 __next40pxDefaultSize: true,
316 }
317 );
318 }
319 }
320
321 /**
322 * Grouped list control field renderer.
323 *
324 * @see wp.components.SelectControl
325 * @link https://developer.wordpress.org/block-editor/reference-guides/components/select-control/
326 */
327 const VBOWidgetBlockFieldGroupedList = class VBOWidgetBlockFieldGroupedList extends VBOWidgetBlockField {
328 constructor(data) {
329 super(data);
330
331 this.children = [];
332
333 for (let groupLabel in this.groups) {
334 if (!this.groups.hasOwnProperty(groupLabel)) {
335 continue;
336 }
337
338 let options = [];
339
340 this.groups[groupLabel].forEach((option) => {
341 options.push(
342 wp.element.createElement(
343 'option',
344 {
345 value: option.value,
346 },
347 option.text
348 )
349 );
350 });
351
352 this.children.push(
353 wp.element.createElement(
354 'optgroup',
355 {
356 label: groupLabel,
357 },
358 options
359 )
360 );
361 }
362 }
363
364 buildElement(props) {
365 return wp.element.createElement(
366 wp.components.SelectControl,
367 {
368 label: this.label,
369 help: this.description,
370 value: props.attributes[this.name],
371 children: this.children,
372 multiple: this.multiple ? true : false,
373 onChange: (value) => {
374 let attrs = {};
375 attrs[this.name] = value;
376
377 props.setAttributes(attrs);
378 },
379 __nextHasNoMarginBottom: true,
380 __next40pxDefaultSize: true,
381 }
382 );
383 }
384 }
385
386 /**
387 * Media manager control field renderer.
388 *
389 * @see wp.editor.MediaPlaceholder
390 * @link https://github.com/WordPress/gutenberg/blob/HEAD/packages/block-editor/src/components/media-placeholder/README.md
391 */
392 const VBOWidgetBlockFieldMedia = class VBOWidgetBlockFieldMedia extends VBOWidgetBlockField {
393 buildElement(props) {
394 let mediaPreview = null;
395
396 if (props.attributes[this.name]) {
397 let children = [];
398
399 // display image only in case the preview is not disabled
400 if (this.preview === undefined || this.preview) {
401 children.push(
402 wp.element.createElement(
403 'img',
404 {
405 src: props.attributes[this.name],
406 style: {
407 marginBottom: '10px',
408 },
409 }
410 )
411 );
412 }
413
414 // add button to clear the selected image
415 children.push(
416 wp.element.createElement(
417 wp.components.Button,
418 {
419 text: wp.i18n.__('Clear'),
420 isDestructive: true,
421 isSecondary: true,
422 style: {
423 marginBottom: '10px',
424 },
425 onClick: () => {
426 let attrs = {};
427 attrs[this.name] = '';
428
429 props.setAttributes(attrs);
430 },
431 }
432 )
433 );
434
435 mediaPreview = wp.element.createElement(
436 'div',
437 {},
438 children
439 );
440 }
441
442 return wp.element.createElement(
443 wp.components.BaseControl,
444 {
445 label: this.label,
446 help: this.description,
447 children: wp.element.createElement(
448 wp.blockEditor.MediaPlaceholder,
449 {
450 labels: { title: '' },
451 multiple: this.multiple ? true : false,
452 // value: props.attributes[this.name],
453 allowedTypes: ['image'],
454 mediaPreview: mediaPreview,
455 onSelect: (value) => {
456 let attrs = {};
457 attrs[this.name] = value.url;
458
459 props.setAttributes(attrs);
460 }
461 }
462 ),
463 __nextHasNoMarginBottom: true,
464 __next40pxDefaultSize: true,
465 }
466 );
467 }
468 }
469
470 /**
471 * Generic HTML control field renderer.
472 */
473 const VBOWidgetBlockFieldHtml = class VBOWidgetBlockFieldHtml extends VBOWidgetBlockField {
474 buildElement(props) {
475 return wp.element.createElement(
476 wp.components.BaseControl,
477 {
478 label: this.label,
479 help: this.description,
480 children: this.createTree(this.layout),
481 __nextHasNoMarginBottom: true,
482 __next40pxDefaultSize: true,
483 }
484 );
485 }
486
487 createTree(nodes) {
488 let children = [];
489
490 nodes.forEach((node) => {
491 let content = [];
492
493 if (node.content) {
494 content.push(node.content);
495 }
496
497 if (node.children) {
498 content = content.concat(this.createTree(node.children));
499 }
500
501 if (node.attributes && node.attributes.class) {
502 // remove any class that might render an element as a notice
503 node.attributes.class = node.attributes.class.replace(/\bnotice(-[a-z]+)?\b/g, '').trim();
504 // convert button classes
505 node.attributes.class = node.attributes.class.replace(/\bbtn\b/g, 'button');
506 }
507
508 children.push(
509 wp.element.createElement(
510 node.tag,
511 node.attributes || {},
512 content
513 )
514 );
515 });
516
517 return children;
518 }
519 }
520 })(window.wp);