Commit e801e33b authored by Romain Courteaud's avatar Romain Courteaud

Allow to declare a gadget with a scope (local ID).

Add methods to fetch an existing gadget from its scope and drop the scope
reference.
parent 8f9c4fbc
...@@ -31,7 +31,11 @@ ...@@ -31,7 +31,11 @@
RSVP.EventTarget.mixin(RenderJSGadget.prototype); RSVP.EventTarget.mixin(RenderJSGadget.prototype);
RenderJSGadget.ready_list = []; function clearGadgetInternalParameters(g) {
g.sub_gadget_dict = {};
}
RenderJSGadget.ready_list = [clearGadgetInternalParameters];
RenderJSGadget.ready = function (callback) { RenderJSGadget.ready = function (callback) {
this.ready_list.push(callback); this.ready_list.push(callback);
return this; return this;
...@@ -111,7 +115,7 @@ ...@@ -111,7 +115,7 @@
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSEmbeddedGadget.ready_list = []; RenderJSEmbeddedGadget.ready_list = RenderJSGadget.ready_list.slice();
RenderJSEmbeddedGadget.ready = RenderJSEmbeddedGadget.ready =
RenderJSGadget.ready; RenderJSGadget.ready;
RenderJSEmbeddedGadget.prototype = new RenderJSGadget(); RenderJSEmbeddedGadget.prototype = new RenderJSGadget();
...@@ -182,7 +186,7 @@ ...@@ -182,7 +186,7 @@
} }
RenderJSGadget.call(this); RenderJSGadget.call(this);
} }
RenderJSIframeGadget.ready_list = []; RenderJSIframeGadget.ready_list = RenderJSGadget.ready_list.slice();
RenderJSIframeGadget.ready = RenderJSIframeGadget.ready =
RenderJSGadget.ready; RenderJSGadget.ready;
RenderJSIframeGadget.prototype = new RenderJSGadget(); RenderJSIframeGadget.prototype = new RenderJSGadget();
...@@ -343,6 +347,11 @@ ...@@ -343,6 +347,11 @@
// Always return the gadget instance after ready function // Always return the gadget instance after ready function
queue.push(ready_wrapper); queue.push(ready_wrapper);
} }
// Store local reference to the gadget instance
if (options.scope !== undefined) {
parent_gadget.sub_gadget_dict[options.scope] = gadget_instance;
}
return gadget_instance; return gadget_instance;
}) })
.push(undefined, function (e) { .push(undefined, function (e) {
...@@ -354,6 +363,20 @@ ...@@ -354,6 +363,20 @@
loading_gadget_promise = queue; loading_gadget_promise = queue;
return loading_gadget_promise; return loading_gadget_promise;
}; };
RenderJSGadget
.declareMethod('getDeclaredGadget', function (gadget_scope) {
if (!this.sub_gadget_dict.hasOwnProperty(gadget_scope)) {
throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
}
return this.sub_gadget_dict[gadget_scope];
})
.declareMethod('dropGadget', function (gadget_scope) {
if (!this.sub_gadget_dict.hasOwnProperty(gadget_scope)) {
throw new Error("Gadget scope '" + gadget_scope + "' is not known.");
}
// http://perfectionkills.com/understanding-delete/
delete this.sub_gadget_dict[gadget_scope];
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// renderJS selector // renderJS selector
...@@ -460,7 +483,7 @@ ...@@ -460,7 +483,7 @@
tmp_constructor = function () { tmp_constructor = function () {
RenderJSGadget.call(this); RenderJSGadget.call(this);
}; };
tmp_constructor.ready_list = []; tmp_constructor.ready_list = RenderJSGadget.ready_list.slice();
tmp_constructor.declareMethod = tmp_constructor.declareMethod =
RenderJSGadget.declareMethod; RenderJSGadget.declareMethod;
tmp_constructor.ready = tmp_constructor.ready =
...@@ -616,7 +639,7 @@ ...@@ -616,7 +639,7 @@
RenderJSGadget.call(this); RenderJSGadget.call(this);
}; };
tmp_constructor.declareMethod = RenderJSGadget.declareMethod; tmp_constructor.declareMethod = RenderJSGadget.declareMethod;
tmp_constructor.ready_list = []; tmp_constructor.ready_list = RenderJSGadget.ready_list.slice();
tmp_constructor.ready = RenderJSGadget.ready; tmp_constructor.ready = RenderJSGadget.ready;
tmp_constructor.prototype = new RenderJSGadget(); tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor; tmp_constructor.prototype.constructor = tmp_constructor;
......
...@@ -10,6 +10,10 @@ ...@@ -10,6 +10,10 @@
.declareMethod('wasReadyCalled', function () { .declareMethod('wasReadyCalled', function () {
return ready_called; return ready_called;
}) })
.declareMethod('isSubGadgetDictInitialize', function () {
return ((this.hasOwnProperty("sub_gadget_dict")) &&
(JSON.stringify(this.sub_gadget_dict) === "{}"));
})
.declareMethod('triggerError', function (value) { .declareMethod('triggerError', function (value) {
throw new Error("Manually triggered embedded error"); throw new Error("Manually triggered embedded error");
}) })
......
...@@ -1647,6 +1647,31 @@ ...@@ -1647,6 +1647,31 @@
}); });
}); });
test('Initialize sub_gadget_dict private property', function () {
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
url = 'https://example.org/files/qunittest/test',
html = "<html>" +
"<body>" +
"<script src='../lib/qunit/qunit.js' " +
"type='text/javascript'></script>" +
"</body></html>";
this.server.respondWith("GET", url, [200, {
"Content-Type": "text/html"
}, html]);
stop();
gadget.declareGadget(url)//, document.getElementById('qunit-fixture'))
.then(function (new_gadget) {
ok(new_gadget.hasOwnProperty("sub_gadget_dict"));
deepEqual(new_gadget.sub_gadget_dict, {});
})
.always(function () {
start();
});
});
test('no parameter', function () { test('no parameter', function () {
// Check that missing url reject the declaration // Check that missing url reject the declaration
var gadget = new RenderJSGadget(); var gadget = new RenderJSGadget();
...@@ -2017,6 +2042,38 @@ ...@@ -2017,6 +2042,38 @@
}); });
}); });
test('Can take a scope options', function () {
// Subclass RenderJSGadget to not pollute its namespace
var gadget = new RenderJSGadget(),
html_url = 'https://example.org/files/qunittest/test98.html';
gadget.sub_gadget_dict = {};
this.server.respondWith("GET", html_url, [200, {
"Content-Type": "text/html"
}, "<html><body><p>foo</p></body></html>"]);
document.getElementById('qunit-fixture').textContent = "";
stop();
renderJS.declareGadgetKlass(html_url)
.then(function (Klass) {
return gadget.declareGadget(
html_url,
{scope: "foo"}
);
})
.then(function (child_gadget) {
ok(gadget.sub_gadget_dict.hasOwnProperty("foo"));
equal(gadget.sub_gadget_dict.foo, child_gadget);
})
.fail(function (e) {
ok(false, e);
})
.always(function () {
start();
});
});
test('Generate aq_parent on created gadget', function () { test('Generate aq_parent on created gadget', function () {
// Check that aq_parent returns parent gadget acquire result // Check that aq_parent returns parent gadget acquire result
var gadget = new RenderJSGadget(), var gadget = new RenderJSGadget(),
...@@ -2123,6 +2180,32 @@ ...@@ -2123,6 +2180,32 @@
}); });
}); });
test('Can take a scope options', function () {
// Subclass RenderJSGadget to not pollute its namespace
var gadget = new RenderJSGadget(),
url = "./embedded.html";
gadget.sub_gadget_dict = {};
document.getElementById("qunit-fixture").textContent = "";
stop();
gadget.declareGadget(url, {
sandbox: 'iframe',
element: document.getElementById('qunit-fixture'),
scope: "foo"
})
.then(function (child_gadget) {
ok(gadget.sub_gadget_dict.hasOwnProperty("foo"));
equal(gadget.sub_gadget_dict.foo, child_gadget);
})
.fail(function (e) {
ok(false, e);
})
.always(function () {
start();
});
});
test('provide an iframed gadget as callback parameter', function () { test('provide an iframed gadget as callback parameter', function () {
// Check that declare gadget returns the gadget // Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(), var gadget = new RenderJSGadget(),
...@@ -2149,6 +2232,27 @@ ...@@ -2149,6 +2232,27 @@
}); });
}); });
test('Initialize sub_gadget_dict private property', function () {
// Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(),
url = "./embedded.html";
document.getElementById("qunit-fixture").textContent = "";
stop();
gadget.declareGadget(url, {
sandbox: 'iframe',
element: document.getElementById('qunit-fixture')
})
.then(function (new_gadget) {
ok(new_gadget.hasOwnProperty("sub_gadget_dict"));
deepEqual(new_gadget.sub_gadget_dict, {});
})
.always(function () {
start();
});
});
test('checking working iframe gadget', function () { test('checking working iframe gadget', function () {
// Check that declare gadget returns the gadget // Check that declare gadget returns the gadget
var gadget = new RenderJSGadget(), var gadget = new RenderJSGadget(),
...@@ -2231,6 +2335,14 @@ ...@@ -2231,6 +2335,14 @@
}); });
}) })
// sub_gadget_dict private property is created
.push(function () {
return new_gadget.isSubGadgetDictInitialize();
})
.push(function (result) {
equal(result, true);
})
// acquire check correctly returns result // acquire check correctly returns result
.push(function () { .push(function () {
return new_gadget.callAcquire( return new_gadget.callAcquire(
...@@ -2290,6 +2402,87 @@ ...@@ -2290,6 +2402,87 @@
}); });
}); });
/////////////////////////////////////////////////////////////////
// RenderJSGadget.getDeclaredGadget
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.getDeclaredGadget", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns value from sub_gadget_dict attribute', function () {
// Check that getDeclaredGadget return a Promise
var gadget = new RenderJSGadget();
gadget.sub_gadget_dict = {foo: "bar"};
stop();
gadget.getDeclaredGadget("foo")
.then(function (result) {
equal(result, "bar");
})
.always(function () {
start();
});
});
test('throw an error if scope is unknown', function () {
// Check that getDeclaredGadget return a Promise
var gadget = new RenderJSGadget();
gadget.sub_gadget_dict = {};
stop();
gadget.getDeclaredGadget("foo")
.then(function () {
ok(false, "getDeclaredGadget should fail");
})
.fail(function (e) {
ok(e instanceof Error);
equal(e.message, "Gadget scope 'foo' is not known.");
})
.always(function () {
start();
});
});
/////////////////////////////////////////////////////////////////
// RenderJSGadget.dropGadget
/////////////////////////////////////////////////////////////////
module("RenderJSGadget.dropGadget", {
setup: function () {
renderJS.clearGadgetKlassList();
}
});
test('returns value from sub_gadget_dict attribute', function () {
// Check that dropGadget return a Promise
var gadget = new RenderJSGadget();
gadget.sub_gadget_dict = {foo: "bar"};
stop();
gadget.dropGadget("foo")
.then(function (result) {
equal(result, undefined);
equal(JSON.stringify(gadget.sub_gadget_dict), "{}");
})
.always(function () {
start();
});
});
test('throw an error if scope is unknown', function () {
// Check that dropGadget return a Promise
var gadget = new RenderJSGadget();
gadget.sub_gadget_dict = {};
stop();
gadget.dropGadget("foo")
.then(function () {
ok(false, "dropGadget should fail");
})
.fail(function (e) {
ok(e instanceof Error);
equal(e.message, "Gadget scope 'foo' is not known.");
})
.always(function () {
start();
});
});
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
// RenderJSGadget bootstrap // RenderJSGadget bootstrap
///////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////
...@@ -2340,6 +2533,8 @@ ...@@ -2340,6 +2533,8 @@
ok(root_gadget instanceof RenderJSGadget); ok(root_gadget instanceof RenderJSGadget);
ok(root_gadget_klass, root_gadget.constructor); ok(root_gadget_klass, root_gadget.constructor);
ok(root_gadget.aq_parent !== undefined); ok(root_gadget.aq_parent !== undefined);
ok(root_gadget.hasOwnProperty("sub_gadget_dict"));
deepEqual(root_gadget.sub_gadget_dict, {});
}) })
.fail(function (e) { .fail(function (e) {
ok(false, e); ok(false, e);
......
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