I am trying to create a list of names. As of now, my code is able to add one name at a time. I want to identify if there is a comma (,) on my input, so I can add add that second or third name and create an individual <li>, how can I identify if an input has a specific character?
var button;
var list = document.getElementById("greatList");
var item = document.getElementById("addItems").value;
//console.log(item);
document.addEventListener('DOMContentLoaded', init);
function init(){
button = document.getElementById('addButton');
document.querySelector('#addButton').addEventListener(addField);
//button.addEventListener('click', getItem)
}
function addField(){
var item = document.getElementById("addItems").value;
var newField = document.createElement('li');
newField.appendChild(document.createTextNode(item));
list.appendChild(newField);
}
function extraInput(){
var item = document.getElementById("addItems").value;
if (item.search(',') !== -1){
console.log(true);
}
}
<div class="wrapper">
<div class="list">
<h2>List: </h2>
<section class="top">
<input type="text" multiple="multiple" id="addItems">
<button type="submit" id="addButton" onclick="addField()">Add</button>
<button>Get Random</button>
</section>
<hr>
<section class="result">
<ul id="greatList">
<li class="singleLine">Hello</li>
</ul>
</section>
</div>
</div>
You can use string.split function. Working code below.
var button;
var list = document.getElementById("greatList");
var item = document.getElementById("addItems").value;
//console.log(item);
document.addEventListener('DOMContentLoaded', init);
function init() {
button = document.getElementById('addButton');
document.querySelector('#addButton').addEventListener(addField);
//button.addEventListener('click', getItem)
}
function addField() {
var item = document.getElementById("addItems").value;
if (item == "") {
alert("enter something");
return false;
}
var items = item.split(',');
for (i = 0; i < items.length; i++) {
var newField = document.createElement('li');
newField.appendChild(document.createTextNode(items[i]));
list.appendChild(newField);
}
}
function extraInput() {
var item = document.getElementById("addItems").value;
if (item.search(',') !== -1) {
console.log(true);
}
}
<div class="wrapper">
<div class="list">
<h2>List: </h2>
<section class="top">
<input type="text" multiple="multiple" id="addItems">
<button type="submit" id="addButton" onclick="addField()">Add</button>
<button>Get Random</button>
</section>
<hr>
<section class="result">
<ul id="greatList">
<li class="singleLine">Hello</li>
</ul>
</section>
</div>
</div>
Update: I didnt f5 to know it already answered. just ignore it.
var button;
var list = document.getElementById("greatList");
var item = document.getElementById("addItems").value;
//console.log(item);
document.addEventListener('DOMContentLoaded', init);
function init(){
button = document.getElementById('addButton');
document.querySelector('#addButton').addEventListener(addField);
//button.addEventListener('click', getItem)
}
function addField(){
var item = document.getElementById("addItems").value;
if(isValid(item )){
var itemArr = item.split(",");
for (var i = 0; i < itemArr.length; i++) {
element = itemArr[i];
var newField = document.createElement('li');
newField.appendChild(document.createTextNode(element ));
list.appendChild(newField);
}
}
else{alert('invalid text!');}
}
function isValid(str){
return !/[~`!#$%\^&*+=\-\[\]\\';/{}|\\":<>\?]/g.test(str);
}
function extraInput(){
var item = document.getElementById("addItems").value;
if (item.search(',') !== -1){
console.log(true);
}
}
<div class="wrapper">
<div class="list">
<h2>List: </h2>
<section class="top">
<input type="text" multiple="multiple" id="addItems">
<button type="submit" id="addButton" onclick="addField()">Add</button>
<button>Get Random</button>
</section>
<hr>
<section class="result">
<ul id="greatList">
<li class="singleLine">Hello</li>
</ul>
</section>
</div>
</div>
try improve your function addField
function addField(){
var item = document.getElementById("addItems").value; //Get the string
var res = item.split(","); //split the string and create an array
res.forEach(function (value) { createField(value); }); //for each element in the array call to createField
}
function createField(text){
var list = document.getElementById("greatList"); // use local variable, not global
var newField = document.createElement('li');
newField.appendChild(document.createTextNode(text));
list.appendChild(newField);
}
<div class="wrapper">
<div class="list">
<h2>List: </h2>
<section class="top">
<input type="text" multiple="multiple" id="addItems">
<button type="submit" id="addButton" onclick="addField()">Add</button>
<button>Get Random</button>
</section>
<hr>
<section class="result">
<ul id="greatList">
<li class="singleLine">Hello</li>
</ul>
</section>
</div>
</div>
Related
<div>
<div class=category> Birthdays </div>
<div class=category> Anniversaries </div>
<div class=category> Newborns </div>
<div class=category> Weddings </div>
</div>
<ul>
<li class="product-filter-items">Birthdays</li>
<li class="product-filter-items">Weddings</li>
<li class="product-filter-items">Newborns</li>
<li class="product-filter-items">Anniversaries</li>
</ul>
<script>
let proCatList = document.querySelectorAll(".category")
let proFilterItems = document.querySelectorAll(".product-filter-items")
for(let i = 0; i < proFilterItems.length; i++){
proFilterItems[i].addEventListener("click" , function(){
if (proCatList[i].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() == proFilterItems[i].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() ){
proFilterItems[i].classList.add("active-filter")
console.log("Class Added")
}
})
}
</script>
I am trying to add a class based on a click event. What I am trying to do is if classname, category and product-filter-items are equal then it should add a classname called active-filter on click. Can anyone point out why this statement does not recognise the textContent of proCatList?
The iteration param i can't be used in the event handler. Therefor you could use the index of the clicked element, which you can call with this.
For getting the index, you can use the following small function:
const getIndex = elem => [...elem.parentNode.children].indexOf(elem);
Working example:
let proCatList = document.querySelectorAll(".category");
let proFilterItems = document.querySelectorAll(".product-filter-items");
/* small function for getting the index */
const getIndex = elem => [...elem.parentNode.children].indexOf(elem);
for (let i = 0; i < proFilterItems.length; i++) {
proFilterItems[i].addEventListener("click", function() {
const elem_index = getIndex(this);
if (proCatList[elem_index].textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim() == this.textContent.toUpperCase().replace(/[\n\r]+|[\s]{2,}/g, ' ').trim()) {
this.classList.add("active-filter");
console.log("Class Added");
}
})
}
<div>
<div class=category> Birthdays </div>
<div class=category> Anniversaries </div>
<div class=category> Newborns </div>
<div class=category> Weddings </div>
</div>
<ul>
<li class="product-filter-items">Birthdays</li>
<li class="product-filter-items">Weddings</li>
<li class="product-filter-items">Newborns</li>
<li class="product-filter-items">Anniversaries</li>
</ul>
Hi im really new to javascript and stuck on a textbook exercise where I increase the increment of variable i by 1 to be able to continuing listing the inputs. Here is my code so far, can anyone guid me on what I am doing incorrect thank you
<body>
<header>
<h1>
Project 2 Test 1
</h1>
</header>
<article>
<div id="results">
<ul>
<li id="item1"></li>
<li id="item2"></li>
<li id="item3"></li>
<li id="item4"></li>
<li id="item5"></li>
</ul>
<p id="resultsExp"></p>
</div>
<form>
<fieldset>
<label for="wishList" id="placeLabel">
Type the name of a wish list item, then click Submit:
</label>
<input type="text" id="wishList" />
</fieldset>
<fieldset>
<button type="button" id="button">Submit</button>
</fieldset>
</form>
</article>
<script>
i = 1;
listitem = "";
function processitems() {
if (i<= 5) {
listitem ="item" +i;
document.getElementById(listitem).innerHTML = document.getElementById("wishList").value;
document.getElementById("wishlist").value ="";
if (i===5) {
document.getElementById("resultsExp").innerHTML = "Your wish list has been submitted";
}
//inside the processitems() function of the main if statement, after the nested if statement, add a statement to increment the value of i by 1.
i =+1;
}
}
var btn = document.getElementById("button");
if (btn.addEventListener) {
btn.addEventListener("click", processitems, false);
} else if (btn.attachEvent) {
btn.attachEvent("onclick", processitems);
}
</script>
i =+1; is assigning 1 to i. You should be doing i += 1 instead:
<body>
<header>
<h1>
Project 2 Test 1
</h1>
</header>
<article>
<div id="results">
<ul>
<li id="item1"></li>
<li id="item2"></li>
<li id="item3"></li>
<li id="item4"></li>
<li id="item5"></li>
</ul>
<p id="resultsExp"></p>
</div>
<form>
<fieldset>
<label for="wishList" id="placeLabel">
Type the name of a wish list item, then click Submit:
</label>
<input type="text" id="wishList" />
</fieldset>
<fieldset>
<button type="button" id="button">Submit</button>
</fieldset>
</form>
</article>
<script>
i = 1;
listitem = "";
function processitems() {
if (i <= 5) {
listitem = "item" + i;
document.getElementById(listitem).innerHTML = document.getElementById("wishList").value;
document.getElementById("wishList").value = "";
if (i === 5) {
document.getElementById("resultsExp").innerHTML = "Your wish list has been submitted";
}
//inside the processitems() function of the main if statement, after the nested if statement, add a statement to increment the value of i by 1.
i += 1;
}
}
var btn = document.getElementById("button");
if (btn.addEventListener) {
btn.addEventListener("click", processitems, false);
} else if (btn.attachEvent) {
btn.attachEvent("onclick", processitems);
}
</script>
When I type something in the first box, and click Next, the word I typed is inserted on my page. However, if I click Back and then click Next again, it is printed a second time.
I want the keyword appended after I've clicked Next to be deleted if I click Back so that if I click Next again it is printed only once (and updated if I have made any edit).
document.addEventListener("DOMContentLoaded", function() {
var stepOne = document.getElementsByClassName("step-1");
var stepTwo = document.getElementsByClassName("step-2");
var nextButton = document.getElementsByClassName("next");
var backButton = document.getElementsByClassName("back");
nextButton[0].onclick = function() {
stepOne[0].style.display = "none";
stepTwo[0].style.display = "block";
var inputKeyword = document.getElementById("inputJobTitle").value;
var newKeyword = document.createElement("p");
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
newKeyword.innerText = inputKeyword;
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
document.getElementById("retrievedFields").appendChild(newKeyword);
}
backButton[0].onclick = function() {
stepOne[0].style.display = "block";
stepTwo[0].style.display = "none";
}
})
.step-1 {
display: block;
}
.step-2 {
display: none;
}
<!--STEP 1-->
<div class="main step-1">
<div class="tab" id="tab-1">
<div class="inputFields">
<p id="jobtitle" class="inputFieldName">Job title</p>
<input type="search" id="inputJobTitle" class="inputBar" />
<p class="and">AND</p>
</div>
<div class="button">
<button class="next">Next ></button>
</div>
</div>
</div>
<!--STEP 2-->
<div class="main step-2">
<div class="tab" id="tab-1">
<div class="inputFields">
<div id="retrievedFields"></div>
<input type="search" class="inputBarAlternative" />
<div class="add">
<button class="addButton">+ Add Keyword</button>
<p id="addKeyword">
Add a skill or keyword that must be in your search results
</p>
</div>
</div>
<div class="buttons">
<button class="back">Back</button>
<button class="next">Next</button>
</div>
</div>
</div>
</body>
Each new click on the next button will trigger an append. So you just have to do the opposite of an append on the click on back. Just add this line in your onclick:
document.getElementById("retrievedFields").removeChild(document.getElementById("retrievedFields").lastElementChild);
You could also check to see if the element exists before you create it..
nextButton[0].onclick = function() {
stepOne[0].style.display = "none";
stepTwo[0].style.display = "block";
var inputKeyword = document.getElementById("inputJobTitle").value;
var newKeyword = document.getElementById("retrievedField-1")
if (!newKeyword) {
newKeyword = document.createElement("p");
newKeyword.setAttribute("id", "retrievedField-1");
newKeyword.setAttribute("class", "retrievedFieldName");
document.getElementById("retrievedFields").appendChild(newKeyword);
}
newKeyword.innerText = inputKeyword;
}
Using innerHTML when I add a new item, the query selector does not seem to add it.
So when I try to calculate my items. I only am getting the original ones to calculate, but not the newly generated ones.
Even when you console.log() the elements by the variable it will only show the original elements.
All these elements have the same class name as the original element.
Just cannot get them to be seen or added on the generated items.
Fiddle code snippet.
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
const cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
//
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
});
cal.addEventListener('mouseover', function(e) {
console.log('total', total);
for (var i = 0; i < price.length; i++) {
let xPrice = price[i].innerHTML.split("$");
let parsePrice = parseFloat(xPrice[1]);
if (textval[i].value === "" || isNaN(textval[i].value)) {
console.log("No Good");
} else {
let x = parseFloat(textval[i].value);
let y = parsePrice;
let z = x * y;
total[i].innerText = z.toFixed(2);
total[i].innerText = z;
for (let k = 0; k < total.length; k++) {
let j = parseFloat(total[k].innerHTML);
console.log(j);
}
}
}
});
<body>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 1</span>
</div>
<div>
<span class="cost">$100.00</span>
</div>
<div id="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<br><br>
<div class="main">
<span class="title">A Title</span>
</div>
<div class="content">
<div class="item">
<span>Item 2</span>
</div>
<div>
<span class="cost">$50.00</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
<p class="error"></p>
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
</div>
<form class ='theform'>
<label>NewItem</label><input placeholder="0" class="new-item">
<button id="create">create</button>
</form>
<span class ="newStuff"></span>
<div class="calc-button">
<button id="calc">Calculate Prices</button>
</div>
</body>
#Phil is right on this. You are running the query selectors at the start of your script and will therefore run only once. So when the user clicks a button and you dynamically add new html to the page, the query selectors will not fire again.
You can initialize those queries at the top of your script just like you have them now, but you will need to re-assign their values to new queries inside your event listener something like the following:
const total = document.querySelectorAll(".tot")
const price = document.querySelectorAll(".cost");
let textval = document.querySelectorAll('.qty-item');
let cal = document.getElementById("calc");
const errorMessage = document.querySelectorAll('.error');
//
let theform = document.querySelector(".theform");
let newitem = document.querySelector('.new-item');
let createBtn = document.getElementById("create");
let theItem = document.querySelector(".newStuff");
form.addEventListener("click",function(e){
let theHtml = `
<div>
<span class="cost">${newitem.value}</span>
</div>
<div class="qty">
<label>QTY:</label><input placeholder="0" class="qty-item">
</div>
<div class="tot">
<span><label>TOTAL</label> $0.0</span>
</div>
`
//append your HTML to the correct target element then update your query inside the event listener
textval = document.querySelectorAll('.qty-item');
cal = document.getElementById("calc");
});
Given all your querySelectorAll() queries are using simple, single-class-name selectors, you can replace them all with document.getElementsByClassName(), ie
const total = document.getElementsByClassName('tot')
const price = document.getElementsByClassName('cost');
const textval = document.getElementsByClassName('qty-item');
const errorMessage = document.getElementsByClassName('error');
This behaves almost the same as querySelectorAll() with one difference...
elements is a live HTMLCollection of found elements.
The elements referenced in these collections will update automatically as elements are added or removed from the document.
I am making a slideshow for a website i am making.
but my slideshow keeps getting error
Cannot set property 'className' of null
here is my code:
window.onload=function(){
var slideshow = document.getElementsByClassName('slideshow').item(0),
train = slideshow.getElementsByClassName('train').item(0),
lists = document.getElementsByClassName('btns').item(0).getElementsByClassName('btn'),
currentSlide = 0;
(go2slide = function (n) {
if(n>lists.length-1) n=0;
if(n<0) n=lists.length-1;
train.style.left=(-310*n)+'px';
lists.item(currentSlide).className = '';
lists.item(n).className = 'active';
currentSlide=n;
})(0); // set active of first li
nextSlide = function(){
go2slide(currentSlide+1);
}
prvSlide = function(){
go2slide(currentSlide-1);
}
var autoPlayIv = false;
(autoPlayStart = slideshow.onmouseout = function(){
if(autoPlayIv) return;
autoPlayIv = setInterval(nextSlide, 2000);
})(); // run auto play
autoPlayStop = slideshow.onmouseover = function(){
clearInterval(autoPlayIv);
autoPlayIv = false;
}
slideshow.getElementsByClassName('next').item(0).onclick=nextSlide;
slideshow.getElementsByClassName('previous').item(0).onclick=prvSlide;
for (var i=0; i<lists.length; i++) {
(function(j){
lists.item(j).onclick=function(){
go2slide(j);
}
})(i);
}
}
i DO have a li tag classes as btn and a btns ul.
its item(0).
and here is the html related to it
<div class="body">
<div class="slide">
<div class="s1">
<div class="slideshow">
<div class="train">
<script type="text/javascript">
var slidesLen = 3;
for(var i=1;i<=slidesLen;i++){
document.write("<div style=\"background-image:url('../images/pic"+i+".jpg');\"></div>");
}
</script>
</div>
<div class="previous"></div>
<div class="next"></div></div>
<ul class="btns">
<i class="btn"></i>
<i class="btn"></i>
<i class="btn"></i>
</ul>
</div>
<div class="s2"></div>
<div class="s3"></div>
<div class="s4"></div>
<div class="s5">
<div class="I"></div>
<div class="II"></div>
<div class="III"></div>
</div>
</div>
<div class="text"></div>
</div>
and of course its only the body.php i am posting here. I don't think header.php which contains the menu and the css and js association tags are needed. tell me if it is