Commit 105dec27 authored by Cédric Le Ninivin's avatar Cédric Le Ninivin

Start Moving to generic way to access data

parent a4c03a17
......@@ -8,11 +8,13 @@
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/jio-latest.js" type="text/javascript"></script>
<!-- custom script -->
<script src="crib-sw-gadget.js" type="text/javascript"></script>
</head>
<body>
<div class="storage-access" style="display:none;"></div>
</body>
</html>
\ No newline at end of file
/*global window, rJS, RSVP */
/*jslint indent: 2, maxerr: 3 */
(function(window, rJS, RSVP) {
(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);
function getStorageGadget(gadget) {
var storage_gadget;
return gadget.getDeclaredGadget("storage")
.push(undefined, function () {
return gadget.declareGadget(
gadget.props.storage_gadget_url,
{
"scope": "storage",
"sandbox": "iframe",
"element": gadget.props.element.querySelector('div')
}
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)
......@@ -83,87 +24,61 @@
return g.getElement()
.push(function (element) {
g.props.element = element;
g.props.storage_gadget_url = "https://cribjs.nexedi.net/gadget/crib-sw-storage-gadget.html";
});
})
.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";
}
return getStorageGadget(gadget);
})
.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'
});
return getStorageGadget(this)
.push(function (storage_gadget) {
return storage_gadget.allDocs(params)
});
})
.declareMethod('get', function(url) {
return ajax({
url: url
return getStorageGadget(this)
.push(function (storage_gadget) {
return storage_gadget.get(url)
})
.push(function (result) {
return jIO.util.dataURItoBlob(result);
});
})
.declareMethod('put', function(url, parameter) {
return new RSVP.Queue()
.push(function() {
var blob, gadget = this;
if (parameter.blob !== undefined) {
return sendMessage({
command: 'add',
url: url,
information: parameter.blob
});
blob = parameter.blob;
} else {
blob = new Blob(
[parameter.content],
{type: parameter.type,}
);
}
return sendMessage({
command: 'add',
url: url,
information: new Blob([parameter.content], {
type: parameter.type,
return RSVP.Queue()
.push(function () {
return RSVP.all([
getStorageGadget(gadget),
jIO.util.readBlobAsDataURL(blob)
]);
})
});
}).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);
.push(function (result_list) {
return result_list[0].put(url, result_list[1].target.result);
})
.push(console.log, console.log)
;
})
.declareMethod('remove', function(url) {
return new RSVP.Queue()
.push(function() {
return sendMessage({
command: 'delete',
url: url
});
return getStorageGadget(this)
.push(function (storage_gadget) {
return storage_gadget.remove(url)
});
});
}(window, rJS, RSVP));
\ No newline at end of file
}(window, rJS, RSVP, jIO));
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Crib SW interface Gadget</title>
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/jio-latest.js" type="text/javascript"></script>
<!-- custom script -->
<script src="crib-sw-storage-gadget.js" type="text/javascript"></script>
</head>
<body>
</body>
</html>
\ No newline at end of file
/*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";
}
})
.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'
});
});
})
.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;
});
})
.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);
})
.declareMethod('remove', function(url) {
return new RSVP.Queue()
.push(function() {
return sendMessage({
command: 'delete',
url: url
});
});
});
}(window, rJS, RSVP, jIO));
\ No newline at end of file
......@@ -8,6 +8,7 @@
<!-- renderjs -->
<script src="/lib/rsvp.js" type="text/javascript"></script>
<script src="/lib/renderjs.js" type="text/javascript"></script>
<script src="/lib/jio-latest.js" type="text/javascript"></script>
<script src="gadget_global.js" type="text/javascript"></script>
<!-- Custom -->
......
/*global window, rJS, loopEventListener */
/*jslint nomen: true, indent: 2, maxerr: 3*/
(function (window, rJS, loopEventListener) {
(function (window, rJS, loopEventListener, jIO) {
"use strict";
var CODE_CONTENT_KEY = "text_content";
......@@ -26,22 +26,32 @@
}
function getUrlTextContent(gadget, event, url) {
var type;
return new RSVP.Queue()
.push(function () {
return RSVP.all([gadget.crib_sw_get(url),
gadget.getDeclaredGadget('codeeditor')])
return gadget.crib_sw_get(url)
})
.push(function (data) {
type = data.type;
return jIO.util.readBlobAsText(data, type);
})
.push(function (evt) {
return RSVP.all([
evt.target.result,
gadget.getDeclaredGadget('codeeditor')]);
})
.push(function(data_list) {
//gadget.props.element.querySelector("form.crib-editor-save .content").value = data_list[0].responseText;
gadget.props.element.querySelector("form.crib-editor-save .mimetype").value = data_list[0].responseType;
gadget.props.element.querySelector("form.crib-editor-save .mimetype").value = type;
return data_list[1].render({
key: CODE_CONTENT_KEY,
value: data_list[0].responseText,
mode: data_list[0].responseType
value: data_list[0],
mode: type
});
});
})
}
rJS(window)
.ready(function (g) {
g.props = {};
......@@ -101,4 +111,4 @@
return RSVP.all(promise_list);
});
})
}(window, rJS, loopEventListener));
\ No newline at end of file
}(window, rJS, loopEventListener, jIO));
\ No newline at end of file
......@@ -175,11 +175,11 @@
zip = new JSZip();
for (i = 0, i_len = response_list.length; i < i_len; i += 1) {
response = response_list[i];
url = response.responseURL.substr(path_to_save_length)
url = url_list[i].substr(path_to_save_length)
if ( url.endsWith("/") ) {
url = url + "index.html";
}
zip.file(url, response.responseText)
zip.file(url, response)
};
return zip.generateAsync({type:"blob"});
})
......
......@@ -5551,6 +5551,34 @@ Query.searchTextToRegExp = searchTextToRegExp;
}
util.readBlobAsDataURL = readBlobAsDataURL;
function base64toBlob(b64String, mimeString) {
var byteString = atob(b64String),
// write the bytes of the string to an ArrayBuffer
arrayBuffer = new ArrayBuffer(byteString.length),
_ia = new Uint8Array(arrayBuffer),
i;
for (i = 0; i < byteString.length; i += 1) {
_ia[i] = byteString.charCodeAt(i);
}
return new Blob([arrayBuffer], {type: mimeString});
}
util.base64toBlob = base64toBlob;
// https://gist.github.com/davoclavo/4424731
function dataURItoBlob(dataURI) {
if (dataURI === 'data:') {
return new Blob();
}
// convert base64 to raw binary data held in a string
var mimeString = dataURI.split(',')[0].split(':')[1];
mimeString = mimeString.slice(0, mimeString.length - ";base64".length);
return base64toBlob(dataURI.split(',')[1], mimeString);
}
util.dataURItoBlob = dataURItoBlob;
// tools
function checkId(argument_list, storage, method_name) {
if (typeof argument_list[0] !== 'string' || argument_list[0] === '') {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment