You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by et...@apache.org on 2009/02/11 21:16:32 UTC

svn commit: r743479 - in /incubator/shindig/trunk/features/views: views-init-test.js views.js

Author: etnu
Date: Wed Feb 11 20:16:32 2009
New Revision: 743479

URL: http://svn.apache.org/viewvc?rev=743479&view=rev
Log:
Improved automatic link interception by hooking into the document element, as suggested by Adam.


Modified:
    incubator/shindig/trunk/features/views/views-init-test.js
    incubator/shindig/trunk/features/views/views.js

Modified: 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=743479&r1=743478&r2=743479&view=diff
==============================================================================
--- incubator/shindig/trunk/features/views/views-init-test.js (original)
+++ incubator/shindig/trunk/features/views/views-init-test.js Wed Feb 11 20:16:32 2009
@@ -55,59 +55,44 @@
   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;
-  };
 
+ViewsInitTest.prototype.testRewriteLinksStandards = function() {
+  var name, func, bubble;
   document = {
-    getElementsByTagName: function(tag) {
-      if (tag === "a") {
-        return anchors;
-      }
-      return [];
+    addEventListener: function() {
+      name = arguments[0];
+      func = arguments[1];
+      bubble = arguments[2];
     }
   };
 
   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.assertEquals("click", name);
+  this.assertTrue(typeof func === "function");
+  this.assertFalse(bubble);
+  this.assertTrue(typeof gadgets.views.getSupportedViews().rewriteLinks === "undefined");
+};
 
-  this.assertTrue(anchors[1].invokedAddEventListener);
-  this.assertTrue(anchors[3].invokedAttachEvent);
+ViewsInitTest.prototype.testRewriteLinksIe = function() {
+  var name, func, self = this;
+  document = {
+    attachEvent: function() {
+      name = arguments[0];
+      func = arguments[1];
+    },
+    addEventListener: function() {
+      self.fail("Tried to call addEventListener in IE.");
+    }
+  };
+
+  gadgets.config.init({views:{rewriteLinks: true}});
 
+  this.assertEquals("onclick", name);
+  this.assertTrue(typeof func === "function");
   this.assertTrue(typeof gadgets.views.getSupportedViews().rewriteLinks === "undefined");
 };
 
+// TODO: Verify behavior of onclick.
+
 })();

Modified: incubator/shindig/trunk/features/views/views.js
URL: http://svn.apache.org/viewvc/incubator/shindig/trunk/features/views/views.js?rev=743479&r1=743478&r2=743479&view=diff
==============================================================================
--- incubator/shindig/trunk/features/views/views.js (original)
+++ incubator/shindig/trunk/features/views/views.js Wed Feb 11 20:16:32 2009
@@ -47,38 +47,40 @@
   /**
    * Forces navigation via requestNavigateTo.
    */
-  function forceNavigate(href) {
-    return function(e) {
-      if (!e) {
-        e = window.event;
-      }
+  function forceNavigate(e) {
+    if (!e) {
+      e = window.event;
+    }
 
-      gadgets.views.requestNavigateTo(currentView, href);
+    var target;
+    if (e.target) {
+      target = e.target;
+    } else if (e.srcElement) {
+      target = e.srcElement;
+    }
 
-      e.cancelBubble = true;
-      if (e.stopPropagation) {
-        e.stopPropagation();
-      }
-      if (e.preventDefault) {
-        e.preventDefault();
-      }
-      return false;
-    };
-  }
+    if (target.nodeType === 3) {
+      target = target.parentNode;
+    }
 
-  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);
+    if (target.nodeName.toLowerCase() === "a") {
+      // We use getAttribute() instead of .href to avoid automatic relative path resolution.
+      var href = target.getAttribute("href");
+      if (href && href[0] !== "#" && href.indexOf("://") === -1) {
+        gadgets.views.requestNavigateTo(currentView, href);
+        if (e.stopPropagation) {
+          e.stopPropagation();
+        }
+        if (e.preventDefault) {
+          e.preventDefault();
         }
+        e.returnValue = false;
+        e.cancelBubble = true;
+        return false;
       }
     }
+
+    return false;
   }
 
   /**
@@ -113,7 +115,11 @@
     currentView = supportedViews[urlParams.view] || supportedViews["default"];
 
     if (conf.rewriteLinks) {
-      attachLinkHandlers();
+      if (document.attachEvent) {
+        document.attachEvent("onclick", forceNavigate);
+      } else {
+        document.addEventListener("click", forceNavigate, false);
+      }
     }
   }