This implementation adds handlers to <a> elements that exist when the config is inited, but it won't catch any anchor elements that are dynamically created. You could instead add a handler to the body and use bubbling (supported by all major browsers for onclick).
On Tue, Feb 10, 2009 at 4:11 PM, <[email protected]> wrote: > 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); > }, > > /** > > >

