Loading images in javascript the interactive way without breaking compatibility - javascript

On my website, I share a lot of large images. I use the following HTML tags to display the images:
<img src="/path/to/image" width=x height=y alt="whatever">
Of course the values are replaced with proper values.
I would like to implement a solution so that all browsers (including those capable of supporting ONLY basic HTML and images including the Arachne browser) can access the image, while the browsers with javascript can see the image loading in action. (for example, the loading screen followed by the image appearing instantly)
The following URL gave me an idea:
http://blog.teamtreehouse.com/learn-asynchronous-image-loading-javascript
It suggested I should use this type of javascript
var image = document.images[0];
var downloadingImage = new Image();
downloadingImage.onload = function(){
image.src = this.src;
};
downloadingImage.src = "http://an.image/to/aynchrounously/download.jpg";
and this type of CSS:
img {
width: 600px;
height: 450px;
background: url(loading.gif) 50% no-repeat;
border: 1px solid black;
border-radius: 5px;
}
The problem with this setup is that browsers that don't support javascript or CSS will always see the loading graphic and therefore become frustrated.
Is there a way I can achieve this loading effect but still allow browsers without javascript or CSS to still see the proper image?
The only thing I can think of is to use javascript to somehow force-stop an image from loading but I don't know if such commands exist. In code, I'm thinking:
<script>
document.getElementById('delayme').dontLoadImage=true;
//stop image from loading
//ajax code to fetch image url as if it was html
document.getElementById('delayme').dontLoadImage=false;
//let image continue loading
</script>
<img ID="delayme" src="image.jpg" width=100 height=100 alt="image">
Any ideas?
and remember, the image must appear regardless of whether the user has javascript enabled or not.
UPDATE
So far, this code works for my needs, but only if both javascript and CSS are enabled or if both javascript and css are disabled. However if CSS is enabled and javascript is disabled, then the image stays hidden. How do I fix this?
<style>
img{display:none}
</style>
<div ID="loading">
</div>
<script>
document.getElementById("loading").innerHTML="Loading picture...";
</script>
<img src="http://127.0.0.1/x.jpg" onload="func()">
<script>
function func(){
document.images[0].style.display="block";
document.getElementById("loading").innerHTML="Picture loaded";
}
</script>

You can make something like this:
var asyncImgs = []; // empty array to store the img src's to load them asyncronously
var imgs = document.getElementsByTagName("img");
for(i = 0; i < imgs.length ; i++) {
asyncImgs.push(imgs[i].src); // store the src
imgs[i].src = null; // remove the src
}
With this method, the non-javascript browsers render the normal <img> tag, but with javascript you iterate all images in page, stores the src into an empty array, and then remove the src of the image. You can add your code to load images with new Image() now.
Good luck!

This will work with CSS on and JS off or both on. I don't know if I've seen anyone running JS with CSS off, but if that is something you are trying to solve, I'll have to rethink this quite a bit. I'll be honest, it's not really pretty, but it works.
If only CSS is enabled or if both JS and CSS are disabled, the page loads like any other basic HTML page. The images are loaded from the src.
Once we have JS support, we insert a loading <div> before the image and hide the image until it is loaded at which time we show it and remove the loading div. This is the best case I could think of without having to enclose every image tag in a <div> in the HTML.
HTML/JS:
<img src="https://upload.wikimedia.org/wikipedia/commons/1/13/05S_Jan_7_2012_1035Z.jpg" />
<img src="https://placehold.it/998x999.png"/>
<img src="https://placehold.it/997x999.png"/>
<img src="https://placehold.it/996x999.png"/>
<img src="https://placehold.it/995x999.png"/>
<img src="https://placehold.it/994x999.png"/>
<img src="https://placehold.it/993x999.png"/>
<img src="https://placehold.it/992x999.png"/>
<img src="https://placehold.it/991x999.png"/>
<img src="https://placehold.it/990x999.png"/>
<img src="https://placehold.it/999x991.png"/>
<img src="https://placehold.it/999x992.png"/>
<img src="https://placehold.it/999x993.png">
<img src="https://placehold.it/999x994.png"/>
<script>
var imgList = document.getElementsByTagName('img');
for (var i = 0; i < 3; i++) {
imgList[i].insertAdjacentHTML('beforebegin', '<div id="loading' + i + '" style="height:' + imgList[i].clientHeight + 'px;width:' + imgList[i].clientWidth + 'px;background: url(\'http://loading.io/assets/img/default-loader.gif\') center no-repeat;z-index:9999;"></div>');
imgList[i].style.display = "none";
imgList[i].onload = function() {
this.style.display = "block";
this.previousSibling.remove();
};
}
</script>
CSS:
img {
display: block;
width: 600px;
height: 450px;
border: 1px solid black;
border-radius: 5px;
}
Demo: https://jsfiddle.net/hopkins_matt/abychvxc/

After looking at answers and my own testing, it turns out that I needed the noscript tag and that I needed to fully generate a new image to attach to the existing DOM structure. Because of Internet Explorer's bugs, I forced internet explorer to load the image an old-fashioned-ish way where the status isn't updated as the image loads. In other browsers, the load is more progressive because those browsers were invented correctly (I hope). Nevertheless, this code works for me and I will use it as my starting point.
<!DOCTYPE HTML>
<html>
<head>
</head>
<body>
<div ID="LOAD"></div>
<div ID="IMAGE">
<noscript>
<img src="/x.jpg">
</noscript>
</div>
<script>
var x=document.getElementById('LOAD');
x.innerHTML='Loading...';
downloadingImage=document.createElement('IMG');
if (navigator.userAgent.indexOf("MSIE") == -1){
downloadingImage.onload=function(){
x.innerHTML='';
document.getElementById('IMAGE').appendChild(downloadingImage);
}
}else{
x.innerHTML='IE';
document.getElementById('IMAGE').appendChild(downloadingImage);
}
downloadingImage.src = "/x.jpg";
</script>
</body>
</html>

Related

Javascript DIV Not Displaying After Changing CSS

I have a DIV for spinner:
<div id="spinner" style="display:none;z-index:100;position:absolute;top:50%;left:50%;margin-top:-50px; margin-left:-50px;">
<img src="..\spinner.gif" alt="Loading" />
</div>
The code document.getElementById("spinner").style.display = "block" changes the style of the spinner to block but the spinner div not showing:
document.getElementById("spinner").style.display = "block";
getAllStudents(); //this function gets data from MySQL tables and populate a table on the page
document.getElementById("spinner").style.display = "none";
Instead of adding display: none; after the function call,
try adding the code just before you start populating the table on page.
document.getElementById("spinner").style.display = "none";
Two Ideas:
If the image src is incorrect, I've sometimes found it doesn't display anything, even with an alt = "Loading" tag. You might want to test the link it's displaying the image from to verify it works. (Don't just test the src link).
Assuming the image src is correct, you could remove the image from <div id="spinner"/> and add it separately as <img id="spinner" src="..\spinner.gif" alt="Loading" /> and then you could have your <div show what you want.
EDIT: (3 ideas now)
Change your src attribute so all of the \ characters are replaced with /. I tried an image in my own script with src = "..\spinner.png" and it wouldn't even run, but doing src = "../spinner.png" did. Hopefully this solves your problem.

Disable loading images while the web-page is loading

Most of my website visitors are using limited bandwidth & slow internet.
so I'm trying to reduce the load time and save their bandwidth by disable loading images & background images while the web-page is loading, then give an option to load the web-page's images when click "show images" button.
i'm thinking of some thing like lazy load but with on-click action.
I appreciate your suggestions.
One idea:
-Keep empty src attributes for images
-Store img urls on an attribute (you can call it data-src)
-Use Jquery to replace src with data-src value when page is loaded or when User clicks "show images"
I think there are 2 different scenarios:
IMG-TAGS
HTML:
<img src="" data-load="http://imagesource" alt="">
jQuery:
$('img[data-load]').each(function(){
$(this).attr('src', $(this).data('load'));
});
BACKGROUND-IMAGES
HTML:
<div class="background-placeholder"></div>
CSS:
.background-placeholder {
background-color:#fff;
width:250px;
height:250px;
}
.show-bg1 {
background-image:url('http://imagesource');
}
jQuery:
$('.background-placeholder').addClass('show-bg1');
CSS background-images are not loaded when a class isn't used (Same on hover etc.)
It's not the most efficient way to do this, but it could give you an idea on how its done.
Maybe you could store css-classes with the right background images also in data-attributes and loop through.
FIDDLE
The nested functions look a bit yucky, but here's a jQuery solution to your problem, using the method mentioned above.
$(document).ready(function(){ // wait until the document is loaded
$('#loadimages').click(function(){ // before registering the event handler
$('img[data-src]').each(function(){ // and for each image with a data-src attribute
$(this).attr('src', $(this).data('src')) // copy it's contents into the src attribute
})
})
})
img[data-src]{
width: 200px;
height: 400px;
background: grey;
position: relative;
}
img[data-src][src=""]::after {
content: 'Placeholder';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, 50%);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<img src="" data-src="http://lorempixel.com/200/400"/>
<img src="" data-src="http://lorempixel.com/200/400"/>
<img src="" data-src="http://lorempixel.com/200/400"/>
<button id="loadimages">Load Images</button>

SlidesJS for JavaScript Disabled User

I am pretty new to JavaScript.
I am using SlidesJS, which works perfectly fine.
However, when dealing with JavaScript disabled users, it is kind of tricky. For JavaScript disabled users, the images will be lined up. And I don't know how to deal with it because the images are embedded in the HTML code.
<div id="slides">
<img src="http://placehold.it/940x528">
<img src="http://placehold.it/940x528">
</div>
<script>
$(function(){
$("#slides").slidesjs({
......
</script>
Is there a way to use SlidesJS still, but for JavaScript disabled user, the webpage shows one default image, and hides all the other images?
Use CSS and Modernizr, which can add a class to the HTML element if and only if JavaScript is enabled.
#slides > img + img {
display: none; // may need to make this !important
}
.js #slides > img + img {
display: block;
}
(Note that modernizr.js should be run before any other JS on the page.)
If all you want is JavaScript detection, you don't even need Modernizr -- just one line of code and the above CSS:
document.getElementsByTagName("html")[0].className = "js";
or, to be non-destructive about it:
document.getElementsByTagName("html")[0].className
= document.getElementsByTagName("html")[0].className + " js";

Why does one of two identical Javascripts work in Firefox?

I have two image swap functions and one works in Firefox and the other does not. The swap functions are identical and both work fine in IE. Firefox does not even recognize the images as hyperlinks. I am very confused and I hope some one can shed some light on this for me. Thank you very much in advance for any and all help.
FYI: the working script swaps by onClick via DIV elements and the non-working script swaps onMouseOver/Out via "a" elements. Remember both of these work just fine in IE.
Joshua
Working Javascript in FF:
<script type="text/javascript">
var aryImages = new Array();
aryImages[1] = "/tires/images/mich_prim_mxv4_profile.jpg";
aryImages[2] = "/tires/images/mich_prim_mxv4_tread.jpg";
aryImages[3] = "/tires/images/mich_prim_mxv4_side.jpg";
for (i=0; i < aryImages.length; i++) {
var preload = new Image();
preload.src = aryImages[i];
}
function swap(imgIndex, imgTarget) {
document[imgTarget].src = aryImages[imgIndex];
}
<div id="image-container">
<div style="text-align: right">Click small images below to view larger.</div>
<div class="thumb-box" onclick="swap(1, 'imgColor')"><img src="/tires/images/thumbs/mich_prim_mxv4_profile_thumb.jpg" width="75" height="75" /></div>
<div class="thumb-box" onclick="swap(2, 'imgColor')"><img src="/tires/images/thumbs/mich_prim_mxv4_tread_thumb.jpg" width="75" height="75" /></div>
<div class="thumb-box" onclick="swap(3, 'imgColor')"><img src="/tires/images/thumbs/mich_prim_mxv4_side_thumb.jpg" width="75" height="75" /></div>
<div><img alt="" name="imgColor" src="/tires/images/mich_prim_mxv4_profile.jpg" /></div>
Not Working in FF:
<script type="text/javascript">
var aryImages = new Array();
aryImages[1] = "/images/home-on.jpg";
aryImages[2] = "/images/home-off.jpg";
aryImages[3] = "/images/services-on.jpg";
aryImages[4] = "/images/services-off.jpg";
aryImages[5] = "/images/contact_us-on.jpg";
aryImages[6] = "/images/contact_us-off.jpg";
aryImages[7] = "/images/about_us-on.jpg";
aryImages[8] = "/images/about_us-off.jpg";
aryImages[9] = "/images/career-on.jpg";
aryImages[10] = "/images/career-off.jpg";
for (i=0; i < aryImages.length; i++) {
var preload = new Image();
preload.src = aryImages[i];
}
function swap(imgIndex, imgTarget) {
document[imgTarget].src = aryImages[imgIndex];
}
<td>
<img name="home" src="/images/home-off.jpg" alt="Home Button" border="0px" />
</td>
Both your examples work for me, though they're pretty unappealing examples of ancient Netscape 3-era coding.
var aryImages = new Array();
aryImages[1] = "/tires/images/mich_prim_mxv4_profile.jpg";
Arrays are 0-indexed. Currently your loop will try to access aryImages[0] and get an undefined, which is will try (and fail) to preload. There is very rarely any use for the new Array constructor today. Instead use array literals:
var images= [
'/tires/images/mich_prim_mxv4_profile.jpg',
'/tires...
];
also:
document[imgTarget].src = aryImages[imgIndex];
We don't do that, or <img name> any more. In preference, give the image an id attribute and access it with document.getElementById().
Otherwise this causes all sorts of problems when image names clash with document properties and other named items on the page. Maybe you've got a name clash problem, something else called “home” in part of the document we can't see. Though if “does not even recognize the images as hyperlinks” means you aren't getting the pointer changing over the links or showing the link address, I suspect what you've actually got is a layout problem in code we can't see here, where you've accidentally positioned another element over the top of the nav so it can't be clicked on.
Anyway, it's poor for manageability, usability and accessibility to be loading images into an element like this. Use normal links to the images (so they work without JavaScript) and add progressive-enhancement JS on top, eg.:
<style type="text/css">
.thumb { display: block; }
.thumb img { width: 75px; height: 75px; border: none; vertical-align: top; }
</style>
<a class="thumb" href="/tires/images/mich_prim_mxv4_profile.jpg">
<img src="/tires/images/thumbs/mich_prim_mxv4_profile_thumb.jpg" alt="" />
</a>
<a class="thumb" href="/tires/images/mich_prim_mxv4_tread.jpg">
<img src="/tires/images/thumbs/mich_prim_mxv4_tread_thumb.jpg" alt="" />
</a>
<a class="thumb" href="/tires/images/mich_prim_mxv4_side.jpg">
<img src="/tires/images/thumbs/mich_prim_mxv4_side_thumb.jpg" alt="" />
</a>
<img id="thumbshow" src="/tires/images/mich_prim_mxv4_profile.jpg" alt="" />
<script type="text/javascript">
// Bind to links with thumb class
//
for (var i= document.links.length; i-->0;) {
if (document.links[i].className==='thumb') {
// Preload main image
//
var img= new Image();
img.src= document.links[i].href;
// When clicked, copy link address into image source
//
document.links[i].onclick= function() {
document.getElementById('thumbshow').src= this.href;
return false;
}
}
}
</script>
Similarly, most people do simple rollovers with CSS background images these days. If you use CSS Sprites, you don't even need two separate images, so no preloading or JavaScript of any kind is necessary.
Check Firebug for errors - the Console will tell you whether it's encountering any JS errors, and the Net panel will tell you whether any requests failed.
Why not put the events on the images instead of the links and see if that helps?
Like:
function swap(el, imgTarget) {
el.src = aryImages[imgIndex];
}
and
<img name="home" src="/images/home-off.jpg" alt="Home Button" border="0px" onMouseOver="swap(this, 'home')" onMouseOut="swap(this, 'home')" />
Just checked up on this. If you are using XHTML, it may not be the JavaScript that is corrupt, but your markup: XHTML needs tags and attributes to be specified in lowercase. I assume, that IE in its much-to-desire standards support perhaps partially ignores this, and evaluates your latter example as you think it should. But Firefox, which, you know, is much more standards compliant, may treat this as an improperly formatted attribute and ignores it.
Like:
<div onclick="swap(1, 'imgColor')"></div> <!-- Should work -->
<a onMouseOver="swap(1, 'home')"></a> <!-- May not work -->
Note, that this may not be the solution at all, just a possible issue.
Bobince made many very well thought out and proper suggestions to correct and enhance my code. For that I am very grateful. He suggested that because the links were not being recognized that I probably had an element that was covering over the menu. He was 100% correct. The header DIV below the menu had a height set to "auto" which caused it to cover from the top of the document down to the bottom of the header. This covered the menu and FF would not allow access to the links below it. I made a quick adjustment to the height and added a top margin for correct placement and now my menu is able to be accessed. I thought I was going crazy when I was not getting any JS errors in Firebug. The thought never crossed my mind to check for an overlapping element. Thanks a MILLION Bobince!!!
Thank you to all for your suggestions and help.

Display the alt attribute under image on iframe html

I have this basic website that has multiple images and I want to display the 'alt' attributes under each image via javascript. I have tried a few ideas and I made it work. But my problem now is that I want this basic website to be loaded by another, a parent website, via 'iframe'.
So I have this line of code into the parent website
<iframe id="iframeID" name="iframeName" src="...my basic website" scrolling="auto" frameborder=0 width="100%" height="700"></iframe>
and it loads the basic website with the images. The website with the images has this kind of code:
<div id="gallery">
<div class="image-container">
<img src="imageOne.jpg" alt="An image of an elephant">
</div>
<div>...</div>
</div>
In the parent website, under
<script></script>
I have this code:
var gallery = document.getElementById('gallery');
var imageContainers = gallery.getElementsByClassName('image-container');
// Loop through the image containers:
for (var i = 0; i < imageContainers.length; i++) {
var image = imageContainers[i].getElementsByTagName('img')[0];
var caption = document.createElement('span');
caption.innerHTML = image.alt;
window.frames[0].document.getElementById('gallery').getElementsByClassName('image-container')[i].appendChild(caption);
}
and nothing happens.
When I have the exact same code but with a different end line in the 'script' of the basic website where the images are
imageContainers[i].appendChild(caption);
or
document.getElementById('gallery').getElementsByClassName('image-container')[i].appendChild(caption);
but without the
window.frames[0]
and I load that website via 'iframe' or just open it via its link, all works. I just can't seem to make the 'alt' attributes or any text to display in the 'iframe' HTML from the parent website. I can change the style of the iframe HTML but cannot add text into a 'div' or 'span' or anything. And I do not understand why.
If you could help it would be great.
Thank you.
p.s: I need the basic website to be loaded by the parent website via 'iframe'; the javascript that displays the 'alt' attributes has to be in the parent website, not in the one that is being loaded
p.s.2: both websites are in the same domain and both are mine

Categories