How to Ensure Elements have Loaded Before Adding Class on PageLoad - javascript

I have the following bit of code, which first loads a navbar to the website on page load (this is so that I don't have to create a new navbar for each page):
<div id="nav"></div>
<script>$( "#nav" ).load( "nav.html" );</script>
And to show the "active" tab for that page, I have the following script:
<script>
window.onload = function() {
document.getElementById('lindex').className = 'active';
};
</script>
However, when the page loads, I am seeing this error in the console (for the document.getElementById line):
index.html:70 Uncaught TypeError: Cannot set property 'className' of null
And the "active" tab does not update when I navigate to the page. Strangely, it does seem to add the class when I reload the page, but intermittently. Does anyone know why this might be happening?
Here is the code for the navbar (nav.html):
<nav class="navbar navbar-inverse ">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<img src="/img/logo.png">
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li id="lindex" class="listitem">Home</li>
<li id="lpandp" class="listitem">Products & Purchasing</li>
<li>Freight & Distribution</li>
<li>Blog</li>
<li>Contact Us</li>
<li class="dropdown">
</li>
</ul>
</div>
</div>
</nav>
I have also tried:
$(function() {
$('#about').addClass('expand');
});
But this doesn't seem to work either, unless I refresh the page after navigating to it.

Try the following
<script>$( "#nav" ).load( "nav.html",function(){
$('#lindex').addClass('active');// add the class after the nav is loaded
});</script>

$( document ).ready(function() {
console.log( "ready!" );
$( "#nav" ).load( "nav.html");
console.log( "after load nav.html!" );
//add the class here
$('#lindex').addClass('active');
});

$("#lindex").addClass("Your Class Name");

Related

updating data on a webpage (with heavy leaflet.js chart)

What is the proper way to update a webpage with new datasets please. I have a webpage with a bootstrap navbar and a dropdown menu which I would like to use to select the dataset. When the webpage first opens it automatically loads one of these datasets. The problem is that when the webpage loads the very same dataset (this time from the dropdown menu) it crashes. The chart is a leaflet chart with a lot of markers (around 300K, which btw wouldnt have been possible without the help of a couple of ppl here!) but it works ok. When however as said earlier the same data are pushed again the browser chokes (it looks to me during the 'layer.on add' callback) and crashes.
I think (and that is a wild guess) this is leaflet related, maybe old data still live somewhere and arent getting dumped, but I dont really know.
That was with chrome but it happens with the other browsers as well. An outline of my code is shown below. (Note: in the snippet nothing is loaded on start-up, you will have to use the menu)
A browser refresh though works fine though.
How can I just clear everything from the webpage and start again (like a reload for instance) but passing my user-defined parameters. I hope it will work this way...
To put it in another way, I would like each time to remove all elements that were added to the webpage at a later stage (and remove associated objects from the memory as well) and then pass-in some parameters with the dropdown menu for example.
function dispatcher(x){
console.log('you clicked '+ x)
cfg = config()
run(cfg)
}
function config(){
var ini = [
{name: 'dataset-1', data:'some data 1'},
{name: 'dataset-2', data:'some data 2'},
];
var out = d3.map(ini, function (d) {return d.name;});
return out
}
function run(config) {
renderChart(config)
}
function renderChart(config) {
console.log('Doing map')
var mapStage = staging(config);
var map = mapStage.map;
console.log("doing some stuff with map and config")
}
function staging(){
try {
mapStage.map.off;
mapStage.map.remove();
console.log("map removed")
}
catch(error)
{
//do nothing
}
var map = L.map('mymap').setView([51.508530, -0.055], 12);
L.tileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png').addTo(map);
mapStage = []
mapStage.map = map
return mapStage
}
<!DOCTYPE html>
<html>
<head>
<title>Simple Leaflet Map</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.1/dist/leaflet.css"/>
</head>
<!--jquery -->
<script src="https://code.jquery.com/jquery-3.3.1.js"></script>
<!-- bootstrap -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
<!-- d3 -->
<script src='https://d3js.org/d3.v4.min.js'></script>
<!-- leaflet -->
<script src="https://unpkg.com/leaflet#1.3.1/dist/leaflet.js"> </script>
<script src="./example.js"> </script>
<body>
<input id="refresh" type="button" value="Refresh" onclick="renderChart();" />
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="container-fluid">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Title</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="dropdown" id="myDropdown">
Select Data <span class="caret"></span>
<ul class="dropdown-menu">
<li><a href="#" id = "dataset-1" onclick='dispatcher("dataset-1")'>Dataset 1</a></li>
<li><a href="#" id = "dataset-2" onclick='dispatcher("dataset-2")'>Dataset 2</a></li>
</ul>
</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li>About</li>
<li>Contact</li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</div>
</div>
<div id="mymap" style="width: 600px; height: 400px"></div>
</body>
</html>

Scrolltop animation not working

I am using this js to scroll to the id of the page. I took it from w3 schools and it works on my other site, so I don't understand why it doesn't work on my new site. It goes to the correct part of the page, but it doesn't do the scroll animation.
js:
<script>
$(document).ready(function () {
$(".navbar a, footer a[href='#myPage']").on('click', function (event) {
if (this.hash !== "") {
event.preventDefault();
var hash = this.hash;
$('html, body').animate({
scrollTop: $(hash).offset().top
}, 900, function () {
window.location.hash = hash;
});
}
});
})
</script>
html navbar code:
<nav class="navbar navbar-default navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#myNavbar">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav navbar-right">
<li>ABOUT</li>
<li>CLIENTS</li>
<li>SESSIONS</li>
<li>CONTACT</li>
</ul>
</div>
</div>
</nav>
Please let me know if you need to see any other code. Thanks!
That should work.
Are you positive that the new site is using jQuery and that the IDs of the element that you are scrolling to are correct?
Is your console displaying an error?

Getting navigation to display the selected page

I'm struggling with getting my navigation menu to show the selected page. I'm using the Bootstrap framework to build my site. This is my navigation menu:
<nav class="navbar">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/index.html">Digital Transformation</a>
</div>
<div id="navbar" class="collapse navbar-collapse">
<ul class="nav navbar-nav pull-right">
<li class="active">Transformation deck</li>
<li>Background information</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
As far as I can tell, Bootstrap uses the following JS to make the selected menu item active, which I have in my header:
<script>
$('label').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
However with this code my primary nav item is active on page load, but when I select the second item it keeps 'Tranformation deck' as active instead of 'Background information'.
Am I missing a trick here? Any help would be greatly appreciated.
If you want to hook up click listeners to your nav items, your script should be something like this:
<script>
$('#navbar nav li a').click(function() {
$(this).parent('li').toggleClass('active');
});
</script>
You don't have any 'label' tags in your code, so there isn't anything to attach click event handlers to.
$(function() {
// this will get the full URL at the address bar
var url = window.location.href;
// passes on every "a" tag
$("#navbar a").each(function() {
// checks if its the same on the address bar
if (url == (this.href)) {
$(this).closest("li").addClass("active");
}
});
});

More efficient way of listening for jQuery hasClass method?

I'm trying to listen if an element with the id of dropdown has the class open. If #dropdown has .open, add class badge-border to class badge. If #dropdown doesn't have .open, remove class badge-border from class badge. Here is my code:
HTML:
<!doctype html>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-right">
<li>Language (EN)
</li>
<li>Currency ($)
</li>
<li><i class="fa fa-user"></i> My Account
</li>
<li class="dropdown" id="dropdown"> <i class="fa fa-shopping-cart"><span class="badge">36</span></i> My Cart
<ul class="dropdown-menu" id="dropdown-menu">
<li>Action
</li>
<li>Another action
</li>
<li>Something else here
</li>
<li role="separator" class="divider"></li>
<li>Separated link
</li>
</ul>
</li>
</ul>
</div>
<!-- /.navbar-collapse -->
</div>
<!-- /.container-fluid -->
</nav>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/vendor/jquery-1.11.3.min.js"><\/script>')
</script>
</body>
JS:
$(document).ready(function () {
var interval = setInterval(changeBadge, 1);
function changeBadge() {
if ($('#dropdown').hasClass('open')) {
console.log('add class border');
// clearInterval(interval);
$(".badge").addClass("badge-border");
} else {
console.log('remove class border');
$(".badge").removeClass("badge-border");
}
};
});
The above way works to accomplish my goals, but I have a feeling that listening to an event every 1 millisecond isn't the best way to do it.
To make more sense of all this, you can view the demo here: http://jsfiddle.net/obliviga/qt7o3u6e/2/
You will need to maximize the viewport until the navbar is not in mobile mode, then click the shopping cart dropdown to see the badge's border added.
EDIT:
The reason why I implemented the way I did is because when the user clicks out of the cart dropdown, it should close, and the styles should revert to how they were before.
Consider using Mutation Observers intended exactly to track DOM changes, including changes of attribute values.
Note that IE supports Mutation Observers since version 11. For IE 10 and older, a fallback is needed.
EDIT: The reason why I implemented the way I did is because when the
user clicks out of the cart dropdown, it should close, and the styles
should revert to how they were before.
Updated , Added click event attached to document which removes .open class from #dropdown if present , calls handler of #dropdown a click event with this set to #dropdown a , with handler remove .badge-border class from .badge element which should revert styles of .badge to properties initially set at css.
Try attaching click event to selector $("#dropdown a") , calling .delay(1) on $(this).parents("#dropdown") within handler , .queue() function to check for open class , .toggleClass() to set $(this).parents("#dropdown") class on $(this).parents("#dropdown") with second argument Boolean $(this).parents("#dropdown")
$(document).ready(function () {
function changeBadge(e) {
$(this).parents("#dropdown")
.delay(1, "check")
.queue("check", function () {
$(".badge").toggleClass("badge-border", $(this).hasClass("open"));
}).dequeue("check")
}
$("#dropdown a").click(changeBadge);
$(document).on("click", function (e) {
var elem = $("#dropdown");
if ($(e.target).is("#dropdown *")) {
return false
} else {
if (elem.is(".open") || $(".badge").hasClass("badge-border")) {
elem.removeClass("open");
changeBadge.call(elem.find("a.dropdown-toggle")[0])
}
}
})
});
jsfiddle http://jsfiddle.net/qt7o3u6e/6/

How To Highlight Show Active Tab In A Navbar-Fixed-Top

I am current changing a website to use Bootstrap and I have been advised that they want to use the navbar-inverse navbar-fixed-top main menu.
The thing is I can't figure out how to highlight the selected page and keep it highlighted.
I have tried the follow Jquery but I cant get none of them working
$(function() {
$('#nav li a').click(function() {
$('#nav li').removeClass();
$($(this).attr('href')).addClass('active');
});
});
My HTML for my menu is:
<div class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" runat="server" href="~/">Logo Here</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a runat="server" href="~/"><span class="glyphicon glyphicon-home"></span></a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/About">About</a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/Session/pg1">Session</a></li>
<li style="border-left: 1px solid lightgray"><a runat="server" href="~/EmailPg">Email</a></li>
</ul>
<asp:LoginView runat="server" ViewStateMode="Disabled">
<AnonymousTemplate>
<ul class="nav navbar-nav navbar-right">
<li><a runat="server" href="~/Contact">Contact us</a></li>
</ul>
</AnonymousTemplate>
</asp:LoginView>
</div>
</div>
</div>
I would prefer if its possible to do it with CSS or Jquery but I was also a little confused as, do I add the Jquery to every page OR can I add one lot to my Site.Master file
You were not selecting the active li tag correctly.
Instead I suggest you use something like this:
$(function() {
$('#nav li a').click(function() {
$(this).closest('li') // select the parent <li> tag
.addClass('active')// add the active class
.siblings() // select the siblings of the active tag
.removeClass('active'); // remove the active class from the other <li>
});
});
Fixed by adding the below JQuery to my Site.Master file
var url = window.location;
// Will only work if string in href matches with location
$('ul.nav a[href="' + url + '"]').parent().addClass('active');
// Will also work for relative and absolute hrefs
$('ul.navbar-nav a').filter(function () {
return this.href == url;
}).parent().addClass('active');

Categories