Index: trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java	(revision 1697)
+++ trunk/src/org/openstreetmap/josm/actions/AbstractInfoAction.java	(revision 1697)
@@ -0,0 +1,83 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.regex.Pattern;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.tools.OpenBrowser;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public abstract class AbstractInfoAction extends JosmAction {
+
+    public AbstractInfoAction() {
+        super();
+    }
+
+    public AbstractInfoAction(String name, String iconName, String tooltip, Shortcut shortcut, boolean register) {
+        super(name, iconName, tooltip, shortcut, register);
+    }
+
+    /**
+     * replies the base URL for browsing information about about a primitive
+     *
+     * @return the base URL, i.e. http://api.openstreetmap.org/browse
+     */
+    protected String getBaseURL() {
+        String baseUrl = Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api");
+        Pattern pattern = Pattern.compile("/api/?$");
+        String ret =  pattern.matcher(baseUrl).replaceAll("/browse");
+        if (ret.equals(baseUrl)) {
+            System.out.println(tr("WARNING: unexpected format of API base URL. Redirection to history page for OSM primitive will probably fail. API base URL is: ''{0}''",baseUrl));
+        }
+        return ret;
+    }
+
+    protected void launchBrowser() {
+        ArrayList<OsmPrimitive> primitivesToShow = new ArrayList<OsmPrimitive>(Main.ds.getSelected());
+
+        // filter out new primitives which are not yet uploaded to the server
+        //
+        Iterator<OsmPrimitive> it = primitivesToShow.iterator();
+        while(it.hasNext()) {
+            if (it.next().id == 0) {
+                it.remove();
+            }
+        }
+
+        if (primitivesToShow.isEmpty()) {
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("Please select at least one already uploaded node, way, or relation."),
+                    tr("Warning"),
+                    JOptionPane.WARNING_MESSAGE
+            );
+            return;
+        }
+
+        // don't launch more than 10 browser instances / browser windows
+        //
+        int max = Math.min(10, primitivesToShow.size());
+        if (max < primitivesToShow.size()) {
+            System.out.println(tr("WARNING: launching browser windows for the first {0} of {1} selected primitives only", 10, primitivesToShow.size()));
+        }
+        for(int i = 0; i < max; i++) {
+            OpenBrowser.displayUrl(
+                    createInfoUrl(primitivesToShow.get(i))
+            );
+        }
+    }
+
+    public void actionPerformed(ActionEvent e) {
+        launchBrowser();
+    }
+
+    protected abstract String createInfoUrl(OsmPrimitive primitive);
+}
Index: trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java	(revision 1696)
+++ trunk/src/org/openstreetmap/josm/actions/HistoryInfoAction.java	(revision 1697)
@@ -4,78 +4,22 @@
 import static org.openstreetmap.josm.tools.I18n.tr;
 
-import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
-import java.util.Collection;
-import java.util.LinkedList;
-import java.util.regex.Pattern;
 
-import javax.swing.JOptionPane;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
-import org.openstreetmap.josm.data.osm.Relation;
-import org.openstreetmap.josm.data.osm.Way;
-import org.openstreetmap.josm.data.osm.visitor.AbstractVisitor;
-import org.openstreetmap.josm.tools.OpenBrowser;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
 import org.openstreetmap.josm.tools.Shortcut;
 
-public class HistoryInfoAction extends JosmAction {
+public class HistoryInfoAction extends AbstractInfoAction {
 
     public HistoryInfoAction() {
         super(tr("History of Element"), "about",
-        tr("Display history information about OSM ways or nodes."),
-        Shortcut.registerShortcut("core:history",
-        tr("History of Element"), KeyEvent.VK_H, Shortcut.GROUP_HOTKEY), true);
+                tr("Display history information about OSM ways, nodes, or relations."),
+                Shortcut.registerShortcut("core:history",
+                        tr("History of Element"), KeyEvent.VK_H, Shortcut.GROUP_HOTKEY), true);
     }
 
-    /**
-     * replies the base URL for browsing the the history of an OSM primitive
-     *
-     * @return the base URL, i.e. http://api.openstreetmap.org/browse
-     */
-    protected String getBaseURL() {
-        String baseUrl = Main.pref.get("osm-server.url", "http://api.openstreetmap.org/api");
-        Pattern pattern = Pattern.compile("/api/?$");
-        String ret =  pattern.matcher(baseUrl).replaceAll("/browse");
-        if (ret.equals(baseUrl)) {
-            System.out.println("WARNING: unexpected format of API base URL. Redirection to history page for OSM primitive will probably fail. API base URL is: " + baseUrl);
-        }
-        return ret;
-    }
-
-    public void actionPerformed(ActionEvent e) {
-        final Collection<Object> sel = new LinkedList<Object>();
-        final String baseUrl  = getBaseURL();
-        new AbstractVisitor() {
-            public void visit(Node n) {
-                if(n.id <= 0) return;
-                OpenBrowser.displayUrl(baseUrl + "/node/" + n.id + "/history");
-                sel.add(n);
-            }
-
-            public void visit(Way w) {
-                if(w.id <= 0) return;
-                OpenBrowser.displayUrl(baseUrl + "/way/" + w.id + "/history");
-                sel.add(w);
-            }
-
-            public void visit(Relation e) {
-                if(e.id <= 0) return;
-                OpenBrowser.displayUrl(baseUrl + "/relation/" + e.id + "/history");
-                sel.add(e);
-            }
-
-            public void visitAll() {
-                for (OsmPrimitive osm : Main.ds.getSelected())
-                    osm.visit(this);
-            }
-        }.visitAll();
-
-        if (sel.isEmpty()) {
-            JOptionPane.showMessageDialog(Main.parent,
-            tr("Please select at least one node, way or relation. Only already uploaded elements have a history."));
-                return;
-        }
+    @Override
+    protected  String createInfoUrl(OsmPrimitive primitive) {
+        return getBaseURL() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.id + "/history";
     }
 }
Index: trunk/src/org/openstreetmap/josm/actions/InfoAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/InfoAction.java	(revision 1697)
+++ trunk/src/org/openstreetmap/josm/actions/InfoAction.java	(revision 1697)
@@ -0,0 +1,25 @@
+//License: GPL. Copyright 2007 by Immanuel Scholz and others
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.KeyEvent;
+
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public class InfoAction extends AbstractInfoAction {
+
+    public InfoAction() {
+        super(tr("Info about Element"), "about",
+                tr("Display object information about OSM nodes, ways, or relations."),
+                Shortcut.registerShortcut("core:information",
+                        tr("Info about Element"), KeyEvent.VK_I, Shortcut.GROUP_HOTKEY), true);
+    }
+
+    @Override
+    protected  String createInfoUrl(OsmPrimitive primitive) {
+        return getBaseURL() + "/" + OsmPrimitiveType.from(primitive).getAPIName() + "/" + primitive.id;
+    }
+}
