1/** 2 * WP File Download - Elementor editor integration 3 * 4 * Runs inside the Elementor editor window (the parent of the WP File Download modal iframe). 5 * 6 * Since Elementor 4.1 the editor document is served with a "Document-Isolation-Policy" header, which can 7 * place the editor and the modal iframe in two different agent clusters. In that case any synchronous 8 * cross document access (iframe.contents(), window.parent.document, ...) is blocked by the browser. 9 * All the communication with the modal is therefore done with window.postMessage, and the modal is 10 * configured through the iframe URL instead of by reaching into its DOM. 11 */ 12 13/** 14 * Load the wp File Download Frame 15 */ 16function wpfd_elementor_frameload() { 17 jQuery("#wpfd_elementor_loader").hide(); 18 jQuery("#wpfdelementormodalframe").css('visibility', "visible"); 19 jQuery("#wpfdelementormodalframe").show(); 20} 21 22function wpfd_file_widget_trigger_controls() { 23 jQuery('.elementor-control.wpfd-file-id-controls input[data-setting="wpfd_file_id"]', window.document).trigger('input'); 24 jQuery('.elementor-control.wpfd-category-id-controls input[data-setting="wpfd_category_id"]', window.document).trigger('input'); 25 jQuery('.elementor-control.wpfd-file-name-controls input[data-setting="wpfd_file_name"]', window.document).trigger('input'); 26} 27 28function wpfd_category_widget_trigger_controls() { 29 jQuery('.elementor-control.elementor-control-wpfd_selected_category_id input[data-setting="wpfd_selected_category_id"]', window.document).trigger('input'); 30 jQuery('.elementor-control.elementor-control-wpfd_selected_category_name input[data-setting="wpfd_selected_category_name"]', window.document).trigger('input'); 31} 32 33function wpfd_pdf_embed_widget_trigger_controls() { 34 jQuery('.elementor-control.wpfd-pdf-embed-file-id-controls input[data-setting="wpfd_pdf_embed_file_id"]', window.document).trigger('input'); 35 jQuery('.elementor-control.wpfd-pdf-embed-category-id-controls input[data-setting="wpfd_pdf_embed_category_id"]', window.document).trigger('input'); 36 jQuery('.elementor-control.wpfd-pdf-embed-file-name-controls input[data-setting="wpfd_pdf_embed_file_name"]', window.document).trigger('input'); 37} 38 39function wpfd_elementor_hide_modal(e) { 40 jQuery('#lean_overlay', window.document).fadeOut(300); 41 jQuery('#wpfdelementormodal', window.document).fadeOut(300); 42} 43 44jQuery(document).ready(function ($) { 45 var WPFD_MODAL_BASE_URL = 'admin.php?page=wpfd&noheader=1&caninsert=1&elementorbuilder=1'; 46 47 /** 48 * Build the modal iframe url for a given mode and current widget selection 49 * 50 * @param {string} mode One of file, category, pdfembed 51 * @param {object} selection Current control values 52 * 53 * @returns {string} 54 */ 55 function wpfdBuildModalUrl(mode, selection) { 56 var url = WPFD_MODAL_BASE_URL + '&wpfdmode=' + encodeURIComponent(mode); 57 58 if (mode === 'pdfembed') { 59 // Kept for backward compatibility with the modal insert buttons 60 url += '&pdfembed=1'; 61 } 62 63 if (selection && selection.categoryId) { 64 url += '&wpfdcatid=' + encodeURIComponent(selection.categoryId); 65 } 66 67 if (selection && selection.fileId) { 68 url += '&wpfdfileid=' + encodeURIComponent(selection.fileId); 69 } 70 71 return url; 72 } 73 74 /** 75 * Open the WP File Download modal 76 * 77 * @param {object} launcher The clicked launcher element 78 * @param {string} mode One of file, category, pdfembed 79 * @param {object} selection Current control values 80 * 81 * @returns {void} 82 */ 83 function wpfdOpenModal(launcher, mode, selection) { 84 var $frame = $('#wpfdelementormodalframe'); 85 var modalId = launcher.attr('href'); 86 var modalWidth = $(modalId).outerWidth(); 87 88 $frame.attr('data-src', wpfdBuildModalUrl(mode, selection)); 89 $('#wpfdelementormodal').css('height', '90%'); 90 $frame.css('visibility', 'hidden').hide(); 91 $frame.attr('src', $frame.attr('data-src')); 92 $('#wpfd_elementor_loader').show(); 93 94 $frame 95 .removeClass('wpfdelementormodalframe-single-file') 96 .removeClass('wpfdelementormodalframe-category') 97 .removeClass('wpfdelementormodalframe-pdf-embed'); 98 99 if (mode === 'file') { 100 $frame.addClass('wpfdelementormodalframe-single-file'); 101 } else if (mode === 'category') { 102 $frame.addClass('wpfdelementormodalframe-category'); 103 } else { 104 $frame.addClass('wpfdelementormodalframe-pdf-embed'); 105 } 106 107 $('#lean_overlay').css({"display": "block", opacity: 0}); 108 $('#lean_overlay').fadeTo(200, 0.5); 109 $(modalId).css({ 110 "visibility": "visible", 111 "display": "block", 112 "text-align": "center", 113 "position": "fixed", 114 "opacity": 0, 115 "z-index": 100102, 116 "left": 50 + "%", 117 "margin-left": -(modalWidth / 2) + "px", 118 "top": "20px" 119 }); 120 $(modalId).fadeTo(200, 1); 121 } 122 123 /** 124 * Update the hidden widget controls of the currently edited widget 125 * 126 * @param {object} values Control name / value pairs 127 * 128 * @returns {boolean} True when at least one control has been updated 129 */ 130 function wpfdUpdateWidgetControls(values) { 131 var updated = false;
132 133 $.each(values, function (setting, value) { 134 var $input = $('.elementor-controls-stack input[data-setting="' + setting + '"], .elementor-control input[data-setting="' + setting + '"]'); 135 136 if ($input.length) { 137 $input.val(value); 138 updated = true; 139 } 140 }); 141 142 return updated; 143 } 144 145 /** 146 * Fallback used when the controls are not rendered as inputs: use the Elementor commands API 147 * 148 * @param {object} values Control name / value pairs 149 * 150 * @returns {boolean} True when the settings have been applied 151 */ 152 function wpfdUpdateWidgetSettings(values) { 153 try { 154 if (typeof window.$e === 'undefined' || typeof window.elementor === 'undefined') { 155 return false; 156 } 157 158 var container = null; 159 var panelView = elementor.getPanelView(); 160 161 if (panelView && panelView.getCurrentPageView) { 162 var pageView = panelView.getCurrentPageView(); 163 164 if (pageView) { 165 if (pageView.getContainer) { 166 container = pageView.getContainer(); 167 } else if (pageView.getOption && pageView.getOption('editedElementView')) { 168 container = pageView.getOption('editedElementView').getContainer(); 169 } 170 } 171 } 172 173 if (!container) { 174 return false; 175 } 176 177 window.$e.run('document/elements/settings', { 178 container: container, 179 settings: values 180 }); 181 182 return true; 183 } catch (error) { 184 return false; 185 } 186 } 187 188 /** 189 * Initialize the PDF.js viewer inside the Elementor preview iframe 190 * 191 * @returns {void} 192 */ 193 function wpfdInitPdfEmbedViewer() { 194 var attempts = 0; 195 var maxAttempts = 20; // ~10s total (20 * 500ms) 196 197 (function initViewer() { 198 var viewer = jQuery(); 199 200 try { 201 var frame = document.getElementById('elementor-preview-iframe'); 202 203 if (frame && frame.contentWindow && frame.contentWindow.jQuery) { 204 viewer = frame.contentWindow.jQuery('.wpfd-pdfemb-viewer'); 205 } 206 } catch (error) { 207 viewer = jQuery(); 208 } 209 210 if (viewer.length && typeof viewer.pdfEmbedder === 'function') { 211 viewer.pdfEmbedder(); 212 return; 213 } 214 215 attempts++; 216 217 if (attempts < maxAttempts) { 218 setTimeout(initViewer, 500); 219 } 220 })(); 221 } 222 223 $('.wpfdelementorlaunch').leanModal({ 224 top: 20, beforeShow: function () { 225 $("#wpfdelementormodal").css("height", "90%"); 226 $("#wpfdelementormodalframe").css('visibility', 'hidden'); 227 $("#wpfdelementormodalframe").hide(); 228 $("#wpfdelementormodalframe").attr('src', $("#wpfdelementormodalframe").data('src')); 229 $("#wpfd_elementor_loader").show(); 230 } 231 }); 232 233 if (typeof wpfd_elemetor_vars !== "undefined") { 234 $('body').append('<div id="wpfdelementormodal" class="wpfdelementormodal-elementor"><img src="' + wpfd_elemetor_vars.dir + 'app/admin/assets/images/spinner-2x.gif" alt="Loading..." width="32" id="wpfd_elementor_loader" /><iframe id="wpfdelementormodalframe" title="WP File Download Iframe" onload="wpfd_elementor_frameload()" width="100%" height="100%" marginWidth="0" marginHeight="0" frameBorder="0" scrolling="auto" data-src="' + WPFD_MODAL_BASE_URL + '"></iframe><button id="wpfd-close-elementor-modal">x</button></div>'); 235 } 236 237 $(document).on("click", '.wpfdelementorlaunch', function (e) { 238 wpfdOpenModal($(this), 'file', { 239 categoryId: $('[data-setting="wpfd_category_id"]').val(), 240 fileId: $('[data-setting="wpfd_file_id"]').val() 241 }); 242 }); 243 244 $(document).on("click", '.wpfdcategorylaunch', function (e) { 245 wpfdOpenModal($(this), 'category', { 246 categoryId: $('[data-setting="wpfd_selected_category_id"]').val() 247 }); 248 }); 249 250 $(document).on("click", '.wpfdpdfembedlaunch', function (e) { 251 wpfdOpenModal($(this), 'pdfembed', { 252 categoryId: $('[data-setting="wpfd_pdf_embed_category_id"]').val(), 253 fileId: $('[data-setting="wpfd_pdf_embed_file_id"]').val() 254 }); 255 }); 256 257 // Insert requests sent by the WP File Download modal iframe 258 window.addEventListener('message', function (event) { 259 if (event.origin !== window.location.origin) { 260 return; 261 } 262 263 var data = event.data; 264 265 if (!data || data.wpfd !== 'elementor') { 266 return; 267 } 268 269 if (data.action === 'close') { 270 wpfd_elementor_hide_modal(); 271 return; 272 } 273 274 if (data.action !== 'insert') { 275 return; 276 } 277 278 var values = {}; 279 280 if (data.mode === 'category') { 281 values.wpfd_selected_category_id = data.categoryId; 282 values.wpfd_selected_category_name = data.categoryName; 283 } else if (data.mode === 'pdfembed') { 284 values.wpfd_pdf_embed_file_id = data.fileId; 285 values.wpfd_pdf_embed_category_id = data.categoryId; 286 values.wpfd_pdf_embed_file_name = data.fileName; 287 } else { 288 values.wpfd_file_id = data.fileId; 289 values.wpfd_category_id = data.categoryId; 290 values.wpfd_file_name = data.fileName; 291 } 292 293 if (wpfdUpdateWidgetControls(values)) { 294 if (data.mode === 'category') { 295 wpfd_category_widget_trigger_controls(); 296 } else if (data.mode === 'pdfembed') { 297 wpfd_pdf_embed_widget_trigger_controls(); 298 } else { 299 wpfd_file_widget_trigger_controls(); 300 } 301 } else { 302 wpfdUpdateWidgetSettings(values); 303 } 304 305 wpfd_elementor_hide_modal(); 306 307 if (data.mode === 'pdfembed') { 308 wpfdInitPdfEmbedViewer(); 309 } 310 }, false); 311 312 $(document).on('click', '#wpfd-close-elementor-modal', function (e) { 313 wpfd_elementor_hide_modal(e); 314 }); 315 316 $('body').on('click', function (e) { 317 if ($('div#wpfdelementormodal').is(':visible') && !$(e.target).is('#wpfdelementormodal')) { 318 wpfd_elementor_hide_modal(e); 319 } 320 }); 321 322 $(document).on('click', '.elementor-control .elementor-control-title', function (e) { 323 e.preventDefault(); 324 }); 325});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.