It is a set of interfaces and methods that allow developers to interact with web browsers. The Browser API is what makes it possible for developers to create dynamic and interactive web applications.
DOM is interface that allows JS to access and manipulate structure and content of HTML or XML document. DOM is hierarchical tree-like structure that represents web page, with each element representing different part of page, such as headings, paragraphs, images, and links. Developers use DOM to access and modify properties and attributes of these elements, such as their text content, styles, and event handlers.
- Fetching
- index.html
- Parsing
- Render Tree (WebKit)
- Frame Tree (Gecko)
- CSSOM (CSS Object Model)
- Layout
- Paint
- background-color; >> background-image; >> border; >> children; >> outline;
- Compositing
BOM, on the other hand, provides JS with access to browser window and its components, such as location bar, history, and navigation buttons. BOM also provides interfaces for working with cookies, timers, and browser's user interface.
- navigator
- User-Agent Client Hints
- screen
- location
- console.log(window.location.href);
- window.location.reload();
- window.location.replace("https://github.com/SKindij");
- Fetch
- history
- pageX/pageY
- pageXOffset
- pageYOffset
- clientX/clientY
- clientXOffset
- clientYOffset
There are several ways to manipulate the DOM using JavaScript.
- Accessing DOM elements:
using document object and one of its methods
getElementById(), getElementsByClassName(), getElementsByTagName(), or querySelector(); - Modifying element content:
using its properties
textContent, innerHTML, or outerHTML; - Modifying element attributes:
using its setAttribute() method; - Modifying element styles:
using its style property - Creating new elements:
using createElement() and appendChild() methods; - Removing elements:
using its remove() method;
- NodeList
- stores any nodes (including comments and text);
- can be both a "live" collection (
getElementsByNameandchildNodes) and a static one (querySelectorAll);let myElement = document.querySelector("#foo > div.bar"); //If there are no required elements, null will be returned. const myChildElement = myElement.querySelector('input[type="submit"]');
- method
.querySelectorAll()returns an array-like static NodeList collection of found elements;let myElements = document.querySelectorAll("div>p");
to search for all elements in general, you need to pass string
'*', which is called a wildcard, as an argument;
To work with collection of elements, we must convert list to array or "borrow" array methods from Array prototype.
Array.from(myElements).forEach(doSomethingWithEachElement); Array.from(myElements).forEach( (item) => { item.classList.add('foo'); } ); Array.prototype.forEach.call(myElements, doSomethingWithEachElement);
- HTMLCollection
- save only HTML element nodes;
- always remains relevant — JS will update it when new element appears;
- method
.getElementById('idName')is only in document object (good for unique elements: title, form);let divAll = document.getElementsByTagName("div"); const newElement = document.createElement('div'); //creates new element with given tag document.body.appendChild(newElement); let myElement = document.querySelector("div"); const myNewTextNode = document.createTextNode('some text'); // creates new text node with given text myElement.appendChild(myNewTextNode);
- method
.getElementsByClassName('class1 class2')defined for any HTML-Element of page;
Take your time writing loops over HTMLCollection. Because cycle can become infinite in those cases when searchable elements are added and removed from page.
HTML attribute values can be read and written using element properties.
- to set class:
element.className = "hacked";
element.className.add('hello');element.className.remove('bye');- add or remove multiple classes:
button.classList.add('active', 'paralel');button.classList.remove('active');- to set styles:
element.style.marginTop = "20px";element.style.color = "gray";element.style.backgroundColor = "beige";elem.style.cssText = "color: blue; border: 1px solid black";- get a child or parent element:
myElement. childrenmyElement.firstChildormyElement.lastChildmyElement.parentElement- get the next/previous neighbor node:
myElement.nextElementSiblingormyElement.previousElementSibling- internal content of elements:
El.innerHTMLreturns the HTML code of everything in the current element (the easiest way to see the HTML content of an element)El.innerTextfor working with textEl.textContentreturns the contents of hidden nested children as well (use to add text)outerHTMLreturns the HTML code of both this element and everything in it- attribute management:
element.setAttribute("style", "color: red; border: 1px solid blue;");someElement.getAttribute('id' || 'class' || 'type');
Date attributes are used to store values on HTML elements. When the server compiles the starting HTML, it can put values in data attributes. The frontend can then use them instead of sending the request to the server.
elem.dataset.columns- the value of the data-columns attribute;
To delete a node: element.remove();
- Local Storage (for long-term data storage) >>>
- we specify name of field in which data (up to 5MB) should be saved (values in form of strings), and then use this name to retrieve it;
- this object is one for all tabs and windows within the source (same domain/protocol/port);
- if we set data in one window, changes become visible in another;
- write:
window.localStorage.setItem("name", "Doka SKj"); - read:
const name = window.localStorage.getItem("name"); - remove:
window.localStorage.removeItem("user"); - clear:
window.localStorage.clear();
- write:
- Session Storage (data is stored only during the lifetime of the current session) >>>
- is created when a new browser tab is opened. The amount of data is limited to 5MB;
- page session remains active as long as the browser window is open and persists between page reloads;
- values are stored in order they are added, so first one added will be stored in position
.key(0)and so on.
Use wrapper functions to prevent errors related to failed write attempts, missing localStorage in the browser, and code duplication.
function setItem(key, value) { try { return window.localStorage.setItem(key, value) } catch (e) { console.log(e) } }function getItem(key) { try { return window.localStorage.getItem(key) } catch (e) { console.log(e) } }function setJSON(key, value) { try { const json = JSON.stringify(value) setItem(key, json) } catch (e) { console.error(e) } }function getJSON(key) { try { const json = getItem(key) return JSON.parse(json) } catch (e) { console.error(e) } }
A global storage event is fired, which can be used to track changes in storage. This event occurs only on other open pages of the current site. The event contains properties: key - the key that was changed; oldValue - the old value recorded in the field; newValue - new value; url - the address of the page where the change was triggered.
window.sessionStorage.setItem("name", "Doka SKj") function readUser() { const userJSON == sessionStorage.getItem("user") if (userJSON === null) { return undefined } try { return JSON.parse(userJSON) } catch (e) {sessionStorage.removeItem("user"); return undefined } }
Global Window object is an object that provides access to the browser's Web API.
In fact, if the programs are written in different languages, it can be difficult to make them friends and make them communicate with each other. That's why APIs (Application Programming Interface) exist.
JavaScript objects are very useful for transferring data from one site to another, especially when using APIs.
API - structured form of communication between different applications.
REST (Representational State Transfer) - component communication style in which all required data is specified in request parameters.
The interaction between the client and the server is reduced to 4 operations
| C | R | U | D |
|---|---|---|---|
| create | read | update | delete |
| POST | GET | PUT, PATCH | DELETE |
RPC (Remote Procedure Call) - is a style in which request message stores action to be performed and data required for that action.
JSON-RPC must have the following fields:
| method | params | id |
|---|---|---|
| "name of method" | [array of data] | establish compliance |
XMLHttpRequest is a built-in browser object that allows you to make HTTP requests to the server without reloading the page. XMLHttpRequest has two modes of operation: synchronous and asynchronous.
To make a request, we need to complete three steps:
- Create an XMLHttpRequest.
let xhr = new XMLHttpRequest();
- Initialize it.
xhr.open(method, URL, async = true, user, password);- HTTP method(usually "GET" or "POST");
- URL where the request is sent;
- Send a request.
xhr.send([body]);
Next, we listen to events on xhr to get the answer:
- load – occurs when any response is received, including HTTP error responses such as 404.
- error – when the request cannot be fulfilled, for example, there is no connection or URL.
- progress - occurs periodically while loading a response, reports progress.
Here is a complete example.
let xhr = new XMLHttpRequest(); xhr.open('GET', '/article/example/load'); xhr.send(); xhr.onload = function() { if (xhr.status != 200) { // analyze HTTP status of response alert(`Error ${xhr.status}: ${xhr.statusText}`); // 404: Not Found } else { alert(`Done, received ${xhr.response.length} byte`); // this is server response } }; xhr.onprogress = function(event) { if (event.lengthComputable) { alert(`Received ${event.loaded} of ${event.total} byte`); } else { alert(`Received ${event.loaded} byte`); } }; xhr.onerror = function() { alert("The request failed"); };
AJAX (Asynchronous JavaScript and XML) allows us to access information from external pages even after our page has loaded.
fetch function allows us to send HTTP requests to the server. With its help, you can both receive and send data.
Result of the fetch call will be a Promise (a wrapper object for asynchronous code) - this is something that will happen between now and the final moment in time (something that will happen in the future, but probably not immediately).
If you are working with JSON API, you will need to check status and parse JSON for each response. You can simplify your code by defining status parsing and JSON parsing as separate functions that return Promises.
You will only have to think about handling the data itself and, of course, exceptions.function status(response) { if (response.status >= 200 && response.status < 300) { return Promise.resolve(response) } else { return Promise.reject(new Error(response.statusText)) } }; function json(response) { return response.json() } fetch('users.json') .then(status) .then(json) .then(function(data) { console.log('Request succeeded with JSON response', data); }) .catch(function(error) { console.log('Request failed', error); });
fetch() method can take a second parameter, the init object, which allows you to control various settings:
An example of sending a POST request:
async function postData(url = '', data = {}) { // Default options are marked with * const response = await fetch(url, { method: 'POST', // *GET, POST, PUT, DELETE, etc. mode: 'cors', // no-cors, *cors, same-origin cache: 'no-cache', // *default, no-cache, reload, force-cache, only-if-cached credentials: 'same-origin', // include, *same-origin, omit headers: { 'Content-Type': 'application/json' // 'Content-Type': 'application/x-www-form-urlencoded', }, redirect: 'follow', // manual, *follow, error referrerPolicy: 'no-referrer', // no-referrer, *client body: JSON.stringify(data) // body data type must match "Content-Type" header }); return await response.json(); // parses JSON response into native JavaScript objects } postData('https://example.com/answer', { answer: 42 }) .then((data) => { console.log(data); // JSON data parsed by `response.json()` call });
Web Workers are a type of browser API that allow web applications to run scripts in the background on a separate thread, independent of the main execution thread. This can be useful for tasks that are CPU-intensive or time-consuming, such as large computations or complex data processing.
Web Workers operate in a separate context from the main execution thread, and communicate with the main thread via a messaging system. This messaging system allows the main thread to pass data to the worker thread, and vice versa.
Web Workers are instantiated using the Worker constructor, and are terminated using the terminate() method. When a worker is terminated, all its resources are released and its memory is freed.
One important thing to note about Web Workers is that they have limited access to the browser's APIs. For example, a worker cannot directly access the DOM or make network requests. However, a worker can communicate with the main thread to request this information.
Web Workers can be used for a variety of tasks, such as:
- Processing large datasets or performing complex calculations without blocking the main thread
- Parsing and validating large amounts of data
- Running tasks in the background while the user interacts with the application
- Creating multiplayer games or real-time applications that require synchronization between multiple clients