Javascript: changing img src onclick only works once [duplicate] - javascript

This question already has answers here:
IF Statement Always True
(3 answers)
Closed 6 years ago.
This is so simple I'm not sure why I'm having trouble with it. I'm trying to imitate a flip card between two images so when clicked, it would simply change to the other image. I'm having trouble with my if/else statement because every time the image is clicked, it never makes it to the else part. In the source code of the HTML page, the src of the image is being changed but passes the if statement every time.
(function() {
// attaches event handler to image
window.onload = function() {
var image1 = document.getElementById("image1");
image1.onclick = changeImage;
};
// changes image when clicked to flip from image to text and text to image
function changeImage() {
if (document.getElementById("image1").src = "img/top.png") {
document.getElementById("image1").src = "img/toptext.png";
//window.alert('hi');
}
else {
window.alert('it passed');
document.getElementById("image1").src="img/top.png";
}
}
})();

use == or === for comparison in if condition check.
using = will assign the value and always be true since the assigned string is not an empty string.
function changeImage() {
if (document.getElementById("image1").src == "img/top.png") {
document.getElementById("image1").src = "img/toptext.png";
//window.alert('hi');
}
else {
window.alert('it passed');
document.getElementById("image1").src="img/top.png";
}
}

You should use == for an if comparaison
if (document.getElementById("image1").src = "img/top.png") {
change into
if (document.getElementById("image1").src == "img/top.png") {

Related

How to add eventListener function to elements with unique id?

I have some dynamic cards:
and I want to add eventListener to all play buttons (their code is):
<a href="link">
<img src="play.svg">
<audio src="myMusic.mp3"></audio>
</a>
When I click to "play", it should look like below:
(it should change image and should also play audio)
My JS code so far done is:
<script>
var imgsPlay = document.getElementsByClassName('play-img-loop');
var audioPlayers = document.getElementsByClassName('audio-player');
window.onload = function() {
for(var i = 0; i < imgsPlay.length; i++) {
imgsPlay[i].addEventListener('click', function(event) {
if(this.getAttribute('src') == "img/icons/play.svg") {
this.setAttribute('src', "img/icons/play_red.svg");
audioPlayers[i].play();
} else if(this.getAttribute('src') == "img/icons/play_red.svg") {
this.setAttribute('src', "img/icons/play.svg");
audioPlayers[i].pause();
}
});
}
}
</script>
(I can do it manually, but) can not dynamically. How can I do this ?
You need to delegate! If not, then your question is just a dupe of JavaScript closure inside loops – simple practical example
Here I assume you have a container called cardContainer
I am a little confused as to _red means playing or paused, so change the code below to match. Your example HTML does not match the code you show, there are no classes on the player and image, I therefor assume you do have those in the actual code
window.addEventListener('load', function() {
document.getElementById('cardContainer').addEventListener('click', function(e) {
const tgt = e.target;
if (tgt.classList.contains('play-img-loop')) {
const src = tgt.getAttribute('src');
const running = src.includes('_red');
const audioPlayer = tgt.closest('a').querySelector('audio');
tgt.setAttribute('src', `img/icons/play$(running?'':'_red').svg`);
if (running) audioPlayer.pause();
else audioPlayer.play();
}
});
});
Your problem is the incorrect handling of closures. The event listener call back will never get the correct value of i by the way you have written it. The value of i will always be the last one when the events are fired.
The easiest workaround is to define the variable i only for the scope of a single iteration - which is what the let do.
for(let i = 0; i < imgsPlay.length; i++) {
imgsPlay[i].addEventListener('click', function(event) {
if(this.getAttribute('src') == "img/icons/play.svg") {
...
}
Useful reference: setTimeout in for-loop does not print consecutive values

changing a value of id in html, then changing it back [duplicate]

This question already exists:
How to reset an html id
Closed 2 years ago.
i know that this is a messy code, but i really need help with this problem that i yet can't solve. so for my project i am building a E-shop. i got modals for my products, and i got a button within the modal for adding the item to the cart. On the button i got an id="1"; and in the javascript as you can see i am changing it from "1" to "2". and i succeeded with that. and now i am stuck in id="2", so i want to reset the value of the id. But i don't know how.
function changeImage(button) {
var exchangeimage = button.id;
if (exchangeimage == 'modalopen1') {
var image = document.getElementById('pic1');
if (image.src.match("https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(24).jpg")) {
image.src = "https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(23).jpg";
} else {
image.src = "https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(24).jpg";
}
}
if (exchangeimage == 'modalopen2') {
var image2 = document.getElementById('pic1');
document.getElementById('1').id='2';
}
if (image2.src.match("https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(26).jpg")) {
image2.src = "https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(23).jpg";
} else {
image2.src = "https://mdbootstrap.com/img/Photos/Horizontal/E-
commerce/Vertical/img%20(26).jpg";
}
}
function add_image(button) {
var image = button.id;
if (image == '1') {
show_image("http://bestjquery.com/tutorial/product-grid/demo11 /images/img-1.jpg", 155, 206, "image");
}
if (image == '2') {
show_image("http://bestjquery.com/tutorial/product-grid/demo11/images/img-3.jpg", 155, 206,
"image");
}
}
just get the element again now with id=2 and set the id back to 1
document.getElementById('1').id='2';
document.getElementById('2').id='1';
<div id='1'></div>
If you are using jquery/bootstrap then you could change it back when the modal closes.
<script>
$(document).ready(function(){
$('#modalopen2').on('hide.bs.modal', function () {
$("#2").attr({"id":"1"})
});
});
</script>
I could provide a better answer if I knew when you wanted the value to change back.

How to get Javascript's "getElementsByClassName()" to work?

When I do this, everything works just fine:
function openTab(tabName)
{
document.getElementById("divUsers").className = "invisible";
document.getElementById("divGroups").className = "invisible";
document.getElementById("divZFSPools").className = "invisible";
document.getElementById("divShares").className = "invisible";
document.getElementById(tabName).className = "visible";
}
But when I do this, nothing happens:
function openTab(tabName)
{
var targetTab, activeTab;
// Get the div:
targetTab = document.getElementById(tabName);
// If it is the active tab, return:
if(targetTab.style.display.className == "visible");
return;
// No, it is not the active tab:
document.getElementsByClassName("visible")[0].className = "invisible";
// Make the target tab visible:
document.getElementById(tabName).className = "visible";
}
FYI: "visible" and "invisible" are two CSS class names.
Does anyone have idea why? How can I achieve the desktop tab control behaviour using HTML and Javascript?
If I don't misunderstood you question just remove the ; after your if condition because a simple typo (;) can make huge difference to your code.
Assume,
if (0 === 1); { alert("Hello World") }
// equivalent to:
if (0 === 1) /*do nothing*/ ;
alert ("Hello World");
This code will alert "Hello World", but not because 0 equals 1, but
because of the semicolon. It makes JavaScript think that you have an
empty statement there, and everything to the right of it is treated as
no longer belonging to the if conditional and thus independent of it.
Source : https://www.codecademy.com/en/forum_questions/507f6dd09266b70200000d7e
So on your code it will be like this,
//If it is the active tab, return:
if(targetTab.style.display.className == "visible");
return; //^^ remove this semicolon

Ideas for a correct function on my webpage?

I am having problems with a javascript function. I want to replace an icon by changing the class.
On my page, I have the following element:
<i class="wait icon" alt="{webui_botstatenotavailable}" title="{webui_botstatenotavailable}" id="{botname}"></i>
The following javascript should change the class, but it does not work:
function incomingBotStatusList(http_request, statusOff, statusOn)
{
if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
if (http_request.responseText.length < 7)
{
// Error
}
else
{
var botStatusList = JSON.parse(http_request.responseText);
for (var key in botStatusList)
{
if (botStatusList.hasOwnProperty(key))
{
var botStatusImage = document.getElementById(key);
if (botStatusImage != null)
{
if (botStatusList[key] == 0)
{
botStatusImage.class.innerHTML = "images/bullet_red.png";
botStatusImage.title = statusOff;
botStatusImage.alt = statusOff;
}
else if (botStatusList[key] == 1)
{
botStatusImage.class.innerHTML = "<i class=\"checkmark green icon\">";
botStatusImage.alt = statusOn;
botStatusImage.title = statusOn;
}
}
}
}
}
}
}
}
Did someone from you know how it will work?
Thanks for your help!
Best Regards
Pierre
I see a couple of problems with your code. First, the <i> element is used to apply italic formatting to text. It is not the HTML code for an icon or an image.
Secondly, you write botStatusImage.class.innerHTML, but the Element.class does not exist, and Element.className is a string. It does not have an innerHTML attribute. So, you could write botStatusImage.className = "new_class_name"; and this would be more correct.
You should then change the image source by calling botStatusImage.setAttribute('src', new_url), where you have set new_url to the new image location.
Check out the javascript reference for the Element class that is returned from document.getElementById: check this link
My recommendation, start simple, then make it complex.
First, try to get the icon to change without the AJAX request. Try writing a function like this:
function changeIcon( imageId, newUrl ){
var element = document.getElementById( imageId );
element.setAttribute( "src", newUrl );
}
Then test this function in the console by passing calling it with the URL's manually.
Once that works, don't change it! Next add the AJAX call, and when you have the Icon url from your server response, all you do is call the function that you already wrote and tested. That way you separate the AJAX code from the image update code and you can test them separately.
The key is smaller functions. Build the easy stuff first, and then call those easy functions from the harder functions. Once you know the easy function works well, it becomes much easier to find problems in the harder functions.

Do an action based on presence of ALT attribute with Javascript

I have some javascript which looks at the body and finds words and if one is present, it outputs a div. This is useful for many things, however...
What I need to do is also look at the body and all the ALT tags for the page as well.
I found this: Use javascript to hide element based on ALT TAG only?
Which seems to change the ALT attribute, however I want to perform an action.
Here's my JS so far.
var bodytext = $('body').text();
if(bodytext.toLowerCase().indexOf('one' || 'two')==-1)
return;
var elem = $("<div>Text Here</div>");
Thank you.
P.S. I am a N00B/ relatively new at JS, I am doing this for a small project, so I am not sure where to start for this in terms of JS functions.
Updated Answer
Try this out, I commented the code to explain it a bit.
// build array of triggers
var triggers = ['trigger1','trigger2','trigger3'];
// wait for page to load
$(function() {
// show loading overlay
$('body').append('<div id="mypluginname-overlay" style="height:100%;width:100%;background-color:#FFF;"></div>');
// check page title
var $title = $('head title');
for(trigger of triggers) {
if($($title).innerHTML.toLowerCase().indexOf(trigger) >= 0) {
$($title).innerHTML = '*censored*';
}
}
// check all meta
$('meta').each(function() {
var $meta = $(this);
for(trigger of triggers) {
if($($meta).attr('name').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
} else if($($meta).attr('content').toLowerCase().indexOf(trigger) >= 0) {
censorPage();
return; //stop script if entire page must be censored
}
}
});
// check all img
$('img').each(function() {
var $img = $(this);
for(trigger of triggers) {
if($($img).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($img);
}
}
});
// check all video
$('video').each(function() {
var $video = $(this);
for(trigger of triggers) {
if($($video).attr('alt').toLowerCase().indexOf(trigger) >= 0) {
censor($video);
}
}
});
// if you want to be extra careful and check things like background image name,
// you'll have to run this code here - very inefficent
// but necessary if you want to check every single element's background image name:
for($element of $('body').children()) {
for(trigger of triggers) {
if($($element).css('background-image').toLowerCase().indexOf(trigger) >= 0) {
$($element).css('background-image','');
}
}
}
, function() { // Not sure if this is totally correct syntax, but use a callback function to determine when
// when the rest of the script has finished running
// hide overlay
$('#mypluginname-overlay').fadeOut(500);
}});
function censor($element) {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$element.innerHTML = 'new content';
}
function censorPage() {
// just a basic example, you'll probably want to make this more complex to overlay it properly
$('body').innerHTML = 'new content';
}
---Original Answer---
I'm not sure exactly what you would like to do here, you should add more detail. However if you choose to use jQuery, it provides tons of useful methods including the method .attr(), which lets you get the value of any attribute of any element.
Example:
var alt = $('#my-selector').attr('alt');
if (alt == 'whatYouWant') {
alert('yay');
} else {
alert('nay');
}
You're using jQuery lib, you could select elements by attribute like:
$('[alt="one"]').each(function(el){
// do something
var x = $(el).arrt('alt');
});
If you use selector $('[alt]') you can get elements that have this attribute set, and then check the value of the element if you have a more complicated selection.
Than you have to change your return, as you could not put a div inside an ALT tag, it didn't work.
Here is about what is your expected output.
UPDATE
As you want to change all images and video in a page, the way to do this with jquery is through $.replaceWith():
$('img,video').replaceWith($('<div>Text Here</div>'));
If you need to filter the elements:
$('img,video').each(function(el){
if($(el).prop('tagName') == 'IMG' &&
$(el).attr('alt') == 'the text...') {
$(el).replaceWith($('<div>Text Here</div>'));
}
})
But I'm not an expert on Chrome Extensions, I just put this code here in jQuery, as you was using jQuery.
Of course it could be done, with much code with plain javascript and the DOM API.

Categories