Introduction to Client-Side JavaScript and jQuery
NodeJS runs JavaScript server-side
So far, we have rendered our pages using ejs (SSR, server-rendered).
Problem: how do we deal with interactive data coming in and out of the page?
- Real-time applications
- Data that changes often
- No access to
process
orprocess.argv
window
is global scope; the same as declaring withoutvar
,let
, orconst
window
is implicit:window.location
===location
Document Object Model
- Tree-like structure
- Composition (vs. inheritence)
- Like a tree: leaf, root node (
html
) - Hierchical structure
Elements all are Node
s; multiple elements are NodeList
instances
document.getElementById
document.getElementByTagName
document.querySelector
document.querySelectorAll
Method (Singular) | Method (Plural) | Support |
---|---|---|
document.getElementById |
N/A | ✅ |
document.getElementByTagName |
document.getElementsByTagName |
✅ |
N/A | document.getElementsByClassName |
✅ |
document.querySelector |
document.querySelectorAll |
𐄂 |
document.querySelector
and document.querySelectorAll
generally preferred
Events bubble up unless otherwise prevented.
Works for any event. List of all the events
Client-side JS library used for DOM interaction
Introduced due to inconsistent browser APIs: Internet Explorer vs. Firefox vs. Chrome
Ex.
var list = document.getElementById("list"); // works in all browsers
var list = document.getElementByTagName("ul"); // works still :)
const listItem = document.getElementById("list"); // doesn't work in IE, old Chrome, old FF
document.querySelector
and document.querySelectorAll
now have good support
Historically, jQuery has been very pervasive on the web due to the inconsistencies of browser support, so we still have to learn it.
Equivalent to document.querySelectorAll
, but works in all browsers.
jQuery returns an Array-like object, whereas document.querySelectorAll
returns a NodeList
.
Vanilla JS
const celebritiesContainer = document.querySelector(".celebrities");
const celebrities = celebritiesContainer.querySelectorAll(".celebrity"); // a NodeList (not an Array!)
Array.from(celebrities).map((celebrity) => console.log(celebrity.innerText));
jQuery
const $celebritiesContainer = $(".celebrities");
const $celebrities = $celebritiesContainer.find(".celebrity"); // an array of Node(s)
$celebrities.map((celebrity) => console.log($(celebrity).text()));
No need to choose between document.querySelector
and document.querySelectorAll
; one method to rule them all
Don't use this one; use .on
instead
No:
$(document).ready(function() {
console.log("ready");
});
Yes:
jQuery(function($) {
console.log("Ready");
});
or:
$(function($) {
console.log("ready");
});
Note that $
is an alias for jQuery
; they are one and the same.
We pass in $
explicity to ensure we have an instance of jQuery
as opposed to a competing framework that may use the $
(MooTools).
Roughly 5 options:
.html
: renders raw HTML.append
,.prepend
(to).before
,.after
Place your HTML in backticks ```:
const text = "list item text";
const $listItem = $(`
<li>${text}</li>
`).appendTo("body");
Or place your template in a <template>
tag.
<template id="listItemTemplate">
<li>
<slot name="list-item"></slot>
</li>
</template>
const text = "list item text";
const $listItemTemplate = $("#listItemTemplate");
const $body = $("body");
$listItemHTML = $listItemTemplate.clone();
$listItemHTML.find("slot:first").parent().text(text);
$body.append($listItemHTML);
<slot>
s tell us where to place dynamic content. We can have as many <slot>
s as we want.
<template>
tags don't get rendered, so we don't need to hide them. We can have as many <template>
tags as we want.
Use back-ticks when placing HTML in your JS for small HTML; use the <template>
tag when you have complex markup.
.show
.hide
.toggle
.slideToggle
.slideIn
.slideOut
CSS Methods
.css
.toggleClass
.addClass
.removeClass
The above use CSS transforms under the hood. Best to use .toggleClass
or .addClass
/.removeClass
instead.
Also, check out the hidden
attribute.
.attr("attribute")
to get, and .attr("attribute", value)
to set
- Prefix variables with the
$
:$const $userMenu = $(".menu");
- Load jQuery via a CDN or NPM
- Check if
.length !== 0
in case the element doesn't exist - Start with your container element, then call
.find
subsequently on that element - Run your jQuery code in an IIFE
- Run your jQuery code in a
jQuery()
callback or equivalent - Use jQuery or don't; choose one or the other
- Load your
<script>
tags withdefer
- Separate out your templates in
<template>
tags (opinion); separate HTML and JS - Build your HTML separately, without jQuery, only updating the DOM once