never bet against the open web

118
© SitePen, Inc. All Rights Reserved Never Bet Against the Open Web presents

Upload: sitepen

Post on 09-May-2015

7.250 views

Category:

Technology


4 download

DESCRIPTION

Never Bet Against The Open Web - Rich Web Experience 2011

TRANSCRIPT

Page 1: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Never Bet Against the Open Web

presents

Page 2: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Nice to Meet you

Co-Founder of Dojo Toolkit

CEO, SitePen, Inc.

President, Dojo Foundation

Dylan Schiemann

@dylans @sitepen @dojo

Page 3: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

This talk was very different just six months ago.

Page 4: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

IE6, Flash and Silverlight Liberation Movement

Page 5: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"Flash to Focus on PC Browsing and Mobile Apps; Adobe to More Aggressively

Contribute to HTML5"

- Danny Winokur, VP & GM, Interactive Development at Adobe

Page 6: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"Silverlight is %&#ing dead... most of the team have been split apart and others have

left the company altogether."

- Scott Barnes, former Rich Platforms Product Manager at Microsoft for the Silverlight team

Page 7: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"Technologies that lock things down tend to lose in the end. People want freedom

and markets want freedom."

- Linus Torvalds, talking about App Stores and Windows 8 Secure Install

Page 8: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"SUN has lost a huge opportunity while not leveraging JWebPane"

- Dominique De Vito

Page 9: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"Project Avatar: One HTML5 Strategy to Rule Them All... unifying ME and EE means agreeing on JSON

as a communication mechanism for passing objects back and forth. And it also means

leveraging Web Sockets"

- TheServerSide.com

Page 10: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

"IE 6 and 7: A Plague Upon Us That Must Die a Bloody Death

Chrome Frame: aka the IE Antivirus or Tapeworm"

-Me, 2009

Page 11: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Where did Flash/Flex and Silverlight Fail?

They tried to replace the web, rather than improving it.

Apple said no.

Developers said no.

HTML5 tsunami.

Chrome and Firefox rate of updates.

Adobe and Microsoft started listening.

Major enterprises contribute

IBM, AOL to Dojo

Adobe, Microsoft to jQuery

Page 12: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Browser Economics: Standards

0% 25% 50% 75% 90% 100%

Cos

t*

Standards Compliance*Cost is an artificial number factoring in R&D and opportunity costs

Page 13: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Key Open Web Components

Tools you need to build great apps and user experiences

Simplicity: content, fast and efficient, easy to parse, hyperlinks, style, standard, easy to distribute

HTTP(S), TCP/IP

HTML(5), CSS(3), JavaScript

Vector graphics (Canvas and SVG)

WebSockets/Comet, Local Storage/Offline, Data/IndexedDB, WebGL, Audio/Video, etc.

Page 14: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Evolution of Web App Development

https://secure.flickr.com/photos/bytemarks/4733371072/sizes/l/in/photostream/

Page 15: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Evolution of Web App Development

https://secure.flickr.com/photos/dylans/3439037456/

Web 1.0

Dumb client, smart server

Focus on HTML & CSS, "separation of markup and presentation"

Page 16: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Evolution of Web App Development

Web 2.0

Smarter client, smart server, con$ict

Initial break of many paradigms

Search indexing, history, navigation

Didn't really account for mobile

DOM-centric

Ajax: sort of real-time

Page 17: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

https://secure.flickr.com/photos/dylans/5206483166/

We Want More

Page 18: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Revolution: Separation of Data and UX

Users want access to data, info

in a variety of experiences

relevant to their current context

Aggregation

User Interfaces and experiences

Challenging past assumptions

statelessness, truly embracing REST

abusing markup for "separation of markup and presentation"

control and federation of data

https://secure.flickr.com/photos/dylans/5916167025/

Page 19: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Multifarious Experiences

Page 20: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Considerations for Modern Apps

Data vs. presentation

Context switching

Packaging

Testing & monitoring

Choice

Real-time considerations

Convenient APIs and approaches to development

Page 21: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Ok. But How?

Page 22: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

https://secure.flickr.com/photos/dylans/5205890223/

One Bite at a Time.

Page 23: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

4 Scenarios in Depth

Modules with AMD

Server-Side JavaScript

Data Separation with Object Stores

Shimming and extending CSS

Page 24: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

AMD

Page 25: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

What is AMD?

Stands for Asynchronous Module De%nition

A grassroots standard for de%ning interoperable code modules

Allows the same code to run on both client and server

Originally a CommonJS proposal, now independent

Includes a plugin framework for additional extensibility

Default module system for Dojo 1.7+

Page 26: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

AMD Basics

Replaces dojo.provide, dojo.require, dojo.requireIf, dojo.requireAfterIf, dojo.platformRequire, and dojo.requireLocalization

Creates two global functions, require and define

define.amd is used to indicate that define is actually an AMD-compatible loader and not some random function

Modules are grouped into collections called packages; dojo, dijit, and dojox are all examples of packages

Modules normally have a 1:1 mapping to %les (except when built)

Page 27: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Why AMD is Awesome

Easy to mix and match code from different projects without risk of name collisions or dependency con$icts

Loads and executes dependencies asynchronously and in parallel; much faster during development

Supports cross-domain loading out of the box, no special builds required

Supports all debuggers out of the box, no need for hacks like debugAtAllCosts or forcing xdomain loading

Trivial to load multiple versions of the same package, or load two different packages with the same name, or patch a single module with another module

Page 28: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

AMD Module Identi%ers

Look like path fragments; e.g. dijit/form/Button

Work a lot like paths, too; relative path fragments like "./" and "../" can be used to refer to other modules within the same package 

Necessary for fully portable packages

Can be aliased/overridden to point to different code

Loaders currently differ on how to do this

Page 29: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Loading non-AMD code

Special module identi%ers can be used to load arbitrary, non-AMD scripts as dependencies, in which case the module's returned value will be unde%ned:

Any identi%er starting with "/"

Any identi%er starting with a protocol (e.g. "http:", "https:")

Any identi%er ending with ".js"

Page 30: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

AMD Modules

De%ned with the define function

Not actually resolved until they they are required (lazy instantiation)

Factory is only called once; the return value is cached by the loader and shared between all modules

Special plugin modules exist to extend loader functionality

Page 31: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Con%guring AMD Loaders

Given this directory structure, the con%guration would look like so:require({  baseUrl: "js/",  packages: [    { name: "dojo", location: "lib/dojo" },    { name: "dijit", location: "lib/dijit" },    { name: "dojox", location: "lib/dojox" },    { name: "my", location: "my" },    { name: "util", location: "util" },    { name: "external", location: "http://foo.com/external" }  ]});

Page 32: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Con%guring AMD Loaders

baseUrl: de%nes the base path for all modules; can be relative or absolute

Relative values are relative to the HTML %le in browsers and relative to the current working directory on servers

packages: de%nes all of the packages registered for the application 

name is the name of the package

location is the location of the package; relative paths are relative to baseUrl

main is the name of the module that will be loaded if someone tries to require the package itself; this defaults to "main" (e.g. requiring "dojo" will load the "dojo/main" module)

Page 33: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Con%guring AMD Loaders

Many other con%guration options exist; only packages is really necessary for a working application

If baseUrl and tlmSiblingOfDojo are both not set, Dojo 1.7's loader uses the directory above the dojo/ directory as baseUrl

Page 34: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

require()

require takes three arguments:

configuration: Optional, a con%guration object for the loader

dependencies: Optional, an array of strings as a list of module identi%ers to load before calling the callback

callback: Optional, a function to call when dependencies are loaded

What does it do?

Recon%gures the loader at runtime

Loads modules and executes an optional callback when they are loaded, passing loaded modules into the callback as arguments

Page 35: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// We're not using the configuration object here,// just an array of requirements and a callbackrequire(["dojo", "populizr/app"], function(dojo, app){ // Do something with dojo and app});

// The same code in the legacy systemdojo.require("populizr.app");dojo.ready(function(){ // Do something with dojo and populizr.app})

require()

Page 36: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

de%ne()

define takes three arguments:

moduleId: Optional, a string to explicitly identify the module

dependencies: Optional, an array of strings as a list of module identi%ers to load before calling the factory

factory: The value of the module, or a function that returns the value of the module

What does it do?

De%nes the value of a module

Typically the moduleId is reserved for the build system - don't explicitly identify your modules!

Page 37: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// Creating a widget old styledojo.provide("populizr.TemplatedWidget");

dojo.require("dijit._WidgetBase");dojo.require("dijit._TemplatedMixin");

dojo.declare("populizr.TemplatedWidget", [dijit._WidgetBase, dijit._TemplatedMixin], { templateString: dojo.cache("populizr","templates/TemplatedWidget.html");});

Creating a widget before

Page 38: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// Creating a widget with AMDdefine( ["dojo/_base/declare", "dijit/_WidgetBase", "dijit/_TemplatedMixin", "dojo/text!./templates/TemplatedWidget.html"], function(declare, _WidgetBase, _TemplatedMixin, template){ return declare([_WidgetBase, _TemplatedMixin], { templateString: template }); });

// Note how the dependencies map into the function call!

Creating a widget with declare

Page 39: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// In populizr/config.jsdefine(["populizr/app"], { enabled: true, animDelay: 500});

The value given for a module can also be just a plain object

In this case, the dependencies will still be resolved as normal, but obviously will not be passed to the factory, since it is not a function

de%ne()

Page 40: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

de%ne()

Differences between these two methods:

AMD is less verbose

AMD is fully self-encapsulated; no references to global variables or the module's own package name

Faster scope lookups

Better mini%cation

Impossible to forget a dependency and still have working code

Zero global namespace pollution

Completely portable

Page 41: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Conditional requires

Use cases for conditional requirements:

Dependencies that cannot be determined until runtime

dojox/gfx uses this concept to decide which rendering engine to use (VML, SVG, canvas, etc)

Modules that you only want to load when a certain condition occurs (con%guration, event, etc)

Page 42: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Special Module Names

requireContext sensitive require

Relative module lookups don't work with global require

exportsAn object that is the initial value of the module

If you are returning an object with functions de%ned on it, use this instead of creating and returning a new object

Page 43: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

define(["dojo", "require", "dojo/domReady!" ], function (dojo, require) { var debugButton = dojo.create('input', { type: 'button', value: 'Debug' }, dojo.body());

dojo.connect(debugButton, "click", function () { require([ "./debugger/console" ], function (console) { console.open(); }); });});

Special Module Names

Page 44: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Plugins

Extend AMD loaders in lots of useful ways

Common plugins available with most loaders are "text", "i18n", and "domReady"

Plugin dependencies are identi%ed by the exclamation point in the module identi%er: "dojo/text!", "dojo/i18n!", "dojo/domReady!"

Data to the left of the "!" identi%es the plugin to load; data to the right of the "!" is passed to the plugin for processing

Page 45: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// in populizr/quoteLogger.jsdefine([ "dojo/text!./quotes.txt" ], function (quotes) { // quotes will simply be the content of the file, // so we'll split on newlines var quotes = quotes.split("\n"); // Write out a random quote to the console console.log(quotes[Math.floor(quotes.length * Math.random())]);});

Loads a string from a %le

Replaces dojo.cache

Used mostly for loading template strings, but can load any string

Build system interns strings loaded using dojo/text, just like dojo.cache

Compatible with RequireJS's text plugin

dojo/text

Page 46: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

define( [ "dojo/i18n!dijit/nls/common", "dojo/i18n!dijit/nls/common/it" ], function (common, commonIT) { console.log(common.buttonCancel); // "Cancel" console.log(commonIT.buttonCancel); // "Annula" });

Loads an internationalization bundle

Replaces dojo.requireLocalization and dojo.getLocalization

Compatible with RequireJS's i18n plugin

dojo/i18n

Page 47: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

define([ "dojo/domReady!" ], function () { console.log("DOM is ready!");});

Ensures the module does not resolve until the DOM is ready

Replaces dojo.ready

Compatible with RequireJS's domReady plugin

dojo/domReady

Page 48: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// in populizr/configureEvents.jsdefine( [ "dojo/has!dom-attachEventListener?./events/w3cHandlers:./events/ieHandlers" ], function (eventHandlers) { // Do something with eventHandlers });

Allows modules to be conditionally loaded, using has.js features

Replaces dojo.requireIf

dojo/has

Page 49: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Portable Modules

moduleId should never be speci%ed explicitly in a de%ne call (it is for build tools)

dojo.declare should never specify the name of the class being declared (unless creating declarative widgets)

If you want to create private classes, remember you can just assign the return value of dojo.declare to a local variable

Dependencies to modules within a package should always use relative module identi%ers

Page 50: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Portable Modules

Using global variables is verboten

There are some areas where this is still required (some Dijits break the rules and declare multiple classes), but should improve beyond 1.7

This is especially relevant if you are de%ning a module without a factory function; if you have any direct dependencies, you should be using a factory function

Conditional requires with relative module identi%ers must use a context-sensitive require

Page 51: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Caveats

Speci%cation is still in $ux, making true interoperability difficult

Some examples here only work in the Dojo 1.7 loader

The spec has been agreed upon by Dojo, MooTools, and jQuery

There are actually no other real caveats, AMD is awesome

Page 52: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

https://github.com/kriszyp/commonjs-package-template/blob/master/component.js

Module Template

Page 53: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

60 Packages and growinghttp://packages.dojofoundation.org/

Dojo Foundation Packages

Page 54: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Server-Side JavaScript

Page 55: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Persevere

REST server for HTML5/Ajax applications

JavaScript persistence framework

Pluggable storage: MongoDB, Redis, CouchDB, MySQL, etc.

Real-time data noti%cations

High performance, asynchronous, scalable

End-to-end JavaScript

SSJS: Extends Node.js or Narwhal+Jack (and perhaps Ringo)

Page 56: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Persevere Design Philosophy

Designed for applications with signi%cant client-side logic

Thin-server applications, zero to minimal server-side code needed

Standards-based, HTTP/REST

Promise-based asynchronicity for scalability and composibility

Modular design, JavaScript everywhere

Each package can be used on its own

Some can be used in browser too

Page 57: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Packages/Sub-Projects

Persevere consists of a number of sub-projects

Cohesively come together for full JavaScript end-to-end stack

Page 58: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Packages/Sub-Projects

Pintura - JSGI based RESTful web framework (standard HTTP middleware API)

Perstore - Persistence framework

Tunguska - Distributed pub/sub framework with Comet noti%cations

RQL - Resource Query Language engine

Promised-IO - Promise-based IO with cross-platform normalization

Page 59: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Packages/Sub-Projects (cont.)

Patr - Promise-based asynchronous test runner

Persevere - Client side data explorer, dependency set

Jsgi-node - JSGI middleware for Node

Multi-node - Scales Persevere across multiple process

Templify - JavaScript template engine

JSON Schema - JSON Schema validator and link handler

Page 60: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

https://github.com/kriszyp/perstore/blob/master/package.json

Each Package is an AMD Module!

Page 61: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Persevere Example Wiki

Good starting point

Project layout

Top level app.js

security

models, page, page-change

wiki media handler

Page 62: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Pintura

HTTP/REST Interaction

GET /Model/id - Get object

POST /Model/ - Create object

PUT /Model/id - Full update (or create) object

POST /Model/id - Incremental update object

DELETE /Model/id - Delete object

GET /Model/?name=value - Query for objects

Page 63: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

newApp = MiddleWare(app); // take an app, add functionality

appWithProtection = // compose functionality CSRFDetect( Session( Authentication(app) ) );

Set of Middleware components

cross-site request forgery protection

cross-domain

authentication

Many more

Pintura

Page 64: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Pintura

Security

Authentication and delegation to authorization mechanisms

Error handling - conversion to HTTP status codes

Content negotiation

Negotiates best media type for a resource

Bulk updates via message/JSON

Range requests

Uses HTTP range units for data paging

Page 65: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Perstore

Persistence framework for data model construction

Data models API based on HTML5 IndexedDB API (get, query, put, delete)

De%ne property constraints using JSON Schema

Perstore provides validation

De%ne prototype of objects

Provides a transaction manager

Page 66: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

DataModel.query().eq(“name”, “Smith”).sort(“age”).forEach(function(item){ // act on each item in result set});

Pluggable data stores

MongoDB, Redis, CouchDB, MySQL, in-memory

Store wrappers used like middleware to add functionality

Data models are a store wrapper

Chainable querying

Perstore

Page 67: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Persevere Template

Using as a starting point for new applications

Templates for:

Model %les

Security

HTTP con%guration

Page 68: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Persevere Explorer

Data model explorer from the browser

Provides visual interface to data

Edit data directly in explorer

Page 69: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Objects Stores and IndexedDB

Page 70: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Why Object Store?

Separate UI from data handling

Independent evolution of UI components and data components

Object Store API redone in 1.6, follows the HTML5 IndexedDB object store API.

Positioned as successor to Dojo Data API

Also aligns with dojox.storage API

Page 71: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Data Backed Objects

A uniform API can provide access to data that comes from any source

In Dojo

Many widgets

The Grid

Charting

Django Template Language

Page 72: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Dojo Store Architecture

Tree Grid ComboBox

CustomStoreJsonRestMemory

Dojo Store API

Page 73: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

What it Provides

Uniform data access layer

Primarily an API speci%cation, but Dojo and DojoX include several implementations of various stores

Variable feature set, with feature discovery

Data is represented as JavaScript objects

Page 74: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Responsibility of Stores

Stores may delegate responsibilities to the server

Associate Items w/ Identifiers

Handle Queries

Sort Data

Save Data Changes

Trigger Notifications

Page 75: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Design Philosophy

Feature Detection LayerNo Separate Interfaces; Implement What is Needed

Simple Core APIEasy to Implement

Object Property MutationUse Plain JS Objects, Directly Access & Mutate Properties

(instead of data items)

Page 76: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Resource Oriented Programming

REST concepts applied to programming

Uniform interface

Layering, store wrappers can be used to add functionality

Easy to implement simple store, add wrappers for more advanced capability

Cacheable

Page 77: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Promise-Based, Functional

Same API for sync and async stores

async returns promises instead of values

sync stores can be used without callbacks for simplicity

dojo.when makes it easy to use stores generically (sync or async)

Highly functional query results, useful iterative functions

Noti%cations built around query results

Page 78: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Dojo Object Store API

Page 79: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Basic API

get(id, options) - Gets an object by identity

query(query, options) - Performs a query

put(object, options) - Stores/updates an object

add(object, options) - Adds an object to the store

remove(id, options) - Deletes an object

getIdentity(object) - Get the identity from an object

Page 80: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

foodStore = new dojo.store.JsonRest({ target: "/Food/"});

foodStore.get("cherry").then(function(cherry){ cherry.color = "red"; foodStore.put(cherry);});foodStore.remove("pickle");

foodStore = dojo.store.Observable(foodStore);

var query = foodStore.query({color:"red"});query.forEach(function(food){...});query.observe(function(object, oldIndex, newIndex){...});

Simple Example

Page 81: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Query Results

Query results object includes methods:

forEach

map

%lter

Based on Array methods, but always there, and may be asynchronous

total - count of all items when a range is used (can be a promise)

Provided by dojo/store/util/QueryResults

Page 82: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

var query = foodStore.query({color:"red"});var renderedNodes = [], i = 0;query.forEach(function(food){ renderedNodes[i++] = renderFood(food);});query.observe(function(food, oldIndex, newIndex){ // on a data change if(oldIndex > -1){ var oldNode = renderedNodes.splice(oldIndex, 1); dojo.destroy(oldNode); } if(newIndex > -1){ renderedNodes.splice(newIndex, 0, renderFood(food)); }});dojo.when(query.total, function(total){ renderTotal(total + " total foods");});dojo.when(query, renderDone);

Using Query Results in a Widget

Page 83: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Query Engines

Pluggable engine

Used by client-side store (Memory) for %ltering

Default is provided (dojo.store.util.SimpleQueryEngine), you can override with custom or alternate engine

RQL makes a good alternate engine

https://github.com/kriszyp/rql

Page 84: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

ProvidedObject Stores

Page 85: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Core Stores

Concrete Stores

Memory - In memory

JsonRest - Connected to store through HTTP/REST

DataStore - Adapter for old Dojo Data stores

Store Wrappers

Observable

Page 86: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/store/Memory store

Similar to ItemFileReadStore/ItemFileWriteStore

Provide a set of data with the data argument

Uses client-side %ltering/querying

Very simple and lightweight

Page 87: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/store/JsonRest

Server-side store

Similar to old JsonRestStore

Follows HTTP/REST interface

GET, PUT, POST, DELETE

Lightweight, little work done on client-side

Page 88: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/store/DataStore

Adapter for legacy Dojo Data stores

Provide a Dojo Data store, returns an object store

Can be used by new widgets with older stores

Page 89: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/data/ObjectStore

Adapter for legacy Dojo Data widgets

Provide an object store, returns an Dojo Data store

Can be used by legacy widgets with newer stores

Page 90: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// Create the memory-based object storememoryStore = new MemoryStore({ data: data});

// Create the dojo.data adapterdataStore = new ObjectStore({ objectStore: memoryStore, labelProperty: "author"});

// Pass it to the new treetree = new Tree({ store: dataStore, onDblClick: function(item){ alert(item.content); }}, dojo.byId("tree"));

Example: Using Object Store with Adapter

Page 91: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Store Wrappers

Page 92: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Store Wrapper

Takes a store, returns one with added functionality

Cache, validate, etc.

Like middleware for stores

Page 93: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/store/Cache

Provides caching of a master store to a cache store

Typical con%g:

dojo/store/JsonRest is master

dojo/store/Memory is caching store

Useful when data to be remotely retrieved, but frequently locally accessed

Page 94: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

dojo/store/Observable

Designed to notify listeners of how data changes affect rendered query results, rather than just notifying.

Preserves sort order

Omits new objects that don't match %lter

Adds changed objects that do match %lter now

Widgets can observe() a result set and properly update UI

Page 95: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

// First wrap a storestore = new dojo.store.Observable(store);

// Now we can queryvar results = store.query({name:"value"}, {start:0, count:10});

// And observe the resultsresults.observe(function(changedObject, removedFromIndex, insertedIntoIndex){ // Notified of changes});

Store wrapper for noti%cations, can wrap any store

Adds observe() method to query results

dojo/store/Observable

Page 96: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Handle Observed Events

If no query engine (JsonRest by default), index won't be provided (not known)

Store Event Observed

removedFromIndex insertedIntoIndex

Both WholeItem was moved

Both EqualUpdated, not moved

Both -1Positions not known

-1Wasn’t in result set before

-1Removed from result set

Page 97: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

socket.on("message", function(event){ store.notify(event.object, event.existingId);});

Observable also adds notify() method

Call notify() to notify of changes from server

Comet Noti%cations with Observable

Page 98: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Hierarchy

Implement getChildren for hierarchical stores, to get the children

Two hierarchy strategies:

Objects have a children array

Preserves/indicates order of children

Useful for smaller lists of children

Objects have a parent reference

Query by parent to get children

Useful for large lists of unordered children

Page 99: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

XStyle

Page 100: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

XStyle

Framework for shimming and extending CSS

Handles loading CSS

Parsing CSS

Uses CSS plugins to handle speci%c shims and extensions

Page 101: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Design Philosophy

Future-oriented

Embrace and enable CSS3 and HTML5 technologies

Write code that will gradually get less dependent on framework

Learn technologies that you will continue to need to know

Leverage familiar paradigms

CSS3

Only load what is needed

Lighter loads on modern browsers

Page 102: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Design Philosophy

Presentation Separation

CSS is the presentation layer for HTML

Stop abusing HTML!

Progressive Loading

Modules don’t encourage progressive loading

Shims and extensions are explicit, no magic

Performance

Need to control when applied, under some situations shims can have more performance degradation then is worth it

Page 103: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

.my-class {border-radius: 5px;box-shadow: 10px 10px 5px #999;transition: 0.5s ease-in;

}

.my-class:hover {color: rgba(255,255,100,100);

}

Shimming/Poly%lling

Page 104: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

@import url(xstyle/shims.css);

.my-class {border-radius: 5px;box-shadow: 10px 10px 5px #999;transition: 2s ease-in;

}

.my-class:hover {color: rgba(255,255,100,100);

}

Shimming/Poly%lling

Page 105: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Shimming

De%ne properties with

x-property {...}

De%ne pseudos with

x-pseudo {...}

Possible values

default

pre%x

module: require(shim/module)

Generally use native/default %rst if available

Page 106: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

x-property {border-radius: default, prefix;box-shadow: default, prefix;transition: default, prefix, require(xstyle/shim/transition);

}x-pseudo {hover: default, require(xstyle/shim/pseudo);

}// ^imported shims.css.my-class {border-radius: 5px;box-shadow: 10px 10px 5px #999;transition: 2s ease-in;

}

.my-class:hover {color: rgba(255,255,100,100);

}

Shimming/Poly%lling

Page 107: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Extensions

Works just like shims

Generally don’t use native/%rst, without a standard we need to preserve behavior

Page 108: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

@import url(xstyle/ext.css);.my-widget {-x-widget: {type: dijit/Tree;store: treeStore;

};-x-resizable: xy;border-radius: 5px;

}

Extensions

Page 109: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Shimming HTML5 with Extensions

Use :unsupported pseudo to apply speci%c widgets when functionality is missing.

Page 110: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

@import url(xstyle/ext.css);progress:unsupported {-x-widget: {type: dijit/ProgressBar;

};}

input[type=range]:unsupported {-x-widget: {type: dijit/form/HorizontalSlider;

};}

Shimming HTML5 with Extensions

Page 111: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Fixing @import

Fix deep level @imports in old IE

Enforces @import-once behavior on browsers

Predictable style overrides

Page 112: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Spin off: put-selector

CSS Selector based DOM node creation and manipulation

One of our favorite new tools

Faster than templating

More consistent

Keep context within code

Page 113: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

put(target, ‘div’);put(target, ‘div.my-class’);put(‘input[type=checkbox].my-input’);put(target, ‘.add-a-class’);put(target, ‘[tabIndex=1]’);put(‘span.has-content’, ‘Hello, World’);put(target, ‘div.has-child’, child,‘div.great-great-grandchild’);put(target, ‘+div.after-target+div.after-that’);put(target, ‘-div.before’);put(‘table tr td << tr td’);put(‘div label.name $ +input[type=text][value=$’, ‘Name’, ‘Value’);put(target, ‘!remove-class[!remove-attribute]’);

Fun with put-selector

Page 114: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

define([‘xstyle/has-class’], function(hasClass){ hasClass(‘mozilla’, ‘no-quirks’, ‘ie-6’, ‘ie-6-7’);});

...

<html class=”has-mozilla has-no-quirks”>

...

<html class=”has-ie-6 has-ie-6-7”>

xstyle/has-class - has() based doc classes

Page 115: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Other Future Possibilities

Generative CSS

Create elements for the rules in CSS

Skip the middleman!

JSON StyleSheets

StyleSheet to be applied to JSON

Could be generative

Could be used on non-HTML platform

Return of JSSS </evil laugh>

Page 116: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Result: Modular Tools

Tools to mix and match to create your app

Separate data from UI logic simply and seamlessly

Modular enough for very simple projects, $exible and consistent enough to handle the most challenging, feature-rich web apps

Page 117: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

Page 118: Never Bet Against The Open Web

© SitePen, Inc. All Rights Reserved

SitePen: We help our clients build great apps.

Web App Development, Design, Advice

Support & Training

Strong advocates and contributors of FOSS

Works with some amazing companies and organizations: