Changeset 3380762
- Timestamp:
- 10/19/2025 10:40:44 AM (4 months ago)
- Location:
- popup-for-elementor
- Files:
-
- 8 edited
- 1 copied
-
tags/1.5.8 (copied) (copied from popup-for-elementor/trunk)
-
tags/1.5.8/assets/popup-widget.js (modified) (8 diffs)
-
tags/1.5.8/includes/editor-options.php (modified) (1 diff)
-
tags/1.5.8/popup-for-elementor.php (modified) (2 diffs)
-
tags/1.5.8/readme.txt (modified) (3 diffs)
-
trunk/assets/popup-widget.js (modified) (8 diffs)
-
trunk/includes/editor-options.php (modified) (1 diff)
-
trunk/popup-for-elementor.php (modified) (2 diffs)
-
trunk/readme.txt (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
popup-for-elementor/tags/1.5.8/assets/popup-widget.js
r3300275 r3380762 5 5 const cookieExpiry = parseInt(config.cookieExpiry, 10) || 7; 6 6 const delayInMilliseconds = parseInt(config.delay, 10) || 0; 7 const isSelectorMode = (config.triggerBySelector === 'yes' && config.triggerSelector && config.triggerSelector.trim() !== ''); 8 7 9 let isClosing = false; 8 10 let popupOpenedAt = 0; // marca de última apertura (ms) 11 let lastExitTs = 0; // anti-rebote de exit-intent (ms) 12 const EXIT_COOLDOWN_MS = 1200; 13 9 14 const $popupOverlay = $('.popup-overlay'); 10 15 const $popupContent = $popupOverlay.find('.popup-content'); … … 44 49 45 50 console.log("Showing popup."); 51 popupOpenedAt = Date.now(); 46 52 $popupOverlay.css({ 47 53 display: 'flex', … … 59 65 function closePopup() { 60 66 console.log("Attempting to close popup..."); 67 68 if (popupOpenedAt && (Date.now() - popupOpenedAt) < 250) { 69 console.log("Close ignored due to debounce after open."); 70 return; 71 } 72 61 73 if (isClosing) { 62 74 console.log("Popup is already closing. Aborting."); 63 75 return; 64 76 } 65 77 66 78 isClosing = true; 67 79 console.log("Closing popup..."); 68 80 81 let handled = false; 69 82 $popupContent 70 .removeClass('animate__fadeIn') 71 .addClass('animate__fadeOut') 72 .one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function () { 83 .removeClass('animate__fadeIn') 84 .addClass('animate__fadeOut') 85 .one('animationend', function (e) { 86 if (handled) return; 87 if (e.target !== this) return; 88 handled = true; 89 73 90 console.log("Fade-out animation ended. Hiding popup."); 74 91 $popupOverlay.css({ … … 77 94 opacity: 0, 78 95 }); 79 $popupContent.removeClass('animate__fadeOut'); 80 isClosing = false; 96 $popupContent.removeClass('animate__fadeOut'); 97 isClosing = false; 81 98 console.log("Popup closed successfully."); 82 99 }); 83 100 84 101 setTimeout(() => { 85 if ( isClosing) {102 if (!handled) { 86 103 console.warn("Fallback triggered: Forcing popup closure."); 104 handled = true; 87 105 $popupOverlay.css({ 88 106 display: 'none', … … 91 109 }); 92 110 $popupContent.removeClass('animate__fadeOut'); 93 isClosing = false; 94 } 95 }, 500); 96 } 111 isClosing = false; 112 } 113 }, 700); 114 } 115 97 116 98 117 function handlePopupDisplay() { … … 122 141 if (config.exitIntent === 'yes') { 123 142 console.log("IntentExit habilitado."); 143 124 144 $(document).on('mouseleave', function (e) { 125 console.log(`Intento de salida detectado: clientY = ${e.clientY}`); 126 if (e.clientY < 0) { 145 const now = Date.now(); 146 const nearTop = (e.clientY <= 0 || e.clientY <= 20); 147 const leavingWindow = (e.relatedTarget === null); 148 149 console.log(`Intento de salida: clientY=${e.clientY}, nearTop=${nearTop}, leaving=${leavingWindow}`); 150 151 if (config.exitIntentDisplayMode === 'once' && getCookie(cookieName)) { 152 console.log('ExitIntent en modo "once" y cookie presente. No se muestra.'); 153 return; 154 } 155 156 if (isClosing || (popupOpenedAt && (now - popupOpenedAt) < 250)) { 157 console.log('Ignorado: está cerrando o se acaba de abrir.'); 158 return; 159 } 160 161 if (now - lastExitTs < EXIT_COOLDOWN_MS) { 162 console.log('Cooldown activo. Ignorando ExitIntent repetido.'); 163 return; 164 } 165 166 if (nearTop || leavingWindow) { 167 lastExitTs = now; 127 168 console.log("Mostrando popup por IntentExit."); 128 169 showPopup(); 170 171 if (config.exitIntentDisplayMode === 'once') { 172 setCookie(cookieName, 'true', cookieExpiry); 173 console.log(`Cookie "${cookieName}" marcada por ExitIntent durante ${cookieExpiry} días.`); 174 } 129 175 } 130 176 }); … … 132 178 console.log("IntentExit no habilitado."); 133 179 } 134 if (config.showOnScroll === 'yes') { 135 console.log(`On Scroll habilitado. Porcentaje configurado: ${config.scrollPercentage}%`); 136 137 let scrollTriggered = false; 138 139 $(window).on('scroll', function () { 140 if (scrollTriggered) return; 141 142 const scrollTop = $(window).scrollTop(); 143 const windowHeight = $(window).height(); 144 const documentHeight = $(document).height(); 145 const scrolledPercentage = (scrollTop / (documentHeight - windowHeight)) * 100; 146 147 if (scrolledPercentage >= config.scrollPercentage) { 148 console.log(`Porcentaje de scroll alcanzado: ${scrolledPercentage.toFixed(2)}%`); 149 showPopup(); 150 scrollTriggered = true; 151 $(window).off('scroll'); 152 } 153 }); 154 } else { 155 console.log("On Scroll no habilitado."); 156 } 180 157 181 158 182 $popupOverlay.on('click', function (e) { … … 170 194 }); 171 195 172 handlePopupDisplay(); 173 }); 174 })(jQuery); 196 if (isSelectorMode) { 197 const raw = config.triggerSelector.trim(); 198 const selector = /^[.#]/.test(raw) ? raw : ('.' + raw); 199 $(document).off('click.popupfeSelector'); 200 console.log('[PopupFE] Trigger por selector activo →', selector, '| matches:', document.querySelectorAll(selector).length); 201 $(document).on('click.popupfeSelector', selector, function(e){ 202 if ($popupOverlay.is(':visible') || isClosing) return; 203 showPopup(); 204 }); 205 } 206 207 208 handlePopupDisplay(); 209 }); 210 })(jQuery); 211 -
popup-for-elementor/tags/1.5.8/includes/editor-options.php
r3300275 r3380762 1 1 <?php 2 // Adds options to Elementor editor for configuring the popup 3 if ( ! defined( 'ABSPATH' ) ) { 4 exit; // Exit if accessed directly 2 // File: popup-handler.php 3 // Dynamically passes configuration from Elementor controls to the JavaScript. 4 5 if (!defined('ABSPATH')) { 6 exit; 5 7 } 6 class Popupfe_Popup_Widget extends \Elementor\Widget_Base 8 function popup_for_elementor_register_assets() 7 9 { 8 public function get_name() 9 { 10 return "popup_widget"; 11 } 12 public function get_title() 13 { 14 return esc_html__("Popup Widget", "popup-for-elementor"); 15 } 10 if (!is_admin()) { 11 wp_register_script( 12 'popup-widget-js', 13 plugin_dir_url(__FILE__) . '../assets/popup-widget.js', 14 array('jquery'), 15 '1.0.0', 16 true 17 ); 18 $post_id = get_the_ID(); 16 19 17 public function get_categories() 18 { 19 return ["basic"]; 20 } 21 public function get_icon() { 22 return 'eicon-table-of-contents'; 23 } 24 25 protected function _register_controls() 26 { 27 // Content controls 28 $this->start_controls_section("content_section", [ 29 "label" => esc_html__("Content", "popup-for-elementor"), 30 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 31 ]); 32 33 $templates = []; 34 if (class_exists("\Elementor\Plugin")) { 35 $template_manager = \Elementor\Plugin::instance()->templates_manager->get_source( 36 "local" 20 if ($post_id) { 21 $dynamic_config = array( 22 'showOnLoad' => get_post_meta($post_id, '_elementor_popup_show_on_load', true) ?: 'no', 23 'delay' => (int) get_post_meta($post_id, '_elementor_popup_delay', true) ?: 0, 24 'showOnScroll' => get_post_meta($post_id, '_elementor_popup_show_on_scroll', true) === 'yes', 25 'scrollPercentage' => (int) (get_post_meta($post_id, '_elementor_popup_scroll_percentage', true) ?: 50), 26 'exitIntent' => get_post_meta($post_id, '_elementor_popup_exit_intent', true) === 'yes', 27 'exitIntentDisplayMode'=> get_post_meta($post_id, '_elementor_exit_intent_display_mode', true) ?: 'always', 28 'cookieName' => 'popup_seen', 29 'cookieExpiry' => 7, 30 'triggerBySelector' => get_post_meta($post_id, '_elementor_trigger_selector_enabled', true) === 'yes', 31 'triggerSelector' => get_post_meta($post_id, '_elementor_trigger_selector', true) ?: '', 32 37 33 ); 38 $templates_raw = $template_manager39 ? $template_manager->get_items()40 : [];41 foreach ($templates_raw as $template) {42 $ templates[$template["template_id"]] = $template["title"];43 }34 35 wp_localize_script( 36 'popup-widget-js', 37 'PopupForElementorConfig', 38 $dynamic_config 39 ); 44 40 } 45 46 $this->add_control("template_id", [ 47 "label" => esc_html__("Select Template", "popup-for-elementor"), 48 "type" => \Elementor\Controls_Manager::SELECT2, // Cambiado a SELECT2 49 "options" => $templates, // Asegúrate de que $templates tiene las opciones disponibles 50 "default" => "", 51 "description" => esc_html__( 52 "Choose a template from your Elementor library.", 53 "popup-for-elementor" 54 ), 55 ]); 56 57 $this->add_control("template_create_link", [ 58 "type" => \Elementor\Controls_Manager::RAW_HTML, 59 "raw" => sprintf( 60 '<a href="%s" target="_blank" class="elementor-button elementor-button-success" style="margin-top: 10px;">%s</a>', 61 admin_url("edit.php?post_type=elementor_library"), 62 esc_html__("Create New Template", "popup-for-elementor") 63 ), 64 "content_classes" => "elementor-control-field", 65 ]); 66 67 $this->add_control("upgrade_to_pro_notice1", [ 68 "type" => \Elementor\Controls_Manager::RAW_HTML, 69 "raw" => sprintf( 70 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 71 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 72 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 73 %s 74 </a> 75 </div>', 76 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 77 "https://popupforelementor.com/en/home/#buy", 78 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 79 ), 80 "content_classes" => "elementor-control-field", 81 ]); 82 83 $this->end_controls_section(); 84 85 // Style controls 86 $this->start_controls_section("style_section", [ 87 "label" => esc_html__("Popup window", "popup-for-elementor"), 88 "tab" => \Elementor\Controls_Manager::TAB_STYLE, 89 ]); 90 $this->add_responsive_control( 91 'popup_background', 92 [ 93 'label' => esc_html__('Background Color', 'popup-for-elementor'), 94 'type' => \Elementor\Controls_Manager::COLOR, 95 'selectors' => [ 96 '{{WRAPPER}} .popup-content' => 'background-color: {{VALUE}};', 97 ], 98 ] 99 ); 100 101 $this->add_control("overlay_color", [ 102 "label" => esc_html__("Overlay Color", "popup-for-elementor"), 103 "type" => \Elementor\Controls_Manager::COLOR, 104 "default" => "rgba(0, 0, 0, 0.5)", 105 "selectors" => [ 106 "{{WRAPPER}} .popup-overlay" => "background-color: {{VALUE}};", 107 ], 108 ]); 109 110 $this->add_control("border_radius", [ 111 "label" => esc_html__("Border Radius", "popup-for-elementor"), 112 "type" => \Elementor\Controls_Manager::SLIDER, 113 "default" => [ 114 "size" => 10, 115 ], 116 "selectors" => [ 117 "{{WRAPPER}} .popup-content" => 118 "border-radius: {{SIZE}}{{UNIT}};", 119 ], 120 ]); 121 122 $this->add_group_control( 123 \Elementor\Group_Control_Box_Shadow::get_type(), 124 [ 125 "name" => "popup_box_shadow", 126 "label" => esc_html__("Box Shadow", "popup-for-elementor"), 127 "selector" => "{{WRAPPER}} .popup-content", 128 "description" => esc_html__( 129 "Configure the shadow settings directly.", 130 "popup-for-elementor" 131 ), 132 ] 133 ); 134 135 $this->add_responsive_control("popup_width", [ 136 "label" => esc_html__("Popup Width", "popup-for-elementor"), 137 "type" => \Elementor\Controls_Manager::SELECT, 138 "default" => "400px", 139 "options" => [ 140 "auto" => esc_html__("Auto (Fit Content)", "popup-for-elementor"), 141 "custom" => esc_html__("Custom", "popup-for-elementor"), 142 ], 143 "selectors" => [ 144 "{{WRAPPER}} .popup-content" => "width: {{VALUE}};", 145 ], 146 ]); 147 148 $this->add_responsive_control("custom_popup_width", [ 149 "label" => esc_html__("Custom Width", "popup-for-elementor"), 150 "type" => \Elementor\Controls_Manager::SLIDER, 151 "default" => [ 152 "size" => 400, 153 "unit" => "px", 154 ], 155 "size_units" => ["px", "%", "vw"], 156 "range" => [ 157 "px" => [ 158 "min" => 100, 159 "max" => 2000, 160 "step" => 10, 161 ], 162 "%" => [ 163 "min" => 1, 164 "max" => 100, 165 ], 166 "vw" => [ 167 "min" => 1, 168 "max" => 100, 169 ], 170 ], 171 "condition" => [ 172 "popup_width" => "custom", 173 ], 174 "selectors" => [ 175 "{{WRAPPER}} .popup-content" => "width: {{SIZE}}{{UNIT}};", 176 ], 177 ]); 178 179 180 $this->add_responsive_control("popup_height", [ 181 "label" => esc_html__("Popup Height", "popup-for-elementor"), 182 "type" => \Elementor\Controls_Manager::SELECT, 183 "default" => "auto", 184 "options" => [ 185 "auto" => esc_html__("Auto (Fit Content)", "popup-for-elementor"), 186 "custom" => esc_html__("Custom", "popup-for-elementor"), 187 ], 188 "selectors" => [ 189 "{{WRAPPER}} .popup-content" => "height: {{VALUE}};", 190 ], 191 ]); 192 193 $this->add_responsive_control("custom_popup_height", [ 194 "label" => esc_html__("Custom Height", "popup-for-elementor"), 195 "type" => \Elementor\Controls_Manager::SLIDER, 196 "default" => [ 197 "size" => 400, 198 "unit" => "px", 199 ], 200 "size_units" => ["px", "%", "vh"], 201 "range" => [ 202 "px" => [ 203 "min" => 100, 204 "max" => 2000, 205 "step" => 10, 206 ], 207 "%" => [ 208 "min" => 1, 209 "max" => 100, 210 ], 211 "vh" => [ 212 "min" => 1, 213 "max" => 100, 214 ], 215 ], 216 "condition" => [ 217 "popup_height" => "custom", 218 ], 219 "selectors" => [ 220 "{{WRAPPER}} .popup-content" => "height: {{SIZE}}{{UNIT}};", 221 ], 222 ]); 223 224 225 226 $this->add_responsive_control("horizontal_position", [ 227 "label" => esc_html__("Horizontal Position", "popup-for-elementor"), 228 "type" => \Elementor\Controls_Manager::CHOOSE, 229 "options" => [ 230 "flex-start" => [ 231 "title" => esc_html__("Left", "popup-for-elementor"), 232 "icon" => "eicon-h-align-left", 233 ], 234 "center" => [ 235 "title" => esc_html__("Center", "popup-for-elementor"), 236 "icon" => "eicon-h-align-center", 237 ], 238 "flex-end" => [ 239 "title" => esc_html__("Right", "popup-for-elementor"), 240 "icon" => "eicon-h-align-right", 241 ], 242 ], 243 "default" => "center", 244 "selectors" => [ 245 "{{WRAPPER}} .popup-overlay" => "justify-content: {{VALUE}};", 246 ], 247 ]); 248 249 $this->add_responsive_control("vertical_position", [ 250 "label" => esc_html__("Vertical Position", "popup-for-elementor"), 251 "type" => \Elementor\Controls_Manager::CHOOSE, 252 "options" => [ 253 "flex-start" => [ 254 "title" => esc_html__("Top", "popup-for-elementor"), 255 "icon" => "eicon-v-align-top", 256 ], 257 "center" => [ 258 "title" => esc_html__("Center", "popup-for-elementor"), 259 "icon" => "eicon-v-align-middle", 260 ], 261 "flex-end" => [ 262 "title" => esc_html__("Bottom", "popup-for-elementor"), 263 "icon" => "eicon-v-align-bottom", 264 ], 265 ], 266 "default" => "center", 267 "selectors" => [ 268 "{{WRAPPER}} .popup-overlay" => "align-items: {{VALUE}};", 269 ], 270 ]); 271 272 // Control para el margen (Responsive) 273 $this->add_responsive_control( 274 'popup_margin', 275 [ 276 'label' => esc_html__('Margin', 'popup-for-elementor'), 277 'type' => \Elementor\Controls_Manager::DIMENSIONS, 278 'size_units' => ['px', '%', 'em'], 279 'selectors' => [ 280 '{{WRAPPER}} .popup-content' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 281 ], 282 ] 283 ); 284 285 // Control para el padding (Responsive) 286 $this->add_responsive_control( 287 'popup_padding', 288 [ 289 'label' => esc_html__('Padding', 'popup-for-elementor'), 290 'type' => \Elementor\Controls_Manager::DIMENSIONS, 291 'size_units' => ['px', '%', 'em'], 292 'selectors' => [ 293 '{{WRAPPER}} .popup-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 294 ], 295 ] 296 ); 297 298 299 $this->end_controls_section(); 300 301 // Animation 302 303 $this->start_controls_section("animation_section_custom", [ 304 "label" => esc_html__("Animation", "popup-for-elementor"), 305 "tab" => \Elementor\Controls_Manager::TAB_STYLE, // Colocamos esta sección en la pestaña de estilo 306 ]); 307 308 $this->add_control("popup_animation_in", [ 309 "label" => esc_html__("Entrance Animation", "popup-for-elementor"), 310 "type" => \Elementor\Controls_Manager::SELECT, 311 "options" => [ 312 "none" => esc_html__("None", "popup-for-elementor"), 313 "animate__fadeIn" => esc_html__("Fade In", "popup-for-elementor"), 314 "animate__fadeInUp" => esc_html__("Fade In Up", "popup-for-elementor"), 315 "anixmate__fadeInDown" => esc_html__("Fade In Down", "popup-for-elementor"), 316 "animate__fadeInLeft" => esc_html__("Fade In Left", "popup-for-elementor"), 317 "animate__fadeInRight" => esc_html__("Fade In Right", "popup-for-elementor"), 318 "animate__zoomIn" => esc_html__("Zoom In", "popup-for-elementor"), 319 "animate__slideInUp" => esc_html__("Slide In Up", "popup-for-elementor"), 320 "animate__slideInDown" => esc_html__("Slide In Down", "popup-for-elementor"), 321 "animate__slideInLeft" => esc_html__("Slide In Left", "popup-for-elementor"), 322 "animate__slideInRight" => esc_html__("Slide In Right", "popup-for-elementor"), 323 ], 324 "default" => "animate__fadeIn", 325 "description" => esc_html__( 326 "Choose an animation for the popup to appear.", 327 "popup-for-elementor" 328 ), 329 ]); 330 331 $this->add_control("popup_animation_out", [ 332 "label" => esc_html__("Exit Animation", "popup-for-elementor"), 333 "type" => \Elementor\Controls_Manager::SELECT, 334 "options" => [ 335 "none" => esc_html__("None", "popup-for-elementor"), 336 "animate__fadeOut" => esc_html__("Fade Out", "popup-for-elementor"), 337 "animate__fadeOutUp" => esc_html__("Fade Out Up", "popup-for-elementor"), 338 "animate__fadeOutDown" => esc_html__("Fade Out Down", "popup-for-elementor"), 339 "animate__fadeOutLeft" => esc_html__("Fade Out Left", "popup-for-elementor"), 340 "animate__fadeOutRight" => esc_html__("Fade Out Right", "popup-for-elementor"), 341 "animate__zoomOut" => esc_html__("Zoom Out", "popup-for-elementor"), 342 "animate__slideOutUp" => esc_html__("Slide Out Up", "popup-for-elementor"), 343 "animate__slideOutDown" => esc_html__("Slide Out Down", "popup-for-elementor"), 344 "animate__slideOutLeft" => esc_html__("Slide Out Left", "popup-for-elementor"), 345 "animate__slideOutRight" => esc_html__( 346 "Slide Out Right", 347 "popup-for-elementor" 348 ), 349 ], 350 "default" => "animate__fadeOut", 351 "description" => esc_html__( 352 "Choose an animation for the popup to disappear.", 353 "popup-for-elementor" 354 ), 355 ]); 356 357 $this->add_control("animation_duration_custom", [ 358 "label" => esc_html__("Animation Duration (ms)", "popup-for-elementor"), 359 "type" => \Elementor\Controls_Manager::SLIDER, 360 "size_units" => ["ms"], 361 "range" => [ 362 "ms" => [ 363 "min" => 100, 364 "max" => 3000, 365 "step" => 100, 366 ], 367 ], 368 "default" => [ 369 "size" => 500, 370 "unit" => "ms", 371 ], 372 "selectors" => [ 373 "{{WRAPPER}} .popup-content" => 374 "animation-duration: {{SIZE}}{{UNIT}};", 375 ], 376 ]); 377 378 $this->end_controls_section(); 379 //Close Button 380 381 $this->start_controls_section("close_button_section", [ 382 "label" => esc_html__("Close Button", "popup-for-elementor"), 383 "tab" => \Elementor\Controls_Manager::TAB_STYLE, 384 ]); 385 $this->add_control("hide_close_button", [ 386 "label" => esc_html__("Hide Close Button", "popup-for-elementor"), 387 "type" => \Elementor\Controls_Manager::SWITCHER, 388 "label_on" => esc_html__("Yes", "popup-for-elementor"), 389 "label_off" => esc_html__("No", "popup-for-elementor"), 390 "return_value" => "yes", 391 "default" => "no", 392 "selectors" => [ 393 "{{WRAPPER}} .popup-close" => "display: none;", 394 ], 395 ]); 396 397 $this->add_control("close_button_background_color", [ 398 "label" => esc_html__("Close Button Background", "popup-for-elementor"), 399 "type" => \Elementor\Controls_Manager::COLOR, 400 "selectors" => [ 401 "{{WRAPPER}} .popup-close" => "background-color: {{VALUE}};", 402 ], 403 ]); 404 405 $this->add_control("close_button_hover_background_color", [ 406 "label" => esc_html__("Close Button Hover Background", "popup-for-elementor"), 407 "type" => \Elementor\Controls_Manager::COLOR, 408 "selectors" => [ 409 "{{WRAPPER}} .popup-close:hover" => 410 "background-color: {{VALUE}};", 411 ], 412 ]); 413 414 $this->add_control("close_button_color", [ 415 "label" => esc_html__("Close Button Color", "popup-for-elementor"), 416 "type" => \Elementor\Controls_Manager::COLOR, 417 "selectors" => [ 418 "{{WRAPPER}} .popup-close" => "color: {{VALUE}};", 419 ], 420 ]); 421 422 $this->add_control("close_button_hover_color", [ 423 "label" => esc_html__("Close Button Hover Color", "popup-for-elementor"), 424 "type" => \Elementor\Controls_Manager::COLOR, 425 "selectors" => [ 426 "{{WRAPPER}} .popup-close:hover" => "color: {{VALUE}};", 427 ], 428 ]); 429 430 $this->add_control("close_button_size", [ 431 "label" => esc_html__("Close Button Size", "popup-for-elementor"), 432 "type" => \Elementor\Controls_Manager::SLIDER, 433 "size_units" => ["px"], // Solo permite px 434 "range" => [ 435 "px" => [ 436 "min" => 10, 437 "max" => 100, 438 ], 439 ], 440 "default" => [ 441 "unit" => "px", 442 "size" => 40, // Tamaño por defecto del botón de cerrar 443 ], 444 "selectors" => [ 445 "{{WRAPPER}} .popup-close" => 446 "width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}}; font-size: calc({{SIZE}}{{UNIT}} / 2);", 447 ], 448 "description" => esc_html__( 449 "Adjust the size of the close button.", 450 "popup-for-elementor" 451 ), 452 ]); 453 $this->add_control("close_button_alignment", [ 454 "label" => esc_html__("Close Button Alignment", "popup-for-elementor"), 455 "type" => \Elementor\Controls_Manager::CHOOSE, 456 "options" => [ 457 "left" => [ 458 "title" => esc_html__("Left", "popup-for-elementor"), 459 "icon" => "eicon-h-align-left", 460 ], 461 "right" => [ 462 "title" => esc_html__("Right", "popup-for-elementor"), 463 "icon" => "eicon-h-align-right", 464 ], 465 ], 466 "default" => "right", 467 "selectors" => [ 468 "{{WRAPPER}} .popup-close" => "{{VALUE}}: 10px;", 469 ], 470 "description" => esc_html__( 471 "Align the close button to the left or right.", 472 "popup-for-elementor" 473 ), 474 ]); 475 476 $this->add_control("close_button_border_radius", [ 477 "label" => esc_html__("Close Button Border Radius", "popup-for-elementor"), 478 "type" => \Elementor\Controls_Manager::SLIDER, 479 "size_units" => ["px"], // Solo permite px 480 "range" => [ 481 "px" => [ 482 "min" => 0, 483 "max" => 50, 484 ], 485 ], 486 "selectors" => [ 487 "{{WRAPPER}} .popup-close" => 488 "border-radius: {{SIZE}}{{UNIT}};", 489 ], 490 "description" => esc_html__( 491 "Controls the border radius of the close button.", 492 "popup-for-elementor" 493 ), 494 ]); 495 496 $this->end_controls_section(); 497 498 // Visibility controls 499 $this->start_controls_section("visibility_section", [ 500 "label" => esc_html__("Visibility", "popup-for-elementor"), 501 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 502 ]); 503 504 $this->add_control("show_on_load", [ 505 "label" => esc_html__("Show on Page Load", "popup-for-elementor"), 506 "type" => \Elementor\Controls_Manager::SWITCHER, 507 "default" => "", 508 "description" => esc_html__("Activate to show popup when the page loads. Will disable other visibility options.", "popup-for-elementor"), 509 "condition" => [ 510 "show_after_delay_enabled!" => "yes", 511 "show_on_exit_intent!" => "yes", 512 "show_once!" => "yes", 513 ], 514 ]); 515 516 $this->add_control("show_after_delay_enabled", [ 517 "label" => esc_html__("Enable Show After Delay", "popup-for-elementor"), 518 "type" => \Elementor\Controls_Manager::SWITCHER, 519 "default" => "", 520 "description" => esc_html__("Activate to show popup after a delay. Will disable other visibility options.", "popup-for-elementor"), 521 "condition" => [ 522 "show_on_load!" => "yes", 523 "show_on_exit_intent!" => "yes", 524 "show_once!" => "yes", 525 ], 526 ]); 527 528 $this->add_control("show_after_delay", [ 529 "label" => esc_html__("Delay (seconds)", "popup-for-elementor"), 530 "type" => \Elementor\Controls_Manager::NUMBER, 531 "default" => 3, 532 "condition" => [ 533 "show_after_delay_enabled" => "yes", 534 ], 535 ]); 536 537 $this->add_control("show_on_exit_intent", [ 538 "label" => esc_html__("Show on Exit Intent", "popup-for-elementor"), 539 "type" => \Elementor\Controls_Manager::SWITCHER, 540 "default" => "", 541 "description" => esc_html__("Activate to show popup when the user intends to exit. Will disable other visibility options.", "popup-for-elementor"), 542 "condition" => [ 543 "show_on_load!" => "yes", 544 "show_after_delay_enabled!" => "yes", 545 "show_once!" => "yes", 546 ], 547 ]); 548 $this->add_control("show_once", [ 549 "label" => esc_html__("Show Only Once", "popup-for-elementor"), 550 "type" => \Elementor\Controls_Manager::SWITCHER, 551 "default" => "", 552 "description" => esc_html__("Show the popup only once per session.", "popup-for-elementor"), 553 "condition" => [ 554 "show_on_load!" => "yes", 555 "show_after_delay_enabled!" => "yes", 556 "show_on_exit_intent!" => "yes", 557 ], 558 ]); 559 560 $this->add_control("upgrade_to_pro_notice2", [ 561 "type" => \Elementor\Controls_Manager::RAW_HTML, 562 "raw" => sprintf( 563 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 564 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 565 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 566 %s 567 </a> 568 </div>', 569 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 570 "https://popupforelementor.com/en/home/#buy", 571 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 572 ), 573 "content_classes" => "elementor-control-field", 574 ]); 575 $this->end_controls_section(); 576 $this->start_controls_section("refresh_section", [ 577 "label" => esc_html__("Refresh", "popup-for-elementor"), 578 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 579 ]); 580 581 $this->add_control( 582 'refresh_popup', 583 [ 584 'label' => esc_html__('Refresh Popup', 'popup-for-elementor'), 585 'type' => \Elementor\Controls_Manager::BUTTON, 586 'button_type' => 'success', 587 'text' => esc_html__('Refresh', 'popup-for-elementor'), 588 'description' => esc_html__('Click to refresh the popup content.', 'popup-for-elementor'), 589 'frontend_available' => true, 590 ] 591 ); 592 $this->add_control("upgrade_to_pro_notice3", [ 593 "type" => \Elementor\Controls_Manager::RAW_HTML, 594 "raw" => sprintf( 595 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 596 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 597 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 598 %s 599 </a> 600 </div>', 601 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 602 "https://popupforelementor.com/en/home/#buy", 603 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 604 ), 605 "content_classes" => "elementor-control-field", 606 ]); 607 $this->end_controls_section(); 608 $this->start_controls_section("upgrade_section", [ 609 "label" => esc_html__("Popup for Elementor (PRO)", "popup-for-elementor"), 610 "tab" => null, 611 ]); 612 613 $this->add_control("pro_upgrade_box", [ 614 "type" => \Elementor\Controls_Manager::RAW_HTML, 615 "raw" => sprintf( 616 '<div style="padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 617 <h3 style="color: #ffffff; font-size: 16px; margin-bottom: 12px; font-weight: 600;">%s</h3> 618 <p style="color: #bbbbbb; font-size: 13px; margin-bottom: 20px;">%s</p> 619 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 620 %s 621 </a> 622 </div>', 623 esc_html__("Unlock More Power", "popup-for-elementor"), 624 esc_html__("Upgrade to Pro and access all premium triggers and features.", "popup-for-elementor"), 625 "https://popupforelementor.com/en/home/#buy", 626 esc_html__("Upgrade to Pro", "popup-for-elementor") 627 ), 628 ]); 629 630 $this->end_controls_section(); 631 632 633 634 } 635 636 protected function render() 637 { 638 $settings = $this->get_settings_for_display(); 639 640 // Configuraciones dinámicas para pasar al script 641 $config = [ 642 'showOnLoad' => isset($settings['show_on_load']) && $settings['show_on_load'] === 'yes' ? 'yes' : 'no', 643 'delay' => isset($settings['show_after_delay']) ? (int) $settings['show_after_delay'] * 1000 : 0, 644 'exitIntent' => isset($settings['show_on_exit_intent']) && $settings['show_on_exit_intent'] === 'yes' ? 'yes' : 'no', 645 'showOnce' => isset($settings['show_once']) && $settings['show_once'] === 'yes' ? 'yes' : 'no', 646 'cookieName' => 'popup_seen', 647 'cookieExpiry' => 7, 648 ]; 649 650 // Pasar configuraciones dinámicas al script 651 wp_localize_script( 652 'popup-widget-js', 653 'PopupForElementorConfig', 654 $config 655 ); 656 657 658 // Obtener animaciones seleccionadas y duración 659 $animation_in = $settings['popup_animation_in'] ?? 'animate__fadeIn'; 660 $animation_out = $settings['popup_animation_out'] ?? 'animate__fadeOut'; 661 $animation_duration = isset($settings['animation_duration_custom']['size']) 662 ? (int) $settings['animation_duration_custom']['size'] 663 : 500; 664 665 // Renderizar plantilla de Elementor si está configurada 666 if (!empty($settings['template_id']) && class_exists('\Elementor\Plugin')) { 667 $popup_content = \Elementor\Plugin::instance()->frontend->get_builder_content_for_display($settings['template_id']); 668 669 if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { 670 // Recuperar la URL del editor de Elementor 671 $edit_url = admin_url('post.php?post=' . absint($settings['template_id']) . '&action=elementor'); 672 673 // Solo eliminar etiquetas que no afecten la funcionalidad 674 $filtered_content = preg_replace('/<meta\b[^>]*>(.*?)<\/meta>/is', '', $popup_content); 675 $filtered_content = preg_replace('/<link\b[^>]*>(.*?)<\/link>/is', '', $filtered_content); 676 677 // Crear contenido para el modal 678 $popup_content = ' 679 <div class="elementor-template-button-wrapper" style="text-align: center; margin-top: 15px;"> 680 <a href="javascript:void(0);" 681 class="popup-edit-button elementor-button elementor-button-success elementor-size-sm button-edit-custom" 682 data-popup-id="' . esc_attr( 'popup_' . get_the_ID() . '_' . $settings['template_id'] ) . '" 683 data-edit-url="' . esc_url($edit_url) . '" 684 id="open-modal"> 685 <i class="eicon-edit" style="margin-right: 8px;"></i>' . esc_html__('Edit Template', 'popup-for-elementor') . ' 686 </a> 687 </div> 688 <div class="popup-editor-content"> 689 ' . $filtered_content . ' 690 </div>'; 41 wp_enqueue_script('popup-widget-js'); 691 42 } 692 43 } 44 add_action('wp_enqueue_scripts', 'popup_for_elementor_register_assets'); 693 45 46 add_action('admin_enqueue_scripts', function () { 47 wp_dequeue_script('popup-widget-js'); 48 wp_deregister_script('popup-widget-js'); 49 }, PHP_INT_MAX); 694 50 695 // Generar un identificador único para el popup696 $current_page_id = get_the_ID();697 $popup_id = get_post_meta($settings['template_id'], '_popup_id_' . $current_page_id, true);698 699 if (empty($popup_id)) {700 $popup_id = 'popup_' . $current_page_id . '_' . uniqid();701 update_post_meta($settings['template_id'], '_popup_id_' . $current_page_id, $popup_id);702 }703 704 // Renderizar el HTML del popup con ID único705 $styles = '';706 if (!defined('ELEMENTOR_VERSION') || !\Elementor\Plugin::$instance->editor->is_edit_mode()) {707 // Aplicar estilos para ocultar el popup fuera del editor708 $styles = 'display: none; visibility: hidden; opacity: 1;';709 }710 711 function filter_popup_content($content)712 {713 // Lista de etiquetas peligrosas a eliminar (pero manteniendo SVGs y estilos de Elementor)714 $dangerous_tags = ['iframe', 'embed', 'object', 'applet', 'meta', 'link'];715 716 foreach ($dangerous_tags as $tag) {717 $content = preg_replace('/<' . $tag . '.*?>.*?<\/' . $tag . '>/is', '', $content);718 $content = preg_replace('/<' . $tag . '.*?>/is', '', $content);719 }720 721 return $content;722 }723 724 /* Escaping is not applied here because the content has already been filtered725 by `filter_popup_content()`, which removes dangerous tags.726 Using `esc_html()` would break Elementor's functionality.727 This code has been reviewed and is safe. */728 729 $popup_content_filtered = filter_popup_content($popup_content);730 731 echo '<div id="' . esc_attr($popup_id) . '" class="popup-overlay popup-widget" style="' . esc_attr($styles) . '">732 <div class="popup-content animate__animated ' . esc_attr($animation_in) . '"733 style="position: relative; animation-duration: ' . esc_attr($animation_duration) . 'ms;">734 <button class="popup-close">×</button>';735 736 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped737 echo $popup_content_filtered;738 739 echo '</div></div>';740 741 // This script controls the popup behavior (open/close, animations, hover effects).742 // It must be injected directly here because Elementor dynamically refreshes widget content.743 // Using wp_enqueue_script or wp_add_inline_script would not persist across reloads.744 745 echo '<script>746 (function($) {747 $(document).ready(function() {748 const popup = $("#' .749 esc_attr($popup_id) .750 '");751 const popupContent = popup.find(".popup-content");752 753 if (popup.length) {754 // Abrir popup con animación de entrada755 popup.closest(".elementor-widget-popup_widget").off("click").on("click", function(e) {756 e.preventDefault();757 popup.css({758 display: "flex",759 visibility: "visible"760 });761 popupContent.removeClass("' .762 esc_attr($animation_out) .763 '").addClass("' .764 esc_attr($animation_in) .765 '");766 });767 768 // Cerrar popup con animación de salida769 popup.find(".popup-close").off("click").on("click", function(e) {770 e.stopPropagation();771 popupContent772 .removeClass("' .773 esc_attr($animation_in) .774 '")775 .addClass("' .776 esc_attr($animation_out) .777 '");778 779 // Esperar la duración de la animación antes de ocultar el popup780 const duration = ' .781 esc_attr($animation_duration) .782 ';783 setTimeout(function() {784 popup.css({785 display: "none",786 visibility: "hidden"787 });788 popupContent.removeClass("' .789 esc_attr($animation_out) .790 '");791 }, duration);792 });793 794 // Hover en el botón para cambiar el fondo del popup795 popup.find(".popup-edit-button").on("mouseenter", function() {796 popupContent.css("background-color", "#ffebf2");797 }).on("mouseleave", function() {798 popupContent.css("background-color", "");799 });800 } else {801 console.error("Popup element not found in the DOM.");802 }803 });804 elementor.hooks.addAction("panel/open_editor/widget", function (panel, model) {805 panel.$el.on("click", ".elementor-control-refresh_popup .elementor-button", function () {806 console.log("¡Botón clicado! Refrescando el widget...");807 808 // Simular un cambio en el modelo809 model.set("refresh_trigger", Date.now()); // Valor ficticio para forzar el cambio810 model.trigger("change"); // Notificar el cambio a Elementor811 812 // Verificar si Elementor actualiza la vista813 setTimeout(function () {814 console.log("Intentando recargar la vista previa...");815 elementor.reloadPreview(); // Forzar la recarga si no responde816 elementor.once("preview:loaded", function () {817 console.log("Vista previa recargada correctamente.");818 819 // Reabrir el popup después de recargar la vista previa820 const $popupOverlay = jQuery(".popup-overlay");821 if ($popupOverlay.length) {822 console.log("Reabriendo el popup...");823 $popupOverlay.css({824 display: "",825 visibility: "",826 opacity: 1,827 });828 console.log("Popup reabierto correctamente.");829 } else {830 console.error("No se encontró el popup en el DOM.");831 }832 });833 }, 500); // Fallback por si el trigger no es suficiente834 });835 });836 })(jQuery);837 </script>';838 839 // This script controls the custom modal editor outside the iframe (open, close, panel resize).840 // Since the modal is rendered outside the iframe (via editor/after_footer),841 // this script needs to access it using parent.jQuery.842 // It must be echoed directly to stay bound to the button rendered in the iframe.843 844 echo '<div id="custom-modal">845 <div class="modal-container">846 <div class="modal-header">847 <div class="modal-title" style="display: flex; align-items: center;">848 <div style="width: 40px; height: 40px; background-color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; margin-right: 10px;">849 <span class="eicon-table-of-contents" style="font-size: 20px; color: #333;"></span> <!-- Icono de Elementor -->850 </div>851 ' . esc_html__("Popup for Elementor", "popup-for-elementor") . '852 </div>853 <button id="close-modal">×</button>854 </div>855 <iframe id="modal-iframe" src=""></iframe>856 </div>857 </div>';858 859 echo '<script>860 (function($) {861 $(document).ready(function() {862 const $modal = $("#custom-modal");863 const $iframe = $("#modal-iframe");864 const $closeButton = $("#close-modal");865 866 let originalPanelStyles = {}; // Guardamos los estilos originales867 868 function refreshWidget() {869 console.log("Ejecutando refresh del widget...");870 if (typeof parent.elementor !== "undefined" && parent.elementor.reloadPreview) {871 parent.elementor.reloadPreview();872 parent.elementor.once("preview:loaded", function() {873 console.log("Vista previa recargada correctamente.");874 });875 }876 }877 878 function toggleElementorPanel(reduce) {879 if (typeof parent.jQuery !== "undefined") {880 const $panel = parent.jQuery("#elementor-panel");881 const $preview = parent.jQuery("#elementor-preview");882 883 if (reduce) {884 console.log("Guardando estado del panel y reduciéndolo...");885 originalPanelStyles = {886 width: $panel.css("width"),887 minWidth: $panel.css("min-width"),888 maxWidth: $panel.css("max-width"),889 overflow: $panel.css("overflow"),890 visibility: $panel.css("visibility"),891 opacity: $panel.css("opacity"),892 };893 894 $panel.css({895 "width": "60px",896 "min-width": "60px",897 "max-width": "60px",898 "overflow": "hidden",899 "visibility": "hidden",900 "opacity": "0",901 "transition": "width 0.3s ease-in-out"902 });903 904 $preview.css({905 "width": "calc(100% - 60px)",906 "transition": "width 0.3s ease-in-out"907 });908 } else {909 console.log("Restaurando el panel de Elementor...");910 $panel.css(originalPanelStyles);911 912 $preview.css({913 "width": "calc(100% - " + originalPanelStyles.width + ")"914 });915 }916 }917 }918 919 $("#open-modal").on("click", function() {920 console.log("Modal abierto, reduciendo panel en la ventana principal...");921 const editUrl = $(this).data("edit-url");922 $iframe.attr("src", editUrl);923 $modal.removeClass("hide").addClass("show");924 925 toggleElementorPanel(true);926 });927 928 $closeButton.on("click", function() {929 console.log("Cerrando modal, restaurando panel en la ventana principal...");930 $modal.removeClass("show").addClass("hide");931 932 setTimeout(() => {933 $iframe.attr("src", ""); // Limpiar el iframe934 toggleElementorPanel(false);935 refreshWidget();936 }, 300);937 });938 939 console.log("Script de reducción de panel cargado.");940 });941 })(jQuery);942 </script>';943 }944 } -
popup-for-elementor/tags/1.5.8/popup-for-elementor.php
r3331799 r3380762 2 2 /** 3 3 * Plugin Name: Popup for Elementor 4 * Plugin URI: https:// popupforelementor.com5 * Description: Enhance your Elementor website with fully customizable popups. Includes triggers, animations, and advanced settings to improve user interaction andengagement.6 * Version: 1.5. 74 * Plugin URI: https://www.popupforelementor.com 5 * Description: Create powerful, fully customizable popups directly in Elementor Free — includes click, delay, load, and exit-intent triggers, animations, and smart visibility controls to boost user engagement. 6 * Version: 1.5.8 7 7 * Author: Veelo 8 8 * Author URI: https://www.veelo.es … … 11 11 * License: GPLv2 or later 12 12 * License URI: https://www.gnu.org/licenses/gpl-2.0.html 13 * Requires at least: 5. 613 * Requires at least: 5.8 14 14 * Requires PHP: 7.4 15 15 * Requires Plugins: elementor 16 * Tested up to: 6. 916 * Tested up to: 6.8.3 17 17 */ 18 18 19 19 20 -
popup-for-elementor/tags/1.5.8/readme.txt
r3331799 r3380762 1 1 === Popup for Elementor === 2 2 Contributors: veelo 3 Tags: popup, elementor, modal, wordpress popup, elementor free 4 Requires at least: 5. 65 Tested up to: 6. 93 Tags: popup, elementor, modal, wordpress popup, elementor free, popup maker, popup builder, modal window 4 Requires at least: 5.8 5 Tested up to: 6.8.3 6 6 Requires PHP: 7.4 7 Stable tag: 1.5. 77 Stable tag: 1.5.8 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Create customizable popups using Elementor Free. Lightweight and easy to use— no coding or Elementor Pro required.11 Create powerful, customizable popups with **Elementor Free** — no coding or Elementor Pro required. 12 12 13 13 == Description == 14 14 15 **Popup for Elementor** brings a native popup widget to **Elementor Free**. Design beautiful, responsive popups directly inside the Elementor editor with full control over appearance, triggers, and behavior. 15 **Popup for Elementor** is the easiest and most lightweight popup builder for **Elementor Free**. 16 Design responsive, conversion-focused popups directly inside Elementor with full visual control — 100% no-code and performance-optimized. 16 17 17 No need for Elementor Pro or third-party modal plugins. Everything you need is built-in.18 Unlike other popup plugins, this one works **without Elementor Pro** and **without third-party modal builders**. Everything is native, simple, and fast. 18 19 19 ### Features Included in the Free Version20 ### 🔹 Key Features 20 21 21 – **Design Freedom **22 Create pixel-perfect popups with Elementor. Customize layout, colors, borders, padding, animations, close button, overlay, and more.22 – **Design Freedom with Elementor** 23 Build beautiful popups visually. Control layout, colors, padding, overlay, borders, animations, and close buttons. 23 24 24 – ** Trigger Options (Free)**25 – **Free Trigger Options (No Pro Needed)** 25 26 – Show on page load 26 27 – Show after a delay (in seconds) 27 – Show on exit intent 28 – Option to show only once (cookie-based) 28 – Show on exit intent *(improved)* 29 – Show on click *(new in 1.5.8)* 30 – Option to show only once (cookie-based, now works with all triggers) 29 31 30 – ** Popup Behavior Controls**32 – **Smart Popup Behavior** 31 33 – Close popup on ESC key 32 34 – Close when clicking outside (overlay) 33 – Option to disable right-click inside the popup35 – Option to disable right-click inside popup content 34 36 35 37 – **Elementor Template Integration** 36 – Load any Elementor template inside the popup for maximumflexibility38 – Load any Elementor section or saved template directly inside the popup for ultimate flexibility 37 39 38 – **Performance Focused**39 – Clean and lightweight code40 – Optimized loading41 – Fully responsive 42 – Compatiblewith any WordPress theme40 – **Performance-First** 41 – Lightweight JavaScript and CSS 42 – Clean code, no dependencies 43 – Fully responsive and SEO-friendly 44 – Works with any WordPress theme 43 45 44 46 – **No Elementor Pro Required** 45 All features are 100% compatible with **Elementor Free**47 Every feature works natively with **Elementor Free**. 46 48 47 **Pro version available** (optional): 48 The Pro version includes additional features and triggers, such as: 49 – Show on scroll 50 – Show on click 51 – Show on user inactivity 52 – Show based on referral URL 53 – Show on specific URLs or schedules 54 – Show based on login status 49 **Optional Pro Version:** 50 Adds advanced targeting and automation features: 51 – Scroll-based and inactivity triggers 52 – Referral URL and login-based display 53 – Time-scheduled popups 55 54 – AdBlock detection 56 – Dynamic content loading with enhanced performance 57 58 The free version works independently and does not require the Pro version. 55 – Dynamic content loading for speed and personalization 59 56 60 57 **Official Website:** https://www.popupforelementor.com … … 62 59 **Support:** [email protected] 63 60 We respond to support requests within 48 hours. 64 Live chat is also available on the officialwebsite with typical response times between 2 and 3 hours.61 Live chat available on our website with typical response times between 2 and 3 hours. 65 62 66 63 == Installation == 67 64 68 65 1. Download the plugin ZIP file. 69 2. In your WordPress admin, go to **Plugins >Add New**.66 2. In your WordPress admin, go to **Plugins → Add New**. 70 67 3. Click **Upload Plugin** and select the downloaded file. 71 68 4. Click **Install Now**, then **Activate**. 72 5. Go to **Elementor > Widgets** and search for **Popup for Elementor**.69 5. In Elementor, search for **Popup for Elementor** in the widget panel. 73 70 74 71 == Frequently Asked Questions == 75 72 76 73 = Do I need Elementor Pro? = 77 No. This plugin works perfectly with **Elementor Free**. 74 No. Popup for Elementor works perfectly with **Elementor Free**. 75 76 = How do I make a popup appear when users click a button or link? = 77 Use the new **Click Trigger** (added in version 1.5.8). 78 You can set a CSS selector or Elementor element to open the popup. 78 79 79 80 = Can I control when the popup appears? = 80 Yes . You can configure triggers: on load, after delay, or when the user is about to exit the page.81 Yes — you can trigger it **on load**, **after a delay**, **on click**, or **on exit intent**. 81 82 82 = Can I prevent the popup from showing multiple times? =83 Yes. You can activate the "show only once" option, which uses cookies to prevent repeated popups.83 = Can I show the popup only once? = 84 Yes. Enable the **Show only once** option to use a cookie that prevents the popup from appearing again. 84 85 85 86 = Can I use Elementor templates inside the popup? = 86 Absolutely. You can insert any Elementor section or templateinside the popup container.87 Absolutely. Load any Elementor template or section inside the popup container. 87 88 88 89 == Screenshots == 89 90 90 1. Popup settings inside the Elementor editor91 2. Trigger sand visibility controls91 1. Popup widget settings inside the Elementor editor 92 2. Trigger and visibility controls 92 93 3. Popup design customization 93 94 4. Example popup rendered on the page 94 5. Elementor template loaded in a popup95 5. Elementor template loaded inside a popup 95 96 96 97 == Changelog == 98 99 = 1.5.8 = 100 * **New:** Added **Click Trigger** to the free version (previously Pro only). 101 * **Improved:** Exit Intent detection logic rewritten for smoother, more accurate behavior. 102 * **Improved:** “Show only once” option now works across all triggers. 103 * **Fix:** Minor issues when combining multiple triggers. 104 * **Update:** Tested up to WordPress 6.8.3 and Elementor 3.22+. 105 * **UI:** Minor visual and label adjustments in the widget controls. 97 106 98 107 = 1.5.7 = … … 115 124 * Integrated cookie-based visibility control. 116 125 * Full Elementor Free compatibility. 117 * Pro version (optional) adds extended triggers: On Scroll, On Click, Referral-based, Inactivity, Schedule-based, Login detection, and AdBlock detection.126 * Pro version adds advanced targeting: scroll, referral, inactivity, schedule, login, and AdBlock detection. 118 127 119 128 == Upgrade Notice == 120 129 121 = 1.5.7 = 122 Recommended update: improves stability, fixes close button behavior, and ensures compatibility with WordPress 6.9. 130 = 1.5.8 = 131 🚀 Major update! Adds **Click Trigger** to the free version, improves Exit Intent detection, and enhances “Show only once” cookie logic. 132 Recommended update for all users. -
popup-for-elementor/trunk/assets/popup-widget.js
r3300275 r3380762 5 5 const cookieExpiry = parseInt(config.cookieExpiry, 10) || 7; 6 6 const delayInMilliseconds = parseInt(config.delay, 10) || 0; 7 const isSelectorMode = (config.triggerBySelector === 'yes' && config.triggerSelector && config.triggerSelector.trim() !== ''); 8 7 9 let isClosing = false; 8 10 let popupOpenedAt = 0; // marca de última apertura (ms) 11 let lastExitTs = 0; // anti-rebote de exit-intent (ms) 12 const EXIT_COOLDOWN_MS = 1200; 13 9 14 const $popupOverlay = $('.popup-overlay'); 10 15 const $popupContent = $popupOverlay.find('.popup-content'); … … 44 49 45 50 console.log("Showing popup."); 51 popupOpenedAt = Date.now(); 46 52 $popupOverlay.css({ 47 53 display: 'flex', … … 59 65 function closePopup() { 60 66 console.log("Attempting to close popup..."); 67 68 if (popupOpenedAt && (Date.now() - popupOpenedAt) < 250) { 69 console.log("Close ignored due to debounce after open."); 70 return; 71 } 72 61 73 if (isClosing) { 62 74 console.log("Popup is already closing. Aborting."); 63 75 return; 64 76 } 65 77 66 78 isClosing = true; 67 79 console.log("Closing popup..."); 68 80 81 let handled = false; 69 82 $popupContent 70 .removeClass('animate__fadeIn') 71 .addClass('animate__fadeOut') 72 .one('animationend webkitAnimationEnd oAnimationEnd MSAnimationEnd', function () { 83 .removeClass('animate__fadeIn') 84 .addClass('animate__fadeOut') 85 .one('animationend', function (e) { 86 if (handled) return; 87 if (e.target !== this) return; 88 handled = true; 89 73 90 console.log("Fade-out animation ended. Hiding popup."); 74 91 $popupOverlay.css({ … … 77 94 opacity: 0, 78 95 }); 79 $popupContent.removeClass('animate__fadeOut'); 80 isClosing = false; 96 $popupContent.removeClass('animate__fadeOut'); 97 isClosing = false; 81 98 console.log("Popup closed successfully."); 82 99 }); 83 100 84 101 setTimeout(() => { 85 if ( isClosing) {102 if (!handled) { 86 103 console.warn("Fallback triggered: Forcing popup closure."); 104 handled = true; 87 105 $popupOverlay.css({ 88 106 display: 'none', … … 91 109 }); 92 110 $popupContent.removeClass('animate__fadeOut'); 93 isClosing = false; 94 } 95 }, 500); 96 } 111 isClosing = false; 112 } 113 }, 700); 114 } 115 97 116 98 117 function handlePopupDisplay() { … … 122 141 if (config.exitIntent === 'yes') { 123 142 console.log("IntentExit habilitado."); 143 124 144 $(document).on('mouseleave', function (e) { 125 console.log(`Intento de salida detectado: clientY = ${e.clientY}`); 126 if (e.clientY < 0) { 145 const now = Date.now(); 146 const nearTop = (e.clientY <= 0 || e.clientY <= 20); 147 const leavingWindow = (e.relatedTarget === null); 148 149 console.log(`Intento de salida: clientY=${e.clientY}, nearTop=${nearTop}, leaving=${leavingWindow}`); 150 151 if (config.exitIntentDisplayMode === 'once' && getCookie(cookieName)) { 152 console.log('ExitIntent en modo "once" y cookie presente. No se muestra.'); 153 return; 154 } 155 156 if (isClosing || (popupOpenedAt && (now - popupOpenedAt) < 250)) { 157 console.log('Ignorado: está cerrando o se acaba de abrir.'); 158 return; 159 } 160 161 if (now - lastExitTs < EXIT_COOLDOWN_MS) { 162 console.log('Cooldown activo. Ignorando ExitIntent repetido.'); 163 return; 164 } 165 166 if (nearTop || leavingWindow) { 167 lastExitTs = now; 127 168 console.log("Mostrando popup por IntentExit."); 128 169 showPopup(); 170 171 if (config.exitIntentDisplayMode === 'once') { 172 setCookie(cookieName, 'true', cookieExpiry); 173 console.log(`Cookie "${cookieName}" marcada por ExitIntent durante ${cookieExpiry} días.`); 174 } 129 175 } 130 176 }); … … 132 178 console.log("IntentExit no habilitado."); 133 179 } 134 if (config.showOnScroll === 'yes') { 135 console.log(`On Scroll habilitado. Porcentaje configurado: ${config.scrollPercentage}%`); 136 137 let scrollTriggered = false; 138 139 $(window).on('scroll', function () { 140 if (scrollTriggered) return; 141 142 const scrollTop = $(window).scrollTop(); 143 const windowHeight = $(window).height(); 144 const documentHeight = $(document).height(); 145 const scrolledPercentage = (scrollTop / (documentHeight - windowHeight)) * 100; 146 147 if (scrolledPercentage >= config.scrollPercentage) { 148 console.log(`Porcentaje de scroll alcanzado: ${scrolledPercentage.toFixed(2)}%`); 149 showPopup(); 150 scrollTriggered = true; 151 $(window).off('scroll'); 152 } 153 }); 154 } else { 155 console.log("On Scroll no habilitado."); 156 } 180 157 181 158 182 $popupOverlay.on('click', function (e) { … … 170 194 }); 171 195 172 handlePopupDisplay(); 173 }); 174 })(jQuery); 196 if (isSelectorMode) { 197 const raw = config.triggerSelector.trim(); 198 const selector = /^[.#]/.test(raw) ? raw : ('.' + raw); 199 $(document).off('click.popupfeSelector'); 200 console.log('[PopupFE] Trigger por selector activo →', selector, '| matches:', document.querySelectorAll(selector).length); 201 $(document).on('click.popupfeSelector', selector, function(e){ 202 if ($popupOverlay.is(':visible') || isClosing) return; 203 showPopup(); 204 }); 205 } 206 207 208 handlePopupDisplay(); 209 }); 210 })(jQuery); 211 -
popup-for-elementor/trunk/includes/editor-options.php
r3300275 r3380762 1 1 <?php 2 // Adds options to Elementor editor for configuring the popup 3 if ( ! defined( 'ABSPATH' ) ) { 4 exit; // Exit if accessed directly 2 // File: popup-handler.php 3 // Dynamically passes configuration from Elementor controls to the JavaScript. 4 5 if (!defined('ABSPATH')) { 6 exit; 5 7 } 6 class Popupfe_Popup_Widget extends \Elementor\Widget_Base 8 function popup_for_elementor_register_assets() 7 9 { 8 public function get_name() 9 { 10 return "popup_widget"; 11 } 12 public function get_title() 13 { 14 return esc_html__("Popup Widget", "popup-for-elementor"); 15 } 10 if (!is_admin()) { 11 wp_register_script( 12 'popup-widget-js', 13 plugin_dir_url(__FILE__) . '../assets/popup-widget.js', 14 array('jquery'), 15 '1.0.0', 16 true 17 ); 18 $post_id = get_the_ID(); 16 19 17 public function get_categories() 18 { 19 return ["basic"]; 20 } 21 public function get_icon() { 22 return 'eicon-table-of-contents'; 23 } 24 25 protected function _register_controls() 26 { 27 // Content controls 28 $this->start_controls_section("content_section", [ 29 "label" => esc_html__("Content", "popup-for-elementor"), 30 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 31 ]); 32 33 $templates = []; 34 if (class_exists("\Elementor\Plugin")) { 35 $template_manager = \Elementor\Plugin::instance()->templates_manager->get_source( 36 "local" 20 if ($post_id) { 21 $dynamic_config = array( 22 'showOnLoad' => get_post_meta($post_id, '_elementor_popup_show_on_load', true) ?: 'no', 23 'delay' => (int) get_post_meta($post_id, '_elementor_popup_delay', true) ?: 0, 24 'showOnScroll' => get_post_meta($post_id, '_elementor_popup_show_on_scroll', true) === 'yes', 25 'scrollPercentage' => (int) (get_post_meta($post_id, '_elementor_popup_scroll_percentage', true) ?: 50), 26 'exitIntent' => get_post_meta($post_id, '_elementor_popup_exit_intent', true) === 'yes', 27 'exitIntentDisplayMode'=> get_post_meta($post_id, '_elementor_exit_intent_display_mode', true) ?: 'always', 28 'cookieName' => 'popup_seen', 29 'cookieExpiry' => 7, 30 'triggerBySelector' => get_post_meta($post_id, '_elementor_trigger_selector_enabled', true) === 'yes', 31 'triggerSelector' => get_post_meta($post_id, '_elementor_trigger_selector', true) ?: '', 32 37 33 ); 38 $templates_raw = $template_manager39 ? $template_manager->get_items()40 : [];41 foreach ($templates_raw as $template) {42 $ templates[$template["template_id"]] = $template["title"];43 }34 35 wp_localize_script( 36 'popup-widget-js', 37 'PopupForElementorConfig', 38 $dynamic_config 39 ); 44 40 } 45 46 $this->add_control("template_id", [ 47 "label" => esc_html__("Select Template", "popup-for-elementor"), 48 "type" => \Elementor\Controls_Manager::SELECT2, // Cambiado a SELECT2 49 "options" => $templates, // Asegúrate de que $templates tiene las opciones disponibles 50 "default" => "", 51 "description" => esc_html__( 52 "Choose a template from your Elementor library.", 53 "popup-for-elementor" 54 ), 55 ]); 56 57 $this->add_control("template_create_link", [ 58 "type" => \Elementor\Controls_Manager::RAW_HTML, 59 "raw" => sprintf( 60 '<a href="%s" target="_blank" class="elementor-button elementor-button-success" style="margin-top: 10px;">%s</a>', 61 admin_url("edit.php?post_type=elementor_library"), 62 esc_html__("Create New Template", "popup-for-elementor") 63 ), 64 "content_classes" => "elementor-control-field", 65 ]); 66 67 $this->add_control("upgrade_to_pro_notice1", [ 68 "type" => \Elementor\Controls_Manager::RAW_HTML, 69 "raw" => sprintf( 70 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 71 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 72 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 73 %s 74 </a> 75 </div>', 76 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 77 "https://popupforelementor.com/en/home/#buy", 78 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 79 ), 80 "content_classes" => "elementor-control-field", 81 ]); 82 83 $this->end_controls_section(); 84 85 // Style controls 86 $this->start_controls_section("style_section", [ 87 "label" => esc_html__("Popup window", "popup-for-elementor"), 88 "tab" => \Elementor\Controls_Manager::TAB_STYLE, 89 ]); 90 $this->add_responsive_control( 91 'popup_background', 92 [ 93 'label' => esc_html__('Background Color', 'popup-for-elementor'), 94 'type' => \Elementor\Controls_Manager::COLOR, 95 'selectors' => [ 96 '{{WRAPPER}} .popup-content' => 'background-color: {{VALUE}};', 97 ], 98 ] 99 ); 100 101 $this->add_control("overlay_color", [ 102 "label" => esc_html__("Overlay Color", "popup-for-elementor"), 103 "type" => \Elementor\Controls_Manager::COLOR, 104 "default" => "rgba(0, 0, 0, 0.5)", 105 "selectors" => [ 106 "{{WRAPPER}} .popup-overlay" => "background-color: {{VALUE}};", 107 ], 108 ]); 109 110 $this->add_control("border_radius", [ 111 "label" => esc_html__("Border Radius", "popup-for-elementor"), 112 "type" => \Elementor\Controls_Manager::SLIDER, 113 "default" => [ 114 "size" => 10, 115 ], 116 "selectors" => [ 117 "{{WRAPPER}} .popup-content" => 118 "border-radius: {{SIZE}}{{UNIT}};", 119 ], 120 ]); 121 122 $this->add_group_control( 123 \Elementor\Group_Control_Box_Shadow::get_type(), 124 [ 125 "name" => "popup_box_shadow", 126 "label" => esc_html__("Box Shadow", "popup-for-elementor"), 127 "selector" => "{{WRAPPER}} .popup-content", 128 "description" => esc_html__( 129 "Configure the shadow settings directly.", 130 "popup-for-elementor" 131 ), 132 ] 133 ); 134 135 $this->add_responsive_control("popup_width", [ 136 "label" => esc_html__("Popup Width", "popup-for-elementor"), 137 "type" => \Elementor\Controls_Manager::SELECT, 138 "default" => "400px", 139 "options" => [ 140 "auto" => esc_html__("Auto (Fit Content)", "popup-for-elementor"), 141 "custom" => esc_html__("Custom", "popup-for-elementor"), 142 ], 143 "selectors" => [ 144 "{{WRAPPER}} .popup-content" => "width: {{VALUE}};", 145 ], 146 ]); 147 148 $this->add_responsive_control("custom_popup_width", [ 149 "label" => esc_html__("Custom Width", "popup-for-elementor"), 150 "type" => \Elementor\Controls_Manager::SLIDER, 151 "default" => [ 152 "size" => 400, 153 "unit" => "px", 154 ], 155 "size_units" => ["px", "%", "vw"], 156 "range" => [ 157 "px" => [ 158 "min" => 100, 159 "max" => 2000, 160 "step" => 10, 161 ], 162 "%" => [ 163 "min" => 1, 164 "max" => 100, 165 ], 166 "vw" => [ 167 "min" => 1, 168 "max" => 100, 169 ], 170 ], 171 "condition" => [ 172 "popup_width" => "custom", 173 ], 174 "selectors" => [ 175 "{{WRAPPER}} .popup-content" => "width: {{SIZE}}{{UNIT}};", 176 ], 177 ]); 178 179 180 $this->add_responsive_control("popup_height", [ 181 "label" => esc_html__("Popup Height", "popup-for-elementor"), 182 "type" => \Elementor\Controls_Manager::SELECT, 183 "default" => "auto", 184 "options" => [ 185 "auto" => esc_html__("Auto (Fit Content)", "popup-for-elementor"), 186 "custom" => esc_html__("Custom", "popup-for-elementor"), 187 ], 188 "selectors" => [ 189 "{{WRAPPER}} .popup-content" => "height: {{VALUE}};", 190 ], 191 ]); 192 193 $this->add_responsive_control("custom_popup_height", [ 194 "label" => esc_html__("Custom Height", "popup-for-elementor"), 195 "type" => \Elementor\Controls_Manager::SLIDER, 196 "default" => [ 197 "size" => 400, 198 "unit" => "px", 199 ], 200 "size_units" => ["px", "%", "vh"], 201 "range" => [ 202 "px" => [ 203 "min" => 100, 204 "max" => 2000, 205 "step" => 10, 206 ], 207 "%" => [ 208 "min" => 1, 209 "max" => 100, 210 ], 211 "vh" => [ 212 "min" => 1, 213 "max" => 100, 214 ], 215 ], 216 "condition" => [ 217 "popup_height" => "custom", 218 ], 219 "selectors" => [ 220 "{{WRAPPER}} .popup-content" => "height: {{SIZE}}{{UNIT}};", 221 ], 222 ]); 223 224 225 226 $this->add_responsive_control("horizontal_position", [ 227 "label" => esc_html__("Horizontal Position", "popup-for-elementor"), 228 "type" => \Elementor\Controls_Manager::CHOOSE, 229 "options" => [ 230 "flex-start" => [ 231 "title" => esc_html__("Left", "popup-for-elementor"), 232 "icon" => "eicon-h-align-left", 233 ], 234 "center" => [ 235 "title" => esc_html__("Center", "popup-for-elementor"), 236 "icon" => "eicon-h-align-center", 237 ], 238 "flex-end" => [ 239 "title" => esc_html__("Right", "popup-for-elementor"), 240 "icon" => "eicon-h-align-right", 241 ], 242 ], 243 "default" => "center", 244 "selectors" => [ 245 "{{WRAPPER}} .popup-overlay" => "justify-content: {{VALUE}};", 246 ], 247 ]); 248 249 $this->add_responsive_control("vertical_position", [ 250 "label" => esc_html__("Vertical Position", "popup-for-elementor"), 251 "type" => \Elementor\Controls_Manager::CHOOSE, 252 "options" => [ 253 "flex-start" => [ 254 "title" => esc_html__("Top", "popup-for-elementor"), 255 "icon" => "eicon-v-align-top", 256 ], 257 "center" => [ 258 "title" => esc_html__("Center", "popup-for-elementor"), 259 "icon" => "eicon-v-align-middle", 260 ], 261 "flex-end" => [ 262 "title" => esc_html__("Bottom", "popup-for-elementor"), 263 "icon" => "eicon-v-align-bottom", 264 ], 265 ], 266 "default" => "center", 267 "selectors" => [ 268 "{{WRAPPER}} .popup-overlay" => "align-items: {{VALUE}};", 269 ], 270 ]); 271 272 // Control para el margen (Responsive) 273 $this->add_responsive_control( 274 'popup_margin', 275 [ 276 'label' => esc_html__('Margin', 'popup-for-elementor'), 277 'type' => \Elementor\Controls_Manager::DIMENSIONS, 278 'size_units' => ['px', '%', 'em'], 279 'selectors' => [ 280 '{{WRAPPER}} .popup-content' => 'margin: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 281 ], 282 ] 283 ); 284 285 // Control para el padding (Responsive) 286 $this->add_responsive_control( 287 'popup_padding', 288 [ 289 'label' => esc_html__('Padding', 'popup-for-elementor'), 290 'type' => \Elementor\Controls_Manager::DIMENSIONS, 291 'size_units' => ['px', '%', 'em'], 292 'selectors' => [ 293 '{{WRAPPER}} .popup-content' => 'padding: {{TOP}}{{UNIT}} {{RIGHT}}{{UNIT}} {{BOTTOM}}{{UNIT}} {{LEFT}}{{UNIT}};', 294 ], 295 ] 296 ); 297 298 299 $this->end_controls_section(); 300 301 // Animation 302 303 $this->start_controls_section("animation_section_custom", [ 304 "label" => esc_html__("Animation", "popup-for-elementor"), 305 "tab" => \Elementor\Controls_Manager::TAB_STYLE, // Colocamos esta sección en la pestaña de estilo 306 ]); 307 308 $this->add_control("popup_animation_in", [ 309 "label" => esc_html__("Entrance Animation", "popup-for-elementor"), 310 "type" => \Elementor\Controls_Manager::SELECT, 311 "options" => [ 312 "none" => esc_html__("None", "popup-for-elementor"), 313 "animate__fadeIn" => esc_html__("Fade In", "popup-for-elementor"), 314 "animate__fadeInUp" => esc_html__("Fade In Up", "popup-for-elementor"), 315 "anixmate__fadeInDown" => esc_html__("Fade In Down", "popup-for-elementor"), 316 "animate__fadeInLeft" => esc_html__("Fade In Left", "popup-for-elementor"), 317 "animate__fadeInRight" => esc_html__("Fade In Right", "popup-for-elementor"), 318 "animate__zoomIn" => esc_html__("Zoom In", "popup-for-elementor"), 319 "animate__slideInUp" => esc_html__("Slide In Up", "popup-for-elementor"), 320 "animate__slideInDown" => esc_html__("Slide In Down", "popup-for-elementor"), 321 "animate__slideInLeft" => esc_html__("Slide In Left", "popup-for-elementor"), 322 "animate__slideInRight" => esc_html__("Slide In Right", "popup-for-elementor"), 323 ], 324 "default" => "animate__fadeIn", 325 "description" => esc_html__( 326 "Choose an animation for the popup to appear.", 327 "popup-for-elementor" 328 ), 329 ]); 330 331 $this->add_control("popup_animation_out", [ 332 "label" => esc_html__("Exit Animation", "popup-for-elementor"), 333 "type" => \Elementor\Controls_Manager::SELECT, 334 "options" => [ 335 "none" => esc_html__("None", "popup-for-elementor"), 336 "animate__fadeOut" => esc_html__("Fade Out", "popup-for-elementor"), 337 "animate__fadeOutUp" => esc_html__("Fade Out Up", "popup-for-elementor"), 338 "animate__fadeOutDown" => esc_html__("Fade Out Down", "popup-for-elementor"), 339 "animate__fadeOutLeft" => esc_html__("Fade Out Left", "popup-for-elementor"), 340 "animate__fadeOutRight" => esc_html__("Fade Out Right", "popup-for-elementor"), 341 "animate__zoomOut" => esc_html__("Zoom Out", "popup-for-elementor"), 342 "animate__slideOutUp" => esc_html__("Slide Out Up", "popup-for-elementor"), 343 "animate__slideOutDown" => esc_html__("Slide Out Down", "popup-for-elementor"), 344 "animate__slideOutLeft" => esc_html__("Slide Out Left", "popup-for-elementor"), 345 "animate__slideOutRight" => esc_html__( 346 "Slide Out Right", 347 "popup-for-elementor" 348 ), 349 ], 350 "default" => "animate__fadeOut", 351 "description" => esc_html__( 352 "Choose an animation for the popup to disappear.", 353 "popup-for-elementor" 354 ), 355 ]); 356 357 $this->add_control("animation_duration_custom", [ 358 "label" => esc_html__("Animation Duration (ms)", "popup-for-elementor"), 359 "type" => \Elementor\Controls_Manager::SLIDER, 360 "size_units" => ["ms"], 361 "range" => [ 362 "ms" => [ 363 "min" => 100, 364 "max" => 3000, 365 "step" => 100, 366 ], 367 ], 368 "default" => [ 369 "size" => 500, 370 "unit" => "ms", 371 ], 372 "selectors" => [ 373 "{{WRAPPER}} .popup-content" => 374 "animation-duration: {{SIZE}}{{UNIT}};", 375 ], 376 ]); 377 378 $this->end_controls_section(); 379 //Close Button 380 381 $this->start_controls_section("close_button_section", [ 382 "label" => esc_html__("Close Button", "popup-for-elementor"), 383 "tab" => \Elementor\Controls_Manager::TAB_STYLE, 384 ]); 385 $this->add_control("hide_close_button", [ 386 "label" => esc_html__("Hide Close Button", "popup-for-elementor"), 387 "type" => \Elementor\Controls_Manager::SWITCHER, 388 "label_on" => esc_html__("Yes", "popup-for-elementor"), 389 "label_off" => esc_html__("No", "popup-for-elementor"), 390 "return_value" => "yes", 391 "default" => "no", 392 "selectors" => [ 393 "{{WRAPPER}} .popup-close" => "display: none;", 394 ], 395 ]); 396 397 $this->add_control("close_button_background_color", [ 398 "label" => esc_html__("Close Button Background", "popup-for-elementor"), 399 "type" => \Elementor\Controls_Manager::COLOR, 400 "selectors" => [ 401 "{{WRAPPER}} .popup-close" => "background-color: {{VALUE}};", 402 ], 403 ]); 404 405 $this->add_control("close_button_hover_background_color", [ 406 "label" => esc_html__("Close Button Hover Background", "popup-for-elementor"), 407 "type" => \Elementor\Controls_Manager::COLOR, 408 "selectors" => [ 409 "{{WRAPPER}} .popup-close:hover" => 410 "background-color: {{VALUE}};", 411 ], 412 ]); 413 414 $this->add_control("close_button_color", [ 415 "label" => esc_html__("Close Button Color", "popup-for-elementor"), 416 "type" => \Elementor\Controls_Manager::COLOR, 417 "selectors" => [ 418 "{{WRAPPER}} .popup-close" => "color: {{VALUE}};", 419 ], 420 ]); 421 422 $this->add_control("close_button_hover_color", [ 423 "label" => esc_html__("Close Button Hover Color", "popup-for-elementor"), 424 "type" => \Elementor\Controls_Manager::COLOR, 425 "selectors" => [ 426 "{{WRAPPER}} .popup-close:hover" => "color: {{VALUE}};", 427 ], 428 ]); 429 430 $this->add_control("close_button_size", [ 431 "label" => esc_html__("Close Button Size", "popup-for-elementor"), 432 "type" => \Elementor\Controls_Manager::SLIDER, 433 "size_units" => ["px"], // Solo permite px 434 "range" => [ 435 "px" => [ 436 "min" => 10, 437 "max" => 100, 438 ], 439 ], 440 "default" => [ 441 "unit" => "px", 442 "size" => 40, // Tamaño por defecto del botón de cerrar 443 ], 444 "selectors" => [ 445 "{{WRAPPER}} .popup-close" => 446 "width: {{SIZE}}{{UNIT}}; height: {{SIZE}}{{UNIT}}; font-size: calc({{SIZE}}{{UNIT}} / 2);", 447 ], 448 "description" => esc_html__( 449 "Adjust the size of the close button.", 450 "popup-for-elementor" 451 ), 452 ]); 453 $this->add_control("close_button_alignment", [ 454 "label" => esc_html__("Close Button Alignment", "popup-for-elementor"), 455 "type" => \Elementor\Controls_Manager::CHOOSE, 456 "options" => [ 457 "left" => [ 458 "title" => esc_html__("Left", "popup-for-elementor"), 459 "icon" => "eicon-h-align-left", 460 ], 461 "right" => [ 462 "title" => esc_html__("Right", "popup-for-elementor"), 463 "icon" => "eicon-h-align-right", 464 ], 465 ], 466 "default" => "right", 467 "selectors" => [ 468 "{{WRAPPER}} .popup-close" => "{{VALUE}}: 10px;", 469 ], 470 "description" => esc_html__( 471 "Align the close button to the left or right.", 472 "popup-for-elementor" 473 ), 474 ]); 475 476 $this->add_control("close_button_border_radius", [ 477 "label" => esc_html__("Close Button Border Radius", "popup-for-elementor"), 478 "type" => \Elementor\Controls_Manager::SLIDER, 479 "size_units" => ["px"], // Solo permite px 480 "range" => [ 481 "px" => [ 482 "min" => 0, 483 "max" => 50, 484 ], 485 ], 486 "selectors" => [ 487 "{{WRAPPER}} .popup-close" => 488 "border-radius: {{SIZE}}{{UNIT}};", 489 ], 490 "description" => esc_html__( 491 "Controls the border radius of the close button.", 492 "popup-for-elementor" 493 ), 494 ]); 495 496 $this->end_controls_section(); 497 498 // Visibility controls 499 $this->start_controls_section("visibility_section", [ 500 "label" => esc_html__("Visibility", "popup-for-elementor"), 501 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 502 ]); 503 504 $this->add_control("show_on_load", [ 505 "label" => esc_html__("Show on Page Load", "popup-for-elementor"), 506 "type" => \Elementor\Controls_Manager::SWITCHER, 507 "default" => "", 508 "description" => esc_html__("Activate to show popup when the page loads. Will disable other visibility options.", "popup-for-elementor"), 509 "condition" => [ 510 "show_after_delay_enabled!" => "yes", 511 "show_on_exit_intent!" => "yes", 512 "show_once!" => "yes", 513 ], 514 ]); 515 516 $this->add_control("show_after_delay_enabled", [ 517 "label" => esc_html__("Enable Show After Delay", "popup-for-elementor"), 518 "type" => \Elementor\Controls_Manager::SWITCHER, 519 "default" => "", 520 "description" => esc_html__("Activate to show popup after a delay. Will disable other visibility options.", "popup-for-elementor"), 521 "condition" => [ 522 "show_on_load!" => "yes", 523 "show_on_exit_intent!" => "yes", 524 "show_once!" => "yes", 525 ], 526 ]); 527 528 $this->add_control("show_after_delay", [ 529 "label" => esc_html__("Delay (seconds)", "popup-for-elementor"), 530 "type" => \Elementor\Controls_Manager::NUMBER, 531 "default" => 3, 532 "condition" => [ 533 "show_after_delay_enabled" => "yes", 534 ], 535 ]); 536 537 $this->add_control("show_on_exit_intent", [ 538 "label" => esc_html__("Show on Exit Intent", "popup-for-elementor"), 539 "type" => \Elementor\Controls_Manager::SWITCHER, 540 "default" => "", 541 "description" => esc_html__("Activate to show popup when the user intends to exit. Will disable other visibility options.", "popup-for-elementor"), 542 "condition" => [ 543 "show_on_load!" => "yes", 544 "show_after_delay_enabled!" => "yes", 545 "show_once!" => "yes", 546 ], 547 ]); 548 $this->add_control("show_once", [ 549 "label" => esc_html__("Show Only Once", "popup-for-elementor"), 550 "type" => \Elementor\Controls_Manager::SWITCHER, 551 "default" => "", 552 "description" => esc_html__("Show the popup only once per session.", "popup-for-elementor"), 553 "condition" => [ 554 "show_on_load!" => "yes", 555 "show_after_delay_enabled!" => "yes", 556 "show_on_exit_intent!" => "yes", 557 ], 558 ]); 559 560 $this->add_control("upgrade_to_pro_notice2", [ 561 "type" => \Elementor\Controls_Manager::RAW_HTML, 562 "raw" => sprintf( 563 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 564 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 565 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 566 %s 567 </a> 568 </div>', 569 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 570 "https://popupforelementor.com/en/home/#buy", 571 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 572 ), 573 "content_classes" => "elementor-control-field", 574 ]); 575 $this->end_controls_section(); 576 $this->start_controls_section("refresh_section", [ 577 "label" => esc_html__("Refresh", "popup-for-elementor"), 578 "tab" => \Elementor\Controls_Manager::TAB_CONTENT, 579 ]); 580 581 $this->add_control( 582 'refresh_popup', 583 [ 584 'label' => esc_html__('Refresh Popup', 'popup-for-elementor'), 585 'type' => \Elementor\Controls_Manager::BUTTON, 586 'button_type' => 'success', 587 'text' => esc_html__('Refresh', 'popup-for-elementor'), 588 'description' => esc_html__('Click to refresh the popup content.', 'popup-for-elementor'), 589 'frontend_available' => true, 590 ] 591 ); 592 $this->add_control("upgrade_to_pro_notice3", [ 593 "type" => \Elementor\Controls_Manager::RAW_HTML, 594 "raw" => sprintf( 595 '<div style="margin-top: 20px; padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 596 <strong style="display: block; color: #ffffff; font-size: 14px; font-weight: 300; margin-bottom: 12px;">%s</strong> 597 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 598 %s 599 </a> 600 </div>', 601 esc_html__("Need more triggers like Scroll, OnClick, or AdBlock detection?", "popup-for-elementor"), 602 "https://popupforelementor.com/en/home/#buy", 603 esc_html__("Get Popup for Elementor Pro", "popup-for-elementor") 604 ), 605 "content_classes" => "elementor-control-field", 606 ]); 607 $this->end_controls_section(); 608 $this->start_controls_section("upgrade_section", [ 609 "label" => esc_html__("Popup for Elementor (PRO)", "popup-for-elementor"), 610 "tab" => null, 611 ]); 612 613 $this->add_control("pro_upgrade_box", [ 614 "type" => \Elementor\Controls_Manager::RAW_HTML, 615 "raw" => sprintf( 616 '<div style="padding: 24px; background: linear-gradient(135deg, #1e1e1e, #2b2b2b); border: 1px solid #3c3c3c; border-radius: 8px; text-align: center; box-shadow: 0 2px 8px rgba(0,0,0,0.2);"> 617 <h3 style="color: #ffffff; font-size: 16px; margin-bottom: 12px; font-weight: 600;">%s</h3> 618 <p style="color: #bbbbbb; font-size: 13px; margin-bottom: 20px;">%s</p> 619 <a href="%s" target="_blank" style="display: inline-block; padding: 10px 20px; background-color: #d33a92; color: #fff; border-radius: 4px; text-decoration: none; font-weight: 600; transition: background-color 0.3s;"> 620 %s 621 </a> 622 </div>', 623 esc_html__("Unlock More Power", "popup-for-elementor"), 624 esc_html__("Upgrade to Pro and access all premium triggers and features.", "popup-for-elementor"), 625 "https://popupforelementor.com/en/home/#buy", 626 esc_html__("Upgrade to Pro", "popup-for-elementor") 627 ), 628 ]); 629 630 $this->end_controls_section(); 631 632 633 634 } 635 636 protected function render() 637 { 638 $settings = $this->get_settings_for_display(); 639 640 // Configuraciones dinámicas para pasar al script 641 $config = [ 642 'showOnLoad' => isset($settings['show_on_load']) && $settings['show_on_load'] === 'yes' ? 'yes' : 'no', 643 'delay' => isset($settings['show_after_delay']) ? (int) $settings['show_after_delay'] * 1000 : 0, 644 'exitIntent' => isset($settings['show_on_exit_intent']) && $settings['show_on_exit_intent'] === 'yes' ? 'yes' : 'no', 645 'showOnce' => isset($settings['show_once']) && $settings['show_once'] === 'yes' ? 'yes' : 'no', 646 'cookieName' => 'popup_seen', 647 'cookieExpiry' => 7, 648 ]; 649 650 // Pasar configuraciones dinámicas al script 651 wp_localize_script( 652 'popup-widget-js', 653 'PopupForElementorConfig', 654 $config 655 ); 656 657 658 // Obtener animaciones seleccionadas y duración 659 $animation_in = $settings['popup_animation_in'] ?? 'animate__fadeIn'; 660 $animation_out = $settings['popup_animation_out'] ?? 'animate__fadeOut'; 661 $animation_duration = isset($settings['animation_duration_custom']['size']) 662 ? (int) $settings['animation_duration_custom']['size'] 663 : 500; 664 665 // Renderizar plantilla de Elementor si está configurada 666 if (!empty($settings['template_id']) && class_exists('\Elementor\Plugin')) { 667 $popup_content = \Elementor\Plugin::instance()->frontend->get_builder_content_for_display($settings['template_id']); 668 669 if (\Elementor\Plugin::$instance->editor->is_edit_mode()) { 670 // Recuperar la URL del editor de Elementor 671 $edit_url = admin_url('post.php?post=' . absint($settings['template_id']) . '&action=elementor'); 672 673 // Solo eliminar etiquetas que no afecten la funcionalidad 674 $filtered_content = preg_replace('/<meta\b[^>]*>(.*?)<\/meta>/is', '', $popup_content); 675 $filtered_content = preg_replace('/<link\b[^>]*>(.*?)<\/link>/is', '', $filtered_content); 676 677 // Crear contenido para el modal 678 $popup_content = ' 679 <div class="elementor-template-button-wrapper" style="text-align: center; margin-top: 15px;"> 680 <a href="javascript:void(0);" 681 class="popup-edit-button elementor-button elementor-button-success elementor-size-sm button-edit-custom" 682 data-popup-id="' . esc_attr( 'popup_' . get_the_ID() . '_' . $settings['template_id'] ) . '" 683 data-edit-url="' . esc_url($edit_url) . '" 684 id="open-modal"> 685 <i class="eicon-edit" style="margin-right: 8px;"></i>' . esc_html__('Edit Template', 'popup-for-elementor') . ' 686 </a> 687 </div> 688 <div class="popup-editor-content"> 689 ' . $filtered_content . ' 690 </div>'; 41 wp_enqueue_script('popup-widget-js'); 691 42 } 692 43 } 44 add_action('wp_enqueue_scripts', 'popup_for_elementor_register_assets'); 693 45 46 add_action('admin_enqueue_scripts', function () { 47 wp_dequeue_script('popup-widget-js'); 48 wp_deregister_script('popup-widget-js'); 49 }, PHP_INT_MAX); 694 50 695 // Generar un identificador único para el popup696 $current_page_id = get_the_ID();697 $popup_id = get_post_meta($settings['template_id'], '_popup_id_' . $current_page_id, true);698 699 if (empty($popup_id)) {700 $popup_id = 'popup_' . $current_page_id . '_' . uniqid();701 update_post_meta($settings['template_id'], '_popup_id_' . $current_page_id, $popup_id);702 }703 704 // Renderizar el HTML del popup con ID único705 $styles = '';706 if (!defined('ELEMENTOR_VERSION') || !\Elementor\Plugin::$instance->editor->is_edit_mode()) {707 // Aplicar estilos para ocultar el popup fuera del editor708 $styles = 'display: none; visibility: hidden; opacity: 1;';709 }710 711 function filter_popup_content($content)712 {713 // Lista de etiquetas peligrosas a eliminar (pero manteniendo SVGs y estilos de Elementor)714 $dangerous_tags = ['iframe', 'embed', 'object', 'applet', 'meta', 'link'];715 716 foreach ($dangerous_tags as $tag) {717 $content = preg_replace('/<' . $tag . '.*?>.*?<\/' . $tag . '>/is', '', $content);718 $content = preg_replace('/<' . $tag . '.*?>/is', '', $content);719 }720 721 return $content;722 }723 724 /* Escaping is not applied here because the content has already been filtered725 by `filter_popup_content()`, which removes dangerous tags.726 Using `esc_html()` would break Elementor's functionality.727 This code has been reviewed and is safe. */728 729 $popup_content_filtered = filter_popup_content($popup_content);730 731 echo '<div id="' . esc_attr($popup_id) . '" class="popup-overlay popup-widget" style="' . esc_attr($styles) . '">732 <div class="popup-content animate__animated ' . esc_attr($animation_in) . '"733 style="position: relative; animation-duration: ' . esc_attr($animation_duration) . 'ms;">734 <button class="popup-close">×</button>';735 736 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped737 echo $popup_content_filtered;738 739 echo '</div></div>';740 741 // This script controls the popup behavior (open/close, animations, hover effects).742 // It must be injected directly here because Elementor dynamically refreshes widget content.743 // Using wp_enqueue_script or wp_add_inline_script would not persist across reloads.744 745 echo '<script>746 (function($) {747 $(document).ready(function() {748 const popup = $("#' .749 esc_attr($popup_id) .750 '");751 const popupContent = popup.find(".popup-content");752 753 if (popup.length) {754 // Abrir popup con animación de entrada755 popup.closest(".elementor-widget-popup_widget").off("click").on("click", function(e) {756 e.preventDefault();757 popup.css({758 display: "flex",759 visibility: "visible"760 });761 popupContent.removeClass("' .762 esc_attr($animation_out) .763 '").addClass("' .764 esc_attr($animation_in) .765 '");766 });767 768 // Cerrar popup con animación de salida769 popup.find(".popup-close").off("click").on("click", function(e) {770 e.stopPropagation();771 popupContent772 .removeClass("' .773 esc_attr($animation_in) .774 '")775 .addClass("' .776 esc_attr($animation_out) .777 '");778 779 // Esperar la duración de la animación antes de ocultar el popup780 const duration = ' .781 esc_attr($animation_duration) .782 ';783 setTimeout(function() {784 popup.css({785 display: "none",786 visibility: "hidden"787 });788 popupContent.removeClass("' .789 esc_attr($animation_out) .790 '");791 }, duration);792 });793 794 // Hover en el botón para cambiar el fondo del popup795 popup.find(".popup-edit-button").on("mouseenter", function() {796 popupContent.css("background-color", "#ffebf2");797 }).on("mouseleave", function() {798 popupContent.css("background-color", "");799 });800 } else {801 console.error("Popup element not found in the DOM.");802 }803 });804 elementor.hooks.addAction("panel/open_editor/widget", function (panel, model) {805 panel.$el.on("click", ".elementor-control-refresh_popup .elementor-button", function () {806 console.log("¡Botón clicado! Refrescando el widget...");807 808 // Simular un cambio en el modelo809 model.set("refresh_trigger", Date.now()); // Valor ficticio para forzar el cambio810 model.trigger("change"); // Notificar el cambio a Elementor811 812 // Verificar si Elementor actualiza la vista813 setTimeout(function () {814 console.log("Intentando recargar la vista previa...");815 elementor.reloadPreview(); // Forzar la recarga si no responde816 elementor.once("preview:loaded", function () {817 console.log("Vista previa recargada correctamente.");818 819 // Reabrir el popup después de recargar la vista previa820 const $popupOverlay = jQuery(".popup-overlay");821 if ($popupOverlay.length) {822 console.log("Reabriendo el popup...");823 $popupOverlay.css({824 display: "",825 visibility: "",826 opacity: 1,827 });828 console.log("Popup reabierto correctamente.");829 } else {830 console.error("No se encontró el popup en el DOM.");831 }832 });833 }, 500); // Fallback por si el trigger no es suficiente834 });835 });836 })(jQuery);837 </script>';838 839 // This script controls the custom modal editor outside the iframe (open, close, panel resize).840 // Since the modal is rendered outside the iframe (via editor/after_footer),841 // this script needs to access it using parent.jQuery.842 // It must be echoed directly to stay bound to the button rendered in the iframe.843 844 echo '<div id="custom-modal">845 <div class="modal-container">846 <div class="modal-header">847 <div class="modal-title" style="display: flex; align-items: center;">848 <div style="width: 40px; height: 40px; background-color: white; border-radius: 50%; display: flex; justify-content: center; align-items: center; margin-right: 10px;">849 <span class="eicon-table-of-contents" style="font-size: 20px; color: #333;"></span> <!-- Icono de Elementor -->850 </div>851 ' . esc_html__("Popup for Elementor", "popup-for-elementor") . '852 </div>853 <button id="close-modal">×</button>854 </div>855 <iframe id="modal-iframe" src=""></iframe>856 </div>857 </div>';858 859 echo '<script>860 (function($) {861 $(document).ready(function() {862 const $modal = $("#custom-modal");863 const $iframe = $("#modal-iframe");864 const $closeButton = $("#close-modal");865 866 let originalPanelStyles = {}; // Guardamos los estilos originales867 868 function refreshWidget() {869 console.log("Ejecutando refresh del widget...");870 if (typeof parent.elementor !== "undefined" && parent.elementor.reloadPreview) {871 parent.elementor.reloadPreview();872 parent.elementor.once("preview:loaded", function() {873 console.log("Vista previa recargada correctamente.");874 });875 }876 }877 878 function toggleElementorPanel(reduce) {879 if (typeof parent.jQuery !== "undefined") {880 const $panel = parent.jQuery("#elementor-panel");881 const $preview = parent.jQuery("#elementor-preview");882 883 if (reduce) {884 console.log("Guardando estado del panel y reduciéndolo...");885 originalPanelStyles = {886 width: $panel.css("width"),887 minWidth: $panel.css("min-width"),888 maxWidth: $panel.css("max-width"),889 overflow: $panel.css("overflow"),890 visibility: $panel.css("visibility"),891 opacity: $panel.css("opacity"),892 };893 894 $panel.css({895 "width": "60px",896 "min-width": "60px",897 "max-width": "60px",898 "overflow": "hidden",899 "visibility": "hidden",900 "opacity": "0",901 "transition": "width 0.3s ease-in-out"902 });903 904 $preview.css({905 "width": "calc(100% - 60px)",906 "transition": "width 0.3s ease-in-out"907 });908 } else {909 console.log("Restaurando el panel de Elementor...");910 $panel.css(originalPanelStyles);911 912 $preview.css({913 "width": "calc(100% - " + originalPanelStyles.width + ")"914 });915 }916 }917 }918 919 $("#open-modal").on("click", function() {920 console.log("Modal abierto, reduciendo panel en la ventana principal...");921 const editUrl = $(this).data("edit-url");922 $iframe.attr("src", editUrl);923 $modal.removeClass("hide").addClass("show");924 925 toggleElementorPanel(true);926 });927 928 $closeButton.on("click", function() {929 console.log("Cerrando modal, restaurando panel en la ventana principal...");930 $modal.removeClass("show").addClass("hide");931 932 setTimeout(() => {933 $iframe.attr("src", ""); // Limpiar el iframe934 toggleElementorPanel(false);935 refreshWidget();936 }, 300);937 });938 939 console.log("Script de reducción de panel cargado.");940 });941 })(jQuery);942 </script>';943 }944 } -
popup-for-elementor/trunk/popup-for-elementor.php
r3331799 r3380762 2 2 /** 3 3 * Plugin Name: Popup for Elementor 4 * Plugin URI: https:// popupforelementor.com5 * Description: Enhance your Elementor website with fully customizable popups. Includes triggers, animations, and advanced settings to improve user interaction andengagement.6 * Version: 1.5. 74 * Plugin URI: https://www.popupforelementor.com 5 * Description: Create powerful, fully customizable popups directly in Elementor Free — includes click, delay, load, and exit-intent triggers, animations, and smart visibility controls to boost user engagement. 6 * Version: 1.5.8 7 7 * Author: Veelo 8 8 * Author URI: https://www.veelo.es … … 11 11 * License: GPLv2 or later 12 12 * License URI: https://www.gnu.org/licenses/gpl-2.0.html 13 * Requires at least: 5. 613 * Requires at least: 5.8 14 14 * Requires PHP: 7.4 15 15 * Requires Plugins: elementor 16 * Tested up to: 6. 916 * Tested up to: 6.8.3 17 17 */ 18 18 19 19 20 -
popup-for-elementor/trunk/readme.txt
r3331799 r3380762 1 1 === Popup for Elementor === 2 2 Contributors: veelo 3 Tags: popup, elementor, modal, wordpress popup, elementor free 4 Requires at least: 5. 65 Tested up to: 6. 93 Tags: popup, elementor, modal, wordpress popup, elementor free, popup maker, popup builder, modal window 4 Requires at least: 5.8 5 Tested up to: 6.8.3 6 6 Requires PHP: 7.4 7 Stable tag: 1.5. 77 Stable tag: 1.5.8 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Create customizable popups using Elementor Free. Lightweight and easy to use— no coding or Elementor Pro required.11 Create powerful, customizable popups with **Elementor Free** — no coding or Elementor Pro required. 12 12 13 13 == Description == 14 14 15 **Popup for Elementor** brings a native popup widget to **Elementor Free**. Design beautiful, responsive popups directly inside the Elementor editor with full control over appearance, triggers, and behavior. 15 **Popup for Elementor** is the easiest and most lightweight popup builder for **Elementor Free**. 16 Design responsive, conversion-focused popups directly inside Elementor with full visual control — 100% no-code and performance-optimized. 16 17 17 No need for Elementor Pro or third-party modal plugins. Everything you need is built-in.18 Unlike other popup plugins, this one works **without Elementor Pro** and **without third-party modal builders**. Everything is native, simple, and fast. 18 19 19 ### Features Included in the Free Version20 ### 🔹 Key Features 20 21 21 – **Design Freedom **22 Create pixel-perfect popups with Elementor. Customize layout, colors, borders, padding, animations, close button, overlay, and more.22 – **Design Freedom with Elementor** 23 Build beautiful popups visually. Control layout, colors, padding, overlay, borders, animations, and close buttons. 23 24 24 – ** Trigger Options (Free)**25 – **Free Trigger Options (No Pro Needed)** 25 26 – Show on page load 26 27 – Show after a delay (in seconds) 27 – Show on exit intent 28 – Option to show only once (cookie-based) 28 – Show on exit intent *(improved)* 29 – Show on click *(new in 1.5.8)* 30 – Option to show only once (cookie-based, now works with all triggers) 29 31 30 – ** Popup Behavior Controls**32 – **Smart Popup Behavior** 31 33 – Close popup on ESC key 32 34 – Close when clicking outside (overlay) 33 – Option to disable right-click inside the popup35 – Option to disable right-click inside popup content 34 36 35 37 – **Elementor Template Integration** 36 – Load any Elementor template inside the popup for maximumflexibility38 – Load any Elementor section or saved template directly inside the popup for ultimate flexibility 37 39 38 – **Performance Focused**39 – Clean and lightweight code40 – Optimized loading41 – Fully responsive 42 – Compatiblewith any WordPress theme40 – **Performance-First** 41 – Lightweight JavaScript and CSS 42 – Clean code, no dependencies 43 – Fully responsive and SEO-friendly 44 – Works with any WordPress theme 43 45 44 46 – **No Elementor Pro Required** 45 All features are 100% compatible with **Elementor Free**47 Every feature works natively with **Elementor Free**. 46 48 47 **Pro version available** (optional): 48 The Pro version includes additional features and triggers, such as: 49 – Show on scroll 50 – Show on click 51 – Show on user inactivity 52 – Show based on referral URL 53 – Show on specific URLs or schedules 54 – Show based on login status 49 **Optional Pro Version:** 50 Adds advanced targeting and automation features: 51 – Scroll-based and inactivity triggers 52 – Referral URL and login-based display 53 – Time-scheduled popups 55 54 – AdBlock detection 56 – Dynamic content loading with enhanced performance 57 58 The free version works independently and does not require the Pro version. 55 – Dynamic content loading for speed and personalization 59 56 60 57 **Official Website:** https://www.popupforelementor.com … … 62 59 **Support:** [email protected] 63 60 We respond to support requests within 48 hours. 64 Live chat is also available on the officialwebsite with typical response times between 2 and 3 hours.61 Live chat available on our website with typical response times between 2 and 3 hours. 65 62 66 63 == Installation == 67 64 68 65 1. Download the plugin ZIP file. 69 2. In your WordPress admin, go to **Plugins >Add New**.66 2. In your WordPress admin, go to **Plugins → Add New**. 70 67 3. Click **Upload Plugin** and select the downloaded file. 71 68 4. Click **Install Now**, then **Activate**. 72 5. Go to **Elementor > Widgets** and search for **Popup for Elementor**.69 5. In Elementor, search for **Popup for Elementor** in the widget panel. 73 70 74 71 == Frequently Asked Questions == 75 72 76 73 = Do I need Elementor Pro? = 77 No. This plugin works perfectly with **Elementor Free**. 74 No. Popup for Elementor works perfectly with **Elementor Free**. 75 76 = How do I make a popup appear when users click a button or link? = 77 Use the new **Click Trigger** (added in version 1.5.8). 78 You can set a CSS selector or Elementor element to open the popup. 78 79 79 80 = Can I control when the popup appears? = 80 Yes . You can configure triggers: on load, after delay, or when the user is about to exit the page.81 Yes — you can trigger it **on load**, **after a delay**, **on click**, or **on exit intent**. 81 82 82 = Can I prevent the popup from showing multiple times? =83 Yes. You can activate the "show only once" option, which uses cookies to prevent repeated popups.83 = Can I show the popup only once? = 84 Yes. Enable the **Show only once** option to use a cookie that prevents the popup from appearing again. 84 85 85 86 = Can I use Elementor templates inside the popup? = 86 Absolutely. You can insert any Elementor section or templateinside the popup container.87 Absolutely. Load any Elementor template or section inside the popup container. 87 88 88 89 == Screenshots == 89 90 90 1. Popup settings inside the Elementor editor91 2. Trigger sand visibility controls91 1. Popup widget settings inside the Elementor editor 92 2. Trigger and visibility controls 92 93 3. Popup design customization 93 94 4. Example popup rendered on the page 94 5. Elementor template loaded in a popup95 5. Elementor template loaded inside a popup 95 96 96 97 == Changelog == 98 99 = 1.5.8 = 100 * **New:** Added **Click Trigger** to the free version (previously Pro only). 101 * **Improved:** Exit Intent detection logic rewritten for smoother, more accurate behavior. 102 * **Improved:** “Show only once” option now works across all triggers. 103 * **Fix:** Minor issues when combining multiple triggers. 104 * **Update:** Tested up to WordPress 6.8.3 and Elementor 3.22+. 105 * **UI:** Minor visual and label adjustments in the widget controls. 97 106 98 107 = 1.5.7 = … … 115 124 * Integrated cookie-based visibility control. 116 125 * Full Elementor Free compatibility. 117 * Pro version (optional) adds extended triggers: On Scroll, On Click, Referral-based, Inactivity, Schedule-based, Login detection, and AdBlock detection.126 * Pro version adds advanced targeting: scroll, referral, inactivity, schedule, login, and AdBlock detection. 118 127 119 128 == Upgrade Notice == 120 129 121 = 1.5.7 = 122 Recommended update: improves stability, fixes close button behavior, and ensures compatibility with WordPress 6.9. 130 = 1.5.8 = 131 🚀 Major update! Adds **Click Trigger** to the free version, improves Exit Intent detection, and enhances “Show only once” cookie logic. 132 Recommended update for all users.
Note: See TracChangeset
for help on using the changeset viewer.