How to get all image urls from a web page using javascript? - javascript

There are couple of ways to load image src urls using javascript, like using document.images or by selecting all img tags and get srcs.
However I can't figure out a way to image urls used within css.
For example, if the webpage has following css code, it loads bg.png, but I can't get that url using methods I mentioned above.
.bg {
background-image: url('bg.png');
}
Anyone has an idea how to get all these urls used within css?

The Resource Timing API collects data on outbound requests, should leave capacity to collect images in both CSS and inline styles performantly.
Haven't tested this, but something akin to this should help you get started:
if ( !('performance' in window) ||
!('getEntriesByType' in window.performance) ||
!(window.performance.getEntriesByType('resource') instanceof Array)
) {
alert('unsupported');
} else {
window.addEventListener('load', function() {
var resources = window.performance.getEntriesByType('resource');
for(var index in resources) {
for(var properties in resources[index]) {
console.log(properties);
console.log(resources[index][properties]);
}
}
});

something like this:
Loop all stylesheet rules
grab the document element from the stylesheet
find the background Image
var sSheetList = document.styleSheets;
for (var sSheet = 0; sSheet < sSheetList.length; sSheet++)
{
var ruleList = document.styleSheets[sSheet].cssRules;
for (var rule = 0; rule < ruleList.length; rule ++)
{
if (rule.style.cssText.match(/background/)) {
var selectorText = ruleList[rule].selectorText );
var img = document.getElementsByClassName(selectorText);
var style = img.currentStyle || window.getComputedStyle(img, false);
if( style.backgroundImage ) {
var bg = style.backgroundImage.slice(4, -1).replace(/"/g, "");
//add to array here or whatever.
}
}
}
}

Related

Extract Content from a Pseudo Element [duplicate]

I need to get :after and assign it to variable. It is possible?
querySelectorAll doesn't work.
alert(some_div_with_pseudo.querySelectorAll('::after')[0]) // undefined
The short answer is that you can’t. It’s not there yet.
JavaScript has access to the DOM, which is built when the page is loaded from HTML, and modified further when JavaScript manipulates it.
A pseudo element is generated by CSS, rather than HTML or JavaScript. It is there purely to give CSS something to hang on to, but it all happens without JavaScript having any idea.
This is how it should be. In the overall scheme of things, the pages starts off as HTML. JavaScript can be used to modify its behaviour and to manipulate the content on one hand, and CSS can be used to control the presentation of the result:
HTML [→ JavaScript] → CSS → Result
You’ll see that CSS, complete with pseudo elements, comes at the end, so JavaScript doesn’t get a look in.
See also:
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector#Usage_notes
https://www.w3.org/TR/selectors-api/#grammar
Edit
It seems that in modern JavaScript there is a workaround using window.getComputedStyle(element,pseudoElement):
var element = document.querySelector(' … ');
var styles = window.getComputedStyle(element,':after')
var content = styles['content'];
You can do this:
window.getComputedStyle(
document.querySelector('somedivId'), ':after'
);
Sample here: https://jsfiddle.net/cfwmqbvn/
I use an arrow pointing in the direction that the content and sidebar will toggle to/from via a CSS pseudo-element. The code below is effectively a write mode however it is entirely possible to read CSS pseudo-element content as well.
Since there is a bit involved I'll also post the prerequisites (source: JAB Creations web platform JavaScript documentation, if anything missing look it up there) so those who wish to try it out can fairly quickly do so.
CSS
#menu a[href*='sidebar']::after {content: '\2192' !important;}
JavaScript Use
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');
JavaScript Prerequisites
var sidebar = 20;
function id_(id)
{
return (document.getElementById(id)) ? document.getElementById(id) : false;
}
function css_rule_set(selector,property,value,important)
{
try
{
for (var i = 0; i<document.styleSheets.length; i++)
{
var ss = document.styleSheets[i];
var r = ss.cssRules ? ss.cssRules : ss.rules;
for (var j = 0; j<r.length; j++)
{
if (r[j].selectorText && r[j].selectorText==selector)
{
if (typeof important=='undefined') {r[j].style.setProperty(property,value);}
else {r[j].style.setProperty(property,value,'important');}
break;
}
}
}
}
catch(e) {if (e.name !== 'SecurityError') {console.log('Developer: '+e);}}
}
function sidebar_toggle()
{
if (id_('menu_mobile')) {id_('menu_mobile').checked = false;}
if (getComputedStyle(id_('side')).getPropertyValue('display') == 'none')
{
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2192"','important');
if (is_mobile())
{
css_rule_set('main','display','none','important');
css_rule_set('#side','width','100%','important');
css_rule_set('#side','display','block','important');
}
else
{
css_rule_set('main','width',(100 - sidebar)+'%');
css_rule_set('#side','display','block');
}
}
else
{
css_rule_set('#menu a[href*="sidebar"]::after','content','"\u2190"','important');
if (is_mobile())
{
css_rule_set('main','display','block','important');
css_rule_set('main','width','100%','important');
css_rule_set('#side','display','none','important');
}
else
{
css_rule_set('main','width','100%','important');
css_rule_set('#side','display','none');
}
}
There is a way in JavaScript to access value of pseudo elements without any library. To get the value, you need to use the 'getComputedStyle' function. The second parameter is optional.
let elem = window.getComputedStyle(parent, ':before');
alert(elem.getPropertyValue('background'))
This will do alert the value of pseudo element.
let elem = window.getComputedStyle(document.querySelector('#item'), ':after');
console.log(elem.getPropertyValue('content'))

Check if an error was thrown when loading an image during page startup

I am trying to write a JS script that will look through the page when it loads to see if any images had an error loading, and to change the src of that image to a default image. What I was trying to do was to loop through all the list of images returned from document.images, and to check every image to see if it finished loading using image[i].complete, and if it didn't, then change the src of that image to the default link. It did not work for me, and I can't think of the solution.
window.onload = function() {
var images = document.images;
for (var i = 0; i < images.length; i++) {
if (!image[i].complete) {
images[i].src = 'assets/default-avatar.jpg';
}
}
}
The solution is to use the error event on IMG tags:
<img src="..." onerror="this.src = 'default_image_url';">
Because complete returns true even if the image couldn't be loaded (at least in some browsers), you could use naturalWidth. If no image is loaded naturalWidth is 0.
window.onload = function() {
var images = document.images;
for (var i = 0; i < images.length; i++) {
if (image[i].naturalWidth === 0) {
images[i].src = 'assets/default-avatar.jpg';
}
}
}

Assign array of image elements to DOM ids

I have an array of URIs that represent .png elements, e.g., "./img/diamond-red-solid-1.png".
I want to assign each element of the array "gameDeck[0], gameDeck[1], etc. to div ids in HTML. Do I need to identify the elements as = SRC.IMG?
var gameDeck[];
var gameBoardCards = function () {
for (let cardArr of cardsToLoad)
gameDeck.push("./img/" + cardArr + ".png");
}
gameBoardCards();
document.addEventListener('DOM Content Loaded', function () {
gameDeck[0] = document.getElementById("card1");
gameDeck[1] = document.getElementById("card2");
etc.
});
The way I'm understanding your question is that you would like to target the divs in your HTML with ids of card1, card2, card3... card12 etc.
You would like to insert an img tag into each of these divs with the src being the URIs of the gameDeck array.
The following code achieves this. I've tested it and it works fine. Hope it helps :)
document.addEventListener('DOMContentLoaded', function () {
//iterate through the gameDeck array.
for (let x = 0;x < gameDeck.length;x++){
//create an img tag for each gameDeck element
var imgElement = document.createElement("img");
//set the source of the img tag to be the current gameDeck element (which will be a URI of a png file)
imgElement.src = gameDeck[x];
//target the div with id "card(x + 1)"
var cardID = "card" + (x + 1);
var cardElement = document.getElementById(cardID);
//append the img tag to the card element
cardElement.appendChild(imgElement);
}
//log the HTML to the console to check it
console.log(document.getElementById('body').innerHTML);
});
Here is a way that you can either insert images as background images, or as <img /> elements into the divs you are referring to:
<div id="card0" style="width: 100px; height: 100px;"></div>
<div id="card1" style="width: 100px; height: 100px;"></div>
let loadedImage = [];
function preloadImages(urls, allImagesLoadedCallback) {
let loadedCounter = 0;
let toBeLoadedNumber = urls.length;
urls.forEach(function(url) {
preloadImage(url, function() {
loadedCounter++;
console.log(`Number of loaded images: ${loadedCounter}`);
if (loadedCounter == toBeLoadedNumber) {
allImagesLoadedCallback();
}
});
});
function preloadImage(url, anImageLoadedCallback) {
img = new Image();
img.src = url;
img.onload = anImageLoadedCallback;
loadedImage.push(img);
}
}
function gameBoardCards() {
for (let i = 0; i < loadedImage.length; i++) {
document.getElementById(`card${i}`).style.backgroundImage = `url('${loadedImage[i].src}')`;
// document.getElementById(`card${i}`).appendChild(loadedImage[i]);
}
}
preloadImages([
`https://upload.wikimedia.org/wikipedia/commons/thumb/7/7d/Color_icon_green.svg/2000px-Color_icon_green.svg.png`, `https://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Solid_blue.svg/225px-Solid_blue.svg.png`
], function() {
console.log(`all images were loaded`);
gameBoardCards();
// continue your code
});
It may seem like a bit much for what you are trying to accomplish, but I threw in a proper image-loading handler there. The preloadImages function will handle the loading of images, that way they are properly preloaded, and can render to the DOM. Often times, we try to use images before they are properly loaded, resulting in them sometimes not being displayed, despite no errors are being thrown.
The rest of the code is straight forward, in the for loop, it loops through the existing divs and you can either use the current active line document.getElementById(`card${i}`).style.backgroundImage = `url('${loadedImage[i].src}')`; to use the loadedImage[i] image src to load that as the divs's background image. Or you can use the commented-out line directly below that document.getElementById(`card${i}`).appendChild(loadedImage[i]); to insert an <img /> element into that div. Just use either one that works for you.
You can see the code in action in this JS Fiddle demo.
Hope this helps :)

Image src relative path to absolute path

I have website and now making a hybrid app for it.
I get all my blog post using Jquery get method.
However the issue is that <img src="/media/image.png"> is sometime relative url and sometime an absolute url.
Everytime an absolute url breaks the image showing 404 error.
How to write Jquery function to find if src is absolute and change it to
https://www.example.com/media/image.png
I will not be able to provide any code samples I have tried since I am not a front end developer and tried whole day solving it.
Note: I need to change images present only in <div id="details"> div.
You should always use same path for all the images, but as of your case you can loop through images and append the domain, as of the use case I have added the domain in variable you can change it as per your requirement.
You can use common function or image onload to rerender but I h
Note: image will rerender once its loaded.
var imageDomain = "https://homepages.cae.wisc.edu/~ece533/";
//javascript solution
// window.onload = function() {
// var images = document.getElementsByTagName('img');
// for (var i = 0; i < images.length; i++) {
// if (images[i].getAttribute('src').indexOf(imageDomain) === -1) {
// images[i].src = imageDomain + images[i].getAttribute('src');
// }
// }
// }
//jquery solution
var b = 'https://www.example.com';
$('img[src^="/media/"]').each(function(e) {
var c = b + $(this).attr('src');
$(this).attr('src', c);
});
//best approach you are using get request
//assuming you are getting this respone from api
var bArray = ["https://www.example.com/media/image.png", "/media/image.png"]
var imgaesCorrected = bArray.map(a => {
if (a.indexOf(b) === -1) {
a = b+a;
}
return a;
});
console.log(imgaesCorrected);
img {
width: 50px
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="/media/image.png">
<img src="https://www.example.com/media/image.png">
document.querySelectorAll('#details img').forEach(img => {
const src = img.getAttribute('src');
// use regex, indexOf, includes or whatever to determine you want to replace the src
if (true) {
img.setAttribute('src', 'https://www.example.com' + src);
}
});
The best would be to do this with the response html from the ajax request before inserting into the main document so as to prevent needless 404 requests made while changing the src
Without seeing how you are making your requests or what you do with the response here's a basic example using $.get()
$.get(url, function(data){
var $data = $(data);
$data.find('img[src^="/media/"]').attr('src', function(_,existing){
return 'https://www.example.com' + existing
});
$('#someContainer').append($data)'
})
You can just get all the images from an object and find/change them if they don't have absolute url.
var images = $('img');
for (var i = 0 ; i < images.length ; i++)
{
var imgSrc = images[i].attributes[0].nodeValue;
if (!imgSrc.match('^http'))
{
imgSrc = images[i].currentSrc;
console.info(imgSrc);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<img src="/media/test.jpg">
<img src="/media/test.jpg">
<img src="https://www.example.com/media/test.jpg">

Finding the image count in a web page

I have a JS code, that gets called in different web pages of my clients. I want to fetch the total number of images. I want only those images that are visible to the user and not just any other images. This is my JS code
function getImageCount(topWindow) {
try {
var images = topWindow.document.getElementsByTagName('img');
var imageCount;
for (var i=0, length = images.length; i < length; i++) {
var image = images[i];
var clientWidth = image.clientWidth;
if(clientWidth && clientWidth > 1) {
var src = image.getAttribute('src');
if(src) {
src = src.toLowerCase();
if(src.indexOf('.jpg') !== -1 ||
src.indexOf('.jpeg') !== -1 ||
src.indexOf('.gif') !== -1 ||
src.indexOf('png') !== -1) {
imageCount = imageCount ? ++imageCount : 1;
}
}
}
}
return imageCount;
} catch (e) {
processError("getImageCount", e);
}
}
var imageCount = getImageCount(top);
I have been trying a lot to stabilize this code so that it works correctly across all different types of web pages. Basically what I want is a generic code that captures image counts correctly.
Eg:
My code gives image count as 1 for http://www.msn.com/en-us/news/other/one-free-agent-every-nfl-team-should-sign-this-offseason/ss-AAmLlC0#image
What I want is a GENERIC CODE that gives me a correct image count irrespective of where it runs. Can some one give me some detailed solutions.
I would appreciate a lot.
To simplt count all the images (<img>) on the page:
document.images.length
And to count all the "visible" images (ones with width and height):
[...document.images].filter(img => img.clientWidth && img.clientHeight).length
This will give you the number of images on the page. This does not include CSS images. since your code didn't either then I take it you want <img> ones
I didn't quite understand the meaning of irrespective of where it runs.. can you elaborate?
// Extract images
websiteImages = document.getElementsByTagName('img');
for (url in websiteImages)
console.log(websiteImages.length);
//Extract inbound and outbound links
Links = document.querySelectorAll('a');
for (link in Links)
console.log(Links[link].href);
Paste this Scripts into your console of browser
Check on the Below Link/ any Link you like
(https://news.google.com/topstories?hl=en-IN&gl=IN&ceid=IN:en&gl=IN&ceid=IN:en)
The above-mentioned script will give all the Images present in the webpages.
And the second script will give all the number of Inbound and Outbound/exit links
Just apply Some filter as per your use case and you will be good to go.
Use this simple approach for links
$$('a').length
To count the number of images on a webpage use the below code:
$$('img').length

Categories