OpenLayers OpenLayers

Ticket #1357: orderingforreview.patch

File orderingforreview.patch, 26.5 kB (added by tcoulter, 1 month ago)

Ordering patch slated for review.

  • tests/Renderer/Elements.html

    old new  
    33<script src="../../lib/OpenLayers.js"></script> 
    44  <script type="text/javascript"> 
    55 
    6     function test_Elements_constructor(t) { 
    7         t.plan(5); 
    8         var el = document.createElement('div'); 
    9         document.body.appendChild(el); 
    10         el.id = "foo"; 
    11          
     6    function setUp() { 
     7        // Stub out functions that are meant to be overridden by 
     8        // subclasses. 
    129        OpenLayers.Renderer.Elements.prototype._createRenderRoot = 
    1310            OpenLayers.Renderer.Elements.prototype.createRenderRoot; 
    1411         
     
    2522            return root; 
    2623        }; 
    2724         
    28         var r = new OpenLayers.Renderer.Elements("foo"); 
     25        OpenLayers.Renderer.Elements.prototype._createNode = 
     26            OpenLayers.Renderer.Elements.prototype.createNode; 
    2927         
    30         t.ok(r instanceof OpenLayers.Renderer.Elements, "new OpenLayers.Renderer.Elements returns Elements object" ); 
    31         t.ok(r.rendererRoot != null, "elements rendererRoot is not null"); 
    32         t.ok(r.root != null, "elements root is not null"); 
     28        OpenLayers.Renderer.Elements.prototype.createNode = function() { 
     29            return document.createElement("div"); 
     30        }; 
     31    } 
     32     
     33    // Create a new Elements renderer based on an id and an ordering 
     34    // type. For these tests, both of these parameters are optional. 
     35    function create_renderer(id, ordering) { 
    3336         
    34         t.ok(r.root.parentNode == rendererRoot, "elements root is correctly appended to rendererRoot"); 
    35         t.ok(r.rendererRoot.parentNode == el, "elements rendererRoot is correctly appended to container"); 
     37        rendererRoot = null; 
    3638         
     39        if (id == null) { 
     40            var el = document.createElement('div'); 
     41            document.body.appendChild(el); 
     42            el.id = OpenLayers.Util.createUniqueID(); 
     43            id = el.id; 
     44        } 
     45         
     46        return new OpenLayers.Renderer.Elements(id, ordering); 
     47    } 
     48     
     49    // Cleanup stubs made in the function above. 
     50    function tearDown() { 
    3751        OpenLayers.Renderer.Elements.prototype.createRenderRoot = 
    3852            OpenLayers.Renderer.Elements.prototype._createRenderRoot; 
    3953        OpenLayers.Renderer.Elements.prototype.createRoot = 
    4054            OpenLayers.Renderer.Elements.prototype._createRoot; 
     55        OpenLayers.Renderer.Elements.prototype.createNode = 
     56            OpenLayers.Renderer.Elements.prototype._createNode; 
    4157    } 
     58 
     59    function test_Elements_constructor(t) { 
     60        t.plan(6); 
     61         
     62        setUp(); 
     63         
     64        var r = create_renderer(); 
     65         
     66        t.ok(r instanceof OpenLayers.Renderer.Elements, "new OpenLayers.Renderer.Elements returns Elements object" ); 
     67        t.ok(r.rendererRoot != null, "elements rendererRoot is not null"); 
     68        t.ok(r.root != null, "elements root is not null"); 
     69        t.ok(r.indexer != null, "indexer is not null."); 
     70         
     71        t.ok(r.root.parentNode == r.rendererRoot, "elements root is correctly appended to rendererRoot"); 
     72        t.ok(r.rendererRoot.parentNode == r.container, "elements rendererRoot is correctly appended to container"); 
     73         
     74        tearDown(); 
     75    } 
    4276     
    4377    function test_Elements_destroy(t) { 
    44         t.plan(5); 
     78        t.plan(8); 
    4579         
    46         OpenLayers.Renderer.Elements.prototype._initialize = 
    47             OpenLayers.Renderer.Elements.prototype.initialize; 
    48          
    49         OpenLayers.Renderer.Elements.prototype.initialize = function() {} 
    50          
    5180        var g_Clear = false, g_Destroy = false; 
    5281         
    5382        OpenLayers.Renderer.prototype._destroy =  
     
    5786            g_Destroy = true; 
    5887        }; 
    5988         
     89        // Stub out SVG's nodeFactory 
     90        OpenLayers.Renderer.SVG.prototype.nodeFactory = function() { 
     91            return document.createElement("div"); 
     92        } 
     93         
    6094        var r = new OpenLayers.Renderer.SVG(document.body); 
     95         
    6196        r.clear = function() { 
    6297            g_Clear = true; 
    6398        }; 
    64         r.rendererRoot = 'foo'; 
    65         r.root = 'bar'; 
    66         r.xmlns = 'dude'; 
    6799         
     100        // Test assumptions. 
     101        t.ok(r.rendererRoot !== null, "rendererRoot not null"); 
     102        t.ok(r.rootnull !== "root not null"); 
     103        t.ok(r.xmlns !== "xmlns not null"); 
     104 
    68105        r.destroy(); 
    69106         
    70107        t.eq(g_Clear, true, "OpenLayers.Renderer.Elements.clear() called"); 
     
    73110        t.eq(r.xmlns, null, "xmlns nullified"); 
    74111        t.eq(g_Destroy, true, "OpenLayers.Renderer.destroy() called"); 
    75112         
    76         OpenLayers.Renderer.Elements.prototype.initialize = 
    77             OpenLayers.Renderer.Elements.prototype._initialize; 
    78113        OpenLayers.Renderer.prototype.destroy =  
    79114            OpenLayers.Renderer.prototype._destroy; 
    80115    } 
     
    82117    function test_Elements_clear(t) { 
    83118        t.plan(1); 
    84119         
    85         OpenLayers.Renderer.Elements.prototype._initialize = 
    86             OpenLayers.Renderer.Elements.prototype.initialize; 
     120        setUp(); 
    87121         
    88         OpenLayers.Renderer.Elements.prototype.initialize = function() {} 
    89          
    90         var r = new OpenLayers.Renderer.Elements(); 
     122        var r = create_renderer(); 
    91123        var element = document.createElement("div"); 
    92124        r.root = element; 
    93125         
     
    98130         
    99131        t.ok(r.root.childNodes.length == 0, "root is correctly cleared"); 
    100132         
    101         OpenLayers.Renderer.Elements.prototype.initialize = 
    102             OpenLayers.Renderer.Elements.prototype._initialize; 
     133        tearDown(); 
    103134    } 
    104135     
    105136    function test_Elements_drawGeometry(t) { 
    106137        t.plan(5); 
     138 
     139        setUp(); 
     140 
     141        var r = create_renderer(); 
    107142         
    108         OpenLayers.Renderer.Elements.prototype._initialize = 
    109             OpenLayers.Renderer.Elements.prototype.initialize; 
    110          
    111         OpenLayers.Renderer.Elements.prototype.initialize = function() {}; 
    112          
    113         var r = new OpenLayers.Renderer.Elements(); 
    114          
    115143        var element = document.createElement("div"); 
    116144        r.root = element; 
    117145 
     
    147175        var style = {'display':'none'}; 
    148176        r.drawGeometry(geometry, style, featureId); 
    149177        t.ok(g_Node.parentNode != r.root, "node is correctly removed"); 
    150         
    151         OpenLayers.Util.getElement = _getElement; 
    152         OpenLayers.Renderer.Elements.prototype.initialize = 
    153             OpenLayers.Renderer.Elements.prototype._initialize; 
     178             
     179        tearDown(); 
    154180    } 
    155181 
    156182    function test_Elements_drawGeometry_2(t) { 
    157183        t.plan(9); 
    158184         
    159         OpenLayers.Renderer.Elements.prototype._initialize = 
    160             OpenLayers.Renderer.Elements.prototype.initialize; 
    161              
    162         OpenLayers.Renderer.Elements.prototype.initialize = function() {}; 
    163  
    164         var r = new OpenLayers.Renderer.Elements(); 
     185        setUp(); 
    165186         
     187        var r = create_renderer(); 
     188         
    166189        var element = document.createElement("div"); 
    167190        r.root = element; 
    168191         
     
    281304        style = true; 
    282305        r.drawGeometry(geometry, style); 
    283306        t.ok(properDraw, "drawGeometry called drawPolygon when passed a multi-polygon"); 
    284          
    285         OpenLayers.Renderer.Elements.prototype.initialize = 
    286             OpenLayers.Renderer.Elements.prototype._initialize; 
     307       
     308        tearDown(); 
    287309    } 
    288310     
    289311    function test_Elements_getfeatureidfromevent(t) { 
     
    310332    function test_Elements_erasegeometry(t) { 
    311333        t.plan(5); 
    312334         
     335        setUp(); 
     336         
    313337        var el = document.createElement('div'); 
    314338        document.body.appendChild(el); 
    315339        el.id = 'bar'; 
    316340        var geometry = { 
    317             id: 'bar' 
     341            id: el.id 
    318342        }; 
    319343         
    320         OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 
     344        var r = create_renderer(el.id); 
     345         
     346        r.eraseGeometry(geometry); 
    321347        t.ok(el.parentNode != document.body, "element correctly removed"); 
    322348 
    323349        var el = document.createElement('div'); 
     
    330356            }] 
    331357        }; 
    332358 
    333         OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 
     359        r.eraseGeometry(geometry); 
    334360        t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipoint"); 
    335361         
    336362        var el = document.createElement('div'); 
     
    343369            }] 
    344370        }; 
    345371         
    346         OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 
     372        r.eraseGeometry(geometry); 
    347373        t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multilinestring"); 
    348374         
    349375        var el = document.createElement('div'); 
     
    356382            }] 
    357383        }; 
    358384         
    359         OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 
     385        r.eraseGeometry(geometry); 
    360386        t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipolygon"); 
    361387         
    362388        var el = document.createElement('div'); 
     
    369395            }] 
    370396        }; 
    371397         
    372         OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 
     398        r.eraseGeometry(geometry); 
    373399        t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a collection"); 
     400         
     401        tearDown(); 
    374402    }     
    375403 
    376404  </script> 
  • lib/OpenLayers/Renderer/Elements.js

    old new  
    55/** 
    66 * @requires OpenLayers/Renderer.js 
    77 */ 
     8/** 
     9 * Class: OpenLayers.ElementsIndexer 
     10 * This class takes care of figuring out which order elements should be 
     11 * placed in the DOM based on given indexing methods.  
     12 */ 
     13OpenLayers.ElementsIndexer = OpenLayers.Class({ 
     14    
     15    /** 
     16     * Property: maxZIndex 
     17     * {Integer} This is the largest-most z-index value for a node 
     18     * contained within the indexer. 
     19     */ 
     20    maxZIndex: null, 
     21     
     22    /** 
     23     * Property: order 
     24     * {Array<String>} This is an array of node id's stored in the 
     25     * order that they should show up on screen. Id's higher up in the 
     26     * array (higher array index) represent nodes with higher z-indeces. 
     27     */ 
     28    order: null,  
     29     
     30    /** 
     31     * Property: indices 
     32     * {Hash} This is a hash that maps node ids to their z-index value 
     33     * stored in the indexer. This is done to make finding a nodes z-index  
     34     * value O(1). 
     35     */ 
     36    indices: null, 
     37     
     38    /** 
     39     * Property: compare 
     40     * {Function} This is the function used to determine placement of 
     41     * of a new node within the indexer. If null, this defaults to to 
     42     * the Z_ORDER_DRAWING_ORDER comparison method. 
     43     */ 
     44    compare: null, 
     45    
     46    /** 
     47     * APIMethod: initialize 
     48     * Create a new indexer with  
     49     *  
     50     * Parameters: 
     51     * ordering - {Function} The canonical name of the indexing method to 
     52     * use. See OpenLayers.ElementsIndexer.Translations below. If null,  
     53     * this defaults to "z". 
     54     */ 
     55    initialize: function(ordering) { 
     56         
     57        var compareMethod = OpenLayers.ElementsIndexer.Translations[ordering]; 
     58         
     59        this.compare = compareMethod || OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER; 
     60        this.order = []; 
     61        this.indices = {}; 
     62        this.maxZIndex = 0; 
     63    }, 
     64     
     65    /** 
     66     * APIMethod: insert 
     67     * Insert a new node into the indexer. In order to find the correct positioning for 
     68     * the node to be inserted, this method uses a binary search. This makes inserting 
     69     * O(log(n)).  
     70     *  
     71     * Parameters: 
     72     * newNode - The new node to be inserted. 
     73     */ 
     74    insert: function(newNode) { 
     75        var nodeId = this.getNodeId(newNode); 
     76         
     77        this.determineZIndex(newNode);        
    878 
     79        var leftIndex = -1; 
     80        var rightIndex = this.order.length; 
     81        var middle; 
     82 
     83        while (rightIndex - leftIndex > 1) { 
     84            middle = parseInt((leftIndex + rightIndex) / 2); 
     85             
     86            var nextId = this.order[middle]; 
     87            var next = OpenLayers.Util.getElement(nextId); 
     88             
     89            var placement = this.compare(this, newNode, next); 
     90             
     91            if (placement > 0) { 
     92                leftIndex = middle; 
     93            } else { 
     94                rightIndex = middle; 
     95            }  
     96        } 
     97         
     98        this.order.splice(rightIndex, 0, nodeId); 
     99        this.indices[nodeId] = this.getZIndex(newNode); 
     100         
     101        // Return the next item in the array -- the id of the node that should 
     102        // follow this one directly in the index order -- if any. 
     103        var nextIndex = rightIndex + 1; 
     104         
     105        var returnVal = null; 
     106        if (nextIndex > 0 && nextIndex < this.order.length) { 
     107            returnVal = this.order[nextIndex]; 
     108        } 
     109        return returnVal; 
     110    }, 
     111     
     112    remove: function(node) { 
     113        var nodeId = this.getNodeId(node); 
     114        var arrayIndex = this.order.indexOf(nodeId); 
     115        if (arrayIndex >= 0) { 
     116            // Remove it from the order array, as well as deleting the node 
     117            // from the indeces hash. 
     118            this.order.splice(arrayIndex, 1); 
     119            delete this.indices[nodeId]; 
     120             
     121            // Reset the maxium z-index based on the last item in the order array. 
     122            var lastId = this.order[this.order.length - 1]; 
     123            this.maxZIndex = this.indices[lastId]; 
     124        } 
     125    }, 
     126     
     127    exists: function(node) { 
     128        var nodeId = this.getNodeId(node); 
     129        return this.indices[nodeId] != null;   
     130    }, 
     131     
     132    /** 
     133     * APIMethod: getZIndex 
     134     * Get the z-index value for the current node from the node data itself. 
     135     */ 
     136    getZIndex: function(node) { 
     137        return node._style.graphicZIndex;   
     138    }, 
     139 
     140    /** 
     141     * APIMethod: getMaxZIndex 
     142     * Get the maximum z-index stored within the indexer. 
     143     */ 
     144    getMaxZIndex: function() { 
     145        return this.maxZIndex; 
     146    }, 
     147     
     148    /** 
     149     * APIMethod: setZIndex 
     150     * Set the z-index for the given node. 
     151     */ 
     152    setZIndex: function(node, zIndex) { 
     153        node._style.graphicZIndex = zIndex;   
     154    }, 
     155     
     156    /** 
     157     * Method: determineZIndex 
     158     * Determine the z-index for the current node if there isn't one,  
     159     * and set the maximum value if we've found a new maximum. 
     160     */ 
     161    determineZIndex: function(node) { 
     162        var zIndex = node._style.graphicZIndex; 
     163         
     164        // Everything must have a zIndex. If none is specified, 
     165        // this means the user *must* (hint: assumption) want this 
     166        // node to succomb to drawing order. To enforce drawing order 
     167        // over all indexing methods, we'll create a new z-index that's 
     168        // greater than any currently in the indexer. 
     169        if (zIndex == null) { 
     170            zIndex = this.maxZIndex; 
     171        } 
     172         
     173        if (zIndex > this.maxZIndex) { 
     174            this.maxZIndex = zIndex; 
     175        } 
     176         
     177        node._style.graphicZIndex = zIndex; 
     178    }, 
     179     
     180    /** 
     181     * Method: getNodeId 
     182     * Get the id of the node passed in. 
     183     */ 
     184    getNodeId: function(node) { 
     185        return node.id;   
     186    }, 
     187    
     188    CLASS_NAME: "OpenLayers.ElementsIndexer" 
     189}); 
     190 
     191 
     192// These are the compare methods for figuring out where a new 
     193// node should be placed within the indexer. These methods are very  
     194// similar to general sorting methods in that they return -1, 0, and 1  
     195// to specify the direction in which new nodes fall in the ordering. 
     196OpenLayers.ElementsIndexer.IndexingMethods = { 
     197    /** 
     198     * Method: Z_ORDER 
     199     * This compare method is used by other comparison methods. 
     200     * It can be used individually for ordering, but is not recommended, 
     201     * because it doesn't subscribe to drawing order. 
     202     */     
     203    Z_ORDER: function(indexer, newNode, next) { 
     204        var newZIndex = indexer.getZIndex(newNode); 
     205 
     206        var returnVal = 0; 
     207        if (next) { 
     208            var nextZIndex = indexer.getZIndex(next); 
     209            returnVal = newZIndex - nextZIndex;  
     210        } 
     211         
     212        return returnVal; 
     213    }, 
     214    /** 
     215     * API Method: Z_ORDER_DRAWING_ORDER 
     216     * This method orders nodes by their z-index, but does so in a way 
     217     * that, if there are other nodes with the same z-index, the newest drawn 
     218     * will be the front most within that z-index. This is the default 
     219     * indexing method. 
     220     */ 
     221    Z_ORDER_DRAWING_ORDER: function(indexer, newNode, next) { 
     222        var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer, newNode, next); 
     223         
     224        // Make Z_ORDER subscribe to drawing order by pushing it above 
     225        // all of the other nodes with the same z-index. 
     226        if (next && returnVal == 0) { 
     227            returnVal = 1; 
     228        } 
     229         
     230        return returnVal; 
     231    }, 
     232    /** 
     233     * API Method: Z_ORDER_Y_ORDER 
     234     * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it 
     235     * best describes which ordering methods have precedence (though, the name would 
     236     * be too long). This method orders nodes by their z-index, but does so in a way 
     237     * that, if there are other nodes with the same z-index, the nodes with the 
     238     * lower y position will be "closer" than those with a higher y position.  
     239     * If two nodes have the exact same y position, however, then this method 
     240     * will revert to using drawing order to decide placement. 
     241     */ 
     242    Z_ORDER_Y_ORDER: function(indexer, newNode, next) { 
     243        var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer, newNode, next); 
     244         
     245        if (next && returnVal == 0) { 
     246            var newLat = newNode._geometry.getBounds().bottom; 
     247            var nextLat = next._geometry.getBounds().bottom; 
     248             
     249            var result = nextLat - newLat; 
     250             
     251            if (result == 0) { 
     252                returnVal = 1; 
     253            } else { 
     254                returnVal = result; 
     255            } 
     256        } 
     257         
     258        return returnVal;        
     259    } 
     260} 
     261 
    9262/** 
     263 * Translate canonical names for ordering methods to their  
     264 * function equivalents.  
     265 */ 
     266OpenLayers.ElementsIndexer.Translations = { 
     267    "z" : OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER, 
     268    "y" : OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER    
     269} 
     270 
     271 
     272/** 
    10273 * Class: OpenLayers.Renderer.Elements 
    11274 * This is another virtual class in that it should never be instantiated by  
    12275 *  itself as a Renderer. It exists because there is *tons* of shared  
     
    42305    xmlns: null, 
    43306     
    44307    /** 
     308     * Property: Indexer 
     309     * An instance of OpenLayers.ElementsIndexer created upon 
     310     * initialization. 
     311     */ 
     312    indexer: null,  
     313     
     314    BACKGROUND_ID_SUFFIX: "_background", 
     315     
     316    /** 
    45317     * Property: minimumSymbolizer 
    46318     * {Object} 
    47319     */ 
     
    57329     *  
    58330     * Parameters: 
    59331     * containerID - {String} 
     332     * ordering - {String} The cononical name for the ordering method 
     333     * used (such as "z"). See OpenLayers.ElementsIndexer.Translations above.  
    60334     */ 
    61     initialize: function(containerID) { 
     335    initialize: function(containerID, ordering) { 
    62336        OpenLayers.Renderer.prototype.initialize.apply(this, arguments); 
    63337 
    64338        this.rendererRoot = this.createRenderRoot(); 
     
    66340         
    67341        this.rendererRoot.appendChild(this.root); 
    68342        this.container.appendChild(this.rendererRoot); 
     343         
     344        this.indexer = new OpenLayers.ElementsIndexer(ordering); 
    69345    }, 
    70346     
    71347    /** 
     
    135411            return; 
    136412        }; 
    137413 
     414        var id = geometry.id; 
     415         
     416        if (style.backgroundGraphic) { 
     417            this.redrawBackgroundNode(id, geometry, style, featureId); 
     418        } 
     419         
    138420        if (style.display != "none") { 
    139             //first we create the basic node and add it to the root 
    140             var nodeType = this.getNodeType(geometry, style); 
    141             var node = this.nodeFactory(geometry.id, nodeType); 
    142             node._featureId = featureId; 
    143             node._geometryClass = geometry.CLASS_NAME; 
    144             node._style = style; 
    145              
    146             //now actually draw the node, and style it 
    147             node = this.drawGeometryNode(node, geometry); 
    148              
    149             // append the node to root (but only if it's new) 
    150             if (node.parentNode != this.root) {  
    151                 this.root.appendChild(node);  
    152             } 
    153             this.postDraw(node); 
     421            this.redrawNode(id, geometry, style, featureId);  
    154422        } else { 
    155             node = OpenLayers.Util.getElement(geometry.id); 
     423            node = OpenLayers.Util.getElement(id); 
    156424            if (node) { 
    157425                node.parentNode.removeChild(node); 
    158426            } 
    159427        } 
    160428    }, 
     429     
     430    redrawNode: function(id, geometry, style, featureId) { 
     431        // Get the node if it's already on the map. 
     432        var currentNode = OpenLayers.Util.getElement(id); 
     433         
     434        // Create a new node, or use the current one if it's 
     435        // already there. 
     436        var newNode; 
     437        if (!currentNode) { 
     438            var nodeType = this.getNodeType(geometry, style); 
     439            newNode = this.createNode(nodeType, id); 
     440        } else { 
     441            newNode = currentNode; 
     442        } 
     443         
     444        // Set the data for the node, then draw it. 
     445        newNode._featureId = featureId; 
     446        newNode._geometry = geometry; 
     447        newNode._geometryClass = geometry.CLASS_NAME; 
     448        newNode._style = style; 
     449        newNode = this.drawGeometryNode(newNode, geometry, style); 
     450         
     451        // If the node is known to the indexer, remove it so we can 
     452        // recalculate where it should go. 
     453        if (this.indexer.exists(newNode)) { 
     454            this.indexer.remove(newNode); 
     455        } 
     456         
     457        // Insert the node into the indexer so it can show us where to place it. 
     458        // Note that this operation is O(log(n)). If there's a performance problem 
     459        // (when dragging, for instance) this is likely where it would be. 
     460        var nextNodeId = this.indexer.insert(newNode); 
    161461 
     462        // If the new node should be before another in the index 
     463        // order, insert the new node before the next; else, lets just 
     464        // append the new one on the end, making it the highest in the index order. 
     465        if (nextNodeId) { 
     466            var nextNode = OpenLayers.Util.getElement(nextNodeId); 
     467            this.root.insertBefore(newNode, nextNode); 
     468        } else { 
     469            this.root.appendChild(newNode); 
     470        } 
     471         
     472        this.postDraw(newNode);  
     473    }, 
     474     
     475    redrawBackgroundNode: function(id, geometry, style, featureId) { 
     476        var backgroundStyle = OpenLayers.Util.extend({}, style); 
     477         
     478        // Set regular style attributes to apply to the background styles. 
     479        backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic; 
     480        backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset; 
     481        backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset; 
     482        backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex; 
     483         
     484        // Erase background styles. 
     485        backgroundStyle.backgroundGraphic = null; 
     486        backgroundStyle.backgroundXOffset = null; 
     487        backgroundStyle.backgroundYOffset = null; 
     488        backgroundStyle.backgroundGraphicZIndex = null; 
     489         
     490        this.redrawNode(id + this.BACKGROUND_ID_SUFFIX, geometry, backgroundStyle, null); 
     491    }, 
     492 
    162493    /** 
    163494     * Method: drawGeometryNode 
    164495     * Given a node, draw a geometry on the specified layer. 
     
    338669                this.eraseGeometry(geometry.components[i]); 
    339670            } 
    340671        } else {     
    341             var element = OpenLayers.Util.getElement(geometry.id); 
     672         
     673            // TODO: Functionalize the next two blocks. 
     674            var elementId = geometry.id; 
     675            var element = OpenLayers.Util.getElement(elementId); 
    342676            if (element && element.parentNode) { 
     677                if (element.geometry) { 
     678                    element.geometry.destroy(); 
     679                    element.geometry = null; 
     680                } 
    343681                element.parentNode.removeChild(element); 
     682                 
     683                this.indexer.remove(element); 
    344684            } 
     685             
     686            var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX; 
     687            var backgroundElement = OpenLayers.Util.getElement(backgroundId); 
     688            if (backgroundElement && backgroundElement.parentNode) { 
     689                if (backgroundElement.geometry) { 
     690                    backgroundElement.geometry.destroy(); 
     691                    backgroundElement.geometry = null; 
     692                } 
     693                backgroundElement.parentNode.removeChild(backgroundElement); 
     694                 
     695                this.indexer.remove(backgroundElement); 
     696            } 
    345697        } 
    346     },     
    347  
     698    }, 
     699     
    348700    /**  
    349701     * Method: nodeFactory 
    350702     * Create new node of the specified type, with the (optional) specified id. 
     
    371723        } 
    372724        return node; 
    373725    }, 
     726     
     727    /**  
     728     * Method: createNode 
     729     *  
     730     * Parameters: 
     731     * type - {String} Kind of node to draw 
     732     * id - {String} Id for node 
     733     *  
     734     * Returns: 
     735     * {DOMElement} A new node of the given type and id. 
     736     * This function must be overridden by subclasses. 
     737     */ 
     738    createNode: function(type, id) {}, 
    374739 
    375740    CLASS_NAME: "OpenLayers.Renderer.Elements" 
    376741}); 
  • lib/OpenLayers/Layer/Vector.js

    old new  
    140140     * {<OpenLayers.Renderer>} 
    141141     */ 
    142142    renderer: null, 
     143     
     144    /** 
     145     * APIProperty: ordering 
     146     * {String} The ordering method that the layer's renderer should use. 
     147     *  
     148     * Valid values are: 
     149     *      "z" - Use z-ordering. 
     150     *      "y" - Use y-ordering. 
     151     *  
     152     * This defaults to z-ordering if no ordering is specified. 
     153     */ 
     154    ordering: "z", 
    143155    
    144156    /**  
    145157     * APIProperty: geometryType 
     
    222234        for (var i = 0; i < this.renderers.length; i++) { 
    223235            var rendererClass = OpenLayers.Renderer[this.renderers[i]]; 
    224236            if (rendererClass && rendererClass.prototype.supported()) { 
    225                this.renderer = new rendererClass(this.div); 
    226                break; 
     237                this.renderer = new rendererClass(this.div, this.ordering); 
     238                break; 
    227239            }   
    228240        }   
    229241    },