You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shindig.apache.org by ev...@apache.org on 2009/05/07 20:31:55 UTC
svn commit: r772737 - in
/incubator/shindig/trunk/features/src/main/javascript/features:
opensocial-data/data.js opensocial-templates/base.js
opensocial-templates/container.js opensocial-templates/loader.js
xmlutil/xmlutil.js
Author: evan
Date: Thu May 7 18:31:49 2009
New Revision: 772737
URL: http://svn.apache.org/viewvc?rev=772737&view=rev
Log:
SHINDIG-1046
Patch from Lev for:
- Bugs fixed in data context handling
- Support for required library declaration via "requireLibrary" param
- Template processing deferred until required libraries are loaded
- Correct timing of feature param processing
- Minor Loader refactoring in preparation for library injection
- Namespace declarations on template container tags honored
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-data/data.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/base.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/loader.js
incubator/shindig/trunk/features/src/main/javascript/features/xmlutil/xmlutil.js
Modified: incubator/shindig/trunk/features/src/main/javascript/features/opensocial-data/data.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-data/data.js?rev=772737&r1=772736&r2=772737&view=diff
==============================================================================
--- incubator/shindig/trunk/features/src/main/javascript/features/opensocial-data/data.js (original)
+++ incubator/shindig/trunk/features/src/main/javascript/features/opensocial-data/data.js Thu May 7 18:31:49 2009
@@ -376,7 +376,7 @@
if (request.tagName == "os:PeopleRequest") {
var groupId = request.getAttribute("groupId");
if ((!groupId || groupId == "@self") && data.length == 1) {
- data = data[0]
+ data = data[0];
}
}
} else {
Modified: incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/base.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/base.js?rev=772737&r1=772736&r2=772737&view=diff
==============================================================================
--- incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/base.js (original)
+++ incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/base.js Thu May 7 18:31:49 2009
@@ -114,7 +114,7 @@
opt_id = opt_id || node.name;
var src = node.value || node.innerHTML;
src = os.trim(src);
- var template = os.compileTemplateString(src, opt_id);
+ var template = os.compileTemplateString(src, opt_id, node);
// Decorate the node with the template's ID, so we consistently render it
// into the same DIV, and so that it doesn't get treated as anonymous anymore.
if (! node.name) {
@@ -127,10 +127,12 @@
* Compile a template without requiring a DOM node.
* @param {string} src XML data to be compiled.
* @param {string} opt_id An optional ID for the new template.
- * @return {os.Template} A compiled Template object.
+ * @param {Element} opt_container An optional container DOM Element
+ * to look for namespaces
+ * @return {opensocial.template.Template} A compiled Template object.
*/
-os.compileTemplateString = function(src, opt_id) {
- src = opensocial.xmlutil.prepareXML(src);
+os.compileTemplateString = function(src, opt_id, opt_container) {
+ src = opensocial.xmlutil.prepareXML(src, opt_container);
var doc = opensocial.xmlutil.parseXML(src);
return os.compileXMLDoc(doc, opt_id);
};
@@ -171,6 +173,13 @@
};
};
+/**
+ * Creates a map of the named children of a node. Lower-cased element names
+ * (including transformed custom tags) are used as keys.
+ * Where multiple elements share a name, the map value will be an array.
+ * @param {Element} node The node whose children are to be mapped
+ * @return {object} A Map of Element names to Elements.
+ */
os.computeChildMap_ = function(node) {
var map = {};
for (var i = 0; i < node.childNodes.length; i++) {
Modified: incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js?rev=772737&r1=772736&r2=772737&view=diff
==============================================================================
--- incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js (original)
+++ incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js Thu May 7 18:31:49 2009
@@ -20,17 +20,17 @@
* @fileoverview Standard methods invoked by containers to use the template API.
*
* Sample usage:
- * <script type="text/os-template" tag="os:Button">
+ * <script type="text/os-template" tag="os:Button">
* <button onclick="alert('Clicked'); return false;">
* <os:renderAll/>
* </button>
- * </script>
+ * </script]
*
- * <script type="text/os-template">
+ * <script type="text/os-template"]
* <os:Button>
* <div>Click me</div>
* </os:Button>
- * </script>
+ * </script]
*
* os.Container.registerDocumentTemplates();
* os.Container.renderInlineTemplates();
@@ -59,21 +59,14 @@
os.Container.domLoaded_ = false;
/**
- * @type {boolean} Determines whether all templates are automatically processed.
+ * @type {number} The number of libraries needed to load.
*/
-os.Container.autoProcess_ = true;
-
+os.Container.requiredLibraries_ = 0;
/**
- * In gadgets, honor the "disableAutoProcessing" feature param.
+ * @type {boolean} Determines whether all templates are automatically processed.
*/
-if (window['gadgets']) {
- var params = gadgets.util.getFeatureParameters("opensocial-templates");
- if (params && params.disableAutoProcessing &&
- params.disableAutoProcessing.toLowerCase != "false") {
- os.Container.autoProcess_ = false;
- }
-};
+os.Container.autoProcess_ = true;
/**
* @type {boolean} Has the document been processed already?
@@ -129,9 +122,9 @@
if (os.Container.domLoaded_) {
return;
}
- while (os.Container.domLoadCallbacks_.length) {
- try {
- os.Container.domLoadCallbacks_.pop()();
+ for (var i = 0; i < os.Container.domLoadCallbacks_.length; i ++) {
+ try {
+ os.Container.domLoadCallbacks_[i]();
} catch (e) {
os.log(e);
}
@@ -189,9 +182,9 @@
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
if (os.Container.isTemplateType_(node.type)) {
- var name = node.getAttribute('name') || node.getAttribute('tag');
+ var name = node.getAttribute('tag') || node.getAttribute('name');
if (!name || name.length < 0) {
- var template = os.compileTemplate(node);
+ var template = os.compileTemplate(node, name);
if (template) {
os.Container.inlineTemplates_.push(
{'template': template, 'node': node});
@@ -203,18 +196,16 @@
}
};
-os.Container.defaultContext = null;
-
+/**
+ * @return {JsEvalContext} the default rendering context to use - this will
+ * contain all available data.
+ */
os.Container.getDefaultContext = function() {
- if (!os.Container.defaultContext) {
- if ((window['gadgets'] && gadgets.util.hasFeature('opensocial-data')) ||
- (opensocial.data.DataContext)) {
- os.Container.defaultContext = os.createContext(opensocial.data.DataContext.getData());
- } else {
- os.Container.defaultContext = os.createContext({});
- }
+ if ((window['gadgets'] && gadgets.util.hasFeature('opensocial-data')) ||
+ (opensocial.data.getDataContext)) {
+ return os.createContext(opensocial.data.getDataContext().getData());
}
- return os.Container.defaultContext;
+ return os.createContext({});
};
/**
@@ -350,19 +341,60 @@
};
/**
+ * Process the gadget configuration when it is available.
+ */
+os.Container.processGadget = function() {
+ if (!window['gadgets']) {
+ return;
+ }
+
+ // Honor the "disableAutoProcessing" feature param.
+ var params = gadgets.util.getFeatureParameters("opensocial-templates");
+ if (!params) {
+ return;
+ }
+ if (params.disableAutoProcessing &&
+ params.disableAutoProcessing.toLowerCase != "false") {
+ os.Container.autoProcess_ = false;
+ }
+
+ // Honor the "requireLibrary" feature param.
+ // TODO: Support multiple params when Shindig does.
+ if (params.requireLibrary) {
+ os.Container.addRequiredLibrary(params.requireLibrary);
+ }
+};
+
+//Process the gadget when the page loads.
+os.Container.executeOnDomLoad(os.Container.processGadget);
+
+/**
+ * A flag to determine if auto processing is waiting for libraries to load.
+ * @type {boolean}
+ */
+os.Container.processWaitingForLibraries_ = false;
+
+/**
* Utility method which will automatically register all templates
* and render all that are inline.
- * @param {Object} opt_doc Optional document to use instead of window.document.
+ * @param {Object} opt_data Optional JSON object to render templates against
+ * @param {Document} opt_doc Optional document to use instead of window.document
*/
-os.Container.processDocument = function(opt_doc) {
+os.Container.processDocument = function(opt_data, opt_doc) {
+ if (os.Container.requiredLibraries_ > 0) {
+ os.Container.processWaitingForLibraries_ = true;
+ return;
+ }
+ os.Container.processWaitingForLibraries_ = false;
os.Container.registerDocumentTemplates(opt_doc);
- os.Container.processInlineTemplates(opt_doc);
+ os.Container.processInlineTemplates(opt_data, opt_doc);
os.Container.processed_ = true;
};
// Expose function in opensocial.template namespace.
os.process = os.Container.processDocument;
+// Process the document when the page loads - unless requested not to.
os.Container.executeOnDomLoad(function() {
if (os.Container.autoProcess_) {
os.Container.processDocument();
@@ -370,12 +402,35 @@
});
/**
+ * A handler called when one of the required libraries loads.
+ */
+os.Container.onLibraryLoad_ = function() {
+ if (os.Container.requiredLibraries_ > 0) {
+ os.Container.requiredLibraries_--;
+ if (os.Container.requiredLibraries_ == 0 &&
+ os.Container.processWaitingForLibraries_) {
+ os.Container.processDocument();
+ }
+ }
+};
+
+/**
+ * Adds a required library - the processing will be deferred until all
+ * required libraries have loaded.
+ * @param {string} libUrl The URL of the library needed to process this page
+ */
+os.Container.addRequiredLibrary = function(libUrl) {
+ os.Container.requiredLibraries_++;
+ os.Loader.loadUrl(libUrl, os.Container.onLibraryLoad_);
+};
+
+/**
* @type {string} Tag name of a template.
* @private
*/
os.Container.TAG_script_ = 'script';
-/***
+/**
* @type {Object} Map of allowed template content types.
* @private
* TODO(davidbyttow): Remove text/template.
Modified: incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/loader.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/loader.js?rev=772737&r1=772736&r2=772737&view=diff
==============================================================================
--- incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/loader.js (original)
+++ incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/loader.js Thu May 7 18:31:49 2009
@@ -91,8 +91,7 @@
req.open("GET", url, true);
req.onreadystatechange = function() {
if (req.readyState == 4) {
- os.Loader.loadContent(req.responseText);
- os.Loader.loadedUrls_[url] = true;
+ os.Loader.loadContent(req.responseText, url);
callback();
}
};
@@ -116,8 +115,7 @@
params[gadgets.io.RequestParameters.CONTENT_TYPE] =
gadgets.io.ContentType.TEXT;
gadgets.io.makeRequest(url, function(obj) {
- os.Loader.loadContent(obj.data);
- os.Loader.loadedUrls_[url] = true;
+ os.Loader.loadContent(obj.data, url);
callback();
}, params);
};
@@ -142,10 +140,11 @@
/**
* Processes the XML markup of a Template Library.
*/
-os.Loader.loadContent = function(xmlString) {
+os.Loader.loadContent = function(xmlString, url) {
var doc = opensocial.xmlutil.parseXML(xmlString);
var templatesNode = doc.firstChild;
os.Loader.processTemplatesNode(templatesNode);
+ os.Loader.loadedUrls_[url] = true;
};
/**
Modified: incubator/shindig/trunk/features/src/main/javascript/features/xmlutil/xmlutil.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/xmlutil/xmlutil.js?rev=772737&r1=772736&r2=772737&view=diff
==============================================================================
--- incubator/shindig/trunk/features/src/main/javascript/features/xmlutil/xmlutil.js (original)
+++ incubator/shindig/trunk/features/src/main/javascript/features/xmlutil/xmlutil.js Thu May 7 18:31:49 2009
@@ -69,21 +69,52 @@
* the supplied code. An empty string is returned if no injection is needed.
*
* @param {string} xml XML-like source code.
+ * @param {Element} opt_container Optional container node to look for namespace
+ * declarations.
* @return {string} A string of xmlns delcarations required for this XML.
*/
-opensocial.xmlutil.getRequiredNamespaces = function(xml) {
- var codeToInject = [];
- for (var ns in opensocial.xmlutil.NSMAP) {
- if (xml.indexOf("<" + ns + ":") >= 0 &&
- xml.indexOf("xmlns:" + ns + ":") < 0) {
- codeToInject.push(" xmlns:");
- codeToInject.push(ns);
- codeToInject.push("=\"");
- codeToInject.push(opensocial.xmlutil.NSMAP[ns]);
- codeToInject.push("\"");
+opensocial.xmlutil.getRequiredNamespaces = function(xml, opt_container) {
+ var namespaces = opt_container ?
+ opensocial.xmlutil.getNamespaceDeclarations_(opt_container) : {};
+ for (var prefix in opensocial.xmlutil.NSMAP) {
+ if (opensocial.xmlutil.NSMAP.hasOwnProperty(prefix)
+ && !namespaces.hasOwnProperty(prefix)
+ && xml.indexOf("<" + prefix + ":") >= 0
+ && xml.indexOf("xmlns:" + prefix + ":") < 0) {
+ namespaces[prefix] = opensocial.xmlutil.NSMAP[prefix];
}
}
- return codeToInject.join("");
+ return opensocial.xmlutil.serializeNamespaces_(namespaces);
+};
+
+
+opensocial.xmlutil.serializeNamespaces_ = function(namespaces) {
+ var buffer = [];
+ for (var prefix in namespaces) {
+ if (namespaces.hasOwnProperty(prefix)) {
+ buffer.push(" xmlns:", prefix, "=\"", namespaces[prefix], "\"");
+ }
+ }
+ return buffer.join("");
+};
+
+
+/**
+ * Returns a map of XML namespaces declared on an DOM Element.
+ * @param {Element} el The Element to inspect
+ * @return {object(string, string)} A Map of keyed by prefix of declared
+ * namespaces.
+ */
+opensocial.xmlutil.getNamespaceDeclarations_ = function(el) {
+ var namespaces = {};
+ for (var i = 0; i < el.attributes.length; i++) {
+ var name = el.attributes[i].nodeName;
+ if (name.substring(0, 6) != 'xmlns:') {
+ continue;
+ }
+ namespaces[name.substring(6, name.length)] = el.getAttribute(name);
+ }
+ return namespaces;
};
@@ -99,10 +130,12 @@
* Prepares an XML-like string to be parsed by browser parser. Injects a DOCTYPE
* with entities and a top-level <root> element to encapsulate the code.
* @param {string} xml XML string to be prepared.
+ * @param {Element} opt_container Optional container Element with namespace
+ * declarations.
* @return {string} XML string prepared for client-side parsing.
*/
-opensocial.xmlutil.prepareXML = function(xml) {
- var namespaces = opensocial.xmlutil.getRequiredNamespaces(xml);
+opensocial.xmlutil.prepareXML = function(xml, opt_container) {
+ var namespaces = opensocial.xmlutil.getRequiredNamespaces(xml, opt_container);
return "<!DOCTYPE root [" + opensocial.xmlutil.ENTITIES +
"]><root xml:space=\"preserve\"" +
namespaces + ">" + xml + "</root>";