remove only the div inside the parent div - javascript

In this websites the user can add as much boxes as he wants, and every box contains a green and blue small boxes, the user should be able to click the blue box to remove the green box. the issue is that every time I click the blue box it doesn't remove the green box unless there is only one parent box is made. I have tried a lot of ways but nothing is working.
let count = 0;
function addBox() {
let box = `
<div class="box">
<div class="lbox" id="lbox">
</div>
<div class="rbox" id="rbox">
</div>
<h1>
${count}
</h1>
</div>
`
$(`#boxes`).append(box);
document.getElementById("lbox").addEventListener("click", function() {
rbox.remove();
})
count++;
}

If you have more than one parent box you need to iterate over each one.
You need to do something like;
let boxes = document.querySelectorAll('.box');
boxes.forEach(function(box){
box.querySelector('lbox').addEventListener('click',function(){
box.remove();
});
})
I haven't tested this, but the key part is the forEach function. This means everything you do inside the function is scoped to that box.

id must, at all times, be unique per-document. Learn about this very basic here: https://www.w3schools.com/hTML/html_id.asp. Your code keeps readding the same id values over and over, making your HTML invalid and your code dysfunctional.
Here's a working code example that doesn't rely on ids to get the job done:
let count = 0;
function addBox() {
let box = document.createElement('div');
box.className = 'box';
box.innerHTML = `
<div class="lbox">
</div>
<div class="rbox">
</div>
<h1>
${count}
</h1>`;
document.getElementById('boxes').appendChild(box);
box.querySelector('.lbox').addEventListener('click', function() {
box.querySelector('.rbox').remove();
})
count++;
}
.lbox, .rbox {
display: inline-block;
height: 40px;
width: 40px;
}
.lbox { background-color: blue; }
.rbox { background-color: green; }
<button onclick="addBox()">Add Box</button>
<div id="boxes"></div>

you need to define to delete the other box inside the same parent div.
I would delete the id because the defenition in class is the same.
I would also change the class names to something, wich makes visible what the green and what the blue box is.
You can do following:
let count = 0;
function addBox() {
let box = `
<div class="box_wrapper">
<div class="blue_box">
</div>
<div class="green_box">
</div>
<h1>
${count}
</h1>
</div>
`
$(`#boxes`).append(box);
$( ".blue_box" ).click(function() {
$(this).parent().find(".green_box").remove();
});
count++;
}

I think document.getElementById will always select the first element only with the given id. Therefore only the first lbox element in the dom keeps getting more and more eventlisteners attached to it, while the others won't get any. Make the id's of your elements unique by appending the count. That will make sure that every element gets it's eventlistener:
let count = 0;
function addBox() {
let box = `
<div class="box">
<div class="lbox" id="lbox${count}">
</div>
<div class="rbox" id="rbox${count}">
</div>
<h1>
${count}
</h1>
</div>
`;
$(`#boxes`).append(box);
document.getElementById("lbox" + count).addEventListener("click", function() {
$(".rbox" + count).remove();
})
count++;
}

Related

Toggle re-hides all divs; need parent div to remain visible

Apologies in advance, I'm not terribly familiar with Javascript, but I do understand what this code is doing and why it is causing me this problem. I'm just not sure how to go about solving it AT all.
On my webpage I have an open/close dialogue toggle which is the parent div, the dialogue box is hidden upon the page loading. Within this dialogue box are more hidden divs for the dialogue options. Problem is, when one of the dialogue options is clicked, the script hides the entire dialogue box, preventing any of the dialogue options from being seen, because it can only show one div at a time, regardless of its parent or child status. When a div is clicked, all other divs are re-hidden.
I need the parent div to remain visible until the dialogue box toggle is clicked again. The individual choices DO need to hide/unhide when another choice is clicked.
Not sure if I should include any CSS here, it's just styling the dialogue box and its buttons within.
<div id="dialogue" style="display:none;">
<div class="room">
Room description here. What do you do?
<div class="buttons">
Pet the cat.
<br>
<div id="cat" style="display:none;">aw yeah kitty time</div>
Turn on the radio.
<br>
<div id="radio" style="display:none;">
<br>
audio file and tracklist here
</div>
</div>
</div>
</div>
<span class="toggle">
[Open/close dialogue.]
</span>
<script type="text/javascript">
var divs = ["cat", "radio", "dialogue"];
var visibleDivId = null;
function divVisibility(divId) {
if(visibleDivId === divId) {
visibleDivId = null;
} else {
visibleDivId = divId;
}
hideNonVisibleDivs();
}
function hideNonVisibleDivs() {
var i, divId, div;
for(i = 0; i < divs.length; i++) {
divId = divs[i];
div = document.getElementById(divId);
if(visibleDivId === divId) {
div.style.display = "block";
} else {
div.style.display = "none";
}
}
}
</script>
I probably need a third function here because currently all the toggles are grouped together, hence why they're interacting like this, but I don't have the first clue how to accomplish this. I have been looking and haven't found anything that seems to match my needs.
Made a few corrections to your HTML so the href does not refresh the page on click. Also added in a few attributes (aria-controls) to track which div the button controls. I added comments to the JavaScript. There are plenty of Aria attributes they typically help with accessibility but they are super useful for keeping track of things in HTML and passing information to JavaScript.
//create a function to handle the click that takes in the event as a argument
function handleClick(event) {
//find out which div the button controls
const ariaControls = event.currentTarget.getAttribute("aria-controls"),
//select the controlled div
controlledAria = document.getElementById(ariaControls);
// if the controlled div is cat
if (ariaControls === "cat") {
// hide the radio div
document.getElementById("radio").classList.add("hide");
// if the controlled div is radio
} else if (ariaControls === "radio") {
// hide the car div
document.getElementById("cat").classList.add("hide");
}
//toggle the hide div on the controlled div
controlledAria.classList.toggle("hide");
}
//select all the buttons
const buttons = document.querySelectorAll("button");
//for each button add an event listener when the button is clicked run the handle click function
buttons.forEach(button => button.addEventListener("click", handleClick))
.hide {
display: none;
}
<div id="dialogue" class="hide">
<div class="room">
Room description here. What do you do?
<div class="buttons">
<button aria-controls="cat">Pet the cat.</button><br>
<div id="cat" class="hide">aw yeah kitty time</div>
<button aria-controls="radio">Turn on the radio.</button><br>
<div id="radio" class="hide">audio file and tracklist here
</div>
</div>
</div>
</div>
<span class="toggle"><button aria-controls="dialogue">[Open/close dialogue.]</button></span>

document.getElementById issues with for loop

My code fetches data from the backend API
for (var i = 0; i < myObj.length; i++) {}
stored object i want to display in variables and im able to display them accordingly
everything is fine until here
but I want to display the description in a popup
https://www.w3schools.com/howto/tryit.asp?filename=tryhow_js_popup
based on this tutorial I have implemented the same
html1 += ` <div class="popup" onclick="myFunction()">Click me to toggle the popup!
<span class="popuptext" id="myPopup">${desc}</span>
</div>
<p > ${desc}</p>
<script>
function myFunction() {
var popup = document.getElementById("myPopup");
popup.classList.toggle("show");
}</script>
`;
but when I clicked on it I expected different cards to show different data accordingly but instead, it's just showing the data of the first card element
when clicked on the second one only the first card element pops up with only that particular data of that card
I thought the issue could be because of ID so gave dynamic variables as id
but it's of no use When clicked nothing is coming up
not even error
is there any way where we can display dynamic data based upon the card in that popup
IDs must be unique
Use the loop number to make a unique call to the function, and give each span its own ID.
html1 += ` <div class="popup" onclick="myFunction('${i}')">Click me to toggle the popup!
<span class="popuptext" id="myPopup-${i}">${desc}</span>
</div>
<p > ${desc}</p>
and you only need one script block for all of them
<script>
function myFunction(id) {
var popup = document.getElementById("myPopup-"+id);
popup.classList.toggle("show");
}</script>
I think it's because you are reusing the same id. In html element IDs have to be unique. You could try to append a sequence number to id="myPopup" as you loop, e.g. id="myPopup1", id="myPopup2" etc...
The problem is because you are using the id property. For that reason the first object works and the others no, Javascript takes the id an use it for the first that find and it discart the others.
Try giving the action by class to every button. Something like this:
const buttons = [...document.querySelectorAll('.btn-toggle')]
buttons.forEach(button => button.addEventListener('click', e => click(e)))
const click = e => e.target.parentElement.children[1].classList.toggle('show')
.show {
color: red;
display: block!important;
}
.hide{
display: none
}
<div>
Hello from div 1
<button class="btn-toggle">Toggle</button>
<div class="hide">Toggle!</div>
</div>
<div>
Hello from div 2
<button class="btn-toggle">Toggle</button>
<div class="hide">Toggle!</div>
</div>
<div>
Hello from div 3
<button class="btn-toggle">Toggle</button>
<div class="hide">Toggle!</div>
</div>
As everyone wrote, id is to be unique to work properly.
If you change your css to react to .popup.show it would become more simple:
//REM: this = div.popup
function myFunction(div){
div.classList.toggle('show');
}
.popup span{
display: none
}
.popup.show span{
display: block
}
<div class = 'popup' onclick = 'myFunction(this)'>click<span>clicked</span></div>

Display elements only if they are filled with text, Empty rule not working

I have built a little filter application with a widget. Now I have some filter tags which show you what kind of filter options you have chosen. Now If there is no filter selected the tags must be hidden. I figured out how to do that with a javascript function. The css empty rule does not work with the widget.
But I cannot figure out how to make them visible again.
let divs = document.getElementsByClassName('display');
for (let x = 0; x < divs.length; x++) {
let div = divs[x];
let content = div.innerText.trim();
console.log("Trim Test" + content);
if (content == '') {
div.style.display = 'none';
}
else{
div.style.display = 'inline';
}
}
<div class="tags123">
<span id="display" class="display"> <p id="display1" class="display1"></p></span>
<span id="display" class="display"> <p id="display3" class="display3"></p></span>
<span id="display" class="display"> <p id="display2" class="display2"></p></span>
</div>
The if condition works, my tags are hidden. But the else condition does not seem to trigger If I enter something in the Tags.
I have attached two pictures to show the if condition is working. Do I have to enclose it with some event listener ? Thank you for your time.
It's not quite clear to me how your widget interacts with your markup, but a simple way to toggle the visibility of empty elements would be to filter out the ones with content and use a class that gets toggled on click, like so:
const btn = document.getElementById('btn');
const items = document.getElementsByClassName('foo');
btn.onclick = () => [...items]
.filter(i => !i.textContent)
.forEach(i => i.classList.toggle('hidden'));
.foo::after {
content: 'x';
border-radius: 50%;
background-color: grey;
}
.foo.hidden {
display: none;
}
<button id="btn">toggle visibilty</button>
<div>
<span class="foo">Text</span>
<span class="foo"></span>
<span class="foo"></span>
</div>

How to undo "this.onclick=null"? How to restore javascript onclick functionality to a div?

I am displaying a div with a default background color. When I click it once, it changes color. A second click does nothing, because the div has this code: "this.onclick=null". That much works well.
However, after I click the div once, I want to click a button to restore its onclick functionality. But the button I have created for that purpose doesn't work, because I don't know what javascript code to use. Does anyone know?
As you can see, I'm working with Bootstrap 3. (Please note that I am a beginner with only basic knowledge of php and js.) Here is my code:
HTML for the div:
<div class="row">
<div class="col-sm-12">
<div id="testDiv" style="background-color: #0000FF" onclick="colorClick(id); this.onclick=null;">
Clicking this div once changes the color.
</div>
</div>
</div>
JAVASCRIPT for the div:
function colorClick(id){
var randomColor = '#'+Math.floor(Math.random()*16777215).toString(16);  
document.getElementById(id).style.backgroundColor=randomColor;
/* The random color generator is from stackoverflow.com/questions/1484506/random-color-generator */
}
HTML for the button:
<div class="row">
<div class="col-sm-12">
    <button type='button' class='btn btn-default btn-lg' onclick=reEnableOnclick()>
This button should re-enable the onclick functionality, but it does not
</button>
</div>
</div>
JAVASCRIPT for the button:
function reEnableOnclick(){
document.getElementById("testDiv").onclick=click;  /* This is only pseudo-code. What real code should I put here? */
}
(Both js functions are in a separate .js document)
EDIT #2: This needs to work for about 100 divs on the same page.
Since you need to apply this functionality to 100s of divs, try keeping track of just the locked states rather than all the divs states at all times. Assuming each div id is unique you could try:
Javascript:
let locked = [];
function lockCheckRun(id) {
let divID = document.getElementById(id);
if (!locked.includes(divID) {
colorClick(id);
locked.push(divID);
}
}
function lockReset() {
locked.length = 0;
}
Explanation:
create an empty array to store locked element ids. We'll call this array 'locked'.
next, create a function which checks to see if the locked array includes the current unique element id. if it does not, then we will run your 'colorClick' function. once that completes, we will add the current element id to the 'locked' array via .push()
when you want to reset your locked element array, run the 'lockReset' function.
Optional Polyfill for comptability with older browsers:
if (!String.prototype.includes) {
String.prototype.includes = function(search, start) {
'use strict';
if (search instanceof RegExp) {
throw TypeError('first argument must not be a RegExp');
}
if (start === undefined) { start = 0; }
return this.indexOf(search, start) !== -1;
};
}
Assign the original onclick code.
function reEnableOnclick() {
document.getElementById("testDiv").onclick = "colorClick(id); this.onclick=null;";
}
You can have a pseudo variable inside your javascript code that serves the purpose
In this case you can write
HTML Code
<div class="row">
<div class="col-sm-12">
<div id="testDiv" style="background-color: #0000FF" onclick="colorClick(id)">
Clicking this div once changes the color.
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<button type='button' class='btn btn-default btn-lg' onclick=reEnableOnclick()>
This button should re-enable the onclick functionality, but it does not
</button>
</div>
</div>
Javascript Code
var divDisabled = false;
function colorClick(id){
if(!divDisabled) {
var randomColor = '#'+Math.floor(Math.random()*16777215).toString(16);
document.getElementById(id).style.backgroundColor=randomColor;
divDisabled = true;
/* The random color generator is from stackoverflow.com/questions/1484506/random-
color-generator */
}
}
function reEnableOnclick(){
divDisabled = false;
}
So now, You will set divDisabled for false by default so the first click of div will work as you want & following clicks on div won't as it is currently,
But As soon as you hit the button click it enables the click on div with setting buttonDisable to false, so it will again work once on div, as you want
Don't remove the click event, just check a flag to see if the behaviour is enabled or not. E.G:
var clickEnabled = true;
function colorClick(id) {
if (clickEnabled) {
var randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
document.getElementById(id).style.backgroundColor = randomColor;
clickEnabled = false;
}
}
function reEnableOnclick() {
clickEnabled = true;
}
<div class="row">
<div class="col-sm-12">
<div id="testDiv" style="background-color: #0000FF" onclick="colorClick(id);">
Clicking this div once changes the color.
</div>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<button type='button' class='btn btn-default btn-lg' onclick=reEnableOnclick()>
This button will re-enable the onclick functionality
</button>
</div>
</div>
You could define the function to run onclick outside of the assignment and use it to set and reset the click handler...
function functionThatRunsWhenButtonClicked() {
// do stuff
}
then in the places you need to assign it, assign it..
<div class="row">
<div class="col-sm-12">
<div id="testDiv" style="background-color: #0000FF" onclick="functionThatRunsWhenButtonClicked(); this.onclick=null;">
Clicking this div once changes the color.
</div>
</div>
</div>
function reEnableOnclick(){
document.getElementById("testDiv").onclick=functionThatRunsWhenButtonClicked; /* This
is only pseudo-code. What real code should I put here? */
}
You can do the same thing with colorClick(id)

Making a number increment when a class is clicked

So right now I have this code:
var s = 0;
$('.inner').click(function () {
$(this).addClass("selected");
$(this).removeClass("inner");
s++;
$('#sslots').replaceWith(s);
};
But for some reason, the javascript wont update, it will start out as blank (not zero) and then change to 1 once I click one of the div's with "inner" as the class but then won't do anything after that..
The problem is after your first click the element sslots does not exists because you are replacing it with the number, instead you have to change the content of sslots - you can use .text() for that
var s = 0;
$('.inner').one('click', function() {
$(this).addClass("selected");
$(this).removeClass("inner");
s++;
$('#sslots').text(s);
});
.inner {
color: green;
}
.selected {
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="sslots">0</div>
<div class="inner">inner</div>
<div class="inner">inner</div>
<div class="inner">inner</div>
<div class="inner">inner</div>
<div class="inner">inner</div>
Also from the code it looks like you want to execute the click once per inner element(ie if you click multiple times in an element only first one should count), in that cause use .one() to register a handler which will be executed only once

Categories