Front end A1 - marcoFijan/projectTech GitHub Wiki

Progressive Enhancement

Wat is Progressive Enhancement?

Simpelgezegd zorgt Progressive Enhancement ervoor dat de website op elke browser een goede User Experience kan geven. Daarnaast zorgt Progressive Enhancement voor meer stabiliteit.

Hoe werkt het

Met Progressive Enhancement bouw je je website op een 'strong foundation'. Als in, de bare bones van je website. Zo kun je bijvoorbeeld je website eerst optimaliseren zodat je website werkt zonder CSS en Javascript. De website is dan te gebruiken voor de gebruiker zonder enig gebruik van styling en responsiveness. Zodra de basis van de website sterk staat (Dus eerst alleen de HTML), dan ga je verschillende features toevoegen zoals CSS en JavaScript. Op die manier is je website goed toegankelijk voor de gebruiker. Je bouwt als het ware op een piramide waarbij elke laag (CSS, Scripts, Responsiveness, etc) Een sterke brede 'foundation' heeft. Naamloos.png

Voordelen

  • Betere toegankelijkheid
  • Betere SEO (Beter vindbaar voor zoekmachines)
  • Makkelijker te onderhouden
  • Content werkt op alle web browsers
  • De gebruikers zijn voorkeuren worden gerespecteerd (Bijvoorbeeld het gebruik van Internet Explorer)

Nadelen

  • Kost veel tijd en plannen om een blueprint te maken voor een progressive enhanced website

Graceful Degradation (GD)

Graceful Degration is eigenlijk omgekeerd. Hier bouw je eerst een mooi werkende website in een moderne browser. Daarna ga je als het ware 'pleisters plakken' om er voor te zorgen dat die website ook te gebruiken is op andere oudere browsers maar dan met een stuk minder features en een lagere usability. Naamloos2.png

Gebruikte bronnen progressive enhancement

Mijn Progressive Enhanced App

Op deze link kunt u mijn Progressive Enhanced Features op een rij bekijken. PE Features


Concepts

Global and Fases

Met het woordje this krijg je je huidige global object het is ook mogelijk om in plaats van this, window te gebruiken om specifiek het global object in de window aan te roepen. Wanneer er gebruikt gemaakt wordt van nodeJS, kun je het globale object aanroepen door global

Javascript leest eerst de codes en slaat alle variables en function declarations op in memory. Daarna leest hij het nog een keer en vult de gegevens ook daadwerkelijk in course = β€˜block tech’ Het assignen gebeurd dus pas in de execution fase. (2de keer lezen na creation fase)

Hoisting

Alle variable declarations (var = β€œstring”) zet hij bovenaan Alleen de declarations worden bovenaan gezet. Niet de assignments:

Console.log(num);
Var num;
Num = 6;

wordt...

Var num;
Console.log(num)
Var = 6

En dus komt er undefined uit

Closure

Functions in functions kunnen alle functions boven in de keten bereiken tot aan de global scope. Functions in een functions worden ook wel inner functions genoemd. Closures laten toe dat de inner function de variablen kan bereiken of zijn outer function:

//global scope
var henk1 = "henk1"

function func1(){
  //local scope
  var henk2 = "henk2"

  function func2(){
    //local scope
    var henk3 = "henk3"

    function func3(){
      //local scope
      var henk 4 = "henk4"

      console.log(henk1);
    }
  }
}

Scope

De huidige context

Global Scope

De window in de browser (niet in een window een variable aanmaakt, wanneer er geen function omheen zit) window.variablenaam is mogelijk wanneer de variable in de global scope zit. (iedereen kan bij het window object en dus is het de global scope)

Versus...

Local scope

Elke keer als je een function declaration doet, krijg je een nieuwe local scope. De data in de function, hoort dus bij de scope, van die function.


Function scope

Binnen een function declaration wordt het een function scope. Local en function scope zijn vrijwel hetzelfde. Wanneer je het echt over de function hebt en de scope daarvan, dan is het een function scope, maar als je het alleen over de code daarbinnen hebt, is het een local scope

Versus...

Block Scope

Binnen een niet function statement. Zoals if-statement en for-loop. (binnen curly braces {} met eventuele label)

Voorbeeld:

//global

function greetings(){
  //function scope / Local Scope
  var henk = "henk" // function scope / Local Scope

  if(true){ //block scope, GEEN nieuwe local scope
    let henk2 = "henk2" //block scope
  }

  console.log(henk); //henk
  console.log(henk2); //ERROR, henk2 not defined
}

Context

Context is niet precies hetzelfde als scope. Een scope houdt zich aan de zichtbaarheid van de variables. Context houdt zich tot de object waaraan een method hoort

Met de keyword this.variable zorg je ervoor dat je zeker weet dat hij de variable uit die function / context haalt. Wanneer je dus bijvoorbeeld de method apply() gebruikt, heb je meer controle over welke variable hij moet gebruiken wanneer er in 2 verschillende functions dezelfde variablen gebruikt worden:

var objA = {
  name: 'objA'
  function sayName(){
    console.log(this.name)
  }
}

var objB = {
  name: 'objB'
  function sayName(){
    console.log(this.name)
  }
}

// Doe alsof abjA de content heeft van objB, maar hij heeft het niet!
objA.sayName.apply(objB); // returns objB

Bronnen


Note to self: Leer meer over ES6 functions:

ES6 Functions

ES6 heeft veel nieuwe manieren om functions te decladeren:

Arrow Functions / fat arrow

Met => maak je een arrow function. Ze zijn anoniem en zorgen er voor dat 'this' anders gebind wordt in functions. Met arrow functions hoeven we niet meer function, return en curly brackets {} te schrijven.

Voorbeelden:

// ES5
var multiplyES5 = function(x, y) {
  return x * y;
};

// ES6
const multiplyES6 = (x, y) => { return x * y };

// ES6 next level
const multiplyES6 = (x, y) => x * y;

Je geeft hier dus als het waarde eerst de variable, zoals normaal, maar dan in plaats van function te schrijven, schrijf je alleen de parameters. Vervolgens typ je de arrow, =>, en schrijf je je expression. Voor de expression hoeven we geen return meer te schrijven. Dit doet de arrow al uit zichzelf. Verder kunnen we de curly brackets ook weglaten. Dit is ook niet meer nodig. Op die manier worden de functions een stuk korter. Het ziet er ingewikkeld uit, maar het valt best mee hoe ingewikkeld het nu echt is.

Wanneer er maar 1 parameter is, hoeven we de () ook niet echt meer te gebruiken. Die laten we dan ook weg.

const phraseSplitterES6 = phrase => phrase.split(" ");

Maar wanneer er helemaal geen parameters zijn, zijn () nog wel nodig voor de leesbaarheid en de arrow function

var docLogEs6 = () => console.log(document);

Om het verschil te zien tussen een object en een block content, gebruik de {}:

//ES5
var setNameIdsEs5 = function setNameIds(id, name) {
  return {
    id: id,
    name: name
  };
};

// ES6
var setNameIdsEs6 = (id, name) => ({ id: id, name: name });

Wanneer je een object wilt omzetten naar een array, gebruiken we map. In ES6 kan dit ook met de arrow function

const smartPhones = [
  { name:'iphone', price:649 },
  { name:'Galaxy S6', price:576 },
  { name:'Galaxy Note 5', price:489 }
];

// ES5
var prices = smartPhones.map(function(smartPhone) {
  return smartPhone.price;
});
console.log(prices); // [649, 576, 489]

//***************************************

// ES6
const prices = smartPhones.map(smartPhone => smartPhone.price);
console.log(prices); // [649, 576, 489]

Hier gebruiken we dus wel weer de () aangezien we een function (map) gebruiken. De parameter heeft geen () nodig aangezien daar maar 1 van is.

Als laatste hebben we nog de promises. Met promises gebruiken we bijvoorbeeld then en done. Als iets gelukt is, then (doe dan)... Dit kan nu ook korter op 1 regel met behulp van de arrow functions

// ES5
aAsync().then(function() {
  returnbAsync();
}).then(function() {
  returncAsync();
}).done(function() {
  finish();
});

// ES6
aAsync().then(() => bAsync()).then(() => cAsync()).done(() => finish);

Bron


Higher order functions

Simpelgezegd zijn higher order functions, functions die in een andere function zitten.

Deze functions kunnen hier volledig in zitten. Zoals

function greaterThan(n) {
  function lesserThan(m){
    return m => m > n;
  }
}
let greaterThan10 = greaterThan(10);
console.log(greaterThan10(11));
// β†’ true

Een function kan ook een andere bestaande function aanpassen. Dan is deze function die de andere function aanpast, ook een higher function

function noisy(f) {
  return (...args) => {
    console.log("calling with", args);
    let result = f(...args);
    console.log("called with", args, ", returned", result);
    return result;
  };
}
noisy(Math.min)(3, 2, 1);
// β†’ calling with [3, 2, 1]
// β†’ called with [3, 2, 1] , returned 1

Bronnen


Loopings

De for loop ken ik al een tijdje sinds Java. Maar er zijn nu ook andere manieren om te loopen. Sinds ES5 is er de forEach loop voor arrays:

myArray.forEach(function (value) {
  console.log(value);
});

Nadeel van de forEach is dat je er niet uit kunt loopen bij een specifieke index. Dit kan dan weer wel bij de for-in loop. Maar die gebruiken we niet! De index wordt omgezet in een string. For-in loop is ontworpen voor oude objects met string keys

for (var index in myArray) {    // don't actually do this
  console.log(myArray[index]);
}

For-in kan dus gebruikt worden als je over object's properties wilt loopen. Of, je kunt de ingebouwde Object.keys() gebruiken:

// dump an object's own enumerable properties to the console
for (var key of Object.keys(someObject)) {
  console.log(key + ": " + someObject[key]);
}

Mocht je daarna nog vastlopen, kun je altijd nog de normale for-loop gebruiken

While

Naast de for-loops, hebben we ook nog de while-loopjes. Zo hebben we de normale:

while (i < 10) {
  text += "The number is " + i;
  i++;
}

Maar ook de do / while:

do {
  // code block to be executed
}
while (condition);

Higher Order Functions Loopings

Voor objects hebben we ook speciale higher order functions loopings. Namelijk map, filter en reduce Bij map loop je over alle items en creeΓ«r je gelijk een array met 1 eigenschap van het object. Zo kunnen alle children van de object de eigenschap name. Je kunt dan met map makkelijk een nieuwe array maken waarbij je in de function in de map aangeeft dat je alleen de name-eigenschap meeneemt.

//ES5
let dogs = animals.filter(function(animal){ //call the map and create a function inside map
  return animal.species // specify which property-type should be added to the new array
})

//ES6
let dogs = animals.filter(animal => animal.species)

Bij filter kun je over de array loopen waarbij je gelijk een nieuwe array kan maken. Met de nieuwe array kun je dan aan de hand van filter gelijk aangeven welke eigenschappen wel of niet toegevoegd moeten worden aan de nieuwe array. Dit kan dus, met arrow functions, op 1 rij.

//ES5
let dogs = animals.filter(function(animal){ //call the filter and create a function inside filter
  return animal.species === 'dog' // specify which properties should be added to the new array
})

//ES6
let dogs = animals.filter(animal => animal.species === 'dog')

Bij reduce tja... die snap ik niet echt

let array = animals.reduce(())

Bronnen Looping


Callbacks, Promises & async

Callbacks

Met callbacks kun je een function opslaan als een parameter. De function hoeft niet gedeclareerd te zijn in de parameter. AddEventListener is een voorbeeld van een callback waar je eerst de input/actie declareert voor dat je de function uitvoert. Een voorbeeld bij AddEventListener is 'click':

addEventListner('click', aFunction(4, 5))

function(x, y){
  return x + y;
}

Callbacks zijn dus ook higher order functions aangezien je een function aanroept in een function

Promises

Een promise heeft 3 verschillende states:

  • Pending (waiting / default state) (Bijvoorbeeld: Je maakt via de telefoon een afspraak bij een restaurant)
  • Fulfilled (When your promise is ready / your received something) (Bijvoorbeeld: Je wordt weer teruggebeld door de restaurant)
  • Rejected (When something goes wrong) (Bijvoorbeeld: Je wordt teruggebeld, maar je krijgt te horen dat je niet langs kan komen bij de restaurant)

Zo schrijf je een promise:

const promise = new Promise((resolve, reject) => {
  setTimeout() => {
  resolve()
  }
  promise.then(onSucces)
  promise.catch(onFailure)
})

Why promises? You can chain them!

function myPromise() {
  return new Promise((resolve, reject) => {
    setTimeout() => {
    resolve()
    }
  }
}

myPromise()
  .then(doThis)
  .then(thenDoThis)
  .then(doThatThing)
  .catch(logErr)

Promises kun je met behulp van .then aan elkaar 'chainen' (koppelen). Op die manier kun je ervoor zorgen dat eerst een bepaalde function wordt uitgevoerd en daarna pas de volgende. Dit is handig voor wanneer je data ergens moet ophalen en dit net even wat langer kan duren dan lokale code.

Lastly, Async-Await

Met Async en await kun je functions makkelijk laten gedragen als promises. Op die manier kun je er ook voor zorgen dat weer een specifieke functie uitgevoerd moet worden voordat er verder gegaan kan worden:

async function getMehData() { //SET ASYNC
  const userData = await getUserData(); //USE THIS FUNCTION LIKE A PROMISE
  const weather = await getCurrentWeather(); //USE THIS FUNCTION LIKE A PROMISE

  return {
    user: userData,
    degrees: weather.currentDegrees
  }
}

Je kunt ook de promises paralel laten lopen met Promises.all:

const data = Promises.all([userData, weather])

Samenvattingen

Chapter 13: Javascript and the Browser

img2-thejournal-ie.gif

Een Network protocol beschrijft een stijl of communicatie over een netwerk. Er zijn protocolen voor het versturen van email, ontvangen van email, delen van bestanden etc. Een Hypertext Transfer Protocol (HTTP) is een protocol voor het ophalen van resources. Voor het ophalen beschijf je de naam van de resource en de versie van de protocol die hij probeert op te halen:

GET /index.html HTTP/1.1

De Transmission Control Protocol (TCP) is een protocol die ervoor zorgt dat de computer wait, of listen. Elke listener heeft een nummer (port). De listening computer heet de server en de connecting computer heet de client.

Een URL (Uniform Resource Locator) is zo opgebouwd: HTTP protocol, Server, path

Met een domain name kun je makkelijk in normale taal IP-adress van computers opzoeken.

Omdat niet iedereen te vertrouwen is op het web, is er besloten dat je met javascript gelimiteerd wordt met wat je op de computer kan doen. Zo kun je bijvoorbeeld niet iemands bestanden inzien vanaf een andere computer met javascript. Het isoleren van een programming environment heet sandboxing

Chapter 14: The Document Object Model

In elke HTML tag kunnen we nagaan waar deze tag voor staat. Dit heet de Document Object Model, of DOM in het kort. Data sctructuur noemen we een 'tree' wanneer het een vertakkeling heeft en geen cycles en heeft daarnaast een alleenstaande root. In DOM, document,documentElement is de root.

Een 'tree' heeft verschillende nodes (bijvoorbeeld identifiers, values en application nodes). Application node kan weer kinderen hebben en dus andere nodes. Identifiers en values hebben geen kinderen en zijn dus 'leaves/bladeren'. Ook in de DOM geldt dit. Zo kunnen nodes kinderen hebben (document.body) of bladeren (tekst of comment nodes).

Nodes hebben 'siblings' Alleen de first child geeft null bij previousSibling en last child geeft null by nextSibling. nodes.jpg

Deze function geeft true terug wanneer een node een bepaalde string heeft:

function talksAbout(node, string) {
  if (node.nodeType == Node.ELEMENT_NODE) {
    for (let i = 0; i < node.childNodes.length; i++) {
      if (talksAbout(node.childNodes[i], string)) {
        return true;
      }
    }
    return false;
  } else if (node.nodeType == Node.TEXT_NODE) {
    return node.nodeValue.indexOf(string) > -1;
  }
}

console.log(talksAbout(document.body, "book"));
// β†’ true

Omdat nodes geen array zijn, kunnen we er niet doorheen komen met for/of.

Wanneer we een bepaalde element willen hebben met bijvoorbeeld getElementsByTagName, kunnen we de [ ] gebruiken om aan te geven welke child we willen:

let link = document.body.getElementsByTagName("a")[0];
console.log(link.href);

Daarnaast kun je natuurlijk ook specifiek een element krijgen door getElementById/getElementByClassName te gebruiken.

Om de DOM aan te passen kun je methods gebruiken als replaceChild en insertBefore:

<p>One</p>
<p>Two</p>
<p>Three</p>

<script>
  let paragraphs = document.body.getElementsByTagName("p");
  document.body.insertBefore(paragraphs[2], paragraphs[0]);
// will give: Three/One/Two
</script>

Als je een alt attribute wilt veranderen van een image, moet je een nieuwe textnode aanmaken. Dit kan met createTextNode

<p>The <img src="img/cat.png" alt="Cat"> in the
  <img src="img/hat.png" alt="Hat">.</p>

<p><button onclick="replaceImages()">Replace</button></p>

<script>
  function replaceImages() {
    let images = document.body.getElementsByTagName("img");
    for (let i = images.length - 1; i >= 0; i--) {
      let image = images[i];
      if (image.alt) {
        let text = document.createTextNode(image.alt);
        image.parentNode.replaceChild(text, image);
      }
    }
  }
</script>

Met data-atributen kun je een element oproepen in Javascript:

<p data-classified>

Daarnaast kun je een waarde meegeven:

<p data-classified="secret"

In javascript kun je de code dan oproepen door:

if(para.getAtribute("data-classified") == "secret"{
 // verwijder html element uit de DOM
 para.remove()

Voor querySelector moet je voor data-atributen [ ] gebruiken:

let para = document.querySelector('[data-paragraph]')

Met dataset krijg je niet alleen de key, maar ook de andere 'waarden'

for (let para of Array.from(paras)){
 console.log(para.dataset);
}
// geeft array van alle values van de array
// DOMStringMap(classified: "value")

Exercise: TagName

<h1>Heading with a <span>span</span> element.</h1>
<p>A paragraph with <span>one</span>, <span>two</span>
  spans.</p>

<script>
  function byTagName(node, tagName) {
    // Your code here.
    let nodesArray = [];
    let currentTagName = node.nodeName;
    let children = node.childNodes;
    
    if (currentTagName.lowercase() === tagName){
      nodesArray.push(node); // Now the user can use the nodes. It is usefull data in the array
  	}
    
    if (children){
      for(let i = 0; i < children.length; i++){
        let childNode = children[i];
        
        byTagName(childNode, tagName);
      }
    }
  }
  byTagName(document.body, "p");
</script>

Chapter 15: Handling Events

Polling is an approach where the computer needs to look at the queue very often to react to input. Because of this, software can feel unresponsive. Handlers are a better way for specific events. For example:

<p>Click this document to activate the handler.</p>
<script>
  window.addEventListener("click", () => {
    console.log("You knocked?");
  });
</script>

There is also a way to remove a eventlistener. For instance when the user pressed the button once:

<button>Act-once button</button>
<script>
  let button = document.querySelector("button");
  function once() {
    console.log("Done.");
    button.removeEventListener("click", once);
  }
  button.addEventListener("click", once);
</script>

The eventlistener gives automaticly the event. That way, you can look up which button has been pressed:

<button>Click me any way you want</button>
<script>
  let button = document.querySelector("button");
  button.addEventListener("mousedown", event => {
    if (event.button == 0) {
      console.log("Left button");
    } else if (event.button == 1) {
      console.log("Middle button");
    } else if (event.button == 2) {
      console.log("Right button");
    }
  });
</script>

Events propagate outwards. Which means that they start at the specific eventhandler. So if you have a button inside a paragraph. And both the paragraph and button have an eventlistener. The buttoneventlistener will be called first when you press the button. To completely stop the events outside the button. You can call the stopPropagation method in the event:

<p>A paragraph with a <button>button</button>.</p>
<script>
  let para = document.querySelector("p");
  let button = document.querySelector("button");
  para.addEventListener("mousedown", () => {
    console.log("Handler for paragraph.");
  });
  button.addEventListener("mousedown", event => {
    console.log("Handler for button.");
    if (event.button == 2) event.stopPropagation();
  });
</script>

With the target property, you can specify the type of event. That way you can have one listner for an array of buttons. And use the target property in an if else statement to specify which button does what:

<button>A</button>
<button>B</button>
<button>C</button>
<script>
  document.body.addEventListener("click", event => {
    if (event.target.nodeName == "BUTTON") {
      console.log("Clicked", event.target.textContent);
    }
  });
</script>

The browser has a lot of basic default actions (arrow down, click link, right-click etc). These default actions will be loaded first and after that the events. If you want to load your events first, you can use the preventDefault method on the event object:

<a href="https://developer.mozilla.org/">MDN</a>
<script>
  let link = document.querySelector("a");
  link.addEventListener("click", event => {
    console.log("Nope.");
    event.preventDefault();
  });
</script>

But only use this when you have a really good reason to.

whith the keydown and keyup event, you kan edit the behavior what happens when you press a key. You can also use shitKey, cntrlKey, altKey and metaKey to make easier keycombinations.

<p>This page turns violet when you hold the V key.</p>
<script>
  window.addEventListener("keydown", event => { //activates when pressed AND held down
    if (event.key == "v") {
      document.body.style.background = "violet";
    }
    else if (event.key == " " && event.ctrlKey) { //when both cntrl and a different key are pressed
     console.log("Continuing!");
  });
  window.addEventListener("keyup", event => {
    if (event.key == "v") {
      document.body.style.background = "";
    }
  });
</script>

There are multiple pointer events:

Mouse clicks

  • mousedown (press and hold the mousebutton)
  • mouseup (release mousebutton)
  • click (press and release mousebutton)
  • dblclick (double click the mousebutton)
  • clientX / clientY (coordinates in pixels of the top-left corner of the window)
  • pageX / pageY (coordinates in pixels of the top-left corner of the whole document may be different when scrolled)

Mouse motion

  • mousedown / mouseup etc (does something when mouse moved in direction)

Touch events For touch events you can use the mousedown, mouseup and click events. But there touch events. Like

  • touchstart (when finger starts touching the screen)
  • touchmove (when finger is moved)
  • touchend (when finger is released)

Because there can be multiple fingers on screen, the event objects have a touches property. That property holds an array-like object of point which each has its own clientX, clientY, pageX and pageY properties. event.touches[0]

It is smart to use the preventDefault property in touch events.

Scroll events with scroll you can look at where the current user is on the page This code gives a progressbar on how far the user is on the page.

<style>
  #progress {
    border-bottom: 2px solid blue;
    width: 0;
    position: fixed;
    top: 0; left: 0;
  }
</style>
<div id="progress"></div>
<script>
  // Create some content
  document.body.appendChild(document.createTextNode(
    "supercalifragilisticexpialidocious ".repeat(1000)));

  let bar = document.querySelector("#progress");
  window.addEventListener("scroll", () => {
    let max = document.body.scrollHeight - innerHeight;
    bar.style.width = `${(pageYOffset / max) * 100}%`;
  });
</script>

Focus event Focus and blur events are used when the user moves form or to the browser tab or window in which the document is shown. Focus events do not propagate like the other events. It parrents don't know that one does become focus or blur.

Load event When a page finishes loading, the load event fires on the window and the document body objects. When a user navigates away of closed a page, a beforeunload event fires. If you prevent default behavior on this event and set the returnValue to a string, the browser will show the user a dialog asking if they really want to leave the page.

Beside the setTimeout(), you can also use the setInterval and clearInterval to set timers:

let bombTimer = setTimeout(() => {
  console.log("BOOM!");
}, 500);

if (Math.random() < 0.5) { // 50% chance
  console.log("Defused.");
  clearTimeout(bombTimer);
}
let ticks = 0;
let clock = setInterval(() => {
  console.log("tick", ticks++);
  if (ticks == 10) {
    clearInterval(clock);
    console.log("stop.");
  }
}, 200);

Chapter 18: HTTP and Forms

Requests can have different kinds of methods: GET = get the specified resource DELETE = delete a resource PUT = create or replace a resource POST = Send information to the resource

The server is not obliged to carry out every request it gets. When you remove the main page, the server will probably refuse.

HTTP/1.1 = indicates the version of the HTTP protocol it is using.

After that there will be a few headers:

HTTP/1.1 200 OK

Content-Length: 65585 //65,585 bytes Content-Type: text/html Last-Modified: Thu, 04 Jan 2018 14:05:30 GMT

URL's have endoced URI componentents. A question mark ? will be printed as %3F. To encode or decode URI's, you can use the decodeURIComponent and encodeURIComponent methods:

console.log(encodeURIComponent("Yes?"));
// β†’ Yes%3F
console.log(decodeURIComponent("Yes%3F"));
// β†’ Yes?

The interface through which browser JavaScript can make HTTP requests is called fetch.

fetch("example/data.txt").then(response => {
  console.log(response.status);
  // β†’ 200
  console.log(response.headers.get("Content-Type"));
  // β†’ text/plain
});

Calling fetch returns a promise that resolves to a Response object holding information about the server’s response, such as its status code and its headers.

You can use range in the header to specify which part you want out of a response:

fetch("example/data.txt", {headers: {Range: "bytes=8-19"}})
  .then(resp => resp.text())
  .then(console.log);
// β†’ the content

Browsers protoect us by desallowing scripts to make HTTP requests to other domains like your bank.

HTTPS uses cryptographic certificates and encryption to prevent eavesdropping and tampering. The browsers should recognize these certificates and this prevents other people from impersonating the website.

you can access forms like arrays with the [ ]

<form action="example/submit.html">
  Name: <input type="text" name="name"><br>
  Password: <input type="password" name="password"><br>
  <button type="submit">Log in</button>
</form>
<script>
  let form = document.querySelector("form");
  console.log(form.elements[1].type);
  // β†’ password
  console.log(form.elements.password.type);
  // β†’ password
  console.log(form.elements.name.form == form);
  // β†’ true
</script>

You can change the tabindex with the following code:

<input type="text" tabindex=1> <a href=".">(help)</a>
<button onclick="console.log('ok')" tabindex=2>OK</button>

You can overwrite words with selectionStart and selectionEnd:

<textarea></textarea>
<script>
  let textarea = document.querySelector("textarea");
  textarea.addEventListener("keydown", event => {
    // The key code for F2 happens to be 113
    if (event.keyCode == 113) {
      replaceSelection(textarea, "Khasekhemwy");
      event.preventDefault();
    }
  });
  function replaceSelection(field, word) {
    let from = field.selectionStart, to = field.selectionEnd;
    field.value = field.value.slice(0, from) + word +
                  field.value.slice(to);
    // Put the cursor after the word
    field.selectionStart = from + word.length;
    field.selectionEnd = from + word.length;
  }
</script>

With the input tag you can use focus and blue methods to tell the browser when the input can recieve inputs:

<input type="text">
<script>
  document.querySelector("input").focus();
  console.log(document.activeElement.tagName);
  // β†’ INPUT
  document.querySelector("input").blur();
  console.log(document.activeElement.tagName);
  // β†’ BODY
</script>

But in this case the code you see above is already being handled by autofocus by HTML

⚠️ **GitHub.com Fallback** ⚠️