What I am trying to achieve is a dropdown menu whose options the user will create by inputting the text content of the option they want to create. I have achieved this but what I want is that the user can delete an option if. I cant figure out how to do this. Help please. Buttons, input fields, anything is fine, but please use vanilla Javascript.
<!DOCTYPE html>
<html>
<div id="name">
<select id="sel"></select>
<input type="text" class="auto-save" id="inputname">
<button id="button" onclick="newnamefunc();document.getElementById('inputname').value='';">
Create Option
</button>
</div>
<script>
function newnamefunc() {
const inputval = document.getElementById('inputname').value;
const createname = document.createElement("option");
createname.setAttribute("class", "option")
const namevalue = document.createTextNode(inputval);
createname.appendChild(namevalue);
const element = document.getElementById("sel");
element.appendChild(createname);
}
</script>
</html>
This is one of the procedures you can follow:
Create a function called deleteOption
Inside function, loop through the selectBoxElem variable and find the selected option. Then Remove the element
Attach the function to a button.
Example:
function newnamefunc() {
const inputval = document.getElementById('inputname').value;
const createname = document.createElement("option");
createname.setAttribute("class", "option")
const namevalue = document.createTextNode(inputval);
createname.appendChild(namevalue);
const element = document.getElementById("sel");
element.appendChild(createname);
}
function deleteOption() {
const selectBoxElem = document.getElementById("sel");
for (var i = 0; i < selectBoxElem.length; i++) {
if (selectBoxElem.options[i].value == selectBoxElem.value)
selectBoxElem.remove(i);
}
}
<!DOCTYPE html>
<html>
<div id="name">
<select id="sel"></select>
<input type="text" class="auto-save" id="inputname">
<button id="button" onclick="newnamefunc();document.getElementById('inputname').value='';">
Create Option
</button>
<button id="button" onclick="deleteOption()">
Delete Selected Option
</button>
</div>
</html>
select element has options collection. The collection has remove method. You can use it like so;
const select = document.querySelector('select'),
options = select.options;
options.remove(select.selectedIndex);
Here is a complete solution which I rewrote to use eventListeners
document.getElementById("name").addEventListener("click",function(e) {
const tgt = e.target;
const src = document.getElementById('inputname');
const sel = document.getElementById("sel");
const inputval = src.value;
src.value="";
if (tgt.id==="add") {
if (sel.querySelector("option[value="+inputval+"]")) {
alert("That already exists")
}
else {
sel.options[sel.options.length] = new Option(inputval,inputval)
sel.value = inputval; // focus the new value
}
}
else if (tgt.id==="del") {
if (sel.selectedIndex === 0) return;
if (inputval) sel.value = inputval; // if filled in, we use it
const curOpt = sel.options[sel.selectedIndex]; // in any case remove the selected option
if (curOpt) {
curOpt.remove();
sel.selectedIndex = -1;
}
}
})
<div id="name">
<select id="sel"><option value="">Please select</option></select>
<input type="text" class="auto-save" id="inputname">
<button type="button" id="add">Create Option</button>
<button type="button" id="del">Remove Option</button>
</div>
Here you go with a solution
function newnamefunc() {
const inputval = document.getElementById('inputname').value;
const createname = document.createElement("option");
createname.setAttribute("class", "option")
const namevalue = document.createTextNode(inputval);
createname.appendChild(namevalue);
const element = document.getElementById("sel");
element.appendChild(createname);
}
function deleteOption() {
const element = document.getElementById("sel");
element.remove(element.selectedIndex);
}
<div id="name">
<select id="sel"></select>
<input type="text" class="auto-save" id="inputname">
<button id="button" onclick="newnamefunc();document.getElementById('inputname').value='';">
Create Option
</button>
<button id="button" onclick="deleteOption();">
Delete Option
</button>
</div>
Documentation: https://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_select_remove
use this:
function RemoveOption(){
var Element = document.getElementById("sel");
Element.remove(Element.selectedIndex);
}
Create new button in html
<button id="button" onclick="remove(document.getElementById('inputname').value);document.getElementById('inputname').value='';">
Delete Option
</button>
And add js function
function remove(val) {
var selectobject = document.getElementById("sel");
for (var i=0; i<selectobject.length; i++) {
if (selectobject.options[i].value == val)
selectobject.remove(i);
}
}
Related
I have a problem in Javascript.I am adding new list items to the 'ul' elements and this list is empty at first and I do not want to add same values twice. When I write the if statement I get the exception because my list is empty so the result return null.
How can I fix this this problem?
Thank you in advance...
Html Codes
<input type="text" id="the-filter" placeholder="Search For..." />
<div class="list-container">
<ul id="myList"></ul>
<button id="button">Click</button>
Javascript Codes
let newlist = document.querySelector("#myList");
const li = document.getElementsByClassName('list-group-item');
const button = document.getElementById("button");
const button.addEventListener('click' , listName);
const input = document.getElementById("the-filter");
function listName()
const inputVal = input.value;
for (i = 0; i < li.length; i++) {
if ((li[i].innerHTML.toLocaleLowerCase().includes(inputVal) && inputVal!="") ||
(li[i].innerHTML.toUpperCase().includes(inputVal) && inputVal!="")) {
let newItem = document.createElement("li");
li[i].classList.add("list-group-item");
let textnode = document.createTextNode(li[i].innerHTML.toLocaleLowerCase());
newItem.appendChild(textnode);
if((newlist.children[0].innerHTML.toLocaleLowerCase().includes(inputVal))){
newlist.insertBefore(newItem, newlist.childNodes[0]);
}
}
}
}
If I understood the task correct, you need to add items to the list by button click.
If same item exists (case insensitive), then nothing happens.
const list = document.querySelector("#myList");
const button = document.getElementById("button");
button.addEventListener("click", listName);
const input = document.getElementById("the-filter");
function listName() {
const inputVal = input.value;
const [...lis] = document.getElementsByClassName("list-group-item");
const same = lis.find((el) => el.textContent.toLowerCase() === inputVal.toLowerCase());
if (same) {
return;
}
let newItem = document.createElement("li");
newItem.classList.add("list-group-item");
newItem.textContent = inputVal;
list.appendChild(newItem)
}
<input type="text" id="the-filter" placeholder="Search For..." />
<div class="list-container">
<ul id="myList"></ul>
<button id="button">Click</button>
</div>
You're on the right track with event listeners and element creation, but your original code didn't quite seem to match your stated goal.
Here's a solution you might find useful, with some explanatory comments:
// Identifies some DOM elements
const
input = document.getElementById("my-input"),
newList = document.getElementById("my-list"),
items = document.getElementsByClassName('list-group-item'),
button = document.getElementById("my-button");
// Focuses input, and calls addItem on button-click
input.focus();
button.addEventListener('click', addItem);
// Defines the listener function
function addItem(){
// Trims whitespace and sets string to lowerCase
const inputTrimmedLower = input.value.trim().toLocaleLowerCase();
// Clears and refocuses input
input.value = "";
input.focus();
// Ignores empty input
if (!inputTrimmedLower) { return; }
// Ignores value if a list item matches it
for (const li of items) {
const liTrimmedLower = li.textContent.trim().toLocaleLowerCase();
if (liTrimmedLower === inputTrimmedLower) {
console.log(`${inputTrimmedLower} is already listed`);
return;
}
}
// If we got this far, we want to add the new item
let newItem = document.createElement("li");
newItem.classList.add("list-group-item");
newItem.append(inputTrimmedLower); // Keeps lowerCase, as your original code
newList.prepend(newItem); // More modern method than `insertBefore()`
}
<input id="my-input" />
<ul id="my-list"></ul>
<button id="my-button">Click</button>
when i add new input box with javascript function, previous input boxes become empty. here is the code:
<div id="field">
<input type="text">
</div>
<div id="error"></div>
<button onclick="Add()">add</button>
<script>
let i=0;
const Add=()=>{
i++
if(i<5)
document.getElementById('field').innerHTML+=`<input type="text" id="value${i}">`
else
document.getElementById('error').innerHTML='Error: Field cant be more then 5'
}
</script>
what can I do to NOT change input values of input box on adding new input box with above codes.
You are overwriting the entire HTML content of ID field,
let i = 0;
const Add = () => {
i++
if (i < 5) {
const input = document.createElement('input');
document.getElementById('field').appendChild(input);
} else
document.getElementById('error').innerHTML = 'Error: Field cant be more then 5'
}
<div id="field">
<input type="text">
</div>
<div id="error"></div>
<button onclick="Add()">add</button>
One way of doing it, keeping in mind separation of concerns and avoiding the creation of unnecessary global variables could be:
#error {
display: none;
}
<div id="field">
<input type="text">
</div>
<div id="error"></div>
<button onclick="Add()">add</button>
<script>
const Add = () => {
const inputContainer = document.querySelector('#field'); // this variable is not strictly necessary but I think it makes the code more readable
const inputNotification = document.querySelector('#error'); // this variable is not strictly necessary but I think it makes the code more readable
const inputCount = inputContainer.querySelectorAll('input[type=text]').length // count how many input elements of type text are already inside the `field` div
if (inputCount < 5) {
const txtInput = document.createElement('input');
txtInput.setAttribute('type', 'text');
txtInput.setAttribute('id', `value${inputCount}`);
inputContainer.append(txtInput);
} else {
inputNotification.innerText = 'Error: Field can\'t be more than 5';
inputNotification.style.display = 'block'
event.target.setAttribute('disabled', true); // optionally, you can disable the add button if you reached the maximum number of input fields
}
}
</script>
You could use Document.createElement() and element.appendChild() so that you do not alter the HTML of the div#field :
<div id="field">
<input type="text">
</div>
<div id="error"></div>
<button onclick="Add()">add</button>
<script>
let i=0;
const Add=()=>{
i++
if(i<5) {
let input = document.createElement("input");
input.type = "text";
input.id = "value" + i;
let button = document.createElement("button");
button.innerText = "delete";
button.onclick = function(){
input.remove(); //remove text input
this.remove(); //remove this delete button
i--; //decrement i
};
document.getElementById('field').appendChild(input);
document.getElementById('field').appendChild(button);
} else {
document.getElementById('error').innerHTML='Error: Field cant be more then 5';
}
}
</script>
I would need help to move forward with my code. I want each time the user writes (,) between two words, they should be separated and form two li elements in a list. Right now the whole code works but I would get tips on how to make a comma separated text.
var names = [];
function convert_to_list()
{
var theName = document.getElementById("enter").value;
if (theName == "" || theName.length == 0)
{
return false; //stop the function since the value is empty.
}
names.push(theName);
document.getElementById("converted_list").children[0].innerHTML += "<li>"+names[names.length-1]+"</li>";
}
<form>
<fieldset>
<textarea id="enter" onkeyup=""></textarea>
<input onclick="convert_to_list()"value="Konvertera" type="button"/>
<div id="converted_list"><ul></ul></div>
</form>
</fieldset>
You could do something like I did in this codepen.
Use the split function to split a string when it encounters a specified character, in your case a comma.
The HTML (pug) would look like this:
form
label
span seperated list
input#js-seperatedList(type="text")
ul.results
And this will be your JavaScript code:
const inputValue = document.querySelector('#js-seperatedList')
const results = document.querySelector('.results');
inputValue.addEventListener('keyup', (e) => {
results.innerHTML = ''
const res = e.target.value.split(",")
for (let i = 0; i < res.length; i += 1) {
const e = document.createElement('li');
e.innerHTML = res[i]
results.appendChild(e)
}
})
Use split() function to separate the words using comma and then create li element and append into final ul element.
const btnEnter = document.getElementById("btnEnter");
btnEnter.addEventListener("click", convert_to_list);
const ulElements = document.getElementById("converted_list").children[0];
function convert_to_list() {
const theName = document.getElementById("enter").value;
if (theName.length <= 0) {
return false;
}
const list = theName.split(",");
const liElements = [];
for (const value of list) {
const li = document.createElement('li');
li.innerHTML = value.trim();
ulElements.appendChild(li);
}
}
<html>
<head></head>
<body>
<form>
<fieldset>
<textarea id="enter" onkeyup=""></textarea>
<input id="btnEnter" value="Konvertera" type="button"/>
<div id="converted_list"><ul></ul></div>
</fieldset>
</form>
</body>
</html>
i would recommend using addEventListener which is much simpler than calling functions inside html elements , and to do what you asking the split() method can do that with any string , if there is something you don't understand with this code i am happy to help
document.querySelector('.btnclick').addEventListener('click', function () {
const theName = document.getElementById('enter').value;
if (theName.includes(',')) {
theName.split(',').map(function (e) {
if (e !== '')
return document
.querySelector('#converted_list')
.insertAdjacentHTML('afterbegin', `<li>${e}</li>`);
});
} else if (theName !== '' || theName.length !== 0) {
document
.querySelector('#converted_list')
.insertAdjacentHTML('afterbegin', `<li>${theName}</li>`);
}
});
<form>
<fieldset>
<textarea id="enter" onkeyup=""></textarea>
<input class="btnclick" value="Konvertera" type="button" />
<div id="converted_list">
<ul></ul>
</div>
</form>
document.querySelector("form").onclick=(ev,v)=>{
if (ev.target.tagName==="BUTTON") {
ev.preventDefault();
v=ev.target.previousElementSibling.value.trim();
ev.target.nextElementSibling.innerHTML=(v>""?"<li>"+v.replaceAll(",","</li><li>")+"</li>":"");
}
}
<html>
<head></head>
<body>
<form>
<fieldset>
<textarea id="enter" onkeyup=""></textarea>
<button>Konvertera</button>
<div id="converted_list"><ul></ul></div>
</fieldset>
</form>
</body>
</html>
I am currently taking Wes Boros JS 30 challenge and for this particular class, we created a list where we add foods we like. As an extra assignment, we are to create a select all function, an unselect all function, and a delete function. I was able to successfully create a select all function where once you click that button, it selects all the items on the current list. My issue is that the delete function I created deletes everything, except for one or two items. Those undeleted items still remain checked, but I have to click on the delete button again in order for it to delete. FYI: I local storage was incorporated in this exercise.
Can somebody help me out and also explain what I was doing wrong?
Here is a jsfiddle of it as well
Here is how I have my HTML set up:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>LocalStorage</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="wrapper">
<h2>LOCAL TAPAS</h2>
<p></p>
<ul class="plates">
<li>Loading Tapas...</li>
</ul>
<form class="add-items">
<input type="text" name="item" placeholder="Item Name" required>
<input type="submit" value="+ Add Item">
</form>
<input type="button" onclick="selectAll()" value="Select All"/>
<input type="button" onclick="UnSelectAll()" value="Unselect All"/>
<input type="button" onclick="deleteItem()" value="delete Item"/>
</div>
</body>
</html>
Here is my Javascript:
const addItems = document.querySelector('.add-items');
const itemsList = document.querySelector('.plates');
const items = JSON.parse(localStorage.getItem('items')) || [];
//DELETE FUNCTION
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
for(var i = 0; i < boxes.length; i++){
box = boxes[i];
txt = texts[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
//SELECT ALL FUNCTION
function selectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = true;
}
}
//UNSELECT ALL FUNCTION
function UnSelectAll(){
var checkedItem = document.getElementsByName('item');
for (var i = 0; i < checkedItem.length; i++) {
if (checkedItem[i].type == 'checkbox')
checkedItem[i].checked = false;
}
}
//ADD ITEM FUNCTIO
function addItem(e){
e.preventDefault()
const text = (this.querySelector('[name=item]')).value;
const item = {
text,
done: false
};
items.push(item);
populateList(items, itemsList);
localStorage.setItem('items', JSON.stringify(items));
this.reset();
}
//DISPLAY THE HTML FUNCTION
function populateList(plates =[], platesList) {
platesList.innerHTML = plates.map((plate, i) => {
return `
<li>
<input class="chk" type="checkbox" name="item" data-index=${i} id="item${i}" ${plate.done ? 'checked' : ''} />
<label class="txt" name="item" for="item${i}">${plate.text}</label>
</li>
`
}).join('');
}
function toggleDone(e){
if(!e.target.matches('input')) return;
const el = e.target;
const index = el.dataset.index;
items[index].done = !items[index].done;
localStorage.setItem('items', JSON.stringify(items));
populateList(items, itemsList);
}
addItems.addEventListener('submit', addItem)
itemsList.addEventListener('click', toggleDone)
populateList(items, itemsList);
//DELETE ITEM EVENT HANDLER
itemsList.addEventListener('click', deleteItem);
The reason why your delete function wasn't working properly it's because Node.childNodes returns a live NodeList which means when you use removeChild on each element in the collection the other elements gets rearranged and the length of list get's smaller causing you to skip some of them so you should convert your html collection to an array using Array.from
function deleteItem(){
var boxes = document.getElementsByClassName('chk');
var texts = document.getElementsByClassName('txt');
arrbox = Array.from(boxes)
arrtext = Array.from(texts)
for(var i = 0; i < arrbox.length; i++){
var box = arrbox[i];
var txt = arrtext[i];
if(box.checked){
box.parentNode.removeChild(box);
txt.parentNode.removeChild(txt);
}
}
}
Here is working jsfiddle
This code successfully takes the contents of the form and saves it to an ordered list, 2 more functions do the same thing but instead create a timestamp. I'm trying to take every li element that gets generated and save it to localStorage when you push the save button and then repopulate it again from the local storage when you push the "load" button. I can't get it to work come hell or high water. The load button does nothing, and oddly enough the "save" button acts as a clear all and actually removes everything rather then saving it. Console log shows no errors. I have the JavaScript below and the corresponding HTML.
let item;
let text;
let newItem;
function todoList() {
item = document.getElementById("todoInput").value
text = document.createTextNode(item)
newItem = document.createElement("li")
newItem.onclick = function() {
this.parentNode.removeChild(this);
}
newItem.onmousemove = function() {
this.style.backgroundColor = "orange";
}
newItem.onmouseout = function() {
this.style.backgroundColor = "lightblue";
}
todoInput.onclick = function() {
this.value = ""
}
newItem.appendChild(text)
document.getElementById("todoList").appendChild(newItem)
};
function save() {
const fieldvalue = querySelectorAll('li').value;
localStorage.setItem('item', JSON.stringify(item));
}
function load() {
const storedvalue = JSON.parse(localStorage.getItem(item));
if (storedvalue) {
document.querySelectorAll('li').value = storedvalue;
}
}
<form id="todoForm">
<input id="todoInput" value="" size="15" placeholder="enter task here">
<button id="button" type="button" onClick="todoList()">Add task</button>
<button id="save" onclick="save()">Save</button>
<button id="load" onclick="load()">Load</button>
</form>
As #Phil and #Gary explained part of your problem is trying to use querySelectorAll('li') as if it would return a single value. You have to cycle through the array it returns.
Check the below code to give yourself a starting point. I had to rename some of your functions since they were causing me some errors.
<form id="todoForm">
<input id="todoInput" value="" size="15" placeholder="enter task here">
<button id="button" type="button" onClick="todoList()">Add task</button>
<button id="save" onclick="saveAll()" type="button">Save</button>
<button id="load" onclick="loadAll()" type="button">Load</button>
</form>
<div id="todoList"></div>
<script>
let item;
let text;
let newItem;
function todoList() {
item = document.getElementById("todoInput").value
text = document.createTextNode(item)
newItem = document.createElement("li")
newItem.onclick = function() {
this.parentNode.removeChild(this);
}
newItem.onmousemove = function() {
this.style.backgroundColor = "orange";
}
newItem.onmouseout = function() {
this.style.backgroundColor = "lightblue";
}
todoInput.onclick = function() {
this.value = ""
}
newItem.appendChild(text)
//Had to add the element
document.getElementById("todoList").appendChild(newItem);
}
function saveAll() {
//Create an array to store the li values
var toStorage = [];
var values = document.querySelectorAll('li');
//Cycle through the li array
for (var i = 0; i < values.length; i++) {
toStorage.push(values[i].innerHTML);
}
console.log(toStorage);
//CanĀ“t test this on stackoverflow se the jsFiddle link
localStorage.setItem('items', JSON.stringify(toStorage));
console.log(localStorage);
}
function loadAll() {
const storedvalue = JSON.parse(localStorage.getItem('items'));
console.log(storedvalue);
//Load your list here
}
</script>
Check https://jsfiddle.net/nbe18k2u/ to see it working