I'm trying to create a dynamic navbar that is different when a user is signed in vs. not signed in.
I have the auth portion working (confirmed with console logs); however, for some reason, the HTML is not getting updated when I use .innerHTML = .... I'm console logging the innerHTML after I update it, and it appears correct in the log but the navbar isn't displaying like it should.
HTML:
...
<ul class="site-menu main-menu js-clone-nav mr-auto d-none d-lg-block">
<li><strong>Home</strong></li>
<li id ="nav-listings">
<strong>Listings</strong>
</li>
<li><strong>Contact</strong></li>
<li class="has-children" id="nav-account">
<strong>Sign-In</strong>
<div id="navDropdown" class="dropdown">
Profile
Sign-Up
</div>
</li>
</ul>
...
js code:
AOS.init({
duration: 800,
easing: 'slide',
once: true
});
jQuery(document).ready(function($) {
"use strict";
$(".loader").delay(1000).fadeOut("slow");
$("#overlayer").delay(1000).fadeOut("slow");
...
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
var username = firebaseUser.email;
console.log(`${firebaseUser ? `- User signed in: ${firebaseUser.email} => ${username}` : "No User Signed in"}`);
document.getElementById("nav-listings").className = "has-children";
document.getElementById("nav-listings").innerHTML = "<a href='Search.html' class='nav-link'><strong>Listings</strong></a>" +
"<div id='listDropdown' class='dropdown'>" +
"<a href='AddHouse.html'>Add Listing</a>" +
"<a href='User.html'>Favorites</a>" +
"</div>";
console.log(document.getElementById("nav-listings").innerHTML);
} else {
btnLogin.disabled = false;
}
});
});
EDIT:
It is appearing in the condensed form of the navbar but the main navbar???
See Here for the full code (minus the CSS... which makes the problem hard to see but all the js and HTML are there).
This should work
HTML:
<ul class="site-menu main-menu js-clone-nav mr-auto d-none d-lg-block">
<li><strong>Home</strong></li>
<li id="nav-listings">
<strong>Listings</strong>
</li>
<li><strong>Contact</strong></li>
<li class="has-children" id="nav-account">
<strong>Sign-In</strong>
<div id="navDropdown" class="dropdown">
Profile
Sign-Up
</div>
</li>
</ul>
JavaScript:
firebase.auth().onAuthStateChanged(firebaseUser => {
if (firebaseUser) {
var username = firebaseUser.email;
console.log(`${firebaseUser ? `- User signed in: ${firebaseUser.email} => ${username}` : "No User Signed in"}`); ;
$("#nav-listings").addClass('has-children').html("<a href='Search.html' class='nav-link'><strong>Listings</strong></a><div id='listDropdown' class='dropdown'><a href='AddHouse.html'>Add Listing</a><a href='User.html'>Favorites</a></div>")
console.log($("#nav-listings").html());
} else {
btnLogin.disabled = false;
}
});
When you are setting the innerHTML you are also setting the class for nav-listings to has-children. This removes the existing class of nav-link.
Do you mean to do this? If you want to keep the nav-link class as well then instead of
document.getElementById("nav-listings").className = "has-children";
put a space before the has-children and add the string to the classname. This will then add has-children to the class and wont remove the nav-link.
document.getElementById("nav-listings").className += " has-children";
If you console.log the outerHTML instead of innerHTML you can check whether both nav-link and has-children are there.
Related
Been trying all day to print an array of objects into the "cart" part of the HTML, but for the life of me I can't figure out what's wrong. The click event is working just fine, it either pushes the object into the array if it's not already there, or if it is, then it adds one to the count of "quantity" property. The issue is that, in order for the HTML to reflect these changes I have to refresh the whole page.
My guess is something not woring right with the storage, here's the initial setting of the "cart" part of the storage:
``if(localStorage.getItem("carrito")) {
productosEnCarrito = JSON.parse(localStorage.getItem("carrito"))
initCartHTML(productosEnCarrito)
}else{
productosEnCarrito = []
localStorage.setItem("carrito", productosEnCarrito)
}`
`
Here is everything involed in the printing and said array:
Event listener on the <button> tag:
`let agregarBtn = document.getElementById(`addCart${curso.clase}`)
agregarBtn.addEventListener("click", () => {
addCart(curso)
})`
the addCart() function:
`function addCart (curso) {
let cursoAgregado = productosEnCarrito.find((elem)=> elem.clase == curso.clase)
if(cursoAgregado == undefined) {
productosEnCarrito.push(curso)
localStorage.setItem("carrito", JSON.stringify(productosEnCarrito))
cartHTML(curso)
} else {
cursoAgregado.quantity++
localStorage.setItem("carrito", JSON.stringify(productosEnCarrito))
cartHTML(curso)
}
console.log(productosEnCarrito)
itemsInCart.innerText = productosEnCarrito.length
}`
the primary printing function (this is the bit not working)
`function cartHTML (curso) {
let cursoAgregado = productosEnCarrito.find((elem)=> elem.clase == curso.clase)
let newCurso = document.createElement("ul")
if (cursoAgregado == undefined) {
newCurso.className = "nav nav-tabs d-flex justify-content-between flex-nowrap"
newCurso.innerHTML =
`<li class="nav-item m-2">${curso.id}</li>
<li class="nav-item m-2">${curso.duration}</li>
<li class="nav-item m-2">€${curso.price}</li>
<li class="nav-item m-2">x${curso.quantity}</li>`
cartList.appendChild(newCurso)
} else {
newCurso.innerHTML =
`<li class="nav-item m-2">${curso.id}</li>
<li class="nav-item m-2">${curso.duration}</li>
<li class="nav-item m-2">€${curso.price}</li>
<li class="nav-item m-2">x${curso.quantity}</li>`
}
}`
I also set another function to retreive the storage and printing it when refreshing, this might have something to do with it, idk:
`function initCartHTML (array) {
for (let curso of array) {
let newCurso = document.createElement("ul") // <-- linea modificada
newCurso.className = "nav nav-tabs d-flex justify-content-between flex-nowrap"
newCurso.innerHTML =
`<li class="nav-item m-2">${curso.id}</li>
<li class="nav-item m-2">${curso.duration}</li>
<li class="nav-item m-2">€${curso.price}</li>
<li class="nav-item m-2">x${curso.quantity}</li>`
cartList.appendChild(newCurso)
}
itemsInCart.innerText = productosEnCarrito.length
}`
I'm trying to get the cart part of the html to reflect the changes immediately after it's modified, but it only does so after refreshing.
I am having an issue with my javascript function in regards to removing elements. What I have below is two lists inside a div menu with each <li> marked by a class according to the category of drink and the drinks themselves. I also have a button that opens a modal box where the user would type in a drink category to remove. I decided to approach this by naming <li> with classes by the drink category and then taking a js function to get the elements by class name from the input text node and to remove those elements with what the user typed.
<div class = "menu">
<ul>
<li class = "coffee">french press</li>
<li class = "tea"><a href="#">english breakfast/a></li>
<li class = "milk">whole</li>
</ul>
<ul>
<li class = "coffee">dark roast</li>
<li class = "tea">green tea</li>
<li class = "milk">two percent</li>
</ul>
</div>
<button type="button" id ="openmodal">Click Me!</button>
<div id="myDeleteModal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<h1 class="modal-title">
<b>Type the drink category you want to remove </b>
</h1>
<input id="deletedrinktext" type="text" />
<button id="delete">Remove</button>
<button type="button" class="btn btn-defaultdeletedrink" id="closedbtn" data-dismiss="modal" onclick="">Close</button>
</div>
</div>
<script>
var modal = document.getElementById("myDeleteModal");
// Get the button that opens the modal
var btn = document.getElementById("openmodal");
var closebtn = document.getElementById("closedbtn");
// When the user clicks the button, open the modal
btn.onclick = function () {
modal.style.display = "block";
}
closebtn.onclick = function (event) {
modal.style.display = "none";
}
</script>
<script>
(function () {
document.querySelector('#delete').addEventListener('click', function () {
let inputRemover = document.querySelector('#deletedrinktext');
let itemRemover = document.createTextNode(inputRemover.value);
let listRemover = document.getElementsByClassName(itemRemover);
for (var i = 0; i < listRemover.length; i++) {
if (document.contains(listRemover)) {
listRemover[i].remove();
}
}
inputRemover.value = ""; // clear input
});
})();
</script>
So what I want to replicate is a user would open the modal box, type in coffee and click remove. This would remove from the document the following two elements:
<li class = "coffee">french press</li>
<li class = "coffee">dark roast</li>
This function isn't working so far and I am not sure if there is an error in my JS in getting each element or if going with the class approach is not the way to go about it? When I type in the name of the category just like written in my HTML, the element in the list still displays.
remove() is not a function of Array in javascript. I think your best approach would be to just not display the elements you want to remove. To do just change your handler function to this:
let inputRemover = document.querySelector('#deletedrinktext');
let listRemover = document.getElementsByClassName(inputRemover.value);
for (let i = 0; i < listRemover.length; i++) {
if (document.contains(listRemover[i])) {
listRemover[i].style.display = 'none';
}
}
JSFiddle to try it out without modal functionality.
This also helps you if you maybe want to reset the list. To do so, just set the display property on every element to block.
Also, I don't knwo if it is a copy paste issue but the a at english breakfast is missing a < in the closing tag.
I am trying to implement a navbar to html which has the effect dynamically switch pages instead of changing links via href. The trick I'm using to accomplish this is by adding a classList of is-active to the div elements in the section tag.
Here is an example code of the generated HTML :
navBar.js
const navbarItem = [
{
navitem : "About",
link: 1
},
{
navitem : "Legal",
link: 2
},
{
navitem : "Contact",
link: 3
}
];
window.onload = function navLoad() {
const navbar = document.getElementById('navbar');
navbar.innerHTML =
`
<div class="toggle">
<i class="fa fa-bars menu" aria-hidden="true"></i>
</div>
<ul class="nav-list">
<li class="tab is-active">
<a onclick="renderNav()">Home</a>
</li>
${navbarItem.map(loadNavitems).join(" ")}
</ul>
`
}
function loadNavitems(navItems) {
return `
<li class="tab">
<a data-switcher data-id="${navItems.link}" onclick="renderNav(); navSwap();">${navItems.navitem}</a>
</li>
`
}
function renderNav(){
const pages = document.getElementById('main');
document.getElementById('alphabetButtons').style.display = "block";
pages.innerHTML =
`
<section class="pages">
${navbarItem.map(item => `
<div class="page" data-page="${item.link}">
<h1>${item.navitem}</h1>
</div>
`).join('')}
</section>
`
};
And here is the code which takes care of the page switching:
navSwitcher.js
function navSwap() {
const tab_switchers = document.querySelectorAll('[data-switcher]');
for (let input of tab_switchers) {
const page_id = input.dataset.switcher;
console.log(page_id);
input.addEventListener('click', function () {
if(document.querySelector('.nav-list .tab.is-active')){
document.querySelector('.nav-list .tab.is-active').classList.remove('is-active');
console.log('removed');
}
if(input.parentNode.classList.contains('tab')){
input.parentNode.classList.add('is-active');
}
//SwitchNav(page_id);
});
}
}
function SwitchNav(page_id) {
const currentPage = document.querySelector('.pages .page');
const next_page = document.querySelector(`.pages .page[data-page="${page_id}"]`);
console.log(next_page);
if(document.querySelector('.pages .page.is-active')){
document.querySelector('.pages .page.is-active').classList.remove('is-active');
}
next_page.classList.add('is-active');
}
Update : The issue is that causes the error comes when attempting to place [data-page="${page_id}"] after .page inside the querySelector. When console logging, [data-page="${page_id}"] will return null. This is weird because data-page is named correctly in the renderNav function which holds the div of class page.
Hence my hypothesis now is that the issue comes from [data-page="${page_id}"] in the SwitchNav(page_id) function. My question is why is this occuring if everything is named correctly?
Fixes tried:
Attempted to change the for/of loop to a regular for loop inside the navSwap function.
Inside the navSwap function, const page_id = input.dataset.tab; was changed to const page_id = input.dataset.switcher; which now returns 3 items.
So after some digging around, in the end it was actually const page_id = tab_switcher.dataset.tab; which was returning undefined, hence causing the error to happen. In reality it was returning id so I changed it to tab_switcher.dataset.id;.
Here is the final attempt at the code (i placed everything in one single file):
navBar.js:
const navbarItem = [
{
navitem : "About",
link: 1
},
{
navitem : "Legal",
link: 2
},
{
navitem : "Contact",
link: 3
}
];
window.onload = function navLoad() {
const navbar = document.getElementById('navbar');
navbar.innerHTML =
`
<div class="toggle">
<i class="fa fa-bars menu" aria-hidden="true"></i>
</div>
<ul class="nav-list">
<li class="tab is-active">
<a onclick="renderNav()">Home</a>
</li>
${navbarItem.map(loadNavitems).join(" ")}
</ul>
`
}
function loadNavitems(navItems) {
return `
<li class="tab">
<a data-switcher data-id="${navItems.link}" onclick="renderNav(); navSwap();">${navItems.navitem}</a>
</li>
`
}
function renderNav(){
const pages = document.getElementById('main');
document.getElementById('alphabetButtons').style.display = "block";
pages.innerHTML =
`
<section class="pages">
${navbarItem.map(item => `
<div class="page" data-page="${item.link}">
<h1>${item.navitem}</h1>
</div>
`).join('')}
</section>
`
};
function navSwap() {
const tab_switchers = document.querySelectorAll('[data-switcher]');
for (let i = 0; i < tab_switchers.length; i++) {
const tab_switcher = tab_switchers[i];
const page_id = tab_switcher.dataset.id;
tab_switcher.addEventListener('click', function(){
document.querySelector('.nav-list .tab.is-active').classList.remove('is-active');
tab_switcher.parentNode.classList.add('is-active');
SwitchNav(page_id);
});
}
}
function SwitchNav(page_id) {
const currentPage = document.querySelector('.pages .page');
const next_page = document.querySelector(`.pages .page[data-page="${page_id}"]`);
console.log(next_page);
if(document.querySelector('.pages .page.is-active')){
currentPage.classList.remove('is-active');
}
if(document.querySelector('.pages .page')){
next_page.classList.add('is-active');
}
}
Although the code generates the intended results, I have to click twice on the tag to fire it's onclick event. If anybody knows why this occurs it would be of much help to know in the comments.
Also let me know if this is a viable fix. Thanks again :)
There are some buttons(actually, links) on a web, and I can click on it menually.
but,
wb:=ComObjCreate("InternetExplorer.Application")
wb.document.getElementById("Status").click()
this script don't work. #critsz said because there is no definition about click.
so, I'm trying to trigger the function after defining "click"
the following is a part of the source.
<ul class="nav nav-pills nav-stacked" id="TabMenu">
<li class="active" id="basic"><i class="fa fa-inbox"></i> Basic
<!-- <span class="label label-primary pull-right">12</span> -->
</li>
<li id="Status"><i class="fa fa-envelope-o"></i> Status</li>
</ul>
function viewPage(Name,Number){
$("#TabMenu li").removeClass("active");
$("#"+Name).addClass("active");
$("#ViewPage").load(
Name+".asp",
{
Number : Number
},
function( response, status, xhr ) {
if ( status == "error" ) {
var msg = "an error: ";
$( "#error" ).html( msg + xhr.status + " " + xhr.statusText );
}
});
}
And I tried this.
wb.document.getElementById("Status").addEventListener("click",viewPage(Status,10000))
but an error occurs : Call to nonexistent function.
Specifically: viewPage(Status,10000)
Does this mean that I need to define the function on my autohotkey script? or Is there any other way to do that?
if i should do, how can I do that?
Try wb.navigate("javascript:viewPage('Status','10010');")
My problem is something like this,
I am using filter function to show the matched elements(LI)in tree,its working fine but its showing all li elements which starts from passed string,for example
if i passed "Application" to filter function,then it's showing me all li, which text start from "Application"
function callme(filterData){
$("ul.treeview").find("li").hide();
if(filterData.indexOf("|")!=-1){
var filterData = filterData.split("|");
for(i=0;i<filterData.length;i++){
jQuery("ul.treeview").find("li").filter(function(index) {
return jQuery.trim($(this).text()) == filterData.trim();
}).show();
}
}else{
jQuery("ul.treeview").find("li").filter(function(index) {
return jQuery.trim($(this).text()) == filterData.trim();
}).show();
}
}
here is my html...
<ul id="leftNavigation" class="treeview">
<li>
<ul>
<li >
Application<font class="leftNavHitsFont"> - (3)</font>
</li>
</ul>
<ul>
<li >
Application Notes<font class="leftNavHitsFont"> - (1)</font>
</li>
</ul>
</li>
</ul>
Yeah, that is the definition of something containing something else.
Maybe you meant to get an exact match?
jQuery("ul.treeview").find("li").filter(function(index) {
return jQuery.trim($(this).text()) == jQuery.trim(filterData);
}).show();
jsFiddle example