These Aren't the Sites You're Looking For:

Modern Web Applications

  -  

Of course we're using Geolocation!

Mike West: +Mike West, https://mikewest.org, @mikewest

Agenda

HTML5/Cloud + Native/Desktop = Modern Web App

Tight Focus

A great web application has a tight focus encouraging people to actively interact, engage, and accomplish something.

Provide Rich Visuals

A great web application provides rich visuals that will delight the eye without distracting the mind.

Great User Experiences

A great web application uses the latest web technologies enhance the user experience, so users can complete their work faster, easier and with confidence.
Because of [insert scary Chromium internals here], synchronous APIs are a bad idea. Asynchronous APIs are more complex, but better.
object.method({ /* ... */ }, function(data) {
  // Callback that does something with `data`
});

How do we create great user experiences?

Make it easy to try & use

Use responsive layout for different form factors

Media Queries for Style Sheets

<link rel="stylesheet" media="all" href="/static/css/base.min.css" />
<link rel="stylesheet" media="only screen and (max-width: 800px)" 
  href="/static/css/mobile.min.css" />

Testing CSS media queries in JavaScript with window.matchMedia()

if (window.matchMedia('only screen and (max-width: 480px)').matches) {
  // Asynchronously provide experience optimized for phone
} else if (window.matchMedia('only screen and (min-width: 481px) and ' +
                             '(max-width: 1024px)').matches) {
  // Asynchronously provide experience optimized for table or smaller screen
} else {
  // Asynchronously provide full screen experience
}

http://formfactorjs.com

Allow for deep linking & single page navigation

function updateHash(push) {
  if (push) {
    var slideNo = curSlide + 1;
    var hash = '#' + slideNo;
    window.history.pushState(slideNo, 'Slide ' + slideNo, hash);
  }
};
window.addEventListener('popstate', handlePopState, false);
function handlePopState(event) {
  if (event.state != null) {
    curSlide = event.state - 1;
    updateSlides(true);
  }
};

http://www.leviroutes.com

Make uploading files easier

<input type="file" id="dir-select" webkitdirectory />
document.querySelector('#dir-select').onchange = function(e) {
  var out = [];
  for (var i = 0, f; f = e.target.files[i]; ++i) {
    out.push(f.webkitRelativePath);
  }
  document.querySelector('output').textContent = out.join('/n');
};

Use desktop file handling paradigms

<a href="src/star.mp3" draggable="true" class="dragout"
  data-downloadurl="MIMETYPE:FILENAME:ABSOLUTE_URI_TO_FILE">
download
</a>
var files = document.querySelectorAll('.dragout');
for (var i = 0, file; file = files[i]; ++i) {
  file.addEventListener('dragstart', function(e) {
    e.dataTransfer.setData('DownloadURL', this.dataset.downloadurl);
  }, false);
}
Drag each of these files onto your desktop: 3D Glasses [PDF] Star [MP3]

( this feature is only available in Google Chrome )

Use desktop file handling paradigms

document.querySelector('#dropzone').
  addEventListener('drop', function(e) {
    var reader = new FileReader();
    reader.onload = function(evt) {
      document.querySelector('img').src = evt.target.result;
    };
    reader.readAsDataURL(e.dataTransfer.files[0]);
}, false);
Drop in images from your desktop

Save data to the local file system

window.requestFileSystem(TEMPORARY, 1048576, initFs, fsError);
function saveFile(arrayBuffer, filename, type, callback) {
  fs.root.getFile(filename, {create: true}, function(fileEntry) {
    fileEntry.createWriter(function(fileWriter) {
      var bb = new BlobBuilder();
      bb.append(arrayBuffer);
      fileWriter.write(bb.getBlob(type));
    }, fsError);
    callback(fileEntry);
  }, fsError);
}
Browse File System

Make it work offline

Application Cache to enable the application

<html manifest="cache.appcache">

Store data locally

window.requestFileSystem(PERSISTENT, 1048576, initFs, fsError);
var idbRequest = window.indexedDB.open('Database Name');
localStorage["key"] = "value";

Track online and offline states

window.addEventListener('online', function(e) {
  // Re-sync data with server.
}, false);

Persist users data

var elems = document.querySelectorAll("textarea, input");
var len = elems.length;
for (var i = 0; i < len; i++) {
  var elem = elems[i];
  elem.addEventListener("input", function(item) {
    localStorage[formName + "-" + item.srcElement.id] = 
      item.srcElement.value;
    var debug = document.getElementById("data-persistence-debug");
    debug.innerHTML = "Last auto-saved at: " + new Date();
  }, false);
}

LawnChair - simple json storage

Let the user tell you what they want

<input type="text" x-webkit-speech />
function startSearch(event) {
  if (event.target.results.length > 1) {
    var second = event.target.results[1].utterance;
    document.getElementById("second_best").value = second;
  }
  event.target.form.submit();
}

Keep your user informed

function showNotifications(pic, title, text) {
  if (window.webkitNotifications.checkPermission() == 0) {
    var notificationWindow = 
      window.webkitNotifications.createNotification(pic, title, text);
    notificationWindow.show();
    
    // close notification automatically after a timeout    
    setTimeout(function(popup) { 
      popup.cancel();
    }, 6000, notificationWindow);
  }
}

Treat performance like a feature

Use Application Cache to provide local caching

<html manifest="cache.appcache">

Store data locally

window.requestFileSystem(PERSISTENT, 1048576, initFs, fsError);
var idbRequest = window.indexedDB.open('Database Name');
localStorage["key"] = "value";

Use CSS3 transitions, transforms and animations

transition: all 1s ease-in-out;

Use WebWorkers for non-blocking JavaScript

var worker = new Worker('myworker.js');

More great tips at http://bit.ly/rizNVE

How about older browsers?

Chrome Frame

<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">

Other helpful libraries

Make it easy for user to discover great apps, extensions, and themes
Make it easy for developers and brands to reach the 200+ million Chrome users
  • No review or approval process
  • No restrictions on advertising
  • No restrictions on the platform

Available in 41 Languages

Play 23% more and spend 147% more
100% more engagement
Step 1. Create application manifest
Step 2. Upload manifest & graphics
Step 3. Publish

OR

AppMator

Chrome Web Store manifest file

{ "name": "My Chrome Web Store",
  "description": "Discover great apps, games, extensions and...",
  "version": "1.0", 
  "icons": {
    "16": "16.png",
    "128": "128.png"
  },
  "app": {
    "urls": ["*://chrome.google.com/webstore"],
    "launch": { 
      "web_url": "https://chrome.google.com/webstore"
    }
  },
  "permissions": ["unlimitedStorage", "notifications"]
}

One last thing...

Aim for a great experience, everything else will follow.

chromestatus.com

HTML5Rocks.com

Resources

Developer Guides

Best Practices

Thanks!

Questions?

Slides:

The web is what you make of it.