Move the check mark in MacOS dropdown - javascript

I made a drop down list using the <select> and <option> tag, where every time a new input is typed, the program creates a new option tag with value attribute to add it to the existing options in the drop down list.
However, my client uses a MacOS and he wanted to move the check mark on the drop down list to the recently added option. The check mark only moves when you click on the selected line, but in my case, I want it to also move to the recently added/typed data.
Here is the HTML code:
<!-- Created select tag so user can access history of talk -->
<div style="top:60px;position:absolute;z-index:2" id="speechBox">
<!-- The select tag acts like a drop down button, so it passes its value to the input box and not to itself -->
<select id = 'combo-box' title = "Saved Talk" onchange="document.getElementById('userText').value=this.options[this.selectedIndex].text; document.getElementById('idValue').value=this.options[this.selectedIndex].value;">
</select>
<span class = "dropdown" name = "Saved Talk"></span>
<input id ="userText" name="userText" type="text" onfocus="this.select()" ></input>
<input name="idValue" id="idValue" type="hidden">
<button id="speakText" class="toolbutton" title="Speak"></button>
<hr>
</div>
And the JS:
hiddenArray(); // Access speakArray
// Function containing the speakArray, which saves the recent talk array
function hiddenArray() {
speakArray = [];
}
function playVoice(language, text) {
playing = text;
//Adds option when text is spoken
var addUserInput = document.createElement("OPTION");
addUserInput.setAttribute("value", playing);
addUserInput.text = playing;
document.getElementById("combo-box").appendChild(addUserInput);
speakArray.push(playing); // Adds recent talks to speakArray
if(document.getElementById('mode').innerHTML=="2"){
//After the voice is loaded, playSound callback is called
getBotReply(text);
setTimeout(function(){
loadVoice(language, playSound);
}, 4000);
}
else{
loadVoice(language, playSound);
}
}

I've figured it out in the end. Here is the code:
hiddenArray(); // Access speakArray
// Function containing the speakArray, which saves the recent talk array
function hiddenArray() {
speakArray = [];
}
function playVoice(language, text) {
playing = text;
//Adds option when text is spoken
var addUserInput = document.createElement("OPTION");
addUserInput.setAttribute("value", playing);
addUserInput.text = playing;
document.getElementById("combo-box").appendChild(addUserInput);
document.getElementById("combo-box").value = playing;
speakArray.push(playing); // Adds recent talks to speakArray
if(document.getElementById('mode').innerHTML=="2"){
//After the voice is loaded, playSound callback is called
getBotReply(text);
setTimeout(function(){
loadVoice(language, playSound);
}, 4000);
}
else{
loadVoice(language, playSound);
}
}
So what I did here is asign the value of the combo box (select tag) to the recently added option (variable playing).

Related

HTML onclick pass parameter to javascript

In javascript, I'm generating this HTML element:
tdSecond.innerHTML += `<select id="train_input" class="custom-select" style="width: 70px; margin-bottom: 10px;" onchange="setAndReload(${data[i]['id']})">
So on a change of this select, I want to call setAndReload function with data[i]['id'] parameter. However, when I do a console log of that parameter in my setAndReload function, what I get is this:
[object HTMLHeadingElement]
How can I pass that parameter into onclick correctly, so that I get the real string?
data[i] is an object, that holds id attribute (and that's string). I want to have a string sent as a parameter.
When you try to get the selected value in onchange function as parameter you can do something like this:
function myFunction(selectedObject) {
var x = document.getElementById("mySelect").value;
document.getElementById("demo").innerHTML = `You selected: ${selectedObject.value} House`;
}
<!DOCTYPE html>
<html>
<body>
<p>Select a new house from the list.</p>
<select id="mySelect" onchange="myFunction(this)">
<option value="Tiny">Tiny House</option>
<option value="Big">Big House</option>
<option value="Small">Small House</option>
</select>
<p>When you select a new house, a function is triggered which outputs the value of the selected house.</p>
<p id="demo"></p>
</body>
</html>
The above example gets you the selected value on OnChange event.
Have a nice day!
You really should use data attributes and delegation
document.getElementById("myTable").addEventListener("change",function(e) {
const tgt = e.target;
if (tgt.classList.contains("custom-select")) {
setAndReload(tgt.dataset.id,tgt.value)
}
})
using
tdSecond.innerHTML += `<select id="train_input" class="custom-select"
style="width: 70px; margin-bottom: 10px;" data-id ="${data[i]['id']}")>`
I am sure you could use a map on the data array instead of concatenating to innerHTML
You might want to use a single event listener instead of multiple inline event handlers, as shown in the following snippet. I wasn't sure exctly what your select element (including its change listener) is intended to do, so I just made it show/hide the corresponding Train from the data array.
You can also sometimes avoid headaches (such as more complicated maintenance, and errors resulting from typos) by creating DOM elements in JavaScript and appending them to existing elements, rather than trying to parse complex strings for use by the innerHTML method -- so the addTrainInput function demonstrates this. (Compare the "sloppier" code I included that displays each train in the setAndReload listener.)
See the in-code comments for further clarification.
// Identifies some DOM elements, and gets the data array
const
trSecond = document.getElementById("trSecond"),
output = document.getElementById("output"),
data = getData();
// Dynamically adds select elements, and shows trains
for(let i = 0; i < data.length; i++){
addTrainInput(data[i]["id"]); // Adds each select element
}
setAndReload(); // To show all trains right away
// Calls setAndReload whenever something in trSecond changes
trSecond.addEventListener("change", setAndReload);
// Defines the change listener (which also gets called directly)
function setAndReload(event){
// B/c we're listening on parent div, checks event's actual target before proceeding
if(event && !event.target.classList.contains("custom-select")){
return;
}
output.innerHTML = ""; // Hides all trains for now
for(let trainInput of trSecond.children){ // Loops through select elements
if(trainInput.value == "shown"){
// Finds matching train in data
const train = data.find(obj => obj.id == trainInput.dataset.id);
// Shows the train
output.innerHTML += train.image + "<br><br>";
}
}
}
// Defines a function to add each select elemement
// (The corresponding train is tracked via a `data-id` attribute)
function addTrainInput(trainId){
// Makes the select element (with class and data-id attrubutes)
trainInput = document.createElement("select");
trainInput.classList.add("custom-select");
trainInput.dataset.id = trainId;
// Makes an option and appends it to the select
opt1 = document.createElement("option");
opt1.value = "shown";
opt1.textContent = trainId + " Shown";
trainInput.appendChild(opt1);
// Makes another option and appends it to the select
opt2 = document.createElement("option");
opt2.value = "hidden";
opt2.textContent = trainId + " Hidden";
trainInput.appendChild(opt2);
// Finally, adds the select (with its options) to the DOM
trSecond.appendChild(trainInput);
}
// Just returns our initial data array
function getData(){
const data = [
{id: "Train1", image: "&nbsp&nbsp< picture of Train 1 >"},
{id: "Train2", image: "&nbsp&nbsp< picture of Train 2 >"},
{id: "Train3", image: "&nbsp&nbsp< picture of Train 3 >"},
];
return data;
}
.custom-select { width: 110px; margin-right: 10px; }
#output { margin-top: 25px; font-size: 1.2em; }
<div id=trSecond></div>
<div id="output"></div>

getting a value of HTML

Im learning JavaScript and Im having problems trying to get the value of HTML of textareaElement. Theres lots online and because of all the information available its making it more confusing. I understand the idea behind the DOM, but not sure how to do the code. I am also trying to use add an event listener to store data in local storage, but without any luck.
// Add a text entry to the page
function addTextEntry(key, text, isNewEntry) {
// Create a textarea element to edit the entry
var textareaElement = document.createElement("TEXTAREA");
textareaElement.rows = 5;
textareaElement.placeholder = "(new entry)";
// Set the textarea's value to the given text (if any)
textareaElement.value = text;
// Add a section to the page containing the textarea
addSection(key, textareaElement);
// If this is a new entry (added by the user clicking a button)
// move the focus to the textarea to encourage typing
if (isNewEntry) {
textareaElement.focus();
// Get HTML input values
var data = textareaElement.value;
}
// ...get the textarea element's current value
var data = textareaElement.value;
// ...make a text item using the value
var item = makeItem("text", data);
// ...store the item in local storage using key
localStorage.setItem(key, item);
// Connect the event listener to the textarea element:
textareaElement.addEventListener('onblur', addTextEntry);
}
HTML is:
<section id="text" class="button">
<button type="button">Add entry</button>
</section>
<section id="image" class="button">
<button type="button">Add photo</button>
<input type="file" accept="image/*" />
</section>
[HTML][1]
'textareaElements' is not plural as you have it here:
var data = textareaElements.value;
This is the correct form:
var data = textareaElement.value;

javascript & html - creating new checkbox option everytime user enters item in textbox

So basically I'm creating a program that allows the user to create and manage a ‘to-do list’. This will allow the user to add new items, remove selected items, highlight/un-highlight selected items, and sort the items, etc. I'm currently working on the add button, but I'm extremely confused with different functions in HTML and code that will allow me to manipulate the DOM.
When the user clicks the add button and the item name is valid, a new item should be added to the page’s to-do list (which esentially creates a new checkbox for every item the user adds). The checkbox is basically so the item can be selected/deselected, as well as the text that was in the item name textbox when the add button was clicked.
I guess I have two problems right now. I'm trying to verify that the item name is at least 1 character long. I wrote code in my "addHandler.js" file but when I write nothing in the textbox and click on the add button on my HTML browser, no error message pops up. I don't know why it's ignoring my function. Another thing I'm struggling with is the part that creates a new checkbox for every valid item that is added. I know how to create a checkbox on my HTML page, but I don't understand how to get my program to create a new one per item that the user inputs.
Any help or push in the right direction would be appreciated. I'm also new to HTML and javascript, so explaining stuff in simple terms would also make me really grateful.
todo.html code:
<html>
<head>
<title>Checklist</title>
</head>
<body>
<div><h1>My to-do list</h1></div><br />
<div id ="myCheckList">Enter an item:</div>
<div>Type something: <input type="text" id="textbox"></input></div>
<button type="button" id="addBut">Add item</button>
<button type="button" id="removeBut">Remove items</button>
<button type="button" id="toggleBut">Toggle highlight</button>
<button type="button" id="sortBut">Sort items</button>
<script src="addHandler.js"></script>
</body>
</html>
addHandler.js code:
function init(){
let button = document.getElementById("addBut");
button.onclick = buttonClicked;
let tb = document.getElementById("textbox");
tb.onblur = validate;
}
function add(){
let someEle = document.getElementById("myCheckList");
someEle.innerHTML = 'You added an item';
}
function validate(){
if(document.getElementById("textbox").value.length == 0){
alert("You need to enter something");
}
}
You should have a wrapper that contains your checkbox items that you can append new elements to.
<div id="checklist_items"></div>
Then you can use the following function to create a new div that contains a checkbox and the entered text, and then append it to your checklist:
function addItem() {
var input = document.getElementById("textbox");
var wrapper = document.getElementById("checklist_items");
if(input.value.trim() != "") {
var new_element = document.createElement("DIV");
new_element.innerHTML = '<input type="checkbox"> '+input.value;
wrapper.appendChild(new_element);
}
else {
alert("You must enter at least 1 character.");
}
}
I would also use the following to add the function to your button:
document.getElementById("addBut").addEventListener("click", addItem);

How do I change more than one element?

EDIT: I changed the var to class but I might have some error in here.
Here it goes, I want to have this paragraph in which the user can change the name on the following paragraph. The code I'm using only changes one name but the rest remains the same.
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
<input id="userInput" type="text" value="Name of kid" />
<input onclick="changey()" type="button" value="Change Name" /><br>
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
No error messages, the code only changes one name instead of all three.
Use class="kiddo" instead of id in the html.
You can then use var kiddos = document.getElementsByClassName('kiddo') which will return an array of all the elements of that class name stored in kiddos.
Then you just need to loop through the values and change what you want.
Example of loop below:
for (var i = 0; i < kiddos.length; i++) {
kiddos[i].innerHTML = userInput;
}
id should be unique on the page. Javascript assumes that there is only one element with any given id. Instead, you should use a class. Then you can use getElementsByClassName() which returns an entire array of elements that you can iterate over and change. See Select ALL getElementsByClassName on a page without specifying [0] etc for an example.
Hello You should not use id, instead use class.
Welcome to the site <b class="kiddo">dude</b> This is how you create a document that changes the name of the <b class="kiddo">dude</b>. If you want to say <b class="kiddo">dude</b> more times, you can!
After That on Js part :
<script type="text/javascript">
function changey(){
var userInput = document.getElementById('userInput').value;
var list = document.getElementByClassName('kiddo');
for (let item of list) {
item.innerHTML = userInput;
}
}
</script>
you should use class instated of id. if you use id then the id [kiddo] must be unique
In short, document.querySelectorAll('.kiddo') OR
document.getElementsByClassName('kiddo') will get you a list of elements to loop through. Take note of querySelectorAll, though - it uses a CSS selector (note the dot) and doesn't technically return an array (you can still loop through it, though).
See the code below for some full working examples (const and arrow functions are similar to var and function, so I'll put up a version using old JavaScript, too):
const formEl = document.querySelector('.js-name-change-form')
const getNameEls = () => document.querySelectorAll('.js-name')
const useNameFromForm = (formEl) => {
const formData = new FormData(formEl)
const nameValue = formData.get('name')
const nameEls = getNameEls()
// Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(el => el.textContent = nameValue)
}
// Handle form submit
formEl.addEventListener('submit', (e) => {
useNameFromForm(e.target)
e.preventDefault() // Prevent the default HTTP request
})
// Run at the start, too
useNameFromForm(formEl)
.name {
font-weight: bold;
}
<!-- Using a <form> + <button> (submit) here instead -->
<form class="js-name-change-form">
<input name="name" value="dude" placeholder="Name of kid" />
<button>Change Name</button>
<form>
<!-- NOTE: Updated to use js- for js hooks -->
<!-- NOTE: Changed kiddo/js-name to spans + name class to remove design details from the HTML -->
<p>
Welcome to the site, <span class="js-name name"></span>! This is how you create a document that changes the name of the <span class="js-name name"></span>. If you want to say <span class="js-name name"></span> more times, you can!
</p>
var formEl = document.querySelector('.js-name-change-form');
var getNameEls = function getNameEls() {
return document.querySelectorAll('.js-name');
};
var useNameFromForm = function useNameFromForm(formEl) {
var formData = new FormData(formEl);
var nameValue = formData.get('name');
var nameEls = getNameEls(); // Set the text of each name element
// NOTE: use .textContent instead of .innerHTML - it doesn't get parsed, so it's faster and less work
nameEls.forEach(function (el) {
return el.textContent = nameValue;
});
};
// Handle form submit
formEl.addEventListener('submit', function (e) {
useNameFromForm(e.target);
e.preventDefault(); // Prevent the default HTTP request
});
// Run at the start, too
useNameFromForm(formEl);
<button class="js-get-quote-btn">Get Quote</button>
<div class="js-selected-quote"><!-- Initially Empty --></div>
<!-- Template to clone -->
<template class="js-quote-template">
<div class="js-quote-root quote">
<h2 class="js-quote"></h2>
<h3 class="js-author"></h3>
</div>
</template>
You have done almost everything right except you caught only first tag with class="kiddo".Looking at your question, as you need to update all the values inside tags which have class="kiddo" you need to catch all those tags which have class="kiddo" using document.getElementsByClassName("kiddo") and looping over the list while setting the innerHTML of each loop element to the userInput.
See this link for examples:https://www.w3schools.com/jsref/met_document_getelementsbyclassname.asp
try:
document.querySelectorAll('.kiddo')
with
<b class="kiddo">dude</b>

Removing child nodes on dynamic select

I'm creating a dynamic selection form. Basically the user picks an option from the select and then depending on what option they chose it goes into a data object and then generates a new selection based on their previous answer. After they answer 3 questions regarding their vehicle choice it prints out their vehicle choice.
The problem I'm running into is having the ability to change a previous option on the fly. I'd like to have them be able to change a previous selection and it would remove the later selection
Ex. The user first selects Car, Ford and a selection for model is displayed. If the user went back and changed Car to Truck. I would like to remove Ford and the model selection. Here is the part of the code I have that holds the data and creates the new selections dynamically
var data=new Object();// create a new data object to hold info
data['init']=['Car','Truck','SUV'];
data['Car']=['Audi','Dodge','Ford','Volkswagon'];
data['Audi']=['A4','TT','R8'];
data['Dodge']=['Charger','Challenger','Stealth'];
data['Ford']=['Focus','Fusion','Mustang'];
data['Volkswagon']=['Jetta','GTI','Beetle'];
data['Truck']=['Dodge Truck','Ford Truck','Toyota Truck'];
data['Dodge Truck'] = ['Ram-1500','Ram-2500','Ram-3500'];
data['Ford Truck'] = ['F-150','F-250','Ranger'];
data['Toyota Truck'] = ['Tundra','Tacoma'];
data['SUV']=['Dodge SUV','Ford SUV','Toyota SUV'];
data['Dodge SUV'] = ['Durango','Journey','Caliber'];
data['Ford SUV'] = ['Escape','Edge','Explorer'];
data['Toyota SUV'] = ['Rav4','Highlander','4runner'];
var hold = data['init'];//Sets data to 'init' by default
var selectedArray = [];//This array holds the selected options (to be used to display the vehicle name)
function init(){//call first to create the first select box and populate with 'init'
firstSelect = document.createElement('select');
firstSelect.setAttribute("onChange","createSelect(this.value)");
createSelect('init');
}
//Main create function for select boxes
function createSelect(value){
selectHold = value;//sets selectHold to the value of the selected item (this will be used for displaying the name in disName)
//This just prevents it from adding "Car, Truck or SUV to the selectedArray
if(value != 'init' && value != 'Truck' && value != 'Car' && value != 'SUV' && value != 'Select your vehicle options'){
selectedArray.push(selectHold);
}
hold=data[value];// sets this holder to the value of the selected item for the if statement
if(hold){ //just checks to see if hold exists
var selEle = document.createElement('select');//creates new select element
//gives selEle onchange function
selEle.setAttribute("onChange","createSelect(this.value)");
//Creates the "default" option. Forcing them to pick something.
var defaultOpt = document.createElement('option');
var vehInfo = document.createTextNode("Select your vehicle options");
defaultOpt.appendChild(vehInfo);
selEle.appendChild(defaultOpt);
//Populates the options and adds it to the document
for(var i = 0, l = hold.length; i < l; i++){
var newOpt = document.createElement('option');
newOpt.appendChild(document.createTextNode( hold[i]));
newOpt.setAttribute('value',hold[i]);
selEle.appendChild(newOpt);
}
//put select on the page
document.getElementById('top-container').appendChild(selEle);
}
else{ //if not, then put out final form
disName(selectHold,selectedArray);//call disName function an dpass it the value of selectHold
}
}
HTML:
<div id="top-container">
<h1>Awesome<br/>
Car<br/>
Picker</h1>
</div>
<div id="middle-container">
<h2>Your vechle choice:</h2>
</div>
<div id="bottom-container">
<div id="mail-form">
<form name='mail-form'>
<label>Name</label>
<input name="name" autofocus>
<label>Email</label>
<input name="email">
<label>Credit Card number</label>
<input name="cc">
<input id="submit" name="submit" value="Submit" onClick="validate()">
</form>
</div>
</div>
<body>
What I'm thinking is to check the to see if the selection is the lastChild of the parent node (top container). and if it is not then delete the child of that until it's at the point where it's only the selection that was changed and any selection that fell before it.
Any suggestions?
Thanks!
In your createSelect function, assign an ID to the new element using something like selEle.id = 'newID';.
Before calling the createSelect function, check to see if the new element exists and if so, remove it:
if (document.getElementById('newID'))
document.getElementById('top-container').removeChild(document.getElementById('newID'));

Categories

Resources