Ticket #1357: ordering.4.patch
| File ordering.4.patch, 47.8 kB (added by tcoulter, 3 weeks ago) |
|---|
-
tests/Renderer/Elements.html
old new 3 3 <script src="../../lib/OpenLayers.js"></script> 4 4 <script type="text/javascript"> 5 5 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. 12 9 OpenLayers.Renderer.Elements.prototype._createRenderRoot = 13 10 OpenLayers.Renderer.Elements.prototype.createRenderRoot; 14 11 … … 25 22 return root; 26 23 }; 27 24 28 var r = new OpenLayers.Renderer.Elements("foo"); 25 OpenLayers.Renderer.Elements.prototype._createNode = 26 OpenLayers.Renderer.Elements.prototype.createNode; 29 27 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) { 33 36 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; 36 38 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() { 37 51 OpenLayers.Renderer.Elements.prototype.createRenderRoot = 38 52 OpenLayers.Renderer.Elements.prototype._createRenderRoot; 39 53 OpenLayers.Renderer.Elements.prototype.createRoot = 40 54 OpenLayers.Renderer.Elements.prototype._createRoot; 55 OpenLayers.Renderer.Elements.prototype.createNode = 56 OpenLayers.Renderer.Elements.prototype._createNode; 41 57 } 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 } 42 76 43 77 function test_Elements_destroy(t) { 44 78 t.plan(5); 45 79 46 OpenLayers.Renderer.Elements.prototype._initialize = 47 OpenLayers.Renderer.Elements.prototype.initialize; 48 49 OpenLayers.Renderer.Elements.prototype.initialize = function() {} 50 51 var g_Clear = false, g_Destroy = false; 52 80 var elems = { 81 'clear': function() { 82 t.ok(true, "clear called"); 83 }, 84 'rendererRoot': {}, 85 'root': {}, 86 'xmlns': {} 87 }; 88 53 89 OpenLayers.Renderer.prototype._destroy = 54 90 OpenLayers.Renderer.prototype.destroy; 55 91 92 var args = [{}, {}, {}]; 56 93 OpenLayers.Renderer.prototype.destroy = function() { 57 g_Destroy = true; 94 t.ok((arguments[0] == args[0]) && 95 (arguments[1] == args[1]) && 96 (arguments[2] == args[2]), "correct arguments passed to OpenLayers.Renderer.destroy()"); 58 97 }; 59 60 var r = new OpenLayers.Renderer.SVG(document.body); 61 r.clear = function() { 62 g_Clear = true; 63 }; 64 r.rendererRoot = 'foo'; 65 r.root = 'bar'; 66 r.xmlns = 'dude'; 67 68 r.destroy(); 69 70 t.eq(g_Clear, true, "OpenLayers.Renderer.Elements.clear() called"); 71 t.eq(r.rendererRoot, null, "rendererRoot nullified"); 72 t.eq(r.root, null, "root nullified"); 73 t.eq(r.xmlns, null, "xmlns nullified"); 74 t.eq(g_Destroy, true, "OpenLayers.Renderer.destroy() called"); 75 76 OpenLayers.Renderer.Elements.prototype.initialize = 77 OpenLayers.Renderer.Elements.prototype._initialize; 98 99 OpenLayers.Renderer.Elements.prototype.destroy.apply(elems, args); 100 101 t.ok(elems.rendererRoot == null, "rendererRoot nullified"); 102 t.ok(elems.root == null, "root nullified"); 103 t.ok(elems.xmlns == null, "xmlns nullified"); 104 78 105 OpenLayers.Renderer.prototype.destroy = 79 106 OpenLayers.Renderer.prototype._destroy; 107 80 108 } 81 109 82 110 function test_Elements_clear(t) { 83 111 t.plan(1); 84 112 85 OpenLayers.Renderer.Elements.prototype._initialize = 86 OpenLayers.Renderer.Elements.prototype.initialize; 113 setUp(); 87 114 88 OpenLayers.Renderer.Elements.prototype.initialize = function() {} 89 90 var r = new OpenLayers.Renderer.Elements(); 115 var r = create_renderer(); 91 116 var element = document.createElement("div"); 92 117 r.root = element; 93 118 … … 98 123 99 124 t.ok(r.root.childNodes.length == 0, "root is correctly cleared"); 100 125 101 OpenLayers.Renderer.Elements.prototype.initialize = 102 OpenLayers.Renderer.Elements.prototype._initialize; 126 tearDown(); 103 127 } 104 128 105 129 function test_Elements_drawGeometry(t) { 106 130 t.plan(5); 131 132 setUp(); 133 134 var r = create_renderer(); 107 135 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 115 136 var element = document.createElement("div"); 116 137 r.root = element; 117 138 … … 147 168 var style = {'display':'none'}; 148 169 r.drawGeometry(geometry, style, featureId); 149 170 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; 171 172 tearDown(); 154 173 } 155 174 156 175 function test_Elements_drawGeometry_2(t) { 157 176 t.plan(9); 158 177 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(); 178 setUp(); 165 179 180 var r = create_renderer(); 181 166 182 var element = document.createElement("div"); 167 183 r.root = element; 168 184 … … 281 297 style = true; 282 298 r.drawGeometry(geometry, style); 283 299 t.ok(properDraw, "drawGeometry called drawPolygon when passed a multi-polygon"); 284 285 OpenLayers.Renderer.Elements.prototype.initialize = 286 OpenLayers.Renderer.Elements.prototype._initialize; 300 301 tearDown(); 287 302 } 288 303 289 304 function test_Elements_getfeatureidfromevent(t) { … … 309 324 310 325 function test_Elements_erasegeometry(t) { 311 326 t.plan(5); 312 327 328 setUp(); 329 313 330 var el = document.createElement('div'); 314 331 document.body.appendChild(el); 315 332 el.id = 'bar'; 316 333 var geometry = { 317 334 id: 'bar' 318 335 }; 336 337 var r = create_renderer(el.id); 319 338 320 OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 321 t.ok(el.parentNode != document.body, "element correctly removed"); 339 r.eraseGeometry(geometry); 340 //t.ok(el.parentNode != document.body, "element correctly removed"); 341 t.ok(el.parentNode != document.body, "element correctry removed"); 322 342 323 var el = document.createElement('div'); 343 344 //multipoint 324 345 document.body.appendChild(el); 325 el.id = 'bar';326 346 var geometry = { 327 347 CLASS_NAME: "OpenLayers.Geometry.MultiPoint", 328 348 components: [{ 329 349 id: 'bar' 330 350 }] 331 351 }; 332 333 OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 352 r.eraseGeometry(geometry); 334 353 t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipoint"); 335 354 336 var el = document.createElement('div'); 355 356 //multilinestring 337 357 document.body.appendChild(el); 338 el.id = 'bar';339 358 var geometry = { 340 359 CLASS_NAME: "OpenLayers.Geometry.MultiLineString", 341 360 components: [{ 342 361 id: 'bar' 343 362 }] 344 363 }; 345 346 OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 364 r.eraseGeometry(geometry); 347 365 t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multilinestring"); 348 366 349 var el = document.createElement('div');367 //multipolygon 350 368 document.body.appendChild(el); 351 el.id = 'bar';352 369 var geometry = { 353 370 CLASS_NAME: "OpenLayers.Geometry.MultiPolygon", 354 371 components: [{ 355 372 id: 'bar' 356 373 }] 357 374 }; 358 359 OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 375 r.eraseGeometry(geometry); 360 376 t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a multipolygon"); 361 362 var el = document.createElement('div');377 378 //collection 363 379 document.body.appendChild(el); 364 el.id = 'bar';365 380 var geometry = { 366 381 CLASS_NAME: "OpenLayers.Geometry.Collection", 367 382 components: [{ 368 383 id: 'bar' 369 384 }] 370 385 }; 386 r.eraseGeometry(geometry); 387 t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a collection"); 371 388 372 OpenLayers.Renderer.Elements.prototype.eraseGeometry(geometry); 373 t.ok(el.parentNode != document.body, "geometry components correctly removed when passed a collection"); 389 tearDown(); 374 390 } 375 391 376 392 </script> -
lib/OpenLayers/Renderer/Elements.js
old new 7 7 */ 8 8 9 9 /** 10 * Class: OpenLayers.ElementsIndexer 11 * This class takes care of figuring out which order elements should be 12 * placed in the DOM based on given indexing methods. 13 */ 14 OpenLayers.ElementsIndexer = OpenLayers.Class({ 15 16 /** 17 * Property: maxZIndex 18 * {Integer} This is the largest-most z-index value for a node 19 * contained within the indexer. 20 */ 21 maxZIndex: null, 22 23 /** 24 * Property: order 25 * {Array<String>} This is an array of node id's stored in the 26 * order that they should show up on screen. Id's higher up in the 27 * array (higher array index) represent nodes with higher z-indeces. 28 */ 29 order: null, 30 31 /** 32 * Property: indices 33 * {Object} This is a hash that maps node ids to their z-index value 34 * stored in the indexer. This is done to make finding a nodes z-index 35 * value O(1). 36 */ 37 indices: null, 38 39 /** 40 * Property: compare 41 * {Function} This is the function used to determine placement of 42 * of a new node within the indexer. If null, this defaults to to 43 * the Z_ORDER_DRAWING_ORDER comparison method. 44 */ 45 compare: null, 46 47 /** 48 * APIMethod: initialize 49 * Create a new indexer with 50 * 51 * Parameters: 52 * yOrdering - {Boolean} Whether to use y-ordering. 53 */ 54 initialize: function(yOrdering) { 55 56 this.compare = yOrdering ? 57 OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER : 58 OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER; 59 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 68 * positioning for the node to be inserted, this method uses a binary 69 * search. This makes inserting O(log(n)). 70 * 71 * Parameters: 72 * newNode - {DOMElement} The new node to be inserted. 73 * root - {DOMElement} The root node from which to insert the new node. 74 */ 75 insert: function(newNode, root) { 76 var nodeId = newNode.id; 77 78 this.determineZIndex(newNode); 79 80 var leftIndex = -1; 81 var rightIndex = this.order.length; 82 var middle; 83 84 while (rightIndex - leftIndex > 1) { 85 middle = parseInt((leftIndex + rightIndex) / 2); 86 87 var nextId = this.order[middle]; 88 var nextNode = OpenLayers.Util.getElement(nextId); 89 90 var placement = this.compare(this, newNode, nextNode); 91 92 if (placement > 0) { 93 leftIndex = middle; 94 } else { 95 rightIndex = middle; 96 } 97 } 98 99 this.order.splice(rightIndex, 0, nodeId); 100 this.indices[nodeId] = this.getZIndex(newNode); 101 102 // If the new node should be before another in the index 103 // order, insert the new node before the next; else, lets just 104 // append the new one on the end, making it the highest in the index order. 105 var nextIndex = rightIndex + 1; 106 if (nextIndex < this.order.length) { 107 var nextNode = OpenLayers.Util.getElement(this.order[nextIndex]); 108 root.insertBefore(newNode, nextNode); 109 } else { 110 root.appendChild(newNode); 111 } 112 }, 113 114 /** 115 * APIMethod: remove 116 * 117 * Parameters: 118 * node - {DOMElement} The node to be removed. 119 */ 120 remove: function(node) { 121 var nodeId = node.id; 122 var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId); 123 if (arrayIndex >= 0) { 124 // Remove it from the order array, as well as deleting the node 125 // from the indeces hash. 126 this.order.splice(arrayIndex, 1); 127 delete this.indices[nodeId]; 128 129 // Reset the maxium z-index based on the last item in the 130 // order array. 131 var lastId = this.order[this.order.length - 1]; 132 this.maxZIndex = this.indices[lastId]; 133 } 134 }, 135 136 /** 137 * APIMethod: exists 138 * 139 * Parameters: 140 * node- {DOMElement} The node to test for existence. 141 * 142 * Returns: 143 * {Boolean} Whether or not the node exists in the indexer? 144 */ 145 exists: function(node) { 146 return (this.indices[node.id] != null); 147 }, 148 149 /** 150 * APIMethod: getZIndex 151 * Get the z-index value for the current node from the node data itself. 152 * 153 * Parameters: 154 * node - {DOMElement} The node whose z-index to get. 155 * 156 * Returns: 157 * {Integer} The z-index value for the specified node (from the node 158 * data itself). 159 */ 160 getZIndex: function(node) { 161 return node._style.graphicZIndex; 162 }, 163 164 /** 165 * Method: determineZIndex 166 * Determine the z-index for the current node if there isn't one, 167 * and set the maximum value if we've found a new maximum. 168 * 169 * Parameters: 170 * node - {DOMElement} 171 */ 172 determineZIndex: function(node) { 173 var zIndex = node._style.graphicZIndex; 174 175 // Everything must have a zIndex. If none is specified, 176 // this means the user *must* (hint: assumption) want this 177 // node to succomb to drawing order. To enforce drawing order 178 // over all indexing methods, we'll create a new z-index that's 179 // greater than any currently in the indexer. 180 if (zIndex == null) { 181 zIndex = this.maxZIndex; 182 node._style.graphicZIndex = zIndex; 183 } else if (zIndex > this.maxZIndex) { 184 this.maxZIndex = zIndex; 185 } 186 }, 187 188 CLASS_NAME: "OpenLayers.ElementsIndexer" 189 }); 190 191 /** 192 * Namespace: OpenLayers.ElementsIndexer.IndexingMethods 193 * These are the compare methods for figuring out where a new node should be 194 * placed within the indexer. These methods are very similar to general 195 * sorting methods in that they return -1, 0, and 1 to specify the 196 * direction in which new nodes fall in the ordering. 197 */ 198 OpenLayers.ElementsIndexer.IndexingMethods = { 199 200 /** 201 * Method: Z_ORDER 202 * This compare method is used by other comparison methods. 203 * It can be used individually for ordering, but is not recommended, 204 * because it doesn't subscribe to drawing order. 205 * 206 * Parameters: 207 * indexer - {<OpenLayers.ElementsIndexer>} 208 * newNode - {DOMElement} 209 * nextNode - {DOMElement} 210 * 211 * Returns: 212 * {Integer} 213 */ 214 Z_ORDER: function(indexer, newNode, nextNode) { 215 var newZIndex = indexer.getZIndex(newNode); 216 217 var returnVal = 0; 218 if (nextNode) { 219 var nextZIndex = indexer.getZIndex(nextNode); 220 returnVal = newZIndex - nextZIndex; 221 } 222 223 return returnVal; 224 }, 225 226 /** 227 * APIMethod: Z_ORDER_DRAWING_ORDER 228 * This method orders nodes by their z-index, but does so in a way 229 * that, if there are other nodes with the same z-index, the newest 230 * drawn will be the front most within that z-index. This is the 231 * default indexing method. 232 * 233 * Parameters: 234 * indexer - {<OpenLayers.ElementsIndexer>} 235 * newNode - {DOMElement} 236 * nextNode - {DOMElement} 237 * 238 * Returns: 239 * {Integer} 240 */ 241 Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) { 242 var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER( 243 indexer, 244 newNode, 245 nextNode 246 ); 247 248 // Make Z_ORDER subscribe to drawing order by pushing it above 249 // all of the other nodes with the same z-index. 250 if (nextNode && returnVal == 0) { 251 returnVal = 1; 252 } 253 254 return returnVal; 255 }, 256 257 /** 258 * APIMethod: Z_ORDER_Y_ORDER 259 * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it 260 * best describes which ordering methods have precedence (though, the 261 * name would be too long). This method orders nodes by their z-index, 262 * but does so in a way that, if there are other nodes with the same 263 * z-index, the nodes with the lower y position will be "closer" than 264 * those with a higher y position. If two nodes have the exact same y 265 * position, however, then this method will revert to using drawing 266 * order to decide placement. 267 * 268 * Parameters: 269 * indexer - {<OpenLayers.ElementsIndexer>} 270 * newNode - {DOMElement} 271 * nextNode - {DOMElement} 272 * 273 * Returns: 274 * {Integer} 275 */ 276 Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) { 277 var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER( 278 indexer, 279 newNode, 280 nextNode 281 ); 282 283 if (nextNode && returnVal == 0) { 284 var newLat = newNode._geometry.getBounds().bottom; 285 var nextLat = nextNode._geometry.getBounds().bottom; 286 287 var result = nextLat - newLat; 288 returnVal = (result ==0) ? 1 : result; 289 } 290 291 return returnVal; 292 } 293 }; 294 295 /** 10 296 * Class: OpenLayers.Renderer.Elements 11 297 * This is another virtual class in that it should never be instantiated by 12 298 * itself as a Renderer. It exists because there is *tons* of shared … … 42 328 xmlns: null, 43 329 44 330 /** 331 * Property: Indexer 332 * {<OpenLayers.ElementIndexer>} An instance of OpenLayers.ElementsIndexer 333 * created upon initialization. 334 */ 335 indexer: null, 336 337 /** 338 * Constant: BACKGROUND_ID_SUFFIX 339 * {String} 340 */ 341 BACKGROUND_ID_SUFFIX: "_background", 342 343 /** 45 344 * Property: minimumSymbolizer 46 345 * {Object} 47 346 */ … … 57 356 * 58 357 * Parameters: 59 358 * containerID - {String} 359 * yOrdering - {Boolean} Whether or not y-ordering is enabled. 60 360 */ 61 initialize: function(containerID ) {361 initialize: function(containerID, yOrdering) { 62 362 OpenLayers.Renderer.prototype.initialize.apply(this, arguments); 63 363 64 364 this.rendererRoot = this.createRenderRoot(); … … 66 366 67 367 this.rendererRoot.appendChild(this.root); 68 368 this.container.appendChild(this.rendererRoot); 369 370 this.indexer = new OpenLayers.ElementsIndexer(yOrdering); 69 371 }, 70 372 71 373 /** … … 135 437 return; 136 438 }; 137 439 440 // 441 if (style.backgroundGraphic) { 442 this.redrawBackgroundNode(geometry.id, geometry, style, featureId); 443 } 444 138 445 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); 446 this.redrawNode(geometry.id, geometry, style, featureId); 154 447 } else { 155 448 node = OpenLayers.Util.getElement(geometry.id); 156 449 if (node) { … … 158 451 } 159 452 } 160 453 }, 454 455 /** 456 * Method: redrawNode 457 * 458 * Parameters: 459 * id - {String} 460 * geometry - {<OpenLayers.Geometry>} 461 * style - {Object} 462 * featureId - {String} 463 */ 464 redrawNode: function(id, geometry, style, featureId) { 465 // Get the node if it's already on the map. 466 var currentNode = OpenLayers.Util.getElement(id); 467 468 // Create a new node, or use the current one if it's 469 // already there. 470 var newNode; 471 if (!currentNode) { 472 var nodeType = this.getNodeType(geometry, style); 473 newNode = this.createNode(nodeType, id); 474 } else { 475 newNode = currentNode; 476 } 477 478 // Set the data for the node, then draw it. 479 newNode._featureId = featureId; 480 newNode._geometry = geometry; 481 newNode._geometryClass = geometry.CLASS_NAME; 482 newNode._style = style; 483 newNode = this.drawGeometryNode(newNode, geometry, style); 484 485 // If the node is known to the indexer, remove it so we can 486 // recalculate where it should go. 487 if (this.indexer.exists(newNode)) { 488 this.indexer.remove(newNode); 489 } 490 491 // Insert the node into the indexer so it can show us where to place it. 492 // Note that this operation is O(log(n)). If there's a performance 493 // problem (when dragging, for instance) this is likely where it 494 // would be. 495 this.indexer.insert(newNode, this.root); 496 497 this.postDraw(newNode); 498 }, 499 500 /** 501 * Method: redrawBackgroundNode 502 * Redraws the node using special 'background' style properties. Basically 503 * just calls redrawNode(), but instead of directly using the 504 * 'externalGraphic', 'graphicXOffset', 'graphicYOffset', and 505 * 'graphicZIndex' properties directly from the specified 'style' 506 * parameter, we create a new style object and set those properties 507 * from the corresponding 'background'-prefixed properties from 508 * specified 'style' parameter. 509 * 510 * Parameters: 511 * id - {String} 512 * geometry - {<OpenLayers.Geometry>} 513 * style - {Object} 514 * featureId - {String} 515 */ 516 redrawBackgroundNode: function(id, geometry, style, featureId) { 517 var backgroundStyle = OpenLayers.Util.extend({}, style); 518 519 // Set regular style attributes to apply to the background styles. 520 backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic; 521 backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset; 522 backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset; 523 backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex; 524 525 // Erase background styles. 526 backgroundStyle.backgroundGraphic = null; 527 backgroundStyle.backgroundXOffset = null; 528 backgroundStyle.backgroundYOffset = null; 529 backgroundStyle.backgroundGraphicZIndex = null; 530 531 this.redrawNode( 532 id + this.BACKGROUND_ID_SUFFIX, 533 geometry, 534 backgroundStyle, 535 null 536 ); 537 }, 161 538 162 539 /** 163 540 * Method: drawGeometryNode … … 213 590 /** 214 591 * Method: postDraw 215 592 * Things that have do be done after the geometry node is appended 216 * to its parent node. To be overridden by subclasses.593 * to its parent node. To be overridden by subclasses. 217 594 * 218 595 * Parameters: 219 596 * node - {DOMElement} … … 223 600 /** 224 601 * Method: drawPoint 225 602 * Virtual function for drawing Point Geometry. 226 * Should be implemented by subclasses.227 * This method is only called by the renderer itself.603 * Should be implemented by subclasses. 604 * This method is only called by the renderer itself. 228 605 * 229 606 * Parameters: 230 607 * node - {DOMElement} … … 235 612 /** 236 613 * Method: drawLineString 237 614 * Virtual function for drawing LineString Geometry. 238 * Should be implemented by subclasses.239 * This method is only called by the renderer itself.615 * Should be implemented by subclasses. 616 * This method is only called by the renderer itself. 240 617 * 241 618 * Parameters: 242 619 * node - {DOMElement} … … 247 624 /** 248 625 * Method: drawLinearRing 249 626 * Virtual function for drawing LinearRing Geometry. 250 * Should be implemented by subclasses.251 * This method is only called by the renderer itself.627 * Should be implemented by subclasses. 628 * This method is only called by the renderer itself. 252 629 * 253 630 * Parameters: 254 631 * node - {DOMElement} … … 259 636 /** 260 637 * Method: drawPolygon 261 638 * Virtual function for drawing Polygon Geometry. 262 * Should be implemented by subclasses.263 * This method is only called by the renderer itself.639 * Should be implemented by subclasses. 640 * This method is only called by the renderer itself. 264 641 * 265 642 * Parameters: 266 643 * node - {DOMElement} … … 271 648 /** 272 649 * Method: drawRectangle 273 650 * Virtual function for drawing Rectangle Geometry. 274 * Should be implemented by subclasses.275 * This method is only called by the renderer itself.651 * Should be implemented by subclasses. 652 * This method is only called by the renderer itself. 276 653 * 277 654 * Parameters: 278 655 * node - {DOMElement} … … 283 660 /** 284 661 * Method: drawCircle 285 662 * Virtual function for drawing Circle Geometry. 286 * Should be implemented by subclasses.287 * This method is only called by the renderer itself.663 * Should be implemented by subclasses. 664 * This method is only called by the renderer itself. 288 665 * 289 666 * Parameters: 290 667 * node - {DOMElement} … … 295 672 /** 296 673 * Method: drawSurface 297 674 * Virtual function for drawing Surface Geometry. 298 * Should be implemented by subclasses.299 * This method is only called by the renderer itself.675 * Should be implemented by subclasses. 676 * This method is only called by the renderer itself. 300 677 * 301 678 * Parameters: 302 679 * node - {DOMElement} … … 312 689 * 313 690 * Returns: 314 691 * {<OpenLayers.Geometry>} A geometry from an event that 315 * happened on a layer692 * happened on a layer. 316 693 */ 317 694 getFeatureIdFromEvent: function(evt) { 318 695 var node = evt.target || evt.srcElement; … … 329 706 * Parameters: 330 707 * geometry - {<OpenLayers.Geometry>} 331 708 */ 332 eraseGeometry: function(geometry ) {709 eraseGeometry: function(geometry, isBackground) { 333 710 if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") || 334 711 (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") || 335 712 (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") || … … 340 717 } else { 341 718 var element = OpenLayers.Util.getElement(geometry.id); 342 719 if (element && element.parentNode) { 720 if (element.geometry) { 721 element.geometry.destroy(); 722 element.geometry = null; 723 } 343 724 element.parentNode.removeChild(element); 725 726 this.indexer.remove(element); 727 728 var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX; 729 var bElem = OpenLayers.Util.getElement(backgroundId); 730 if (bElem && bElem.parentNode) { 731 // No need to destroy the geometry since the element and the background 732 // node share the same geometry. 733 bElem.parentNode.removeChild(bElem); 734 } 344 735 } 345 736 } 346 737 }, … … 354 745 * 355 746 * Parameters: 356 747 * id - {String} 357 * type - {String} type Kind of node to draw 748 * type - {String} type Kind of node to draw. 358 749 * 359 750 * Returns: 360 * {DOMElement} A new node of the given type and id 751 * {DOMElement} A new node of the given type and id. 361 752 */ 362 753 nodeFactory: function(id, type) { 363 754 var node = OpenLayers.Util.getElement(id); … … 371 762 } 372 763 return node; 373 764 }, 765 766 /** 767 * Method: createNode 768 * 769 * Parameters: 770 * type - {String} Kind of node to draw. 771 * id - {String} Id for node. 772 * 773 * Returns: 774 * {DOMElement} A new node of the given type and id. 775 * This function must be overridden by subclasses. 776 */ 777 createNode: function(type, id) {}, 374 778 375 779 CLASS_NAME: "OpenLayers.Renderer.Elements" 376 780 }); -
lib/OpenLayers/Layer/Vector.js
old new 140 140 * {<OpenLayers.Renderer>} 141 141 */ 142 142 renderer: null, 143 144 /** 145 * APIProperty: yOrdering 146 * {String} Whether or not externalGraphic y-ordering is enabled on this 147 * layer. Default is false. 148 */ 149 yOrdering: false, 143 150 144 151 /** 145 152 * APIProperty: geometryType … … 222 229 for (var i=0, len=this.renderers.length; i<this.renderers.length; i++) { 223 230 var rendererClass = OpenLayers.Renderer[this.renderers[i]]; 224 231 if (rendererClass && rendererClass.prototype.supported()) { 225 this.renderer = new rendererClass(this.div);226 break;232 this.renderer = new rendererClass(this.div, this.yOrdering); 233 break; 227 234 } 228 235 } 229 236 }, … … 297 304 this.renderer.setExtent(extent); 298 305 299 306 this.renderer.root.style.visibility = "visible"; 300 307 301 308 // Force a reflow on gecko based browsers to prevent jump/flicker. 302 309 // This seems to happen on only certain configurations; it was originally 303 310 // noticed in FF 2.0 and Linux. -
examples/marker-shadow.html
old new 1 <html xmlns="http://www.w3.org/1999/xhtml"> 2 <head> 3 <link rel="stylesheet" href="../theme/default/style.css" type="text/css" /> 4 <link rel="stylesheet" href="style.css" type="text/css" /> 5 <style type="text/css"> 6 .smallmap { 7 width: 300px; 8 } 9 10 .docs { 11 padding: 0px 5px; 12 } 13 14 td { 15 vertical-align: top; 16 } 17 18 </style> 19 <script src="../lib/OpenLayers.js" type="text/javascript"></script> 20 <script type="text/javascript"> 21 22 var SHADOW_Z_INDEX = 10; 23 var MARKER_Z_INDEX = 11; 24 25 var DIAMETER = 200; 26 var NUMBER_OF_FEATURES = 15; 27 28 var map, layer; 29 30 function init() { 31 map = new OpenLayers.Map("map"); 32 33 layer = new OpenLayers.Layer.Vector( 34 "Marker Drop Shadows", 35 { 36 styleMap: new OpenLayers.StyleMap({ 37 // Set the external graphic and background graphic images. 38 externalGraphic: "../img/marker-gold.png", 39 backgroundGraphic: "./marker_shadow.png", 40 41 // Makes sure the background graphic is placed correctly relative 42
