how to apply same function to multiple divs - javascript

on this page (http://jodiaries.com/test/) I need to make a popup appear when I click on the red boxes.
So far it works, I added the onclick = "div1" attribute to the red box (on the others = "div2", etc) and use this:
function showhide(divElement) {
var e = document.getElementById(divElement);
if(e.style.display == 'flex'){
e.style.display = 'none';
} else {
e.style.display = 'flex';
}
}
for now the popup closes when I click again on the number, I would like to make it close by clicking anywhere outside that div/popup. I created another script (probably wrong) with this:
window.onload = function(){
var divToHide = document.getElementById('div1');
document.onclick = function(e){
if(e.target.id !== 'div_block-286-119'){
divToHide.style.display = 'none';
}
};
};
but it works only on the first red box, not on the others (because I target only div_block-286-119).
How can I get it to work with all popups (i will add more as soon as everything works)?
thanks in advance!

It's a bad idea to work with ids in your case, also in general. Instead of onclick="yourFunction()" use event listener. I didn't test the code down below, but it should work.
document.querySelectorAll(".crono-day-red").forEach(red => {
red.addEventListener("click", () => showhide(red));
})
const showhide = red => {
// I prefer to control styles by toggling classes.
// IMO, it's easier, especially for multiple styles.
red.closest(".ct-div-block").classList.toggle("popup-visible");
}
const closePopups = () => {
window.addEventListener("click", () => {
let clickedInside = event.target.classList.contains(".popup-visible")
|| event.target.closest(".popup-visible)"
if (clickedInside) {
return;
}
document.querySelectorAll(".popup-visible").forEach(x => x.classList.remove("popup-visible"));
})
}
window.onload = closePopups();
.ct-div-block .nove-gen-click { display: none }
.ct-div-block.popup-visible .nove-gen-click { display: flex }
All you need to do is to toggle "popup-visible" class by your functions.
I also noticed that you define popup styles in #div1 and #div2... Very bad practice.
EDIT AFTER COMMENT
To close currently open red box when you click the new one:
const showhide = red => {
red.closest(".ct-section-inner-wrap")
.querySelectorAll(".popup-visible")
.forEach(x => x.classList.remove("popup-visible"));
red.closest(".ct-div-block").classList.add("popup-visible");
}

Related

Disable dragging in HTML webpage

I'm trying to make an etch-a-sketch with HTML where I have a div container with lots of div elements in it, using grid display in CSS.
HTML: <div id="canvas"></div>
Then I use JS to add the div elements:
for(let i =1;i<=256;i++){
let squareDiv = document.createElement("div");
canvasElement.appendChild(squareDiv);
canvasElement.setAttribute("draggable","false");}
The draggable attribute doesn't work.
When I click and drag to draw something, it is dragging a faint image as below:
Is there an attribute I could use to disable this ?
Edit: All javascript code:
canvasElement =document.getElementById("canvas")
let isToggling = false;
function enableToggle(e) {
isToggling = true;
}
function disableToggle() {
isToggling = false;
}
function toggle(e) {
if (isToggling === false) {
return;
}
console.log('toggle:', e.target);
e.target.classList.add('red');
}
for(let i =1;i<=256;i++){
let squareDiv = document.createElement("div");
canvasElement.appendChild(squareDiv);
canvasElement.setAttribute("draggable","false");
squareDiv.onmousedown=enableToggle;
squareDiv.onmouseenter=toggle;
squareDiv.onmouseup=disableToggle;
}
You can use e.preventDefault() to prevent the default effect from happening inside your onmousedown event.
Add e.preventDefault() inside your enableToggle(e) function
function enableToggle(e) {
isToggling = true;
e.preventDefault()
}
If that doesn't work add it to toggle() and disableToggle()
I had your exact issue with Etch-A-Sketch and this is how I did it: similar to the other user's answer, this also uses preventDefault() but this activates using the ondragstart HTML attribute.
First, use this JS function to enable preventDefault().
function dragstart (event) {
event.preventDefault()
}
Next, apply dragstart (event) to all your elements in your etch grid. In my case, I used the spread syntax [...nodeList] with the forEach method in a function which runs immediately after generating my grid squares.
let grid = document.getElementById('grid');
function addSquare () {
let sliderValue = document.getElementById('slider').value;
for (let i = 0; i < sliderValue ** 2; i++) {
const square = document.createElement('div');
square.className = 'square';
grid.appendChild(square);
}
}
function modifyGridProperty () {
let square = [...document.getElementsByClassName('square')];
square.forEach(element => {
element.setAttribute('ondragstart', 'dragstart(event)');
});
}

How can I get an EventListener on a Select dropdown using a loop to work as expected

I have some HTML tabs which use radio buttons to control them. However I am using a select drop down menu with some javascript to control them on mobile screen sizes.
// Get select element for mobile navigation
const select = document.getElementById("location");
// Event listener for selecting tabs event for mobile
select.addEventListener("change", (e) => {
const target = e.target.value;
const venueTabs = document.querySelectorAll(".tabs__radio");
for (let i = 0; i < venueTabs.length; i++) {
if (venueTabs[i].id === target) {
venueTabs[i].setAttribute("checked", "checked");
console.log(venueTabs[i], target);
} else if (venueTabs[i].id !== target) {
venueTabs[i].removeAttribute("checked");
}
}
});
My eventListener seems to work and is logging out what is expected. It compares the tab div id to the event target.
However this only seems to work when I test each select option twice, on the 3rd attempt the tabbed content disappears (css switches to display: none).
I can't seem to work out what is causing the error.
I have set up a code sandbox with my code https://codesandbox.io/s/nice-ramanujan-2yq1r?file=/src/index.js to help debug it. If the drop down menus isn't showing, you may have to view it for mobile/ below 700px wide & it'll display the select drop down menu.
Can anyone help identify what is causing this bug? I previously had hard coded the EventListener that worked perfectly, it looked like this
select.addEventListener("change", (e) => {
const target = e.target;
const tabone = document.getElementById("tab0");
const tabtwo = document.getElementById("tab1");
const tabthree = document.getElementById("tab2");
const tabfour = document.getElementById("tab3");
if (target.value === "tab0") {
tabtwo.removeAttribute("checked");
tabthree.removeAttribute("checked");
tabfour.removeAttribute("checked");
tabone.setAttribute("checked", "checked");
} else if (target.value === "tab1") {
tabthree.removeAttribute("checked");
tabfour.removeAttribute("checked");
tabone.removeAttribute("checked");
tabtwo.setAttribute("checked", "checked");
} else if (target.value === "tab2") {
tabfour.removeAttribute("checked");
tabone.removeAttribute("checked");
tabtwo.removeAttribute("checked");
tabthree.setAttribute("checked", "checked");
} else if (target.value === "tab3") {
tabone.removeAttribute("checked");
tabtwo.removeAttribute("checked");
tabthree.removeAttribute("checked");
tabfour.setAttribute("checked", "checked");
}
});
However it's not dynamic enough to take any number of tabs that may exist.
This doesn't need any looping over all the radio buttons to begin with - just select the one element you want to set checked via its id:
select.addEventListener("change", (e) => {
const target = e.target.value;
const venueTab = document.querySelector("#"+target);
venueTab.checked = true;
});

How to delete a function effect when a second click on the button in javascript? [duplicate]

This question already has answers here:
How do I add an underline for all the links on the website when I click the button?
(2 answers)
Closed 2 years ago.
maybe one of you can help me. I've written a feature in javascript that adds underlining to all "a" selectors. The function is called with the "onclick" attribute. I would like to reverse the effect, i.e. remove the underscore at second click on the same button. The question is how to do it ?
HTML code:
<button type="button" class="underlineLinks" id="underlineLinks" onclick="underlineLinks()">Click</button>
JS code:
function underlineLinks() {
const links = document.querySelectorAll("a");
links.forEach(a => a.style.textDecoration = "underline");
}
You can create a CSS class with the decoration underline
.class
{
text-decoration: underline
}
and use toggle in the JS.
Toggle will add the class if it isn't applied to your link and remove the class if it is applied to your link
function underlineLinks() {
const links = document.querySelectorAll("a");
links.forEach(a => a.classList.toggle("class"));
}
https://jsfiddle.net/u4sxfdy5/
you could do this
function getUnderLineLinksSetter() {
let areLinksUnderlines = false;
return () => {
const links = document.querySelectorAll('a');
areLinksUnderlines = !areLinksUnderlines;
links.forEach(a => {
if (areLinksUnderlines) {
a.style.textDecoration = 'initial';
} else {
a.style.textDecoration = 'underline';
}
});
};
}
and then use the following html
<button type="button" class="underlineLinks" id="underlineLinks" onclick="getUnderLineLinksSetter()()">Click</button>
Its better to add event listeners from code and not using html inline functions by that i mean instead of setting the on click using html, you set it using javascript like this
// put this code inside a load event in the page so you make sure the button is in the dom
function getUnderLineLinksSetter() {
let areLinksUnderlines = false;
return () => {
const links = document.querySelectorAll('a');
areLinksUnderlines = !areLinksUnderlines;
links.forEach(a => {
if (areLinksUnderlines) {
a.style.textDecoration = 'initial';
} else {
a.style.textDecoration = 'underline';
}
});
};
}
document.getElementById('underlineLinks').addEventLisetner('click', getUnderLineLinksSetter())
And then remove the onclick from html
<button type="button" class="underlineLinks" id="underlineLinks">Click</button>
function underlineLinks() {
const links = document.querySelectorAll("a");
var toChange = "underline"
if(links[0].style.textDecoration != "underline")) toChange = "none"
links.forEach(a => a.style.textDecoration = toChange);
}
Probably there is an easier way but idk, I shoot my shot

How to fire "onmouseenter" only if cursor came from outside of that element

I have 2 images, one and two
On hover of one, the two is displayed, and one is hidden
And then, if I clicked two, it should hide and show the one again
So far all okay
BUT, problem is, mouse is already on the one image so onmouseenter triggers again. I want it to trigger only if mouse came from outside of image without jQuery
Just like the Chat icon here on bottom-right
document.getElementById("one").onmouseenter = function onmouseoverRobot() {
document.querySelector("#two").style = 'display:inline-block !important'
document.querySelector("#one").style = 'display:none !important'
}
document.getElementById("two").onclick = function X_CHAT_01() {
document.querySelector("#two").style = 'display:none !important'
document.querySelector("#one").style = 'display:inline-block !important'
}
<img id='one' src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSoMUKwCL1uINRV035jkpfQzAbiObKqraXA6369mZBe0To0UuWP'>
<img id='two' style='display:none' src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSMYIpY4d8KlTzhAd38KZW8DIadeEV59WtLlxeIH3PS4uPXL0RP'>
In order to avoid the mouseenter event firing when you show the image try removing the listener and then adding it back after a mouseleave event.
img#one:mouseenter - Remove mouseenter listener from img#one. Hide img#one and show img#two.
img#two:click - Show img#one and hide img#two.
img#one:mouseleave - Add mouseenter listener to img#one.
You can also use one-time listeners for a simpler flow.
const onMouseEnter = function() {
hide(one)
show(two)
two.addEventListener("click", onClick, { once: true })
}
const onClick = function() {
one.addEventListener("mouseleave", onMouseLeave, { once: true })
hide(two)
show(one)
}
const onMouseLeave = function() {
one.addEventListener("mouseenter", onMouseEnter, { once: true })
}
one.addEventListener("mouseenter", onMouseEnter, { once: true })
The simplest solution that doesn't require event listeners mangling is to add a boolean indicator that tells if the chat has been enabled or not.
var chatEnabled = false;
var one = document.getElementById('one');
var two = document.getElementById('two');
one.onmouseenter = function onmouseoverRobot() {
if (chatEnabled) {
return;
}
two.style = 'display:inline-block !important';
one.style = 'display:none !important';
};
one.onmouseout = function onmouseoutRobot() {
chatEnabled = false;
};
two.onclick = function X_CHAT_01() {
chatEnabled = true;
two.style = 'display:none !important';
one.style = 'display:inline-block !important';
};
Please, take a look at the demo.

Javascript click event requires double clicks

I have a simple HTML-CSS-JavaScript page with an event listener on a button to toggle a div.
However, all is working but the animation function takes two clicks first time to work, although i consoled the click event to prove that the button listens to the first click too.
i tried to wrap into window.onload but same thing.
note: i want to use pure javascript only.
thank you
this pic shows the first click (it says "clicked" in the console):
this pic shows the second click (animation took place):
Here is my code:
var showDivButton = document.getElementById('showDivButton');
var info = document.getElementById('info');
showDivButton.addEventListener('click', animation) ;
// animation func
function animation () {
console.log('Clicked!');
if (info.style.display === 'none'){
info.style.display = 'inline-block';
showDivButton.style.background = 'green';
} else {
info.style.display = 'none';
showDivButton.style.background = 'gray';
}
}
Look at My Plunker Here please. Thank you in advance.
Try to revise your function block as follow:
function animation () {
console.log('Clicked!');
if (info.style.display == '' || info.style.display == 'none'){
info.style.display = 'inline-block';
showDivButton.style.background = 'green';
} else {
info.style.display = 'none';
showDivButton.style.background = 'gray';
}
}
info.style.display is '' on initial
Because info.style.display refers to the style attribute of your div, not the computed Style, so on the first click, this is not set.
You may want to look at getComputedStyle, but i would advise switching class instead of directly modifying style.

Categories