Commit 23e359df authored by Romain Courteaud's avatar Romain Courteaud

Iframed gadget prototype.

parent f72bcfc4
......@@ -14,6 +14,7 @@ all: external lint test build doc
external: lib/sinon/sinon.js \
lib/sinon/sinon-qunit.js \
lib/jquery/jquery.js \
lib/jschannel/jschannel.js \
lib/require/require.js \
lib/qunit/qunit.js \
lib/qunit/qunit.css \
......@@ -35,6 +36,10 @@ lib/jquery/jquery.js:
@mkdir -p $(@D)
curl -s -o $@ http://code.jquery.com/jquery-2.0.3.js
lib/jschannel/jschannel.js:
@mkdir -p $(@D)
curl -s -o $@ http://mozilla.github.io/jschannel/src/jschannel.js
lib/require/require.js:
@mkdir -p $(@D)
curl -s -o $@ http://requirejs.org/docs/release/2.1.8/comments/require.js
......@@ -80,4 +85,4 @@ lint: ${BUILDDIR}/$(RENDERJS).lint
doc:
$(YUIDOC_CMD) .
clean:
rm -rf $(RENDERJS_MIN) ${BUILDDIR} lib/sinon lib/jquery lib/qunit lib/jio lib/require
rm -rf $(RENDERJS_MIN) ${BUILDDIR} lib/sinon lib/jquery lib/jschannel lib/qunit lib/jio lib/require
......@@ -3,6 +3,7 @@
<title>Catalog Gadget</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="../../lib/jquery/jquery.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../../renderjs.js" type="text/javascript"></script>
<script src="catalog.js" type="text/javascript"></script>
</head>
......
......@@ -3,6 +3,7 @@
<title>Simple Text Editor Gadget</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="../../lib/jquery/jquery.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../../renderjs.js" type="text/javascript"></script>
<script src="editor.js" type="text/javascript"></script>
<link rel="http://www.renderjs.org/rel/interface"
......
......@@ -3,6 +3,7 @@
<title>IO</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<script src="../../lib/jquery/jquery.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../../renderjs.js" type="text/javascript"></script>
<script src="../../lib/jio/md5.js" type="text/javascript"></script>
<script src="../../lib/jio/jio.js" type="text/javascript"></script>
......
......@@ -4,6 +4,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" href="jqte/jquery-te-1.4.0.css" />
<script src="../../lib/jquery/jquery.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../../renderjs.js" type="text/javascript"></script>
<script src="jqte/jquery-te-1.4.0.js" type="text/javascript"></script>
<script src="jqteditor.js" type="text/javascript"></script>
......
iframe {
border:0;
margin:0;
padding:0;
width:80%;
height:100px;
}
......@@ -5,7 +5,9 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Office JS</title>
<link rel="stylesheet" href="../../lib/jqm/jquery.mobile.css" />
<link rel="stylesheet" href="officejs.css" />
<script src="../../lib/jquery/jquery.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../../renderjs.js" type="text/javascript"></script>
<script src="officejs.js" type="text/javascript"></script>
<script src="../../lib/jqm/jquery.mobile.js" type="text/javascript"></script>
......
......@@ -37,7 +37,7 @@
// Load 1 editor and 1 IO and plug them
$.when(
g.declareGadget(editor_list[0].path, editor_a_context),
g.declareIframedGadget(editor_list[0].path, editor_a_context),
g.declareGadget(io_list[0].path, io_a_context),
"officejs").done(attachIOToEditor);
......@@ -49,7 +49,7 @@
'data-iconpos="left">' + editor_definition.title + '</a>');
panel_context.find('a').last().click(function () {
$.when(
g.declareGadget(editor_definition.path, editor_a_context),
g.declareIframedGadget(editor_definition.path, editor_a_context),
g.declareGadget(io_list[0].path, io_a_context),
"officejs").done(attachIOToEditor);
});
......
This diff is collapsed.
/*! RenderJs v0.2 */
/*global $, jQuery, localStorage, jIO, window, document, DOMParser */
/*global $, jQuery, localStorage, jIO, window, document, DOMParser, Channel */
/*jslint evil: true, indent: 2, maxerr: 3, maxlen: 79 */
"use strict";
......@@ -51,7 +51,7 @@
* renderJs - Generic Gadget library renderer.
* http://www.renderjs.org/documentation
*/
(function (document, window, $, DOMParser) {
(function (document, window, $, DOMParser, Channel, undefined) {
var gadget_model_dict = {},
javascript_registration_dict = {},
......@@ -137,9 +137,133 @@
return this.html;
});
// Class inheritance
function RenderJSEmbeddedGadget() {
RenderJSGadget.call(this);
}
RenderJSEmbeddedGadget.ready_list = [];
RenderJSEmbeddedGadget.declareMethod =
RenderJSGadget.declareMethod;
RenderJSEmbeddedGadget.ready =
RenderJSGadget.ready;
RenderJSEmbeddedGadget.prototype = new RenderJSGadget();
RenderJSEmbeddedGadget.prototype.constructor = RenderJSEmbeddedGadget;
// XXX Declare method in same non root url gadget
RenderJSEmbeddedGadget.declareMethod = function (name, callback) {
RenderJSEmbeddedGadget.root_gadget.chan.notify({
method: "declareMethod",
params: name,
});
return RenderJSGadget.declareMethod.apply(this, [name, callback]);
};
// Class inheritance
function RenderJSIframeGadget() {
RenderJSGadget.call(this);
}
RenderJSIframeGadget.ready_list = [];
RenderJSIframeGadget.declareMethod =
RenderJSGadget.declareMethod;
RenderJSIframeGadget.ready =
RenderJSGadget.ready;
RenderJSIframeGadget.prototype = new RenderJSGadget();
RenderJSIframeGadget.prototype.constructor = RenderJSIframeGadget;
RenderJSGadget.prototype.declareIframedGadget =
function (url, jquery_context) {
var previous_loading_gadget_promise = loading_gadget_promise,
next_loading_gadget_deferred = $.Deferred();
// Change the global variable to update the loading queue
loading_gadget_promise = next_loading_gadget_deferred.promise();
// Wait for previous gadget loading to finish first
previous_loading_gadget_promise.always(function () {
// Instanciate iframe
var gadget = new RenderJSIframeGadget();
gadget.context = jquery_context;
// XXX Do not set this info on the instance!
gadget.path = url;
// XXX onload onerror
// $('iframe').load(function() {
// RunAfterIFrameLoaded();
// });
// Create the iframe
if (gadget.context !== undefined) {
$(gadget.context).html(
// Use encodeURI to prevent XSS
'<iframe src="' + encodeURI(url) + '"></iframe>'
);
gadget.chan = Channel.build({
window: gadget.context.find('iframe').first()[0].contentWindow,
origin: "*",
scope: "renderJS"
});
// gadget.getTitle = function () {
// var dfr = $.Deferred();
// gadget.chan.call({
// method: "getTitle",
// success: function (v) {
// dfr.resolve(v);
// }
// });
// return dfr.promise();
// };
gadget.chan.bind("declareMethod", function (trans, method_name) {
console.log("Receive declaration " + method_name + " on " +
gadget.path);
gadget[method_name] = function () {
var dfr = $.Deferred();
gadget.chan.call({
method: "methodCall",
params: [
method_name,
Array.prototype.slice.call(arguments, 0)],
success: function () {
dfr.resolveWith(gadget, arguments);
}
// XXX Error callback
});
return dfr.promise();
};
});
// Wait for the iframe to be loaded before continuing
gadget.chan.bind("ready", function (trans) {
console.log(gadget.path + " is ready");
next_loading_gadget_deferred.resolve(gadget);
});
gadget.chan.bind("failed", function (trans) {
next_loading_gadget_deferred.reject();
});
} else {
next_loading_gadget_deferred.reject();
}
});
loading_gadget_promise
// Drop the current loading klass info used by selector
.done(function () {
gadget_loading_klass = undefined;
})
.fail(function () {
gadget_loading_klass = undefined;
})
.done(function (created_gadget) {
$.each(created_gadget.constructor.ready_list,
function (i, callback) {
callback.apply(created_gadget);
});
});
return loading_gadget_promise;
};
RenderJSGadget.prototype.declareGadget = function (url, jquery_context) {
var loaded = false,
previous_loading_gadget_promise = loading_gadget_promise,
var previous_loading_gadget_promise = loading_gadget_promise,
next_loading_gadget_deferred = $.Deferred();
// Change the global variable to update the loading queue
......@@ -515,23 +639,82 @@
if (gadget_model_dict.hasOwnProperty(url)) {
throw new Error("bootstrap should not be called twice");
}
// XXX Copy/Paste from declareGadgetKlass
tmp_constructor = function () {
RenderJSGadget.call(this);
};
tmp_constructor.declareMethod = RenderJSGadget.declareMethod;
tmp_constructor.ready_list = [];
tmp_constructor.ready = RenderJSGadget.ready;
tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.path = url;
gadget_model_dict[url] = tmp_constructor;
// Create the root gadget instance and put it in the loading stack
root_gadget = new gadget_model_dict[url]();
loading_gadget_promise = loading_gadget_deferred.promise();
if (window.self === window.top) {
// XXX Copy/Paste from declareGadgetKlass
tmp_constructor = function () {
RenderJSGadget.call(this);
};
tmp_constructor.declareMethod = RenderJSGadget.declareMethod;
tmp_constructor.ready_list = [];
tmp_constructor.ready = RenderJSGadget.ready;
tmp_constructor.prototype = new RenderJSGadget();
tmp_constructor.prototype.constructor = tmp_constructor;
tmp_constructor.prototype.path = url;
gadget_model_dict[url] = tmp_constructor;
// Create the root gadget instance and put it in the loading stack
root_gadget = new gadget_model_dict[url]();
} else {
// Create the root gadget instance and put it in the loading stack
tmp_constructor = RenderJSEmbeddedGadget;
root_gadget = new RenderJSEmbeddedGadget();
RenderJSEmbeddedGadget.root_gadget = root_gadget;
// Create the communication channel
root_gadget.chan = Channel.build({
window: window.parent,
origin: "*",
scope: "renderJS"
});
root_gadget.chan.bind("methodCall", function (trans, v) {
root_gadget[v[0]].apply(root_gadget, v[1]).done(function (g) {
trans.complete(g);
});
trans.delayReturn(true);
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getInterfaceList",
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getRequiredCSSList",
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getRequiredJSList",
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getPath",
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getTitle",
});
root_gadget.chan.notify({
method: "declareMethod",
params: "getHTML",
});
// Surcharge declareMethod to inform parent window
// XXX TODO
// Inform parent window that gadget is correctly loaded
loading_gadget_promise.done(function () {
// XXX Wait for all previous declaration before ending ready message
setTimeout(function () {
root_gadget.chan.notify({method: "ready"});
}, 100);
}).fail(function () {
root_gadget.chan.notify({method: "failed"});
});
}
gadget_loading_klass = tmp_constructor;
loading_gadget_promise = loading_gadget_deferred.promise();
......@@ -560,12 +743,14 @@
});
gadget_loading_klass = undefined;
loading_gadget_deferred.resolve();
}).fail(function () {
loading_gadget_deferred.reject();
});
});
}
bootstrap();
}(document, window, jQuery, DOMParser));
}(document, window, jQuery, DOMParser, Channel));
///**
......
......@@ -10,6 +10,7 @@
<script src="../lib/qunit/qunit.js" type="text/javascript"></script>
<script src="../lib/sinon/sinon.js" type="text/javascript"></script>
<script src="../sinon-qunit.js" type="text/javascript"></script>
<script src="../../lib/jschannel/jschannel.js" type="text/javascript"></script>
<script src="../renderjs.js" type="text/javascript"></script>
<script src="renderjs_test2.js" type="text/javascript"></script>
</head>
......
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