===
Module leader:
General queries and admin issues:
Graeme Stuart: [email protected]
===
Codecademy free courses:
===
questions we have been asked:
- assignment instructions and GitHub pages
- maximum number of pages
- using JS libraries
- assignment deadline: BlackBoard/Assessment or in Module Handbook
number of pages:
"if you can get all the required functionality into a single page, that is acceptable. Otherwise, try to keep the number of separate sections or HTML pages or to 4 or less. More pages does not equate to better marks."
libraries
do NOT use JQuery. For others, there are limited marks to gain or lose for using libraries - it carries a risk unless done right. The code needs to be integrated properly, example: adjust code tutorials or examples to use consistent functions, let/const…, and to match the standard expected from the rest of the JS - inconsistent code is bad.
Sometimes people copy code in or use a library from the web and make it look like it’s doing something, but halfway through marking it's obvious that it doesn’t do anything as its been used without understanding.
APIs
Try to use an online API, but if it's causing inconsistent issues, you can bring in a JSON-like object locally and populate a section in the DOM if done well…
…not just code copied from the labs.
===
JS is a top skill
72% of companies want JS developers, and test for JS:
===
it's important to clean up your code, for example…
…the new tesla/kitten code (code) - Lecture 05 slide updated
function showImage() {
picture.innerHTML = "";
picture.classList = event.target.id;
}
[car,cat].forEach(c => c.addEventListener( "click", showImage ));
Changed photo1
, photo2
classes to cat
, car
to match IDs
previous horrible code: lots of repetition,
not DRY (Do not Repeat Yourself!)
function showImage(whichPic) {
picture.innerHTML = "";
if (whichPic === "photo1") {
picture.classList.remove("cat");
picture.classList.add("car");
} else {
picture.classList.remove("car");
picture.classList.add("cat");
}
}
photo1.addEventListener("click", function(){ showImage(this.id) });
photo2.addEventListener("click", showImage);
===
There a few ways to store data for browsing sessions:
- cookies and databases (server)
- browser storage (client):
sessionStorage
localStorage
IndexedDB
client-side storage holds more data (devices/browsers vary) than cookies (4Kb) (Safari is preventing cookies 3rd party tracking cookies)
(If you see mention of WebSQL, it's old and dying)
the front-end (client) methods are:
sessionStorage
: per-page/tab, deleted on closelocalStorage
: per-site, stored permanently as a stringIndexedDB
: structured data, stored permanently including files/blobs
In all these, data are stored as ‘NoSQL’ key-value pairs
Resources:
CORS same-origin policy is domain-specific so websites can’t access databases on other sites
- the protocol/host/port (if specified) must be the same
- storage can be cleared by the user, or browser (if limits are reached)
In production, some browser storage requires a site to run under https
with an SSL certificate
(LetsEncrypt is free and can be set up on a server to auto-renew)
is per-domain
Data is available to all scripts loaded from pages from the same origin that previously stored the data.
It persists after the browser is closed and does not suffer cookie Weak Integrity/Weak Confidentiality issues. Session storage is per-origin and per-instance (window/tab) until the window/tab is closed; it allows separate instances of the same web app to run in different windows without interference, a use case not well supported by cookies.
localStorage
clashes: check for a key before writinglocalStorage
andindexedDB
write to disc (using browser internals)
The StorageManager API is still experimental—check browser support before using in production.
check storage limits (rough estimate):
<p>
You're currently using about <span id="percent">
</span>% of your available storage.
</p>
navigator.storage.estimate().then(function(estimate) {
document.getElementById("percent").innerHTML =
(estimate.usage / estimate.quota * 100).toFixed(8);
});
check storage (complete readout):
async function showEstimatedQuota(est) {
return await navigator.storage && navigator.storage.estimate ?
navigator.storage.estimate() :
undefined;
}
console.log(showEstimatedQuota());
DEMO: js-storage-check
IndexedDB
can be erased because of low disk space on a device—a database may be deleted without notifying the user to free up space for other website’s data used more recently.…a good thing, as end-users may not want everything stored forever for every site. So if
IndexedDB
is critical for your application, this browser behavior needs managing.
===
Browsers have their own storage
We're using one of the storage functions: localStorage
- it’s for small amounts of data (between 2Mb-10Mb)
- it stores data in key value pairs
localStorage
is insecure (no good for sensitive data - see Please Stop Using Local Storage).
However, it’s good for non-critical data.
Instead of cookies, many websites now use local storage to keep small amounts of data between visits. It can:
- store user preferences
- personalise each visit
You can see what a website stores in your own browser:
- open the web inspector
- select the "Application" tab…
Facebook uses localStorage
for several settings:
You can see stored objects ({…}
) and arrays ([…]
)
Some of the keys describe their purpose…
Setting and getting data:
localStorage.setItem("name", "Dave");
localStorage.getItem("name"); // Dave
Changing data: basic syntax:
localStorage["name"] = "Fania";
console.log(localStorage["name"]); // Fania
Example: set a localStorage item from a field value:
const theName = document.getElementById("name-field");
localStorage.setItem("name", theName.value);
myElement.innerText = localStorage.getItem("name");
remove an item from localStorage
or clear all:
localStorage.removeItem("name");
localStorage.clear();
you can also attach an eventListener
for various uses:
localStorage.addEventListener("change", myFunction);
myFunction
handles actions on the localStorage
data.
NOTE browser support is still patchy for LocalStorage events
===
- Store a name with local storage from an input form
view code - store multiple names in localStorage
view code
===
Being a style language based on key-value pairs CSS originally had no variables. LESS and Sass filled the gap and added other functionality, but CSS custom properties are now usable in all modern browsers.
Unlike LESS/Sass variables (@
and $
) they're prefixed with “--
”:
--myYellow: #fd3;
They are scoped to the selector in which they are defined, and inherited by its descendants
the :root
pseudo-element is often used in examples as a “global” selector (SVGs need the variable in :root
because the SVG DOM is separate)…
:root {
--darkGreen: #051;
--myYellow: #fd3;
}
main {
color: var(--darkGreen);
background: var(--myYellow);
}
.my-class {
border-color: var(--myYellow);
}
…however, any selector (element, class, id) can be used to set CSS Custom Properties (not just :root
) - you can then access them in all child elements of that selector
So CSS variables in html
or body
also mean that any element in your CSS file has access to them…
body {
--darkGreen: #051;
}
.my-class {
color: var(--darkGreen);
}
Elements outside the variable selector which contains the variables cannot access them:
<main>main content</main>
<footer>footer content</footer>
main {
--darkGreen: #051;
}
footer {
color: var(--darkGreen);
/* OOPS: cannot see the variable in “main” */
}
store an attribute value once, then use elsewhere:
/* set the variables in a root element */
html {
--myWidth: 360px;
--myBorder: 4px solid var(--myYellow);
--codeFont: "Courier New", monospace;
}
/* use the variables anywhere */
section {
border: var(--myBorder);
}
figure {
width: var(--myWidth);
}
code {
font-family: var(--codeFont);
}
For responsive design, you can reset custom properties inside @media
queries. For example, you could expand the margin around major layout elements for wider screen widths:
:root {
--gutter: 4px;
}
section {
margin: var(--gutter);
}
@media (min-width: 600px) {
:root {
--gutter: 16px;
}
/* this change is only activated above 600px */
}
Resources:
- Browser support for CSS variables (Can I Use)
- Using CSS custom properties/variables (MDN)
- CSS Variables: Why Should You Care?
===
one:
if(condition){
do stuff;
} else {
do other stuff;
}
two:
if(condition){
do stuff;
}
else {
do other stuff;
}
===
Please discuss module-related issues and questions with your module tutor or module leader