var x = ["s1","s2","s3","s4","s5","s6","s7","s8","s9","s10","s11",......,"s100"];
for (var i = 0; i < x.length; i++) {
document.getElementById(x[i]); }
var c = document.getElementById(x);
var a = document.getElementById("s2");
var b = document.getElementById("hover");
c.addEventListener('mouseover', function() {
b.style.display = "block";
});
c.addEventListener("mouseout", function() {
b.style.display = "none";
});
I have gallery of 100pictures, that needs mouseover action, so I wanted to use array like Id selector,and as you see I am not quite sure how to do this :D, so if anyone could help me a would be very thankful.
Related
I have a photo gallery in JavaScript, using Nuxt.js. For more information, see this post.
Here is the new code :
// Open PopUp
const photoGalleryFullscreen = document.querySelector(".photo-gallery-fullscreen");
const imagesFullscreen = document.querySelectorAll(".slide-container img");
for (let i = 0; i < imagesFullscreen.length; i++) {
photo[i].onclick = function() {
photoGalleryFullscreen.style.display = "block";
imagesFullscreen[i].style.display = "block";
slideIndex = i;
}
// Close PopUp
document.querySelector(".out").onclick = function() {
photoGalleryFullscreen.style.display = "none";
imagesFullscreen[i].style.display = "none";
slideIndex = 1;
};
}
In the last part of the new code (//Close PopUp) this is not working (the rest is working), if you can help (thank you very much) :
imagesFullscreen[i].style.display = "none";
On contrary, if I set manually i, it is working for the selected image
I just had to determine which image is clicked and save it in a variable.
Here is the new code that is working :
const photoGalleryFullscreen = document.querySelector(".photo-gallery-fullscreen");
const imagesFullscreen = document.querySelectorAll(".slide-container img");
for (let i = 0; i < imagesFullscreen.length; i++) {
// Open PopUp
photo[i].onclick = function() {
photoGalleryFullscreen.style.display = "block";
imagesFullscreen[i].style.display = "block";
globalThis.imageClickedNumber = i;
slideIndex = i;
document.body.setAttribute("class", "disable-scroll");
}
// Close PopUp
document.querySelector(".out").onclick = function() {
if (imagesFullscreen[imageClickedNumber].style.display == "block") {
photoGalleryFullscreen.style.display = "none";
imagesFullscreen[imageClickedNumber].style.display = "none";
slideIndex = 1;
document.body.removeAttribute("class");
}
};
}
I have this code, repeating 20 times with only change of variables prefix. How can i possibly make a loop and iterate by it to avoid this huge block of code?
It is used in my website and I want to make the development process more clear.
var keepElements = document.getElementsByName("keep-type");
for(var i = 0; i < keepElements.length; i++){
keep = document.getElementById(keepElements[i].value);
if(keepElements[i].checked == true){
keep.style.display = "block";
}
else{keep.style.display = "none";}
}
var offworkshopElements = document.getElementsByName("offworkshop-type");
for(var i = 0; i < offworkshopElements.length; i++){
offworkshop = document.getElementById(offworkshopElements[i].value);
if(offworkshopElements[i].checked == true){
offworkshop.style.display = "block";
}
else{offworkshop.style.display = "none";}
}
var defworkshopElements = document.getElementsByName("defworkshop-type");
for(var i = 0; i < defworkshopElements.length; i++){
defworkshop = document.getElementById(defworkshopElements[i].value);
if(defworkshopElements[i].checked == true){
defworkshop.style.display = "block";
}
else{defworkshop.style.display = "none";}
}
Move the logic to a function:
function keepElements(name) {
var keepElements = document.getElementsByName(name);
for (var i = 0; i < keepElements.length; i++) {
keep = document.getElementById(keepElements[i].value);
if (keepElements[i].checked == true) {
keep.style.display = "block";
}
else { keep.style.display = "none"; }
}
}
keepElements("keep-type");
keepElements("offworkshop-type");
keepElements("defworkshop-type");
If I didn't miss any details, you're repeating the same block 3 times:
["keep-type", "offworkshop-type", "defworkshop-type"].forEach(name => {
var elements = document.getElementsByName(name);
for(var i = 0; i < elements.length; i++){
element = document.getElementById(elements[i].value);
if(elements[i].checked == true){
element.style.display = "block";
}
else{element.style.display = "none";}
}
});
I prefer the array / forEach syntax, because the block starts with the list of name. But you could use a for...of loop instead.
for (const name of ["keep-type", "offworkshop-type", "defworkshop-type"]) {
var elements = document.getElementsByName(name);
for(var i = 0; i < elements.length; i++){
element = document.getElementById(elements[i].value);
if(elements[i].checked == true){
element.style.display = "block";
}
else{element.style.display = "none";}
}
}
The answers saying you should put the common functionality into a single function are absolutely right.
I just wanted to add that there are also solutions on the query side of things:
you could have all the elements be collected in one javascript function, querySelectorAll()
const elements = document.querySelectorAll('[name="keep-type"], [name="offworkshop-type"], [name="defworkshop-type"]')
Alternatively you could give them all the same class and select by that class.
const elements = document.getElementsByClassName("requiredElements");
And this way you have all your elements in one array.
var my_toggle = document.getElementsByClassName('my_toggle');
var my_toggle_button = document.getElementsByClassName('my_toggle_button');
var my_toggle_array = [];
var i;
for(i = 0; i < my_toggle.length; i++){
//my_toggle_array.push(0);
my_toggle[i].style.display = "none";
my_toggle_button[i].addEventListener("click", function(){
if(my_toggle[i].style.display == "none" /* || my_toggle_array[i] == 0 */){
my_toggle[i].style.display = "block";
my_toggle_button[i].innerHTML = "- show less";
//my_toggle_array[i] = 1;
} else {
my_toggle[i].style.display = "none";
my_toggle_button[i].innerHTML = "+ show more";
//my_toggle_array[i] = 0;
}
});
}
<div class="my_toggle">
<p class="lead"></p>
</div>
<button class="my_toggle_button"></button>
<!-- and so on 11 times <div class="my_toggle><p class="lead"></p></div><button class="my_toggle_button"></button> -->
This code doesn't work when I upload it in cPanel or at least not all of it, it works until these lines
for(i = 0; i < my_toggle.length; i++){
//my_toggle_array.push(0);
my_toggle[i].style.display = "none";
So basically the eventListener doesn't work, I tried like 2 hours in a script tag inside the page I wanted to do this toggle in but didn't work, then I put this code inside an external js file and I get like an error message "do not use functions inside a loop", why not using functions inside a loop?I commented out this code and used like this code which works but is way too long...
var my_toggle = document.getElementsByClassName('my_toggle');
var my_toggle_button = document.getElementsByClassName('my_toggle_button');
var my_toggle_id = [];
var my_toggle_button_id = [];
var i;
for(i = 0; i < my_toggle.length; i++){
my_toggle[i].setAttribute("id", "my_toggle_" + i.toString());
my_toggle_id.push("my_toggle_" + i.toString());
my_toggle_button[i].setAttribute("id", "my_toggle_button_" + i.toString());
my_toggle_button_id.push("my_toggle_button_" + i.toString());
}
function function1(){
let x = document.getElementById(my_toggle_id[0]);
let y = document.getElementById(my_toggle_button_id[0]);
if (x.style.display === "none") {
x.style.display = "block";
y.innerHTML = "- mostra di meno";
} else {
x.style.display = "none"; y.innerHTML = "+ scopri di più";
}
}
/* [...] and so on until */
function function11(){
let x = document.getElementById(my_toggle_id[10]);
let y = document.getElementById(my_toggle_button_id[10]);
if (x.style.display === "none") {
x.style.display = "block";
y.innerHTML = "- mostra di meno";
} else {
x.style.display = "none"; y.innerHTML = "+ scopri di più";
}
}
How can I add the EventListener to all classes without writing 130 lines of code?Is javascript the problem?Should I use PHP perhaps?Why?
The problem here is use of var.
The var statement declares a function-scoped or globally-scoped variable
Read about var and let
When you declare var i , increment it inside the loop to make it 1 and then click function is called, the value of i remains 1 and hence my_toggle[i] becomes undefined and my_toggle[i].style would throw an error "Cannot read property 'style' of undefined". Use let for your index i to keep it block scoped. See below code:
<!DOCTYPE html>
<head>
<title>The Alphabet</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class="my_toggle">
<p class="lead">And so on 11 times</p>
</div>
<button class="my_toggle_button"></button>
</body>
<script type="text/javascript">
var my_toggle = document.getElementsByClassName('my_toggle');
var my_toggle_button = document.getElementsByClassName('my_toggle_button');
var my_toggle_array = [];
for(let i = 0; i < my_toggle.length; i++){
//my_toggle_array.push(0);
my_toggle[i].style.display = "none";
my_toggle_button[i].addEventListener("click", function(){
if(my_toggle[i].style.display == "none" /* || my_toggle_array[i] == 0 */){
my_toggle[i].style.display = "block";
my_toggle_button[i].innerHTML = "- show less";
//my_toggle_array[i] = 1;
} else {
my_toggle[i].style.display = "none";
my_toggle_button[i].innerHTML = "+ show more";
//my_toggle_array[i] = 0;
}
});
}
</script>
</html>
I am trying to create an array of a parent div's (id="lol") children and them fetch them to change display:none; except for the child with id="a". I've tried this but it doesn't work. How can I improve this to get it to work?
function myFunction() {
var x = document.getElementById('a');
var children = [].slice.call(document.getElementById('lol').getElementsByTagName('*'),0);
var arrayLength = children.length;
for (var i = 0; i < arrayLength; i++) {
var name = children[i].getAttribute('id');
var z = document.getElementById(name);
z.style.display = 'none';
}
x.style.display = 'block';
}
If every child has an id attribute than it will work. Otherwise, some children might not have id attribute, in that case variable z will be undefined and accessing style property over z which is undefined will give error. Simple fix would be just handling undefined variable:
if(z)
z.style.display = 'none';
Same goes with variable x, too.
function myFunction() {
var children = [].slice.call(document.getElementById('lol').getElementsByTagName('*'),0);
var arrayLength = children.length;
for (var i = 0; i < arrayLength; i++) {
children[i].style.display = 'none';
}
document.getElementById('a').style.display = 'block';
}
How about using jQuery?
$('#lol').children(':not(#a)').hide();
If jQuery is not an option you can do this:
var lol = document.getElementById('lol');
var children = lol.querySelectorAll(':not(#a)');
for(var i=0;i<children.length;i++) {
children[i].style.display = 'none';
}
Even more "low-level":
var lol = document.getElementById('lol');
var children = lol.childNodes;
for(var i=0;i<children.length;i++){
if(children[i].id != 'a') {
children[i].style.display = 'none';
}
}
I have a table with a background image that, when clicked, displays other images for the user to choose from. This is working and appears or hides on click events. However, when the user clicks to add a second image the menu of images appears again (as it should) but twice. I have commented out a solution I tried. I thought on first click I could display my_div and then delete it in allImages.onclick. This is throwing up a null error in Chrome, probably understandably. The problem here is similar. Hope I added link correctly. Anyway, advice or help appreciated.
function addImage(col) {
var img = new Image();
img.src = "../www/images/TEST.png";
col.appendChild(img);
img.onclick = function () {
var myImages = new Array();
myImages[0] = "../www/images/TEST3.png";
myImages[1] = "../www/images/TEST2.png";
myImages[2] = "../www/images/TEST4.png";
for (var i = 0; i < myImages.length; i++) {
var allImages = new Image();
allImages.src = myImages[i];
var newList = document.createElement("ul");
newList.appendChild(allImages);
my_div = document.getElementById("showPics");
my_div.appendChild(newList);
my_div.style.display = 'block';
allImages.onclick = function (e) {
img.src = e.target.src;
my_div.style.display = 'none';
//var element = document.getElementById("showPics");
//element.parentNode.removeChild(element);
};
}
};
};
for (r = 0; r < howOften; r++) {
row = table.insertRow(-1);
for (c = 0; c < numDays; c++) {
col = row.insertCell(-1);
addImage(col);
}
}
document.getElementById('holdTable').appendChild(table);
I modified your code adding ul to hold all img. It works, but could be better.
function addImage(col) {
var img = new Image();
img.src = "../www/images/TEST.png";
col.appendChild(img);
var myImages = new Array();
myImages[0] = "../www/images/TEST1.png";
myImages[1] = "../www/images/TEST2.png";
myImages[2] = "../www/images/TEST3.png";
var container = document.createElement("ul"); //ul to simplify hide/show
container.style.display = "none";
for (var i = 0; i < myImages.length; i++) {
var newList = document.createElement("li");
var im = document.createElement("img");
im.src = myImages[i];
newList.appendChild(im);
im.onclick = function () {
img.src = this.src;
};
container.appendChild(newList);
}
col.appendChild(container);
col.onclick = function () {
if (container.style.display == "none")
container.style.display = "block";
else
container.style.display = "none";
};
}