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

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>

Related

jquery blur methods does not work with angular ng-view

I am a newbie to the angular jquery world. I am writing a Single Page app with nav-bars that works with a couple of REST-API's.
I have an index.html page where I have imported all the js scripts needed for my application(and its subpage/divs)
The subpage (a div page) gets loaded inside the <div ng-view> when a particular nav-bar gets created. I have implemented a .blur() method for a couple of form elements which I hope to use it to call some REST APIs. But the .blur method doesnt seem to get invoked at all when the form element goes out of scope. I have inspected that the js file is loaded. It also doesnt throw any errors in the console.
I tried moving the <script> importing the jquery-blurs.js to the particular div which results in the blur function getting called but then I get warning in the console and I get errors for $.md5() not found which from this post [The mystery of '$.md5 is not a function' I understand is due to different versions of jquery.
Any help is appreciated.
index.html
<html lang="en" ng-app="masterApp">
<head>
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css" />
</head>
<body>
<div class="container">
<!-- Static navbar -->
<nav class="navbar navbar-default">
<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="#/">TestAPP</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active">Home</li>
</ul>
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
Schedules <span class="caret"></span>
<ul class="dropdown-menu">
<li>Past/Current Schedules status</li>
<li>Future Schedules</li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Requires Admin access</li>
<li>Create Schedule</li>
<li>Manage Schedules</li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div><!--/.container-fluid -->
</nav>
<!-- Main component for a primary marketing message or call to action -->
<div ng-view></div>
</div> <!-- /container -->
</body>
<script src="bower_components/jquery/dist/jquery.min.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="js/jquery-dateformat.js"></script>
<script src="js/jquery-blurs.js"></script>
<script src="app.js"></script>
</html>
jquery-blurs.js
$(document).ready(function(){
var date_str = "";
$("#ID").blur(function(){
console.log($("#ID").val());
var id = $("#ID").val();
if (id == "") {
return;
}
$.getJSON("http://my-rest-api-url.com" + $("#ID").val()
)
.done(function(data){
if(data.msg != "") {
alert("Verify ID \n" + data.msg);
location.reload();
}
var comment = data.teams.names[0] + ' vs ' + data.teams.names[1];
console.log($.md5(comment));
date_str = $.format.date(data.date, "yyyy.MM.ddTHH.mm.ss")
$('#start_datetime').val(date_str);
var markup = '<tr name="entry"> <td>' +
data.date +
'</td><td>' +
$.md5(comment) +
'</td><td>' +
data.teams.names[0] + ' vs ' + data.teams.names[1] +
'</td><td></tr>';
$("table tbody").empty();
$("table tbody").eq(0).append(markup);
$("#program_id").val($.md5(comment));
$("#comment").val(comment)
$("#sport").val(data.sport)
$("#broadcast_id").val($("#StreamID").val() + '_' + $("#program_id").val() + '_' + date_str)
console.log($("#broadcast_id").val())
})
});
});

Bootstrap navbar dropdown only should activate once clicked

I want the navbar button hover drop-down effect to only activate once one of the navbar buttons is clicked. After that once clicked outside like body hover again should be disabled. At the moment hover is working where if I move the mouse around it activate (hence hover effect) but this can be annoying if user meant to not use navbar.
So normally when hovering the navbar, buttons shouldn't drop down any list. But once any of the navbar button is clicked, till you click out side, like the body all navbar buttons should be hovering like normally. I tried some jQuery but wasn't successful.
<!DOCTYPE html>
<html lang="en">
<head>
<title>BAPTIST</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./headerAndFooter.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</head>
<body>
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="navbar-header">
</div>
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav top-nav pull-right">
<div class="dropdown">
<li class="dropbtn"><i class="fa fa-chevron-down" aria-hidden="true"></i> About Us</li>
<div class="dropdown-content">
Action
Another action
Something else here
Separated link
One more separated link
</div>
</div>
<div class="dropdown">
<li class="dropbtn"><i class="fa fa-chevron-down" aria-hidden="true"></i> Providers</li>
<div class="dropdown-content">
Action
Another action
Something else here
Separated link
One more separated link
</div>
</div>
<div class="dropdown">
<li class="dropbtn"><i class="fa fa-chevron-down" aria-hidden="true"></i> Payors</li>
<div class="dropdown-content">
Action
Another action
Something else here
Separated link
One more separated link
</div>
</div>
<div class="dropdown">
<li class="dropbtn"><i class="fa fa-chevron-down" aria-hidden="true"></i> Employers</li>
<div class="dropdown-content">
Action
Another action
Something else here
Separated link
One more separated link
</div>
</div>
<div class="dropdown">
<li class="dropbtn"><i class="fa fa-chevron-down" aria-hidden="true"></i> Patients</li>
<div class="dropdown-content">
Action
Another action
Something else here
Separated link
One more separated link
</div>
</div>
</ul>
</div>
</div>
</nav>
</body>
</html>
I was having trouble with getting your navbar to work without all the css you have, so I used the generic Bootstrap 3 navbar from the site to show you.
What the code below does is this:
Anytime a link tag inside the nav is clicked, it will set the variable allowHover to true.
Anytime the users mouse enters the div with class of "content", allowHover is set to false.
I believe the other two functions are self explanatory, but if they require explanation, let me know.
let allowHover = false
$('nav a').click(function() {
allowHover = true
})
$('.content').mouseenter(function() {
allowHover = false
})
$('ul.nav .dropdown').hover(function() {
if(allowHover)
$(this).find('.dropdown-menu').stop(true, true).delay(200).fadeIn('fast');
})
$('ul.nav .dropdown').mouseleave(function() {
$(this).find('.dropdown-menu').stop(true, true).delay(200).fadeOut('fast');
})
Check out the codepen. Make sure you when you click a regular link in the nav, don't move your mouse outside of the navbar, or the dropdown won't work.
This is a close example to what you asked for, but I think its quite sufficient in getting you where you need to be to get your own rendition working.

How to Ensure Elements have Loaded Before Adding Class on PageLoad

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");

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/

Categories