Skip to content

Events in the Fire KingDOM

Objective

Make a button that we can click on to fly to a location for each of the markers you made.

  1. Add a place for the buttons to go

  2. Create the function to add buttons to the DOM that also moves the map

  3. Call the new function in our addMarker function

The HTM-Elements: Ava<tag> the last Airbender

Remember, when you see tags that have an open and /end in HTML, like <body></body>, they are referred to as elements, so for example:

<water>Katara</water> 
<air>Aang</air> 
<earth>Toph</earth> 
<fire>Zuko</fire>
Above we have four elements. Each element has a content, for example, the earth element’s content is Toph. Unfortunately, despite how exciting those elements are, the most common HTML element is the <div></div> element, which is a generic container.

This is not an element: <link> because there is not /link to close it.

Elements can contain other elements, for example:

<kingdom>
    <earth>Toph</earth>
</kingdom>
Here Toph is inside the earth element, which is inside the kingdom element.

Reminder that all tags can have attributes:

<kingdom>
    <earth attribute="valueForTheAttribute">Toph</earth>
</kingdom>

The DOM (Document Object Model) how HTML elements are treated as objects that can be manipulated by JavaScript. The DOM has an API (Application Programming Interface) with JavaScript is used to interact with the elements.

The DOM is a tree structure, which means that the document is the root of the DOM tree, and all elements are children of the document.

DOM Tree

Just think of the DOM as the foundation of our HTML house and the elements are the rooms where we can use JavaScript appliances to interact with them. Anything outside the <html> element (i.e. after the </html>) is not part of the DOM so you can’t use JavaScript to access it.

Creating elements in the DOM?!

To create HTML elements with JavaScript you need to use the createElement method.

Add a place for the buttons to go

A contents container

Our buttons needs a place to go, so let’s add a <div> with an ID called contents for our map.

divs vs. spans, what’s the DIVfference?

divs are generic HTML elements that stand for division of content, you can think of them as boxes of content. Spans are like divs, but for text content. Check out Mozilla Developer Network for more information:

After the <div id="contents"></div> element, add a new <div></div> element, and give it an ID attribute of contents like the follwing:

<div id="contents"></div>
And let’s add it after our portfolio div:

Our current index.html should look like the following:

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Hello World with MapLibreGl</title>
        <!-- hint: remember to change your page title! -->
        <meta charset="utf-8" />
        <link rel="shortcut icon" href="#">
        <link rel="stylesheet" href="styles/style.css">

        <!-- MapLibreGL's css-->
        <link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" />

        <!-- MapLibreGL's JavaScript-->
        <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
    </head>

    <body>
        <header>
            Hello World
            <!-- hint: you can make a menu with other links here if you'd like -->
        </header>

        <main>
            <div class="portfolio">
                <div id="contents"></div>
                <!-- Portfolio content goes here -->
                 <h2>Where I work</h2>
                 <ul>
                     <li>Los Angeles Metro</li>
                     <li>UCLA</li>
                     <li>Yindee Games</li>
                 </ul>
            </div>
            <div id="map"></div>
        </main>
        <div id="footer">
            Copyright(2024)
        </div>
        <script src="js/init.js"></script>
    </body>
</html>

Prepping the CSS

Let’s incorporate our new div that has the id ofthe_map into our CSS now.

Reminder: IDs vs. Classes

  • IDs: There can only be ONE unique ID on a HTML page and in CSS you refer to it with a #, like #the_map.
  • Classes: There can be multiple classes on an HTML page and in CSS you refer to it with a .
styles/style.css
#contents{
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
}

Create the function to add buttons and move the map

Next we will add our new function. Notice how we are using the lat,lng,and title from the addMarker function? That’s why it was helpful to do step one first.

js/init.js
function createButtons(lat,lng,title){
    const newButton = document.createElement("button"); // (1)! 
    newButton.id = "button"+title; // (2)! 
    newButton.innerHTML = title; // (3)! 
    newButton.setAttribute("lat",lat); // (4)! 
    newButton.setAttribute("lng",lng); // (5)! 
    newButton.addEventListener('click', function(){
        map.flyTo({
            center: [lng,lat], //(6)!
        })
    })
    document.getElementById("contents").appendChild(newButton); //(7)! 
}
  1. Creates a new button element
  2. Gives the button a unique id
  3. Gives the button a title
  4. Sets the latitude
  5. Sets the longitude
  6. Tells MapLibre where to flyTo(), which is the longitude/latitude
  7. This targets the id where the buttons should be added to! In this case it is the div
    with the id contents!

Call the createButtons() in our addMarker function

Remember, the only way functions work is if they are called, so the last step is to call the createButtons() in our addMarker() function.

js/init.js
function addMarker(lat,lng,title,message){
    let popup_message = `<h2>${title}</h2> <h3>${message}</h3>`
    maplibregl.Marker()
        .setLngLat([lng, lat])
        .addTo(map)
        .bindPopup(popup_message)
    createButtons(lat,lng,title);
    return message
}
  1. This is the line that calls our createButtons() function!

Try clicking the button on the webpage and it should fly to the location of that marker!

🏁 Final Checkpoint

  • You should have a button that when clicked, moves the map to the location of the marker.
  • You should have a button for each marker you have created.

Your code should look like this:

js/init.js
// Initialize the map
const map = new maplibregl.Map({
    container: 'map', // container ID
    style: 'https://api.maptiler.com/maps/streets-v2-light/style.json?key=wsyYBQjqRwKnNsZrtci1', // Your style URL
    center: [-118.4430,34.0691], // Starting position [lng, lat]
    zoom: 15 // Starting zoom level
});

function addMarker(lat,lng,title,message){
    let popup_message = `<h2>${title}</h2> <h3>${message}</h3>`
    new maplibregl.Marker()
        .setLngLat([lng, lat])
        .setPopup(new maplibregl.Popup()
            .setHTML(popup_message))
        .addTo(map)
    createButtons(lat,lng,title);
    return message
}

function createButtons(lat,lng,title){
    const newButton = document.createElement("button"); // (1)! 
    newButton.id = "button"+title; // (2)! 
    newButton.innerHTML = title; // (3)! 
    newButton.setAttribute("lat",lat); // (4)! 
    newButton.setAttribute("lng",lng); // (5)! 
    newButton.addEventListener('click', function(){
        map.flyTo({
            center: [lng,lat], //(6)!
        })
    })
    document.getElementById("contents").appendChild(newButton); //(7)! 
}

addMarker(34.070,-118.444, "UCLA", "Where I work on campus")
addMarker(34.056,-118.234, "Metro", "Where I work at Metro")
addMarker(34.059,-118.374, "Games", "Where I work at games")
index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Hello World with MapLibreGl</title>
        <!-- hint: remember to change your page title! -->
        <meta charset="utf-8" />
        <link rel="shortcut icon" href="#">
        <link rel="stylesheet" href="styles/style.css">

        <!-- MapLibreGL's css-->
        <link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" />

        <!-- MapLibreGL's JavaScript-->
        <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
    </head>

    <body>
        <header>
            Hello World
            <!-- hint: you can make a menu with other links here if you'd like -->
        </header>

        <main>
            <div class="portfolio">
                <div id="contents"></div>
                <!-- Portfolio content goes here -->
                 <h2>Where I work</h2>
                 <ul>
                     <li>Los Angeles Metro</li>
                     <li>UCLA</li>
                     <li>Yindee Games</li>
                 </ul>
            </div>
            <div id="map"></div>
        </main>
        <div id="footer">
            Copyright(2024)
        </div>
        <script src="js/init.js"></script>
    </body>
</html>
styles/style.css
/* Global reset to ensure consistency across browsers */
* {
    font-family: Arial, sans-serif; /* Sets a default font for the whole page */
    margin: 0; /* Removes default margins */
    padding: 0; /* Removes default padding */
    box-sizing: border-box; /* Makes sure borders and paddings are included in the element's total width and height */
}

/* Sets the background color of the whole page and ensures content fits the screen height */
html {
    background-color: aqua; /* Sets a light blue background color */
}

/* Applies to both <html> and <body> */
html, body {
    height: 80vh; /* Sets the height to 80% of the viewport height, making sure the content fits on the screen */
    padding: 1rem; /* Adds a bit of space around the content for better readability */
    box-sizing: border-box; /* Ensures padding does not add to the set height */
}

/* Defines the main layout of the page using CSS Grid */
body {
    display: grid; /* Enables CSS Grid layout */
    grid-template-areas: 
        "header" /* Top area for the header */
        "main"   /* Middle area for the main content */
        "footer"; /* Bottom area for the footer */
    grid-template-rows: auto 1fr auto; /* Sizes: auto for header and footer to fit content, 1fr for main to fill remaining space */
}

/* Sets up the layout for the main content area, dividing it into two columns */
main {
    display: grid; /* Enables CSS Grid within the main element */
    grid-template-areas:
        "portfolio map"; /* Divides the main area into portfolio and map sections side by side */
    grid-template-columns: 1fr 1fr; /* Allocates equal width to both sections */
}

/* Grid area assignments for each major section, linking them to their respective areas in the grid */
header { 
    grid-area: header; /* Assigns the header to its grid area */
}

main { 
    grid-area: main; /* Assigns the main content to its grid area */
}

.portfolio {
    grid-area: portfolio;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}


#map { 
    grid-area: map; /* Assigns the map section to its grid area */
    height: 80vh; /* Sets the map's height to 80% of the viewport height */
}

#footer {
    grid-area: footer;
    padding: 5px; /* Adds padding for better spacing */
    background-color: #4677a0; /* Sets a dark background for contrast */
    color: #fff; /* Ensures text is readable against the dark background */
    text-align: center; /* Centers the footer content */
}

#contents{
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 10px;
}