Could not bind event to each item in array loop - javascript

I want to add an event to every image in the document, this is the code:
let images = document.getElementsByTagName("img")
const self = this;
for (var img of images) {
img.onclick = function(e) {
e.stopPropagation();
if (!e.target.src) {
return;
}
self.source = e.target.src;
self.alt = e.target.alt;
}
}
I log all of the images and find that only the last image has the click event. I had tried converting images into an array and used forEach methods, which got the same result. What's up?
By the way, I do that in Vue's mounted hook method.

Best way to attach events to multiple DOM elements is to use Event Delegation. You should attach the event to the parent element and check if the target element is img or not. Then you can access the src and alt attributes of the image.
var images = document.querySelector('.images');
images.onclick = function(e) {
if(e.target.tagName === 'IMG') {
console.log(e.target.src +" : " + e.target.alt);
}
}
<div class="images">
<img alt="1" src="https://randomuser.me/api/portraits/men/83.jpg" />
<img alt="2" src="https://randomuser.me/api/portraits/med/men/83.jpg" />
<img alt="3" src="https://randomuser.me/api/portraits/thumb/men/83.jpg" />
</div>

Related

Saving the original image before mouseover

I am trying to realize JavaScript that would change image on mouseover and revert it back, when mouseout. I have this code for that:
var list = document.querySelectorAll('span[data-oe-id] img');
var i;
var imgsrc=[];
for(i=0;i<3;i++)
{
imgsrc[i] = list[i].src;
console.log(imgsrc[i]);
list[i].addEventListener("mouseover",function(event){event.target.src="https://media1.giphy.com/media/PfFtibPKBbQrK/giphy.gif?cid=ecf05e47b668e5062e9a561e681f23705e106d8d495b3915&rid=giphy.gif";},false);
list[i].addEventListener("mouseout",function(event){event.target.src=imgsrc[i];},false);
}
It is changing image on mouseover perfectly fine, but on mouseout, image is changed to undefined. For example:
<img src="undefined" class="img img-fluid" alt="A4Tech Bloody V8M">
Is result after mouseout
Src attribute cannot be set using event argument. you can use this keywords to access same selected element.
View Output in full screen
var list = document.querySelectorAll('img');
var i;
var imgsrc=[];
for(i=0;i<3;i++)
{
imgsrc[i] = list[i].src;
list[i].addEventListener("mouseover",function()
{
this.src="https://media1.giphy.com/media/PfFtibPKBbQrK/giphy.gif?cid=ecf05e47b668e5062e9a561e681f23705e106d8d495b3915&rid=giphy.gif";
});
list[i].addEventListener("mouseout",function()
{
this.src=imgsrc[i];
});
}
<img id="1" src="1" alt="img1"/>
<img id="2" src="2" alt="img2"/>
<img id="3" src="3" alt="img3"/>

Implementing mouseover/mouseout for many images in an external JavaScript file

I'm trying to enable onMouseOver and onMouseOut for all of my icons and replacing them with unique icons.
Originally I had this:
<img id="EEProfile" src="images/EEProfile.png" alt="Employee Profile" onMouseOver="mouseOver()" onMouseOut="mouseOut()">
External JS file:
function mouseOver() { document.getElementById("EEProfile").src = 'images/EEProfile_Hover.png'; }
function mouseOut() { document.getElementById("EEProfile").src = 'images/EEProfile.png'; }
There are a few issues with this:
This method works on IE but for some reason on Chrome onMouseOut isn't working, so hover images are remaining.
Requires some inline javascript. I'm trying to move towards eliminating all inline JS.
Requires me to hardcode image paths for each and every image on the page.
Since all image paths are the same and follow the same naming convention, which is just
'images/ImageID.png' or 'images/ImageID_Hover.png'
I was hoping to implement something like this:
Pseudocode HTML:
<img id="EEProfile" src="images/EEProfile.png" alt="Employee Profile" onMouseOver="mouseOver(this.id)" OnMouseOut="mouseOut(this.id)">
Pseudocode JavaScript:
function mouseOver(id) { document.getElementById("id").src = 'images/id.png'; }
function mouseOut(id) { document.getElementById("id").src = 'images/id_Hover.png'; }
I want to pass over the ID of the image element to the mouseOver and mouseOut functions as a parameter, then use that ID's string literal in the image path so I don't have to hardcode every image's path. Is something like this possible? Is there a way to do this without inline JS?
I've considered using content:hover without JS but it isn't supported in IE.
I would give all the images you want to have the hover effect a specific class name. Then you can get all the element with that class and add event listeners for mouseover and mouseout. I used the current src to determine the new src. You could just as easily get the id with event.target.id and use that to build the src. You also could build the regular expression to match more than just .png files.
(function(window, document, undefined)
{
var images = document.getElementsByClassName('hoverImage');
for (var i = 0; i < images.length; i++) {
images[i].addEventListener('mouseover', imageMouseOver, false);
images[i].addEventListener('mouseout', imageMouseOut, false);
}
})(window, window.document);
function imageMouseOver(event)
{
event = event || window.event;
var image = event.target;
image.src = getNewImagePath(image.src);
console.log(image);
}
function imageMouseOut(event)
{
event = event || window.event;
var image = event.target;
image.src = getNewImagePath(image.src);
console.log(image);
}
function getNewImagePath(path)
{
var newPath;
if (path.indexOf('_Hover') === -1) {
newPath = path.replace('.png', '_Hover.png');
} else {
newPath = path.replace('_Hover', '');
}
return newPath;
}
.hoverImage {
width: 50px;
height: 50px;
}
<img id="1" src="images/1.png" alt="Employee Profile" class="hoverImage">
<img id="2" src="images/2.png" alt="Employee Profile" class="hoverImage">
<img id="3" src="images/3.png" alt="Employee Profile" class="hoverImage">

Javascript, A sytax returns two different values?

Display the image the mouse hovers on, clearing the <ul>
But when I store the src attribute of the <img> in a
variable it returns two different src. Like src of the
image , at the point and the modified one by the substring
Eg:
//images/Hassum_Harrod_03.jpg
//images/Hassum_Harrod.jpg
I want only a single output not two why does this happen please give a reason.
Note
If <img src="images/Hassum_Harrod_03_tn.jpg" /> THUMBNAIL
If <img src="images/Hassum_Harrod_03" /> FULL IMAGE
HTML CODE
<body>
<div id="art">
<h2>Art Preview</h2>
<p>Mouse over the following pieces of art to preview a large version</p>
<ul class="grid">
<li><img src="images/Hassum_Harrod_03_tn.jpg" alt="Hassum Harod's Summer Trees"></li>
<li><img src="images/LaVonne_LaRue_02_tn.jpg" alt="LaVonne_LaRue's Mighty Duck"></li>
<li><img src="images/Lorenzo_Garcia_01_tn.jpg" alt="Lorenzo Garcia's The Dancer"></li>
<--FEW OTHER <li>'s-->
</div>
<script src="script.js"></script>
</body>
Javascript
document.querySelector('.grid').addEventListener('mouseover', function(e) {
if (e.target.tagName === 'IMG') {
ulNode = e.target.parentNode.parentNode;
var getAtt = e.target.getAttribute('src');
var imgLoc = getAtt.substring(0,getAtt.length-7)+".jpg";
console.log(imgLoc); //images/Hassum_Harrod_03.jpg
//images/Hassum_Harrod.jpg
var createElement = document.createElement("img");
createElement.setAttribute("src",imgLoc);
ulNode.innerHTML="";
ulNode.appendChild(createElement);
} // check to see that I clicked on IMG only
}, false); // click event
The first time you mouseover the "Hassum_Harrod_03_tn.jpg", the code:
getAtt.substring(0,getAtt.length-7)+".jpg"
should return the "images/Hassum_Harrod_03.jpg". However when it runs to:
var createElement = document.createElement("img");
createElement.setAttribute("src",getAtt + ".jpg");
ulNode.innerHTML="";
ulNode.appendChild(createElement);
The DOM was broken now as the "ul" element contains no "li" at all but an "img" in it.
Note the "mouseover" binding still works as the "ul" still lives.
Then a second mouseover on the "Hassum_Harrod_03.jpg" will get "Hassum_Harrod.jpg" and the "ulNode" in your code is no longer the "ul" but the upper "div" node. And the "mouseover" binding fails as no "ul" exists.
I guess this would work!
document.querySelector('.grid').addEventListener('mouseover', function(e) {
if (e.target.tagName === 'IMG') {
ulNode = e.target.parentNode.parentNode;
var getAtt = e.target.getAttribute('src');
var imgLoc = getAtt.substring(0,getAtt.length-7)+".jpg";
console.log(imgLoc); //images/Hassum_Harrod_03.jpg
//images/Hassum_Harrod.jpg
var createElement = document.createElement("img");
createElement.setAttribute("src",getAtt + ".jpg");
ulNode.innerHTML="";
ulNode.appendChild(createElement);
} // check to see that I clicked on IMG only
}, false); // click event
<div id="art">
<h2>Art Preview</h2>
<p>Mouse over the following pieces of art to preview a large version</p>
<ul class="grid">
<li><img src="images/Hassum_Harrod_03_tn.jpg" alt="Hassum Harod's Summer Trees" /></li>
<li><img src="images/LaVonne_LaRue_02_tn.jpg" alt="LaVonne_LaRue's Mighty Duck" /></li>
<li><img src="images/Lorenzo_Garcia_01_tn.jpg" alt="Lorenzo Garcia's The Dancer" /></li>
</ul>
</div>
The reason is, the onMouseOver event binds the image by changing it to the full version. That's the reason you get so.
You are facing this issue because your are binding mouseover event for all img element (the one you created dynamically also) just check classname of in mouseover function will work, I guess.
document.querySelector('.grid').addEventListener('mouseover', function(e) {
if (e.target.tagName === 'IMG') {
ulNode = e.target.parentNode.parentNode;
if(ulNode.className == 'grid'){
var getAtt = e.target.getAttribute('src');
var imgLoc = getAtt.substring(0,getAtt.length-7)+".jpg";
alert(imgLoc); //images/Hassum_Harrod_03.jpg
//images/Hassum_Harrod.jpg
var createElement = document.createElement("img");
createElement.setAttribute("src",imgLoc);
ulNode.innerHTML="";
ulNode.appendChild(createElement);
}
} // check to see that I clicked on IMG only
}, false); // click event
document.querySelector('.grid').addEventListener('mouseover', function(e) {
if (e.target.tagName === 'IMG') {
ulNode = e.target.parentNode.parentNode;
ulNode.innerHTML="";
var getAtt = e.target.getAttribute('src');
var imgLoc = getAtt.substring(0,getAtt.length-7)+".jpg";
console.log(imgLoc); //images/Hassum_Harrod_03.jpg
//images/Hassum_Harrod.jpg
var createElement = document.createElement("img");
createElement.setAttribute("src",imgLoc);
ulNode.appendChild(createElement);
} // check to see that I clicked on IMG only
}, false); // click event

.appendchild executing twice in CKeditor

I'm using the simpleuploads plugin for CKeditor. Everything's working perfect except for one itsy bitsy problem.
I'm trying wrap an uploaded image object in a div like so
<div class="image-container>
<img class="addedImg>
</div>
and have added the following at the bottom of /app/assets/javascripts/ckeditor/config.js
CKEDITOR.on('instanceReady', function(e) {
e.editor.on( 'simpleuploads.finishedUpload' , function(ev)
{
var element = ev.data.element;
if (element.getName() == 'img')
{
var img = element.$,
doc = img.ownerDocument,
div = doc.createElement('div');
img.setAttribute('class', 'addedImg');
img.removeAttribute('width');
img.removeAttribute('height');
div.setAttribute('class', 'image-container');
img.parentNode.replaceChild(div, img);
div.appendChild(img);
}
});
});
The problem is div is wrapped in another div like so:
<div class="image-container">
<div class="image-container">
<img class="addedImg">
</div>
</div>
How do I get the script to execute only once?
EDIT:
Issue caused by my custom assets/javascripts/ckeditor/config.js being loaded, and then the galetahub gem's assets/ckeditor/config.js being loaded again. Not sure where the problem lies. Will post more details if solution is found.
The code is fine, but that file is being included twice so the listener is executed twice. The problem can be avoided by stopping the finishedUpload event after is being executed the first time:
CKEDITOR.on('instanceReady', function(e) {
e.editor.on( 'simpleuploads.finishedUpload' , function(ev)
{
var element = ev.data.element;
if (element.getName() == 'img')
{
var img = element.$,
doc = img.ownerDocument,
div = doc.createElement('div');
img.setAttribute('class', 'addedImg');
img.removeAttribute('width');
img.removeAttribute('height');
div.setAttribute('class', 'image-container');
img.parentNode.replaceChild(div, img);
div.appendChild(img);
ev.stop(); // Stop the event in case the listener is inserted twice
}
});
});

Javascript: onmouseover function

I have a problem with changing onmouseover and onmouseout attributes on dynamic pictures. The way i want it to work is whenever i put my mouse over images the images must change and when i take my mouse away it must be changed to the original picture. and whenever i select any image, that image must be changed to the image which was displayed while moving the mouse across the image. and when i select any other image the same process must take place but the previous image that was changed must be changed back to the original picture.
I have accomplished all of the above but my problem is when i select multiple pictures and put my mouse over images that were previously selected, those images do not change (onmouseover attribute does not work on them anymore).
<script language="javascript">
function changeleft(loca){
var od=''
var imgs = document.getElementById("leftsec").getElementsByTagName("img");
for (var i = 0, l = imgs.length; i < l; i++) {
od=imgs[i].id;
if(od==loca){
imgs[i].src="images/"+od+"_over.gif";
imgs[i].onmouseover="";
imgs[i].onmouseout="";
}else{
od = imgs[i].id;
imgs[i].src="images/"+od+".gif";
this.onmouseover = function (){this.src="images/"+od+"_over.gif";};
this.onmouseout = function (){this.src="images/"+od+".gif";};
}
}
}
</script>
<div class="leftsec" id="leftsec" >
<img id='wits' class="wits1" src="images/wits.gif" onmouseover="this.src='images/wits_over.gif'" onmouseout="this.src='images/wits.gif'" onclick="changeleft(this.id)" /><br />
<img id='city' class="city1" src="images/city.gif" onmouseover="this.src='images/city_over.gif'" onmouseout="this.src='images/city.gif'" onclick="changeleft(this.id)" /><br />
<img id='organise' class="city1" src="images/organise.gif" onmouseover="this.src='images/organise_over.gif'" onmouseout="this.src='images/organise.gif'" onclick="changeleft(this.id)" /><br />
<img id='people' class="city1" src="images/people.gif" onmouseover="this.src='images/people_over.gif'" onmouseout="this.src='images/people.gif'" onclick="changeleft(this.id)" /><br />
</div>
I would recommend to use an Ajax library (jQuery, YUI, dojo, ExtJS, ...). In jQuery I would do something like:
Edit: Extended the example with .click() ability.
var ignoreAttrName = 'data-ignore';
var imgTags = jQuery('#leftsec img'); // Select all img tags from the div with id 'leftsec'
jQuery(imgTags)
.attr(ignoreAttrName , 'false') // Supplying an ignore attribute to the img tag
.on('click', function () {
jQuery(imgTags).attr(ignoreAttrName, 'false'); // Resetting the data tag
jQuery(this).attr(ignoreAttrName, 'true'); // only the current will be ignored
// Do whatever you want on click ...
})
.on('mouseover', function () {
// This will be called with the img dom node as the context
var me = jQuery(this);
if (me.attr(ignoreAttrName) === 'false') {
me.attr('src', me.attr('id') + '.gif');
}
})
.on('mouseout', function () {
// This will be called when leaving the img node
var me = jQuery(this);
if (me.attr(ignoreAttrName) === 'false') {
me.attr('src', me.attr('id') + '-over.gif');
}
});
With a library it's cleaner and more scalable I think and the chance that it's working in other browsers is increased too :).
Hope this helps you out!

Categories

Resources