/** * @requires OpenLayers/BaseTypes/Class.js * @requires OpenLayers/Util.js * @requires OpenLayers/Control.js * @requires OpenLayers/Format.js * @requires OpenLayers/Request.js * @requires OpenLayers/Layer/WMS.js * @requires OpenLayers/Layer/MapServer.js * @requires OpenLayers/Tile.js * @requires OpenLayers/Request/XMLHttpRequest.js * @requires OpenLayers/Layer/Vector.js * @requires OpenLayers/Layer/Markers.js * @requires OpenLayers/Console.js * @requires OpenLayers/Lang.js * @requires OpenLayers/Feature.js * @requires OpenLayers/Layer/EventPane.js * @requires OpenLayers/Layer/FixedZoomLevels.js * @requires OpenLayers/Layer/SphericalMercator.js * @requires OpenLayers/Protocol.js * @requires OpenLayers/Format/JSON.js * @requires OpenLayers/Format/WKT.js * @requires OpenLayers/Format/XML.js * @requires OpenLayers/Geometry.js * @requires OpenLayers/Renderer/Elements.js * @requires OpenLayers/Popup/Anchored.js * @requires Rico/Corner.js */ /** * About: Deprecated * The deprecated.js script includes all methods, properties, and constructors * that are not supported as part of the long-term API. If you use any of * these, you have to explicitly include this script in your application. * * For example: * (code) * * (end) * * You are strongly encouraged to avoid using deprecated functionality. The * documentation here should point you to the supported alternatives. */ /** * Namespace: OpenLayers.Class */ /** * Property: isPrototype * *Deprecated*. This is no longer needed and will be removed at 3.0. */ OpenLayers.Class.isPrototype = function () {}; /** * APIFunction: OpenLayers.create * *Deprecated*. Old method to create an OpenLayers style class. Use the * constructor instead. * * Returns: * An OpenLayers class */ OpenLayers.Class.create = function() { return function() { if (arguments && arguments[0] != OpenLayers.Class.isPrototype) { this.initialize.apply(this, arguments); } }; }; /** * APIFunction: inherit * *Deprecated*. Old method to inherit from one or more OpenLayers style * classes. Use the constructor instead. * * Parameters: * class - One or more classes can be provided as arguments * * Returns: * An object prototype */ OpenLayers.Class.inherit = function (P) { var C = function() { P.call(this); }; var newArgs = [C].concat(Array.prototype.slice.call(arguments)); OpenLayers.inherit.apply(null, newArgs); return C.prototype; }; /** * Namespace: OpenLayers.Util */ /** * Function: clearArray * *Deprecated*. This function will disappear in 3.0. * Please use "array.length = 0" instead. * * Parameters: * array - {Array} */ OpenLayers.Util.clearArray = function(array) { OpenLayers.Console.warn( OpenLayers.i18n( "methodDeprecated", {'newMethod': 'array = []'} ) ); array.length = 0; }; /** * Function: setOpacity * *Deprecated*. This function has been deprecated. Instead, please use * * or * * * Set the opacity of a DOM Element * Note that for this function to work in IE, elements must "have layout" * according to: * http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/haslayout.asp * * Parameters: * element - {DOMElement} Set the opacity on this DOM element * opacity - {Float} Opacity value (0.0 - 1.0) */ OpenLayers.Util.setOpacity = function(element, opacity) { OpenLayers.Util.modifyDOMElement(element, null, null, null, null, null, null, opacity); }; /** * Function: safeStopPropagation * *Deprecated*. This function has been deprecated. Please use directly * passing 'true' as the 2nd * argument (preventDefault) * * Safely stop the propagation of an event *without* preventing * the default browser action from occurring. * * Parameters: * evt - {Event} */ OpenLayers.Util.safeStopPropagation = function(evt) { OpenLayers.Event.stop(evt, true); }; /** * Function: getArgs * *Deprecated*. Will be removed in 3.0. Please use instead * * * Parameters: * url - {String} Optional url used to extract the query string. * If null, query string is taken from page location. * * Returns: * {Object} An object of key/value pairs from the query string. */ OpenLayers.Util.getArgs = function(url) { OpenLayers.Console.warn( OpenLayers.i18n( "methodDeprecated", {'newMethod': 'OpenLayers.Util.getParameters'} ) ); return OpenLayers.Util.getParameters(url); }; /** * Maintain existing definition of $. * * The use of our $-method is deprecated and the mapping of * OpenLayers.Util.getElement will eventually be removed. Do not depend on * window.$ being defined by OpenLayers. */ if(typeof window.$ === "undefined") { window.$ = OpenLayers.Util.getElement; } /** * Namespace: OpenLayers.Ajax */ /** * Function: OpenLayers.nullHandler * @param {} request */ OpenLayers.nullHandler = function(request) { OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText})); }; /** * APIFunction: OpenLayers.loadURL * Background load a document. * *Deprecated*. Use method instead. * * Parameters: * uri - {String} URI of source doc * params - {String} or {Object} GET params. Either a string in the form * "?hello=world&foo=bar" (do not forget the leading question mark) * or an object in the form {'hello': 'world', 'foo': 'bar} * caller - {Object} object which gets callbacks * onComplete - {Function} Optional callback for success. The callback * will be called with this set to caller and will receive the request * object as an argument. Note that if you do not specify an onComplete * function, will be called (which pops up a * user friendly error message dialog). * onFailure - {Function} Optional callback for failure. In the event of * a failure, the callback will be called with this set to caller and will * receive the request object as an argument. Note that if you do not * specify an onComplete function, will be called * (which pops up a user friendly error message dialog). * * Returns: * {} The request object. To abort loading, * call request.abort(). */ OpenLayers.loadURL = function(uri, params, caller, onComplete, onFailure) { if(typeof params == 'string') { params = OpenLayers.Util.getParameters(params); } var success = (onComplete) ? onComplete : OpenLayers.nullHandler; var failure = (onFailure) ? onFailure : OpenLayers.nullHandler; return OpenLayers.Request.GET({ url: uri, params: params, success: success, failure: failure, scope: caller }); }; /** * Function: OpenLayers.parseXMLString * Parse XML into a doc structure * * Parameters: * text - {String} * * Returns: * {?} Parsed AJAX Responsev */ OpenLayers.parseXMLString = function(text) { //MS sucks, if the server is bad it dies var index = text.indexOf('<'); if (index > 0) { text = text.substring(index); } var ajaxResponse = OpenLayers.Util.Try( function() { var xmldom = new ActiveXObject('Microsoft.XMLDOM'); xmldom.loadXML(text); return xmldom; }, function() { return new DOMParser().parseFromString(text, 'text/xml'); }, function() { var req = new XMLHttpRequest(); req.open("GET", "data:" + "text/xml" + ";charset=utf-8," + encodeURIComponent(text), false); if (req.overrideMimeType) { req.overrideMimeType("text/xml"); } req.send(null); return req.responseXML; } ); return ajaxResponse; }; OpenLayers.Ajax = { /** * Method: emptyFunction */ emptyFunction: function () {}, /** * Method: getTransport * * Returns: * {Object} Transport mechanism for whichever browser we're in, or false if * none available. */ getTransport: function() { return OpenLayers.Util.Try( function() {return new XMLHttpRequest();}, function() {return new ActiveXObject('Msxml2.XMLHTTP');}, function() {return new ActiveXObject('Microsoft.XMLHTTP');} ) || false; }, /** * Property: activeRequestCount * {Integer} */ activeRequestCount: 0 }; /** * Namespace: OpenLayers.Ajax.Responders * {Object} */ OpenLayers.Ajax.Responders = { /** * Property: responders * {Array} */ responders: [], /** * Method: register * * Parameters: * responderToAdd - {?} */ register: function(responderToAdd) { for (var i = 0; i < this.responders.length; i++){ if (responderToAdd == this.responders[i]){ return; } } this.responders.push(responderToAdd); }, /** * Method: unregister * * Parameters: * responderToRemove - {?} */ unregister: function(responderToRemove) { OpenLayers.Util.removeItem(this.reponders, responderToRemove); }, /** * Method: dispatch * * Parameters: * callback - {?} * request - {?} * transport - {?} */ dispatch: function(callback, request, transport) { var responder; for (var i = 0; i < this.responders.length; i++) { responder = this.responders[i]; if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport]); } catch (e) {} } } } }; OpenLayers.Ajax.Responders.register({ /** * Function: onCreate */ onCreate: function() { OpenLayers.Ajax.activeRequestCount++; }, /** * Function: onComplete */ onComplete: function() { OpenLayers.Ajax.activeRequestCount--; } }); /** * Class: OpenLayers.Ajax.Base */ OpenLayers.Ajax.Base = OpenLayers.Class({ /** * Constructor: OpenLayers.Ajax.Base * * Parameters: * options - {Object} */ initialize: function(options) { this.options = { method: 'post', asynchronous: true, contentType: 'application/xml', parameters: '' }; OpenLayers.Util.extend(this.options, options || {}); this.options.method = this.options.method.toLowerCase(); if (typeof this.options.parameters == 'string') { this.options.parameters = OpenLayers.Util.getParameters(this.options.parameters); } } }); /** * Class: OpenLayers.Ajax.Request * *Deprecated*. Use method instead. * * Inherit: * - */ OpenLayers.Ajax.Request = OpenLayers.Class(OpenLayers.Ajax.Base, { /** * Property: _complete * * {Boolean} */ _complete: false, /** * Constructor: OpenLayers.Ajax.Request * * Parameters: * url - {String} * options - {Object} */ initialize: function(url, options) { OpenLayers.Ajax.Base.prototype.initialize.apply(this, [options]); if (OpenLayers.ProxyHost && OpenLayers.String.startsWith(url, "http")) { url = OpenLayers.ProxyHost + encodeURIComponent(url); } this.transport = OpenLayers.Ajax.getTransport(); this.request(url); }, /** * Method: request * * Parameters: * url - {String} */ request: function(url) { this.url = url; this.method = this.options.method; var params = OpenLayers.Util.extend({}, this.options.parameters); if (this.method != 'get' && this.method != 'post') { // simulate other verbs over post params['_method'] = this.method; this.method = 'post'; } this.parameters = params; if (params = OpenLayers.Util.getParameterString(params)) { // when GET, append parameters to URL if (this.method == 'get') { this.url += ((this.url.indexOf('?') > -1) ? '&' : '?') + params; } else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { params += '&_='; } } try { var response = new OpenLayers.Ajax.Response(this); if (this.options.onCreate) { this.options.onCreate(response); } OpenLayers.Ajax.Responders.dispatch('onCreate', this, response); this.transport.open(this.method.toUpperCase(), this.url, this.options.asynchronous); if (this.options.asynchronous) { window.setTimeout( OpenLayers.Function.bind(this.respondToReadyState, this, 1), 10); } this.transport.onreadystatechange = OpenLayers.Function.bind(this.onStateChange, this); this.setRequestHeaders(); this.body = this.method == 'post' ? (this.options.postBody || params) : null; this.transport.send(this.body); // Force Firefox to handle ready state 4 for synchronous requests if (!this.options.asynchronous && this.transport.overrideMimeType) { this.onStateChange(); } } catch (e) { this.dispatchException(e); } }, /** * Method: onStateChange */ onStateChange: function() { var readyState = this.transport.readyState; if (readyState > 1 && !((readyState == 4) && this._complete)) { this.respondToReadyState(this.transport.readyState); } }, /** * Method: setRequestHeaders */ setRequestHeaders: function() { var headers = { 'X-Requested-With': 'XMLHttpRequest', 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*', 'OpenLayers': true }; if (this.method == 'post') { headers['Content-type'] = this.options.contentType + (this.options.encoding ? '; charset=' + this.options.encoding : ''); /* Force "Connection: close" for older Mozilla browsers to work * around a bug where XMLHttpRequest sends an incorrect * Content-length header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType && (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005) { headers['Connection'] = 'close'; } } // user-defined headers if (typeof this.options.requestHeaders == 'object') { var extras = this.options.requestHeaders; if (typeof extras.push == 'function') { for (var i = 0, length = extras.length; i < length; i += 2) { headers[extras[i]] = extras[i+1]; } } else { for (var i in extras) { headers[i] = extras[i]; } } } for (var name in headers) { this.transport.setRequestHeader(name, headers[name]); } }, /** * Method: success * * Returns: * {Boolean} - */ success: function() { var status = this.getStatus(); return !status || (status >=200 && status < 300); }, /** * Method: getStatus * * Returns: * {Integer} - Status */ getStatus: function() { try { return this.transport.status || 0; } catch (e) { return 0; } }, /** * Method: respondToReadyState * * Parameters: * readyState - {?} */ respondToReadyState: function(readyState) { var state = OpenLayers.Ajax.Request.Events[readyState]; var response = new OpenLayers.Ajax.Response(this); if (state == 'Complete') { try { this._complete = true; (this.options['on' + response.status] || this.options['on' + (this.success() ? 'Success' : 'Failure')] || OpenLayers.Ajax.emptyFunction)(response); } catch (e) { this.dispatchException(e); } var contentType = response.getHeader('Content-type'); } try { (this.options['on' + state] || OpenLayers.Ajax.emptyFunction)(response); OpenLayers.Ajax.Responders.dispatch('on' + state, this, response); } catch (e) { this.dispatchException(e); } if (state == 'Complete') { // avoid memory leak in MSIE: clean up this.transport.onreadystatechange = OpenLayers.Ajax.emptyFunction; } }, /** * Method: getHeader * * Parameters: * name - {String} Header name * * Returns: * {?} - response header for the given name */ getHeader: function(name) { try { return this.transport.getResponseHeader(name); } catch (e) { return null; } }, /** * Method: dispatchException * If the optional onException function is set, execute it * and then dispatch the call to any other listener registered * for onException. * * If no optional onException function is set, we suspect that * the user may have also not used * OpenLayers.Ajax.Responders.register to register a listener * for the onException call. To make sure that something * gets done with this exception, only dispatch the call if there * are listeners. * * If you explicitly want to swallow exceptions, set * request.options.onException to an empty function (function(){}) * or register an empty function with * for onException. * * Parameters: * exception - {?} */ dispatchException: function(exception) { var handler = this.options.onException; if(handler) { // call options.onException and alert any other listeners handler(this, exception); OpenLayers.Ajax.Responders.dispatch('onException', this, exception); } else { // check if there are any other listeners var listener = false; var responders = OpenLayers.Ajax.Responders.responders; for (var i = 0; i < responders.length; i++) { if(responders[i].onException) { listener = true; break; } } if(listener) { // call all listeners OpenLayers.Ajax.Responders.dispatch('onException', this, exception); } else { // let the exception through throw exception; } } } }); /** * Property: Events * {Array(String)} */ OpenLayers.Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; /** * Class: OpenLayers.Ajax.Response */ OpenLayers.Ajax.Response = OpenLayers.Class({ /** * Property: status * * {Integer} */ status: 0, /** * Property: statusText * * {String} */ statusText: '', /** * Constructor: OpenLayers.Ajax.Response * * Parameters: * request - {Object} */ initialize: function(request) { this.request = request; var transport = this.transport = request.transport, readyState = this.readyState = transport.readyState; if ((readyState > 2 && !(!!(window.attachEvent && !window.opera))) || readyState == 4) { this.status = this.getStatus(); this.statusText = this.getStatusText(); this.responseText = transport.responseText == null ? '' : String(transport.responseText); } if(readyState == 4) { var xml = transport.responseXML; this.responseXML = xml === undefined ? null : xml; } }, /** * Method: getStatus */ getStatus: OpenLayers.Ajax.Request.prototype.getStatus, /** * Method: getStatustext * * Returns: * {String} - statusText */ getStatusText: function() { try { return this.transport.statusText || ''; } catch (e) { return ''; } }, /** * Method: getHeader */ getHeader: OpenLayers.Ajax.Request.prototype.getHeader, /** * Method: getResponseHeader * * Returns: * {?} - response header for given name */ getResponseHeader: function(name) { return this.transport.getResponseHeader(name); } }); /** * Function: getElementsByTagNameNS * * Parameters: * parentnode - {?} * nsuri - {?} * nsprefix - {?} * tagname - {?} * * Returns: * {?} */ OpenLayers.Ajax.getElementsByTagNameNS = function(parentnode, nsuri, nsprefix, tagname) { var elem = null; if (parentnode.getElementsByTagNameNS) { elem = parentnode.getElementsByTagNameNS(nsuri, tagname); } else { elem = parentnode.getElementsByTagName(nsprefix + ':' + tagname); } return elem; }; /** * Function: serializeXMLToString * Wrapper function around XMLSerializer, which doesn't exist/work in * IE/Safari. We need to come up with a way to serialize in those browser: * for now, these browsers will just fail. #535, #536 * * Parameters: * xmldom {XMLNode} xml dom to serialize * * Returns: * {?} */ OpenLayers.Ajax.serializeXMLToString = function(xmldom) { var serializer = new XMLSerializer(); var data = serializer.serializeToString(xmldom); return data; }; /** * Namespace: OpenLayers.Element */ OpenLayers.Util.extend(OpenLayers.Element, { /** * APIFunction: hide * *Deprecated*. Hide element(s) passed in * * Parameters: * element - {DOMElement} Actually user can pass any number of elements */ hide: function() { OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated", { newMethod: "element.style.display = 'none';" })); for (var i=0, len=arguments.length; i} * * Returns: * bounds - {} */ getBoundsFromBaseLayer: function(position) { var msg = OpenLayers.i18n('reprojectDeprecated', {'layerName':this.layer.name}); OpenLayers.Console.warn(msg); var topLeft = this.layer.map.getLonLatFromLayerPx(position); var bottomRightPx = position.clone(); bottomRightPx.x += this.size.w; bottomRightPx.y += this.size.h; var bottomRight = this.layer.map.getLonLatFromLayerPx(bottomRightPx); // Handle the case where the base layer wraps around the date line. // Google does this, and it breaks WMS servers to request bounds in // that fashion. if (topLeft.lon > bottomRight.lon) { if (topLeft.lon < 0) { topLeft.lon = -180 - (topLeft.lon+180); } else { bottomRight.lon = 180+bottomRight.lon+180; } } var bounds = new OpenLayers.Bounds(topLeft.lon, bottomRight.lat, bottomRight.lon, topLeft.lat); return bounds; } }); /** * Class: OpenLayers.Control.MouseDefaults * This class is DEPRECATED in 2.4 and will be removed by 3.0. * If you need this functionality, use * instead!!! * * Inherits from: * - */ OpenLayers.Control.MouseDefaults = OpenLayers.Class(OpenLayers.Control, { /** WARNING WARNING WARNING!!! This class is DEPRECATED in 2.4 and will be removed by 3.0. If you need this functionality, use Control.Navigation instead!!! */ /** * Property: performedDrag * {Boolean} */ performedDrag: false, /** * Property: wheelObserver * {Function} */ wheelObserver: null, /** * Constructor: OpenLayers.Control.MouseDefaults */ initialize: function() { OpenLayers.Control.prototype.initialize.apply(this, arguments); }, /** * APIMethod: destroy */ destroy: function() { if (this.handler) { this.handler.destroy(); } this.handler = null; this.map.events.un({ "click": this.defaultClick, "dblclick": this.defaultDblClick, "mousedown": this.defaultMouseDown, "mouseup": this.defaultMouseUp, "mousemove": this.defaultMouseMove, "mouseout": this.defaultMouseOut, scope: this }); //unregister mousewheel events specifically on the window and document OpenLayers.Event.stopObserving(window, "DOMMouseScroll", this.wheelObserver); OpenLayers.Event.stopObserving(window, "mousewheel", this.wheelObserver); OpenLayers.Event.stopObserving(document, "mousewheel", this.wheelObserver); this.wheelObserver = null; OpenLayers.Control.prototype.destroy.apply(this, arguments); }, /** * Method: draw */ draw: function() { this.map.events.on({ "click": this.defaultClick, "dblclick": this.defaultDblClick, "mousedown": this.defaultMouseDown, "mouseup": this.defaultMouseUp, "mousemove": this.defaultMouseMove, "mouseout": this.defaultMouseOut, scope: this }); this.registerWheelEvents(); }, /** * Method: registerWheelEvents */ registerWheelEvents: function() { this.wheelObserver = OpenLayers.Function.bindAsEventListener( this.onWheelEvent, this ); //register mousewheel events specifically on the window and document OpenLayers.Event.observe(window, "DOMMouseScroll", this.wheelObserver); OpenLayers.Event.observe(window, "mousewheel", this.wheelObserver); OpenLayers.Event.observe(document, "mousewheel", this.wheelObserver); }, /** * Method: defaultClick * * Parameters: * evt - {Event} * * Returns: * {Boolean} */ defaultClick: function (evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } var notAfterDrag = !this.performedDrag; this.performedDrag = false; return notAfterDrag; }, /** * Method: defaultDblClick * * Parameters: * evt - {Event} */ defaultDblClick: function (evt) { var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); this.map.setCenter(newCenter, this.map.zoom + 1); OpenLayers.Event.stop(evt); return false; }, /** * Method: defaultMouseDown * * Parameters: * evt - {Event} */ defaultMouseDown: function (evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } this.mouseDragStart = evt.xy.clone(); this.performedDrag = false; if (evt.shiftKey) { this.map.div.style.cursor = "crosshair"; this.zoomBox = OpenLayers.Util.createDiv('zoomBox', this.mouseDragStart, null, null, "absolute", "2px solid red"); this.zoomBox.style.backgroundColor = "white"; this.zoomBox.style.filter = "alpha(opacity=50)"; // IE this.zoomBox.style.opacity = "0.50"; this.zoomBox.style.fontSize = "1px"; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.viewPortDiv.appendChild(this.zoomBox); } document.onselectstart = OpenLayers.Function.False; OpenLayers.Event.stop(evt); }, /** * Method: defaultMouseMove * * Parameters: * evt - {Event} */ defaultMouseMove: function (evt) { // record the mouse position, used in onWheelEvent this.mousePosition = evt.xy.clone(); if (this.mouseDragStart != null) { if (this.zoomBox) { var deltaX = Math.abs(this.mouseDragStart.x - evt.xy.x); var deltaY = Math.abs(this.mouseDragStart.y - evt.xy.y); this.zoomBox.style.width = Math.max(1, deltaX) + "px"; this.zoomBox.style.height = Math.max(1, deltaY) + "px"; if (evt.xy.x < this.mouseDragStart.x) { this.zoomBox.style.left = evt.xy.x+"px"; } if (evt.xy.y < this.mouseDragStart.y) { this.zoomBox.style.top = evt.xy.y+"px"; } } else { var deltaX = this.mouseDragStart.x - evt.xy.x; var deltaY = this.mouseDragStart.y - evt.xy.y; var size = this.map.getSize(); var newXY = new OpenLayers.Pixel(size.w / 2 + deltaX, size.h / 2 + deltaY); var newCenter = this.map.getLonLatFromViewPortPx( newXY ); this.map.setCenter(newCenter, null, true); this.mouseDragStart = evt.xy.clone(); this.map.div.style.cursor = "move"; } this.performedDrag = true; } }, /** * Method: defaultMouseUp * * Parameters: * evt - {} */ defaultMouseUp: function (evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } if (this.zoomBox) { this.zoomBoxEnd(evt); } else { if (this.performedDrag) { this.map.setCenter(this.map.center); } } document.onselectstart=null; this.mouseDragStart = null; this.map.div.style.cursor = ""; }, /** * Method: defaultMouseOut * * Parameters: * evt - {Event} */ defaultMouseOut: function (evt) { if (this.mouseDragStart != null && OpenLayers.Util.mouseLeft(evt, this.map.viewPortDiv)) { if (this.zoomBox) { this.removeZoomBox(); } this.mouseDragStart = null; } }, /** * Method: defaultWheelUp * User spun scroll wheel up * */ defaultWheelUp: function(evt) { if (this.map.getZoom() <= this.map.getNumZoomLevels()) { this.map.setCenter(this.map.getLonLatFromPixel(evt.xy), this.map.getZoom() + 1); } }, /** * Method: defaultWheelDown * User spun scroll wheel down */ defaultWheelDown: function(evt) { if (this.map.getZoom() > 0) { this.map.setCenter(this.map.getLonLatFromPixel(evt.xy), this.map.getZoom() - 1); } }, /** * Method: zoomBoxEnd * Zoombox function. */ zoomBoxEnd: function(evt) { if (this.mouseDragStart != null) { if (Math.abs(this.mouseDragStart.x - evt.xy.x) > 5 || Math.abs(this.mouseDragStart.y - evt.xy.y) > 5) { var start = this.map.getLonLatFromViewPortPx( this.mouseDragStart ); var end = this.map.getLonLatFromViewPortPx( evt.xy ); var top = Math.max(start.lat, end.lat); var bottom = Math.min(start.lat, end.lat); var left = Math.min(start.lon, end.lon); var right = Math.max(start.lon, end.lon); var bounds = new OpenLayers.Bounds(left, bottom, right, top); this.map.zoomToExtent(bounds); } else { var end = this.map.getLonLatFromViewPortPx( evt.xy ); this.map.setCenter(new OpenLayers.LonLat( (end.lon), (end.lat) ), this.map.getZoom() + 1); } this.removeZoomBox(); } }, /** * Method: removeZoomBox * Remove the zoombox from the screen and nullify our reference to it. */ removeZoomBox: function() { this.map.viewPortDiv.removeChild(this.zoomBox); this.zoomBox = null; }, /** * Mouse ScrollWheel code thanks to http://adomas.org/javascript-mouse-wheel/ */ /** * Method: onWheelEvent * Catch the wheel event and handle it xbrowserly * * Parameters: * e - {Event} */ onWheelEvent: function(e){ // first determine whether or not the wheeling was inside the map var inMap = false; var elem = OpenLayers.Event.element(e); while(elem != null) { if (this.map && elem == this.map.div) { inMap = true; break; } elem = elem.parentNode; } if (inMap) { var delta = 0; if (!e) { e = window.event; } if (e.wheelDelta) { delta = e.wheelDelta/120; if (window.opera && window.opera.version() < 9.2) { delta = -delta; } } else if (e.detail) { delta = -e.detail / 3; } if (delta) { // add the mouse position to the event because mozilla has a bug // with clientX and clientY (see https://bugzilla.mozilla.org/show_bug.cgi?id=352179) // getLonLatFromViewPortPx(e) returns wrong values e.xy = this.mousePosition; if (delta < 0) { this.defaultWheelDown(e); } else { this.defaultWheelUp(e); } } //only wheel the map, not the window OpenLayers.Event.stop(e); } }, CLASS_NAME: "OpenLayers.Control.MouseDefaults" }); /** * Class: OpenLayers.Control.MouseToolbar * This class is DEPRECATED in 2.4 and will be removed by 3.0. * If you need this functionality, use * instead!!! */ OpenLayers.Control.MouseToolbar = OpenLayers.Class( OpenLayers.Control.MouseDefaults, { /** * Property: mode */ mode: null, /** * Property: buttons */ buttons: null, /** * APIProperty: direction * {String} 'vertical' or 'horizontal' */ direction: "vertical", /** * Property: buttonClicked * {String} */ buttonClicked: null, /** * Constructor: OpenLayers.Control.MouseToolbar * * Parameters: * position - {} * direction - {String} */ initialize: function(position, direction) { OpenLayers.Control.prototype.initialize.apply(this, arguments); this.position = new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X, OpenLayers.Control.MouseToolbar.Y); if (position) { this.position = position; } if (direction) { this.direction = direction; } this.measureDivs = []; }, /** * APIMethod: destroy */ destroy: function() { for( var btnId in this.buttons) { var btn = this.buttons[btnId]; btn.map = null; btn.events.destroy(); } OpenLayers.Control.MouseDefaults.prototype.destroy.apply(this, arguments); }, /** * Method: draw */ draw: function() { OpenLayers.Control.prototype.draw.apply(this, arguments); OpenLayers.Control.MouseDefaults.prototype.draw.apply(this, arguments); this.buttons = {}; var sz = new OpenLayers.Size(28,28); var centered = new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,0); this._addButton("zoombox", "drag-rectangle-off.png", "drag-rectangle-on.png", centered, sz, "Shift->Drag to zoom to area"); centered = centered.add((this.direction == "vertical" ? 0 : sz.w), (this.direction == "vertical" ? sz.h : 0)); this._addButton("pan", "panning-hand-off.png", "panning-hand-on.png", centered, sz, "Drag the map to pan."); centered = centered.add((this.direction == "vertical" ? 0 : sz.w), (this.direction == "vertical" ? sz.h : 0)); this.switchModeTo("pan"); return this.div; }, /** * Method: _addButton */ _addButton:function(id, img, activeImg, xy, sz, title) { var imgLocation = OpenLayers.Util.getImageLocation(img); var activeImgLocation = OpenLayers.Util.getImageLocation(activeImg); // var btn = new ol.AlphaImage("_"+id, imgLocation, xy, sz); var btn = OpenLayers.Util.createAlphaImageDiv( "OpenLayers_Control_MouseToolbar_" + id, xy, sz, imgLocation, "absolute"); //we want to add the outer div this.div.appendChild(btn); btn.imgLocation = imgLocation; btn.activeImgLocation = activeImgLocation; btn.events = new OpenLayers.Events(this, btn, null, true); btn.events.on({ "mousedown": this.buttonDown, "mouseup": this.buttonUp, "dblclick": OpenLayers.Event.stop, scope: this }); btn.action = id; btn.title = title; btn.alt = title; btn.map = this.map; //we want to remember/reference the outer div this.buttons[id] = btn; return btn; }, /** * Method: buttonDown * * Parameters: * evt - {Event} */ buttonDown: function(evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } this.buttonClicked = evt.element.action; OpenLayers.Event.stop(evt); }, /** * Method: buttonUp * * Parameters: * evt - {Event} */ buttonUp: function(evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } if (this.buttonClicked != null) { if (this.buttonClicked == evt.element.action) { this.switchModeTo(evt.element.action); } OpenLayers.Event.stop(evt); this.buttonClicked = null; } }, /** * Method: defaultDblClick * * Parameters: * evt - {Event} */ defaultDblClick: function (evt) { this.switchModeTo("pan"); this.performedDrag = false; var newCenter = this.map.getLonLatFromViewPortPx( evt.xy ); this.map.setCenter(newCenter, this.map.zoom + 1); OpenLayers.Event.stop(evt); return false; }, /** * Method: defaultMouseDown * * Parameters: * evt - {Event} */ defaultMouseDown: function (evt) { if (!OpenLayers.Event.isLeftClick(evt)) { return; } this.mouseDragStart = evt.xy.clone(); this.performedDrag = false; this.startViaKeyboard = false; if (evt.shiftKey && this.mode !="zoombox") { this.switchModeTo("zoombox"); this.startViaKeyboard = true; } else if (evt.altKey && this.mode !="measure") { this.switchModeTo("measure"); } else if (!this.mode) { this.switchModeTo("pan"); } switch (this.mode) { case "zoombox": this.map.div.style.cursor = "crosshair"; this.zoomBox = OpenLayers.Util.createDiv('zoomBox', this.mouseDragStart, null, null, "absolute", "2px solid red"); this.zoomBox.style.backgroundColor = "white"; this.zoomBox.style.filter = "alpha(opacity=50)"; // IE this.zoomBox.style.opacity = "0.50"; this.zoomBox.style.fontSize = "1px"; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.viewPortDiv.appendChild(this.zoomBox); this.performedDrag = true; break; case "measure": var distance = ""; if (this.measureStart) { var measureEnd = this.map.getLonLatFromViewPortPx(this.mouseDragStart); distance = OpenLayers.Util.distVincenty(this.measureStart, measureEnd); distance = Math.round(distance * 100) / 100; distance = distance + "km"; this.measureStartBox = this.measureBox; } this.measureStart = this.map.getLonLatFromViewPortPx(this.mouseDragStart);; this.measureBox = OpenLayers.Util.createDiv(null, this.mouseDragStart.add( -2-parseInt(this.map.layerContainerDiv.style.left), -2-parseInt(this.map.layerContainerDiv.style.top)), null, null, "absolute"); this.measureBox.style.width="4px"; this.measureBox.style.height="4px"; this.measureBox.style.fontSize = "1px"; this.measureBox.style.backgroundColor="red"; this.measureBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.layerContainerDiv.appendChild(this.measureBox); if (distance) { this.measureBoxDistance = OpenLayers.Util.createDiv(null, this.mouseDragStart.add( -2-parseInt(this.map.layerContainerDiv.style.left), 2-parseInt(this.map.layerContainerDiv.style.top)), null, null, "absolute"); this.measureBoxDistance.innerHTML = distance; this.measureBoxDistance.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.layerContainerDiv.appendChild(this.measureBoxDistance); this.measureDivs.push(this.measureBoxDistance); } this.measureBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.layerContainerDiv.appendChild(this.measureBox); this.measureDivs.push(this.measureBox); break; default: this.map.div.style.cursor = "move"; break; } document.onselectstart = OpenLayers.Function.False; OpenLayers.Event.stop(evt); }, /** * Method: switchModeTo * * Parameters: * mode - {String} */ switchModeTo: function(mode) { if (mode != this.mode) { if (this.mode && this.buttons[this.mode]) { OpenLayers.Util.modifyAlphaImageDiv(this.buttons[this.mode], null, null, null, this.buttons[this.mode].imgLocation); } if (this.mode == "measure" && mode != "measure") { for(var i=0, len=this.measureDivs.length; i} A Bounds object representing the bounds of all the * currently loaded tiles (including those partially or not at all seen * onscreen) */ getGridBounds: function() { var msg = "The getGridBounds() function is deprecated. It will be " + "removed in 3.0. Please use getTilesBounds() instead."; OpenLayers.Console.warn(msg); return this.getTilesBounds(); } }); /** * Class: OpenLayers.Format.XML */ OpenLayers.Util.extend(OpenLayers.Format.XML.prototype, { /** * APIMethod: concatChildValues * *Deprecated*. Use instead. * * Concatenate the value of all child nodes if any exist, or return an * optional default string. Returns an empty string if no children * exist and no default value is supplied. Not optimized for large * numbers of child nodes. * * Parameters: * node - {DOMElement} The element used to look for child values. * def - {String} Optional string to return in the event that no * child exist. * * Returns: * {String} The concatenated value of all child nodes of the given node. */ concatChildValues: function(node, def) { var value = ""; var child = node.firstChild; var childValue; while(child) { childValue = child.nodeValue; if(childValue) { value += childValue; } child = child.nextSibling; } if(value == "" && def != undefined) { value = def; } return value; } }); /** * Class: OpenLayers.Layer.WMS.Post * Instances of OpenLayers.Layer.WMS.Post are used to retrieve data from OGC * Web Mapping Services via HTTP-POST (application/x-www-form-urlencoded). * Create a new WMS layer with the constructor. * * *Deprecated*. Instead of this layer, use with * configured in the layer's * . * * Inherits from: * - */ OpenLayers.Layer.WMS.Post = OpenLayers.Class(OpenLayers.Layer.WMS, { /** * APIProperty: unsupportedBrowsers * {Array} Array with browsers, which should use the HTTP-GET protocol * instead of HTTP-POST for fetching tiles from a WMS . * Defaults to ["mozilla", "firefox", "opera"], because Opera is not able * to show transparent images in IFrames and Firefox/Mozilla has some ugly * effects of viewport-shaking when panning the map. Both browsers, Opera * and Firefox/Mozilla, have no problem with long urls, which is the reason * for using POST instead of GET. The strings to pass to this array are * the ones returned by . */ unsupportedBrowsers: ["mozilla", "firefox", "opera"], /** * Property: SUPPORTED_TRANSITIONS * {Array} * no supported transitions for this type of layer, because it is not * possible to modify the initialized tiles (iframes) */ SUPPORTED_TRANSITIONS: [], /** * Property: usePost * {Boolean} */ usePost: null, /** * Constructor: OpenLayers.Layer.WMS.Post * Creates a new WMS layer object. * * Example: * (code) * var wms = new OpenLayers.Layer.WMS.Post( * "NASA Global Mosaic", * "http://wms.jpl.nasa.gov/wms.cgi", * {layers: "modis, global_mosaic"}); * (end) * * Parameters: * name - {String} A name for the layer * url - {String} Base url for the WMS * (e.g. http://wms.jpl.nasa.gov/wms.cgi) * params - {Object} An object with key/value pairs representing the * GetMap query string parameters and parameter values. * options - {Object} Hashtable of extra options to tag onto the layer. */ initialize: function(name, url, params, options) { var newArguments = []; newArguments.push(name, url, params, options); OpenLayers.Layer.WMS.prototype.initialize.apply(this, newArguments); this.usePost = OpenLayers.Util.indexOf( this.unsupportedBrowsers, OpenLayers.BROWSER_NAME) == -1; }, /** * Method: addTile * addTile creates a tile, initializes it and adds it as iframe to the * layer div. * * Parameters: * bounds - {} * position - {} * * Returns: * {} The added OpenLayers.Tile.Image.IFrame */ addTile: function(bounds,position) { return new OpenLayers.Tile.Image( this, position, bounds, null, this.tileSize, { maxGetUrlLength: this.usePost ? 0 : null }); }, CLASS_NAME: 'OpenLayers.Layer.WMS.Post' }); /** * Class: OpenLayers.Layer.WMS.Untiled * *Deprecated*. To be removed in 3.0. Instead use OpenLayers.Layer.WMS and * pass the option 'singleTile' as true. * * Inherits from: * - */ OpenLayers.Layer.WMS.Untiled = OpenLayers.Class(OpenLayers.Layer.WMS, { /** * APIProperty: singleTile * {singleTile} Always true for untiled. */ singleTile: true, /** * Constructor: OpenLayers.Layer.WMS.Untiled * * Parameters: * name - {String} * url - {String} * params - {Object} * options - {Object} */ initialize: function(name, url, params, options) { OpenLayers.Layer.WMS.prototype.initialize.apply(this, arguments); var msg = "The OpenLayers.Layer.WMS.Untiled class is deprecated and " + "will be removed in 3.0. Instead, you should use the " + "normal OpenLayers.Layer.WMS class, passing it the option " + "'singleTile' as true."; OpenLayers.Console.warn(msg); }, /** * Method: clone * Create a clone of this layer * * Returns: * {} An exact clone of this layer */ clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer.WMS.Untiled(this.name, this.url, this.params, this.getOptions()); } //get all additions from superclasses obj = OpenLayers.Layer.WMS.prototype.clone.apply(this, [obj]); // copy/set any non-init, non-simple values here return obj; }, CLASS_NAME: "OpenLayers.Layer.WMS.Untiled" }); /** * Class: OpenLayers.Layer.MapServer.Untiled * *Deprecated*. To be removed in 3.0. Instead use OpenLayers.Layer.MapServer * and pass the option 'singleTile' as true. * * Inherits from: * - */ OpenLayers.Layer.MapServer.Untiled = OpenLayers.Class(OpenLayers.Layer.MapServer, { /** * APIProperty: singleTile * {singleTile} Always true for untiled. */ singleTile: true, /** * Constructor: OpenLayers.Layer.MapServer.Untiled * * Parameters: * name - {String} * url - {String} * params - {Object} * options - {Object} */ initialize: function(name, url, params, options) { OpenLayers.Layer.MapServer.prototype.initialize.apply(this, arguments); var msg = "The OpenLayers.Layer.MapServer.Untiled class is deprecated and " + "will be removed in 3.0. Instead, you should use the " + "normal OpenLayers.Layer.MapServer class, passing it the option " + "'singleTile' as true."; OpenLayers.Console.warn(msg); }, /** * Method: clone * Create a clone of this layer * * Returns: * {} An exact clone of this layer */ clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer.MapServer.Untiled(this.name, this.url, this.params, this.getOptions()); } //get all additions from superclasses obj = OpenLayers.Layer.MapServer.prototype.clone.apply(this, [obj]); // copy/set any non-init, non-simple values here return obj; }, CLASS_NAME: "OpenLayers.Layer.MapServer.Untiled" }); /** * Class: OpenLayers.Tile.WFS * Instances of OpenLayers.Tile.WFS are used to manage the image tiles * used by various layers. Create a new image tile with the * constructor. * * Inherits from: * - */ OpenLayers.Tile.WFS = OpenLayers.Class(OpenLayers.Tile, { /** * Property: features * {Array()} list of features in this tile */ features: null, /** * Property: url * {String} */ url: null, /** * Property: request * {} */ request: null, /** TBD 3.0 - reorder the parameters to the init function to put URL * as last, so we can continue to call tile.initialize() * without changing the arguments. * * Constructor: OpenLayers.Tile.WFS * Constructor for a new instance. * * Parameters: * layer - {} layer that the tile will go in. * position - {} * bounds - {} * url - {} * size - {} */ initialize: function(layer, position, bounds, url, size) { OpenLayers.Tile.prototype.initialize.apply(this, arguments); this.url = url; this.features = []; }, /** * APIMethod: destroy * nullify references to prevent circular references and memory leaks */ destroy: function() { OpenLayers.Tile.prototype.destroy.apply(this, arguments); this.destroyAllFeatures(); this.features = null; this.url = null; if(this.request) { this.request.abort(); //this.request.destroy(); this.request = null; } }, /** * Method: clear * Clear the tile of any bounds/position-related data so that it can * be reused in a new location. */ clear: function() { this.destroyAllFeatures(); }, /** * Method: draw * Check that a tile should be drawn, and load features for it. */ draw:function() { if (OpenLayers.Tile.prototype.draw.apply(this, arguments)) { if (this.isLoading) { //if already loading, send 'reload' instead of 'loadstart'. this.events.triggerEvent("reload"); } else { this.isLoading = true; this.events.triggerEvent("loadstart"); } this.loadFeaturesForRegion(this.requestSuccess); } }, /** * Method: loadFeaturesForRegion * Abort any pending requests and issue another request for data. * * Input are function pointers for what to do on success and failure. * * Parameters: * success - {function} * failure - {function} */ loadFeaturesForRegion:function(success, failure) { if(this.request) { this.request.abort(); } this.request = OpenLayers.Request.GET({ url: this.url, success: success, failure: failure, scope: this }); }, /** * Method: requestSuccess * Called on return from request succcess. Adds results via * layer.addFeatures in vector mode, addResults otherwise. * * Parameters: * request - {} */ requestSuccess:function(request) { if (this.features) { var doc = request.responseXML; if (!doc || !doc.documentElement) { doc = request.responseText; } if (this.layer.vectorMode) { this.layer.addFeatures(this.layer.formatObject.read(doc)); } else { var xml = new OpenLayers.Format.XML(); if (typeof doc == "string") { doc = xml.read(doc); } var resultFeatures = xml.getElementsByTagNameNS( doc, "http://www.opengis.net/gml", "featureMember" ); this.addResults(resultFeatures); } } if (this.events) { this.events.triggerEvent("loadend"); } //request produced with success, we can delete the request object. //this.request.destroy(); this.request = null; }, /** * Method: addResults * Construct new feature via layer featureClass constructor, and add to * this.features. * * Parameters: * results - {Object} */ addResults: function(results) { for (var i=0; i < results.length; i++) { var feature = new this.layer.featureClass(this.layer, results[i]); this.features.push(feature); } }, /** * Method: destroyAllFeatures * Iterate through and call destroy() on each feature, removing it from * the local array */ destroyAllFeatures: function() { while(this.features.length > 0) { var feature = this.features.shift(); feature.destroy(); } }, CLASS_NAME: "OpenLayers.Tile.WFS" } ); /** * Class: OpenLayers.Feature.WFS * WFS handling class, for use as a featureClass on the WFS layer for handling * 'point' WFS types. Good for subclassing when creating a custom WFS like * XML application. * * Inherits from: * - */ OpenLayers.Feature.WFS = OpenLayers.Class(OpenLayers.Feature, { /** * Constructor: OpenLayers.Feature.WFS * Create a WFS feature. * * Parameters: * layer - {} * xmlNode - {XMLNode} */ initialize: function(layer, xmlNode) { var newArguments = arguments; var data = this.processXMLNode(xmlNode); newArguments = new Array(layer, data.lonlat, data); OpenLayers.Feature.prototype.initialize.apply(this, newArguments); this.createMarker(); this.layer.addMarker(this.marker); }, /** * Method: destroy * nullify references to prevent circular references and memory leaks */ destroy: function() { if (this.marker != null) { this.layer.removeMarker(this.marker); } OpenLayers.Feature.prototype.destroy.apply(this, arguments); }, /** * Method: processXMLNode * When passed an xmlNode, parses it for a GML point, and passes * back an object describing that point. * * For subclasses of Feature.WFS, this is the feature to change. * * Parameters: * xmlNode - {XMLNode} * * Returns: * {Object} Data Object with 'id', 'lonlat', and private properties set */ processXMLNode: function(xmlNode) { //this should be overridden by subclasses // must return an Object with 'id' and 'lonlat' values set var point = OpenLayers.Ajax.getElementsByTagNameNS(xmlNode, "http://www.opengis.net/gml", "gml", "Point"); var text = OpenLayers.Util.getXmlNodeValue(OpenLayers.Ajax.getElementsByTagNameNS(point[0], "http://www.opengis.net/gml","gml", "coordinates")[0]); var floats = text.split(","); return {lonlat: new OpenLayers.LonLat(parseFloat(floats[0]), parseFloat(floats[1])), id: null}; }, CLASS_NAME: "OpenLayers.Feature.WFS" }); /** * Class: OpenLayers.Layer.WFS * *Deprecated*. To be removed in 3.0. Instead use OpenLayers.Layer.Vector * with a Protocol.WFS and one or more Strategies. * * Inherits from: * - * - */ OpenLayers.Layer.WFS = OpenLayers.Class( OpenLayers.Layer.Vector, OpenLayers.Layer.Markers, { /** * APIProperty: isBaseLayer * {Boolean} WFS layer is not a base layer by default. */ isBaseLayer: false, /** * Property: tile * {} */ tile: null, /** * APIProperty: ratio * {Float} The ratio property determines the size of the serverside query * relative to the map viewport size. By default, we load an area twice * as big as the map, to allow for panning without immediately reload. * Setting this to 1 will cause the area of the WFS request to match * the map area exactly. It is recommended to set this to some number * at least slightly larger than 1, otherwise accidental clicks can * cause a data reload, by moving the map only 1 pixel. */ ratio: 2, /** * Property: DEFAULT_PARAMS * {Object} Hashtable of default key/value parameters */ DEFAULT_PARAMS: { service: "WFS", version: "1.0.0", request: "GetFeature" }, /** * APIProperty: featureClass * {} If featureClass is defined, an old-style markers * based WFS layer is created instead of a new-style vector layer. If * sent, this should be a subclass of OpenLayers.Feature */ featureClass: null, /** * APIProperty: format * {} The format you want the data to be parsed with. * Must be passed in the constructor. Should be a class, not an instance. * This option can only be used if no featureClass is passed / vectorMode * is false: if a featureClass is passed, then this parameter is ignored. */ format: null, /** * Property: formatObject * {} Internally created/managed format object, used by * the Tile to parse data. */ formatObject: null, /** * APIProperty: formatOptions * {Object} Hash of options which should be passed to the format when it is * created. Must be passed in the constructor. */ formatOptions: null, /** * Property: vectorMode * {Boolean} Should be calculated automatically. Determines whether the * layer is in vector mode or marker mode. */ vectorMode: true, /** * APIProperty: encodeBBOX * {Boolean} Should the BBOX commas be encoded? The WMS spec says 'no', * but some services want it that way. Default false. */ encodeBBOX: false, /** * APIProperty: extractAttributes * {Boolean} Should the WFS layer parse attributes from the retrieved * GML? Defaults to false. If enabled, parsing is slower, but * attributes are available in the attributes property of * layer features. */ extractAttributes: false, /** * Constructor: OpenLayers.Layer.WFS * * Parameters: * name - {String} * url - {String} * params - {Object} * options - {Object} Hashtable of extra options to tag onto the layer */ initialize: function(name, url, params, options) { if (options == undefined) { options = {}; } if (options.featureClass || !OpenLayers.Layer.Vector || !OpenLayers.Feature.Vector) { this.vectorMode = false; } // Uppercase params params = OpenLayers.Util.upperCaseObject(params); // Turn off error reporting, browsers like Safari may work // depending on the setup, and we don't want an unneccesary alert. OpenLayers.Util.extend(options, {'reportError': false}); var newArguments = []; newArguments.push(name, options); OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments); if (!this.renderer || !this.vectorMode) { this.vectorMode = false; if (!options.featureClass) { options.featureClass = OpenLayers.Feature.WFS; } OpenLayers.Layer.Markers.prototype.initialize.apply(this, newArguments); } if (this.params && this.params.typename && !this.options.typename) { this.options.typename = this.params.typename; } if (!this.options.geometry_column) { this.options.geometry_column = "the_geom"; } this.params = OpenLayers.Util.applyDefaults( params, OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS) ); this.url = url; }, /** * APIMethod: destroy */ destroy: function() { if (this.vectorMode) { OpenLayers.Layer.Vector.prototype.destroy.apply(this, arguments); } else { OpenLayers.Layer.Markers.prototype.destroy.apply(this, arguments); } if (this.tile) { this.tile.destroy(); } this.tile = null; this.ratio = null; this.featureClass = null; this.format = null; if (this.formatObject && this.formatObject.destroy) { this.formatObject.destroy(); } this.formatObject = null; this.formatOptions = null; this.vectorMode = null; this.encodeBBOX = null; this.extractAttributes = null; }, /** * Method: setMap * * Parameters: * map - {} */ setMap: function(map) { if (this.vectorMode) { OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments); var options = { 'extractAttributes': this.extractAttributes }; OpenLayers.Util.extend(options, this.formatOptions); if (this.map && !this.projection.equals(this.map.getProjectionObject())) { options.externalProjection = this.projection; options.internalProjection = this.map.getProjectionObject(); } this.formatObject = this.format ? new this.format(options) : new OpenLayers.Format.GML(options); } else { OpenLayers.Layer.Markers.prototype.setMap.apply(this, arguments); } }, /** * Method: moveTo * * Parameters: * bounds - {} * zoomChanged - {Boolean} * dragging - {Boolean} */ moveTo:function(bounds, zoomChanged, dragging) { if (this.vectorMode) { OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments); } else { OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments); } // don't load wfs features while dragging, wait for drag end if (dragging) { // TBD try to hide the vector layer while dragging // this.setVisibility(false); // this will probably help for panning performances return false; } if ( zoomChanged ) { if (this.vectorMode) { this.renderer.clear(); } } //DEPRECATED - REMOVE IN 3.0 // don't load data if current zoom level doesn't match if (this.options.minZoomLevel) { OpenLayers.Console.warn(OpenLayers.i18n('minZoomLevelError')); if (this.map.getZoom() < this.options.minZoomLevel) { return null; } } if (bounds == null) { bounds = this.map.getExtent(); } var firstRendering = (this.tile == null); //does the new bounds to which we need to move fall outside of the // current tile's bounds? var outOfBounds = (!firstRendering && !this.tile.bounds.containsBounds(bounds)); if (zoomChanged || firstRendering || (!dragging && outOfBounds)) { //determine new tile bounds var center = bounds.getCenterLonLat(); var tileWidth = bounds.getWidth() * this.ratio; var tileHeight = bounds.getHeight() * this.ratio; var tileBounds = new OpenLayers.Bounds(center.lon - (tileWidth / 2), center.lat - (tileHeight / 2), center.lon + (tileWidth / 2), center.lat + (tileHeight / 2)); //determine new tile size var tileSize = this.map.getSize(); tileSize.w = tileSize.w * this.ratio; tileSize.h = tileSize.h * this.ratio; //determine new position (upper left corner of new bounds) var ul = new OpenLayers.LonLat(tileBounds.left, tileBounds.top); var pos = this.map.getLayerPxFromLonLat(ul); //formulate request url string var url = this.getFullRequestString(); var params = null; // Cant combine "filter" and "BBOX". This is a cheap hack to help // people out who can't migrate to the WFS protocol immediately. var filter = this.params.filter || this.params.FILTER; if (filter) { params = {FILTER: filter}; } else { params = {BBOX: this.encodeBBOX ? tileBounds.toBBOX() : tileBounds.toArray()}; } if (this.map && !this.projection.equals(this.map.getProjectionObject())) { var projectedBounds = tileBounds.clone(); projectedBounds.transform(this.map.getProjectionObject(), this.projection); if (!filter){ params.BBOX = this.encodeBBOX ? projectedBounds.toBBOX() : projectedBounds.toArray(); } } url += "&" + OpenLayers.Util.getParameterString(params); if (!this.tile) { this.tile = new OpenLayers.Tile.WFS(this, pos, tileBounds, url, tileSize); this.addTileMonitoringHooks(this.tile); this.tile.draw(); } else { if (this.vectorMode) { this.destroyFeatures(); this.renderer.clear(); } else { this.clearMarkers(); } this.removeTileMonitoringHooks(this.tile); this.tile.destroy(); this.tile = null; this.tile = new OpenLayers.Tile.WFS(this, pos, tileBounds, url, tileSize); this.addTileMonitoringHooks(this.tile); this.tile.draw(); } } }, /** * Method: addTileMonitoringHooks * This function takes a tile as input and adds the appropriate hooks to * the tile so that the layer can keep track of the loading tile * (making sure to check that the tile is always the layer's current * tile before taking any action). * * Parameters: * tile - {} */ addTileMonitoringHooks: function(tile) { tile.onLoadStart = function() { //if this is the the layer's current tile, then trigger // a 'loadstart' if (this == this.layer.tile) { this.layer.events.triggerEvent("loadstart"); } }; tile.events.register("loadstart", tile, tile.onLoadStart); tile.onLoadEnd = function() { //if this is the the layer's current tile, then trigger // a 'tileloaded' and 'loadend' if (this == this.layer.tile) { this.layer.events.triggerEvent("tileloaded"); this.layer.events.triggerEvent("loadend"); } }; tile.events.register("loadend", tile, tile.onLoadEnd); tile.events.register("unload", tile, tile.onLoadEnd); }, /** * Method: removeTileMonitoringHooks * This function takes a tile as input and removes the tile hooks * that were added in addTileMonitoringHooks() * * Parameters: * tile - {} */ removeTileMonitoringHooks: function(tile) { tile.unload(); tile.events.un({ "loadstart": tile.onLoadStart, "loadend": tile.onLoadEnd, "unload": tile.onLoadEnd, scope: tile }); }, /** * Method: onMapResize * Call the onMapResize method of the appropriate parent class. */ onMapResize: function() { if(this.vectorMode) { OpenLayers.Layer.Vector.prototype.onMapResize.apply(this, arguments); } else { OpenLayers.Layer.Markers.prototype.onMapResize.apply(this, arguments); } }, /** * Method: display * Call the display method of the appropriate parent class. */ display: function() { if(this.vectorMode) { OpenLayers.Layer.Vector.prototype.display.apply(this, arguments); } else { OpenLayers.Layer.Markers.prototype.display.apply(this, arguments); } }, /** * APIMethod: mergeNewParams * Modify parameters for the layer and redraw. * * Parameters: * newParams - {Object} */ mergeNewParams:function(newParams) { var upperParams = OpenLayers.Util.upperCaseObject(newParams); var newArguments = [upperParams]; return OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this, newArguments); }, /** * APIMethod: clone * * Parameters: * obj - {Object} * * Returns: * {} An exact clone of this OpenLayers.Layer.WFS */ clone: function (obj) { if (obj == null) { obj = new OpenLayers.Layer.WFS(this.name, this.url, this.params, this.getOptions()); } //get all additions from superclasses if (this.vectorMode) { obj = OpenLayers.Layer.Vector.prototype.clone.apply(this, [obj]); } else { obj = OpenLayers.Layer.Markers.prototype.clone.apply(this, [obj]); } // copy/set any non-init, non-simple values here return obj; }, /** * APIMethod: getFullRequestString * combine the layer's url with its params and these newParams. * * Add the SRS parameter from 'projection' -- this is probably * more eloquently done via a setProjection() method, but this * works for now and always. * * Parameters: * newParams - {Object} * altUrl - {String} Use this as the url instead of the layer's url */ getFullRequestString:function(newParams, altUrl) { var projectionCode = this.projection.getCode() || this.map.getProjection(); this.params.SRS = (projectionCode == "none") ? null : projectionCode; return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply( this, arguments); }, /** * APIMethod: commit * Write out the data to a WFS server. */ commit: function() { if (!this.writer) { var options = {}; if (this.map && !this.projection.equals(this.map.getProjectionObject())) { options.externalProjection = this.projection; options.internalProjection = this.map.getProjectionObject(); } this.writer = new OpenLayers.Format.WFS(options,this); } var data = this.writer.write(this.features); OpenLayers.Request.POST({ url: this.url, data: data, success: this.commitSuccess, failure: this.commitFailure, scope: this }); }, /** * Method: commitSuccess * Called when the Ajax request returns a response * * Parameters: * response - {XmlNode} from server */ commitSuccess: function(request) { var response = request.responseText; if (response.indexOf('SUCCESS') != -1) { this.commitReport(OpenLayers.i18n("commitSuccess", {'response':response})); for(var i = 0; i < this.features.length; i++) { this.features[i].state = null; } // TBD redraw the layer or reset the state of features // foreach features: set state to null } else if (response.indexOf('FAILED') != -1 || response.indexOf('Exception') != -1) { this.commitReport(OpenLayers.i18n("commitFailed", {'response':response})); } }, /** * Method: commitFailure * Called when the Ajax request fails * * Parameters: * response - {XmlNode} from server */ commitFailure: function(request) {}, /** * APIMethod: commitReport * Called with a 'success' message if the commit succeeded, otherwise * a failure message, and the full request text as a second parameter. * Override this function to provide custom transaction reporting. * * string - {String} reporting string * response - {String} full XML response */ commitReport: function(string, response) { OpenLayers.Console.userError(string); }, /** * APIMethod: refresh * Refreshes all the features of the layer */ refresh: function() { if (this.tile) { if (this.vectorMode) { this.renderer.clear(); this.features.length = 0; } else { this.clearMarkers(); this.markers.length = 0; } this.tile.draw(); } }, /** * APIMethod: getDataExtent * Calculates the max extent which includes all of the layer data. * * Returns: * {} */ getDataExtent: function () { var extent; //get all additions from superclasses if (this.vectorMode) { extent = OpenLayers.Layer.Vector.prototype.getDataExtent.apply(this); } else { extent = OpenLayers.Layer.Markers.prototype.getDataExtent.apply(this); } return extent; }, /** * APIMethod: setOpacity * Call the setOpacity method of the appropriate parent class to set the * opacity. * * Parameters: * opacity - {Float} */ setOpacity: function (opacity) { if (this.vectorMode) { OpenLayers.Layer.Vector.prototype.setOpacity.apply(this, [opacity]); } else { OpenLayers.Layer.Markers.prototype.setOpacity.apply(this, [opacity]); } }, CLASS_NAME: "OpenLayers.Layer.WFS" }); /** * Class: OpenLayers.Layer.VirtualEarth * *Deprecated*. Use instead. * * Instances of OpenLayers.Layer.VirtualEarth are used to display the data from * the Bing Maps AJAX Control (see e.g. * http://msdn.microsoft.com/library/bb429619.aspx). Create a VirtualEarth * layer with the constructor. * * Inherits from: * - * - */ OpenLayers.Layer.VirtualEarth = OpenLayers.Class( OpenLayers.Layer.EventPane, OpenLayers.Layer.FixedZoomLevels, { /** * Constant: MIN_ZOOM_LEVEL * {Integer} 1 */ MIN_ZOOM_LEVEL: 1, /** * Constant: MAX_ZOOM_LEVEL * {Integer} 19 */ MAX_ZOOM_LEVEL: 19, /** * Constant: RESOLUTIONS * {Array(Float)} Hardcode these resolutions so that they are more closely * tied with the standard wms projection */ RESOLUTIONS: [ 1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 0.0006866455078125, 0.00034332275390625, 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125, 0.00002145767211914062, 0.00001072883605957031, 0.00000536441802978515 ], /** * APIProperty: type * {VEMapType} */ type: null, /** * APIProperty: wrapDateLine * {Boolean} Allow user to pan forever east/west. Default is true. * Setting this to false only restricts panning if * is true. */ wrapDateLine: true, /** * APIProperty: sphericalMercator * {Boolean} Should the map act as a mercator-projected map? This will * cause all interactions with the map to be in the actual map * projection, which allows support for vector drawing, overlaying * other maps, etc. */ sphericalMercator: false, /** * APIProperty: animationEnabled * {Boolean} If set to true, the transition between zoom levels will be * animated. Set to false to match the zooming experience of other * layer types. Default is true. */ animationEnabled: true, /** * Constructor: OpenLayers.Layer.VirtualEarth * Creates a new instance of a OpenLayers.Layer.VirtualEarth. If you use an * instance of OpenLayers.Layer.VirtualEarth in you map, you should set * the option restrictedExtent to a meaningful value, * e.g.: * (code) * var map = new OpenLayers.Map( 'map', { * // other map options * restrictedExtent : OpenLayers.Bounds(-20037508, -20037508, 20037508, 20037508) * } ); * * var veLayer = new OpenLayers.Layer.VirtualEarth ( * "Virtual Earth Layer" * ); * * map.addLayer( veLayer ); * (end) * * Parameters: * name - {String} * options - {Object} */ initialize: function(name, options) { OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments); OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, arguments); if(this.sphericalMercator) { OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator); this.initMercatorParameters(); } }, /** * Method: loadMapObject */ loadMapObject:function() { // create div and set to same size as map var veDiv = OpenLayers.Util.createDiv(this.name); var sz = this.map.getSize(); veDiv.style.width = sz.w + "px"; veDiv.style.height = sz.h + "px"; this.div.appendChild(veDiv); try { // crash prevention this.mapObject = new VEMap(this.name); } catch (e) { } if (this.mapObject != null) { try { // this is to catch a Mozilla bug without falling apart // The fourth argument is whether the map is 'fixed' -- not // draggable. See: // http://blogs.msdn.com/virtualearth/archive/2007/09/28/locking-a-virtual-earth-map.aspx // this.mapObject.LoadMap(null, null, this.type, true); this.mapObject.AttachEvent("onmousedown", OpenLayers.Function.True); } catch (e) { } this.mapObject.HideDashboard(); if(typeof this.mapObject.SetAnimationEnabled == "function") { this.mapObject.SetAnimationEnabled(this.animationEnabled); } } //can we do smooth panning? this is an unpublished method, so we need // to be careful if ( !this.mapObject || !this.mapObject.vemapcontrol || !this.mapObject.vemapcontrol.PanMap || (typeof this.mapObject.vemapcontrol.PanMap != "function")) { this.dragPanMapObject = null; } }, /** * Method: onMapResize */ onMapResize: function() { this.mapObject.Resize(this.map.size.w, this.map.size.h); }, /** * APIMethod: getWarningHTML * * Returns: * {String} String with information on why layer is broken, how to get * it working. */ getWarningHTML:function() { return OpenLayers.i18n( "getLayerWarning", {'layerType':'VE', 'layerLib':'VirtualEarth'} ); }, /************************************ * * * MapObject Interface Controls * * * ************************************/ // Get&Set Center, Zoom /** * APIMethod: setMapObjectCenter * Set the mapObject to the specified center and zoom * * Parameters: * center - {Object} MapObject LonLat format * zoom - {int} MapObject zoom format */ setMapObjectCenter: function(center, zoom) { this.mapObject.SetCenterAndZoom(center, zoom); }, /** * APIMethod: getMapObjectCenter * * Returns: * {Object} The mapObject's current center in Map Object format */ getMapObjectCenter: function() { return this.mapObject.GetCenter(); }, /** * APIMethod: dragPanMapObject * * Parameters: * dX - {Integer} * dY - {Integer} */ dragPanMapObject: function(dX, dY) { this.mapObject.vemapcontrol.PanMap(dX, -dY); }, /** * APIMethod: getMapObjectZoom * * Returns: * {Integer} The mapObject's current zoom, in Map Object format */ getMapObjectZoom: function() { return this.mapObject.GetZoomLevel(); }, // LonLat - Pixel Translation /** * APIMethod: getMapObjectLonLatFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Object} MapObject LonLat translated from MapObject Pixel */ getMapObjectLonLatFromMapObjectPixel: function(moPixel) { //the conditional here is to test if we are running the v6 of VE return (typeof VEPixel != 'undefined') ? this.mapObject.PixelToLatLong(moPixel) : this.mapObject.PixelToLatLong(moPixel.x, moPixel.y); }, /** * APIMethod: getMapObjectPixelFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Object} MapObject Pixel transtlated from MapObject LonLat */ getMapObjectPixelFromMapObjectLonLat: function(moLonLat) { return this.mapObject.LatLongToPixel(moLonLat); }, /************************************ * * * MapObject Primitives * * * ************************************/ // LonLat /** * APIMethod: getLongitudeFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Float} Longitude of the given MapObject LonLat */ getLongitudeFromMapObjectLonLat: function(moLonLat) { return this.sphericalMercator ? this.forwardMercator(moLonLat.Longitude, moLonLat.Latitude).lon : moLonLat.Longitude; }, /** * APIMethod: getLatitudeFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Float} Latitude of the given MapObject LonLat */ getLatitudeFromMapObjectLonLat: function(moLonLat) { return this.sphericalMercator ? this.forwardMercator(moLonLat.Longitude, moLonLat.Latitude).lat : moLonLat.Latitude; }, /** * APIMethod: getMapObjectLonLatFromLonLat * * Parameters: * lon - {Float} * lat - {Float} * * Returns: * {Object} MapObject LonLat built from lon and lat params */ getMapObjectLonLatFromLonLat: function(lon, lat) { var veLatLong; if(this.sphericalMercator) { var lonlat = this.inverseMercator(lon, lat); veLatLong = new VELatLong(lonlat.lat, lonlat.lon); } else { veLatLong = new VELatLong(lat, lon); } return veLatLong; }, // Pixel /** * APIMethod: getXFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Integer} X value of the MapObject Pixel */ getXFromMapObjectPixel: function(moPixel) { return moPixel.x; }, /** * APIMethod: getYFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Integer} Y value of the MapObject Pixel */ getYFromMapObjectPixel: function(moPixel) { return moPixel.y; }, /** * APIMethod: getMapObjectPixelFromXY * * Parameters: * x - {Integer} * y - {Integer} * * Returns: * {Object} MapObject Pixel from x and y parameters */ getMapObjectPixelFromXY: function(x, y) { //the conditional here is to test if we are running the v6 of VE return (typeof VEPixel != 'undefined') ? new VEPixel(x, y) : new Msn.VE.Pixel(x, y); }, CLASS_NAME: "OpenLayers.Layer.VirtualEarth" }); /* * Copyright 2007, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of Google Inc. nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Sets up google.gears.*, which is *the only* supported way to access Gears. * * Circumvent this file at your own risk! * * In the future, Gears may automatically define google.gears.* without this * file. Gears may use these objects to transparently fix bugs and compatibility * issues. Applications that use the code below will continue to work seamlessly * when that happens. */ (function() { // We are already defined. Hooray! if (window.google && google.gears) { return; } var factory = null; // Firefox if (typeof GearsFactory != 'undefined') { factory = new GearsFactory(); } else { // IE try { factory = new ActiveXObject('Gears.Factory'); // privateSetGlobalObject is only required and supported on WinCE. if (factory.getBuildInfo().indexOf('ie_mobile') != -1) { factory.privateSetGlobalObject(this); } } catch (e) { // Safari if ((typeof navigator.mimeTypes != 'undefined') && navigator.mimeTypes["application/x-googlegears"]) { factory = document.createElement("object"); factory.style.display = "none"; factory.width = 0; factory.height = 0; factory.type = "application/x-googlegears"; document.documentElement.appendChild(factory); } } } // *Do not* define any objects if Gears is not installed. This mimics the // behavior of Gears defining the objects in the future. if (!factory) { return; } // Now set up the objects, being careful not to overwrite anything. // // Note: In Internet Explorer for Windows Mobile, you can't add properties to // the window object. However, global objects are automatically added as // properties of the window object in all browsers. if (!window.google) { google = {}; } if (!google.gears) { google.gears = {factory: factory}; } })(); /** * Class: OpenLayers.Protocol.SQL * Abstract SQL protocol class. Not to be instantiated directly. Use * one of the SQL protocol subclasses instead. * * Inherits from: * - */ OpenLayers.Protocol.SQL = OpenLayers.Class(OpenLayers.Protocol, { /** * APIProperty: databaseName * {String} */ databaseName: 'ol', /** * APIProperty: tableName * Name of the database table into which Features should be saved. */ tableName: "ol_vector_features", /** * Property: postReadFiltering * {Boolean} Whether the filter (if there's one) must be applied after * the features have been read from the database; for example the * BBOX strategy passes the read method a BBOX spatial filter, if * postReadFiltering is true every feature read from the database * will go through the BBOX spatial filter, which can be costly; * defaults to true. */ postReadFiltering: true, /** * Constructor: OpenLayers.Protocol.SQL */ initialize: function(options) { OpenLayers.Protocol.prototype.initialize.apply(this, [options]); }, /** * APIMethod: destroy * Clean up the protocol. */ destroy: function() { OpenLayers.Protocol.prototype.destroy.apply(this); }, /** * APIMethod: supported * This should be overridden by specific subclasses * * Returns: * {Boolean} Whether or not the browser supports the SQL backend */ supported: function() { return false; }, /** * Method: evaluateFilter * If postReadFiltering is true evaluate the filter against the feature * and return the result of the evaluation, otherwise return true. * * Parameters: * {} The feature. * {} The filter. * * Returns: * {Boolean} true if postReadFiltering if false, the result of the * filter evaluation otherwise. */ evaluateFilter: function(feature, filter) { return filter && this.postReadFiltering ? filter.evaluate(feature) : true; }, CLASS_NAME: "OpenLayers.Protocol.SQL" }); /** * Class: OpenLayers.Protocol.SQL.Gears * This Protocol stores feature in the browser via the Gears Database module * . * * The main advantage is that all the read, create, update and delete operations * can be done offline. * * Inherits from: * - */ OpenLayers.Protocol.SQL.Gears = OpenLayers.Class(OpenLayers.Protocol.SQL, { /** * Property: FID_PREFIX * {String} */ FID_PREFIX: '__gears_fid__', /** * Property: NULL_GEOMETRY * {String} */ NULL_GEOMETRY: '__gears_null_geometry__', /** * Property: NULL_FEATURE_STATE * {String} */ NULL_FEATURE_STATE: '__gears_null_feature_state__', /** * Property: jsonParser * {} */ jsonParser: null, /** * Property: wktParser * {} */ wktParser: null, /** * Property: fidRegExp * {RegExp} Regular expression to know whether a feature was * created in offline mode. */ fidRegExp: null, /** * Property: saveFeatureState * {Boolean} Whether to save the feature state () * into the database, defaults to true. */ saveFeatureState: true, /** * Property: typeOfFid * {String} The type of the feature identifier, either "number" or * "string", defaults to "string". */ typeOfFid: "string", /** * Property: db * {GearsDatabase} */ db: null, /** * Constructor: OpenLayers.Protocol.SQL.Gears */ initialize: function(options) { if (!this.supported()) { return; } OpenLayers.Protocol.SQL.prototype.initialize.apply(this, [options]); this.jsonParser = new OpenLayers.Format.JSON(); this.wktParser = new OpenLayers.Format.WKT(); this.fidRegExp = new RegExp('^' + this.FID_PREFIX); this.initializeDatabase(); }, /** * Method: initializeDatabase */ initializeDatabase: function() { this.db = google.gears.factory.create('beta.database'); this.db.open(this.databaseName); this.db.execute( "CREATE TABLE IF NOT EXISTS " + this.tableName + " (fid TEXT UNIQUE, geometry TEXT, properties TEXT," + " state TEXT)"); }, /** * APIMethod: destroy * Clean up the protocol. */ destroy: function() { this.db.close(); this.db = null; this.jsonParser = null; this.wktParser = null; OpenLayers.Protocol.SQL.prototype.destroy.apply(this); }, /** * APIMethod: supported * Determine whether a browser supports Gears * * Returns: * {Boolean} The browser supports Gears */ supported: function() { return !!(window.google && google.gears); }, /** * APIMethod: read * Read all features from the database and return a * instance. If the options parameter * contains a callback attribute, the function is called with the response * as a parameter. * * Parameters: * options - {Object} Optional object for configuring the request; it * can have the {Boolean} property "noFeatureStateReset" which * specifies if the state of features read from the Gears * database must be reset to null, if "noFeatureStateReset" * is undefined or false then each feature's state is reset * to null, if "noFeatureStateReset" is true the feature state * is preserved. * * Returns: * {} An * object. */ read: function(options) { OpenLayers.Protocol.prototype.read.apply(this, arguments); options = OpenLayers.Util.applyDefaults(options, this.options); var feature, features = []; var rs = this.db.execute("SELECT * FROM " + this.tableName); while (rs.isValidRow()) { feature = this.unfreezeFeature(rs); if (this.evaluateFilter(feature, options.filter)) { if (!options.noFeatureStateReset) { feature.state = null; } features.push(feature); } rs.next(); } rs.close(); var resp = new OpenLayers.Protocol.Response({ code: OpenLayers.Protocol.Response.SUCCESS, requestType: "read", features: features }); if (options && options.callback) { options.callback.call(options.scope, resp); } return resp; }, /** * Method: unfreezeFeature * * Parameters: * row - {ResultSet} * * Returns: * {} */ unfreezeFeature: function(row) { var feature; var wkt = row.fieldByName('geometry'); if (wkt == this.NULL_GEOMETRY) { feature = new OpenLayers.Feature.Vector(); } else { feature = this.wktParser.read(wkt); } feature.attributes = this.jsonParser.read( row.fieldByName('properties')); feature.fid = this.extractFidFromField(row.fieldByName('fid')); var state = row.fieldByName('state'); if (state == this.NULL_FEATURE_STATE) { state = null; } feature.state = state; return feature; }, /** * Method: extractFidFromField * * Parameters: * field - {String} * * Returns * {String} or {Number} The fid. */ extractFidFromField: function(field) { if (!field.match(this.fidRegExp) && this.typeOfFid == "number") { field = parseFloat(field); } return field; }, /** * APIMethod: create * Create new features into the database. * * Parameters: * features - {Array({})} or * {} The features to create in * the database. * options - {Object} Optional object for configuring the request. * * Returns: * {} An * object. */ create: function(features, options) { options = OpenLayers.Util.applyDefaults(options, this.options); var resp = this.createOrUpdate(features); resp.requestType = "create"; if (options && options.callback) { options.callback.call(options.scope, resp); } return resp; }, /** * APIMethod: update * Construct a request updating modified feature. * * Parameters: * features - {Array({})} or * {} The features to update in * the database. * options - {Object} Optional object for configuring the request. * * Returns: * {} An * object. */ update: function(features, options) { options = OpenLayers.Util.applyDefaults(options, this.options); var resp = this.createOrUpdate(features); resp.requestType = "update"; if (options && options.callback) { options.callback.call(options.scope, resp); } return resp; }, /** * Method: createOrUpdate * Construct a request for updating or creating features in the * database. * * Parameters: * features - {Array({})} or * {} The feature to create or update * in the database. * * Returns: * {} An * object. */ createOrUpdate: function(features) { if (!(OpenLayers.Util.isArray(features))) { features = [features]; } var i, len = features.length, feature; var insertedFeatures = new Array(len); for (i = 0; i < len; i++) { feature = features[i]; var params = this.freezeFeature(feature); this.db.execute( "REPLACE INTO " + this.tableName + " (fid, geometry, properties, state)" + " VALUES (?, ?, ?, ?)", params); var clone = feature.clone(); clone.fid = this.extractFidFromField(params[0]); insertedFeatures[i] = clone; } return new OpenLayers.Protocol.Response({ code: OpenLayers.Protocol.Response.SUCCESS, features: insertedFeatures, reqFeatures: features }); }, /** * Method: freezeFeature * * Parameters: * feature - {} * state - {String} The feature state to store in the database. * * Returns: * {Array} */ freezeFeature: function(feature) { // 2 notes: // - fid might not be a string // - getFeatureStateForFreeze needs the feature fid to it's stored // in the feature here feature.fid = feature.fid != null ? "" + feature.fid : OpenLayers.Util.createUniqueID(this.FID_PREFIX); var geometry = feature.geometry != null ? feature.geometry.toString() : this.NULL_GEOMETRY; var properties = this.jsonParser.write(feature.attributes); var state = this.getFeatureStateForFreeze(feature); return [feature.fid, geometry, properties, state]; }, /** * Method: getFeatureStateForFreeze * Get the state of the feature to store into the database. * * Parameters: * feature - {} The feature. * * Returns * {String} The state */ getFeatureStateForFreeze: function(feature) { var state; if (!this.saveFeatureState) { state = this.NULL_FEATURE_STATE; } else if (this.createdOffline(feature)) { // if the feature was created in offline mode, its // state must remain INSERT state = OpenLayers.State.INSERT; } else { state = feature.state; } return state; }, /** * APIMethod: delete * Delete features from the database. * * Parameters: * features - {Array({})} or * {} * options - {Object} Optional object for configuring the request. * This object is modified and should not be reused. * * Returns: * {} An * object. */ "delete": function(features, options) { if (!(OpenLayers.Util.isArray(features))) { features = [features]; } options = OpenLayers.Util.applyDefaults(options, this.options); var i, len, feature; for (i = 0, len = features.length; i < len; i++) { feature = features[i]; // if saveFeatureState is set to true and if the feature wasn't created // in offline mode we don't delete it in the database but just update // it state column if (this.saveFeatureState && !this.createdOffline(feature)) { var toDelete = feature.clone(); toDelete.fid = feature.fid; if (toDelete.geometry) { toDelete.geometry.destroy(); toDelete.geometry = null; } toDelete.state = feature.state; this.createOrUpdate(toDelete); } else { this.db.execute( "DELETE FROM " + this.tableName + " WHERE fid = ?", [feature.fid]); } } var resp = new OpenLayers.Protocol.Response({ code: OpenLayers.Protocol.Response.SUCCESS, requestType: "delete", reqFeatures: features }); if (options && options.callback) { options.callback.call(options.scope, resp); } return resp; }, /** * Method: createdOffline * Returns true if the feature had a feature id when it was created in * the Gears database, false otherwise; this is determined by * checking the form of the feature's fid value. * * Parameters: * feature - {} * * Returns: * {Boolean} */ createdOffline: function(feature) { return (typeof feature.fid == "string" && !!(feature.fid.match(this.fidRegExp))); }, /** * APIMethod: commit * Go over the features and for each take action * based on the feature state. Possible actions are create, * update and delete. * * Parameters: * features - {Array({})} * options - {Object} Object whose possible keys are "create", "update", * "delete", "callback" and "scope", the values referenced by the * first three are objects as passed to the "create", "update", and * "delete" methods, the value referenced by the "callback" key is * a function which is called when the commit operation is complete * using the scope referenced by the "scope" key. * * Returns: * {Array({})} An array of * objects, one per request made * to the database. */ commit: function(features, options) { var opt, resp = [], nRequests = 0, nResponses = 0; function callback(resp) { if (++nResponses < nRequests) { resp.last = false; } this.callUserCallback(options, resp); } var feature, toCreate = [], toUpdate = [], toDelete = []; for (var i = features.length - 1; i >= 0; i--) { feature = features[i]; switch (feature.state) { case OpenLayers.State.INSERT: toCreate.push(feature); break; case OpenLayers.State.UPDATE: toUpdate.push(feature); break; case OpenLayers.State.DELETE: toDelete.push(feature); break; } } if (toCreate.length > 0) { nRequests++; opt = OpenLayers.Util.applyDefaults( {"callback": callback, "scope": this}, options.create ); resp.push(this.create(toCreate, opt)); } if (toUpdate.length > 0) { nRequests++; opt = OpenLayers.Util.applyDefaults( {"callback": callback, "scope": this}, options.update ); resp.push(this.update(toUpdate, opt)); } if (toDelete.length > 0) { nRequests++; opt = OpenLayers.Util.applyDefaults( {"callback": callback, "scope": this}, options["delete"] ); resp.push(this["delete"](toDelete, opt)); } return resp; }, /** * Method: clear * Removes all rows of the table. */ clear: function() { this.db.execute("DELETE FROM " + this.tableName); }, /** * Method: callUserCallback * This method is called from within commit each time a request is made * to the database, it is responsible for calling the user-supplied * callbacks. * * Parameters: * options - {Object} The map of options passed to the commit call. * resp - {} */ callUserCallback: function(options, resp) { var opt = options[resp.requestType]; if (opt && opt.callback) { opt.callback.call(opt.scope, resp); } if (resp.last && options.callback) { options.callback.call(options.scope); } }, CLASS_NAME: "OpenLayers.Protocol.SQL.Gears" }); /** * Class: OpenLayers.Layer.Yahoo * * Inherits from: * - * - */ OpenLayers.Layer.Yahoo = OpenLayers.Class( OpenLayers.Layer.EventPane, OpenLayers.Layer.FixedZoomLevels, { /** * Constant: MIN_ZOOM_LEVEL * {Integer} 0 */ MIN_ZOOM_LEVEL: 0, /** * Constant: MAX_ZOOM_LEVEL * {Integer} 17 */ MAX_ZOOM_LEVEL: 17, /** * Constant: RESOLUTIONS * {Array(Float)} Hardcode these resolutions so that they are more closely * tied with the standard wms projection */ RESOLUTIONS: [ 1.40625, 0.703125, 0.3515625, 0.17578125, 0.087890625, 0.0439453125, 0.02197265625, 0.010986328125, 0.0054931640625, 0.00274658203125, 0.001373291015625, 0.0006866455078125, 0.00034332275390625, 0.000171661376953125, 0.0000858306884765625, 0.00004291534423828125, 0.00002145767211914062, 0.00001072883605957031 ], /** * APIProperty: type * {YahooMapType} */ type: null, /** * APIProperty: wrapDateLine * {Boolean} Allow user to pan forever east/west. Default is true. * Setting this to false only restricts panning if * is true. */ wrapDateLine: true, /** * APIProperty: sphericalMercator * {Boolean} Should the map act as a mercator-projected map? This will * cause all interactions with the map to be in the actual map projection, * which allows support for vector drawing, overlaying other maps, etc. */ sphericalMercator: false, /** * Constructor: OpenLayers.Layer.Yahoo * * Parameters: * name - {String} * options - {Object} */ initialize: function(name, options) { OpenLayers.Layer.EventPane.prototype.initialize.apply(this, arguments); OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this, arguments); if(this.sphericalMercator) { OpenLayers.Util.extend(this, OpenLayers.Layer.SphericalMercator); this.initMercatorParameters(); } }, /** * Method: loadMapObject */ loadMapObject:function() { try { //do not crash! var size = this.getMapObjectSizeFromOLSize(this.map.getSize()); this.mapObject = new YMap(this.div, this.type, size); this.mapObject.disableKeyControls(); this.mapObject.disableDragMap(); //can we do smooth panning? (moveByXY is not an API function) if ( !this.mapObject.moveByXY || (typeof this.mapObject.moveByXY != "function" ) ) { this.dragPanMapObject = null; } } catch(e) {} }, /** * Method: onMapResize * */ onMapResize: function() { try { var size = this.getMapObjectSizeFromOLSize(this.map.getSize()); this.mapObject.resizeTo(size); } catch(e) {} }, /** * APIMethod: setMap * Overridden from EventPane because we need to remove this yahoo event * pane which prohibits our drag and drop, and we can only do this * once the map has been loaded and centered. * * Parameters: * map - {} */ setMap: function(map) { OpenLayers.Layer.EventPane.prototype.setMap.apply(this, arguments); this.map.events.register("moveend", this, this.fixYahooEventPane); }, /** * Method: fixYahooEventPane * The map has been centered, so the mysterious yahoo eventpane has been * added. we remove it so that it doesnt mess with *our* event pane. */ fixYahooEventPane: function() { var yahooEventPane = OpenLayers.Util.getElement("ygddfdiv"); if (yahooEventPane != null) { if (yahooEventPane.parentNode != null) { yahooEventPane.parentNode.removeChild(yahooEventPane); } this.map.events.unregister("moveend", this, this.fixYahooEventPane); } }, /** * APIMethod: getWarningHTML * * Returns: * {String} String with information on why layer is broken, how to get * it working. */ getWarningHTML:function() { return OpenLayers.i18n( "getLayerWarning", {'layerType':'Yahoo', 'layerLib':'Yahoo'} ); }, /********************************************************/ /* */ /* Translation Functions */ /* */ /* The following functions translate GMaps and OL */ /* formats for Pixel, LonLat, Bounds, and Zoom */ /* */ /********************************************************/ // // TRANSLATION: MapObject Zoom <-> OpenLayers Zoom // /** * APIMethod: getOLZoomFromMapObjectZoom * * Parameters: * gZoom - {Integer} * * Returns: * {Integer} An OpenLayers Zoom level, translated from the passed in gZoom * Returns null if null value is passed in. */ getOLZoomFromMapObjectZoom: function(moZoom) { var zoom = null; if (moZoom != null) { zoom = OpenLayers.Layer.FixedZoomLevels.prototype.getOLZoomFromMapObjectZoom.apply(this, [moZoom]); zoom = 18 - zoom; } return zoom; }, /** * APIMethod: getMapObjectZoomFromOLZoom * * Parameters: * olZoom - {Integer} * * Returns: * {Integer} A MapObject level, translated from the passed in olZoom * Returns null if null value is passed in */ getMapObjectZoomFromOLZoom: function(olZoom) { var zoom = null; if (olZoom != null) { zoom = OpenLayers.Layer.FixedZoomLevels.prototype.getMapObjectZoomFromOLZoom.apply(this, [olZoom]); zoom = 18 - zoom; } return zoom; }, /************************************ * * * MapObject Interface Controls * * * ************************************/ // Get&Set Center, Zoom /** * APIMethod: setMapObjectCenter * Set the mapObject to the specified center and zoom * * Parameters: * center - {Object} MapObject LonLat format * zoom - {int} MapObject zoom format */ setMapObjectCenter: function(center, zoom) { this.mapObject.drawZoomAndCenter(center, zoom); }, /** * APIMethod: getMapObjectCenter * * Returns: * {Object} The mapObject's current center in Map Object format */ getMapObjectCenter: function() { return this.mapObject.getCenterLatLon(); }, /** * APIMethod: dragPanMapObject * * Parameters: * dX - {Integer} * dY - {Integer} */ dragPanMapObject: function(dX, dY) { this.mapObject.moveByXY({ 'x': -dX, 'y': dY }); }, /** * APIMethod: getMapObjectZoom * * Returns: * {Integer} The mapObject's current zoom, in Map Object format */ getMapObjectZoom: function() { return this.mapObject.getZoomLevel(); }, // LonLat - Pixel Translation /** * APIMethod: getMapObjectLonLatFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Object} MapObject LonLat translated from MapObject Pixel */ getMapObjectLonLatFromMapObjectPixel: function(moPixel) { return this.mapObject.convertXYLatLon(moPixel); }, /** * APIMethod: getMapObjectPixelFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Object} MapObject Pixel transtlated from MapObject LonLat */ getMapObjectPixelFromMapObjectLonLat: function(moLonLat) { return this.mapObject.convertLatLonXY(moLonLat); }, /************************************ * * * MapObject Primitives * * * ************************************/ // LonLat /** * APIMethod: getLongitudeFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Float} Longitude of the given MapObject LonLat */ getLongitudeFromMapObjectLonLat: function(moLonLat) { return this.sphericalMercator ? this.forwardMercator(moLonLat.Lon, moLonLat.Lat).lon : moLonLat.Lon; }, /** * APIMethod: getLatitudeFromMapObjectLonLat * * Parameters: * moLonLat - {Object} MapObject LonLat format * * Returns: * {Float} Latitude of the given MapObject LonLat */ getLatitudeFromMapObjectLonLat: function(moLonLat) { return this.sphericalMercator ? this.forwardMercator(moLonLat.Lon, moLonLat.Lat).lat : moLonLat.Lat; }, /** * APIMethod: getMapObjectLonLatFromLonLat * * Parameters: * lon - {Float} * lat - {Float} * * Returns: * {Object} MapObject LonLat built from lon and lat params */ getMapObjectLonLatFromLonLat: function(lon, lat) { var yLatLong; if(this.sphericalMercator) { var lonlat = this.inverseMercator(lon, lat); yLatLong = new YGeoPoint(lonlat.lat, lonlat.lon); } else { yLatLong = new YGeoPoint(lat, lon); } return yLatLong; }, // Pixel /** * APIMethod: getXFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Integer} X value of the MapObject Pixel */ getXFromMapObjectPixel: function(moPixel) { return moPixel.x; }, /** * APIMethod: getYFromMapObjectPixel * * Parameters: * moPixel - {Object} MapObject Pixel format * * Returns: * {Integer} Y value of the MapObject Pixel */ getYFromMapObjectPixel: function(moPixel) { return moPixel.y; }, /** * APIMethod: getMapObjectPixelFromXY * * Parameters: * x - {Integer} * y - {Integer} * * Returns: * {Object} MapObject Pixel from x and y parameters */ getMapObjectPixelFromXY: function(x, y) { return new YCoordPoint(x, y); }, // Size /** * APIMethod: getMapObjectSizeFromOLSize * * Parameters: * olSize - {} * * Returns: * {Object} MapObject Size from olSize parameter */ getMapObjectSizeFromOLSize: function(olSize) { return new YSize(olSize.w, olSize.h); }, CLASS_NAME: "OpenLayers.Layer.Yahoo" }); /** * Class: OpenLayers.Layer.GML * Create a vector layer by parsing a GML file. The GML file is * passed in as a parameter. * *Deprecated*. To be removed in 3.0. Instead use OpenLayers.Layer.Vector * with Protocol.HTTP and Strategy.Fixed. Provide the protocol with a * format parameter to get the parser you want for your data. * * Inherits from: * - */ OpenLayers.Layer.GML = OpenLayers.Class(OpenLayers.Layer.Vector, { /** * Property: loaded * {Boolean} Flag for whether the GML data has been loaded yet. */ loaded: false, /** * APIProperty: format * {} The format you want the data to be parsed with. */ format: null, /** * APIProperty: formatOptions * {Object} Hash of options which should be passed to the format when it is * created. Must be passed in the constructor. */ formatOptions: null, /** * Constructor: OpenLayers.Layer.GML * Load and parse a single file on the web, according to the format * provided via the 'format' option, defaulting to GML. * * Parameters: * name - {String} * url - {String} URL of a GML file. * options - {Object} Hashtable of extra options to tag onto the layer. */ initialize: function(name, url, options) { var newArguments = []; newArguments.push(name, options); OpenLayers.Layer.Vector.prototype.initialize.apply(this, newArguments); this.url = url; }, /** * APIMethod: setVisibility * Set the visibility flag for the layer and hide/show&redraw accordingly. * Fire event unless otherwise specified * GML will be loaded if the layer is being made visible for the first * time. * * Parameters: * visible - {Boolean} Whether or not to display the layer * (if in range) * noEvent - {Boolean} */ setVisibility: function(visibility, noEvent) { OpenLayers.Layer.Vector.prototype.setVisibility.apply(this, arguments); if(this.visibility && !this.loaded){ // Load the GML this.loadGML(); } }, /** * Method: moveTo * If layer is visible and GML has not been loaded, load GML, then load GML * and call OpenLayers.Layer.Vector.moveTo() to redraw at the new location. * * Parameters: * bounds - {Object} * zoomChanged - {Object} * minor - {Object} */ moveTo:function(bounds, zoomChanged, minor) { OpenLayers.Layer.Vector.prototype.moveTo.apply(this, arguments); // Wait until initialisation is complete before loading GML // otherwise we can get a race condition where the root HTML DOM is // loaded after the GML is paited. // See http://trac.openlayers.org/ticket/404 if(this.visibility && !this.loaded){ this.loadGML(); } }, /** * Method: loadGML */ loadGML: function() { if (!this.loaded) { this.events.triggerEvent("loadstart"); OpenLayers.Request.GET({ url: this.url, success: this.requestSuccess, failure: this.requestFailure, scope: this }); this.loaded = true; } }, /** * Method: setUrl * Change the URL and reload the GML * * Parameters: * url - {String} URL of a GML file. */ setUrl:function(url) { this.url = url; this.destroyFeatures(); this.loaded = false; this.loadGML(); }, /** * Method: requestSuccess * Process GML after it has been loaded. * Called by initialize() and loadUrl() after the GML has been loaded. * * Parameters: * request - {String} */ requestSuccess:function(request) { var doc = request.responseXML; if (!doc || !doc.documentElement) { doc = request.responseText; } var options = {}; OpenLayers.Util.extend(options, this.formatOptions); if (this.map && !this.projection.equals(this.map.getProjectionObject())) { options.externalProjection = this.projection; options.internalProjection = this.map.getProjectionObject(); } var gml = this.format ? new this.format(options) : new OpenLayers.Format.GML(options); this.addFeatures(gml.read(doc)); this.events.triggerEvent("loadend"); }, /** * Method: requestFailure * Process a failed loading of GML. * Called by initialize() and loadUrl() if there was a problem loading GML. * * Parameters: * request - {String} */ requestFailure: function(request) { OpenLayers.Console.userError('Error in loading GML file ' + this.url); this.events.triggerEvent("loadend"); }, CLASS_NAME: "OpenLayers.Layer.GML" }); /** * Class: OpenLayers.Geometry.Rectangle * This class is *not supported*, and probably isn't what you're looking for. * Instead, most users probably want something like: * (code) * var poly = new OpenLayers.Bounds(0,0,10,10).toGeometry(); * (end) * This will create a rectangular Polygon geometry. * * Inherits: * - */ OpenLayers.Geometry.Rectangle = OpenLayers.Class(OpenLayers.Geometry, { /** * Property: x * {Float} */ x: null, /** * Property: y * {Float} */ y: null, /** * Property: width * {Float} */ width: null, /** * Property: height * {Float} */ height: null, /** * Constructor: OpenLayers.Geometry.Rectangle * * Parameters: * points - {Array()} */ initialize: function(x, y, width, height) { OpenLayers.Geometry.prototype.initialize.apply(this, arguments); this.x = x; this.y = y; this.width = width; this.height = height; }, /** * Method: calculateBounds * Recalculate the bounds for the geometry. */ calculateBounds: function() { this.bounds = new OpenLayers.Bounds(this.x, this.y, this.x + this.width, this.y + this.height); }, /** * APIMethod: getLength * * Returns: * {Float} The length of the geometry */ getLength: function() { var length = (2 * this.width) + (2 * this.height); return length; }, /** * APIMethod: getArea * * Returns: * {Float} The area of the geometry */ getArea: function() { var area = this.width * this.height; return area; }, CLASS_NAME: "OpenLayers.Geometry.Rectangle" }); /** * Class: OpenLayers.Renderer.NG * * Inherits from: * - */ OpenLayers.Renderer.NG = OpenLayers.Class(OpenLayers.Renderer.Elements, { /** * Constant: labelNodeType * {String} The node type for text label containers. To be defined by * subclasses. */ labelNodeType: null, /** * Constructor: OpenLayers.Renderer.NG * * 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. */ /** * Method: updateDimensions * To be extended by subclasses - here we set positioning related styles * on HTML elements, subclasses have to do the same for renderer specific * elements (e.g. viewBox, width and height of the rendererRoot) * * Parameters: * zoomChanged - {Boolean} Has the zoom changed? If so, subclasses may have * to update feature styles/dimensions. */ updateDimensions: function(zoomChanged) { var mapExtent = this.map.getExtent(); var renderExtent = mapExtent.scale(3); this.setExtent(renderExtent, true); var res = this.getResolution(); var div = this.rendererRoot.parentNode; var layerLeft = parseFloat(div.parentNode.style.left); var layerTop = parseFloat(div.parentNode.style.top); div.style.left = ((renderExtent.left - mapExtent.left) / res - layerLeft) + "px"; div.style.top = ((mapExtent.top - renderExtent.top) / res - layerTop) + "px"; }, /** * Method: resize */ setSize: function() { this.map.getExtent() && this.updateDimensions(); }, /** * Method: drawFeature * Draw the feature. The optional style argument can be used * to override the feature's own style. This method should only * be called from layer.drawFeature(). * * Parameters: * feature - {} * style - {} * * Returns: * {Boolean} true if the feature has been drawn completely, false if not, * undefined if the feature had no geometry */ drawFeature: function(feature, style) { if(style == null) { style = feature.style; } if (feature.geometry) { var rendered = this.drawGeometry(feature.geometry, style, feature.id); if(rendered !== false && style.label) { var location = feature.geometry.getCentroid(); this.drawText(feature.id, style, location); } else { this.removeText(feature.id); } return rendered; } }, /** * Method: drawText * Function for drawing text labels. * This method is only called by the renderer itself. * * Parameters: * featureId - {String|DOMElement} * style - {Object} * location - {}, will be modified inline * * Returns: * {DOMElement} container holding the text label (to be populated by * subclasses) */ drawText: function(featureId, style, location) { var label; if (typeof featureId !== "string") { label = featureId; } else { label = this.nodeFactory(featureId + this.LABEL_ID_SUFFIX, this.labelNodeType); label._featureId = featureId; } label._style = style; label._x = location.x; label._y = location.y; if(style.labelXOffset || style.labelYOffset) { var xOffset = isNaN(style.labelXOffset) ? 0 : style.labelXOffset; var yOffset = isNaN(style.labelYOffset) ? 0 : style.labelYOffset; var res = this.getResolution(); location.move(xOffset*res, yOffset*res); } if(label.parentNode !== this.textRoot) { this.textRoot.appendChild(label); } return label; }, CLASS_NAME: "OpenLayers.Renderer.NG" }); // Monkey-patching Layer.Vector for Renderer.NG support (function() { var moveTo = OpenLayers.Layer.Vector.prototype.moveTo; OpenLayers.Layer.Vector.prototype.moveTo = function(bounds, zoomChanged, dragging) { if (OpenLayers.Renderer.NG && this.renderer instanceof OpenLayers.Renderer.NG) { OpenLayers.Layer.prototype.moveTo.apply(this, arguments); dragging || this.renderer.updateDimensions(zoomChanged); if (!this.drawn) { this.drawn = true; var feature; for(var i=0, len=this.features.length; i */ OpenLayers.Renderer.SVG2 = OpenLayers.Class(OpenLayers.Renderer.NG, { /** * Property: xmlns * {String} */ xmlns: "http://www.w3.org/2000/svg", /** * Property: xlinkns * {String} */ xlinkns: "http://www.w3.org/1999/xlink", /** * Property: symbolMetrics * {Object} Cache for symbol metrics according to their svg coordinate * space. This is an object keyed by the symbol's id, and values are * an object with size, x and y properties. */ symbolMetrics: null, /** * Constant: labelNodeType * {String} The node type for text label containers. */ labelNodeType: "g", /** * Constructor: OpenLayers.Renderer.SVG2 * * Parameters: * containerID - {String} */ initialize: function(containerID) { if (!this.supported()) { return; } OpenLayers.Renderer.Elements.prototype.initialize.apply(this, arguments); this.symbolMetrics = {}; }, /** * APIMethod: supported * * Returns: * {Boolean} Whether or not the browser supports the SVG renderer */ supported: function() { var svgFeature = "http://www.w3.org/TR/SVG11/feature#"; return (document.implementation && (document.implementation.hasFeature("org.w3c.svg", "1.0") || document.implementation.hasFeature(svgFeature + "SVG", "1.1") || document.implementation.hasFeature(svgFeature + "BasicStructure", "1.1") )); }, /** * Method: updateDimensions * * Parameters: * zoomChanged - {Boolean} */ updateDimensions: function(zoomChanged) { OpenLayers.Renderer.NG.prototype.updateDimensions.apply(this, arguments); var res = this.getResolution(); var width = this.extent.getWidth(); var height = this.extent.getHeight(); var extentString = [ this.extent.left, -this.extent.top, width, height ].join(" "); this.rendererRoot.setAttributeNS(null, "viewBox", extentString); this.rendererRoot.setAttributeNS(null, "width", width / res); this.rendererRoot.setAttributeNS(null, "height", height / res); if (zoomChanged === true) { // update styles for the new resolution var i, len; var nodes = this.vectorRoot.childNodes; for (i=0, len=nodes.length; i} * style - {Object} * * Returns: * {String} The corresponding node type for the specified geometry */ getNodeType: function(geometry, style) { var nodeType = null; switch (geometry.CLASS_NAME) { case "OpenLayers.Geometry.Point": if (style.externalGraphic) { nodeType = "image"; } else if (this.isComplexSymbol(style.graphicName)) { nodeType = "svg"; } else { nodeType = "circle"; } break; case "OpenLayers.Geometry.Rectangle": nodeType = "rect"; break; case "OpenLayers.Geometry.LineString": nodeType = "polyline"; break; case "OpenLayers.Geometry.LinearRing": nodeType = "polygon"; break; case "OpenLayers.Geometry.Polygon": case "OpenLayers.Geometry.Curve": nodeType = "path"; break; default: break; } return nodeType; }, /** * Method: setStyle * Use to set all the style attributes to a SVG node. * * Takes care to adjust stroke width and point radius to be * resolution-relative * * Parameters: * node - {SVGDomElement} An SVG element to decorate * style - {Object} * options - {Object} Currently supported options include * 'isFilled' {Boolean} and * 'isStroked' {Boolean} */ setStyle: function(node, style, options) { style = style || node._style; options = options || node._options; var resolution = this.getResolution(); var r = node._radius; var widthFactor = resolution; if (node._geometryClass == "OpenLayers.Geometry.Point" && r) { node.style.visibility = ""; if (style.graphic === false) { node.style.visibility = "hidden"; } else if (style.externalGraphic) { if (style.graphicTitle) { node.setAttributeNS(null, "title", style.graphicTitle); //Standards-conformant SVG // Prevent duplicate nodes. See issue https://github.com/openlayers/openlayers/issues/92 var titleNode = node.getElementsByTagName("title"); if (titleNode.length > 0) { titleNode[0].firstChild.textContent = style.graphicTitle; } else { var label = this.nodeFactory(null, "title"); label.textContent = style.graphicTitle; node.appendChild(label); } } if (style.graphicWidth && style.graphicHeight) { node.setAttributeNS(null, "preserveAspectRatio", "none"); } var width = style.graphicWidth || style.graphicHeight; var height = style.graphicHeight || style.graphicWidth; width = width ? width : style.pointRadius*2; height = height ? height : style.pointRadius*2; width *= resolution; height *= resolution; var xOffset = (style.graphicXOffset != undefined) ? style.graphicXOffset * resolution : -(0.5 * width); var yOffset = (style.graphicYOffset != undefined) ? style.graphicYOffset * resolution : -(0.5 * height); var opacity = style.graphicOpacity || style.fillOpacity; node.setAttributeNS(null, "x", node._x + xOffset); node.setAttributeNS(null, "y", node._y + yOffset); node.setAttributeNS(null, "width", width); node.setAttributeNS(null, "height", height); node.setAttributeNS(this.xlinkns, "href", style.externalGraphic); node.setAttributeNS(null, "style", "opacity: "+opacity); node.onclick = OpenLayers.Renderer.SVG2.preventDefault; } else if (this.isComplexSymbol(style.graphicName)) { // the symbol viewBox is three times as large as the symbol var offset = style.pointRadius * 3 * resolution; var size = offset * 2; var src = this.importSymbol(style.graphicName); widthFactor = this.symbolMetrics[src.id].size * 3 / size * resolution; // remove the node from the dom before we modify it. This // prevents various rendering issues in Safari and FF var parent = node.parentNode; var nextSibling = node.nextSibling; if(parent) { parent.removeChild(node); } // The more appropriate way to implement this would be use/defs, // but due to various issues in several browsers, it is safer to // copy the symbols instead of referencing them. // See e.g. ticket http://trac.osgeo.org/openlayers/ticket/2985 // and this email thread // http://osgeo-org.1803224.n2.nabble.com/Select-Control-Ctrl-click-on-Feature-with-a-graphicName-opens-new-browser-window-tc5846039.html node.firstChild && node.removeChild(node.firstChild); node.appendChild(src.firstChild.cloneNode(true)); node.setAttributeNS(null, "viewBox", src.getAttributeNS(null, "viewBox")); node.setAttributeNS(null, "width", size); node.setAttributeNS(null, "height", size); node.setAttributeNS(null, "x", node._x - offset); node.setAttributeNS(null, "y", node._y - offset); // now that the node has all its new properties, insert it // back into the dom where it was if(nextSibling) { parent.insertBefore(node, nextSibling); } else if(parent) { parent.appendChild(node); } } else { node.setAttributeNS(null, "r", style.pointRadius * resolution); } var rotation = style.rotation; if (rotation !== undefined || node._rotation !== undefined) { node._rotation = rotation; rotation |= 0; if (node.nodeName !== "svg") { node.setAttributeNS(null, "transform", ["rotate(", rotation, node._x, node._y, ")"].join(" ") ); } else { var metrics = this.symbolMetrics[src.id]; node.firstChild.setAttributeNS(null, "transform", ["rotate(", rotation, metrics.x, metrics.y, ")"].join(" ") ); } } } if (options.isFilled) { node.setAttributeNS(null, "fill", style.fillColor); node.setAttributeNS(null, "fill-opacity", style.fillOpacity); } else { node.setAttributeNS(null, "fill", "none"); } if (options.isStroked) { node.setAttributeNS(null, "stroke", style.strokeColor); node.setAttributeNS(null, "stroke-opacity", style.strokeOpacity); node.setAttributeNS(null, "stroke-width", style.strokeWidth * widthFactor); node.setAttributeNS(null, "stroke-linecap", style.strokeLinecap || "round"); // Hard-coded linejoin for now, to make it look the same as in VML. // There is no strokeLinejoin property yet for symbolizers. node.setAttributeNS(null, "stroke-linejoin", "round"); style.strokeDashstyle && node.setAttributeNS(null, "stroke-dasharray", this.dashStyle(style, widthFactor)); } else { node.setAttributeNS(null, "stroke", "none"); } if (style.pointerEvents) { node.setAttributeNS(null, "pointer-events", style.pointerEvents); } if (style.cursor != null) { node.setAttributeNS(null, "cursor", style.cursor); } return node; }, /** * Method: dashStyle * * Parameters: * style - {Object} * widthFactor - {Number} * * Returns: * {String} A SVG compliant 'stroke-dasharray' value */ dashStyle: function(style, widthFactor) { var w = style.strokeWidth * widthFactor; var str = style.strokeDashstyle; switch (str) { case 'solid': return 'none'; case 'dot': return [widthFactor, 4 * w].join(); case 'dash': return [4 * w, 4 * w].join(); case 'dashdot': return [4 * w, 4 * w, widthFactor, 4 * w].join(); case 'longdash': return [8 * w, 4 * w].join(); case 'longdashdot': return [8 * w, 4 * w, widthFactor, 4 * w].join(); default: var parts = OpenLayers.String.trim(str).split(/\s+/g); for (var i=0, ii=parts.length; i} * * Returns: * {DOMElement} or false if the renderer could not draw the point */ drawPoint: function(node, geometry) { return this.drawCircle(node, geometry, 1); }, /** * Method: drawCircle * This method is only called by the renderer itself. * * Parameters: * node - {DOMElement} * geometry - {} * radius - {Float} * * Returns: * {DOMElement} or false if the renderer could not draw the circle */ drawCircle: function(node, geometry, radius) { var x = geometry.x; var y = -geometry.y; node.setAttributeNS(null, "cx", x); node.setAttributeNS(null, "cy", y); node._x = x; node._y = y; node._radius = radius; return node; }, /** * Method: drawLineString * This method is only called by the renderer itself. * * Parameters: * node - {DOMElement} * 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) { var path = this.getComponentsString(geometry.components); node.setAttributeNS(null, "points", path); return node; }, /** * Method: drawLinearRing * This method is only called by the renderer itself. * * Parameters: * node - {DOMElement} * 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) { var path = this.getComponentsString(geometry.components); node.setAttributeNS(null, "points", path); return node; }, /** * Method: drawPolygon * This method is only called by the renderer itself. * * Parameters: * node - {DOMElement} * 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) { var d = []; var draw = true; var complete = true; var linearRingResult, path; for (var j=0, len=geometry.components.length; j} * * Returns: * {DOMElement} or false if the renderer could not draw the rectangle */ drawRectangle: function(node, geometry) { node.setAttributeNS(null, "x", geometry.x); node.setAttributeNS(null, "y", -geometry.y); node.setAttributeNS(null, "width", geometry.width); node.setAttributeNS(null, "height", geometry.height); return node; }, /** * Method: drawText * Function for drawing text labels. * This method is only called by the renderer itself. * * Parameters: * featureId - {String|DOMElement} * style - {Object} * location - {}, will be modified inline * * Returns: * {DOMElement} container holding the text label */ drawText: function(featureId, style, location) { var g = OpenLayers.Renderer.NG.prototype.drawText.apply(this, arguments); var text = g.firstChild || this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_text", "text"); var res = this.getResolution(); text.setAttributeNS(null, "x", location.x / res); text.setAttributeNS(null, "y", - location.y / res); g.setAttributeNS(null, "transform", "scale(" + res + ")"); if (style.fontColor) { text.setAttributeNS(null, "fill", style.fontColor); } if (style.fontOpacity) { text.setAttributeNS(null, "opacity", style.fontOpacity); } if (style.fontFamily) { text.setAttributeNS(null, "font-family", style.fontFamily); } if (style.fontSize) { text.setAttributeNS(null, "font-size", style.fontSize); } if (style.fontWeight) { text.setAttributeNS(null, "font-weight", style.fontWeight); } if (style.fontStyle) { text.setAttributeNS(null, "font-style", style.fontStyle); } if (style.labelSelect === true) { text.setAttributeNS(null, "pointer-events", "visible"); text._featureId = featureId; } else { text.setAttributeNS(null, "pointer-events", "none"); } var align = style.labelAlign || OpenLayers.Renderer.defaultSymbolizer.labelAlign; text.setAttributeNS(null, "text-anchor", OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[0]] || "middle"); if (OpenLayers.IS_GECKO === true) { text.setAttributeNS(null, "dominant-baseline", OpenLayers.Renderer.SVG2.LABEL_ALIGN[align[1]] || "central"); } var labelRows = style.label.split('\n'); var numRows = labelRows.length; while (text.childNodes.length > numRows) { text.removeChild(text.lastChild); } for (var i = 0; i < numRows; i++) { var tspan = text.childNodes[i] || this.nodeFactory(featureId + this.LABEL_ID_SUFFIX + "_tspan_" + i, "tspan"); if (style.labelSelect === true) { tspan._featureId = featureId; } if (OpenLayers.IS_GECKO === false) { tspan.setAttributeNS(null, "baseline-shift", OpenLayers.Renderer.SVG2.LABEL_VSHIFT[align[1]] || "-35%"); } tspan.setAttribute("x", location.x / res); if (i == 0) { var vfactor = OpenLayers.Renderer.SVG2.LABEL_VFACTOR[align[1]]; if (vfactor == null) { vfactor = -.5; } tspan.setAttribute("dy", (vfactor*(numRows-1)) + "em"); } else { tspan.setAttribute("dy", "1em"); } tspan.textContent = (labelRows[i] === '') ? ' ' : labelRows[i]; if (!tspan.parentNode) { text.appendChild(tspan); } } if (!text.parentNode) { g.appendChild(text); } return g; }, /** * Method: getComponentString * * Parameters: * components - {Array()} Array of points * separator - {String} character between coordinate pairs. Defaults to "," * * Returns: * {Object} hash with properties "path" (the string created from the * components and "complete" (false if the renderer was unable to * draw all components) */ getComponentsString: function(components, separator) { var len = components.length; var strings = new Array(len); for (var i=0; i} * * Returns: * {String} or false if point is outside the valid range */ getShortString: function(point) { return point.x + "," + (-point.y); }, /** * Method: importSymbol * add a new symbol definition from the rendererer's symbol hash * * Parameters: * graphicName - {String} name of the symbol to import * * Returns: * {DOMElement} - the imported symbol */ importSymbol: function (graphicName) { if (!this.defs) { // create svg defs tag this.defs = this.createDefs(); } var id = this.container.id + "-" + graphicName; // check if symbol already exists in the defs var existing = document.getElementById(id); if (existing != null) { return existing; } var symbol = OpenLayers.Renderer.symbol[graphicName]; if (!symbol) { throw new Error(graphicName + ' is not a valid symbol name'); } var symbolNode = this.nodeFactory(id, "symbol"); var node = this.nodeFactory(null, "polygon"); symbolNode.appendChild(node); var symbolExtent = new OpenLayers.Bounds( Number.MAX_VALUE, Number.MAX_VALUE, 0, 0); var points = []; var x,y; for (var i=0, len=symbol.length; i object * * Returns: * {String} A feature id or undefined. */ getFeatureIdFromEvent: function(evt) { var featureId = OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this, arguments); if(!featureId) { var target = evt.target; featureId = target.parentNode && target != this.rendererRoot ? target.parentNode._featureId : undefined; } return featureId; }, CLASS_NAME: "OpenLayers.Renderer.SVG2" }); /** * Constant: OpenLayers.Renderer.SVG2.LABEL_ALIGN * {Object} */ OpenLayers.Renderer.SVG2.LABEL_ALIGN = { "l": "start", "r": "end", "b": "bottom", "t": "hanging" }; /** * Constant: OpenLayers.Renderer.SVG2.LABEL_VSHIFT * {Object} */ OpenLayers.Renderer.SVG2.LABEL_VSHIFT = { // according to // http://www.w3.org/Graphics/SVG/Test/20061213/htmlObjectHarness/full-text-align-02-b.html // a baseline-shift of -70% shifts the text exactly from the // bottom to the top of the baseline, so -35% moves the text to // the center of the baseline. "t": "-70%", "b": "0" }; /** * Constant: OpenLayers.Renderer.SVG2.LABEL_VFACTOR * {Object} */ OpenLayers.Renderer.SVG2.LABEL_VFACTOR = { "t": 0, "b": -1 }; /** * Function: OpenLayers.Renderer.SVG2.preventDefault * Used to prevent default events (especially opening images in a new tab on * ctrl-click) from being executed for externalGraphic and graphicName symbols */ OpenLayers.Renderer.SVG2.preventDefault = function(e) { e.preventDefault && e.preventDefault(); }; /** * Class: OpenLayers.Popup.AnchoredBubble * This class is *deprecated*. Use {} and * round corners using CSS3's border-radius property. * * Inherits from: * - */ OpenLayers.Popup.AnchoredBubble = OpenLayers.Class(OpenLayers.Popup.Anchored, { /** * Property: rounded * {Boolean} Has the popup been rounded yet? */ rounded: false, /** * Constructor: OpenLayers.Popup.AnchoredBubble * * Parameters: * id - {String} * lonlat - {} * contentSize - {} * contentHTML - {String} * anchor - {Object} Object to which we'll anchor the popup. Must expose * a 'size' () and 'offset' () * (Note that this is generally an ). * closeBox - {Boolean} * closeBoxCallback - {Function} Function to be called on closeBox click. */ initialize:function(id, lonlat, contentSize, contentHTML, anchor, closeBox, closeBoxCallback) { this.padding = new OpenLayers.Bounds( 0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE, 0, OpenLayers.Popup.AnchoredBubble.CORNER_SIZE ); OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments); }, /** * Method: draw * * Parameters: * px - {} * * Returns: * {DOMElement} Reference to a div that contains the drawn popup. */ draw: function(px) { OpenLayers.Popup.Anchored.prototype.draw.apply(this, arguments); this.setContentHTML(); //set the popup color and opacity this.setBackgroundColor(); this.setOpacity(); return this.div; }, /** * Method: updateRelativePosition * The popup has been moved to a new relative location, in which case * we will want to re-do the rico corners. */ updateRelativePosition: function() { this.setRicoCorners(); }, /** * APIMethod: setSize * * Parameters: * contentSize - {} the new size for the popup's * contents div (in pixels). */ setSize:function(contentSize) { OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments); this.setRicoCorners(); }, /** * APIMethod: setBackgroundColor * * Parameters: * color - {String} */ setBackgroundColor:function(color) { if (color != undefined) { this.backgroundColor = color; } if (this.div != null) { if (this.contentDiv != null) { this.div.style.background = "transparent"; OpenLayers.Rico.Corner.changeColor(this.groupDiv, this.backgroundColor); } } }, /** * APIMethod: setOpacity * * Parameters: * opacity - {float} */ setOpacity:function(opacity) { OpenLayers.Popup.Anchored.prototype.setOpacity.call(this, opacity); if (this.div != null) { if (this.groupDiv != null) { OpenLayers.Rico.Corner.changeOpacity(this.groupDiv, this.opacity); } } }, /** * Method: setBorder * Always sets border to 0. Bubble Popups can not have a border. * * Parameters: * border - {Integer} */ setBorder:function(border) { this.border = 0; }, /** * Method: setRicoCorners * Update RICO corners according to the popup's current relative postion. */ setRicoCorners:function() { var corners = this.getCornersToRound(this.relativePosition); var options = {corners: corners, color: this.backgroundColor, bgColor: "transparent", blend: false}; if (!this.rounded) { OpenLayers.Rico.Corner.round(this.div, options); this.rounded = true; } else { OpenLayers.Rico.Corner.reRound(this.groupDiv, options); //set the popup color and opacity this.setBackgroundColor(); this.setOpacity(); } }, /** * Method: getCornersToRound * * Returns: * {String} The proper corners string ("tr tl bl br") for rico to round. */ getCornersToRound:function() { var corners = ['tl', 'tr', 'bl', 'br']; //we want to round all the corners _except_ the opposite one. var corner = OpenLayers.Bounds.oppositeQuadrant(this.relativePosition); OpenLayers.Util.removeItem(corners, corner); return corners.join(" "); }, CLASS_NAME: "OpenLayers.Popup.AnchoredBubble" }); /** * Constant: CORNER_SIZE * {Integer} 5. Border space for the RICO corners. */ OpenLayers.Popup.AnchoredBubble.CORNER_SIZE = 5;