How to cancel a background image from loading - javascript

How can you cancel the loading of an image defined by a background-image attribute?
There a few questions that show how to cancel the loading of an <img> tag by setting the src to '' or to a different image (such as this one, answered by Luca Fagioli). But this does not work for background images.
Luca provided a jsfiddle ( jsfiddle.net/nw34gLgt/ ) to demonstrate the <img src="" /> approach to canceling an image load.
But modifying that jsfiddle to use background-image instead clearly shows that the image continues loading, even if:
you do background-image: none (as suggested here)
or background-image: url("web.site/other_image.jpg")
or background-image: url('').
In fact, in my testing on Firefox 54, the background image continues loading even if you do window.stop() or close the tab.
So, is there any way at all to stop loading a background image once it starts?
My use-case for this is client-side, so I can't change the site to not use background images. I am viewing a gallery of many thumbnail images, but the thumbnails are much larger than they need to be. Smaller versions are available so I wanted to replace the large thumbnails with the smaller versions via Greasemonkey to ease the network load on my poor, slow connection. Each entry in the gallery is a <div> with a background-image inside an <a> linking to the full-size image. (using Fotorama).

If you need to target inline styles on the elements, then I think you can run a script near the bottom of the page to do that.
Testing this locally, the original images do not show as loading in the network tab.
var allDivs = document.getElementsByTagName('DIV');
for (var i = 0; i < allDivs.length; i++) {
// check for inline style
var inlineStyle = allDivs[i].getAttribute('style');
// check if background-image is applied inline
if (inlineStyle && inlineStyle.indexOf('background-image') != 1 ) {
allDivs[i].style.backgroundImage = 'url("newImg.jpg")'; // assign new value?
}
}
That is going to grab every div, so hopefully these elements have a class you can use to query first. Then you have a smaller collection to run the above on.
Classes, not inline styles:
If you could target classes, it would look a bit cleaner. You could create a new class and use it.
var els = document.querySelectorAll('.bg-img');
for (var i = 0; i < els.length; i++) {
els[i].classList.remove('bg-img');
els[i].classList.add('no-bg-img');
}

Related

In Chrome the currentSrc of an img element is sometimes empty. How can I prevent this?

UPDATE:
I just found some more info. It seems that in Chrome, the currentSrc of the image will often be empty, whereas in Firefox, the URL is always correct. Is the JS trying to access currentSrc before it's available? Is there a way to prevent this?
I am creating a Drupal 8 website, and in order to use the responsive images module with a background-image, I came up with the following workaround. The JS function below, setParallaxImage(), takes the currentSrc from the img in the picture element and sets it as the background-image for the outermost div. The img itself is not displayed (display: none in CSS) and is given a dummy image, as I only need it to get the currentSrc. The function is called with onload and onresize.
The code seems to work well in Firefox. When resizing the browser past a breakpoint, the image goes grey for a split second, then loads the image from the proper source. However, with Chrome, when quickly resizing past a breakpoint, the image may become grey and not get displayed at all, that is, background-image: url(). Usually if I resize the window a couple more times, the image will finally appear. Does anyone know why this might be happening? Thank you for reading.
JS
function setParallaxImage() {
const parallaxContainer = document.getElementsByClassName('paragraph--type--parallax-banner-with-text');
for(var i = 0; i < parallaxContainer.length; i++) {
console.log('in setparallax');
var x = parallaxContainer[i];
var parallax = x.getElementsByClassName('field--name-field-parallax-image-top-')[0];
var picture = parallax.getElementsByTagName("picture")[0];
var sourceURL = picture.querySelector('img').currentSrc;
x.setAttribute('style', 'background-image: url(' + sourceURL +')');
var img = picture.getElementsByTagName("img")[0].setAttribute('src', '/sites/default/files/src_images/dummy_image.gif');
}
}
window.onload = setParallaxImage
window.onresize = setParallaxImage;
HTML
<div class='paragraph--type--parallax-banner-with-text'>
<div class='field--name-field-parallax-image-top-'>
<picture>
<!-- several source tags here -->
<img src="will-be-given-dummy-image-in-JS">
</picture>
</div>
</div>
You can use the property "complete" to check, if the image was already loaded. If not, u can use the onload-Event to fire, when the image is available.
if (img.complete) {
console.log(img.currentSrc);
} else {
img.onload = function() {
console.log(img.currentSrc);
}
}

Flickering images

I'm currently making a little game where every few seconds some images are removed and reloaded to update their new status and position, which is done with the code below. However, this causes these images to flicker at every reload which is especially annoying when an image is on the exact same spot and can actually cause a miss-click now and then. Is there any way I can prevent my images from flickering?
$(".armysprite").remove();
for (var i = 0; i < armies.length; i++) {
iniArmies(i); // Function that adds the new army images back into the DOM
}
The easiest way is to do it is: to load new image in hidden div, and on the function of onload of the image to show this div and hide your old div (like css property: display:none; / display:block;)

css - change an image frequently with less server requests

I have a in html. Its content is described in css.
With different functions the classname of the div is changed to imageholder1,2 etc.
.imageholder1 { content: url('image1.png')}
.imageholder2 { content: url('image2.png')}
But I think this causes multiple server requests , each time the classname is changed.
Is there a way to reduce the server requests to the image file.
I would like a way to store the image into a variable and then point it from css code. Is it possible?
I also tried to use a css image sprite but I need to need a more flexible way.
If you put all your images in a hidden (display none) div, they'll load all at once. The browser should cache them, so then each time it changes, it pulls from the client system.
<div style="display: none;">
<img src="image1.jpg">
<img src="image2.jpg">
<img src="image3.jpg">
</div>
Preload the images and it will cache the images and only request each image once (it will also allow for smoother transitions between the images because subsequent images will already be downloaded). This will limit your http requests to one request per image (the minimum you can achieve without sprite sheets).
Here is a really nice jQuery solution (that doesn't add hidden elements to the DOM) but really any preloading scheme should work:
$.preloadImages = function() {
for (var i = 0; i < arguments.length; i++) {
$("<img />").attr("src", arguments[i]);
}
}
$.preloadImages("hoverimage1.jpg","hoverimage2.jpg");
Reference
According to me, if we load multiple images on a page it is going to have multiple requests.
Instead of this simply use a sprite combining all the images.
This will cause to fetch a single image from server.
Then define css properties for background for classes such that they will have different position values of the sprite used causing to show required image.
.imageholder1 {
background: url(/path/to/sprite.png) -60px -120px no-repeat;
}
.imageholder2 {
background: url(/path/to/sprite.png) -20px -120px no-repeat;
}

Improve image load time

I have a few img tags whose src is changed onmouseover. This takes an inordinate amount of time to load. How can I improve the load time? The images are basically just different icons.
You can do a few things.
1) CSS Sprites is probably the preferred method.
2) You can load the images in a div and set that div to display none, making it so the images are already loaded so on mouseover they'll be there instantly.
Also here's a link on how to PreLoad images with CSS
There are a few ways to do it, the ideal solution in your case would be to use CSS sprites considering they're icons. However, depending on the situation sometimes sprites aren't ideal.
Here's one solution using JavaScript to preload images:
var images = new Array();
function preload() {
for (i = 0; i < preload.arguments.length; i++) {
images[i] = new Image();
images[i].src = preload.arguments[i];
}
}
preload(
'http://image-1.jpg',
'http://image-2.jpg',
'http://image-3.jpg'
);
What you're trying to do is achieve a rollover. It is strange that you'd experience a very long delay in this process. Usually, if the images aren't stored in some remote location, they're pretty fast.
Look at this article for some guidance
Other things you could try:
- sprites in css
- you could use two overlapping divs and hide one and unhide the other and vice versa

Javascript load background-image asynchrously

Is it possible to load a background-image asynchronously?
I've seen many jQuery plugins to load normal image in an asynchronous way, but I can't find if it's possible to preload / asynchronously load a background-image.
EDIT
I clarify my problem. I've been working on this test site http://mentalfaps.com/
The background image is loaded randomly from a set of images refreshed each hour by a chron job (which takes random images on a flickr catalog).
The host is free and slow at the moment, so the background image takes some time to load.
The positioning of the first overlay (the one with the PNG transparent mentalfaps logo) and width are regulated by a function created in the jQuery(document).ready construct.
If you try to refresh the page many times, the width of the right overlay div is 0 (and so you see a "hole" in the layout)
Here is the method to set my positions:
function setPositions(){
var oH = $('#overlay-header');
var overlayHeaderOffset = oH.offset();
var overlayRightWidth = $(window).width() - (overlayHeaderOffset.left + oH.width());
if (overlayRightWidth >= 0) {
$('#overlay-right').width(overlayRightWidth);
} else {
$('#overlay-right').width(0);
}
var lW = $('#loader-wrapper');
lW.offset({
left: (overlayHeaderOffset.left + oH.width() - lW.width())
});
}
The problem is that the $(window).width() is lower then the effective window width! so the check fails and the script goes for $('#overlay-right').width(0);
any ideas?
Not sure whether I really understand your question, but background images (and all other images) are already loaded asynchronously - the browser will start separate requests for them as soon as it encounters the URL while parsing the HTML.
See this excellent answer for background on loading order: Load and execution sequence of a web page?
If you meant something else, please clarify.
The trick to loading something in the background is to load it once, so the next time when it is loaded it already is in the cache.
Put the following at the end of your html:
<script>
var img = new Image();
img.onload = function () {
document.getElementsByTagName('body')[0].style.backgroundImage = 'background.png';
};
img.src = 'background.png';
</script>
You could use a prefetch link in the head.
<link rel="prefetch" href="/images/background.jpg">
You should be able to add these links to the head via JavaScript.
I like to use CSS to fill the background with a color for page load.
After DOM ready event, I use jQuery to modify the CSS and add a background image. That way, the image isn't loaded until after page loads. Not sure about async, but this method gives the user a decent experience.
Example: http://it.highpoint.edu/
The right side navigation links have a background image. The page initializes with a background color. It is replaced with a background image after page load, via jQuery.
changes in this file jquery.ImageOverlay.js
set your height and width and enjoy this...
imageContainer.css({
width : "299px",
height : "138px",
borderColor : hrefOpts.border_color
});
As it is already mentioned, the background image is loaded asynchronously. If you need to load the background image from JQuery code you may also set the addClass() method to set a CSS class or attr("style=\"background-image:url('myimage.png')\"")
Ive found the answer myself, it was a problem due to the .offset() method that gived sometimes the wrong values.
I had the write values using the .position() :
var overlayHeaderOffset = oH.position();

Categories