i am trying to close let´s say Dropdown A automatically, when Dropdown B gets classList.toggle("active) (in this case i toggle the ClassList with a Click)
I can open (classList.toggle("active)) and close (classList.toggle("inactive)) it manually, but i want to close it automatically.
Right now i got this:
function dropdown() {
let employerBranding = document.querySelector(".employer-branding");
let marketing = document.querySelector(".marketing");
let corporateOverall = document.querySelector(".corporate-overall");
let technicalData = document.querySelector(".technical-data");
let categoryModules = [employerBranding, marketing, corporateOverall, technicalData];
let categoryDropdown = $(".category-dropdown");
for (let i = 0; i < categoryModules.length; i++) {
categoryModules[i].addEventListener("click", function () {
categoryDropdown.slideDown();
});
}
}
dropdown();
The Problem is now: when i click on one of the 4 Modules of course it opens all of the Dropdowns.
How can i trigger the correct Dropdown to the correct Module, so only one (the one below the clicked Module) opens up
&&
How can i add with another click a .slideUp() to slide it up again?
Here is a very basic example of what you want to achieve:
const one = document.querySelector('#one');
const two = document.querySelector('#two');
const toggle = (e) => {
if (e.target.id === 'one') {
one.classList.toggle('active');
two.classList.remove('active');
} else {
two.classList.toggle('active');
one.classList.remove('active');
}
}
one.addEventListener('click', (e) => toggle(e));
two.addEventListener('click', (e) => toggle(e));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
display: inline;
margin: 20px;
padding: 100px;
background-color: #444;
}
.active {
padding: 200px 100px;
}
</style>
</head>
<body>
<div id="one"></div>
<div id="two"></div>
</body>
</html>
Generally (and especially if creating more dropdowns), I would suggest a more sophisticated approach involving looping through all of them, such as Rounin mentioned.
Whenever a dropdown is activated with a click:
Close all the dropdowns (ie. loop through the dropdowns and set each to .inactive)
Open the activated dropdown
After a little while a came up with this solution
function closeDropdown() {
// let employerBrandingDropdown = document.querySelector(".employer-branding-dropdown");
let employerBrandingDropdown = $('.employer-branding-dropdown');
let marketingDropdown = $(".marketing-dropdown");
let corporateOverallDropdown = $(".corporate-overall-dropdown");
let technicalDataDropdown = $(".technical-data-dropdown");
let dropdownArray = [employerBrandingDropdown, marketingDropdown, corporateOverallDropdown, technicalDataDropdown];
window.addEventListener('mouseup', function (event) {
for (let i = 0; i < dropdownArray.length; i++) {
let categoryDropdown = dropdownArray[i];
if ($(event.target !== categoryDropdown) && $(event.target).parent() !== categoryDropdown) {
$(categoryDropdown).stop().slideUp();
}
}
})
}
Related
script which loads consecutive numeric values until 0 is encountered, then find the highest value among the given numbers my script below:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!---Napisz skrypt który pozwoli na wczytanie kolejnych wartości liczbowych aż do napotkania 0 następnie
wsród podanych liczb znajdź wartość największą-->
<script>
let tab = [], i = 0, max, min;
//wczytywanie danych
do
{
tab[i] = parseInt(prompt("Podaj jakąś wartość. \n Zero kończy wprowadzanie danych:"));
i++;
}
while(tab[i-1]);
max = tab[0]; min = tab[0];
for(i=1; i < tab.length-1; i++)
{
if(tab[i]>max) max = tab[i];
}
document.write()
</script>
</body>
</html>
How to fix it?
if,else it should show the biggest and the lowest typed number
you can do something like this
const numbers = []
while(true) {
const num = parseInt(prompt('Insert a number. zero to exit'))
if(num === 0){
break;
}
numbers.push(num)
console.log(`the max number entered is ${Math.max(...numbers)}`)
console.log(`the min number entered is ${Math.min(...numbers)}`)
}
Window.prompt() is easy to write in your code, but the experience it creates for the user can be quite disruptive. From the linked MDN documentation:
Dialog boxes are modal windows; they prevent the user from accessing the rest of the program's interface until the dialog box is closed. For this reason, you should not overuse any function that creates a dialog box (or modal window).
In the case of your question, making use of a number input provides multiple advantages (non-blocking, built-in validation, etc.)
Here's an example of using a number input element and keeping track of the user's input history, which allows for an always updated value for min and max as the user commits new values:
If you want to prevent input of duplicate values, you could use a Set instead of an array.
const numbersElm = document.getElementById('numbers');
const minElm = document.getElementById('min');
const maxElm = document.getElementById('max');
const input = document.querySelector('input');
const button = document.querySelector('button');
const state = {
numbers: [],
min: NaN,
max: NaN,
};
// Allow the user to commit values using the keyboard's Enter key:
input.addEventListener('keyup', (ev) => {
if (ev.key === 'Enter') handleCommit();
});
// Or by clicking the button:
button.addEventListener('click', handleCommit);
function updateOutput () {
numbersElm.textContent = state.numbers.join(', ');
if (Number.isFinite(state.min)) minElm.textContent = state.min;
if (Number.isFinite(state.max)) maxElm.textContent = state.max;
}
function parseInput () {
const trimmed = input.value.trim();
// Avoid invalid (or a lack of) input:
if (!trimmed) return NaN;
const number = Number(trimmed);
if (Number.isNaN(number)) return NaN;
// You can return the valid number now:
// return number;
// Or convert it to an integer first:
return parseInt(number, 10);
}
function handleCommit () {
const number = parseInput();
// Cancel if the input is not valid:
if (Number.isNaN(number)) {
// Select the value in the input
// so that the user can overwrite it easily (or modify it):
input.select();
return;
}
state.numbers.push(number);
state.min = Math.min(...state.numbers);
state.max = Math.max(...state.numbers);
updateOutput();
// Clear the input so that the user doesn't have to:
input.value = '';
input.focus();
}
* { box-sizing: border-box; } body, button { font-family: sans-serif; font-size: 1rem; } input[type="number"], #numbers { font-family: monospace; } button, input { font-size: 1rem; padding: 0.5rem; } #output { margin-bottom: 1rem; display: flex; flex-direction: column; gap: 1rem; }
<div id="output">
<div id="numbers">Commit a number to get started</div>
<div>Min: <span id="min"></span></div>
<div>Min: <span id="max"></span></div>
</div>
<input type="number" />
<button>Commit number</button>
let snare = new Audio (`snare.mp3`);
let kick = new Audio (`kick.mp3`);
let hihat = new Audio (`hihat.mp3`);
let arr =[snare,kick,hihat];
let divs = document.querySelectorAll(`div`);
let body = document.querySelector(`body`);
body.addEventListener(`keydown`,(e)=>{
if(e.key ===`d`){
console.log(`ITS ${e.key}`);
e.stopPropagation();
arr[0].play()
}
if(e.key ===`f`){
console.log(`ITS ${e.key}`)
arr[1].play()
}
if(e.key ===`g`){
console.log(`ITS ${e.key}`);
arr[2].play()
}
})
div {
width:50px;
height:50px;
border:1px solid red
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="music.css" type="text/css">
</head>
<body>
<div id="d">d</div>
<div id="f">f</div>
<div id="g">g</div>
<script src="music.js"></script>
</body>
</html>
Hello, currently I'm trying to make a drum kit , where you would press the button and a different type of sound would play. But I run into a problem where if I keep pressing the same button the previous EventListener wouldnt stop playing. So my question is whats the best way to solve this problem? For example , what I want to do is keep mashing the same F button, to get the sound played repeatedly. But right now it doesnt play if the previous sound hasnt ended. Any help is appreciated :)
I rewrite your script in another way to reach your goal. Here is my script:
let audiArr = [
{
source: "snare.mp3",
buttonKey: "d"
},
{
source: "kick.mp3",
buttonKey: "f"
},
{
source: "hihat.mp3",
buttonKey: "g"
}
];
let body = document.querySelector(`body`);
let currentAudio = [];
body.addEventListener(`keydown`,(e)=>{
playSound(e.key);
});
function playSound(keyArgu) {
let keyArr;
let audioContainer;
audiArr.forEach(ele => {
keyArr = ele.buttonKey;
if (keyArr == keyArgu) {
audioContainer = new Audio (ele.source);
currentAudio.push( audioContainer );
stopPlay(currentAudio);
audioContainer.play();
}
});
}
function stopPlay(currentAudioArgu) {
let lengVar = currentAudioArgu.length;
for (let index = 0; index < lengVar -1; index++) {
currentAudioArgu[index].pause();
}
}
I first grouped each key with the corresponding sound in an array of objects, then I used playSound() function to determine if the special key was pressed at first with the help of stopPlay() function pause other sounds and then play the sound that is related to this key. The role of currentAudio array is important to reach your goal, it stores the list of last audios and by pressing new key it pauses them.
Background information: I'm dealing with many divs and recording the data-id of the particular div that user has clicked on.
I'm not sure why the click listener doesn't log the very first time I click on a div but it does log every other time.
For example, if I navigate to the page and click on a div, the data-id doesn't get logged at all.
But when I click on another div, it does get logged. If I keep clicking on another div, it does get logged, and so on.
How can I fix it so that whenever I navigate to the page for the first time and click on a div, the data gets logged?
Here's my JS code:
let img = document.getElementsByClassName('item');
let userClicked = function () {
let attribute = this.getAttribute("data-id");
console.log("clicked " + attribute);
}
for(let i = 0; i < img.length; i++) {
img[i].addEventListener('click', userClicked, false);
}
In my view problem is somewhere else. Try checking if any other element overlaps or your JS is loading at right time. You can check sample code here. Paste it in separate html file and it will work perfectly file.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title>Image</title>
<style>
div {
background-color:#eaeaea;
margin-bottom:5px;
}
</style>
</head>
<body>
<div data-id="1" class="item">1 </div>
<div data-id="2" class="item">2 </div>
<div data-id="3" class="item">3 </div>
<div data-id="4" class="item">4 </div>
<script>
let img = document.getElementsByClassName('item');
let userClicked = function () {
let attribute = this.getAttribute("data-id");
console.log("clicked " + attribute);
}
for (let i = 0; i < img.length; i++) {
img[i].addEventListener('click', userClicked, false);
}
</script>
</body>
</html>
I have a group of images in my HTML with the ID's "Hole#" ex: "Hole1", "Hole2" ... "HoleN". These IMG tags are loading a locally stored image. My goal is to print an alert when one of the images is clicked.
I found another StackOverflow question that I thought would answer my question. I've incorporated it into my code below. Unfortunately it did not achieve the desired effect.
//Dynamically creates images
for (let i = 1; i <= NUM_HOLES; i++) {
let HoleID = `"hole${i}"`;
let HoleIDPic = `"holePic${i}"`;
holesString +=
`<div id=`+ HoleID + `>
<img id=` + HoleIDPic + ` src="" />
</div>`
}
window.onload = function() {
document.getElementById("img[id|=hole]").onclick = function()
{
alert("Clicked");
};
};
HTML:
<section id="holes">
</section>
replacing the code "img[id|=hole]" with "hole1" does work however (for hole1), So I've concluded its my syntax the ID selection.
The whole idea of using similar ids on all images is the wrong approach.
Use a common CSS class instead. Then, to find out which image was clicked, use a single delegate listener and make use of the event object that is automatically passed to your click handler. I'm showing you an example with buttons instead of images:
const buttonDiv = document.querySelector('.buttons');
// lets add some buttons
for (let i = 0; i < 5; i++) {
let button = document.createElement('button');
button.type = 'button';
button.className = 'button';
button.textContent = 'Button Number ' + i;
buttonDiv.appendChild(button);
}
// now let's add a delegate click listener on the div containing the buttons
buttonDiv.addEventListener('click', function(event) {
// in any event listener, the event object has a `target` property, telling you which element the event was raised on
// this allows us to only react in the click listener if the clicked element meets certain conditions
if (event.target.matches('button.button'))
console.log('you clicked on ' + event.target.textContent);
})
.buttons {
background-color: #f0f0f0;
padding: 10px;
}
<div class="buttons"></div>
Try this
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<section id="holes"></section>
<script>
loadImages(2);
function loadImages(NUM_HOLES){
const sectionHoles = document.getElementById('holes');
//Dynamically creates images
for (let i = 1; i <= NUM_HOLES; i++) {
let HoleID = `hole${i}`;
let HoleIDPic = `holePic${i}`;
let div = document.createElement('div');
let img = document.createElement('img');
div.id = HoleID;
img.id = HoleIDPic;
img.src = "someimage.png";
// put image element in div
div.appendChild(img);
// put div in section
sectionHoles.appendChild(div);
// adding event listener to the img element
document.getElementById(HoleIDPic).addEventListener('click', function(){
alert(HoleIDPic + 'clicked');
});
}
}
</script>
</body>
</html>
I'm building a small memory game. Where the user is presented by different objects that are displayed one at a time (which is done by an animation). The user can choose or not choose to click an object. The user is presented with a list indicating which objects should not be clicked, if the user clicks an object that should be clicked he gets one point. If the user decides to not click on a faulty object he should be rewarded one point as well. And the latter is my question, how can I control when the user doesn't click an object? My if statement right now only checks when the user actually clicks an object.
I'm aware that I need to move the verify function to my setTimout call for each object. But I'm not sure what to look for in the if statement?
function createShapes() {
var classes = [
"shape blue size200",
"shape size200 bluetriangle",
];
var id = [
"wrong",
"right",
];
var randomOrderArray = [];
for (i = 0; i < classes.length; i++) {
var randomElement = document.createElement("div");
randomElement.setAttribute("id", id[i]);
randomElement.setAttribute("class", classes[i]);
randomElement.classList.add();
randomOrderArray.push(randomElement);
}
// Calls shuffleArray
shuffleArray(randomOrderArray);
for (i = 0; i < randomOrderArray.length; i++) {
objectElement.appendChild(randomOrderArray[i]);
}
}
// Adds eventlisteners to shapes
var objects = document.querySelectorAll(".shape");
for (i = 0; i < objects.length; i++) {
objects[i].addEventListener("click", verifyShapes);
});
}
let counter = 0;
// Verifies clicked objects
function verifyShapes() {
if (this.id == "right") {
points++;
this.removeEventListener("click", verifyShapes);
counter++;
}
}
HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>.....</title>
<body>
<div class="content" id="content"></div>
<div class="object" id="object"></div>
</body>
</html>