| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017 |
- /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
- * full list of contributors). Published under the Clear BSD license.
- * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
- * full text of the license. */
- /**
- * @requires OpenLayers/Renderer.js
- */
- /**
- * Class: OpenLayers.ElementsIndexer
- * This class takes care of figuring out which order elements should be
- * placed in the DOM based on given indexing methods.
- */
- OpenLayers.ElementsIndexer = OpenLayers.Class({
-
- /**
- * Property: maxZIndex
- * {Integer} This is the largest-most z-index value for a node
- * contained within the indexer.
- */
- maxZIndex: null,
-
- /**
- * Property: order
- * {Array<String>} This is an array of node id's stored in the
- * order that they should show up on screen. Id's higher up in the
- * array (higher array index) represent nodes with higher z-indeces.
- */
- order: null,
-
- /**
- * Property: indices
- * {Object} This is a hash that maps node ids to their z-index value
- * stored in the indexer. This is done to make finding a nodes z-index
- * value O(1).
- */
- indices: null,
-
- /**
- * Property: compare
- * {Function} This is the function used to determine placement of
- * of a new node within the indexer. If null, this defaults to to
- * the Z_ORDER_DRAWING_ORDER comparison method.
- */
- compare: null,
-
- /**
- * APIMethod: initialize
- * Create a new indexer with
- *
- * Parameters:
- * yOrdering - {Boolean} Whether to use y-ordering.
- */
- initialize: function(yOrdering) {
- this.compare = yOrdering ?
- OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER :
- OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;
- this.clear();
- },
-
- /**
- * APIMethod: insert
- * Insert a new node into the indexer. In order to find the correct
- * positioning for the node to be inserted, this method uses a binary
- * search. This makes inserting O(log(n)).
- *
- * Parameters:
- * newNode - {DOMElement} The new node to be inserted.
- *
- * Returns
- * {DOMElement} the node before which we should insert our newNode, or
- * null if newNode can just be appended.
- */
- insert: function(newNode) {
- // If the node is known to the indexer, remove it so we can
- // recalculate where it should go.
- if (this.exists(newNode)) {
- this.remove(newNode);
- }
-
- var nodeId = newNode.id;
-
- this.determineZIndex(newNode);
- var leftIndex = -1;
- var rightIndex = this.order.length;
- var middle;
- while (rightIndex - leftIndex > 1) {
- middle = parseInt((leftIndex + rightIndex) / 2);
-
- var placement = this.compare(this, newNode,
- OpenLayers.Util.getElement(this.order[middle]));
-
- if (placement > 0) {
- leftIndex = middle;
- } else {
- rightIndex = middle;
- }
- }
-
- this.order.splice(rightIndex, 0, nodeId);
- this.indices[nodeId] = this.getZIndex(newNode);
-
- // If the new node should be before another in the index
- // order, return the node before which we have to insert the new one;
- // else, return null to indicate that the new node can be appended.
- return this.getNextElement(rightIndex);
- },
-
- /**
- * APIMethod: remove
- *
- * Parameters:
- * node - {DOMElement} The node to be removed.
- */
- remove: function(node) {
- var nodeId = node.id;
- var arrayIndex = OpenLayers.Util.indexOf(this.order, nodeId);
- if (arrayIndex >= 0) {
- // Remove it from the order array, as well as deleting the node
- // from the indeces hash.
- this.order.splice(arrayIndex, 1);
- delete this.indices[nodeId];
-
- // Reset the maxium z-index based on the last item in the
- // order array.
- if (this.order.length > 0) {
- var lastId = this.order[this.order.length - 1];
- this.maxZIndex = this.indices[lastId];
- } else {
- this.maxZIndex = 0;
- }
- }
- },
-
- /**
- * APIMethod: clear
- */
- clear: function() {
- this.order = [];
- this.indices = {};
- this.maxZIndex = 0;
- },
-
- /**
- * APIMethod: exists
- *
- * Parameters:
- * node- {DOMElement} The node to test for existence.
- *
- * Returns:
- * {Boolean} Whether or not the node exists in the indexer?
- */
- exists: function(node) {
- return (this.indices[node.id] != null);
- },
- /**
- * APIMethod: getZIndex
- * Get the z-index value for the current node from the node data itself.
- *
- * Parameters:
- * node - {DOMElement} The node whose z-index to get.
- *
- * Returns:
- * {Integer} The z-index value for the specified node (from the node
- * data itself).
- */
- getZIndex: function(node) {
- return node._style.graphicZIndex;
- },
-
- /**
- * Method: determineZIndex
- * Determine the z-index for the current node if there isn't one,
- * and set the maximum value if we've found a new maximum.
- *
- * Parameters:
- * node - {DOMElement}
- */
- determineZIndex: function(node) {
- var zIndex = node._style.graphicZIndex;
-
- // Everything must have a zIndex. If none is specified,
- // this means the user *must* (hint: assumption) want this
- // node to succomb to drawing order. To enforce drawing order
- // over all indexing methods, we'll create a new z-index that's
- // greater than any currently in the indexer.
- if (zIndex == null) {
- zIndex = this.maxZIndex;
- node._style.graphicZIndex = zIndex;
- } else if (zIndex > this.maxZIndex) {
- this.maxZIndex = zIndex;
- }
- },
- /**
- * APIMethod: getNextElement
- * Get the next element in the order stack.
- *
- * Parameters:
- * index - {Integer} The index of the current node in this.order.
- *
- * Returns:
- * {DOMElement} the node following the index passed in, or
- * null.
- */
- getNextElement: function(index) {
- var nextIndex = index + 1;
- if (nextIndex < this.order.length) {
- var nextElement = OpenLayers.Util.getElement(this.order[nextIndex]);
- if (nextElement == undefined) {
- nextElement = this.getNextElement(nextIndex);
- }
- return nextElement;
- } else {
- return null;
- }
- },
-
- CLASS_NAME: "OpenLayers.ElementsIndexer"
- });
- /**
- * Namespace: OpenLayers.ElementsIndexer.IndexingMethods
- * These are the compare methods for figuring out where a new node should be
- * placed within the indexer. These methods are very similar to general
- * sorting methods in that they return -1, 0, and 1 to specify the
- * direction in which new nodes fall in the ordering.
- */
- OpenLayers.ElementsIndexer.IndexingMethods = {
-
- /**
- * Method: Z_ORDER
- * This compare method is used by other comparison methods.
- * It can be used individually for ordering, but is not recommended,
- * because it doesn't subscribe to drawing order.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER: function(indexer, newNode, nextNode) {
- var newZIndex = indexer.getZIndex(newNode);
- var returnVal = 0;
- if (nextNode) {
- var nextZIndex = indexer.getZIndex(nextNode);
- returnVal = newZIndex - nextZIndex;
- }
-
- return returnVal;
- },
- /**
- * APIMethod: Z_ORDER_DRAWING_ORDER
- * This method orders nodes by their z-index, but does so in a way
- * that, if there are other nodes with the same z-index, the newest
- * drawn will be the front most within that z-index. This is the
- * default indexing method.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER_DRAWING_ORDER: function(indexer, newNode, nextNode) {
- var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
- indexer,
- newNode,
- nextNode
- );
-
- // Make Z_ORDER subscribe to drawing order by pushing it above
- // all of the other nodes with the same z-index.
- if (nextNode && returnVal == 0) {
- returnVal = 1;
- }
-
- return returnVal;
- },
- /**
- * APIMethod: Z_ORDER_Y_ORDER
- * This one should really be called Z_ORDER_Y_ORDER_DRAWING_ORDER, as it
- * best describes which ordering methods have precedence (though, the
- * name would be too long). This method orders nodes by their z-index,
- * but does so in a way that, if there are other nodes with the same
- * z-index, the nodes with the lower y position will be "closer" than
- * those with a higher y position. If two nodes have the exact same y
- * position, however, then this method will revert to using drawing
- * order to decide placement.
- *
- * Parameters:
- * indexer - {<OpenLayers.ElementsIndexer>}
- * newNode - {DOMElement}
- * nextNode - {DOMElement}
- *
- * Returns:
- * {Integer}
- */
- Z_ORDER_Y_ORDER: function(indexer, newNode, nextNode) {
- var returnVal = OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(
- indexer,
- newNode,
- nextNode
- );
-
- if (nextNode && returnVal === 0) {
- var result = nextNode._boundsBottom - newNode._boundsBottom;
- returnVal = (result === 0) ? 1 : result;
- }
-
- return returnVal;
- }
- };
- /**
- * Class: OpenLayers.Renderer.Elements
- * This is another virtual class in that it should never be instantiated by
- * itself as a Renderer. It exists because there is *tons* of shared
- * functionality between different vector libraries which use nodes/elements
- * as a base for rendering vectors.
- *
- * The highlevel bits of code that are implemented here are the adding and
- * removing of geometries, which is essentially the same for any
- * element-based renderer. The details of creating each node and drawing the
- * paths are of course different, but the machinery is the same.
- *
- * Inherits:
- * - <OpenLayers.Renderer>
- */
- OpenLayers.Renderer.Elements = OpenLayers.Class(OpenLayers.Renderer, {
- /**
- * Property: rendererRoot
- * {DOMElement}
- */
- rendererRoot: null,
-
- /**
- * Property: root
- * {DOMElement}
- */
- root: null,
-
- /**
- * Property: vectorRoot
- * {DOMElement}
- */
- vectorRoot: null,
- /**
- * Property: textRoot
- * {DOMElement}
- */
- textRoot: null,
- /**
- * Property: xmlns
- * {String}
- */
- 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.
- */
- indexer: null,
-
- /**
- * Constant: BACKGROUND_ID_SUFFIX
- * {String}
- */
- BACKGROUND_ID_SUFFIX: "_background",
-
- /**
- * Constant: LABEL_ID_SUFFIX
- * {String}
- */
- LABEL_ID_SUFFIX: "_label",
-
- /**
- * Constructor: OpenLayers.Renderer.Elements
- *
- * Parameters:
- * containerID - {String}
- * options - {Object} options for this renderer. Supported options are:
- * * yOrdering - {Boolean} Whether to use y-ordering
- * * zIndexing - {Boolean} Whether to use z-indexing. Will be ignored
- * if yOrdering is set to true.
- */
- initialize: function(containerID, options) {
- OpenLayers.Renderer.prototype.initialize.apply(this, arguments);
- this.rendererRoot = this.createRenderRoot();
- this.root = this.createRoot("_root");
- this.vectorRoot = this.createRoot("_vroot");
- this.textRoot = this.createRoot("_troot");
-
- this.root.appendChild(this.vectorRoot);
- this.root.appendChild(this.textRoot);
-
- this.rendererRoot.appendChild(this.root);
- this.container.appendChild(this.rendererRoot);
-
- if(options && (options.zIndexing || options.yOrdering)) {
- this.indexer = new OpenLayers.ElementsIndexer(options.yOrdering);
- }
- },
-
- /**
- * Method: destroy
- */
- destroy: function() {
- this.clear();
- this.rendererRoot = null;
- this.root = null;
- this.xmlns = null;
- OpenLayers.Renderer.prototype.destroy.apply(this, arguments);
- },
-
- /**
- * Method: clear
- * Remove all the elements from the root
- */
- clear: function() {
- var child;
- var root = this.vectorRoot;
- if (root) {
- while (child = root.firstChild) {
- root.removeChild(child);
- }
- }
- root = this.textRoot;
- if (root) {
- while (child = root.firstChild) {
- root.removeChild(child);
- }
- }
- if (this.indexer) {
- this.indexer.clear();
- }
- },
- /**
- * Method: getNodeType
- * This function is in charge of asking the specific renderer which type
- * of node to create for the given geometry and style. All geometries
- * in an Elements-based renderer consist of one node and some
- * attributes. We have the nodeFactory() function which creates a node
- * for us, but it takes a 'type' as input, and that is precisely what
- * this function tells us.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {String} The corresponding node type for the specified geometry
- */
- getNodeType: function(geometry, style) { },
- /**
- * Method: drawGeometry
- * Draw the geometry, creating new nodes, setting paths, setting style,
- * setting featureId on the node. This method should only be called
- * by the renderer itself.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the geometry has been drawn completely; null if
- * incomplete; false otherwise
- */
- drawGeometry: function(geometry, style, featureId) {
- var className = geometry.CLASS_NAME;
- var rendered = true;
- if ((className == "OpenLayers.Geometry.Collection") ||
- (className == "OpenLayers.Geometry.MultiPoint") ||
- (className == "OpenLayers.Geometry.MultiLineString") ||
- (className == "OpenLayers.Geometry.MultiPolygon")) {
- for (var i = 0, len=geometry.components.length; i<len; i++) {
- rendered = this.drawGeometry(
- geometry.components[i], style, featureId) && rendered;
- }
- return rendered;
- };
- rendered = false;
- var removeBackground = false;
- if (style.display != "none") {
- if (style.backgroundGraphic) {
- this.redrawBackgroundNode(geometry.id, geometry, style,
- featureId);
- } else {
- removeBackground = true;
- }
- rendered = this.redrawNode(geometry.id, geometry, style,
- featureId);
- }
- if (rendered == false) {
- var node = document.getElementById(geometry.id);
- if (node) {
- if (node._style.backgroundGraphic) {
- removeBackground = true;
- }
- node.parentNode.removeChild(node);
- }
- }
- if (removeBackground) {
- var node = document.getElementById(
- geometry.id + this.BACKGROUND_ID_SUFFIX);
- if (node) {
- node.parentNode.removeChild(node);
- }
- }
- return rendered;
- },
-
- /**
- * Method: redrawNode
- *
- * Parameters:
- * id - {String}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the complete geometry could be drawn, null if parts of
- * the geometry could not be drawn, false otherwise
- */
- redrawNode: function(id, geometry, style, featureId) {
- style = this.applyDefaultSymbolizer(style);
- // Get the node if it's already on the map.
- var node = this.nodeFactory(id, this.getNodeType(geometry, style));
-
- // Set the data for the node, then draw it.
- node._featureId = featureId;
- node._boundsBottom = geometry.getBounds().bottom;
- node._geometryClass = geometry.CLASS_NAME;
- node._style = style;
- var drawResult = this.drawGeometryNode(node, geometry, style);
- if(drawResult === false) {
- return false;
- }
-
- node = drawResult.node;
-
- // 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.
- if (this.indexer) {
- var insert = this.indexer.insert(node);
- if (insert) {
- this.vectorRoot.insertBefore(node, insert);
- } else {
- this.vectorRoot.appendChild(node);
- }
- } else {
- // if there's no indexer, simply append the node to root,
- // but only if the node is a new one
- if (node.parentNode !== this.vectorRoot){
- this.vectorRoot.appendChild(node);
- }
- }
-
- this.postDraw(node);
-
- return drawResult.complete;
- },
-
- /**
- * Method: redrawBackgroundNode
- * Redraws the node using special 'background' style properties. Basically
- * just calls redrawNode(), but instead of directly using the
- * 'externalGraphic', 'graphicXOffset', 'graphicYOffset', and
- * 'graphicZIndex' properties directly from the specified 'style'
- * parameter, we create a new style object and set those properties
- * from the corresponding 'background'-prefixed properties from
- * specified 'style' parameter.
- *
- * Parameters:
- * id - {String}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- * featureId - {String}
- *
- * Returns:
- * {Boolean} true if the complete geometry could be drawn, null if parts of
- * the geometry could not be drawn, false otherwise
- */
- redrawBackgroundNode: function(id, geometry, style, featureId) {
- var backgroundStyle = OpenLayers.Util.extend({}, style);
-
- // Set regular style attributes to apply to the background styles.
- backgroundStyle.externalGraphic = backgroundStyle.backgroundGraphic;
- backgroundStyle.graphicXOffset = backgroundStyle.backgroundXOffset;
- backgroundStyle.graphicYOffset = backgroundStyle.backgroundYOffset;
- backgroundStyle.graphicZIndex = backgroundStyle.backgroundGraphicZIndex;
- backgroundStyle.graphicWidth = backgroundStyle.backgroundWidth || backgroundStyle.graphicWidth;
- backgroundStyle.graphicHeight = backgroundStyle.backgroundHeight || backgroundStyle.graphicHeight;
-
- // Erase background styles.
- backgroundStyle.backgroundGraphic = null;
- backgroundStyle.backgroundXOffset = null;
- backgroundStyle.backgroundYOffset = null;
- backgroundStyle.backgroundGraphicZIndex = null;
-
- return this.redrawNode(
- id + this.BACKGROUND_ID_SUFFIX,
- geometry,
- backgroundStyle,
- null
- );
- },
- /**
- * Method: drawGeometryNode
- * Given a node, draw a geometry on the specified layer.
- * node and geometry are required arguments, style is optional.
- * This method is only called by the render itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- * style - {Object}
- *
- * Returns:
- * {Object} a hash with properties "node" (the drawn node) and "complete"
- * (null if parts of the geometry could not be drawn, false if nothing
- * could be drawn)
- */
- drawGeometryNode: function(node, geometry, style) {
- style = style || node._style;
- var options = {
- 'isFilled': style.fill === undefined ?
- true :
- style.fill,
- 'isStroked': style.stroke === undefined ?
- !!style.strokeWidth :
- style.stroke
- };
- var drawn;
- switch (geometry.CLASS_NAME) {
- case "OpenLayers.Geometry.Point":
- if(style.graphic === false) {
- options.isFilled = false;
- options.isStroked = false;
- }
- drawn = this.drawPoint(node, geometry);
- break;
- case "OpenLayers.Geometry.LineString":
- options.isFilled = false;
- drawn = this.drawLineString(node, geometry);
- break;
- case "OpenLayers.Geometry.LinearRing":
- drawn = this.drawLinearRing(node, geometry);
- break;
- case "OpenLayers.Geometry.Polygon":
- drawn = this.drawPolygon(node, geometry);
- break;
- case "OpenLayers.Geometry.Surface":
- drawn = this.drawSurface(node, geometry);
- break;
- case "OpenLayers.Geometry.Rectangle":
- drawn = this.drawRectangle(node, geometry);
- break;
- default:
- break;
- }
- node._options = options;
- //set style
- //TBD simplify this
- if (drawn != false) {
- return {
- node: this.setStyle(node, style, options, geometry),
- complete: drawn
- };
- } else {
- return false;
- }
- },
-
- /**
- * Method: postDraw
- * Things that have do be done after the geometry node is appended
- * to its parent node. To be overridden by subclasses.
- *
- * Parameters:
- * node - {DOMElement}
- */
- postDraw: function(node) {},
-
- /**
- * Method: drawPoint
- * Virtual function for drawing Point Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the point
- */
- drawPoint: function(node, geometry) {},
- /**
- * Method: drawLineString
- * Virtual function for drawing LineString Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components of
- * the linestring, or false if nothing could be drawn
- */
- drawLineString: function(node, geometry) {},
- /**
- * Method: drawLinearRing
- * Virtual function for drawing LinearRing Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the linear ring, or false if nothing could be drawn
- */
- drawLinearRing: function(node, geometry) {},
- /**
- * Method: drawPolygon
- * Virtual function for drawing Polygon Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or null if the renderer could not draw all components
- * of the polygon, or false if nothing could be drawn
- */
- drawPolygon: function(node, geometry) {},
- /**
- * Method: drawRectangle
- * Virtual function for drawing Rectangle Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the rectangle
- */
- drawRectangle: function(node, geometry) {},
- /**
- * Method: drawCircle
- * Virtual function for drawing Circle Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the circle
- */
- drawCircle: function(node, geometry) {},
- /**
- * Method: drawSurface
- * Virtual function for drawing Surface Geometry.
- * Should be implemented by subclasses.
- * This method is only called by the renderer itself.
- *
- * Parameters:
- * node - {DOMElement}
- * geometry - {<OpenLayers.Geometry>}
- *
- * Returns:
- * {DOMElement} or false if the renderer could not draw the surface
- */
- drawSurface: function(node, geometry) {},
- /**
- * Method: removeText
- * Removes a label
- *
- * Parameters:
- * featureId - {String}
- */
- removeText: function(featureId) {
- var label = document.getElementById(featureId + this.LABEL_ID_SUFFIX);
- if (label) {
- this.textRoot.removeChild(label);
- }
- },
- /**
- * Method: getFeatureIdFromEvent
- *
- * Parameters:
- * evt - {Object} An <OpenLayers.Event> object
- *
- * Returns:
- * {<OpenLayers.Geometry>} A geometry from an event that
- * happened on a layer.
- */
- getFeatureIdFromEvent: function(evt) {
- var target = evt.target;
- var useElement = target && target.correspondingUseElement;
- var node = useElement ? useElement : (target || evt.srcElement);
- var featureId = node._featureId;
- return featureId;
- },
- /**
- * Method: eraseGeometry
- * Erase a geometry from the renderer. In the case of a multi-geometry,
- * we cycle through and recurse on ourselves. Otherwise, we look for a
- * node with the geometry.id, destroy its geometry, and remove it from
- * the DOM.
- *
- * Parameters:
- * geometry - {<OpenLayers.Geometry>}
- * featureId - {String}
- */
- eraseGeometry: function(geometry, featureId) {
- if ((geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPoint") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiLineString") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.MultiPolygon") ||
- (geometry.CLASS_NAME == "OpenLayers.Geometry.Collection")) {
- for (var i=0, len=geometry.components.length; i<len; i++) {
- this.eraseGeometry(geometry.components[i], featureId);
- }
- } else {
- var element = OpenLayers.Util.getElement(geometry.id);
- if (element && element.parentNode) {
- if (element.geometry) {
- element.geometry.destroy();
- element.geometry = null;
- }
- element.parentNode.removeChild(element);
- if (this.indexer) {
- this.indexer.remove(element);
- }
-
- if (element._style.backgroundGraphic) {
- var backgroundId = geometry.id + this.BACKGROUND_ID_SUFFIX;
- var bElem = OpenLayers.Util.getElement(backgroundId);
- if (bElem && bElem.parentNode) {
- // No need to destroy the geometry since the element and the background
- // node share the same geometry.
- bElem.parentNode.removeChild(bElem);
- }
- }
- }
- }
- },
- /**
- * Method: nodeFactory
- * Create new node of the specified type, with the (optional) specified id.
- *
- * If node already exists with same ID and a different type, we remove it
- * and then call ourselves again to recreate it.
- *
- * Parameters:
- * id - {String}
- * type - {String} type Kind of node to draw.
- *
- * Returns:
- * {DOMElement} A new node of the given type and id.
- */
- nodeFactory: function(id, type) {
- var node = OpenLayers.Util.getElement(id);
- if (node) {
- if (!this.nodeTypeCompare(node, type)) {
- node.parentNode.removeChild(node);
- node = this.nodeFactory(id, type);
- }
- } else {
- node = this.createNode(type, id);
- }
- return node;
- },
-
- /**
- * Method: nodeTypeCompare
- *
- * Parameters:
- * node - {DOMElement}
- * type - {String} Kind of node
- *
- * Returns:
- * {Boolean} Whether or not the specified node is of the specified type
- * This function must be overridden by subclasses.
- */
- nodeTypeCompare: function(node, type) {},
-
- /**
- * Method: createNode
- *
- * Parameters:
- * type - {String} Kind of node to draw.
- * id - {String} Id for node.
- *
- * Returns:
- * {DOMElement} A new node of the given type and id.
- * This function must be overridden by subclasses.
- */
- createNode: function(type, id) {},
- /**
- * Method: moveRoot
- * moves this renderer's root to a different renderer.
- *
- * Parameters:
- * renderer - {<OpenLayers.Renderer>} target renderer for the moved root
- */
- moveRoot: function(renderer) {
- var root = this.root;
- if(renderer.root.parentNode == this.rendererRoot) {
- root = renderer.root;
- }
- root.parentNode.removeChild(root);
- renderer.rendererRoot.appendChild(root);
- },
-
- /**
- * Method: getRenderLayerId
- * Gets the layer that this renderer's output appears on. If moveRoot was
- * used, this will be different from the id of the layer containing the
- * features rendered by this renderer.
- *
- * Returns:
- * {String} the id of the output layer.
- */
- getRenderLayerId: function() {
- return this.root.parentNode.parentNode.id;
- },
-
- /**
- * Method: isComplexSymbol
- * Determines if a symbol cannot be rendered using drawCircle
- *
- * Parameters:
- * graphicName - {String}
- *
- * Returns
- * {Boolean} true if the symbol is complex, false if not
- */
- isComplexSymbol: function(graphicName) {
- return (graphicName != "circle") && !!graphicName;
- },
- CLASS_NAME: "OpenLayers.Renderer.Elements"
- });
- /**
- * Constant: OpenLayers.Renderer.symbol
- * Coordinate arrays for well known (named) symbols.
- */
- OpenLayers.Renderer.symbol = {
- "star": [350,75, 379,161, 469,161, 397,215, 423,301, 350,250, 277,301,
- 303,215, 231,161, 321,161, 350,75],
- "cross": [4,0, 6,0, 6,4, 10,4, 10,6, 6,6, 6,10, 4,10, 4,6, 0,6, 0,4, 4,4,
- 4,0],
- "x": [0,0, 25,0, 50,35, 75,0, 100,0, 65,50, 100,100, 75,100, 50,65, 25,100, 0,100, 35,50, 0,0],
- "square": [0,0, 0,1, 1,1, 1,0, 0,0],
- "triangle": [0,10, 10,10, 5,0, 0,10]
- };
|