CycleTracker: JavaScript functionality - Progressive web apps

CycleTracker: JavaScript functionality
======================================

* Previous
* Overview: CycleTracker
* Next

In the previous section, we wrote the HTML and CSS for CycleTracker, creating a static version of our web app. In this section, we will write the JavaScript required to convert static HTML into a fully functional web application.

If you haven't already done so, copy the HTML and CSS and save them to files called `index.html` and `style.css`.

The last line in the HTML file calls the `app.js` JavaScript file. This is the script we are creating in this section. In this lesson, we will be writing client-side JavaScript code to capture form submissions, locally store submitted data, and populate the past-periods section.

At the end of this lesson, you will have a fully functional app. In future lessons, we will progressively enhance the app to create a fully installable PWA that works even when the user is offline.

JavaScript task
---------------

When a user visits the page, we check if they have existing data stored in local storage. The first time a user visits the page, there won't be any data. When a new user selects two dates and submits the form, we need to:

1. Create a "`<h2>Past periods</h2>`" header
2. Create an `<ul>`
3. Populate the `<ul>` with a single `<li>` containing information about that cycle
4. Save the data to local storage

For each subsequent form submission, we need to:

1. Add the new menstrual cycle to the current list
2. Sort the list in date order
3. Repopulate the `<ul>` with the new list, one `<li>` per cycle
4. Append the data to our saved local storage

Existing users will have existing data in local storage. When a user comes back to our webpage with the same browser on the same device, we need to:

1. Retrieve the data from local storage
2. Create a "`<h2>Past periods</h2>`" header
3. Create an `<ul>`
4. Populate the `<ul>` with an `<li>` for every menstrual cycle saved in local storage.

This is a beginner-level demonstration application. The goal is to teach the basics of converting a web application to a PWA. This application does not contain necessary features like form validation, error checking, edit or delete functionality, etc. You are welcome to expand on the features that are covered and tailor the lesson and applications to your learning goals and application needs.

Form submission
---------------

The page contains a `<form>` with date pickers for selecting the start and end dates of each menstrual cycle. The date pickers are `<input>` of type date with the `id` of `start-date` and `end-date` respectively.

The form has no method or action. Instead, we add an event listener with `addEventListener()` to the form. When the user tries to submit the form, we prevent the form from submitting, store the new menstrual cycle, render this period along with previous ones, and then reset the form.

```js
// create constants for the form and the form controls
const newPeriodFormEl = document.getElementsByTagName("form")[0];
const startDateInputEl = document.getElementById("start-date");
const endDateInputEl = document.getElementById("end-date");

// Listen to form submissions.
newPeriodFormEl.addEventListener("submit", (event) => {
  // Prevent the form from submitting to the server
  // since everything is client-side.
  event.preventDefault();

  // Get the start and end dates from the form.
  const startDate = startDateInputEl.value;
  const endDate = endDateInputEl.value;

  // Check if the dates are invalid
  if (checkDatesInvalid(startDate, endDate)) {
    // If the dates are invalid, exit.
    return;
  }

  // Store the new period in our client-side storage.
  storeNewPeriod(startDate, endDate);

  // Refresh the UI.
  renderPastPeriods();

  // Reset the form.
  newPeriodFormEl.reset();
});
```

After preventing the form submission with `preventDefault()`, we:

1. Validate user input; exiting if invalid,
2. store the new period by retrieving, parsing, appending, sorting, stringifying, and re-storing data in localStorage,
3. render the form data along with the data of past menstrual cycles and a section header, and
4. reset the form using the HTMLFormElement `reset()` method
### Validate user input

We check if the dates are invalid. We do minimal error checking. We make sure neither date is null, which the `required` attribute should prevent from happening. We also check that the start date is not greater than the end date. If there is an error, we clear the form.

```js
function checkDatesInvalid(startDate, endDate) {
  // Check that end date is after start date and neither is null.
  if (!startDate || !endDate || startDate > endDate) {
    // To make the validation robust we could:
    // 1. add error messaging based on error type
    // 2. Alert assistive technology users about the error
    // 3. move focus to the error location
    // instead, for now, we clear the dates if either
    // or both are invalid
    newPeriodFormEl.reset();
    // as dates are invalid, we return true
    return true;
  }
  // else
  return false;
}
```

In a more robust version of this app, we would, at minimum, include error messaging informing the user there is an error. A good application would inform the user what the error is, put focus on the offending form control, and use ARIA live regions to alert assistive technology users to the error.

Local storage
-------------

We are using the Web Storage API, specifically window.localStorage, to store start and end date pairs in a stringified JSON object.

LocalStorage has several limitations, but suffices for our apps needs. We're using localStorage to make this simple and client-side only. This means the data will only be stored on one browser on a single device. Clearing the browser data will also lose all locally stored periods. What may seem like a limitation for many applications may be an asset in the case of this application, as menstrual cycle data is personal, and the user of such an app may very rightly be concerned about privacy.

For a more robust application, other client side storage options like IndexedDB (IDB) and, discussed later, service workers, have better performance.

Limitations of `localStorage` include:

* Limited data storage: `localStorage` is limited to 5MB of data per origin. Our storage needs are much less than that.
* Stores strings only: `localStorage` stores data as string key and string value pairs. Our start and end dates will be stored as a JSON object parsed as a string. For more complex data, a more robust storage mechanism like IDB would be required.
* Can cause poor performance: Getting and setting from and to local storage is done synchronously on the main thread. When the main thread is occupied, apps are not responsive and appear frozen. With the limited nature of this app, this blip of bad user experience is negligible.
* Only available to the main thread: In addition to the performance issues of occupying the main thread, service workers do not have access to the main thread, meaning the service worker can't directly set or get the local storage data.
### Retrieve, append, sort, and re-store data

Because we're using localStorage, which comprises of a single string, we retrieve the JSON string of data from local storage, parse the JSON data (if any), push the new pair of dates to the existing array, sort the dates, parse the JSON object back into a string, and save that string back to `localStorage`.

This process requires the creation of a few functions:

```js
// Add the storage key as an app-wide constant
const STORAGE\_KEY = "period-tracker";

function storeNewPeriod(startDate, endDate) {
  // Get data from storage.
  const periods = getAllStoredPeriods();

  // Add the new period objet to the end of the array of period objects.
  periods.push({ startDate, endDate });

  // Sort the array so that periods are ordered by start date, from newest
  // to oldest.
  periods.sort((a, b) => {
    return new Date(b.startDate) - new Date(a.startDate);
  });

  // Store the updated array back in the storage.
  window.localStorage.setItem(STORAGE\_KEY, JSON.stringify(periods));
}

function getAllStoredPeriods() {
  // Get the string of period data from localStorage
  const data = window.localStorage.getItem(STORAGE\_KEY);

  // If no periods were stored, default to an empty array
  // otherwise, return the stored data as parsed JSON
  const periods = data ? JSON.parse(data) : [];

  return periods;
}
```

Render data to screen
---------------------

The last step of our application is to render the list of past periods to the screen along with a heading.

In our HTML, we added a `<section id="past-periods">` placeholder to contain the heading and list of past periods.

Add the container element to the list of contents at the top of your script.

```js
const pastPeriodContainer = document.getElementById("past-periods");
```

We retrieve the parsed string of past periods, or an empty array. If empty, we exit. If past periods exist, we clear the current contents from the past period container. We create a header and an unordered list. We loop through the past periods, adding list items containing formatted from and to dates.

```js
function renderPastPeriods() {
  // get the parsed string of periods, or an empty array.
  const periods = getAllStoredPeriods();

  // exit if there are no periods
  if (periods.length === 0) {
    return;
  }

  // Clear the list of past periods, since we're going to re-render it.
  pastPeriodContainer.innerHTML = "";

  const pastPeriodHeader = document.createElement("h2");
  pastPeriodHeader.textContent = "Past periods";

  const pastPeriodList = document.createElement("ul");

  // Loop over all periods and render them.
  periods.forEach((period) => {
    const periodEl = document.createElement("li");
    periodEl.textContent = `From ${formatDate(
 period.startDate,
 )} to ${formatDate(period.endDate)}`;
    pastPeriodList.appendChild(periodEl);
  });

  pastPeriodContainer.appendChild(pastPeriodHeader);
  pastPeriodContainer.appendChild(pastPeriodList);
}

function formatDate(dateString) {
  // Convert the date string to a Date object.
  const date = new Date(dateString);

  // Format the date into a locale-specific string.
  // include your locale for better user experience
  return date.toLocaleDateString("en-US", { timeZone: "UTC" });
}
```

### Render past periods on load

When the deferred JavaScript runs on page load, we render past periods, if any.

```js
// Start the app by rendering the past periods.
renderPastPeriods();
```

Complete JavaScript
-------------------

Your `app.js` file should look similar to this JavaScript:

```js
const newPeriodFormEl = document.getElementsByTagName("form")[0];
const startDateInputEl = document.getElementById("start-date");
const endDateInputEl = document.getElementById("end-date");
const pastPeriodContainer = document.getElementById("past-periods");

// Add the storage key as an app-wide constant
const STORAGE\_KEY = "period-tracker";

// Listen to form submissions.
newPeriodFormEl.addEventListener("submit", (event) => {
  event.preventDefault();
  const startDate = startDateInputEl.value;
  const endDate = endDateInputEl.value;
  if (checkDatesInvalid(startDate, endDate)) {
    return;
  }
  storeNewPeriod(startDate, endDate);
  renderPastPeriods();
  newPeriodFormEl.reset();
});

function checkDatesInvalid(startDate, endDate) {
  if (!startDate || !endDate || startDate > endDate) {
    newPeriodFormEl.reset();
    return true;
  }
  return false;
}

function storeNewPeriod(startDate, endDate) {
  const periods = getAllStoredPeriods();
  periods.push({ startDate, endDate });
  periods.sort((a, b) => {
    return new Date(b.startDate) - new Date(a.startDate);
  });
  window.localStorage.setItem(STORAGE\_KEY, JSON.stringify(periods));
}

function getAllStoredPeriods() {
  const data = window.localStorage.getItem(STORAGE\_KEY);
  const periods = data ? JSON.parse(data) : [];
  console.dir(periods);
  console.log(periods);
  return periods;
}

function renderPastPeriods() {
  const pastPeriodHeader = document.createElement("h2");
  const pastPeriodList = document.createElement("ul");
  const periods = getAllStoredPeriods();
  if (periods.length === 0) {
    return;
  }
  pastPeriodContainer.innerHTML = "";
  pastPeriodHeader.textContent = "Past periods";
  periods.forEach((period) => {
    const periodEl = document.createElement("li");
    periodEl.textContent = `From ${formatDate(
 period.startDate,
 )} to ${formatDate(period.endDate)}`;
    pastPeriodList.appendChild(periodEl);
  });

  pastPeriodContainer.appendChild(pastPeriodHeader);
  pastPeriodContainer.appendChild(pastPeriodList);
}

function formatDate(dateString) {
  const date = new Date(dateString);
  return date.toLocaleDateString("en-US", { timeZone: "UTC" });
}

renderPastPeriods();
```

You can try the fully functioning CycleTracker period tracking web app and view the web app source code on GitHub. Yes, it works, but it's not a yet PWA.

Up next
-------

At its core, a PWA is a web application that can be installed is progressively enhanced to work offline. Now that we have a fully functional web application, we add the features required to convert it to a PWA, including the manifest file, secure connection, and service worker.

Up first, we create the CycleTracker's manifest file, including the identity, appearance, and iconography for our CycleTracker PWA.

* Previous
* Overview: CycleTracker
* Next


CycleTracker: Service workers - Progressive web apps

CycleTracker: Service workers
=============================

* Previous
* Overview: CycleTracker

Thus far, we've written the HTML, CSS, and JavaScript for CycleTracker. We added a manifest file defining colors, icons, URL, and other app features. We have a working web app! But it isn't yet a PWA. In this section, we will write the JavaScript required to convert our fully functional web application into a PWA that can be distributed as a standalone app and works seamlessly offline.

If you haven't already done so, copy the HTML, CSS, JavaScript, and manifest JSON file. Save them to files called `index.html`, `style.css`, `app.js`, and `cycletracker.json`, respectively.

In this section, we are creating `sw.js`, the service worker script, that will convert our Web App into a PWA. We already have one JavaScript file; the last line in the HTML file calls the `app.js`. This JavaScript provides all the functionality for the standard web application features. Instead of calling the `sw.js` file like we did the `app.js` file with the `src` attribute of `<script>`, we will create a relationship between the web app and its service worker by registering the service worker.

At the end of this lesson, you will have a fully functional PWA; a progressively enhanced web application that is fully installable that works even when the user is offline.

Service worker responsibilities
-------------------------------

The service worker is what makes the application work offline while making sure the application is always up to date. To do this well, the service worker should include the following:

* Version number (or other identifier).
* List of resources to cache.
* Cache version name.

The service worker is also responsible for:

* Installing the cache when the app is installed.
* Updating itself and the other application file as needed.
* Removing cached files that are no longer used.

We achieve these tasks by reacting to three service worker events, including the

* `fetch`,
* `install`, and
* `activate` events.
### Version number

Once the PWA is installed on the user's machine, the only way to inform the browser that there are updated files to be retrieved is for there to be a change in the service worker. If a change is made to any other PWA resource — if the HTML is updated, a bug is fixed in the CSS, a function is added to `app.js`, an image is compressed to reduce the file save, etc. — the service worker of your installed PWA will not know it needs to download updated resources. Only when the service worker is altered in any way, will the PWA know it may be time to update the cache; which is the service worker's task to initiate.

While changing any character may technically suffice, a PWA best practice is to create a version number constant that gets updated sequentially to indicate an update to the file. Updating a version number (or date), provides an official edit to the service worker even if nothing else is changed in the service worker itself and provides developers with a way of identifying app versions.

#### Task

Start a JavaScript file by including a version number:

```js
const VERSION = "v1";
```

Save the file as `sw.js`

### Offline resource list

For a good offline experience, the list of cached files should include all the resources used within the PWA's offline experience. While the manifest file may have a multitude of icons listed in various sizes, the application cache only needs to include the assets used by the app in offline mode.

```js
const APP\_STATIC\_RESOURCES = [
  "/",
  "/index.html",
  "/style.css",
  "/app.js",
  "/icon-512x512.png",
];
```

You don't need to include the various icons that are used by all the different operating systems and devices in the list. But do include any images that are used within the app, including assets to used within any splash pages that may be visible if the app is slow as the app loads or used in any "you need to connect to the internet for the full experience" type pages.

Do not include the service worker file in the list of resources to be cached.

#### Task

Add the list of resources to be cached for the CycleTracker PWA to `sw.js`.

#### Example solution

We include the static resources created in other sections of this tutorial that CycleTracker needs to function when offline. Our current `sw.js` file is:

```js
const VERSION = "v1";

const APP\_STATIC\_RESOURCES = [
  "/",
  "/index.html",
  "/style.css",
  "/app.js",
  "/cycletrack.json",
  "/icons/wheel.svg",
];
```

We included the `wheel.svg` icon, even though our current application doesn't use it, in case you are enhancing the PWA UI, such as displaying the logo when there is no period data.

### Application cache name

We have a version number and we have the files that need to be cached. Before caching the files, we need to create a name of the cache that will be used to store the app's static resources. This cache name should be versioned to ensure that when the app is updated, a new cache will be created and the old one will be deleted.

#### Task

Use the `VERSION` number to create a versioned `CACHE_NAME`, adding it as a constant to `sw.js`.

#### Example solution

We name our cache `period-tracker-` with the current `VERSION` appended. As the constant declaration is on a single line, we put it before the array of resources constant for better legibility.

```js
const VERSION = "v1";
const CACHE\_NAME = `period-tracker-${VERSION}`;

const APP\_STATIC\_RESOURCES = [ ... ];
```

We have successfully declared our constants; a unique identifier, the list of offline resources as an array, and the application's cache name that changes every time the identifier is updated. Now let's focus on installing, updating, and deleting unused cached resources.

### Saving the cache on PWA installation

When a user installs a PWA or simply visits a website with a service worker, an `install` event is fired in the service worker scope. We want to listen for this event, filling the cache with the PWA's static resources upon installation. Every time the service worker version is updated, the browser installs the new service worker and the install event occurs.

The `install` event happens when the app is used for the first time, or when a new version of the service worker is detected by the browser. When an older service worker is being replaced by a new one, the old service worker is used as the PWA's service worker until the new service work is activated.

Only available in secure contexts, the `caches` global property returns a `CacheStorage` object associated with the current context. The `CacheStorage.open()` method returns a `Promise` that resolves to the `Cache` object matching name of the cache, passed as a parameter.

The `Cache.addAll()` method takes an array of URLs as a parameter, retrieves them, then adds the responses to the given cache. The `waitUntil()` method tells the browser that work is ongoing until the promise settles, and it shouldn't terminate the service worker if it wants that work to complete. While browsers are responsible for executing and terminating service workers when necessary, the `waitUntil` method is a request to the browser to not terminate the service worker while a task is being executed.

```js
self.addEventListener("install", (e) => {
  e.waitUntil((async () => {
      const cache = await caches.open("cacheName\_identifier");
      cache.addAll([
        "/",
        "/index.html"
        "/style.css"
        "/app.js"
      ]);
    })()
  );
});
```

#### Task

Add an install event listener that retrieves and stores the files listed in `APP_STATIC_RESOURCES` into the cache named `CACHE_NAME`.

#### Example solution

```js
self.addEventListener("install", (event) => {
  event.waitUntil(
    (async () => {
      const cache = await caches.open(CACHE\_NAME);
      cache.addAll(APP\_STATIC\_RESOURCES);
    })(),
  );
});
```

### Updating the PWA and deleting old caches

As mentioned, when an existing service worker is being replaced by a new one, the existing service worker is used as the PWA's service worker until the new service worker is activated. We use the `activate` event to delete old caches to avoid running out of space. We iterate over named `Cache` objects, deleting all but the current one, and then set the service worker as the `controller` for the PWA.

We listen for the current service worker's global scope `activate` event.

We get the names of the existing named caches. We use the `CacheStorage.keys()` method (again accessing `CacheStorage` through the global `caches` property) which returns a `Promise` that resolves with an array containing strings corresponding to all of the named `Cache` objects in the order they were created.

We use the `Promise.all()` method to iterate through that list of name cache promises. The `all()` method takes as input a list of iterable promises and returns a single `Promise`. For each name in the list of named caches, check if the cache is the currently active cache. If not, delete it with the `Cache` `delete()` method.

The last line, the `await clients.claim()` uses the `claim()` method of the `Clients` interface to enable our service worker to set itself as the controller for our client; the "client" referring to a running instance of the PWA. The `claim()` method enables the service worker to "claim control" of all clients within its scope. This way, clients loaded in the same scope don't need to be reloaded.

```js
self.addEventListener("activate", (event) => {
  event.waitUntil(
    (async () => {
      const names = await caches.keys();
      await Promise.all(
        names.map((name) => {
          if (name !== CACHE\_NAME) {
            return caches.delete(name);
          }
        }),
      );
      await clients.claim();
    })(),
  );
});
```

#### Task

Add the above `activate` eventListener to your `sw.js` file.

### The fetch event

We can take advantage of the `fetch` event, to prevent an installed PWA from making requests if the user is online. Listening to the fetch event makes it possible to intercept all requests and respond with cached responses instead of going to the network. Most applications don't require this behavior. In fact, many business models want users to regularly make server requests for tracking and marketing purposes. So, while intercepting requests may be an anti-pattern for some, to improve the privacy of our CycleTracker app, we don't want the app to make unnecessary server requests.

As our PWA consists of a single page, for page navigation requests, we go back to the `index.html` home page. There are no other pages and we don't ever want to go to the server. If the Fetch API's `Request` readonly `mode` property is `navigate`, meaning it's looking for a web page, we use the FetchEvent's `respondWith()` method to prevent the browser's default fetch handling, providing our own response promise employing the `caches.match()` method.

For all other request modes, we open the caches as done in the install event response, instead passing the event request to the same `match()` method. It checks if the request is a key for a stored `Response`. If yes, it returns the cached response. If not, we return a 404 status as a response.

Using the `Response()` constructor to pass a `null` body and a `status: 404` as options, doesn't mean there is an error in our PWA. Rather, everything we need should already be in the cache, and if it isn't, we're not going to the server to resolve this non-issue.

```js
self.addEventListener("fetch", (event) => {
  // when seeking an HTML page
  if (event.request.mode === "navigate") {
    // Return to the index.html page
    event.respondWith(caches.match("/"));
    return;
  }

  // For every other request type
  event.respondWith(
    (async () => {
      const cache = await caches.open(CACHE\_NAME);
      const cachedResponse = await cache.match(event.request.url);
      if (cachedResponse) {
        // Return the cached response if it's available.
        return cachedResponse;
      }
      // Respond with a HTTP 404 response status.
      return new Response(null, { status: 404 });
    })(),
  );
});
```

Complete service worker file
----------------------------

Your `sw.js` file should look similar to the following JavaScript. Note that when updating any of the resources listed in the `APP_STATIC_RESOURCES` array, the only constant or function that must be updated within this service worker is the value of `VERSION`.

```js
// The version of the cache.
const VERSION = "v1";

// The name of the cache
const CACHE\_NAME = `period-tracker-${VERSION}`;

// The static resources that the app needs to function.
const APP\_STATIC\_RESOURCES = [
  "/",
  "/index.html",
  "/app.js",
  "/style.css",
  "/icons/wheel.svg",
];

// On install, cache the static resources
self.addEventListener("install", (event) => {
  event.waitUntil(
    (async () => {
      const cache = await caches.open(CACHE\_NAME);
      cache.addAll(APP\_STATIC\_RESOURCES);
    })(),
  );
});

// delete old caches on activate
self.addEventListener("activate", (event) => {
  event.waitUntil(
    (async () => {
      const names = await caches.keys();
      await Promise.all(
        names.map((name) => {
          if (name !== CACHE\_NAME) {
            return caches.delete(name);
          }
        }),
      );
      await clients.claim();
    })(),
  );
});

// On fetch, intercept server requests
// and respond with cached responses instead of going to network
self.addEventListener("fetch", (event) => {
  // As a single page app, direct app to always go to cached home page.
  if (event.request.mode === "navigate") {
    event.respondWith(caches.match("/"));
    return;
  }

  // For all other requests, go to the cache first, and then the network.
  event.respondWith(
    (async () => {
      const cache = await caches.open(CACHE\_NAME);
      const cachedResponse = await cache.match(event.request.url);
      if (cachedResponse) {
        // Return the cached response if it's available.
        return cachedResponse;
      }
      // If resource isn't in the cache, return a 404.
      return new Response(null, { status: 404 });
    })(),
  );
});
```

When updating a service worker, the VERSION constant doesn't need to be updated, as any change in the content of the service worker script itself will trigger the browser to install the new service worker. However, it is a good practice to update the version number as it makes it easier for devs, including yourself, to see which version of the service worker is currently running in the browser, by checking the name of the Cache in the Application tool (or Sources tool).

**Note:** Updating VERSION is important when making changes to any application resource, including the CSS, HTML, and JS code, and image assets. The version number, or any change to the service worker file, is the only way to force an update of the app for your users.

Register the service worker
---------------------------

Now that our service worker script is complete, we need to register the service worker.

We start by checking that the browser supports the Service Worker API by using feature detection for the presence of the `serviceWorker` property on the global `navigator` object:

```html
<script>
 // Does "serviceWorker" exist
 if ("serviceWorker" in navigator) {
 // If yes, we register the service worker
 }
</script>
```

If the property is supported, we can then use the `register()` method of the service worker API's `ServiceWorkerContainer` interface.

```html
<script>
 if ("serviceWorker" in navigator) {
 // Register the app's service worker
 // Passing the filename where that worker is defined.
 navigator.serviceWorker.register("sw.js");
 }
</script>
```

While the above suffices for the CycleTracker app needs, the `register()` method does return a `Promise` that resolves with a `ServiceWorkerRegistration` object. For a more robust application, error check the registration:

```js
if ("serviceWorker" in navigator) {
  navigator.serviceWorker.register("sw.js").then(
    (registration) => {
      console.log("Service worker registration successful:", registration);
    },
    (error) => {
      console.error(`Service worker registration failed: ${error}`);
    },
  );
} else {
  console.error("Service workers are not supported.");
}
```

### Task

Open `index.html` and add the following `<script>` after the script to include `app.js` and before the closing `</body>` tag.

```html
<!-- Register the app's service worker. -->
<script>
 if ("serviceWorker" in navigator) {
 navigator.serviceWorker.register("sw.js");
 }
</script>
```

You can try the fully functioning CycleTracker period tracking web app and view the web app source code on GitHub. Yes, it works, and it is now, officially, a PWA!

Debugging service workers
-------------------------

Because of the way we have set up the service worker, once it is registered, every request will pull from the cache instead of loading new content. When developing, you will be editing your code frequently. You likely want to test your edits in the browser regularly; likely with every save.

### By updating the version number and doing a hard reset

To get a new cache, you can change the version number and then do a hard browser refresh. The way you do a hard refresh depends on the browser and operating system:

* On Windows: Ctrl+F5, Shift+F5, or Ctrl+Shift+R.
* On MacOS: Shift+Command+R.
* Safari on MacOS: Option+Command+E to empty the cache, then Option+Command+R.
* On Mobile: Go to the browser (Android) or operating system (Samsung, iOS) settings, under advanced setting find the browser (iOS) or website data (Android, Samsung) site settings, and delete the data for CycleTracker, before reloading the page.
### With developer tools

You likely don't want to update the version number with every save. Until you are ready to launch a new version of your PWA to production and give everyone a new version of your PWA, instead of changing the version number on save, you can unregister the service worker.

You can unregister a service worker by clicking on the `unregister` button in the browser developer tools. Hard refreshing the page will re-register the service worker and create a new cache.

![Firefox developer tools application panel with a stopped service worker and an unregister button](/en-US/docs/Web/Progressive_web_apps/Tutorials/CycleTracker/Service_workers/firefox_sw.jpg)

In some developer tools, you can manually unregister a service worker, or you can select the service workers "update on reload" option which sets the developer tools to reset and re-activate the service worker on every reload as long as the developer tools are open. There is also an option to bypass the service worker and load resources from the network. This panel includes features we are not covering in this tutorial, but will be helpful as you create more advanced PWAs that include syncing and push, which are both covered in the offline and background operation guide.

![Edge developer tools showing the application panel set to a service worker](/en-US/docs/Web/Progressive_web_apps/Tutorials/CycleTracker/Service_workers/edge_sw.jpg)

The service worker window within the DevTools' application panel, provides a link to access to pop up window containing a list of all the registered service workers for the browser; not just the service worker for the application opened in the current tab. Each service worker list of workers has buttons to stop, start, or unregister that individual service worker.

![Two service workers exist at localhost:8080. The can be unregistered from the list of service workers](/en-US/docs/Web/Progressive_web_apps/Tutorials/CycleTracker/Service_workers/edge_sw_list.jpg)

In other words, as you are working on your PWA, you don't have to update the version number for every app view. But remember, when you are done with all your changes, update the service worker VERSION value before distributing the updated version of your PWA. If you forget, no one who has already installed your app or even visited your online PWA without installing it will ever get to see your changes!

We're done!
-----------

At its core, a PWA is a web application that can be installed and that is progressively enhanced to work offline. We created a fully functional web application. We then added the two features - a manifest file and a service worker - required to convert it to a PWA. If you want to share your app with others, make it available via a secure connection. Alternatively, if you just want to use the cycle tracker yourself, create a local development environment, install the PWA, and enjoy! Once installed, you no longer need to run localhost.

Congratulations!

* Previous
* Overview: CycleTracker


CycleTracker: Secure connection - Progressive web apps

CycleTracker: Secure connection
===============================

* Previous
* Overview: CycleTracker
* Next

Service workers, and therefore PWAs, are restricted to secure contexts. Secure contexts include TLS contexts served with the `https://` protocol and locally-delivered resources, including `127.0.0.1` and `localhost` URLs served with the `http://` protocol. In this section, we will discuss ways of serving the application locally and remotely with a secure connection.

In the previous section, we used HTML and CSS to create the shell of our period tracking application. In this section, we'll open the CycleTracker static content in a browser, view the content from a locally started development environment, and view the content on a remote, secure server.

Viewing with the `file://` protocol
-----------------------------------

Any browser will render your HTML. To view the HTML file with the CSS applied you created in the previous section, open the `index.html` file by navigating to it via your computer's file structure or from your browser using the "Open File" menu option.

With the `index.html` updated, and the `style.css` housed in the same directory, viewing the page in a narrow browser window should look similar to this screenshot:

![Light green web page with a large header, a form with a legend, two date pickers and a button. The bottom shows two placeholder menstrual cycles and a header.](/en-US/docs/Web/Progressive_web_apps/Tutorials/CycleTracker/Secure_connection/filefile.jpg)

We are viewing our page using the `file://` protocol. This works for the current state of our codebase, and will continue to suffice as we add JavaScript functionality. However, manifest files and service workers, both PWA requirements, require a secure connection, as do several other APIs. PWAs need to be served from a web server over `https` or a local development environment, using `localhost`, `127.0.0.1`, with or without a port number. If we view our finished app using the `file://` protocol, our manifest file will be ignored and any service workers we add will fail.

**Note:** Serving your app over `https` isn't only good for PWAs, but for all websites as it ensures the information that transits between your web server and the user's browser is encrypted end to end. Several Web APIs require secure contexts. Even if you aren't creating installable PWAs, as you add features to any web app, you may run into cases where a secure context is required.

We need a local development environment to work through the tutorial. Part of making a PWA installable is a secure server. The files will need to be served over a secure connection on the web to access the benefits PWAs provide and to distribute our application as a PWA.

localhost
---------

The default method for setting up a local development environment varies by operating system. While the default location for the index and configuration files on your operating system may differ, most desktop operating systems enable a server configuration accessible to you, the developer.

For example, on macOS, at least on Sierra and Monterey, entering `sudo apachectl start` enables an Apache HTTP server. Once the server is started, entering `http://localhost` in the browser displays an basic web page that reads "It works!". By default, the HTML file displayed is `Library/WebServer/Documents/index.html.en`. To enable file extensions other than `.html.en` or to change the root directory away from `Library/WebServer/Documents/`, you have to edit the apache http configuration file, located at `/etc/apache2/httpd.conf`. The server can be stopped with `sudo apachectl stop`.

The OS's default `localhost` has an easy-to-remember URL, but a difficult to remember server root location and configuration process. It also only allows for one local server in one location at a time. Fortunately, there are more intuitive server set up method options to create one or more local development environments on multiple ports.

localhost with a port number
----------------------------

There are several IDE extensions and programming-language specific packages that enable starting a development environment with a single click or terminal command. You can even start multiple local servers, each with a different port number.

You can run a local HTTP server using a VSCode plugin, which enables running a local server on a single or different port. The Preview on Web Server extension for the VSCode IDE creates a server at the root of the directory currently opened by the editor, with a default port of `8080`. VS Code extensions are configurable. The `previewServer.port` setting is the port number of the web server. The extensions default setting of `8080` can be edited and changed. By default, entering `localhost:8080` in the browser URL bar will load the page.

**Note:** that the Preview on Web Server extension uses Browsersync. When your development environment is started by this extension, `localhost:3001` provides a user interface for Browsersync, providing an overview of the current server environment.

Learn how to set up a local testing server using Python or local server side language like PHP.

Localhost with npx
------------------

If you have node installed, you may have npm and npx installed as well. At the command line, enter `npx -v`. If a version number is returned, you can use http-server, a non-configurable static HTTP server, without needing to install any requirements. Enter `npx http-server [path]` at the command line, where `[path]` is the folder where your index file is stored.

By default, entering `localhost:8080` in the browser URL bar will load the page. If you already started a server at port `8080`, it will automatically change the port number, starting the developer environment using an available port, such at `8081`.

You can choose a different port number. Entering `npx http-server /user/yourName/CycleTracker -p 8787` will start local server at port `8787` if available. If not, if you enter a port number that is already being used, you will get an `address already in use` or similar error. If successful, entering `localhost:8787` in the browser URL bar will render the index file stored as `~/user/yourName/CycleTracker/index.html`, or will display the directory contents of `~/user/yourName/CycleTracker/` if no index file is present.

This non-configurable static HTTP server suffices for our basic app. Apps served via `localhost` and `127.0.0.1` are exempt from https and always considered secure. Browser insecure warnings, if given, can be bypassed. While not necessary, to configurable your local web server to be served over HTTPS, you can add a built-in TLS certificate. With the certificate, you will be able to install and run local-web-server from the command line to serve your project locally over `https`, preventing any security warning.

```bash
npm install -g local-web-server
cd ~/user/yourName/CycleTracker/
ws --https
```

In the above, you may need to prefix the install with `sudo`.

**Note:** If you are seeking privacy, realize you are building this PWA yourself and it can be installed on your own machine from your own development environment, without ever accessing the Internet. This app has no tracking. It's as private an app as you get.

Secure external server
----------------------

The previous options are fine, and necessary, for testing your application as you progress through this PWA tutorial, or any web development project. While you can host your web app on your device and make it available to anyone with an Internet connection, this is not recommended.

To get the added features of PWAs, including single click installation, a standalone UI, and admission to app stores, it needs to be a PWA, which means it needs a service worker, which means we will need a secure connection. To distribute your app, enabling others to view, use, and install your PWA, you'll want to have your content hosted and available on a secure *remote* server.

When officially publishing a PWA, you will likely want to invest in a domain name and web hosting. For open source projects, where developers can learn from the codebase and even contribute back to the project, you can host your progress on GitHub Pages.

GitHub Pages
------------

The current state of the CycleTracker application is viewable on GitHub, served securely at https://mdn.github.io/pwa-examples/cycletracker/html\_and\_css. We've posted the files to the MDN GitHub account. Similarly, if you have a GitHub account, you can post it to yours. Just note that while securely served over TLS, actions on GitHub are not necessarily private, and all GitHub pages are public. If you live in an area with a repressive government that tracks menstrual cycles, consider copying and pasting the code rather than forking it.

To create a publicly available secure site, create a GitHub Pages site. Create a repository named `<username>.github.io`, where `<username>` is your GitHub username. Create a `gh-pages` branch. This branch of your application will be available at `https://<username>.github.io`.

As noted, all GitHub Pages are publicly available on the internet, even if you set the repository to private. As the period data is saved using localStorage, the application will be available via the GitHub URL, but the user's data is only available in the one browser on the one device where the data was entered. Deleting the localStorage directly, which is done in the browser, will delete all the stored data.

If you don't want your PWA to be top level, you can make your app appear as if it is residing in a subdirectory. You can either create a subdirectory within the `<username>.github.io` repository, or publish from your PWA's separate repository. By configuring a publishing source within your PWA repository, your app will be visible at `https://<username>.github.io/<repository>` where `<repository>` is the repository's name. You can set GitHub to auto-publish your site when changes are published to a specific branch within that repository, including `main`.

In the case of the CycleTracker demo app in the various stages of development, the `<username>` is `mdn` and the repository is `pwa-examples`. Because this repository has multiple example PWAs, each with progress at several steps in the development process, the files, and therefore the PWA, are nested a few levels deep.

Note that you can configure a custom domain for a GitHub Pages site.

Up next
-------

We are able to view a styled, static version of the CycleTracker application shell. Now that we know how to view the application we are about to build, let's get to building it. Up next, we create `app.js`, the JavaScript that converts our static design into a fully functional web application that stores data locally, on the users machine.

* Previous
* Overview: CycleTracker
* Next


CycleTracker: Base HTML and CSS - Progressive web apps

CycleTracker: Base HTML and CSS
===============================

* Previous
* Overview: CycleTracker
* Next

To build a PWA, a progressive web application, we need to create a fully-functioning web application. In this section, we will markup the HTML for a static web page and enhance the appearance with CSS.

 Our project is to create CycleTracker, a menstrual cycle tracker.
 The first step in this introductory PWA tutorial is to write the HTML and CSS. The top section of the page is a form for the user to enter the start and end dates of each period. The bottom is a list of previous menstrual cycles.

We create an HTML file, with meta data in the head and a static web page containing a form and a placeholder to display user inputted data. We'll then add an external CSS stylesheet to improve the site's appearance.

To complete this tutorial, it is helpful to have a basic level of understanding of HTML, CSS, and JavaScript. If you're not familiar with these, MDN is the home of Getting Started, an introduction to web development series.

In the next sections, we'll set up a local development environment and take a look at our progress before adding JavaScript functionality to convert the static content created in this section into a functional web application. Once we have a functioning app we will have something that we can progressively enhance into a PWA that is installable and works offline.

Static web content
------------------

Our static site HTML, with placeholder `<link>` and `<script>` elements for yet-to-be-created external CSS and JavaScript files, is:

```html
<!doctype html>
<html lang="en-US">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>Cycle Tracker</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <h1>Period tracker</h1>
    <form>
      <fieldset>
        <legend>Enter your period start and end date</legend>
        <p>
          <label for="start-date">Start date</label>
          <input type="date" id="start-date" required />
        </p>
        <p>
          <label for="end-date">End date</label>
          <input type="date" id="end-date" required />
        </p>
      </fieldset>
      <p>
        <button type="submit">Add Period</button>
      </p>
    </form>
    <section id="past-periods"></section>
    <script src="app.js" defer></script>
  </body>
</html>
```

Copy this HTML and save it in a file called `index.html`.

HTML content
------------

Even if the HTML in `index.html` is familiar to you, we recommend reading through this section before adding some temporary hard-coded data, adding CSS to a `style.css` external stylesheet, and creating `app.js`, the application's JavaScript that makes this web page function.

The HTML's first line is a doctype preamble, which ensures the content behaves correctly.

```html
<!doctype html>
```

The root `<html>` tags wrap all the content with the `lang` attribute defining the primary language of the page.

```html
<!doctype html>
<html lang="en-US">
  <!-- the <head> and <body> will go here -->
</html>
```

### Document head

The `<head>` contains machine-readable information about the web application that's not visible to readers except for the `<title>`, which is displayed as the heading of the browser tab.

The `<head>` includes all the meta data. The first two bits of information in your `<head>` should always be the character set definition, which defines the character encoding, and the viewport `<meta>` tag, which ensures the page renders at the width of the viewport and isn't shrunken down when loaded on very small screens.

```html
<head>
  <meta charset="utf-8" />
  <meta name="viewport" content="width=device-width" />
</head>
```

We set the title of the page to "Cycle Tracker" with the `<title>` element. While the contents of the `<head>` are not displayed within the page, the contents of the `<title>` are seen! The `<title>` element's inner text appears in the browser tab when the page is loaded, in search engine results, and is the default title used when a user bookmarks a web page. The title also provides an accessible name for screen reader users who depend on it to know which tab they're currently on.

While the title could be "Menstrual cycle tracking application", we opted for a shortened name that is more discreet.

```html
<title>Cycle Tracker</title>
```

While officially optional, for better user experience, these two `<meta>` tags and the `<title>` are the three components of the `<head>` that should be considered required components of any HTML document.

For right now, the last component we include in the `<head>` is a `<link>` element linking `style.css`, our yet-to-be-written stylesheet, to our HTML.

```html
<link rel="stylesheet" href="style.css" />
```

The HTML `<link>` element is used to specify a relationship between the current document and an external resource. There are more than 25 defined values for the `rel` attribute—and many more values that are not in any specification. The most common value, `rel="stylesheet"`, imports an external resource as a stylesheet.

We will revisit the `<link>` element and its `rel` attribute in a future section when we include the link to the manifest file.

### Document body

The `<body>` element contains all the content we want displayed when users visit the site on the Internet.

Within the `<body>`, we include the name of the app as a level-1 heading using an `<h1>` and a `<form>`.

```html
<body>
  <h1>Period tracker</h1>
  <form></form>
</body>
```

The form will contain instructions, form controls, a label for each form control, and a submit button. In terms of form controls, we need the user to enter both a start date and an end date for each menstrual cycle submitted.

Within the `<form>`, we include a `<fieldset>` with a `<legend>` labeling the purpose of that set of form fields.

```html
<form>
  <fieldset>
    <legend>Enter your period start and end date</legend>
  </fieldset>
</form>
```

The date pickers are `<input>` elements of type date. We include the `required` attribute to reduce user errors by preventing the user from accidentally submitting an incomplete form.

To associate a `<label>` with a form control, each `<input>` has an `id` attribute matching the `for` attribute of the associated `<label>`. The associated label provides each `<input>` with an accessible name.

```html
<label for="start-date">Start date</label>
<input type="date" id="start-date" required />
```

Putting it altogether, within the `<fieldset>`, we include two paragraphs (`<p>` elements), each with a date picker for the start and end dates of the menstrual cycle currently being entered, along with the date pickers' associated `<label>`s. We also include a `<button>` element which submits the form; we label it "Add period" by including that text between the opening and closing tags. The `type="submit"` is optional, as `submit` is the default type for `<button>`.

```html
<form>
  <fieldset>
    <legend>Enter your period start and end date</legend>
    <p>
      <label for="start-date">Start date</label>
      <input type="date" id="start-date" required />
    </p>
    <p>
      <label for="end-date">End date</label>
      <input type="date" id="end-date" required />
    </p>
  </fieldset>
  <p>
    <button type="submit">Add Period</button>
  </p>
</form>
```

We encourage you to learn more about making accessible web forms.

### Temporary hard-coded results text

We then include an empty `<section>`. This container will be populated using JavaScript.

```html
<section id="past-periods"></section>
```

When the user submits the form, we will use JavaScript to capture the data and present a list of past periods along with a header for the section.

For the time being, we temporarily hardcode some content within this `<section>`, including an `<h2>` header and a few past periods, to have something to style as we write the page's CSS.

```html
<section id="past-periods">
  <h2>Past periods</h2>
  <ul>
    <li>From 01/01/2024 to 01/06/2024</li>
    <li>From 01/29/2024 to 02/04/2024</li>
  </ul>
</section>
```

This content, other than the container `<section id="past-periods"></section>`, is temporary. We will remove or comment-out this temporary data once we complete the CSS and are satisfied with the app's appearance.

### JavaScript link

Before closing the `</body>`, we include a link to the yet-to-be-written `app.js` JavaScript file. We include the `defer` attribute to defer the loading of this script and ensure the JavaScript is executed after the document's HTML has been parsed.

```html
<script src="app.js" defer></script>
```

The `app.js` file will include all the workings of our application, including the event handlers for the `<button>`, saving the data submitted to local storage, and displaying cycles within the content of the body.

The HTML file for this step is now complete! You can open the file in your browser at this point, but you'll notice that it's quite plain. We'll fix that in the next section.

CSS content
-----------

We can now style the static HTML using CSS. Our final CSS is:

```css
body {
  margin: 1vh 1vw;
  background-color: #efe;
}
ul,
fieldset,
legend {
  border: 1px solid;
  background-color: #fff;
}
ul {
  padding: 0;
  font-family: monospace;
}
li,
legend {
  list-style-type: none;
  padding: 0.2em 0.5em;
  background-color: #cfc;
}
li:nth-of-type(even) {
  background-color: inherit;
}
```

If every line is familiar to you, you can copy the above CSS, or write your own CSS, and save the file as `style.css`, then finish up the static HTML and CSS. If anything in the above CSS is new to you, keep reading for an explanation.

![Light green web page with a large header, a form with a legend, two date pickers and a button. The bottom shows fake data for two menstrual cycles and a header.](/en-US/docs/Web/Progressive_web_apps/Tutorials/CycleTracker/HTML_and_CSS/html.jpg)

### CSS explained

We use the `background-color` property to set a light green (`#efe`) background color on the `body`. Then on the unordered list, fieldset, and legend, we use a white (`#fff`) background color, along with a thin solid border added with the `border` property. We override the `background-color` for the legend, making the legend and the list items a darker green (`#cfc`).

We use the `:nth-of-type(even)` pseudo-class selector to set every even-numbered list item to `inherit` the background color from its parent; in this case, inheriting the `#fff` background color from the unordered list.

```css
body {
  background-color: #efe;
}
ul,
fieldset,
legend {
  border: 1px solid;
  background-color: #fff;
}
li,
legend {
  background-color: #cfc;
}
li:nth-of-type(even) {
  background-color: inherit;
}
```

To make the unordered list and list items not look like a list, we remove the padding by setting `padding: 0` on the `ul` and remove the list markers by setting `list-style-type: none` on the list items themselves.

```css
ul {
  padding: 0;
}
li {
  list-style-type: none;
}
```

We add a little white space by setting the `body`'s `margin` using the `vw` and `vh` viewport units, making white space on the outside of our app be proportional to the viewport's size. We also add a little padding to the `li` and `legend`. Finally, to improve, but not fix, the alignment of the past-periods data, we set the `font-family` of the `ul` results section to be `monospace`, making each glyph have the same fixed width.

```css
body {
  margin: 1vh 1vw;
}
ul {
  font-family: monospace;
}
li,
legend {
  padding: 0.2em 0.5em;
}
```

We can combine the above, putting multiple properties in each selector declaration block. We can even put the styles for the `li` and `legend` together; irrelevant styles, like the `list-style-type` declaration on `legend`, are ignored.

```css
body {
  margin: 1vh 1vw;
  background-color: #efe;
}
ul,
fieldset,
legend {
  border: 1px solid;
  background-color: #fff;
}
ul {
  padding: 0;
  font-family: monospace;
}
li,
legend {
  list-style-type: none;
  padding: 0.2em 0.5em;
  background-color: #cfc;
}
li:nth-of-type(even) {
  background-color: inherit;
}
```

If any of the above CSS still looks unfamiliar to you, you can look up the CSS properties and selectors, or work through the getting started with CSS learning path.

Whether you use the above CSS verbatim, edit the above styles to your preference, or write your own CSS from scratch, include all the CSS in a new file and save it as `style.css` in the same directory as your `index.html` file.

### Finishing the static HTML and CSS for our PWA

Before moving on, comment out or delete the fake past period data and header:

```html
<section id="past-periods">
  <!--
 <h2>Past periods</h2>
 <ul>
 <li>From 01/01/2024 to 01/06/2024</li>
 <li>From 01/29/2024 to 02/04/2024</li>
 </ul>
 -->
</section>
```

Up next
-------

Before adding the JavaScript functionality to convert this static content into a web app and then enhancing it into a progressive web app with a manifest file and service worker, we'll create a local development environment to view our progress.

Until then, you can view the static CycleTracker shell and download the CycleTracker HTML and CSS source code from GitHub.

* Previous
* Overview: CycleTracker
* Next


Creating and triggering events - Event reference

Creating and triggering events
==============================

This article demonstrates how to create and dispatch DOM events. Such events are commonly called **synthetic events**, as opposed to the events fired by the browser itself.

Creating custom events
----------------------

Events can be created with the `Event` constructor as follows:

```js
const event = new Event("build");

// Listen for the event.
elem.addEventListener(
  "build",
  (e) => {
    /\* … \*/
  },
  false,
);

// Dispatch the event.
elem.dispatchEvent(event);
```

The above code example uses the EventTarget.dispatchEvent() method.

This constructor is supported in most modern browsers. For a more verbose approach, see the old-fashioned way below.

### Adding custom data – CustomEvent()

 To add more data to the event object, the CustomEvent interface exists and the **detail** property can be used to pass custom data.
 For example, the event could be created as follows:

```js
const event = new CustomEvent("build", { detail: elem.dataset.time });
```

This will then allow you to access the additional data in the event listener:

```js
function eventHandler(e) {
  console.log(`The time is: ${e.detail}`);
}
```

### The old-fashioned way

The older approach to creating events uses APIs inspired by Java. The following shows an example with `document.createEvent()`:

```js
// Create the event.
const event = document.createEvent("Event");

// Define that the event name is 'build'.
event.initEvent("build", true, true);

// Listen for the event.
elem.addEventListener(
  "build",
  (e) => {
    // e.target matches elem
  },
  false,
);

// target can be any Element or other EventTarget.
elem.dispatchEvent(event);
```

### Event bubbling

It is often desirable to trigger an event from a child element, and have an ancestor catch it; optionally, with data:

```html
<form>
  <textarea></textarea>
</form>
```

```js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

// Create a new event, allow bubbling, and provide any data you want to pass to the "detail" property
const eventAwesome = new CustomEvent("awesome", {
  bubbles: true,
  detail: { text: () => textarea.value },
});

// The form element listens for the custom "awesome" event and then consoles the output of the passed text() method
form.addEventListener("awesome", (e) => console.log(e.detail.text()));

// As the user types, the textarea inside the form dispatches/triggers the event to fire, and uses itself as the starting point
textarea.addEventListener("input", (e) => e.target.dispatchEvent(eventAwesome));
```

### Creating and dispatching events dynamically

Elements can listen for events that haven't been created yet:

```html
<form>
  <textarea></textarea>
</form>
```

```js
const form = document.querySelector("form");
const textarea = document.querySelector("textarea");

form.addEventListener("awesome", (e) => console.log(e.detail.text()));

textarea.addEventListener("input", function () {
  // Create and dispatch/trigger an event on the fly
  // Note: Optionally, we've also leveraged the "function expression" (instead of the "arrow function expression") so "this" will represent the element
  this.dispatchEvent(
    new CustomEvent("awesome", {
      bubbles: true,
      detail: { text: () => textarea.value },
    }),
  );
});
```

Triggering built-in events
--------------------------

This example demonstrates simulating a click (that is programmatically generating a click event) on a checkbox using DOM methods. View the example in action.

```js
function simulateClick() {
  const event = new MouseEvent("click", {
    view: window,
    bubbles: true,
    cancelable: true,
  });
  const cb = document.getElementById("checkbox");
  const cancelled = !cb.dispatchEvent(event);

  if (cancelled) {
    // A handler called preventDefault.
    alert("cancelled");
  } else {
    // None of the handlers called preventDefault.
    alert("not cancelled");
  }
}
```

See also
--------

* CustomEvent()
* `document.createEvent()`
* `Event.initEvent()`
* `EventTarget.dispatchEvent()`
* `EventTarget.addEventListener()`


Event handling (overview) - Event reference

Event handling (overview)
=========================

Events are signals fired inside the browser window that notify of changes in the browser or operating system environment. Programmers can create *event handler* code that will run when an event fires, allowing web pages to respond appropriately to change.

This page provides a very brief "reminder" of how to work with events and event handlers. New developers should instead read Introduction to events.

What are the available events?
------------------------------

Events are documented in and/or below the pages for the JavaScript objects that emit them. For example, to find out events fired on the browser window or the current document see the events sections in `Window` and `Document`.

You can use the Event reference to find out what JavaScript objects fire events for particular APIs, e.g. animation, media, and so on.

Registering event handlers
--------------------------

There are two recommended approaches for registering handlers. Event handler code can be made to run when an event is triggered by assigning it to the target element's corresponding *onevent* property, or by registering the handler as a listener for the element using the `addEventListener()` method. In either case the handler will receive an object that conforms to the `Event` interface (or a derived interface). The main difference is that multiple event handlers can be added (or removed) using the event listener methods.

**Warning:** A third approach for setting event handlers using HTML onevent attributes is not recommended! They inflate the markup and make it less readable and harder to debug. For more information see Inline event handlers.

### Using onevent properties

By convention, JavaScript objects that fire events have a corresponding "onevent" properties (named by prefixing "on" to the name of the event). These properties are called to run associated handler code when the event is fired, and may also be called directly by your own code.

To set event handler code you can just assign it to the appropriate onevent property. Only one event handler can be assigned for every event in an element. If needed the handler can be replaced by assigning another function to the same property.

Below we show how to set a simple `greet()` function for the `click` event using the `onclick` property.

```js
const btn = document.querySelector("button");

function greet(event) {
  console.log("greet:", event);
}

btn.onclick = greet;
```

Note that an object representing the event is passed as the first argument to the event handler. This event object either implements or is derived from the `Event` interface.

### EventTarget.addEventListener

The most flexible way to set an event handler on an element is to use the `EventTarget.addEventListener` method. This approach allows multiple listeners to be assigned to an element, and for listeners to be *removed* if needed (using `EventTarget.removeEventListener`).

**Note:** The ability to add and remove event handlers allows you to, for example, have the same button performing different actions in different circumstances. In addition, in more complex programs cleaning up old/unused event handlers can improve efficiency.

Below we show how a simple `greet()` function can be set as a listener/event handler for the `click` event (you could use a lambda function instead of a named function if desired). Note again that the event is passed as the first argument to the event handler.

```js
const btn = document.querySelector("button");

function greet(event) {
  console.log("greet:", event);
}

btn.addEventListener("click", greet);
```

The method can also take additional arguments/options to control aspects of how the events are captured and removed. More information can be found on the `EventTarget.addEventListener` reference page.

#### Using an Abort Signal

A notable event listener feature is the ability to use an abort signal to clean up multiple event handlers at the same time.

This is done by passing the same `AbortSignal` to the `addEventListener()` call for all the event handlers that you want to be able to remove together. You can then call `abort()` on the controller owning the `AbortSignal`, and it will remove all event handlers that were added with that signal. For example, to add an event handler that we can remove with an `AbortSignal`:

```js
const controller = new AbortController();

btn.addEventListener(
  "click",
  (event) => {
    console.log("greet:", event);
  },
  { signal: controller.signal },
); // pass an AbortSignal to this handler
```

Then the event handler created by the code above can be removed like this:

```js
controller.abort(); // removes any/all event handlers associated with this controller
```


Attributes - MathML

Attributes
==========

This is an alphabetical list of MathML attributes. More details for each attribute are available on relevant MathML element pages and on the global attributes page. The values page also describes some notes on common values used by MathML attributes.

**Note:** As explained on the main MathML page, MDN uses MathML Core as a reference specification. However, legacy features that are still implemented by some browsers are also documented. You can find further details for these and other features in MathML 4.

| Name | Elements accepting attribute | Description |
| --- | --- | --- |
| `accent` | `<mo>` | A `<boolean>` indicating whether the operator should be treated as an accent when used as an under- or over-script. |
| `accent` | `<mover>`,
 `<munderover>` | A `<boolean>` indicating whether the under script should be treated as an accent. |
| `accentunder` | `<munder>`,
 `<munderover>` | A `<boolean>` indicating whether the over script should be treated as an accent. |
| `actiontype`
Deprecated
 | `<maction>` | A string value specifying the action happening for this element. |
| `align` | `<mtable>` | Specifies vertical alignment of the table with respect to its environment. |
| `background`
Deprecated
 | `<mstyle>` | Use CSS `background-color` instead. |
| `close`
Deprecated
 | `<mfenced>` | A string for the closing delimiter. |
| `color`
Deprecated
 | `<mstyle>` | Use CSS `color` instead. |
| `columnalign` | `<mtable>`,
 `<mtd>`,
 `<mtr>` | Specifies the horizontal alignment of table cells. |
| `columnlines` | `<mtable>` | Specifies table column borders. |
| `columnspacing` | `<mtable>` | Specifies the space between table columns. |
| `columnspan` | `<mtd>` |
 A non-negative integer value that indicates over how many table columns
 the cell extends.
  |
| `denomalign`
Deprecated
 | `<mfrac>` | The alignment of the denominator under the fraction. |
| `depth` | `<mpadded>` | A `<length-percentage>` indicating the desired depth (below the baseline). |
| `dir` | All MathML elements |
 The text direction. Possible values are either `ltr` (left to right) or
 `rtl` (right to left).
  |
| `display` | `<math>` |
 Specifies the rendering mode. The values `block` and
 `inline` are allowed.
  |
| `displaystyle` | All MathML elements |
 A `<boolean>` specifying whether to set the
 math-style
 to `normal` (if true) or `compact` (otherwise).
  |
| `fence` | `<mo>` |
 A `<boolean>` specifying whether the operator is a fence (such as
 parentheses). There is no visual effect for this attribute.
  |
| `fontfamily`
Deprecated
 | `<mstyle>` | Use CSS `font-family` instead. |
| `fontsize`
Deprecated
 | `<mstyle>` | Use CSS `font-size` instead. |
| `fontstyle`
Deprecated
 | `<mstyle>` | Use CSS `font-style` instead. |
| `fontweight`
Deprecated
 | `<mstyle>` | Use CSS `font-weight` instead. |
| `frame` | `<mtable>` |
 Specifies borders of an entire `<mtable>`.
 Possible values are: `none` (default), `solid` and
 `dashed`.
  |
| `framespacing` | `<mtable>` |
 Specifies additional space added between the table and
 `frame`.
  |
| `height` | `<mpadded>`,
 `<mspace>` | A `<length-percentage>` indicating the desired height (above the baseline). |
| `href` | All MathML elements | Used to set a hyperlink to a specified URI. |
| `id` | All MathML elements | Sets up a unique identifier associated with the element. |
| `linethickness` | `<mfrac>` | A `<length-percentage>` indicating the thickness of the horizontal fraction line. |
| `lspace` | `<mo>` | A `<length-percentage>` indicating amount of space before the operator. |
| `lspace` | `<mpadded>` | A `<length-percentage>` indicating the horizontal location of the positioning point of the child content with respect to the positioning point of the element. |
| `lquote`
Deprecated
 | `<ms>` | The opening quote to enclose the content. The default value is `"`. |
| `mathbackground` | All MathML elements | A background-color for the element. |
| `mathcolor` | All MathML elements | A color for the element. |
| `mathsize` | All MathML elements | A `<length-percentage>` used as a `font-size` for the element. |
| `mathvariant` | All MathML elements | The logical class of token elements, which varies in typography. |
| `maxsize` | `<mo>` | A `<length-percentage>` indicating the maximum size of the operator when it is stretchy. |
| `minsize` | `<mo>` | A `<length-percentage>` indicating the minimum size of the operator when it is stretchy. |
| `movablelimits` | `<mo>` | A `<boolean>` indicating whether attached under- and overscripts move to sub- and superscript positions when math-style is set to `compact`. |
| `notation` | `<menclose>` |
 A list of notations, separated by white space, to apply to the child
 elements.
  |
| `numalign`
Deprecated
 | `<mfrac>` | The alignment of the numerator over the fraction. |
| `open`
Deprecated
 | `<mfenced>` | A string for the opening delimiter. |
| `rowalign` | `<mtable>`,
 `<mtd>`,
 `<mtr>` | Specifies the vertical alignment of table cells. |
| `rowlines` | `<mtable>` | Specifies table row borders. |
| `rowspacing` | `<mtable>` | Specifies the space between table rows. |
| `rowspan` | `<mtd>` |
 A non-negative integer value that indicates on how many rows does the
 cell extend.
  |
| `rspace` | `<mo>` | A `<length-percentage>` indicating the amount of space after the operator. |
| `rquote`
Deprecated
 | `<ms>` | The closing quote to enclose the content. The default value is `"`. |
| `scriptlevel` | All MathML elements | Specifies a math-depth for the element. See the scriptlevel page for accepted values and mapping. |
| `scriptminsize`
Deprecated
 | `<mstyle>` |
 Specifies a minimum font size allowed due to changes in
 `scriptlevel`.
  |
| `scriptsizemultiplier`
Deprecated
 | `<mstyle>` |
 Specifies the multiplier to be used to adjust font size due to changes
 in `scriptlevel`.
  |
| `selection`
Deprecated
 | `<maction>` | The child element visible, only taken into account for some `actiontype` values. |
| `separator` | `<mo>` |
 A `<boolean>` specifying whether
 the operator is a separator (such as commas).
 There is no visual effect for this attribute.
  |
| `separators`
Deprecated
 | `<mfenced>` |
 A sequence of zero or more characters to be used for different
 separators.
  |
| `stretchy` | `<mo>` | A `<boolean>` indicating whether the operator stretches to the size of the adjacent element. |
| `subscriptshift`
Deprecated
 | `<msub>`,
 `<msubsup>`,
 `<mmultiscripts>` | A `<length-percentage>` indicating the minimum amount to shift the baseline of the subscript down. |
| `superscriptshift`
Deprecated
 | `<msup>`,
 `<msubsup>`,
 `<mmultiscripts>` | A `<length-percentage>` indicating the minimum amount to shift the baseline of the superscript up. |
| `symmetric` | `<mo>` | A `<boolean>` indicating whether a stretchy operator should be vertically symmetric around the imaginary math axis (centered fraction line). |
| `voffset` | `<mpadded>` | A `<length-percentage>` indicating the vertical location of the positioning point of the child content with respect to the positioning point of the element. |
| `width` | `<mpadded>`,
 `<mspace>`,
 `<mtable>` | A `<length-percentage>` indicating the desired width. |
| `xmlns` | `<math>` | Specifies the URI for the MathML namespace (`http://www.w3.org/1998/Math/MathML`) |


MathML element reference - MathML

MathML element reference
========================

This is an alphabetical list of MathML elements. All of them implement the `MathMLElement` class.

**Note:** As explained on the main MathML page, MDN uses MathML Core as a reference specification. However, legacy features that are still implemented by some browsers are also documented. You can find further details for these and other features in MathML 4.

MathML elements A to Z
----------------------

### math

* `<math>` (Top-level element)
### A

* `<maction>`
Deprecated
 (Bound actions to sub-expressions)
* `<annotation>` (Data annotations)
* `<annotation-xml>` (XML annotations)
### E

* `<menclose>`
Non-standard
 (Enclosed contents)
* `<merror>` (Enclosed syntax error messages)
### F

* `<mfenced>`
Non-standard

Deprecated
 (Parentheses)
* `<mfrac>` (Fraction)
### I

* `<mi>` (Identifier)
### M

* `<mmultiscripts>` (Prescripts and tensor indices)
### N

* `<mn>` (Number)
### O

* `<mo>` (Operator)
* `<mover>` (Overscript)
### P

* `<mpadded>` (Space around content)
* `<mphantom>` (Invisible content with reserved space)
* `<mprescripts>` (delimiter for prescripts)
### R

* `<mroot>` (Radical with specified index)
* `<mrow>` (Grouped sub-expressions)
### S

* `<ms>` (String literal)
* `<semantics>` (Container for semantic annotations)
* `<mspace>` (Space)
* `<msqrt>` (Square root without an index)
* `<mstyle>` (Style change)
* `<msub>` (Subscript)
* `<msup>` (Superscript)
* `<msubsup>` (Subscript-superscript pair)
### T

* `<mtable>` (Table or matrix)
* `<mtd>` (Cell in a table or a matrix)
* `<mtext>` (Text)
* `<mtr>` (Row in a table or a matrix)
### U

* `<munder>` (Underscript)
* `<munderover>` (Underscript-overscript pair)
MathML elements by category
---------------------------

### Top-level elements

* `<math>` (Top-level element)
### Token elements

* `<mi>` (Identifier)
* `<mn>` (Number)
* `<mo>` (Operator)
* `<ms>` (String literal)
* `<mspace>` (Space)
* `<mtext>` (Text)
### General layout

* `<menclose>`
Non-standard
 (Enclosed contents)
* `<merror>` (Enclosed syntax error messages)
* `<mfenced>`
Non-standard

Deprecated
 (Parentheses)
* `<mfrac>` (Fraction)
* `<mpadded>` (Space around content)
* `<mphantom>` (Invisible content with reserved space)
* `<mroot>` (Radical with specified index)
* `<mrow>` (Grouped sub-expressions)
* `<msqrt>` (Square root without an index)
* `<mstyle>` (Style change)
### Script and limit elements

* `<mmultiscripts>` (Prescripts and tensor indices)
* `<mover>` (Overscript)
* `<mprescripts>` (Delimiter for prescripts)
* `<msub>` (Subscript)
* `<msubsup>` (Subscript-superscript pair)
* `<msup>` (Superscript)
* `<munder>` (Underscript)
* `<munderover>` (Underscript-overscript pair)
### Tabular math

* `<mtable>` (Table or matrix)
* `<mtd>` (Cell in a table or a matrix)
* `<mtr>` (Row in a table or a matrix)
### Uncategorized elements

* `<maction>`
Deprecated
 (Bound actions to sub-expressions)
Semantic annotations
--------------------

* `<annotation>` (Data annotations)
* `<annotation-xml>` (XML annotations)
* `<semantics>` (Container for semantic annotations)
See also
--------

* MathML
* MathML attribute reference


MathML Attribute Values - MathML

MathML Attribute Values
=======================

MathML-specific types
---------------------

In addition to CSS data types, some MathML attributes accept the following types:

* `<unsigned-integer>`: An `<integer>`, whose first character is neither U+002D HYPHEN-MINUS character (-) nor U+002B PLUS SIGN (+); for example `1234`.
* `<boolean>`: A string `true` or `false` representing a boolean value.
Legacy MathML lengths
---------------------

**Deprecated:** This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

Instead of `<length-percentage>`, MathML used to define its own type to describe lengths. Accepted values included non-zero unitless length values (e.g. `5` to mean `500%`), values containing numbers ending with a dot (e.g. `34.px`), or named spaces (e.g. `thinmathspace`). For compatibility reasons, it is recommended to replace non-zero unitless length values with equivalent `<percentage>` values, to remove unnecessary dots in numbers, and to use the following replacement for named lengths:
```

veryverythinmathspace  => 0.05555555555555555em
verythinmathspace      => 0.1111111111111111em
thinmathspace          => 0.16666666666666666em
mediummathspace        => 0.2222222222222222em
thickmathspace         => 0.2777777777777778em
verythickmathspace     => 0.3333333333333333em
veryverythickmathspace => 0.3888888888888889em
```

### Units

| Unit | Description |
| --- | --- |
| `em` | `Font-relative` unit |
| `ex` | `Font-relative` unit. (The "x"-height of the element, `1ex ≈ 0.5em` in many fonts) |
| `px` | Pixels |
| `in` | Inches (1 inch = 2.54 centimeters) |
| `cm` | Centimeters |
| `mm` | Millimeters |
| `pt` | Points (1 point = 1/72 inch) |
| `pc` | Picas (1 pica = 12 points) |
| `%` | Percentage of the default value. |

### Constants

| Constant | Value |
| --- | --- |
| `veryverythinmathspace` | 1/18`em` |
| `verythinmathspace` | 2/18`em` |
| `thinmathspace` | 3/18`em` |
| `mediummathspace` | 4/18`em` |
| `thickmathspace` | 5/18`em` |
| `verythickmathspace` | 6/18`em` |
| `veryverythickmathspace` | 7/18`em` |
| `negativeveryverythinmathspace` | -1/18`em` |
| `negativeverythinmathspace` | -2/18`em` |
| `negativethinmathspace` | -3/18`em` |
| `negativemediummathspace` | -4/18`em` |
| `negativethickmathspace` | -5/18`em` |
| `negativeverythickmathspace` | -6/18`em` |
| `negativeveryverythickmathspace` | -7/18`em` |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.


Fonts for MathML - MathML

Fonts for MathML
================

 Fonts with appropriate Unicode coverage and Open Font Format features are required for good math rendering.
 This page describes how users can install such math fonts to properly display MathML in browsers.

Installation instructions
-------------------------

As a general rule of thumb, it is recommended to install both *Latin Modern Math* (which uses Computer Modern style popular for math formulas) and *STIX Two Math* (which has large unicode coverage for scientific characters). In the next sections, you will find detailed instructions to install these fonts in various operating systems.

### Windows

Install the *Latin Modern Math* and *STIX Two Math* fonts as follows:

1. Download latinmodern-math-1959.zip.
2. Open the ZIP archive, move inside the `latinmodern-math-1959` directory and then inside the `otf` directory. You will find a `latinmodern-math` font file.
3. Open the `latinmodern-math` font file and click the **Install** button.
4. Download static\_otf.zip.
5. Open the `static_otf.zip` ZIP archive, and then move inside the `static_otf` directory. Among the files there, you will find a `STIXTwoMath-Regular` file.
6. Open the `STIXTwoMath-Regular` file and click the **Install** button. If desired, you may also do the same for the other font files in the directory.

**Note:** *Cambria Math* is installed by default on Windows and should ensure relatively good MathML rendering.

### macOS

Install the *Latin Modern Math* font as follows:

1. Download latinmodern-math-1959.zip.
2. Extract the ZIP archive, move inside the `latinmodern-math-1959` directory and then inside the `otf` directory. You will find a `latinmodern-math` font file.
3. Double-click the `latinmodern-math` font file click the **Install font** button from the window that opens.

**Note:** If you are using macOS Ventura (version 13) or higher, then *STIX Two Math* is already pre-installed and you can skip the steps below.

Install the *STIX Two Math* font as follows:

1. Download static\_otf.zip.
2. Open the `static_otf.zip` ZIP archive, and then move inside the `static_otf` directory. Among the files there, you will find a `STIXTwoMath-Regular.otf` file.
3. Open the `STIXTwoMath-Regular.otf` file and click the **Install Font** button from the window that opens. If desired, you may also do the same for the other font files in the directory.

**Note:** A deprecated version of *STIX* is preinstalled starting with OS X Lion (version 10.7). Although some browsers are able to make use of it, it is strongly recommended to follow the instructions above for optimal math rendering.

### Linux

 Below, you can find commands to execute on popular Linux distributions
 in order to install the *Latin Modern Math* and *STIX Two Math* fonts from your
 package manager. Alternative approaches are also provided if your Linux
 distribution does not provide dedicated packages for these fonts.

#### Debian-based distributions (including Ubuntu and Mint)

```bash
sudo apt-get install fonts-lmodern fonts-stix
```

#### Fedora-based distributions

```bash
sudo dnf install texlive-lm-math stix-math-fonts
```

#### openSUSE-based distributions

```bash
sudo zypper install texlive-lm-math stix-fonts
```

#### Arch Linux

```bash
sudo pacman -S otf-latinmodern-math otf-stix
```

#### TeXLive packages

If your Linux distribution does not provide packages for the *Latin Modern Math* and *STIX* fonts, consider instead installing the `texlive` packages containing the *Latin Modern Math* and *XITS* fonts. For example on Mageia:

```bash
sudo urpmi texlive-dist texlive-fontsextra
```

However, you will likely need to ensure that these fonts are known by your system. Add a fontconfig configuration `/etc/fonts/conf.avail/09-texlive-fonts.conf` that points to the `opentype` directory of TeXLive, such as:

```xml
<?xml version="1.0"?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
<fontconfig>
  <dir>/your/path/to/texmf-dist/fonts/opentype</dir>
</fontconfig>
```

Finally, add this configuration file to the system font location list and regenerate the fontconfig cache:

```bash
ln -sf /etc/fonts/conf.avail/09-texlive-fonts.conf /etc/fonts/conf.d/
fc-cache -sf
```

#### Upstream packages

If no packages are available on your Linux distributions, or if you just want to install upstream packages then try this:

1. Download latinmodern-math-1959.zip and static\_otf.zip.
2. Create a `~/.fonts` if it does not exist already and place `latinmodern-math.otf` and `STIXTwoMath-Regular.otf` in that directory.
3. Run `fc-cache -f` to regenerate the fontconfig cache.
### Android

You must use the MathML-fonts add-on.

**Note:** Noto Sans Math provides good Unicode coverage for math symbols and Google plans to add support for math layout features.

### Other systems

On other systems, consider installing a font with a MATH table using your package manager. Note that these fonts are generally delivered with TeX distributions such as TeX Live, but you might need to follow specific instructions so that your system is aware of the fonts. As a last resort, install the MathML fonts add-on.

Advanced setup
--------------

 In the next sections, you will find other useful tips for installation and
 configuration of fonts for MathML.

### Arabic mathematical alphabetic symbols

Currently, very few fonts have appropriate glyphs for the Arabic Mathematical Alphabetic Symbols. If you are likely to need these characters, we recommend to install the *XITS* or Amiri fonts.

### Installation without administrator privilege

If you need to install fonts on a system without administrator privilege, the easiest option is to use math font the MathML-fonts add-on. Note that using the add-on is not optimal since it forces your Gecko browser to load a CSS stylesheet on each page you visit as well as Web math fonts on all pages with MathML content.

A better alternative on UNIX systems is to install the OTF files for Latin Modern Math and STIX into some local font folder and (if necessary) to run `fc-cache` on it. On macOS and Linux, the standard paths are respectively `~/Library/Fonts/` and `~/.fonts`.

### Fonts with a MATH table

You can actually install any mathematical OpenType font and use them for MathML rendering. Some browsers provide a way to configure the default font for MathML in their font preference menu. Alternatively, you can try the MathML-fontsettings add-on.

* Asana Math
* Cambria Math
* DejaVu Math TeX Gyre
* Garamond Math
* Latin Modern Math
* Libertinus Math
* STIX Math
* TeX Gyre Bonum Math
* TeX Gyre Pagella Math
* TeX Gyre Schola Math
* TeX Gyre Termes Math
* XITS Math
* Fira Math
* GFS Neohellenic Math


Global attributes - MathML

Global attributes
=================

**Global attributes** are attributes common to all MathML elements; they can be used on all elements, though they may have no effect on some elements.

Global attributes may be specified on all MathML elements, *even those not specified in the standard*. That means that any non-standard elements must still permit these attributes, even though using those elements means that the document is no longer MathML-compliant.

In addition to the basic MathML global attributes, the following global attributes also exist:

* The event handler attributes such as **`onclick`**, **`onfocus`**, etc.
* The `href` attribute for making MathML element a hyperlink.
List of global attributes
-------------------------

`class`

A space-separated list of the classes of the element. Classes allow CSS and JavaScript to select and access specific elements via the class selectors or functions like the method `Document.getElementsByClassName()`.

`data-*`

Forms a class of attributes, called custom data attributes, that allow proprietary information to be exchanged between the MathML and its DOM representation that may be used by scripts. All such custom data are available via the `MathMLElement` interface of the element the attribute is set on. The `HTMLElement.dataset` property gives access to them.

`dir`

An enumerated attribute indicating the directionality of the MathML element. It can have the following values:

* `ltr`, which means *left to right* and is used to render mathematical expressions from the left to the right (e.g. English or Moroccan style);
* `rtl`, which means *right to left* and is used to render mathematical expressions from the right to the left (e.g. Maghreb or Machrek style);

`displaystyle`:

a boolean setting the math-style for the element.

* `true`, which means `normal`.
* `false`, which means `compact`.

`id`

Defines a unique identifier (ID) which must be unique in the whole document. Its purpose is to identify the element when linking (using a fragment identifier), scripting, or styling (with CSS).

`mathbackground`

A background-color for the element.

`mathcolor`

A color for the element.

`mathsize`

A `<length-percentage>` used as a font-size for the element.

`nonce`

A cryptographic nonce ("number used once") which can be used by Content Security Policy to determine whether a given fetch will be allowed to proceed.

`scriptlevel`

Specifies a math-depth for the element. See the scriptlevel page for accepted values and mapping.

`style`

Contains CSS styling declarations to be applied to the element. Note that it is recommended for styles to be defined in a separate file or files. This attribute and the `<style>` element have mainly the purpose of allowing for quick styling, for example for testing purposes.

`tabindex`

An integer attribute indicating if the element can take input focus (is *focusable*), if it should participate to sequential keyboard navigation, and if so, at what position. It can take several values:

* a *negative value* means that the element should be focusable, but should not be reachable via sequential keyboard navigation;
* `0` means that the element should be focusable and reachable via sequential keyboard navigation, but its relative order is defined by the platform convention;
* a *positive value* means that the element should be focusable and reachable via sequential keyboard navigation; the order in which the elements are focused is the increasing value of the **tabindex**. If several elements share the same tabindex, their relative order follows their relative positions in the document.

Specifications
--------------

| Specification |
| --- |
| MathML Core # dfn-dir |
| MathML Core # dfn-displaystyle |
| MathML Core # dfn-mathbackground |
| MathML Core # dfn-mathcolor |
| MathML Core # dfn-mathsize |
| MathML Core # dfn-scriptlevel |

Browser compatibility
---------------------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

See also
--------

* `Element` interface that allows querying most global attributes.


Examples - MathML

Examples
========

Below you'll find some examples you can look at to help you to understand how to use MathML.

MathML formulas
---------------

The following demos display increasingly complex mathematical concepts in Web content.

Pythagorean Theorem

Small example showing a proof of the Pythagorean Theorem.

Deriving the Quadratic Formula

Outlines the derivation of the Quadratic Formula.

Mozilla MathML Test

Original test from the Mozilla MathML project. It contains examples from the TeXbook with image references generated by TeX.

MathML Browser Test

A similar test with concrete formulas taken from Wikipedia.

Other Web technologies
----------------------

The following demos mix MathML with other Web technologies to produce advanced content.

`<la-tex>` custom element

A custom element that accepts LaTeX content.

Magnetic field demo

A 3D representation of a magnetic field, using SVG and WebGL.

Συνάρτηση ζήτα Ρήμαν (el)

A greek article about the Riemann zeta function, with Web fonts from the Greek Font Society.

Pell's equation

A JavaScript program to solve Pell's equation using `BigInt`.

Lovelace's program for Bernouilli numbers

An emulator for Ada Lovelace's program to calculate Bernouilli numbers, using Private properties.