I'm not quite sure why my code isn't working at this point. I am trying to make an Instagram like button. I have an image of a black heart and when double clicked on I want to switch it to another image of a red heart. I've dug around here and there but couldn't quite pin point the problem. The code snippet works but it does not work when I run it in my project.
const button = document.querySelector('#like');
document.querySelector('button').addEventListener('dblclick', (e) => {
if (button.src == "https://www.w3schools.com/html/img_chania.jpg") {
button.src = "https://www.w3schools.com/html/pic_trulli.jpg";
} else {
button.src = "https://www.w3schools.com/html/img_chania.jpg";
}
});
.under-image-nav button {
border: none;
width: 30px;
}
<nav class="under-image-nav">
<button><img id="like" src="https://www.w3schools.com/html/img_chania.jpg" alt="like button"> </button>
</nav>
I got rid of the button and simply allowed javascript to control the source of the image.
To shorten the code, I used a ternary operator
let heartEl = document.querySelector(".heart");
const fullHeart = 'https://external-content.duckduckgo.com/iu/?u=http%3A%2F%2Ffrogermcs.github.io%2Fimages%2F6%2Fheart_red.png&f=1&nofb=1"'
const emptyHeart = 'https://freeiconshop.com/wp-content/uploads/edd/heart-outline.png'
heartEl.addEventListener("dblclick", () => {
heartEl.src == emptyHeart ? heartEl.src = fullHeart : heartEl.src = emptyHeart
});
<img class='heart' src='https://freeiconshop.com/wp-content/uploads/edd/heart-outline.png'>
You should attach the event listener to the button instead.
const img = document.querySelector('#like');
document.querySelector('button').addEventListener('dblclick', (e) => {
if (img.src == "https://www.w3schools.com/html/pic_trulli.jpg") {
img.src = "https://www.w3schools.com/html/img_chania.jpg";
} else {
img.src = "https://www.w3schools.com/html/pic_trulli.jpg";
}
});
<button><img id="like" src="https://www.w3schools.com/html/pic_trulli.jpg" alt="like button" width="100" height="100"></button>
Related
fiddle:
https://jsfiddle.net/0r7v923u/2/
<img src="https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png" class="logo" alt="Banner" onclick="ratesD(this)" />
JS:
function ratesD(image) {
if (img.attr('src') == "https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png") {
image.src = "https://dirask.com/static/bucket/1633375165831-yjQ7G6WQeL--image.png";
} else {
image.src = "https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png"
}
}
I am simply trying to change the image back and forth on click. The function below changes it but it does not return to the previous image:
function ratesD(image) {
image.src = 'https://dirask.com/static/bucket/1633375165831-yjQ7G6WQeL--image.png';
}
I thought it only needs to change using img.attr('src') == what do I need to change for the if condition?
First you are trying to access the wrong property of the image object (attr instead of src) and the second function is not checking the current image source before changing it. To fix this, the function should check the current src of the image and change it to the other URL depending on its value. Try this.
function ratesD(image) {
if (image.src == "https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png") {
image.src = "https://dirask.com/static/bucket/1633375165831-yjQ7G6WQeL--image.png";
} else {
image.src = "https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png"
}
}
<img src="https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png" class="logo" alt="Banner" onclick="ratesD(this)" />
It's a bad idea to force load/unload your images (even if they are in the system cache) every time you click on them.
Load them only once, and switch their display at each click.
const bannerImgs = document.querySelector('#banner-images');
bannerImgs.onclick =_=> bannerImgs.classList.toggle('seeOther');
#banner-images > img {
width : 100px;
height : 100px;
}
#banner-images.seeOther > img:first-of-type,
#banner-images:not(.seeOther) > img:last-of-type {
display : none;
}
<div id="banner-images" >
<img src="https://dirask.com/static/bucket/1631898942509-VMYrnXyYZv--image.png" alt="Banner" >
<img src="https://dirask.com/static/bucket/1633375165831-yjQ7G6WQeL--image.png" alt="Banner" >
</div>
How can I switch between icons with javascript when clicked?
function mode() {
var moon = document.getElementById("mode");
moon.src = "https://img.icons8.com/sf-black-filled/35/fffffe/moon-symbol.png";
moon.id = "lightmode";
moon.onclick = lightmode();
}
function lightmode() {
var sun = document.getElementById("lightmode");
sun.src = "https://img.icons8.com/sf-black-filled/34/000000/sun.png";
sun.onclick = mode();
}
body { background-color:grey }
<div class="nav-icons">
<img id="mode" class="moon" onclick="mode()" src="https://img.icons8.com/sf-black-filled/35/fffffe/moon-symbol.png">
<img id="notification" src="https://img.icons8.com/ios-glyphs/34/fffffe/notification-center.png" alt="" srcset="">
</div>
You are setting up event listeners in an incorrect manner
Here is a toggle using classes and data attributes
const srcs = {
"dark": "https://img.icons8.com/sf-black-filled/35/fffffe/moon-symbol.png",
"light": "https://img.icons8.com/sf-black-filled/34/000000/sun.png"
};
const modeToggle = document.getElementById("modeToggle");
modeToggle.addEventListener("click", function() {
let mode = this.dataset.mode;
mode = mode === "dark" ? "light" : "dark"; // toggle
this.src = srcs[mode]; // image
this.dataset.mode = mode; // save in element
document.body.classList.toggle("dark",mode==="dark"); // toggle page too
})
document.body.classList.toggle("dark",modeToggle.dataset.mode==="dark"); // initialise the page, possibly from localStorage
body {
background-color: grey
}
body.dark {
background-color: black;
}
<div class="nav-icons">
<img id="modeToggle" data-mode="light" src="https://img.icons8.com/sf-black-filled/34/000000/sun.png">
<img id="notification" src="https://img.icons8.com/ios-glyphs/34/fffffe/notification-center.png" alt="" srcset="">
</div>
this may solve your problem, please use proper names for your functions, e.g instead of mode() use changeMode() as a name
javascript:
let isChanged = false;
let mode = document.querySelector('#mode');
function changeMode(){
isChanged = !isChanged;
if(isChanged) {
mode.src = "https://img.icon8.com/sf-black-filled/35/ffffffe/moon-symbol.png"
} else {
mode.src = "https://img.icon8.com/sf-black-filled/34/000000/sun.png"
}
}
Toggling between two different images/icons/styles is very simple in Javascript. You could, for instance, create a simple Object literal with name/value pairs for both icons as per the following. A simple ternary operator determines what the src should be based upon the current src
document.querySelector('.nav-icons > img.sunmoon').addEventListener('click',function(e){
let icons={
sun:'https://img.icons8.com/sf-black-filled/34/000000/sun.png',
moon:'https://img.icons8.com/sf-black-filled/35/fffffe/moon-symbol.png'
};
this.src = this.src==icons.moon ? icons.sun : icons.moon;
});
body {
background-color: grey
}
<div class="nav-icons">
<img class="sunmoon" src="https://img.icons8.com/sf-black-filled/35/fffffe/moon-symbol.png" />
<img id="notification" src="https://img.icons8.com/ios-glyphs/34/fffffe/notification-center.png" alt="" srcset="" />
</div>
I've made a dark mode toggle button for my demo website that adds a class to change the background color. The button works, but I want to swap out the image the button is using depending on if the class is present. It's not working. I think I've messed up MutationObserver somehow, can anyone help?
Javascript
let buttonIMG = document.getElementById("darkButtonIMG");
const observer = new MutationObserver(darkImage);
observer.observe(buttonIMG, {
attributes: true
});
function darkImage() {
let buttonIMG = document.getElementById("darkButtonIMG");
let buttonSRC = buttonIMG.hasAttribute("dark");
if (buttonSRC === true) {
buttonIMG.setAttribute("src", "images/Sun_Icon.png");
} else {
buttonIMG.setAttribute("src", "images/Moon_Icon.png");
}
}
HTML
<nav>
<div class="row">
<button class="buttonHide" id="hamburgerBtn">☰</button>
<ul id="navOpen">
...
<li><button id="darkButton" type="button" class=""><img id="darkButtonIMG"src="images\Moon_Icon.png" alt="Dark mode icon"></button></li>
</ul>
</div> <!-- End of Navbar Row -->
</nav>
I want to swap out the image the button is using depending on if the
class is present.
I'm assuming that when you click the button you're adding class dark to it.
In your callback method you're checking for the presence of dark attribute, but you should check for the presence of a class instead.
let buttonSRC = buttonIMG.classList.contains("dark");
You need to setAttribute for check hasAttribute
let buttonIMG = document.getElementById("darkButtonIMG");
const observer = new MutationObserver(darkImage);
observer.observe(buttonIMG, {
attributes: true
});
function darkImage() {
let buttonIMG = document.getElementById("darkButtonIMG");
let buttonSRC = buttonIMG.hasAttribute("dark");
if (buttonSRC === true) {
buttonIMG.setAttribute("src", "images/Sun_Icon.png");
buttonIMG.removeAttribute("dark");
} else {
buttonIMG.setAttribute("src", "images/Moon_Icon.png");
buttonIMG.setAttribute("dark", "dark");
}
}
I'd like to detect a click inside or outside a div area. The tricky part is that the div will contain other elements and if one of the elements inside the div is clicked, it should be considered a click inside, the same way if an element from outside the div is clicked, it should be considered an outside click.
I've been researching a lot but all I could find were examples in jquery and I need pure javascript.
Any suggestion will be appreciated.
It depends on the individual use case but it sounds like in this example there are likely to be other nested elements inside the main div e.g. more divs, lists etc. Using Node.contains would be a useful way to check whether the target element is within the div that is being checked.
window.addEventListener('click', function(e){
if (document.getElementById('clickbox').contains(e.target)){
// Clicked in box
} else{
// Clicked outside the box
}
});
An example that has a nested list inside is here.
You can check if the clicked Element is the div you want to check or not:
document.getElementById('outer-container').onclick = function(e) {
if(e.target != document.getElementById('content-area')) {
console.log('You clicked outside');
} else {
console.log('You clicked inside');
}
}
Referring to Here.
you can apply if check for that inside your click event
if(event.target.parentElement.id == 'yourID')
In Angular 6 and IONIC 3, I do same as here:
import {Component} from 'angular/core';
#Component({
selector: 'my-app',
template: `
<ion-content padding (click)="onClick($event)">
<div id="warning-container">
</div>
</ion-content>
`
})
export class AppComponent {
onClick(event) {
var target = event.target || event.srcElement || event.currentTarget;
if (document.getElementById('warning-container').contains(target)){
// Clicked in box
} else{
// Clicked outside the box
}
}
}
This working fine on web/android/ios.
It might be helpful for someone, Thanks.
Try this solution it uses pure javascript and it solves your problem. I added css just for better overview... but it is not needed.
document.getElementById('outer-div').addEventListener('click', function(){
alert('clicked outer div...');
});
document.getElementById('inner-div').addEventListener('click', function(e){
e.stopPropagation()
alert('clicked inner div...');
});
#outer-div{
width: 200px;
height: 200px;
position: relative;
background: black;
}
#inner-div{
top: 50px;
left: 50px;
width: 100px;
height: 100px;
position: absolute;
background: red;
}
<div id="outer-div">
<div id="inner-div">
</div>
</div>
I came up with a hack for this that's working well for me and that might help others.
When I pop up my dialog DIV, I simultaneously display another transparent DIV just behind it, covering the whole screen.
This invisible background DIV closes the dialog DIV onClick.
This is pretty straightforward, so I'm not going to bother with the code here. LMK in the comments if you want to see it and I'll add it in.
HTH!
closePopover () {
var windowBody = window
var popover = document.getElementById('popover-wrapper') as HTMLDivElement;
windowBody?.addEventListener('click', function(event){
if(popover === event.target) {
console.log("clicked on the div")
}
if(popover !== event.target) {
console.log("clicked outside the div")
}
})
}
}
I recently needed a simple vanilla JS solution which solves for:
Ignoring specific selectors including whether a parent contains one of these selectors
Ignoring specific DOM nodes
This solution has worked quite well in my app.
const isClickedOutsideElement = ({ clickEvent, elToCheckOutside, ignoreElems = [], ignoreSelectors = [] }) => {
const clickedEl = clickEvent.srcElement;
const didClickOnIgnoredEl = ignoreElems.filter(el => el).some(element => element.contains(clickedEl) || element.isEqualNode(clickedEl));
const didClickOnIgnoredSelector = ignoreSelectors.length ? ignoreSelectors.map(selector => clickedEl.closest(selector)).reduce((curr, accumulator) => curr && accumulator, true) : false;
if (
isDOMElement(elToCheckOutside) &&
!elToCheckOutside.contains(clickedEl) &&
!didClickOnIgnoredEl &&
!didClickOnIgnoredSelector
){
return true;
}
return false;
}
const isDOMElement = (element) => {
return element instanceof Element || element instanceof HTMLDocument;
}
In React you can use useClickOutside hook from react-cool-onclickoutside.
Demo from Github:
import { useClickOutside } from 'use-events';
const Example = () => {
const ref1 = React.useRef(null);
const ref2 = React.useRef(null);
const [isActive] = useClickOutside([ref1, ref2], event => console.log(event));
return (
<div>
<div ref={ref1} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
<br />
<div ref={ref2} style={{ border: '1px dotted black' }}>
You are {isActive ? 'clicking' : 'not clicking'} outside of this div
</div>
</div>
);
};
Live demo
By default I can see my heart img in button. Once button is clicked it is changing to added to list but I can't see img here. Image is hidden here, I can see that using background color for the image. Not sure where I am doing wrong. thanks for your help in advance
changeHeart = () => {
if (this.emptyHeart) {
this.emptyHeart = false;
document.getElementById('heartImage').src = '../../img/filledHeart.png';
document.getElementById('heartImage').style.visibility = '';
document.getElementById('addButtonText').innerHTML = "Added to List";
} else {
this.emptyHeart = true;
document.getElementById('heartImage').src ='../../img/emptyHeart.png';
document.getElementById('heartImage').style.visibility = 'hidden';
document.getElementById('addButtonText').innerHTML = "Add to List";
}
};
<button onClick={this.changeHeart} className="btn">
<img id="heartImage" className="heartBtnImg" src={require('../../img/emptyHeart.png')} alt=""/>
<span id="addButtonText" className="btntxt">Add to Wish List</span>
</button>
I suggest you start with a tutorial on React before jumping in. You should use the state for this.
changeHeart = () => {
if (this.state.emptyHeart) {
this.setState({
emptyHeart: false,
imgSrc: require('../../img/filledHeart.png'),
btnText: 'Added to List'
});
} else {
this.setState({
emptyHeart: true,
imgSrc: require('../../img/emptyHeart.png'),
btnText: 'Add to List'
});
}
};
In your render function:
<button onClick={this.changeHeart} className="btn">
<img id="heartImage" className="heartBtnImg" src={this.state.imgSrc} alt=""/>
<span id="addButtonText" className="btntxt">{this.state.btnText}</span>
</button>
I don't have access to your entire code, so please fix the paths and texts to suit your needs. You will also need to initialize your state in the constructor.