Commit fb351cef authored by Romain Courteaud's avatar Romain Courteaud

[erp5_xhtml_style/erp5_web_renderjs_ui] Update renderJS 0.21.0

parent 74c44681
/* /*
* js_channel is a very lightweight abstraction on top of * js_channel is a very lightweight abstraction on top of
* postMessage which defines message formats and semantics * postMessage which defines message formats and semantics
...@@ -1339,8 +1338,9 @@ if (typeof document.contains !== 'function') { ...@@ -1339,8 +1338,9 @@ if (typeof document.contains !== 'function') {
} }
function startService(gadget) { function startService(gadget) {
if ((gadget.constructor.__service_list.length === 0) && if (((gadget.constructor.__service_list.length === 0) &&
(!gadget.constructor.__job_declared)) { (!gadget.constructor.__job_declared)) ||
(gadget.hasOwnProperty('__monitor'))) {
return; return;
} }
createGadgetMonitor(gadget); createGadgetMonitor(gadget);
...@@ -1607,11 +1607,9 @@ if (typeof document.contains !== 'function') { ...@@ -1607,11 +1607,9 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget // privateDeclarePublicGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function createPrivateInstanceFromKlass(Klass, options, parent_gadget) { function createPrivateInstanceFromKlass(Klass, options, parent_gadget,
old_element) {
// Get the gadget class and instanciate it // Get the gadget class and instanciate it
if (options.element === undefined) {
options.element = document.createElement("div");
}
var i, var i,
gadget_instance, gadget_instance,
template_node_list = Klass.__template_element.body.childNodes, template_node_list = Klass.__template_element.body.childNodes,
...@@ -1626,10 +1624,18 @@ if (typeof document.contains !== 'function') { ...@@ -1626,10 +1624,18 @@ if (typeof document.contains !== 'function') {
} }
gadget_instance.element.appendChild(fragment); gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget); setAqParent(gadget_instance, parent_gadget);
clearGadgetInternalParameters(gadget_instance);
if (old_element !== undefined) {
// Add gadget to the DOM if needed
// Do it when all DOM modifications are done
old_element.parentNode.replaceChild(options.element,
old_element);
}
return gadget_instance; return gadget_instance;
} }
function privateDeclarePublicGadget(url, options, parent_gadget) { function privateDeclarePublicGadget(url, options, parent_gadget,
old_element) {
var klass = renderJS.declareGadgetKlass(url); var klass = renderJS.declareGadgetKlass(url);
// gadget loading should not be interrupted // gadget loading should not be interrupted
// if not, gadget's definition will not be complete // if not, gadget's definition will not be complete
...@@ -1637,10 +1643,12 @@ if (typeof document.contains !== 'function') { ...@@ -1637,10 +1643,12 @@ if (typeof document.contains !== 'function') {
//so loading_klass_promise can't be cancel //so loading_klass_promise can't be cancel
if (typeof klass.then === 'function') { if (typeof klass.then === 'function') {
return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) { return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) {
return createPrivateInstanceFromKlass(Klass, options, parent_gadget); return createPrivateInstanceFromKlass(Klass, options, parent_gadget,
old_element);
}); });
} }
return createPrivateInstanceFromKlass(klass, options, parent_gadget); return createPrivateInstanceFromKlass(klass, options, parent_gadget,
old_element);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1672,17 +1680,18 @@ if (typeof document.contains !== 'function') { ...@@ -1672,17 +1680,18 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclareIframeGadget // privateDeclareIframeGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclareIframeGadget(url, options, parent_gadget) { function privateDeclareIframeGadget(url, options, parent_gadget,
old_element) {
var gadget_instance, var gadget_instance,
iframe, iframe,
iframe_loading_deferred = RSVP.defer(); iframe_loading_deferred = RSVP.defer();
if (options.element === undefined) { if (old_element === undefined) {
throw new Error("DOM element is required to create Iframe Gadget " + throw new Error("DOM element is required to create Iframe Gadget " +
url); url);
} }
// Check if the element is attached to the DOM // Check if the element is attached to the DOM
if (!document.contains(options.element)) { if (!document.contains(old_element)) {
throw new Error("The parent element is not attached to the DOM for " + throw new Error("The parent element is not attached to the DOM for " +
url); url);
} }
...@@ -1706,8 +1715,12 @@ if (typeof document.contains !== 'function') { ...@@ -1706,8 +1715,12 @@ if (typeof document.contains !== 'function') {
gadget_instance.__path = url; gadget_instance.__path = url;
gadget_instance.element = options.element; gadget_instance.element = options.element;
gadget_instance.state = {}; gadget_instance.state = {};
// Attach it to the DOM
options.element.appendChild(iframe); options.element.appendChild(iframe);
clearGadgetInternalParameters(gadget_instance);
// Add gadget to the DOM if needed
// Do it when all DOM modifications are done
old_element.parentNode.replaceChild(options.element,
old_element);
// XXX Manage unbind when deleting the gadget // XXX Manage unbind when deleting the gadget
...@@ -1775,7 +1788,8 @@ if (typeof document.contains !== 'function') { ...@@ -1775,7 +1788,8 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclareDataUrlGadget // privateDeclareDataUrlGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclareDataUrlGadget(url, options, parent_gadget) { function privateDeclareDataUrlGadget(url, options, parent_gadget,
old_element) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function waitForDataUrlAjax() { .push(function waitForDataUrlAjax() {
...@@ -1795,7 +1809,8 @@ if (typeof document.contains !== 'function') { ...@@ -1795,7 +1809,8 @@ if (typeof document.contains !== 'function') {
return readBlobAsDataURL(blob); return readBlobAsDataURL(blob);
}) })
.push(function handleDataURL(data_url) { .push(function handleDataURL(data_url) {
return privateDeclareIframeGadget(data_url, options, parent_gadget); return privateDeclareIframeGadget(data_url, options, parent_gadget,
old_element);
}); });
} }
...@@ -1803,31 +1818,10 @@ if (typeof document.contains !== 'function') { ...@@ -1803,31 +1818,10 @@ if (typeof document.contains !== 'function') {
// RenderJSGadget.declareGadget // RenderJSGadget.declareGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function setGadgetInstanceHTMLContext(gadget_instance, options, function setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url) { parent_gadget, url,
old_element, scope) {
var i, var i,
scope,
queue; 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) { function ready_executable_wrapper(fct) {
return function executeReadyWrapper() { return function executeReadyWrapper() {
...@@ -1836,6 +1830,11 @@ if (typeof document.contains !== 'function') { ...@@ -1836,6 +1830,11 @@ if (typeof document.contains !== 'function') {
} }
function ready_wrapper() { function ready_wrapper() {
// Always set the parent reference when all ready are finished
// in case the gadget declaration is cancelled
// (and ready are not finished)
gadget_instance.element._gadget = gadget_instance;
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
if (document.contains(gadget_instance.element)) { if (document.contains(gadget_instance.element)) {
startService(gadget_instance); startService(gadget_instance);
} }
...@@ -1863,7 +1862,9 @@ if (typeof document.contains !== 'function') { ...@@ -1863,7 +1862,9 @@ if (typeof document.contains !== 'function') {
.declareMethod('declareGadget', function declareGadget(url, options) { .declareMethod('declareGadget', function declareGadget(url, options) {
var parent_gadget = this, var parent_gadget = this,
method, method,
result; result,
scope,
old_element;
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
...@@ -1871,10 +1872,39 @@ if (typeof document.contains !== 'function') { ...@@ -1871,10 +1872,39 @@ if (typeof document.contains !== 'function') {
if (options.sandbox === undefined) { if (options.sandbox === undefined) {
options.sandbox = "public"; options.sandbox = "public";
} }
if (options.element === undefined) {
options.element = document.createElement('div');
} else if (typeof options.element === 'string') {
options.element = document.createElement(options.element);
} else if (options.element.parentNode) {
old_element = options.element;
// Clean up the element content
// Remove all existing event listener
options.element = old_element.cloneNode(false);
} else {
throw new Error('No need to manually provide a DOM element ' +
'without a parentNode: ' + url);
}
// 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);
// 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;
}
}
options.element.setAttribute("data-gadget-scope", scope);
// Put some attribute to ease page layout comprehension
options.element.setAttribute("data-gadget-url", url);
options.element.setAttribute("data-gadget-sandbox", options.sandbox);
if (options.sandbox === "public") { if (options.sandbox === "public") {
method = privateDeclarePublicGadget; method = privateDeclarePublicGadget;
} else if (options.sandbox === "iframe") { } else if (options.sandbox === "iframe") {
...@@ -1885,7 +1915,7 @@ if (typeof document.contains !== 'function') { ...@@ -1885,7 +1915,7 @@ if (typeof document.contains !== 'function') {
throw new Error("Unsupported sandbox options '" + throw new Error("Unsupported sandbox options '" +
options.sandbox + "'"); options.sandbox + "'");
} }
result = method(url, options, parent_gadget); result = method(url, options, parent_gadget, old_element);
// Set the HTML context // Set the HTML context
if (typeof result.then === 'function') { if (typeof result.then === 'function') {
return new RSVP.Queue() return new RSVP.Queue()
...@@ -1894,11 +1924,13 @@ if (typeof document.contains !== 'function') { ...@@ -1894,11 +1924,13 @@ if (typeof document.contains !== 'function') {
}) })
.push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) { .push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) {
return setGadgetInstanceHTMLContext(gadget_instance, options, return setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url); parent_gadget, url,
old_element, scope);
}); });
} }
return setGadgetInstanceHTMLContext(result, options, return setGadgetInstanceHTMLContext(result, options,
parent_gadget, url); parent_gadget, url, old_element,
scope);
}) })
.declareMethod('getDeclaredGadget', .declareMethod('getDeclaredGadget',
function getDeclaredGadget(gadget_scope) { function getDeclaredGadget(gadget_scope) {
...@@ -2473,10 +2505,11 @@ if (typeof document.contains !== 'function') { ...@@ -2473,10 +2505,11 @@ if (typeof document.contains !== 'function') {
} }
// Surcharge declareMethod to inform parent window // Surcharge declareMethod to inform parent window
TmpConstructor.declareMethod = function declareMethod(name, callback) { TmpConstructor.declareMethod = function declareMethod(name, callback,
options) {
var result = RenderJSGadget.declareMethod.apply( var result = RenderJSGadget.declareMethod.apply(
this, this,
[name, callback] [name, callback, options]
); );
notifyDeclareMethod(name); notifyDeclareMethod(name);
return result; return result;
......
...@@ -230,7 +230,7 @@ ...@@ -230,7 +230,7 @@
</item> </item>
<item> <item>
<key> <string>serial</string> </key> <key> <string>serial</string> </key>
<value> <string>970.14223.48899.20224</string> </value> <value> <string>971.50934.11399.39782</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>1536912990.11</float> <float>1542986111.27</float>
<string>UTC</string> <string>UTC</string>
</tuple> </tuple>
</state> </state>
......
...@@ -716,9 +716,26 @@ if (typeof document.contains !== 'function') { ...@@ -716,9 +716,26 @@ if (typeof document.contains !== 'function') {
window.URL = URL; window.URL = URL;
}(DOMParser));;/*! RenderJs */ }(DOMParser));;/*
* Copyright 2012, Nexedi SA
*
* This program is free software: you can Use, Study, Modify and Redistribute
* it under the terms of the GNU General Public License version 3, or (at your
* option) any later version, as published by the Free Software Foundation.
*
* You can also Link and Combine this program with other software covered by
* the terms of any of the Free Software licenses or any of the Open Source
* Initiative approved licenses and Convey the resulting work. Corresponding
* source of such a combination shall include the source code for all other
* software used.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
* See COPYING file for full licensing terms.
* See https://www.nexedi.com/licensing for rationale and options.
*/
/*jslint nomen: true*/ /*jslint nomen: true*/
/* /*
* renderJs - Generic Gadget library renderer. * renderJs - Generic Gadget library renderer.
* https://renderjs.nexedi.com/ * https://renderjs.nexedi.com/
...@@ -1321,8 +1338,9 @@ if (typeof document.contains !== 'function') { ...@@ -1321,8 +1338,9 @@ if (typeof document.contains !== 'function') {
} }
function startService(gadget) { function startService(gadget) {
if ((gadget.constructor.__service_list.length === 0) && if (((gadget.constructor.__service_list.length === 0) &&
(!gadget.constructor.__job_declared)) { (!gadget.constructor.__job_declared)) ||
(gadget.hasOwnProperty('__monitor'))) {
return; return;
} }
createGadgetMonitor(gadget); createGadgetMonitor(gadget);
...@@ -1343,6 +1361,13 @@ if (typeof document.contains !== 'function') { ...@@ -1343,6 +1361,13 @@ if (typeof document.contains !== 'function') {
); );
} }
function registerMethod(gadget_klass, method_name, method_type) {
if (!gadget_klass.hasOwnProperty('__method_type_dict')) {
gadget_klass.__method_type_dict = {};
}
gadget_klass.__method_type_dict[method_name] = method_type;
}
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget.declareJob // RenderJSGadget.declareJob
// gadget internal method, which trigger execution // gadget internal method, which trigger execution
...@@ -1360,6 +1385,7 @@ if (typeof document.contains !== 'function') { ...@@ -1360,6 +1385,7 @@ if (typeof document.contains !== 'function') {
context.__job_list.push([name, callback, argument_list]); context.__job_list.push([name, callback, argument_list]);
} }
}; };
registerMethod(this, name, 'job');
// Allow chain // Allow chain
return this; return this;
}; };
...@@ -1389,6 +1415,7 @@ if (typeof document.contains !== 'function') { ...@@ -1389,6 +1415,7 @@ if (typeof document.contains !== 'function') {
} }
return ensurePushableQueue(callback, argument_list, context); return ensurePushableQueue(callback, argument_list, context);
}; };
registerMethod(this, name, 'method');
// Allow chain // Allow chain
return this; return this;
}; };
...@@ -1398,6 +1425,21 @@ if (typeof document.contains !== 'function') { ...@@ -1398,6 +1425,21 @@ if (typeof document.contains !== 'function') {
// Returns the list of gadget prototype // Returns the list of gadget prototype
return this.__interface_list; return this.__interface_list;
}) })
.declareMethod('getMethodList', function getMethodList(type) {
// Returns the list of gadget methods
var key,
method_list = [],
method_dict = this.constructor.__method_type_dict || {};
for (key in method_dict) {
if (method_dict.hasOwnProperty(key)) {
if ((type === undefined) ||
(type === method_dict[key])) {
method_list.push(key);
}
}
}
return method_list;
})
.declareMethod('getRequiredCSSList', function getRequiredCSSList() { .declareMethod('getRequiredCSSList', function getRequiredCSSList() {
// Returns a list of CSS required by the gadget // Returns a list of CSS required by the gadget
return this.__required_css_list; return this.__required_css_list;
...@@ -1505,7 +1547,7 @@ if (typeof document.contains !== 'function') { ...@@ -1505,7 +1547,7 @@ if (typeof document.contains !== 'function') {
gadget gadget
); );
}; };
registerMethod(this, name, 'acquired_method');
// Allow chain // Allow chain
return this; return this;
}; };
...@@ -1565,11 +1607,9 @@ if (typeof document.contains !== 'function') { ...@@ -1565,11 +1607,9 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclarePublicGadget // privateDeclarePublicGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function createPrivateInstanceFromKlass(Klass, options, parent_gadget) { function createPrivateInstanceFromKlass(Klass, options, parent_gadget,
old_element) {
// Get the gadget class and instanciate it // Get the gadget class and instanciate it
if (options.element === undefined) {
options.element = document.createElement("div");
}
var i, var i,
gadget_instance, gadget_instance,
template_node_list = Klass.__template_element.body.childNodes, template_node_list = Klass.__template_element.body.childNodes,
...@@ -1584,10 +1624,18 @@ if (typeof document.contains !== 'function') { ...@@ -1584,10 +1624,18 @@ if (typeof document.contains !== 'function') {
} }
gadget_instance.element.appendChild(fragment); gadget_instance.element.appendChild(fragment);
setAqParent(gadget_instance, parent_gadget); setAqParent(gadget_instance, parent_gadget);
clearGadgetInternalParameters(gadget_instance);
if (old_element !== undefined) {
// Add gadget to the DOM if needed
// Do it when all DOM modifications are done
old_element.parentNode.replaceChild(options.element,
old_element);
}
return gadget_instance; return gadget_instance;
} }
function privateDeclarePublicGadget(url, options, parent_gadget) { function privateDeclarePublicGadget(url, options, parent_gadget,
old_element) {
var klass = renderJS.declareGadgetKlass(url); var klass = renderJS.declareGadgetKlass(url);
// gadget loading should not be interrupted // gadget loading should not be interrupted
// if not, gadget's definition will not be complete // if not, gadget's definition will not be complete
...@@ -1595,10 +1643,12 @@ if (typeof document.contains !== 'function') { ...@@ -1595,10 +1643,12 @@ if (typeof document.contains !== 'function') {
//so loading_klass_promise can't be cancel //so loading_klass_promise can't be cancel
if (typeof klass.then === 'function') { if (typeof klass.then === 'function') {
return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) { return klass.then(function createAsyncPrivateInstanceFromKlass(Klass) {
return createPrivateInstanceFromKlass(Klass, options, parent_gadget); return createPrivateInstanceFromKlass(Klass, options, parent_gadget,
old_element);
}); });
} }
return createPrivateInstanceFromKlass(klass, options, parent_gadget); return createPrivateInstanceFromKlass(klass, options, parent_gadget,
old_element);
} }
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -1630,17 +1680,18 @@ if (typeof document.contains !== 'function') { ...@@ -1630,17 +1680,18 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclareIframeGadget // privateDeclareIframeGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclareIframeGadget(url, options, parent_gadget) { function privateDeclareIframeGadget(url, options, parent_gadget,
old_element) {
var gadget_instance, var gadget_instance,
iframe, iframe,
iframe_loading_deferred = RSVP.defer(); iframe_loading_deferred = RSVP.defer();
if (options.element === undefined) { if (old_element === undefined) {
throw new Error("DOM element is required to create Iframe Gadget " + throw new Error("DOM element is required to create Iframe Gadget " +
url); url);
} }
// Check if the element is attached to the DOM // Check if the element is attached to the DOM
if (!document.contains(options.element)) { if (!document.contains(old_element)) {
throw new Error("The parent element is not attached to the DOM for " + throw new Error("The parent element is not attached to the DOM for " +
url); url);
} }
...@@ -1664,8 +1715,12 @@ if (typeof document.contains !== 'function') { ...@@ -1664,8 +1715,12 @@ if (typeof document.contains !== 'function') {
gadget_instance.__path = url; gadget_instance.__path = url;
gadget_instance.element = options.element; gadget_instance.element = options.element;
gadget_instance.state = {}; gadget_instance.state = {};
// Attach it to the DOM
options.element.appendChild(iframe); options.element.appendChild(iframe);
clearGadgetInternalParameters(gadget_instance);
// Add gadget to the DOM if needed
// Do it when all DOM modifications are done
old_element.parentNode.replaceChild(options.element,
old_element);
// XXX Manage unbind when deleting the gadget // XXX Manage unbind when deleting the gadget
...@@ -1733,7 +1788,8 @@ if (typeof document.contains !== 'function') { ...@@ -1733,7 +1788,8 @@ if (typeof document.contains !== 'function') {
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// privateDeclareDataUrlGadget // privateDeclareDataUrlGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function privateDeclareDataUrlGadget(url, options, parent_gadget) { function privateDeclareDataUrlGadget(url, options, parent_gadget,
old_element) {
return new RSVP.Queue() return new RSVP.Queue()
.push(function waitForDataUrlAjax() { .push(function waitForDataUrlAjax() {
...@@ -1753,7 +1809,8 @@ if (typeof document.contains !== 'function') { ...@@ -1753,7 +1809,8 @@ if (typeof document.contains !== 'function') {
return readBlobAsDataURL(blob); return readBlobAsDataURL(blob);
}) })
.push(function handleDataURL(data_url) { .push(function handleDataURL(data_url) {
return privateDeclareIframeGadget(data_url, options, parent_gadget); return privateDeclareIframeGadget(data_url, options, parent_gadget,
old_element);
}); });
} }
...@@ -1761,31 +1818,10 @@ if (typeof document.contains !== 'function') { ...@@ -1761,31 +1818,10 @@ if (typeof document.contains !== 'function') {
// RenderJSGadget.declareGadget // RenderJSGadget.declareGadget
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
function setGadgetInstanceHTMLContext(gadget_instance, options, function setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url) { parent_gadget, url,
old_element, scope) {
var i, var i,
scope,
queue; 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) { function ready_executable_wrapper(fct) {
return function executeReadyWrapper() { return function executeReadyWrapper() {
...@@ -1794,6 +1830,11 @@ if (typeof document.contains !== 'function') { ...@@ -1794,6 +1830,11 @@ if (typeof document.contains !== 'function') {
} }
function ready_wrapper() { function ready_wrapper() {
// Always set the parent reference when all ready are finished
// in case the gadget declaration is cancelled
// (and ready are not finished)
gadget_instance.element._gadget = gadget_instance;
parent_gadget.__sub_gadget_dict[scope] = gadget_instance;
if (document.contains(gadget_instance.element)) { if (document.contains(gadget_instance.element)) {
startService(gadget_instance); startService(gadget_instance);
} }
...@@ -1821,7 +1862,9 @@ if (typeof document.contains !== 'function') { ...@@ -1821,7 +1862,9 @@ if (typeof document.contains !== 'function') {
.declareMethod('declareGadget', function declareGadget(url, options) { .declareMethod('declareGadget', function declareGadget(url, options) {
var parent_gadget = this, var parent_gadget = this,
method, method,
result; result,
scope,
old_element;
if (options === undefined) { if (options === undefined) {
options = {}; options = {};
...@@ -1829,10 +1872,39 @@ if (typeof document.contains !== 'function') { ...@@ -1829,10 +1872,39 @@ if (typeof document.contains !== 'function') {
if (options.sandbox === undefined) { if (options.sandbox === undefined) {
options.sandbox = "public"; options.sandbox = "public";
} }
if (options.element === undefined) {
options.element = document.createElement('div');
} else if (typeof options.element === 'string') {
options.element = document.createElement(options.element);
} else if (options.element.parentNode) {
old_element = options.element;
// Clean up the element content
// Remove all existing event listener
options.element = old_element.cloneNode(false);
} else {
throw new Error('No need to manually provide a DOM element ' +
'without a parentNode: ' + url);
}
// 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);
// 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;
}
}
options.element.setAttribute("data-gadget-scope", scope);
// Put some attribute to ease page layout comprehension
options.element.setAttribute("data-gadget-url", url);
options.element.setAttribute("data-gadget-sandbox", options.sandbox);
if (options.sandbox === "public") { if (options.sandbox === "public") {
method = privateDeclarePublicGadget; method = privateDeclarePublicGadget;
} else if (options.sandbox === "iframe") { } else if (options.sandbox === "iframe") {
...@@ -1843,7 +1915,7 @@ if (typeof document.contains !== 'function') { ...@@ -1843,7 +1915,7 @@ if (typeof document.contains !== 'function') {
throw new Error("Unsupported sandbox options '" + throw new Error("Unsupported sandbox options '" +
options.sandbox + "'"); options.sandbox + "'");
} }
result = method(url, options, parent_gadget); result = method(url, options, parent_gadget, old_element);
// Set the HTML context // Set the HTML context
if (typeof result.then === 'function') { if (typeof result.then === 'function') {
return new RSVP.Queue() return new RSVP.Queue()
...@@ -1852,11 +1924,13 @@ if (typeof document.contains !== 'function') { ...@@ -1852,11 +1924,13 @@ if (typeof document.contains !== 'function') {
}) })
.push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) { .push(function setAsyncGadgetInstanceHTMLContext(gadget_instance) {
return setGadgetInstanceHTMLContext(gadget_instance, options, return setGadgetInstanceHTMLContext(gadget_instance, options,
parent_gadget, url); parent_gadget, url,
old_element, scope);
}); });
} }
return setGadgetInstanceHTMLContext(result, options, return setGadgetInstanceHTMLContext(result, options,
parent_gadget, url); parent_gadget, url, old_element,
scope);
}) })
.declareMethod('getDeclaredGadget', .declareMethod('getDeclaredGadget',
function getDeclaredGadget(gadget_scope) { function getDeclaredGadget(gadget_scope) {
...@@ -2358,7 +2432,7 @@ if (typeof document.contains !== 'function') { ...@@ -2358,7 +2432,7 @@ if (typeof document.contains !== 'function') {
TmpConstructor.__ready_list = []; 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 TmpConstructor();
setAqParent(root_gadget, createLastAcquisitionGadget()); setAqParent(root_gadget, createLastAcquisitionGadget());
declare_method_list_waiting = [ declare_method_list_waiting = [
...@@ -2366,7 +2440,8 @@ if (typeof document.contains !== 'function') { ...@@ -2366,7 +2440,8 @@ if (typeof document.contains !== 'function') {
"getRequiredCSSList", "getRequiredCSSList",
"getRequiredJSList", "getRequiredJSList",
"getPath", "getPath",
"getTitle" "getTitle",
"getMethodList"
]; ];
// Inform parent gadget about declareMethod calls here. // Inform parent gadget about declareMethod calls here.
...@@ -2430,10 +2505,11 @@ if (typeof document.contains !== 'function') { ...@@ -2430,10 +2505,11 @@ if (typeof document.contains !== 'function') {
} }
// Surcharge declareMethod to inform parent window // Surcharge declareMethod to inform parent window
TmpConstructor.declareMethod = function declareMethod(name, callback) { TmpConstructor.declareMethod = function declareMethod(name, callback,
options) {
var result = RenderJSGadget.declareMethod.apply( var result = RenderJSGadget.declareMethod.apply(
this, this,
[name, callback] [name, callback, options]
); );
notifyDeclareMethod(name); notifyDeclareMethod(name);
return result; return result;
......
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