[OpenLayers-Dev] #1666 - One Single, Mother Of All Vector Layers

VR26A vinci.w.cat at gmail.com
Sat Nov 15 23:43:19 EST 2008


Hi All,

This may not be a good news: the demo page is broken because the trailing
comma found in the patched Openlayers.js and the demo html js
problem found in patch:
line 481:
+                         : null,
it should be
+                         : null

And there are problems on the element.addEventListener (line 588) in IE - IE
doesn't support the DOM Level 2 Event Model, the solution here is using the
OpenLayers.Event.observe (the OpenLayer wrapper of the Prototype.js Event
module)
line 588:
+        container.addEventListener(
it should be 
+        OpenLayers.Event.observe(container,

Then theOpenLayers.js should be fixed on the patch. For the demo page, you
need to remove the comma after the last element/property on the array and
the object.

However, after I fixed the js error, another serious problem come: the
object lost its position and width so the top layer is nothing here. Anybody
can help?

*I checked the debugger and seems IE ignore the width, height, top,
left....I wonder why

==================IE Partial Solution====================
Grouping Vector Features
========================

Author: Volker Grabsch


Index: tests/Layer/Vector.html
===================================================================
--- tests/Layer/Vector.html	(Revision 8115)
+++ tests/Layer/Vector.html	(Arbeitskopie)
@@ -343,43 +343,43 @@
                 graphicYOffset: -16
         });
                
-        var root = renderer.root;
         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.SVG') {
                 feature.style = customStyle1;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.getAttributeNS(null, 'width'),
+                var element = renderer.root.firstChild.firstChild;
+                t.eq(element.getAttributeNS(null, 'width'),
                              (2*customStyle1.pointRadius).toString(),
                              "given a pointRadius, width equals
2*pointRadius");
-                t.eq(root.firstChild.getAttributeNS(null, 'height'),
+                t.eq(element.getAttributeNS(null, 'height'),
                              (2*customStyle1.pointRadius).toString(),
                              "given a pointRadius, height equals
2*pointRadius");
                 feature.style = customStyle2;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.getAttributeNS(null, 'width'),
-                             root.firstChild.getAttributeNS(null,
'height'),
+                t.eq(element.getAttributeNS(null, 'width'),
+                             element.getAttributeNS(null, 'height'),
                              "given a graphicWidth, width equals height");
-                t.eq(root.firstChild.getAttributeNS(null, 'width'),
+                t.eq(element.getAttributeNS(null, 'width'),
                              customStyle2.graphicWidth.toString(),
                              "width is set correctly");
                 feature.style = customStyle3;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.getAttributeNS(null, 'height'),
-                             root.firstChild.getAttributeNS(null, 'width'),
+                t.eq(element.getAttributeNS(null, 'height'),
+                             element.getAttributeNS(null, 'width'),
                              "given a graphicHeight, height equals width");
-                t.eq(root.firstChild.getAttributeNS(null, 'height'),
+                t.eq(element.getAttributeNS(null, 'height'),
                              customStyle3.graphicHeight.toString(),
                              "height is set correctly");
                 feature.style = customStyle4;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.getAttributeNS(null, 'height'),
+                t.eq(element.getAttributeNS(null, 'height'),
                              customStyle4.graphicHeight.toString(),
                              "given graphicHeight and graphicWidth, both
are set: height");
-                t.eq(root.firstChild.getAttributeNS(null, 'width'),
+                t.eq(element.getAttributeNS(null, 'width'),
                              customStyle4.graphicWidth.toString(),
                              "given graphicHeight and graphicWidth, both
are set: width");
                 feature.style = customStyle5;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.getAttributeNS(null, 'style'),
+                t.eq(element.getAttributeNS(null, 'style'),
                              'opacity:
'+customStyle5.graphicOpacity.toString()+((OpenLayers.Util.getBrowserName()
== "opera" || OpenLayers.Util.getBrowserName() == "safari") ? "" : ';'),
                              "graphicOpacity correctly set");
                 feature.style = customStyle6;
@@ -393,56 +393,57 @@
                 // toFixed() returns a string
                 x = parseFloat(x);
                 y = parseFloat(y);
-                t.eq(root.firstChild.getAttributeNS(null, 'x'),
+                t.eq(element.getAttributeNS(null, 'x'),
                         (x +
customStyle6.graphicXOffset).toFixed().toString(),
                         "graphicXOffset correctly set");
-                t.eq(root.firstChild.getAttributeNS(null, 'y'),
+                t.eq(element.getAttributeNS(null, 'y'),
                         (-y +
customStyle6.graphicYOffset).toFixed().toString(),
                         "graphicYOffset correctly set");
         }
         if (layer.renderer.CLASS_NAME == 'OpenLayers.Renderer.VML') {
                 feature.style = customStyle1;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.style.width,
+                var element = renderer.root.firstChild.firstChild;
+                t.eq(element.style.width,
                              (2*customStyle1.pointRadius).toString()+'px',
                              "given a pointRadius, width equals
2*pointRadius");
-                t.eq(root.firstChild.style.height,
+                t.eq(element.style.height,
                              (2*customStyle1.pointRadius).toString()+'px',
                              "given a pointRadius, height equals
2*pointRadius");
                 feature.style = customStyle2;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.style.width,
-                             root.firstChild.style.height,
+                t.eq(element.style.width,
+                             element.style.height,
                              "given a graphicWidth, width equals height");
-                t.eq(root.firstChild.style.width,
+                t.eq(element.style.width,
                              customStyle2.graphicWidth.toString()+'px',
                              "width is set correctly");
                 feature.style = customStyle3;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.style.height,
-                             root.firstChild.style.width,
+                t.eq(element.style.height,
+                             element.style.width,
                              "given a graphicHeight, height equals width");
-                t.eq(root.firstChild.style.height,
+                t.eq(element.style.height,
                              customStyle3.graphicHeight.toString()+'px',
                              "height is set correctly");
                 feature.style = customStyle4;
                 layer.drawFeature(feature);
-                t.eq(root.firstChild.style.height,
+                t.eq(element.style.height,
                              customStyle4.graphicHeight.toString()+'px',
                              "given graphicHeight and graphicWidth, both
are set: height");
-                t.eq(root.firstChild.style.width,
+                t.eq(element.style.width,
                              customStyle4.graphicWidth.toString()+'px',
                              "given graphicHeight and graphicWidth, both
are set: width");
                 feature.style = customStyle5;
                 layer.renderer.clear();
                 layer.drawFeature(feature);
-                var fill =
root.firstChild.getElementsByTagName("v:fill")[0];
+                var fill = element.getElementsByTagName("v:fill")[0];
                 var opacity;
                 if(fill) {
                     opacity = fill.getAttribute('opacity');
                 }
                 if(opacity === undefined) {
-                    fill = root.firstChild.getElementsByTagName("fill")[0];
+                    fill = element.getElementsByTagName("fill")[0];
                     opacity = fill.getAttribute('opacity');
                 }
                 t.eq(opacity,
@@ -452,12 +453,12 @@
                 layer.drawFeature(feature);
                 var x = geometryX / renderer.getResolution();
                 var y = geometryY / renderer.getResolution();
-                t.eq(root.firstChild.style.left,
+                t.eq(element.style.left,
                             (x +
customStyle6.graphicXOffset).toFixed().toString()+'px',
                             "graphicXOffset correctly set");
                             
-                t.eq(root.firstChild.style.top,
-                            (y -
(customStyle6.graphicYOffset+parseInt(root.firstChild.style.height))).toFixed().toString()+'px',
+                t.eq(element.style.top,
+                            (y -
(customStyle6.graphicYOffset+parseInt(element.style.height))).toFixed().toString()+'px',
                             "graphicYOffset correctly set");
 
         }
Index: tests/Renderer/Elements.html
===================================================================
--- tests/Renderer/Elements.html	(Revision 8115)
+++ tests/Renderer/Elements.html	(Arbeitskopie)
@@ -22,6 +22,10 @@
             return root;
         };
         
+        OpenLayers.Renderer.Elements.prototype.createGroupContainer =
function(group) {
+            return document.createElement("div");
+        };
+        
         OpenLayers.Renderer.Elements.prototype._createNode =
             OpenLayers.Renderer.Elements.prototype.createNode;
         
@@ -66,7 +70,7 @@
         t.ok(r instanceof OpenLayers.Renderer.Elements, "new
OpenLayers.Renderer.Elements returns Elements object" );
         t.ok(r.rendererRoot != null, "elements rendererRoot is not null");
         t.ok(r.root != null, "elements root is not null");
-        t.ok(r.indexer == null, "indexer is null if unused.");
+        t.ok(r.groups["default"] == null, "default group is null");
         
         t.ok(r.root.parentNode == r.rendererRoot, "elements root is
correctly appended to rendererRoot");
         t.ok(r.rendererRoot.parentNode == r.container, "elements
rendererRoot is correctly appended to container");
@@ -146,10 +150,11 @@
             g_Node = node;
             return {node: node, complete: true};
         };
+        r._redrawBackgroundNode = r.redrawBackgroundNode;
         r.redrawBackgroundNode = function(id, geometry, style, featureId) {
-            b_Node = r.nodeFactory();
-            b_Node.id = "foo_background";
-            r.root.appendChild(b_Node);
+            var complete = r._redrawBackgroundNode(id, geometry, style,
featureId);
+            b_Node = g_Node;
+            return complete;
         };
 
         r.getNodeType = function(geometry, style) {
@@ -162,8 +167,8 @@
         var style = {'backgroundGraphic': 'foo'};
         var featureId = 'dude';
         r.drawGeometry(geometry, style, featureId);
-        t.ok(g_Node.parentNode == r.root, "node is correctly appended to
root");
-        t.ok(b_Node.parentNode == r.root, "redrawBackgroundNode appended
background node");
+        t.ok(g_Node.parentNode == r.root.firstChild, "node is correctly
appended to root");
+        t.ok(b_Node.parentNode == r.root.firstChild, "redrawBackgroundNode
appended background node");
         t.eq(g_Node._featureId, 'dude', "_featureId is correct");
         t.eq(g_Node._style.backgroundGraphic, "foo", "_style is correct");
         t.eq(g_Node._geometryClass, 'bar', "_geometryClass is correct");
@@ -178,8 +183,8 @@
         
         style = {'display':'none'};
         r.drawGeometry(geometry, style, featureId);
-        t.ok(g_Node.parentNode != r.root, "node is correctly removed");
-        t.ok(b_Node.parentNode != r.root, "background node correctly
removed")
+        t.ok(g_Node.parentNode != r.root.firstChild, "node is correctly
removed");
+        t.ok(b_Node.parentNode != r.root.firstChild, "background node
correctly removed")
         
         document.getElementById = _getElement;
             
@@ -340,6 +345,7 @@
         t.plan(15);
 
         var elements = {
+            'groups': {},
             'eraseGeometry': function(geometry) {
                 gErased.push(geometry);
             }
@@ -412,9 +418,13 @@
         // (no tests here, just make sure it doesn't bomb)      
       
       //valid element.parentNode, element.geometry
-        elements.indexer = {
-            'remove': function(elem) {
-                gIndexerRemoved = elem;
+        elements.groups = {
+            'default': {
+                'indexer': {
+                    'remove': function(elem) {
+                        gIndexerRemoved = elem;
+                    }
+                }
             }
         };
 
@@ -468,7 +478,7 @@
     }
 
     function test_Elements_drawAndErase(t) {
-        t.plan(20);
+        t.plan(18);
 
         setUp();
 
@@ -505,40 +515,38 @@
             return result;
         }
 
-        t.eq(r.root.childNodes.length, 1, "root is correctly filled");
-        t.eq(r.indexer.maxZIndex, 10, "indexer.maxZIndex is correctly
filled");
-        t.eq(r.indexer.order.length, 1, "indexer.order is correctly
filled");
-        t.eq(count(r.indexer.indices), 1, "indexer.indices is correctly
filled");
+        t.eq(r.root.firstChild.childNodes.length, 1, "default group is
correctly filled");
+        t.eq(r.groups["default"].indexer.maxZIndex, 10, "indexer.maxZIndex
is correctly filled");
+        t.eq(r.groups["default"].indexer.order.length, 1, "indexer.order is
correctly filled");
+        t.eq(count(r.groups["default"].indexer.indices), 1,
"indexer.indices is correctly filled");
 
         r.eraseGeometry(geometry);
 
-        t.eq(r.root.childNodes.length, 0, "root is correctly cleared");
-        t.eq(r.indexer.maxZIndex, 0, "indexer.maxZIndex is correctly
reset");
-        t.eq(r.indexer.order.length, 0, "indexer.order is correctly
reset");
-        t.eq(count(r.indexer.indices), 0, "indexer.indices is correctly
reset");
+        t.eq(r.root.firstChild.childNodes.length, 0, "default group is
correctly cleared");
+        t.eq(r.groups["default"].indexer.maxZIndex, 0, "indexer.maxZIndex
is correctly reset");
+        t.eq(r.groups["default"].indexer.order.length, 0, "indexer.order is
correctly reset");
+        t.eq(count(r.groups["default"].indexer.indices), 0,
"indexer.indices is correctly reset");
 
         delete(style.graphicZIndex);
         r.drawGeometry(geometry, style, featureId);
 
-        t.eq(r.root.childNodes.length, 1, "root is correctly filled");
-        t.eq(r.indexer.maxZIndex, 0, "indexer.maxZIndex is correctly
filled");
-        t.eq(r.indexer.order.length, 1, "indexer.order is correctly
filled");
-        t.eq(count(r.indexer.indices), 1, "indexer.indices is correctly
filled");
+        t.eq(r.root.firstChild.childNodes.length, 1, "default group is
correctly filled");
+        t.eq(r.groups["default"].indexer.maxZIndex, 0, "indexer.maxZIndex
is correctly filled");
+        t.eq(r.groups["default"].indexer.order.length, 1, "indexer.order is
correctly filled");
+        t.eq(count(r.groups["default"].indexer.indices), 1,
"indexer.indices is correctly filled");
 
         r.clear();
 
         t.eq(r.root.childNodes.length, 0, "root is correctly cleared");
-        t.eq(r.indexer.maxZIndex, 0, "indexer.maxZIndex is correctly
reset");
-        t.eq(r.indexer.order.length, 0, "indexer.order is correctly
reset");
-        t.eq(count(r.indexer.indices), 0, "indexer.indices is correctly
reset");
+        t.eq(r.groups["default"], null, "indexer is correctly removed");
 
         style.graphicZIndex = 12;
         r.drawGeometry(geometry, style, featureId);
 
-        t.eq(r.root.childNodes.length, 1, "root is correctly filled");
-        t.eq(r.indexer.maxZIndex, 12, "indexer.maxZIndex is correctly
filled");
-        t.eq(r.indexer.order.length, 1, "indexer.order is correctly
filled");
-        t.eq(count(r.indexer.indices), 1, "indexer.indices is correctly
filled");
+        t.eq(r.root.firstChild.childNodes.length, 1, "default group is
correctly filled");
+        t.eq(r.groups["default"].indexer.maxZIndex, 12, "indexer.maxZIndex
is correctly filled");
+        t.eq(r.groups["default"].indexer.order.length, 1, "indexer.order is
correctly filled");
+        t.eq(count(r.groups["default"].indexer.indices), 1,
"indexer.indices is correctly filled");
 
         tearDown();
     }
Index: doc/walkthru.html
===================================================================
--- doc/walkthru.html	(Revision 8115)
+++ doc/walkthru.html	(Arbeitskopie)
@@ -72,6 +72,7 @@
     <li> ../examples/vector-formats.html Serializing to other formats </li>
     <li> ../examples/select-feature.html Selecting features </li>
     <li> ../examples/select-feature-openpopup.html Attaching popups to
features </li>
+    <li> ../examples/vector-groups.html Grouping features </li>
 </ol>
 
 <h2>Editing Tools</h2>
Index: lib/OpenLayers/Renderer.js
===================================================================
--- lib/OpenLayers/Renderer.js	(Revision 8115)
+++ lib/OpenLayers/Renderer.js	(Arbeitskopie)
@@ -238,5 +238,24 @@
      */
     eraseGeometry: function(geometry) {},
 
+    /**
+     * Method: getGroupContainer
+     * Returns the container of a feature group.
+     * The group is created if it doesn't exist.
+     * virtual function.
+     * 
+     * Parameters:
+     * groupName - {String}
+     *
+     * Returns:
+     * {DOMElement}
+     */
+    getGroupContainer: function(group) {
+        // for renderers that don't support feature groups
+        // it's okay to return just the main container,
+        // i.e. everything is put into one big group.
+        return container;
+    },
+
     CLASS_NAME: "OpenLayers.Renderer"
-});
\ Kein Zeilenvorschub am Ende der Datei
+});
Index: lib/OpenLayers/Renderer/Elements.js
===================================================================
--- lib/OpenLayers/Renderer/Elements.js	(Revision 8115)
+++ lib/OpenLayers/Renderer/Elements.js	(Arbeitskopie)
@@ -344,12 +344,21 @@
     xmlns: null,
     
     /**
-     * Property: Indexer
-     * {<OpenLayers.ElementIndexer>} An instance of
OpenLayers.ElementsIndexer 
-     *     created upon initialization if the zIndexing or yOrdering
options
-     *     passed to this renderer's constructor are set to true.
+     * Property: groups
+     * {Object} A hash that maps each group name to an object containing:
+     *     * container - {DOMElement} the group's container DOM element.
+     *     * indexer - {<OpenLayers.ElementIndexer>} the group's indexer.
+     *         Will be null unless the zIndexing or yOrdering options
+     *         passed to this renderer's constructor are set to true.
      */
-    indexer: null, 
+    groups: null,
+
+    /**
+     * Property: options
+     * {Object} Options for this renderer. See {<OpenLayers.Renderer>} for
+     *     supported options.
+     */
+    options: null,
     
     /**
      * Constant: BACKGROUND_ID_SUFFIX
@@ -388,9 +397,8 @@
         this.rendererRoot.appendChild(this.root);
         this.container.appendChild(this.rendererRoot);
         
-        if(options && (options.zIndexing || options.yOrdering)) {
-            this.indexer = new
OpenLayers.ElementsIndexer(options.yOrdering);
-        }
+        this.options = options || {};
+        this.groups = {};
     },
     
     /**
@@ -417,9 +425,7 @@
                 this.root.removeChild(this.root.firstChild);
             }
         }
-        if (this.indexer) {
-            this.indexer.clear();
-        }
+        this.groups = {};
     },
 
     /** 
@@ -510,6 +516,7 @@
         
         // Set the data for the node, then draw it.
         node._featureId = featureId;
+        node.setAttribute("feature-id", featureId);
         node._geometry = geometry;
         node._geometryClass = geometry.CLASS_NAME;
         node._style = style;
@@ -521,16 +528,22 @@
          
         node = drawResult.node;
         
+        // Reveal the geometry's group container and index.
+        // Create them if necessary.
+        var groupName = geometry.groupName || "default";
+        this.getGroupContainer(groupName);
+        var group = this.groups[groupName];
+
         // Insert the node into the indexer so it can show us where to
         // place it. Note that this operation is O(log(n)). If there's a
         // performance problem (when dragging, for instance) this is
         // likely where it would be.
-        var insert = this.indexer ? this.indexer.insert(node) : null;
+        var insert = group.indexer ? group.indexer.insert(node) : null;
 
         if(insert) {
-            this.root.insertBefore(node, insert);
+            group.container.insertBefore(node, insert);
         } else {
-            this.root.appendChild(node);
+            group.container.appendChild(node);
         }
         
         this.postDraw(node);
@@ -800,6 +813,7 @@
                 this.eraseGeometry(geometry.components[i]);
             }
         } else {    
+            var group = this.groups[geometry.groupName || "default"];
             var element = OpenLayers.Util.getElement(geometry.id);
             if (element && element.parentNode) {
                 if (element.geometry) {
@@ -808,8 +822,8 @@
                 }
                 element.parentNode.removeChild(element);
 
-                if (this.indexer) {
-                    this.indexer.remove(element);
+                if (group && group.indexer) {
+                    group.indexer.remove(element);
                 }
                 
                 if (element._style.backgroundGraphic) {
@@ -892,6 +906,33 @@
         return (graphicName != "circle") && !!graphicName;
     },
 
+    /**
+     * Method: getGroupContainer
+     * Returns the container of a feature group.
+     * The group and its indexer are created if necessary.
+     * 
+     * Parameters:
+     * groupName - {String}
+     *
+     * Returns:
+     * {DOMElement}
+     */
+    getGroupContainer: function(groupName) {
+        var group = this.groups[groupName];
+        if (!group) {
+            // Create a new DOM element and indexer.
+            group = {
+                container: this.createGroupContainer(groupName),
+                indexer: (this.options.zIndexing || this.options.yOrdering)
+                         ? new
OpenLayers.ElementsIndexer(this.options.yOrdering)
+                         : null
+            };
+            this.root.appendChild(group.container);
+            this.groups[groupName] = group;
+        }
+        return group.container;
+    },
+
     CLASS_NAME: "OpenLayers.Renderer.Elements"
 });
 
Index: lib/OpenLayers/Renderer/VML.js
===================================================================
--- lib/OpenLayers/Renderer/VML.js	(Revision 8115)
+++ lib/OpenLayers/Renderer/VML.js	(Arbeitskopie)
@@ -588,12 +588,23 @@
      * Create the main root element
      *
      * Returns:
-     * {DOMElement} The main root element to which we'll add vectors
+     * {DOMElement} The main root element to which we'll add groups
      */
     createRoot: function() {
         return this.nodeFactory(this.container.id + "_root", "olv:group");
     },
     
+    /**
+     * Method: createGroupContainer
+     * 
+     * Returns:
+     * {DOMElement} A new group element to which we'll add vectors
+     */
+    createGroupContainer: function(group) {
+        var id = this.container.id + "_group_" + group;
+        return this.nodeFactory(id, "olv:group");
+    },
+
     /**************************************
      *                                    *
      *     GEOMETRY DRAWING FUNCTIONS     *
Index: lib/OpenLayers/Renderer/SVG.js
===================================================================
--- lib/OpenLayers/Renderer/SVG.js	(Revision 8115)
+++ lib/OpenLayers/Renderer/SVG.js	(Arbeitskopie)
@@ -414,13 +414,24 @@
      * Method: createRoot
      * 
      * Returns:
-     * {DOMElement} The main root element to which we'll add vectors
+     * {DOMElement} The main root element to which we'll add groups
      */
     createRoot: function() {
         return this.nodeFactory(this.container.id + "_root", "g");
     },
 
     /**
+     * Method: createGroupContainer
+     * 
+     * Returns:
+     * {DOMElement} A new group element to which we'll add vectors
+     */
+    createGroupContainer: function(group) {
+        var id = this.container.id + "_group_" + group;
+        return this.nodeFactory(id, "g");
+    },
+
+    /**
      * Method: createDefs
      *
      * Returns:
Index: lib/OpenLayers/Layer/Vector.js
===================================================================
--- lib/OpenLayers/Layer/Vector.js	(Revision 8115)
+++ lib/OpenLayers/Layer/Vector.js	(Arbeitskopie)
@@ -742,5 +742,58 @@
         return maxExtent;
     },
 
+    /**
+     * Method: toggleGroup
+     * Toggle the visibility of a feature group.
+     *
+     * Parameters:
+     * groupName - {String}
+     */
+    toggleGroup: function(groupName) {
+        var container = this.renderer.getGroupContainer(groupName);
+        if (container.style.visibility == "hidden") {
+            container.style.visibility = "visible";
+        } else {
+            container.style.visibility = "hidden";
+        }
+    },
+
+    /**
+     * Method: addGroupEventListener
+     * Registration an event listener for a feature group.
+     *
+     * Parameters:
+     * groupName - {String}
+     * type - {String}
+     * listener - {EventListener}
+     * useCapture - {Boolean}
+     */
+    addGroupEventListener: function(groupName, type, listener, useCapture)
{
+        var container = this.renderer.getGroupContainer(groupName);
+        var layer = this;
+        OpenLayers.Event.observe(container,
+            type,
+            function(evt) {
+                evt.feature = layer.getFeatureById(evt.target._featureId);
+                evt.groupName = groupName;
+                listener(evt);
+            },
+            useCapture);
+    },
+
+    /**
+     * Method: raiseGroupToTop
+     * Raise a feature group to the top.
+     *
+     * Parameters:
+     * groupName - {String}
+     */
+    raiseGroupToTop: function(groupName) {
+        var container = this.renderer.getGroupContainer(groupName);
+        var containerParent = container.parentNode;
+        containerParent.removeChild(container);
+        containerParent.appendChild(container);
+    },
+
     CLASS_NAME: "OpenLayers.Layer.Vector"
 });
Index: examples/vector-groups.html
===================================================================
--- examples/vector-groups.html	(Revision 0)
+++ examples/vector-groups.html	(Revision 0)
@@ -0,0 +1,227 @@
+<html xmlns="http://www.w3.org/1999/xhtml">
+  <head>
+    <link rel="stylesheet" href="../theme/default/style.css"
type="text/css" />
+    <link rel="stylesheet" href="style.css" type="text/css" />
+    <script src="../lib/OpenLayers.js" type="text/javascript"></script>
+    <script type="text/javascript">
+
+        var vectorLayer;
+
+        function clear_text(evt)
+        {
+            document.getElementById('status_text').textContent =
+                "";
+        }
+
+        function show_mouseover_text(evt)
+        {
+            document.getElementById('status_text').textContent =
+                "The mouse is over" +
+                " feature '" + evt.feature.id + "'" +
+                " of group '" + evt.groupName + "'.";
+        }
+
+        function show_click_text(evt)
+        {
+            document.getElementById('status_text').textContent =
+                "You're clicking on" +
+                " feature '" + evt.feature.id + "'" +
+                " of group '" + evt.groupName + "'.";
+        }
+
+        function init()
+        {
+            // map
+            var map = new OpenLayers.Map('map');
+
+            // styles
+            var style_blue = OpenLayers.Util.extend({
+                strokeColor: 'blue',
+                fillColor:   'blue',
+                fillOpacity: 0.2,
+                strokeWidth: 1
+            });
+            var style_green = OpenLayers.Util.extend({
+                strokeColor: 'green',
+                fillColor:   'green',
+                fillOpacity: 0.2,
+                strokeWidth: 1
+            });
+
+            // background layer
+            var backgroundLayer = new OpenLayers.Layer.WMS(
+                "OpenLayers WMS",
+                "http://labs.metacarta.com/wms/vmap0",
+                {layers: 'basic'});
+            map.addLayer(backgroundLayer);
+
+            // zoom map
+            map.zoomToMaxExtent();
+
+            // features for vector layer
+            var feature1 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(15, 22),
+                    new OpenLayers.Geometry.Point(15,  6),
+                    new OpenLayers.Geometry.Point(22, 10),
+                    new OpenLayers.Geometry.Point(22, 15),
+                    new OpenLayers.Geometry.Point(24, 15),
+                    new OpenLayers.Geometry.Point(23, 19),
+                    new OpenLayers.Geometry.Point(16, 23),
+                    new OpenLayers.Geometry.Point(15, 22)
+                ])
+            ]));
+            var feature2 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(15, 22),
+                    new OpenLayers.Geometry.Point(15,  6),
+                    new OpenLayers.Geometry.Point( 3, 11),
+                    new OpenLayers.Geometry.Point( 4, 19),
+                    new OpenLayers.Geometry.Point(15, 22)
+                ])
+            ]));
+            var feature3 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point( 74, 39),
+                    new OpenLayers.Geometry.Point( 91, 27),
+                    new OpenLayers.Geometry.Point(119, 47),
+                    new OpenLayers.Geometry.Point(104, 51),
+                    new OpenLayers.Geometry.Point( 87, 49),
+                    new OpenLayers.Geometry.Point( 74, 39)
+                ])
+            ]));
+            var feature4 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(104, 51),
+                    new OpenLayers.Geometry.Point( 87, 49),
+                    new OpenLayers.Geometry.Point( 74, 39),
+                    new OpenLayers.Geometry.Point( 75, 61),
+                    new OpenLayers.Geometry.Point(104, 51)
+                ])
+            ]));
+            var feature5 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point( 78, 45),
+                    new OpenLayers.Geometry.Point(105, 45),
+                    new OpenLayers.Geometry.Point(105, 65),
+                    new OpenLayers.Geometry.Point( 78, 65),
+                    new OpenLayers.Geometry.Point( 78, 45)
+                ])
+            ]));
+            var feature6 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(-3, 29),
+                    new OpenLayers.Geometry.Point(-3, 16),
+                    new OpenLayers.Geometry.Point(31, 16),
+                    new OpenLayers.Geometry.Point(31, 29),
+                    new OpenLayers.Geometry.Point(-3, 29)
+                ])
+            ]));
+            var feature7 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(-116, 55),
+                    new OpenLayers.Geometry.Point(-116, 39),
+                    new OpenLayers.Geometry.Point(-98 , 39),
+                    new OpenLayers.Geometry.Point(-98 , 55),
+                    new OpenLayers.Geometry.Point(-116, 55)
+                ])
+            ]));
+            var feature8 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(19, 47),
+                    new OpenLayers.Geometry.Point(63, 47),
+                    new OpenLayers.Geometry.Point(40, 65),
+                    new OpenLayers.Geometry.Point(19, 47)
+                ])
+            ]));
+            var feature9 = new OpenLayers.Feature.Vector(new
OpenLayers.Geometry.Polygon([
+                new OpenLayers.Geometry.LinearRing([
+                    new OpenLayers.Geometry.Point(-40, 78),
+                    new OpenLayers.Geometry.Point(-47, 70),
+                    new OpenLayers.Geometry.Point(-33, 70),
+                    new OpenLayers.Geometry.Point(-40, 78)
+                ])
+            ]));
+
+            // assign styles
+            feature5.style = style_blue;
+            feature6.style = style_blue;
+            feature7.style = style_blue;
+            feature8.style = style_green;
+            feature9.style = style_green;
+
+            // assign groups
+            feature1.geometry.groupName = 'default'; // not necessary
+            feature2.geometry.groupName = 'default'; // not necessary
+            feature3.geometry.groupName = 'default'; // not necessary
+            feature4.geometry.groupName = 'default'; // not necessary
+            feature5.geometry.groupName = 'blue';
+            feature6.geometry.groupName = 'blue';
+            feature7.geometry.groupName = 'blue';
+            feature8.geometry.groupName = 'green';
+            feature9.geometry.groupName = 'green';
+
+            // vector layer
+            vectorLayer = new OpenLayers.Layer.Vector();
+            vectorLayer.toggleGroup('green'); // disable group 'green' by
default
+            vectorLayer.addFeatures([
+                feature1, feature2, feature3, feature4,
+                feature5, feature6, feature7,
+                feature8, feature9
+            ]);
+            map.addLayer(vectorLayer);
+
+            // events on the vector layer
+            var groupNames = ['default', 'blue', 'green'];
+            for (i in groupNames) {
+                var groupName = groupNames[i];
+                vectorLayer.addGroupEventListener(groupName, 'mouseover',
show_mouseover_text, false);
+                vectorLayer.addGroupEventListener(groupName, 'mouseout', 
clear_text,          false);
+                vectorLayer.addGroupEventListener(groupName, 'mousedown',
show_click_text,     false);
+                vectorLayer.addGroupEventListener(groupName, 'mouseup',  
show_mouseover_text, false);
+            }
+        }
+    </script>
+  </head>
+  <body onload="init()">
+    <h1 id="title">Grouping Vector Features</h1>
+    <div id="tags">
+    </div>
+    <p id="shortdesc">
+        Shows how to group vector features into sub layers.
+    </p>
+    <div style="text-align: right">
+        <div id="map" class="smallmap"></div>
+    </div>
+    <div style="font-weight: bold; margin: 10pt 0pt 10pt 0pt">
+        <div style="margin-top: 5pt">
+            Toggle group:
+            <button
onclick="vectorLayer.toggleGroup('default')">default</button>
+            <button onclick="vectorLayer.toggleGroup('blue')">blue</button>
+            <button
onclick="vectorLayer.toggleGroup('green')">green</button>
+        </div>
+        <div style="margin-top: 5pt">
+            Raise to top:
+            <button
onclick="vectorLayer.raiseGroupToTop('default')">default</button>
+            <button
onclick="vectorLayer.raiseGroupToTop('blue')">blue</button>
+            <button
onclick="vectorLayer.raiseGroupToTop('green')">green</button>
+        </div>
+        <div style="margin-top: 5pt">
+            
+            &nbsp;
+        </div>
+    </div>
+    <div id="docs">
+        <p>This example shows the usage of the optional
+           "groupName" property of "features.geometry".
+           The feature data will be inserted into the appropriate
group.</p>
+        <p>Please inspect the vector layer DOM structure (eg. firebug).
+           Move the mouse over some features and click
+           to see the groups in action.</p>
+        <p>A group can be shown and hidden as a whole,
+           even before features are added.
+           Thus, you can disable a group by default,
+           which is here demonstrated with the "green" group.</p>
+    </div>
+  </body>
+</html>



Matthias Pohl wrote:
> 
> This is the first attempt to implement the "One Single, Mother Of All
> Vector Layers" approach as described in issue #1666. See a working
> example and details on the project page http://ol.m-click.ws
> 
> - the patch URL is http://ol.m-click.ws/grouping-vector-features.patch
> - the patch is tested with version 2.7 and trunk
> - it works fine in our application (no performance issues)
> - no BC breaks
> - of course needs testing (VML)
> - a new "sublayer" switch has to be added to the OL layerswitch control
> 
> Please review and comment.
> 
> Regards, matt
> _______________________________________________
> Dev mailing list
> Dev at openlayers.org
> http://openlayers.org/mailman/listinfo/dev
> 
> 

-- 
View this message in context: http://n2.nabble.com/-1666---One-Single%2C-Mother-Of-All-Vector-Layers-tp1340452p1504998.html
Sent from the OpenLayers Dev mailing list archive at Nabble.com.




More information about the Dev mailing list