Created
January 5, 2016 21:06
-
-
Save munro/7f81bd1657499866f7c2 to your computer and use it in GitHub Desktop.
Selenium wait for all images to load, including background images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 extractCSSURL(text) { | |
var url_str = text.replace(/.*url\((.*)\).*/, '$1'); | |
if (url_str[0] === '"') { | |
return JSON.parse(url_str); | |
} | |
if (url_str[0] === "'") { | |
return JSON.parse( | |
url_str | |
.replace(/'/g, '__DOUBLE__QUOTE__HERE__') | |
.replace(/"/g, "'") | |
.replace(/__DOUBLE__QUOTE__HERE__/g, '"') | |
); | |
} | |
return url_str; | |
} | |
function imageResolved(url) { | |
return new $.Deferred(function (d) { | |
var img = new Image(); | |
img.onload = img.onload = function () { | |
d.resolve(url); | |
}; | |
img.src = url; | |
if (img.complete) { | |
d.resolve(url); | |
} | |
}).promise(); | |
} | |
var callback = arguments[arguments.length - 1]; | |
$.when.apply($, [].concat( | |
$('img[src]') | |
.map(function (elem) { return $(this).attr('src'); }) | |
.toArray(), | |
$('[style*="url("]') | |
.map(function () { return extractCSSURL($(this).attr('style')); }) | |
.toArray() | |
.map(function (url) { return imageResolved(url); }) | |
)).then(function () { 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;
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.