'eppro_form_nonce', 'search' => 'eppro_live_search', 'post_grid' => 'eppro_post_grid', 'popup_view' => 'eppro_popup_view', 'woo_products' => 'eppro_woo_products', ]; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- This endpoint issues nonces and performs no action. $kind = isset( $_POST['kind'] ) ? sanitize_key( wp_unslash( $_POST['kind'] ) ) : ''; if ( ! isset( $actions[ $kind ] ) ) { wp_send_json_error( [], 400 ); } nocache_headers(); wp_send_json_success( [ 'nonce' => wp_create_nonce( $actions[ $kind ] ) ] ); } /** * One badge style for the whole Elementor panel: the "EPP" mark on the * plugin's widget tiles and on every control section the plugin adds * (see EPPRO_Elementor_Helper::panel_label()). */ public static function enqueue_editor_badge(): void { $css = ' .eppro-panel-badge, #elementor-panel-category-eppro-elements .elementor-element-wrapper::after { display: inline-block; background: linear-gradient(135deg, #7c3aed, #6d28d9); color: #fff; font-size: 9px; font-weight: 700; line-height: 1.4; letter-spacing: .5px; padding: 1px 6px; border-radius: 20px; vertical-align: middle; box-shadow: 0 1px 4px rgba(124, 58, 237, .35); } .eppro-panel-badge { margin-inline-start: 4px; } #elementor-panel-category-eppro-elements .elementor-element-wrapper { position: relative; overflow: visible !important; } #elementor-panel-category-eppro-elements .elementor-element-wrapper::after { content: "EPP"; position: absolute; top: 5px; inset-inline-end: 5px; pointer-events: none; z-index: 1; } '; wp_add_inline_style( 'elementor-editor', $css ); } // ------------------------------------------------------------------------- // Register — called early so handles exist before Elementor renders // ------------------------------------------------------------------------- public static function register_all(): void { static $done = false; if ( $done ) return; $done = true; /* ── Swiper: bundled local copy (assets/vendor/swiper/) ────────────── * No CDN fallback — WordPress.org plugin guidelines prohibit loading * scripts from external CDNs without explicit user consent. * Files: swiper-bundle.min.css and swiper-bundle.min.js * Source: https://swiperjs.com (MIT licence, GPL-compatible) * ─────────────────────────────────────────────────────────────────── */ if ( ! wp_style_is( 'swiper', 'registered' ) ) { $local_css_path = EPPRO_PATH . 'assets/vendor/swiper/swiper-bundle.min.css'; if ( file_exists( $local_css_path ) ) { wp_register_style( 'swiper', EPPRO_URL . 'assets/vendor/swiper/swiper-bundle.min.css', [], '11.1' ); } else { add_action( 'admin_notices', static function () { echo '

Essential Pro Pack: ' . esc_html__( 'Missing vendor file: assets/vendor/swiper/swiper-bundle.min.css. Carousel widgets may not display correctly. Please reinstall the plugin.', 'admore-widgets-suite' ) . '

'; } ); wp_register_style( 'swiper', false, [], '11.1' ); } } if ( ! wp_script_is( 'swiper', 'registered' ) ) { $local_js_path = EPPRO_PATH . 'assets/vendor/swiper/swiper-bundle.min.js'; if ( file_exists( $local_js_path ) ) { wp_register_script( 'swiper', EPPRO_URL . 'assets/vendor/swiper/swiper-bundle.min.js', [], '11.1', true ); } else { add_action( 'admin_notices', static function () { echo '

Essential Pro Pack: ' . esc_html__( 'Missing vendor file: assets/vendor/swiper/swiper-bundle.min.js. Carousel widgets will not function. Please reinstall the plugin.', 'admore-widgets-suite' ) . '

'; } ); wp_register_script( 'swiper', false, [], '11.1', true ); } } /* ── Global shared (always loaded on any EPP page) ── */ wp_register_style( 'eppro-global', EPPRO_URL . 'assets/css/frontend.css', [], eppro_asset_ver( 'assets/css/frontend.css' ) ); wp_register_script( 'eppro-main-script', EPPRO_URL . 'assets/js/frontend.js', [ 'jquery' ], eppro_asset_ver( 'assets/js/frontend.js' ), true ); // Localise at registration so EPPRO is available wherever the script is printed. self::localize_script(); /* ── Per-widget CSS ── */ self::register_widget_style( 'eppro-btn', 'widgets/advanced-button/assets/css/style.css' ); self::register_widget_style( 'eppro-adv-faq', 'widgets/advanced-faq/assets/css/style.css' ); self::register_widget_style( 'eppro-form', 'widgets/form/assets/css/style.css' ); self::register_widget_style( 'eppro-mega-menu', 'widgets/mega-menu/assets/css/style.css' ); self::register_widget_style( 'eppro-advanced-slider', 'widgets/advanced-slider/assets/css/style.css', [ 'swiper' ] ); self::register_widget_style( 'eppro-advanced-search', 'widgets/advanced-search/assets/css/style.css' ); self::register_widget_style( 'eppro-breadcrumbs', 'widgets/breadcrumbs/assets/css/style.css' ); self::register_widget_style( 'eppro-advanced-tabs', 'widgets/advanced-tabs/assets/css/style.css' ); self::register_widget_style( 'eppro-pricing-table', 'widgets/pricing-table/assets/css/style.css' ); self::register_widget_style( 'eppro-gallery-pro', 'widgets/gallery-pro/assets/css/style.css' ); self::register_widget_style( 'eppro-post-grid', 'widgets/post-grid/assets/css/style.css' ); self::register_widget_style( 'eppro-off-canvas', 'widgets/off-canvas/assets/css/style.css' ); self::register_widget_style( 'eppro-stats-counter', 'widgets/stats-counter/assets/css/style.css' ); self::register_widget_style( 'eppro-before-after', 'widgets/before-after/assets/css/style.css' ); self::register_widget_style( 'eppro-logo-grid', 'widgets/logo-grid/assets/css/style.css', [ 'swiper' ] ); self::register_widget_style( 'eppro-team-member', 'widgets/team-member/assets/css/style.css' ); self::register_widget_style( 'eppro-icon-box', 'widgets/icon-box/style.css' ); self::register_widget_style( 'eppro-image-box', 'widgets/image-box/style.css' ); self::register_widget_style( 'eppro-timeline', 'widgets/timeline/style.css' ); /* ── New widget styles ── */ self::register_widget_style( 'eppro-fancy-heading', 'widgets/fancy-heading/style.css' ); self::register_widget_style( 'eppro-image-carousel', 'widgets/image-carousel/style.css', [ 'swiper' ] ); self::register_widget_style( 'eppro-lottie', 'widgets/lottie/style.css' ); self::register_widget_style( 'eppro-pie-chart', 'widgets/pie-chart/style.css' ); self::register_widget_style( 'eppro-author-box', 'widgets/author-box/style.css' ); self::register_widget_style( 'eppro-related-posts', 'widgets/related-posts/style.css' ); self::register_widget_style( 'eppro-google-map', 'widgets/google-map/style.css' ); self::register_widget_style( 'eppro-woo-products', 'widgets/woo-products/style.css' ); self::register_widget_style( 'eppro-woo-mini-cart', 'widgets/woo-mini-cart/style.css' ); self::register_widget_style( 'eppro-woo-add-to-cart', 'widgets/woo-add-to-cart/style.css' ); self::register_widget_style( 'eppro-post-comments', 'widgets/post-comments/style.css' ); self::register_widget_style( 'eppro-site-logo', 'widgets/site-logo/style.css' ); self::register_widget_style( 'eppro-nav-menu', 'widgets/nav-menu/style.css' ); self::register_widget_style( 'eppro-site-title', 'widgets/site-title/style.css' ); self::register_widget_style( 'eppro-site-tagline', 'widgets/site-tagline/style.css' ); self::register_widget_style( 'eppro-post-title', 'widgets/post-title/style.css' ); self::register_widget_style( 'eppro-post-content', 'widgets/post-content/style.css' ); self::register_widget_style( 'eppro-post-featured-image', 'widgets/post-featured-image/style.css' ); self::register_widget_style( 'eppro-post-excerpt', 'widgets/post-excerpt/style.css' ); self::register_widget_style( 'eppro-post-meta', 'widgets/post-meta/style.css' ); self::register_widget_style( 'eppro-archive-title', 'widgets/archive-title/style.css' ); self::register_widget_style( 'eppro-archive-description', 'widgets/archive-description/style.css' ); self::register_widget_style( 'eppro-post-navigation', 'widgets/post-navigation/style.css' ); /* ── Previously unregistered widget styles ── */ self::register_widget_style( 'eppro-animated-heading', 'widgets/animated-heading/assets/css/style.css' ); self::register_widget_style( 'eppro-countdown-timer', 'widgets/countdown-timer/assets/css/style.css' ); self::register_widget_style( 'eppro-flip-box', 'widgets/flip-box/style.css' ); self::register_widget_style( 'eppro-hotspot', 'widgets/hotspot/style.css' ); self::register_widget_style( 'eppro-price-list', 'widgets/price-list/style.css' ); self::register_widget_style( 'eppro-progress-bar', 'widgets/progress-bar/style.css' ); self::register_widget_style( 'eppro-social-icons', 'widgets/social-icons/style.css' ); self::register_widget_style( 'eppro-testimonial', 'widgets/testimonial/assets/css/style.css', [ 'swiper' ] ); self::register_widget_style( 'eppro-video', 'widgets/video/style.css' ); /* ── Per-widget JS (loaded on-demand via get_script_depends) ── */ wp_register_script( 'eppro-form-script', EPPRO_URL . 'widgets/form/assets/js/form.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/form/assets/js/form.js' ), true ); wp_register_script( 'eppro-mega-menu-script', EPPRO_URL . 'widgets/mega-menu/assets/js/mega-menu.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/mega-menu/assets/js/mega-menu.js' ), true ); wp_register_script( 'eppro-faq-script', EPPRO_URL . 'widgets/advanced-faq/assets/js/faq.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/advanced-faq/assets/js/faq.js' ), true ); wp_register_script( 'eppro-extensions', EPPRO_URL . 'assets/js/extensions.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'assets/js/extensions.js' ), true ); wp_register_script( 'eppro-advanced-slider-script', EPPRO_URL . 'widgets/advanced-slider/assets/js/slider.js', [ 'jquery', 'swiper', 'eppro-main-script' ], eppro_asset_ver( 'widgets/advanced-slider/assets/js/slider.js' ), true ); wp_register_script( 'eppro-advanced-search-script', EPPRO_URL . 'widgets/advanced-search/assets/js/search.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/advanced-search/assets/js/search.js' ), true ); wp_register_script( 'eppro-advanced-tabs', EPPRO_URL . 'widgets/advanced-tabs/assets/js/tabs.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/advanced-tabs/assets/js/tabs.js' ), true ); wp_register_script( 'eppro-pricing-table-script', EPPRO_URL . 'widgets/pricing-table/assets/js/pricing.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/pricing-table/assets/js/pricing.js' ), true ); wp_register_script( 'eppro-gallery-pro-script', EPPRO_URL . 'widgets/gallery-pro/assets/js/gallery.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/gallery-pro/assets/js/gallery.js' ), true ); wp_register_script( 'eppro-post-grid-script', EPPRO_URL . 'widgets/post-grid/assets/js/post-grid.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/post-grid/assets/js/post-grid.js' ), true ); wp_register_script( 'eppro-off-canvas', EPPRO_URL . 'widgets/off-canvas/assets/js/script.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/off-canvas/assets/js/script.js' ), true ); wp_register_script( 'eppro-stats-counter', EPPRO_URL . 'widgets/stats-counter/assets/js/script.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/stats-counter/assets/js/script.js' ), true ); wp_register_script( 'eppro-before-after', EPPRO_URL . 'widgets/before-after/assets/js/script.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/before-after/assets/js/script.js' ), true ); wp_register_script( 'eppro-logo-grid', EPPRO_URL . 'widgets/logo-grid/assets/js/script.js', [ 'jquery', 'swiper', 'eppro-main-script' ], eppro_asset_ver( 'widgets/logo-grid/assets/js/script.js' ), true ); wp_register_script( 'eppro-timeline-script', EPPRO_URL . 'widgets/timeline/script.js', [], eppro_asset_ver( 'widgets/timeline/script.js' ), true ); /* ── New widget scripts ── */ wp_register_script( 'eppro-image-carousel-script', EPPRO_URL . 'widgets/image-carousel/script.js', [ 'swiper' ], eppro_asset_ver( 'widgets/image-carousel/script.js' ), true ); // lottie-web: MIT licensed, bundled locally (see assets/vendor/lottie/README.txt) wp_register_script( 'lottie-web', EPPRO_URL . 'assets/vendor/lottie/lottie.min.js', [], '5.12.2', true ); wp_register_script( 'eppro-lottie-script', EPPRO_URL . 'widgets/lottie/script.js', [ 'lottie-web' ], eppro_asset_ver( 'widgets/lottie/script.js' ), true ); wp_register_script( 'eppro-pie-chart-script', EPPRO_URL . 'widgets/pie-chart/script.js', [], eppro_asset_ver( 'widgets/pie-chart/script.js' ), true ); wp_register_script( 'eppro-woo-mini-cart-script', EPPRO_URL . 'widgets/woo-mini-cart/script.js', [ 'jquery' ], eppro_asset_ver( 'widgets/woo-mini-cart/script.js' ), true ); wp_register_script( 'eppro-nav-menu-script', EPPRO_URL . 'widgets/nav-menu/script.js', [ 'jquery' ], eppro_asset_ver( 'widgets/nav-menu/script.js' ), true ); wp_register_script( 'eppro-team-member-script', EPPRO_URL . 'widgets/team-member/assets/js/script.js', [], eppro_asset_ver( 'widgets/team-member/assets/js/script.js' ), true ); wp_register_script( 'eppro-woo-products-script', EPPRO_URL . 'widgets/woo-products/script.js', [ 'jquery', 'eppro-main-script' ], eppro_asset_ver( 'widgets/woo-products/script.js' ), true ); wp_localize_script( 'eppro-woo-products-script', 'epproWooProducts', [ 'close' => __( 'Close', 'admore-widgets-suite' ), 'loading' => __( 'Loading…', 'admore-widgets-suite' ), 'error' => __( 'Sorry, this product could not be loaded.', 'admore-widgets-suite' ), ] ); /* ── Previously unregistered widget scripts ── */ wp_register_script( 'eppro-animated-heading-script', EPPRO_URL . 'widgets/animated-heading/assets/js/animated-heading.js', [], eppro_asset_ver( 'widgets/animated-heading/assets/js/animated-heading.js' ), true ); wp_register_script( 'eppro-countdown-timer-script', EPPRO_URL . 'widgets/countdown-timer/assets/js/countdown.js', [], eppro_asset_ver( 'widgets/countdown-timer/assets/js/countdown.js' ), true ); wp_register_script( 'eppro-progress-bar-script', EPPRO_URL . 'widgets/progress-bar/script.js', [], eppro_asset_ver( 'widgets/progress-bar/script.js' ), true ); wp_register_script( 'eppro-testimonial-script', EPPRO_URL . 'widgets/testimonial/assets/js/testimonial.js', [ 'jquery', 'swiper' ], eppro_asset_ver( 'widgets/testimonial/assets/js/testimonial.js' ), true ); wp_register_script( 'eppro-hotspot-script', EPPRO_URL . 'widgets/hotspot/script.js', [ 'jquery' ], eppro_asset_ver( 'widgets/hotspot/script.js' ), true ); wp_register_script( 'eppro-video-script', EPPRO_URL . 'widgets/video/script.js', [ 'jquery' ], eppro_asset_ver( 'widgets/video/script.js' ), true ); // Defer scroll-triggered / visual-enhancement scripts (WP 6.3+ strategy API). // These are purely progressive-enhancement — deferring them frees the main // thread earlier without any visible impact. $defer_scripts = [ 'eppro-stats-counter', 'eppro-pie-chart-script', 'eppro-lottie-script', 'eppro-timeline-script', 'eppro-team-member-script', ]; foreach ( $defer_scripts as $handle ) { wp_script_add_data( $handle, 'strategy', 'defer' ); } } // ------------------------------------------------------------------------- // Enqueue global assets (only on pages where Elementor frontend renders) // ------------------------------------------------------------------------- public static function enqueue_global(): void { static $done = false; if ( $done ) return; $done = true; self::register_all(); wp_enqueue_style( 'eppro-global' ); wp_enqueue_script( 'eppro-main-script' ); wp_enqueue_script( 'eppro-extensions' ); self::add_customizer_inline_css(); } // ------------------------------------------------------------------------- // Helpers // ------------------------------------------------------------------------- private static function register_widget_style( string $handle, string $relative_path, array $deps = [] ): void { $full_deps = array_merge( [ 'eppro-global' ], $deps ); wp_register_style( $handle, EPPRO_URL . $relative_path, $full_deps, eppro_asset_ver( $relative_path ) ); } /** * Public data for the frontend. Never add plugin settings here: this is * printed on every page, and the settings contain the CAPTCHA secret key. */ private static function localize_script(): void { wp_localize_script( 'eppro-main-script', 'EPPRO', [ 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'homeUrl' => trailingslashit( home_url() ), ] ); } private static function add_customizer_inline_css(): void { $custom = class_exists( 'EPPRO_Customizer' ) ? EPPRO_Customizer::get_settings() : []; if ( empty( $custom ) ) return; $css = ':root{'; $map = [ 'input_bg' => '--eppro-input-bg', 'input_color' => '--eppro-input-color', 'btn_bg' => '--eppro-btn-bg', 'btn_color' => '--eppro-btn-color', 'card_bg' => '--eppro-card-bg', ]; foreach ( $map as $key => $var ) { if ( ! empty( $custom[ $key ] ) ) { $css .= $var . ':' . esc_attr( $custom[ $key ] ) . ';'; } } if ( ! empty( $custom['radius'] ) ) { $css .= '--eppro-radius:' . intval( $custom['radius'] ) . 'px;'; } $css .= '}'; wp_add_inline_style( 'eppro-global', wp_strip_all_tags( $css ) ); } }