Problem: The previously loaded images have to be changed dynamically when a new image is downloaded and detected by image.onload event. Say, picture1.png downloaded and immediately changed, picture2.png downloaded and immediately changed and so on. I have tried it as below, but it didn't work:
<script type="text/javascript">
loadImage = function(){
var imgs = new Array();
var IMG = document.getElementsByTagName('img');
for(var i=1;i<=IMG.length;i++)
{
imgs[i] = new Image();
imgs[i].src = "picture" + i + ".png";
imgs[i].onload = function(){
alert('picture'+i+' loaded');
IMG[i].setAttribute('src',imgs[i].getAttribute('src'));
}
}
}
</script>
<img src="sample.png" />
<img src="sample.png" />
<img src="sample.png" />
<img src="sample.png" />
<input type="button" value="Load Image" onclick="loadImage()">
How things will happen in the desired manner?
From this answer,
Well, the problem is that the variable i, within each of your
anonymous functions, is bound to the same variable outside of the
function.
What you want to do is bind the variable within each function to a
separate, unchanging value outside of the function:
So your code should look somewhat like this :
<script type="text/javascript">
var IMG = document.getElementsByTagName('img');
var imgs = new Array();
loadImage = function(){
for(var i=0;i<IMG.length;i++)
{
imgs[i] = new Image();
imgs[i].src = "http://dummyimage.com/150/000/fff&text=Image"+i;
imgs[i].onload = onloaded(i);
}
}
function onloaded(i) {
IMG[i].setAttribute('src',imgs[i].getAttribute('src'));
}
</script>
<img src="http://placehold.it/150" />
<img src="http://placehold.it/150" />
<img src="http://placehold.it/150" />
<img src="http://placehold.it/150" />
<input type="button" value="Load Image" onclick="loadImage()">
Note : array index of IMG starts with 0
If I understood your question correctly, you want to change the placeholder images as soon as the new images are completely loaded. By just passing the src attribute you rely on caching but the method below, although untested, should do the replacing in place. The i is kind of like a pointer which holds the growing value, so you can't use it as a reference in event callbacks.
function loadImage() {
var imgs = document.querySelectorAll("img");
for (var i = 0; i < imgs.length; i++) {
var newImg = new Image();
newImg.src = "picture" + i + ".png";
newImg.onload = function(img) { // Construct a callback for this <img>
return function() {
img.parentNode.replaceChild(newImg, img);
}
}(imgs[i]);
}
}
Edit: as said, I previously introduced another scoping issue in my code when fixing the original one. This is now fixed with a callback constructor function.
Because variables declared with the var keyword is function scoped and the onload function executes after the loop has finished variable i will not equal the value of i in that iteration when executing.
Replace your onload function with this code instead. It will create a new function scope.
imgs[i].onload = function(index) {
return function(index) {
alert('picture' + index + ' loaded');
IMG[index].setAttribute('src', imgs[index].getAttribute('src'));
}
}(i)
I would also change you're code to not loading the image twice.
function loadImage() {
var images = document.getElementsByTagName('img');
for (var i = 0; i <= images.length; i++) {
var newImg = new Image();
newImg.src = "http://dummyimage.com/150/000/fff&text=Image" + i;
newImg.onload = function(index, newImg) {
return function() {
var img = images[index];
img.parentNode.replaceChild(newImg, img);
}
}(i, newImg)
}
}
Related
I am trying to create functions to mouseover and mouseout of images. The tricky part is this function needs to work for any image, and I cannot use direct image names. I have to therefore use variables.
The HTML code is as follows for the images:
The HTML for the images is like this, and there are 3 images:
<img src="images/h1.jpg" alt="" id="images/h4.jpg" onmouseover="swapToNewImage(this)" onmouseout="swapImageBack(this)">
I'm expecting that you have to reference the id for the new image, and then the src attribute for the previous image to revert when you mouseout.
The problem is that, if I reference the id attribute, the image no longer has information on the src attribute so I cannot call it to revert back.
Here is the JavaScript I have thus far. It works to swap the image to a new one, but not to swap it back :(
//FUNCTION
var $ = function (id) {
return document.getElementById(id);
}
//ONLOAD EVENT HANDLER
window.onload = function () {
//GET ALL IMG TAGS
var ulTree = $("image_rollovers");
var imgElements = ulTree.getElementsByTagName("img");
//PROCESS EACH IMAGE
//1. GET IMG TAG
for (var i = 0; i < imgElements.length; i++) {
console.log (imgElements[i]);
console.log (imgElements[i].getAttribute("src"));
//2. PRELOAD IMAGE FROM IMG TAG
var image = new Image();
image.setAttribute("src", imgElements[i].getAttribute("src"));
//3. Mouseover and Mouseout Functions Called
image.addEventListener("mouseover", swapToNewImage);
image.addEventListener("mouseout", swapImageBack);
}
}
//MOUSE EVENT FUNCTIONS
var swapToNewImage = function(img) {
var secondImage = img.getAttribute("id", "src");
img.src = secondImage;
}
var swapImageBack = function(img) {
var previousImage = img.getAttribute("src");
img.src = previousImage;
}
Let me know if you can help me figure out how to call the image's src attribute so it can be reverted back. Again, I cannot reference specific image names, because that would be a lot easier (: Thank you!
Well, You can use a data attribute to store your src, and a data attribute to store the image you want to swap when mouseover.
Please try the following example.
var swapToNewImage = function(img) {
var secondImage = img.dataset.swapSrc
img.src = secondImage;
}
var swapImageBack = function(img) {
var previousImage = img.dataset.src
img.src = previousImage;
}
<img src="https://images.pexels.com/photos/259803/pexels-photo-259803.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" alt="" data-src="https://images.pexels.com/photos/259803/pexels-photo-259803.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" data-swap-src="https://images.pexels.com/photos/416160/pexels-photo-416160.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500" onmouseover="swapToNewImage(this)" onmouseout="swapImageBack(this)">
I also notice that the image tag is generated by code, in order to set the dataset values, we can do this:
var image = new Image();
image.scr = [src]
image.dataset.src = [src]
image.dataset.swapSrc = [swap src]
<!DOCTYPE html>
<html>
<head>
<meta charset="{CHARSET}">
<title>imagegame</title>
<style>
body { margin: 20px; }
img { margin: 20px; }
</style>
</head>
<body>
<img id="pic1" src="img/charpter9/zeroblur.jpg">
<img id="pic2" src="img/charpter9/oneblur.jpg">
<img id="pic3" src="img/charpter9/twoblur.jpg">
<img id="pic4" src="img/charpter9/threeblur.jpg">
<img id="pic5" src="img/charpter9/fourblur.jpg">
<img id="pic6" src="img/charpter9/fiveblur.jpg">
<script>
function init() {
var imgs = document.getElementsByTagName("img");
for(var i = 0; i < imgs.length; i++){
imgs[i].onclick = onClick;
}
}
function onClick(e){
var img = e.target;
var imgsrc = img.src;
var imgid = img.id;
var imgsrc0 = imgsrc;
imgsrc = imgsrc.replace("blur","");
img.src = imgsrc;
setTimeout(refresh, 5000, imgsrc0, imgid);
}
function refresh(imgsrc,id){
var img = document.getElementById(id);
img.setAttribute("src",imgsrc);
}
window.onload = init;
</script>
</body>
</html>
above is the code, my main consideration is whether there is a plan to solve mouse double-click when clicking on one element whose trigger is onclick.
the error I found is when I double-click the image showed on the page, the pic can't be reblurrd automatically. the case is head-first javascript book chapter 9 on about page 142.
thank for your time.
enter image description here
The main issue is, that the second time the src has no blur anymore already and the time the second timeout is finished it gets set to that src instead of the one with the blur.
You could keep the original source in a data-attribute and set the src back on that attribute. Furthermore you can cancel the setTimeout() on doubleclicks.
function onClick(e){
var img = e.target;
var imgsrc = img.src;
var imgid = img.id;
var imgsrc0 = imgsrc;
//REM: Keep the original src
if(!img.getAttribute('data-img-src')){
img.setAttribute('data-img-src', imgsrc)
};
imgsrc = imgsrc.replace("blur","");
img.src = imgsrc;
//REM: Clear and reassign the timeout
clearTimeout(img.timeout); //REM: Dirty way, but fast to show
img.timeout = setTimeout(refresh, 5000, imgsrc0, imgid)
}
function refresh(imgsrc,id){
var img = document.getElementById(id);
//REM: Set the original src
img.setAttribute("src",img.getAttribute('data-img-src'));
img.removeAttribute('data-img-src')
}
Yet I think it would be much easier to keep all the images in an object and create the img on the fly. Also it makes your code unbound from a fixed naming scheme in your image sources. Like this for example:
var _Images = [
{Blurred: 'https://image.flaticon.com/icons/svg/172/172838.svg', Active: 'https://image.flaticon.com/icons/svg/196/196138.svg'},
{Blurred: 'https://image.flaticon.com/icons/svg/196/196138.svg', Active: 'https://image.flaticon.com/icons/svg/172/172838.svg'},
{Blurred: 'https://image.flaticon.com/icons/svg/172/172838.svg', Active: 'https://image.flaticon.com/icons/svg/196/196138.svg'}
];
window.onload = function(){
for(var i=0, j=_Images.length; i<j; i++){
var tImage = document.body.appendChild(document.createElement('img'));
tImage.src = _Images[i].Blurred;
tImage.setAttribute('width', '20px');
tImage.onclick = function(image){
this.src = image.Active;
window.clearTimeout(image.Timeout);
image.Timeout = window.setTimeout(function(){
this.src = image.Blurred
}.bind(this, image), 5000)
}.bind(tImage, _Images[i])
}
};
I have a problem with my self made image slider, i get the error: Uncaught TypeError: Cannot set property 'src' of null
Edit: I have called all images like this: img1, img2, img3 etc with extension .jpg
this is my javascript code:
// JavaScript Document
var imagecount = 1;
var total = 3;
window.setInterval(function slideA(x)
{
var Image = document.getElementById('img');
imagecount = imagecount + x;
if(imagecount > total) { imagecount = 1; }
if(imagecount < 1) { imagecount = total; }
Image.src = "images_slider/img" + imagecount + ".jpeg";
}, 5000);
function init()
{
slideA();
}
window.onload = init;
<div id="LandingImage">
<img src="../images/landingimage.png" alt="LandingImage" width="100%" height="100%" />
</div>
Can someone help me with this?
Thanks!
Kevin.
Your html element does not have an id of img, you appear to be trying to select the tag name.
I also suggest not using Image as the variable name, since Image is an object name in JavaScript.
<img src="../images/landingimage.png" alt="LandingImage" width="100%" height="100%" id="img" /> <!-- id at the end, was missing -->
It appears that you are trying to iterate through a list of images by changing the source of an image. If so, refer to the following JS fiddle for an example:
https://jsfiddle.net/hqq1k2Lk/3/
I made a few changes, so let's go through it together.
// JavaScript Document
var imagecount = 1;
var total = 3;
function slideA()
{
//slideA starts the interval
window.setInterval(function(){
var myImage = document.getElementById('LandingImage');
imagecount++;
if(imagecount > total) { imagecount = 1; }
if(imagecount < 1) { imagecount = total; }
myImage.src = "images_slider/img" + imagecount + ".jpeg";
}, 5000);
}
function init()
{
slideA();
}
window.onload = init();
First, I moved your function call slideA outside the interval. Thus calling slideA(); will start the interval.
Next, I moved your ID LandingImage to the img element itself, so we can get the image from the DOM using document.getElementById('LandingImage');
Since you need to keep track of what image you're on, I elected to use imagecount as your counter. You can increment a number by 1 by using ++ such as imagecount++;
As others have pointed out Image is a protected object name in Javascript, so I renamed your variable to myImage
Lastly, in order to start the whole process, I added a function call to your window onload event. Whenever you want to call a function, remember to use ()
window.onload = init();
As another poster mentioned, do not use Image as your variable name.
To access the src attribute of the element, you use element.setAttribute('src', 'insert src here') not element.src.
<div id="3" class="dsi" onmousedown="test(3);" ondrop="checkImg('3');dropIt(event,3);" ondragover="event.preventDefault();">
<img src="1.gif" draggable="true" ondragstart="dragIt(event,4);" id="pic4" />
I want to change src value using javascript. There are nine dives and they already have 1 to 9 gif images. How can I add new src values leaving the rest of the things unchanged? (I mean draggable="true" ondragstart="dragIt(event,4);" id="pic4")
function ft1() {
var imgSrcs = ['2.gif', '1.gif', '3.gif', '4.gif', '5.gif', '6.gif', '7.gif', '8.gif'];
var myImages = [];
for (var i = 0 ;i <=((imgSrcs.length)-1);i++) {
var v = i;
var img = new Image();
img.src = imgSrcs[i];
var div0 = document.getElementById(v+1);
div0.appendChild(img);
myImages[v+1] = img;
}
Using this I can replace div images. But how can I remove first assigned src value and then replace new images?
As stated here, simply do:
document.getElementById("pic4").src="...";
Try this.
$('.img').attr('src','http://source');
I'am using the following javascript code to implement image-loaded-show function in mobile web browser (supporting HTML5). Image-loaded-show means that before the image is completely loaded, the width and height is 0, namely it willn't show and occupy any space.
Now the problem is that the images will not show until all the images are loaded.
What I need is that the iamge in the page is seperate, once loaded, the image show up.
Any tips on how to modify this javascript code? thanks.
<script type='text/javascript'>
var srcs = [];
window.doBindLinks = function() {
var elems = document.getElementsByTagName('img');
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
var link = elem.getAttribute('src');
elem.setAttribute('link', link);
elem.removeAttribute('width');
elem.removeAttribute('height');
elem.removeAttribute('class');
elem.removeAttribute('style');
if(link.indexOf('.gif')>0)
{
elem.parentNode.removeChild(elem);
}else{
}
}
var content = document.getElementById('content');
var images = content.getElementsByTagName('img');
for (var i = 0; i < images.length; i++) {
srcs[i] = images[i].src;
loadImage(images[i], srcs[i],
function (cur, img, cached) {
cur.src = img.src;},
function (cur, img) {
cur.style.display = 'none';});
}
};
var loadImage = function (cur, url, callback, onerror) {
var img = new Image();
img.src = url;
img.width = '100%';
if (img.complete) {
callback && callback(cur, img, true);
return;
}
img.onload = function () {
callback && callback(cur, img, true);
return;
};
if (typeof onerror == 'function') {
img.onerror = function () {
onerror && onerror(cur, img);
}
}
};
</script>
The source code of the page is :
<body onload="doBindLinks();"><div id="content"> images and text </div></body>
P.S: Because I need to write this javascript string in C#, I replace the (") into (').
Edited:
Is the following right:
window.doBindLinks = function() {
var elems = document.getElementsByTagName('img');
for (var i = 0; i < elems.length; i++) {
var elem = elems[i];
var link = elem.getAttribute('src');
elem.setAttribute('link', link);
elem.removeAttribute('width');
elem.removeAttribute('height');
elem.removeAttribute('class');
elem.removeAttribute('style');
elem.setAttribute('display','none');
if(link.indexOf('.gif')>0)
{
elem.parentNode.removeChild(elem);
}else{
}
elem.attachEvent('onload',onImageLoaded);
}
};
window.onImageLoaded = function() {
var elem = event.srcElement;
if ( elem != null ) {
elem.setAttribute('display','block');
}
return false;
};
Besides, the css code is:
img {width: 100%; border-style:none;text-align:center;}
But the images still wouldn't show until all are loaded.
I'm not 100% sure I understand your question. Are you trying to hide the image until it is fully loaded? Are you writing the images out to the page, or are they already in the page? Here are a couple of options:
set style="display:none". Then add onload="this.style.display='';" event listener to image.
images will each show as they are loaded.
if you are able to change the c# code, then simply write all the image urls out as a list of strings into an imageload function. Then use this function to create the images and add them to the content div.
I hope this helps you. If not, please provide more context, and I will try to help farther.
Ok, I see where you are going now. You can take out all that javascript that you have written. Maybe print it out so that you can throw it in the trash. Then take my example here... and it will do the trick for you. each image shown only as it is loaded. Obviously if you want to change any other properties you can do it in the showImage function. hope this helps.
<html>
<head>
<style>
img{display:none;}
</style>
<script type="text/javascript">
function showImage(elem) {
elem.style.display = 'block';
}
</script>
</head>
<body><div id="content">
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
<img src="http://t0.gstatic.com/images?q=tbn:ANd9GcTlpi72nRCVE5cOz3AImtbb7GEbEYRVLkLJxAZsT5Z4XKicteDo" onload="showImage(this)" />
</dvi>
</body>
</html>