PluginProbe
Booking Calendar / 11.8.4
Booking Calendar v11.8.4
11.8.4 11.8.3 11.8.2 11.8.1 11.8 11.7 11.6.1 11.6 11.5 11.4.3 11.4.2 11.4.1 11.4 11.3 11.2.1 11.2 11.1 11.0 10.15.7 10.15.6 10.1.3 10.10 10.10.1 10.10.2 10.11 All 204 releases
← All changes | js/wpbc-gutenberg.js +238 -43 11.511.8.4 View file →
@@ -12,8 +12,13 @@
12 12 */
13 13
14 14 // FixIn: 8.3.3.99.
15 15
16 +var wpbc_gutenberg_active_block_target = {
17 + block_id: '',
18 + set_attributes: null
19 +};
20 +
16 21 /*
17 22 window.wp.blocks,
18 23 window.wp.components,
19 24 window.wp.element
@@ -20,8 +25,103 @@
20 25
21 26 */
22 27 //( function( blocks, components, element ) {
23 28
29 +/**
30 + * Open the Booking Calendar block configurator for a specific block.
31 + *
32 + * This helper receives the clicked element directly because WordPress 7.1 renders
33 + * the editor canvas in an iframe whose events and DOM are not available through
34 + * the parent admin document.
35 + *
36 + * @param {string} block_id Gutenberg client ID for the block.
37 + * @param {string|number} popup_tab_index Legacy configurator tab index.
38 + * @param {string} popup_shortcode_id Modern configurator section ID.
39 + * @param {Element|null} trigger_element Element that opened the configurator.
40 + * @param {Function|null} set_attributes Attribute updater from the live block edit instance.
41 + * @return {boolean} Whether the configurator was opened.
42 + */
43 +function wpbc_gutenberg_open_configurator( block_id, popup_tab_index, popup_shortcode_id, trigger_element, set_attributes ) {
44 + var block_wrapper;
45 + var normalized_tab_index = parseInt( popup_tab_index, 10 );
46 +
47 + if ( ! block_id || ( 'function' !== typeof wpbc_tiny_btn_click ) ) {
48 + return false;
49 + }
50 +
51 + if ( isNaN( normalized_tab_index ) ) {
52 + normalized_tab_index = 0;
53 + }
54 +
55 + if ( trigger_element && ( 'function' === typeof trigger_element.closest ) ) {
56 + block_wrapper = trigger_element.closest( 'div[data-block]' );
57 + if ( block_wrapper ) {
58 + block_wrapper.classList.remove( 'is-selected' );
59 + }
60 + }
61 +
62 + wpbc_tiny_btn_click( '' );
63 + jQuery( '#wpbc_text_gettenberg_section_id' ).val( block_id );
64 + wpbc_gutenberg_active_block_target = {
65 + block_id: block_id,
66 + set_attributes: ( 'function' === typeof set_attributes ) ? set_attributes : null
67 + };
68 +
69 + if ( popup_shortcode_id && jQuery( '#wpbc_shortcode_config__nav_tab__' + popup_shortcode_id + ' a' ).length ) {
70 + jQuery( '#wpbc_shortcode_config__nav_tab__' + popup_shortcode_id + ' a' ).first().trigger( 'click' );
71 + } else {
72 + jQuery( '#wpbc_tiny_modal .wpdvlp-top-tabs a.nav-tab' ).eq( normalized_tab_index ).trigger( 'click' );
73 + }
74 +
75 + return true;
76 +}
77 +
78 +/**
79 + * Handle the React click event for the block configuration control.
80 + *
81 + * @param {Event} event React synthetic click event from the editor iframe.
82 + * @param {Function} set_attributes Attribute updater from the live block edit instance.
83 + * @return {boolean} Whether the configurator was opened.
84 + */
85 +function wpbc_gutenberg_handle_configure_click( event, set_attributes ) {
86 + var trigger_element = event.currentTarget;
87 +
88 + event.preventDefault();
89 + event.stopPropagation();
90 +
91 + return wpbc_gutenberg_open_configurator(
92 + trigger_element.getAttribute( 'data_block_id' ),
93 + trigger_element.getAttribute( 'popup_tab_index' ),
94 + trigger_element.getAttribute( 'popup_shortcode_id' ),
95 + trigger_element,
96 + set_attributes
97 + );
98 +}
99 +
100 +/**
101 + * Handle the React click event for the preview's edit control.
102 + *
103 + * @param {Event} event React synthetic click event from the editor iframe.
104 + * @return {boolean} Whether a matching configuration control was activated.
105 + */
106 +function wpbc_gutenberg_handle_preview_edit_click( event ) {
107 + var preview_wrapper;
108 + var configure_button;
109 +
110 + event.preventDefault();
111 + event.stopPropagation();
112 +
113 + preview_wrapper = event.currentTarget.closest( '.wpbc_gb_div_block' );
114 + configure_button = preview_wrapper ? preview_wrapper.querySelector( '.wpbc-gutenberg-open-btn' ) : null;
115 +
116 + if ( ! configure_button ) {
117 + return false;
118 + }
119 +
120 + configure_button.click();
121 + return true;
122 +}
123 +
24 124 ( function( wp ) {
25 125 /**
26 126 * Registers a new block provided a unique name and an object defining its behavior.
27 127 * @see https://github.com/WordPress/gutenberg/tree/master/blocks#api
@@ -107,9 +207,49 @@
107 207 default: ''
108 208 }
109 209 },
110 210
211 + deprecated: [
212 + {
213 + supports: {},
214 + attributes: {
215 + wpbc_shortcode: {
216 + type: 'string',
217 + source: 'text',
218 + selector: 'div',
219 + default: ''
220 + }
221 + },
111 222
223 + /**
224 + * Migrate a shortcode recovered from historical saved block markup.
225 + *
226 + * Some released posts contain a missing or stale comment attribute while
227 + * retaining the complete shortcode inside the saved div. The deprecated
228 + * parser makes that visible text authoritative only during recovery.
229 + *
230 + * @param {Object} attributes Parsed deprecated block attributes.
231 + * @return {Object} Current block attributes containing the recovered shortcode.
232 + */
233 + migrate: function( attributes ) {
234 + return {
235 + wpbc_shortcode: attributes.wpbc_shortcode || ''
236 + };
237 + },
238 +
239 + /**
240 + * Reproduce the historical wrapper while WordPress validates old content.
241 + *
242 + * @param {Object} props Deprecated block properties.
243 + * @return {Object} WordPress element for the historical saved markup.
244 + */
245 + save: function( props ) {
246 + return el( 'div', null, props.attributes.wpbc_shortcode );
247 + }
248 + }
249 + ],
250 +
251 +
112 252 edit: function( props ) {
113 253
114 254 //console.log( 'WPBC-Gb :: Edit :', props );
115 255
@@ -123,24 +263,17 @@
123 263
124 264 ////////////////////////////////////////////////////////////////////////////////////////////////////
125 265 ////////////////////////////////////////////////////////////////////////////////////////////////////
126 266
127 - // Old value from attribute
267 + // The block attribute is the only authoritative editor value. Reading the
268 + // mounted input here races React's next commit: after the configurator
269 + // calls setAttributes(), the old input still contains the previous value
270 + // and would immediately overwrite the new shortcode during this render.
128 271 var _val = props.attributes.wpbc_shortcode;
129 272
130 - // Possibly new value, set to the text field programmatically from popup
131 - var _valNew = jQuery( 'div[data-block="' + cid + '"] .wpbc_gb_text_shortcode' ).val();
132 -
133 -//console.log( '%cWPBC-Gb :: E d i t >>> _valNew , _val , cid, obj', 'color: green; font-weight: bold;', _valNew , _val , cid , jQuery( 'div[data-block="' + cid + '"] .wpbc_gb_text_shortcode' ) );
134 -
135 - // Default value here
136 273 if ( typeof _val == typeof undefined ) {
137 274 _val = '';
138 275 }
139 - if ( ( typeof _valNew != typeof undefined ) && ( _val !== _valNew ) ) {
140 - _val = _valNew;
141 - props.setAttributes( { wpbc_shortcode: _val } );
142 - }
143 276
144 277 ////////////////////////////////////////////////////////////////////////////////////////////////////
145 278 ////////////////////////////////////////////////////////////////////////////////////////////////////
146 279
@@ -153,8 +286,11 @@
153 286 href : '#!',
154 287 data_block_id: cid,
155 288 popup_tab_index: 0, // Will be index for active tab in popup dialog
156 289 popup_shortcode_id: '',
290 + onClick: function( event ) {
291 + return wpbc_gutenberg_handle_configure_click( event, props.setAttributes );
292 + },
157 293 key: 'configure_' + cid // FixIn: 8.7.3.18.
158 294 },
159 295 __( 'Configure Booking Calendar Block' )
160 296 )
@@ -240,37 +376,15 @@
240 376 */
241 377 $( document ).on( 'click', '.wpbc-gutenberg-open-btn', function( e ) {
242 378
243 379 e.preventDefault();
380 + wpbc_gutenberg_open_configurator(
381 + $( this ).attr( 'data_block_id' ),
382 + $( this ).attr( 'popup_tab_index' ),
383 + $( this ).attr( 'popup_shortcode_id' ),
384 + this
385 + );
244 386
245 - // Set ID of currently edited section in post (just in case if we will have several sections
246 - var _id = $( this ).attr( 'data_block_id' );
247 -
248 -
249 - // Remove CSS class 'is-selected' (remove blue focus) in main DIV (after popup opened), because of that hide via CSS BIG blue button: "Configure Booking Calendar Block"
250 - jQuery( 'div[data-block="' + _id + '"]' ).removeClass( 'is-selected' ); // FixIn: 8.8.2.10.
251 -
252 - // Get num. of popup active tab to set
253 - var popup_tab_index = $( this ).attr( 'popup_tab_index' );
254 - var popup_shortcode_id = $( this ).attr( 'popup_shortcode_id' );
255 -
256 - var wpbc_tag = '';
257 -
258 - wpbc_tiny_btn_click( wpbc_tag );
259 -
260 - jQuery( "#wpbc_text_gettenberg_section_id" ).val( _id );
261 -
262 - // Select the matching shortcode section for modern workflow previews.
263 - if ( popup_shortcode_id && jQuery( '#wpbc_shortcode_config__nav_tab__' + popup_shortcode_id + ' a' ).length ) {
264 - jQuery( '#wpbc_shortcode_config__nav_tab__' + popup_shortcode_id + ' a' ).first().trigger( 'click' );
265 - } else {
266 - // Select specific TAB in popup dialog for legacy shortcode previews.
267 - jQuery( "#wpbc_tiny_modal .wpdvlp-top-tabs a.nav-tab" ).eq( popup_tab_index ).trigger( 'click' ); // FixIn: 8.7.11.12.
268 - }
269 -
270 -
271 -//console.log( 'WPBC-Gb :: Popup window for configuration Booking Calendar shortcode. Section #', _id );
272 -
273 387 });
274 388
275 389
276 390 /**
@@ -299,8 +413,13 @@
299 413 function wpbc_send_text_to_gutenberg( shortcode_text ){
300 414
301 415 // Get ID of section, where to insert shortcode configuraiton
302 416 var block_section_id = jQuery( "#wpbc_text_gettenberg_section_id" ).val();
417 + var block_editor_select;
418 + var block_editor_dispatch;
419 + var target_block;
420 + var shortcode_input;
421 + var active_set_attributes;
303 422
304 423 //console.log( 'WPBC-Gb :: wpbc_send_text_to_gutenberg' , shortcode_text, block_section_id );
305 424
306 425 if ( '' == block_section_id ) {
@@ -307,14 +426,61 @@
307 426
308 427 return false; // if no such block then just return false, its means tha inserting in Classic block - TinyMCE
309 428 }
310 429
430 + // Use the updater from this exact block edit instance. Unlike the global
431 + // data registry, this callback remains bound to a scoped BlockEditorProvider.
432 + if (
433 + block_section_id === wpbc_gutenberg_active_block_target.block_id &&
434 + 'function' === typeof wpbc_gutenberg_active_block_target.set_attributes
435 + ) {
436 + active_set_attributes = wpbc_gutenberg_active_block_target.set_attributes;
437 + wpbc_gutenberg_active_block_target = {
438 + block_id: '',
439 + set_attributes: null
440 + };
441 + active_set_attributes(
442 + { wpbc_shortcode: shortcode_text }
443 + );
444 + return true;
445 + }
311 446
447 + // Retain a verified fallback for editors that expose their block store in
448 + // the global registry. Do not report success unless that registry owns the
449 + // exact Booking Calendar block targeted by the configurator.
450 + if (
451 + wp.data &&
452 + ( 'function' === typeof wp.data.select ) &&
453 + ( 'function' === typeof wp.data.dispatch )
454 + ) {
455 + block_editor_select = wp.data.select( 'core/block-editor' );
456 + target_block = block_editor_select && ( 'function' === typeof block_editor_select.getBlock )
457 + ? block_editor_select.getBlock( block_section_id )
458 + : null;
459 +
460 + if ( target_block && ( 'booking/booking' === target_block.name ) ) {
461 + block_editor_dispatch = wp.data.dispatch( 'core/block-editor' );
462 + }
463 +
464 + if ( block_editor_dispatch && ( 'function' === typeof block_editor_dispatch.updateBlockAttributes ) ) {
465 + block_editor_dispatch.updateBlockAttributes(
466 + block_section_id,
467 + { wpbc_shortcode: shortcode_text }
468 + );
469 + return true;
470 + }
471 + }
472 +
473 +
312 474 // Code to insert into Gutenberg section in our text field
313 - jQuery( 'div[data-block="' + block_section_id + '"] .wpbc_gb_text_shortcode' ).val( shortcode_text );
475 + shortcode_input = jQuery( 'div[data-block="' + block_section_id + '"] .wpbc_gb_text_shortcode' );
476 + if ( ! shortcode_input.length ) {
477 + return false;
478 + }
479 + shortcode_input.val( shortcode_text );
314 480
315 481 //Its does not work for automatic generating "Edit" event :((( , so we make some workarround in Edit block event
316 - jQuery( 'div[data-block="' + block_section_id + '"] .wpbc_gb_text_shortcode' ).trigger( 'focus' ).trigger('mousedown').trigger( 'click' ).trigger('mouseup').trigger('change');
482 + shortcode_input.trigger( 'focus' ).trigger('mousedown').trigger( 'click' ).trigger('mouseup').trigger('change');
317 483
318 484 // FixIn: 8.4.2.10.
319 485 //FixIn: 8.7.3.17 href: '#!'
320 486 //FixIn: 8.7.3.19 - chnaged <a href="#!" to '<div href="#!" - its make update of block after clicking on DIV (and not A) element
@@ -699,8 +865,20 @@
699 865 { key: 'provider_id', label: wp.i18n.__( 'Preselected Provider' ), prefix: 'ID = ' },
700 866 { key: 'services', label: wp.i18n.__( 'Allowed Services' ), prefix: 'ID = ' },
701 867 { key: 'providers', label: wp.i18n.__( 'Allowed Providers' ), prefix: 'ID = ' },
702 868 { key: 'auto_select_provider', label: wp.i18n.__( 'Auto-select the only Provider' ) },
869 + { key: 'catalog_layout', label: wp.i18n.__( 'Catalog layout' ) },
870 + { key: 'show_resource_filters', label: wp.i18n.__( 'Show catalog search' ) },
871 + { key: 'show_resource_image', label: wp.i18n.__( 'Show images' ) },
872 + { key: 'show_resource_title', label: wp.i18n.__( 'Show titles' ) },
873 + { key: 'show_resource_description', label: wp.i18n.__( 'Show Service descriptions' ) },
874 + { key: 'catalog_item_width', label: wp.i18n.__( 'Catalog item width' ) },
875 + { key: 'catalog_item_max_width', label: wp.i18n.__( 'Maximum catalog item width (px)' ) },
876 + { key: 'catalog_grid_items_per_row', label: wp.i18n.__( 'Grid items per row' ) },
877 + { key: 'catalog_list_items_per_row', label: wp.i18n.__( 'List items per row' ) },
878 + { key: 'show_resource_hierarchy', label: wp.i18n.__( 'Show Service relationship' ) },
879 + { key: 'show_availability', label: wp.i18n.__( 'Show availability summary' ) },
880 + { key: 'show_starting_price', label: wp.i18n.__( 'Show starting price' ) },
703 881 { key: 'form_type', label: wp.i18n.__( 'Booking Form' ) },
704 882 { key: 'nummonths', label: wp.i18n.__( 'Visible months number' ) },
705 883 { key: 'startmonth', label: wp.i18n.__( 'Start month' ) },
706 884 { key: 'calendar_dates_start', label: wp.i18n.__( 'First calendar date' ) },
@@ -753,8 +931,20 @@
753 931 { key: 'selected_resource_id', label: wp.i18n.__( 'Preselected Booking Resource (compatibility)' ), prefix: 'ID = ' },
754 932 { key: 'selected_type', label: wp.i18n.__( 'Preselected Booking Resource (legacy)' ), prefix: 'ID = ' },
755 933 { key: 'aggregate', label: wp.i18n.__( 'Aggregate Booking Resources' ), prefix: 'ID = ' },
756 934 { key: 'auto_select_resource', label: wp.i18n.__( 'Auto-select Booking Resource' ) },
935 + { key: 'catalog_layout', label: wp.i18n.__( 'Resource layout' ) },
936 + { key: 'show_resource_filters', label: wp.i18n.__( 'Show Resource search' ) },
937 + { key: 'show_resource_image', label: wp.i18n.__( 'Show Resource image' ) },
938 + { key: 'show_resource_title', label: wp.i18n.__( 'Show Resource title' ) },
939 + { key: 'show_resource_description', label: wp.i18n.__( 'Show Resource description' ) },
940 + { key: 'catalog_item_width', label: wp.i18n.__( 'Resource item width' ) },
941 + { key: 'catalog_item_max_width', label: wp.i18n.__( 'Maximum Resource item width (px)' ) },
942 + { key: 'catalog_grid_items_per_row', label: wp.i18n.__( 'Grid items per row' ) },
943 + { key: 'catalog_list_items_per_row', label: wp.i18n.__( 'List items per row' ) },
944 + { key: 'show_resource_hierarchy', label: wp.i18n.__( 'Show Resource hierarchy' ) },
945 + { key: 'show_availability', label: wp.i18n.__( 'Show availability summary' ) },
946 + { key: 'show_starting_price', label: wp.i18n.__( 'Show starting price' ) },
757 947 { key: 'form_type', label: wp.i18n.__( 'Booking Form' ) },
758 948 { key: 'nummonths', label: wp.i18n.__( 'Visible months number' ) },
759 949 { key: 'startmonth', label: wp.i18n.__( 'Start month' ) },
760 950 { key: 'calendar_dates_start', label: wp.i18n.__( 'First calendar date' ) },
@@ -1757,9 +1947,14 @@
1757 1947 // FixIn: 8.7.3.18.
1758 1948 return [
1759 1949 el( 'h3', {className: 'wpbc_gb_block_preview_inner_title_text', key: 'h3header_' + props[ 'cid_key' ] }, props.header ),
1760 1950
1761 - el( 'a', {className: 'wpbc_gb_block_preview_inner_title_edit', key: 'a_clickedit_' + props[ 'cid_key' ] }, wp.i18n.__( 'Click to edit' ) ),
1951 + el( 'a', {
1952 + className: 'wpbc_gb_block_preview_inner_title_edit',
1953 + href: '#!',
1954 + onClick: wpbc_gutenberg_handle_preview_edit_click,
1955 + key: 'a_clickedit_' + props[ 'cid_key' ]
1956 + }, wp.i18n.__( 'Click to edit' ) ),
1762 1957
1763 1958 el( 'div', {className: 'wpbc_gb_block_preview_inner_title_desc', key: 'div_notreal_' + props[ 'cid_key' ] }, wp.i18n.__( 'This is not real preview. Its configuration block of "Booking Calendar".' ) )
1764 1959 ];
1765 1960 }
@@ -1822,5 +2017,5 @@
1822 2017 // FixIn: 8.7.3.18.
1823 2018 return [
1824 2019 el( 'div', { className: 'wpbc_gb_block_preview_inner_shortcode', key: 'div_foot_' + props[ 'cid_key' ] }, props.shortcode_in_text )
1825 2020 ];
1826 -}
2021 +}