Skip to content

Instantly share code, notes, and snippets.

@rkatic
Last active October 24, 2017 17:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rkatic/22d3a69d50b0ae71132442642e103b19 to your computer and use it in GitHub Desktop.
Save rkatic/22d3a69d50b0ae71132442642e103b19 to your computer and use it in GitHub Desktop.
// This is a quick example on how we could wait for real loaded state
// by monitoring traffic. If needed, traffic filtering could be added.
var dataByTabId = {}
function getDataByTabId (tabId) {
if (!dataByTabId[tabId]) {
dataByTabId[tabId] = {
reqCounter: 0,
callbacks: [],
flushTimeout: null
}
}
return dataByTabId[tabId]
}
chrome.tabs.onRemoved.addListener(function (tabId) {
delete dataByTabId[tabId]
})
// Flush is debounced to ensure callbacks are called after multiple sequential requests.
function abortFlush (tabData) {
if (tabData.flushTimeout) {
clearTimeout(tabData.flushTimeout)
tabData.flushTimeout = null
}
}
function onReqEnd (details) {
var tabData = getDataByTabId(details.tabId)
abortFlush(tabData)
// In case of tabs before extension start, this could be negative,
// but the extension will not be operating on those tabs anyway.
if (--tabData.reqCounter === 0) {
tabData.flushTimeout = setTimeout(flush, 200, tabId)
}
}
function flush (tabId) {
var tabData = getDataByTabId(tabId)
var cbs = tabData.callbacks
tabData.callbacks = []
cbs.forEach(function(cb) {
cb()
})
}
chrome.webRequest.onBeforeRequest.addListener(function (details) {
var tabData = getDataByTabId(details.tabId)
abortFlush(tabData)
tabData.reqCounter += 1
})
chrome.webRequest.onErrorOccurred.addListener(onReqEnd)
chrome.webRequest.onCompleted.addListener(onReqEnd)
function afterAllLoaded (tabId, cb) {
var tabData = getDataByTabId(tabId)
if (tabData.reqCounter === 0) {
cb()
} else {
tabData.callbacks.push(cb)
}
}
function isVisible(el) {
// should be enough
return el.offsetHeight > 0 || el.offsetParent !== null
}
function selectVisible(selector) {
var elements = document.querySelectorAll(selector)
return [].filter.call(elements, isVisible)
}
function getVisibleLoaders() {
return selectVisible('#loading, .loading, #loader, .loader, img[alt*="loading"], img[alt*="loader"]')
}
// With ES6 we would use Set
var loadersToIgnore = []
function isLoading() {
return getVisibleLoaders().some(function (el) {
return loadersToIgnore.indexOf(el) === -1
})
}
// This is best to call a moment before the action
// that could trigger loading we want to wait.
function ignoreCurrentLoaders() {
loadersToIgnore = getVisibleLoaders()
}
function afterLoading(cb) {
if (!isLoading()) {
return cb()
}
var intervalId = setInterval(function () {
if (!isLoading()) {
clearInterval(intervalId)
cb()
}
}, 200)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment