Tuesday, March 31, 2015

Tracking Compliance and Scope Draft Published

The Tracking Protection Working Group has published a Working Draft of Tracking Compliance and Scope. This specification defines a set of practices for compliance with a user’s Do Not Track (DNT) tracking preference to which a server may claim adherence. Learn more about the Privacy Activity.





by Maria Auday via W3C News

Updated Candidate Recommendation of Media Source Extensions; Encrypted Media Extensions Draft Published

The HTML Working Group invites implementation of the Candidate Recommendation of Media Source Extensions. This specification extends HTMLMediaElement to allow JavaScript to generate media streams for playback. Allowing JavaScript to generate streams facilitates a variety of use cases like adaptive streaming and time shifting live streams.


The group also published a Working Draft of Encrypted Media Extensions. This proposal extends HTMLMediaElement [HTML5] providing APIs to control playback of protected content. Learn more about the HTML Activity.





by Maria Auday via W3C News

W3C launches first HTML5 Course in new partnership with edX - SDTimes.com









W3C launches first HTML5 Course in new partnership with edX

SDTimes.com

The World Wide Web Consortium (W3C), the global technical standards organization for the Web, announced today that it has joined edX, one of the world's leading online course platforms, as a new member and will offer its first course on HTML5 on 1 June ...







by via HTML5 news - Google News

W3C launches First HTML5 Course in new partnership with edX

In support of its on-going engagement to developer training programs, the W3C today announced a new member partnership with edX on its Massive Open Online Course (MOOC) platform under the name W3Cx. The W3Cx courses mean that thousands of developers around the world will have greater access to high quality training programs developed by W3C.


The first W3Cx course, HTML5-part 1, will focus on Web design fundamentals at an intermediate level. It is widely recognized that HTML5 is and will be the essential technology for organizations delivering applications across multiple platforms. HTML5-part 1 will be taught by Michel Buffa Professor at the University of Côte d’Azur (UFR Sciences). Read the course description and register for the W3Cx course HTML5-part 1 which starts 1 June 2015. To learn more, read the press release.





by Coralie Mercier via W3C News

Friday, March 27, 2015

WOW! adds HTML5 programming interface for streaming service - Rapid tv news









WOW! adds HTML5 programming interface for streaming service

Rapid tv news

The implementation is part of the WOW! Streamland service, available via the pay-TV provider's Ultra TV set-top boxes, which provide cable subscribers with an HTML5-based user interface. Streamland offers applications like Netflix and Toon Goggles ...







by via HTML5 news - Google News

Thursday, March 26, 2015

CSS Scroll Snap Points Module Level 1 First Public Draft Published; CSS Template Layout Module Note Published

The Cascading Style Sheets (CSS) Working Group has published a First Public Working Draft of CSS Scroll Snap Points Module Level 1. This module contains features to control panning and scrolling behavior with “snap points”. The group also published a Group Note of CSS Template Layout Module. A grid template can be seen as a cross between table layout and absolute positioning, and can also be associated with pages in paged media to create page templates. Learn more about the Style Activity.





by Maria Auday via W3C News

Monday, March 23, 2015

JavaScript Software Engineer / Entwickler - HTML5/CSS3/Angular - ElectronicsWeekly.com









JavaScript Software Engineer / Entwickler - HTML5/CSS3/Angular

ElectronicsWeekly.com

JavaScript Software Engineer / Entwickler - HTML5/CSS3/Angular. Recruiter. European Recruitment Ltd. Posted. 23 March 2015. Closes. 20 April 2015. Ref. GSC02BB. Contact. Gabrielle Seaton. Location. Dresden. Job Function. Applications Engineering.







by via HTML5 news - Google News

HTML5 Form Validation Example - TheServerSide.com









HTML5 Form Validation Example

TheServerSide.com

HTML5 has introduced a lot of changes welcomed by developers, including adding additional types of form input elements that helps in form processing activities like validation. Validating web forms has always been a painful task for many developers.







by via HTML5 news - Google News

Friday, March 20, 2015

Responsive Web Design Training Course; Early Bird Rate through 10 April

Today, W3C opens registration for a new session of the Responsive Web Design training course, to start 8 May 2015. This course leads students step by step through an approach that focuses on HTML and CSS to make Web sites work across devices. You will be working with viewport declarations and media-queries for responsive layout, responsive images, navigation, typography, tables, forms and video. Taught by trainer Frances de Waal, this course is 5 weeks long. Enroll before 10 April to benefit from the early bird rate! Learn more about W3DevCampus, W3C’s online training for Web developers and watch our fun intro video.





by Coralie Mercier via W3C News

6-Week HTML5/CSS3 Bootcamp at Artisan's Asylum - Scout Somerville








Scout Somerville



6-Week HTML5/CSS3 Bootcamp at Artisan's Asylum

Scout Somerville

Alright, let's get through this winter by tackling that website you keep meaning to do. Maybe you want to update your existing one because it's just so… outdated. Maybe you really want to add these skills to your resumé. Maybe you really want to ...







by via HTML5 news - Google News

Now You Can Use Beats Music With HTML5 In Safari For Mac - TechFrag









Now You Can Use Beats Music With HTML5 In Safari For Mac

TechFrag

If you are a music addict and can't stay away from it then Beats Music is the right subscribe. As a subscriber you know that Beats Music service can only give you amazing music if you have Flash up and running. If you are like me and despise Flash and ...







by via HTML5 news - Google News

Thursday, March 19, 2015

UI Events (formerly DOM Level 3 Events) Draft Published

The Web Applications Working Group has published a Working Draft of UI Events (formerly DOM Level 3 Events). This specification defines UI Events which extend the DOM Event objects defined in DOM4. UI Events are those typically implemented by visual user agents for handling user interaction such as mouse and keyboard input. Learn more about the Rich Web Client Activity.





by Maria Auday via W3C News

Tuesday, March 17, 2015

W3C Invites Implementations of Mixed Content

W3C and the Web Application Security Working Group invite implementation of “Mixed Content,” a specification that aims to improve web security by describing how a user agent should handle fetching of content loaded in a mixed security context. Specifically, it provides recommendations for the handling of content fetched over unencrypted or unauthenticated connections in the context of an encrypted and authenticated document. The WebAppSec WG, part of the Security Activity, welcomes comments on its public mailing list.





by Maria Auday via W3C News

Edited Recommendations for RDFa 1.1 Published

The RDFa Working Group has published four Edited Recommendations for RDFa 1.1, namely HTML+RDFa 1.1, RDFa Core 1.1, RDFa Lite 1.1, and XHTML+RDFa 1.1. The HTML+RDFa 1.1 Recommendation had to be updated now that both RDF 1.1 Concepts and HTML5 are Recommendations, in order to resolve dependencies and finalize the pending normative status of some HTML+RDFa 1.1 features. Using the opportunity of a republication of this document, the few editorial errata in all the RDFa 1.1 documents have also been taken care of. The Working Group has also published a new version of the RDFa 1.1 Primer Working Group Note. Learn more about the Data Activity.





by Maria Auday via W3C News

Web MIDI API Draft Published

The Audio Working Group has published an updated Working Draft of Web MIDI API. This specification provides users with a bridge between a Web browser and their MIDI-capable devices, such as musical instruments, lighting controls, or any other MIDI device. With this API, users can control or exchange information with MIDI devices directly from the browser. The Web MIDI API is a low-level feature, intended for use with other web platform features, like the Web Audio API, with the goal of familiarity for users of operating-system-level MIDI APIs, such as Apple’s CoreMIDI and Microsoft’s Windows MIDI API. Learn more about the Rich Web Client Activity.





by Maria Auday via W3C News

CSS Grid Layout Module Level 1 Draft Published

The Cascading Style Sheets (CSS) Working Group has published a Working Draft of CSS Grid Layout Module Level 1. This CSS module defines a two-dimensional grid-based layout system, optimized for user interface design. In the grid layout model, the children of a grid container can be positioned into arbitrary slots in a flexible or fixed predefined layout grid. Learn more about the Style Activity.





by Maria Auday via W3C News

Public Identifiers for entity resolution in XHTML Note Published

The HTML Working Group has published a Group Note of Public Identifiers for entity resolution in XHTML. This document adds an additional public identifier that should be recognized by XHTML user agents and cause the HTML character entity definitions to be loaded. Unlike the identifiers already listed by the HTML 5 specification, the identifier added by this extension references the set of definitions that is used by HTML. Learn more about the HTML Activity.





by Maria Auday via W3C News

Build a website: Introduction to HTML5 and CSS3 - The Guardian









Build a website: Introduction to HTML5 and CSS3

The Guardian

Whether you want to promote your business, host an online CV or explore a personal passion, building a website is a significant, but daunting, progression from blogging. But it's easier to master than you think. This step-by-step course shows how to ...







by via HTML5 news - Google News

Monday, March 16, 2015

HTML5 in Industrial Applications - Automation World









HTML5 in Industrial Applications

Automation World

Working with the latest in web development technologies, however, allows for the easy creation of a beautiful and responsive user interface through new CSS3 style definitions. This led me to to consider the idea of using HTML5 for industrial web ...







by via HTML5 news - Google News

Dailymotion picks new logo, launches beta of HTML5 player - Telecompaper (subscription)









Dailymotion picks new logo, launches beta of HTML5 player

Telecompaper (subscription)

Dailymotion has made several major visual changes to its website and mobile apps for Android and iOS, 01net reports. The French video streaming portal has adopted a simple blue 'd' as its new logo. It has also introduced an HTML5 player in beta version.







by via HTML5 news - Google News

Accusoft Introduces Services for Easy, Fast Deployment of HTML5 Viewing - Business Wire (press release)









Accusoft Introduces Services for Easy, Fast Deployment of HTML5 Viewing

Business Wire (press release)

Accusoft Enablement Services deliver the right combination of architecture knowledge and best practices to quickly optimize Accusoft's Prizm Content Connect HTML5 viewer for the Enablement Services customer's unique requirements and goals.







by via HTML5 news - Google News

Friday, March 13, 2015

Upcoming Workshop: Digital Marketing

W3C announced today the W3C Workshop on Digital Marketing, 29-30 April 2015, in Tampa, Florida (USA). The event is hosted by Nielsen.


Digital Marketing and the ecosystem surrounding it are growing at an unprecedented pace as consumers take advantage of new devices, features, and content on the Web; our core focus. As the Open Web Platform and technologies such as HTML5 continue to expand and offer new functionalities, brands, interactive marketers, content publishers and third party providers are calling W3C’s attention to gaps and challenges.


Our goal is to better understand which changes to the Open Web Platform would help improve interoperability, increase efficiencies, enable new innovations, and enhance communications. Topics of discussion include Security, and interaction with security measures; Data-gathering and measurement; performance, etc. W3C membership is not required to participate. The event is open to all. All participants are required to submit a position paper by 6 April 2015.





by Coralie Mercier via W3C News

FlipHTML5 Introduces HTML5 Flipbook Solution for Users to Improve Content ... - Press Release Rocket









FlipHTML5 Introduces HTML5 Flipbook Solution for Users to Improve Content ...

Press Release Rocket

The constant forward march into mobile and tablet technology has forced a change in how companies do business on the web. Companies must now be mobile and tablet friendly if they want to capture those users who prefer to do their shopping on the web.







by via HTML5 news - Google News

Thursday, March 12, 2015

[GDC 2015] AD 2460 is a space strategy HTML5 browser game playable on ... - DroidGamers (blog)









[GDC 2015] AD 2460 is a space strategy HTML5 browser game playable on ...

DroidGamers (blog)

While GDC 2015 is usually about the newly released or upcoming titles developers want to show off, AD 2460 is a little different. This game was built entirely out of Javascript and HTML5 and was actually released a couple of months ago. Since the game ...







by via HTML5 news - Google News

W3C Invites Implementations of XQuery and XPath Full Text 3.0; XQuery and XPath Full Text 3.0 Requirements and Use Cases Draft Updated

The XML Query Working Group and the XSLT Working Group invite implementation of the Candidate Recommendation of XQuery and XPath Full Text 3.0. The Full Text specification extends the XPath and XQuery languages to support fast and efficient full text searches over arbitrarily large collections of documents. This release brings the Full Text specification up to date with XQuery 3.0 and XPath 3.0; the language itself is unchanged.


Both groups also published an updated Working Draft of XQuery and XPath Full Text 3.0 Requirements and Use Cases. This document specifies requirements and use cases for Full-Text Search for use in XQuery 3.0 and XPath 3.0. The goal of XQuery and XPath Full Text 3.0 is to extend XQuery and XPath Full Text 1.0 with additional functionality in response to requests from users and implementors.


Learn more about the XML Activity.





by Maria Auday via W3C News

Push Notifications on the Open Web

If you ask a room of developers what mobile device features are missing from the web, push messages are always high on the list.


Push messaging is a great feature that allows you to re-engage with your users and provide a smooth user experience with timely and customised content.


As of Chrome version 42, the Push API and Notification API are available to developers.


The Push API in Chrome relies on a few different pieces of technology, including Web App Manifests and Service Workers. In this post we’ll look at each of these technologies, but only the bare minimum to get push messaging up and running. To get a better understanding of some of the other features of manifests and the offline capabilities of service workers, please check out the links above.


We will also look at what will be added to the API in future versions of Chrome, and finally we’ll have an FAQ.


Implementing Push Messaging for Chrome


This section describes each step you need to complete in order to support push messaging in your web app.


Register a Service Worker


There is a dependency of having a service worker to implement push messages for the web. The reason for this is that when a push message is received, the browser can start up a service worker, which runs in the background without a page being open, and dispatch an event so that you can decide how to handle that push message.


Below is an example of how you register a service worker in your web app. When the registration has completed successfully we call initialiseState(), which we’ll cover shortly.




var isPushEnabled = false;



window.addEventListener('load', function() {
var pushButton = document.querySelector('.js-push-button');
pushButton.addEventListener('click', function() {
if (isPushEnabled) {
unsubscribe();
} else {
subscribe();
}
});

// Check that service workers are supported, if so, progressively
// enhance and add push messaging support, otherwise continue without it.
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/service-worker.js')
.then(initialiseState);
} else {
console.warn('Service workers aren\'t supported in this browser.');
}
});


The button click handler subscribes or unsubscribes the user to push messages. isPushEnabled is a global variable which simply tracks whether push messaging is currently subscribed or not. These will be referenced throughout the code snippets.


We then check that service workers are supported before registering the service-worker.js file which has the logic for handling a push message. Here we are simply telling the browser that this JavaScript file is the service worker for our site.


Set Up the Initial State


Example of enabled and disabled push messaging UX in Chrome


Once the service worker is registered, we need to set up our UI’s state.


Users will expect a simple UI to enable or disable push messages for your site, and they’ll expect it to keep up to date with any changes that occur. In other words, if they enable push messages for your site, then leave and come back a week later, your UI should show that push messages are already enabled.


You can find some UX guidelines in this doc, in this article we’ll be focusing on the technical aspects.


At this point you may be thinking there are only two states to deal with, enabled or disabled. There are however some other states surrounding notifications which you need to take into account.


A diagram highlighting the different considerations and state of push in Chrome


There are a number of things we need to check before we enable our button, and if everything is supported, we can enable our UI and set the initial state to indicate whether push messaging is subscribed or not.


Since the majority of these checks result in our UI being disabled, you should set the initial state to disabled. This also avoids any confusion should there be an issue with your page’s JavaScript, for example the JS file can’t be downloaded or the user has disabled JavaScript.




<button class="js-push-button" disabled>
Enable Push Messages
</button>


With this initial state, we can perform the checks outlined above in the initialiseState() method, i.e. after our service worker is registered.




// Once the service worker is registered set the initial state
function initialiseState() {
// Are Notifications supported in the service worker?
if (!('showNotification' in ServiceWorkerRegistration.prototype)) {
console.warn('Notifications aren\'t supported.');
return;
}

// Check the current Notification permission.
// If its denied, it's a permanent block until the
// user changes the permission
if (Notification.permission === 'denied') {
console.warn('The user has blocked notifications.');
return;
}

// Check if push messaging is supported
if (!('PushManager' in window)) {
console.warn('Push messaging isn\'t supported.');
return;
}

// We need the service worker registration to check for a subscription
navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// Do we already have a push message subscription?
serviceWorkerRegistration.pushManager.getSubscription()
.then(function(subscription) {
// Enable any UI which subscribes / unsubscribes from
// push messages.
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = false;

if (!subscription) {
// We aren't subscribed to push, so set UI
// to allow the user to enable push
return;
}

// Keep your server in sync with the latest subscriptionId
sendSubscriptionToServer(subscription);

// Set your UI to show they have subscribed for
// push messages
pushButton.textContent = 'Disable Push Messages';
isPushEnabled = true;
})
.catch(function(err) {
console.warn('Error during getSubscription()', err);
});
});
}


A brief overview of these steps:



  • We check that showNotification is available in the ServiceWorkerRegistration prototype. Without it we won’t be able to show a notification from our service worker when a push message is received.

  • We check what the current Notification.permission is to ensure it’s not “denied”. A denied permission means that you can’t show notifications until the user manually changes the permission in the browser.

  • To check if push messaging is supported we check that PushManager is available in the window object.

  • Finally, we used pushManager.getSubscription() to check whether we already have a subscription or not. If we do, we send the subscription details to our server to ensure we have the right information and set our UI to indicate that push messaging is already enabled or not. We’ll look at what details exist in the subscription object later in this article.


We wait until navigator.serviceWorker.ready is resolved to check for a subscription and to enable the push button because it’s only after the service worker is active that you can actually subscribe to push messages.


The next step is to handle when the user wants to enable push messages, but before we can do this, we need to set up a Google Developer Console project and add some parameters to our manifest to use Google Cloud Messaging (GCM).


Make a Project on the Google Developer Console


Chrome uses GCM to handle the sending and delivery of push messages, however, to use the GCM API, you need to set up a project on the Google Developer Console. Follow the instructions in the getting started guide, making sure you enable both “Google Cloud Messaging for Android” and “Google Cloud Messaging for Chrome”, and make a note of the project number and API key as you’ll need to use them later on.


This step is specific to Chrome since it relies on GCM for handling push messages. We’ll discuss how this would work in other browsers later on in the article.


Below are screenshots highlighting where the project number and API keys are.


Highlighting where the project number is in the Google Developer Console


Highlighting where the API key is in the Google Developer Console


The project number will be used in the Web App Manifest (see the next section) as the gcm_sender_id parameter, and the API Key will be needed on your server when you use GCM’s restful API.


Add a Web App Manifest


For push, we need to add a manifest file with two fields, gcm_sender_id and gcm_user_visible_only, to get the push subscription to succeed. These parameters are only required by Chrome to use GCM.


The gcm_sender_id (i.e. the project number) is used by Chrome when establishing a subscription with GCM. This means that GCM can link a subscriptionId to a corresponding project number which has has a corresponding API key. This ensures that your server is permitted to send messages to the client web app by validating these three pieces of information against the projects whitelisted IP Addresses.


The gcm_user_visible_only parameter is used to indicate that you promise to show a notification whenever you receive a push. Not including this parameter or having a value of false will prevent you from subscribing to push messages.


Below is a super-simple manifest file:




{
"name": "Push Demo",
"short_name": "Push Demo",
"icons": [{
"src": "images/icon-192x192.png",
"sizes": "192x192"
}],
"start_url": "/index.html?homescreen=1",
"display": "standalone",
"gcm_sender_id": "123456789012",
"gcm_user_visible_only": true
}


You’ll need to swap out the gcm_sender_id with your project number from the Google Developer Console mentioned in the previous step.


Once you have saved your manifest file in your project (manifest.json is a good name), reference it from your HTML with the following tag in the head of your page.




<link rel="manifest" href="manifest.json">

If you don’t add a web manifest with these parameters you’ll get an exception when you attempt to subscribe the user to push messages, with the error “Registration failed - no sender id provided” or “Registration failed - permission denied”.


Subscribe to Push Messaging


To subscribe, we just have to call the subscribe() method on the PushManager object, which you access through the ServiceWorkerRegistration object.


This will ask the user to give your origin permission to send push notifications. Without this permission, you will not be able to successfully subscribe.


If the promise returned by the subscribe() method resolves, you’ll be given a PushSubscription object which will contain a subscriptionId and an endpoint.


The subscriptionId is used to identify the user to GCM and the endpoint will be the URL of the GCM API endpoint to use.


Both the subscriptionId and endpoint should be saved on your server for each user, since you’ll need them to send push messages at a later date.


The following code subscribes the user for push messaging:




function subscribe() {
// Disable the button so it can't be changed while
// we process the permission request
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;

navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
serviceWorkerRegistration.pushManager.subscribe()
.then(function(subscription) {
// The subscription was successful
isPushEnabled = true;
pushButton.textContent = 'Disable Push Messages';
pushButton.disabled = false;

// TODO: Send the subscription.subscriptionId and
// subscription.endpoint to your server
// and save it to send a push message at a later date
return sendSubscriptionToServer(subscription);
})
.catch(function(e) {
if (Notification.permission === 'denied') {
// The user denied the notification permission which
// means we failed to subscribe and the user will need
// to manually change the notification permission to
// subscribe to push messages
console.warn('Permission for Notifications was denied');
pushButton.disabled = true;
} else {
// A problem occurred with the subscription; common reasons
// include network errors, and lacking gcm_sender_id and/or
// gcm_user_visible_only in the manifest.
console.error('Unable to subscribe to push.', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
}
});
});
}


At this point your web app is ready to receive a push message, although nothing will happen until we add a push event listener to our service worker file.


Service Worker Push Event Listener


When a push message is received (we’ll talk more about how to send a push message from your server in the next section), a push event will be dispatched in your service worker, at which point you’ll need to display a notification.




self.addEventListener('push', function(event) {
console.log('Received a push message', event);

var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';

event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});


This code registers a push event listener and displays a notification with a predefined title, body text, icon and a notification tag.

One subtlety to highlight with this example is the event.waitUntil() method. This method takes a promise and extends the lifetime of an event handler until the promise is settled; In this case, until the promise returned from showNotification() is resolved.


The notification tag identifies unique notifications. If we sent two push messages to the same subscriptionId, with a short delay between them, and displayed a notification with the same tag for both, the browser will display the first notification and replace it with the second notification when the push message is received.


If you want to show multiple notifications at once then use a different tag, or no tag at all.

We’ll look at a more complete example of showing a notification later on in this post. For now, let’s keep things simple and see if sending a push message shows this notification.


Sending a Push Message


We’ve subscribed to push messages and our service worker is ready to show a notification, so it’s time to send a push message through GCM.


GCM has some great docs on what you need to do to send a message. The key aspects of their API are:



  • An Authorization header with a value of key=<YOUR_API_KEY>, where <YOUR_API_KEY> is the API key from the Google Developer Console.

    • The API key is used by GCM to find the appropriate project number, match it with the subscriptionId’s project number, which you are trying to send a message too and finally ensuring that the server’s IP address is whitelisted for that project.



  • An appropriate Content-Type header of application/json or application/x-www-form-urlencoded;charset=UTF-8 depending on whether you send the data as JSON or form data.

  • An array of registration_ids - these are just the subscriptionId’s you’d have for the users you would like to send a push message to.


Please do check out the docs about how to send push messages from your server, but for a quick sanity check of your service worker you can use cURL to send a push message to your browser (as long as you whitelisted your IP address on the Google Developer Console).


Swap out the <YOUR_API_KEY> and <YOUR_SUBSCRIPTION_ID> in this cURL command, run it from a terminal and you should see a glorious notification:



curl --header "Authorization: key=<YOUR_API_KEY>" --header
"Content-Type: application/json" http://ift.tt/YbbTRA -d
"{\"registration_ids\":[\"<YOUR_SUBSCRIPTION_ID>\"]}"


Example of a push message from Chrome for Android


When developing your backend logic, remember that the Authorization header and format of the POST body are specific to the GCM endpoint, so detect when the endpoint is for GCM and conditionally add the header and format the POST body.


A downside to the current implementation of the Push API in Chrome is that you can’t send any data with a push message. Nope, nothing. The reason for this is that in a future implementation, payload data will have to be encrypted on your server before it’s sent to a push messaging endpoint. This way the endpoint, whatever push provider it is, will not be able to easily view the content of the push message. This also protects against other vulnerabilities like poor validation of HTTPS certificates and man-in-the-middle attacks between your server and the push provider. However, this encryption isn’t supported yet, so in the meantime you’ll need to perform a fetch to get information needed to populate a notification.


A More Complete Push Event Example


The notification we’ve seen so far is pretty basic and as far as samples go, it’s pretty poor at covering a real world use case.


Realistically, most people will want to get some information from their server before displaying the notification. This may be data to populate the notification title and message with something specific, or going a step further and caching some pages or data so that when the user clicks on the notification, everything is immediately available when the browser is opened—even if the network isn’t available at that time.


In the following code we fetch some data from an API, convert the response to an object and use it to populate our notification.




self.addEventListener('push', function(event) {
// Since there is no payload data with the first version
// of push messages, we'll grab some data from
// an API and use it to populate a notification
event.waitUntil(
fetch(SOME_API_ENDPOINT).then(function(response) {
if (response.status !== 200) {
// Either show a message to the user explaining the error
// or enter a generic message and handle the
// onnotificationclick event to direct the user to a web page
console.log('Looks like there was a problem. Status Code: ' + response.status);
throw new Error();
}

// Examine the text in the response
return response.json().then(function(data) {
if (data.error || !data.notification) {
console.error('The API returned an error.', data.error);
throw new Error();
}

var title = data.notification.title;
var message = data.notification.message;
var icon = data.notification.icon;
var notificationTag = data.notification.tag;

return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
});
}).catch(function(err) {
console.error('Unable to retrieve data', err);

var title = 'An error occured';
var message = 'We were unable to get the information for this push message';
var icon = URL_TO_DEFAULT_ICON;
var notificationTag = 'notification-error';
return self.registration.showNotification(title, {
body: message,
icon: icon,
tag: notificationTag
});
})
);
});


It’s worth, once again, highlighting that the event.waitUntil() takes a promise which results in the promise returned by showNotification(), meaning that our event listener won’t exit until the asynchronous fetch() call is complete, and the notification is shown.


You’ll notice that we show a notification even when there is an error, that is because if we don’t, Chrome will show it’s own generic notification.


Opening a URL when the User Clicks a Notification


When the user clicks a notification, a notificationclick event is dispatched in your service worker. Within your handler, you can take appropriate action, like focusing a tab or opening a window with a particular URL:




self.addEventListener('notificationclick', function(event) {
console.log('On notification click: ', event.notification.tag);
// Android doesn't close the notification when you click on it
// See: http://crbug.com/463146
event.notification.close();

// This looks to see if the current is already open and
// focuses if it is
event.waitUntil(
clients.matchAll({
type: "window"
})
.then(function(clientList) {
for (var i = 0; i &lt; clientList.length; i++) {
var client = clientList[i];
if (client.url == '/' && 'focus' in client)
return client.focus();
}
if (clients.openWindow) {
return clients.openWindow('/');
}
})
);
});


This example opens the browser to the root of the site’s origin, by focusing an existing same-origin tab if one exists, and otherwise opening a new one.


There are two parts of today’s implementation of Notifications which require some unpleasant work arounds:



  1. There is no easy way to stash data with the notification (i.e. what URL to open when a particular notification is clicked). There is a data attribute in the Notification spec, but it’s not implemented yet.

  2. You can only open a URL which is on the same origin as your service worker (This will hopefully be addressed soon).


But don’t worry, there are ways to overcome these issues.


To get around not being able to tie data to your notification, you can use IndexedDB to save a URL for a particular notification tag, this way you can look it up in the notificationclick event and open the window to that particular URL.


An alternative approach (albeit somewhat unconventional) would be to use a fragment identifier on the end of your icon URL. This way it won’t affect the image’s cachability while giving you access to a short URL. (H/T to Casey at GoRoost for this idea.)


The simplest way to overcome the temporary issue of only being able to open URLs on the same origin, is to have a page on your domain which performs a redirect.


Unsubscribe a User’s Device


You’ve subscribed a user’s device and they’re receiving push messages, but how can you

unsubscribe them?


The main things required to unsubscribe a users device is to call the unsubscribe() method on the PushSubscription object and to remove the subscriptionId from your servers (just so you aren’t sending push messages which you know won’t be received). The code below does exactly this:




function unsubscribe() {
var pushButton = document.querySelector('.js-push-button');
pushButton.disabled = true;

navigator.serviceWorker.ready.then(function(serviceWorkerRegistration) {
// To unsubscribe from push messaging, you need get the
// subscription object, which you can call unsubscribe() on.
serviceWorkerRegistration.pushManager.getSubscription().then(
function(pushSubscription) {
// Check we have a subscription to unsubscribe
if (!pushSubscription) {
// No subscription object, so set the state
// to allow the user to subscribe to push
isPushEnabled = false;
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
return;
}

var subscriptionId = pushSubscription.subscriptionId;
// TODO: Make a request to your server to remove
// the subscriptionId from your data store so you
// don't attempt to send them push messages anymore

// We have a subscription, so call unsubscribe on it
pushSubscription.unsubscribe().then(function(successful) {
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
isPushEnabled = false;
}).catch(function(e) {
// We failed to unsubscribe, this can lead to
// an unusual state, so may be best to remove
// the users data from your data store and
// inform the user that you have done so

console.log('Unsubscription error: ', e);
pushButton.disabled = false;
pushButton.textContent = 'Enable Push Messages';
});
}).catch(function(e) {
console.error('Error thrown while unsubscribing from push messaging.', e);
});
});
}


Keeping the Subscription Up to Date


Subscriptions may get out of sync between GCM and your server. Make sure your server parses the response body of the GCM API’s send POST, looking for error:NotRegistered and canonical_id results, as explained in the GCM documentation.


Subscriptions may also get out of sync between the service worker and your server. For example, after subscribing/unsubscribing successfully, a flaky network connection may prevent you from updating your server; or a user might revoke notifications permission, which triggers an automatic unsubscribe. Handle such cases by checking the result of serviceWorkerRegistration.pushManager.getSubscription() periodically (e.g. on page load) and synchronizing it with the server. You may also wish to re-subscribe automatically if you no longer have a subscription and Notification.permission == ‘granted’.


In sendSubscriptionToServer() you will need to consider how you handle failed network requests when updating the subscriptionId. One solution is to track the state of the subscriptionId and endpoint in a cookie to determine whether your server needs the latest details or not.


All of the above steps results in a full implementation of push messaging on the web in Chrome 42. There are still spec’d features that will make things easier (like notifications having data tied to them), but this release enables you to start building push messaging into your web apps today.


How to Debug Your Web App


While implementing push messages, bugs will live in one of two places: your page or your service worker.


Bugs in the page can be debugged using DevTools. To debug service worker issues, you have two options:



  1. Go to chrome://inspect > Service workers. This view doesn’t provide much information other than the currently running service workers.

  2. Go to chrome://serviceworker-internals and from here you can view the state of service workers, and see errors, if there are any. This page is temporary until DevTools has a similar feature set.


One of the best tips I can give to anyone who is new to service workers is make use of the checkbox called “Open DevTools window and pause JavaScript execution on Service Worker startup for debugging.” This checkbox will add a breakpoint at the start of your service worker and pause execution, this allows you to resume or step through your service worker script and see if you hit any problems.


Screenshot showing where the pause execution checkbox is on serviceworker-internals


If there seems to be an issue between GCM and your service worker’s push event, then there isn’t much you can do to debug the problem since there is no way for you to see whether Chrome received anything. The key thing to ensure is that the response from GCM is successful when your server makes an API call. It’ll look something like:



{"multicast_id":1234567890,"success":1,"failure":0,"canonical_ids":0,"results":[{"message_id":"0:1234567890"}]}


Notice the “success”: 1 response. If you see a failure instead, then that suggests that something isn’t right with the GCM subscription and the push message isn’t getting sent to Chrome.


Debugging Service Workers on Chrome for Android


At the moment debugging service workers on Chrome for Android is not obvious. You need to navigate to chrome://inspect, find your device and look for a list item with the name “Worker pid:….” which has the URL of your service worker.


Screenshot showing where service workers live in chrome inspect


UX for Push Notifications


The Chrome team has been putting together a document of best practices for push notifications UX as well as a document covering some of the edge cases when working with push notifications.



Future of Push Messaging on Chrome and the Open Web


This section goes into a little bit of detail surrounding some of the Chrome specific parts of this implementation that you should be aware of and how it will differ from other browser implementations.


Web Push Protocol and Endpoints


The beauty of the Push API standard is that you should be able to take the subscriptionId and endpoint, pass them to your server and send push messages by implementing the Web Push Protocol.


The Web Push Protocol is a new standard which push providers can implement, allowing developers to not have to worry about who the push provider is. The idea is that this avoids the need to sign up for API keys and send specially formatted data, like we have to with GCM.


At the moment Chrome is the only implementation of the Push API and GCM does not support the Web Push Protocol, which is the reason why Chrome requires the gcm_sender_id and you need to use the restful API for GCM with a specific format for the body of the request and the Authorization header.


The end goal is to move away from requiring these steps and to move to using the Web Push Protocol with Chrome and GCM.


Until then, you need to detect the endpoint “http://ift.tt/YbbTRA” and handle it seperately from other endpoints, i.e. format the payload data in a specific way and add the Authorization key.


How to Implement the Web Push Protocol?


At the moment there is no push service which implements the Web Push Protocol meaning there is no sample to give on how to send a push message on your server for anything other than GCM.


FAQs


Where are the specs?


http://ift.tt/RByJEk

http://ift.tt/1yM0V9o

http://ift.tt/1nRmQcu


Can I prevent duplicate notifications if my web presence has multiple origins, or if I have both a web and native presence?


There isn’t a solution to this at the moment, but you can follow progress on Chromium.


The ideal scenario would be to have some kind of ID for a users device and then on the server side match up the native app and web app subscription ID’s and decide which one to send a push message to. You could do this via screen size, device model, sharing a generated key between the web app and native app, but each approach has pro’s and con’s.


Why do I need a gcm_sender_id?


This is required so that Chrome can make use of the Google Cloud Messaging (GCM) API. The goal is to use the Web Push Protocol when the standard is finalised and GCM can support it.


Why not use Web Sockets or Server-Sent Events (EventSource)?


The advantage of using push messages is that even if your page is closed, your service worker will be woken up and be able to show a notification. Web Sockets and EventSource have their connection closed when the page or browser is closed.


What if I don’t need backgound event delivery?


If you don’t need background delivery then Web Sockets are a great option.


When can I use push without showing notifications (i.e. silent background push)?


There is no timeline for when this will be available yet, but there is an intent to implement background sync and while it’s not decided or spec’d, there is some discussion of enabling silent push with background sync.


Why does this require HTTPS? How do I work around this during development?


Service workers require secure origins to ensure that the service worker script is from the intended origin and hasn’t come about from a man-in-the-middle attack. Currently, that means using HTTPS on live sites, though localhost will work during development.


What does browser support look like?


At the moment Chrome is the only browser to implement this standard, but Mozilla have begun work on implementing the Push API and you can track their Notification implementation here.


Can I remove a notification after a certain time period?


At the moment this isn’t possible and we are planning on adding support to get a list of past notifications. If you have a use case to set an expiration when the notification is created, we’d love to know what that is, so please add a comment and we’ll pass it back to the Chrome team.


What are the limitations of push messaging in Chrome 42?


There are a few limitations outlined in this post:



  • Data can’t be sent in a push message.

  • Chrome’s usage of GCM as a push service creates a number of proprietary requirements. We’re working together to see if some of these can be lifted in the future.

  • You have to show a notification when you receive a push message.

  • There is no way to add data to a notification. The data parameter isn’t implemented in Chrome yet, but is in the spec.

  • Chrome on desktop has the caveat that if Chrome isn’t running, push messages won’t be received. This differs from Chrome OS and Android where push messages will always be received. This is something we hope to resolve in the future.


Shouldn’t we be using the Permissions API?


The Permission API is still being spec’d and isn’t implemented in Chrome yet. When it is available in Chrome, you should move away from using Notifications.permission and use the Permissions API instead.


Why doesn’t Chrome open up the previous tab when I click a notification?


This issue only affects pages which aren’t currently controlled by a service worker. You can learn more here.


What if a notification is out of date by the time the users device received the push?


You always have to show a notification when you receive a push message. In the scenario where you want to send a notification but it’s only useful for a certain period time, you can use the ‘time_to_live’ parameter on GCM so that GCM won’t send the push message if it passes the expiry time.


More details can be found here.


What happens if I send 10 push messages but only want the device to receive one?


GCM has a ‘collapse_key’ parameter you can use to tell GCM to replace any pending message which has the same ‘collapse_key’, with the new message.


More details can be found here.




by mattgaunt via HTML5Rocks

Introduction to fetch()

So long XMLHttpRequest


fetch() allows you to make network requests similar to XMLHttpRequest (XHR). The main difference is that the Fetch API uses Promises, which enables a simpler and cleaner API, avoiding callback hell and having to remember the complex API of XMLHttpRequest.


The Fetch API has been available in the Service Worker global scope since Chrome 40, but it’ll be enabled in the window scope in Chrome 42. There is also a rather fetching polyfill by GitHub that you can use today.


If you’ve never used Promises before, check out this great article by Jake Archibald.


Basic Fetch Request


Let’s start by comparing a simple example implemented with an XMLHttpRequest and then with fetch. We just want to request a URL, get a response and parse it as JSON.


XMLHttpRequest


An XMLHttpRequest would need two listeners to be set to handle the success and error cases and a call to open() and send(). Example from MDN docs .




function reqListener() {
var data = JSON.parse(this.responseText);
console.log(data);
}

function reqError(err) {
console.log('Fetch Error :-S', err);
}

var oReq = new XMLHttpRequest();
oReq.onload = reqListener;
oReq.onerror = reqError;
oReq.open('get', './api/some.json', true);
oReq.send();


Fetch


Our fetch request looks a little like this:




fetch('./api/some.json')
.then(
function(response) {
if (response.status !== 200) {
console.log('Looks like there was a problem. Status Code: ' +
response.status);
return;
}

// Examine the text in the response
response.json().then(function(data) {
console.log(data);
});
}
)
.catch(function(err) {
console.log('Fetch Error :-S', err);
});


We start by checking that the response status is 200 before parsing the response as JSON.


The response of a fetch() request is a Stream object, which means that when we call the json() method, a Promise is returned since the reading of the stream will happen asynchronously.


Response Metadata


In the previous example we looked at the status of the Response object as well as how to parse the response as JSON. Other metadata we may want to access, like headers, are illustrated below.




fetch('users.json').then(function(response) {
console.log(response.headers.get('Content-Type'));
console.log(response.headers.get('Date'));

console.log(response.status);
console.log(response.statusText);
console.log(response.type);
console.log(response.url);
});


Response Types


When we make a fetch request, the response will be given a response.type of “basic”, “cors” or “opaque”. These “types” indicate where the resource has come from and can be used to inform how you should treat the response object.


When a request is made for a resource on the same origin, the response will have a “basic” type and there aren’t any restrictions on what you can view from the response.


If a request is made for a resource on another origin which returns the CORs headers, then the type is “cors”. “cors” and “basic” responses are almost identical except that a “cors” response restricts the headers you can view to `Cache-Control`, `Content-Language`, `Content-Type`, `Expires`, `Last-Modified`, and `Pragma`.


An “opaque” response is for a request made for a resource on a different origin that doesn’t return CORS headers. With an opaque response we won’t be able to read the data returned or view the status of the request, meaning we can’t check if the request was successful or not. With the current fetch() implementation it’s not possible to make requests for resources on a different origin from the window global scope. Find out why here, it should be added when the Cache API is available in the window object.


You can define a mode for a fetch request such that only certain requests will resolve. The modes you can set are as follows:



  • “same-origin” only succeeds for requests for assets on the same origin, all other requests will reject.

  • “cors” will allow requests for assets on the same-origin and other origins which return the appropriate CORs headers.

  • “cors-with-forced-preflight” will always perform a preflight check before making the actual request.

  • “no-cors” is intended to make requests to other origins that do not have CORS headers and result in an opaque response, but as stated, this isn’t possible in the window global scope at the moment.


To define the mode, add an options object as the second parameter in the fetch request and define the mode in that object:




fetch('http://ift.tt/1GIC0IG;, {mode: 'cors'})
.then(function(response) {
return response.text();
})
.then(function(text) {
console.log('Request successful', text);
})
.catch(function(error) {
log('Request failed', error)
});


Chaining Promises


One of the great features of promises is the ability to chain them together. For fetch, this allows you to share logic across fetch requests.


If you are working with a JSON API, you’ll need to check the status and parse the JSON for each response. You can simplify your code by defining the status and JSON parsing in separate functions which return promises, freeing you to only worry about handling the final data and the error case.




function status(response) {
if (response.status &gt;= 200 && response.status &lt; 300) {
return Promise.resolve(response)
} else {
return Promise.reject(new Error(response.statusText))
}
}

function json(response) {
return response.json()
}

fetch('users.json')
.then(status)
.then(json)
.then(function(data) {
console.log('Request succeeded with JSON response', data);
}).catch(function(error) {
console.log('Request failed', error);
});


We define the status function which checks the response.status and returns the result of Promise.resolve() or Promise.reject(), which return a resolved or rejected Promise. This is the first method called in our fetch() chain, if it resolves, we then call our json() method which again returns a Promise from the response.json() call. After this we have an object of the parsed JSON. If the parsing fails the Promise is rejected and the catch statement executes.


The great thing with this is that you can share the logic across all of your fetch requests, making code easier to maintain, read and test.


POST Request


It’s not uncommon for web apps to want to call an API with a POST method and supply some parameters in the body of the request.


To do this we can set the method and body parameters in the fetch() options.




fetch(url, {
method: 'post',
headers: {
"Content-type": "application/x-www-form-urlencoded; charset=UTF-8"
},
body: 'foo=bar&lorem=ipsum'
})
.then(json)
.then(function (data) {
console.log('Request succeeded with JSON response', data);
})
.catch(function (error) {
console.log('Request failed', error);
});


Sending Credentials with a Fetch Request


Should you want to make a fetch request with credentials such as cookies, you should set the credentials of the request to “include”.




fetch(url, {
credentials: 'include'
})


FAQ


How do I cancel a fetch() request?


At the moment there is no way to cancel a fetch, but this is being discussed on GitHub . H/T @jaffathecake for this link.


Is there a polyfill?


GitHub has a polyfill for fetch. H/T @Nexii for pointing this out.


Why is “no-cors” supported in service workers but not the window?


This is due to a security concern, you can learn more here.




by mattgaunt via HTML5Rocks