/** * Available spaces: * * _window.$usb - Basic object for mounting and initializing all extensions of the builder * _window.$usbcore - Auxiliary functions for the builder and his extensions * _window.$ush - US Helper Library * * Note: Double underscore `__funcname` is introduced for functions that are created through `$ush.debounce(...)`. */ ! function( $, _undefined ) { const _window = window; if ( ! _window.$usb ) { return; } _window.$ush = _window.$ush || {}; _window.$usbcore = _window.$usbcore || {}; /** * @type {{}} Private temp data */ var _$tmp = { $categorySections: {}, // list section categories isLoaded: {}, // this param will be True when templates are loaded by category {id}:{status}. Example: `fn:true` }; /** * @class Templates - Functionality of importing and adding rows from provided templates * @param {String} container The container */ function Templates( container ) { const self = this; // Private "Variables" self.name = 'templates'; // Bondable events self._events = { clickTabTemplates: self._clickTabTemplates.bind( self ), expandCategory: self._expandCategory.bind( self ), } $( () => { // Elements self.$container = $( container ); self.$tabButton = $( '.usb_action_show_templates', $usb.$panel ); self.$error = $( '.usb-templates-error', self.$container ); // Events $usb.$panel .on( 'click', '.usb-template-title', self._events.expandCategory ) .on( 'click', '.usb_action_show_templates', self._events.clickTabTemplates ); } ); } // Templates API $.extend( Templates.prototype, $ush.mixinEvents, { /** * Determines if ready * * @return {Boolean} True if ready, False otherwise */ isReady: function() { return ! $ush.isUndefined( this.$container ); }, /** * Determines if show * * @return {Boolean} True if show, False otherwise */ isShow: function() { // TODO: Optimize ".is( ':visible' )" return this.$container.is( ':visible' ); }, /** * Determines whether the specified identifier is template * * @param @param {String} id Shortcode's usbid, e.g. "import_template:1" * @return {Boolean} True if the specified id is template, False otherwise */ isTemplate: function( id ) { const self = this; if ( $usb.builder.isValidId( id ) ) { id = $usb.builder.getElmType( id ); } return id === 'import_template'; }, /** * Check the config load * * @return {Boolean} Returns true if config is loaded, otherwise false */ configIsLoaded: function() { return ! $.isEmptyObject( _$tmp.$categorySections ); }, /** * Check the category is load * * @param {String} categoryId The category id * @return {Boolean} Returns true if the category is loaded, otherwise false */ categoryIsLoaded: function( categoryId ) { return _$tmp.isLoaded.hasOwnProperty( categoryId ); }, /** * Check the load of templates in the category * * @param {String} categoryId The category id * @return {Boolean} Returns true if the category templates are loaded, otherwise false */ templateIsLoaded: function( categoryId ) { return this.categoryIsLoaded( categoryId ) && _$tmp.isLoaded[ categoryId ]; }, /** * Handler for click on tab button * * @event handler */ _clickTabTemplates: function() { const self = this; // Load the config if it is not loaded if ( ! self.configIsLoaded() ) { self._loadConfig(); } // Init Drag & Drop if ( $usb.licenseIsActivated() ) { $usb.builder.initDragDrop(); } // Set the "Add Elements" button to active in the header if ( $usb.find( 'builderPanel' ) ) { $usb.builderPanel.$actionAddElms.addClass( 'active' ); } // Collapse all template categories $( '.usb-template', self.$container ).removeClass( 'expand' ); }, /** * Handler for expand category * * @event handler * @param {Event} e */ _expandCategory: function( e ) { const self = this; const categoryId = $( e.currentTarget ).parent().data( 'template-category-id' ); // If it was not possible to load the category id, then exit the method if ( ! categoryId ) { return; } // Check and preload category templates if ( $usb.licenseIsActivated() ) { self._loadTemplates( categoryId ); } // If click on an expand category, then collapse the category const $activeTemplate = $( '.usb-template.expand', self.$container ); if ( $activeTemplate.data( 'template-category-id' ) === categoryId ) { $activeTemplate.removeClass( 'expand' ); return; } /** * Show category section by categoryId * * @param {String} categoryId The category id */ function showSectionById( categoryId ) { $( '.usb-template', self.$container ) .removeClass( 'expand' ) .filter( `[data-template-category-id="${categoryId}"]` ) .addClass( 'expand' ); }; // After load show category templates if ( ! self.configIsLoaded() ) { self.one( 'configLoaded', showSectionById.bind( self, categoryId ) ); } else { showSectionById( categoryId ); } }, /** * Load templates config */ _loadConfig: function() { const self = this; if ( self.configIsLoaded() ) { return; } $usb.panel.showPreloader(); $usb.ajax( 'templates.loadConfig', { data: { _nonce: $usb.config( '_nonce' ), action: $usb.config( 'action_get_templates_config' ), }, success: ( res ) => { if ( ! res.success || ! $.isPlainObject( res.data ) ) { self.$error.addClass( 'active' ); return; } for ( categoryId in res.data ) { // If the category section is loaded then skip the iteration if ( _$tmp.$categorySections[ categoryId ] ) { continue; } // Get category section const categorySection = res.data[ categoryId ]; if ( categorySection ) { self.$container.append( categorySection ); _$tmp.$categorySections[ categoryId ] = $( categorySection ); } } self.trigger( 'configLoaded' ); }, complete: () => { $usb.panel.hidePreloader(); }, } ); }, /** * Check and preload category templates * * @param {String} categoryId The category id */ _loadTemplates: function( categoryId ) { const self = this; if ( $ush.isUndefined( categoryId ) || categoryId == '' || self.templateIsLoaded( categoryId ) ) { return; } $usb.ajax( 'templates.loadTemplates', { data:{ _nonce: $usb.config( '_nonce' ), action: $usb.config( 'action_preload_template_category' ), template_category_id: categoryId, }, success: ( res ) => { // Saved the result in any case, to understand whether there was a download or not _$tmp.isLoaded[ categoryId ] = res.success; if ( ! res.success ) { return; } // Set parameter for render shortcode start self.trigger( 'templatesLoaded', [ categoryId ] ); }, } ); }, /** * Insert template in content and preview. * * @param {String} categoryId The template category id. * @param {String} templateId The unique template id in the category. * @param {String} parentId ID of the element's parent element. * @param {Number} currentIndex Position of the element inside the parent. */ insertTemplate: function( categoryId, templateId, parentId, currentIndex ) { const self = this; // Check if the templates category id is correct if ( ! categoryId ) { $usb.log( 'Error: Template category ID is not set', args ); return; } // Check if the template id is correct if ( ! templateId ) { $usb.log( 'Error: Template ID is not set', args ); return; } // Check if the parent container is correct if ( ! $usb.builder.isMainContainer( parentId ) ) { $usb.log( 'Error: Invalid parent container, templates can only be added to mainContainer', args ); return; } const insert = $usb.builder.getInsertPosition( parentId, currentIndex ); /** * @type {Function} Get template data */ const _getTemplateData = function() { // Get html shortcode code and set on preview page $usb.postMessage( 'showPreloader', [ insert.parent, insert.position, ] ); $usb.builder.renderShortcode( 'templates.insertTemplate', { data: { template_category_id: categoryId, template_id: templateId, isReturnContent: true // returns the content for the page (shortcodes) }, success: ( res ) => { $usb.postMessage( 'hidePreloader', insert.parent ); // Check the correctness of the answer and the availability of data if ( ! res.success || ! res.data.content || ! res.data.html ) { return; } // Update IDs in content const newData = $usb.builder.updateIdsInContent( res.data.content, res.data.html ); // Adds shortcode to content if ( ! $usb.builder.insertShortcodeIntoContent( parentId, currentIndex, newData.content ) ) { return false; } // Adds new template to preview page $usb.postMessage( 'insertElm', [ insert.parent, insert.position, newData.html ] ); // Add the first row to the history and open for edit if ( $usb.builder.isRow( newData.firstElmId ) ) { // Commit to save changes to history $usb.history.commitChange( newData.firstElmId, ACTION_CONTENT.CREATE ); } // Note: A timeout is used to release the main thread. $ush.timeout( () => { $usb.builder.reloadElementsMap(); }, 0 ); $usb.trigger( 'builder.contentChange' ); } } ); }; // Determines if current category shortcodes loaded if ( ! self.templateIsLoaded( categoryId ) ) { self.off( 'templatesLoaded' ) .one( 'templatesLoaded', ( _categoryId ) => { if ( categoryId == _categoryId ) { _getTemplateData(); } } ); if ( self.categoryIsLoaded( categoryId ) ) { $usb.log( 'Error: Failed to load template category:', [ categoryId ] ); } return; } _getTemplateData(); } } ); // Export API $usb.templates = new Templates( /* container */'#usb-templates' ); } ( jQuery );