PageSourceSearch

https://aluminium-stewardship.org/wp-content/plugins/advanced-iframe/js/ai.min.js?ver=813720

js aluminium-stewardship.org collected 2026-10-02 04:54:42 UTC 86,275 bytes, 2,204 lines download raw bytes

1/**
2 *  Advanced iframe pro functions v2023
3*/
4/* jslint devel: true, unused: false */
5/* globals ai_show_id_only:false, aiIsIe8: false, aiChangeUrl: false, aiResizeIframeHeightId: false, aiShowIframeId: false, findAndReplaceDOMText: false, aiShowDebug: false */
6
7var aiEnableCookie=false;
8var aiId='';
9var aiExtraSpace = 0;
10var aiAccTime = 0;
11var aiOnloadEventsCounter = 0;
12var aiOverflowHtml=jQuery('html').css('overflow') ?? 'visible';
13var aiOverflowBody=jQuery('body').css('overflow') ?? 'visible';
14
15var aiCallbackExists = typeof aiReadyCallbacks !== 'undefined' && aiReadyCallbacks instanceof Array;
16var aiReadyCallbacks = aiCallbackExists ? aiReadyCallbacks : [];
17
18
19/**
20* The debug messages are enabled if you enable the debug console.
21*/
22function aiDebugExtended(message) {
23  if (typeof aiShowDebug !== 'undefined' && aiShowDebug) {
24    if (console && console.log) {
25      console.log("Advanced iframe: " + message);
26    }
27  }
28}
29
30/**
31 *  This function resizes the iframe after loading to the height
32 *  of then content of the iframe.
33 *
34 *  The extra space is not stored in the cookie! The height would
35 *  be added every time otherwise and the iframe would grow,
36 */
37function aiResizeIframe(obj, resizeWidth, resizeMinHeight) {
38  aiDebugExtended("aiResizeIframe");
39  try {
40    if (obj.contentWindow.location.href === 'about:blank') {
41        return;
42    }
43    if (obj.contentWindow.document.body != null) {
44      var oldScrollposition = jQuery(window).scrollTop();
45      obj.style.marginTop = 0; 
46	  obj.style.marginBottom = 0;
47      obj.height = Number(resizeMinHeight); // set to 1 because otherwise the iframe does never get smaller.
48      obj.style.height = Number(resizeMinHeight) + 'px';
49      var newheight = aiGetIframeHeight(obj);
50	  aiDebugExtended("aiResizeIframe - newheight: " + newheight);
51      obj.height = newheight;
52      obj.style.height = newheight + 'px';
53
54       // set the height of the zoom div
55      if (jQuery('#ai-zoom-div-' + obj.id).length !== 0) {
56         var zoom = window['zoom_' + obj.id];
57         jQuery('#ai-zoom-div-' + obj.id).css('height', newheight * zoom);
58      }
59
60      if (aiEnableCookie && aiExtraSpace === 0 ) {
61          aiWriteCookie(newheight);
62      }
63      var hash = aiGetIframeHash(obj.contentWindow.location.href);
64      if (hash !== -1) {
65		  var iframeId = '#'+ obj.id;
66          try {
67              var hashposition = jQuery(iframeId).contents().find('#'+ hash);
68              if (hashposition.length !== 0) {
69                var hashpositionTop = hashposition.offset().top;
70                oldScrollposition = Math.round(jQuery(iframeId).offset().top + hashpositionTop);
71              }
72          } catch(e) {
73              // in case of an invalid hash it is ignored. 
74          }
75      }
76	  setTimeout(function() {
77           jQuery("html,body").scrollTop(oldScrollposition);
78      }, 50);   
79
80      if (resizeWidth === 'true') {
81        var newWidth = aiGetIframeWidth(obj);
82        obj.width = newWidth;
83        obj.style.width = newWidth + 'px';
84      }
85      var fCallback = window['resizeCallback' + obj.id];
86      fCallback();
87      // fires the onload event again if iframes are wrapped
88      if (window.frameElement != null) {
89        parent.jQuery('iframe').trigger('onload');
90      }
91    } else {
92      // body is not loaded yet - we wait 100 ms.
93      setTimeout(function() { aiResizeIframe(obj, resizeWidth); },100);
94    }
95  } catch(e) {
96    if (console && console.error) {
97      console.error('Advanced iframe configuration error: You have enabled the resize of the iframe for pages on the same domain. But you use an iframe page on a different domain. You need to use the external workaround like described in the settings. Also check the next log. There the browser message for this error is displayed.');
98      console.log(e);
99    }
100  }
101}
102
103/**
104 * returns the position of a #hash in the iframe or -1 if none was found.
105 */
106 
107function aiGetIframeHash(url) {
108    var hash = url.split('#')[1];
109    return (hash) ? hash : '-1';
110}
111
112/**
113 *  Get the iframe height
114 */
115function aiGetIframeHeight(obj) {
116      var bodyHeight = Math.max(obj.contentWindow.document.body.scrollHeight,
117       obj.contentWindow.document.body.offsetHeight,
118       obj.contentWindow.document.documentElement.scrollHeight,
119       obj.contentWindow.document.documentElement.offsetHeight);
120       var newheight = bodyHeight + aiExtraSpace;
121       return newheight;
122}
123
124/**
125 *  Get the iframe width
126 */
127function aiGetIframeWidth(obj) {
128    var oldWidth =  obj.width;
129    obj.width = 1; // set to 1 because otherwise I don't get the minimum width
130    obj.style.width = '1px';
131    var bodyWidth = Math.max(obj.contentWindow.document.body.scrollWidth,
132          obj.contentWindow.document.body.offsetWidth,
133          obj.contentWindow.document.documentElement.scrollWidth,
134          obj.contentWindow.document.documentElement.offsetWidth);
135    if (bodyWidth !== 1) { // avoid that fully responsive sites do not get displayed at all.
136      obj.width = bodyWidth;
137      obj.style.width = bodyWidth + 'px';
138    } else {
139      obj.width = oldWidth;
140      obj.style.width = oldWidth + 'px';
141    }
142    return bodyWidth;
143}
144
145/**
146 *  Get the current width of the iframe inside the parent.
147 */
148function aiGetParentIframeWidth(obj) {
149    if (obj != null && jQuery('#' + obj.id).length !== 0) {
150        return jQuery('#' + obj.id).width();
151    } else {
152        return -1;
153    }
154}
155
156
157/**
158 *  Resizes an iframe to a given height.
159 *  this is used for xss enabled iframes.
160 *  Please read the documentation!
161 */
162function aiResizeIframeHeightById(id, nHeight) {
163  aiDebugExtended("aiResizeIframeHeightById - id: " + id + ", nHeight: " + nHeight);
164  try {
165    var fCallback = window['resizeCallback' + id];
166    fCallback();
167    var height = parseInt(nHeight,10) + aiExtraSpace;
168    var iframe = document.getElementById(id);
169	if (iframe === null) {	
170      if (console && console.error) {
171        console.error('Advanced iframe configuration error: The iframe to resize could not be found. The id of the iframe and the one defined for ai_external.js (' + id + ') are most likely different! Check your settings.');
172        console.log(e);
173	    return;
174      }
175	}
176	var oldScrollposition = jQuery(document).scrollTop();
177    iframe.height = height;
178    iframe.style.height = height + 'px';
179    jQuery("html,body").scrollTop(oldScrollposition); 
180    if (aiEnableCookie && aiExtraSpace === 0) {
181      aiWriteCookie(height);
182    }
183    // send the new height to the parent if it is a wrapped call
184    var parentResizeCall = window['aiExecuteWorkaround_' + id];
185    if (parentResizeCall != null) {
186      parentResizeCall();
187    }
188  }  catch(e) {
189    if (console && console.error) {
190      console.error('Advanced iframe configuration error: The id of the parent and the external workaround are different! Check your settings.');
191      console.log(e);
192    }
193  }
194}
195
196
197/**
198 * Scrolls the parent window to the top.
199 * This is e.g. wanted when you have a link in the iframe and you want that the
200 * page starts at the top and not that only the iframe changes.
201 *
202 * Sometimes are 2 onload events after another. To prevent that this causes 
203 * a jump to the top a delay of 1 sec is used for the increase of the counter.
204 */
205function aiScrollToTop(id, position) {
206   aiDebugExtended("aiScrollToTop - id: " + id + ", position: " + position);
207  
208  if (aiOnloadEventsCounter > 0) {
209	  var posTop = 0;
210	  if (position === 'iframe') {
211		posTop = jQuery('#' + id).offset().top;
212	  }
213	  setTimeout(function() {
214        aiDebugExtended("aiScrollToTop - posTop: " + posTop);   
215		window.scrollTo(0, posTop);
216	  }, 100);   
217  }
218  setTimeout(function() {
219    aiOnloadEventsCounter++;
220  }, 1000);  
221}
222
223/**
224 * Writes the last height to the cookie.
225 */
226function aiWriteCookie(height) {
227  var cookieName = 'ai-last-height';
228  if (aiId !== '') {
229    cookieName =  cookieName + '-' + aiId ;
230  }
231  var cookieStr = cookieName + '=' + height;
232  document.cookie=cookieStr;
233}
234
235/**
236 * Reads the cookie and preset the height of the iframe
237 */
238function aiUseCookie() {
239  var cookieName = 'ai-last-height';
240  if (aiId !== '') {
241    cookieName = cookieName + '-' + aiId ;
242  }
243  var allcookies = document.cookie;
244  // Get all the cookies pairs in an array
245  var cookiearray  = allcookies.split(';');
246  // Now take key value pair out of this array
247  for (var i = 0; i < cookiearray.length; i++) {
248    var name = cookiearray[i].split('=')[0];
249    var value = cookiearray[i].split('=')[1];
250    // cookie does exist and has a numeric value
251    if (name === cookieName && value !== null && aiIsNumeric(value)) {
252       var iframe = document.getElementById(aiId);
253       iframe.height = parseInt(value,10);
254       iframe.style.height = value + 'px';
255    }
256  }
257}
258
259/**
260 *  check if we have a numeric input
261 */
262function aiIsNumeric(input){
263    return !isNaN(input);
264}
265
266/**
267* Disable the additional_height input field
268*/
269function aiDisableHeight() {
270  jQuery('#additional_height').attr('readonly','readonly');
271  jQuery('#additional_height').val('0');
272}
273
274/**
275* Enable the additional_height input field
276*/
277function aiEnableHeight() {
278  jQuery('#additional_height').removeAttr('readonly');
279}
280
281/**
282 * Removes all elements from an iframe except the given one
283 *
284 * @param iframeId id of the iframe
285 * @param showElement the id, class (jQuery syntax) of the element that should be displayed.
286 */
287function aiShowElementOnly( iframeId, showElement ) {
288  aiDebugExtended("aiShowElementOnly");
289  try {
290    var iframe = jQuery(iframeId).contents().find('body');
291    var selectedBox = iframe.find(showElement).clone(true,true);
292    iframe.find('*').not(jQuery('script')).remove();
293    iframe.prepend(selectedBox);
294  }  catch(e) {
295    if (console && console.error) {
296      console.error('Advanced iframe configuration error: You have enabled to show only one element of the iframe for pages on the same domain. But you use an iframe page on a different domain. You need to use the pro version of the external workaround like described in the settings. Also check the next log. There the browser message for this error is displayed.');
297      console.log(e);
298    }
299  }
300}
301
302function aiCheckIfValidTarget(evt, elements) {
303  var targ;
304  if (!evt) {
305    evt = window.event;
306  }
307  if (evt.target) {
308    targ = evt.target;
309  } else if (evt.srcElement) {
310    targ = evt.srcElement;
311  }
312  if (targ.nodeType === 3) {
313    targ = targ.parentNode;
314  }
315
316  var parts = elements.split(',');
317  // check each part if we have a match...
318  for (var i=0; i< parts.length; ++i) {
319    var selectorArray = parts[i].split(':');
320    if (selectorArray[0].toLowerCase() === targ.nodeName.toLowerCase()) {
321      if (selectorArray.length > 1) {
322           if (targ.id.toLowerCase().indexOf(selectorArray[1].toLowerCase()) !== -1) {
323               return true;
324           }
325      } else {
326        return true;
327      }
328    }
329  }
330  return false;
331}
332
333function aiOpenSelectorWindow (url) {
334   aiDebugExtended("aiOpenSelectorWindow");
335   var localWidth =  jQuery('#width').val();
336   var localHeight = jQuery('#ai-height-0').val();
337
338   if (localWidth.indexOf('%') >= 0 || Number(localWidth) < 900) {
339       localWidth = 900;
340   }
341   localWidth = Number(localWidth) + 40;
342   if ( localWidth > (screen.width)) {
343       localWidth = screen.width;
344   }
345   if (localHeight.indexOf('%') >= 0) {
346       localHeight = screen.height;
347   } else {
348        localHeight =  Number(localHeight) + 480;
349   }
350   if ( localHeight > (screen.height-50)) {
351       localHeight = screen.height-50;
352   }
353   var options = 'width='+localWidth+',height='+localHeight+',left=0,top=0,resizable=1,scrollbars=1';
354   var popup_window = window.open(url, '', options);
355   popup_window.focus();
356}
357
358function aiDisableAiResizeOptions(value) {
359  jQuery('#onload_resize_delay').prop('readonly',value);
360  jQuery('input[id=store_height_in_cookie1]:radio, input[id=store_height_in_cookie2]:radio').attr('disabled',value);
361  jQuery('#additional_height').prop('readonly', value);
362  jQuery('input[id=onload_resize_width1]:radio, input[id=onload_resize_width2]:radio').attr('disabled',value);
363  jQuery('#resize_on_click').prop('readonly', value);
364  jQuery('#resize_on_click_elements').prop('readonly', value);
365  jQuery('#resize_on_ajax').prop('readonly', value);
366  jQuery('input[id=resize_on_ajax_jquery1]:radio, input[id=resize_on_ajax_jquery2]:radio').attr('disabled',value);
367  
368  var selector = '#onload_resize_delay, #store_height_in_cookie1, #additional_height, #onload_resize_width1, ';
369  selector += '#resize_on_click, #resize_on_click_elements, #resize_on_ajax, #resize_on_ajax_jquery1';
370  aiDisableTextSection(value, selector);
371}
372
373function aiDisablePartOfIframeOptions(value) {
374  jQuery('#show_part_of_iframe_x').prop('readonly',value);
375  jQuery('#show_part_of_iframe_y').prop('readonly',value);
376  jQuery('#show_part_of_iframe_height').prop('readonly',value);
377  jQuery('#show_part_of_iframe_width').prop('readonly',value);
378  jQuery('input[id=show_part_of_iframe_allow_scrollbar_horizontal1]:radio, input[id=show_part_of_iframe_allow_scrollbar_horizontal2]:radio').attr('disabled',value);
379  jQuery('input[id=show_part_of_iframe_allow_scrollbar_vertical1]:radio, input[id=show_part_of_iframe_allow_scrollbar_vertical2]:radio').attr('disabled',value);
380  jQuery('#show_part_of_iframe_next_viewports').prop('readonly',value);
381  jQuery('input[id=show_part_of_iframe_next_viewports_loop1]:radio, input[id=show_part_of_iframe_next_viewports_loop2]:radio').attr('disabled',value);
382  jQuery('#show_part_of_iframe_new_window').prop('readonly',value);
383  jQuery('#show_part_of_iframe_new_url').prop('readonly',value);
384  jQuery('input[id=show_part_of_iframe_next_viewports_hide1]:radio, input[id=show_part_of_iframe_next_viewports_hide2]:radio').attr('disabled',value);
385  jQuery('#show_part_of_iframe_style').prop('readonly',value);
386  jQuery('input[id=show_part_of_iframe_zoom1]:radio, input[id=show_part_of_iframe_zoom2]:radio, input[id=show_part_of_iframe_zoom3]:radio').attr('disabled',value);
387  jQuery('.media-query-input').prop('readonly',value);
388 
389 
390  var selector = '#show_part_of_iframe_x, #show_part_of_iframe_y, #show_part_of_iframe_height, #show_part_of_iframe_width, ';
391  selector += '#show_part_of_iframe_allow_scrollbar_horizontal1, #show_part_of_iframe_next_viewports, #show_part_of_iframe_next_viewports_loop1, ';
392  selector += '#show_part_of_iframe_new_window, #show_part_of_iframe_new_url, #show_part_of_iframe_next_viewports_hide1, #show_part_of_iframe_style, ';
393  selector += '#show_part_of_iframe_zoom1, #show_part_of_iframe_allow_scrollbar_vertical1, #add-media-query-show_part_of_iframe_media_query';
394  aiDisableTextSection(value, selector);
395  
396  if (value) {
397      jQuery('#add-media-query-show_part_of_iframe_media_query').hide();
398	  jQuery('.ai-delete').hide();
399  } else {
400	  jQuery('#add-media-query-show_part_of_iframe_media_query').show();
401	  jQuery('.ai-delete').show();
402  }
403  
404}
405
406function aiDisableLazyLoadOptions(value) {
407  jQuery('#enable_lazy_load_threshold').prop('readonly', value);
408  jQuery('#enable_lazy_load_fadetime').prop('readonly', value);
409  jQuery('input[id=enable_lazy_load_reserve_space1]:radio, input[id=enable_lazy_load_reserve_space2]:radio').attr('disabled',value);
410  jQuery('input[id=enable_lazy_load_manual1]:radio, input[id=enable_lazy_load_manual2]:radio, input[id=enable_lazy_load_manual3]:radio').attr('disabled',value);
411   
412  var selector = '#enable_lazy_load_threshold, #enable_lazy_load_fadetime, #enable_lazy_load_reserve_space1, #enable_lazy_load_manual1';
413  aiDisableTextSection(value, selector);
414  }
415
416function aiDisableIframeAsLayerOptions(value) {
417  jQuery('input[id=show_iframe_as_layer_full]:radio').attr('disabled',value);
418  jQuery('#show_iframe_as_layer_header_file').prop('readonly', value);
419  jQuery('#show_iframe_as_layer_header_height').prop('readonly', value);
420  jQuery('#show_iframe_as_layer_autoclick_delay').prop('readonly', value);
421  jQuery('#show_iframe_as_layer_autoclick_hide_time').prop('readonly', value);
422  jQuery('input[id=show_iframe_as_layer_header_position1]:radio, input[id=show_iframe_as_layer_header_position2]:radio').attr('disabled',value);
423  jQuery('input[id=show_iframe_as_layer_full1]:radio, input[id=show_iframe_as_layer_full2]:radio, input[id=show_iframe_as_layer_full3]:radio').attr('disabled',value);
424  jQuery('input[id=show_iframe_as_layer_keep_content1]:radio, input[id=show_iframe_as_layer_keep_content2]:radio').attr('disabled',value);
425
426  var selector = '#show_iframe_as_layer_full, #show_iframe_as_layer_header_file, #show_iframe_as_layer_header_height, ';
427  selector += '#show_iframe_as_layer_header_position1, #show_iframe_as_layer_full1, #show_iframe_as_layer_keep_content1, ';
428  selector += '#show_iframe_as_layer_autoclick_delay, #show_iframe_as_layer_autoclick_hide_time';
429    
430  aiDisableTextSection(value, selector);
431 
432}
433
434function aiDisableAddParamOptions(value) {
435	jQuery('input[id=add_iframe_url_as_param_direct1]:radio, input[id=add_iframe_url_as_param_direct2]:radio').attr('disabled',value);
436	jQuery('#add_iframe_url_as_param_prefix').prop('readonly',value);
437    var selector = '#add_iframe_url_as_param_prefix, #add_iframe_url_as_param_direct1';
438    aiDisableTextSection(value, selector);
439}
440
441function aiDisableTextSection(value, selector) {
442	if (value) {
443        jQuery(selector).closest('tr').addClass('disabled');
444    } else {
445	    jQuery(selector).closest('tr').removeClass('disabled');
446    }
447}
448
449var aiInstance;
450
451/**
452 *  This function initializes all checks that are done by Javascript
453 *  on the admin page like enabling disabling fields...
454 */
455function aiInitAdminConfiguration(isPro, acc_type) {
456    // enable checkbox of onload_resize_delay and if resize is set to true external workaround is set to false
457    if (jQuery('input[type=radio][name=onload_resize]:checked').val() === 'false') {
458        aiDisableAiResizeOptions(true);
459    }
460    jQuery('input[type=radio][name=onload_resize]').click( function(){
461    if (jQuery(this).val() === 'true') {
462           jQuery('input:radio[name=enable_external_height_workaround]')[1].checked = true; // set to external!
463           aiDisableAiResizeOptions(false);
464        } else {
465           jQuery('#onload_resize_delay').val('');
466           aiDisableAiResizeOptions(true);
467
468        }
469    });
470
471    // if external workaround is set to to true resize on load is set to false and the
472    // onload_resize_delay is made readonly
473    jQuery('input[type=radio][name=enable_external_height_workaround]').click( function(){
474    if (jQuery(this).val() === 'true') {
475           jQuery('input:radio[name=onload_resize]')[1].checked = true;
476           jQuery('#onload_resize_delay').val('');
477           aiDisableAiResizeOptions(true);
478        }
479    });
480
481    // Show only a part of the iframe enable/disable
482     if (jQuery('input[type=radio][name=show_part_of_iframe]:checked').val() === 'false') {
483        aiDisablePartOfIframeOptions(true);
484     }
485      jQuery('input[type=radio][name=show_part_of_iframe]').click( function(){
486    if (jQuery(this).val() === 'false') {
487          aiDisablePartOfIframeOptions(true);
488        } else {
489          aiDisablePartOfIframeOptions(false);
490        }
491    });
492
493    // show_iframe_as_layer enable/disable
494     if (jQuery('input[type=radio][name=show_iframe_as_layer]:checked').val() === 'false') {
495        aiDisableIframeAsLayerOptions(true);
496     }
497      jQuery('input[type=radio][name=show_iframe_as_layer]').click( function(){
498    if (jQuery(this).val() === 'false') {
499          aiDisableIframeAsLayerOptions(true);
500        } else {
501          aiDisableIframeAsLayerOptions(false);
502        }
503    });
504
505    // if expert mode
506    if (jQuery('input[type=radio][name=expert_mode]:checked').val() === 'true') {
507      jQuery('.description').css('display','none');
508      jQuery('table.form-table th').css('cursor','pointer');
509      jQuery('table.form-table th').css('padding-top','8px').css('padding-bottom','2px');
510      jQuery('table.form-table td').css('padding-top','5px').css('padding-bottom','5px');
511      jQuery('table.form-table th').click(function() {
512           jQuery('.description').css('display','none');
513           jQuery('.description', jQuery(this).parent()).css('display','block');
514        });
515    }
516    jQuery('input[type=radio][name=expert_mode]').click( function(){
517      if (jQuery(this).val() === 'false') {
518        jQuery('.description').css('display','block');
519        jQuery('table.form-table th').css('cursor','auto');
520        jQuery('table.form-table th').off('click');
521        jQuery('table.form-table th').css('padding-top','20px').css('padding-bottom','20px');
522        jQuery('table.form-table td').css('padding-top','15px').css('padding-bottom','15px');
523      } else {
524        jQuery('.description').css('display','none');
525        jQuery('table.form-table th').css('cursor','pointer');
526        jQuery('table.form-table th').css('padding-top','8px').css('padding-bottom','2px');
527        jQuery('table.form-table td').css('padding-top','5px').css('padding-bottom','5px');
528        jQuery('table.form-table th').click(function() {
529           jQuery('.description').css('display','none');
530           jQuery('.description', jQuery(this).parent()).css('display','block');
531        });
532      }
533    });
534
535
536     jQuery('#accordion').find('h1').click(function(){
537         jQuery(this).next().slideToggle(aiAccTime);
538     }).next().hide();
539
540     jQuery('#accordion').find('a').click(function(){
541         var hash = jQuery(this).prop('hash');
542         var hash_only = '#h1-' + hash.substring(1);
543         jQuery(hash_only).next().show();
544         location.hash = hash_only;
545     });
546
547    // lazy load
548    if (jQuery('input[type=radio][name=enable_lazy_load_manual]:checked').val() === 'false') {
549        jQuery('#enable_lazy_load_manual_element').prop('readonly',true);
550    }
551
552    jQuery('input[type=radio][name=enable_lazy_load_manual]').click( function(){
553    if (jQuery(this).val() === 'false' || jQuery(this).val() === 'auto') {
554           jQuery('#enable_lazy_load_manual_element').prop('readonly',true);
555        } else {
556           jQuery('#enable_lazy_load_manual_element').prop('readonly',false);
557        }
558    });
559	
560	// add_iframe_url_as_param
561	if (jQuery('input[type=radio][name=add_iframe_url_as_param]:checked').val() === 'false') {
562        aiDisableAddParamOptions(true);
563    }
564	jQuery('input[type=radio][name=add_iframe_url_as_param]').click( function(){
565        aiDisableAddParamOptions(jQuery(this).val() === 'false');
566    });
567	
568    if (jQuery('input[type=radio][name=enable_lazy_load]:checked').val() === 'false') {
569        aiDisableLazyLoadOptions(true);
570        jQuery('#enable_lazy_load_manual_element').prop('readonly',true);
571    }
572
573    jQuery('input[type=radio][name=enable_lazy_load]').click( function(){
574    if (jQuery(this).val() === 'false') {
575           aiDisableLazyLoadOptions(true);
576           jQuery('#enable_lazy_load_manual_element').prop('readonly',true);
577        } else {
578           aiDisableLazyLoadOptions(false);
579           if (jQuery('input[type=radio][name=enable_lazy_load_manual]:checked').val() === 'false' ||
580               jQuery('input[type=radio][name=enable_lazy_load_manual]:checked').val() === 'auto' ) {
581             jQuery('#enable_lazy_load_manual_element').prop('readonly',true);
582           } else {
583             jQuery('#enable_lazy_load_manual_element').prop('readonly', false);
584           }
585        }
586    });
587
588    jQuery('.confirmation').on('click', function () {
589        return confirm('Are you sure? Selecting OK will set all settings to the default.');
590    });
591	
592	jQuery('.confirmation-file').on('click', function () {
593        return confirm('Do you really want to delete the file?');
594    });
595	
596	jQuery('.confirmation-hash').on('click', function () {
597        return confirm('Do you really want to delete the hash/URL cache?');
598    });
599
600     jQuery('a.post').click(function(e) {
601          e.stopPropagation();
602          e.preventDefault();
603          var href = this.href;
604          var parts = href.split('?');
605          var url = parts[0];
606          var params = parts[1].split('&');
607          var pp, inputs = '';
608          url += '?' + params[0];
609          for(var i = 1, n = params.length; i < n; i++) {
610              pp = params[i].split('=');
611              inputs += '<input type="hidden" name="' + pp[0] + '" value="' + pp[1] + '" />';
612          }
613		  // Add twg-options nonce
614          var nonceValue = jQuery('#twg-options').val();
615          inputs += '<input type="hidden" name="twg-options" value="' + nonceValue + '" />';
616
617          jQuery('body').append('<form action="'+url+'" method="post" id="poster">'+inputs+'</form>');
618          jQuery('#poster').submit();
619      });
620
621      jQuery('.ai-input-search').keyup(function(e) {
622           var searchTerm = jQuery('input.ai-input-search').val().toLowerCase();
623           aiSettingsSearch(searchTerm, acc_type);
624      });
625       jQuery('.ai-input-search').on('click', function(e) {
626           setTimeout(function() {
627           var searchTerm = jQuery('input.ai-input-search').val().toLowerCase();
628           aiSettingsSearch(searchTerm, acc_type);
629           }, 100);
630      });
631
632      jQuery(document).on( 'click', '.nav-tab-wrapper a', function() {
633        var current_tab = jQuery(this).attr('id');
634        jQuery('section').hide();
635        jQuery('section.' + current_tab ).show();
636        jQuery('#current_tab').val(current_tab.substr(4,1));
637        jQuery('.nav-tab').removeClass('nav-tab-active');
638        jQuery(this).addClass('nav-tab-active');
639        jQuery(this).blur();
640		
641        return false;
642      });
643
644      // set the links between tabs and open the right one at the right section.
645        jQuery(document).on( 'click', 'a#external-workaround-link', function() {
646          jQuery('.external-workaround').click();
647          location.hash = 'tab_3';
648		  // no flash
649		  aiShowHeader('tab_3');
650          return false;
651        });
652        jQuery(document).on( 'click', 'a#resize-same-link', function() {
653          jQuery('.advanced-settings-tab').click();
654		  jQuery('#id-advanced-resize').removeClass('closed');
655          location.hash = 'id-advanced-resize';
656		  // no flash
657          aiShowHeader('id-advanced-resize');  
658          return false;
659        });
660         jQuery(document).on( 'click', 'a.jquery-help-link', function() {
661          jQuery('.help-tab').click();
662		  jQuery('#id-help-jquery').removeClass('closed');
663          jQuery('#jquery-help').show();
664          location.hash = 'id-help-jquery';
665		  // no flash
666		  aiShowHeader('id-help-jquery');
667		  return false;
668        });
669        jQuery(document).on( 'click', 'a#browser-detection-link', function() {
670          jQuery('.help-tab').click();
671		  jQuery('#id-help-browser').removeClass('closed');
672          jQuery('#browser-help').show();
673          location.hash = 'id-help-browser';
674		  // no flash
675          aiShowHeader('id-help-browser');
676          return false;
677        });
678        jQuery(document).on( 'click', 'a.howto-id-link', function() {
679          jQuery('.help-tab').click();
680		  jQuery('#id-help-id').removeClass('closed');
681          location.hash = 'id-help-id';
682		  // no flash
683          aiShowHeader('id-help-id');
684          return false;
685        });
686        jQuery(document).on( 'click', '.modifycontent-link', function() {
687          jQuery('.advanced-settings-tab').click();
688		  jQuery('#id-advanced-modify-iframe').removeClass('closed');
689          location.hash = 'id-advanced-modify-iframe';
690           aiShowHeader('id-advanced-modify-iframe', 'tr-' + jQuery(this).data('detail'));   
691          return false;
692        });
693		
694        jQuery(document).on( 'click', '.id-modify-css-iframe-link', function() {
695          jQuery('.advanced-settings-tab').click();
696		  jQuery('#id-advanced-modify-iframe').removeClass('closed');
697          location.hash = 'id-modify-css-iframe';
698           aiShowHeader('id-advanced-modify-iframe', 'tr-' + jQuery(this).data('detail'));   
699          return false;
700        });
701		
702		 jQuery(document).on( 'click', '.modify-target', function() {
703          jQuery('.advanced-settings-tab').click();
704		  jQuery('#id-advanced-modify-iframe').removeClass('closed');
705          location.hash = 'id-modify-target';
706          aiShowHeader('id-advanced-modify-iframe', 'tr-' + jQuery(this).data('detail'));  
707          return false;
708        });
709
710         jQuery(document).on( 'click', 'a.link-external-domain', function() {     
711          jQuery('#id-external-different').removeClass('closed');
712		  location.hash = '#id-external-different';
713		  // no flash - 'id-external-different'
714		  aiShowHeader('id-external-different');
715          return false;
716        });
717		jQuery(document).on( 'click', 'a.link-id-external-ai-config-post', function() {
718          jQuery('#id-external-ai-config-post').removeClass('closed');
719		  location.hash = '#id-external-ai-config-post';  
720		  aiShowHeader('id-external-ai-config-post', 'tr-use_post_message');
721          return false;
722        });
723		jQuery(document).on( 'click', 'a.link-id-external-ai-overview', function() {
724          jQuery('#id-external-ai-overview').removeClass('closed');
725		  location.hash = '#id-external-ai-overview';
726		  aiShowHeader('id-external-ai-overview', 'id-external-ai-overview');
727          return false;
728        });
729		jQuery(document).on( 'click', 'a.post-message-help-link', function() {
730          jQuery('.help-tab').click();
731          jQuery('#id-help-communication').removeClass('closed');
732		  location.hash = '#id-help-communication';
733          aiShowHeader('id-help-communication','id-help-communication');
734          return false;
735        });
736		
737		jQuery(document).on( 'click', 'a.enable-admin', function() {
738          jQuery('.options-tab').click();
739		  jQuery('#id-options-display').removeClass('closed');
740          location.hash = '#id-options-display';
741          aiShowHeader('id-options-display', 'tr-demo');    
742          return false;
743        });
744		
745		jQuery(document).on( 'click', 'a.enter-registration', function() {
746          jQuery('.options-tab').click();
747		  jQuery('#id-options-registration').removeClass('closed');
748          location.hash = '#id-options-registration';
749          aiShowHeader('id-options-registration', 'tr-demo');    
750          return false;
751        });
752	
753      jQuery(document).on( 'click', 'a#user-help-link', function() {
754          jQuery('#user-help').css('display', 'block');
755          return false;
756      });
757      jQuery(document).on( 'click', 'a#user-meta-link', function() {
758          jQuery('#meta-help').css('display', 'block');
759          return false;
760      });
761
762      jQuery(document).on( 'click', '#ai-selector-help-link', function() {
763          jQuery('#ai-selector-help').slideDown(1000);
764          return false;
765        });
766
767      jQuery(document).on( 'click', '.ai-selector-help-link-move', function() {
768          jQuery('#ai-selector-help').show('slow');
769		  location.hash = '#ai-selector-help-link';
770          // no flash
771		  aiShowHeader('ai-selector-help-link');   
772          return false;
773        });
774
775      jQuery('#ai_form').submit(function() {
776        aiSetScrollposition();
777      });
778			
779	// Close postboxes that should be closed.
780	jQuery('.if-js-closed').removeClass('if-js-closed').addClass('closed');
781	// Postboxes setup.
782	if (typeof postboxes !== 'undefined') {
783		postboxes.add_postbox_toggles('toplevel_page_advanced-iframe');
784	}
785 	
786	jQuery('.ai-spinner').css('display','none');
787	jQuery("#" + acc_type).next().show();
788	
789	jQuery(document).on( 'click', '#test-pro-admin.is-permanent-closable button', function() {
790	  closeInfoPermanent('test-pro-admin');
791    });
792	
793	jQuery(document).on( 'click', '#show-registration-message.is-permanent-closable button', function() {
794	  closeInfoPermanent('show-registration-message');
795    });
796
797	jQuery(document).on( 'click', '#show-version-message.is-permanent-closable button', function() {
798	  closeInfoPermanent('show-version-message');
799    });	
800	
801	
802	 jQuery(document).on( 'click', '.mq-breakpoint-height a', function(evt) {
803	  jQuery(this).parent().remove();
804	  aiUpdateHeightHiddenField('height');
805	  evt.preventDefault();
806	  return false;
807	});
808	
809    jQuery(document).on( 'click', 'a#add-media-query-height', function(evt) {
810	  // count existing elements
811	  var nextNr =  jQuery(".mq-breakpoint-height").length + 1; 
812	  jQuery(this).parent().append('<div id="breakpoint-row-height-'+nextNr+'" class="mq-breakpoint-height">' + 
813	  '<input type="text" id="ai-height-' + nextNr + '" style="width:150px;margin-top:5px;"  onblur="aiCheckHeightNumber(this, \'height\');" placeholder="Insert height"/> &nbsp;
813Breakpoint: ' + 
814	  '<input type="text" id="ai-breakpoint-height-' +nextNr + '" style="width:130px;" onblur="aiCheckHeightNumber(this, \'height\');" placeholder="Insert breakpoint"/>' +
815	  '<a id="delete-media-query-'+nextNr+'" href="#" class="delete ai-delete">Delete</a>');  	   
816	  evt.preventDefault();
817	  return false;
818	});
819	
820    jQuery(document).on( 'click', '.mq-breakpoint-show_part_of_iframe_media_query a', function(evt) {
821	  jQuery(this).parent().remove();
822	  aiUpdateHeightHiddenFieldMediaQuery('show_part_of_iframe_media_query');
823	  evt.preventDefault();
824	  return false;
825	});
826	
827    jQuery(document).on( 'click', 'a#add-media-query-show_part_of_iframe_media_query', function(evt) {
828	  // count existing elements
829	  var nextNr =  jQuery(".mq-breakpoint-show_part_of_iframe_media_query").length + 1; 
830	  jQuery(this).parent().append('<div id="breakpoint-row-show_part_of_iframe_media_query-'+nextNr+'" class="mq-breakpoint-show_part_of_iframe_media_query">' + 
831	  'x: <input type="text" id="ai-x-show_part_of_iframe_media_query-' + nextNr + '" class="media-query-input" ' +
832	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="x"/>' +
833	  ' &nbsp;y: <input type="text" id="ai-y-show_part_of_iframe_media_query-' + nextNr + '" class="media-query-input" ' + 
834	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="y"/>'+
835	  ' &nbsp;w: <input type="text" id="ai-w-show_part_of_iframe_media_query-' + nextNr + '" class="media-query-input" ' + 
836	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="width"/>'+
837	  ' &nbsp;h: <input type="text" id="ai-h-show_part_of_iframe_media_query-' + nextNr + '" class="media-query-input" ' + 
838	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="height"/>'+
839	  ' &nbsp;iframe width: <input type="text" id="ai-i-show_part_of_iframe_media_query-' + nextNr + '" class="media-query-input" style="width:100px;" ' + 
840	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="iframe width"/>'+
841	  ' &nbsp;Breakpoint: <input type="text" id="ai-breakpoint-show_part_of_iframe_media_query-' +nextNr + '" class="media-query-input" style="width:130px;" ' + 
842	  ' onblur="aiCheckHeightNumberMediaQuery(this, \'show_part_of_iframe_media_query\');" placeholder="Insert breakpoint"/>' + 
843	  '<a id="delete-media-query-show_part_of_iframe_media_query-'+nextNr+'" href="#" class="delete ai-delete">Delete</a>');  	   
844	  evt.preventDefault();
845	  return false;
846	});		
847}
848
849function aiCheckHeightNumber(element, id) {
850	aiCheckInputNumber(element);
851	aiUpdateHeightHiddenField(id);
852}
853
854function aiCheckHeightNumberMediaQuery(element, id) {
855	aiCheckInputNumber(element);
856	aiUpdateHeightHiddenFieldMediaQuery(id);
857}
858
859
860function aiUpdateHeightHiddenField(id) {
861	var heightDefault = jQuery('#ai-'+id+'-0').val();
862	var breakpoints = [];
863	jQuery('.mq-breakpoint-'+id).each(function( index ) {
864      
865	   var heightChild = jQuery(this).children().eq(0).val();
866	   var breakpointChild = jQuery(this).children().eq(1).val();
867	   
868	   if (heightChild !== '' && breakpointChild !== '') { 
869		  breakpoints.push({
870             heightChild: heightChild,
871             breakpointChild: breakpointChild
872         });
873       }
874    });
875	
876	// we sort to have higher breakpoints first. Because of css cascading styles order is important
877	breakpoints.sort(function(a, b) { 
878	    return b.breakpointChild - a.breakpointChild; 
879	});
880
881	let output = heightDefault; 
882	breakpoints.forEach(function(element) { output += ',' + element.heightChild + '|' + element.breakpointChild; });
883	jQuery('#'+id).val(output);
884	const newVal = jQuery('#description-'+id).html().split('Shortcode attribute: ')[0];
885	jQuery('#description-'+id).html(newVal + 'Shortcode attribute: ' + id + '="' + output + '"');
886	
887}
888
889function aiUpdateHeightHiddenFieldMediaQuery(id) {
890	var breakpoints = [];
891	jQuery('.mq-breakpoint-'+id).each(function( index ) {
892      
893	   var mediaX = jQuery(this).children().eq(0).val();
894	   var mediaY = jQuery(this).children().eq(1).val();
895	   var mediaW = jQuery(this).children().eq(2).val();
896	   var mediaH = jQuery(this).children().eq(3).val(); 
897	   var mediaIW = jQuery(this).children().eq(4).val(); 
898	   var breakpointChild = jQuery(this).children().eq(5).val();
899	   
900	   if ((mediaX !== '' || mediaY !== '' || mediaW !== '' || mediaH !== '' || mediaIW !== '') &&
901 	       breakpointChild !== '') { 
902		   breakpoints.push({
903             mediaX: mediaX,
904			 mediaY: mediaY,
905			 mediaW: mediaW,
906			 mediaH: mediaH,
907			 mediaIW: mediaIW,
908             breakpointChild: breakpointChild
909         });
910       }
911    });
912	
913	// we sort to have higher breakpoints first. Because of css cascading styles order is important
914	breakpoints.sort(function(a, b) { 
915	    return b.breakpointChild - a.breakpointChild; 
916	});
917	
918	let output = '';
919	breakpoints.forEach(function(element) { output += ',' + element.mediaX + '|' + element.mediaY + '|' + 
920	element.mediaW + '|' + element.mediaH + '|' + element.mediaIW + '|' + element.breakpointChild });
921	output = output.replace(/(^,)|(,$)/g, "");
922	jQuery('#'+id).val(output);
923	// update description
924	const newVal = jQuery('#description-'+id).html().split('Shortcode attribute: ')[0];
925	jQuery('#description-'+id).html(newVal + 'Shortcode attribute: ' + id + '="' + output + '"');
926}
927
928		   
929function aiSettingsSearch(searchTerm, accType) {
930 var found = 0;
931
932 if (searchTerm !== '') {
933   jQuery('#ai p').not('.form-table p').hide();
934   jQuery('#ai ul').not('.form-table ul').hide();
935   jQuery('#ai ol').not('.form-table ol').hide();
936   if (accType !== 'false') {
937     jQuery('#ai h1').not('.show-always').hide();
938     jQuery('#ai #accordion').attr('id','acc');
939     jQuery('#ai #acc > div').show();
940     jQuery('#ai #spacer-div').show();
941   }
942   jQuery('#ai h2,#ai .icon_ai,#ai h3,#ai h4').not('.show-always').hide();
943   jQuery('#ai .form-table').addClass('ai-remove-margin');
944   jQuery('#ai hr, .signup_account_container, .config-file-block').hide();
945   jQuery('#ai .hide-always').hide();
946   jQuery('#ai .hide-search').hide();
947   jQuery('#ai .postbox-container').not('.show-always').hide();
948   jQuery('#ai .show-always p').show();
949   jQuery('#ai .show-always ul').show();
950   jQuery('#ai .show-always ol').show();
951   jQuery('#ai .show-always h2,#ai .show-always .icon_ai,#ai .show-always h3,#ai .show-always h4').show();
952 } else {
953   jQuery('#ai p').not('.form-table p').show();
954   jQuery('#ai section .ai-anchor').show();
955   jQuery('#ai ul').not('.form-table ul').show();
956   jQuery('#ai ol').not('.form-table ol').show();
957   if (accType !== 'false') {
958     jQuery('#ai h1').not('.show-always').show();
959     jQuery('#ai #acc').attr('id','accordion');
960     jQuery('#ai #accordion > div').hide();
961     jQuery('#ai #spacer-div').hide();
962   }
963   jQuery('#ai h2,#ai .icon_ai,#ai h3,#ai h4').not('.show-always').show();
964   jQuery('#ai .form-table').removeClass('ai-remove-margin');
965   jQuery('#ai hr, .signup_account_container, .config-file-block').show();
966   jQuery('#ai .sub-domain-container').show();
967   jQuery('#ai .hide-search').show();
968   jQuery('#ai .hide-always').hide();
969   jQuery('#ai .postbox-container').show();
970   
971   setTimeout(function() {
972       jQuery('#ai .postbox-container .closed .inside').css('display', '');
973   }, 5);   
974   
975 }
976
977 jQuery('#ai .mark-tab-header').removeClass('mark-tab-header');
978
979 var firstHit = '';
980
981 // check the search.
982  jQuery('#ai tr').each(function() {
983    var $this = jQuery(this);
984    var valueLabel = $this.find('th').text();
985    var valueDescription = $this.find('p.description').text();
986
987    valueLabel = (valueLabel !== undefined) ?  valueLabel.toLowerCase() : 'XXXXXXX';
988    valueDescription = (valueDescription !== undefined) ?  valueDescription.toLowerCase() : 'XXXXXXX';
989
990    if (valueLabel.indexOf(searchTerm) === -1 && valueDescription.indexOf(searchTerm) === -1) {
991      if ($this.parents('.show-always').length == 0) {
992	    $this.addClass('hide-setting');
993	  }
994    } else {
995	  $this.closest('table').prevAll('h2:first').show();
996	  $this.closest('.postbox-container').show();
997	  $this.closest('.postbox-container').find('h2, .inside').show();
998      $this.closest('table').prevAll('#ai .icon_ai:first').show();
999      $this.closest('table').nextAll('p.button-submit:first').show();
1000      $this.removeClass('hide-setting');
1001      $this.closest('.hide-search').show();
1002
1003      if (searchTerm.length > 2) {
1004        var headerId = $this.closest('section').attr('class');
1005        if (headerId !== undefined) {
1006            jQuery('#' + headerId).addClass('mark-tab-header');
1007            if (firstHit==='') {
1008              firstHit = headerId;
1009            }
1010        }
1011      }
1012      found++;
1013    }
1014  });
1015  if (found === 0) {
1016    jQuery('#ai-input-search-result').show();
1017    jQuery('#ai .mark-tab-header').removeClass('mark-tab-header');
1018  } else {
1019    jQuery('#ai-input-search-result').hide();
1020    // https://github.com/padolsey/findAndReplaceDOMText
1021    aiInstance && aiInstance.revert();
1022      if (searchTerm !== '' && searchTerm.length > 2) {
1023      var regex = RegExp(searchTerm, 'gi');
1024      aiInstance = findAndReplaceDOMText(document.getElementById('tab_wrapper'), {
1025        find: regex,
1026        wrap: 'em'
1027      });
1028    }
1029    jQuery('#' + firstHit).click();
1030
1031  }
1032}
1033
1034
1035/**
1036 *  Resizes the iframe with a certain ratio.
1037 *  Width is read and the height is than calculated.
1038 */
1039function aiResizeIframeRatio(obj, ratio) {
1040   aiDebugExtended("aiResizeIframeRatio");
1041   var width = jQuery('#' + obj.id).width();
1042   var valueRatio = parseFloat(ratio.replace(',', '.'));
1043   var newHeight = Math.ceil(width * valueRatio);
1044   obj.height = newHeight;
1045   obj.style.height = newHeight + 'px';
1046}
1047
1048/**
1049 * Generate a shortcode string from the current settings.
1050 */
1051function aiGenerateShortcode(isPro) {
1052    var output = '[advanced_iframe ';
1053
1054    // default section
1055    if (jQuery('#securitykey').val() !=='') {
1056      output += 'securitykey="' + jQuery('#securitykey').val() + '" ';
1057    }
1058    output += 'use_shortcode_attributes_only="true" ';
1059
1060    var include_html_val = jQuery('#include_html').val();
1061    var include_url_val = jQuery('#include_url').val();
1062    var document_domain_add = jQuery('#document_domain_add').val();
1063
1064    if (include_html_val === undefined || (include_html_val === '' && include_url_val === ''))  {
1065        var src = jQuery('#src').val();
1066        if (src === '') {
1067           alert('Required url is missing.');
1068        } else {
1069           output += 'src="' + src + '" ';
1070        }
1071
1072        output += aiGenerateTextShortcode('src_hide');
1073        output += aiGenerateTextShortcode('width');
1074        output += aiGenerateTextShortcode('height');
1075        output += aiGenerateRadioShortcode('scrolling','none');
1076		output += aiGenerateRadioShortcode('add_surrounding_p','false');
1077        output += aiGenerateRadioShortcode('enable_ios_mobile_scolling','false');
1078        output += aiGenerateTextShortcode('marginwidth');
1079        output += aiGenerateTextShortcode('marginheight');
1080        output += aiGenerateTextShortcode('frameborder');
1081        output += aiGenerateRadioShortcode('transparency','true');
1082        output += aiGenerateTextShortcode('class');
1083        output += aiGenerateTextShortcode('style');
1084        output += aiGenerateTextShortcodeWithDefault('id', 'advanced_iframe');
1085        output += aiGenerateTextShortcode('name');
1086        output += aiGenerateRadioShortcode('allowfullscreen','false');
1087        output += aiGenerateTextShortcode('safari_fix_url');
1088		output += aiGenerateTextShortcode('sandbox');
1089        output += aiGenerateTextShortcode('title');
1090        output += aiGenerateTextShortcode('allow');
1091		output += aiGenerateRadioShortcode('loading','lazy');
1092		output += aiGenerateTextShortcode('referrerpolicy');
1093		output += aiGenerateTextShortcode('custom');
1094		
1095		// advanced settings
1096        output += aiGenerateTextShortcode('url_forward_parameter');
1097        output += aiGenerateTextShortcode('map_parameter_to_url');
1098        output += aiGenerateRadioShortcode('add_iframe_url_as_param','false');
1099        output += aiGenerateTextShortcode('add_iframe_url_as_param_prefix');
1100		output += aiGenerateRadioShortcode('add_iframe_url_as_param_direct','false');
1101        output += aiGenerateRadioShortcode('use_iframe_title_for_parent','false');
1102        output += aiGenerateRadioShortcode('onload_scroll_top','false');
1103        output += aiGenerateRadioShortcode('hide_page_until_loaded','false');
1104        output += aiGenerateRadioShortcode('show_iframe_loader','false');
1105        output += aiGenerateTextShortcode('hide_content_until_iframe_color');
1106        output += aiGenerateTextShortcode('iframe_zoom');
1107        output += aiGenerateRadioShortcode('iframe_zoom_ie8', 'false');
1108        output += aiGenerateRadioShortcode('use_zoom_absolute_fix', 'false');
1109        output += aiGenerateRadioShortcode('auto_zoom', 'false');
1110        output += aiGenerateTextShortcode('auto_zoom_by_ratio');
1111
1112        output += aiGenerateRadioShortcode('enable_responsive_iframe','false');
1113        output += aiGenerateTextShortcode('iframe_height_ratio');
1114
1115
1116        output += aiGenerateRadioShortcode('enable_lazy_load','false');
1117        output += aiGenerateTextShortcodeWithDefault('enable_lazy_load_threshold','3000');
1118        output += aiGenerateRadioShortcode('enable_lazy_load_reserve_space','true');
1119
1120        output += aiGenerateTextShortcode('enable_lazy_load_fadetime');
1121        output += aiGenerateRadioShortcode('enable_lazy_load_manual','fal
1121se');
1122        output += aiGenerateRadioShortcode('enable_lazy_load_manual_element','false');
1123        output += aiGenerateTextShortcode('reload_interval');
1124
1125        // modify the parent page
1126       output += aiGenerateTextShortcode('hide_elements');
1127       output += aiGenerateTextShortcode('content_id');
1128       output += aiGenerateTextShortcode('content_styles');
1129       output += aiGenerateTextShortcode('parent_content_css');
1130       output += aiGenerateRadioShortcode('add_css_class_parent','false');
1131
1132       output += aiGenerateTextShortcode('change_parent_links_target');
1133       output += aiGenerateRadioShortcode('show_iframe_as_layer', 'false');
1134       output += aiGenerateRadioShortcode('show_iframe_as_layer_full', 'false');
1135
1136       output += aiGenerateTextShortcode('show_iframe_as_layer_autoclick_delay');
1137       output += aiGenerateTextShortcode('show_iframe_as_layer_autoclick_hide_time');
1138       output += aiGenerateTextShortcode('show_iframe_as_layer_header_file');
1139       output += aiGenerateTextShortcodeWithDefault('show_iframe_as_layer_header_height','100');
1140       output += aiGenerateRadioShortcode('show_iframe_as_layer_header_position', 'top');
1141       output += aiGenerateRadioShortcode('show_iframe_as_layer_keep_content', 'true');
1142
1143       // show only a part of the iframe
1144       var showPartOfIframe = aiGenerateRadioShortcode('show_part_of_iframe','false');
1145       output += showPartOfIframe;
1146
1147       if (showPartOfIframe !== '') {
1148         output += aiGenerateTextShortcodeWithDefault('show_part_of_iframe_x',-1);
1149         output += aiGenerateTextShortcodeWithDefault('show_part_of_iframe_y',-1);
1150         output += aiGenerateTextShortcode('show_part_of_iframe_width');
1151         output += aiGenerateTextShortcode('show_part_of_iframe_height');
1152		 output += aiGenerateTextShortcode('show_part_of_iframe_media_query');
1153         output += aiGenerateRadioShortcode('show_part_of_iframe_allow_scrollbar_horizontal','false');
1154         output += aiGenerateRadioShortcode('show_part_of_iframe_allow_scrollbar_vertical','false');
1155         output += aiGenerateTextShortcode('show_part_of_iframe_style');
1156         output += aiGenerateRadioShortcode('show_part_of_iframe_zoom','false');
1157
1158         output += aiGenerateTextShortcode('show_part_of_iframe_next_viewports');
1159         output += aiGenerateRadioShortcode('show_part_of_iframe_next_viewports_loop','false');
1160         output += aiGenerateTextShortcode('show_part_of_iframe_new_window');
1161         output += aiGenerateTextShortcode('show_part_of_iframe_new_url');
1162         output += aiGenerateRadioShortcode('show_part_of_iframe_next_viewports_hide','false');
1163       }
1164	   
1165	   // hide cover parts on an iframe
1166       output += aiGenerateTextShortcode('hide_part_of_iframe');
1167	   output += aiGenerateRadioShortcode('fullscreen_button','false');
1168	   output += aiGenerateTextShortcode('fullscreen_button_hide_elements');
1169	    
1170       // same domain
1171       output += aiGenerateRadioShortcode('add_css_class_iframe','false');
1172       output += aiGenerateTextShortcode('iframe_hide_elements');
1173       output += aiGenerateTextShortcode('onload_show_element_only');
1174       output += aiGenerateTextShortcode('iframe_content_id');
1175       output += aiGenerateTextShortcode('iframe_content_styles');
1176       output += aiGenerateTextShortcode('iframe_content_css');
1177       output += aiGenerateTextShortcode('change_iframe_links');
1178       output += aiGenerateTextShortcode('change_iframe_links_target');
1179       output += aiGenerateTextShortcode('change_iframe_links_href');
1180       
1181       // resize content height
1182       output += aiGenerateTextShortcode('onload');
1183       output += aiGenerateRadioShortcode('onload_resize','false');
1184       output += aiGenerateTextShortcode('onload_resize_delay');
1185       output += aiGenerateRadioShortcode('store_height_in_cookie','false');
1186       output += aiGenerateTextShortcode('additional_height');
1187       output += aiGenerateRadioShortcode('onload_resize_width','false');
1188       output += aiGenerateTextShortcode('resize_on_ajax');
1189       output += aiGenerateRadioShortcode('resize_on_ajax_jquery','true');
1190       output += aiGenerateTextShortcode('resize_on_click');
1191       output += aiGenerateTextShortcodeWithDefault('resize_on_click_elements','a');
1192
1193       output += aiGenerateTextShortcode('resize_on_element_resize');
1194       output += aiGenerateTextShortcodeWithDefault('resize_on_element_resize_delay','250');
1195
1196       // tabs
1197       output += aiGenerateTextShortcode('tab_hidden');
1198       output += aiGenerateTextShortcode('tab_visible');
1199       // cross domain ....
1200       output += aiGenerateRadioShortcode('add_document_domain','false');
1201       //
1202       if (document_domain_add === 'true') {
1203           output += aiGenerateTextShortcode('document_domain');
1204       }
1205       output += aiGenerateRadioShortcode('enable_external_height_workaround','external');
1206       output += aiGenerateRadioShortcode('hide_page_until_loaded_external','false');
1207       output += aiGenerateTextShortcode('pass_id_by_url');
1208	   output += aiGenerateRadioShortcode('multi_domain_enabled','true');
1209       if (isPro === 'true') {
1210           output += aiGenerateRadioShortcode('use_post_message','true');
1211	   } else {
1212		   output += aiGenerateRadioShortcode('use_post_message','false');
1213	   }
1214       // additional files
1215       output += aiGenerateTextShortcode('additional_css');
1216       output += aiGenerateTextShortcode('additional_js');
1217       output += aiGenerateTextShortcode('additional_js_file_iframe');
1218       output += aiGenerateTextShortcode('additional_css_file_iframe');
1219   } else { // include content directly
1220      if (include_html_val === '')  {
1221         output += aiGenerateTextShortcode('include_url');
1222         output += aiGenerateTextShortcode('include_content');
1223         output += aiGenerateTextShortcode('include_height');
1224         output += aiGenerateTextShortcode('include_fade');
1225         output += aiGenerateRadioShortcode('include_hide_page_until_loaded','false');
1226      } else {
1227         output += aiGenerateTextShortcode('include_html');
1228      }
1229   }
1230   // options
1231   output += aiGenerateRadioShortcode('debug_js','false');
1232   output = output.slice(0, -1);
1233   output += ']';
1234   jQuery('#gen-shortcode').html(output);
1235}
1236
1237/**
1238 * Generate a text shortcode with default
1239 */
1240function aiGenerateTextShortcodeWithDefault(field, defaultValue) {
1241    var output = '';
1242    var value = jQuery('#' + field);
1243    var val = value.val();
1244    if (value.length > 0 && val !== '' && val !== defaultValue) {
1245        output = field + '="' + val + '" ';
1246    }
1247    return output;
1248}
1249
1250/**
1251 * Generate a text shortcode if the value is not empty or != 0
1252 */
1253function aiGenerateTextShortcode(field) {
1254    var output = '';
1255    var value = jQuery('#' + field);
1256    var val = value.val();
1257    if (value.length > 0 && val !== '' && val !== '0') {
1258        output = field + '="' + val + '" ';
1259    }
1260    return output;
1261}
1262
1263/**
1264 * Generate a radio shortcode with default
1265 */
1266function aiGenerateRadioShortcode(field, defaultValue) {
1267    var output = '';
1268    var value = jQuery('input:radio[name='+field+']:checked');
1269    var val = value.val();
1270    
1271	if (field === 'enable_ios_mobile_scolling') {
1272	    field = 'enable_ios_mobile_scrolling';
1273	}
1274	
1275	if (value.length > 0 && val !== defaultValue) {
1276        output += field + '="' + val + '" ';
1277    }
1278    return output;
1279}
1280
1281/**
1282 * Add a css class to the parents to enable that the iframe parents
1283 * can be identified very easy. Is an is ist set ai-class-<id> is used.
1284 * Otherwise a-class-<number> with an increasing number is used.
1285 */
1286function aiAddCssClassAllParents(element) {
1287  var parents = jQuery(element).parentsUntil( 'html' );
1288  var ai_class= 'ai-class-';
1289  for(var i = 0; i < parents.length; i++){
1290    var id = jQuery(parents[i]).attr('id');
1291    if (typeof id !== 'undefined') {
1292      if (id.indexOf('ai-') !== 0) {
1293          jQuery(parents[i]).addClass(ai_class + id);
1294      }
1295    } else {
1296      jQuery(parents[i]).addClass(ai_class + i);
1297    }
1298  }
1299}
1300
1301function aiAutoZoomExternalHeight(id, width, height, responsive) {
1302    aiDebugExtended("aiAutoZoomExternalHeight");
1303	var parentWidth = aiAutoZoomExternal(id, width, responsive);
1304    var zoomRatio = window['zoom_' + id];
1305    var oldScrollposition = jQuery(document).scrollTop();
1306    var newHeight = Math.ceil(height*zoomRatio);
1307    jQuery('#ai-zoom-div-' + id).css('height', newHeight);
1308    jQuery("html,body").scrollTop(oldScrollposition); 
1309 return parentWidth;
1310}
1311
1312
1313function aiAutoZoomExternal(id, width, responsive) {
1314   aiDebugExtended("aiAutoZoomExternal");
1315   var obj =  document.getElementById(id);
1316   var objAround =  document.getElementById('ai-zoom-div-' +id);
1317   var jObj = jQuery('#' + id);
1318
1319   if (responsive === 'true') {
1320    jObj.css('max-width', '100%');
1321   }
1322   var iframeWidth = width;
1323   var parentWidth = aiGetParentIframeWidth(obj);
1324   if (parentWidth === iframeWidth) {
1325     // we check again the surrounding div as some browser do return the zoomes value!
1326     parentWidth = aiGetParentIframeWidth(objAround);
1327   }
1328   var zoomRatio = parentWidth / iframeWidth;
1329   var zoomRatioRounded = Math.floor(zoomRatio * 100) / 100;
1330   if (zoomRatioRounded > 1) {
1331     zoomRatioRounded = 1;
1332   }
1333
1334   aiSetZoom(id, zoomRatioRounded);
1335   window['zoom_' + id] = zoomRatioRounded;
1336   jObj.width(iframeWidth).css('max-width', 'none');
1337   return parentWidth;
1338}
1339function aiAutoZoom(id, responsive, ratio) {
1340   aiDebugExtended("aiAutoZoom");
1341   var parts = ratio.split('|');
1342   ratio = parts[0];
1343   var width = -1;
1344   if (parts.length !== 1) {
1345     width = parts[1];
1346   }
1347
1348   var obj = document.getElementById(id);
1349   var iframeWidth; 
1350   if (width === -1) {
1351     obj.width = 1; // set to 1 because otherwise the iframe does never get smaller.
1352     obj.style.width = '1px';
1353     iframeWidth = aiGetIframeWidth(obj);
1354     obj.width = iframeWidth;
1355     obj.style.width = iframeWidth + 'px';
1356   } else {
1357     iframeWidth = width;
1358   }
1359
1360   var parentWidth = aiAutoZoomExternal(id, iframeWidth, responsive);
1361   if (ratio === '') {
1362     aiResizeIframe(obj, false);
1363   } else {
1364      var newheight = Math.ceil(iframeWidth * ratio);
1365      obj.height = newheight;
1366      obj.style.height = newheight + 'px';
1367      // set the height of the zoom div
1368      if (jQuery('#ai-zoom-div-' + obj.id).length !== 0) {
1369         var zoom = window['zoom_' + obj.id];
1370         jQuery('#ai-zoom-div-' + obj.id).css('height', Math.ceil(newheight * zoom));
1371      }
1372   }
1373   return parentWidth;
1374}
1375
1376/**
1377 * Set the zoom div settings dynamically.
1378 */
1379function aiSetZoom(id, zoom) {
1380
1381  var obj = jQuery('#' + id);
1382
1383  if (aiIsIe8 === true) {
1384    obj.css('-ms-zoom', zoom);
1385  }
1386
1387  obj.css({
1388    '-ms-transform': 'scale(' + zoom + ')',
1389    '-moz-transform': 'scale(' + zoom + ')',
1390    '-o-transform': 'scale(' + zoom + ')',
1391    '-webkit-transform': 'scale(' + zoom + ')',
1392    'transform': 'scale(' + zoom + ')'
1393  });
1394}
1395
1396function aiAutoZoomViewport(id, full) {
1397
1398  var viewportDiv = jQuery(id);
1399  var outerDiv = viewportDiv.parent();
1400  var counter = 0;
1401
1402  // We only go up and look for divs which are not from ai or p elements which are rendered by mistake.
1403  while (outerDiv.is('p') || (outerDiv.attr('id') !== undefined && outerDiv.attr('id').indexOf('ai-') === 0)) {
1404     outerDiv = outerDiv.parent();
1405     if (counter++ > 10) {
1406        alert('Unexpected div structure. Please disable the zoom.');
1407        break;
1408     }
1409  }
1410
1411  var viewportDivWidth = viewportDiv.width();
1412  var outer_div_width = outerDiv.width();
1413  var viewportDivHeight = viewportDiv.height();
1414  var zoom = outer_div_width / viewportDivWidth;
1415
1416  if (full === 'true' && zoom > 1) {
1417     zoom = 1;
1418  }
1419
1420  aiSetZoom(viewportDiv.attr('id'), zoom);
1421  // set the margin because otherwise it is normally "centered" in the old area
1422  var marginLeft = -Math.round((viewportDivWidth - viewportDivWidth * zoom) / 2);
1423  var marginTop = -Math.round((viewportDivHeight - viewportDivHeight * zoom) / 2);
1424  viewportDiv.css({
1425    'margin-left':  marginLeft + 'px',
1426    'margin-right':  marginLeft + 'px',
1427    'margin-top':  marginTop + 'px',
1428    'margin-bottom':  marginTop + 'px'
1429  });
1430
1431
1432}
1433
1434function aiResetAiSettings() {
1435  jQuery('#action').val('reset');
1436}
1437
1438function aiCheckInputNumber(inputField) {
1439    inputField.value = inputField.value.split(' ').join('');
1440    var f = inputField.value;
1441    if (inputField.value === '') { 
1442        return;
1443    }
1444    var match = f.match(/^(\-){0,1}([\d.])+(px|%|em|pt|vh|vw|rem|ch)?(\-|\+){0,1}([\d.]){0,7}(px|%|em|pt|vh|vw|rem|ch)?$/);
1445
1446    if (!match) {
1447        alert('Please check the value you have entered. Only numbers with a dot or with an optional px, %, em or pt are allowed.');
1448        setTimeout(function(){inputField.focus();}, 10);
1449    }
1450}
1451
1452
1453function aiCheckInputPurchaseCode (inputField) {
1454    inputField.value = inputField.value.split(' ').join('');
1455    var f = inputField.value;
1456    if (inputField.value === '') { 
1457        return;
1458    }
1459	
1460	if (!f.match(/^([a-f0-9]{8})-(([a-f0-9]{4})-){3}([a-f0-9]{12})$/i)) {
1461        alert('Please check the value you have entered. Your input seems not to be a valid purchase code.');
1462		inputField.value = '';
1463        setTimeout(function(){inputField.focus();}, 10);
1464    }
1465}
1466
1467
1468
1469function aiCheckInputNumberOnly(inputField) {
1470    inputField.value = inputField.value.split(' ').join('');
1471    var f = inputField.value;
1472    if (inputField.value === '') {
1473      inputField.value = '0';
1474      return;
1475    }
1476    var match = f.match(/^(\-){0,1}([\d.])+$/);
1477
1478    if (!match) {
1479        alert('Please check the value you have entered. Only numbers without a dot or optional px, %, em or pt are allowed.');
1480        setTimeout(function(){inputField.focus();}, 10);
1481    }
1482}
1483// https://codepen.io/anon/pen/baaLYB/
1484function aiShowHeader(id, element) {
1485  var y = jQuery(window).scrollTop();
1486  jQuery(window).scrollTop(y-40);
1487  if (element !== undefined) {
1488    aiFlashElement(element);
1489  }
1490}
1491
1492function aiFlashElement(element) {
1493  setTimeout(function() { jQuery('#' +element).css('background-color','#eee'); } , 500); 
1494  setTimeout(function() { jQuery('#' +element).css('background-color','#fff'); } , 900); 
1495  setTimeout(function() { jQuery('#' +element).css('background-color','#eee'); } , 1300); 
1496  setTimeout(function() { jQuery('#' +element).css('background-color','#fff'); } , 1700); 
1497}
1498
1499function aiSetScrollposition() {
1500  var scrollposition = jQuery(document).scrollTop();
1501  jQuery('#scrollposition').val(scrollposition); // +32
1502}
1503
1504function aiResetShowPartOfAnIframe(id) {
1505  jQuery('#' + id).css('top','0px').css('left','0px').css('position','static');
1506  jQuery('#ai-div-' + id).css('width','auto').css('height','auto').css('overflow','auto').css('position','static');
1507}
1508
1509function aiShowLayerIframe(event, id, path, hideUntilLoaded, showLoadingIcon, keep, reload) {
1510  aiDebugExtended("aiShowLayerIframe");
1511  keep = (keep === undefined) ? false : keep;
1512  reload = (reload === undefined) ? true : reload;
1513
1514  var layerId = '#' + id;
1515  jQuery('#ai-zoom-div-' + id).show();
1516  if  (reload && hideUntilLoaded === 'true') {
1517      jQuery(layerId).css('visibility', 'hidden');
1518  }
1519  jQuery(layerId).show();
1520  if ( jQuery( '#ai-layer-div-' + id ).length ) {
1521    layerId = '#ai-layer-div-' + id;
1522    jQuery(layerId).show();
1523  }
1524
1525  jQuery('body').css('overflow','hidden');
1526  jQuery('html').css('overflow-y','visible');
1527  jQuery('body').append('<img id="ai_backlink" src="'+path+'close.png" style="z-index:100005;position:fixed;top:0;right:0;cursor:pointer" />');
1528  // was 'body' before
1529
1530  var icon = '<!-- -->';
1531  if (reload && showLoadingIcon==='true') {
1532    icon = '<div id="ai-div-loader-global" style="position: fixed;z-index:100004;margin-left:-33px;left: 50%;top:50%;margin-top:-33px"><img src="' + path + 'loader.gif" width="66" height="66" title="Loading" alt="Loading"></div>';
1533  }
1534
1535  if (jQuery('#ai_backlayer').length === 0) { // we do not have a layer yet...
1536      jQuery(layerId).parent().append('<div id="ai_backlayer" style="z-index:100001;position:fixed;top:0;left:0;width:100%;height:100%;background-color: rgba(50,50,50,0.5);overflow:hidden;cursor:pointer"><!-- --></div>' + icon);
1537  }
1538  
1539  jQuery( '#ai_backlink, #ai_backlayer' ).click(function() {
1540    aiHideLayerIframe(id, keep);
1541  });
1542  if (!reload) {
1543    event.preventDefault();
1544    event.stopPropagation();
1545  }
1546}
1547
1548function aiHideLayerIframe(id, keep) {
1549  aiDebugExtended("aiHideLayerIframe");
1550  jQuery('#' + id).hide();
1551  if (!keep) {
1552      jQuery('#' + id).attr('src', 'about:blank');
1553      aiLayerIframeHrefs[id] = 'about:blank';
1554  }
1555  jQuery('#ai-zoom-div-' + id).hide();
1556  jQuery('#ai-layer-div-' + id).hide();
1557  jQuery('#ai_backlink').remove();
1558  jQuery('#ai_backlayer').remove();
1559  jQuery('#ai-div-loader-global').remove();
1560  jQuery('body').css('overflow','auto');
1561  jQuery('html').css('overflow-y','scroll');
1562}
1563
1564
1565/**
1566 * As the src of an iframe cannot be read from a remote domain we remember
1567 * the urls from the links here for each opened iframe.
1568 */
1569var aiLayerIframeHrefs = [];
1570
1571/**
1572 * Check if the location of the iframe is already the one of the link.
1573 * The iframe is only loaded if it is was not loaded already.
1574 *
1575 * true - if src and url of the iframe is different and need to be loaded
1576 * false - if it is already the same;
1577 */
1578
1579
1580function aiCheckReload (link, id) {
1581    var iframeSrc;
1582    if(typeof aiLayerIframeHrefs[id] === 'undefined') {
1583        iframeSrc = jQuery('#' + id).attr('src');
1584    } else {
1585        iframeSrc = aiLayerIframeHrefs[id];
1586    }
1587    var linkHref = jQuery(link).attr('href');
1588    // alert(linkHref + ": iframe:" + iframeSrc);
1589    aiLayerIframeHrefs[id] = linkHref;
1590    return (iframeSrc !== linkHref);
1591}
1592
1593function aiChangeTitle(id) {
1594   aiDebugExtended("aiChangeTitle");
1595   try {
1596   var title = document.getElementById(id).contentDocument.title;
1597	   if (title !== null && title !== 'undefined' && title !== '') {
1598		   document.title = title;  
1599	   } 
1600   } catch(e) {
1601    if (console && console.error) {
1602      console.error('Advanced iframe configuration error: You have enabled to add the title if the iframe to the parent on the same domain. But you use an iframe page on a different domain. You need to use the pro version of the external workaround like described in the settings. Also check the next log. There the browser message for this error is displayed.');
1603      console.log(e);
1604    }
1605  }
1606}
1607
1608/**
1609 * This changes the current url and adds or updates the
1610 * existing parameter with the given url
1611 */
1612function aiChangeUrlParam(loc, param, orig, prefix, isDirect) {
1613   aiDebugExtended("aiChangeUrlParam");
1614   var newUrl;
1615   var keepSlash = false;
1616   
1617   // add protocol if // is used in the shortcode 
1618   if (orig.lastIndexOf("//", 0) !== -1) {
1619	   orig = location.protocol + orig;
1620   }
1621   
1622   if (loc !== encodeURIComponent(orig)) {
1623	 newUrl = aiSetGetParameter(param, loc);
1624	 var removeProtocol = true;
1625     if (prefix.startsWith('hash')) {
1626		 var locBase = loc; // aiRemoveQueryString(loc);
1627		 return aiGetUrlMapping(locBase, param, prefix);
1628	 } else if (prefix) {
1629       var repUrl = newUrl.replace(prefix,'');
1630       if (repUrl === newUrl) {
1631         removeProtocol = false;
1632       }
1633       newUrl = repUrl;
1634     }
1635     
1636	 // remove protocoll
1637     if (removeProtocol) {
1638       newUrl = newUrl.replace('http%3A%2F%2F','');
1639       if (window.location.href.toLowerCase().lastIndexOf("http:", 0) !== -1) {
1640           newUrl = newUrl.replace('https%3A%2F%2F','s|');  
1641       } else {
1642           newUrl = newUrl.replace('https%3A%2F%2F','');
1643       }
1644     }
1645	 
1646     if (isDirect) {		
1647		var newUrl = aiRemoveQueryString(window.location.href);
1648		var locDecoded = decodeURIComponent(loc);
1649		var queryStart = locDecoded.indexOf('?');
1650		if (queryStart !== -1) {
1651			var queryPart = locDecoded.slice(queryStart + 1);
1652			newUrl += '?' + queryPart;
1653			keepSlash = true;
1654		}		
1655	 } 
1656	 if (aiEndsWidth(newUrl, param + "=")) { 
1657        newUrl = aiRemoveURLParameter(newUrl, param);
1658     }
1659   } else {
1660      var fullUrl = window.location.href;
1661	  // remove param/* first
1662	  fullUrl = fullUrl.split("/" + param + "/",1)[0];
1663	  newUrl = aiRemoveURLParameter(fullUrl, param);
1664   }
1665
1666   aiSetBrowserUrl(newUrl, keepSlash); 
1667}
1668
1669function aiGetUrlMappingUrl(param, prefix, id) {
1670	 var fullUrl = window.location.href;
1671	 
1672	 param = param.replace(":short", "");
1673	 var newUrl = aiRemoveURLParameter(fullUrl, param);
1674	 if (prefix.startsWith('hashrewrite')) {
1675		 // remove param/* first
1676		 var queryString = "";
1677		 if (newUrl.indexOf('?') >= 0) {
1678			 var newUrlArray = newUrl.split('?'); 
1679			 newUrl = newUrlArray[0];
1680			 queryString = '?' + newUrlArray[1]; 
1681		 }
1682		 var baseUrl = newUrl.split("/" + param + "/",1)[0];
1683		 // add the path before the query string 
1684		 if (!aiEndsWidth(baseUrl, "/")) {
1685			 baseUrl += '/';
1686		 }
1687		 var path = param +"/";
1688		 newUrl = baseUrl + path + id + queryString;
1689	 } else {
1690		 var seperator = (newUrl.indexOf('?') >= 0) ? '&' : '?'; 
1691		 newUrl += seperator+param+"=" + id;
1692	 }		 
1693	return newUrl;
1694}
1695
1696function aiSetBrowserUrl(newUrl, keepSlash) {
1697	if (aiSupportsHistoryApi()) {
1698        if (!keepSlash) {
1699		    newUrl = newUrl.replace(/%2F/g,'/');
1700		}
1701        window.history.pushState({}, '', newUrl);
1702        // I asume the back button is clicked.
1703        window.onpopstate = function(event) {
1704          if(event && event.state) {
1705            window.history.back();
1706          }
1707        };
1708    }
1709}
1710
1711function aiRemoveQueryString(loc) {
1712    if (loc.indexOf('%3F') >= 0) {
1713	    return loc.split('%3F')[0]; 
1714	} else if (loc.indexOf('?') >= 0) {
1715	    return loc.split('?')[0]; 
1716	} else { 
1717	 return loc;
1718	}
1719}	
1720
1721function aiGetUrlMapping(url, param, prefix) {
1722	var data = {
1723      action: 'aip_map_url_action',
1724      security : MyAjax.security,
1725      url: url
1726    };
1727	
1728    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1729    jQuery.post(MyAjax.ajaxurl, data, function(id) {
1730       var newUrl = aiGetUrlMappingUrl(param, prefix, id);
1731	   aiSetBrowserUrl(newUrl, false);   
1732   });  
1733}
1734
1735function closeInfoPermanent(id) {
1736	var data = {
1737      action: 'aip_close_message_permanent',
1738      security : MyAjax.security,
1739      id: id
1740    };
1741    // since 2.8 ajaxurl is always defined in the admin header and points to admin-ajax.php
1742    var message = 'The message before will only appear again when you reset the advanced iframe settings.';
1743	if (id === 'show-discount-message') {
1744		message = 'The message of advanced iframe shown before will only appear again when you reset the advanced iframe settings or a new discount is available.';
1745	} else if (id === 'show-registration-message') {
1746		message = 'The message will appear again until have entered your purchase code.';
1747	}
1748	
1749	jQuery.post(MyAjax.ajaxurl, data, function(id) {
1750	   jQuery('h1').after('<div class="message-notice notice notice-success"><p>' + message + '</p></div>'); 
1751    }); 
1752    setTimeout(function() { jQuery(".message-notice").fadeOut() }, 4000);     
1753}
1754
1755
1756function aiSupportsHistoryApi() {
1757  return !!(window.history && history.pushState);
1758}
1759
1760function aigetIframeLocation(id) {
1761  try {
1762    var location = document.getElementById(id).contentWindow.location;
1763    return encodeURIComponent(location);
1764  }  catch(e) {
1765    if (console && console.error) {
1766      console.error('Advanced iframe configuration error: You have enabled to add the url to the url on the same domain. But you use an iframe page on a different domain. You need to use the pro version of the external workaround like described 
1766in the settings. Also check the next log. There the browser message for this error is displayed.');
1767      console.log(e);
1768    }
1769  }
1770}
1771
1772
1773/**
1774 * Replaces a url parameter with a given value.
1775 */
1776function aiSetGetParameter(paramName, paramValue)
1777{
1778    var url = window.location.href;
1779    var splitAtAnchor = url.split('#');
1780    url = splitAtAnchor[0];
1781    var anchor = typeof splitAtAnchor[1] === 'undefined' ? '' : '#' + splitAtAnchor[1];
1782    if (url.indexOf(paramName + '=') >= 0) {
1783        var prefix = url.substring(0, url.indexOf(paramName+ '='));
1784        var suffix = url.substring(url.indexOf(paramName+ '='));
1785        suffix = suffix.substring(suffix.indexOf('=') + 1);
1786        suffix = (suffix.indexOf('&') >= 0) ? suffix.substring(suffix.indexOf('&')) : '';
1787        url = prefix + paramName + '=' + paramValue + suffix;
1788    } else {
1789      if (url.indexOf('?') < 0)  {
1790          url += '?' + paramName + '=' + paramValue;
1791      } else {
1792          url += '&' + paramName + '=' + paramValue;
1793      }
1794    }
1795    return url + anchor;
1796}
1797
1798/**
1799 * Remove a given parameter from the url
1800 */
1801function aiRemoveURLParameter(url, parameter) {
1802    //prefer to use l.search if you have a location/link object
1803    var urlparts= url.split('?');
1804    if (urlparts.length>=2) {
1805
1806        var prefix= encodeURIComponent(parameter)+'=';
1807        var pars= urlparts[1].split(/[&;]/g);
1808
1809        //reverse iteration as may be destructive
1810        for (var i= pars.length; i-- > 0;) {
1811            //idiom for string.startsWith
1812            if (pars[i].lastIndexOf(prefix, 0) !== -1) {
1813                pars.splice(i, 1);
1814            }
1815        }
1816        if (pars.length !== 0) {
1817            url= urlparts[0]+'?'+pars.join('&');
1818        } else {
1819            url= urlparts[0];
1820        }
1821        return url;
1822    } else {
1823        return url;
1824    }
1825}
1826
1827function aiEndsWidth(string, target) {
1828  return string.substr(-target.length) === target;
1829}
1830
1831/**
1832* Adds css to the end of the body to make sure that styles are
1833* not overwritten by inline css of any kind.
1834*/
1835function aiAddCss(id,css){
1836    css = decodeURIComponent(css.replace(/\+/g, '%20'));
1837
1838    var body = jQuery(id).contents().find('body');
1839    var s = document.createElement('style');
1840    s.setAttribute('type', 'text/css');
1841    if (s.styleSheet) {   // IE
1842        s.styleSheet.cssText = css;
1843    } else {                // the world
1844        s.appendChild(document.createTextNode(css));
1845    }
1846    body.append(s);
1847}
1848
1849/**
1850 * add a css file to the end of the body to make sure that styles
1851 *  are not overwritten by inline css of any kind.
1852 */
1853function aiAddCssFile(id, filename) {
1854    var body = jQuery(id).contents().find('body');
1855    var link = document.createElement('link');
1856    link.rel = 'stylesheet';
1857    link.type ='text/css';
1858    link.href = filename;
1859    body.append(link);
1860}
1861
1862/**
1863 * Add a Javascript file to the end of the body
1864 */
1865function aiAddJsFile(id, filename) {
1866    jQuery.ajaxSetup({ cache:true});
1867
1868    var body = jQuery(id).contents().find('body');
1869    var script = document.createElement('script');
1870    script.type ='text/javascript';
1871    script.src = filename;
1872    body.append(script);
1873}
1874
1875function aiPresetFullscreen() {
1876    jQuery('#style').val('position:fixed;z-index:9000;top:0px;left:0px;margin:0px');
1877    jQuery('#width').val('100%');
1878    jQuery('#ai-height-0').val('100%');
1879    jQuery('#content_id').val('html,body');
1880    jQuery('#content_styles').val('overflow:hidden');
1881    jQuery('#hide_content_until_iframe_color').val('#ffffff');
1882}
1883
1884/**
1885 * main ready function that calls all generated callbacks.
1886 * Add dynamically created functions that should be loaded
1887 * when the page is read to aiReadyCallbacks
1888 */
1889jQuery(document).ready(function() {
1890	aiDebugExtended("document.ready called");
1891   
1892	// wordpress adds often p elements that have margins we remove here. 
1893	jQuery('iframe').parent('p').css('margin','0');
1894	
1895	aiWindowWidth = jQuery(window).width();
1896    jQuery.each(aiReadyCallbacks, function(index, callback){
1897      callback();
1898    });
1899	
1900	jQuery('.ai-fullscreen-open').on('click', function(){ 
1901		jQuery(this).closest('.ai-wrapper-div').addClass("ai-fullscreen-wrapper");
1902		jQuery(this).closest('.ai-wrapper-div').find('iframe').addClass("ai-fullscreen");
1903		jQuery('.ai-fullscreen-open').hide();
1904		jQuery('.ai-fullscreen-hide').addClass("ai-fullscreen-display-none");
1905		
1906		jQuery('html,body').css('overflow','hidden');
1907		
1908		var id = jQuery(this).data("id");
1909		// show/render the close button
1910		jQuery('.ai-fullscreen-close-' + id).show();
1911        jQuery(document).on('keydown',function(evt) {
1912        if (evt.key == "Escape") {
1913           jQuery('.ai-fullscreen-close').trigger( "click" );
1914        }
1915        });
1916    });
1917	
1918	jQuery('.ai-fullscreen-close').on('click', function(){ 
1919		// remove css for fullscreen-open
1920		jQuery('div.ai-wrapper-div').removeClass("ai-fullscreen-wrapper")
1921		jQuery('iframe.ai-fullscreen').removeClass("ai-fullscreen");
1922		jQuery('html').css('overflow',aiOverflowHtml);
1923		jQuery('body').css('overflow',aiOverflowBody);
1924		
1925		// hide/remove the close button
1926		jQuery('.ai-fullscreen-close').hide();
1927		// show the fullscreen icon again
1928		jQuery('.ai-fullscreen-open').show();
1929		jQuery('.ai-fullscreen-display-none').removeClass("ai-fullscreen-display-none");
1930
1931        jQuery(document).off("keydown");
1932    });
1933	
1934	setTimeout(function() { jQuery("#ai #ai-updated-text").css("visibility","hidden")}, 4000);
1935	
1936    jQuery('#ai #checkIframes').on('click', function(){ 
1937        jQuery('.ai-spinner').css('display','inline-table');
1938		jQuery(this).addClass('disabled');
1939		setTimeout(aiDisableCheckIframes, 200);
1940    });
1941
1942    var moved=false;
1943    jQuery('#aiDebugDivTotal').mousedown(function(){moved=false;}).mousemove(function(){moved=true;}).mouseup(function(event){
1944        if(!moved){
1945           var elem = jQuery('#aiDebugDiv');
1946            if (Math.floor(elem.height()) > '300') {
1947                elem.height('0px');
1948            } else {
1949               elem.height('400px');
1950            }
1951        }
1952    });
1953
1954    if (typeof ai_show_id_only !== 'undefined') {
1955         if (jQuery('#' + ai_show_id_only).length === 0) {
1956             alert('The element with the id "' + ai_show_id_only + '" cannot be found. Please check your configuration.');
1957         } else {
1958             var element = jQuery('#' + ai_show_id_only);
1959             element.siblings().hide();
1960             var parents = element.parents();
1961             parents.siblings().hide();
1962             parents.css('padding', '0px').css('margin', '0px').css('overflow', 'hidden');
1963
1964             // we send the size of the element as post message if we are in an iframe
1965             if(parent===top) {
1966                var elementRaw = element[0];
1967				elementRaw.style.marginTop = elementRaw.style.marginBottom = 0;
1968                elementRaw.style.overflow = "hidden";
1969                var newHeightRaw =  Math.max(elementRaw.scrollHeight, elementRaw.offsetHeight);
1970                var newHeight = parseInt(newHeightRaw,10);
1971                var data = { 'aitype' : 'height', 'height' : newHeight, 'id' : ai_show_id_only};
1972                var json_data = JSON.stringify(data);
1973                window.parent.postMessage(json_data, '*');
1974            }
1975       }
1976    }
1977	
1978	jQuery('#ai #checkIframes').on('click', function(){ 
1979        jQuery('.ai-spinner').css('display','inline-table');
1980		jQuery(this).addClass('disabled');
1981		setTimeout(aiDisableCheckIframes, 200);
1982    });	
1983});
1984
1985function aiDisableCheckIframes() {
1986	var input = jQuery("<input>").attr("type", "hidden").attr("name", "checkIframes").val("true");
1987    jQuery("#ai_form").append(input);
1988	jQuery( "#ai_form" ).submit();
1989    jQuery('#checkIframes').prop('disabled','disabled');
1990}
1991
1992function aiProcessMessage(event,id,debug) {
1993   var jsObject;
1994  try {
1995    var jsObject = JSON.parse(event.data);
1996  } catch(e) {
1997    // Result is not expected so we try if data is an object already
1998    // because a converter was not implemented properly.
1999     if (debug === 'debug' && console && console.log) {
2000          console.log('Advanced iframe: The received message cannot be parsed and seems not to belong to advanced iframe pro. Please disable the postMessage debug mode if this o.k. and that this message is not shown anymore.');
2001          console.log("Advanced iframe: Unknown event: ", event);
2002        }
2003    var jsObject = event.data; 
2004  }  
2005  try {
2006    // we only process objects from advanced iframe
2007    if (jsObject.hasOwnProperty('aitype')) {
2008      // we only process the ones for the same id here.
2009      if ( id === jsObject.id) {
2010          var type = jsObject.aitype;
2011          if (type === 'debug') {
2012             aiProcessDebug(jsObject);
2013          } else if (type === 'scrollToTop') {
2014             aiProcessScrollToTop(jsObject);
2015          } else {
2016            // check if the data is of the expected
2017            if (type === 'height') {
2018              aiProcessHeight(jsObject);
2019            } else if (type === 'show') {
2020              aiProcessShow(jsObject);
2021            }
2022            for (var key in jsObject.data) {
2023              if (jsObject.data.hasOwnProperty(key)) {
2024                jQuery(key).html(jsObject.data[key]);
2025              }
2026            }
2027          } 
2028        } 
2029	  }
2030	} catch(e) {
2031        if (debug === 'debug' && console && console.log) {
2032          console.log('Advanced iframe: The received message do not belong to advanced iframe pro. Please disable the postMessage debug mode if this o.k. and that this message is not shown anymore.');
2033          console.log(e);
2034        }
2035  }
2036}
2037
2038function aiProcessDebug(jsObject) {
2039    var debugData = jsObject.data;
2040    if (jQuery('#aiDebugDiv').length !== 0) {
2041		debugData = debugData.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
2042        debugData = debugData.replace('\"', '"').replace(/\\/g,"");
2043		jQuery('#aiDebugDiv').append('<p class="ai-debug-remote"> r: ' + debugData + '</p>');
2044    }
2045}
2046
2047function aiProcessScrollToTop(jsObject) {
2048     var id = jsObject.id;
2049     aiScrollToTop(id, aiOnloadScrollTop);
2050}
2051
2052function aiProcessHeight(jsObject) {
2053    var nHeight = jsObject.height; 
2054    var nWidth = jsObject.width; 
2055    var iAnchor = parseInt(jsObject.anchor,10);
2056    var id = jsObject.id;
2057
2058    if (nHeight != null) {
2059      try {
2060        var loc = jsObject.loc;
2061        if (loc != null && !loc.includes("send_console_log")) {
2062          if (typeof aiChangeUrl === "function"){
2063		      aiChangeUrl(loc);
2064		  }
2065        }
2066		var title = jsObject.title;
2067        if (title != null && title != "undefined" && title != "") {
2068            document.title = decodeURIComponent(title);
2069        }
2070        if (id != null) {
2071            var iHeight = parseInt(nHeight,10);
2072            var iWidth = parseInt(nWidth,10);
2073            aiResizeIframeHeightId(iHeight,iWidth, id);
2074            if (!isNaN(iAnchor) && iAnchor > -1) {
2075				// 
2076				var iframeTop = jQuery("#" + id).offset().top; 
2077                setTimeout(function() {
2078                    jQuery("html,body").scrollTop(Math.round(iframeTop + iAnchor));
2079					aiShowIframeId(id);
2080                }, 100);   
2081            } else {
2082				aiShowIframeId(id);
2083			}
2084        } else {
2085            alert('Please update the ai_external.js to the current version.');
2086        }
2087    	} catch(e) {
2088        if (console && console.log) {
2089          console.log(e);
2090        }
2091      }
2092    }
2093}
2094
2095function aiProcessShow(jsObject) {
2096  var id = jsObject.id;
2097
2098  try {
2099     aiShowIframeId(id);
2100  } catch(e) {
2101    if (console && console.log) {
2102      console.log(e);
2103    }
2104  }
2105}
2106
2107function aiDisableRightClick(id) {
2108	try {	
2109	   window.frames[id].document.oncontextmenu = function(){ return false; };
2110	} catch(e) {
2111	   // we ignore the error as it only works on the same domain.	 
2112	}	 
2113}
2114
2115function aiRemoveElementsFromHeight(id,height,removeElements) {
2116	var iframe = jQuery('#' + id);
2117	var elementArray  = removeElements.split(',');
2118    var totalHeight = 0;
2119	for (var i = 0; i < elementArray.length; i++) {
2120		try {
2121			var el = elementArray[i];
2122			if (el.includes("|")) {
2123			  var rangeArray = el.split('|');
2124			  var bottomElement = jQuery(rangeArray[0]);
2125			  var beforeBottom = Math.round(bottomElement.offset().top + bottomElement.outerHeight(true));
2126			  var nextTop = Math.round(jQuery(rangeArray[1]).offset().top);
2127			  totalHeight += nextTop - beforeBottom;
2128			} else if (el === 'top') { 
2129			  totalHeight +=  Math.round(jQuery('#' + id).offset().top);
2130			} else if (isNaN(el)) {
2131			  totalHeight += jQuery(el).outerHeight(true);
2132			} else {
2133			  totalHeight += parseInt(el);
2134			}
2135		}  catch(e) {
2136			if (console && console.error) {
2137			  console.error('Advanced iframe configuration error: The configuration of remove_elements_from_height "'+removeElements+'" is invalid. Please check if the elements you defined do exist and ids/classes are defined properly.');
2138			  console.log(e);
2139			}
2140		  }
2141    }
2142	var calc = 'calc(' + height + ' - ' + totalHeight + 'px)';
2143	iframe.css('height', calc);
2144}
2145
2146function aiTriggerAutoOpen(id, selector, autoclickDelay, hideTime) {
2147	aiDebugExtended("aiTriggerAutoOpen");
2148   
2149	if (autoclickDelay === 0) {
2150		aiOpenIframeOnClick(id, selector);
2151	} else {
2152		setTimeout(function() {
2153		    aiOpenIframeOnClick(id, selector);	
2154		}, autoclickDelay);
2155	}
2156	
2157	var now = new Date();
2158    var time = now.getTime();
2159    var expireTime = time + (hideTime * 86400000);
2160    now.setTime(expireTime);
2161    var	trimmedSelector = selector.replace(/[^A-Za-z0-9\-]/g, '');
2162	document.cookie = 'ai_disable_autoclick_iframe_' + trimmedSelector + '=Auto open is disabled until this cookie expires;expires='+now.toUTCString()+';path=/';
2163}
2164
2165function aiCheckAutoOpenHash(id, autoclickDelay, hideTime) {
2166	if (window.location.hash) {
2167       var hash = window.location.hash;
2168	   var trimmedHash = hash.replace(/[^A-Za-z0-9\-]/g, '');
2169	   trimmedHash = "#" + trimmedHash;
2170	   if (jQuery(trimmedHash).length !== 0) { // id does exist   
2171		   if (jQuery(trimmedHash).first().attr('target') == id) { // target is iframe
2172		       aiTriggerAutoOpen(id, trimmedHash, autoclickDelay, hideTime);   
2173		   }
2174       }
2175    }
2176}
2177
2178function aiOpenIframeOnClick(id, selector) {
2179	var myelement = jQuery(selector).first().attr("href"); 
2180    jQuery("#" + id).attr("src", myelement); 
2181	jQuery(selector).first().click();
2182}
2183
2184
2185// IE11 does not support includes
2186if (!String.prototype.includes) {
2187  String.prototype.includes = function(search, start) {
2188    if (typeof start !== 'number') {
2189      start = 0;
2190    }
2191    if (start + search.length > this.length) {
2192      return false;
2193    } else {
2194      return this.indexOf(search, start) !== -1;
2195    }
2196  };
2197}
2198
2199if (!String.prototype.startsWith) {
2200  String.prototype.startsWith = function(searchString, position) {
2201    position = position || 0;
2202    return this.indexOf(searchString, position) === position;
2203  };
2204}

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.