From SO threads Does ID have to be unique in the whole page? and Is multiple ids allowed in html and javascript? thread, I understand that while HTML/CSS may not allow for same ID to be linked to Javascript/Script on a webpage.
However, I am looking for an efficient & less complicated solution than simply copying over the large-sized Javascript and adding a progressive number to each id.
I have this submit button with a spinner:
<button class="submit-button" id="SubmitButton">
<div class="spinner hidden" id="spinner"></div>
<span id="buttonText">Submit Now</span>
</button>
and that is linked to a LARGE_SIZED SCRIPT as follows:
<script>
const myConst = MyNUM('<?php echo SOME_DETAILS; ?>');
// Select submit button
const subBtn = document.querySelector("#SubmitButton");
// Submit request handler
.......
.......
.......
// Several hundred lines of script code,
// including functions and other processing logic for spinners and whatnot
.......
.......
</script>
I need to have multiple such SubmitButton on the same webpage, so one way is to suffix the id with an incrementing number (like id="SubmitButton1", id="SubmitButton2" and so on)
and copy-paste the same <script></script> part for each button id.
However, that will make the webpage very bulky and lengthy.
Is there any way to use minimal code without repeating the whole block again and again, yet achieve the desired (multiple submit buttons)?
You really should delegate. If you then navigate the DOM of the target using the class names, then you have no need of IDs
document.addEventListener("click", function(e) {
const tgt = e.target.closest("button");
if (tgt.matches(".submit-button")) {
const spinner = tgt.querySelector("div.spinner");
tgt.querySelector("span.buttonText").hidden = true;
spinner.hidden = false;
console.log(spinner.textContent)
}
})
<button class="submit-button">
<div class="spinner" hidden>Spinner 1</div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner" hidden>Spinner 2</div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner" hidden>Spinner 3</div>
<span class="buttonText">Submit Now</span>
</button>
Maybe this helps.
// Get all elements with the same class in an array
const submitButtons = document.getElementsByClassName("submit-button") // or document.querySelectorAll(".submit-button");
// Loop through the array
for (let i = 0; i < submitButtons.length; i++) {
// Get each individual element including the element's children
const submitButton = submitButtons[i]
const spinner = submitButton.querySelector(".spinner");
const submitText = submitButton.querySelector(".buttonText");
console.log(submitButton, spinner, submitText)
}
// if you want a specific button you use the index
console.log(submitButtons[3])
<button class="submit-button">
<div class="spinner hidden"></div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner hidden"></div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner hidden"></div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner hidden"></div>
<span class="buttonText">Submit Now</span>
</button>
<button class="submit-button">
<div class="spinner hidden"></div>
<span class="buttonText">Submit Now</span>
</button>
Related
I am looking to add multiple 'see more' buttons through out my page. At the moment when when I add a new one only the first button works and it breaks the second. So the first button works fine but when I've tried to copy this thumbnail over and make another one with the same see more details. The second button only changes the first thumbnails 'see more'
function toggle() {
let Text = document.getElementById('moreDetails');
if (Text.style.display == "none") {
Text.style.display = "block";
} else {
Text.style.display = "none";
}
}
document.getElementById("moreDetails").style.display = "none";
<div id="thumbnail-frame">
<div id="thumbnail" <div id="details">
<div id="moreDetails">
<h3> 001 </h3>
<h3> Saturate Radio </h3>
<h4> N00DS </h4>
</div>
<button title="Click to Show" type="button" onclick="toggle()">More Details</button>
</div>
</div>
<div id="thumbnail-frame">
<div id="thumbnail" <div id="details">
<div id="moreDetails">
<h3> 002 </h3>
<h3> Saturate Radio </h3>
<h4> N00DS </h4>
</div>
<button title="Click to Show" type="button" onclick="toggle()">More Details</button>
</div>
</div>
Main problem is that you can't have duplicate IDs on a page. Using classes works ok, or using relative position of your html elements.
function toggle(button){
// this works because the button is immediately after the "moreDetails" element it pertains to
let Text = button.previousElementSibling;
// this would work if you move the button so it is not immediately after moreDetails, but still in the same parent div.
//let Text = button.parentElement.querySelector(".moreDetails");
if(Text.style.display == "none"){
Text.style.display= "block";
}
else {
Text.style.display = "none";
}
}
const moreDetailses = document.querySelectorAll(".moreDetails");
for (let i = 0; i < moreDetailses.length; i++) {
moreDetailses[i].style.display = "none";
}
<div class="details">
<div class="moreDetails">
<h3> 001 </h3>
<h3> Saturate Radio </h3>
<h4> N00DS </h4>
</div>
<button title="Click to Show" type="button" onclick="toggle(this)">More Details</button>
</div>
<div class="details">
<div class="moreDetails">
<h3> 002 </h3>
<h3> Saturate Radio </h3>
<h4> N00DS </h4>
</div>
<button title="Click to Show" type="button" onclick="toggle(this)">More Details</button>
</div>
An id is only allowed to be used once per page, so that your toggle script will not work as expected when you have multiple elements with the same id.
To make it functional, and keep the required changes to a minimum, you should do the following:
switch id to class so the HTML is valid
allow your toggle button to pass along itself, for example onclick="toggle(this)"
move through the dom to get to the element you want to toggle (parentNode, firstChild etc.)
I am new on laravel framework.
I have created an component (lecture-content) having some files input options, and there is an button onclick which should add one more (lecture-content) component. On DOM.
function addContent()
{
let newDoc = "#include('inc.lecture-content')";
let extendContent = document.getElementById('addNew').innerHtml;
console.log(extendContent);
console.log(newDoc);
extendContent+=newDoc;
document.getElementById('addNew').innerHtml= extendContent;
}
<div class="cariculum-heading my-2">
<h5 class="my-auto py-auto font-weight-normal ">Curriculum </h5>
<button class="px-2 btn my-auto py-auto add-content-btn" onclick="addContent()" id="add-content">+ content</button>
</div>
<div class="content-section" id="addNew">
#include('inc.lecture-content')
</div>
but this is not working at this position let newDoc = "#include('inc.lecture-content')"; it shows syntax error. can anyone help me to resolve it. What I am doing wrong here
Use clone()
Below jQuery code will fulfill your purpose.
function addContent()
{
var clone = $('#addNew').clone().css('display','block');
$('#newEle').append(clone);
}
Add one more div to your blade file.
<div id="newEle">
</div>
This newly created div will be used to append cloned div.
function addContent()
{
var clone = $('#addNew').clone().css('display','block');
$('#newEle').append(clone);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="cariculum-heading my-2">
<h5 class="my-auto py-auto font-weight-normal ">Curriculum </h5>
<button class="px-2 btn my-auto py-auto add-content-btn" onclick="addContent()" id="add-content">+ content</button>
</div>
<div id="newEle">
</div>
<div class="content-section" id="addNew" style="display: none;">
#include('inc.lecture-content')
</div>
I have the following
<p>haha</p>
<button class="btn btn-light" onclick="nextSibling.classList.toggle('d-none');">
<i class="fa fa-ellipsis-h"></i>
</button>
<div class="prev-content d-none">
<p>second reply from second account</p>
<br>
<button class="btn btn-light" onclick="nextSibling.classList.toggle('d-none');">
<i class="fa fa-ellipsis-h"></i>
</button>
<div class="prev-content d-none">
<p>reply from system</p>
</div>
</div>
I want to show only next sibling <div class="prev-content"> by click on button, but there is some strange behavior. It shows all divs or it hides all divs. I think the reason in bubbling events.
How can I resolve that?
Don't use inline JS same as you don't use inline style attributes
Use addEventListener
Use Event.currentTarget inside the function handler to refer to the event delegated Element
Use nextElementSibling
Use finally classList.toggle to toggle a specific class
const toggleNext = (ev) => {
const EL = ev.currentTarget;
const EL_next = EL.nextElementSibling;
EL_next.classList.toggle("u-none");
};
const ELs_tog = document.querySelectorAll("[data-toggle-next]");
ELs_tog.forEach(EL => EL.addEventListener("click", toggleNext));
.u-none {display: none;}
<button type="button" data-toggle-next>TOGGLE</button>
<div class="u-none">
<p>second reply from second account</p>
<button type="button" data-toggle-next>TOGGLE</button>
<div class="u-none">
<p>reply from system</p>
</div>
</div>
Additional read:
Node.nodeType
Using puppeteer, I tried getting two objects in but failed.
My test code is like this
const btnUp = await page.$('div#ember322 > a:nth-child(0)');
const btnDown = await page.$('div#ember322 > a:nth-child(1)');
How can I solve this problem?
This is my example codes for the test.
<div id="ember322" class="ember-view">
<div class="order-btn-group">
<div class="order-value"><span>0.8</span></div>
<div class="row">
<div class="col-xs-6">
<a class="btn-order btn-down txt-left" data-ember-action="" data-ember-action-323="323">
<span class="btn-order-text">down</span>
<span class="btn-order-value txt-center">
<small>300</small>
</span>
<i class="btn-order-status"></i>
</a>
</div>
<div class="col-xs-6">
<a class="btn-order btn-up txt-right" data-ember-action="" data-ember-action-324="324">
<span class="btn-order-text">up</span>
<span class="btn-order-value txt-center">
<small>500</small>
</span>
<i class="btn-order-status"></i>
</a>
</div>
</div>
</div>
</div>
Try the selectors without the >. It would require the <a> elements to be direct children of the <div> (see for example W3Schools). Like so:
const btnUp = await page.$('div#ember322 a:nth-child(0)');
const btnDown = await page.$('div#ember322 a:nth-child(1)');
And, maybe instead of using nth-child, why not try the btn-up and btn-down classes?
I'm trying to build my first calculator. When adding the eventListener, the function only sometimes enters the if statement. I.e. if I click some number it doesn't log but when I try other numbers and then the first one again it works. I really don't get this behavior.
Here you can have a look (logs to the console) https://jsfiddle.net/ert54b7z/2/
const keys = document.querySelector(".keypad");
keys.addEventListener("click", function(e) {
if (e.target.matches("button")) {
const button = e.target;
const key = button.dataset.key;
console.log(key);
}
});
<div class="keypad">
<div class="clear">
<button data-key="clear" class="button"><p>C</p></button>
<button data-key="all-clear" class="button"><p>AC</p></button>
</div>
<div class="operations">
<button data-key="plus" class="button"><p>+</p></button>
<button data-key="minus" class="button"><p>-</p></button>
// ...
</div>
<div class="numbers">
<button data-key="7" class="button"><p>7</p></button>
<button data-key="8" class="button"><p>8</p></button>
// ...
</div>
<button data-key="equals" class="button equals"><p>=</p></button>
</div>
It's a good intuition to use event delegation. You check for the target of the click event, but since your buttons contain paragraph tags, they become the click target if you click somewhere in the center of the buttons. Remove the <p> tags (they aren't needed anyway), and the keys will be logged on every click.
You're attaching the event listener to the outer div. You need to attach it to the buttons.
$('.keypad').on('click', myFunction);
function myFunction(e) {
// do stuff here
}
<div class="">
<div class="clear">
<button data-key="clear" class="keypad button"><p>C</p></button>
<button data-key="all-clear" class="keypad button"><p>AC</p></button>
</div>
<div class="operations">
<button data-key="plus" class="keypad button"><p>+</p></button>
<button data-key="minus" class="keypad button"><p>-</p></button>
// ...
</div>
<div class="numbers">
<button data-key="7" class="keypad button"><p>7</p></button>
<button data-key="8" class="keypad button"><p>8</p></button>
// ...
</div>
<button data-key="equals" class="keypad button equals"><p>=</p></button>
</div>
<!-- include jquery -->
<script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-3.4.1.min.js"></script>