-
-
Save munro/7f81bd1657499866f7c2 to your computer and use it in GitHub Desktop.
from textwrap import dedent | |
def wait_until_images_loaded(driver, timeout=30): | |
"""Waits for all images & background images to load.""" | |
driver.set_script_timeout(timeout) | |
driver.execute_async_script(dedent(''' | |
// Function to extract URL from CSS 'url()' function | |
function extractCSSURL(text) { | |
var url_str = text.replace(/.*url\((.*)\).*/, '$1'); | |
// If the URL is enclosed with double quotes | |
if (url_str[0] === '"') { | |
return JSON.parse(url_str); | |
} | |
// If the URL is enclosed with single quotes | |
if (url_str[0] === "'") { | |
return JSON.parse( | |
url_str | |
.replace(/'/g, '__DOUBLE__QUOTE__HERE__') | |
.replace(/"/g, "'") | |
.replace(/__DOUBLE__QUOTE__HERE__/g, '"') | |
); | |
} | |
// Return the URL as is | |
return url_str; | |
} | |
// Function to create a promise that resolves when the image is loaded | |
function imageResolved(url) { | |
return new Promise(function (resolve) { | |
var img = new Image(); | |
img.onload = function () { | |
resolve(url); | |
}; | |
img.src = url; | |
// If the image is already loaded, resolve the promise immediately | |
if (img.complete) { | |
resolve(url); | |
} | |
}); | |
} | |
// The last argument is expected to be a callback function | |
var callback = arguments[arguments.length - 1]; | |
Promise.all([ | |
// Get all img tags, create a promise for each one | |
...Array.from(document.querySelectorAll('img[src]'), img => imageResolved(img.src)), | |
// Get all inline styles with 'url()' and create a promise for each one | |
...Array.from(document.querySelectorAll('[style*="url("]'), elem => imageResolved(extractCSSURL(elem.style.cssText))) | |
]) | |
.then(function () { | |
// After all images are loaded, wait for all fonts to load | |
return document.fonts.ready; | |
}) | |
.then(function() { | |
// After all fonts are loaded, check for images in CSS stylesheets | |
let cssImagesPromises = []; | |
for(let i = 0; i < document.styleSheets.length; i++) { | |
let rules = document.styleSheets[i].cssRules; | |
for (let j = 0; j < rules.length; j++) { | |
let style = rules[j].style; | |
// Check if a background image is found and if it's a URL | |
if (style && String(style.backgroundImage).startsWith('url(')) { | |
let url = extractCSSURL(style.backgroundImage); | |
cssImagesPromises.push(imageResolved(url)); | |
} | |
} | |
} | |
return Promise.all(cssImagesPromises); | |
}) | |
.then(function () { | |
// Call the callback function when all promises are resolved | |
callback(arguments); | |
}); | |
return undefined; | |
''')) |
@madsheep aw thanks man, I’m glad it helped!
Bro sorry for the inconvenience but I don't know how the script works can you help me, I'm trying to wait for the visibility of an image on a
It's an incredible job. Thank you for accomplishing this great work 8 years ago.
Awesome yet functional for the poor souls, not for making bad decisions, thank you very much!!!
I haven't fully tested this (which is why I haven't updated the gist) but here's code that works without jQuery dependency:
Let me know if this works and I'll update the gist!!
// Function to extract URL from CSS 'url()' function
function extractCSSURL(text) {
var url_str = text.replace(/.*url\((.*)\).*/, '$1');
// If the URL is enclosed with double quotes
if (url_str[0] === '"') {
return JSON.parse(url_str);
}
// If the URL is enclosed with single quotes
if (url_str[0] === "'") {
return JSON.parse(
url_str
.replace(/'/g, '__DOUBLE__QUOTE__HERE__')
.replace(/"/g, "'")
.replace(/__DOUBLE__QUOTE__HERE__/g, '"')
);
}
// Return the URL as is
return url_str;
}
// Function to create a promise that resolves when the image is loaded
function imageResolved(url) {
return new Promise(function (resolve) {
var img = new Image();
img.onload = function () {
resolve(url);
};
img.src = url;
// If the image is already loaded, resolve the promise immediately
if (img.complete) {
resolve(url);
}
});
}
// The last argument is expected to be a callback function
var callback = arguments[arguments.length - 1];
Promise.all([
// Get all img tags, create a promise for each one
...Array.from(document.querySelectorAll('img[src]'), img => imageResolved(img.src)),
// Get all inline styles with 'url()' and create a promise for each one
...Array.from(document.querySelectorAll('[style*="url("]'), elem => imageResolved(extractCSSURL(elem.style.cssText)))
])
.then(function () {
// After all images are loaded, wait for all fonts to load
return document.fonts.ready;
})
.then(function() {
// After all fonts are loaded, check for images in CSS stylesheets
let cssImagesPromises = [];
for(let i = 0; i < document.styleSheets.length; i++) {
let rules = document.styleSheets[i].cssRules;
for (let j = 0; j < rules.length; j++) {
let style = rules[j].style;
// Check if a background image is found and if it's a URL
if (style && String(style.backgroundImage).startsWith('url(')) {
let url = extractCSSURL(style.backgroundImage);
cssImagesPromises.push(imageResolved(url));
}
}
}
return Promise.all(cssImagesPromises);
})
.then(function () {
// Call the callback function when all promises are resolved
callback(arguments);
});
return undefined;
I haven't fully tested this (which is why I haven't updated the gist) but here's code that works without jQuery dependency:
Let me know if this works and I'll update the gist!!
// Function to extract URL from CSS 'url()' function function extractCSSURL(text) { var url_str = text.replace(/.*url\((.*)\).*/, '$1'); // If the URL is enclosed with double quotes if (url_str[0] === '"') { return JSON.parse(url_str); } // If the URL is enclosed with single quotes if (url_str[0] === "'") { return JSON.parse( url_str .replace(/'/g, '__DOUBLE__QUOTE__HERE__') .replace(/"/g, "'") .replace(/__DOUBLE__QUOTE__HERE__/g, '"') ); } // Return the URL as is return url_str; } // Function to create a promise that resolves when the image is loaded function imageResolved(url) { return new Promise(function (resolve) { var img = new Image(); img.onload = function () { resolve(url); }; img.src = url; // If the image is already loaded, resolve the promise immediately if (img.complete) { resolve(url); } }); } // The last argument is expected to be a callback function var callback = arguments[arguments.length - 1]; Promise.all([ // Get all img tags, create a promise for each one ...Array.from(document.querySelectorAll('img[src]'), img => imageResolved(img.src)), // Get all inline styles with 'url()' and create a promise for each one ...Array.from(document.querySelectorAll('[style*="url("]'), elem => imageResolved(extractCSSURL(elem.style.cssText))) ]) .then(function () { // After all images are loaded, wait for all fonts to load return document.fonts.ready; }) .then(function() { // After all fonts are loaded, check for images in CSS stylesheets let cssImagesPromises = []; for(let i = 0; i < document.styleSheets.length; i++) { let rules = document.styleSheets[i].cssRules; for (let j = 0; j < rules.length; j++) { let style = rules[j].style; // Check if a background image is found and if it's a URL if (style && String(style.backgroundImage).startsWith('url(')) { let url = extractCSSURL(style.backgroundImage); cssImagesPromises.push(imageResolved(url)); } } } return Promise.all(cssImagesPromises); }) .then(function () { // Call the callback function when all promises are resolved callback(arguments); }); return undefined;
I can confirm this script works great thanks!
awesome updated 😄
Hi man - just letting you know, this is pretty cool. I know you did it 5 years ago, but you should know, you saved a poor soul from doing dumb stuff today. Kudos over the internet.