WebP Image Replacement - javascript

My end goal is to detect if the browser is capable of displaying webp images. If it is, replace all the images on the page with their webp equivalent (located in the same directory with the same name, just different extension)
Currently I have a script that successfully detects if the browser is able to display webp
(function(){
var WebP=new Image();
WebP.onload=WebP.onerror=function(){
if(WebP.height!=2){
console.log("You do not have WebP support.");
} else {
console.log("You do have WebP support.");
}
};
WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
})();
Inside the case for having webp support I have tried the following code but been unsuccessful.
// replace .gif with .webp
var allImages = document.body.getElementsByTagName("img");
var length = allImages.length;
var i;
for(i = 0; i < length; i++){
allImages[i].src.replace("png", "testtest");
console.log(allImages[i]);
}
When placed in the header the console does correctly show all of the image tags, but the source has not been changed from the filename.png that it originally was.
Any ideas on what is being done incorrectly?
Edit: I found found out the problem with why it was not loading the images, thanks to wsanville. Looking at the network tab in chrome however still reveals that I am loading both the png and now the webp image as well. How can I prevent the png image from loading in the first place?

The replace function returns a string, it doesn't mutate it. You just need to assign the value back:
allImages[i].src = allImages[i].src.replace("old", "new")
Edited for comment:
All browsers will download the corresponding file in the src attribute of an image. As an alternate to your approach, I suggest storing the file name in a different attribute of the img tag.
Your image tags could look like:
<img alt="" data-png-source="/path/to/image.png" />
The corresponding Javascript could set the src attribute to the correct version.
var supportsWebP = true; //set this variable properly
for(i = 0; i < length; i++)
{
var image = allImages[i];
var pngSource = image.getAttribute('data-png-source');
image.src = supportsWebP ? pngSource.replace('.png', '.webp') : pngSource;
}

I know this a very old question, but as I looked for a way to replace webp images with corresponding jpgs, I didn't find much.
With this post, I put this together which seems to work through IE 9.
(It might actually work further back with an older jQuery version, but I'm using jQuery 2.1.1 which breaks in IE <= 8 so I'm not certain)
It checks for .webp support, then if the browser doesn't support .webp, it replaces all occurrences with a .jpg equivalent.
$(function() {
var WebP=new Image();
WebP.onload=WebP.onerror=function(){
if(WebP.height!=2){
$('img[src$=".webp"]').each(function(index,element) {
element.src = element.src.replace('.webp','.jpg');
});
}
};
WebP.src='data:image/webp;base64,UklGRjoAAABXRUJQVlA4IC4AAACyAgCdASoCAAIALmk0mk0iIiIiIgBoSygABc6WWgAA/veff/0PP8bA//LwYAAA';
});

If you have (some) control of the server, you can use content negotiation instead of javascript. See http://httpd.apache.org/docs/2.2/content-negotiation.html for how it's done in Apache.

You are actually trying to solve a variation of the classic responsive image problem.
The problem you have with changing the image src attributes is that a modern browser will look ahead and start downloading images with the wrong extension. You probably don't want to download images you aren't going to use.
The trick is to place the image inside a noscript tag, then progressively enhance that by changing the path as you read the textContent of the tag. In older browsers you will need a simple polyfill to read out the content of noscript tags.
You can view my series on responsive images and webP support here. View an example here based on Ethan Marcotte's classic responsive design.

Related

How to pull images from the DOM in javascript?

If you have looked at Pinterest you will know they have a bookmarklet that the user can press and it loads up more javascript which gathers certain images from the DOM and lets them pin them at the site. I found the gathering images interesting and would like to be able to do that. Where would I be able to look to learn how to gather images from the DOM so that I could let the user do stuff with them? I have done google searches but most are about scraping with php and that doesn't really work if the user is on a page that requires login, for instance.
Am not very sure what you are asking but here is how you get an image using javascript:
var images = document.getElementsByTagName("img");
This will return a nodeList which you can loop through to work on a single image at a time
for (var i=0,l=images.length;i<l;i++){
// your code here
console.log(images[i].src);
}
it is actually quite simple using jquery http://jquery.com/
you can do a simple selector like $('img') .. which will give you a collection of all the images on a page ... from that you can get the source of any of them using $('img').first().attr('src') <=== this will return the source of the first image on the page
hope this helps
Create a bookmarklet. To get all the images on the page do something like this:
var images = document.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
var imageSrc = images[i].src;
// Do something with the image
// ie, add it to the DOM and let them select one.
// It also might be worth looking at the offsetWidth property to only grab larger images
}
Here's the source to the Pinterest bookmarklet for reference

Preloading images in jQuery gallery

I would like to use this gallery in my website. The only issue is that when clicking next to load the picture, it takes a lot of time. I would like to preload the next two images, when the user clicks the image to enlarge it.
I came across this solution but it's manually coding the image names, but my images are loaded dynamically. Is there any other way I can do it?
Here's a simple-ish solution. You can add a click event to the thumbs so that when one is clicked it preloads the next three images. Some way of preloading the next image once you are in individual image navigation would still have to be worked out though, but hopefully this will hep you get there..
$("#content img").on("click",function(){ // use .live instead if you are using an older version of jQuery
var next = $(this).next();
for (var i = 0; i < 3; i++)
{
var img = new Image();
img.src = next.attr("alt");
next = next.next();
}
});
You can use the solution you mentioned, you just need to extract the src attribute of the gallery's images:
preload($('#gallery-images img').map(function() { return this.src; }));
This will actually call the preload function with the needed array.
I recommend using this gallery - http://dimsemenov.com/plugins/royal-slider/gallery/ it does exactly what you need - preloads nearby images and you may set how much to preload. But note that it's commercial and costs around 10 bucks.
If your images are stored in a mysql you could use the solution you found with a few modifications adding a json encode from the sql query of image names. Passing the information onto jQuery for preloading
require_once('JSON.php');
$json = new Services_JSON();
$out = $json->encode($query)

JavaScript to change links on page?

I'm pretty new to JavaScript and am wondering how on a page with links to images, i.e. http://www.example.com/image.jpg I can get them to be changed automatically by JavaScript to be embedded, ie with <img> tag
Hope that makes sense!
Thanks
We're particularly fond of the jQuery framework here, as it makes this sort of task very easy. With jQuery on your page, you can easily do this:
$(document).ready(function() {
$('a[href$=.jpg]').each(function() {
var imageSrc = $(this).attr('href');
var img = $('<img />').attr('src', imageSrc);
$(this).replaceWith(img);
});
});
This will work specifically for <a> tags whose href attributes end with .jpg You can expand it to other file extensions, of course, but to dynamically determine whether a link leads to an image if the URL is not obvious would be a far greater challenge.
Do you mean convert all image url's to hyperlinks "pointing" to the images?
var x = document.getElementById('body');
x.innerHTML = x.innerHTML.replace(/(http:\/\/[^ ]+)/g,'$1/');
I haven't tested this, but it should work. No third-party frameworks are needed.
From here

How can I determine img width/height of dynamically loaded images in IE?

My markup is a simple div element with id 'load'. Using jQuery I then load a list of image elements into this div:
$('#load').load('images.html', { }, function() {
$(this).onImagesLoad({
selectorCallback: function() {
....do something....
}
});
});
where images.html is a list like this:
<img src='1.jpg' caption='img 1'>
<img src='2.jpg' caption='img 2'>
...
To ensure that all images are loaded completely, I use the onImagesLoad plugin. This, so far, works just fine on all browsers.
However, on IE8 (and I assume other versions of IE also) when I then iterate over the img elements, I am unable to determine the width/height of the images loaded. The image.context.naturalWidth and naturalHeight attributes don't seem to work.
How do I get a hold of the images' dimension?
Thanks heaps :)
Update
#Simon: That didn't work on IE, and broke the other browsers as well.
#Jenechka: If "imageDomElement" is just another name for the "image" variable in my example above, then it doesn't work. Or what do you mean by that DomElement?
If you haven't resized the image, you could use:
image.width()
and
image.height()
It's been a while but I finally found some time to tinker with this again. The above problems are still there, but here is what I think is going on.
When I load the initial images then yes, the file is loaded and image objects are generated. But it seems that the attributes are not correct yet, and they won't be until the image is actually added to the DOM of the site and rendered. A div/image on hide() on IE has no dimension information whatsoever, on Safari there is some information available. For example, without adding the following div anywhere
var test = $("<div><img src='test.jpg'></div>")
the image contained there has the following information:
width() = 0,
attr("width") = 600,
css("width") = "", and
img[0].clientWidth = 0.
That's on Safari; on IE it's the same except attr("width") = 0 and css("width") = "auto". Now I can't use this, and that's what broke my script and why I posted my initial question. However, the moment I append this div and have it rendered, all the correct values show up in the image object.
I'm writing a little gallery thinghie, which shows whatever images I have in that second .html file that I load; that gallery, however, computes and places the thumbnails, and prepares the images it shows in full resolution. To make this look ok, I basically wanted to create the entire thing hidden, and then fade it in. Alas, it seems that this whole idea won't pan out. A friend suggested to load everything into a tiny iframe off to the left where it's not visible, and work with that. Perhaps that's the way to go.
Another thing I noticed, and that seems to be very closely related to the aforementioned load issue is clone(). It seems that if an image is rendered, a
var newimg = img.clone()
generates the same "empty" image object that I have to deal above. Even when the original image is visible and contains all the right attributes, its clone does not.
Right now I don't see any other way than to rethink and rewrite parts of my gallery.
This is quite similar to the other answers, but I have tested it in IE7, so it might be closer to what you want:
$(document).onImagesLoad({
selectorCallback: function() {
$('img').each(function(){
alert($(this).width()+', '+$(this).height());
});
}
});
See here, this may not be exactly how you were using it, but I'm not familiar with this onImagesLoad thing.
imageDomElement.width
imageDomElement.height
or try
imageDomElement.clientWidth
imageDomElement.clientHeight
If you play with jquery, then image.attr(width) should do the trick
But why not using the document.ready instead, could give you less headeache. .
Use the following code instead
$(document).onImagesLoad({
selectorCallback: function() {
$('img').each(function(){
alert($(this)[0].clientWidth +', '+$(this)[0].clientHeight);
});
}
});
What about?
$("#load img").each(function() {
var img = new Image();
img.src = this.src;
alert(img.height + " x " + img.width);
});

color to B/W javascript affect

Is there any known/simple/open-source library that provide
a javascript function that will switch colored picture that is displayed in an html page into a black and white
That can be used in all the most used browsers (IE, FireFox, Chrome)?
I mean something like:
<html>
...
<img id="myPic" src="pic.jpg">
...
<script type="text/javascript">
function onEvent(){
var pic = document.getElementById("myPic");
magicFunctionToBlackAndWhite(pic);
}
</script>
</html>
looking for that magicFunctionToBlackAndWhite()
There's no one solution that works across all browsers, but you can combine different solutions:
For IE, use the following CSS: filter: Gray
A lot of other browsers supports canvas, so you should be able to use this javascript code for that.
Of course it should't be too much of a hassle to make an image b/w in a serverside language such as .net, so you could always have a javascript that in principle does something like the following:
var imgs = document.getElementsByTagName('img');
for(var i = 0; i < imgs.length; i++) {
imgs[i].src = 'convertimage.aspx?img=' + imgs[i].src;
}
...and then have all of the magic happening on the server.
That might be somehow possible by using the <canvas> element, but I would recommend you to do the black and white versions yourself, either manually or through some sort of script. Trust me – it'll save you a lot of trouble.

Categories

Resources