/** * BFB Publish modal controller. * * Responsibilities: * - Open Publish modal from toolbar button. * - Support legacy inline call: wpbc_modal_dialog__show__resource_publish( resource_id ). * - Keep shortcode in sync with current form name. * - Ask user to save current form before publishing. * - Publish shortcode into existing/new page via AJAX. * - Show success/error message without page reload. * * @package Booking Calendar * @subpackage Booking Form Builder * @since 11.0.0 * @file ../includes/page-form-builder/publish/_out/bfb-publish.js */ (function ( $, window, document ) { 'use strict'; var publish_api = { /** * Init module. * * @return void */ init: function() { this.bind_events(); this.bind_form_ajax_loaded_events(); this.register_global_helpers(); this.refresh_publish_button_shortcodes( this.get_current_form_name() ); }, /** * Get localized vars. * * @return {Object} */ get_vars: function() { return window.wpbc_bfb_publish_vars || {}; }, /** * Get i18n vars. * * @return {Object} */ get_i18n: function() { var vars = this.get_vars(); return vars.i18n || {}; }, /** * Get modal jQuery object. * * @return {jQuery} */ get_modal: function() { var vars = this.get_vars(); var selector = vars.modal_selector || '#wpbc_bfb_modal__publish'; return $( selector ); }, /** * Sanitize form name similar to WP sanitize_key(). * * @param {string} form_name Form name. * * @return {string} */ sanitize_form_name: function( form_name ) { form_name = String( form_name || '' ).toLowerCase(); form_name = form_name.replace( /[^a-z0-9_-]/g, '' ); if ( ! form_name ) { form_name = this.get_vars().default_form_name || 'standard'; } return form_name; }, /** * Normalize resource ID. * * @param {number|string} resource_id Resource ID. * * @return {number} */ normalize_resource_id: function( resource_id ) { resource_id = parseInt( resource_id, 10 ); if ( ! resource_id || resource_id < 1 ) { resource_id = parseInt( this.get_vars().default_resource_id || 1, 10 ); } if ( ! resource_id || resource_id < 1 ) { resource_id = 1; } return resource_id; }, /** * Get current BFB form name. * * @return {string} */ get_current_form_name: function() { var vars = this.get_vars(); var form_name = ''; if ( window.WPBC_BFB_Ajax && window.WPBC_BFB_Ajax.form_name ) { form_name = window.WPBC_BFB_Ajax.form_name; } if ( ! form_name && vars.default_form_name ) { form_name = vars.default_form_name; } return this.sanitize_form_name( form_name || 'standard' ); }, /** * Build default shortcode raw. * * @param {number|string} resource_id Resource ID. * @param {string} form_name Form name. * * @return {string} */ build_default_shortcode_raw: function( resource_id, form_name ) { resource_id = this.normalize_resource_id( resource_id ); form_name = this.sanitize_form_name( form_name ); return "[booking resource_id=" + resource_id + " form_type='" + form_name + "']"; }, /** * Upsert one shortcode attribute. * * @param {string} shortcode_raw Shortcode. * @param {string} attr_name Attribute name. * @param {string} attr_value Attribute value. * @param {string} quote_char Quote char. * * @return {string} */ upsert_shortcode_attr: function( shortcode_raw, attr_name, attr_value, quote_char ) { var escaped_attr_name, pattern, replacement_value, replacement; shortcode_raw = trim_string( shortcode_raw ); attr_name = String( attr_name || '' ); attr_value = String( attr_value || '' ); quote_char = String( quote_char || '' ); if ( ! attr_name ) { return shortcode_raw; } replacement_value = attr_value; if ( quote_char ) { replacement_value = quote_char + attr_value + quote_char; } replacement = attr_name + '=' + replacement_value; escaped_attr_name = attr_name.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); pattern = new RegExp( "\\b" + escaped_attr_name + "\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^\\s\\]]+)", 'i' ); if ( pattern.test( shortcode_raw ) ) { return shortcode_raw.replace( pattern, replacement ); } if ( /\]$/.test( shortcode_raw ) ) { return shortcode_raw.replace( /\]$/, ' ' + replacement + ']' ); } return shortcode_raw + ' ' + replacement; }, /** * Normalize shortcode to current resource + form type. * * @param {string} shortcode_raw Shortcode. * @param {number|string} resource_id Resource ID. * @param {string} form_name Form name. * * @return {string} */ normalize_shortcode_raw: function( shortcode_raw, resource_id, form_name ) { resource_id = this.normalize_resource_id( resource_id ); form_name = this.sanitize_form_name( form_name ); shortcode_raw = trim_string( shortcode_raw ); if ( ( ! shortcode_raw || 0 !== shortcode_raw.indexOf( '[booking' ) ) ) { return this.build_default_shortcode_raw( resource_id, form_name ); } shortcode_raw = this.upsert_shortcode_attr( shortcode_raw, 'resource_id', String( resource_id ), '' ); shortcode_raw = this.upsert_shortcode_attr( shortcode_raw, 'form_type', form_name, '\'' ); return trim_string( shortcode_raw ); }, /** * Refresh toolbar button shortcode attributes. * * @param {string} form_name Form name. * * @return void */ refresh_publish_button_shortcodes: function( form_name ) { var self = this; var vars = this.get_vars(); var $buttons = $( '[data-wpbc-bfb-top-publish-btn="1"]' ); form_name = this.sanitize_form_name( form_name ); $buttons.each( function() { var $button = $( this ); var resource_id = self.normalize_resource_id( $button.attr( 'data-wpbc-bfb-resource-id' ) || vars.default_resource_id || 1 ); var shortcode_raw = $button.attr( 'data-wpbc-bfb-shortcode-raw' ) || vars.default_shortcode_raw || ''; shortcode_raw = self.normalize_shortcode_raw( shortcode_raw, resource_id, form_name ); $button.attr( 'data-wpbc-bfb-shortcode-raw', shortcode_raw ); $button.attr( 'data-wpbc-bfb-form-name', form_name ); } ); }, /** * Keep publish shortcode in sync after AJAX form load. * * @return void */ bind_form_ajax_loaded_events: function() { var self = this; if ( window.__wpbc_bfb_publish__form_ajax_loaded_bound === '1' ) { return; } window.__wpbc_bfb_publish__form_ajax_loaded_bound = '1'; document.addEventListener( 'wpbc:bfb:form:ajax_loaded', function( ev ) { var detail = ( ev && ev.detail ) ? ev.detail : {}; var form_name = self.sanitize_form_name( detail.form_name || self.get_current_form_name() ); var $modal = self.get_modal(); var resource_id, shortcode_raw; window.WPBC_BFB_Ajax = window.WPBC_BFB_Ajax || {}; window.WPBC_BFB_Ajax.form_name = form_name; self.refresh_publish_button_shortcodes( form_name ); if ( $modal.length ) { resource_id = $modal.find( '#wpbc_bfb_publish__resource_id' ).val() || self.get_vars().default_resource_id || 1; shortcode_raw = $modal.find( '#wpbc_bfb_publish__shortcode_raw' ).val() || self.get_vars().default_shortcode_raw || ''; $modal.find( '#wpbc_bfb_publish__form_name' ).val( form_name ); $modal.find( '#wpbc_bfb_publish__shortcode_raw' ).val( self.normalize_shortcode_raw( shortcode_raw, resource_id, form_name ) ); } }, { passive: true } ); }, /** * Bind DOM events. * * @return void */ bind_events: function() { var self = this; $( document ).on( 'click', '[data-wpbc-bfb-top-publish-btn="1"]', function( event ) { self.open_from_button( event, $( this ) ); } ); $( document ).on( 'click', '[data-wpbc-bfb-publish-save-step="save"]', function( event ) { self.start_save_and_continue( event, $( this ) ); } ); $( document ).on( 'click', '[data-wpbc-bfb-publish-save-step="skip"]', function( event ) { event.preventDefault(); self.show_chooser_step(); } ); $( document ).on( 'click', '[data-wpbc-bfb-publish-mode]', function( event ) { self.open_mode_panel( event, $( this ).attr( 'data-wpbc-bfb-publish-mode' ) ); } ); $( document ).on( 'click', '[data-wpbc-bfb-publish-submit]', function( event ) { self.submit_publish( event, $( this ).attr( 'data-wpbc-bfb-publish-submit' ) ); } ); $( document ).on( 'click', '[data-wpbc-bfb-publish-back="1"]', function( event ) { self.go_back( event ); } ); }, /** * Register global helpers for backward compatibility. * * @return void */ register_global_helpers: function() { var self = this; window.wpbc_bfb_publish__open = function( resource_id, shortcode_raw ) { self.open_modal( resource_id, shortcode_raw ); }; window.wpbc_modal_dialog__show__resource_publish = function( resource_id ) { self.open_modal( resource_id, '' ); }; }, /** * Reset modal to default state. * * @return void */ reset_modal: function() { var $modal = this.get_modal(); if ( ! $modal.length ) { return; } $modal.find( '.wpbc_bfb_publish__notice' ).html( '' ); $modal.find( '.wpbc_bfb_publish__save_step' ).hide(); $modal.find( '.wpbc_bfb_publish__chooser' ).hide(); $modal.find( '.wpbc_bfb_publish__panel' ).hide(); $modal.find( '.modal-footer' ).hide(); $modal.find( '.wpbc_bfb_publish__result_actions' ).hide(); $modal.find( '[data-wpbc-bfb-publish-open-page="1"]' ).hide().attr( 'href', '#' ); $modal.find( '[data-wpbc-bfb-publish-edit-page="1"]' ).hide().attr( 'href', '#' ); }, /** * Show initial save step. * * @return void */ show_save_step: function() { var $modal = this.get_modal(); if ( ! $modal.length ) { return; } $modal.find( '.wpbc_bfb_publish__chooser' ).hide(); $modal.find( '.wpbc_bfb_publish__panel' ).hide(); $modal.find( '.wpbc_bfb_publish__result_actions' ).hide(); $modal.find( '.wpbc_bfb_publish__save_step' ).show(); $modal.find( '.modal-footer' ).hide(); }, /** * Show chooser step. * * @return void */ show_chooser_step: function() { var $modal = this.get_modal(); if ( ! $modal.length ) { return; } $modal.find( '.wpbc_bfb_publish__notice' ).html( '' ); $modal.find( '.wpbc_bfb_publish__save_step' ).hide(); $modal.find( '.wpbc_bfb_publish__panel' ).hide(); $modal.find( '.wpbc_bfb_publish__result_actions' ).hide(); $modal.find( '.wpbc_bfb_publish__chooser' ).show(); $modal.find( '.modal-footer' ).show(); }, /** * Open modal from toolbar button. * * @param {Object} event Click event. * @param {jQuery} $button Button. * * @return void */ open_from_button: function( event, $button ) { var vars = this.get_vars(); var resource_id; var shortcode_raw; var form_name; event.preventDefault(); resource_id = $button.attr( 'data-wpbc-bfb-resource-id' ) || vars.default_resource_id || 1; form_name = this.get_current_form_name(); shortcode_raw = $button.attr( 'data-wpbc-bfb-shortcode-raw' ) || vars.default_shortcode_raw || ''; shortcode_raw = this.normalize_shortcode_raw( shortcode_raw, resource_id, form_name ); $button.attr( 'data-wpbc-bfb-shortcode-raw', shortcode_raw ); $button.attr( 'data-wpbc-bfb-form-name', form_name ); this.open_modal( resource_id, shortcode_raw ); }, /** * Open modal. * * @param {number|string} resource_id Resource ID. * @param {string} shortcode_raw Shortcode. * * @return void */ open_modal: function( resource_id, shortcode_raw ) { var $modal = this.get_modal(); var vars = this.get_vars(); var form_name; if ( ! $modal.length ) { return; } resource_id = this.normalize_resource_id( resource_id || vars.default_resource_id || 1 ); form_name = this.get_current_form_name(); shortcode_raw = this.normalize_shortcode_raw( shortcode_raw || vars.default_shortcode_raw || '', resource_id, form_name ); this.reset_modal(); $modal.find( '#wpbc_bfb_publish__resource_id' ).val( resource_id ); $modal.find( '#wpbc_bfb_publish__form_name' ).val( form_name ); $modal.find( '#wpbc_bfb_publish__shortcode_raw' ).val( shortcode_raw ); $modal.find( '#wpbc_bfb_publish_page_title' ).val( '' ); $modal.find( '#wpbc_bfb_publish_page_id' ).val( '0' ); if ( typeof $modal.wpbc_my_modal === 'function' ) { $modal.wpbc_my_modal( 'show' ); } else { $modal.show(); } if ( parseInt( vars.is_demo || 0, 10 ) !== 1 ) { this.show_save_step(); } }, /** * Open selected mode panel. * * @param {Object} event Click event. * @param {string} mode Mode. * * @return void */ open_mode_panel: function( event, mode ) { var $modal = this.get_modal(); event.preventDefault(); if ( ! $modal.length ) { return; } $modal.find( '.wpbc_bfb_publish__notice' ).html( '' ); $modal.find( '.wpbc_bfb_publish__save_step' ).hide(); $modal.find( '.wpbc_bfb_publish__chooser' ).hide(); $modal.find( '.wpbc_bfb_publish__panel' ).hide(); $modal.find( '.wpbc_bfb_publish__panel--' + mode ).show(); $modal.find( '.modal-footer' ).show(); $modal.find( '.wpbc_bfb_publish__result_actions' ).hide(); }, /** * Return from current step. * * @param {Object} event Click event. * * @return void */ go_back: function( event ) { var $modal = this.get_modal(); event.preventDefault(); if ( ! $modal.length ) { return; } $modal.find( '.wpbc_bfb_publish__notice' ).html( '' ); $modal.find( '.wpbc_bfb_publish__result_actions' ).hide(); if ( $modal.find( '.wpbc_bfb_publish__panel:visible' ).length ) { this.show_chooser_step(); return; } if ( $modal.find( '.wpbc_bfb_publish__chooser:visible' ).length ) { this.show_save_step(); return; } this.show_save_step(); }, /** * Render notice inside modal. * * @param {string} type success | error | info * @param {string} message Message HTML. * * @return void */ render_notice: function( type, message ) { var $modal = this.get_modal(); var css_class = 'notice-info'; if ( ! $modal.length ) { return; } if ( 'success' === type ) { css_class = 'notice-success'; } else if ( 'error' === type ) { css_class = 'notice-error'; } $modal.find( '.wpbc_bfb_publish__notice' ).html( '