module.exports = function elementIsVisible(el) { if (el.dom) el = el.dom; //ExtJS Element (hopefully) if (el instanceof jQuery) el = el[0]; var t = benchmarkBox.now(); /* variant 1: Ext2: has dependency on ext2 //var ret = Ext2.fly(el).isVisible(); */ /* variant 2: jquery: not always correct //var ret = $(el).is(':visible'); */ /* variant 3: manuallycheck visiblity+display, basically what ext2 does */ var ret = true; while (el && el.tagName && el.tagName.toLowerCase() != "body") { var vis = !($(el).css('visibility') == 'hidden' || $(el).css('display') == 'none'); if (!vis) { ret = false; break; } el = el.parentNode; } benchmarkBox.time('isVisible uncached', benchmarkBox.now()-t); return ret; };
module.exports = function getCachedWidth(e) { if (e.dom) e = e.dom; //ExtJS Element (hopefully) if (e.jquery) e = e.get(0); var ret = false; while (e) { if (e.getAttribute('data-width') == '100%') { } else if (typeof e.kwfWidthCache != 'undefined') { ret = e.kwfWidthCache; break; } else { var t = benchmarkBox.now(); if (e.tagName == 'MAIN') { //IE 12 returns clientWidth 0 for <main>??! ret = e.offsetWidth; } else { ret = e.clientWidth; } benchmarkBox.time('getWidth uncached', benchmarkBox.now()-t); e.kwfWidthCache = ret; cachedWidthEls.push(e); break; } e = e.parentNode; } return ret; };
setTimeout(function() { deferredStart = benchmarkBox.now(); if (enableOnReadyConsoleProfile) console.profile("callOnContentReady body deferred"); onReadyState = 'callDefer'; callOnContentReady(document.body, { action: 'render' }); onReadyState = 'calledDefer'; }, 10);
var processNext = function processNext() { benchmarkBox.count('chunks'); var t = benchmarkBox.now(); while (onReadyElQueue.length && benchmarkBox.now()-t < 50) { processOnReadyElQueueEntry(); } if (onReadyElQueue.length) { setTimeout(processNext, 1); } else { onReadyIsCalling = false; benchmarkBox.time('time', benchmarkBox.now()-deferredStart); if (enableOnReadyConsoleProfile) console.profileEnd(); benchmarkBox.create({ type: 'onReady defer' }); } };
//call the callback of an element ready handler function callQueueFn(queueEntry, config) { var t = benchmarkBox.now(); var el = queueEntry.el; if (queueEntry.onAction != 'contentReady') { el = $(el); } queueEntry.fn.call(queueEntry.options.scope || window, el, config); var fnName = queueEntry.fn.name; if (!fnName) { fnName = 'unknown'; } benchmarkBox.subTime( 'on'+queueEntry.onAction.charAt(0).toUpperCase() + queueEntry.onAction.slice(1), 'fn: '+fnName, benchmarkBox.now()-t ); };
module.exports = function getCachedWidth(e) { if (e.dom) renderedEl = e.dom; //ExtJS Element (hopefully) if (e instanceof $) e = e.get(0); var ret = false; while (e) { if (e.getAttribute('data-width') == '100%') { } else if (typeof e.kwfWidthCache != 'undefined') { ret = e.kwfWidthCache; break; } else { var t = benchmarkBox.now(); ret = e.clientWidth; benchmarkBox.time('getWidth uncached', benchmarkBox.now()-t); e.kwfWidthCache = ret; cachedWidthEls.push(e); break; } e = e.parentNode; } return ret; };
$(document).ready(function() { if ($(document.body).is('.kwfUp-frontend')) { if (!document.body) { //this happens if a redirect by changing location in JS is done //in that case no contentReady needs to be called return; } var t = benchmarkBox.now(); if (enableOnReadyConsoleProfile) console.profile("callOnContentReady body"); onReadyState = 'callNonDefer'; callOnContentReady(document.body, { action: 'render' }); onReadyState = 'calledNonDefer'; if (enableOnReadyConsoleProfile) console.profileEnd(); benchmarkBox.time('time', benchmarkBox.now()-t); benchmarkBox.create({ type: 'onReady' }); setTimeout(function() { deferredStart = benchmarkBox.now(); if (enableOnReadyConsoleProfile) console.profile("callOnContentReady body deferred"); onReadyState = 'callDefer'; callOnContentReady(document.body, { action: 'render' }); onReadyState = 'calledDefer'; }, 10); var timeoutId; $(window).resize(function() { if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(function() { callOnContentReady(document.body, { action: 'widthChange' } ); }, 100); }); } });
var callOnContentReady = function(renderedEl, options) { benchmarkBox.count('callOnContentReady'); if (!options) options = {}; if (typeof options.newRender != 'undefined') { //backwards compatibility, for callOnContentReady call options.action = options.newRender ? 'render' : 'show'; delete options.newRender; } if (!options.action) { if (typeof console != 'undefined' && console.warn) console.warn('Please set option action on callOnContentReady'); options.action = 'render'; } if (!renderedEl) { if (typeof console != 'undefined' && console.warn) console.warn('Please pass element argument on callOnContentReady'); renderedEl = document.body; } if (renderedEl.dom) renderedEl = renderedEl.dom; //ExtJS Element (hopefully) if (renderedEl.jquery) { renderedEl.each(function(){ callOnContentReady(this, options); }); return; } //add entries to onReadyElQueue, depending on renderedEl var onActions; if (options.action == 'render') { onActions = ['render', 'show', 'widthChange', 'contentReady']; } else if (options.action == 'show') { onActions = ['show', 'widthChange', 'contentReady']; } else if (options.action == 'hide') { onActions = ['hide']; } else if (options.action == 'widthChange') { onActions = ['widthChange', 'contentReady']; } var html = false; for (var i = 0; i < readyElHandlers.length; i++) { var hndl = readyElHandlers[i]; if (options.handlerNum && $.inArray(hndl.num, options.handlerNum) == -1) { continue; } //onReadyState gets set before callOnContentReady(body) //can not be part of options as it would be missing in recursive calls if (onReadyState == 'callNonDefer') { if (hndl.options.defer) { continue; } } else if (onReadyState == 'callDefer') { if (!hndl.options.defer) { continue; } } if (hndl.options.checkVisibility) { if (renderedEl != document.body && !elementIsVisible(renderedEl)) { if (options.action == 'render' && hndl.selector && elCacheBySelector[hndl.selector]) { //mark cache as dirty as we don't query (and update the selector) as the renderedEl is invisible //TODO don't always mark as dirty especially when we have multiple handlers with same selector elCacheBySelector[hndl.selector].dirty = true; } continue; } //if checkVisibility is activated, don't skip based on onActions as //even a widthChange action could make an element visible (media queries) } else { if ($.inArray(hndl.onAction, onActions) == -1) { continue; } } if (options.action == 'render' && !html) { var t = benchmarkBox.now(); html = renderedEl.innerHTML; benchmarkBox.time('innerHTML', benchmarkBox.now()-t); } var useSelectorCache; if (options.action != 'render' || !hndl.selector) { useSelectorCache = true; } else { if (onReadyState == 'callDefer' && renderedEl == document.body && elCacheBySelector[hndl.selector]) { useSelectorCache = true; } else { var t = benchmarkBox.now(); var m = hndl.selector.match(/^[a-z]*\.([a-z]+)/i); //do a stupid text search on the selector, using that we can skip query for many selectors that don't exist in the current el if (m && html.indexOf(m[1]) == -1) { useSelectorCache = true; if (!elCacheBySelector[hndl.selector]) { elCacheBySelector[hndl.selector] = []; } } else { useSelectorCache = false; } benchmarkBox.time('checkInnerHtml', benchmarkBox.now()-t); } } if (useSelectorCache && elCacheBySelector[hndl.selector] && !elCacheBySelector[hndl.selector].dirty) { benchmarkBox.count('queryCache'); var els = []; for (var j=0; j<elCacheBySelector[hndl.selector].length; j++) { if (renderedEl == document.body || renderedEl == elCacheBySelector[hndl.selector][j] || $.contains(renderedEl, elCacheBySelector[hndl.selector][j]) ) { els.push(elCacheBySelector[hndl.selector][j]); } } } else if (!hndl.selector) { var els = $.makeArray($(renderedEl)); } else { var t = benchmarkBox.now(); var els = $.makeArray($(renderedEl).find(hndl.selector)); if (matchesSelector(renderedEl, hndl.selector)) { els.push(renderedEl); } benchmarkBox.time('query', benchmarkBox.now() - t); if (!elCacheBySelector[hndl.selector]) { elCacheBySelector[hndl.selector] = els; } else { for(var j=0; j<els.length; ++j) { if ($.inArray(els[j], elCacheBySelector[hndl.selector]) == -1) { elCacheBySelector[hndl.selector].push(els[j]); } } } } for (var j = 0; j< els.length; ++j) { var alreadyInQueue = false; $.each(onReadyElQueue, function(indx, queueEntry) { if (queueEntry.num == hndl.num && els[j] == queueEntry.el) { alreadyInQueue = true; } }); if (!alreadyInQueue) { var parentsCount = 0; var n = els[j]; while (n = n.parentNode) { parentsCount++; } benchmarkBox.count('readyEl'); onReadyElQueue.push({ el: els[j], fn: hndl.fn, options: hndl.options, num: hndl.num, callerOptions: options, onAction: hndl.onAction, selector: hndl.selector, priority: hndl.options.priority || 0, parentsCount: parentsCount }); } } } //sort onReadyElQueue var t = benchmarkBox.now(); onReadyElQueue.sort(function sortOnReadyElQueue(a, b) { if (a.priority != b.priority) { return a.priority - b.priority; } else { if (a.parentsCount != b.parentsCount) { return a.parentsCount - b.parentsCount; } else { return a.num - b.num; } } }); benchmarkBox.time('sort', benchmarkBox.now() - t); if (onReadyIsCalling) { return; } onReadyIsCalling = true; //call the callback of an element ready handler function callQueueFn(queueEntry, config) { var t = benchmarkBox.now(); var el = queueEntry.el; if (queueEntry.onAction != 'contentReady') { el = $(el); } queueEntry.fn.call(queueEntry.options.scope || window, el, config); var fnName = queueEntry.fn.name; if (!fnName) { fnName = 'unknown'; } benchmarkBox.subTime( 'on'+queueEntry.onAction.charAt(0).toUpperCase() + queueEntry.onAction.slice(1), 'fn: '+fnName, benchmarkBox.now()-t ); }; //process one entry of the readyElQueue //own function so it can be called in sync or in deferred chunks function processOnReadyElQueueEntry() { var queueEntry = onReadyElQueue.shift(); var el = queueEntry.el; if (queueEntry.onAction == 'render') { if (queueEntry.options.checkVisibility && !elementIsVisible(el)) { return; } if (!el.initDone) el.initDone = {}; if (el.initDone[queueEntry.num]) { return; } el.initDone[queueEntry.num] = true; var config = {}; var configEl = $(el).find('> input[type="hidden"]'); if (configEl.length) { try { var v = configEl.get(0).value; if (v.substr(0, 1) == '{' || v.substr(0, 1) == '[') { config = $.parseJSON(v); } } catch (err) {} } callQueueFn(queueEntry, config); } else if (queueEntry.onAction == 'show') { if (elementIsVisible(el)) { callQueueFn(queueEntry); } } else if (queueEntry.onAction == 'hide') { if (!elementIsVisible(el)) { callQueueFn(queueEntry); } } else if (queueEntry.onAction == 'widthChange') { if (!queueEntry.options.checkVisibility || elementIsVisible(el)) { callQueueFn(queueEntry); } } else if (queueEntry.onAction == 'contentReady') { var options = { newRender: (queueEntry.callerOptions.action == 'render'), action: queueEntry.callerOptions.action }; callQueueFn(queueEntry, options); } } if (onReadyState == 'callDefer') { var processNext = function processNext() { benchmarkBox.count('chunks'); var t = benchmarkBox.now(); while (onReadyElQueue.length && benchmarkBox.now()-t < 50) { processOnReadyElQueueEntry(); } if (onReadyElQueue.length) { setTimeout(processNext, 1); } else { onReadyIsCalling = false; benchmarkBox.time('time', benchmarkBox.now()-deferredStart); if (enableOnReadyConsoleProfile) console.profileEnd(); benchmarkBox.create({ type: 'onReady defer' }); } }; processNext(); } else { while (onReadyElQueue.length) { processOnReadyElQueueEntry(); } onReadyIsCalling = false; } };