JezK
Edit File: ai-insert.js
if (typeof ai_insertion_js != 'undefined') { ai_insert = function (insertion, selector, insertion_code) { var ai_debug = typeof ai_debugging !== 'undefined'; // 1 // var ai_debug = false; // if (selector.indexOf (':eq') != - 1) { // *** if (selector.indexOf (':eq(') != - 1) { var jq = window.jQuery && window.jQuery.fn; if (ai_debug) console.log ('AI INSERT USING jQuery QUERIES:', selector); if (!jq) { console.error ('AI INSERT USING jQuery QUERIES:', selector, '- jQuery not found'); return; } else var elements = jQuery (selector); } else var elements = document.querySelectorAll (selector); // Array.prototype.forEach.call (elements, function (element, index) { for (var index = 0, len = elements.length; index < len; index++) { var element = elements [index]; if (element.hasAttribute ('id')) { selector_string = '#' + element.getAttribute ('id'); } else if (element.hasAttribute ('class')) { selector_string = '.' + element.getAttribute ('class').replace (new RegExp (' ', 'g'), '.'); } else selector_string = ''; if (ai_debug) console.log (''); if (ai_debug) console.log ('AI INSERT', insertion, selector, '(' + element.tagName.toLowerCase() + selector_string + ')'); var template = document.createElement ('div'); template.innerHTML = insertion_code; var ai_selector_counter = template.getElementsByClassName ("ai-selector-counter")[0]; if (ai_selector_counter != null) { ai_selector_counter.innerText = index + 1; } var ai_debug_name_ai_main = template.getElementsByClassName ("ai-debug-name ai-main")[0]; if (ai_debug_name_ai_main != null) { var insertion_name = insertion.toUpperCase (); if (typeof ai_front != 'undefined') { if (insertion == 'before') { insertion_name = ai_front.insertion_before; } else if (insertion == 'after') { insertion_name = ai_front.insertion_after; } else if (insertion == 'prepend') { insertion_name = ai_front.insertion_prepend; } else if (insertion == 'append') { insertion_name = ai_front.insertion_append; } else if (insertion == 'replace-content') { insertion_name = ai_front.insertion_replace_content; } else if (insertion == 'replace-element') { insertion_name = ai_front.insertion_replace_element; } } if (selector_string.indexOf ('.ai-viewports') == - 1) { ai_debug_name_ai_main.innerText = insertion_name + ' ' + selector + ' (' + element.tagName.toLowerCase() + selector_string + ')'; } } var range = document.createRange (); var fragment_ok = true; try { var fragment = range.createContextualFragment (template.innerHTML); } catch (err) { var fragment_ok = false; if (ai_debug) console.log ('AI INSERT', 'range.createContextualFragment ERROR:', err.message); } if (insertion == 'before') { // *** // if (!fragment_ok) { // jQuery (template.innerHTML).insertBefore (jQuery (element)); // } else element.parentNode.insertBefore (fragment, element); } else if (insertion == 'after') { // *** // if (!fragment_ok) { // jQuery (template.innerHTML).insertBefore (jQuery (element.nextSibling)); // } else element.parentNode.insertBefore (fragment, element.nextSibling); } else if (insertion == 'prepend') { // *** // if (!fragment_ok) { // jQuery (template.innerHTML).insertBefore (jQuery (element.firstChild)); // } else element.insertBefore (fragment, element.firstChild); } else if (insertion == 'append') { // *** // if (!fragment_ok) { // jQuery (template.innerHTML).appendTo (jQuery (element)); // } else element.insertBefore (fragment, null); } else if (insertion == 'replace-content') { element.innerHTML = ''; // *** // if (!fragment_ok) { // jQuery (template.innerHTML).appendTo (jQuery (element)); // } else element.insertBefore (fragment, null); } else if (insertion == 'replace-element') { // *** // if (!fragment_ok) { // jQuery (template.innerHTML).insertBefore (jQuery (element)); // } else element.parentNode.insertBefore (fragment, element); element.parentNode.removeChild (element); } // }); ai_process_elements (); }; } ai_insert_code = function (element) { function hasClass (element, cls) { if (element == null) return false; if (element.classList) return element.classList.contains (cls); else return (' ' + element.className + ' ').indexOf (' ' + cls + ' ') > - 1; } function addClass (element, cls) { if (element == null) return; if (element.classList) element.classList.add (cls); else element.className += ' ' + cls; } function removeClass (element, cls) { if (element == null) return; if (element.classList) element.classList.remove (cls); else element.className = element.className.replace (new RegExp ('(^|\\b)' + cls.split (' ').join ('|') + '(\\b|$)', 'gi'), ' '); } if (typeof element == 'undefined') return; var insertion = false; var ai_debug = typeof ai_debugging !== 'undefined'; // 2 // var ai_debug = false; if (ai_debug) console.log ('AI INSERT ELEMENT class:', element.getAttribute ('class')); if (hasClass (element, 'no-visibility-check')) { var visible = true; } else var visible = !!(element.offsetWidth || element.offsetHeight || element.getClientRects().length); if (ai_debug) { var block = element.getAttribute ('data-block'); } if (visible) { if (ai_debug) console.log ('AI ELEMENT VISIBLE: block', block, 'offsetWidth:', element.offsetWidth, 'offsetHeight:', element.offsetHeight, 'getClientRects().length:', element.getClientRects().length); var insertion_code = element.getAttribute ('data-code'); var insertion_type = element.getAttribute ('data-insertion-position'); var selector = element.getAttribute ('data-selector'); if (insertion_code != null) { if (insertion_type != null && selector != null) { // *** if (selector.indexOf (':eq(') != - 1) { var jq = window.jQuery && window.jQuery.fn; if (jq) { var selector_exists = jQuery (selector).length; } else var selector_exists = false; } else var selector_exists = document.querySelectorAll (selector).length; if (ai_debug) console.log ('AI ELEMENT VISIBLE: block', block, insertion_type, selector, selector_exists ? '' : 'NOT FOUND'); if (selector_exists) { ai_insert (insertion_type, selector, b64d (insertion_code)); removeClass (element, 'ai-viewports'); } } else { if (ai_debug) console.log ('AI ELEMENT VISIBLE: block', block); var range = document.createRange (); var fragment_ok = true; try { var fragment = range.createContextualFragment (b64d (insertion_code)); } catch (err) { var fragment_ok = false; if (ai_debug) console.log ('AI INSERT NEXT', 'range.createContextualFragment ERROR:', err.message); } // *** // if (!fragment_ok) { // jQuery (b64d (insertion_code)).insertBefore (jQuery (element.nextSibling)); // } else element.parentNode.insertBefore (fragment, element.nextSibling); removeClass (element, 'ai-viewports'); } } insertion = true; // Should not be removed here as it is needed for tracking - removed there // var ai_check_block_data = element.getElementsByClassName ('ai-check-block'); // if (typeof ai_check_block_data [0] != 'undefined') { // // Remove span // ai_check_block_data [0].parentNode.removeChild (ai_check_block_data [0]); // } } else { if (ai_debug) console.log ('AI ELEMENT NOT VISIBLE: block', block, 'offsetWidth:', element.offsetWidth, 'offsetHeight:', element.offsetHeight, 'getClientRects().length:', element.getClientRects().length); var debug_bar = element.previousElementSibling; if (hasClass (debug_bar, 'ai-debug-bar') && hasClass (debug_bar, 'ai-debug-script')) { removeClass (debug_bar, 'ai-debug-script'); addClass (debug_bar, 'ai-debug-viewport-invisible'); } removeClass (element, 'ai-viewports'); } return insertion; } ai_insert_list_code = function (id) { var ai_block_div = document.getElementsByClassName (id) [0]; if (typeof ai_block_div != 'undefined') { var inserted = ai_insert_code (ai_block_div); var wrapping_div = ai_block_div.closest ('div.' + ai_block_class_def); if (wrapping_div) { if (!inserted) { wrapping_div.removeAttribute ('data-ai'); } var debug_block = wrapping_div.querySelectorAll ('.ai-debug-block'); if (wrapping_div && debug_block.length) { wrapping_div.classList.remove ('ai-list-block'); wrapping_div.classList.remove ('ai-list-block-ip'); wrapping_div.classList.remove ('ai-list-block-filter'); wrapping_div.style.visibility = ''; if (wrapping_div.classList.contains ('ai-remove-position')) { wrapping_div.style.position = ''; } } } ai_block_div.classList.remove (id); if (inserted) ai_process_elements (); } } ai_insert_viewport_code = function (id) { var ai_block_div = document.getElementsByClassName (id) [0]; if (typeof ai_block_div != 'undefined') { var inserted = ai_insert_code (ai_block_div); ai_block_div.classList.remove (id); if (inserted) { var wrapping_div = ai_block_div.closest ('div.' + ai_block_class_def); if (wrapping_div != null) { var viewport_style = ai_block_div.getAttribute ('style'); if (viewport_style != null) { wrapping_div.setAttribute ('style', wrapping_div.getAttribute ('style') + ' ' + viewport_style); } } } setTimeout (function () { ai_block_div.removeAttribute ('style'); }, 2); ai_process_elements (); } } ai_insert_adsense_fallback_codes = function (adsense_unfilled_ins) { var ai_debug = typeof ai_debugging !== 'undefined'; // 3 // var ai_debug = false; adsense_unfilled_ins.style.display = "none"; var fallback_wrapper = adsense_unfilled_ins.closest ('.ai-fallback-adsense'); var fallback_div = fallback_wrapper.nextElementSibling; if (!!fallback_div.getAttribute ('data-code')) { var inserted = ai_insert_code (fallback_div); if (inserted) { ai_process_elements (); } } else { fallback_div.style.display = "block"; } if (fallback_wrapper.classList.contains ('ai-empty-code') && adsense_unfilled_ins.closest ('.' + ai_block_class_def) != null) { var label_div = adsense_unfilled_ins.closest ('.' + ai_block_class_def).getElementsByClassName ('code-block-label'); if (label_div.length != 0) { label_div [0].style.display = "none"; } } if (ai_debug) { console.log ('AI FALLBACK ADSENSE UNFILLED:', adsense_unfilled_ins.closest ('.' + ai_block_class_def) != null ? adsense_unfilled_ins.closest ('.' + ai_block_class_def).classList.value : '', !!fallback_div.getAttribute ('data-code') ? 'INSERT' : 'SHOW'); } } //ai_insert_fallback_codes = function () { // var ai_debug = typeof ai_debugging !== 'undefined'; // 3 //// var ai_debug = false; // var ai_fallback_divs = document.getElementsByClassName ('ai-fallback-adsense'); // var fallback_check = ai_fallback_divs.length; // if (ai_debug && fallback_check) { // console.log (''); // console.log ('AI FALLBACK CHECK ADSENSE:', ai_fallback_divs.length, 'block' + (ai_fallback_divs.length == 1 ? '' : 's')) ; // } // for (var adsense = 0; adsense < ai_fallback_divs.length; adsense ++) { // var adsense_div = ai_fallback_divs [adsense]; // var adsense_unfilled_ins = adsense_div.querySelector ('ins.adsbygoogle[data-ad-status="filled"]'); // if (!!adsense_unfilled_ins) { // adsense_unfilled_ins.style.display = "none"; // var fallback_div = adsense_div.nextElementSibling; // var insert = !!fallback_div.getAttribute ('data-code'); // if (insert) { // if (ai_debug) { // var block = fallback_div.getAttribute ('data-block'); // console.log ('AI INSERT FALLBACK CODE FOR BLOCK', block); // } // var inserted = ai_insert_code (fallback_div); // if (inserted) { // ai_process_elements (); // } // } else { // if (ai_debug) { // var block = fallback_div.getAttribute ('data-block'); // console.log ('AI SHOW FALLBACK CODE FOR BLOCK', block); // } // fallback_div.style.display = "block"; // } // } // } // if (ai_debug && fallback_check) { // console.log (''); // } //} ai_insert_code_by_class = function (id) { var ai_block_div = document.getElementsByClassName (id) [0]; if (typeof ai_block_div != 'undefined') { ai_insert_code (ai_block_div); ai_block_div.classList.remove (id); } } ai_insert_client_code = function (id, len) { var ai_debug = typeof ai_debugging !== 'undefined'; // 4 // var ai_debug = false; var ai_block_div = document.getElementsByClassName (id) [0]; if (ai_debug) { var block = ai_block_div.getAttribute ('data-block'); console.log ('AI INSERT PROTECTED BLOCK', block, '.' + id); } if (typeof ai_block_div != 'undefined') { var insertion_code = ai_block_div.getAttribute ('data-code'); // if (insertion_code != null && ai_check_block () && ai_check_and_insert_block ()) { if (insertion_code != null && ai_check_block () /*&& ai_check_and_insert_block ()*/) { ai_block_div.setAttribute ('data-code', insertion_code.substring (Math.floor (len / 19))); ai_insert_code_by_class (id); ai_block_div.remove(); } } } ai_process_elements_active = false; function ai_process_elements () { if (!ai_process_elements_active) setTimeout (function() { ai_process_elements_active = false; if (typeof ai_process_rotations == 'function') { ai_process_rotations (); } if (typeof ai_process_lists == 'function') { // *** // ai_process_lists (jQuery (".ai-list-data")); ai_process_lists (); } if (typeof ai_process_ip_addresses == 'function') { // *** // ai_process_ip_addresses (jQuery (".ai-ip-data")); ai_process_ip_addresses (); } if (typeof ai_process_filter_hooks == 'function') { // *** // ai_process_filter_hooks (jQuery (".ai-filter-check")); ai_process_filter_hooks (); } if (typeof ai_adb_process_blocks == 'function') { ai_adb_process_blocks (); } if (typeof ai_process_impressions == 'function' && ai_tracking_finished == true) { ai_process_impressions (); } if (typeof ai_install_click_trackers == 'function' && ai_tracking_finished == true) { ai_install_click_trackers (); } if (typeof ai_install_close_buttons == 'function') { ai_install_close_buttons (document); } if (typeof ai_process_wait_for_interaction == 'function') { ai_process_wait_for_interaction (); } if (typeof ai_process_delayed_blocks == 'function') { ai_process_delayed_blocks (); } }, 5); ai_process_elements_active = true; } const targetNode = document.querySelector ('body'); const config = {attributes: true, childList: false, subtree: true}; const ai_adsense_callback = function (mutationsList, observer) { // Use traditional 'for loops' for IE 11 for (const mutation of mutationsList) { if (mutation.type === 'attributes' && mutation.attributeName == 'data-ad-status' && mutation.target.dataset.adStatus == 'unfilled' && !!mutation.target.closest ('.ai-fallback-adsense')) { ai_insert_adsense_fallback_codes (mutation.target); } } }; const observer = new MutationObserver (ai_adsense_callback); observer.observe (targetNode, config); // Later, we can stop observing //observer.disconnect(); /*globals jQuery,Window,HTMLElement,HTMLDocument,HTMLCollection,NodeList,MutationObserver */ /*exported Arrive*/ /*jshint latedef:false */ /* * arrive.js * v2.4.1 * https://github.com/uzairfarooq/arrive * MIT licensed * * Copyright (c) 2014-2017 Uzair Farooq */ var Arrive = (function(window, $, undefined) { "use strict"; if(!window.MutationObserver || typeof HTMLElement === 'undefined'){ return; //for unsupported browsers } var arriveUniqueId = 0; var utils = (function() { var matches = HTMLElement.prototype.matches || HTMLElement.prototype.webkitMatchesSelector || HTMLElement.prototype.mozMatchesSelector || HTMLElement.prototype.msMatchesSelector; return { matchesSelector: function(elem, selector) { return elem instanceof HTMLElement && matches.call(elem, selector); }, // to enable function overloading - By John Resig (MIT Licensed) addMethod: function (object, name, fn) { var old = object[ name ]; object[ name ] = function(){ if ( fn.length == arguments.length ) { return fn.apply( this, arguments ); } else if ( typeof old == 'function' ) { return old.apply( this, arguments ); } }; }, callCallbacks: function(callbacksToBeCalled, registrationData) { if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) { // as onlyOnce param is true, make sure we fire the event for only one item callbacksToBeCalled = [callbacksToBeCalled[0]]; } for (var i = 0, cb; (cb = callbacksToBeCalled[i]); i++) { if (cb && cb.callback) { cb.callback.call(cb.elem, cb.elem); } } if (registrationData && registrationData.options.onceOnly && registrationData.firedElems.length == 1) { // unbind event after first callback as onceOnly is true. registrationData.me.unbindEventWithSelectorAndCallback.call( registrationData.target, registrationData.selector, registrationData.callback); } }, // traverse through all descendants of a node to check if event should be fired for any descendant checkChildNodesRecursively: function(nodes, registrationData, matchFunc, callbacksToBeCalled) { // check each new node if it matches the selector for (var i=0, node; (node = nodes[i]); i++) { if (matchFunc(node, registrationData, callbacksToBeCalled)) { callbacksToBeCalled.push({ callback: registrationData.callback, elem: node }); } if (node.childNodes.length > 0) { utils.checkChildNodesRecursively(node.childNodes, registrationData, matchFunc, callbacksToBeCalled); } } }, mergeArrays: function(firstArr, secondArr){ // Overwrites default options with user-defined options. var options = {}, attrName; for (attrName in firstArr) { if (firstArr.hasOwnProperty(attrName)) { options[attrName] = firstArr[attrName]; } } for (attrName in secondArr) { if (secondArr.hasOwnProperty(attrName)) { options[attrName] = secondArr[attrName]; } } return options; }, toElementsArray: function (elements) { // check if object is an array (or array like object) // Note: window object has .length property but it's not array of elements so don't consider it an array if (typeof elements !== "undefined" && (typeof elements.length !== "number" || elements === window)) { elements = [elements]; } return elements; } }; })(); // Class to maintain state of all registered events of a single type var EventsBucket = (function() { var EventsBucket = function() { // holds all the events this._eventsBucket = []; // function to be called while adding an event, the function should do the event initialization/registration this._beforeAdding = null; // function to be called while removing an event, the function should do the event destruction this._beforeRemoving = null; }; EventsBucket.prototype.addEvent = function(target, selector, options, callback) { var newEvent = { target: target, selector: selector, options: options, callback: callback, firedElems: [] }; if (this._beforeAdding) { this._beforeAdding(newEvent); } this._eventsBucket.push(newEvent); return newEvent; }; EventsBucket.prototype.removeEvent = function(compareFunction) { for (var i=this._eventsBucket.length - 1, registeredEvent; (registeredEvent = this._eventsBucket[i]); i--) { if (compareFunction(registeredEvent)) { if (this._beforeRemoving) { this._beforeRemoving(registeredEvent); } // mark callback as null so that even if an event mutation was already triggered it does not call callback var removedEvents = this._eventsBucket.splice(i, 1); if (removedEvents && removedEvents.length) { removedEvents[0].callback = null; } } } }; EventsBucket.prototype.beforeAdding = function(beforeAdding) { this._beforeAdding = beforeAdding; }; EventsBucket.prototype.beforeRemoving = function(beforeRemoving) { this._beforeRemoving = beforeRemoving; }; return EventsBucket; })(); /** * @constructor * General class for binding/unbinding arrive and leave events */ var MutationEvents = function(getObserverConfig, onMutation) { var eventsBucket = new EventsBucket(), me = this; var defaultOptions = { fireOnAttributesModification: false }; // actual event registration before adding it to bucket eventsBucket.beforeAdding(function(registrationData) { var target = registrationData.target, observer; // mutation observer does not work on window or document if (target === window.document || target === window) { target = document.getElementsByTagName("html")[0]; } // Create an observer instance observer = new MutationObserver(function(e) { onMutation.call(this, e, registrationData); }); var config = getObserverConfig(registrationData.options); observer.observe(target, config); registrationData.observer = observer; registrationData.me = me; }); // cleanup/unregister before removing an event eventsBucket.beforeRemoving(function (eventData) { eventData.observer.disconnect(); }); this.bindEvent = function(selector, options, callback) { options = utils.mergeArrays(defaultOptions, options); var elements = utils.toElementsArray(this); for (var i = 0; i < elements.length; i++) { eventsBucket.addEvent(elements[i], selector, options, callback); } }; this.unbindEvent = function() { var elements = utils.toElementsArray(this); eventsBucket.removeEvent(function(eventObj) { for (var i = 0; i < elements.length; i++) { if (this === undefined || eventObj.target === elements[i]) { return true; } } return false; }); }; this.unbindEventWithSelectorOrCallback = function(selector) { var elements = utils.toElementsArray(this), callback = selector, compareFunction; if (typeof selector === "function") { compareFunction = function(eventObj) { for (var i = 0; i < elements.length; i++) { if ((this === undefined || eventObj.target === elements[i]) && eventObj.callback === callback) { return true; } } return false; }; } else { compareFunction = function(eventObj) { for (var i = 0; i < elements.length; i++) { if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector) { return true; } } return false; }; } eventsBucket.removeEvent(compareFunction); }; this.unbindEventWithSelectorAndCallback = function(selector, callback) { var elements = utils.toElementsArray(this); eventsBucket.removeEvent(function(eventObj) { for (var i = 0; i < elements.length; i++) { if ((this === undefined || eventObj.target === elements[i]) && eventObj.selector === selector && eventObj.callback === callback) { return true; } } return false; }); }; return this; }; /** * @constructor * Processes 'arrive' events */ var ArriveEvents = function() { // Default options for 'arrive' event var arriveDefaultOptions = { fireOnAttributesModification: false, onceOnly: false, existing: false }; function getArriveObserverConfig(options) { var config = { attributes: false, childList: true, subtree: true }; if (options.fireOnAttributesModification) { config.attributes = true; } return config; } function onArriveMutation(mutations, registrationData) { mutations.forEach(function( mutation ) { var newNodes = mutation.addedNodes, targetNode = mutation.target, callbacksToBeCalled = [], node; // If new nodes are added if( newNodes !== null && newNodes.length > 0 ) { utils.checkChildNodesRecursively(newNodes, registrationData, nodeMatchFunc, callbacksToBeCalled); } else if (mutation.type === "attributes") { if (nodeMatchFunc(targetNode, registrationData, callbacksToBeCalled)) { callbacksToBeCalled.push({ callback: registrationData.callback, elem: targetNode }); } } utils.callCallbacks(callbacksToBeCalled, registrationData); }); } function nodeMatchFunc(node, registrationData, callbacksToBeCalled) { // check a single node to see if it matches the selector if (utils.matchesSelector(node, registrationData.selector)) { if(node._id === undefined) { node._id = arriveUniqueId++; } // make sure the arrive event is not already fired for the element if (registrationData.firedElems.indexOf(node._id) == -1) { registrationData.firedElems.push(node._id); return true; } } return false; } arriveEvents = new MutationEvents(getArriveObserverConfig, onArriveMutation); var mutationBindEvent = arriveEvents.bindEvent; // override bindEvent function arriveEvents.bindEvent = function(selector, options, callback) { if (typeof callback === "undefined") { callback = options; options = arriveDefaultOptions; } else { options = utils.mergeArrays(arriveDefaultOptions, options); } var elements = utils.toElementsArray(this); if (options.existing) { var existing = []; for (var i = 0; i < elements.length; i++) { var nodes = elements[i].querySelectorAll(selector); for (var j = 0; j < nodes.length; j++) { existing.push({ callback: callback, elem: nodes[j] }); } } // no need to bind event if the callback has to be fired only once and we have already found the element if (options.onceOnly && existing.length) { return callback.call(existing[0].elem, existing[0].elem); } setTimeout(utils.callCallbacks, 1, existing); } mutationBindEvent.call(this, selector, options, callback); }; return arriveEvents; }; /** * @constructor * Processes 'leave' events */ var LeaveEvents = function() { // Default options for 'leave' event var leaveDefaultOptions = {}; function getLeaveObserverConfig() { var config = { childList: true, subtree: true }; return config; } function onLeaveMutation(mutations, registrationData) { mutations.forEach(function( mutation ) { var removedNodes = mutation.removedNodes, callbacksToBeCalled = []; if( removedNodes !== null && removedNodes.length > 0 ) { utils.checkChildNodesRecursively(removedNodes, registrationData, nodeMatchFunc, callbacksToBeCalled); } utils.callCallbacks(callbacksToBeCalled, registrationData); }); } function nodeMatchFunc(node, registrationData) { return utils.matchesSelector(node, registrationData.selector); } leaveEvents = new MutationEvents(getLeaveObserverConfig, onLeaveMutation); var mutationBindEvent = leaveEvents.bindEvent; // override bindEvent function leaveEvents.bindEvent = function(selector, options, callback) { if (typeof callback === "undefined") { callback = options; options = leaveDefaultOptions; } else { options = utils.mergeArrays(leaveDefaultOptions, options); } mutationBindEvent.call(this, selector, options, callback); }; return leaveEvents; }; var arriveEvents = new ArriveEvents(), leaveEvents = new LeaveEvents(); function exposeUnbindApi(eventObj, exposeTo, funcName) { // expose unbind function with function overriding utils.addMethod(exposeTo, funcName, eventObj.unbindEvent); utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorOrCallback); utils.addMethod(exposeTo, funcName, eventObj.unbindEventWithSelectorAndCallback); } /*** expose APIs ***/ function exposeApi(exposeTo) { exposeTo.arrive = arriveEvents.bindEvent; exposeUnbindApi(arriveEvents, exposeTo, "unbindArrive"); exposeTo.leave = leaveEvents.bindEvent; exposeUnbindApi(leaveEvents, exposeTo, "unbindLeave"); } if ($) { exposeApi($.fn); } exposeApi(HTMLElement.prototype); exposeApi(NodeList.prototype); exposeApi(HTMLCollection.prototype); exposeApi(HTMLDocument.prototype); exposeApi(Window.prototype); var Arrive = {}; // expose functions to unbind all arrive/leave events exposeUnbindApi(arriveEvents, Arrive, "unbindAllArrive"); exposeUnbindApi(leaveEvents, Arrive, "unbindAllLeave"); return Arrive; })(window, typeof jQuery === 'undefined' ? null : jQuery, undefined); }
Paket Wisata Karimunjawa Terlengkap & Harga Terbaik 2026
https://validator.w3.org/feed/docs/rss2.html
Promo Paket Wisata Karimunjawa
Info Harga dan Paket Liburan ke Karimunjawa
Pulau Karimun Jawa
Paket Mancing Karimunjawa
Paket Trip Karimunjawa
Pelabuhan Karimunjawa
Kuliner Khas Karimunjawa
Pantai Bobby Karimunjawa
Whales: Giants of the Ocean
Whales: Giants of the Ocean
Taka Sendok Karimunjawa
Contact US
Informasi Perjalanan Paket Travel Wisata Karimunjawa
Rental Mobil Karimunjawa
Paket Open Trip Karimunjawa
Paket Snorkeling Karimunjawa
Sama Sama Homestay Karimunjawa
Paket Tour Karimunjawa Jepara
Informasi Biaya Liburan ke Karimunjawa
Paket Wisata Karimunjawa 4 Hari 3 Malam
Oleh Oleh Khas Karimunjawa
Promo Open Trip Karimun Jawa
Tentang Kami
Sunset Karimunjawa
Tiket Kapal Karimunjawa
Informasi Reservasi Hotel Resort Java Paradise Karimunjawa
Taman Nasional Karimunjawa
Informasi Harga Paket Wisata Karimunjawa Murah
Informasi Jadwal Kapal Pelni Semarang ke Karimunjawa
Informasi Jadwal Kapal Karimunjawa Ferry Siginjai
Paket Wisata Karimunjawa Rombongan
Tiket Kapal
Rincian Biaya Wisata Karimunjawa
Paket Wisata Karimunjawa 2 Hari 1 Malam
Booking
Informasi Jadwal Kapal Express Karimunjawa
Paket Diving Karimunjawa
Informasi Harga Paket Wisata Karimunjawa 3 Hari 2 Malam
Harga Paket Travel Karimunjawa
Private Trip Karimunjawa
Paket Wisata Karimunjawa dari Solo
Paket Homestay RGJS Karimunjawa
Cara ke Karimunjawa
Pantai Sunset Beach Karimunjawa
Sitemap
Paket Regular Karimunjawa 3 Hari 2 Malam
Cuaca Karimun Jawa
Karimunjawa Dimana
Narayana Resort Karimunjawa
Pantai Laendra Karimunjawa