Skip to content

JavaScript FUNctions

Before we dive into functions, we need to talk a little more about JavaScript variables, because functions will often use or output variables!

Reminder: variable definitions

What we really need to understand about variables is that they act like boxes where you can store or take information out of. - const acts like a locked safe that will not let you put anything into it after you define it - let is like a regular box that can be opened and closed, but only one thing can be stored in it at a time- if you put something new in it, the old thing is replaced - var is VARy problematic because it can be both locked and unlocked

Objects are a collection of variables that can be of different types.

Here are some of the types in JavaScript:

//number
let box1 = 5;
let box2 = 5.0;

//string
let box3 = 'five';
let box4 = "five";

// string literal, uses backticks and ${variable} to bring in another variable
let box5 = `this is from box #4: ${box4}`;

// array (also known as a list)
let box6 = [1,2,3,4,5]; 

// object, stores variables together, can be of different types!
let box7 = {"number": 'five', "value":5};

// boolean (true or false)
let box8 = true;

// null value
let emptyBox;

Remember, to declare a variable (give it a value) you must use the = symbol, like so:

let my_variable = "exist!";

Anatomy of a variable declaration

  • let is the keyword declaration of a variable
  • my_variable is the variable’s name
  • "exist!" is the value for this variable
  • ; defines the end of a line in JavaScript

Let’s warm up by using making variables in our init.js file.

js/init.js
// original code
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
});

new maplibregl.Marker()
    .setLngLat([ -118.444, 34.0709])
    .setPopup(new maplibregl.Popup({ offset: 25 }) // Add popups
        .setHTML('Math Sciences 4328 aka the Technology Sandbox<br> is the lab where I used to work in '))
    .addTo(map);

// adding markers
let ucla;
let metro;
let games;

Unique variable names

When you create new marker variables, you must give the marker variable a new name, like marker2 or you will simply override the previous marker! 😭

Time for FUNctions

What if I told you, you’ve already been using functions? 😱

Remember when we used .setLngLat() and .addTo() in Marker:

new maplibregl.Marker()
    .setLngLat([ -118.444, 34.0709])
    .setPopup(new maplibregl.Popup({ offset: 25 }) // Add popups
        .setHTML('Math Sciences 4328 aka the Technology Sandbox<br> is the lab where I used to work in '))
    .addTo(map);

Those are functions!

What is a function?

A function is a block of code that can be reused and called multiple times.

In the example above, .setLngLat() and .addTo() are functions that belong to the maplibregl.Marker class.

Why is Marker capitalized? Because it is a class!

Classes vs Functions

Classes and functions are similar, but they are not the same. A class is basically a template for creating objects, that can have properties (variables) and methods (functions) that belong to it.

The new keyword is used to make a new object from a class.

This is why we use new maplibregl.Marker() to create a new marker or new maplibregl.Map() to create a new map.

the . is used to access the methods, like .setLngLat() and .addTo(). Remember that methods just stands for a function that is a part of a class- in this case the maplibregl’s Marker class.

A method to my madness?!

Variables also have built-in functions (also called a method!!!!)

For example, string-type variables have methods for changing the string, like .toUpperCase() making all the letters UPPERCASE or .split() splitting a character based on a . To access a method, you use the . after the variable has been declared as that type.

Calling methods for what they are ()

Since methods are functions, you must call them in the same way with the () at the end. This is because some methods have parameters you can fill in.

A helping console hand!

You can check what methods are available right in Firefox’s web developer console! Most modern web browsers have this feature as well.

To give this a try, copy and paste this right into your web browser and see what happens!

let myString = "hi, this is a test string"
let divideBySpace = myString.split(" ")
console.log(divideBySpace) 
Did you get this response?

result: Array(6) [ "hi,", "this", "is", "a", "test", "string" ]

If you did, yay! This is an array (list), of 6 strings!

⚽In-class Exercise #1 - What other methods are available?

As with all languages, learning to look-up things is important to expand what you can say and do! The following is a table of where you can find some methods:

Location Type
MDN Strings
W3 Strings
W3 Numbers
W3 Arrays
W3 Objects

Tasks

  1. Visit one of the links above or search online to find other methods.
  2. Get the result to display in your console.
  3. Bonus: read the next section try to chain multiple methods together.
Answer

Here is an example of an uppercase method:

let myString = "hi, this is a test string"
let divideBySpace = myString.toUpperCase()
console.log(divideBySpace) 

Result:

"HI, THIS IS A TEST STRING"

Method chaining

In JavaScript whenever you see a . after a parenthesis(),it means you are chaining a function to follow it.

For example:

let myString = "hi this is a test string"
let divideBySpace = myString.toUpperCase().split(" ")
console.log(divideBySpace)

The output should look a little bit different than last time thanks to the toUpperCase() method!

Output

Array(6) [ "HI", "THIS", "IS", "A", "TEST", "STRING" ]

Let’s add this code to our init.js and can you see where the chaining is happening?

js/init.js
// adding markers
let ucla = new maplibregl.Marker()
    .setLngLat([-118.444, 34.0709])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work on campus'))
    .addTo(map)

It is happening 4 times in this code! Can you identify which chains are associated with which class?

Answer

.setLngLat() and .setPopup() .addTo(), are methods of the Marker class, while .setHTML() is a method of the Popup class.

Focusing on Functions

Programmers are often programming because they have to get something done, but a true programmer likes to automate (as well as copy and paste) when pre-existing functions don’t do what they want.

So, instead of using built-in functions, like with MapLibre’s .setLngLat() or methods like .toUpperCase(), we can create our own functions!

Add 2 more markers to your init.js:

let metro = new maplibregl.Marker()
    .setLngLat([-118.234, 34.056])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work at Metro'))
    .addTo(map)

let games = new maplibregl.Marker()
    .setLngLat([-118.234, 34.056])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work at games'))
    .addTo(map)

Your init.js 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
});

// adding markers
let ucla = new maplibregl.Marker()
    .setLngLat([-118.444, 34.0709])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work on campus'))
    .addTo(map)

let metro = new maplibregl.Marker()
    .setLngLat([-118.234, 34.056])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work at Metro'))
    .addTo(map)

let games = new maplibregl.Marker()
    .setLngLat([-118.234, 34.056])
    .setPopup(new maplibregl.Popup()
        .setHTML('Where I work at games'))
    .addTo(map)

Would it be cumbersome to add 10 points like this? What about 100? 1,000?

That’s where functions come in handy!

Our first new function!

Functions are declared like variables by a keyword, however instead of let, const, or var we use the keyword… function, what FUNCTIONal keyword!

A basic function looks likes this:

function our_first(){
    // do something
}

Functions with Parameters

Functions can also take in parameters. Parameters are like variables that are passed into the function.

function brand_new_one(parameter1,parameter2){
    // do something
    console.log("Parameter 1 is: " + parameter1, "and Parameter 2 is: " + parameter2)
}

In this example, parameter1 and parameter2 are the parameters of the function. Now let’s open up the console and see what happens!

Go ahead and check the console!

WHAT?! Nothing has changed! 🤔

That’s because we haven’t called the function yet!

Call for one and one for call-ing a function!

In order for a function to run, it needs to be used! This is called “invoking” or “calling” the function. When a function has no parameters, you can call it like so:

    our_first()

When it has parameters, you must pass in the parameters like so:

    brand_new_one(parameter1,parameter2)

Go ahead and call either of the functions, and you should see the console log the message so up!

Here is how it may look (just an example):

function brand_new_one(parameter1,parameter2){
    // do something
    console.log("Parameter 1 is: " + parameter1, "and Parameter 2 is: " + parameter2)
}

brand_new_one('hello','1')

creating a marker function

Let’s apply to creating a marker!

We know from the documentation and our previous usage that .setLngLat(), needs latitude and longitude, and it is stored in an array like this []. So, we can automate the marker creation by creating a function like this:

js/init.js
function addMarker(lat,lng,message){ //(1)!
    console.log(message) //(2)!
    maplibregl.Marker() //(3)!
        .setLngLat([lng, lat]) //(5)!
        .setPopup(new maplibregl.Popup()
            .setHTML(popup_message)) //(7)!
        .addTo(map) //(6)!
    return message //(4)!
}
  1. function is the declaration of our function, addMarker is the name, and lat,lng,message is the parameter, which are passed in to a function to be utilized. Parameters are optional, but parentheses () are not!! The { is the begining of the function.
  2. The console.log in the body will tell us if the function is working.
  3. Here we use the maplibregl.Marker() to create a new marker.
  4. The return is used to exit a function and return a value.
  5. We use the setLngLat method to set the latitude and longitude of the marker. Notice we flipped lng to be first and lat to be second because that’s what the setLngLat method expects.
  6. The addTo method adds the marker to the map.
  7. The bindPopup method adds a popup to the marker.
Why did we include a third parameter called message?

It allows us to customize our popups!

Notice how the how function accesses our parameters: - .setLngLat([lng, lat]) uses lng,lat - .bindPopUp uses message

Function parameters

You can pass in variables into functions and multiple parameters are seperated by a comma. In this function, there are 3 parameters: (lat,lng,message). Remember that if you even if you have NO parameters, you must include the parenthesis () like follows: - js#! function our_first_function(){return "hello world"}

But since our function does have parameters (namely the lat,lng,and message), you must specify what those are when you call the function.

Add this to the end of our init.js file:

js/init.js

    addMaker(37,-122,'you are awesome! you automated a marker function')

Warning about the order of parameters!

The order of the parameters (lat,lng,message) is must be in the SAME order that the function reads them!! Try swapping the 37 and -122 to see what I mean.

Now your console should return the “message” AND you should see a new marker on the map!

Inside function blocks you can create variables, change HTML, and do all sorts of things like play videos and even design games using them!

⚽Class Exercise #2 - Using the marker function

Create your own marker function that does the following:

  • Utilizes at least four parameters
  • Declare a new variable inside the function
  • Returns a value (return values are optional, but can be used to exit a function and return/output a value.)

Use your function to create 3 markers with it.

Check
    // create a function
    function addMarker(lat,lng,title,message){
        console.log(message)
        new maplibregl.Marker()
            .setLngLat([lng, lat])
            .setPopup(new maplibregl.Popup()
                .setHTML(popup_message))
            .addTo(map)
        return message
    }

    // use the function
    addMarker(34.070,-118.444, "UCLA", "Where I work on campus")
    addMarker(34.056,-118.234, "Metro", "Where I work at Metro")
    addMarker(34.056,-118.234, "Games", "Where I work at games")

If you finished early, try these extra challenges:

  • Try to style your pop-up with 2 attributes!

Bonus Exercise - Create your own function

Create your own function that does the following:

  • Utilizes at least two parameters
  • Declare a new variable inside the function
  • Returns a value
Bonus Answer
    // create function
    function addNumbers(value1,value2){
        let result = value1 + value2
        return result
    }

    // use the function
    addNumbers(1,10)   // result: 11

Combining Strings

We can combine strings with the + operator. For example:

let zoomLevel = 10
let popup = 'The zoom level is ' + zoomLevel

Side note: String Literals

String literals or template strings allow you to subsitute variables into strings with the ${VARIABLE_NAME} syntax inside the place holders.

Declaring a string with ` instead of ' ' or " ", allows you to convert variables to strings.

This technique will be helpful for our pop-ups as follows:

// creating a function
function addMarker(lat,lng,title,message){
    console.log(message)
    maplibregl.Marker()
        .setLngLat([lng, lat])
        .addTo(map)
        .bindPopup(`<h2>${title}</h2> <h3>${message}</h3>`)
    return message
}
  1. Notice how title is added to the <h2> tag element and message is added to an <h3> element?

Alternative Method

You can also bundle the pop-up into a variable, and then use that to populate the bindPopup() call:

// creating a function
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)
    return message
}

🏁 Checkpoint

  • You should have a function that creates markers on the map
  • You should have a function that takes in parameters

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)

    return message
}

addMarker(34.070,-118.444, "UCLA", "Where I work on campus")
addMarker(34.056,-118.234, "Metro", "Where I work at Metro")
addMarker(34.056,-118.234, "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">
                <!-- 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 */
}