Replacing an old image with a new one. JavaScript - javascript

I have a function that places an image provided by the input of the user into the body of an html page. When a second input is received I want to replace this picture with the new one. I have attempted to do just this in the below function.
function show_image(src, alt) {
var img = document.createElement("img");
img.src = src;
img.width = 400;
img.height = 300;
img.alt = alt;
var counter;
var mynodes= new Array();
mynodes.push(img);
counter+=1;
if(counter==1){
// This next line will just add it to the <body> tag
document.body.appendChild(img);
}
else if(counter!=1)
{
var newNode=mynodes[counter-1];
var oldNode=mynodes[counter-2];
document.body.replaceChild(newNode,oldNode);
}

The variable counter is a local variable.
Each time the method is called counter is initialized to 0.
Same thing with your mynodesvariable. It is always going to have only one node in the array.
So you may want to change your logic here. Do you want help rewriting this function?

Your code is totally awkward. As far as I can tell, you could simply change the same img tag instead of changing the whole node each time. There's barely a reason for a function..
Click here for a live demo.
function changeImg(img, src, alt) {
//I doubt you even need a function for this.
img.src = src;
img.alt = alt;
}
var img = document.createElement('img');
//you could just use a css class instead...
//that's probably better anyway...why does your js care how it looks?
img.width = 400;
img.height = 300;
document.body.appendChild(img);
changeImg(img, 'http://static.jsbin.com/images/favicon.png', 'image');
var imgSrcInput = document.getElementById('imgSrc');
var imgAltInput = document.getElementById('imgAlt');
var button = document.getElementById('change');
button.addEventListener('click', function() {
changeImg(img, imgSrcInput.value, imgAltInput.value);
});
I put together an object oriented example. This makes your logic very reusable and friendly. Check out the code in action here (click).
window.onload = function() { //usage
var someElement = document.getElementById('someIdHere');
var anotherElement = document.getElementById('anotherIdHere');
imageReplacer.setup({
element: someElement,
initSrc: 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRg-icdkibfDt8VE7FkaKZyVUh8SBR4YTGd-2Jz1wZeUVacv4YD8zrvwclN',
initAlt: 'Starting Image'
});
imageReplacer.setup({
element: anotherIdHere,
initSrc: 'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRrHWuOzgYPbsuSF9cYQo3ORkcdIC4-8xaszlCrI3f7arAC7vhV7HwMN_fG',
initAlt: 'Starting Image'
});
};
var imageReplacer = { //package up your app
setup : function(options) {
//create a new imageReplacer so that each one will operate independently. The "this" pointer will refer to each element's imageReplacer.
options.element.imageReplacer = Object.create(imageReplacer);
options.element.imageReplacer.makeReplacer(options);
},
makeReplacer : function(options) {
options.element.className = 'imageReplacer';
var markup = this.createMarkup();
this.changeImage(options.initSrc, options.initAlt);
this.addClick(this.button);
options.element.appendChild(markup);
},
createMarkup : function() {
var frag = document.createDocumentFragment();
this.srcInput = document.createElement('input');
this.srcInput.type = 'text';
this.srcInput.placeholder = 'Image Source';
this.altInput = document.createElement('input');
this.altInput.type = 'text';
this.altInput.placeholder = 'Image Alt';
this.button = document.createElement('button');
this.button.textContent = 'Change Image';
this.imgTag = document.createElement('img');
frag.appendChild(this.srcInput);
frag.appendChild(this.altInput);
frag.appendChild(this.button);
frag.appendChild(this.imgTag);
return frag;
},
addClick : function(button) {
var that = this;
button.addEventListener('click', function() {
that.changeImage(that.srcInput, that.altInput);
});
},
changeImage : function(src, alt) {
this.imgTag.src = src;
this.imgTag.alt = alt;
}
};

Instead of creating a function to dynamically change the picture(which did work), I decided to hide one picture on my index.html file. And then changed the src with $("#my_image").attr("src","img/fire.gif"); #my_image being the id of the image tag.

Related

Trying to add attribute "onclick" to a html "img" element created by javascript function

This is part of a function that is creating a table with images and the name of the image inserted by the user.
var NameFile = [];//Where the names of the files are stored
Function handleFiles() {
var inputElement = document.getElementById("input");
var fileList = inputElement.files;
for(var i = 0; i < fileList.length; i++){
NameFile.push(fileList[i].name);
var Img = document.createElement("tr");
Img.setAttribute("id", "ImgTr" +(i));
document.getElementById("galeria" +(i)).appendChild(Img);
/.../
var Img = document.createElement("tr");
Img.setAttribute("id", "ImgTr" +(i));
document.getElementById("galeria" +(i)).appendChild(Img);
var Imgz = document.createElement("td");
var image =document.createElement("img");
image.setAttribute("id", "imageID" +(i));
image.setAttribute("className", "bordered");
image.setAttribute("src","http://placehold.it/200/200/pink/black");
image.setAttribute("onclick","imgClick(this)");
image.src = window.URL.createObjectURL(fileList[i]);
image.height = 50;
image.with = 50;
image.onload = function(){
window.URL.revokeObjectURL(this.src);
}
Now this is the function i want to call if the image is clicked on. This function is supposed to show a border around the image clicked by the user.
function imgClick(img) {
if (img.className.indexOf('bordered') > -1) {
img.className = img.className.replace('bordered', '').trim();
} else {
img.className += ' bordered';
}
It compares the img clicked id atributte with the others images ids, and when it equals it shows the name of the file stored in the array
NameFile
for( var i=0; i<NameFile.length;i++){
if("imageID"+[i]===img.getAttribute("id")){
alert(NameFile[i]);
}
}
}
The problem mostly lies with this line:
var imgTag=document.getElementsByTagName('img');
as document.getElementsByTagName('img'); returns a HTMLCollection and not a single element. So when you try setting the style prop, you are doing it on the HTMLCollection and not the actual node
Try this instead:
function imgClick(img){
img.style.border = '5px solid pink';
}
var img = document.createElement('img');
img.setAttribute('src','http://placehold.it/200/200/pink/black');
img.setAttribute('onclick','imgClick(this)');
document.body.append(img);
EDIT:
If you want the second click to remove the border, there are several ways to do it. One way would be to add a class to the element when it is clicked once. We can then check for the class each time it is clicked to decide whether to add the border or remove it.
Sample:
function imgClick(img) {
if (img.className.indexOf('bordered') > -1) {
// Already has border
img.style.border = 'none';
img.className = img.className.replace('bordered', '').trim();
} else {
// Does not have border
img.style.border = '5px solid pink';
img.className += ' bordered';
}
}
var img = document.createElement('img');
img.setAttribute('src', 'http://placehold.it/200/200/pink/black');
img.setAttribute('onclick', 'imgClick(this)');
document.body.append(img);
Note: If the styling of the border does not change, you can move the styling out to a CSS style and just toggle the class on the image like this:
function imgClick(img) {
if (img.className.indexOf('bordered') > -1) {
img.className = img.className.replace('bordered', '').trim();
} else {
img.className += ' bordered';
}
}
var img = document.createElement('img');
img.setAttribute('src', 'http://placehold.it/200/200/pink/black');
img.setAttribute('onclick', 'imgClick(this)');
document.body.append(img);
img.bordered{
border: 3px solid pink;
}
EDIT 2:
You can retrieve the file name as you set it and update your array
// Initialize empty array
var myImages = [];
function imgClick(img) {
// Add image file name to array after getting it from data attribute
myImages.push(img.dataset.name);
console.log(myImages);
}
function appendImage() {
var img = document.createElement('img');
var file = document.getElementById('file_in').files[0];
var url = window.URL.createObjectURL(file);
img.setAttribute('src', url);
img.setAttribute('onclick', 'imgClick(this)');
// Set the file name as a data attribute for later use
img.dataset.name = file.name;
document.body.append(img);
}
img.bordered {
border: 3px solid pink;
}
<input type=file id="file_in" />
<button onclick="appendImage()">Upload</button>
Instead of adding an "onclick" attribute, I strongly advise you add an event listener to your img element.
image.addEventListener("click", imgClick);
There is also an issue in your imgClick function : you don't need to look for your img element in there. You can instead add an event variable to your function declaration. That way you can retrieve the events target and do whatever you want with it :
function imgClick(event) {
event.target.style.border='2px solid #33cc33';
}
You can access to clicked item using event.target, like so:
function imgClick(e) {
e.target.style.border = '2px solid #33cc33';
}
And bind event like below (as you did in your code):
image.onclick = imgClick;
Or using addEventListener:
image.addEventListener("click", imgClick, false);
Notice that var imgTag = document.getElementsByTagName('img') returns array (like) of found item(s)/node(s), so imgTag.style... won't work.
If you want to set onclick, then you need to set the property directly
image.onclick = imgClick;
Better solution would be to add event listener instead
image.addEventListener( "click", imgClick );
And you imgClick method becomes
function imgClick(e){
var imgTag = e.currentTarget;
imgTag.onload = function()
{
window.URL.revokeObjectURL( imgTag.src );
imgTag.hasImageLoaded = true;
}
if ( imgTag.hasImageLoaded )
{
imgTag.style.border = '2px solid #33cc33';
}
}
or
function imgClick(e){
var imgTag = e.currentTarget;
imgTag.addEventListener("load", function()
{
window.URL.revokeObjectURL( imgTag.src );
imgTag.hasImageLoaded = true;
});
if ( imgTag.hasImageLoaded )
{
imgTag.style.border = '2px solid #33cc33';
}
}
setting onclick as attribute will not set the event on image you have assign onclick to image
image.onclick = imgclick
Also you can create the image with the HTMLInstance:
<div id="gallery"></div>
<script>
function createImg(src, height, weight, onclick) {
const img = new Image(height, weight)
img.src = src
img.onclick = onclick
return img
}
function addNewImage(image) {
gallery.appendChild(image)
}
function handleClick () {
alert('Image catch click event!')
}
const src = 'https://loremflickr.com/320/240'
const img1 = createImg(src, 100, 100, handleClick)
addNewImage(img1)
</script>

Third nested blank iframe is invisible

I ran into a very surprising behaviour and I can't figure out what it comes from : I build 3 nested blank iframes in javascript but the third one is invisible.
Tested in Chrome. Here is the code : (https://jsfiddle.net/44uL3bku/)
(function() {
var i1 = document.createElement('iframe');
i1.width = 315;
i1.height = 300;
i1.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 1<br>';
var i2 = this.contentDocument.createElement('iframe');
i2.width = '100%';
i2.height = '100%';
i2.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 2<br>';
var i3 = this.contentDocument.createElement('iframe');
i3.width = '100%';
i3.height = '100%';
i3.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 3<br>';
});
this.contentDocument.body.appendChild(i3);
var i4 = this.contentDocument.createElement('iframe');
i4.width = '100%';
i4.height = '100%';
i4.addEventListener('load', function() {
this.contentDocument.body.innerHTML = 'IFRAME 3<br>';
});
this.contentDocument.body.appendChild(i4);
var bottom = document.createElement('div');
bottom.innerHTML = 'bottom';
this.contentDocument.body.appendChild(bottom);
});
this.contentDocument.body.appendChild(i2);
});
document.body.appendChild(i1);
})();
Just to be clear : the DOM tree is properly set, and the "IFRAME 3" is actually there. But it is just not displayed.
Also it only concerns blank iframes. As soon as there is a regular src everything works fine again.
Any idea ?
Thank you all !

Adding a counter to a prev/next image slideshow(javascript/css only)?

I have created a "prev/next" slideshow using javascript, now I want to add a counter(1/10, 2/10, 3/10...) beside my "prev/next" buttons but nothing seemed to work.
This is my first time attempting to make a website, I know nothing about jQuery, so please stick with html+javascript if possible. Here is my script
var image = new Array(
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg")
var imgNumber=1
var numberOfImg=2
function previousImage(){
if(imgNumber>1){
imgNumber--
}
else{
imgNumber = numberOfImg
}
document.slideImage.src = image[imgNumber-1]
}
function nextImage(){
if(imgNumber < numberOfImg){
imgNumber++
}
else{
imgNumber = 1
}
document.slideImage.src = image[imgNumber-1]
}
if(document.images){
var image1 = new Image()
image1.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg"
var image2 = new Image()
image2.src = "http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg"
}
Script+html: http://jsfiddle.net/nLHY9/5/
(Prev/Next buttons seem not to be working on this----they work fine when I launched them from laptop to browser.)
you could have used some existing javascript image sliders, for example, sliderman slider, for your current code, you can do like, add an element like span, to hold the count, and you could add a function like:
function changeCounter(cur, total) {
document.getElementById("counter").innerHTML = cur + "/" + total;
}
and call it in your previousImage() and nextImage() functions, as in this demo jsfiddle
There are many pure css slideshows that are beautiful and can do impressive things. However, as you try to support older browsers, the pure css slideshows get less and less impressive or even impossible. JavaScript is the most flexible and powerful way to go. That being, I wanted to help you clean up your code. I only had a few minutes, so this is a quickly thrown together plugin, but it should get you on the right track.
First, a few notes on your code:
//you're missing semicolons everywhere. ";"
/* "var image" is very unclear.
* it's an array, so it should be plural "images"
* there aren't images in this array - it's image urls or sources
* instead of "new Array" you could just use "[]"
*/
var image = new Array(
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg")
var imgNumber=1 //the name doesn't mean anything. I have to assume that you mean "currentImgNumber" or something to that effect
var numberOfImg=2 //this could be determined by checking the length of your array - myArray.length
And here's my exampe plugin:
Live demo here (click).
/***** This section is how you use the plugin. I start writing with the usage and then I make it mean something *****/
window.onload = function() { //when the page is loaded
var fooElem = document.getElementById('foo'); //get an element where we will attach the plugin
var foo = Object.create(slideshow); //create a new slideshow object
foo.create({ //create a slideshow with the given options
element: fooElem, //the element where the slideshow will be
sources: [ //image urls
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/_MG_7747.jpg",
"http://i990.photobucket.com/albums/af24/callmeaaaaj/AJ/1109163s.jpg"
]
});
//we can make more of these and with different options
var barElem = document.getElementById('bar');
var bar = Object.create(slideshow);
bar.create({
element: barElem,
sources: [
"http://eggboss.com/wp-content/uploads/2013/09/The-Gentleman-233x300.png",
"http://fc07.deviantart.net/fs71/f/2013/040/8/a/profile_picture_by_classy_like_a_sir-d5uf426.jpg"
]
});
};
/**** now let's create the plugin and make it work as it is used above *****/
var slideshow = {
currentIndex: 0,
imgs: [],
create: function(options) {
options.element.className+= ' slideshow'; //add a class to the main element for styling
this.imgs = this.getImgs(options.sources); //make img html
var controls = this.getControls(); //make controls
//add the html to the element from the options
var frag = document.createDocumentFragment();
this.imgs.forEach(function(img) {
frag.appendChild(img);
});
frag.appendChild(controls);
options.element.appendChild(frag);
},
getImgs: function(sources) {
var imgs = [];
sources.forEach(function(src, i) {
var img = document.createElement('img');
img.src = src;
imgs.push(img);
if (i > 0) {
img.style.display = 'none'; //hide all but first image
}
});
return imgs;
},
getControls: function() {
var that = this; //so that we can access "this" within the click functions
var controls = document.createElement('div');
controls.className = 'controls';
var counter = document.createElement('span');
counter.className = 'counter';
this.setCounter(counter);
var prev = document.createElement('a');
prev.textContent = 'Prev';
prev.className = 'prev';
prev.addEventListener('click', function() {
newIndex = (that.currentIndex) ? that.currentIndex-1 : that.imgs.length-1;
that.changeImg(newIndex, counter);
});
var next = document.createElement('a');
next.textContent = 'Next';
next.className = 'next';
next.addEventListener('click', function() {
newIndex = (that.currentIndex !== that.imgs.length-1) ? that.currentIndex+1 : 0;
that.changeImg(newIndex, counter);
});
controls.appendChild(prev);
controls.appendChild(next);
controls.appendChild(counter);
return controls;
},
changeImg: function(newIndex, counter) {
this.imgs[this.currentIndex].style.display = 'none';
this.imgs[newIndex].style.display = 'inline';
this.currentIndex = newIndex;
this.setCounter(counter);
},
setCounter: function(counter) {
counter.textContent = (this.currentIndex+1)+' / '+this.imgs.length;
}
};

how to assign images using javascript to div

function ft1(){
var imgSrcs = ['1.gif','2.gif','3.gif','4.gif','5.gif','6.gif','7.gif','8.gif'];
var myImages = [], img;
for (var i = 1; i <=8; i++) {
img = new Image();
img.onload = function() {
var div0 = document.getElementById(i);
div0.style.backgroundImage = "url(" + this.src + ")";
};
img.src = imgSrcs[i];
myImages[i] = img;
}
}
<input name="Button1" type="button" value="button" onclick="ft1();" />
my div ids are 1 to 8. i want to add images for that dives using javascript.but this code didn't work properly. if u know where is the error plz tel me.
I made some changes in your code:
function ft1() {
var imgSrcs = ['1.gif', '2.gif', '3.gif', '4.gif', '5.gif', '6.gif', '7.gif', '8.gif'];
var myImages = [];
for (var i = 1; i <= imgSrcs.length; i++) {
var img = new Image();
img.src = imgSrcs[i];
var div0 = document.getElementById(i);
//I am not sure what you are trying to do in the below line.
//div0.style.backgroundImage = "url(" + this.src + ")";
div0.appendChild(img);
myImages[i] = img;
}
}
AFAIK, img.onload will not work because img variable is not part of DOM. First you need to make it part of DOM using appendChild method as shown above.
I have one question, what does this.src referring to?
try using this code in the loop
var elem = document.createElement("img");
elem.src = this.src;
elem.setAttribute("height", "250");
elem.setAttribute("width", "1024");
elem.setAttribute("alt", "alt text");
document.getElementById("placehere").appendChild(elem);
good luck!
I think You should use imgSrcs[i] instead of this.src
<script type="text/javascript">
var myImages = new Array("usa.gif","canada.gif","jamaica.gif","mexico.gif");// list of images
function changeImg(that) // function call on_click of image below
{
var newImgNumber = Math.round(Math.random()*3); // create math to random the images
while (that.src.indexOf(myImages[newImgNumber]) != -1) // make sure that the randomization corresponds to the list of images
{
newImgNumber = Math.round(Math.random()*3) // sets the math to the new image
}
that.src = myImages[newImgNumber]; // change the image
return false; // makes it able to be done again
}
</script>
If you are trying to add images to all the divs, I would try simplifying it to:
function ft1(){
var imgSrcs = ['1.gif','2.gif','3.gif','4.gif','5.gif','6.gif','7.gif','8.gif'];
for (i = 1; i <=8; i++) {
var div = document.getElementById(i);
div.style.backgroundImage = "url(" + imgSrcs[i] + ")";//make sure images are in the right folder
}
}
<input name="Button1" type="button" value="button" onclick="ft1()" /> //remove semicolon
Here is a link to a jsfiddle with color instead of images http://jsfiddle.net/CKFrantz/gLfXA/
The problem with the loop is probably that the loop-counter will be the same in all of the callbacks. (Mind that the closures just share the same scope, so the value will be 8 for all of them after the loop is exited.)
This can be overcome by a factory function (passing a simple value as argument will result in it being copied):
function loadImageToElement(id, imgscr) {
var img = new Image();
img.onload = function() {
var el = document.getElementById(id);
el.style.backgroundImage = "url(" + this.src + ")";
// we could use just the same:
// el.style.backgroundImage = "url(" + imgscr + ")";
};
img.src = imgscr;
return img;
}
function ft1(){
var imgSrcs = ['1.gif','2.gif','3.gif','4.gif','5.gif','6.gif','7.gif','8.gif'];
var myImages = [];
for (var i = 0; i < 8; i++) {
myImages[i] = loadImageToElement('div' + (i+1), imgSrcs[i]);
}
}
<input name="Button1" type="button" value="button" onclick="ft1();" />
Edit: you may want to check for img.complete:
function loadImageToElement(id, imgscr) {
var img = new Image();
var f = function() {
var el = document.getElementById(id);
el.style.backgroundImage = "url(" + imgsrc + ")";
}
img.src = imgscr;
if (img.complete) {
f();
}
else {
img.onload = f;
}
return img;
}
(Note: Image.complete is true, if the image is already cached. In this case the onload-event wont fire in some browsers.)

referencing function inside a for loop in js

I have the following code:
function fn_get_natural_dim(){
var width = this.width;
var height = this.height;
var ratiow = width/600;
var ratioh = height/300;
$("#output").append(img_name,",");
if(ratiow>=ratioh)
{
height = height/ratiow;
$(slide_image).css("width","600px");
$(slide_image).css("height",height);
var margin = (300-height)/2;
$(slide_image).css("margin-top",margin);
}
else
{
width = width/ratioh;
$(slide_image).css("width",width);
$(slide_image).css("height","300px");
var margin = (600-width)/2;
$(slide_image).css("margin-left",margin);
}
}
var max_count = $(".slider").children().length;
for(var count=1;count<=max_count;count++)
{
var count_string = count.toString();
var img_name = "img" + count_string;
var slide_image = document.getElementById(img_name);
var img = new Image();
img.onload = fn_get_natural_dim;
img.src = $(slide_image).attr("src");
}
});
For each image (i have three at the moment), im getting its natural dimensions so that i can calculate the margin necessary to fit a 600x300 div.
but i only works for the very last one, ie the third one.
in other words, in the #output, it shows "img3,img3,img3," (called by $("#output").append(img_name,",");)
how do i make it show "img1,img2,img3,"??
You can do this:
img.onload = (function(img_name, slide_image) {
return function() {fn_get_natural_dim(img_name, slide_image); };
})(img_name, slide_image);
and change fn_get_natural_dim to take the image name as a parameter:
function fn_get_natural_dim(img_name, slide_image) {
The above code captures each successive value of img_name in a closure variable.
Edit
As Barmar pointed out, this solution isn't exactly correct. I'll leave it up as it's a fairly common mistake and is important to note the difference between his solution and my own.
Pass img_name into your fn_get_natural_dim function:
function fn_get_natural_dim( img_name ) { ... }
Then call it like:
img.onload = function() { fn_get_natural_dim(img_name); };

Categories