Author: etnu
Date: Wed Feb 11 00:11:51 2009
New Revision: 743176
URL: http://svn.apache.org/viewvc?rev=743176&view=rev
Log:
Patch for SHINDIG-750.
This patch does a few things:
- Adds several tests
- Allows requestNavigateTo to take a string instead of a View (spec change)
- Optionally adds event handlers to all anchors with hrefs that are not
missing, fragments, or absolute. The remaining URIs (relative uris) would not
work under existing gadgets anyway. To use this, you must add rewriteLinks :
true to your container config for the "views" feature.
GadgetRenderingServlet still has to be modified to accept a parameter that will
specify the relative path for navigation as required by the spec. Containers
that are supporting the enhanced requestNavigateTo must ensure that they are
passing this parameter in order for it to work correctly.
Added:
incubator/shindig/trunk/features/views/requestnavigateto-test.js
incubator/shindig/trunk/features/views/views-init-test.js
Modified:
incubator/shindig/trunk/features/core.io/io.js
incubator/shindig/trunk/features/views/views.js
Modified: incubator/shindig/trunk/features/core.io/io.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/core.io/io.js?rev=743176&r1=743175&r2=743176&view=diff
==============================================================================
--- incubator/shindig/trunk/features/core.io/io.js (original)
+++ incubator/shindig/trunk/features/core.io/io.js Wed Feb 11 00:11:51 2009
@@ -255,7 +255,7 @@
* @private
*/
function init (configuration) {
- config = configuration["core.io"];
+ config = configuration["core.io"] || {};
}
var requiredConfig = {
Added: incubator/shindig/trunk/features/views/requestnavigateto-test.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/views/requestnavigateto-test.js?rev=743176&view=auto
==============================================================================
--- incubator/shindig/trunk/features/views/requestnavigateto-test.js (added)
+++ incubator/shindig/trunk/features/views/requestnavigateto-test.js Wed Feb 11
00:11:51 2009
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+
+function RequestNavigateToTest(name) {
+ TestCase.call(this, name);
+}
+
+RequestNavigateToTest.inherits(TestCase);
+
+(function() {
+
+var rpcs, oldRpc = gadgets.rpc;
+
+RequestNavigateToTest.prototype.setUp = function() {
+ rpcs = [];
+ gadgets.rpc = {
+ call: function() {
+ rpcs.push(arguments);
+ }
+ };
+};
+
+RequestNavigateToTest.prototype.tearDown = function() {
+ gadgets.rpc.call = oldRpc;
+};
+
+RequestNavigateToTest.prototype.testBasic = function() {
+ gadgets.views.requestNavigateTo("canvas");
+
+ this.assertEquals("requestNavigateTo", rpcs[0][1]);
+ this.assertEquals("canvas", rpcs[0][3]);
+};
+
+RequestNavigateToTest.prototype.testViewObject = function() {
+ gadgets.views.requestNavigateTo(new gadgets.views.View("canvas"));
+
+ this.assertEquals("requestNavigateTo", rpcs[0][1]);
+ this.assertEquals("canvas", rpcs[0][3]);
+};
+
+RequestNavigateToTest.prototype.testKeyValueParams = function() {
+ gadgets.views.requestNavigateTo("canvas", {foo:"bar"});
+
+ this.assertEquals("requestNavigateTo", rpcs[0][1]);
+ this.assertEquals("canvas", rpcs[0][3]);
+ this.assertEquals("bar", rpcs[0][4].foo);
+};
+
+RequestNavigateToTest.prototype.testUriParams = function() {
+ gadgets.views.requestNavigateTo("canvas", "/foo/bar?blah");
+
+ this.assertEquals("requestNavigateTo", rpcs[0][1]);
+ this.assertEquals("canvas", rpcs[0][3]);
+ this.assertEquals("/foo/bar?blah", rpcs[0][4]);
+};
+
+})();
+
Added: incubator/shindig/trunk/features/views/views-init-test.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/views/views-init-test.js?rev=743176&view=auto
==============================================================================
--- incubator/shindig/trunk/features/views/views-init-test.js (added)
+++ incubator/shindig/trunk/features/views/views-init-test.js Wed Feb 11
00:11:51 2009
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+function ViewsInitTest(name) {
+ TestCase.call(this, name);
+}
+
+ViewsInitTest.inherits(TestCase);
+
+(function() {
+
+var oldDocument = document;
+var callback;
+
+ViewsInitTest.prototype.tearDown = function() {
+ document = oldDocument;
+};
+
+ViewsInitTest.prototype.testObjectParams = function() {
+ gadgets.util.getUrlParameters = function() {
+ return {"view-params": gadgets.json.stringify({foo: "bar"})};
+ };
+
+ gadgets.config.init({views:{}});
+
+ this.assertEquals("bar", gadgets.views.getParams().foo);
+};
+
+ViewsInitTest.prototype.testStringParams = function() {
+ // In practice, containers should actually be passing this as the 'path'
query string param
+ // to the gadget renderer, but we want to be sure that we can handle it just
in case.
+ var path = "/foo/bar/baz.html?blah=blah&foo=bar";
+ gadgets.util.getUrlParameters = function() {
+ return {"view-params": gadgets.json.stringify(path)};
+ };
+
+ gadgets.config.init({views:{}});
+
+ this.assertEquals(path, gadgets.views.getParams());
+};
+
+function createAnchors(input) {
+ var anchors = [];
+ for (var i = 0, j = input.length; i < j; ++i) {
+ anchors[i] = {
+ href: input[i],
+ eventName: null,
+ addEventListener: function(name, func) {
+ this.invokedAddEventListener = true;
+ this.eventName = name;
+ }
+ };
+ }
+ return anchors;
+}
+
+ViewsInitTest.prototype.testRewriteLinks = function() {
+ var input = [
+ "http://example.org/absolute",
+ "/relative/path?arg=foo",
+ "#fragment",
+ "/relative/path?arg=foo",
+ null
+ ];
+
+ var anchors = createAnchors(input);
+
+ // Make the last one pretend to be IE.
+ anchors[3].attachEvent = function(name, func) {
+ this.invokedAttachEvent = true;
+ this.eventName = name;
+ };
+
+ document = {
+ getElementsByTagName: function(tag) {
+ if (tag === "a") {
+ return anchors;
+ }
+ return [];
+ }
+ };
+
+ gadgets.config.init({views:{rewriteLinks: true}});
+
+ this.assertEquals(null, anchors[0].eventName);
+ this.assertEquals("click", anchors[1].eventName);
+ this.assertEquals(null, anchors[2].eventName);
+ this.assertEquals("onclick", anchors[3].eventName);
+ this.assertEquals(null, anchors[4].eventName);
+
+ this.assertTrue(anchors[1].invokedAddEventListener);
+ this.assertTrue(anchors[3].invokedAttachEvent);
+
+ this.assertTrue(typeof gadgets.views.getSupportedViews().rewriteLinks ===
"undefined");
+};
+
+})();
Modified: incubator/shindig/trunk/features/views/views.js
URL:
http://svn.apache.org/viewvc/incubator/shindig/trunk/features/views/views.js?rev=743176&r1=743175&r2=743176&view=diff
==============================================================================
--- incubator/shindig/trunk/features/views/views.js (original)
+++ incubator/shindig/trunk/features/views/views.js Wed Feb 11 00:11:51 2009
@@ -45,6 +45,43 @@
var params = {};
/**
+ * Forces navigation via requestNavigateTo.
+ */
+ function forceNavigate(href) {
+ return function(e) {
+ if (!e) {
+ e = window.event;
+ }
+
+ gadgets.views.requestNavigateTo(currentView, href);
+
+ e.cancelBubble = true;
+ if (e.stopPropagation) {
+ e.stopPropagation();
+ }
+ if (e.preventDefault) {
+ e.preventDefault();
+ }
+ return false;
+ };
+ }
+
+ function attachLinkHandlers() {
+ var anchors = document.getElementsByTagName("a");
+ for (var i = 0, j = anchors.length; i < j; ++i) {
+ var anchor = anchors[i];
+ var href = anchor.href;
+ if (href && !(href[0] === "#" || href.indexOf("://") !== -1)) {
+ if (anchor.attachEvent) {
+ anchor.attachEvent("onclick", forceNavigate(href));
+ } else {
+ anchor.addEventListener("click", forceNavigate(href), false);
+ }
+ }
+ }
+ }
+
+ /**
* Initializes views. Assumes that the current view is the "view"
* url parameter (or default if "view" isn't supported), and that
* all view parameters are in the form view-<name>
@@ -52,17 +89,19 @@
*
*/
function init(config) {
- var supported = config["views"];
-
- for (var s in supported) if (supported.hasOwnProperty(s)) {
- var obj = supported[s];
- if (!obj) {
- continue;
- }
- supportedViews[s] = new gadgets.views.View(s, obj.isOnlyVisible);
- var aliases = obj.aliases || [];
- for (var i = 0, alias; alias = aliases[i]; ++i) {
- supportedViews[alias] = new gadgets.views.View(s, obj.isOnlyVisible);
+ var conf = config.views || {};
+ for (var s in conf) if (conf.hasOwnProperty(s)) {
+ // TODO: Fix this by moving view names / config into a sub property.
+ if (s != "rewriteLinks") {
+ var obj = conf[s];
+ if (!obj) {
+ continue;
+ }
+ supportedViews[s] = new gadgets.views.View(s, obj.isOnlyVisible);
+ var aliases = obj.aliases || [];
+ for (var i = 0, alias; alias = aliases[i]; ++i) {
+ supportedViews[alias] = new gadgets.views.View(s, obj.isOnlyVisible);
+ }
}
}
@@ -72,6 +111,10 @@
params = gadgets.json.parse(urlParams["view-params"]) || params;
}
currentView = supportedViews[urlParams.view] || supportedViews["default"];
+
+ if (conf.rewriteLinks) {
+ attachLinkHandlers();
+ }
}
gadgets.config.register("views", null, init);
@@ -204,15 +247,17 @@
* supports parameters will pass the optional parameters along to the
gadget
* in the new view.
*
- * @param {gadgets.views.View} view The view to navigate to
+ * @param {string | gadgets.views.View} view The view to navigate to
* @param {Map.<String, String>} opt_params Parameters to pass to the
* gadget after it has been navigated to on the surface
* @param {string} opt_ownerId The ID of the owner of the page to navigate
to;
* defaults to the current owner.
*/
requestNavigateTo : function(view, opt_params, opt_ownerId) {
- gadgets.rpc.call(
- null, "requestNavigateTo", null, view.getName(), opt_params,
opt_ownerId);
+ if (typeof view !== "string") {
+ view = view.getName();
+ }
+ gadgets.rpc.call(null, "requestNavigateTo", null, view, opt_params,
opt_ownerId);
},
/**