ten things every developer should know about...

Post on 26-May-2020

6 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Ten Things Every Developer Should Know About HTML5

Jeff Prosise

jeffpro@wintellect.com

Canvas is Your Best Friend for Advanced UIs

The canvas API brings pixel-addressable graphics to JavaScript

Supports transforms, animations, layered graphics, and much more

Makes possible entire genres of apps (games, photo editors, etc.) that weren't

possible before

Makes possible advanced visual effects that weren't possible before

Corollary: Never do with Canvas what you could do with CSS3

Generating an Image

var bitmap = context.createImageData(100, 100);

for (x = 0; x < bitmap.width; x++)for (y = 0; y < bitmap.height; y++)

drawRandomColor(bitmap, x, y);

context.putImageData(bitmap, 0, 0);

function drawRandomColor(bitmap, x, y) {var index = (x + y * bitmap.width) << 2;bitmap.data[index + 0] = Math.random() * 256; // Redbitmap.data[index + 1] = Math.random() * 256; // Greenbitmap.data[index + 2] = Math.random() * 256; // Bluebitmap.data[index + 3] = 255; // Alpha

Modifying an Image

var image = new Image();image.src = "flowers.jpg";

image.onload = function () {context.drawImage(image, 0, 0, canvas.width, canvas.height);bitmap = dc.getImageData(0, 0, canvas.width, canvas.height);for (x = 0; x < bitmap.width; x++)

for (y = 0; y < bitmap.height; y++)toGray(bitmap, x, y); // Helper function (not shown)

context.putImageData(bitmap, 0, 0);}

The Canvas API

Never Take Performance for Granted

The same code can perform dramatically differently in different browsers

Each browser has its own JavaScript engine, and each tends to be optimized differently

V8 engine in Chrome

Chakra engine in Internet Explorer

SpiderMonkey engine in Firefox

Modern engines JIT-compile JavaScript, often on background threads running on separate cores

Because JavaScript is a (mostly) typeless language, JIT compilers have to make assumptions

Don't assume that because it performs acceptably in Chrome, it will also perform

acceptably in IE (or vice versa)

Test, test, and test some more!

JavaScript Performance

Web Workers Make JavaScript a Modern Language

Web workers allow JavaScript apps to be multithreaded

Make apps more responsive by consigning long-running loops to background threads

Allow apps to leverage multiple cores in modern processors

Web workers run in a special scope that lacks access to document or window

Workers can't update UIs directly because they can't access the browser DOM

Workers can post messages to the UI thread and allow that thread to update the UI

Can also receive message from the UI thread

Limited worker scope takes much of the pain out of multithreading

Starting a Worker and Posting a Message

var worker = new Worker("add.js");worker.addEventListener("message", onMessage, false);worker.postMessage({ op1: 2, op2: 2 }); // Pass values to worker...

function onMessage(e) {alert(e.data); // Display sum

}

Receiving and Posting Messages in a Worker

// add.jsaddEventListener("message", onMessage, false);

function onMessage (e) {var a = e.data.op1;var b = e.data.op2;postMessage(a + b); // Post sum to the main thread

}

Multithreaded JavaScript

Storage Options in HTML5 are Limited

Local Storage provides persistent data store to apps

Data written to local storage subject to shared quota of approx. 5 MB

Data written to local storage can be read, modified, and deleted by any apps that share an origin

Data written to local storage is stored in plaintext and is easily inspected by users

Data written to local storage is unstructured

Indexed DB solves some of these problems

Apps can create multiple client-side databases containing object stores

Indexed DB somewhat alleviates the quotas placed on storage

Indexed DB supports indexing for fast retrieval of data

Indexed DB supports transactions but lacks a query language

Reading and Writing Local Storage

// Write point to local storagevar x = 100;var y = 200;var point = [x, y]; // Stored as "100,200"window.localStorage["point"] = point;

// Read point from local storagevar point = window.localStorage["point"];

if (point != null){

var coords = point.split(",");var x = parseInt(coords[0]);var y = parseInt(coords[1]);

}

Creating and Initializing an Indexed Database

var request = window.indexedDB.open("MyDatabase", 1); // Version 1

request.onupgradeneeded = function (e) {var db = e.target.result; // Contains IDBDatabase reference

// Create an object storevar store = db.createObjectStore(

"employees", { keyPath: "alias" });

// Create an index on the object storestore.createIndex("alias", "alias", { unique: true });

};

Adding an Object to an Object Store

store.add({ firstName: "Jeff", lastName: "Prosise",alias: "v-jeffpr" }).onsuccess = function (e) {// Object added

};

Retrieving Objects from an Object Store

store.get("v-jeffpr").onsuccess = function (e) {var employee = e.target.result;alert(employee.firstName + " " + employee.lastName);

};

Modifying an Object in an Object Store

store.get("v-jeffpr").onsuccess = function (e) {var employee = e.target.result;employee.firstName = "Jeffrey";store.put(employee).onsuccess = function (e) {

// Object modified};

};

Retrieving Records Through an Index Using an "only" Range

var index = store.index("firstName");var range = IDBKeyRange.only("Jeff"); // Case-sensitive!

index.openCursor(range).onsuccess = function(e) {var cursor = e.target.result;if (cursor) {

alert(cursor.key + ": " +cursor.value.firstName + " " +cursor.value.lastName

);cursor.continue();

}};

Indexed DB

Read Access to the Local File System is Limited but Functional

File(Reader) API allows files to be opened and read

File object represents individual files

FileList object represents collections of files

FileReader object provides API for reading data

Blob object holds data

Files must be selected by the user in order to be opened and read; gallery apps

simply are not possible (and probably never will be)

Selected through an <input type="file"> element

Selected through drag-and-drop

File(Reader) API is widely supported by browsers

Loading a File

// HTML<input type="file" id="picker" />

// JavaScriptdocument.getElementById("picker").addEventListener

("change", onFileSelected, false);

function onFileSelected(e) {// Get a File object representing the selected filevar file = e.target.files[0];

}

Getting Information About a File

// Retrieve a File from a FileListvar file = e.target.files[0];

// Get the file's name, type, size, and last-modified datevar name = file.name;var type = file.type; // e.g., "image/jpeg"var size = file.size;var stamp = file.lastModifiedDate;

// Determine whether the file is an image fileif (file.type.match("image.*") {

// It's an image!}

Reading a Text File

var reader = new FileReader();

reader.onload = function(e) {// Read the file's text content from e.target.resultvar data = e.target.result;

}

reader.onerror = function(e) {// If an error occurred, make the user awarealert(e.target.error.code); // Display error code

}

reader.readAsText(file);

Reading an Image File

var reader = new FileReader();

reader.onload = function(e) {// Assign data URL to src property of <img> elementvar img = document.getElementById("image");image.src = e.target.result;

}

reader.onerror = function(e) {alert(e.target.error.code); // Display error code

}

reader.readAsDataUrl(file);

Reading a Binary File

var reader = new FileReader();

reader.onload = function(e) {// Wrap an array around the ArrayBuffer and read each bytevar bytes = new Uint8Array(e.target.result);for (i=0; i<bytes.length; i++) {

var byte = bytes[i];}

}

reader.onerror = function(e) {alert(e.target.error.code); // Display error code

}

reader.readAsArrayBuffer(file);

Reading from the Local File System

Write Access to the Local File System Sucks

FileSystem and FileWriter APIs provide for file writing, but…

W3C has officially discontinued work on both

Only Chrome and recent versions of Opera support these APIs

Even in Chrome, APIs write to a virtual file system, not the physical file system

Must rely on browser-specific APIs to save files to the local file system

Saving a Blob (IE10+)

// Save a blob containing a stringvar blob = new Blob(["Hello, blob!"]);window.navigator.msSaveBlob(blob, "Sample.txt");

// Save a blob containing a canvas imagevar blob = canvas.msToBlob();window.navigator.msSaveBlob(blob, "Sample.jpg");

XMLHttpRequest Level 2 is Awesome

Networking has been too limited for too long in JavaScript

No cross-origin requests

No intrinsic support for time-outs or progress events

Limited ability to transmit and receive binary data

XMLHttpRequest Level 2 brings JavaScript networking out of the Stone Age

Support for cross-origin requests

Support for file uploads and progress events

Support for request time-outs

Support for binary input and output and more

Sending a Request

var xhr = new XMLHttpRequest();xhr.open("GET", "services/weather/98052", true);xhr.addEventListener("load", onLoad, false);xhr.addEventListener("error", onError, false);xhr.addEventListener("timeout", onTimeout, false);xhr.timeout = 10000; // 10 secondsxhr.send();...

function onLoad(e) {// Request completed successfully

}

Sending a String

var xhr = new XMLHttpRequest();xhr.open("POST", "services/weather", true);xhr.addEventListener("load", onLoad, false);xhr.send("98052");...

function onLoad(e) {// Request completed successfully

}

Sending Binary Data

var xhr = new XMLHttpRequest();xhr.open("POST", "services/upload", true);xhr.addEventListener("load", onLoad, false);var bytes = new Uint8Array([1, 2, 3, ...]);xhr.send(bytes.buffer);...

function onLoad(e) {// Request completed successfully

}

Uploading a File

var xhr = new XMLHttpRequest();xhr.open("POST", "services/upload", true);xhr.addEventListener("load", onLoad, false);xhr.send(file);

HTML5 file object representing file to be uploaded

Monitoring Upload Progress

var xhr = new XMLHttpRequest();xhr.open("POST", "services/upload", true);xhr.addEventListener("load", onLoad, false);xhr.upload.addEventListener("progress", onProgressChanged, false);xhr.send(file);...

function onProgressChanged(e) {if (e.lengthComputable) {

var percentComplete = (e.loaded / e.total) * 100;}

Downloading Binary Data

var xhr = new XMLHttpRequest();xhr.open("GET", "images/image.png", true);xhr.responseType = "arraybuffer";xhr.addEventListener("load", onLoad, false);xhr.send();...

function onLoad(e) {var type = this.responseType; // e.g., "arraybuffer"var bytes = new Uint8Array(this.response);

};

"" (text), "text", "json", "arraybuffer", "document", or "blob"

Cross-Domain Calls with XMLHttpRequest Level 2

No One Knows What Touch Will Look Like in HTML5

Original Touch Events specification was based on Safari touch API

http://www.w3.org/TR/touch-events/

Originally blessed by Apple, work stopped in 2012 due to patent considerations

Patent issues were settled and Touch Events were formalized in 2013

Newer Pointer Events API is based on pointer events in Internet Explorer

http://www.w3.org/TR/pointerevents/

Many at W3C were wary of Apple and were searching for an alternative touch API; Microsoft responded

Future looked bright for a while, but Chromium dropped support for pointer events in August 2014

In March 2015, Google announced that Chrome would support pointer events

It's anybody's guess what will happen next

Detecting Presses and Releases with the Pointer API

var canvas = document.getElementById("#canvas");canvas.addEventListener("pointerdown", onPointerDown, false);canvas.addEventListener("pointerup", onPointerUp, false);

function onPointerDown(e) {// Pointer pressed

}

function onPointerUp(e) {// Pointer released

}

Getting the Pointer Type

function onPointerDown(e) {switch (e.pointerType) {

case "mouse":alert("You used a mouse!");break;

case "pen":alert("You used a pen!");break;

case "touch":alert("You used a finger!");break;

}}

Pointer Events

New APIs Will Keep HTML5 Relevant for a Long Time

HTML5 is constantly evolving with new APIs, many of them needed for mobile

apps, apps that deal with media content, and apps that network

Device-motion API

Media Capture and Streams (getUserMedia) API

WebRTC API

Web Notifications API

Web Speech API

Web NFC API

Web Cryptography API

Battery Status API

And many more…

Using the Device-Motion API

window.addEventListener("devicemotion", onMotionChanged);...

function onMotionChanged(e) {// Accelerations expressed in meters/second2 (1G == 9.81)var ax = e.acceleration.x; // Acceleration in X directionvar ay = e.acceleration.y; // Acceleration in Y directionvar az = e.acceleration.z; // Acceleration in Z direction

// Rotation rates expressed in degrees/secondvar rx = e.rotationRate.alpha; // Rate around Z axisvar ry = e.rotationRate.beta; // Rate around X axisvar rz = e.rotationRate.gamma; // Rate around Y axis

}

Using the getUserMedia API

// Request webcam accessnavigator.getUserMedia({

video: true, // Request webcam accessaudio: true // Request microphone access

}, onMediaReady, onError);...

function onMediaReady(stream) {// Play the audio/video stream in a VIDEO elementvar video = document.getElementById("video");video.src = window.URL.createObjectURL(stream);video.play();

}

Using the Battery Status API

navigator.getBattery().then(function(battery) {// Get the battery levelvar level = battery.level; // 0.0 to 1.0

// If the battery is charging, get the remaining charge timeif (battery.charging) {

var time = battery.chargingTime; // Seconds}

});

Some of the Best Parts of HTML5 Aren't Part of HTML5

All HTML5 browsers support a native JSON API

JSON.stringify - Generate a JSON string from an object

JSON.parse - Generate an object from a JSON string

Modern selectors API provides more flexibility than document.getElementById

document.querySelector

document.querySelectorAll

WebGL offers hardware-accelerated rendering for 2D and 3D graphics

Specification maintained by non-profit Khronos Group

Generating and Consuming JSON

// Generate a JSON stringvar person = { firstName: "Jeff", lastName: "Prosise" };var json = JSON.stringify(person);

// Consume the JSON stringvar somebody = JSON.parse(json);var firstName = somebody.firstName;

Querying the Browser DOM

// Get all elements whose class is "content"var elements = document.querySelectorAll(".content");

// Get all checkboxes that are checked in "myform"var elements = document.querySelectorAll

("#myform input[type='checkbox']:checked");

// Set the background color of every other row of "mytable"// to light grayvar rows = document.querySelectorAll

("#mytable tr:nth-child(even)");

for (var i = 0; i < rows.length; i++) {rows[i].style.backgroundColor = "#e0e0e0";

}

Download the Code

http://1drv.ms/1tO5j5Y

top related