Author: evan
Date: Fri May 15 17:40:29 2009
New Revision: 775254
URL: http://svn.apache.org/viewvc?rev=775254&view=rev
Log:
SHINDIG-1061
Patch from Lev:
Changes to client-side Templates implementation
- @field support for DataPipelining
- removed need for jstemplate_debug.js file
- added rudimentary typing to identifier resolution
- @repeat values are requested as arrays
- when arrays are requested and objects found, we now look for the .list
property (this enables proper DP support)
- fixed passing in defaults for compilation (only the last element is
defaulted)
- @onAttach is also supported as @onChange, @onchange, @x-onChange and
@x-onchange
Removed:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jstemplate_debug.js
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/compiler.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/container.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/feature.xml
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/os.js
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/template.js
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/compiler_test.js
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/index.html
incubator/shindig/trunk/java/server/src/test/resources/endtoend/opensocial-templates/compiler_test.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=775254&r1=775253&r2=775254&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
Fri May 15 17:40:29 2009
@@ -533,18 +533,38 @@
/**
+ * Parses a string of comma-separated field names and adds the resulting array
+ * (if any) to the params object.
+ * @param {object} params The params object used to construct an Opensocial
+ * DataRequest
+ * @param {string} fieldStr A string containing comma-separated field names
+ */
+opensocial.data.addFieldsToParams_ = function(params, fieldsStr) {
+ if (!fieldsStr) {
+ return;
+ }
+ var fields = fieldsStr.replace(/(^\s*|\s*$)/g, '').split(/\s*,\s*/);
+ params[opensocial.DataRequest.PeopleRequestFields.PROFILE_DETAILS] = fields;
+};
+
+
+/**
* Anonymous function defines OpenSocial specific requests.
* Automatically called when this file is loaded.
*/
(function() {
opensocial.data.registerRequestHandler("os:ViewerRequest",
function(descriptor) {
- var req =
opensocial.data.getCurrentAPIRequest().newFetchPersonRequest("VIEWER");
+ var params = {};
+ opensocial.data.addFieldsToParams_(params,
descriptor.getAttribute("fields"));
+ var req =
opensocial.data.getCurrentAPIRequest().newFetchPersonRequest("VIEWER", params);
// TODO: Support @fields param.
opensocial.data.addToCurrentAPIRequest(req, descriptor.key);
});
opensocial.data.registerRequestHandler("os:OwnerRequest",
function(descriptor) {
- var req =
opensocial.data.getCurrentAPIRequest().newFetchPersonRequest("OWNER");
+ var params = {};
+ opensocial.data.addFieldsToParams_(params,
descriptor.getAttribute("fields"));
+ var req =
opensocial.data.getCurrentAPIRequest().newFetchPersonRequest("OWNER", params);
// TODO: Support @fields param.
opensocial.data.addToCurrentAPIRequest(req, descriptor.key);
});
@@ -557,9 +577,11 @@
if (groupId != "@self") {
idSpec.groupId = opensocial.data.transformSpecialValue(groupId);
}
+ var params = {};
+ opensocial.data.addFieldsToParams_(params,
descriptor.getAttribute("fields"));
// TODO: Support other params.
var req = opensocial.data.getCurrentAPIRequest().newFetchPeopleRequest(
- opensocial.newIdSpec(idSpec));
+ opensocial.newIdSpec(idSpec), params);
// TODO: Annotate with the @ids property.
opensocial.data.addToCurrentAPIRequest(req, descriptor.key);
});
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=775254&r1=775253&r2=775254&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
Fri May 15 17:40:29 2009
@@ -87,9 +87,16 @@
os.VAR_parentnode = "$parentnode";
os.VAR_uniqueId = "$uniqueId";
os.VAR_identifierresolver = "$_ir";
+os.VAR_emptyArray = "$_ea";
os.VAR_callbacks = "$callbacks_";
/**
+ * Reusable empty array instance
+ * IE6 PERF: To avoid creating empty arrays when they are needed.
+ */
+os.EMPTY_ARRAY = [];
+
+/**
* Regular expressions
* TODO(levik): Move all regular expressions here.
*/
@@ -247,14 +254,6 @@
};
/**
- * Globally disallowed dynamic attributes. These are the attributes where
- * ${} notation will be ignored reguardless of the tag.
- */
-os.globalDisallowedAttributes_ = {
- 'data': 1
-};
-
-/**
* A map of custom attributes keyed by attribute name.
* Maps {string} types onto Function({Element|string|Object|JSEvalContext}).
* @type {Object}
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/compiler.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/compiler.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/compiler.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/compiler.js
Fri May 15 17:40:29 2009
@@ -204,6 +204,9 @@
* @return {Object|String}
*/
os.getFromContext = function(context, name, opt_default) {
+ if (!context) {
+ return opt_default;
+ }
var ret;
// Check if this is a context object.
if (context.vars_ && context.data_) {
@@ -238,6 +241,11 @@
} else {
ret = "";
}
+ } else if (opt_default && os.isArray(opt_default) && !os.isArray(ret) &&
+ ret.list && os.isArray(ret.list)) {
+ // If we were trying to get an array, but got a JSON object with an
+ // array property "list", return that instead.
+ ret = ret.list;
}
return ret;
};
@@ -317,8 +325,7 @@
var outName = os.attributeMap_.hasOwnProperty(name) ?
os.attributeMap_[name] : name;
var substitution =
- (os.attributeMap_[name] ||
- opt_customTag && os.globalDisallowedAttributes_[outName]) ?
+ (os.attributeMap_[name]) ?
null : os.parseAttribute_(value);
if (substitution) {
@@ -361,8 +368,10 @@
value.charAt(value.length - 1) == '}') {
value = value.substring(2, value.length - 1);
}
- // In special attributes, default value is null.
- value = os.transformExpression_(value, 'null');
+ // In special attributes, default value is empty array for repeats,
+ // null for others
+ value = os.transformExpression_(value,
+ name == 'repeat' ? os.VAR_emptyArray : 'null');
} else if (outName == 'class') {
// In IE, we must set className instead of class.
to.setAttribute('className', value);
@@ -654,6 +663,7 @@
* Parses an attribute value into a JS expression. "Hello, ${user}!" becomes
* "Hello, " + user + "!".
*
+ * @param {string} value Attribute value to parse
* TODO: Rename to parseExpression()
*/
os.parseAttribute_ = function(value) {
@@ -676,7 +686,8 @@
if (!expr) {
expr = VAR_this;
}
- parts.push('(' + os.transformExpression_(expr) + ')');
+ parts.push('(' +
+ os.transformExpression_(expr) + ')');
text = match[3];
match = text.match(substRex);
}
@@ -839,7 +850,11 @@
var iden = identifiers[i];
parts = os.breakUpParens(iden);
if (!parts) {
- output = os.wrapSingleIdentifier(iden, output, opt_default);
+ if (i == identifiers.length - 1) {
+ output = os.wrapSingleIdentifier(iden, output, opt_default);
+ } else {
+ output = os.wrapSingleIdentifier(iden, output);
+ }
} else {
buffer.length = 0;
buffer.push(os.wrapSingleIdentifier(parts[0], output));
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=775254&r1=775253&r2=775254&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
Fri May 15 17:40:29 2009
@@ -245,8 +245,7 @@
if (requiredData) {
// This template will render when the specified data is available.
var keys = requiredData.split(/[\, ]+/);
- var callback = os.Container.createRenderClosure(template, el, null,
- os.Container.getDefaultContext());
+ var callback = os.Container.createRenderClosure(template, el);
if ("true" == node.getAttribute("autoUpdate")) {
opensocial.data.DataContext.registerListener(keys, callback);
} else {
@@ -274,7 +273,17 @@
os.Container.createRenderClosure = function(template, element, opt_data,
opt_context) {
var closure = function() {
- template.renderInto(element, opt_data, opt_context);
+ var context = opt_context;
+ var data = opt_data;
+ if (!context) {
+ if (data) {
+ context = os.createContext(data);
+ } else {
+ context = os.Container.getDefaultContext();
+ data = context.data_;
+ }
+ }
+ template.renderInto(element, data, context);
};
return closure;
};
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/feature.xml
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/feature.xml?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/feature.xml
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/feature.xml
Fri May 15 17:40:29 2009
@@ -37,7 +37,6 @@
<script src="jsTemplate/util.js"></script>
<script src="jsTemplate/jsevalcontext.js"></script>
<script src="jsTemplate/jstemplate.js"></script>
- <script src="jstemplate_debug.js"></script>
<script src="base.js"></script>
<script src="namespaces.js"></script>
<script src="util.js"></script>
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js
Fri May 15 17:40:29 2009
@@ -909,7 +909,7 @@
*/
function jstGetTemplateOrDie(name, opt_loadHtmlFn) {
var x = jstGetTemplate(name, opt_loadHtmlFn);
- check(x !== null);
+ //check(x !== null);
return /** @type Element */(x);
}
@@ -1016,7 +1016,7 @@
}
if (jstAttributeValues) {
msg += '<tr><td>' + 'attr:' +
- '</td><td>' + jsToSource(jstAttributeValues) + '</td></tr>';
+ '</td><td>' + /*jsToSource*/(jstAttributeValues) + '</td></tr>';
}
msg += '</tbody></table><br/>';
this.logs_.push(msg);
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/os.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/os.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/os.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/os.js
Fri May 15 17:40:29 2009
@@ -111,6 +111,10 @@
callbacks.push(createClosure(node, func));
}
os.registerAttribute_("onAttach", processOnAttach);
+ os.registerAttribute_("onCreate", processOnAttach);
+ os.registerAttribute_("oncreate", processOnAttach);
+ os.registerAttribute_("x-oncreate", processOnAttach);
+ os.registerAttribute_("x-onCreate", processOnAttach);
};
os.defineBuiltinTags();
Modified:
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/template.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/template.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/template.js
(original)
+++
incubator/shindig/trunk/features/src/main/javascript/features/opensocial-templates/template.js
Fri May 15 17:40:29 2009
@@ -29,6 +29,7 @@
var context = JsEvalContext.create(data);
context.setVariable(os.VAR_callbacks, []);
context.setVariable(os.VAR_identifierresolver, os.getFromContext);
+ context.setVariable(os.VAR_emptyArray, os.EMPTY_ARRAY);
if (opt_globals) {
for (var global in opt_globals) {
if (opt_globals.hasOwnproperty(global)) {
Modified:
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/compiler_test.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/compiler_test.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/compiler_test.js
(original)
+++
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/compiler_test.js
Fri May 15 17:40:29 2009
@@ -53,24 +53,27 @@
* "foo(bar)[baz]"
*/
function testWrapIdentifiers() {
- assertEquals("$_ir($_ir($context, 'foo'), 'bar')",
+ assertEquals("$_ir($_ir($context, 'foo'), 'bar')",
os.wrapIdentifiersInExpression("foo.bar"));
assertEquals("$_ir($_ir($context, 'data'), 'array')()",
os.wrapIdentifiersInExpression("data.array()"));
- assertEquals("$_ir($_ir($context, 'data')(), 'array')",
+ assertEquals("$_ir($_ir($context, 'data')(), 'array')",
os.wrapIdentifiersInExpression('data().array'));
- // Check that namespaced tags are treated as single identifiers.
- assertEquals("$_ir($context, 'os:Item')",
+ // Check that namespaced tags are treated as single identifiers.
+ assertEquals("$_ir($context, 'os:Item')",
os.wrapIdentifiersInExpression("os:Item"));
-
- // Check that a colon surrounded by spaces is not treated as
- // part of identifier
- assertEquals("$_ir($context, 'foo') ? $_ir($context, 'bar') : " +
+
+ // Check that a colon surrounded by spaces is not treated as
+ // part of identifier
+ assertEquals("$_ir($context, 'foo') ? $_ir($context, 'bar') : " +
"$_ir($context, 'baz')",
os.wrapIdentifiersInExpression("foo ? bar : baz"));
+
+ assertEquals("$_ir($_ir($context, 'viewer'), 'foo', $_ea)",
+ os.wrapIdentifiersInExpression("viewer.foo", "$_ea"));
}
function testTransformVariables() {
@@ -127,7 +130,7 @@
*/
function testTbodyInjection() {
var src, check, template, output;
-
+
// One row.
src = "<table><tr><td>foo</td></tr></table>";
check = "<table><tbody><tr><td>foo</td></tr></tbody></table>";
@@ -136,25 +139,25 @@
output = output.toLowerCase();
output = output.replace(/\s/g, '');
assertEquals(check, output);
-
+
// Two rows.
src = "<table><tr><td>foo</td></tr><tr><td>bar</td></tr></table>";
- check = "<table><tbody><tr><td>foo</td></tr>" +
+ check = "<table><tbody><tr><td>foo</td></tr>" +
"<tr><td>bar</td></tr></tbody></table>";
template = os.compileTemplateString(src);
output = template.templateRoot_.innerHTML;
output = output.toLowerCase();
output = output.replace(/\s/g, '');
- assertEquals(check, output);
+ assertEquals(check, output);
};
function testEventHandlers() {
var src, template, output;
-
+
window['testEvent'] = function(value) {
window['testValue'] = value;
};
-
+
// Static handler
src = "<button onclick=\"testEvent(true)\">Foo</button>";
template = os.compileTemplateString(src);
@@ -165,7 +168,7 @@
output.firstChild.click();
document.body.removeChild(output);
assertEquals(true, window['testValue']);
-
+
// Dynamic handler
src = "<button onclick=\"testEvent('${title}')\">Foo</button>";
template = os.compileTemplateString(src);
@@ -175,13 +178,13 @@
window['testValue'] = false;
output.firstChild.click();
document.body.removeChild(output);
- assertEquals('foo', window['testValue']);
+ assertEquals('foo', window['testValue']);
};
function testNestedIndex() {
var src, template, output;
-
- src = '<table><tr repeat="${list}" var="row" context="x">' +
+
+ src = '<table><tr repeat="${list}" var="row" context="x">' +
'<td repeat="${row}"
context="y">${x.Index},${y.Index}</td></tr></table>';
template = os.compileTemplateString(src);
output = template.render({ list: [ ['a', 'b'], ['c', 'd'] ] });
@@ -193,12 +196,12 @@
var src = '<div repeat="foo">a</div>';
var template = os.compileTemplateString(src);
var select = template.templateRoot_.firstChild.getAttribute("jsselect");
- assertEquals("$_ir($context, 'foo', null)", select);
+ assertEquals("$_ir($context, 'foo', $_ea)", select);
};
/*
function testEmbed() {
var src, template, output;
-
+
src = '<embed sRc="http://www.youtube.com/v/${$my.movie}&hl=en"
type="application/x-shockwave-flash" wmode="transparent" height="${$my.height}"
width="${$my.width}"/>';
template = os.compileTemplateString(src);
src = '<img sRc="http://www.youtube.com/v/${$my.movie}&hl=en"
type="application/x-shockwave-flash" wmode="transparent" height="${$my.height}"
width="${$my.width}"/>';
@@ -211,18 +214,18 @@
// JSON context
var context = { foo: 'bar' };
assertEquals('bar', os.getFromContext(context, 'foo'));
-
- // JsEvalContext
+
+ // JsEvalContext
context = os.createContext(context);
assertEquals('bar', os.getFromContext(context, 'foo'));
-
+
// Variable from context
context.setVariable('baz', 'bing');
assertEquals('bing', os.getFromContext(context, 'baz'));
-
+
// Non-existent value
assertEquals('', os.getFromContext(context, 'title'));
-
+
// Non-existent value with default
assertEquals(null, os.getFromContext(context, 'title', null));
};
Modified:
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/index.html
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/index.html?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/index.html
(original)
+++
incubator/shindig/trunk/features/src/test/javascript/features/opensocial-templates/index.html
Fri May 15 17:40:29 2009
@@ -44,7 +44,7 @@
<script
src="../../../../main/javascript/features/opensocial-templates/jsTemplate/util.js"></script>
<script
src="../../../../main/javascript/features/opensocial-templates/jsTemplate/jsevalcontext.js"></script>
<script
src="../../../../main/javascript/features/opensocial-templates/jsTemplate/jstemplate.js"></script>
- <script
src="../../../../main/javascript/features/opensocial-templates/jstemplate_debug.js"></script>
+
<script
src="../../../../main/javascript/features/opensocial-data-context/datacontext.js"></script>
<script
src="../../../../main/javascript/features/xmlutil/xmlutil.js"></script>
<script
src="../../../../main/javascript/features/opensocial-data/data.js"></script>
Modified:
incubator/shindig/trunk/java/server/src/test/resources/endtoend/opensocial-templates/compiler_test.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/java/server/src/test/resources/endtoend/opensocial-templates/compiler_test.js?rev=775254&r1=775253&r2=775254&view=diff
==============================================================================
---
incubator/shindig/trunk/java/server/src/test/resources/endtoend/opensocial-templates/compiler_test.js
(original)
+++
incubator/shindig/trunk/java/server/src/test/resources/endtoend/opensocial-templates/compiler_test.js
Fri May 15 17:40:29 2009
@@ -194,7 +194,7 @@
var src = '<div repeat="foo">a</div>';
var template = os.compileTemplateString(src);
var select = template.templateRoot_.firstChild.getAttribute("jsselect");
- assertEquals("$_ir($context, 'foo', null)", select);
+ assertEquals("$_ir($context, 'foo', $_ea)", select);
}
function testGetFromContext() {