Commit 954f9dee authored by Romain Courteaud's avatar Romain Courteaud

[erp5_xhtml_style/erp5_web_renderjs_ui] Update renderjs 0.18.0

parent f2f166b5
...@@ -728,6 +728,25 @@ if (typeof document.contains !== 'function') { ...@@ -728,6 +728,25 @@ if (typeof document.contains !== 'function') {
Event, URL) { Event, URL) {
"use strict"; "use strict";
function ensurePushableQueue(callback, argument_list, context) {
var result;
try {
result = callback.apply(context, argument_list);
} catch (e) {
return new RSVP.Queue()
.push(function returnPushableError() {
return RSVP.reject(e);
});
}
if (result instanceof RSVP.Queue) {
return result;
}
return new RSVP.Queue()
.push(function returnPushableResult() {
return result;
});
}
function readBlobAsDataURL(blob) { function readBlobAsDataURL(blob) {
var fr = new FileReader(); var fr = new FileReader();
return new RSVP.Promise(function waitFormDataURLRead(resolve, reject) { return new RSVP.Promise(function waitFormDataURLRead(resolve, reject) {
...@@ -884,54 +903,22 @@ if (typeof document.contains !== 'function') { ...@@ -884,54 +903,22 @@ if (typeof document.contains !== 'function') {
if (!(this instanceof Mutex)) { if (!(this instanceof Mutex)) {
return new Mutex(); return new Mutex();
} }
this._latest_defer = null; this._latest_promise = null;
}; };
Mutex.prototype = { Mutex.prototype = {
constructor: Mutex, constructor: Mutex,
lockAndRun: function lockMutexAndRun(callback) {
lock: function lockMutex() { var previous_promise = this._latest_promise;
var previous_defer = this._latest_defer, if (previous_promise === null) {
current_defer = RSVP.defer(), this._latest_promise = RSVP.resolve(callback());
queue = new RSVP.Queue(); } else {
this._latest_promise = this._latest_promise
this._latest_defer = current_defer; .always(function () {
return callback();
if (previous_defer !== null) { });
queue.push(function acquireMutex() {
return previous_defer.promise;
});
} }
return this._latest_promise;
// Create a new promise (.then) not cancellable
// to allow external cancellation of the callback
// without breaking the mutex implementation
queue
.fail(current_defer.resolve.bind(current_defer));
return queue
.push(function generateMutexUnlock() {
return function runAndUnlock(callback) {
return new RSVP.Queue()
.push(function executeMutexCallback() {
return callback();
})
.push(function releaseMutexAfterSuccess(result) {
current_defer.resolve(result);
return result;
}, function releaseMutexAfterError(error) {
current_defer.resolve(error);
throw error;
});
};
});
},
lockAndRun: function (callback) {
return this.lock()
.push(function executeLockAndRunCallback(runAndUnlock) {
return runAndUnlock(callback);
});
} }
}; };
...@@ -1178,13 +1165,17 @@ if (typeof document.contains !== 'function') { ...@@ -1178,13 +1165,17 @@ if (typeof document.contains !== 'function') {
RenderJSGadget.prototype.__required_css_list = []; RenderJSGadget.prototype.__required_css_list = [];
RenderJSGadget.prototype.__required_js_list = []; RenderJSGadget.prototype.__required_js_list = [];
function createGadgetMonitor(g) { function deleteGadgetMonitor(g) {
if (g.__monitor !== undefined) { if (g.hasOwnProperty('__monitor')) {
g.__monitor.cancel(); g.__monitor.cancel();
delete g.__monitor;
g.__job_list = [];
} }
}
function createGadgetMonitor(g) {
g.__monitor = new Monitor(); g.__monitor = new Monitor();
g.__job_dict = {}; g.__job_dict = {};
g.__job_list = [];
g.__job_triggered = false; g.__job_triggered = false;
g.__monitor.fail(function handleGadgetMonitorError(error) { g.__monitor.fail(function handleGadgetMonitorError(error) {
if (!(error instanceof RSVP.CancellationError)) { if (!(error instanceof RSVP.CancellationError)) {
...@@ -1194,9 +1185,12 @@ if (typeof document.contains !== 'function') { ...@@ -1194,9 +1185,12 @@ if (typeof document.contains !== 'function') {
}).fail(letsCrash); }).fail(letsCrash);
} }
function clearGadgetInternalParameters() { function clearGadgetInternalParameters(gadget) {
this.__sub_gadget_dict = {}; gadget.__sub_gadget_dict = {};
createGadgetMonitor(this); gadget.__job_list = [];
if (gadget.__json_state !== undefined) {
gadget.state = JSON.parse(gadget.__json_state);
}
} }
function loadSubGadgetDOMDeclaration() { function loadSubGadgetDOMDeclaration() {
...@@ -1241,17 +1235,13 @@ if (typeof document.contains !== 'function') { ...@@ -1241,17 +1235,13 @@ if (typeof document.contains !== 'function') {
return RSVP.all(promise_list); return RSVP.all(promise_list);
} }
RenderJSGadget.__ready_list = [clearGadgetInternalParameters, RenderJSGadget.__ready_list = [];
loadSubGadgetDOMDeclaration];
RenderJSGadget.ready = function ready(callback) { RenderJSGadget.ready = function ready(callback) {
this.__ready_list.push(callback); this.__ready_list.push(callback);
return this; return this;
}; };
RenderJSGadget.setState = function setState(state_dict) { RenderJSGadget.setState = function setState(state_dict) {
var json_state = JSON.stringify(state_dict); this.prototype.__json_state = JSON.stringify(state_dict);
this.__ready_list.unshift(function setStateDefaultValue() {
this.state = JSON.parse(json_state);
});
return this; return this;
}; };
RenderJSGadget.onStateChange = function onStateChange(callback) { RenderJSGadget.onStateChange = function onStateChange(callback) {
...@@ -1301,10 +1291,7 @@ if (typeof document.contains !== 'function') { ...@@ -1301,10 +1291,7 @@ if (typeof document.contains !== 'function') {
}; };
function runJob(gadget, name, callback, argument_list) { function runJob(gadget, name, callback, argument_list) {
var job_promise = new RSVP.Queue() var job_promise = ensurePushableQueue(callback, argument_list, gadget);
.push(function waitForJobCallback() {
return callback.apply(gadget, argument_list);
});
if (gadget.__job_dict.hasOwnProperty(name)) { if (gadget.__job_dict.hasOwnProperty(name)) {
gadget.__job_dict[name].cancel(); gadget.__job_dict[name].cancel();
} }
...@@ -1321,6 +1308,11 @@ if (typeof document.contains !== 'function') { ...@@ -1321,6 +1308,11 @@ if (typeof document.contains !== 'function') {
} }
function startService(gadget) { function startService(gadget) {
if ((gadget.constructor.__service_list.length === 0) &&
(!gadget.constructor.__job_declared)) {
return;
}
createGadgetMonitor(gadget);
gadget.__monitor.monitor(new RSVP.Queue() gadget.__monitor.monitor(new RSVP.Queue()
.push(function monitorAllServiceList() { .push(function monitorAllServiceList() {
var i, var i,
...@@ -1344,6 +1336,7 @@ if (typeof document.contains !== 'function') { ...@@ -1344,6 +1336,7 @@ if (typeof document.contains !== 'function') {
// of a function inside a service // of a function inside a service
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
RenderJSGadget.declareJob = function declareJob(name, callback) { RenderJSGadget.declareJob = function declareJob(name, callback) {
this.__job_declared = true;
this.prototype[name] = function triggerJob() { this.prototype[name] = function triggerJob() {
var context = this, var context = this,
argument_list = arguments; argument_list = arguments;
...@@ -1377,10 +1370,11 @@ if (typeof document.contains !== 'function') { ...@@ -1377,10 +1370,11 @@ if (typeof document.contains !== 'function') {
if (!context.hasOwnProperty(mutex_name)) { if (!context.hasOwnProperty(mutex_name)) {
context[mutex_name] = new Mutex(); context[mutex_name] = new Mutex();
} }
return context[mutex_name].lockAndRun(waitForMethodCallback); return ensurePushableQueue(context[mutex_name].lockAndRun,
[waitForMethodCallback],
context[mutex_name]);
} }
return new RSVP.Queue() return ensurePushableQueue(callback, argument_list, context);
.push(waitForMethodCallback);
}; };
// Allow chain // Allow chain
return this; return this;
...@@ -1437,10 +1431,11 @@ if (typeof document.contains !== 'function') { ...@@ -1437,10 +1431,11 @@ if (typeof document.contains !== 'function') {
} }
if (modified && context.__state_change_callback !== undefined) { if (modified && context.__state_change_callback !== undefined) {
context.__modification_dict = modification_dict; context.__modification_dict = modification_dict;
return new RSVP.Queue() return ensurePushableQueue(
.push(function waitForStateChangeCallback() { context.__state_change_callback,
return context.__state_change_callback(modification_dict); [modification_dict],
}) context
)
.push(function handleStateChangeSuccess(result) { .push(function handleStateChangeSuccess(result) {
delete context.__modification_dict; delete context.__modification_dict;
return result; return result;
...@@ -1453,9 +1448,18 @@ if (typeof document.contains !== 'function') { ...@@ -1453,9 +1448,18 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function acquire(child_gadget, method_name, argument_list) { function acquire(child_gadget, method_name, argument_list) {
var gadget = this, var gadget = this,
// Do not specify default __acquired_method_dict on prototype
// to prevent modifying this default value (with
// allowPublicAcquiredMethod for example)
aq_dict = gadget.__acquired_method_dict || {},
key, key,
gadget_scope; gadget_scope;
if (!aq_dict.hasOwnProperty(method_name)) {
// "aq_dynamic is not defined"
return gadget.__aq_parent(method_name, argument_list);
}
for (key in gadget.__sub_gadget_dict) { for (key in gadget.__sub_gadget_dict) {
if (gadget.__sub_gadget_dict.hasOwnProperty(key)) { if (gadget.__sub_gadget_dict.hasOwnProperty(key)) {
if (gadget.__sub_gadget_dict[key] === child_gadget) { if (gadget.__sub_gadget_dict[key] === child_gadget) {
...@@ -1463,18 +1467,12 @@ if (typeof document.contains !== 'function') { ...@@ -1463,18 +1467,12 @@ if (typeof document.contains !== 'function') {
} }
} }
} }
return new RSVP.Queue()
.push(function waitForAcquireMethod() { return ensurePushableQueue(
// Do not specify default __acquired_method_dict on prototype aq_dict[method_name],
// to prevent modifying this default value (with [argument_list, gadget_scope],
// allowPublicAcquiredMethod for example) gadget
var aq_dict = gadget.__acquired_method_dict || {}; )
if (aq_dict.hasOwnProperty(method_name)) {
return aq_dict[method_name].apply(gadget,
[argument_list, gadget_scope]);
}
throw new renderJS.AcquisitionError("aq_dynamic is not defined");
})
.push(undefined, function handleAcquireMethodError(error) { .push(undefined, function handleAcquireMethodError(error) {
if (error instanceof renderJS.AcquisitionError) { if (error instanceof renderJS.AcquisitionError) {
return gadget.__aq_parent(method_name, argument_list); return gadget.__aq_parent(method_name, argument_list);
...@@ -1488,10 +1486,11 @@ if (typeof document.contains !== 'function') { ...@@ -1488,10 +1486,11 @@ if (typeof document.contains !== 'function') {
this.prototype[name] = function acquireMethod() { this.prototype[name] = function acquireMethod() {
var argument_list = Array.prototype.slice.call(arguments, 0), var argument_list = Array.prototype.slice.call(arguments, 0),
gadget = this; gadget = this;
return new RSVP.Queue() return ensurePushableQueue(
.push(function waitForAqParent() { gadget.__aq_parent,
return gadget.__aq_parent(method_name_to_acquire, argument_list); [method_name_to_acquire, argument_list],
}); gadget
);
}; };
// Allow chain // Allow chain
...@@ -1532,7 +1531,7 @@ if (typeof document.contains !== 'function') { ...@@ -1532,7 +1531,7 @@ if (typeof document.contains !== 'function') {
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSEmbeddedGadget.__ready_list = RenderJSGadget.__ready_list.slice(); RenderJSEmbeddedGadget.__ready_list = [];
RenderJSEmbeddedGadget.__service_list = RenderJSEmbeddedGadget.__service_list =
RenderJSGadget.__service_list.slice(); RenderJSGadget.__service_list.slice();
RenderJSEmbeddedGadget.ready = RenderJSEmbeddedGadget.ready =
...@@ -1553,34 +1552,40 @@ if (typeof document.contains !== 'function') { ...@@ -1553,34 +1552,40 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget // privateDeclarePublicGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclarePublicGadget(url, options, parent_gadget) { function createPrivateInstanceFromKlass(Klass, options, parent_gadget) {
// Get the gadget class and instanciate it
if (options.element === undefined) {
options.element = document.createElement("div");
}
var i,
gadget_instance,
template_node_list = Klass.__template_element.body.childNodes,
fragment = document.createDocumentFragment();
gadget_instance = new Klass();
gadget_instance.element = options.element;
gadget_instance.state = {};
for (i = 0; i < template_node_list.length; i += 1) {
fragment.appendChild(
template_node_list[i].cloneNode(true)
);
}
gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget);
return gadget_instance;
}
return renderJS.declareGadgetKlass(url) function privateDeclarePublicGadget(url, options, parent_gadget) {
// gadget loading should not be interrupted var klass = renderJS.declareGadgetKlass(url);
// if not, gadget's definition will not be complete // gadget loading should not be interrupted
//.then will return another promise // if not, gadget's definition will not be complete
//so loading_klass_promise can't be cancel //.then will return another promise
.then(function createPrivateInstanceFromKlass(Klass) { //so loading_klass_promise can't be cancel
// Get the gadget class and instanciate it if (typeof klass.then === 'function') {
if (options.element === undefined) { return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) {
options.element = document.createElement("div"); return createPrivateInstanceFromKlass(Klass, options, parent_gadget);
}
var i,
gadget_instance,
template_node_list = Klass.__template_element.body.childNodes,
fragment = document.createDocumentFragment();
gadget_instance = new Klass();
gadget_instance.element = options.element;
gadget_instance.state = {};
for (i = 0; i < template_node_list.length; i += 1) {
fragment.appendChild(
template_node_list[i].cloneNode(true)
);
}
gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget);
return gadget_instance;
}); });
}
return createPrivateInstanceFromKlass(klass, options, parent_gadget);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1592,14 +1597,14 @@ if (typeof document.contains !== 'function') { ...@@ -1592,14 +1597,14 @@ if (typeof document.contains !== 'function') {
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSIframeGadget.__ready_list = RenderJSGadget.__ready_list.slice(); RenderJSIframeGadget.__ready_list = [];
RenderJSIframeGadget.ready = RenderJSIframeGadget.ready =
RenderJSGadget.ready; RenderJSGadget.ready;
RenderJSIframeGadget.setState = RenderJSIframeGadget.setState =
RenderJSGadget.setState; RenderJSGadget.setState;
RenderJSIframeGadget.onStateChange = RenderJSIframeGadget.onStateChange =
RenderJSGadget.onStateChange; RenderJSGadget.onStateChange;
RenderJSIframeGadget.__service_list = RenderJSGadget.__service_list.slice(); RenderJSIframeGadget.__service_list = [];
RenderJSIframeGadget.declareService = RenderJSIframeGadget.declareService =
RenderJSGadget.declareService; RenderJSGadget.declareService;
RenderJSIframeGadget.onEvent = RenderJSIframeGadget.onEvent =
...@@ -1677,10 +1682,10 @@ if (typeof document.contains !== 'function') { ...@@ -1677,10 +1682,10 @@ if (typeof document.contains !== 'function') {
}); });
} }
); );
return new RSVP.Queue()
.push(function waitForChannelCall() { return ensurePushableQueue(function waitForChannelCall() {
return wait_promise; return wait_promise;
}); });
}; };
return "OK"; return "OK";
} }
...@@ -1698,7 +1703,10 @@ if (typeof document.contains !== 'function') { ...@@ -1698,7 +1703,10 @@ if (typeof document.contains !== 'function') {
}); });
gadget_instance.__chan.bind("acquire", gadget_instance.__chan.bind("acquire",
function handleChannelAcquire(trans, params) { function handleChannelAcquire(trans, params) {
gadget_instance.__aq_parent.apply(gadget_instance, params) new RSVP.Queue()
.push(function () {
return gadget_instance.__aq_parent.apply(gadget_instance, params);
})
.then(trans.complete) .then(trans.complete)
.fail(function handleChannelAcquireError(e) { .fail(function handleChannelAcquireError(e) {
trans.error(e.toString()); trans.error(e.toString());
...@@ -1739,9 +1747,68 @@ if (typeof document.contains !== 'function') { ...@@ -1739,9 +1747,68 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget // RenderJSGadget.declareGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url) {
var i,
scope,
queue;
clearGadgetInternalParameters(gadget_instance);
// Store local reference to the gadget instance
scope = options.scope;
if (scope === undefined) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
}
}
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
gadget_instance.element.setAttribute("data-gadget-scope",
scope);
// Put some attribute to ease page layout comprehension
gadget_instance.element.setAttribute("data-gadget-url", url);
gadget_instance.element.setAttribute("data-gadget-sandbox",
options.sandbox);
gadget_instance.element._gadget = gadget_instance;
function ready_executable_wrapper(fct) {
return function executeReadyWrapper() {
return fct.call(gadget_instance, gadget_instance);
};
}
function ready_wrapper() {
if (document.contains(gadget_instance.element)) {
startService(gadget_instance);
}
// Always return the gadget instance after ready function
return gadget_instance;
}
if (gadget_instance.constructor.__ready_list.length) {
queue = new RSVP.Queue();
// Trigger calling of all ready callback
for (i = 0; i < gadget_instance.constructor.__ready_list.length;
i += 1) {
// Put a timeout?
queue.push(ready_executable_wrapper(
gadget_instance.constructor.__ready_list[i]
));
}
queue.push(ready_wrapper);
return queue;
}
return ready_wrapper();
}
RenderJSGadget RenderJSGadget
.declareMethod('declareGadget', function declareGadget(url, options) { .declareMethod('declareGadget', function declareGadget(url, options) {
var parent_gadget = this; var parent_gadget = this,
method,
result;
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
...@@ -1753,74 +1820,30 @@ if (typeof document.contains !== 'function') { ...@@ -1753,74 +1820,30 @@ if (typeof document.contains !== 'function') {
// transform url to absolute url if it is relative // transform url to absolute url if it is relative
url = renderJS.getAbsoluteURL(url, this.__path); url = renderJS.getAbsoluteURL(url, this.__path);
return new RSVP.Queue() if (options.sandbox === "public") {
.push(function waitForPrivateDeclareGadget() { method = privateDeclarePublicGadget;
var method; } else if (options.sandbox === "iframe") {
if (options.sandbox === "public") { method = privateDeclareIframeGadget;
method = privateDeclarePublicGadget; } else if (options.sandbox === "dataurl") {
} else if (options.sandbox === "iframe") { method = privateDeclareDataUrlGadget;
method = privateDeclareIframeGadget; } else {
} else if (options.sandbox === "dataurl") { throw new Error("Unsupported sandbox options '" +
method = privateDeclareDataUrlGadget; options.sandbox + "'");
} else { }
throw new Error("Unsupported sandbox options '" + result = method(url, options, parent_gadget);
options.sandbox + "'"); // Set the HTML context
} if (typeof result.then === 'function') {
return method(url, options, parent_gadget); return new RSVP.Queue()
}) .push(function () {
// Set the HTML context return result;
.push(function setGadgetInstanceHTMLContext(gadget_instance) { })
var i, .push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) {
scope, return setGadgetInstanceHTMLContext(gadget_instance, options,
queue = new RSVP.Queue(); parent_gadget, url);
// Trigger calling of all ready callback });
function ready_wrapper() { }
return gadget_instance; return setGadgetInstanceHTMLContext(result, options,
} parent_gadget, url);
function ready_executable_wrapper(fct) {
return function executeReadyWrapper() {
return fct.call(gadget_instance, gadget_instance);
};
}
for (i = 0; i < gadget_instance.constructor.__ready_list.length;
i += 1) {
// Put a timeout?
queue.push(ready_executable_wrapper(
gadget_instance.constructor.__ready_list[i]
));
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
}
// Store local reference to the gadget instance
scope = options.scope;
if (scope === undefined) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
}
}
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
gadget_instance.element.setAttribute("data-gadget-scope",
scope);
// Put some attribute to ease page layout comprehension
gadget_instance.element.setAttribute("data-gadget-url", url);
gadget_instance.element.setAttribute("data-gadget-sandbox",
options.sandbox);
gadget_instance.element._gadget = gadget_instance;
if (document.contains(gadget_instance.element)) {
// Put a timeout
queue.push(startService);
}
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
return queue;
});
}) })
.declareMethod('getDeclaredGadget', .declareMethod('getDeclaredGadget',
function getDeclaredGadget(gadget_scope) { function getDeclaredGadget(gadget_scope) {
...@@ -1958,7 +1981,7 @@ if (typeof document.contains !== 'function') { ...@@ -1958,7 +1981,7 @@ if (typeof document.contains !== 'function') {
tmp_constructor = function createSuperKlass() { tmp_constructor = function createSuperKlass() {
RenderJSGadget.call(this); RenderJSGadget.call(this);
}; };
tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice(); tmp_constructor.__ready_list = [];
tmp_constructor.__service_list = RenderJSGadget.__service_list.slice(); tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();
tmp_constructor.declareMethod = tmp_constructor.declareMethod =
RenderJSGadget.declareMethod; RenderJSGadget.declareMethod;
...@@ -1998,6 +2021,11 @@ if (typeof document.contains !== 'function') { ...@@ -1998,6 +2021,11 @@ if (typeof document.contains !== 'function') {
tmp_constructor.prototype['__' + key] = parsed_html[key]; tmp_constructor.prototype['__' + key] = parsed_html[key];
} }
} }
// Check if there is a HTML declared subgadget
if (tmp_constructor.__template_element
.querySelectorAll('[data-gadget-url]').length) {
tmp_constructor.__ready_list.push(loadSubGadgetDOMDeclaration);
}
return tmp_constructor; return tmp_constructor;
} }
...@@ -2015,9 +2043,9 @@ if (typeof document.contains !== 'function') { ...@@ -2015,9 +2043,9 @@ if (typeof document.contains !== 'function') {
return defer.promise; return defer.promise;
} }
if (gadget_model_defer_dict[url].is_resolved) { if (gadget_model_defer_dict[url].is_resolved) {
return RSVP.resolve(gadget_model_defer_dict[url].result); return gadget_model_defer_dict[url].result;
} }
return RSVP.reject(gadget_model_defer_dict[url].result); throw gadget_model_defer_dict[url].result;
} }
gadget_model_defer_dict[url] = { gadget_model_defer_dict[url] = {
...@@ -2213,7 +2241,7 @@ if (typeof document.contains !== 'function') { ...@@ -2213,7 +2241,7 @@ if (typeof document.contains !== 'function') {
if (node.nodeType === Node.ELEMENT_NODE) { if (node.nodeType === Node.ELEMENT_NODE) {
if (node.hasAttribute("data-gadget-url") && if (node.hasAttribute("data-gadget-url") &&
(node._gadget !== undefined)) { (node._gadget !== undefined)) {
createGadgetMonitor(node._gadget); deleteGadgetMonitor(node._gadget);
} }
added_list = added_list =
node.querySelectorAll("[data-gadget-url]"); node.querySelectorAll("[data-gadget-url]");
...@@ -2221,7 +2249,7 @@ if (typeof document.contains !== 'function') { ...@@ -2221,7 +2249,7 @@ if (typeof document.contains !== 'function') {
for (k = 0; k < len2; k += 1) { for (k = 0; k < len2; k += 1) {
node = added_list[k]; node = added_list[k];
if (node._gadget !== undefined) { if (node._gadget !== undefined) {
createGadgetMonitor(node._gadget); deleteGadgetMonitor(node._gadget);
} }
} }
} }
...@@ -2311,7 +2339,7 @@ if (typeof document.contains !== 'function') { ...@@ -2311,7 +2339,7 @@ if (typeof document.contains !== 'function') {
// Create the root gadget instance and put it in the loading stack // Create the root gadget instance and put it in the loading stack
TmpConstructor = RenderJSEmbeddedGadget; TmpConstructor = RenderJSEmbeddedGadget;
TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice(); TmpConstructor.__ready_list = [];
TmpConstructor.__service_list = RenderJSGadget.__service_list.slice(); TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
TmpConstructor.prototype.__path = url; TmpConstructor.prototype.__path = url;
root_gadget = new RenderJSEmbeddedGadget(); root_gadget = new RenderJSEmbeddedGadget();
...@@ -2419,25 +2447,19 @@ if (typeof document.contains !== 'function') { ...@@ -2419,25 +2447,19 @@ if (typeof document.contains !== 'function') {
var i, var i,
ready_queue = new RSVP.Queue(); ready_queue = new RSVP.Queue();
function ready_wrapper() {
return root_gadget;
}
function ready_executable_wrapper(fct) { function ready_executable_wrapper(fct) {
return function wrapReadyFunction(g) { return function wrapReadyFunction() {
return fct.call(g, g); return fct.call(root_gadget, root_gadget);
}; };
} }
TmpConstructor.ready(function startServiceInReady() { TmpConstructor.ready(function startServiceInReady() {
return startService(this); return startService(root_gadget);
}); });
ready_queue.push(ready_wrapper);
for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) { for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) {
// Put a timeout? // Put a timeout?
ready_queue ready_queue
.push(ready_executable_wrapper(TmpConstructor.__ready_list[i])) .push(ready_executable_wrapper(TmpConstructor.__ready_list[i]));
// Always return the gadget instance after ready function
.push(ready_wrapper);
} }
return ready_queue; return ready_queue;
} }
...@@ -2510,6 +2532,8 @@ if (typeof document.contains !== 'function') { ...@@ -2510,6 +2532,8 @@ if (typeof document.contains !== 'function') {
return configureMutationObserver(TmpConstructor, url, root_gadget); return configureMutationObserver(TmpConstructor, url, root_gadget);
}) })
.push(function waitForReadyList() { .push(function waitForReadyList() {
clearGadgetInternalParameters(root_gadget);
TmpConstructor.__ready_list.unshift(loadSubGadgetDOMDeclaration);
// Trigger all ready functions // Trigger all ready functions
return triggerReadyList(TmpConstructor, root_gadget); return triggerReadyList(TmpConstructor, root_gadget);
}) })
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>964.57262.9791.60330</string> </value> <value> <string>967.39405.57847.43571</string> </value>
</item> </item>
<item> <item>
<key> <string>state</string> </key> <key> <string>state</string> </key>
...@@ -248,7 +248,7 @@ ...@@ -248,7 +248,7 @@
</tuple> </tuple>
<state> <state>
<tuple> <tuple>
<float>1516196938.48</float> <float>1526568046.47</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -728,6 +728,25 @@ if (typeof document.contains !== 'function') { ...@@ -728,6 +728,25 @@ if (typeof document.contains !== 'function') {
Event, URL) { Event, URL) {
"use strict"; "use strict";
function ensurePushableQueue(callback, argument_list, context) {
var result;
try {
result = callback.apply(context, argument_list);
} catch (e) {
return new RSVP.Queue()
.push(function returnPushableError() {
return RSVP.reject(e);
});
}
if (result instanceof RSVP.Queue) {
return result;
}
return new RSVP.Queue()
.push(function returnPushableResult() {
return result;
});
}
function readBlobAsDataURL(blob) { function readBlobAsDataURL(blob) {
var fr = new FileReader(); var fr = new FileReader();
return new RSVP.Promise(function waitFormDataURLRead(resolve, reject) { return new RSVP.Promise(function waitFormDataURLRead(resolve, reject) {
...@@ -884,54 +903,22 @@ if (typeof document.contains !== 'function') { ...@@ -884,54 +903,22 @@ if (typeof document.contains !== 'function') {
if (!(this instanceof Mutex)) { if (!(this instanceof Mutex)) {
return new Mutex(); return new Mutex();
} }
this._latest_defer = null; this._latest_promise = null;
}; };
Mutex.prototype = { Mutex.prototype = {
constructor: Mutex, constructor: Mutex,
lockAndRun: function lockMutexAndRun(callback) {
lock: function lockMutex() { var previous_promise = this._latest_promise;
var previous_defer = this._latest_defer, if (previous_promise === null) {
current_defer = RSVP.defer(), this._latest_promise = RSVP.resolve(callback());
queue = new RSVP.Queue(); } else {
this._latest_promise = this._latest_promise
this._latest_defer = current_defer; .always(function () {
return callback();
if (previous_defer !== null) { });
queue.push(function acquireMutex() {
return previous_defer.promise;
});
} }
return this._latest_promise;
// Create a new promise (.then) not cancellable
// to allow external cancellation of the callback
// without breaking the mutex implementation
queue
.fail(current_defer.resolve.bind(current_defer));
return queue
.push(function generateMutexUnlock() {
return function runAndUnlock(callback) {
return new RSVP.Queue()
.push(function executeMutexCallback() {
return callback();
})
.push(function releaseMutexAfterSuccess(result) {
current_defer.resolve(result);
return result;
}, function releaseMutexAfterError(error) {
current_defer.resolve(error);
throw error;
});
};
});
},
lockAndRun: function (callback) {
return this.lock()
.push(function executeLockAndRunCallback(runAndUnlock) {
return runAndUnlock(callback);
});
} }
}; };
...@@ -1178,13 +1165,17 @@ if (typeof document.contains !== 'function') { ...@@ -1178,13 +1165,17 @@ if (typeof document.contains !== 'function') {
RenderJSGadget.prototype.__required_css_list = []; RenderJSGadget.prototype.__required_css_list = [];
RenderJSGadget.prototype.__required_js_list = []; RenderJSGadget.prototype.__required_js_list = [];
function createGadgetMonitor(g) { function deleteGadgetMonitor(g) {
if (g.__monitor !== undefined) { if (g.hasOwnProperty('__monitor')) {
g.__monitor.cancel(); g.__monitor.cancel();
delete g.__monitor;
g.__job_list = [];
} }
}
function createGadgetMonitor(g) {
g.__monitor = new Monitor(); g.__monitor = new Monitor();
g.__job_dict = {}; g.__job_dict = {};
g.__job_list = [];
g.__job_triggered = false; g.__job_triggered = false;
g.__monitor.fail(function handleGadgetMonitorError(error) { g.__monitor.fail(function handleGadgetMonitorError(error) {
if (!(error instanceof RSVP.CancellationError)) { if (!(error instanceof RSVP.CancellationError)) {
...@@ -1194,9 +1185,12 @@ if (typeof document.contains !== 'function') { ...@@ -1194,9 +1185,12 @@ if (typeof document.contains !== 'function') {
}).fail(letsCrash); }).fail(letsCrash);
} }
function clearGadgetInternalParameters() { function clearGadgetInternalParameters(gadget) {
this.__sub_gadget_dict = {}; gadget.__sub_gadget_dict = {};
createGadgetMonitor(this); gadget.__job_list = [];
if (gadget.__json_state !== undefined) {
gadget.state = JSON.parse(gadget.__json_state);
}
} }
function loadSubGadgetDOMDeclaration() { function loadSubGadgetDOMDeclaration() {
...@@ -1241,17 +1235,13 @@ if (typeof document.contains !== 'function') { ...@@ -1241,17 +1235,13 @@ if (typeof document.contains !== 'function') {
return RSVP.all(promise_list); return RSVP.all(promise_list);
} }
RenderJSGadget.__ready_list = [clearGadgetInternalParameters, RenderJSGadget.__ready_list = [];
loadSubGadgetDOMDeclaration];
RenderJSGadget.ready = function ready(callback) { RenderJSGadget.ready = function ready(callback) {
this.__ready_list.push(callback); this.__ready_list.push(callback);
return this; return this;
}; };
RenderJSGadget.setState = function setState(state_dict) { RenderJSGadget.setState = function setState(state_dict) {
var json_state = JSON.stringify(state_dict); this.prototype.__json_state = JSON.stringify(state_dict);
this.__ready_list.unshift(function setStateDefaultValue() {
this.state = JSON.parse(json_state);
});
return this; return this;
}; };
RenderJSGadget.onStateChange = function onStateChange(callback) { RenderJSGadget.onStateChange = function onStateChange(callback) {
...@@ -1301,10 +1291,7 @@ if (typeof document.contains !== 'function') { ...@@ -1301,10 +1291,7 @@ if (typeof document.contains !== 'function') {
}; };
function runJob(gadget, name, callback, argument_list) { function runJob(gadget, name, callback, argument_list) {
var job_promise = new RSVP.Queue() var job_promise = ensurePushableQueue(callback, argument_list, gadget);
.push(function waitForJobCallback() {
return callback.apply(gadget, argument_list);
});
if (gadget.__job_dict.hasOwnProperty(name)) { if (gadget.__job_dict.hasOwnProperty(name)) {
gadget.__job_dict[name].cancel(); gadget.__job_dict[name].cancel();
} }
...@@ -1321,6 +1308,11 @@ if (typeof document.contains !== 'function') { ...@@ -1321,6 +1308,11 @@ if (typeof document.contains !== 'function') {
} }
function startService(gadget) { function startService(gadget) {
if ((gadget.constructor.__service_list.length === 0) &&
(!gadget.constructor.__job_declared)) {
return;
}
createGadgetMonitor(gadget);
gadget.__monitor.monitor(new RSVP.Queue() gadget.__monitor.monitor(new RSVP.Queue()
.push(function monitorAllServiceList() { .push(function monitorAllServiceList() {
var i, var i,
...@@ -1344,6 +1336,7 @@ if (typeof document.contains !== 'function') { ...@@ -1344,6 +1336,7 @@ if (typeof document.contains !== 'function') {
// of a function inside a service // of a function inside a service
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
RenderJSGadget.declareJob = function declareJob(name, callback) { RenderJSGadget.declareJob = function declareJob(name, callback) {
this.__job_declared = true;
this.prototype[name] = function triggerJob() { this.prototype[name] = function triggerJob() {
var context = this, var context = this,
argument_list = arguments; argument_list = arguments;
...@@ -1377,10 +1370,11 @@ if (typeof document.contains !== 'function') { ...@@ -1377,10 +1370,11 @@ if (typeof document.contains !== 'function') {
if (!context.hasOwnProperty(mutex_name)) { if (!context.hasOwnProperty(mutex_name)) {
context[mutex_name] = new Mutex(); context[mutex_name] = new Mutex();
} }
return context[mutex_name].lockAndRun(waitForMethodCallback); return ensurePushableQueue(context[mutex_name].lockAndRun,
[waitForMethodCallback],
context[mutex_name]);
} }
return new RSVP.Queue() return ensurePushableQueue(callback, argument_list, context);
.push(waitForMethodCallback);
}; };
// Allow chain // Allow chain
return this; return this;
...@@ -1437,10 +1431,11 @@ if (typeof document.contains !== 'function') { ...@@ -1437,10 +1431,11 @@ if (typeof document.contains !== 'function') {
} }
if (modified && context.__state_change_callback !== undefined) { if (modified && context.__state_change_callback !== undefined) {
context.__modification_dict = modification_dict; context.__modification_dict = modification_dict;
return new RSVP.Queue() return ensurePushableQueue(
.push(function waitForStateChangeCallback() { context.__state_change_callback,
return context.__state_change_callback(modification_dict); [modification_dict],
}) context
)
.push(function handleStateChangeSuccess(result) { .push(function handleStateChangeSuccess(result) {
delete context.__modification_dict; delete context.__modification_dict;
return result; return result;
...@@ -1453,9 +1448,18 @@ if (typeof document.contains !== 'function') { ...@@ -1453,9 +1448,18 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function acquire(child_gadget, method_name, argument_list) { function acquire(child_gadget, method_name, argument_list) {
var gadget = this, var gadget = this,
// Do not specify default __acquired_method_dict on prototype
// to prevent modifying this default value (with
// allowPublicAcquiredMethod for example)
aq_dict = gadget.__acquired_method_dict || {},
key, key,
gadget_scope; gadget_scope;
if (!aq_dict.hasOwnProperty(method_name)) {
// "aq_dynamic is not defined"
return gadget.__aq_parent(method_name, argument_list);
}
for (key in gadget.__sub_gadget_dict) { for (key in gadget.__sub_gadget_dict) {
if (gadget.__sub_gadget_dict.hasOwnProperty(key)) { if (gadget.__sub_gadget_dict.hasOwnProperty(key)) {
if (gadget.__sub_gadget_dict[key] === child_gadget) { if (gadget.__sub_gadget_dict[key] === child_gadget) {
...@@ -1463,18 +1467,12 @@ if (typeof document.contains !== 'function') { ...@@ -1463,18 +1467,12 @@ if (typeof document.contains !== 'function') {
} }
} }
} }
return new RSVP.Queue()
.push(function waitForAcquireMethod() { return ensurePushableQueue(
// Do not specify default __acquired_method_dict on prototype aq_dict[method_name],
// to prevent modifying this default value (with [argument_list, gadget_scope],
// allowPublicAcquiredMethod for example) gadget
var aq_dict = gadget.__acquired_method_dict || {}; )
if (aq_dict.hasOwnProperty(method_name)) {
return aq_dict[method_name].apply(gadget,
[argument_list, gadget_scope]);
}
throw new renderJS.AcquisitionError("aq_dynamic is not defined");
})
.push(undefined, function handleAcquireMethodError(error) { .push(undefined, function handleAcquireMethodError(error) {
if (error instanceof renderJS.AcquisitionError) { if (error instanceof renderJS.AcquisitionError) {
return gadget.__aq_parent(method_name, argument_list); return gadget.__aq_parent(method_name, argument_list);
...@@ -1488,10 +1486,11 @@ if (typeof document.contains !== 'function') { ...@@ -1488,10 +1486,11 @@ if (typeof document.contains !== 'function') {
this.prototype[name] = function acquireMethod() { this.prototype[name] = function acquireMethod() {
var argument_list = Array.prototype.slice.call(arguments, 0), var argument_list = Array.prototype.slice.call(arguments, 0),
gadget = this; gadget = this;
return new RSVP.Queue() return ensurePushableQueue(
.push(function waitForAqParent() { gadget.__aq_parent,
return gadget.__aq_parent(method_name_to_acquire, argument_list); [method_name_to_acquire, argument_list],
}); gadget
);
}; };
// Allow chain // Allow chain
...@@ -1532,7 +1531,7 @@ if (typeof document.contains !== 'function') { ...@@ -1532,7 +1531,7 @@ if (typeof document.contains !== 'function') {
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSEmbeddedGadget.__ready_list = RenderJSGadget.__ready_list.slice(); RenderJSEmbeddedGadget.__ready_list = [];
RenderJSEmbeddedGadget.__service_list = RenderJSEmbeddedGadget.__service_list =
RenderJSGadget.__service_list.slice(); RenderJSGadget.__service_list.slice();
RenderJSEmbeddedGadget.ready = RenderJSEmbeddedGadget.ready =
...@@ -1553,34 +1552,40 @@ if (typeof document.contains !== 'function') { ...@@ -1553,34 +1552,40 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget // privateDeclarePublicGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclarePublicGadget(url, options, parent_gadget) { function createPrivateInstanceFromKlass(Klass, options, parent_gadget) {
// Get the gadget class and instanciate it
if (options.element === undefined) {
options.element = document.createElement("div");
}
var i,
gadget_instance,
template_node_list = Klass.__template_element.body.childNodes,
fragment = document.createDocumentFragment();
gadget_instance = new Klass();
gadget_instance.element = options.element;
gadget_instance.state = {};
for (i = 0; i < template_node_list.length; i += 1) {
fragment.appendChild(
template_node_list[i].cloneNode(true)
);
}
gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget);
return gadget_instance;
}
return renderJS.declareGadgetKlass(url) function privateDeclarePublicGadget(url, options, parent_gadget) {
// gadget loading should not be interrupted var klass = renderJS.declareGadgetKlass(url);
// if not, gadget's definition will not be complete // gadget loading should not be interrupted
//.then will return another promise // if not, gadget's definition will not be complete
//so loading_klass_promise can't be cancel //.then will return another promise
.then(function createPrivateInstanceFromKlass(Klass) { //so loading_klass_promise can't be cancel
// Get the gadget class and instanciate it if (typeof klass.then === 'function') {
if (options.element === undefined) { return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) {
options.element = document.createElement("div"); return createPrivateInstanceFromKlass(Klass, options, parent_gadget);
}
var i,
gadget_instance,
template_node_list = Klass.__template_element.body.childNodes,
fragment = document.createDocumentFragment();
gadget_instance = new Klass();
gadget_instance.element = options.element;
gadget_instance.state = {};
for (i = 0; i < template_node_list.length; i += 1) {
fragment.appendChild(
template_node_list[i].cloneNode(true)
);
}
gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget);
return gadget_instance;
}); });
}
return createPrivateInstanceFromKlass(klass, options, parent_gadget);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1592,14 +1597,14 @@ if (typeof document.contains !== 'function') { ...@@ -1592,14 +1597,14 @@ if (typeof document.contains !== 'function') {
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSIframeGadget.__ready_list = RenderJSGadget.__ready_list.slice(); RenderJSIframeGadget.__ready_list = [];
RenderJSIframeGadget.ready = RenderJSIframeGadget.ready =
RenderJSGadget.ready; RenderJSGadget.ready;
RenderJSIframeGadget.setState = RenderJSIframeGadget.setState =
RenderJSGadget.setState; RenderJSGadget.setState;
RenderJSIframeGadget.onStateChange = RenderJSIframeGadget.onStateChange =
RenderJSGadget.onStateChange; RenderJSGadget.onStateChange;
RenderJSIframeGadget.__service_list = RenderJSGadget.__service_list.slice(); RenderJSIframeGadget.__service_list = [];
RenderJSIframeGadget.declareService = RenderJSIframeGadget.declareService =
RenderJSGadget.declareService; RenderJSGadget.declareService;
RenderJSIframeGadget.onEvent = RenderJSIframeGadget.onEvent =
...@@ -1677,10 +1682,10 @@ if (typeof document.contains !== 'function') { ...@@ -1677,10 +1682,10 @@ if (typeof document.contains !== 'function') {
}); });
} }
); );
return new RSVP.Queue()
.push(function waitForChannelCall() { return ensurePushableQueue(function waitForChannelCall() {
return wait_promise; return wait_promise;
}); });
}; };
return "OK"; return "OK";
} }
...@@ -1698,7 +1703,10 @@ if (typeof document.contains !== 'function') { ...@@ -1698,7 +1703,10 @@ if (typeof document.contains !== 'function') {
}); });
gadget_instance.__chan.bind("acquire", gadget_instance.__chan.bind("acquire",
function handleChannelAcquire(trans, params) { function handleChannelAcquire(trans, params) {
gadget_instance.__aq_parent.apply(gadget_instance, params) new RSVP.Queue()
.push(function () {
return gadget_instance.__aq_parent.apply(gadget_instance, params);
})
.then(trans.complete) .then(trans.complete)
.fail(function handleChannelAcquireError(e) { .fail(function handleChannelAcquireError(e) {
trans.error(e.toString()); trans.error(e.toString());
...@@ -1739,9 +1747,68 @@ if (typeof document.contains !== 'function') { ...@@ -1739,9 +1747,68 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget.declareGadget // RenderJSGadget.declareGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url) {
var i,
scope,
queue;
clearGadgetInternalParameters(gadget_instance);
// Store local reference to the gadget instance
scope = options.scope;
if (scope === undefined) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
}
}
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
gadget_instance.element.setAttribute("data-gadget-scope",
scope);
// Put some attribute to ease page layout comprehension
gadget_instance.element.setAttribute("data-gadget-url", url);
gadget_instance.element.setAttribute("data-gadget-sandbox",
options.sandbox);
gadget_instance.element._gadget = gadget_instance;
function ready_executable_wrapper(fct) {
return function executeReadyWrapper() {
return fct.call(gadget_instance, gadget_instance);
};
}
function ready_wrapper() {
if (document.contains(gadget_instance.element)) {
startService(gadget_instance);
}
// Always return the gadget instance after ready function
return gadget_instance;
}
if (gadget_instance.constructor.__ready_list.length) {
queue = new RSVP.Queue();
// Trigger calling of all ready callback
for (i = 0; i < gadget_instance.constructor.__ready_list.length;
i += 1) {
// Put a timeout?
queue.push(ready_executable_wrapper(
gadget_instance.constructor.__ready_list[i]
));
}
queue.push(ready_wrapper);
return queue;
}
return ready_wrapper();
}
RenderJSGadget RenderJSGadget
.declareMethod('declareGadget', function declareGadget(url, options) { .declareMethod('declareGadget', function declareGadget(url, options) {
var parent_gadget = this; var parent_gadget = this,
method,
result;
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
...@@ -1753,74 +1820,30 @@ if (typeof document.contains !== 'function') { ...@@ -1753,74 +1820,30 @@ if (typeof document.contains !== 'function') {
// transform url to absolute url if it is relative // transform url to absolute url if it is relative
url = renderJS.getAbsoluteURL(url, this.__path); url = renderJS.getAbsoluteURL(url, this.__path);
return new RSVP.Queue() if (options.sandbox === "public") {
.push(function waitForPrivateDeclareGadget() { method = privateDeclarePublicGadget;
var method; } else if (options.sandbox === "iframe") {
if (options.sandbox === "public") { method = privateDeclareIframeGadget;
method = privateDeclarePublicGadget; } else if (options.sandbox === "dataurl") {
} else if (options.sandbox === "iframe") { method = privateDeclareDataUrlGadget;
method = privateDeclareIframeGadget; } else {
} else if (options.sandbox === "dataurl") { throw new Error("Unsupported sandbox options '" +
method = privateDeclareDataUrlGadget; options.sandbox + "'");
} else { }
throw new Error("Unsupported sandbox options '" + result = method(url, options, parent_gadget);
options.sandbox + "'"); // Set the HTML context
} if (typeof result.then === 'function') {
return method(url, options, parent_gadget); return new RSVP.Queue()
}) .push(function () {
// Set the HTML context return result;
.push(function setGadgetInstanceHTMLContext(gadget_instance) { })
var i, .push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) {
scope, return setGadgetInstanceHTMLContext(gadget_instance, options,
queue = new RSVP.Queue(); parent_gadget, url);
// Trigger calling of all ready callback });
function ready_wrapper() { }
return gadget_instance; return setGadgetInstanceHTMLContext(result, options,
} parent_gadget, url);
function ready_executable_wrapper(fct) {
return function executeReadyWrapper() {
return fct.call(gadget_instance, gadget_instance);
};
}
for (i = 0; i < gadget_instance.constructor.__ready_list.length;
i += 1) {
// Put a timeout?
queue.push(ready_executable_wrapper(
gadget_instance.constructor.__ready_list[i]
));
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
}
// Store local reference to the gadget instance
scope = options.scope;
if (scope === undefined) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
while (parent_gadget.__sub_gadget_dict.hasOwnProperty(scope)) {
scope = 'RJS_' + scope_increment;
scope_increment += 1;
}
}
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
gadget_instance.element.setAttribute("data-gadget-scope",
scope);
// Put some attribute to ease page layout comprehension
gadget_instance.element.setAttribute("data-gadget-url", url);
gadget_instance.element.setAttribute("data-gadget-sandbox",
options.sandbox);
gadget_instance.element._gadget = gadget_instance;
if (document.contains(gadget_instance.element)) {
// Put a timeout
queue.push(startService);
}
// Always return the gadget instance after ready function
queue.push(ready_wrapper);
return queue;
});
}) })
.declareMethod('getDeclaredGadget', .declareMethod('getDeclaredGadget',
function getDeclaredGadget(gadget_scope) { function getDeclaredGadget(gadget_scope) {
...@@ -1958,7 +1981,7 @@ if (typeof document.contains !== 'function') { ...@@ -1958,7 +1981,7 @@ if (typeof document.contains !== 'function') {
tmp_constructor = function createSuperKlass() { tmp_constructor = function createSuperKlass() {
RenderJSGadget.call(this); RenderJSGadget.call(this);
}; };
tmp_constructor.__ready_list = RenderJSGadget.__ready_list.slice(); tmp_constructor.__ready_list = [];
tmp_constructor.__service_list = RenderJSGadget.__service_list.slice(); tmp_constructor.__service_list = RenderJSGadget.__service_list.slice();
tmp_constructor.declareMethod = tmp_constructor.declareMethod =
RenderJSGadget.declareMethod; RenderJSGadget.declareMethod;
...@@ -1998,6 +2021,11 @@ if (typeof document.contains !== 'function') { ...@@ -1998,6 +2021,11 @@ if (typeof document.contains !== 'function') {
tmp_constructor.prototype['__' + key] = parsed_html[key]; tmp_constructor.prototype['__' + key] = parsed_html[key];
} }
} }
// Check if there is a HTML declared subgadget
if (tmp_constructor.__template_element
.querySelectorAll('[data-gadget-url]').length) {
tmp_constructor.__ready_list.push(loadSubGadgetDOMDeclaration);
}
return tmp_constructor; return tmp_constructor;
} }
...@@ -2015,9 +2043,9 @@ if (typeof document.contains !== 'function') { ...@@ -2015,9 +2043,9 @@ if (typeof document.contains !== 'function') {
return defer.promise; return defer.promise;
} }
if (gadget_model_defer_dict[url].is_resolved) { if (gadget_model_defer_dict[url].is_resolved) {
return RSVP.resolve(gadget_model_defer_dict[url].result); return gadget_model_defer_dict[url].result;
} }
return RSVP.reject(gadget_model_defer_dict[url].result); throw gadget_model_defer_dict[url].result;
} }
gadget_model_defer_dict[url] = { gadget_model_defer_dict[url] = {
...@@ -2213,7 +2241,7 @@ if (typeof document.contains !== 'function') { ...@@ -2213,7 +2241,7 @@ if (typeof document.contains !== 'function') {
if (node.nodeType === Node.ELEMENT_NODE) { if (node.nodeType === Node.ELEMENT_NODE) {
if (node.hasAttribute("data-gadget-url") && if (node.hasAttribute("data-gadget-url") &&
(node._gadget !== undefined)) { (node._gadget !== undefined)) {
createGadgetMonitor(node._gadget); deleteGadgetMonitor(node._gadget);
} }
added_list = added_list =
node.querySelectorAll("[data-gadget-url]"); node.querySelectorAll("[data-gadget-url]");
...@@ -2221,7 +2249,7 @@ if (typeof document.contains !== 'function') { ...@@ -2221,7 +2249,7 @@ if (typeof document.contains !== 'function') {
for (k = 0; k < len2; k += 1) { for (k = 0; k < len2; k += 1) {
node = added_list[k]; node = added_list[k];
if (node._gadget !== undefined) { if (node._gadget !== undefined) {
createGadgetMonitor(node._gadget); deleteGadgetMonitor(node._gadget);
} }
} }
} }
...@@ -2311,7 +2339,7 @@ if (typeof document.contains !== 'function') { ...@@ -2311,7 +2339,7 @@ if (typeof document.contains !== 'function') {
// Create the root gadget instance and put it in the loading stack // Create the root gadget instance and put it in the loading stack
TmpConstructor = RenderJSEmbeddedGadget; TmpConstructor = RenderJSEmbeddedGadget;
TmpConstructor.__ready_list = RenderJSGadget.__ready_list.slice(); TmpConstructor.__ready_list = [];
TmpConstructor.__service_list = RenderJSGadget.__service_list.slice(); TmpConstructor.__service_list = RenderJSGadget.__service_list.slice();
TmpConstructor.prototype.__path = url; TmpConstructor.prototype.__path = url;
root_gadget = new RenderJSEmbeddedGadget(); root_gadget = new RenderJSEmbeddedGadget();
...@@ -2419,25 +2447,19 @@ if (typeof document.contains !== 'function') { ...@@ -2419,25 +2447,19 @@ if (typeof document.contains !== 'function') {
var i, var i,
ready_queue = new RSVP.Queue(); ready_queue = new RSVP.Queue();
function ready_wrapper() {
return root_gadget;
}
function ready_executable_wrapper(fct) { function ready_executable_wrapper(fct) {
return function wrapReadyFunction(g) { return function wrapReadyFunction() {
return fct.call(g, g); return fct.call(root_gadget, root_gadget);
}; };
} }
TmpConstructor.ready(function startServiceInReady() { TmpConstructor.ready(function startServiceInReady() {
return startService(this); return startService(root_gadget);
}); });
ready_queue.push(ready_wrapper);
for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) { for (i = 0; i < TmpConstructor.__ready_list.length; i += 1) {
// Put a timeout? // Put a timeout?
ready_queue ready_queue
.push(ready_executable_wrapper(TmpConstructor.__ready_list[i])) .push(ready_executable_wrapper(TmpConstructor.__ready_list[i]));
// Always return the gadget instance after ready function
.push(ready_wrapper);
} }
return ready_queue; return ready_queue;
} }
...@@ -2510,6 +2532,8 @@ if (typeof document.contains !== 'function') { ...@@ -2510,6 +2532,8 @@ if (typeof document.contains !== 'function') {
return configureMutationObserver(TmpConstructor, url, root_gadget); return configureMutationObserver(TmpConstructor, url, root_gadget);
}) })
.push(function waitForReadyList() { .push(function waitForReadyList() {
clearGadgetInternalParameters(root_gadget);
TmpConstructor.__ready_list.unshift(loadSubGadgetDOMDeclaration);
// Trigger all ready functions // Trigger all ready functions
return triggerReadyList(TmpConstructor, root_gadget); return triggerReadyList(TmpConstructor, root_gadget);
}) })
...@@ -2532,4 +2556,4 @@ if (typeof document.contains !== 'function') { ...@@ -2532,4 +2556,4 @@ if (typeof document.contains !== 'function') {
); );
}(document, window, RSVP, DOMParser, Channel, MutationObserver, Node, }(document, window, RSVP, DOMParser, Channel, MutationObserver, Node,
FileReader, Blob, navigator, Event, URL)); FileReader, Blob, navigator, Event, URL));
\ No newline at end of file
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