Set background-image for button to element already contained within page - javascript

Basically I want to specify the background-image for a button using something other than an image url. Being able to set the background-image to an already loaded element contained within the DOM would be ideal. This is so that I can cache a loading gif (displayed on the button) within the DOM and don't have to fetch it when the button is clicked.
I didn't think code was necessary to illustrate the problem but here is some anyway
Not ideal due to image loading on click:
that.submitButtonSelector.css('background-image', 'url(/Content/_activity/ajax-loader.gif)');
Ideal (but no obvious way to achieve)
that.submitButtonSelector.css('background-image', '#precachedImage');

If you load the loading gif via the url, it will be cached in most cases. You only need to download it once. After that it will be served up from cache. The only other thing I can think of is to use a base64 source. This has the benefit if not generating an HTTP request, but is larger when it comes to actual bytes (I don't think the larger size is slower than another HTTP request, but you can always benchmark them).
In my experience I believe base64 images are great if you need to immediately show the loading icon and if the icon is small enough, but if you don't need to show it right away, I suggest preloading the image via url with javascript and just relying on the cached version.
So in your case, if you went with base64, you could use
that.submitButtonSelector.css('background-image', 'url(data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==)');
body:after {
content: url(data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH+GkNyZWF0ZWQgd2l0aCBhamF4bG9hZC5pbmZvACH5BAAKAAAAIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQACgABACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkEAAoAAgAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkEAAoAAwAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkEAAoABAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQACgAFACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQACgAGACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAAKAAcALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA==)
}

You can have a hidden div that preloads the image into cache, and then once it's loaded you can add the background.
HTML:
<img id="img" src="/Content/_activity/ajax-loader.gif" />
CSS:
#img {
display: none;
}
jQuery:
$("#img").load(function() {
$(submitButtonSelector).click(function() {
that.submitButtonSelector.css("background-image", "/Content/_activity/ajax-loader.gif");
});
});

Related

Using jQuery to replace UIKit's Slideshow source image with a responsive one based on srcset

HTML:
<div id="rb-hero" class="rb-hero uk-block uk-flex uk-flex-middle uk-contrast arrowed">
<ul class="uk-slideshow uk-slideshow-fullscreen" id="biggie_slides" data-uk-slideshow="{pauseOnHover: false, autoplay:true}">
<li><img src="{theUrlMedium}" alt="{theAltText}" srcset="{theUrlSmall} 750w, {theUrlMedium} 1200w, {theUrlLarge} 2000w, {theUrlXL} 3000w" ></li>
</ul>
</div>
jQuery:
$('#rb-hero li img').each(function() {
var theSrc = $(this).prop('currentSrc');
// console.log(theSrc);
$(this).prev('div').attr('style', 'background-image: url( '+theSrc+' )');
});
UIKit provides a slideshow function, and I have it in use and it works just fine. The way it works is to use each image slide's src as an inline background-image style attribute on a dynamically-created div. All works fine.
The problem is that UIKit does not use the appropriately-sized image from the provided srcset (which is also working correctly per the currentSrc info in devtools), it simply grabs the fallback img src and thus a pretty high-res image when on mobile.
I'm trying to loop through the elements and replace the inline style's background-imagesource with the currentSrc, but I'm hitting a wall.
The each() method is doing its magic and the console logs the smaller-sized image based on the appropriate srcset source at smaller screens, but the setting of the inline style is going nowhere.
So I'm missing something, and it's probably going to be obvious and glaring but in addition to sleep I need an assist.
Thanks.
Edit: Updated code to a better working place and now only the final bit's not working.
I edited my first answer as it was complete nonsense.
I did some testing with your code and two differently sized images and found that it actually works, but only if certain conditions are met:
I noticed that the browser won't load a smaller sized image from the srcset if there's a larger one already in the cache. I guess it's meant to work this way, but you'll have to keep that in mind and clear the browser cache while testing.
But if you first resize your browser window, then clear the cache and reload the page, the smaller images actually are being loaded and set as background images. I also had to wrap your code in a setTimeout function, otherwise even the console.log was empty and nothing happened. This wasn't necessary with an enlarged browser window (probably because it loaded the image straight from the src tag so there was no delay).
Another problem is that uikit will have set the background image from the src tag and the browser will have loaded it before you set the image url from the srcset, so you'll load both files (which is even worse than only loading the large one on a small screen).
The cleanest and easiest solution would be to modify uikit's slideshow component. They only had to change the part where the image url is read from attr('src') to prop('currentSrc').

jquery - replace broken image icon while image is loading

I have a page that has a list of many <img> tag. So it takes a long time to load all images. Before loading any image, I see the broken image icon. I want to replace broken image while loading the images. I tested this answer, but it just worked when a error happens. Is there anyway for doing that with javascript or jquery?
I found a good solution on GitHub. Just use the CSS code below:
img[src=""],
img:not([src]) {
visibility: hidden;
}
Link: https://github.com/wp-media/rocket-lazy-load/issues/60
You can load a placeholder image, but then you must load that image (when you're already loading another image). If you load something like a spinner via a GET request, that should be ok since you can set cache headers from the server so the browser does not actually make any additional requests for that loading image. A way that Pinterest gets around this is by loading a solid color and the title of each of their posts in the post boxes while the images are loading, but now we're getting into a design discussion. There are multiple ways to skin a cat.
Regarding loading several images, you have to understand a couple considerations:
The time it takes to fetch and download an image.
The time it takes to decode this image.
The maximum number of concurrent sockets you may have open on a page.
If you don't have a ton of images that need to be loaded up front, consideration 3 is typically not a problem since you can optimistically load images under the fold, but if you have 100s of images on the page that need to be loaded quickly for a good user experience, then you may need to find a better solution. Why? Because you're incurring 100s of additional round trips to your server just load each image which makes up a small portion of the total loading spectrum (the spectrum being 100s of images). Not only that, but you're getting choked by the browser limitation of having X number of concurrent requests to fetch these images.
If you have many small images, you may want to go with an approach similar to what Dropbox describes here. The basic gist is that you make one giant request for multiple thumbnails and then get a chunked encoding response back. That means that each packet on the response will contain the payload of each thumbnail. Usually this means that you're getting back the base64-encoded version of the payload, which means that, although you are reducing the number of round trips to your server to potentially just one, you will have a greater amount of data to transfer to the client (browser) since the string representation of the payload will be larger than the binary representation. Another issue is that you can no longer safely cache this request on the browser without using something like IndexedDB. You also incur a decode cost when you set the background image of each img tag to a base64 string since the browser now must convert the string to binary and then have the img tag decode that as whatever file format it is (instead of skipping the base64->binary step altogether when you request an image and get a binary response back).
you can use placeholder image, which is very light weight and use that in place of each image.
same time while loading page, you can load all the images in hidden div.
then on document ready you can replace all the images with jQuery.
e.g.
HTML
<img src="tiny_placeholder_image" alt="" data-src="original_image_src"/>
<!-- upto N images -->
<!-- images are loading in background -->
<div style="display:none">
<img src="original_image_src" alt=""/>
<!-- upto N images -->
</div>
JavaScript
(function($){
// Now replace all data-src with src in images.
})(jQuery);

How do I replace the background image of a webpage in Javascript before it's loaded?

I am currently overwriting the CSS of a webgame I play to give a more pleasant user experience. The only thing that I am having difficulty with is replacing the background image correctly, as the original background image loads onto the screen before the script replaces it to a solid color. The solid color that I am replacing it with loads, but not until after the page loads.
Here is a gif of the issue I am running into.
I have tried using document.onload, .onDomContentLoaded, .ready, etc, but for some reason none of these are working. Is there any way I can prevent the background image from loading before the script is run?
window.onload will wait for all the resources to load.
However, it sounds like you should just add a background-color to the element and let the background render beneath it.
Have you tried the property as important? background-color: gray !important
I think this should prevent the image from showing up at all
Place this in an external Javascript file, and make a request for it before anything else in your head.
var myImage = new Image();
myImage.src = 'your_image_here';
What happens is that an external Javascript file blocks the rendering of the page. And the script itself will not finish till the image has been downloaded. So there won’t be any delay when you do switch the background.
You could use:
document.style.backgroundImage="url('img.png')";
I believe AmmarCSE is hinting at a possible answer, but the cause is unknown.
You should first review your HTML for the order in which your resources are loaded. The CSS is a loaded resource and can specify background colors and images. This will possibly explain the following:
If your CSS specifies colors/image resources, and the HTML loads the CSS resource prior to executing your document functions, you will continue to get this behavior.
You should review the CSS for the background image/color and change it there instead of attempting to override it with document functions.
This is an assumption of the problem. You should provide some HTML, JavaScript, and CSS in your original post to help others answer and review.

How to select a loaded image and insert it into a div

I've got an image that is loaded when the site is called.
<img id="some_Image" src="some_source">
Now I want to reuse that image and NOT request it again from "some_source". (Because it has to be computed and I do not want to recalculate it). I want that image later to be displayed in some JQuery dialog. I know the existance of append and prepend functions, but reading the documentation it seems like I have to insert a whole image tag as an argument, which results in requesting the image again. (if the browser doesn't cache the image)
have a look at the jQuery clone
it is supposed to work with images as well, if the image has been loaded by the browser its supposed to reuse it.
EDIT:
$( "#some_image" ).clone().appendTo( "#some_div" );
By default, all browsers cache as much as they can (js, css, images). This way, the moment your image is loaded you can create a new <img> tag with the same source path and the browser will use its local cached file.

jQuery changing <img> src with $(selector).prop takes a long time

So there's no issue with this code functionality itself. I have something like this:
<div>
<div><img id="imageToChange" src="/path/image.png" /></div>
<div id="textToChange">Text</div>
</div>
I have another part of my code, that changes the image src/text with jQuery.
function changeImage() {
$('#imageToChange').prop('src', '/path/image2.png');
$('#textToChange').html('New Text');
}
As you may expect, this works exactly as I expect it to. But with 1 quirk.
In all the main browsers (chrome/FF/IE). The image takes a long time to change.
So for example, when I call changeImage(), the text will change instantly, but the image may not change until 1-2 seconds later. (Not large images by any stretch, about ~6KB, and local)
I haven't found anyone else really complaining about it, but what I'm wondering is if there's any way to speed up the changing of the image src? Perhaps a better way to do it?
This is jquery 1.8.0 as well.
Thanks
I have seen this behavior before. The delay is caused by the image not being cached and the subsequent load time. The only solutions I know of:
Preload your images with JavaScript Image objects.
Handle the load event on the image and update the text after the image as loaded. Note jQuery lists some issues to watch out for:
Caveats of the load event when used with images
A common challenge developers attempt to solve using the .load()
shortcut is to execute a function when an image (or collection of
images) have completely loaded. There are several known caveats with
this that should be noted. These are:
It doesn't work consistently nor reliably cross-browser
It doesn't fire correctly in WebKit if the image src is set to the same src as before
It doesn't correctly bubble up the DOM tree
Can cease to fire for images that already live in the browser's cache
http://api.jquery.com/load-event/
You may want to try altering the attribute using the jquery .attr function. If I recall correctly the src tag of an image is an attribute not a property. Although both .prop and .attr do relatively the same function, to ensure consistent behavior between browsers you may want to use the .attr tag instead.
$('#imageToChange').attr('src', '/path/image2.png');
As far as the delay goes, this could be due to the size of the image. The browser has to make a GET request to the server for the image and then paint the DOM with it. If the image is large, it could cause a time lapse between when the code changes the source and when the new image is properly written to the DOM. If the image is large, you may want to consider scaling it down or optimizing it for web use.
Hope this helps.
You can pre-load the image using the Javascript Image object.
In the head of your document put
<script type="text/javascript">
img2 = new Image();
img2.src = "/path/image2.png";
</script>
when you change the src of the image you fetch another image file. it makes an HTTP request for the new image, so it needs to load before showing it. could this be it?
btw, for this reason you can pre-load the image with js. either add
<img src="path/to/image.jpg" style="display: none" />
to your html or using JS
var im = new Image(1,1);
im.src = "path/to/image.jpg";
this way the image will be cached
It's the delay of network. Try this:
<div>
<div><img id="imageToChange" src="/path/image.png" /></div>
<div id="textToChange">Text</div>
</div>
<img src='/path/image2.png' style='display:none'>
it is likely the load time of your images. if this is the case, loading the image the first time should be the only slow one. a follow up load, after changing the image to something else, would be fast.
$('#imageToChange').prop('src', '/path/image1.png');
//slow, need to fetch image
$('#imageToChange').prop('src', '/path/image2.png');
//slow, need to fetch image
$('#imageToChange').prop('src', '/path/image1.png');
//fast, it already has this image
As a solution, you could try preloading your images. Or, better yet, use css sprites.

Categories