How do I add multiple classes to an element with JS? - javascript

I have below JS code:
<script>
function CommentStyle() {
var elementAuthor = document.getElementById("author");
var elementEmail = document.getElementById("email");
var elementUrl = document.getElementById("url");
elementAuthor.classList.add("form-control ulockd-form-bps required email");
elementEmail.classList.add("form-control ulockd-form-bps required email");
elementUrl.classList.add("form-control ulockd-form-bps required email");
}
window.onload = CommentStyle;
alert("Hello! I am an alert box!!");
</script>
ffee
<style>
.form-control {
border: 1px dashed #cccccc;
}
</style>
Alert works but the class is not added.Also how can I short this code instead of add new line for every id because the class is same?

classList.add takes multiple parameters, but will not accept strings with a space in it. You can pass in multiple strings, or if you have your classes stored in a variable classes in the form "firstClass secondClass thirdClass", you can use .split(' ') to split by spaces and then use the spread operator ... to pass the array's contents into classList.add as individual arguments.
This is even simpler for this case, since each element shares the same classes:
(Edit: OP actually ran this code on every page, including those without the relevant elements, so a check was added to exit if they did not exist in the DOM.)
function CommentStyle() {
let elementAuthor = document.getElementById("author"),
elementEmail = document.getElementById("email"),
elementUrl = document.getElementById("url");
// check IDs exist
if (!elementAuthor || !elementEmail || !elementUrl) return;
let classes = "form-control ulockd-form-bps required email".split(' ');
elementAuthor.classList.add(...classes),
elementEmail.classList.add(...classes),
elementUrl.classList.add(...classes);
// for demo purposes:
let [authorClasses, emailClasses, urlClasses] = [
elementAuthor.className,
elementEmail.className,
elementUrl.className
];
console.log({
authorClasses,
emailClasses,
urlClasses
});
}
window.onload = CommentStyle;
<label for="author">Author</label><br>
<input type="text" id="author"><br><br>
<label for="email">Email</label><br>
<input type="text" id="email"><br><br>
<label for="email">Url</label><br>
<input type="text" id="url"><br>

You don't have to access each field separately by ID, just give them all the same class and loop through that class.
<div class="comment-field" id="author"></div>
<div class="comment-field" id="email"></div>
<div class="comment-field" id="url"></div>
function CommentStyle() {
var comment_fields = document.querySelectorAll(".comment-field");
comment_fields.forEach(function(el){
el.classList.add("form-control","ulockd-form-bps","required","email");
});
}

Related

How to clone or create a nested DOM node and change all its containing id values according to a current id?

I need to display some numbers, strings from a class named Student, but i can't figure it out how i can change the id from children element. I have to use JavaScript.
what i tried to do:
class Student{
static count = 0;
constructor(nume, prenume, data_nasterii, foaie_matricola){
this.IdClasa = ++Student.count;
//definirea atributelor
this.nume = nume;
this.prenume = prenume;
this.data_nasterii = data_nasterii;
this.foaie_matricola = foaie_matricola;
}
afiseazaVarsta(){
}
afiseazaNotele(){
}
calculeazaMedia(){
}
adaugaNota(nota_noua){
}
}
var Stud = [new Student("Name", "Name1", "2000.01.01", "0123123"),
new Student("Green", "Blue", "2022/12.12", "321321")];
function afisareStudenti(){
let i = 0; let bol = false;
for(let x=1; x<=Student.count; x++) {
console.log(document.getElementById("AfisareStudenti"+x)==null);
if(document.getElementById("AfisareStudenti"+x)==null)
{
i = x;
bol = true;
break;
} else {
bol = false;
}
}
if((i<=Student.count)&&(bol==true)){
for(i; i<=Student.count; i++) {
console.log("i="+i);
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
console.log(divClone);
divClone.id = 'AfisareStudenti'+(i);
div.after(divClone);
var NumeStud = document.getElementById("NumeStudent"+(i-1));
var PrenumeStud = document.getElementById("PrenumeStudent"+(i-1));
var dataNastStud = document.getElementById("intData"+(i-1));
var FoaiaMatStud = document.getElementById("FoaiaMatStud"+(i-1));
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
}
}
}
and this is the html file(the div that i want to clone):
<!--AFISARE-->
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1"><br><br>
<input class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti()">
</form>
</div>
the class is saved in a dynamic array (could be n object of the class) so i have to make somehow to display the information dynamic. My version changes the id from all elements with the same id (every incrementation of i, the idnumber from id is incremented also). I tried to create that div with document.createElement but is impossible(at least for me) xD . I started coding in javascript 2 days ago, so please take it slow on me :(
I think i found the problem, but it doesn't solve it. (i need to put (i-1) when calling for getting the ids). (Newbie mistake)
Having commented ...
"I have the feeling that if provided with the broader picture the audience could be of much more help since the OP could be provided back with leaner/cleaner and better maintainable approaches."
... I nevertheless hereby lately provide a template-based approach which, besides supporting the OP's id based querying of student-items, is also easier to read and to maintain.
The code provided within the example-code's main function does not just implement the usage of the template-based node-creation via template literals and DOMParser.parseFromString but also prevents the default behavior of each student-form's submit-button by making use of event-delegation.
function createStudentElement(studentId) {
const markup =
`<div class="student-item" id="AfisareStudenti${ studentId }">
<h2> Afisare Student ${ studentId }</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent${ studentId }"><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent${ studentId }"><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData${ studentId }"><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud${ studentId }"><br><br>
<input
class="butoane" type="submit" value="Afisare"
onclick="afisareMeniuAfisStudenti(${ studentId })"
>
</form>
</div>`;
const doc = (new DOMParser).parseFromString(markup, 'text/html');
return doc.body.removeChild(doc.body.firstElementChild);
}
// the button click handler.
function afisareMeniuAfisStudenti(studentId) {
console.log({ studentId })
}
function main() {
const itemsRoot = document.querySelector('.student-items');
// - prevent any form-submit by making use of event-delegation.
itemsRoot.addEventListener('submit', evt => evt.preventDefault());
// - just for demonstration purpose ...
// ... create student-items from a list of student IDs.
[1, 2, 3, 4, 5].forEach(studentId =>
itemsRoot.appendChild(
createStudentElement(studentId)
)
);
}
main();
.as-console-wrapper { left: auto!important; width: 50%; min-height: 100%; }
<div class="student-items"></div>
Tom's answer above is what you want for the element id problem that you asked about.
For your code in particular, you are going to have a couple other problems:
Because the final input is type="submit", its going to reload the page by default when it is clicked. The name of the "onclick" function also needs to match the function you defined (afisareStudenti).
You have:
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()">
Change this to:
<input class="butoane" type="submit" value="Afisare" onclick="afisareStudenti(event)">
Now, when you click that button, it will call the afisareStudenti function and pass in the "event". So if you change:
function afisareStudenti(){
let i = 0; let bol = false;
to:
function afisareStudenti(event){
event.preventDefault()
let i = 0; let bol = false;
This will correctly call your function, and prevent the "default" action of that submit button from reloading the page.
To change the id attribute of children elements, you could use Element.querySelector() on divClone.
Because if you use Document.querySelector() or Document.getElementById() you will get the first element that matches your selector (i.e.children of div#AfisareStudenti1).
let i = 2;
var div = document.querySelector('#AfisareStudenti1');
var divClone = div.cloneNode(true);
divClone.id = 'AfisareStudenti'+(i);
divClone.querySelector("h2").innerText = "Afisare Student " + i;
var NumeStud = divClone.querySelector("#NumeStudent1");
var PrenumeStud = divClone.querySelector("#PrenumeStudent1");
var dataNastStud = divClone.querySelector("#intData1");
var FoaiaMatStud = divClone.querySelector("#FoaiaMatStud1");
NumeStud.id = "NumeStudent"+(i);
PrenumeStud.id = "PrenumeStud"+(i);
dataNastStud.id = "intData"+(i);
FoaiaMatStud.id = "FoaiaMatStud"+(i);
div.after(divClone);
<div id="AfisareStudenti1">
<h2> Afisare Student 1</h2>
<label>Ce student doriti sa modificati? </label>
<form>
<label>Nume:</label><br>
<input type="text" id="NumeStudent1" /><br>
<label>Prenume:</label><br>
<input type="text" id="PrenumeStudent1" /><br>
<label>Data Nasterii:</label><br>
<input type="date" id="intData1" /><br>
<label>Foaie matricola:</label><br>
<input type="text" id="FoaiaMatStud1" /><br><br>
<input class="butoane" type="submit" value="Afisare" onclick="afisareMeniuAfisStudenti()" />
</form>
</div>

How to make a text appear with a desired innerHTML using javascript/jquery

There is a button and a h2 tag. the h2 tag has its visibilty=hidden.
When the button is clicked, I want to call a function that calculates the cost and changes the innerHTML of h2 accordingly and then changes its visibility=visible.
HTML:
<main class="form-signin">
<form>
<div class="card">
<label for="inputAdult">Enter number of adults</label><input type="number" id="inputAdult" class="form-control" placeholder="No. of adults" required>
<label for="inputChildren">Enter number of children (4-12yo)</label><input type="number" id="inputChildren" class="form-control" placeholder="No. of children" required>
<button type="button" onclick="showCost()" id="btn3">Calculate my cost</button>
<h2 class="changeCost">Your total cost: $0</h2>
</div>
</form>
</main>
JavaScript / jQuery :
$("h2").css("visibility","hidden");
function calculateCost(){
var a = $("#inputAdult").val();
var c = $("#inputchildren").val();
if (((a+c)%3==0)||((a+c)%3==1)) {
var rooms = (a+c)/3;
}
else {
var rooms = ((a+c)/3)+1;
}
var cost = rooms*300;
return cost;
}
function showCost() {
var display = "Your total cost is: $" + calculateCost();
var x = $("h2");
x.value = display;
$("h2").css("visibility","visible");
}
Try x.text(display) instead of setting value. That changes the innerText of the element. If you'd like to set its HTML content, use x.html(display).
The value accessor is used for plain HTMLElement objects, not for jQuery-wrapped objects.
Apart from this, you should never access a tag solely by its tag name. Always give it some kind of class name or ID. You already gave it the changeCost class, so you could do $("h2.changeCost") rather than $("h2").
To avoid getting NaN do the following:
Javascript is case sensitive so replace line
var c = $("#inputchildren").val();
with
var c = $("#inputChildren").val();
I would also consider declaring rooms variable from if and else scope so it is accessible on calculations: see full function bellow:
function calculateCost(){
var a = $("#inputAdult").val();
var c = $("#inputChildren").val();
var rooms = 0;
if (((a+c)%3==0)||((a+c)%3==1)) {
rooms = (a+c)/3;
}
else {
rooms = ((a+c)/3)+1;
}
var cost = rooms*300;
return cost;
}

How to query multiple elements that start with the same ID and then check whether the input has changed

I have a list of text inputs which all start with the same id but are slightly different at the end. When text is entered by the user in any of these input fields I want to execute a function. At the moment this is working with the following code:
var heightInches = document.querySelector("#Height_Inches");
var heightFeet = document.querySelector("#Height_Feet");
var heightCentimeters = document.querySelector("#Height_Centimeters");
heightInches.oninput = function (e) {
console.log("Edited");
}
heightFeet.oninput = function (e) {
console.log("Edited");
}
heightCentimeters.oninput = function (e) {
console.log("Edited")
}
The issue is that I don't like the repetition and would rather query all of the ids that begin with "Height_" and do something (as what is excuted inside each function will be the same.
Here is what I have tried but does not work:
var allHeight = document.querySelector('[id*="Height_"]');
allHeight.oninput = function (e) {
console.log("edited");
}
I have also tried the same with querySelectorAll
Please could someone help with where I am going wrong here? Every other Stack Overflow answer and article I see seems to suggest that id* is the correct way to select? Thank you
If I understand correctly, this is what you are looking for.
The only thing you were missing is looping through your elements.
const inputs = document.querySelectorAll('[id*="Height_"]');
inputs.forEach( input => {
input.oninput = function (e) {
console.log("edited");
}
})
<input type="text" id="Height_1">
<input type="text" id="Height_2">
<input type="text" id="Height_3">
Rather than use an ID, which is intended to be unique, why not add a class like .height-input to each input and then you can select them all?
// Get elements
const inputs = document.querySelectorAll('.height-input');
const outputEl = document.querySelector('.output');
// Attach event handlers
for (let i = 0; i < inputs.length; i++) {
inputs[i].oninput = function(e) {
// Handle input
outputEl.innerHTML = `Input received on #${e.target.id}`;
}
}
.output {
margin-top: 10px;
}
<input type="text" class="height-input" id="HeightInches">
<input type="text" class="height-input" id="HeightFeet">
<input type="text" class="height-input" id="HeightCentimeters">
<div class="output">Waiting for input...</div>

Having trouble displaying an array value within console.log event using .push function in Jquery

The issue here is that I have designed a basic website which takes in a users input on a form, what I then intend to do is print that value out to the console.log. however, when I check the console under developer tools in Google Chrome, all I get printed out is []length: 0__proto__: Array(0)
and not the value the user has inputted.
<input type="text" name="username" value="testuser">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
function error() {
var error1 = [];
var list_of_values = [];
username_error = $('input[name="username"]').val();
if (!username_error){
error1.push('Fill in the username field.');
}
console.log(error1);
if (error1.length > 0){
for(let username_error of error1){
alert(username_error);
return false;
}
}
string = $('input[name="username"]').val('');
if(string.length <= 1){
for (let list_of_values of string){
string.push();
}
console.log(string);
return true;
}
}
error();
</script>
Suggestion, you can make it actually things easier with the following code.
the function below scans all input fields under fieldset element
$("fieldset *[name]").each....
the issue above is multiple alert, what if you have a lot of inputs, it would alert in every input, which wont be nice for the users :) instead you can do this
alert(error1.toString().replace(/,/g, "\n"));
to alert the lists of errors at once.
string = $('input[name="username"]').val('');
that is actually clearing your value.. so it wont give you anything in console.log().
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<fieldset>
<input type="text" name="name" value="" placeholder="name"/><br/><br/>
<input type="text" name="username" value="" placeholder="username"/><br/><br/>
<button onclick="error()">check</button>
</fieldset>
<script>
function error() {
var error1 = [];
var list_of_values = [];
$("fieldset *[name]").each(function(){
var inputItem = $(this);
if(inputItem.val()) {
return list_of_values.push(inputItem.val());
}
error1.push('Fill in the '+inputItem.attr('name')+' field!')
});
if(error1.length > 0) {
console.log(error1);
alert(error1.toString().replace(/,/g, "\n"));
}
if(list_of_values.length > 0) {
console.log(list_of_values);
}
}
</script>
Register the <input> to the input event. When the user types anything into the <input> the input event can trigger an event handler (a function, in the demo it's log()).
Demo
Details commented in demo
// Reference the input
var text = document.querySelector('[name=username]');
// Register the input to the input event
text.oninput = log;
/*
Whenever a user types into the input...
Reference the input as the element being typed into
if the typed element is an input...
log its value in the console.
*/
function log(event) {
var typed = event.target;
if (typed.tagName === 'INPUT') {
console.log(typed.value);
}
}
<input type="text" name="username" value="testuser">

possible to change one variable or another inside of a function

I don't know if this is possible so I figured this would be the place to ask.
I have two inputs and they each hold a unique value. They each have their own respective variable that the value is saved into. I was wondering if there was a way to use just one function to update their values instead of two seperate ones. Below is my code so far.
<form>
<input type="text" id="valueOne" onchange="changeValueOne(this.value)">
<input type="text" id="valueTwo" onchange="changeValueTwo(this.value)">
</form>
var valueOne = parseFloat($('#valueOne'));
var valueTwo = parseFloat($('#valueTwo'));
function changeValueOne(newValueOne) {
valueOne = newValueOne;
}
function changeValueTwo(newValueTwo) {
valueTwo = newValueTwo;
}
Try this:
var valueOne, valueTwo;
$("#valueOne, #valueTwo").change(function(){
if($(this).attr('id') == 'valueOne') {
valueOne = $(this).val();
} else {
valueTwo = $(this).val();
}
});
You could have a second parameter to indicate which variable to store and/or where.
var values;
function changeValue(newValue, pos){
values[pos] = newValue;
}
Change html to:
<input type="text" id="valueOne" onchange="changeValue(this.value, 'first')">
<input type="text" id="valueOne" onchange="changeValue(this.value, 'second')">
Alternatively if you want to store them in separate variables:
function changeValue(newValue, pos){
if(pos == 'first'){
valueOne = newValue;
} else if(pos == 'second'){
valueTwo = newValue;
}
}
the simple expandable way uses a collection instead of vars:
<form>
<input type="text" id="valueOne" onchange="changeValue(value, id)">
<input type="text" id="valueTwo" onchange="changeValue(value, id)">
</form>
<script>
var vals={
valueOne : parseFloat($('#valueOne').val()),
valueTwo : parseFloat($('#valueTwo').val())
};
function changeValue(newValue, slot) {
vals[slot] = newValue;
}
</script>
not only is it incredibly simple and fast, this lets you add many options without reworking the forking code (ifs), all you need to do is modify the vals object and the handler will keep up automatically with all available options, even creating new ones on-the-fly if needed (from new inputs being appended during run-time).

Categories