Hello Ray :)

Would you take a look at this patch for the Hyperlink widget? It takes
the behavior from incubator's HyperlinkOverride widget and moves it
into the core Hyperlink.

This means that on a click event with a modifier key (with specific
keys counting, per-browser), we let the default browser action happen,
usually something like opening that link in a new tab.

I have a small doubt about this patch with regard to Chrome, but
please let me know what you think -- as far as I can tell, Chrome
doesn't do an "open in new tab" when you ctrl-click on a link to a URL
fragment (for example, our history tokens) -- but on the assumption
that this may change soon, this patch tries to do the behavior that
Chrome does for regular links, which is just like Firefox.

Patch is intended for the 1.6 release branch, r4214.

Thanks!

-- 
Alex Rudnick
swe, gwt, atl

--~--~---------~--~----~------------~-------~--~----~
http://groups.google.com/group/Google-Web-Toolkit-Contributors
-~----------~----~----~----~------~----~------~--~---

Index: user/src/com/google/gwt/user/Hyperlink.gwt.xml
===================================================================
--- user/src/com/google/gwt/user/Hyperlink.gwt.xml	(revision 0)
+++ user/src/com/google/gwt/user/Hyperlink.gwt.xml	(revision 0)
@@ -0,0 +1,19 @@
+<module>
+  <inherits name="com.google.gwt.core.Core"/>
+  <inherits name="com.google.gwt.user.UserAgent"/>
+
+  <replace-with class="com.google.gwt.user.client.ui.impl.HyperlinkImplOpera">
+    <when-type-is class="com.google.gwt.user.client.ui.impl.HyperlinkImpl"/>
+    <when-property-is name="user.agent" value="opera"/>
+  </replace-with>
+
+  <replace-with class="com.google.gwt.user.client.ui.impl.HyperlinkImplSafari">
+    <when-type-is class="com.google.gwt.user.client.ui.impl.HyperlinkImpl"/>
+    <when-property-is name="user.agent" value="safari"/>
+  </replace-with>
+
+  <replace-with class="com.google.gwt.user.client.ui.impl.HyperlinkImplIE">
+    <when-type-is class="com.google.gwt.user.client.ui.impl.HyperlinkImpl"/>
+    <when-property-is name="user.agent" value="ie6"/>
+  </replace-with>
+</module>
Index: user/src/com/google/gwt/user/User.gwt.xml
===================================================================
--- user/src/com/google/gwt/user/User.gwt.xml	(revision 4214)
+++ user/src/com/google/gwt/user/User.gwt.xml	(working copy)
@@ -39,6 +39,7 @@
    <inherits name="com.google.gwt.user.CaptionPanel" />
    <inherits name="com.google.gwt.user.Window" />
    <inherits name="com.google.gwt.user.Tree"/>
+   <inherits name="com.google.gwt.user.Hyperlink"/>
     
     <super-source path="translatable"/>
     <source path="client"/>
Index: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplIE.java
===================================================================
--- user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplIE.java	(revision 0)
+++ user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplIE.java	(revision 0)
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed 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.
+ */
+
+package com.google.gwt.user.client.ui.impl;
+
+import com.google.gwt.user.client.Event;
+
+/**
+ * IE version of HyperlinkImpl. IE6 and IE7 actually have different
+ * behavior; both have special behavior for shift-click, but IE7 also opens
+ * in a new tab on ctrl-click. IE6 treats ctrl-click as a standard click.
+ */
+public class HyperlinkImplIE extends HyperlinkImpl {
+  
+  private static boolean ctrlisModifier;
+
+  static {
+    ctrlisModifier = (getInternetExplorerVersion() >= 7);
+  }
+
+  /**
+   * Returns the version of Internet Explorer or a -1, (indicating the use of
+   * another browser). Based on code from MSDN.
+   * http://msdn2.microsoft.com/en-us/library/ms537509.aspx
+   */
+  private static native int getInternetExplorerVersion() /*-{
+    var rv = -1; // Assume that we're not IE.
+           
+    if (navigator.appName == 'Microsoft Internet Explorer') {
+      var ua = navigator.userAgent;
+      var re  = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
+      if (re.exec(ua) != null)
+        rv = parseFloat( RegExp.$1 );
+    }
+    
+    return rv;
+  }-*/;
+  
+  @Override
+  public boolean handleAsClick(Event event) {
+    int mouseButtons = event.getButton();
+    boolean ctrl = event.getCtrlKey();
+    boolean shift = event.getShiftKey();
+    boolean middle = mouseButtons == Event.BUTTON_MIDDLE;
+    boolean right = mouseButtons == Event.BUTTON_RIGHT;
+    boolean modifiers;
+    
+    if (ctrlisModifier) {
+      modifiers = shift || ctrl;
+    } else {
+      modifiers = shift;  
+    }
+
+    return !modifiers && !middle && !right;
+  }
+}

Property changes on: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplIE.java
___________________________________________________________________
Name: svn:mime-type
   + text/x-java
Name: svn:eol-style
   + native

Index: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplSafari.java
===================================================================
--- user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplSafari.java	(revision 0)
+++ user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplSafari.java	(revision 0)
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed 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.
+ */
+
+package com.google.gwt.user.client.ui.impl;
+
+import com.google.gwt.user.client.Event;
+
+/**
+ * HyperlinkImpl for Safari and Google Chrome. Safari has special behavior for
+ * all the modifier keys except shift, which behaves like a regular click.
+ * Chrome, however, opens a new window on a shift-click.
+ */
+public class HyperlinkImplSafari extends HyperlinkImpl {
+
+  private static boolean shiftIsModifier;
+
+  static {
+    shiftIsModifier = onChrome();
+  }
+
+  private static native boolean onChrome() /*-{
+    return navigator.userAgent.indexOf("Chrome") != -1;
+  }-*/;
+
+  @Override
+  public boolean handleAsClick(Event event) {
+    int mouseButtons = event.getButton();
+    boolean alt = event.getAltKey();
+    boolean ctrl = event.getCtrlKey();
+    boolean meta = event.getMetaKey();
+    boolean shift = event.getShiftKey();
+    boolean middle = mouseButtons == Event.BUTTON_MIDDLE;
+    boolean right = mouseButtons == Event.BUTTON_RIGHT;
+
+    boolean modifiers = alt || ctrl || meta;
+    if (shiftIsModifier) {
+      modifiers |= shift;
+    }
+    
+    return !modifiers && !middle && !right;
+  }
+}

Property changes on: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplSafari.java
___________________________________________________________________
Name: svn:mime-type
   + text/x-java
Name: svn:eol-style
   + native

Index: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplOpera.java
===================================================================
--- user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplOpera.java	(revision 0)
+++ user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplOpera.java	(revision 0)
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed 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.
+ */
+
+package com.google.gwt.user.client.ui.impl;
+
+import com.google.gwt.user.client.Event;
+
+/**
+ * Opera version of HyperlinkImpl. As of Opera 9, the only modifier key
+ * that changes click behavior on links is shift.
+ */
+public class HyperlinkImplOpera extends HyperlinkImpl {
+  @Override
+  public boolean handleAsClick(Event event) {
+    int mouseButtons = event.getButton();
+    boolean shift = event.getShiftKey();
+    boolean middle = mouseButtons == Event.BUTTON_MIDDLE;
+    boolean right = mouseButtons == Event.BUTTON_RIGHT;
+
+    return !shift && !middle && !right;
+  }
+}

Property changes on: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImplOpera.java
___________________________________________________________________
Name: svn:mime-type
   + text/x-java
Name: svn:eol-style
   + native

Index: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImpl.java
===================================================================
--- user/src/com/google/gwt/user/client/ui/impl/HyperlinkImpl.java	(revision 0)
+++ user/src/com/google/gwt/user/client/ui/impl/HyperlinkImpl.java	(revision 0)
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2008 Google Inc.
+ * 
+ * Licensed 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.
+ */
+
+package com.google.gwt.user.client.ui.impl;
+
+import com.google.gwt.user.client.Event;
+
+/**
+ * Methods that need browser-specific implementations for Hyperlink.
+ * By default, we're very conservative and let the browser handle any clicks
+ * with non-left buttons or with modifier keys. This happens to be the correct
+ * behavior for Firefox.
+ */
+public class HyperlinkImpl {
+
+  /**
+   * Default version, useful for Firefox. Don't fire if it's a rightclick,
+   * middleclick, or if any modifiers are held down.
+   */
+  public boolean handleAsClick(Event event) {   
+    int mouseButtons = event.getButton();
+    boolean alt = event.getAltKey();
+    boolean ctrl = event.getCtrlKey();
+    boolean meta = event.getMetaKey();
+    boolean shift = event.getShiftKey();    
+    boolean modifiers = alt || ctrl || meta || shift;
+    boolean middle = mouseButtons == Event.BUTTON_MIDDLE;
+    boolean right = mouseButtons == Event.BUTTON_RIGHT;
+
+    return !modifiers && !middle && !right;
+  }
+}

Property changes on: user/src/com/google/gwt/user/client/ui/impl/HyperlinkImpl.java
___________________________________________________________________
Name: svn:mime-type
   + text/x-java
Name: svn:eol-style
   + native

Index: user/src/com/google/gwt/user/client/ui/Hyperlink.java
===================================================================
--- user/src/com/google/gwt/user/client/ui/Hyperlink.java	(revision 4214)
+++ user/src/com/google/gwt/user/client/ui/Hyperlink.java	(working copy)
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.user.client.ui;
 
+import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.HasClickHandlers;
@@ -23,6 +24,7 @@
 import com.google.gwt.user.client.Element;
 import com.google.gwt.user.client.Event;
 import com.google.gwt.user.client.History;
+import com.google.gwt.user.client.ui.impl.HyperlinkImpl;
 
 /**
  * A widget that serves as an "internal" hyperlink. That is, it is a link to
@@ -52,6 +54,8 @@
 public class Hyperlink extends Widget implements HasHTML, SourcesClickEvents,
     HasClickHandlers {
 
+  private static HyperlinkImpl impl = GWT.create(HyperlinkImpl.class);
+  
   private Element anchorElem;
   private String targetHistoryToken;
 
@@ -126,8 +130,11 @@
   public void onBrowserEvent(Event event) {
     if (DOM.eventGetType(event) == Event.ONCLICK) {
       super.onBrowserEvent(event);
-      History.newItem(targetHistoryToken);
-      DOM.eventPreventDefault(event);
+      
+      if (impl.handleAsClick(event)) {
+        History.newItem(getTargetHistoryToken());
+        DOM.eventPreventDefault(event);
+      }
     }
   }
 

Reply via email to