I need to dynamically generate a drop-menu list from an array via JavaScript. I'm getting close, but while I can populate the array elements into the Bootstrap-enabled drop-menu that appears on my index.html page, I cannot select those individual elements that show up as drop menu items. I need to edit my code so I can click on one of those elements and run my second function, that populates the selection to an input field.
First, here's my script to iterate over the array:
<script>
let select = document.getElementById("selectJob");
let options = ["Job 1", "Job 2", "Job 3", "Job 4", "Job 5"];
for (let i = 0; i < options.length; i++) {
let opt = options[i];
let el = document.createElement("option");
el.textContent = opt;
el.value = opt;
select.appendChild(el);
}
</script>
And here's the second script I use:
<script>
function populateJobVal(val) {
document.getElementById("selection").value = val;
}
</script>
And here's the drop-menu section in my HTML where I'm trying to use this:
<div class="dropdown">
<button class="btn btn-default btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
Select Job Type to Schedule
<span class="caret"></span></button>
<ul class="dropdown-menu" id="selectJob">
<li>
<a href="#" role="button" onclick="populateJobVal(selectJob)" class="btn btn-link">
</a>
</li>
</ul>
</div>
Notice I am adding the "id" to the <ul> element. Should it be going elsewhere? I did try putting the "id" on the <li> element, but that makes all the array elements one clickable field, rather than each one being clickable.
Right now, when I click on the drop-menu button, the different jobs do appear. However, they are not individually clickable.
What do I need to edit in my code to make each element a clickable link?
To match what you have templated, you need to do the following:
let select = document.getElementById("selectJob");
let options = ["Job 1", "Job 2", "Job 3", "Job 4", "Job 5"];
for (let i = 0; i < options.length; i++) {
let opt = options[i];
let a = document.createElement("a");
a.textContent = opt;
a.setAttribute('href', '#');
a.setAttribute('onclick', 'populateJobVal(selectJob)');
a.setAttribute('class', 'btn btn-link');
let li = document.createElement("li");
li.appendChild(a);
select.appendChild(li);
}
function populateJobVal(val) {
document.getElementById("selection").value = val;
}
<div class="dropdown">
<button class="btn btn-default btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
Select Job Type to Schedule
<span class="caret"></span></button>
<ul class="dropdown-menu" id="selectJob">
</ul>
</div>
Related
I'm new to JavaScript and have 2 html links:
<li><a class="dropdown-item confirm" href="#">wtdata</a></li>
<li><a class="dropdown-item confirm" href="#">ftdata</a></li>
The first step is getting the specific text value by clicking each link. For example, if I click the first link I will get the text wtdata. If I click the second link, I get the text ftdata. I have completed this step by:
<script>
var myFunction = function() {
var attribute = this.innerHTML;
alert(attribute);
};
var elements = document.getElementsByClassName("dropdown-item");
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', myFunction, false);
}
</script>
After clicking the link in last step, a Bootstrap modal will automatically pop out which has 2 buttons. This is a built-in Bootstrap function, already done. The buttons are:
<button id='cancel_btn'>Cancel</button>
<button id='confirm_btn'>Confirm</button>
The second step is:
If in the first step link wtdata is clicked and Confirm button in pop windows has been clicked,then replace the href value of link wtdata with 'wtdata_url'.
Same as link ftdata,if
in the first step link ftdata is clicked and Confirm button in pop window has been clicked ,replace the href value of link ftdata with 'ftdata_url'.
How to complete the second step?I have tried build a function to return the specific text that has been clicked ,but I can't get the return value:
<script>
function getLinkname(cl){
var elements = document.getElementsByClassName(cl);
var getText = function() {
var attribute = this.innerHTML;
document.getElementById("staticBackdropLabel").innerHTML='Run ' + attribute + ' ?';
};
for (var i = 0; i < elements.length; i++) {
elements[i].addEventListener('click', getText, false);
}
return attribute;
}
var linkname = getLinkname('confirm');
console.log(linkname);
</script>
error:
Uncaught ReferenceError: attribute is not defined
at getLinkname ((index):159:1)
This example I wrote is based on my undertanding about your question.
📌 I use the id attribute, because it is a simple way.
📌 If you want to change innerText of <a/> tag dynamically, the better way is to produce your <ul/> link list by JavaScript.
function clickATag (e) {
document.getElementById('input').value = e.innerText
document.getElementById('aTagId').innerText = e.id
var myModal = getMyModal();
myModal.show()
}
function clickButton (e) {
const aTagId = document.getElementById('aTagId').innerText;
const a = document.getElementById(aTagId);
a.innerText = document.getElementById("input").value;
const result = document.getElementById('result');
result.innerText = "new url: " + document.getElementById("input").value;
}
function getMyModal () {
var myModal = new bootstrap.Modal(document.getElementById('myModal'), {
keyboard: false
})
return myModal;
}
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"></script>
<ul>
<li><a id="a1" class="dropdown-item confirm" href="#" onclick="clickATag(this)">wtdata</a></li>
<li><a id="a2" class="dropdown-item confirm" href="#" onclick="clickATag(this)">ftdata</a></li>
</ul>
<div id="myModal" class="modal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Modal title</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<input id="input" />
<p id="result">new url:</p>
<p id="aTagId" hidden></p>
<p>Buttons</p>
<button id='cancel_btn' type="button" class="btn btn-primary" onclick="clickButton(this)">Confirm</button>
<button id='confirm_btn' type="button" class="btn btn-secondary">Cancel</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
I have made a navigation tab with buttons, and a side-button which displays a list of files when I click the nav button.
Visual representation:
check1 check2 check3
dropdown (assuming check1 is clicked)
1.txt
2.txt
All the information comes up properly when I click on these checks in the console. but when I click on the button second time, it doesn't display any dropdown even though it shows correct information in console.
Code for function to create dropdown:
function add_pvt_dropdown(files) {
const dropdown_div = document.getElementById("pvt_list_dropdown");
//console.log(dropdown_div.childNodes[2])
console.log("these are the child nodes \n:", dropdown_div.childNodes, "and this is the lenght", dropdown_div.childNodes.length)
if (dropdown_div.childNodes[2])
dropdown_div.removeChild(dropdown_div.childNodes[2])
console.log(dropdown_div)
const UL = document.createElement("ul");
//files = localStorage.getItem('all_file_in_dir').split(',')
if (typeof (files) === undefined && files == null) {
alert("choose something")
} else {
UL.setAttribute("class", "dropdown-menu");
UL.setAttribute("id", "pvt_option");
UL.setAttribute("aria-labelledby", "dropdownMenuButton");
files.forEach(val => {
if (val.includes('CSV_')) {
var li = document.createElement('li');
var a = document.createElement('a');
a.setAttribute('class', "dropdown-item")
a.setAttribute('id', val)
li.appendChild(a);
UL.appendChild(li)
t = document.createTextNode(val);
a.innerHTML = a.innerHTML + val;
console.log(a.innerHTML)
}
});
dropdown_div.appendChild(UL)
}
}
HTML code
<div id="pvt_list_dropdown" class="dropdown" data-toggle="dropdown" data-bs-toggle="dropdown" data-bs-toggle="dropdown" >
<button class="btn btn-secondary dropdown-toggle btn-sm" type="button" id="dropdownMenuButtonPvt" data-toggle="dropdown" data-bs-toggle="dropdown" aria-expanded="false">
List
</button>
</div>
Functionality: when I click on the navigation buttons, it takes all the files from a particular directory and shows as dropdown. As mentioned, it works just once, but when I click any other button or the same button twice, nothing is shows up in the dropdown.
Further information: I checked that it may be an arrangement issue with js and bootstrap but even correcting that doesn't help:
<script src="https://unpkg.com/#popperjs/core#2"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-+0n0xVW2eSR5OomGNYDnhzAbDsOXxcvSN1TPprVMTNDbiYZCxYbOOl7+AMvyTG2x" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-gtEjrD/SeCtmISkJkNUaaKMoLD0//ElJ19smozuHV6z3Iehds+3Ulb9Bn9Plx0x4" crossorigin="anonymous"></script>
how information is shown for that element:
<div id="pvt_list_dropdown" class="dropdown">
<button class="btn btn-secondary dropdown-toggle btn-sm" type="button" id="dropdownMenuButtonPvt" data-bs-toggle="dropdown" aria-expanded="false">List</button>
<ul class="dropdown-menu" id="pvt_option" aria-labelledby="dropdownMenuButton">
<li>
<a class="dropdown-item" id="f1.csv">f1.csv
</a>
</li>
<li>
<a class="dropdown-item" id="f2.csv">f2.csv
</a>
</li>
</ul>
</div>
Edit:
information on how events are triggered:
the menu bar is called when DOM is loaded:
document.addEventListener("DOMContentLoaded", menu_tags)
menu_tags is a function that will dynamically create the menu using create an element
function menu_tags() {
var check = ["check1",
"check2"
]
sub_checks = [
"sub_checks1"
]
var toadd = document.createDocumentFragment();
var i;
for (let i = 0; i < check.length; i++) {
var newLi = document.createElement('a');
newLi.href = "#" + check[i];
newLi.innerHTML = check[i];
newLi.id = check[i];
newLi.className = "tablinks"
newLi.onclick = function() {open(event, check[i])};
// if(lib_verify_check[i] == "lib-checker"){
// }
toadd.appendChild(newLi);
}
document.getElementById("myTopnav").appendChild(toadd)
}
The open function will fetch the information for files for selected check
function open(event, checkname){
var i, tabcontent, tablinks;
tablinks = document.getElementsByClassName("tablinks");
for (i = 0; i < tablinks.length; i++) {
tablinks[i].className = tablinks[i].className.replace("active", "");
}
event.currentTarget.className += " active";
console.log(event.currentTarget.id)
localStorage.setItem('selected_check', event.currentTarget.id)
// Exists.
if(event.currentTarget.id){
get_files()
console.log("changed")
}
//localStorage.getItem('get_files')
}
in the get_files() function, all the file information will be stored and that information will be displayed in dropdown.
Please find the fiddle link below:
Note that get_files wont work in fiddle, this is for checking the functionality:
fiddle_link
Good morning!
I am obviously pretty new to the whole programming thing, so I am working on a basic PoS application for a restaurant. I am trying to figure out how I can assign different values to the different buttons while using the same button click function. I know I could write out a new function for each button with the correct object properties pushed, but there has to be a better way. I currently just have it set for the top right port nachos button to push the information into the tab section (though right now I am drawing a blank as to why it is the only one to do this instead of all the foodbuttons pushing the pork nachos info). Any help would be greatly appreciated. Thanks again!
<body>
<header>
<h1>Point of Sale</h1>
</header>
<section id="foodOptionsSection">
<h3>Food Options</h3>
<button type="button" class= "foodButtons buttons" id="porkNachosFood">Pulled Pork Nachoes</button>
<button type="button" class= "foodButtons buttons" id="wingsFood">6 Wings</button>
<button type="button" class= "foodButtons buttons" id="totsFood">Tater Tots</button>
<button type="button" class= "foodButtons buttons" id="hamburgerFood">Hamburger</button>
<button type="button" class= "foodButtons buttons" id="cbqbbqFood">CBWBBQ</button>
<button type="button" class= "foodButtons buttons" id="ppgcFood">PPGC</button>
<button type="button" class= "foodButtons buttons" id="tacosFood">Tacos</button>
<button type="button" class= "foodButtons buttons" id="friesFood">Fries</button>
<button type="button" class= "foodButtons buttons" id="porkRindsFood">Pork Rinds</button>
</section>
<section id="tabList">
<h3>Current Tab</h3>
<div class="tabNameList tab">
</div>
<div class="tabAmountList tab">
</div>
</section>
<script src="script.js"></script>
</body>
//Vars
const food = [
{
name: "Pulled Pork Nachos",
price: 10.00
},
{
name: "6 Wings",
price: 5.00
},
{
name: "Pork Rinds",
price: 4.00
}
];
const drinks = [
{
name: "Well Vodka",
price: 5.00
},
{
name: "Well Whiskey",
price: 5.00
}
];
const merch = [
{
name: "Well Vodka",
price: 5.00
},
{
name: "T Shirt",
price: 20.00
}
];
const tabNameSection = document.querySelector('.tabNameList');
const tabAmountSection = document.querySelector('.tabAmountList');
const btns = document.querySelector('.foodButtons');
// const wings = document.querySelector('#wingsFood');
// wings.assign('wings', 6.00)
// console.log(wings);
//Functions
function addTab(event) {
//Name Div
const tabNames = document.createElement('div');
tabNames.classList.add('tabNameList');
//Amt Div
const tabAmt = document.createElement('div');
tabAmt.classList.add('tabAmtList');
//Create LI Tab Names
const tabNameList = document.createElement('li');
tabNameList.innerText = food[0].name;
tabNameList.classList.add('tabScreenNames');
tabNames.appendChild(tabNameList);
//Create LI Tab Amounts
const tabAmountList = document.createElement('li');
tabAmountList.innerText = food[0].price;
tabAmountList.classList.add('tabScreenAmount');
tabAmt.appendChild(tabAmountList);
//Check trash button
const trashButton = document.createElement("button")
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
//append to LIs
tabNameSection.appendChild(tabNames);
tabAmountSection.appendChild(tabAmt);
tabAmountSection.appendChild(trashButton);
};
//Events
btns.addEventListener('click', addTab);
Basically, I use the innerText of each html element as keys in the object
On a side note: only Pulled Pork Nachos, 6 Wings and Pork Rinds have any relation in the food variable so it will work better when you use your full variable and not JUST these 3 indexes(for an item that is non-existent in the food variable, an alert is shown)
NOW as to what I fully did:
FIRSTLY, I made 3 variables outside the function; blankElemState which is the tab element's innerHTML when holding NOTHING, amount as TOTAL tab amount and purchases for holding the object equivalent of each purchase(because of reference logic, one can search through the food, drink and merch arrays and when a value EQUALS a value in purchases, that's the exact item of purchase). For example of the reference logic, purchases[8] might EQUAL food[2]
SECONDLY, I made a variable i that holds the place in the food array of the requested item(for drinks you can change that part to drinks.forEach instead of food.forEach and so forth).
NEXT, if there is nothing in the array that refers to the requested item(by user), I warn that there is nothing available for the order(which naturally should not happen).
THEN, if tabAmountSection already has elements appended to it(not equal to blankElemState), I clear tabAmountSection(by making its innerHTML back to blankElemState) so that there aren't multiple "final" purchase values and remove buttons
//Vars
//also, only "Pulled Pork Nachos", "6 Wings" and "Pork Rinds" have any relation in the food variable so it will work better when you use your full variable and not JUST these 3 indexes
const food = [
{
name: "Pulled Pork Nachos",
price: 10.00
},
{
name: "6 Wings",
price: 5.00
},
{
name: "Pork Rinds",
price: 4.00
}
];
const drinks = [
{
name: "Well Vodka",
price: 5.00
},
{
name: "Well Whiskey",
price: 5.00
}
];
const merch = [
{
name: "Well Vodka",
price: 5.00
},
{
name: "T Shirt",
price: 20.00
}
];
const tabNameSection = document.querySelector('.tabNameList');
const tabAmountSection = document.querySelector('.tabAmountList');
const blankElemState=tabAmountSection.innerHTML;
const btns = document.querySelectorAll('.foodButtons');
let amount=0; let purchases=[];
// const wings = document.querySelector('#wingsFood');
// wings.assign('wings', 6.00)
// console.log(wings);
//Functions
function addTab(event) {
//make index for getting data
var i=-1; var elem=this;
food.forEach(function (a,c){if(elem.innerText==a.name){i=c}});
if(i==-1){return alert("There is nothing in the respective options array that links to the requested item.. if you are a client playing around, kindly cease it")}
purchases.push(food[i]); //if not returned by now, the item is valid and now I'm taking record
//all you have to do for drinks or merch is change which array you're doing this function to(like food, drink, or merch)
//please note that document.querySelector ONLY selects ONE element, for your purpose, please use document.querySelectAll
//you can easily just have it in one array for simplicity to add it to ALL buttons, but since you're not doing that, change which variable is being forEach-ed for the 3 different sections
//btw i would console.warn when there's nothing in the array linked to the requested item(as for what you gave us, a lot of the items have no instance in the array)
//finally, there was a logical error occuring when it first worked.. with each click, NEW elements of price and trashbuttons were created.. I understand the names adding up as one person can buy many things, but I made it that the price and trashbuttons dont make new ones each time
//example of reference logic to see if an index of purchase is in an array
function purchaseIsInArray(indexOfPurchase, arrayInQuestion){
return arrayInQuestion.includes(purchases[indexOfPurchase])
}
//Name Div
const tabNames = document.createElement('div');
tabNames.classList.add('tabNameList');
//Amt Div
const tabAmt = document.createElement('div');
tabAmt.classList.add('tabAmtList');
//Create LI Tab Names
const tabNameList = document.createElement('li');
tabNameList.innerText = food[i].name;
tabNameList.classList.add('tabScreenNames');
tabNames.appendChild(tabNameList);
//Create LI Tab Amounts
amount+=food[i].price;
const tabAmountList = document.createElement('li');
tabAmountList.innerText = amount;
tabAmountList.classList.add('tabScreenAmount');
tabAmt.appendChild(tabAmountList);
//Check trash button
function resetEverything(ev){
tabAmountSection.innerHTML=blankElemState;
tabNameSection.innerHTML=blankElemState;
amount=0; purchases=[];
}
const trashButton = document.createElement("button")
trashButton.innerHTML = '<i class="fas fa-trash"></i>';
trashButton.classList.add("trash-btn");
trashButton.addEventListener('click', resetEverything);
//append to LIs
tabNameSection.appendChild(tabNames);
if(tabAmountSection.innerHTML!=blankElemState){
tabAmountSection.innerHTML=blankElemState;
}
tabAmountSection.appendChild(tabAmt);
tabAmountSection.appendChild(trashButton);
};
//Events
btns.forEach(a=>a.addEventListener('click', addTab));
<body>
<header>
<h1>Point of Sale</h1>
</header>
<section id="foodOptionsSection">
<h3>Food Options</h3>
<button type="button" class= "foodButtons buttons" id="porkNachosFood">Pulled Pork Nachos</button>
<button type="button" class= "foodButtons buttons" id="wingsFood">6 Wings</button>
<button type="button" class= "foodButtons buttons" id="totsFood">Tater Tots</button>
<button type="button" class= "foodButtons buttons" id="hamburgerFood">Hamburger</button>
<button type="button" class= "foodButtons buttons" id="cbqbbqFood">CBWBBQ</button>
<button type="button" class= "foodButtons buttons" id="ppgcFood">PPGC</button>
<button type="button" class= "foodButtons buttons" id="tacosFood">Tacos</button>
<button type="button" class= "foodButtons buttons" id="friesFood">Fries</button>
<button type="button" class= "foodButtons buttons" id="porkRindsFood">Pork Rinds</button>
</section>
<section id="tabList">
<h3>Current Tab</h3>
<div class="tabNameList tab">
</div>
<div class="tabAmountList tab">
</div>
</section>
<script src="script.js"></script>
</body>
I'm creating a script to perform a click action to only select in-stock items. But I'm having a hard time selecting the content "Disponible"
HTML below:
<div class="top namePartPriceContainer">
<span id="InventoryStatus_OnlineStatus_691003" class="text inventoryStatus inv-status-3" itemprop="availability" href="https://schema.org/InStock" content="Disponible">In Stock
</span>
<div id="InventoryStatus_ShowLink_Section_691003" class="left available" style="display:none;">
<span class="text Select attributes to see availability">Select attributes to see availability
</span>
</div>
My JavaScript code:
var products = document.getElementById("dijit__WidgetBase_0");
var items = products.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i) {
if(items[i].getElementsByTagName("span")[0].innerText === "In Stock"){
document.getElementById("productPageAdd2Cart").click();
}
}
getAttribute(); looks like the solution for you.
var content = document.getElementById('id').getAttribute('content');
and then:
if(content == 'Disponible') {
document.getElementById("productPageAdd2Cart").click();
}
I'm trying to make the rest of my chat room app disabled while a modal is open. I've been using element.disable = true to disable the buttons and this has worked. I have a ul where each li is the name of a chat room that is clickable and opens up its respective chat room in another container. I'm trying to disable the lis using the same disable.true method. I'm using a for loop to iterate through the array of lis, but it isn't working.
I used console.log to view the variable with the array stored in it (var lis) as well as the console.log(lis.length). The console shows that the array has a length of 5 but returns lis.length as 0.
Would be much appreciated if someone could tell me what I'm doing incorrectly.
HTML:
<div class"home-template" id="home">
<div class="rooms-container">
<h1 class="app-title">Bloc Chat</h1>
<ul id="rooms-list">
<li class="room-item" id="room-item" ng-repeat="chat in home.chatRooms">
{{ chat.$value }}
</li>
</ul>
<button class="btn btn-warning" id="new-room-button" type="button" ng-click="home.open()">New room</button>
<button class="btn btn-warning" id="delete-cookies-button" type="button" ng-click="home.deleteCookies()">Delete Cookie for testing</button>
</div>
<div class="messages-container">
<h1 class="current-room" ng-bind="home.activeRoom"></h1>
<ul class="messages-list">
<li class="message-bubble" ng-repeat="message in home.messages">
<div class="username">{{ message.username }}</div>
<div class="sentAt">{{ message.sentAt }}</div>
<div class="content">{{ message.content }}</div>
</li>
</ul>
</div>
</div>
JavaScript in a home controller:
home.cookieDisplay = $cookies.get('blocChatCurrentUser');
var modals = document.getElementsByClassName('modal');
var lis = document.getElementsByClassName('room-item');
var newButton = document.getElementById('new-room-button');
var delButton = document.getElementById('delete-cookies-button');
if (modals.length === 0) {
newButton.disabled = false;
delButton.disabled = false;
for (var i = 0; i < lis.length; i++) {
lis[i].disabled.false;
}
} else if (modals.length !== 0) {
newButton.disabled = true;
delButton.disabled = true;
for (var i = 0; i < lis.length; i++) {
// lis[i].setAttribute('display', 'none');
lis[i].disabled.true;
}
}
Here's what my console looks like:
You can't disable the li itself.
You can either disable the anchor tag (a) in it for example like this (refernece):
document.getElementById("tab_c").childNodes[0].onclick = function() {return false;};​
Or you can set pointer-events:noneas it has been done using CSS (reference):
.disabled {
pointer-events:none; //This makes it not clickable
opacity:0.6; //This grays it out to look disabled
}