Change time based on input timezone with JS - javascript

I'd like to do a simple clocks project.
In this project the user has to choose a timezone from combobox and when click one of them, the main time (id=digital-clock) has to change with timezone time.
I've one txt file (zone.txt) which contain all timezones.
This is my code: (it doesn't work here as a snippet).
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Clockify</title>
<link rel="shortcut icon" href="http://cdn.onlinewebfonts.com/svg/img_461716.png">
<link rel="stylesheet" href="style.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1/animate.min.css" />
<style>
body {
background: linear-gradient(-45deg, #ee7752, #e73c7e, #23a6d5, #23d5ab);
background-size: 400% 400%;
animation: gradient 15s ease infinite;
height: 100vh;
font: open-sans-serif;
}
a {
text-decoration: none;
color: black;
}
#keyframes gradient {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
.dst-btn {
margin-right: 75px;
}
</style>
</head>
<body class="unselectable">
<div class="time-label">
<div id="analog-clock" class="clock" style="margin-left:200px; margin-top: -180px;">
<div class="hour">
<div class="hr" id="hr"></div>
</div>
<div class="min">
<div class="mn" id="mn"></div>
</div>
<div class="sec">
<div class="sc" id="sc"></div>
</div>
</div>
<div id="digital-clock" style="margin-top:-350px;"><span id="time" style="font-size:170px;font-weight:bold;color:#fff;"></span></div>
<br><br><br>
<div class="buttons animate__animated animate__bounceInUp" style="display: inline-block;">
<button type="button" class="btn btn-light btn-lg dst-btn">Alarm</button>
<select onchange="changeTimeZone();" style="padding: 10px;border-radius: 5px;padding-bottom:-2px;width:200px;" class="btn btn-light dst-btn" name="timezone-label" id="timezone-label" aria-required="true">
<script src="https://cdn.jsdelivr.net/npm/#popperjs/core#2.9.3/dist/umd/popper.min.js "></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.1.1/dist/js/bootstrap.min.js "></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<script src="script.js "></script>
<script>
// Load data from file ['Europe/Rome, Europe/Amsterdam, etc.'] into combobox
$.ajax({
url: 'zone.txt',
success: function(data) {
var splitData = data.split("\n");
for(i = 0; i <= splitData.length; i++) {
$('#timezone-label').append("<option id='timezone-label' value='" + splitData[i] + "'>" + splitData[i] + "</option>");
}
}
});
</script>
</select>
<button id="style" type="button" class="btn btn-light btn-lg dst-btn">Style</button>
<button id="stopwatch" type="button " class="btn btn-light btn-lg dst-btn ">Stopwatch</button>
<button type="button" class="btn btn-light btn-lg dst-btn ">Countdown</button>
</div>
</div>
<script>
function changeTimeZone() {
var timeZone = document.getElementById('timezone-label');
const str = new Date().toLocaleString('it-IT', {
timeZone: timeZone
});
var myArray = str.split(",");
document.getElementById("time").innerHTML = myArray[1];
}
</script>
</body>
</html>
I tried to use this code , but it doesn't work :
function changeTimeZone() {
var timeZone = document.getElementById('timezone-label');
const str = new Date().toLocaleString('it-IT', {
timeZone: timeZone
});
var myArray = str.split(",");
document.getElementById("time").innerHTML = myArray[1];
}
I use boostrap 5, jquery and ajax in my project.
In my opinion, the problem is with this line: timeZone: timeZone. How can I do it? I want to set a timezone variable as attribute.
I've this error in javascript console:
Uncaught RangeError: Invalid time zone specified: [object HTMLSelectElement]
at Date.toLocaleString (<anonymous>)
at changeTimeZone (clocks.html:87)
at HTMLSelectElement.onchange (clocks.html:62)

timeZone: timeZone
change to
timeZone: timeZone.value
try => This

Related

Traversing through them DOM

Im having trouble trying to do the following:
When I hit the button(the first time), I want it to select the first box and then change the background to grey, and as the button is being pressed, I want it to jump to the next box and change that box into grey. Help Please!
const boxes = document.querySelector('#boxes');
const button = document.querySelector('button');
button.addEventListener('click', () => {
let firstChild = boxes.firstElementChild;
for (let i = 0; i < boxes.length; i++) {
firstChild.nextElementSibling.style.backgroundColor = 'grey';
}
})
body {
background: rgb(78, 78, 78);
}
.boxes {
height: 600px;
width: 380px;
background: rgb(236, 236, 236);
border-radius: 20px;
}
.box {
height: 100px;
background: rgb(26, 149, 187);
}
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<!-- My CSS -->
<link rel="stylesheet" href="main.css">
<title>Hello, world!</title>
</head>
<body>
<div class="container boxes mt-5">
<h1 class="text-center mb-4">App.js</h1>
<div id='boxes' class="row justify-content-around">
<div class="col-3 box "></div>
<div class="col-3 box "></div>
<div class="col-3 box "></div>
</div>
<div class="row mt-4 justify-content-around">
<div class="col-3 box "></div>
<div class="col-3 box "></div>
<div class="col-3 box "></div>
</div>
<div class="container text-center mt-4">
<button id="button" type="button" class="btn btn-warning">Submit</button>
</div>
</div>
</body>
</html>
This is one way to do it using closures:
const boxes = document.querySelector('#boxes');
const button = document.querySelector('button');
const createListener = () => {
let counter = 0
return () => {
boxes.children[counter %
boxes.children.length].style.backgroundColor = 'gray'
counter++
}
}
button.addEventListener('click', createListener())
I did not test it but it should work. If you don't understand what's going on please research on closures. It'll be very useful.

How can I turn the array of numbers into a list that only appears when the plus icon is clicked?

I have returned an array of results and turned it into an average, but below the average, I wish to reveal each individual test result of the student when the grey plus icon is clicked.
like the link below shows.
https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/f-1/735fae21-9b8d-4431-8978-5098a2217fd2/part4.webm
any help is appreciated
const apiInfo = $('.info');
const avg = (arr) => arr.reduce((acc, x) => acc + x, 0) / arr.length;
const nameSeachInput = $('#nameSearch');
nameSeachInput.on('input',
function() {
apiInfo.empty();
allStudents.filter(student => student.firstName.toLowerCase().includes(this.value.toLowerCase()) || student.lastName.toLowerCase().includes(this.value.toLowerCase())).forEach(student => {
if (student.id.includes('')) {
renderStudentInfo(student, apiInfo);
}
});
});
let allStudents;
const renderStudentInfo = (student, $target) => {
const fullName = student.firstName + ' ' + student.lastName,
average = avg(student.grades.map(grade => parseInt(grade, 10)));
$target.append($(`
<div class="infoB">
<img class="pPic float-left m-3"
src="${student.pic}" alt="profile pic" />
<h4 class="title">${fullName}<h4>
<p class="mb-1 stats">Email: ${student.email}</p>
<p class="mb-1 stats">Comapny: ${student.company}</p>
<p class="mb-1 stats">Skill: ${student.skill}</p>
<p class="mb-1 stats">Average: ${average.toFixed(2)}%</p>
<p class="mb-1 d-none" id="stats"> ${student.grades}%<p>
<i class="mb-5 fa fa-plus float-right"></i>
</div>
`));
};
$( "#plus" ).click(function() {
$( '#stats' ).toggleClass( "d-none" );
});
const init = () => {
$.ajax({
url: 'https://api.hatchways.io/assessment/students',
method: 'GET',
}).then(({
students
}) => {
allStudents = students;
students.forEach((student) => {
if (student.id.includes('')) {
renderStudentInfo(student, apiInfo);
}
});
});
}
init();
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="input mt-5 mx-5">
<input
id="nameSearch"
type="text"
class="form-control"
placeholder="Search by name"
aria-label="Search by name"
aria-describedby="basic-addon1"
/>
</div>
<div class="input mb-0 mt-2 mx-5">
<input
id="tagSearch"
type="text"
class="form-control"
placeholder="Search tags"
aria-label="Search tags"
aria-describedby="basic-addon1"
/>
</div>
<div class="container mt-0">
<div class="info card scroll shadow p-3 mb-5 bg-white rounded"></div>
<span class="glyphicon glyphicon-plus"></span>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="index.js"></script>
</body>
</html>
body{
background-color: rgb(243, 240, 240);
}
img{
border-radius: 50%;
border: solid rgb(156, 148, 148) 1px;
min-width: 130px;
}
.infoB{
border-bottom: solid grey 1px;
}
.stats{
color: grey;
margin-left: 175px;
}
.title{
font-size: 50px;
}
.card {
margin-top: 100px;
}
.scroll {
max-height: 575px;
overflow-y: auto;
}
.fa-plus{
color: grey;
font-size: 50px;
}
There are several ways to do it, but the simplest way would be to have the individual numbers in a container that you show/hide every time the plus icon is clicked. You may also want to swap the plus icon image for a minus icon on each toggle.
I've implemented a basic version here: https://jsfiddle.net/r63ctej0/
Essentially, in the above implementation, I've put the numbers in a <ul> tag and I give this list an id {fullName}_numbers so that each card has a unique id.
Then I create a toggleNumbers(id) function that takes that id and switches its display state.
Lastly, I added onclick=toggleName('{fullName}_numbers') to the plus icon

How can I filter the results by first and last name?

I need the search bars to filter out the results by first and last name
as shown in this link,
https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/f-1/735fae21-9b8d-4431-8978-5098a2217fd2/part3.webm
as well as the plus button to expand the percentages back to a list instead of an average.
https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/f-1/735fae21-9b8d-4431-8978-5098a2217fd2/part4.webm
as shown here.
As well as an input field to add tags to each student for the second search bar to find.
https://storage.googleapis.com/hatchways-app.appspot.com/assessments/data/frontend/f-1/735fae21-9b8d-4431-8978-5098a2217fd2/part5.webm
as shown here.
I am very stumped on this problem. any assistance would be welcome.
thank you!
const apiInfo = $('.info');
const avg = (arr) => arr.reduce((acc, x) => acc + x, 0) / arr.length;
const renderStudentInfo = (student, $target) => {
const fullName = student.firstName + ' ' + student.lastName,
average = avg(student.grades.map(grade => parseInt(grade, 10)));
$target.append($(`
<div class="infoB">
<img class="pPic float-left m-3"
src="${student.pic}" alt="profile pic" />
<h4 class="title">${fullName}<h4>
<p class="mb-1 stats">Email: ${student.email}</p>
<p class="mb-1 stats">Comapny: ${student.company}</p>
<p class="mb-1 stats">Skill: ${student.skill}</p>
<p class="mb-1 stats">Average: ${average.toFixed(2)}%</p>
<i class="mb-5 fa fa-plus float-right"></i>
</div>
`));
};
const init = () => {
$.ajax({
url: 'https://api.hatchways.io/assessment/students',
method: 'GET',
}).then(({ students }) => {
students.forEach((student) => {
if (student.id.includes('')) {
renderStudentInfo(student, apiInfo);
}
});
});
}
init();
body{
background-color: rgb(243, 240, 240);
}
img{
border-radius: 50%;
border: solid rgb(156, 148, 148) 1px;
min-width: 130px;
}
.infoB{
border-bottom: solid grey 1px;
}
.stats{
color: grey;
margin-left: 175px;
}
.title{
font-size: 50px;
}
.card {
margin-top: 100px;
}
.scroll {
max-height: 575px;
overflow-y: auto;
}
.fa-plus{
color: grey;
font-size: 50px;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<link
rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z"
crossorigin="anonymous"
/>
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="input mt-5 mx-5">
<input
id="nameSearch"
type="text"
class="form-control"
placeholder="Search by name"
aria-label="Search by name"
aria-describedby="basic-addon1"
/>
</div>
<div class="input mb-0 mt-2 mx-5">
<input
id="tagSearch"
type="text"
class="form-control"
placeholder="Search tags"
aria-label="Search tags"
aria-describedby="basic-addon1"
/>
</div>
<div class="container mt-0">
<div class="info card scroll shadow p-3 mb-5 bg-white rounded"></div>
<span class="glyphicon glyphicon-plus"></span>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js"></script>
<script src="index.js"></script>
</body>
</html>

Create a custom/prettier confirm() and use it in if() statement

The closest I found researching for what I was looking for is this: Making a confirm box
Unfortunately, I could not make it do exactly what I wanted or I didn't understand. I am new to Java/Javascript and HTML.
I am using Google Scripts to create a custom user interface for, Google Sheets to make capturing the input needed user friendly. I am stuck on trying to include a custom confirm in my validation code. To test it I just created a simple web app with below code: (I created some Psuedo code and commented it out in the myFunction function within the code below)
function doGet(){
var template = HtmlService.createTemplateFromFile('Basic');
return template.evaluate()
.setTitle('Example App')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
.confirmBox {
display: none;
background-color: rgba(0, 0, 0, 0.40);
border: 1px solid #ddd;
position: fixed;
-webkit-transition: -webkit-box-shadow .25s;
transition: -webkit-box-shadow .25s;
transition: box-shadow .25s;
transition: box-shadow .25s, -webkit-box-shadow .25s;
border-radius: 2px;
width: 250px;
left: 50%;
margin-left: -100px;
padding: 6px 8px 8px;
box-sizing: border-box;
text-align: center;
color: #ffffff;
font-size: 24px;
z-index:99;
}
.confirm .message {
text-align: left;
}
</style>
</head>
<body>
<div id="cfrmBox" class="confirmBox">
<div id="cfrmBoxMsg" class="message"></div>
<button id="idYesButton" class="btn waves-effect waves-light z-depth-5" >Yes</button>
<button id="idNoButton" class="btn waves-effect waves-light z-depth-5" >No</button>
</div>
<div class="container">
<div class="row">
<div class="col s12">
<br><br>
<div class="card">
<div class="card-image">
<span class="card-title">Timer</span>
<a class="btn-floating halfway-fab waves-effect waves-light teal z-depth-5 tooltipped"
data-position="top"
data-tooltip="Press to start and stop timer" onclick="startStopTimer()">
<i id="idStopWatch" class="large material-icons">access_time</i></a>
</div>
<div id ="idCardContent" class="card-content" style="color: #4db6ac;
font-weight: bold;
font-weight: 150%">
<p id = "idCardContentP">04:10:24</p>
</div>
</div>
<button class="btn waves-effect waves-light z-depth-5" id="btnNextTask" onclick="myFunction()">Next Task
<i class="material-icons right">music_note</i>
</button>
</div> <!-- END col END -->
</div> <!-- END row END -->
</div> <!-- END Container -->
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"> </script>
<script>
function appearNow(tMessage){
var x = document.getElementById('cfrmBoxMsg');
x.innerHTML = tMessage;
var y = document.getElementById('cfrmBox');
y.style.display = "inline";
}
function myFunction() {
var stTime = document.getElementById('idCardContentP').innerHTML;
if (stTime != "") {
//Had function left in front. Corrected
appearNow('Do you want to save your time for this task?')
// This is where I want to capture if the 'yes' or 'no' button was pressed
//Psuedo code below
/*
if(document.getElementById('idYesButton').click == true){
y.style.display = "none";
M.toast({html: 'You clicked YES and time has been saved and here is the next task'});
} else {
y.style.display = "none";
M.toast({html: 'You clicked NO and we will do nothing'});
}
*/
//Continue with more validation code
} else {
M.toast({html: 'Since the timer has not started you can freely move to the next task'});
}
}
function startStopTimer() {
M.toast({html: 'Timer is hard coded to be greater than 0 for testing!'});
}
</script>
</body>
</html>
I greatly appreciate any help.
It really seems like nested if statements to create one function to do one particular set of validations isn't really workable in this world since once a function is called it has to complete unless the built-in confirm() is called which is practical but ugly. So I had to rethink my logic route and realized to do what I want and have a custom confirm box I can't make it a nice reusable, neat and tidy function. I have to create a separate function for each validation and create a new '
<div id="cfrmBox" class="confirmBox">
' each time I want to use it, with the buttons that call a specific function with the 'onclick' each time specific to that validation. This can, in my opinion, make the code bulky. But, it works.
function doGet(){
var template = HtmlService.createTemplateFromFile('Basic');
return template.evaluate()
.setTitle('Example App')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<!--Import Google Icon Font-->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<!-- Compiled and minified CSS -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<!--Let browser know website is optimized for mobile-->
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<style>
.confirmBox {
display: none;
background-color: rgba(0, 0, 0, 0.40);
border: 1px solid #ddd;
position: fixed;
-webkit-transition: -webkit-box-shadow .25s;
transition: -webkit-box-shadow .25s;
transition: box-shadow .25s;
transition: box-shadow .25s, -webkit-box-shadow .25s;
border-radius: 2px;
width: 250px;
left: 50%;
margin-left: -100px;
padding: 6px 8px 8px;
box-sizing: border-box;
text-align: center;
color: #ffffff;
font-size: 24px;
z-index:99;
}
.confirm .message {
text-align: left;
}
</style>
</head>
<body>
<div id="cfrmBox" class="confirmBox">
<div id="cfrmBoxMsg" class="message"></div>
<button id="idYesButton" class="btn waves-effect waves-light z-depth-5" value="yes" onclick="confirmYesNo(this.value)">Yes</button>
<button id="idNoButton" class="btn waves-effect waves-light z-depth-5" value="no" onclick="confirmYesNo(this.value)">No</button>
</div>
<div id="idContainer" class="container">
<div class="row">
<div class="col s12">
<br><br>
<div class="card">
<div class="card-image">
<span class="card-title">Timer</span>
<a id="idStopWatchBtn" class="btn-floating halfway-fab waves-effect waves-light teal z-depth-5 tooltipped"
data-position="top"
data-tooltip="Press to start and stop timer" onclick="startStopTimer()">
<i id="idStopWatch" class="large material-icons">access_time</i></a>
</div>
<div id ="idCardContent" class="card-content" style="color: #4db6ac;
font-weight: bold;
font-weight: 150%">
<p id = "idCardContentP">04:10:24</p>
</div>
</div>
<div class="row">
<div class="col s12">
<div id="idCardPanel" class="card-panel teal">
<span id="idCardPanelSpan"class="white-text">Task 1: Do something fun
</span>
</div>
</div>
</div>
<button class="btn waves-effect waves-light z-depth-5" id="btnNextTask" onclick="myFunction()">Next Task
<i class="material-icons right">music_note</i>
</button>
</div> <!-- END col END -->
</div> <!-- END row END -->
</div> <!-- END Container -->
<!-- Compiled and minified JavaScript -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"> </script>
<script>
function appearNow(tMessage){
var x = document.getElementById('cfrmBoxMsg');
x.innerHTML = tMessage;
var y = document.getElementById('cfrmBox');
y.style.display = "inline";
}
function myFunction() {
var stTime = document.getElementById('idCardContentP').innerHTML;
if (stTime != "") {
document.getElementById("idStopWatchBtn").classList.add("disabled");
document.getElementById("btnNextTask").classList.add("disabled");
appearNow('Do you want to save your time for this task?')
} else {
document.getElementById('idCardPanelSpan').innerHTML = "Task 2: Do something even funner!";
M.toast({html: 'Since the timer has not started you can freely move to the next task'});
}
}
function startStopTimer() {
M.toast({html: 'Timer is hard coded to be greater than 0 for testing!'});
}
function confirmYesNo(btnValue){
switch (btnValue) {
case "yes":
document.getElementById('idCardContentP').innerHTML = '';
showHideElements('cfrmBox');
M.toast({html: 'You clicked yes.'});
//Since timer is blank it will hit code to move to next task
myFunction();
break;
case "no":
showHideElements('cfrmBox');
M.toast({html: 'You clicked no so nothing happens'});
break;
default:
M.toast({html: 'Oops this should not happen'});
}
document.getElementById("idStopWatchBtn").classList.remove("disabled");
document.getElementById("btnNextTask").classList.remove("disabled");
}
function showHideElements(showHideWhat) {
//Be careful with this function if you start with display block versus inline
var x = document.getElementById(showHideWhat);
if (x.style.display !== "none") {
x.style.display = "none";
} else {
x.style.display = "inline";
}
}
</script>
</body>
</html>

Bootstrap dropdown menu button not showing with Leaflet map

I'm trying to create a leafletJS Map with Bootstrap buttons. I made the map fullscreen and placed the buttons on top of it. Here is the code:
<!DOCTYPE html>
<html>
<head>
<title>Map</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="static/bootstrap/js/bootstrap.min.js"></script>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css" integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA==" crossorigin=""/>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js" integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA==" crossorigin=""></script>
<link rel="stylesheet" media="screen" href ="static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap/css/bootstrap-theme.min.css">
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100%;
}
#back_button {
position: absolute;
top: 20px;
left: 20px;
padding: 10px;
z-index: 1001;
}
#drop_button {
position: absolute;
top: 80px;
left: 20px;
padding: 10px;
z-index: 1001;
}
</style>
</head>
<body>
<div id='map'>
</div>
<form action="/" method="post" role="form">
<button type="submit" class="btn btn-default" id="back_button"><- Back</button>
</form>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" id="drop_button">Dropdown Example
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</div>
<script>
var map = L.map('map', {zoomControl:false}).setView([47.57768554635565,-122.16660887002944], 13);
var coordinate = {{list_latlong | tojson | safe}};
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var logoIcon = L.icon({
iconUrl: './static/picture.png',
iconSize: [22, 22], // size of the icon
iconAnchor: [11, 22], // point of the icon which will correspond to marker's location
});
var i;
for (i = 0; i < coordinate.length; i++) {
var point = coordinate[i]
var text = "";
text = "<dl><dt>Number: " + point[2] + "</dt>"
+ "<dt>" + point[5] + "</dt>"
+ "<dt>" + point[6] + ", " + point[7] + ", " + point[8] + "</dt>"
+"</dl>"
L.marker([point[3],point[4]], {icon: logoIcon}).bindPopup(text).addTo(map);
}
</script>
</body>
</html>
Running this code will only show the "Back" button and no dropdown button. If I remove
<link rel="stylesheet" media="screen" href ="static/bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="static/bootstrap/css/bootstrap-theme.min.css">
The dropdown button and back button is showing but the elements in the dropdown menu are not showing.
I've fixed that for you, for more than one reason, first the bootstrap link is wrong, second you add wrong styles on wrong id #dropdown button, so the button was displayed but in footer so you don't see it, here's the full code with edit some files places and urls with update new style from #dropdown to parent div .dropdown
<!DOCTYPE html>
<html>
<head>
<title>Map</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet#1.3.4/dist/leaflet.css"/>
<style>
body {
padding: 0;
margin: 0;
}
html, body, #map {
height: 100%;
width: 100%;
}
#back_button {
position: absolute;
top: 20px;
left: 20px;
padding: 10px;
z-index: 1001;
}
.dropdown {
position: absolute;
top: 80px;
left: 20px;
z-index: 1001;
}
</style>
</head>
<body>
<div id='map'>
</div>
<form action="/" method="post" role="form">
<button type="submit" class="btn btn-default" id="back_button"><- Back</button>
</form>
<div class="dropdown">
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown" id="drop_button">Dropdown Example
<span class="caret"></span></button>
<ul class="dropdown-menu">
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
</ul>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/leaflet#1.3.4/dist/leaflet.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>
var map = L.map('map', {zoomControl:false}).setView([47.57768554635565,-122.16660887002944], 13);
var coordinate = {{list_latlong | tojson | safe}};
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '© OpenStreetMap contributors'
}).addTo(map);
var logoIcon = L.icon({
iconUrl: './static/picture.png',
iconSize: [22, 22], // size of the icon
iconAnchor: [11, 22], // point of the icon which will correspond to marker's location
});
var i;
for (i = 0; i < coordinate.length; i++) {
var point = coordinate[i]
var text = "";
text = "<dl><dt>Number: " + point[2] + "</dt>"
+ "<dt>" + point[5] + "</dt>"
+ "<dt>" + point[6] + ", " + point[7] + ", " + point[8] + "</dt>"
+"</dl>"
L.marker([point[3],point[4]], {icon: logoIcon}).bindPopup(text).addTo(map);
}
</script>
</body>
</html>
<script src="static/bootstrap/js/bootstrap.min.js"></script>
This is the bootstrap script file to make the menus and other fancy js-dependent stuff work. But in order for it to work it needs to have a DOM (document object model) to work with. What you currently have is the script firing right at the top after jQuery, without any DOM element for it to work with (the menu elements haven't been parsed yet!).
Try putting this at the spot right before you close your </body> tag. That should make the menu elements work.

Categories

Resources