/*global window, rJS, RSVP */ /*jslint indent: 2, maxerr: 3 */ (function(window, rJS, RSVP, jIO) { "use strict"; /** * Send request with XHR and return a promise. xhr.onload: The promise is * resolved when the status code is lower than 400 with the xhr object as * first parameter. xhr.onerror: reject with xhr object as first * parameter. xhr.onprogress: notifies the xhr object. * * @param {Object} param The parameters * @param {String} [param.type="GET"] The request method * @param {String} [param.dataType=""] The data type to retrieve * @param {String} param.url The url * @param {Any} [param.data] The data to send * @param {Function} [param.beforeSend] A function called just before the * send request. The first parameter of this function is the XHR object. * @return {Promise} The promise */ function ajax(param) { var xhr = new XMLHttpRequest(); return new RSVP.Promise(function(resolve, reject, notify) { var k; xhr.open(param.type || "GET", param.url, true); xhr.addEventListener("load", function(e) { var answer = {}; if (e.target.status >= 400) { return reject(e); } answer.responseText = this.responseText; answer.responseType = this.getResponseHeader("content-type"); answer.responseURL = param.url; resolve(answer); }); xhr.addEventListener("error", reject); xhr.addEventListener("progress", notify); if (typeof param.xhrFields === 'object' && param.xhrFields !== null) { for (k in param.xhrFields) { if (param.xhrFields.hasOwnProperty(k)) { xhr[k] = param.xhrFields[k]; } } } xhr.send(); }, function() { xhr.abort(); }); } function sendMessage(message) { // This wraps the message posting/response in a promise, which will resolve if the response doesn't // contain an error, and reject with the error if it does. If you'd prefer, it's possible to call // controller.postMessage() and set up the onmessage handler independently of a promise, but this is // a convenient wrapper. return new RSVP.Promise(function(resolve, reject, notify) { var messageChannel = new MessageChannel(); messageChannel.port1.onmessage = function(event) { console.log(event); if (event.data.error) { reject(event.data.error); } else { resolve(event.data); } }; // This sends the message data as well as transferring messageChannel.port2 to the service worker. // The service worker can then use the transferred port to reply via postMessage(), which // will in turn trigger the onmessage handler on messageChannel.port1. // See https://html.spec.whatwg.org/multipage/workers.html#dom-worker-postmessage return navigator.serviceWorker.controller.postMessage(message, [messageChannel.port2]); }); } function setStatus(statusMessage) { console.log(statusMessage); } rJS(window) .ready(function (g) { g.props = {}; return g.getElement() .push(function (element) { g.props.element = element; }); }) .ready(function(gadget) { // Initialize the gadget local parameters gadget.state_parameter_dict = {}; if ('serviceWorker' in navigator) { // XXX Hack to not add a new service worker when one is already declared if (!navigator.serviceWorker.controller) { return new RSVP.Promise(function(resolve, reject, notify) { navigator.serviceWorker.register('/sw.js', {scope: '/'}).then( function(){ if (navigator.serviceWorker.controller) { resolve(); } else { reject("Please reload this page to allow Service Worker to control this page"); } }).catch(function(error) { reject(error); }); }); } } else { throw "Service Worker are not available in your browser"; } }) /** * allDocs return the list of document in the cache * * @params {Object} Not taken into account * @return {} Return the data url of the document */ .declareMethod('allDocs', function(params) { if (params && params.cached_only) { return new RSVP.Queue() .push(function() { return sendMessage({ command: 'keys' }); }); } return new RSVP.Queue() .push(function() { return sendMessage({ command: 'allDocs' }); }); }) /** * get Return a data url. Cannot return a blob as the data * is transmitted through an iFrame * * @url {string} url of the document to retrieve * @return {data_url} Return the data url of the document */ .declareMethod('get', function(url) { return new RSVP.Queue() .push(function () { return ajax({ url: url }); }) .push(function (result) { return new Blob([result.responseText], {type: result.responseType}) }) .push(function(result) { return jIO.util.readBlobAsDataURL(result); }) .push(function(e) { return e.target.result; }); }) /** * put Return a data url. Cannot provide a blob as the data * is transmitted through an iFrame * * @url {string} url of the document to update * @parameter {data_url} data url of the document to put, it will be transformed in a blob * @return {data_url} Return the data url of the document */ .declareMethod('put', function(url, parameter) { return new RSVP.Queue() .push(function() { return sendMessage({ command: 'add', url: url, information: jIO.util.dataURItoBlob(parameter) }); }).push(function() { // If the promise resolves, just display a success message. console.log("Done adding "+ url); return 'Added to cache: ' + url + ' at ' + Date(); }).fail(setStatus); }) /** * Remove an url from the cache * * @url {string} url of the document to remove * @return {} */ .declareMethod('remove', function(url) { return new RSVP.Queue() .push(function() { return sendMessage({ command: 'delete', url: url }); }); }); }(window, rJS, RSVP, jIO));