How can i create a submenu using the DOM in javascript - javascript

I'm trying to create a submenu, so that when the item on the menu line is clicked then a submenu will appear along with all its values.
I've created a label along with a div to illustate it.
Once the label is clicked, another div needs to produce another list of items, i haven't got a clue how to do this. Please help !!
<script>
var div = document.createElement("div");
var lbl = document.createElement("label");
lbl.innerHTML = "Menu";
div.appendChild(lbl)
btn.onlclick = function() {
var alert = prompt("This button works");
};
The list works but i need to show up when i click on the label
(function() {
var outerUL, li, innerUL, thirdLI, index;
outerUL = document.createElement('ul');
for (index = 0; index < 5; ++index) {
li = document.createElement('li');
li.innerHTML = "SubMenu" + index;
if (index === 2) {
thirdLI = li;
}
outerUL.appendChild(li);
}
innerUL = document.createElement('ul');
for (index = 0; index < 3; ++index) {
li = document.createElement('li');
li.innerHTML = "Subsubmenu #" + index;
innerUL.appendChild(li);
}
thirdLI.appendChild(innerUL);
document.body.appendChild(outerUL);
})();
document.body.appendChild(div);
Any Suggestions ??
Thank you

Related

How to add all checked boxes into separate LI tags

I want to separate all checked items into LI tags but right now it is adding them all to a single LI tag. What am I doing wrong? It's probably simple and I'm just dumb :(
let ul = document.querySelector('.ul')
let li = document.createElement('li')
getSelectedToys() {
let { selectedToys } = this;
const checked = document.querySelectorAll('input[type=checkbox]:checked')
for (var i = 0; i < checked.length; i++) {
selectedToys.push(checked[i].value)
console.log(selectedToys[i])
}
selectedToys.forEach(function(item) {
ul.appendChild(li)
let text = document.createTextNode(item);
li.appendChild(text)
})

Javascript passing info from one function to another

I've created a JS function that hides a certain amount of breadcrumbs if there are too many. They are replaced by a button (ellipsis), when you click the button the hidden breadcrumbs are revealed.
The Problem: I loop through the breadcrumbs to see if there are enough to hide. If there are I hide them. But I can't figure out how to then call the code to create the button. If I call the button code in the loop I get more than 1 button generated.
Right now the button will always appear whether there are enough breadcrumbs to hide or not.
In my mind, I would have the for loop with the if statement return true to what would then be the button function. But I can't figure out how to do this. Please offer any pointers for restructuring this code if you can.
Here's a Codepen: https://codepen.io/sibarad/pen/GRvpEbp
Basic HTML:
<nav aria-label="breadcrumb">
<ol class="c-breadcrumb mb-7 md:mb-8">
<li class="c-breadcrumb-item">
Breadcrumb 1
</li>
<li class="c-breadcrumb-item">
Breadcrumb 2
</li>
<li class="c-breadcrumb-item">
Longer Breadcrumb Name 03
</li>
</ol>
</nav>
Javascript:
function breadcrumb() {
// Target specific breadcrumbs, not 1st or last 2
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item:nth-child(1n+2):nth-last-child(n+3)');
// Loop through select breadcrumbs, if length is greater than x hide them.
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
if(hiddenbreadcrumb.length >= 3) {
hiddenbreadcrumb[i].style.display = "none";
}
}
// This would be the button function, but I don't know how to engage this only if the if statement above was met.
let li = document.createElement('li');
li.className = 'c-breadcrumb-item';
let ellipbutton = document.createElement('button');
ellipbutton.type = 'button';
ellipbutton.innerHTML = '...';
ellipbutton.className = 'c-breadcrumb_btn u-btn-clear';
ellipbutton.onclick = function() {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
li.appendChild(ellipbutton);
let container = document.querySelector('.c-breadcrumb-item:first-child');
container.insertAdjacentElement("afterend", li);
}
breadcrumb();
We can refactor your code slightly to achieve this - the if statement which checks whether there are more than 3 breadcrumbs doesn't need to be inside the for loop - it's redundant to keep checking the same value multiple times.
If we move that outside the loop then it can
a) prevent unnecessary looping when there aren't enough breadcrumbs, and
b) wrap around the button creation code as well, which should solve your problem.
For example:
if (hiddenbreadcrumb.length >= 3) {
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
let li = document.createElement('li');
li.className = 'c-breadcrumb-item';
let ellipbutton = document.createElement('button');
ellipbutton.type = 'button';
ellipbutton.innerHTML = '...';
ellipbutton.className = 'c-breadcrumb_btn u-btn-clear';
ellipbutton.onclick = function() {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
let container = document.querySelector('.c-breadcrumb-item:first-child');
container.insertAdjacentElement("afterend", li);
}
It looks like some small initialization issues. This should correct it:
Change this:
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item:nth-child(1n+2):nth-last-child(n+3)');
// Loop through select breadcrumbs, if length is greater than x hide them.
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
if(hiddenbreadcrumb.length >= 3) {
hiddenbreadcrumb[i].style.display = "none";
}
}
to this:
let hiddenbreadcrumb = document.querySelectorAll('.c-breadcrumb-item');
if(hiddenbreadcrumb.length < 3)
return
for (var i = 1; i < hiddenbreadcrumb.length - 1; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
Try this... it allows 3 li items as item1 ... item2ndLast, itemLast
(function () {
"use strict";
function breadcrumb() {
let hiddenbreadcrumb = document.querySelectorAll(".c-breadcrumb-item:nth-child(1n+2)");
if (hiddenbreadcrumb.length <= 3) return;
for (var i = 1; i < hiddenbreadcrumb.length - 1; i++) {
hiddenbreadcrumb[i].style.display = "none";
}
let li = document.createElement("li");
li.className = "c-breadcrumb-item";
let ellipbutton = document.createElement("button");
ellipbutton.type = "button";
ellipbutton.innerHTML = "...";
ellipbutton.className = "c-breadcrumb_btn u-btn-clear";
ellipbutton.onclick = function () {
console.log("clicked");
for (var i = 0; i < hiddenbreadcrumb.length; i++) {
hiddenbreadcrumb[i].style.display = "flex";
}
li.style.display = "none";
};
li.appendChild(ellipbutton);
let container = document.querySelector(".c-breadcrumb-item:first-child");
container.insertAdjacentElement("afterend", li);
}
breadcrumb();
})();

Card from Javascript into HTML, there must be a better way (working)

There must be a better, shorter way to generate many cards from javascript into HTML.
This is the format to follow, it's working but can it be better?????
span{color: red;}
<div id="mycard"></div>
var dateSpan = document.createElement('span')
var ul = document.createElement('ul')
var ol = document.createElement('ol')
var li = document.createElement('li');
var li2 = document.createElement('li')
dateSpan.innerHTML = '#3500';
li.textContent = 'Title of card '
li2.textContent = '"Small description"'
li.appendChild(dateSpan);
li.appendChild(ul);
ul.appendChild(li2);
ol.appendChild(li);
var app = document.querySelector('#mycard');
app.appendChild(ol)
Note: Yeah, you can add a '<b/r>' but the "Small description" should be stylish later on... :)
Create a function to generate html content and then call that function as many time as you want.
For example
function generateList(title, description){
var htmlVal = `<li>${title}<br>${description}</li>`;
return htmlVal;
}
Then call the function however you like and append it to the element.
document.getElementById("myCard") += generateList("Title of Card #3500","Small description");
Where in your html there's an element with id "myCard"
You can create a class cardMaker and create instances with a for loop:
class cardMaker {
constructor(n) {
var dateSpan = document.createElement('span')
var ul = document.createElement('ul')
var ol = document.createElement('ol')
var li = document.createElement('li');
var li2 = document.createElement('li')
dateSpan.innerHTML = '#3500' + n;
li.textContent = 'Title of card '
li2.textContent = '"Small description"'
li.appendChild(dateSpan);
li.appendChild(ul);
ul.appendChild(li2);
ol.appendChild(li);
var app = document.querySelector('#mycard');
app.appendChild(ol)
}
}
let cards = [];
for (let i = 0; i < 10; i++) {
cards[i] = new cardMaker(i);
}

How the heck do I do string comparison from a list item to the items in an array

I am attempting to take the contents of an individual list items in one UL and when one is clicked add the value of that individual LI to an array and append the text string of the list item to an ordered list item somewhere else on the page.
I am having trouble comparing the string of the clicked LI,iterating through the array to make sure the string of the LI listed once, and then adding the text to the OL. Help appreciated.
var list = $('.list'),
listItem = $('.list li'),
container = $('.list-content ul'),
containerItem = $('.list-items li');
itemArray = [];
listItem.on({
'click' : function(){
var current = $(this),
currentText = $(this).text();
if( itemArray.length <= 0 ) {
itemArray.push(currentText);
$('<li>'+ currentText + '</li>').appendTo(container); //add text to new area
}else{
for( var count = 0; count < itemArray.length; count++){
if( currentText === itemArray[count] ){
return false;
break;
} else {
itemArray.push(currentText);
$('<li>'+ currentText + '</li>').appendTo(container); //add text to new area
break;
}
}
}
}//end of click function
});
You can use $.inArray() to check whether an object is present in an array
this should do
var list = $('.list'),
listItem = $('.list li'),
container = $('.list-content ul'),
containerItem = $('.list-items li'),
itemArray = [];
listItem.on({
'click' : function(){
var current = $(this),
currentText = $(this).text();
if($.inArray(currentText, itemArray) == -1){
itemArray.push(currentText);
$('<li>'+ currentText + '</li>').appendTo(container); //add text to new area
}
}//end of click function
});
Demo: Fiddle

Remove clicked <li> onclick

I have this JavaScript code:
window.onload = init;
function init () {
var button = document.getElementById("submitButton");
button.onclick = addItem;
var listItems = document.querySelectorAll("li"); //assigning the remove click event to all list items
for (var i = 0; i < listItems.length; i++) {
listItems[i].onclick = li.parentNode.removeChild(li);
}
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
}
else {
ul.insertBefore(li, ul.firstChild);
}
}
function remove(e) {
var li = e.target;
var listItems = document.querySelectorAll("li");
var ul = document.getElementById("ul");
li.parentNode.removeChild(li);
}
and this HTML:
<body>
<form>
<label for="item">Add an item: </label>
<input id="item" type="text" size="20"><br>
<input id="submitButton" type="button" value="Add!">
</form>
<ul id="ul">
</ul>
<p>
Click an item to remove it from the list.
</p>
</body>
What I want to do is remove the whichever <li> element the user clicks, but this doesn't seem to be working and I am unable to find an answer anywhere else online for this specific scenario. Hoping someone can help me out here and show me what i am missing.
UPDATE
Plain JS delegation
Add the eventListener to the UL to delegate the click even on dynamically inserted LIs:
document.getElementById("ul").addEventListener("click",function(e) {
var tgt = e.target;
if (tgt.tagName.toUpperCase() == "LI") {
tgt.parentNode.removeChild(tgt); // or tgt.remove();
}
});
jQuery delegation
$(function() {
$("#submitButton").on("click",function() {
var text = $("#item").val(); //getting value of text input element
var li = $('<li/>').text(text)
$("#ul").prepend(li);
});
$("#ul").on("click","li",function() {
$(this).remove();
});
});
Original answer
Since you did not mention jQuery
var listItems = document.getElementsByTagName("li"); // or document.querySelectorAll("li");
for (var i = 0; i < listItems.length; i++) {
listItems[i].onclick = function() {this.parentNode.removeChild(this);}
}
you may want to wrap that in
window.onload=function() { // or addEventListener
// do stuff to the DOM here
}
Re-reading the question I think you also want to add that to the dynamic LIs
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {
this.parentNode.removeChild(this);
// or this.remove(); if supported
}
Here is the complete code as I expect you meant to code it
Live Demo
window.onload=function() {
var button = document.getElementById("submitButton");
button.onclick = addItem;
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {
this.parentNode.removeChild(this);
// or this.remove(); if supported
}
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
}
else {
ul.insertBefore(li, ul.firstChild);
}
}
In case you want to use jQuery, the whole thing gets somewhat simpler
Live Demo
$(function() {
$("#submitButton").on("click",function() {
var text = $("#item").val(); //getting value of text input element
var li = $('<li/>')
.text(text)
.on("click",function() { $(this).remove()});
$("#ul").prepend(li);
});
});
I know you already received an answer, but back to your original remove function. You have the following:
function remove(e) {
var li = e.target;
var listItems = document.querySelectorAll("li");
var ul = document.getElementById("ul");
li.parentNode.removeChild(li);
}
Change it to this and you should get what you were trying to achieve:
function remove(e)
{
var li = e.target;
var ol = li.parentElement;
ol.removeChild( li);
return false;
}
I'd suggest simplifying things a little:
Object.prototype.remove = function(){
this.parentNode.removeChild(this);
};
var lis = document.querySelectorAll('li');
for (var i = 0, len = lis.length; i < len; i++) {
lis[i].addEventListener('click', remove, false);
}
JS Fiddle demo.
Of course, having done the above, I'd then have to go further (possibly because I like jQuery too much) and also:
Object.prototype.on = function (evt, fn) {
var self = this.length ? this : [this];
for (var i = 0, len = self.length; i < len; i++){
self[i].addEventListener(evt, fn, false);
}
};
Object.prototype.remove = function(){
var self = this.length ? this : [this];
for (var i = 0, len = self.length; i < len; i++){
self[i].parentNode.removeChild(self[i]);
}
};
document.querySelectorAll('li').on('click', remove);
JS Fiddle demo.
If you don't want to write function in javascript, you can use immediately invoked anonymous function like below...
<elem onclick="(function(_this){_this.parentNode.removeChild(_this);})(this);"
If I understood you correctly:
$("li").on("click", function() {
$(this).remove()
});
The answer is more obvious than it could seem, you forgot to add init() in your script, is normal that the click event aren't triggered, they're not set on the element!
EDIT:
Your code has some logical errors. If you don't add an onclick function for all those created elements you will not be able to remove the clicked element. This is because the function init() is called one time at the load of the page!
function init() {
var button = document.getElementById("submitButton");
button.onclick = function() {addItem()};
}
function addItem() {
var textInput = document.getElementById("item"); //getting text input
var text = textInput.value; //getting value of text input element
var ul = document.getElementById("ul"); //getting element <ul> to add element to
var li = document.createElement("li"); //creating li element to add
li.innerHTML = text; //inserting text into newly created <li> element
li.onclick = function() {this.parentNode.removeChild(this);}
if (ul.childElementCount == 0) { //using if/else statement to add items to top of list
ul.appendChild(li); // will add if count of ul children is 0 otherwise add before first item
} else {
ul.insertBefore(li, ul.firstChild);
}
}
init();

Categories

Resources