I am currently creating a web application.One of the function is to allow the users to create a div and assign a label to it which will be added to the class.The label name will then be displayed at the side based on the div's class name.Problem is I want to change the label name when I change the 's class name.I am unable to change the label for just one if i have multiple divs.
I am using event.target to get the clicked but if clicked on 2 divs separately,both are still selected and both class name will change.
//assign label and display it on the sides
$("#boxContain").click(function (event) {
console.log(event.target.nodeName);
$("#labels").on("change", function () {
var modal = document.getElementById('lblList');
if ($(event.target).attr('name') == null) {
var e = document.getElementById("labels");
var strUser = e.options[e.selectedIndex].text;
console.log(strUser);
var btn = document.getElementById("submitLbl"); //get submit btn
btn.onclick = function () {
event.target.setAttribute('name', strUser); //set the div name to the label
$(event.target).addClass(strUser);
var p = document.createElement("p");
$(p).text(strUser);
$(p).attr('id', strUser);
$(p).attr('class', 'lbl');
$(p).addClass(strUser);
$("#existingLbl").append(p);
modal.style.display = "none";
$('#labels')[0].selectedIndex = 0;
}
} else {
event.target.removeAttribute('ondblclick');
}
});
});
//Edit labels
function edit(e) {
var classname = e.className.split(' ')[4];
return classname;
};
$('#createBoxBtn').click(function () {
$('.box').click(function () {
var currentLbl = edit(this);
console.log(currentLbl);
var element = this;
$('#editLblBtn').on('click', function () {
document.getElementById('errorMessage').style.display = "none";
var modal = document.getElementById('lblList');
var span = document.getElementsByClassName("close")[0];
var btn = document.getElementById('submitLbl');
var edit = document.getElementById('editLbl');
btn.style.display = "none";
edit.style.display = "block";
modal.style.display = "block";
$('#labels').on('change', function () {
var list = document.getElementById("labels");
var newLbl = list.options[list.selectedIndex].text;
$(edit).on('click', function () {
var p = document.getElementById(currentLbl);
if ($(p).attr('id') == currentLbl) {
$(p).text(newLbl);
$(p).removeClass(currentLbl);
$(p).addClass(newLbl);
$(p).attr('id', newLbl);
$(element).removeClass(currentLbl);
$(element).addClass(newLbl);
$(element).attr('name', newLbl);
$('#labels')[0].selectedIndex = 0;
} else if ($(p).attr('id') == "Copyof" + currentLbl) {
$(p).text(newLbl);
$(p).removeClass(currentLbl);
$(p).addClass(newLbl);
$(p).attr('id', 'Copyof' + newLbl);
$(element).removeClass(currentLbl);
$(element).addClass('Copyof' + newLbl);
$(element).attr('name', newLbl);
$('#labels')[0].selectedIndex = 0;
}
}); //end of edit
}); //end of #labels
span.onclick = function () {
modal.style.display = "none";
};
edit.onclick = function () {
modal.style.display = "none";
};
window.onclick = function (event) {
if (event.target == modal) {
modal.style.display = "none";
}
};
$('#labels')[0].selectedIndex = 0;
}); //end of #editLblBtn
}); //end of .box
}); //end of #createBoxBtn
When I edit the label,the div's classname AND name should change to a new label and the corresponding p tag should change as well.What should I do to achieve this?Is there any way to clear the data stored in event when I click on different elements?
Related
I'm not sure if is this what i need but i think its neccesery. Propably i need add another condition to this line
const div = document.querySelector(`#result_${i}`);
I have simple .js file with array of object. Currently every object has question, answer. I would like to expand it by "text" where i would tell some details about results etc.
//For Text
const text = document.createElement("div");
text.id = "text_" + i;
text.style.display = "none";
text.classList.add("pokus");
text.innerHTML = ex.text;
card.appendChild(text);
Logic is same as for answer. I can see it in the DOM but it's it's not showing for user. I think the reason is missing condition in querySelector? If yes. How can i add another? I tried (`#result_${i}, #text_$(i)`) or (`#result_${i}`, `#text_${i}`);
Whole code.
import("./Objects/" + selectedPage + ".js")
.then((array) => {
const { examples } = array;
console.log(array);
function toggle(i) {
const div = document.querySelector(`#result_${i}`);
if (div.style.display !== "none") {
div.style.display = "none";
} else {
div.style.display = "block";
}
}
const container = document.querySelector("#examples-container");
examples.forEach((ex, i) => {
const card = document.createElement("div");
card.classList.add("card");
const example = document.createElement("div");
example.classList.add("example");
example.innerHTML = ex.question;
card.appendChild(example);
//For Button
const button = document.createElement("button");
button.classList.add("toggle");
button.innerHTML = "výsledek";
button.addEventListener("click", () => toggle(i));
card.appendChild(button);
//For answer
const result = document.createElement("div");
result.id = "result_" + i;
result.style.display = "none";
result.classList.add("result");
result.innerHTML = ex.answer;
card.appendChild(result);
//For Text
const text = document.createElement("div");
text.id = "text_" + i;
text.style.display = "none";
text.classList.add("pokus");
text.innerHTML = ex.text;
card.appendChild(text);
// Add the card to the container
container.appendChild(card);
});
})
.catch((err) => {
console.log(err);
});
Im not 100% sure I understand your question, but right now you're using QuerySelector and it will only return the first element.
If you want to select multiple elements use QuerySelectorAll / getElementByClassName and then loop over the list they return.
Use querySelectorAll
As you want to target more than 1 node (here result, text) you need to use querySelectorAll instead of querySelector
function toggle(i) {
const divs = document.querySelectorAll(`#result_${i}`,`#text_${i}`);
for (let div of divs) {
if (div.style.display !== "none") {
div.style.display = "none";
} else {
div.style.display = "block";
}
}
}
I've written a simple code that takes text from the input field, stores it as a string in an array and creates a div with that same text every time the "add" button is pressed.
Then there's a "remove" button, that removes the item from array if the input matches the item in the array.
I need a function to remove the previously created div with the same text inside as the current input.
E.g. if I type "book1" press "add" - array gets 'book1' as a first item and a div "book1" is created, "book2", "book3" and so on. If I type 'book2' and press remove, it gets removed from the array and a respective div should be removed.
That last function I just can't figure out.
let addBtn = document.getElementById("add-btn");
let removeBtn = document.getElementById("rmv-btn");
let bookArray = [];
addBtn.addEventListener("click", addBook);
removeBtn.addEventListener("click", removeBook);
let innerDiv = document.body.newDiv.innerHTML
function addBook() {
newBook = document.getElementById("input").value;
if (newBook != '') {
bookArray.push(newBook);
addElement();
clear();
console.log(bookArray);
} else {
clear();
console.log(bookArray);
}
}
function removeBook() {
inputBook = document.getElementById("input").value;
for (i = 0; i < bookArray.length; i++) {
if (inputBook.toString() === bookArray[i].toString()) {
bookArray.splice([i], 1);
console.log(bookArray);
removeElement()
return;
} else {
clear();
}
}
console.log(bookArray);
}
function clear() {
document.getElementById("input").value = "";
}
function addElement() {
let newDiv = document.createElement("div");
newDiv.innerHTML = newBook;
my_div = document.getElementById("mydiv");
document.body.appendChild(newDiv, my_div);
}
function removeElement() {
alert("this bit needs working out");//???
}
<input type="text" id="input" />
<button id="add-btn">Add</button>
<button id="rmv-btn">Remove</button>
<div id="mydiv"></div>
</div>
You need to change how you are adding the div because it adding it outside and not as a child of my_div
let addBtn = document.getElementById("add-btn");
let removeBtn = document.getElementById("rmv-btn");
let bookArray = [];
addBtn.addEventListener("click", addBook);
removeBtn.addEventListener("click", removeBook);
function addBook() {
newBook = document.getElementById("input").value;
if (newBook != '') {
bookArray.push(newBook);
addElement();
clear();
console.log(bookArray);
} else {
clear();
console.log(bookArray);
}
}
function removeBook() {
inputBook = document.getElementById("input").value;
for (i = 0; i < bookArray.length; i++) {
if (inputBook.toString() === bookArray[i].toString()) {
bookArray.splice([i], 1);
console.log(bookArray);
removeElement(i);
return;
} else {
clear();
}
}
console.log(bookArray);
}
function clear() {
document.getElementById("input").value = "";
}
function addElement() {
let newDiv = document.createElement("div");
// count number of children in mydiv
let count = document.getElementById("mydiv").childElementCount;
// add an id
newDiv.id = 'mydiv-' + count;
newDiv.innerHTML = newBook;
my_div = document.getElementById("mydiv");
my_div.appendChild(newDiv, my_div);
}
function removeElement(el) {
// remove html element from dom
let my_div = document.getElementById("mydiv");
my_div.removeChild(my_div.childNodes[el]);
}
A workaround to remove book by the input value by user:
Modify the addElement function to:
function addElement() {
let newDiv = document.createElement("div");
newDiv.innerHTML = newBook;
newDiv.setAttribute('data-book-name', newBook); //new added line | setting data attribute
my_div = document.getElementById("mydiv");
document.body.appendChild(newDiv, my_div);
}
removeElement will be:
function removeElement() {
document.querySelector('[data-book-name="'+ newBook +'"]')?.remove();
}
But this will remove first book in the DOM. If you want to remove all books with same name use:
function removeElement() {
var books = document.querySelectorAll('[data-book-name="'+ newBook +'"]');
if(books.length == 0) return;
books.forEach(x => x.remove())
}
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 a page with three tables (Table A, Table B, Table C), which I want to display depending on which button the user clicks. I am able to do this just fine with the following script:
var tableA = document.getElementById("tableA");
var tableB = document.getElementById("tableB");
var tableC = document.getElementById("tableC");
var btnTabA = document.getElementById("showTableA");
var btnTabB = document.getElementById("showTableB");
var btnTabC = document.getElementById("showTableC");
btnTabA.onclick = function () {
tableA.style.display = "table";
tableB.style.display = "none";
tableC.style.display = "none"; }
btnTabB.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "table";
tableC.style.display = "none"; }
btnTabC.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "none";
tableC.style.display = "table"; }
However, I also want to include the html code for these tables into this page. I am also able to do this with the following script:
$(function(){ $("#include-tables").load("P1/1_0/table.html"); });
That said I cannot get these to work together. For example, when I combine all of this -- see sample code below -- my tables are included, but the buttons no longer work. If I check the error log in the browser, it says Null is not a object, and so I think the issue is to due with all variables and Id's being defined before the code for the button executes. That said with my (very) limited knowledge of javascript I am have not been able to figure out how to resolve this.
$(function(){
$("#include-tables").load("/1_0/tables.html");
});
var tableA = document.getElementById("tableA");
var tableB = document.getElementById("tableB");
var tableC = document.getElementById("tableC");
var btnTabA = document.getElementById("showTableA");
var btnTabB = document.getElementById("showTableB");
var btnTabC = document.getElementById("showTableC");
btnTabA.onclick = function () {
tableA.style.display = "table";
tableB.style.display = "none";
tableC.style.display = "none";
}
btnTabB.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "table";
tableC.style.display = "none";
}
btnTabC.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "none";
tableC.style.display = "table";
}
#tableA {
}
#tableB {
display: none;
}
#tableC {
display: none;
}
<div id="include-tables"></div>
<div class="button-div">
<input type="button" id="showTableA" value="TableA">
<input type="button" id="showTableB" value="TableB">
<input type="button" id="showTableC" value="TableC">
</div>
<script src="script.js"></script>
.load() is asynchronous, so you can't access the elements until after it completes. Put all your code in its callback function.
$(function(){
$("#include-tables").load("/1_0/tables.html", function() {
var tableA = document.getElementById("tableA");
var tableB = document.getElementById("tableB");
var tableC = document.getElementById("tableC");
var btnTabA = document.getElementById("showTableA");
var btnTabB = document.getElementById("showTableB");
var btnTabC = document.getElementById("showTableC");
btnTabA.onclick = function () {
tableA.style.display = "table";
tableB.style.display = "none";
tableC.style.display = "none";
}
btnTabB.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "table";
tableC.style.display = "none";
}
btnTabC.onclick = function () {
tableA.style.display = "none";
tableB.style.display = "none";
tableC.style.display = "table";
}
});
});
Or you could use event delegation to bind event handlers to dynamically-added elements. See Event binding on dynamically created elements?
I am looking for a way to simplify this code using for loops. Any help is appreciated.
I am setting up a system of opening modal frames full of images when somebody clicks on a link with a date on it (e.g. a photo archive). I have a lot of different dates and each time I make a new one I have to insert it a million times into the code as shown below. Maybe I could make an array of some sort that holds the dates and loop through the array and generate the code below. There is probably a simple fix to this, but I am new to web development. Thanks!!!!
// Get the modal gallery
var gallery161207 = document.getElementById('gallery161207');
var gallery161130 = document.getElementById('gallery161130');
...
var gallery150916 = document.getElementById('gallery150916');
// Get the close button
var closeButton161207 = document.getElementById('closeModal161207');
var closeButton161130 = document.getElementById('closeModal161130');
...
var closeButton150916 = document.getElementById('closeModal150916');
// Get the buttons
var btn161207 = document.getElementById('161207');
var btn161130 = document.getElementById('161130');
...
var btn150916 = document.getElementById('150916');
// When the user clicks on the button, open the modal gallery
function openGallery(source) {
// Open the modal gallery depending on what was clicked
if (source == '161207')
gallery161207.style.display = "block";
if (source == '161130')
gallery161130.style.display = "block";
...
if (source == '150916')
gallery150916.style.display = "block";
}
// When the user clicks on <span> (x), close the modal
closeButton161207.onclick = function() {
gallery161207.style.display = "none";
}
closeButton161130.onclick = function() {
gallery161130.style.display = "none";
}
...
closeButton150916.onclick = function() {
gallery150916.style.display = "none";
}
btn161207.onclick = function() { openGallery('161207'); }
btn161130.onclick = function() { openGallery('161130'); }
...
btn150916.onclick = function() { openGallery('150916'); }
window.onclick = function(event) {
if (event.target == gallery161207) {
closeButton161207.onclick();
}
if (event.target == gallery161130) {
closeButton161130.onclick();
}
...
if (event.target == gallery150916) {
closeButton150916.onclick();
}
}
You could do this fairly easily using jQuery, but I assume, since you're new to web development, you'll want to start out from scratch.
First, let's deal with setting up the buttons to show the galleries. I'd say you give each button a class="gallery-button" attribute and an id="<id of gallery>". The galleries also should have IDs id="gallery-<id of gallery>". Then:
var buttons = document.getElementsByClassName("gallery-button");
for(var i =0; i < buttons.length; i++){
var elem = buttons[i];
elem.onclick = function() {
document.getElementById('gallery' + elem.id).style.display="block";
};
}
}
We can do a similar thing for the close buttons (assuming they have IDs of id="close-<id of gallery>" and their class="close-button":
var closeButtons = document.getElementsByClassName("close-button");
for(var i =0; i < buttons.length; i++){
var elem = closeButtons[i];
elem.onclick = function() {
document.getElementById('gallery-' + elem.id.replace("close-", "")).style.display="none";
};
}
}
And then:
window.onclick = function(event) {
var id = event.target.id;
if (id.startsWith("gallery-") {
var closeButton = document.getElementById("close-" + id.replace("gallery-", ""));
closeButton.onclick();
}
}
You can try making an object saving all the dom references and using those. This answer makes use of jQuery for its document ready function.
var sourceList = [];
var sources = {};
var wrappers = document.getElementsByClassName('gallery-wrapper');
for(var i = 0; i < wrappers.length; i++){
sourceList.push(wrappers[i].id);
}
$( document ).ready(function() {
for(var i = 0; i < sourceList.length; i++){
var source = {};
source.gallery = document.getElementById("gallery"+sourceList[i]);
source.button = document.getElementById("button"+sourceList[i]);
source.closeButton = document.getElementById('closeButton'+sourceList[i]);
source.button.onclick = function() {
if(source.gallery)source.gallery.style.display = "block";
}
source.closeButton.onclick = function() {
if(source.gallery)source.gallery.style.display = "none";
}
sources[sourceList[i]] = source;
}
window.onclick = function(event) {
for (var source in sources)
if (event.target == sources[source].gallery)
sources[source].closeButton.onclick();
}
});