set_key( "_tve_js_modules$key" ); } public function __construct( $post_id ) { $this->ID = $post_id; } /** * Set meta key for reading/writing modules * * @param $key * * @return $this */ public function set_key( $key ) { $this->key = $key; return $this; } /** * Save js modules that are used in this post * * @param array $modules Array of modules */ public function save_js_modules( $modules = [] ) { if ( ! is_array( $modules ) ) { $modules = []; } update_post_meta( $this->ID, $this->key, $modules ); } public function enqueue_scripts() { /* enqueue general file with the base functionality */ tve_enqueue_script( 'tve_frontend', tve_editor_js() . '/modules/general' . \TCB_Utils::get_js_suffix(), [ 'jquery', 'jquery-ui-autocomplete', 'jquery-masonry', ] ); $this->load_modules(); } /** * Load js modules needed for the current post, or all of them if it was not optimized * * @param false $return_inline * * @return string */ public function load_modules( $return_inline = false ) { $js_modules = ''; $modules_to_load = $this->get_modules_to_load(); foreach ( $modules_to_load as $module ) { $js_modules .= JSModule::get_instance( $module, static::get_module_data( $module, 'libraries' ) )->load( $return_inline ); } do_action( 'tve_lightspeed_enqueue_module_scripts', $this->ID, $modules_to_load ); return $js_modules; } /** * Return urls for the modules we have to load * * @return array|array[] */ public function get_modules_urls() { $modules_to_load = $this->get_modules_to_load(); return JS::get_js_urls( $modules_to_load ); } /** * Return urls for an array of modules * * @return array|array[] */ public static function get_js_urls( $modules ) { $urls = []; if ( is_array( $modules ) ) { foreach ( $modules as $module ) { $urls = array_merge( $urls, static::get_module_data( $module, 'libraries' ) ); $urls[ $module ] = JSModule::get_instance( $module, [] )->get_url(); } } return $urls; } public function has_optimized_modules() { return empty( $_GET['force-all-js'] ) && Main::is_enabled() && ! is_editor_page_raw() && /* never optimize editor JS */ metadata_exists( 'post', $this->ID, $this->key ); /* make sure the meta is set */ } public function get_modules_to_load() { if ( $this->has_optimized_modules() ) { if ( empty( $this->modules ) ) { $this->modules = get_post_meta( $this->ID, $this->key, true ); if ( empty( $this->modules ) || ! is_array( $this->modules ) ) { $this->modules = []; } if ( ! empty( $this->modules ) ) { $this->load_module_dependencies(); } $this->include_post_format_modules(); } } else if ( Main::requires_architect_assets( $this->ID ) || Main::has_architect_content( $this->ID ) ) { /* load all modules */ $this->modules = array_keys( static::get_module_data() ); if ( ! empty( $this->modules ) ) { $this->load_module_dependencies(); } } else { $this->modules = []; } return $this->modules; } /** * Each module can have other modules as dependencies, and through this function they are also added to the module list */ public function load_module_dependencies() { /* load the dependencies for each module */ foreach ( $this->modules as $module ) { $dependencies = static::get_module_data( $module, 'dependencies' ); foreach ( $dependencies as $dependency ) { $this->add_module( $dependency ); } } } /** * If this post has an audio/video format, add that JS file to the modules that we're loading ( if it's not already included ) */ public function include_post_format_modules() { $post_format = get_post_format( $this->ID ); if ( ! empty( $post_format ) && in_array( $post_format, [ 'audio', 'video' ], true ) ) { $this->add_module( $post_format ); } } /** * @param $module_to_add */ public function add_module( $module_to_add ) { if ( ! in_array( $module_to_add, $this->modules, true ) ) { $this->modules[] = $module_to_add; } } //todo add more modules, including 'general', which depends on buttons, content boxes, etc public static function get_module_data( $module = '', $key = '' ) { $data = [ 'acf-dynamic-elements' => [ /** * '.tcb-custom-field-source' is the general ACF class * [data-tar-shortcode-attr] is for some frontend json parsing * a[data-shortcode-id^="acf_"] is for checking ACF shortcode links */ 'identifier' => '.tcb-custom-field-source,[data-tar-shortcode-attr],a[data-shortcode-id^="acf_"]', ], 'audio' => [ 'identifier' => '.thrv_audio', ], 'carousel' => [ 'identifier' => '[data-type="carousel"]', 'libraries' => [ 'carousel-libs' => tve_editor_js( '/carousel-libs' . \TCB_Utils::get_js_suffix() ), ], ], /* this is the old contact form element which is no longer visible in the sidebar, but still has frontend JS */ 'contact-form-compat' => [ 'identifier' => '.thrv-contact-form', ], 'content-reveal' => [ 'identifier' => '.thrv_content_reveal', ], 'countdown' => [ 'identifier' => '.tve-countdown', ], 'conditional-display' => [ 'identifier' => '[data-display-group]', ], 'search-form' => [ 'identifier' => '.thrv-search-form', ], 'dropdown' => [ 'identifier' => '.tve_lg_dropdown, .tve_lg_state, .tcb-form-dropdown, .tve-dynamic-dropdown', ], 'country' => [ 'identifier' => '.tve_lg_country', ], 'state' => [ 'identifier' => '.tve_lg_state', ], 'datepicker' => [ 'identifier' => '.lg-date-picker', 'libraries' => [ 'date-picker' => tve_editor_js( '/date-picker' . \TCB_Utils::get_js_suffix() ), ], ], 'divider' => [ 'identifier' => '.thrv-divider', ], 'file-upload' => [ 'identifier' => '.tve_lg_file', 'libraries' => [ 'moxie' => includes_url() . 'js/plupload/moxie.min.js', 'plupload' => includes_url() . 'js/plupload/plupload.min.js', ], ], 'avatar-picker' => [ 'identifier' => '.tve-avatar-picker-element', 'dependencies' => [ 'google-api', 'facebook-api', 'modal' ], 'libraries' => [ 'google-client' => 'https://accounts.google.com/gsi/client', 'google-api' => 'https://apis.google.com/js/api.js', ], ], 'fill-counter' => [ 'identifier' => '.thrv-fill-counter', ], 'number-counter' => [ 'identifier' => '.tve-number-counter', ], 'image-gallery' => [ 'identifier' => '.tcb-image-gallery', 'libraries' => [ 'image-gallery-libs' => tve_editor_js( '/image-gallery-libs.min.js' ), ], 'dependencies' => [ 'carousel' ], ], 'lead-generation' => [ 'identifier' => '.thrv_lead_generation', 'dependencies' => [ 'dropdown' ], ], 'login' => [ 'identifier' => '.thrv-login-element', 'dependencies' => [ 'lead-generation' ], ], 'menu' => [ 'identifier' => '.thrv_widget_menu', ], 'number-counter-compat' => [ 'identifier' => '.thrv_number_counter', ], 'post-grid-compat' => [ 'identifier' => '.thrv_post_grid', ], 'pagination' => [ 'identifier' => '.tcb-pagination', 'dependencies' => [ 'post-list' ], ], 'post-list' => [ 'identifier' => '.tcb-post-list, .tva-course-list, .thrive-display-testimonials', 'dependencies' => [ 'post-grid-compat', 'dropdown' ], ], 'post-list-filter' => [ 'identifier' => '.tcb-post-list-filter', ], 'pricing-table' => [ 'identifier' => '.thrv-pricing-table', ], 'progress-bar' => [ 'identifier' => '.tve-progress-bar-wrapper', ], 'social-share' => [ 'identifier' => '.thrv_social_custom,.tve_social_custom', ], 'table' => [ 'identifier' => '.thrv_table', ], 'tabs' => [ 'identifier' => '.thrv_tabs_shortcode, .thrv-tabbed-content', ], 'timer' => [ 'identifier' => '.thrv-countdown_timer_evergreen,.tve_countdown_timer_evergreen,.thrv-countdown_timer_plain,.thrv_countdown_timer', ], 'toc' => [ 'identifier' => '.tve-toc, .thrv_contents_table', /* thrv_contents_table is the old TOC */ ], 'toggle' => [ 'identifier' => '.thrv_toggle, .thrv_toggle_shortcode', ], 'twitter' => [ 'identifier' => '.thrv_tw_qs', ], 'user-profile' => [ 'identifier' => '.tve-user-profile', ], 'video' => [ 'identifier' => '.thrv_responsive_video, .tcb-responsive-video, .tcb-video-background-el', ], ]; if ( ! empty( $key ) ) { $data = array_map( static function ( $item ) use ( $key ) { return empty( $item[ $key ] ) ? [] : $item[ $key ]; }, $data ); } if ( ! empty( $module ) ) { $data = isset( $data[ $module ] ) ? $data[ $module ] : []; } return $data; } /** * these libraries are enqueued from wordpress, so we don't have to do it ourselves; however, when printing inline, they still have to be printed */ const LIBRARIES_ENQUEUED_AUTOMATICALLY = [ 'moxie' ]; }