2010-01-18 Miguel de Dios <miguel.dedios@artica.es>

* include/javascript/OpenLayers/*: commit lost files of OpenLayer library.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@2293 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
mdtrooper 2010-01-21 17:02:47 +00:00
parent a3f1d2b8b1
commit 1157b194dd
42 changed files with 15420 additions and 0 deletions

View File

@ -1,3 +1,7 @@
2010-01-18 Miguel de Dios <miguel.dedios@artica.es>
* include/javascript/OpenLayers/*: commit lost files of OpenLayer library.
2010-01-20 Ramon Novoa <rnovoa@artica.es>
* godmode/setup/file_manager.php: Added support for file and empty

View File

@ -0,0 +1,677 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Request/XMLHttpRequest.js
* @requires OpenLayers/Console.js
*/
OpenLayers.ProxyHost = "";
//OpenLayers.ProxyHost = "examples/proxy.cgi?url=";
/**
* Ajax reader for OpenLayers
*
* @uri url to do remote XML http get
* @param {String} 'get' format params (x=y&a=b...)
* @who object to handle callbacks for this request
* @complete the function to be called on success
* @failure the function to be called on failure
*
* example usage from a caller:
*
* caps: function(request) {
* -blah-
* },
*
* OpenLayers.loadURL(url,params,this,caps);
*
* Notice the above example does not provide an error handler; a default empty
* handler is provided which merely logs the error if a failure handler is not
* supplied
*
*/
/**
* Function: OpenLayers.nullHandler
* @param {} request
*/
OpenLayers.nullHandler = function(request) {
OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest", {'statusText':request.statusText}));
};
/**
* APIFunction: loadURL
* Background load a document. For more flexibility in using XMLHttpRequest,
* see the <OpenLayers.Request> methods.
*
* 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, <OpenLayers.nullHandler> 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, <OpenLayers.nullHandler> will be called
* (which pops up a user friendly error message dialog).
*
* Returns:
* {<OpenLayers.Request.XMLHttpRequest>} 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: 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;
};
/**
* Namespace: OpenLayers.Ajax
*/
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 <OpenLayers.Request> method instead.
*
* Inherit:
* - <OpenLayers.Ajax.Base>
*/
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 <OpenLayers.Ajax.Responders>
* 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;
};

View File

@ -0,0 +1,529 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/BaseTypes/Class.js
* @requires OpenLayers/BaseTypes/LonLat.js
* @requires OpenLayers/BaseTypes/Size.js
* @requires OpenLayers/BaseTypes/Pixel.js
* @requires OpenLayers/BaseTypes/Bounds.js
* @requires OpenLayers/BaseTypes/Element.js
* @requires OpenLayers/Lang/en.js
* @requires OpenLayers/Console.js
*/
/**
* Header: OpenLayers Base Types
* OpenLayers custom string, number and function functions are described here.
*/
/**
* Namespace: OpenLayers.String
* Contains convenience functions for string manipulation.
*/
OpenLayers.String = {
/**
* APIFunction: startsWith
* Test whether a string starts with another string.
*
* Parameters:
* str - {String} The string to test.
* sub - {Sring} The substring to look for.
*
* Returns:
* {Boolean} The first string starts with the second.
*/
startsWith: function(str, sub) {
return (str.indexOf(sub) == 0);
},
/**
* APIFunction: contains
* Test whether a string contains another string.
*
* Parameters:
* str - {String} The string to test.
* sub - {String} The substring to look for.
*
* Returns:
* {Boolean} The first string contains the second.
*/
contains: function(str, sub) {
return (str.indexOf(sub) != -1);
},
/**
* APIFunction: trim
* Removes leading and trailing whitespace characters from a string.
*
* Parameters:
* str - {String} The (potentially) space padded string. This string is not
* modified.
*
* Returns:
* {String} A trimmed version of the string with all leading and
* trailing spaces removed.
*/
trim: function(str) {
return str.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
},
/**
* APIFunction: camelize
* Camel-case a hyphenated string.
* Ex. "chicken-head" becomes "chickenHead", and
* "-chicken-head" becomes "ChickenHead".
*
* Parameters:
* str - {String} The string to be camelized. The original is not modified.
*
* Returns:
* {String} The string, camelized
*/
camelize: function(str) {
var oStringList = str.split('-');
var camelizedString = oStringList[0];
for (var i=1, len=oStringList.length; i<len; i++) {
var s = oStringList[i];
camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
}
return camelizedString;
},
/**
* APIFunction: format
* Given a string with tokens in the form ${token}, return a string
* with tokens replaced with properties from the given context
* object. Represent a literal "${" by doubling it, e.g. "${${".
*
* Parameters:
* template - {String} A string with tokens to be replaced. A template
* has the form "literal ${token}" where the token will be replaced
* by the value of context["token"].
* context - {Object} An optional object with properties corresponding
* to the tokens in the format string. If no context is sent, the
* window object will be used.
* args - {Array} Optional arguments to pass to any functions found in
* the context. If a context property is a function, the token
* will be replaced by the return from the function called with
* these arguments.
*
* Returns:
* {String} A string with tokens replaced from the context object.
*/
format: function(template, context, args) {
if(!context) {
context = window;
}
// Example matching:
// str = ${foo.bar}
// match = foo.bar
var replacer = function(str, match) {
var replacement;
// Loop through all subs. Example: ${a.b.c}
// 0 -> replacement = context[a];
// 1 -> replacement = context[a][b];
// 2 -> replacement = context[a][b][c];
var subs = match.split(/\.+/);
for (var i=0; i< subs.length; i++) {
if (i == 0) {
replacement = context;
}
replacement = replacement[subs[i]];
}
if(typeof replacement == "function") {
replacement = args ?
replacement.apply(null, args) :
replacement();
}
// If replacement is undefined, return the string 'undefined'.
// This is a workaround for a bugs in browsers not properly
// dealing with non-participating groups in regular expressions:
// http://blog.stevenlevithan.com/archives/npcg-javascript
if (typeof replacement == 'undefined') {
return 'undefined';
} else {
return replacement;
}
};
return template.replace(OpenLayers.String.tokenRegEx, replacer);
},
/**
* Property: OpenLayers.String.tokenRegEx
* Used to find tokens in a string.
* Examples: ${a}, ${a.b.c}, ${a-b}, ${5}
*/
tokenRegEx: /\$\{([\w.]+?)\}/g,
/**
* Property: OpenLayers.String.numberRegEx
* Used to test strings as numbers.
*/
numberRegEx: /^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,
/**
* APIFunction: OpenLayers.String.isNumeric
* Determine whether a string contains only a numeric value.
*
* Examples:
* (code)
* OpenLayers.String.isNumeric("6.02e23") // true
* OpenLayers.String.isNumeric("12 dozen") // false
* OpenLayers.String.isNumeric("4") // true
* OpenLayers.String.isNumeric(" 4 ") // false
* (end)
*
* Returns:
* {Boolean} String contains only a number.
*/
isNumeric: function(value) {
return OpenLayers.String.numberRegEx.test(value);
},
/**
* APIFunction: numericIf
* Converts a string that appears to be a numeric value into a number.
*
* Returns
* {Number|String} a Number if the passed value is a number, a String
* otherwise.
*/
numericIf: function(value) {
return OpenLayers.String.isNumeric(value) ? parseFloat(value) : value;
}
};
if (!String.prototype.startsWith) {
/**
* APIMethod: String.startsWith
* *Deprecated*. Whether or not a string starts with another string.
*
* Parameters:
* sStart - {Sring} The string we're testing for.
*
* Returns:
* {Boolean} Whether or not this string starts with the string passed in.
*/
String.prototype.startsWith = function(sStart) {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.String.startsWith'}));
return OpenLayers.String.startsWith(this, sStart);
};
}
if (!String.prototype.contains) {
/**
* APIMethod: String.contains
* *Deprecated*. Whether or not a string contains another string.
*
* Parameters:
* str - {String} The string that we're testing for.
*
* Returns:
* {Boolean} Whether or not this string contains with the string passed in.
*/
String.prototype.contains = function(str) {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.String.contains'}));
return OpenLayers.String.contains(this, str);
};
}
if (!String.prototype.trim) {
/**
* APIMethod: String.trim
* *Deprecated*. Removes leading and trailing whitespace characters from a string.
*
* Returns:
* {String} A trimmed version of the string - all leading and
* trailing spaces removed
*/
String.prototype.trim = function() {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.String.trim'}));
return OpenLayers.String.trim(this);
};
}
if (!String.prototype.camelize) {
/**
* APIMethod: String.camelize
* *Deprecated*. Camel-case a hyphenated string.
* Ex. "chicken-head" becomes "chickenHead", and
* "-chicken-head" becomes "ChickenHead".
*
* Returns:
* {String} The string, camelized
*/
String.prototype.camelize = function() {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.String.camelize'}));
return OpenLayers.String.camelize(this);
};
}
/**
* Namespace: OpenLayers.Number
* Contains convenience functions for manipulating numbers.
*/
OpenLayers.Number = {
/**
* Property: decimalSeparator
* Decimal separator to use when formatting numbers.
*/
decimalSeparator: ".",
/**
* Property: thousandsSeparator
* Thousands separator to use when formatting numbers.
*/
thousandsSeparator: ",",
/**
* APIFunction: limitSigDigs
* Limit the number of significant digits on a float.
*
* Parameters:
* num - {Float}
* sig - {Integer}
*
* Returns:
* {Float} The number, rounded to the specified number of significant
* digits.
*/
limitSigDigs: function(num, sig) {
var fig = 0;
if (sig > 0) {
fig = parseFloat(num.toPrecision(sig));
}
return fig;
},
/**
* APIFunction: format
* Formats a number for output.
*
* Parameters:
* num - {Float}
* dec - {Integer} Number of decimal places to round to.
* Defaults to 0. Set to null to leave decimal places unchanged.
* tsep - {String} Thousands separator.
* Default is ",".
* dsep - {String} Decimal separator.
* Default is ".".
*
* Returns:
* {String} A string representing the formatted number.
*/
format: function(num, dec, tsep, dsep) {
dec = (typeof dec != "undefined") ? dec : 0;
tsep = (typeof tsep != "undefined") ? tsep :
OpenLayers.Number.thousandsSeparator;
dsep = (typeof dsep != "undefined") ? dsep :
OpenLayers.Number.decimalSeparator;
if (dec != null) {
num = parseFloat(num.toFixed(dec));
}
var parts = num.toString().split(".");
if (parts.length == 1 && dec == null) {
// integer where we do not want to touch the decimals
dec = 0;
}
var integer = parts[0];
if (tsep) {
var thousands = /(-?[0-9]+)([0-9]{3})/;
while(thousands.test(integer)) {
integer = integer.replace(thousands, "$1" + tsep + "$2");
}
}
var str;
if (dec == 0) {
str = integer;
} else {
var rem = parts.length > 1 ? parts[1] : "0";
if (dec != null) {
rem = rem + new Array(dec - rem.length + 1).join("0");
}
str = integer + dsep + rem;
}
return str;
}
};
if (!Number.prototype.limitSigDigs) {
/**
* APIMethod: Number.limitSigDigs
* *Deprecated*. Limit the number of significant digits on an integer. Does *not*
* work with floats!
*
* Parameters:
* sig - {Integer}
*
* Returns:
* {Integer} The number, rounded to the specified number of significant digits.
* If null, 0, or negative value passed in, returns 0
*/
Number.prototype.limitSigDigs = function(sig) {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.Number.limitSigDigs'}));
return OpenLayers.Number.limitSigDigs(this, sig);
};
}
/**
* Namespace: OpenLayers.Function
* Contains convenience functions for function manipulation.
*/
OpenLayers.Function = {
/**
* APIFunction: bind
* Bind a function to an object. Method to easily create closures with
* 'this' altered.
*
* Parameters:
* func - {Function} Input function.
* object - {Object} The object to bind to the input function (as this).
*
* Returns:
* {Function} A closure with 'this' set to the passed in object.
*/
bind: function(func, object) {
// create a reference to all arguments past the second one
var args = Array.prototype.slice.apply(arguments, [2]);
return function() {
// Push on any additional arguments from the actual function call.
// These will come after those sent to the bind call.
var newArgs = args.concat(
Array.prototype.slice.apply(arguments, [0])
);
return func.apply(object, newArgs);
};
},
/**
* APIFunction: bindAsEventListener
* Bind a function to an object, and configure it to receive the event
* object as first parameter when called.
*
* Parameters:
* func - {Function} Input function to serve as an event listener.
* object - {Object} A reference to this.
*
* Returns:
* {Function}
*/
bindAsEventListener: function(func, object) {
return function(event) {
return func.call(object, event || window.event);
};
}
};
if (!Function.prototype.bind) {
/**
* APIMethod: Function.bind
* *Deprecated*. Bind a function to an object.
* Method to easily create closures with 'this' altered.
*
* Parameters:
* object - {Object} the this parameter
*
* Returns:
* {Function} A closure with 'this' altered to the first
* argument.
*/
Function.prototype.bind = function() {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.Function.bind'}));
// new function takes the same arguments with this function up front
Array.prototype.unshift.apply(arguments, [this]);
return OpenLayers.Function.bind.apply(null, arguments);
};
}
if (!Function.prototype.bindAsEventListener) {
/**
* APIMethod: Function.bindAsEventListener
* *Deprecated*. Bind a function to an object, and configure it to receive the
* event object as first parameter when called.
*
* Parameters:
* object - {Object} A reference to this.
*
* Returns:
* {Function}
*/
Function.prototype.bindAsEventListener = function(object) {
OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",
{'newMethod':'OpenLayers.Function.bindAsEventListener'}));
return OpenLayers.Function.bindAsEventListener(this, object);
};
}
/**
* Namespace: OpenLayers.Array
* Contains convenience functions for array manipulation.
*/
OpenLayers.Array = {
/**
* APIMethod: filter
* Filter an array. Provides the functionality of the
* Array.prototype.filter extension to the ECMA-262 standard. Where
* available, Array.prototype.filter will be used.
*
* Based on well known example from http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Array:filter
*
* Parameters:
* array - {Array} The array to be filtered. This array is not mutated.
* Elements added to this array by the callback will not be visited.
* callback - {Function} A function that is called for each element in
* the array. If this function returns true, the element will be
* included in the return. The function will be called with three
* arguments: the element in the array, the index of that element, and
* the array itself. If the optional caller parameter is specified
* the callback will be called with this set to caller.
* caller - {Object} Optional object to be set as this when the callback
* is called.
*
* Returns:
* {Array} An array of elements from the passed in array for which the
* callback returns true.
*/
filter: function(array, callback, caller) {
var selected = [];
if (Array.prototype.filter) {
selected = array.filter(callback, caller);
} else {
var len = array.length;
if (typeof callback != "function") {
throw new TypeError();
}
for(var i=0; i<len; i++) {
if (i in array) {
var val = array[i];
if (callback.call(caller, val, i, array)) {
selected.push(val);
}
}
}
}
return selected;
}
};

View File

@ -0,0 +1,245 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Namespace: OpenLayers.Console
* The OpenLayers.Console namespace is used for debugging and error logging.
* If the Firebug Lite (../Firebug/firebug.js) is included before this script,
* calls to OpenLayers.Console methods will get redirected to window.console.
* This makes use of the Firebug extension where available and allows for
* cross-browser debugging Firebug style.
*
* Note:
* Note that behavior will differ with the Firebug extention and Firebug Lite.
* Most notably, the Firebug Lite console does not currently allow for
* hyperlinks to code or for clicking on object to explore their properties.
*
*/
OpenLayers.Console = {
/**
* Create empty functions for all console methods. The real value of these
* properties will be set if Firebug Lite (../Firebug/firebug.js script) is
* included. We explicitly require the Firebug Lite script to trigger
* functionality of the OpenLayers.Console methods.
*/
/**
* APIFunction: log
* Log an object in the console. The Firebug Lite console logs string
* representation of objects. Given multiple arguments, they will
* be cast to strings and logged with a space delimiter. If the first
* argument is a string with printf-like formatting, subsequent arguments
* will be used in string substitution. Any additional arguments (beyond
* the number substituted in a format string) will be appended in a space-
* delimited line.
*
* Parameters:
* object - {Object}
*/
log: function() {},
/**
* APIFunction: debug
* Writes a message to the console, including a hyperlink to the line
* where it was called.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
debug: function() {},
/**
* APIFunction: info
* Writes a message to the console with the visual "info" icon and color
* coding and a hyperlink to the line where it was called.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
info: function() {},
/**
* APIFunction: warn
* Writes a message to the console with the visual "warning" icon and
* color coding and a hyperlink to the line where it was called.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
warn: function() {},
/**
* APIFunction: error
* Writes a message to the console with the visual "error" icon and color
* coding and a hyperlink to the line where it was called.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
error: function() {},
/**
* APIFunction: userError
* A single interface for showing error messages to the user. The default
* behavior is a Javascript alert, though this can be overridden by
* reassigning OpenLayers.Console.userError to a different function.
*
* Expects a single error message
*
* Parameters:
* object - {Object}
*/
userError: function(error) {
alert(error);
},
/**
* APIFunction: assert
* Tests that an expression is true. If not, it will write a message to
* the console and throw an exception.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
assert: function() {},
/**
* APIFunction: dir
* Prints an interactive listing of all properties of the object. This
* looks identical to the view that you would see in the DOM tab.
*
* Parameters:
* object - {Object}
*/
dir: function() {},
/**
* APIFunction: dirxml
* Prints the XML source tree of an HTML or XML element. This looks
* identical to the view that you would see in the HTML tab. You can click
* on any node to inspect it in the HTML tab.
*
* Parameters:
* object - {Object}
*/
dirxml: function() {},
/**
* APIFunction: trace
* Prints an interactive stack trace of JavaScript execution at the point
* where it is called. The stack trace details the functions on the stack,
* as well as the values that were passed as arguments to each function.
* You can click each function to take you to its source in the Script tab,
* and click each argument value to inspect it in the DOM or HTML tabs.
*
*/
trace: function() {},
/**
* APIFunction: group
* Writes a message to the console and opens a nested block to indent all
* future messages sent to the console. Call OpenLayers.Console.groupEnd()
* to close the block.
*
* May be called with multiple arguments as with OpenLayers.Console.log().
*
* Parameters:
* object - {Object}
*/
group: function() {},
/**
* APIFunction: groupEnd
* Closes the most recently opened block created by a call to
* OpenLayers.Console.group
*/
groupEnd: function() {},
/**
* APIFunction: time
* Creates a new timer under the given name. Call
* OpenLayers.Console.timeEnd(name)
* with the same name to stop the timer and print the time elapsed.
*
* Parameters:
* name - {String}
*/
time: function() {},
/**
* APIFunction: timeEnd
* Stops a timer created by a call to OpenLayers.Console.time(name) and
* writes the time elapsed.
*
* Parameters:
* name - {String}
*/
timeEnd: function() {},
/**
* APIFunction: profile
* Turns on the JavaScript profiler. The optional argument title would
* contain the text to be printed in the header of the profile report.
*
* This function is not currently implemented in Firebug Lite.
*
* Parameters:
* title - {String} Optional title for the profiler
*/
profile: function() {},
/**
* APIFunction: profileEnd
* Turns off the JavaScript profiler and prints its report.
*
* This function is not currently implemented in Firebug Lite.
*/
profileEnd: function() {},
/**
* APIFunction: count
* Writes the number of times that the line of code where count was called
* was executed. The optional argument title will print a message in
* addition to the number of the count.
*
* This function is not currently implemented in Firebug Lite.
*
* Parameters:
* title - {String} Optional title to be printed with count
*/
count: function() {},
CLASS_NAME: "OpenLayers.Console"
};
/**
* Execute an anonymous function to extend the OpenLayers.Console namespace
* if the firebug.js script is included. This closure is used so that the
* "scripts" and "i" variables don't pollute the global namespace.
*/
(function() {
/**
* If Firebug Lite is included (before this script), re-route all
* OpenLayers.Console calls to the console object.
*/
var scripts = document.getElementsByTagName("script");
for(var i=0, len=scripts.length; i<len; ++i) {
if(scripts[i].src.indexOf("firebug.js") != -1) {
if(console) {
OpenLayers.Util.extend(OpenLayers.Console, console);
break;
}
}
}
})();

View File

@ -0,0 +1,349 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Console.js
*/
/**
* Class: OpenLayers.Control
* Controls affect the display or behavior of the map. They allow everything
* from panning and zooming to displaying a scale indicator. Controls by
* default are added to the map they are contained within however it is
* possible to add a control to an external div by passing the div in the
* options parameter.
*
* Example:
* The following example shows how to add many of the common controls
* to a map.
*
* > var map = new OpenLayers.Map('map', { controls: [] });
* >
* > map.addControl(new OpenLayers.Control.PanZoomBar());
* > map.addControl(new OpenLayers.Control.MouseToolbar());
* > map.addControl(new OpenLayers.Control.LayerSwitcher({'ascending':false}));
* > map.addControl(new OpenLayers.Control.Permalink());
* > map.addControl(new OpenLayers.Control.Permalink('permalink'));
* > map.addControl(new OpenLayers.Control.MousePosition());
* > map.addControl(new OpenLayers.Control.OverviewMap());
* > map.addControl(new OpenLayers.Control.KeyboardDefaults());
*
* The next code fragment is a quick example of how to intercept
* shift-mouse click to display the extent of the bounding box
* dragged out by the user. Usually controls are not created
* in exactly this manner. See the source for a more complete
* example:
*
* > var control = new OpenLayers.Control();
* > OpenLayers.Util.extend(control, {
* > draw: function () {
* > // this Handler.Box will intercept the shift-mousedown
* > // before Control.MouseDefault gets to see it
* > this.box = new OpenLayers.Handler.Box( control,
* > {"done": this.notice},
* > {keyMask: OpenLayers.Handler.MOD_SHIFT});
* > this.box.activate();
* > },
* >
* > notice: function (bounds) {
* > OpenLayers.Console.userError(bounds);
* > }
* > });
* > map.addControl(control);
*
*/
OpenLayers.Control = OpenLayers.Class({
/**
* Property: id
* {String}
*/
id: null,
/**
* Property: map
* {<OpenLayers.Map>} this gets set in the addControl() function in
* OpenLayers.Map
*/
map: null,
/**
* Property: div
* {DOMElement}
*/
div: null,
/**
* Property: type
* {OpenLayers.Control.TYPES} Controls can have a 'type'. The type
* determines the type of interactions which are possible with them when
* they are placed into a toolbar.
*/
type: null,
/**
* Property: allowSelection
* {Boolean} By deafault, controls do not allow selection, because
* it may interfere with map dragging. If this is true, OpenLayers
* will not prevent selection of the control.
* Default is false.
*/
allowSelection: false,
/**
* Property: displayClass
* {string} This property is used for CSS related to the drawing of the
* Control.
*/
displayClass: "",
/**
* Property: title
* {string} This property is used for showing a tooltip over the
* Control.
*/
title: "",
/**
* Property: active
* {Boolean} The control is active.
*/
active: null,
/**
* Property: handler
* {<OpenLayers.Handler>} null
*/
handler: null,
/**
* APIProperty: eventListeners
* {Object} If set as an option at construction, the eventListeners
* object will be registered with <OpenLayers.Events.on>. Object
* structure must be a listeners object as shown in the example for
* the events.on method.
*/
eventListeners: null,
/**
* Property: events
* {<OpenLayers.Events>} Events instance for triggering control specific
* events.
*/
events: null,
/**
* Constant: EVENT_TYPES
* {Array(String)} Supported application event types. Register a listener
* for a particular event with the following syntax:
* (code)
* control.events.register(type, obj, listener);
* (end)
*
* Listeners will be called with a reference to an event object. The
* properties of this event depends on exactly what happened.
*
* All event objects have at least the following properties:
* object - {Object} A reference to control.events.object (a reference
* to the control).
* element - {DOMElement} A reference to control.events.element (which
* will be null unless documented otherwise).
*
* Supported map event types:
* activate - Triggered when activated.
* deactivate - Triggered when deactivated.
*/
EVENT_TYPES: ["activate", "deactivate"],
/**
* Constructor: OpenLayers.Control
* Create an OpenLayers Control. The options passed as a parameter
* directly extend the control. For example passing the following:
*
* > var control = new OpenLayers.Control({div: myDiv});
*
* Overrides the default div attribute value of null.
*
* Parameters:
* options - {Object}
*/
initialize: function (options) {
// We do this before the extend so that instances can override
// className in options.
this.displayClass =
this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
OpenLayers.Util.extend(this, options);
this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
if(this.eventListeners instanceof Object) {
this.events.on(this.eventListeners);
}
if (this.id == null) {
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
}
},
/**
* Method: destroy
* The destroy method is used to perform any clean up before the control
* is dereferenced. Typically this is where event listeners are removed
* to prevent memory leaks.
*/
destroy: function () {
if(this.events) {
if(this.eventListeners) {
this.events.un(this.eventListeners);
}
this.events.destroy();
this.events = null;
}
this.eventListeners = null;
// eliminate circular references
if (this.handler) {
this.handler.destroy();
this.handler = null;
}
if(this.handlers) {
for(var key in this.handlers) {
if(this.handlers.hasOwnProperty(key) &&
typeof this.handlers[key].destroy == "function") {
this.handlers[key].destroy();
}
}
this.handlers = null;
}
if (this.map) {
this.map.removeControl(this);
this.map = null;
}
},
/**
* Method: setMap
* Set the map property for the control. This is done through an accessor
* so that subclasses can override this and take special action once
* they have their map variable set.
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
this.map = map;
if (this.handler) {
this.handler.setMap(map);
}
},
/**
* Method: draw
* The draw method is called when the control is ready to be displayed
* on the page. If a div has not been created one is created. Controls
* with a visual component will almost always want to override this method
* to customize the look of control.
*
* Parameters:
* px - {<OpenLayers.Pixel>} The top-left pixel position of the control
* or null.
*
* Returns:
* {DOMElement} A reference to the DIV DOMElement containing the control
*/
draw: function (px) {
if (this.div == null) {
this.div = OpenLayers.Util.createDiv(this.id);
this.div.className = this.displayClass;
if (!this.allowSelection) {
this.div.className += " olControlNoSelect";
this.div.setAttribute("unselectable", "on", 0);
this.div.onselectstart = function() { return(false); };
}
if (this.title != "") {
this.div.title = this.title;
}
}
if (px != null) {
this.position = px.clone();
}
this.moveTo(this.position);
return this.div;
},
/**
* Method: moveTo
* Sets the left and top style attributes to the passed in pixel
* coordinates.
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*/
moveTo: function (px) {
if ((px != null) && (this.div != null)) {
this.div.style.left = px.x + "px";
this.div.style.top = px.y + "px";
}
},
/**
* Method: activate
* Explicitly activates a control and it's associated
* handler if one has been set. Controls can be
* deactivated by calling the deactivate() method.
*
* Returns:
* {Boolean} True if the control was successfully activated or
* false if the control was already active.
*/
activate: function () {
if (this.active) {
return false;
}
if (this.handler) {
this.handler.activate();
}
this.active = true;
if(this.map) {
OpenLayers.Element.addClass(
this.map.viewPortDiv,
this.displayClass.replace(/ /g, "") + "Active"
);
}
this.events.triggerEvent("activate");
return true;
},
/**
* Method: deactivate
* Deactivates a control and it's associated handler if any. The exact
* effect of this depends on the control itself.
*
* Returns:
* {Boolean} True if the control was effectively deactivated or false
* if the control was already inactive.
*/
deactivate: function () {
if (this.active) {
if (this.handler) {
this.handler.deactivate();
}
this.active = false;
if(this.map) {
OpenLayers.Element.removeClass(
this.map.viewPortDiv,
this.displayClass.replace(/ /g, "") + "Active"
);
}
this.events.triggerEvent("deactivate");
return true;
}
return false;
},
CLASS_NAME: "OpenLayers.Control"
});
OpenLayers.Control.TYPE_BUTTON = 1;
OpenLayers.Control.TYPE_TOGGLE = 2;
OpenLayers.Control.TYPE_TOOL = 3;

View File

@ -0,0 +1,828 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Util.js
*/
/**
* Namespace: OpenLayers.Event
* Utility functions for event handling.
*/
OpenLayers.Event = {
/**
* Property: observers
* {Object} A hashtable cache of the event observers. Keyed by
* element._eventCacheID
*/
observers: false,
/**
* Constant: KEY_BACKSPACE
* {int}
*/
KEY_BACKSPACE: 8,
/**
* Constant: KEY_TAB
* {int}
*/
KEY_TAB: 9,
/**
* Constant: KEY_RETURN
* {int}
*/
KEY_RETURN: 13,
/**
* Constant: KEY_ESC
* {int}
*/
KEY_ESC: 27,
/**
* Constant: KEY_LEFT
* {int}
*/
KEY_LEFT: 37,
/**
* Constant: KEY_UP
* {int}
*/
KEY_UP: 38,
/**
* Constant: KEY_RIGHT
* {int}
*/
KEY_RIGHT: 39,
/**
* Constant: KEY_DOWN
* {int}
*/
KEY_DOWN: 40,
/**
* Constant: KEY_DELETE
* {int}
*/
KEY_DELETE: 46,
/**
* Method: element
* Cross browser event element detection.
*
* Parameters:
* event - {Event}
*
* Returns:
* {DOMElement} The element that caused the event
*/
element: function(event) {
return event.target || event.srcElement;
},
/**
* Method: isLeftClick
* Determine whether event was caused by a left click.
*
* Parameters:
* event - {Event}
*
* Returns:
* {Boolean}
*/
isLeftClick: function(event) {
return (((event.which) && (event.which == 1)) ||
((event.button) && (event.button == 1)));
},
/**
* Method: isRightClick
* Determine whether event was caused by a right mouse click.
*
* Parameters:
* event - {Event}
*
* Returns:
* {Boolean}
*/
isRightClick: function(event) {
return (((event.which) && (event.which == 3)) ||
((event.button) && (event.button == 2)));
},
/**
* Method: stop
* Stops an event from propagating.
*
* Parameters:
* event - {Event}
* allowDefault - {Boolean} If true, we stop the event chain but
* still allow the default browser
* behaviour (text selection, radio-button
* clicking, etc)
* Default false
*/
stop: function(event, allowDefault) {
if (!allowDefault) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
}
if (event.stopPropagation) {
event.stopPropagation();
} else {
event.cancelBubble = true;
}
},
/**
* Method: findElement
*
* Parameters:
* event - {Event}
* tagName - {String}
*
* Returns:
* {DOMElement} The first node with the given tagName, starting from the
* node the event was triggered on and traversing the DOM upwards
*/
findElement: function(event, tagName) {
var element = OpenLayers.Event.element(event);
while (element.parentNode && (!element.tagName ||
(element.tagName.toUpperCase() != tagName.toUpperCase()))){
element = element.parentNode;
}
return element;
},
/**
* Method: observe
*
* Parameters:
* elementParam - {DOMElement || String}
* name - {String}
* observer - {function}
* useCapture - {Boolean}
*/
observe: function(elementParam, name, observer, useCapture) {
var element = OpenLayers.Util.getElement(elementParam);
useCapture = useCapture || false;
if (name == 'keypress' &&
(navigator.appVersion.match(/Konqueror|Safari|KHTML/)
|| element.attachEvent)) {
name = 'keydown';
}
//if observers cache has not yet been created, create it
if (!this.observers) {
this.observers = {};
}
//if not already assigned, make a new unique cache ID
if (!element._eventCacheID) {
var idPrefix = "eventCacheID_";
if (element.id) {
idPrefix = element.id + "_" + idPrefix;
}
element._eventCacheID = OpenLayers.Util.createUniqueID(idPrefix);
}
var cacheID = element._eventCacheID;
//if there is not yet a hash entry for this element, add one
if (!this.observers[cacheID]) {
this.observers[cacheID] = [];
}
//add a new observer to this element's list
this.observers[cacheID].push({
'element': element,
'name': name,
'observer': observer,
'useCapture': useCapture
});
//add the actual browser event listener
if (element.addEventListener) {
element.addEventListener(name, observer, useCapture);
} else if (element.attachEvent) {
element.attachEvent('on' + name, observer);
}
},
/**
* Method: stopObservingElement
* Given the id of an element to stop observing, cycle through the
* element's cached observers, calling stopObserving on each one,
* skipping those entries which can no longer be removed.
*
* parameters:
* elementParam - {DOMElement || String}
*/
stopObservingElement: function(elementParam) {
var element = OpenLayers.Util.getElement(elementParam);
var cacheID = element._eventCacheID;
this._removeElementObservers(OpenLayers.Event.observers[cacheID]);
},
/**
* Method: _removeElementObservers
*
* Parameters:
* elementObservers - {Array(Object)} Array of (element, name,
* observer, usecapture) objects,
* taken directly from hashtable
*/
_removeElementObservers: function(elementObservers) {
if (elementObservers) {
for(var i = elementObservers.length-1; i >= 0; i--) {
var entry = elementObservers[i];
var args = new Array(entry.element,
entry.name,
entry.observer,
entry.useCapture);
var removed = OpenLayers.Event.stopObserving.apply(this, args);
}
}
},
/**
* Method: stopObserving
*
* Parameters:
* elementParam - {DOMElement || String}
* name - {String}
* observer - {function}
* useCapture - {Boolean}
*
* Returns:
* {Boolean} Whether or not the event observer was removed
*/
stopObserving: function(elementParam, name, observer, useCapture) {
useCapture = useCapture || false;
var element = OpenLayers.Util.getElement(elementParam);
var cacheID = element._eventCacheID;
if (name == 'keypress') {
if ( navigator.appVersion.match(/Konqueror|Safari|KHTML/) ||
element.detachEvent) {
name = 'keydown';
}
}
// find element's entry in this.observers cache and remove it
var foundEntry = false;
var elementObservers = OpenLayers.Event.observers[cacheID];
if (elementObservers) {
// find the specific event type in the element's list
var i=0;
while(!foundEntry && i < elementObservers.length) {
var cacheEntry = elementObservers[i];
if ((cacheEntry.name == name) &&
(cacheEntry.observer == observer) &&
(cacheEntry.useCapture == useCapture)) {
elementObservers.splice(i, 1);
if (elementObservers.length == 0) {
delete OpenLayers.Event.observers[cacheID];
}
foundEntry = true;
break;
}
i++;
}
}
//actually remove the event listener from browser
if (foundEntry) {
if (element.removeEventListener) {
element.removeEventListener(name, observer, useCapture);
} else if (element && element.detachEvent) {
element.detachEvent('on' + name, observer);
}
}
return foundEntry;
},
/**
* Method: unloadCache
* Cycle through all the element entries in the events cache and call
* stopObservingElement on each.
*/
unloadCache: function() {
// check for OpenLayers.Event before checking for observers, because
// OpenLayers.Event may be undefined in IE if no map instance was
// created
if (OpenLayers.Event && OpenLayers.Event.observers) {
for (var cacheID in OpenLayers.Event.observers) {
var elementObservers = OpenLayers.Event.observers[cacheID];
OpenLayers.Event._removeElementObservers.apply(this,
[elementObservers]);
}
OpenLayers.Event.observers = false;
}
},
CLASS_NAME: "OpenLayers.Event"
};
/* prevent memory leaks in IE */
OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
// FIXME: Remove this in 3.0. In 3.0, Event.stop will no longer be provided
// by OpenLayers.
if (window.Event) {
OpenLayers.Util.applyDefaults(window.Event, OpenLayers.Event);
} else {
var Event = OpenLayers.Event;
}
/**
* Class: OpenLayers.Events
*/
OpenLayers.Events = OpenLayers.Class({
/**
* Constant: BROWSER_EVENTS
* {Array(String)} supported events
*/
BROWSER_EVENTS: [
"mouseover", "mouseout",
"mousedown", "mouseup", "mousemove",
"click", "dblclick", "rightclick", "dblrightclick",
"resize", "focus", "blur"
],
/**
* Property: listeners
* {Object} Hashtable of Array(Function): events listener functions
*/
listeners: null,
/**
* Property: object
* {Object} the code object issuing application events
*/
object: null,
/**
* Property: element
* {DOMElement} the DOM element receiving browser events
*/
element: null,
/**
* Property: eventTypes
* {Array(String)} list of support application events
*/
eventTypes: null,
/**
* Property: eventHandler
* {Function} bound event handler attached to elements
*/
eventHandler: null,
/**
* APIProperty: fallThrough
* {Boolean}
*/
fallThrough: null,
/**
* APIProperty: includeXY
* {Boolean} Should the .xy property automatically be created for browser
* mouse events? In general, this should be false. If it is true, then
* mouse events will automatically generate a '.xy' property on the
* event object that is passed. (Prior to OpenLayers 2.7, this was true
* by default.) Otherwise, you can call the getMousePosition on the
* relevant events handler on the object available via the 'evt.object'
* property of the evt object. So, for most events, you can call:
* function named(evt) {
* this.xy = this.object.events.getMousePosition(evt)
* }
*
* This option typically defaults to false for performance reasons:
* when creating an events object whose primary purpose is to manage
* relatively positioned mouse events within a div, it may make
* sense to set it to true.
*
* This option is also used to control whether the events object caches
* offsets. If this is false, it will not: the reason for this is that
* it is only expected to be called many times if the includeXY property
* is set to true. If you set this to true, you are expected to clear
* the offset cache manually (using this.clearMouseCache()) if:
* the border of the element changes
* the location of the element in the page changes
*/
includeXY: false,
/**
* Method: clearMouseListener
* A version of <clearMouseCache> that is bound to this instance so that
* it can be used with <OpenLayers.Event.observe> and
* <OpenLayers.Event.stopObserving>.
*/
clearMouseListener: null,
/**
* Constructor: OpenLayers.Events
* Construct an OpenLayers.Events object.
*
* Parameters:
* object - {Object} The js object to which this Events object is being
* added element - {DOMElement} A dom element to respond to browser events
* eventTypes - {Array(String)} Array of custom application events
* fallThrough - {Boolean} Allow events to fall through after these have
* been handled?
* options - {Object} Options for the events object.
*/
initialize: function (object, element, eventTypes, fallThrough, options) {
OpenLayers.Util.extend(this, options);
this.object = object;
this.fallThrough = fallThrough;
this.listeners = {};
// keep a bound copy of handleBrowserEvent() so that we can
// pass the same function to both Event.observe() and .stopObserving()
this.eventHandler = OpenLayers.Function.bindAsEventListener(
this.handleBrowserEvent, this
);
// to be used with observe and stopObserving
this.clearMouseListener = OpenLayers.Function.bind(
this.clearMouseCache, this
);
// if eventTypes is specified, create a listeners list for each
// custom application event.
this.eventTypes = [];
if (eventTypes != null) {
for (var i=0, len=eventTypes.length; i<len; i++) {
this.addEventType(eventTypes[i]);
}
}
// if a dom element is specified, add a listeners list
// for browser events on the element and register them
if (element != null) {
this.attachToElement(element);
}
},
/**
* APIMethod: destroy
*/
destroy: function () {
if (this.element) {
OpenLayers.Event.stopObservingElement(this.element);
if(this.element.hasScrollEvent) {
OpenLayers.Event.stopObserving(
window, "scroll", this.clearMouseListener
);
}
}
this.element = null;
this.listeners = null;
this.object = null;
this.eventTypes = null;
this.fallThrough = null;
this.eventHandler = null;
},
/**
* APIMethod: addEventType
* Add a new event type to this events object.
* If the event type has already been added, do nothing.
*
* Parameters:
* eventName - {String}
*/
addEventType: function(eventName) {
if (!this.listeners[eventName]) {
this.eventTypes.push(eventName);
this.listeners[eventName] = [];
}
},
/**
* Method: attachToElement
*
* Parameters:
* element - {HTMLDOMElement} a DOM element to attach browser events to
*/
attachToElement: function (element) {
if(this.element) {
OpenLayers.Event.stopObservingElement(this.element);
}
this.element = element;
for (var i=0, len=this.BROWSER_EVENTS.length; i<len; i++) {
var eventType = this.BROWSER_EVENTS[i];
// every browser event has a corresponding application event
// (whether it's listened for or not).
this.addEventType(eventType);
// use Prototype to register the event cross-browser
OpenLayers.Event.observe(element, eventType, this.eventHandler);
}
// disable dragstart in IE so that mousedown/move/up works normally
OpenLayers.Event.observe(element, "dragstart", OpenLayers.Event.stop);
},
/**
* Method: on
* Convenience method for registering listeners with a common scope.
*
* Example use:
* (code)
* events.on({
* "loadstart": loadStartListener,
* "loadend": loadEndListener,
* scope: object
* });
* (end)
*/
on: function(object) {
for(var type in object) {
if(type != "scope") {
this.register(type, object.scope, object[type]);
}
}
},
/**
* APIMethod: register
* Register an event on the events object.
*
* When the event is triggered, the 'func' function will be called, in the
* context of 'obj'. Imagine we were to register an event, specifying an
* OpenLayers.Bounds Object as 'obj'. When the event is triggered, the
* context in the callback function will be our Bounds object. This means
* that within our callback function, we can access the properties and
* methods of the Bounds object through the "this" variable. So our
* callback could execute something like:
* : leftStr = "Left: " + this.left;
*
* or
*
* : centerStr = "Center: " + this.getCenterLonLat();
*
* Parameters:
* type - {String} Name of the event to register
* obj - {Object} The object to bind the context to for the callback#.
* If no object is specified, default is the Events's
* 'object' property.
* func - {Function} The callback function. If no callback is
* specified, this function does nothing.
*
*
*/
register: function (type, obj, func) {
if ( (func != null) &&
(OpenLayers.Util.indexOf(this.eventTypes, type) != -1) ) {
if (obj == null) {
obj = this.object;
}
var listeners = this.listeners[type];
listeners.push( {obj: obj, func: func} );
}
},
/**
* APIMethod: registerPriority
* Same as register() but adds the new listener to the *front* of the
* events queue instead of to the end.
*
* TODO: get rid of this in 3.0 - Decide whether listeners should be
* called in the order they were registered or in reverse order.
*
*
* Parameters:
* type - {String} Name of the event to register
* obj - {Object} The object to bind the context to for the callback#.
* If no object is specified, default is the Events's
* 'object' property.
* func - {Function} The callback function. If no callback is
* specified, this function does nothing.
*/
registerPriority: function (type, obj, func) {
if (func != null) {
if (obj == null) {
obj = this.object;
}
var listeners = this.listeners[type];
if (listeners != null) {
listeners.unshift( {obj: obj, func: func} );
}
}
},
/**
* Method: un
* Convenience method for unregistering listeners with a common scope.
*
* Example use:
* (code)
* events.un({
* "loadstart": loadStartListener,
* "loadend": loadEndListener,
* scope: object
* });
* (end)
*/
un: function(object) {
for(var type in object) {
if(type != "scope") {
this.unregister(type, object.scope, object[type]);
}
}
},
/**
* APIMethod: unregister
*
* Parameters:
* type - {String}
* obj - {Object} If none specified, defaults to this.object
* func - {Function}
*/
unregister: function (type, obj, func) {
if (obj == null) {
obj = this.object;
}
var listeners = this.listeners[type];
if (listeners != null) {
for (var i=0, len=listeners.length; i<len; i++) {
if (listeners[i].obj == obj && listeners[i].func == func) {
listeners.splice(i, 1);
break;
}
}
}
},
/**
* Method: remove
* Remove all listeners for a given event type. If type is not registered,
* does nothing.
*
* Parameters:
* type - {String}
*/
remove: function(type) {
if (this.listeners[type] != null) {
this.listeners[type] = [];
}
},
/**
* APIMethod: triggerEvent
* Trigger a specified registered event.
*
* Parameters:
* type - {String}
* evt - {Event}
*
* Returns:
* {Boolean} The last listener return. If a listener returns false, the
* chain of listeners will stop getting called.
*/
triggerEvent: function (type, evt) {
var listeners = this.listeners[type];
// fast path
if(!listeners || listeners.length == 0) {
return;
}
// prep evt object with object & div references
if (evt == null) {
evt = {};
}
evt.object = this.object;
evt.element = this.element;
if(!evt.type) {
evt.type = type;
}
// execute all callbacks registered for specified type
// get a clone of the listeners array to
// allow for splicing during callbacks
var listeners = listeners.slice(), continueChain;
for (var i=0, len=listeners.length; i<len; i++) {
var callback = listeners[i];
// bind the context to callback.obj
continueChain = callback.func.apply(callback.obj, [evt]);
if ((continueChain != undefined) && (continueChain == false)) {
// if callback returns false, execute no more callbacks.
break;
}
}
// don't fall through to other DOM elements
if (!this.fallThrough) {
OpenLayers.Event.stop(evt, true);
}
return continueChain;
},
/**
* Method: handleBrowserEvent
* Basically just a wrapper to the triggerEvent() function, but takes
* care to set a property 'xy' on the event with the current mouse
* position.
*
* Parameters:
* evt - {Event}
*/
handleBrowserEvent: function (evt) {
if (this.includeXY) {
evt.xy = this.getMousePosition(evt);
}
this.triggerEvent(evt.type, evt);
},
/**
* APIMethod: clearMouseCache
* Clear cached data about the mouse position. This should be called any
* time the element that events are registered on changes position
* within the page.
*/
clearMouseCache: function() {
this.element.scrolls = null;
this.element.lefttop = null;
this.element.offsets = null;
},
/**
* Method: getMousePosition
*
* Parameters:
* evt - {Event}
*
* Returns:
* {<OpenLayers.Pixel>} The current xy coordinate of the mouse, adjusted
* for offsets
*/
getMousePosition: function (evt) {
if (!this.includeXY) {
this.clearMouseCache();
} else if (!this.element.hasScrollEvent) {
OpenLayers.Event.observe(window, "scroll", this.clearMouseListener);
this.element.hasScrollEvent = true;
}
if (!this.element.scrolls) {
this.element.scrolls = [
(document.documentElement.scrollLeft
|| document.body.scrollLeft),
(document.documentElement.scrollTop
|| document.body.scrollTop)
];
}
if (!this.element.lefttop) {
this.element.lefttop = [
(document.documentElement.clientLeft || 0),
(document.documentElement.clientTop || 0)
];
}
if (!this.element.offsets) {
this.element.offsets = OpenLayers.Util.pagePosition(this.element);
this.element.offsets[0] += this.element.scrolls[0];
this.element.offsets[1] += this.element.scrolls[1];
}
return new OpenLayers.Pixel(
(evt.clientX + this.element.scrolls[0]) - this.element.offsets[0]
- this.element.lefttop[0],
(evt.clientY + this.element.scrolls[1]) - this.element.offsets[1]
- this.element.lefttop[1]
);
},
CLASS_NAME: "OpenLayers.Events"
});

View File

@ -0,0 +1,222 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Util.js
* @requires OpenLayers/Marker.js
* @requires OpenLayers/Popup/AnchoredBubble.js
*/
/**
* Class: OpenLayers.Feature
* Features are combinations of geography and attributes. The OpenLayers.Feature
* class specifically combines a marker and a lonlat.
*/
OpenLayers.Feature = OpenLayers.Class({
/**
* Property: layer
* {<OpenLayers.Layer>}
*/
layer: null,
/**
* Property: id
* {String}
*/
id: null,
/**
* Property: lonlat
* {<OpenLayers.LonLat>}
*/
lonlat: null,
/**
* Property: data
* {Object}
*/
data: null,
/**
* Property: marker
* {<OpenLayers.Marker>}
*/
marker: null,
/**
* APIProperty: popupClass
* {<OpenLayers.Class>} The class which will be used to instantiate
* a new Popup. Default is <OpenLayers.Popup.AnchoredBubble>.
*/
popupClass: OpenLayers.Popup.AnchoredBubble,
/**
* Property: popup
* {<OpenLayers.Popup>}
*/
popup: null,
/**
* Constructor: OpenLayers.Feature
* Constructor for features.
*
* Parameters:
* layer - {<OpenLayers.Layer>}
* lonlat - {<OpenLayers.LonLat>}
* data - {Object}
*
* Returns:
* {<OpenLayers.Feature>}
*/
initialize: function(layer, lonlat, data) {
this.layer = layer;
this.lonlat = lonlat;
this.data = (data != null) ? data : {};
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
},
/**
* Method: destroy
* nullify references to prevent circular references and memory leaks
*/
destroy: function() {
//remove the popup from the map
if ((this.layer != null) && (this.layer.map != null)) {
if (this.popup != null) {
this.layer.map.removePopup(this.popup);
}
}
this.layer = null;
this.id = null;
this.lonlat = null;
this.data = null;
if (this.marker != null) {
this.destroyMarker(this.marker);
this.marker = null;
}
if (this.popup != null) {
this.destroyPopup(this.popup);
this.popup = null;
}
},
/**
* Method: onScreen
*
* Returns:
* {Boolean} Whether or not the feature is currently visible on screen
* (based on its 'lonlat' property)
*/
onScreen:function() {
var onScreen = false;
if ((this.layer != null) && (this.layer.map != null)) {
var screenBounds = this.layer.map.getExtent();
onScreen = screenBounds.containsLonLat(this.lonlat);
}
return onScreen;
},
/**
* Method: createMarker
* Based on the data associated with the Feature, create and return a marker object.
*
* Returns:
* {<OpenLayers.Marker>} A Marker Object created from the 'lonlat' and 'icon' properties
* set in this.data. If no 'lonlat' is set, returns null. If no
* 'icon' is set, OpenLayers.Marker() will load the default image.
*
* Note - this.marker is set to return value
*
*/
createMarker: function() {
if (this.lonlat != null) {
this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon);
}
return this.marker;
},
/**
* Method: destroyMarker
* Destroys marker.
* If user overrides the createMarker() function, s/he should be able
* to also specify an alternative function for destroying it
*/
destroyMarker: function() {
this.marker.destroy();
},
/**
* Method: createPopup
* Creates a popup object created from the 'lonlat', 'popupSize',
* and 'popupContentHTML' properties set in this.data. It uses
* this.marker.icon as default anchor.
*
* If no 'lonlat' is set, returns null.
* If no this.marker has been created, no anchor is sent.
*
* Note - the returned popup object is 'owned' by the feature, so you
* cannot use the popup's destroy method to discard the popup.
* Instead, you must use the feature's destroyPopup
*
* Note - this.popup is set to return value
*
* Parameters:
* closeBox - {Boolean} create popup with closebox or not
*
* Returns:
* {<OpenLayers.Popup>} Returns the created popup, which is also set
* as 'popup' property of this feature. Will be of whatever type
* specified by this feature's 'popupClass' property, but must be
* of type <OpenLayers.Popup>.
*
*/
createPopup: function(closeBox) {
if (this.lonlat != null) {
var id = this.id + "_popup";
var anchor = (this.marker) ? this.marker.icon : null;
if (!this.popup) {
this.popup = new this.popupClass(id,
this.lonlat,
this.data.popupSize,
this.data.popupContentHTML,
anchor,
closeBox);
}
if (this.data.overflow != null) {
this.popup.contentDiv.style.overflow = this.data.overflow;
}
this.popup.feature = this;
}
return this.popup;
},
/**
* Method: destroyPopup
* Destroys the popup created via createPopup.
*
* As with the marker, if user overrides the createPopup() function, s/he
* should also be able to override the destruction
*/
destroyPopup: function() {
if (this.popup) {
this.popup.feature = null;
this.popup.destroy();
this.popup = null;
}
},
CLASS_NAME: "OpenLayers.Feature"
});

View File

@ -0,0 +1,66 @@
/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Util.js
* @requires OpenLayers/Style.js
*/
/**
* Class: OpenLayers.Filter
* This class represents an OGC Filter.
*/
OpenLayers.Filter = OpenLayers.Class({
/**
* Constructor: OpenLayers.Filter
* This is an abstract class. Create an instance of a filter subclass.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*
* Returns:
* {<OpenLayers.Filter>}
*/
initialize: function(options) {
OpenLayers.Util.extend(this, options);
},
/**
* APIMethod: destroy
* Remove reference to anything added.
*/
destroy: function() {
},
/**
* APIMethod: evaluate
* Evaluates this filter in a specific context. Should be implemented by
* subclasses.
*
* Parameters:
* context - {Object} Context to use in evaluating the filter.
*
* Returns:
* {Boolean} The filter applies.
*/
evaluate: function(context) {
return true;
},
/**
* APIMethod: clone
* Clones this filter. Should be implementted by subclasses.
*
* Returns:
* {<OpenLayers.Filter>} Clone of this filter.
*/
clone: function() {
return null;
},
CLASS_NAME: "OpenLayers.Filter"
});

View File

@ -0,0 +1,122 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Util.js
* @requires OpenLayers/Console.js
*/
/**
* Class: OpenLayers.Format
* Base class for format reading/writing a variety of formats. Subclasses
* of OpenLayers.Format are expected to have read and write methods.
*/
OpenLayers.Format = OpenLayers.Class({
/**
* Property: options
* {Object} A reference to options passed to the constructor.
*/
options: null,
/**
* APIProperty: externalProjection
* {<OpenLayers.Projection>} When passed a externalProjection and
* internalProjection, the format will reproject the geometries it
* reads or writes. The externalProjection is the projection used by
* the content which is passed into read or which comes out of write.
* In order to reproject, a projection transformation function for the
* specified projections must be available. This support may be
* provided via proj4js or via a custom transformation function. See
* {<OpenLayers.Projection.addTransform>} for more information on
* custom transformations.
*/
externalProjection: null,
/**
* APIProperty: internalProjection
* {<OpenLayers.Projection>} When passed a externalProjection and
* internalProjection, the format will reproject the geometries it
* reads or writes. The internalProjection is the projection used by
* the geometries which are returned by read or which are passed into
* write. In order to reproject, a projection transformation function
* for the specified projections must be available. This support may be
* provided via proj4js or via a custom transformation function. See
* {<OpenLayers.Projection.addTransform>} for more information on
* custom transformations.
*/
internalProjection: null,
/**
* APIProperty: data
* {Object} When <keepData> is true, this is the parsed string sent to
* <read>.
*/
data: null,
/**
* APIProperty: keepData
* {Object} Maintain a reference (<data>) to the most recently read data.
* Default is false.
*/
keepData: false,
/**
* Constructor: OpenLayers.Format
* Instances of this class are not useful. See one of the subclasses.
*
* Parameters:
* options - {Object} An optional object with properties to set on the
* format
*
* Valid options:
* keepData - {Boolean} If true, upon <read>, the data property will be
* set to the parsed object (e.g. the json or xml object).
*
* Returns:
* An instance of OpenLayers.Format
*/
initialize: function(options) {
OpenLayers.Util.extend(this, options);
this.options = options;
},
/**
* APIMethod: destroy
* Clean up.
*/
destroy: function() {
},
/**
* Method: read
* Read data from a string, and return an object whose type depends on the
* subclass.
*
* Parameters:
* data - {string} Data to read/parse.
*
* Returns:
* Depends on the subclass
*/
read: function(data) {
OpenLayers.Console.userError(OpenLayers.i18n("readNotImplemented"));
},
/**
* Method: write
* Accept an object, and return a string.
*
* Parameters:
* object - {Object} Object to be serialized
*
* Returns:
* {String} A string representation of the object.
*/
write: function(object) {
OpenLayers.Console.userError(OpenLayers.i18n("writeNotImplemented"));
},
CLASS_NAME: "OpenLayers.Format"
});

View File

@ -0,0 +1,883 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Rule.js
* @requires OpenLayers/Format/SLD.js
* @requires OpenLayers/Format/Filter/v1_0_0.js
*/
/**
* Class: OpenLayers.Format.SLD.v1
* Superclass for SLD version 1 parsers.
*
* Inherits from:
* - <OpenLayers.Format.Filter.v1_0_0>
*/
OpenLayers.Format.SLD.v1 = OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0, {
/**
* Property: namespaces
* {Object} Mapping of namespace aliases to namespace URIs.
*/
namespaces: {
sld: "http://www.opengis.net/sld",
ogc: "http://www.opengis.net/ogc",
gml: "http://www.opengis.net/gml",
xlink: "http://www.w3.org/1999/xlink",
xsi: "http://www.w3.org/2001/XMLSchema-instance"
},
/**
* Property: defaultPrefix
*/
defaultPrefix: "sld",
/**
* Property: schemaLocation
* {String} Schema location for a particular minor version.
*/
schemaLocation: null,
/**
* APIProperty: defaultSymbolizer.
* {Object} A symbolizer with the SLD defaults.
*/
defaultSymbolizer: {
fillColor: "#808080",
fillOpacity: 1,
strokeColor: "#000000",
strokeOpacity: 1,
strokeWidth: 1,
strokeDashstyle: "solid",
pointRadius: 3,
graphicName: "square"
},
/**
* Constructor: OpenLayers.Format.SLD.v1
* Instances of this class are not created directly. Use the
* <OpenLayers.Format.SLD> constructor instead.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this, [options]);
},
/**
* Method: read
*
* Parameters:
* data - {DOMElement} An SLD document element.
* options - {Object} Options for the reader.
*
* Valid options:
* namedLayersAsArray - {Boolean} Generate a namedLayers array. If false,
* the namedLayers property value will be an object keyed by layer name.
* Default is false.
*
* Returns:
* {Object} An object representing the SLD.
*/
read: function(data, options) {
options = OpenLayers.Util.applyDefaults(options, this.options);
var sld = {
namedLayers: options.namedLayersAsArray === true ? [] : {}
};
this.readChildNodes(data, sld);
return sld;
},
/**
* Property: readers
* Contains public functions, grouped by namespace prefix, that will
* be applied when a namespaced node is found matching the function
* name. The function will be applied in the scope of this parser
* with two arguments: the node being read and a context object passed
* from the parent.
*/
readers: OpenLayers.Util.applyDefaults({
"sld": {
"StyledLayerDescriptor": function(node, sld) {
sld.version = node.getAttribute("version");
this.readChildNodes(node, sld);
},
"Name": function(node, obj) {
obj.name = this.getChildValue(node);
},
"Title": function(node, obj) {
obj.title = this.getChildValue(node);
},
"Abstract": function(node, obj) {
obj.description = this.getChildValue(node);
},
"NamedLayer": function(node, sld) {
var layer = {
userStyles: [],
namedStyles: []
};
this.readChildNodes(node, layer);
// give each of the user styles this layer name
for(var i=0, len=layer.userStyles.length; i<len; ++i) {
layer.userStyles[i].layerName = layer.name;
}
if(sld.namedLayers instanceof Array) {
sld.namedLayers.push(layer);
} else {
sld.namedLayers[layer.name] = layer;
}
},
"NamedStyle": function(node, layer) {
layer.namedStyles.push(
this.getChildName(node.firstChild)
);
},
"UserStyle": function(node, layer) {
var obj = {defaultsPerSymbolizer: true, rules: []};
this.readChildNodes(node, obj);
var style = new OpenLayers.Style(this.defaultSymbolizer, obj);
layer.userStyles.push(style);
},
"IsDefault": function(node, style) {
if(this.getChildValue(node) == "1") {
style.isDefault = true;
}
},
"FeatureTypeStyle": function(node, style) {
// OpenLayers doesn't have a place for FeatureTypeStyle
// Name, Title, Abstract, FeatureTypeName, or
// SemanticTypeIdentifier so, we make a temporary object
// and later just use the Rule(s).
var obj = {
rules: []
};
this.readChildNodes(node, obj);
style.rules = obj.rules;
},
"Rule": function(node, obj) {
var rule = new OpenLayers.Rule();
this.readChildNodes(node, rule);
obj.rules.push(rule);
},
"ElseFilter": function(node, rule) {
rule.elseFilter = true;
},
"MinScaleDenominator": function(node, rule) {
rule.minScaleDenominator = parseFloat(this.getChildValue(node));
},
"MaxScaleDenominator": function(node, rule) {
rule.maxScaleDenominator = parseFloat(this.getChildValue(node));
},
"TextSymbolizer": function(node, rule) {
// OpenLayers doens't do painter's order, instead we extend
var symbolizer = rule.symbolizer["Text"] || {};
this.readChildNodes(node, symbolizer);
// in case it didn't exist before
rule.symbolizer["Text"] = symbolizer;
},
"Label": function(node, symbolizer) {
// only supporting literal or property name
var obj = {};
this.readChildNodes(node, obj);
if(obj.property) {
symbolizer.label = "${" + obj.property + "}";
} else {
var value = this.readOgcExpression(node);
if(value) {
symbolizer.label = value;
}
}
},
"Font": function(node, symbolizer) {
this.readChildNodes(node, symbolizer);
},
"Halo": function(node, symbolizer) {
// halo has a fill, so send fresh object
var obj = {};
this.readChildNodes(node, obj);
symbolizer.haloRadius = obj.haloRadius;
symbolizer.haloColor = obj.fillColor;
symbolizer.haloOpacity = obj.fillOpacity;
},
"Radius": function(node, symbolizer) {
var radius = this.readOgcExpression(node);
if(radius != null) {
// radius is only used for halo
symbolizer.haloRadius = radius;
}
},
"LineSymbolizer": function(node, rule) {
// OpenLayers doesn't do painter's order, instead we extend
var symbolizer = rule.symbolizer["Line"] || {};
this.readChildNodes(node, symbolizer);
// in case it didn't exist before
rule.symbolizer["Line"] = symbolizer;
},
"PolygonSymbolizer": function(node, rule) {
// OpenLayers doens't do painter's order, instead we extend
var symbolizer = rule.symbolizer["Polygon"] || {};
this.readChildNodes(node, symbolizer);
// in case it didn't exist before
rule.symbolizer["Polygon"] = symbolizer;
},
"PointSymbolizer": function(node, rule) {
// OpenLayers doens't do painter's order, instead we extend
var symbolizer = rule.symbolizer["Point"] || {};
this.readChildNodes(node, symbolizer);
// in case it didn't exist before
rule.symbolizer["Point"] = symbolizer;
},
"Stroke": function(node, symbolizer) {
symbolizer.stroke = true;
this.readChildNodes(node, symbolizer);
},
"Fill": function(node, symbolizer) {
symbolizer.fill = true;
this.readChildNodes(node, symbolizer);
},
"CssParameter": function(node, symbolizer) {
var cssProperty = node.getAttribute("name");
var symProperty = this.cssMap[cssProperty];
if(symProperty) {
// Limited support for parsing of OGC expressions
var value = this.readOgcExpression(node);
// always string, could be an empty string
if(value) {
symbolizer[symProperty] = value;
}
}
},
"Graphic": function(node, symbolizer) {
symbolizer.graphic = true;
var graphic = {};
// painter's order not respected here, clobber previous with next
this.readChildNodes(node, graphic);
// directly properties with names that match symbolizer properties
var properties = [
"strokeColor", "strokeWidth", "strokeOpacity",
"strokeLinecap", "fillColor", "fillOpacity",
"graphicName", "rotation", "graphicFormat"
];
var prop, value;
for(var i=0, len=properties.length; i<len; ++i) {
prop = properties[i];
value = graphic[prop];
if(value != undefined) {
symbolizer[prop] = value;
}
}
// set other generic properties with specific graphic property names
if(graphic.opacity != undefined) {
symbolizer.graphicOpacity = graphic.opacity;
}
if(graphic.size != undefined) {
symbolizer.pointRadius = graphic.size / 2;
}
if(graphic.href != undefined) {
symbolizer.externalGraphic = graphic.href;
}
if(graphic.rotation != undefined) {
symbolizer.rotation = graphic.rotation;
}
},
"ExternalGraphic": function(node, graphic) {
this.readChildNodes(node, graphic);
},
"Mark": function(node, graphic) {
this.readChildNodes(node, graphic);
},
"WellKnownName": function(node, graphic) {
graphic.graphicName = this.getChildValue(node);
},
"Opacity": function(node, obj) {
var opacity = this.readOgcExpression(node);
// always string, could be empty string
if(opacity) {
obj.opacity = opacity;
}
},
"Size": function(node, obj) {
var size = this.readOgcExpression(node);
// always string, could be empty string
if(size) {
obj.size = size;
}
},
"Rotation": function(node, obj) {
var rotation = this.readOgcExpression(node);
// always string, could be empty string
if(rotation) {
obj.rotation = rotation;
}
},
"OnlineResource": function(node, obj) {
obj.href = this.getAttributeNS(
node, this.namespaces.xlink, "href"
);
},
"Format": function(node, graphic) {
graphic.graphicFormat = this.getChildValue(node);
}
}
}, OpenLayers.Format.Filter.v1_0_0.prototype.readers),
/**
* Property: cssMap
* {Object} Object mapping supported css property names to OpenLayers
* symbolizer property names.
*/
cssMap: {
"stroke": "strokeColor",
"stroke-opacity": "strokeOpacity",
"stroke-width": "strokeWidth",
"stroke-linecap": "strokeLinecap",
"stroke-dasharray": "strokeDashstyle",
"fill": "fillColor",
"fill-opacity": "fillOpacity",
"font-family": "fontFamily",
"font-size": "fontSize",
"font-weight": "fontWeight",
"font-style": "fontStyle"
},
/**
* Method: getCssProperty
* Given a symbolizer property, get the corresponding CSS property
* from the <cssMap>.
*
* Parameters:
* sym - {String} A symbolizer property name.
*
* Returns:
* {String} A CSS property name or null if none found.
*/
getCssProperty: function(sym) {
var css = null;
for(var prop in this.cssMap) {
if(this.cssMap[prop] == sym) {
css = prop;
break;
}
}
return css;
},
/**
* Method: getGraphicFormat
* Given a href for an external graphic, try to determine the mime-type.
* This method doesn't try too hard, and will fall back to
* <defautlGraphicFormat> if one of the known <graphicFormats> is not
* the file extension of the provided href.
*
* Parameters:
* href - {String}
*
* Returns:
* {String} The graphic format.
*/
getGraphicFormat: function(href) {
var format, regex;
for(var key in this.graphicFormats) {
if(this.graphicFormats[key].test(href)) {
format = key;
break;
}
}
return format || this.defautlGraphicFormat;
},
/**
* Property: defaultGraphicFormat
* {String} If none other can be determined from <getGraphicFormat>, this
* default will be returned.
*/
defaultGraphicFormat: "image/png",
/**
* Property: graphicFormats
* {Object} Mapping of image mime-types to regular extensions matching
* well-known file extensions.
*/
graphicFormats: {
"image/jpeg": /\.jpe?g$/i,
"image/gif": /\.gif$/i,
"image/png": /\.png$/i
},
/**
* Method: write
*
* Parameters:
* sld - {Object} An object representing the SLD.
*
* Returns:
* {DOMElement} The root of an SLD document.
*/
write: function(sld) {
return this.writers.sld.StyledLayerDescriptor.apply(this, [sld]);
},
/**
* Property: writers
* As a compliment to the readers property, this structure contains public
* writing functions grouped by namespace alias and named like the
* node names they produce.
*/
writers: OpenLayers.Util.applyDefaults({
"sld": {
"StyledLayerDescriptor": function(sld) {
var root = this.createElementNSPlus(
"StyledLayerDescriptor",
{attributes: {
"version": this.VERSION,
"xsi:schemaLocation": this.schemaLocation
}}
);
// add in optional name
if(sld.name) {
this.writeNode("Name", sld.name, root);
}
// add in optional title
if(sld.title) {
this.writeNode("Title", sld.title, root);
}
// add in optional description
if(sld.description) {
this.writeNode("Abstract", sld.description, root);
}
// add in named layers
// allow namedLayers to be an array
if(sld.namedLayers instanceof Array) {
for(var i=0, len=sld.namedLayers.length; i<len; ++i) {
this.writeNode("NamedLayer", sld.namedLayers[i], root);
}
} else {
for(var name in sld.namedLayers) {
this.writeNode("NamedLayer", sld.namedLayers[name], root);
}
}
return root;
},
"Name": function(name) {
return this.createElementNSPlus("Name", {value: name});
},
"Title": function(title) {
return this.createElementNSPlus("Title", {value: title});
},
"Abstract": function(description) {
return this.createElementNSPlus(
"Abstract", {value: description}
);
},
"NamedLayer": function(layer) {
var node = this.createElementNSPlus("NamedLayer");
// add in required name
this.writeNode("Name", layer.name, node);
// optional sld:LayerFeatureConstraints here
// add in named styles
if(layer.namedStyles) {
for(var i=0, len=layer.namedStyles.length; i<len; ++i) {
this.writeNode(
"NamedStyle", layer.namedStyles[i], node
);
}
}
// add in user styles
if(layer.userStyles) {
for(var i=0, len=layer.userStyles.length; i<len; ++i) {
this.writeNode(
"UserStyle", layer.userStyles[i], node
);
}
}
return node;
},
"NamedStyle": function(name) {
var node = this.createElementNSPlus("NamedStyle");
this.writeNode("Name", name, node);
return node;
},
"UserStyle": function(style) {
var node = this.createElementNSPlus("UserStyle");
// add in optional name
if(style.name) {
this.writeNode("Name", style.name, node);
}
// add in optional title
if(style.title) {
this.writeNode("Title", style.title, node);
}
// add in optional description
if(style.description) {
this.writeNode("Abstract", style.description, node);
}
// add isdefault
if(style.isDefault) {
this.writeNode("IsDefault", style.isDefault, node);
}
// add FeatureTypeStyles
this.writeNode("FeatureTypeStyle", style, node);
return node;
},
"IsDefault": function(bool) {
return this.createElementNSPlus(
"IsDefault", {value: (bool) ? "1" : "0"}
);
},
"FeatureTypeStyle": function(style) {
var node = this.createElementNSPlus("FeatureTypeStyle");
// OpenLayers currently stores no Name, Title, Abstract,
// FeatureTypeName, or SemanticTypeIdentifier information
// related to FeatureTypeStyle
// add in rules
for(var i=0, len=style.rules.length; i<len; ++i) {
this.writeNode("Rule", style.rules[i], node);
}
return node;
},
"Rule": function(rule) {
var node = this.createElementNSPlus("Rule");
// add in optional name
if(rule.name) {
this.writeNode("Name", rule.name, node);
}
// add in optional title
if(rule.title) {
this.writeNode("Title", rule.title, node);
}
// add in optional description
if(rule.description) {
this.writeNode("Abstract", rule.description, node);
}
// add in LegendGraphic here
// add in optional filters
if(rule.elseFilter) {
this.writeNode("ElseFilter", null, node);
} else if(rule.filter) {
this.writeNode("ogc:Filter", rule.filter, node);
}
// add in scale limits
if(rule.minScaleDenominator != undefined) {
this.writeNode(
"MinScaleDenominator", rule.minScaleDenominator, node
);
}
if(rule.maxScaleDenominator != undefined) {
this.writeNode(
"MaxScaleDenominator", rule.maxScaleDenominator, node
);
}
// add in symbolizers (relies on geometry type keys)
var types = OpenLayers.Style.SYMBOLIZER_PREFIXES;
var type, symbolizer;
for(var i=0, len=types.length; i<len; ++i) {
type = types[i];
symbolizer = rule.symbolizer[type];
if(symbolizer) {
this.writeNode(
type + "Symbolizer", symbolizer, node
);
}
}
return node;
},
"ElseFilter": function() {
return this.createElementNSPlus("ElseFilter");
},
"MinScaleDenominator": function(scale) {
return this.createElementNSPlus(
"MinScaleDenominator", {value: scale}
);
},
"MaxScaleDenominator": function(scale) {
return this.createElementNSPlus(
"MaxScaleDenominator", {value: scale}
);
},
"LineSymbolizer": function(symbolizer) {
var node = this.createElementNSPlus("LineSymbolizer");
this.writeNode("Stroke", symbolizer, node);
return node;
},
"Stroke": function(symbolizer) {
var node = this.createElementNSPlus("Stroke");
// GraphicFill here
// GraphicStroke here
// add in CssParameters
if(symbolizer.strokeColor != undefined) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "strokeColor"},
node
);
}
if(symbolizer.strokeOpacity != undefined) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "strokeOpacity"},
node
);
}
if(symbolizer.strokeWidth != undefined) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "strokeWidth"},
node
);
}
return node;
},
"CssParameter": function(obj) {
// not handling ogc:expressions for now
return this.createElementNSPlus("CssParameter", {
attributes: {name: this.getCssProperty(obj.key)},
value: obj.symbolizer[obj.key]
});
},
"TextSymbolizer": function(symbolizer) {
var node = this.createElementNSPlus("TextSymbolizer");
// add in optional Label
if(symbolizer.label != null) {
this.writeNode("Label", symbolizer.label, node);
}
// add in optional Font
if(symbolizer.fontFamily != null ||
symbolizer.fontSize != null ||
symbolizer.fontWeight != null ||
symbolizer.fontStyle != null) {
this.writeNode("Font", symbolizer, node);
}
// add in optional Halo
if(symbolizer.haloRadius != null ||
symbolizer.haloColor != null ||
symbolizer.haloOpacity != null) {
this.writeNode("Halo", symbolizer, node);
}
// add in optional Fill
if(symbolizer.fillColor != null ||
symbolizer.fillOpacity != null) {
this.writeNode("Fill", symbolizer, node);
}
return node;
},
"Font": function(symbolizer) {
var node = this.createElementNSPlus("Font");
// add in CssParameters
if(symbolizer.fontFamily) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fontFamily"},
node
);
}
if(symbolizer.fontSize) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fontSize"},
node
);
}
if(symbolizer.fontWeight) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fontWeight"},
node
);
}
if(symbolizer.fontStyle) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fontStyle"},
node
);
}
return node;
},
"Label": function(label) {
// only the simplest of ogc:expression handled
// {label: "some text and a ${propertyName}"}
var node = this.createElementNSPlus("Label");
var tokens = label.split("${");
node.appendChild(this.createTextNode(tokens[0]));
var item, last;
for(var i=1, len=tokens.length; i<len; i++) {
item = tokens[i];
last = item.indexOf("}");
if(last > 0) {
this.writeNode(
"ogc:PropertyName",
{property: item.substring(0, last)},
node
);
node.appendChild(
this.createTextNode(item.substring(++last))
);
} else {
// no ending }, so this is a literal ${
node.appendChild(
this.createTextNode("${" + item)
);
}
}
return node;
},
"Halo": function(symbolizer) {
var node = this.createElementNSPlus("Halo");
if(symbolizer.haloRadius) {
this.writeNode("Radius", symbolizer.haloRadius, node);
}
if(symbolizer.haloColor || symbolizer.haloOpacity) {
this.writeNode("Fill", {
fillColor: symbolizer.haloColor,
fillOpacity: symbolizer.haloOpacity
}, node);
}
return node;
},
"Radius": function(value) {
return node = this.createElementNSPlus("Radius", {
value: value
});
},
"PolygonSymbolizer": function(symbolizer) {
var node = this.createElementNSPlus("PolygonSymbolizer");
if(symbolizer.fillColor != undefined ||
symbolizer.fillOpacity != undefined) {
this.writeNode("Fill", symbolizer, node);
}
if(symbolizer.strokeWidth != undefined ||
symbolizer.strokeColor != undefined ||
symbolizer.strokeOpacity != undefined ||
symbolizer.strokeDashstyle != undefined) {
this.writeNode("Stroke", symbolizer, node);
}
return node;
},
"Fill": function(symbolizer) {
var node = this.createElementNSPlus("Fill");
// GraphicFill here
// add in CssParameters
if(symbolizer.fillColor) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fillColor"},
node
);
}
if(symbolizer.fillOpacity != null) {
this.writeNode(
"CssParameter",
{symbolizer: symbolizer, key: "fillOpacity"},
node
);
}
return node;
},
"PointSymbolizer": function(symbolizer) {
var node = this.createElementNSPlus("PointSymbolizer");
this.writeNode("Graphic", symbolizer, node);
return node;
},
"Graphic": function(symbolizer) {
var node = this.createElementNSPlus("Graphic");
if(symbolizer.externalGraphic != undefined) {
this.writeNode("ExternalGraphic", symbolizer, node);
} else {
this.writeNode("Mark", symbolizer, node);
}
if(symbolizer.graphicOpacity != undefined) {
this.writeNode("Opacity", symbolizer.graphicOpacity, node);
}
if(symbolizer.pointRadius != undefined) {
this.writeNode("Size", symbolizer.pointRadius * 2, node);
}
if(symbolizer.rotation != undefined) {
this.writeNode("Rotation", symbolizer.rotation, node);
}
return node;
},
"ExternalGraphic": function(symbolizer) {
var node = this.createElementNSPlus("ExternalGraphic");
this.writeNode(
"OnlineResource", symbolizer.externalGraphic, node
);
var format = symbolizer.graphicFormat ||
this.getGraphicFormat(symbolizer.externalGraphic);
this.writeNode("Format", format, node);
return node;
},
"Mark": function(symbolizer) {
var node = this.createElementNSPlus("Mark");
if(symbolizer.graphicName) {
this.writeNode("WellKnownName", symbolizer.graphicName, node);
}
this.writeNode("Fill", symbolizer, node);
this.writeNode("Stroke", symbolizer, node);
return node;
},
"WellKnownName": function(name) {
return this.createElementNSPlus("WellKnownName", {
value: name
});
},
"Opacity": function(value) {
return this.createElementNSPlus("Opacity", {
value: value
});
},
"Size": function(value) {
return this.createElementNSPlus("Size", {
value: value
});
},
"Rotation": function(value) {
return this.createElementNSPlus("Rotation", {
value: value
});
},
"OnlineResource": function(href) {
return this.createElementNSPlus("OnlineResource", {
attributes: {
"xlink:type": "simple",
"xlink:href": href
}
});
},
"Format": function(format) {
return this.createElementNSPlus("Format", {
value: format
});
}
}
}, OpenLayers.Format.Filter.v1_0_0.prototype.writers),
CLASS_NAME: "OpenLayers.Format.SLD.v1"
});

View File

@ -0,0 +1,50 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Format/SLD/v1.js
* @requires OpenLayers/Format/Filter/v1_0_0.js
*/
/**
* Class: OpenLayers.Format.SLD.v1_0_0
* Write SLD version 1.0.0.
*
* Inherits from:
* - <OpenLayers.Format.SLD.v1>
*/
OpenLayers.Format.SLD.v1_0_0 = OpenLayers.Class(
OpenLayers.Format.SLD.v1, {
/**
* Constant: VERSION
* {String} 1.0.0
*/
VERSION: "1.0.0",
/**
* Property: schemaLocation
* {String} http://www.opengis.net/sld
* http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd
*/
schemaLocation: "http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd",
/**
* Constructor: OpenLayers.Format.SLD.v1_0_0
* Instances of this class are not created directly. Use the
* <OpenLayers.Format.SLD> constructor instead.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.SLD.v1.prototype.initialize.apply(
this, [options]
);
},
CLASS_NAME: "OpenLayers.Format.SLD.v1_0_0"
});

View File

@ -0,0 +1,117 @@
/**
* @requires OpenLayers/Format/WFSCapabilities.js
*/
/**
* Class: OpenLayers.Format.WFSCapabilities.v1
* Abstract class not to be instantiated directly.
*
* Inherits from:
* - <OpenLayers.Format.XML>
*/
OpenLayers.Format.WFSCapabilities.v1 = OpenLayers.Class(
OpenLayers.Format.WFSCapabilities, {
/**
* Constructor: OpenLayers.Format.WFSCapabilities.v1_1
* Create an instance of one of the subclasses.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
this.options = options;
},
/**
* APIMethod: read
* Read capabilities data from a string, and return a list of layers.
*
* Parameters:
* data - {String} or {DOMElement} data to read/parse.
*
* Returns:
* {Array} List of named layers.
*/
read: function(data) {
if(typeof data == "string") {
data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
}
var capabilities = {};
var root = data.documentElement;
this.runChildNodes(capabilities, root);
return capabilities;
},
/**
* Method: runChildNodes
*/
runChildNodes: function(obj, node) {
var children = node.childNodes;
var childNode, processor;
for(var i=0; i<children.length; ++i) {
childNode = children[i];
if(childNode.nodeType == 1) {
processor = this["read_cap_" + childNode.nodeName];
if(processor) {
processor.apply(this, [obj, childNode]);
}
}
}
},
/**
* Method: read_cap_FeatureTypeList
*/
read_cap_FeatureTypeList: function(request, node) {
var featureTypeList = {
featureTypes: []
};
this.runChildNodes(featureTypeList, node);
request.featureTypeList = featureTypeList;
},
/**
* Method: read_cap_FeatureType
*/
read_cap_FeatureType: function(featureTypeList, node, parentLayer) {
var featureType = {};
this.runChildNodes(featureType, node);
featureTypeList.featureTypes.push(featureType);
},
/**
* Method: read_cap_Name
*/
read_cap_Name: function(obj, node) {
var name = this.getChildValue(node);
if(name) {
obj.name = name;
}
},
/**
* Method: read_cap_Title
*/
read_cap_Title: function(obj, node) {
var title = this.getChildValue(node);
if(title) {
obj.title = title;
}
},
/**
* Method: read_cap_Abstract
*/
read_cap_Abstract: function(obj, node) {
var abst = this.getChildValue(node);
if(abst) {
obj["abstract"] = abst;
}
},
CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1"
});

View File

@ -0,0 +1,31 @@
/**
* @requires OpenLayers/Format/WFSCapabilities/v1.js
*/
/**
* Class: OpenLayers.Format.WFSCapabilities/v1_0_0
* Read WMS Capabilities version 1.0.0.
*
* Inherits from:
* - <OpenLayers.Format.WFSCapabilities>
*/
OpenLayers.Format.WFSCapabilities.v1_0_0 = OpenLayers.Class(
OpenLayers.Format.WFSCapabilities.v1, {
/**
* Constructor: OpenLayers.Format.WFSCapabilities.v1_0_0
* Create a new parser for WFS capabilities version 1.0.0.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(
this, [options]
);
},
CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_0_0"
});

View File

@ -0,0 +1,31 @@
/**
* @requires OpenLayers/Format/WFSCapabilities/v1.js
*/
/**
* Class: OpenLayers.Format.WFSCapabilities/v1_1_0
* Read WFS Capabilities version 1.1.0.
*
* Inherits from:
* - <OpenLayers.Format.WFSCapabilities>
*/
OpenLayers.Format.WFSCapabilities.v1_1_0 = OpenLayers.Class(
OpenLayers.Format.WFSCapabilities.v1, {
/**
* Constructor: OpenLayers.Format.WFSCapabilities.v1_1_0
* Create a new parser for WFS capabilities version 1.1.0.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(
this, [options]
);
},
CLASS_NAME: "OpenLayers.Format.WFSCapabilities.v1_1_0"
});

View File

@ -0,0 +1,266 @@
/**
* @requires OpenLayers/Format/WMSCapabilities.js
* @requires OpenLayers/Format/XML.js
*/
/**
* Class: OpenLayers.Format.WMSCapabilities.v1_1
* Abstract class not to be instantiated directly.
*
* Inherits from:
* - <OpenLayers.Format.XML>
*/
OpenLayers.Format.WMSCapabilities.v1_1 = OpenLayers.Class(
OpenLayers.Format.XML, {
/**
* Constructor: OpenLayers.Format.WMSCapabilities.v1_1
* Create an instance of one of the subclasses.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.XML.prototype.initialize.apply(this, [options]);
this.options = options;
},
/**
* APIMethod: read
* Read capabilities data from a string, and return a list of layers.
*
* Parameters:
* data - {String} or {DOMElement} data to read/parse.
*
* Returns:
* {Array} List of named layers.
*/
read: function(data) {
if(typeof data == "string") {
data = OpenLayers.Format.XML.prototype.read.apply(this, [data]);
}
var capabilities = {};
var root = data.documentElement;
this.runChildNodes(capabilities, root);
return capabilities;
},
/**
* Method: runChildNodes
*/
runChildNodes: function(obj, node) {
var children = node.childNodes;
var childNode, processor;
for(var i=0; i<children.length; ++i) {
childNode = children[i];
if(childNode.nodeType == 1) {
processor = this["read_cap_" + childNode.nodeName];
if(processor) {
processor.apply(this, [obj, childNode]);
}
}
}
},
/**
* Method: read_cap_Capability
*/
read_cap_Capability: function(capabilities, node) {
var capability = {
layers: []
};
this.runChildNodes(capability, node);
capabilities.capability = capability;
},
/**
* Method: read_cap_Request
*/
read_cap_Request: function(obj, node) {
var request = {};
this.runChildNodes(request, node);
obj.request = request;
},
/**
* Method: read_cap_GetMap
*/
read_cap_GetMap: function(request, node) {
var getmap = {
formats: []
};
this.runChildNodes(getmap, node);
request.getmap = getmap;
},
/**
* Method: read_cap_Format
*/
read_cap_Format: function(obj, node) {
if(obj.formats) {
obj.formats.push(this.getChildValue(node));
}
},
/**
* Method: read_cap_DCPType
* Super simplified HTTP href extractor. Assumes the first online resource
* will work.
*/
read_cap_DCPType: function(obj, node) {
var children = node.getElementsByTagName("OnlineResource");
if(children.length > 0) {
this.read_cap_OnlineResource(obj, children[0]);
}
},
/**
* Method: read_cap_Service
*/
read_cap_Service: function(capabilities, node) {
var service = {};
this.runChildNodes(service, node);
capabilities.service = service;
},
/**
* Method: read_cap_Layer
*/
read_cap_Layer: function(capability, node, parentLayer) {
var layer = {
formats: capability.request.getmap.formats || [],
styles: [],
queryable: (node.getAttribute("queryable") === "1"
|| node.getAttribute("queryable") === "true")
};
// deal with property inheritance
if(parentLayer) {
// add style
layer.styles = layer.styles.concat(parentLayer.styles);
// use llbbox
layer.llbbox = parentLayer.llbbox;
// use min/maxScale
layer.minScale = parentLayer.minScale;
layer.maxScale = parentLayer.maxScale;
}
var children = node.childNodes;
var childNode, nodeName, processor;
for(var i=0; i<children.length; ++i) {
childNode = children[i];
nodeName = childNode.nodeName;
processor = this["read_cap_" + childNode.nodeName];
if(processor) {
if(nodeName == "Layer") {
processor.apply(this, [capability, childNode, layer]);
} else {
processor.apply(this, [layer, childNode]);
}
}
}
if(layer.name) {
var index = layer.name.indexOf(":");
if(index > 0) {
layer.prefix = layer.name.substring(0, index);
}
capability.layers.push(layer);
}
},
/**
* Method: read_cap_ScaleHint
* The Layer ScaleHint element has min and max attributes that relate to
* the minimum and maximum resolution that the server supports. The
* values are pixel diagonals measured in meters (on the ground).
*/
read_cap_ScaleHint: function(layer, node) {
var min = node.getAttribute("min");
var max = node.getAttribute("max");
var rad2 = Math.pow(2, 0.5);
var ipm = OpenLayers.INCHES_PER_UNIT["m"];
layer.maxScale = parseFloat(
((rad2 * min) * ipm * OpenLayers.DOTS_PER_INCH).toPrecision(13)
);
layer.minScale = parseFloat(
((rad2 * max) * ipm * OpenLayers.DOTS_PER_INCH).toPrecision(13)
);
},
/**
* Method: read_cap_Name
*/
read_cap_Name: function(obj, node) {
var name = this.getChildValue(node);
if(name) {
obj.name = name;
}
},
/**
* Method: read_cap_Title
*/
read_cap_Title: function(obj, node) {
var title = this.getChildValue(node);
if(title) {
obj.title = title;
}
},
/**
* Method: read_cap_Abstract
*/
read_cap_Abstract: function(obj, node) {
var abst = this.getChildValue(node);
if(abst) {
obj["abstract"] = abst;
}
},
/**
* Method: read_cap_LatLonBoundingBox
*/
read_cap_LatLonBoundingBox: function(layer, node) {
layer.llbbox = [
parseFloat(node.getAttribute("minx")),
parseFloat(node.getAttribute("miny")),
parseFloat(node.getAttribute("maxx")),
parseFloat(node.getAttribute("maxy"))
];
},
/**
* Method: read_cap_Style
*/
read_cap_Style: function(layer, node) {
var style = {};
this.runChildNodes(style, node);
layer.styles.push(style);
},
/**
* Method: read_cap_LegendURL
*/
read_cap_LegendURL: function(style, node) {
var legend = {
width: node.getAttribute('width'),
height: node.getAttribute('height')
};
var links = node.getElementsByTagName("OnlineResource");
if(links.length > 0) {
this.read_cap_OnlineResource(legend, links[0]);
}
style.legend = legend;
},
/**
* Method: read_cap_OnlineResource
*/
read_cap_OnlineResource: function(obj, node) {
obj.href = this.getAttributeNS(
node, "http://www.w3.org/1999/xlink", "href"
);
},
CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1"
});

View File

@ -0,0 +1,37 @@
/**
* @requires OpenLayers/Format/WMSCapabilities/v1_1.js
*/
/**
* Class: OpenLayers.Format.WMSCapabilities/v1_1_0
* Read WMS Capabilities version 1.1.0.
*
* Inherits from:
* - <OpenLayers.Format.WMSCapabilities.v1_1>
*/
OpenLayers.Format.WMSCapabilities.v1_1_0 = OpenLayers.Class(
OpenLayers.Format.WMSCapabilities.v1_1, {
/**
* Property: version
* {String} The specific parser version.
*/
version: "1.1.0",
/**
* Constructor: OpenLayers.Format.WMSCapabilities.v1_1_0
* Create a new parser for WMS capabilities version 1.1.0.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(
this, [options]
);
},
CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_0"
});

View File

@ -0,0 +1,37 @@
/**
* @requires OpenLayers/Format/WMSCapabilities/v1_1.js
*/
/**
* Class: OpenLayers.Format.WMSCapabilities/v1_1_1
* Read WMS Capabilities version 1.1.1.
*
* Inherits from:
* - <OpenLayers.Format.WMSCapabilities.v1_1>
*/
OpenLayers.Format.WMSCapabilities.v1_1_1 = OpenLayers.Class(
OpenLayers.Format.WMSCapabilities.v1_1, {
/**
* Property: version
* {String} The specific parser version.
*/
version: "1.1.1",
/**
* Constructor: OpenLayers.Format.WMSCapabilities.v1_1_1
* Create a new parser for WMS capabilities version 1.1.1.
*
* Parameters:
* options - {Object} An optional object whose properties will be set on
* this instance.
*/
initialize: function(options) {
OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(
this, [options]
);
},
CLASS_NAME: "OpenLayers.Format.WMSCapabilities.v1_1_1"
});

View File

@ -0,0 +1,455 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Format/WKT.js
* @requires OpenLayers/Feature/Vector.js
*/
/**
* Class: OpenLayers.Geometry
* A Geometry is a description of a geographic object. Create an instance of
* this class with the <OpenLayers.Geometry> constructor. This is a base class,
* typical geometry types are described by subclasses of this class.
*/
OpenLayers.Geometry = OpenLayers.Class({
/**
* Property: id
* {String} A unique identifier for this geometry.
*/
id: null,
/**
* Property: parent
* {<OpenLayers.Geometry>}This is set when a Geometry is added as component
* of another geometry
*/
parent: null,
/**
* Property: bounds
* {<OpenLayers.Bounds>} The bounds of this geometry
*/
bounds: null,
/**
* Constructor: OpenLayers.Geometry
* Creates a geometry object.
*/
initialize: function() {
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME+ "_");
},
/**
* Method: destroy
* Destroy this geometry.
*/
destroy: function() {
this.id = null;
this.bounds = null;
},
/**
* APIMethod: clone
* Create a clone of this geometry. Does not set any non-standard
* properties of the cloned geometry.
*
* Returns:
* {<OpenLayers.Geometry>} An exact clone of this geometry.
*/
clone: function() {
return new OpenLayers.Geometry();
},
/**
* Set the bounds for this Geometry.
*
* Parameters:
* object - {<OpenLayers.Bounds>}
*/
setBounds: function(bounds) {
if (bounds) {
this.bounds = bounds.clone();
}
},
/**
* Method: clearBounds
* Nullify this components bounds and that of its parent as well.
*/
clearBounds: function() {
this.bounds = null;
if (this.parent) {
this.parent.clearBounds();
}
},
/**
* Method: extendBounds
* Extend the existing bounds to include the new bounds.
* If geometry's bounds is not yet set, then set a new Bounds.
*
* Parameters:
* newBounds - {<OpenLayers.Bounds>}
*/
extendBounds: function(newBounds){
var bounds = this.getBounds();
if (!bounds) {
this.setBounds(newBounds);
} else {
this.bounds.extend(newBounds);
}
},
/**
* APIMethod: getBounds
* Get the bounds for this Geometry. If bounds is not set, it
* is calculated again, this makes queries faster.
*
* Returns:
* {<OpenLayers.Bounds>}
*/
getBounds: function() {
if (this.bounds == null) {
this.calculateBounds();
}
return this.bounds;
},
/**
* APIMethod: calculateBounds
* Recalculate the bounds for the geometry.
*/
calculateBounds: function() {
//
// This should be overridden by subclasses.
//
},
/**
* APIMethod: distanceTo
* Calculate the closest distance between two geometries (on the x-y plane).
*
* Parameters:
* geometry - {<OpenLayers.Geometry>} The target geometry.
* options - {Object} Optional properties for configuring the distance
* calculation.
*
* Valid options depend on the specific geometry type.
*
* Returns:
* {Number | Object} The distance between this geometry and the target.
* If details is true, the return will be an object with distance,
* x0, y0, x1, and x2 properties. The x0 and y0 properties represent
* the coordinates of the closest point on this geometry. The x1 and y1
* properties represent the coordinates of the closest point on the
* target geometry.
*/
distanceTo: function(geometry, options) {
},
/**
* APIMethod: getVertices
* Return a list of all points in this geometry.
*
* Parameters:
* nodes - {Boolean} For lines, only return vertices that are
* endpoints. If false, for lines, only vertices that are not
* endpoints will be returned. If not provided, all vertices will
* be returned.
*
* Returns:
* {Array} A list of all vertices in the geometry.
*/
getVertices: function(nodes) {
},
/**
* Method: atPoint
* Note - This is only an approximation based on the bounds of the
* geometry.
*
* Parameters:
* lonlat - {<OpenLayers.LonLat>}
* toleranceLon - {float} Optional tolerance in Geometric Coords
* toleranceLat - {float} Optional tolerance in Geographic Coords
*
* Returns:
* {Boolean} Whether or not the geometry is at the specified location
*/
atPoint: function(lonlat, toleranceLon, toleranceLat) {
var atPoint = false;
var bounds = this.getBounds();
if ((bounds != null) && (lonlat != null)) {
var dX = (toleranceLon != null) ? toleranceLon : 0;
var dY = (toleranceLat != null) ? toleranceLat : 0;
var toleranceBounds =
new OpenLayers.Bounds(this.bounds.left - dX,
this.bounds.bottom - dY,
this.bounds.right + dX,
this.bounds.top + dY);
atPoint = toleranceBounds.containsLonLat(lonlat);
}
return atPoint;
},
/**
* Method: getLength
* Calculate the length of this geometry. This method is defined in
* subclasses.
*
* Returns:
* {Float} The length of the collection by summing its parts
*/
getLength: function() {
//to be overridden by geometries that actually have a length
//
return 0.0;
},
/**
* Method: getArea
* Calculate the area of this geometry. This method is defined in subclasses.
*
* Returns:
* {Float} The area of the collection by summing its parts
*/
getArea: function() {
//to be overridden by geometries that actually have an area
//
return 0.0;
},
/**
* APIMethod: getCentroid
* Calculate the centroid of this geometry. This method is defined in subclasses.
*
* Returns:
* {<OpenLayers.Geometry.Point>} The centroid of the collection
*/
getCentroid: function() {
return null;
},
/**
* Method: toString
* Returns the Well-Known Text representation of a geometry
*
* Returns:
* {String} Well-Known Text
*/
toString: function() {
return OpenLayers.Format.WKT.prototype.write(
new OpenLayers.Feature.Vector(this)
);
},
CLASS_NAME: "OpenLayers.Geometry"
});
/**
* Function: OpenLayers.Geometry.fromWKT
* Generate a geometry given a Well-Known Text string.
*
* Parameters:
* wkt - {String} A string representing the geometry in Well-Known Text.
*
* Returns:
* {<OpenLayers.Geometry>} A geometry of the appropriate class.
*/
OpenLayers.Geometry.fromWKT = function(wkt) {
var format = arguments.callee.format;
if(!format) {
format = new OpenLayers.Format.WKT();
arguments.callee.format = format;
}
var geom;
var result = format.read(wkt);
if(result instanceof OpenLayers.Feature.Vector) {
geom = result.geometry;
} else if(result instanceof Array) {
var len = result.length;
var components = new Array(len);
for(var i=0; i<len; ++i) {
components[i] = result[i].geometry;
}
geom = new OpenLayers.Geometry.Collection(components);
}
return geom;
};
/**
* Method: OpenLayers.Geometry.segmentsIntersect
* Determine whether two line segments intersect. Optionally calculates
* and returns the intersection point. This function is optimized for
* cases where seg1.x2 >= seg2.x1 || seg2.x2 >= seg1.x1. In those
* obvious cases where there is no intersection, the function should
* not be called.
*
* Parameters:
* seg1 - {Object} Object representing a segment with properties x1, y1, x2,
* and y2. The start point is represented by x1 and y1. The end point
* is represented by x2 and y2. Start and end are ordered so that x1 < x2.
* seg2 - {Object} Object representing a segment with properties x1, y1, x2,
* and y2. The start point is represented by x1 and y1. The end point
* is represented by x2 and y2. Start and end are ordered so that x1 < x2.
* options - {Object} Optional properties for calculating the intersection.
*
* Valid options:
* point - {Boolean} Return the intersection point. If false, the actual
* intersection point will not be calculated. If true and the segments
* intersect, the intersection point will be returned. If true and
* the segments do not intersect, false will be returned. If true and
* the segments are coincident, true will be returned.
* tolerance - {Number} If a non-null value is provided, if the segments are
* within the tolerance distance, this will be considered an intersection.
* In addition, if the point option is true and the calculated intersection
* is within the tolerance distance of an end point, the endpoint will be
* returned instead of the calculated intersection. Further, if the
* intersection is within the tolerance of endpoints on both segments, or
* if two segment endpoints are within the tolerance distance of eachother
* (but no intersection is otherwise calculated), an endpoint on the
* first segment provided will be returned.
*
* Returns:
* {Boolean | <OpenLayers.Geometry.Point>} The two segments intersect.
* If the point argument is true, the return will be the intersection
* point or false if none exists. If point is true and the segments
* are coincident, return will be true (and the instersection is equal
* to the shorter segment).
*/
OpenLayers.Geometry.segmentsIntersect = function(seg1, seg2, options) {
var point = options && options.point;
var tolerance = options && options.tolerance;
var intersection = false;
var x11_21 = seg1.x1 - seg2.x1;
var y11_21 = seg1.y1 - seg2.y1;
var x12_11 = seg1.x2 - seg1.x1;
var y12_11 = seg1.y2 - seg1.y1;
var y22_21 = seg2.y2 - seg2.y1;
var x22_21 = seg2.x2 - seg2.x1;
var d = (y22_21 * x12_11) - (x22_21 * y12_11);
var n1 = (x22_21 * y11_21) - (y22_21 * x11_21);
var n2 = (x12_11 * y11_21) - (y12_11 * x11_21);
if(d == 0) {
// parallel
if(n1 == 0 && n2 == 0) {
// coincident
intersection = true;
}
} else {
var along1 = n1 / d;
var along2 = n2 / d;
if(along1 >= 0 && along1 <= 1 && along2 >=0 && along2 <= 1) {
// intersect
if(!point) {
intersection = true;
} else {
// calculate the intersection point
var x = seg1.x1 + (along1 * x12_11);
var y = seg1.y1 + (along1 * y12_11);
intersection = new OpenLayers.Geometry.Point(x, y);
}
}
}
if(tolerance) {
var dist;
if(intersection) {
if(point) {
var segs = [seg1, seg2];
var seg, x, y;
// check segment endpoints for proximity to intersection
// set intersection to first endpoint within the tolerance
outer: for(var i=0; i<2; ++i) {
seg = segs[i];
for(var j=1; j<3; ++j) {
x = seg["x" + j];
y = seg["y" + j];
dist = Math.sqrt(
Math.pow(x - intersection.x, 2) +
Math.pow(y - intersection.y, 2)
);
if(dist < tolerance) {
intersection.x = x;
intersection.y = y;
break outer;
}
}
}
}
} else {
// no calculated intersection, but segments could be within
// the tolerance of one another
var segs = [seg1, seg2];
var source, target, x, y, p, result;
// check segment endpoints for proximity to intersection
// set intersection to first endpoint within the tolerance
outer: for(var i=0; i<2; ++i) {
source = segs[i];
target = segs[(i+1)%2];
for(var j=1; j<3; ++j) {
p = {x: source["x"+j], y: source["y"+j]};
result = OpenLayers.Geometry.distanceToSegment(p, target);
if(result.distance < tolerance) {
if(point) {
intersection = new OpenLayers.Geometry.Point(p.x, p.y);
} else {
intersection = true;
}
break outer;
}
}
}
}
}
return intersection;
};
/**
* Function: OpenLayers.Geometry.distanceToSegment
*
* Parameters:
* point - {Object} An object with x and y properties representing the
* point coordinates.
* segment - {Object} An object with x1, y1, x2, and y2 properties
* representing endpoint coordinates.
*
* Returns:
* {Object} An object with distance, x, and y properties. The distance
* will be the shortest distance between the input point and segment.
* The x and y properties represent the coordinates along the segment
* where the shortest distance meets the segment.
*/
OpenLayers.Geometry.distanceToSegment = function(point, segment) {
var x0 = point.x;
var y0 = point.y;
var x1 = segment.x1;
var y1 = segment.y1;
var x2 = segment.x2;
var y2 = segment.y2;
var dx = x2 - x1;
var dy = y2 - y1;
var along = ((dx * (x0 - x1)) + (dy * (y0 - y1))) /
(Math.pow(dx, 2) + Math.pow(dy, 2));
var x, y;
if(along <= 0.0) {
x = x1;
y = y1;
} else if(along >= 1.0) {
x = x2;
y = y2;
} else {
x = x1 + along * dx;
y = y1 + along * dy;
}
return {
distance: Math.sqrt(Math.pow(x - x0, 2) + Math.pow(y - y0, 2)),
x: x, y: y
};
};

View File

@ -0,0 +1,285 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Events.js
*/
/**
* Class: OpenLayers.Handler
* Base class to construct a higher-level handler for event sequences. All
* handlers have activate and deactivate methods. In addition, they have
* methods named like browser events. When a handler is activated, any
* additional methods named like a browser event is registered as a
* listener for the corresponding event. When a handler is deactivated,
* those same methods are unregistered as event listeners.
*
* Handlers also typically have a callbacks object with keys named like
* the abstracted events or event sequences that they are in charge of
* handling. The controls that wrap handlers define the methods that
* correspond to these abstract events - so instead of listening for
* individual browser events, they only listen for the abstract events
* defined by the handler.
*
* Handlers are created by controls, which ultimately have the responsibility
* of making changes to the the state of the application. Handlers
* themselves may make temporary changes, but in general are expected to
* return the application in the same state that they found it.
*/
OpenLayers.Handler = OpenLayers.Class({
/**
* Property: id
* {String}
*/
id: null,
/**
* APIProperty: control
* {<OpenLayers.Control>}. The control that initialized this handler. The
* control is assumed to have a valid map property - that map is used
* in the handler's own setMap method.
*/
control: null,
/**
* Property: map
* {<OpenLayers.Map>}
*/
map: null,
/**
* APIProperty: keyMask
* {Integer} Use bitwise operators and one or more of the OpenLayers.Handler
* constants to construct a keyMask. The keyMask is used by
* <checkModifiers>. If the keyMask matches the combination of keys
* down on an event, checkModifiers returns true.
*
* Example:
* (code)
* // handler only responds if the Shift key is down
* handler.keyMask = OpenLayers.Handler.MOD_SHIFT;
*
* // handler only responds if Ctrl-Shift is down
* handler.keyMask = OpenLayers.Handler.MOD_SHIFT |
* OpenLayers.Handler.MOD_CTRL;
* (end)
*/
keyMask: null,
/**
* Property: active
* {Boolean}
*/
active: false,
/**
* Property: evt
* {Event} This property references the last event handled by the handler.
* Note that this property is not part of the stable API. Use of the
* evt property should be restricted to controls in the library
* or other applications that are willing to update with changes to
* the OpenLayers code.
*/
evt: null,
/**
* Constructor: OpenLayers.Handler
* Construct a handler.
*
* Parameters:
* control - {<OpenLayers.Control>} The control that initialized this
* handler. The control is assumed to have a valid map property; that
* map is used in the handler's own setMap method.
* callbacks - {Object} An object whose properties correspond to abstracted
* events or sequences of browser events. The values for these
* properties are functions defined by the control that get called by
* the handler.
* options - {Object} An optional object whose properties will be set on
* the handler.
*/
initialize: function(control, callbacks, options) {
OpenLayers.Util.extend(this, options);
this.control = control;
this.callbacks = callbacks;
if (control.map) {
this.setMap(control.map);
}
OpenLayers.Util.extend(this, options);
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
},
/**
* Method: setMap
*/
setMap: function (map) {
this.map = map;
},
/**
* Method: checkModifiers
* Check the keyMask on the handler. If no <keyMask> is set, this always
* returns true. If a <keyMask> is set and it matches the combination
* of keys down on an event, this returns true.
*
* Returns:
* {Boolean} The keyMask matches the keys down on an event.
*/
checkModifiers: function (evt) {
if(this.keyMask == null) {
return true;
}
/* calculate the keyboard modifier mask for this event */
var keyModifiers =
(evt.shiftKey ? OpenLayers.Handler.MOD_SHIFT : 0) |
(evt.ctrlKey ? OpenLayers.Handler.MOD_CTRL : 0) |
(evt.altKey ? OpenLayers.Handler.MOD_ALT : 0);
/* if it differs from the handler object's key mask,
bail out of the event handler */
return (keyModifiers == this.keyMask);
},
/**
* APIMethod: activate
* Turn on the handler. Returns false if the handler was already active.
*
* Returns:
* {Boolean} The handler was activated.
*/
activate: function() {
if(this.active) {
return false;
}
// register for event handlers defined on this class.
var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
for (var i=0, len=events.length; i<len; i++) {
if (this[events[i]]) {
this.register(events[i], this[events[i]]);
}
}
this.active = true;
return true;
},
/**
* APIMethod: deactivate
* Turn off the handler. Returns false if the handler was already inactive.
*
* Returns:
* {Boolean} The handler was deactivated.
*/
deactivate: function() {
if(!this.active) {
return false;
}
// unregister event handlers defined on this class.
var events = OpenLayers.Events.prototype.BROWSER_EVENTS;
for (var i=0, len=events.length; i<len; i++) {
if (this[events[i]]) {
this.unregister(events[i], this[events[i]]);
}
}
this.active = false;
return true;
},
/**
* Method: callback
* Trigger the control's named callback with the given arguments
*
* Parameters:
* name - {String} The key for the callback that is one of the properties
* of the handler's callbacks object.
* args - {Array(*)} An array of arguments (any type) with which to call
* the callback (defined by the control).
*/
callback: function (name, args) {
if (name && this.callbacks[name]) {
this.callbacks[name].apply(this.control, args);
}
},
/**
* Method: register
* register an event on the map
*/
register: function (name, method) {
// TODO: deal with registerPriority in 3.0
this.map.events.registerPriority(name, this, method);
this.map.events.registerPriority(name, this, this.setEvent);
},
/**
* Method: unregister
* unregister an event from the map
*/
unregister: function (name, method) {
this.map.events.unregister(name, this, method);
this.map.events.unregister(name, this, this.setEvent);
},
/**
* Method: setEvent
* With each registered browser event, the handler sets its own evt
* property. This property can be accessed by controls if needed
* to get more information about the event that the handler is
* processing.
*
* This allows modifier keys on the event to be checked (alt, shift,
* and ctrl cannot be checked with the keyboard handler). For a
* control to determine which modifier keys are associated with the
* event that a handler is currently processing, it should access
* (code)handler.evt.altKey || handler.evt.shiftKey ||
* handler.evt.ctrlKey(end).
*
* Parameters:
* evt - {Event} The browser event.
*/
setEvent: function(evt) {
this.evt = evt;
return true;
},
/**
* Method: destroy
* Deconstruct the handler.
*/
destroy: function () {
// unregister event listeners
this.deactivate();
// eliminate circular references
this.control = this.map = null;
},
CLASS_NAME: "OpenLayers.Handler"
});
/**
* Constant: OpenLayers.Handler.MOD_NONE
* If set as the <keyMask>, <checkModifiers> returns false if any key is down.
*/
OpenLayers.Handler.MOD_NONE = 0;
/**
* Constant: OpenLayers.Handler.MOD_SHIFT
* If set as the <keyMask>, <checkModifiers> returns false if Shift is down.
*/
OpenLayers.Handler.MOD_SHIFT = 1;
/**
* Constant: OpenLayers.Handler.MOD_CTRL
* If set as the <keyMask>, <checkModifiers> returns false if Ctrl is down.
*/
OpenLayers.Handler.MOD_CTRL = 2;
/**
* Constant: OpenLayers.Handler.MOD_ALT
* If set as the <keyMask>, <checkModifiers> returns false if Alt is down.
*/
OpenLayers.Handler.MOD_ALT = 4;

View File

@ -0,0 +1,227 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Class: OpenLayers.Icon
*
* The icon represents a graphical icon on the screen. Typically used in
* conjunction with a <OpenLayers.Marker> to represent markers on a screen.
*
* An icon has a url, size and position. It also contains an offset which
* allows the center point to be represented correctly. This can be
* provided either as a fixed offset or a function provided to calculate
* the desired offset.
*
*/
OpenLayers.Icon = OpenLayers.Class({
/**
* Property: url
* {String} image url
*/
url: null,
/**
* Property: size
* {<OpenLayers.Size>}
*/
size: null,
/**
* Property: offset
* {<OpenLayers.Pixel>} distance in pixels to offset the image when being rendered
*/
offset: null,
/**
* Property: calculateOffset
* {<OpenLayers.Pixel>} Function to calculate the offset (based on the size)
*/
calculateOffset: null,
/**
* Property: imageDiv
* {DOMElement}
*/
imageDiv: null,
/**
* Property: px
* {<OpenLayers.Pixel>}
*/
px: null,
/**
* Constructor: OpenLayers.Icon
* Creates an icon, which is an image tag in a div.
*
* url - {String}
* size - {<OpenLayers.Size>}
* offset - {<OpenLayers.Pixel>}
* calculateOffset - {Function}
*/
initialize: function(url, size, offset, calculateOffset) {
this.url = url;
this.size = (size) ? size : new OpenLayers.Size(20,20);
this.offset = offset ? offset : new OpenLayers.Pixel(-(this.size.w/2), -(this.size.h/2));
this.calculateOffset = calculateOffset;
var id = OpenLayers.Util.createUniqueID("OL_Icon_");
this.imageDiv = OpenLayers.Util.createAlphaImageDiv(id);
},
/**
* Method: destroy
* Nullify references and remove event listeners to prevent circular
* references and memory leaks
*/
destroy: function() {
// erase any drawn elements
this.erase();
OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);
this.imageDiv.innerHTML = "";
this.imageDiv = null;
},
/**
* Method: clone
*
* Returns:
* {<OpenLayers.Icon>} A fresh copy of the icon.
*/
clone: function() {
return new OpenLayers.Icon(this.url,
this.size,
this.offset,
this.calculateOffset);
},
/**
* Method: setSize
*
* Parameters:
* size - {<OpenLayers.Size>}
*/
setSize: function(size) {
if (size != null) {
this.size = size;
}
this.draw();
},
/**
* Method: setUrl
*
* Parameters:
* url - {String}
*/
setUrl: function(url) {
if (url != null) {
this.url = url;
}
this.draw();
},
/**
* Method: draw
* Move the div to the given pixel.
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*
* Returns:
* {DOMElement} A new DOM Image of this icon set at the location passed-in
*/
draw: function(px) {
OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,
null,
null,
this.size,
this.url,
"absolute");
this.moveTo(px);
return this.imageDiv;
},
/**
* Method: erase
* Erase the underlying image element.
*
*/
erase: function() {
if (this.imageDiv != null && this.imageDiv.parentNode != null) {
OpenLayers.Element.remove(this.imageDiv);
}
},
/**
* Method: setOpacity
* Change the icon's opacity
*
* Parameters:
* opacity - {float}
*/
setOpacity: function(opacity) {
OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, null,
null, null, null, null, opacity);
},
/**
* Method: moveTo
* move icon to passed in px.
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*/
moveTo: function (px) {
//if no px passed in, use stored location
if (px != null) {
this.px = px;
}
if (this.imageDiv != null) {
if (this.px == null) {
this.display(false);
} else {
if (this.calculateOffset) {
this.offset = this.calculateOffset(this.size);
}
var offsetPx = this.px.offset(this.offset);
OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, offsetPx);
}
}
},
/**
* Method: display
* Hide or show the icon
*
* Parameters:
* display - {Boolean}
*/
display: function(display) {
this.imageDiv.style.display = (display) ? "" : "none";
},
/**
* APIMethod: isDrawn
*
* Returns:
* {Boolean} Whether or not the icon is drawn.
*/
isDrawn: function() {
// nodeType 11 for ie, whose nodes *always* have a parentNode
// (of type document fragment)
var isDrawn = (this.imageDiv && this.imageDiv.parentNode &&
(this.imageDiv.parentNode.nodeType != 11));
return isDrawn;
},
CLASS_NAME: "OpenLayers.Icon"
});

View File

@ -0,0 +1,132 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Console.js
*/
/**
* Namespace: OpenLayers.Lang
* Internationalization namespace. Contains dictionaries in various languages
* and methods to set and get the current language.
*/
OpenLayers.Lang = {
/**
* Property: code
* {String} Current language code to use in OpenLayers. Use the
* <setCode> method to set this value and the <getCode> method to
* retrieve it.
*/
code: null,
/**
* APIProperty: defaultCode
* {String} Default language to use when a specific language can't be
* found. Default is "en".
*/
defaultCode: "en",
/**
* APIFunction: getCode
* Get the current language code.
*
* Returns:
* The current language code.
*/
getCode: function() {
if(!OpenLayers.Lang.code) {
OpenLayers.Lang.setCode();
}
return OpenLayers.Lang.code;
},
/**
* APIFunction: setCode
* Set the language code for string translation. This code is used by
* the <OpenLayers.Lang.translate> method.
*
* Parameters-
* code - {String} These codes follow the IETF recommendations at
* http://www.ietf.org/rfc/rfc3066.txt. If no value is set, the
* browser's language setting will be tested. If no <OpenLayers.Lang>
* dictionary exists for the code, the <OpenLayers.String.defaultLang>
* will be used.
*/
setCode: function(code) {
var lang;
if(!code) {
code = (OpenLayers.Util.getBrowserName() == "msie") ?
navigator.userLanguage : navigator.language;
}
var parts = code.split('-');
parts[0] = parts[0].toLowerCase();
if(typeof OpenLayers.Lang[parts[0]] == "object") {
lang = parts[0];
}
// check for regional extensions
if(parts[1]) {
var testLang = parts[0] + '-' + parts[1].toUpperCase();
if(typeof OpenLayers.Lang[testLang] == "object") {
lang = testLang;
}
}
if(!lang) {
OpenLayers.Console.warn(
'Failed to find OpenLayers.Lang.' + parts.join("-") +
' dictionary, falling back to default language'
);
lang = OpenLayers.Lang.defaultCode;
}
OpenLayers.Lang.code = lang;
},
/**
* APIMethod: translate
* Looks up a key from a dictionary based on the current language string.
* The value of <getCode> will be used to determine the appropriate
* dictionary. Dictionaries are stored in <OpenLayers.Lang>.
*
* Parameters:
* key - {String} The key for an i18n string value in the dictionary.
* context - {Object} Optional context to be used with
* <OpenLayers.String.format>.
*
* Returns:
* {String} A internationalized string.
*/
translate: function(key, context) {
var dictionary = OpenLayers.Lang[OpenLayers.Lang.getCode()];
var message = dictionary[key];
if(!message) {
// Message not found, fall back to message key
message = key;
}
if(context) {
message = OpenLayers.String.format(message, context);
}
return message;
}
};
/**
* APIMethod: OpenLayers.i18n
* Alias for <OpenLayers.Lang.translate>. Looks up a key from a dictionary
* based on the current language string. The value of
* <OpenLayers.Lang.getCode> will be used to determine the appropriate
* dictionary. Dictionaries are stored in <OpenLayers.Lang>.
*
* Parameters:
* key - {String} The key for an i18n string value in the dictionary.
* context - {Object} Optional context to be used with
* <OpenLayers.String.format>.
*
* Returns:
* {String} A internationalized string.
*/
OpenLayers.i18n = OpenLayers.Lang.translate;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,71 @@
/* Copyright 2006-2008 MetaCarta, Inc., published under the Clear BSD license.
* See http://svn.openlayers.org/trunk/openlayers/license.txt for the full text
* of the license. */
/**
* @requires OpenLayers/Layer/MapServer.js
* @requires OpenLayers/Console.js
*/
/**
* 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>
*/
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:
* {<OpenLayers.Layer.MapServer.Untiled>} 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.options);
}
//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"
});

View File

@ -0,0 +1,156 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Layer/Vector.js
*/
/**
* Class: OpenLayers.Layer.Vector.RootContainer
* A special layer type to combine multiple vector layers inside a single
* renderer root container. This class is not supposed to be instantiated
* from user space, it is a helper class for controls that require event
* processing for multiple vector layers.
*
* Inherits from:
* - <OpenLayers.Layer.Vector>
*/
OpenLayers.Layer.Vector.RootContainer = OpenLayers.Class(OpenLayers.Layer.Vector, {
/**
* Property: displayInLayerSwitcher
* Set to false for this layer type
*/
displayInLayerSwitcher: false,
/**
* APIProperty: layers
* Layers that are attached to this container. Required config option.
*/
layers: null,
/**
* Constructor: OpenLayers.Layer.Vector.RootContainer
* Create a new root container for multiple vector layer. This constructor
* is not supposed to be used from user space, it is only to be used by
* controls that need feature selection across multiple vector layers.
*
* Parameters:
* name - {String} A name for the layer
* options - {Object} Optional object with non-default properties to set on
* the layer.
*
* Required options properties:
* layers - {Array(<OpenLayers.Layer.Vector>)} The layers managed by this
* container
*
* Returns:
* {<OpenLayers.Layer.Vector.RootContainer>} A new vector layer root
* container
*/
initialize: function(name, options) {
OpenLayers.Layer.Vector.prototype.initialize.apply(this, arguments);
},
/**
* Method: display
*/
display: function() {},
/**
* Method: getFeatureFromEvent
* walk through the layers to find the feature returned by the event
*
* Parameters:
* evt - {Object} event object with a feature property
*
* Returns:
* {<OpenLayers.Feature.Vector>}
*/
getFeatureFromEvent: function(evt) {
var layers = this.layers;
var feature;
for(var i=0; i<layers.length; i++) {
feature = layers[i].getFeatureFromEvent(evt);
if(feature) {
return feature;
}
}
},
/**
* Method: setMap
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
setMap: function(map) {
OpenLayers.Layer.Vector.prototype.setMap.apply(this, arguments);
this.collectRoots();
map.events.register("changelayer", this, this.handleChangeLayer);
},
/**
* Method: removeMap
*
* Parameters:
* map - {<OpenLayers.Map>}
*/
removeMap: function(map) {
map.events.unregister("changelayer", this, this.handleChangeLayer);
this.resetRoots();
OpenLayers.Layer.Vector.prototype.removeMap.apply(this, arguments);
},
/**
* Method: collectRoots
* Collects the root nodes of all layers this control is configured with
* and moveswien the nodes to this control's layer
*/
collectRoots: function() {
var layer;
// walk through all map layers, because we want to keep the order
for(var i=0; i<this.map.layers.length; ++i) {
layer = this.map.layers[i];
if(OpenLayers.Util.indexOf(this.layers, layer) != -1) {
layer.renderer.moveRoot(this.renderer);
}
}
},
/**
* Method: resetRoots
* Resets the root nodes back into the layers they belong to.
*/
resetRoots: function() {
var layer;
for(var i=0; i<this.layers.length; ++i) {
layer = this.layers[i];
if(this.renderer && layer.renderer.getRenderLayerId() == this.id) {
this.renderer.moveRoot(layer.renderer);
}
}
},
/**
* Method: handleChangeLayer
* Event handler for the map's changelayer event. We need to rebuild
* this container's layer dom if order of one of its layers changes.
* This handler is added with the setMap method, and removed with the
* removeMap method.
*
* Parameters:
* evt - {Object}
*/
handleChangeLayer: function(evt) {
var layer = evt.layer;
if(evt.property == "order" &&
OpenLayers.Util.indexOf(this.layers, layer) != -1) {
this.resetRoots();
this.collectRoots();
}
},
CLASS_NAME: "OpenLayers.Layer.Vector.RootContainer"
});

View File

@ -0,0 +1,71 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Layer/WMS.js
* @requires OpenLayers/Console.js
*/
/**
* 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>
*/
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:
* {<OpenLayers.Layer.WMS.Untiled>} 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.options);
}
//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"
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,241 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Events.js
* @requires OpenLayers/Icon.js
*/
/**
* Class: OpenLayers.Marker
* Instances of OpenLayers.Marker are a combination of a
* <OpenLayers.LonLat> and an <OpenLayers.Icon>.
*
* Markers are generally added to a special layer called
* <OpenLayers.Layer.Markers>.
*
* Example:
* (code)
* var markers = new OpenLayers.Layer.Markers( "Markers" );
* map.addLayer(markers);
*
* var size = new OpenLayers.Size(10,17);
* var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
* var icon = new OpenLayers.Icon('http://boston.openguides.org/markers/AQUA.png',size,offset);
* markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon));
* markers.addMarker(new OpenLayers.Marker(new OpenLayers.LonLat(0,0),icon.clone()));
*
* (end)
*
* Note that if you pass an icon into the Marker constructor, it will take
* that icon and use it. This means that you should not share icons between
* markers -- you use them once, but you should clone() for any additional
* markers using that same icon.
*/
OpenLayers.Marker = OpenLayers.Class({
/**
* Property: icon
* {<OpenLayers.Icon>} The icon used by this marker.
*/
icon: null,
/**
* Property: lonlat
* {<OpenLayers.LonLat>} location of object
*/
lonlat: null,
/**
* Property: events
* {<OpenLayers.Events>} the event handler.
*/
events: null,
/**
* Property: map
* {<OpenLayers.Map>} the map this marker is attached to
*/
map: null,
/**
* Constructor: OpenLayers.Marker
* Parameters:
* lonlat - {<OpenLayers.LonLat>} the position of this marker
* icon - {<OpenLayers.Icon>} the icon for this marker
*/
initialize: function(lonlat, icon) {
this.lonlat = lonlat;
var newIcon = (icon) ? icon : OpenLayers.Marker.defaultIcon();
if (this.icon == null) {
this.icon = newIcon;
} else {
this.icon.url = newIcon.url;
this.icon.size = newIcon.size;
this.icon.offset = newIcon.offset;
this.icon.calculateOffset = newIcon.calculateOffset;
}
this.events = new OpenLayers.Events(this, this.icon.imageDiv, null);
},
/**
* APIMethod: destroy
* Destroy the marker. You must first remove the marker from any
* layer which it has been added to, or you will get buggy behavior.
* (This can not be done within the marker since the marker does not
* know which layer it is attached to.)
*/
destroy: function() {
// erase any drawn features
this.erase();
this.map = null;
this.events.destroy();
this.events = null;
if (this.icon != null) {
this.icon.destroy();
this.icon = null;
}
},
/**
* Method: draw
* Calls draw on the icon, and returns that output.
*
* Parameters:
* px - {<OpenLayers.Pixel>}
*
* Returns:
* {DOMElement} A new DOM Image with this marker's icon set at the
* location passed-in
*/
draw: function(px) {
return this.icon.draw(px);
},
/**
* Method: erase
* Erases any drawn elements for this marker.
*/
erase: function() {
if (this.icon != null) {
this.icon.erase();
}
},
/**
* Method: moveTo
* Move the marker to the new location.
*
* Parameters:
* px - {<OpenLayers.Pixel>} the pixel position to move to
*/
moveTo: function (px) {
if ((px != null) && (this.icon != null)) {
this.icon.moveTo(px);
}
this.lonlat = this.map.getLonLatFromLayerPx(px);
},
/**
* APIMethod: isDrawn
*
* Returns:
* {Boolean} Whether or not the marker is drawn.
*/
isDrawn: function() {
var isDrawn = (this.icon && this.icon.isDrawn());
return isDrawn;
},
/**
* Method: onScreen
*
* Returns:
* {Boolean} Whether or not the marker is currently visible on screen.
*/
onScreen:function() {
var onScreen = false;
if (this.map) {
var screenBounds = this.map.getExtent();
onScreen = screenBounds.containsLonLat(this.lonlat);
}
return onScreen;
},
/**
* Method: inflate
* Englarges the markers icon by the specified ratio.
*
* Parameters:
* inflate - {float} the ratio to enlarge the marker by (passing 2
* will double the size).
*/
inflate: function(inflate) {
if (this.icon) {
var newSize = new OpenLayers.Size(this.icon.size.w * inflate,
this.icon.size.h * inflate);
this.icon.setSize(newSize);
}
},
/**
* Method: setOpacity
* Change the opacity of the marker by changin the opacity of
* its icon
*
* Parameters:
* opacity - {float} Specified as fraction (0.4, etc)
*/
setOpacity: function(opacity) {
this.icon.setOpacity(opacity);
},
/**
* Method: setUrl
* Change URL of the Icon Image.
*
* url - {String}
*/
setUrl: function(url) {
this.icon.setUrl(url);
},
/**
* Method: display
* Hide or show the icon
*
* display - {Boolean}
*/
display: function(display) {
this.icon.display(display);
},
CLASS_NAME: "OpenLayers.Marker"
});
/**
* Function: defaultIcon
* Creates a default <OpenLayers.Icon>.
*
* Returns:
* {<OpenLayers.Icon>} A default OpenLayers.Icon to use for a marker
*/
OpenLayers.Marker.defaultIcon = function() {
var url = OpenLayers.Util.getImagesLocation() + "marker.png";
var size = new OpenLayers.Size(21, 25);
var calculateOffset = function(size) {
return new OpenLayers.Pixel(-(size.w/2), -size.h);
};
return new OpenLayers.Icon(url, size, null, calculateOffset);
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,177 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Util.js
*/
/**
* Class: OpenLayers.Projection
* Class for coordinate transforms between coordinate systems.
* Depends on the proj4js library. If proj4js is not available,
* then this is just an empty stub.
*/
OpenLayers.Projection = OpenLayers.Class({
/**
* Property: proj
* {Object} Proj4js.Proj instance.
*/
proj: null,
/**
* Property: projCode
* {String}
*/
projCode: null,
/**
* Constructor: OpenLayers.Projection
* This class offers several methods for interacting with a wrapped
* pro4js projection object.
*
* Parameters:
* projCode - {String} A string identifying the Well Known Identifier for
* the projection.
* options - {Object} An optional object to set additional properties
* on the layer.
*
* Returns:
* {<OpenLayers.Projection>} A projection object.
*/
initialize: function(projCode, options) {
OpenLayers.Util.extend(this, options);
this.projCode = projCode;
if (window.Proj4js) {
this.proj = new Proj4js.Proj(projCode);
}
},
/**
* APIMethod: getCode
* Get the string SRS code.
*
* Returns:
* {String} The SRS code.
*/
getCode: function() {
return this.proj ? this.proj.srsCode : this.projCode;
},
/**
* APIMethod: getUnits
* Get the units string for the projection -- returns null if
* proj4js is not available.
*
* Returns:
* {String} The units abbreviation.
*/
getUnits: function() {
return this.proj ? this.proj.units : null;
},
/**
* Method: toString
* Convert projection to string (getCode wrapper).
*
* Returns:
* {String} The projection code.
*/
toString: function() {
return this.getCode();
},
/**
* Method: equals
* Test equality of two projection instances. Determines equality based
* soley on the projection code.
*
* Returns:
* {Boolean} The two projections are equivalent.
*/
equals: function(projection) {
if (projection && projection.getCode) {
return this.getCode() == projection.getCode();
} else {
return false;
}
},
/* Method: destroy
* Destroy projection object.
*/
destroy: function() {
delete this.proj;
delete this.projCode;
},
CLASS_NAME: "OpenLayers.Projection"
});
/**
* Property: transforms
* Transforms is an object, with from properties, each of which may
* have a to property. This allows you to define projections without
* requiring support for proj4js to be included.
*
* This object has keys which correspond to a 'source' projection object. The
* keys should be strings, corresponding to the projection.getCode() value.
* Each source projection object should have a set of destination projection
* keys included in the object.
*
* Each value in the destination object should be a transformation function,
* where the function is expected to be passed an object with a .x and a .y
* property. The function should return the object, with the .x and .y
* transformed according to the transformation function.
*
* Note - Properties on this object should not be set directly. To add a
* transform method to this object, use the <addTransform> method. For an
* example of usage, see the OpenLayers.Layer.SphericalMercator file.
*/
OpenLayers.Projection.transforms = {};
/**
* APIMethod: addTransform
* Set a custom transform method between two projections. Use this method in
* cases where the proj4js lib is not available or where custom projections
* need to be handled.
*
* Parameters:
* from - {String} The code for the source projection
* to - {String} the code for the destination projection
* method - {Function} A function that takes a point as an argument and
* transforms that point from the source to the destination projection
* in place. The original point should be modified.
*/
OpenLayers.Projection.addTransform = function(from, to, method) {
if(!OpenLayers.Projection.transforms[from]) {
OpenLayers.Projection.transforms[from] = {};
}
OpenLayers.Projection.transforms[from][to] = method;
};
/**
* APIMethod: transform
* Transform a point coordinate from one projection to another. Note that
* the input point is transformed in place.
*
* Parameters:
* point - {{OpenLayers.Geometry.Point> | Object} An object with x and y
* properties representing coordinates in those dimensions.
* sourceProj - {OpenLayers.Projection} Source map coordinate system
* destProj - {OpenLayers.Projection} Destination map coordinate system
*
* Returns:
* point - {object} A transformed coordinate. The original point is modified.
*/
OpenLayers.Projection.transform = function(point, source, dest) {
if (source.proj && dest.proj) {
point = Proj4js.transform(source.proj, dest.proj, point);
} else if (source && dest &&
OpenLayers.Projection.transforms[source.getCode()] &&
OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]) {
OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point);
}
return point;
};

View File

@ -0,0 +1,227 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Class: OpenLayers.Protocol
* Abstract vector layer protocol class. Not to be instantiated directly. Use
* one of the protocol subclasses instead.
*/
OpenLayers.Protocol = OpenLayers.Class({
/**
* Property: format
* {<OpenLayers.Format>} The format used by this protocol.
*/
format: null,
/**
* Property: options
* {Object} Any options sent to the constructor.
*/
options: null,
/**
* Property: autoDestroy
* {Boolean} The creator of the protocol can set autoDestroy to false
* to fully control when the protocol is destroyed. Defaults to
* true.
*/
autoDestroy: true,
/**
* Constructor: OpenLayers.Protocol
* Abstract class for vector protocols. Create instances of a subclass.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*/
initialize: function(options) {
options = options || {};
OpenLayers.Util.extend(this, options);
this.options = options;
},
/**
* APIMethod: destroy
* Clean up the protocol.
*/
destroy: function() {
this.options = null;
this.format = null;
},
/**
* APIMethod: read
* Construct a request for reading new features.
*
* Parameters:
* options - {Object} Optional object for configuring the request.
*
* Returns:
* {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
* object, the same object will be passed to the callback function passed
* if one exists in the options object.
*/
read: function() {
},
/**
* APIMethod: create
* Construct a request for writing newly created features.
*
* Parameters:
* features - {Array({<OpenLayers.Feature.Vector>})} or
* {<OpenLayers.Feature.Vector>}
* options - {Object} Optional object for configuring the request.
*
* Returns:
* {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
* object, the same object will be passed to the callback function passed
* if one exists in the options object.
*/
create: function() {
},
/**
* APIMethod: update
* Construct a request updating modified features.
*
* Parameters:
* features - {Array({<OpenLayers.Feature.Vector>})} or
* {<OpenLayers.Feature.Vector>}
* options - {Object} Optional object for configuring the request.
*
* Returns:
* {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
* object, the same object will be passed to the callback function passed
* if one exists in the options object.
*/
update: function() {
},
/**
* APIMethod: delete
* Construct a request deleting a removed feature.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
* options - {Object} Optional object for configuring the request.
*
* Returns:
* {<OpenLayers.Protocol.Response>} An <OpenLayers.Protocol.Response>
* object, the same object will be passed to the callback function passed
* if one exists in the options object.
*/
"delete": function() {
},
/**
* 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({<OpenLayers.Feature.Vector>})}
* 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({<OpenLayers.Protocol.Response>})} An array of
* <OpenLayers.Protocol.Response> objects.
*/
commit: function() {
},
/**
* Method: abort
* Abort an ongoing request.
*
* Parameters:
* response - {<OpenLayers.Protocol.Response>}
*/
abort: function(response) {
},
CLASS_NAME: "OpenLayers.Protocol"
});
/**
* Class: OpenLayers.Protocol.Response
* Protocols return Response objects to their users.
*/
OpenLayers.Protocol.Response = OpenLayers.Class({
/**
* Property: code
* {Number} - OpenLayers.Protocol.Response.SUCCESS or
* OpenLayers.Protocol.Response.FAILURE
*/
code: null,
/**
* Property: requestType
* {String} The type of request this response corresponds to. Either
* "create", "read", "update" or "delete".
*/
requestType: null,
/**
* Property: last
* {Boolean} - true if this is the last response expected in a commit,
* false otherwise, defaults to true.
*/
last: true,
/**
* Property: features
* {Array({<OpenLayers.Feature.Vector>})} or {<OpenLayers.Feature.Vector>}
* The features returned in the response by the server.
*/
features: null,
/**
* Property: reqFeatures
* {Array({<OpenLayers.Feature.Vector>})} or {<OpenLayers.Feature.Vector>}
* The features provided by the user and placed in the request by the
* protocol.
*/
reqFeatures: null,
/**
* Property: priv
*/
priv: null,
/**
* Constructor: OpenLayers.Protocol.Response
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*/
initialize: function(options) {
OpenLayers.Util.extend(this, options);
},
/**
* Method: success
*
* Returns:
* {Boolean} - true on success, false otherwise
*/
success: function() {
return this.code > 0;
},
CLASS_NAME: "OpenLayers.Protocol.Response"
});
OpenLayers.Protocol.Response.SUCCESS = 1;
OpenLayers.Protocol.Response.FAILURE = 0;

View File

@ -0,0 +1,301 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Class: OpenLayers.Renderer
* This is the base class for all renderers.
*
* This is based on a merger code written by Paul Spencer and Bertil Chapuis.
* It is largely composed of virtual functions that are to be implemented
* in technology-specific subclasses, but there is some generic code too.
*
* The functions that *are* implemented here merely deal with the maintenance
* of the size and extent variables, as well as the cached 'resolution'
* value.
*
* A note to the user that all subclasses should use getResolution() instead
* of directly accessing this.resolution in order to correctly use the
* cacheing system.
*
*/
OpenLayers.Renderer = OpenLayers.Class({
/**
* Property: container
* {DOMElement}
*/
container: null,
/**
* Property: root
* {DOMElement}
*/
root: null,
/**
* Property: extent
* {<OpenLayers.Bounds>}
*/
extent: null,
/**
* Property: locked
* {Boolean} If the renderer is currently in a state where many things
* are changing, the 'locked' property is set to true. This means
* that renderers can expect at least one more drawFeature event to be
* called with the 'locked' property set to 'true': In some renderers,
* this might make sense to use as a 'only update local information'
* flag.
*/
locked: false,
/**
* Property: size
* {<OpenLayers.Size>}
*/
size: null,
/**
* Property: resolution
* {Float} cache of current map resolution
*/
resolution: null,
/**
* Property: map
* {<OpenLayers.Map>} Reference to the map -- this is set in Vector's setMap()
*/
map: null,
/**
* Constructor: OpenLayers.Renderer
*
* Parameters:
* containerID - {<String>}
* options - {Object} options for this renderer. See sublcasses for
* supported options.
*/
initialize: function(containerID, options) {
this.container = OpenLayers.Util.getElement(containerID);
},
/**
* APIMethod: destroy
*/
destroy: function() {
this.container = null;
this.extent = null;
this.size = null;
this.resolution = null;
this.map = null;
},
/**
* APIMethod: supported
* This should be overridden by specific subclasses
*
* Returns:
* {Boolean} Whether or not the browser supports the renderer class
*/
supported: function() {
return false;
},
/**
* Method: setExtent
* Set the visible part of the layer.
*
* Resolution has probably changed, so we nullify the resolution
* cache (this.resolution) -- this way it will be re-computed when
* next it is needed.
* We nullify the resolution cache (this.resolution) if resolutionChanged
* is set to true - this way it will be re-computed on the next
* getResolution() request.
*
* Parameters:
* extent - {<OpenLayers.Bounds>}
* resolutionChanged - {Boolean}
*/
setExtent: function(extent, resolutionChanged) {
this.extent = extent.clone();
if (resolutionChanged) {
this.resolution = null;
}
},
/**
* Method: setSize
* Sets the size of the drawing surface.
*
* Resolution has probably changed, so we nullify the resolution
* cache (this.resolution) -- this way it will be re-computed when
* next it is needed.
*
* Parameters:
* size - {<OpenLayers.Size>}
*/
setSize: function(size) {
this.size = size.clone();
this.resolution = null;
},
/**
* Method: getResolution
* Uses cached copy of resolution if available to minimize computing
*
* Returns:
* The current map's resolution
*/
getResolution: function() {
this.resolution = this.resolution || this.map.getResolution();
return this.resolution;
},
/**
* 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 - {<OpenLayers.Feature.Vector>}
* style - {<Object>}
*
* 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 bounds = feature.geometry.getBounds();
if(bounds) {
if (!bounds.intersectsBounds(this.extent)) {
style = {display: "none"};
}
var rendered = this.drawGeometry(feature.geometry, style, feature.id);
if(style.display != "none" && style.label && rendered !== false) {
this.drawText(feature.id, style, feature.geometry.getCentroid());
} else {
this.removeText(feature.id);
}
return rendered;
}
}
},
/**
* Method: drawGeometry
*
* Draw a geometry. This should only be called from the renderer itself.
* Use layer.drawFeature() from outside the renderer.
* virtual function
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
* style - {Object}
* featureId - {<String>}
*/
drawGeometry: function(geometry, style, featureId) {},
/**
* Method: drawText
* Function for drawing text labels.
* This method is only called by the renderer itself.
*
* Parameters:
* featureId - {String}
* style -
* location - {<OpenLayers.Geometry.Point>}
*/
drawText: function(featureId, style, location) {},
/**
* Method: removeText
* Function for removing text labels.
* This method is only called by the renderer itself.
*
* Parameters:
* featureId - {String}
*/
removeText: function(featureId) {},
/**
* Method: clear
* Clear all vectors from the renderer.
* virtual function.
*/
clear: function() {},
/**
* Method: getFeatureIdFromEvent
* Returns a feature id from an event on the renderer.
* How this happens is specific to the renderer. This should be
* called from layer.getFeatureFromEvent().
* Virtual function.
*
* Parameters:
* evt - {<OpenLayers.Event>}
*
* Returns:
* {String} A feature id or null.
*/
getFeatureIdFromEvent: function(evt) {},
/**
* Method: eraseFeatures
* This is called by the layer to erase features
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>)}
*/
eraseFeatures: function(features) {
if(!(features instanceof Array)) {
features = [features];
}
for(var i=0, len=features.length; i<len; ++i) {
this.eraseGeometry(features[i].geometry);
this.removeText(features[i].id);
}
},
/**
* Method: eraseGeometry
* Remove a geometry from the renderer (by id).
* virtual function.
*
* Parameters:
* geometry - {<OpenLayers.Geometry>}
*/
eraseGeometry: function(geometry) {},
/**
* Method: moveRoot
* moves this renderer's root to a (different) renderer.
* To be implemented by subclasses that require a common renderer root for
* feature selection.
*
* Parameters:
* renderer - {<OpenLayers.Renderer>} target renderer for the moved root
*/
moveRoot: function(renderer) {},
/**
* Method: getRenderLayerId
* Gets the layer that this renderer's output appears on. If moveRoot was
* used, this will be different from the id of the layer containing the
* features rendered by this renderer.
*
* Returns:
* {String} the id of the output layer.
*/
getRenderLayerId: function() {
return this.container.id;
},
CLASS_NAME: "OpenLayers.Renderer"
});

View File

@ -0,0 +1,332 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Events.js
*/
/**
* Namespace: OpenLayers.Request
* The OpenLayers.Request namespace contains convenience methods for working
* with XMLHttpRequests. These methods work with a cross-browser
* W3C compliant <OpenLayers.Request.XMLHttpRequest> class.
*/
OpenLayers.Request = {
/**
* Constant: DEFAULT_CONFIG
* {Object} Default configuration for all requests.
*/
DEFAULT_CONFIG: {
method: "GET",
url: window.location.href,
async: true,
user: undefined,
password: undefined,
params: null,
proxy: OpenLayers.ProxyHost,
headers: {},
data: null,
callback: function() {},
success: null,
failure: null,
scope: null
},
/**
* APIProperty: events
* {<OpenLayers.Events>} An events object that handles all
* events on the {<OpenLayers.Request>} object.
*
* All event listeners will receive an event object with three properties:
* request - {<OpenLayers.Request.XMLHttpRequest>} The request object.
* config - {Object} The config object sent to the specific request method.
* requestUrl - {String} The request url.
*
* Supported event types:
* complete - Triggered when we have a response from the request, if a
* listener returns false, no further response processing will take
* place.
* success - Triggered when the HTTP response has a success code (200-299).
* failure - Triggered when the HTTP response does not have a success code.
*/
events: new OpenLayers.Events(this, null, ["complete", "success", "failure"]),
/**
* APIMethod: issue
* Create a new XMLHttpRequest object, open it, set any headers, bind
* a callback to done state, and send any data. It is recommended that
* you use one <GET>, <POST>, <PUT>, <DELETE>, <OPTIONS>, or <HEAD>.
* This method is only documented to provide detail on the configuration
* options available to all request methods.
*
* Parameters:
* config - {Object} Object containing properties for configuring the
* request. Allowed configuration properties are described below.
* This object is modified and should not be reused.
*
* Allowed config properties:
* method - {String} One of GET, POST, PUT, DELETE, HEAD, or
* OPTIONS. Default is GET.
* url - {String} URL for the request.
* async - {Boolean} Open an asynchronous request. Default is true.
* user - {String} User for relevant authentication scheme. Set
* to null to clear current user.
* password - {String} Password for relevant authentication scheme.
* Set to null to clear current password.
* proxy - {String} Optional proxy. Defaults to
* <OpenLayers.ProxyHost>.
* params - {Object} Any key:value pairs to be appended to the
* url as a query string. Assumes url doesn't already include a query
* string or hash. Typically, this is only appropriate for <GET>
* requests where the query string will be appended to the url.
* Parameter values that are arrays will be
* concatenated with a comma (note that this goes against form-encoding)
* as is done with <OpenLayers.Util.getParameterString>.
* headers - {Object} Object with header:value pairs to be set on
* the request.
* data - {String | Document} Optional data to send with the request.
* Typically, this is only used with <POST> and <PUT> requests.
* Make sure to provide the appropriate "Content-Type" header for your
* data. For <POST> and <PUT> requests, the content type defaults to
* "application-xml". If your data is a different content type, or
* if you are using a different HTTP method, set the "Content-Type"
* header to match your data type.
* callback - {Function} Function to call when request is done.
* To determine if the request failed, check request.status (200
* indicates success).
* success - {Function} Optional function to call if request status is in
* the 200s. This will be called in addition to callback above and
* would typically only be used as an alternative.
* failure - {Function} Optional function to call if request status is not
* in the 200s. This will be called in addition to callback above and
* would typically only be used as an alternative.
* scope - {Object} If callback is a public method on some object,
* set the scope to that object.
*
* Returns:
* {XMLHttpRequest} Request object. To abort the request before a response
* is received, call abort() on the request object.
*/
issue: function(config) {
// apply default config - proxy host may have changed
var defaultConfig = OpenLayers.Util.extend(
this.DEFAULT_CONFIG,
{proxy: OpenLayers.ProxyHost}
);
config = OpenLayers.Util.applyDefaults(config, defaultConfig);
// create request, open, and set headers
var request = new OpenLayers.Request.XMLHttpRequest();
var url = config.url;
if(config.params) {
var paramString = OpenLayers.Util.getParameterString(config.params);
if(paramString.length > 0) {
var separator = (url.indexOf('?') > -1) ? '&' : '?';
url += separator + paramString;
}
}
if(config.proxy && (url.indexOf("http") == 0)) {
url = config.proxy + encodeURIComponent(url);
}
request.open(
config.method, url, config.async, config.user, config.password
);
for(var header in config.headers) {
request.setRequestHeader(header, config.headers[header]);
}
// bind callbacks to readyState 4 (done)
var complete = (config.scope) ?
OpenLayers.Function.bind(config.callback, config.scope) :
config.callback;
// optional success callback
var success;
if(config.success) {
success = (config.scope) ?
OpenLayers.Function.bind(config.success, config.scope) :
config.success;
}
// optional failure callback
var failure;
if(config.failure) {
failure = (config.scope) ?
OpenLayers.Function.bind(config.failure, config.scope) :
config.failure;
}
var events = this.events;
request.onreadystatechange = function() {
if(request.readyState == OpenLayers.Request.XMLHttpRequest.DONE) {
var proceed = events.triggerEvent(
"complete",
{request: request, config: config, requestUrl: url}
);
if(proceed !== false) {
complete(request);
if (!request.status || (request.status >= 200 && request.status < 300)) {
events.triggerEvent(
"success",
{request: request, config: config, requestUrl: url}
);
if(success) {
success(request);
}
}
if(request.status && (request.status < 200 || request.status >= 300)) {
events.triggerEvent(
"failure",
{request: request, config: config, requestUrl: url}
);
if(failure) {
failure(request);
}
}
}
}
};
// send request (optionally with data) and return
// call in a timeout for asynchronous requests so the return is
// available before readyState == 4 for cached docs
if(config.async === false) {
request.send(config.data);
} else {
window.setTimeout(function(){
request.send(config.data);
}, 0);
}
return request;
},
/**
* APIMethod: GET
* Send an HTTP GET request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to GET.
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties.
* This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
GET: function(config) {
config = OpenLayers.Util.extend(config, {method: "GET"});
return OpenLayers.Request.issue(config);
},
/**
* APIMethod: POST
* Send a POST request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to POST and "Content-Type" header set to "application/xml".
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties. The
* default "Content-Type" header will be set to "application-xml" if
* none is provided. This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
POST: function(config) {
config = OpenLayers.Util.extend(config, {method: "POST"});
// set content type to application/xml if it isn't already set
config.headers = config.headers ? config.headers : {};
if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
config.headers["Content-Type"] = "application/xml";
}
return OpenLayers.Request.issue(config);
},
/**
* APIMethod: PUT
* Send an HTTP PUT request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to PUT and "Content-Type" header set to "application/xml".
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties. The
* default "Content-Type" header will be set to "application-xml" if
* none is provided. This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
PUT: function(config) {
config = OpenLayers.Util.extend(config, {method: "PUT"});
// set content type to application/xml if it isn't already set
config.headers = config.headers ? config.headers : {};
if(!("CONTENT-TYPE" in OpenLayers.Util.upperCaseObject(config.headers))) {
config.headers["Content-Type"] = "application/xml";
}
return OpenLayers.Request.issue(config);
},
/**
* APIMethod: DELETE
* Send an HTTP DELETE request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to DELETE.
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties.
* This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
DELETE: function(config) {
config = OpenLayers.Util.extend(config, {method: "DELETE"});
return OpenLayers.Request.issue(config);
},
/**
* APIMethod: HEAD
* Send an HTTP HEAD request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to HEAD.
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties.
* This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
HEAD: function(config) {
config = OpenLayers.Util.extend(config, {method: "HEAD"});
return OpenLayers.Request.issue(config);
},
/**
* APIMethod: OPTIONS
* Send an HTTP OPTIONS request. Additional configuration properties are
* documented in the <issue> method, with the method property set
* to OPTIONS.
*
* Parameters:
* config - {Object} Object with properties for configuring the request.
* See the <issue> method for documentation of allowed properties.
* This object is modified and should not be reused.
*
* Returns:
* {XMLHttpRequest} Request object.
*/
OPTIONS: function(config) {
config = OpenLayers.Util.extend(config, {method: "OPTIONS"});
return OpenLayers.Request.issue(config);
}
};

View File

@ -0,0 +1,209 @@
/* Copyright (c) 2006 MetaCarta, Inc., published under a modified BSD license.
* See http://svn.openlayers.org/trunk/openlayers/repository-license.txt
* for the full text of the license. */
/**
* @requires OpenLayers/Util.js
* @requires OpenLayers/Style.js
*/
/**
* Class: OpenLayers.Rule
* This class represents an SLD Rule, as being used for rule-based SLD styling.
*/
OpenLayers.Rule = OpenLayers.Class({
/**
* Property: id
* {String} A unique id for this session.
*/
id: null,
/**
* APIProperty: name
* {String} name of this rule
*/
name: 'default',
/**
* Property: title
* {String} Title of this rule (set if included in SLD)
*/
title: null,
/**
* Property: description
* {String} Description of this rule (set if abstract is included in SLD)
*/
description: null,
/**
* Property: context
* {Object} An optional object with properties that the rule should be
* evaluated against. If no context is specified, feature.attributes will
* be used.
*/
context: null,
/**
* Property: filter
* {<OpenLayers.Filter>} Optional filter for the rule.
*/
filter: null,
/**
* Property: elseFilter
* {Boolean} Determines whether this rule is only to be applied only if
* no other rules match (ElseFilter according to the SLD specification).
* Default is false. For instances of OpenLayers.Rule, if elseFilter is
* false, the rule will always apply. For subclasses, the else property is
* ignored.
*/
elseFilter: false,
/**
* Property: symbolizer
* {Object} Symbolizer or hash of symbolizers for this rule. If hash of
* symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The
* latter if useful if it is required to style e.g. vertices of a line
* with a point symbolizer. Note, however, that this is not implemented
* yet in OpenLayers, but it is the way how symbolizers are defined in
* SLD.
*/
symbolizer: null,
/**
* APIProperty: minScaleDenominator
* {Number} or {String} minimum scale at which to draw the feature.
* In the case of a String, this can be a combination of text and
* propertyNames in the form "literal ${propertyName}"
*/
minScaleDenominator: null,
/**
* APIProperty: maxScaleDenominator
* {Number} or {String} maximum scale at which to draw the feature.
* In the case of a String, this can be a combination of text and
* propertyNames in the form "literal ${propertyName}"
*/
maxScaleDenominator: null,
/**
* Constructor: OpenLayers.Rule
* Creates a Rule.
*
* Parameters:
* options - {Object} An optional object with properties to set on the
* rule
*
* Returns:
* {<OpenLayers.Rule>}
*/
initialize: function(options) {
this.symbolizer = {};
OpenLayers.Util.extend(this, options);
this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
},
/**
* APIMethod: destroy
* nullify references to prevent circular references and memory leaks
*/
destroy: function() {
for (var i in this.symbolizer) {
this.symbolizer[i] = null;
}
this.symbolizer = null;
},
/**
* APIMethod: evaluate
* evaluates this rule for a specific feature
*
* Parameters:
* feature - {<OpenLayers.Feature>} feature to apply the rule to.
*
* Returns:
* {Boolean} true if the rule applies, false if it does not.
* This rule is the default rule and always returns true.
*/
evaluate: function(feature) {
var context = this.getContext(feature);
var applies = true;
if (this.minScaleDenominator || this.maxScaleDenominator) {
var scale = feature.layer.map.getScale();
}
// check if within minScale/maxScale bounds
if (this.minScaleDenominator) {
applies = scale >= OpenLayers.Style.createLiteral(
this.minScaleDenominator, context);
}
if (applies && this.maxScaleDenominator) {
applies = scale < OpenLayers.Style.createLiteral(
this.maxScaleDenominator, context);
}
// check if optional filter applies
if(applies && this.filter) {
// feature id filters get the feature, others get the context
if(this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") {
applies = this.filter.evaluate(feature);
} else {
applies = this.filter.evaluate(context);
}
}
return applies;
},
/**
* Method: getContext
* Gets the context for evaluating this rule
*
* Paramters:
* feature - {<OpenLayers.Feature>} feature to take the context from if
* none is specified.
*/
getContext: function(feature) {
var context = this.context;
if (!context) {
context = feature.attributes || feature.data;
}
if (typeof this.context == "function") {
context = this.context(feature);
}
return context;
},
/**
* APIMethod: clone
* Clones this rule.
*
* Returns:
* {<OpenLayers.Rule>} Clone of this rule.
*/
clone: function() {
var options = OpenLayers.Util.extend({}, this);
// clone symbolizer
options.symbolizer = {};
for(var key in this.symbolizer) {
value = this.symbolizer[key];
type = typeof value;
if(type === "object") {
options.symbolizer[key] = OpenLayers.Util.extend({}, value);
} else if(type === "string") {
options.symbolizer[key] = value;
}
}
// clone filter
options.filter = this.filter && this.filter.clone();
// clone context
options.context = this.context && OpenLayers.Util.extend({}, this.context);
return new OpenLayers.Rule(options);
},
CLASS_NAME: "OpenLayers.Rule"
});

View File

@ -0,0 +1,9 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
var OpenLayers = {
singleFile: true
};

View File

@ -0,0 +1,116 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* Class: OpenLayers.Strategy
* Abstract vector layer strategy class. Not to be instantiated directly. Use
* one of the strategy subclasses instead.
*/
OpenLayers.Strategy = OpenLayers.Class({
/**
* Property: layer
* {<OpenLayers.Layer.Vector>} The layer this strategy belongs to.
*/
layer: null,
/**
* Property: options
* {Object} Any options sent to the constructor.
*/
options: null,
/**
* Property: active
* {Boolean} The control is active.
*/
active: null,
/**
* Property: autoActivate
* {Boolean} The creator of the strategy can set autoActivate to false
* to fully control when the protocol is activated and deactivated.
* Defaults to true.
*/
autoActivate: true,
/**
* Property: autoDestroy
* {Boolean} The creator of the strategy can set autoDestroy to false
* to fully control when the strategy is destroyed. Defaults to
* true.
*/
autoDestroy: true,
/**
* Constructor: OpenLayers.Strategy
* Abstract class for vector strategies. Create instances of a subclass.
*
* Parameters:
* options - {Object} Optional object whose properties will be set on the
* instance.
*/
initialize: function(options) {
OpenLayers.Util.extend(this, options);
this.options = options;
// set the active property here, so that user cannot override it
this.active = false;
},
/**
* APIMethod: destroy
* Clean up the strategy.
*/
destroy: function() {
this.deactivate();
this.layer = null;
this.options = null;
},
/**
* Method: setLayer
* Called to set the <layer> property.
*
* Parameters:
* {<OpenLayers.Layer.Vector>}
*/
setLayer: function(layer) {
this.layer = layer;
},
/**
* Method: activate
* Activate the strategy. Register any listeners, do appropriate setup.
*
* Returns:
* {Boolean} True if the strategy was successfully activated or false if
* the strategy was already active.
*/
activate: function() {
if (!this.active) {
this.active = true;
return true;
}
return false;
},
/**
* Method: deactivate
* Deactivate the strategy. Unregister any listeners, do appropriate
* tear-down.
*
* Returns:
* {Boolean} True if the strategy was successfully deactivated or false if
* the strategy was already inactive.
*/
deactivate: function() {
if (this.active) {
this.active = false;
return true;
}
return false;
},
CLASS_NAME: "OpenLayers.Strategy"
});

View File

@ -0,0 +1,407 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Util.js
* @requires OpenLayers/Feature/Vector.js
*/
/**
* Class: OpenLayers.Style
* This class represents a UserStyle obtained
* from a SLD, containing styling rules.
*/
OpenLayers.Style = OpenLayers.Class({
/**
* APIProperty: name
* {String}
*/
name: null,
/**
* Property: title
* {String} Title of this style (set if included in SLD)
*/
title: null,
/**
* Property: description
* {String} Description of this style (set if abstract is included in SLD)
*/
description: null,
/**
* APIProperty: layerName
* {<String>} name of the layer that this style belongs to, usually
* according to the NamedLayer attribute of an SLD document.
*/
layerName: null,
/**
* APIProperty: isDefault
* {Boolean}
*/
isDefault: false,
/**
* Property: rules
* {Array(<OpenLayers.Rule>)}
*/
rules: null,
/**
* Property: context
* {Object} An optional object with properties that symbolizers' property
* values should be evaluated against. If no context is specified,
* feature.attributes will be used
*/
context: null,
/**
* Property: defaultStyle
* {Object} hash of style properties to use as default for merging
* rule-based style symbolizers onto. If no rules are defined,
* createSymbolizer will return this style. If <defaultsPerSymbolizer> is set to
* true, the defaultStyle will only be taken into account if there are
* rules defined.
*/
defaultStyle: null,
/**
* Property: defaultsPerSymbolizer
* {Boolean} If set to true, the <defaultStyle> will extend the symbolizer
* of every rule. Properties of the <defaultStyle> will also be used to set
* missing symbolizer properties if the symbolizer has stroke, fill or
* graphic set to true. Default is false.
*/
defaultsPerSymbolizer: false,
/**
* Property: propertyStyles
* {Hash of Boolean} cache of style properties that need to be parsed for
* propertyNames. Property names are keys, values won't be used.
*/
propertyStyles: null,
/**
* Constructor: OpenLayers.Style
* Creates a UserStyle.
*
* Parameters:
* style - {Object} Optional hash of style properties that will be
* used as default style for this style object. This style
* applies if no rules are specified. Symbolizers defined in
* rules will extend this default style.
* options - {Object} An optional object with properties to set on the
* style.
*
* Valid options:
* rules - {Array(<OpenLayers.Rule>)} List of rules to be added to the
* style.
*
* Return:
* {<OpenLayers.Style>}
*/
initialize: function(style, options) {
OpenLayers.Util.extend(this, options);
this.rules = [];
if(options && options.rules) {
this.addRules(options.rules);
}
// use the default style from OpenLayers.Feature.Vector if no style
// was given in the constructor
this.setDefaultStyle(style ||
OpenLayers.Feature.Vector.style["default"]);
},
/**
* APIMethod: destroy
* nullify references to prevent circular references and memory leaks
*/
destroy: function() {
for (var i=0, len=this.rules.length; i<len; i++) {
this.rules[i].destroy();
this.rules[i] = null;
}
this.rules = null;
this.defaultStyle = null;
},
/**
* Method: createSymbolizer
* creates a style by applying all feature-dependent rules to the base
* style.
*
* Parameters:
* feature - {<OpenLayers.Feature>} feature to evaluate rules for
*
* Returns:
* {Object} symbolizer hash
*/
createSymbolizer: function(feature) {
var style = this.defaultsPerSymbolizer ? {} : this.createLiterals(
OpenLayers.Util.extend({}, this.defaultStyle), feature);
var rules = this.rules;
var rule, context;
var elseRules = [];
var appliedRules = false;
for(var i=0, len=rules.length; i<len; i++) {
rule = rules[i];
// does the rule apply?
var applies = rule.evaluate(feature);
if(applies) {
if(rule instanceof OpenLayers.Rule && rule.elseFilter) {
elseRules.push(rule);
} else {
appliedRules = true;
this.applySymbolizer(rule, style, feature);
}
}
}
// if no other rules apply, apply the rules with else filters
if(appliedRules == false && elseRules.length > 0) {
appliedRules = true;
for(var i=0, len=elseRules.length; i<len; i++) {
this.applySymbolizer(elseRules[i], style, feature);
}
}
// don't display if there were rules but none applied
if(rules.length > 0 && appliedRules == false) {
style.display = "none";
}
return style;
},
/**
* Method: applySymbolizer
*
* Parameters:
* rule - {OpenLayers.Rule}
* style - {Object}
* feature - {<OpenLayer.Feature.Vector>}
*
* Returns:
* {Object} A style with new symbolizer applied.
*/
applySymbolizer: function(rule, style, feature) {
var symbolizerPrefix = feature.geometry ?
this.getSymbolizerPrefix(feature.geometry) :
OpenLayers.Style.SYMBOLIZER_PREFIXES[0];
var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;
if(this.defaultsPerSymbolizer === true) {
var defaults = this.defaultStyle;
OpenLayers.Util.applyDefaults(symbolizer, {
pointRadius: defaults.pointRadius
});
if(symbolizer.stroke === true || symbolizer.graphic === true) {
OpenLayers.Util.applyDefaults(symbolizer, {
strokeWidth: defaults.strokeWidth,
strokeColor: defaults.strokeColor,
strokeOpacity: defaults.strokeOpacity,
strokeDashstyle: defaults.strokeDashstyle,
strokeLinecap: defaults.strokeLinecap
});
}
if(symbolizer.fill === true || symbolizer.graphic === true) {
OpenLayers.Util.applyDefaults(symbolizer, {
fillColor: defaults.fillColor,
fillOpacity: defaults.fillOpacity
});
}
if(symbolizer.graphic === true) {
OpenLayers.Util.applyDefaults(symbolizer, {
pointRadius: this.defaultStyle.pointRadius,
externalGraphic: this.defaultStyle.externalGraphic,
graphicName: this.defaultStyle.graphicName,
graphicOpacity: this.defaultStyle.graphicOpacity,
graphicWidth: this.defaultStyle.graphicWidth,
graphicHeight: this.defaultStyle.graphicHeight,
graphicXOffset: this.defaultStyle.graphicXOffset,
graphicYOffset: this.defaultStyle.graphicYOffset
});
}
}
// merge the style with the current style
return this.createLiterals(
OpenLayers.Util.extend(style, symbolizer), feature);
},
/**
* Method: createLiterals
* creates literals for all style properties that have an entry in
* <this.propertyStyles>.
*
* Parameters:
* style - {Object} style to create literals for. Will be modified
* inline.
* feature - {Object}
*
* Returns:
* {Object} the modified style
*/
createLiterals: function(style, feature) {
var context = this.context || feature.attributes || feature.data;
for (var i in this.propertyStyles) {
style[i] = OpenLayers.Style.createLiteral(style[i], context, feature);
}
return style;
},
/**
* Method: findPropertyStyles
* Looks into all rules for this style and the defaultStyle to collect
* all the style hash property names containing ${...} strings that have
* to be replaced using the createLiteral method before returning them.
*
* Returns:
* {Object} hash of property names that need createLiteral parsing. The
* name of the property is the key, and the value is true;
*/
findPropertyStyles: function() {
var propertyStyles = {};
// check the default style
var style = this.defaultStyle;
this.addPropertyStyles(propertyStyles, style);
// walk through all rules to check for properties in their symbolizer
var rules = this.rules;
var symbolizer, value;
for (var i=0, len=rules.length; i<len; i++) {
symbolizer = rules[i].symbolizer;
for (var key in symbolizer) {
value = symbolizer[key];
if (typeof value == "object") {
// symbolizer key is "Point", "Line" or "Polygon"
this.addPropertyStyles(propertyStyles, value);
} else {
// symbolizer is a hash of style properties
this.addPropertyStyles(propertyStyles, symbolizer);
break;
}
}
}
return propertyStyles;
},
/**
* Method: addPropertyStyles
*
* Parameters:
* propertyStyles - {Object} hash to add new property styles to. Will be
* modified inline
* symbolizer - {Object} search this symbolizer for property styles
*
* Returns:
* {Object} propertyStyles hash
*/
addPropertyStyles: function(propertyStyles, symbolizer) {
var property;
for (var key in symbolizer) {
property = symbolizer[key];
if (typeof property == "string" &&
property.match(/\$\{\w+\}/)) {
propertyStyles[key] = true;
}
}
return propertyStyles;
},
/**
* APIMethod: addRules
* Adds rules to this style.
*
* Parameters:
* rules - {Array(<OpenLayers.Rule>)}
*/
addRules: function(rules) {
this.rules = this.rules.concat(rules);
this.propertyStyles = this.findPropertyStyles();
},
/**
* APIMethod: setDefaultStyle
* Sets the default style for this style object.
*
* Parameters:
* style - {Object} Hash of style properties
*/
setDefaultStyle: function(style) {
this.defaultStyle = style;
this.propertyStyles = this.findPropertyStyles();
},
/**
* Method: getSymbolizerPrefix
* Returns the correct symbolizer prefix according to the
* geometry type of the passed geometry
*
* Parameters:
* geometry {<OpenLayers.Geometry>}
*
* Returns:
* {String} key of the according symbolizer
*/
getSymbolizerPrefix: function(geometry) {
var prefixes = OpenLayers.Style.SYMBOLIZER_PREFIXES;
for (var i=0, len=prefixes.length; i<len; i++) {
if (geometry.CLASS_NAME.indexOf(prefixes[i]) != -1) {
return prefixes[i];
}
}
},
CLASS_NAME: "OpenLayers.Style"
});
/**
* Function: createLiteral
* converts a style value holding a combination of PropertyName and Literal
* into a Literal, taking the property values from the passed features.
*
* Parameters:
* value - {String} value to parse. If this string contains a construct like
* "foo ${bar}", then "foo " will be taken as literal, and "${bar}"
* will be replaced by the value of the "bar" attribute of the passed
* feature.
* context - {Object} context to take attribute values from
* feature - {OpenLayers.Feature.Vector} The feature that will be passed
* to <OpenLayers.String.format> for evaluating functions in the context.
*
* Returns:
* {String} the parsed value. In the example of the value parameter above, the
* result would be "foo valueOfBar", assuming that the passed feature has an
* attribute named "bar" with the value "valueOfBar".
*/
OpenLayers.Style.createLiteral = function(value, context, feature) {
if (typeof value == "string" && value.indexOf("${") != -1) {
value = OpenLayers.String.format(value, context, [feature]);
value = (isNaN(value) || !value) ? value : parseFloat(value);
}
return value;
};
/**
* Constant: OpenLayers.Style.SYMBOLIZER_PREFIXES
* {Array} prefixes of the sld symbolizers. These are the
* same as the main geometry types
*/
OpenLayers.Style.SYMBOLIZER_PREFIXES = ['Point', 'Line', 'Polygon', 'Text'];

View File

@ -0,0 +1,159 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Style.js
* @requires OpenLayers/Feature/Vector.js
*/
/**
* Class: OpenLayers.StyleMap
*/
OpenLayers.StyleMap = OpenLayers.Class({
/**
* Property: styles
* Hash of {<OpenLayers.Style>}, keyed by names of well known
* rendering intents (e.g. "default", "temporary", "select", "delete").
*/
styles: null,
/**
* Property: extendDefault
* {Boolean} if true, every render intent will extend the symbolizers
* specified for the "default" intent at rendering time. Otherwise, every
* rendering intent will be treated as a completely independent style.
*/
extendDefault: true,
/**
* Constructor: OpenLayers.StyleMap
*
* Parameters:
* style - {Object} Optional. Either a style hash, or a style object, or
* a hash of style objects (style hashes) keyed by rendering
* intent. If just one style hash or style object is passed,
* this will be used for all known render intents (default,
* select, temporary)
* options - {Object} optional hash of additional options for this
* instance
*/
initialize: function (style, options) {
this.styles = {
"default": new OpenLayers.Style(
OpenLayers.Feature.Vector.style["default"]),
"select": new OpenLayers.Style(
OpenLayers.Feature.Vector.style["select"]),
"temporary": new OpenLayers.Style(
OpenLayers.Feature.Vector.style["temporary"]),
"delete": new OpenLayers.Style(
OpenLayers.Feature.Vector.style["delete"])
};
// take whatever the user passed as style parameter and convert it
// into parts of stylemap.
if(style instanceof OpenLayers.Style) {
// user passed a style object
this.styles["default"] = style;
this.styles["select"] = style;
this.styles["temporary"] = style;
this.styles["delete"] = style;
} else if(typeof style == "object") {
for(var key in style) {
if(style[key] instanceof OpenLayers.Style) {
// user passed a hash of style objects
this.styles[key] = style[key];
} else if(typeof style[key] == "object") {
// user passsed a hash of style hashes
this.styles[key] = new OpenLayers.Style(style[key]);
} else {
// user passed a style hash (i.e. symbolizer)
this.styles["default"] = new OpenLayers.Style(style);
this.styles["select"] = new OpenLayers.Style(style);
this.styles["temporary"] = new OpenLayers.Style(style);
this.styles["delete"] = new OpenLayers.Style(style);
break;
}
}
}
OpenLayers.Util.extend(this, options);
},
/**
* Method: destroy
*/
destroy: function() {
for(var key in this.styles) {
this.styles[key].destroy();
}
this.styles = null;
},
/**
* Method: createSymbolizer
* Creates the symbolizer for a feature for a render intent.
*
* Parameters:
* feature - {<OpenLayers.Feature>} The feature to evaluate the rules
* of the intended style against.
* intent - {String} The intent determines the symbolizer that will be
* used to draw the feature. Well known intents are "default"
* (for just drawing the features), "select" (for selected
* features) and "temporary" (for drawing features).
*
* Returns:
* {Object} symbolizer hash
*/
createSymbolizer: function(feature, intent) {
if(!feature) {
feature = new OpenLayers.Feature.Vector();
}
if(!this.styles[intent]) {
intent = "default";
}
feature.renderIntent = intent;
var defaultSymbolizer = {};
if(this.extendDefault && intent != "default") {
defaultSymbolizer = this.styles["default"].createSymbolizer(feature);
}
return OpenLayers.Util.extend(defaultSymbolizer,
this.styles[intent].createSymbolizer(feature));
},
/**
* Method: addUniqueValueRules
* Convenience method to create comparison rules for unique values of a
* property. The rules will be added to the style object for a specified
* rendering intent. This method is a shortcut for creating something like
* the "unique value legends" familiar from well known desktop GIS systems
*
* Parameters:
* renderIntent - {String} rendering intent to add the rules to
* property - {String} values of feature attributes to create the
* rules for
* symbolizers - {Object} Hash of symbolizers, keyed by the desired
* property values
* context - {Object} An optional object with properties that
* symbolizers' property values should be evaluated
* against. If no context is specified, feature.attributes
* will be used
*/
addUniqueValueRules: function(renderIntent, property, symbolizers, context) {
var rules = [];
for (var value in symbolizers) {
rules.push(new OpenLayers.Rule({
symbolizer: symbolizers[value],
context: context,
filter: new OpenLayers.Filter.Comparison({
type: OpenLayers.Filter.Comparison.EQUAL_TO,
property: property,
value: value
})
}));
}
this.styles[renderIntent].addRules(rules);
},
CLASS_NAME: "OpenLayers.StyleMap"
});

View File

@ -0,0 +1,280 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/*
* @requires OpenLayers/Util.js
* @requires OpenLayers/Console.js
*/
/*
* Class: OpenLayers.Tile
* This is a class designed to designate a single tile, however
* it is explicitly designed to do relatively little. Tiles store
* information about themselves -- such as the URL that they are related
* to, and their size - but do not add themselves to the layer div
* automatically, for example. Create a new tile with the
* <OpenLayers.Tile> constructor, or a subclass.
*
* TBD 3.0 - remove reference to url in above paragraph
*
*/
OpenLayers.Tile = OpenLayers.Class({
/**
* Constant: EVENT_TYPES
* {Array(String)} Supported application event types
*/
EVENT_TYPES: [ "loadstart", "loadend", "reload", "unload"],
/**
* APIProperty: events
* {<OpenLayers.Events>} An events object that handles all
* events on the tile.
*/
events: null,
/**
* Property: id
* {String} null
*/
id: null,
/**
* Property: layer
* {<OpenLayers.Layer>} layer the tile is attached to
*/
layer: null,
/**
* Property: url
* {String} url of the request.
*
* TBD 3.0
* Deprecated. The base tile class does not need an url. This should be
* handled in subclasses. Does not belong here.
*/
url: null,
/**
* APIProperty: bounds
* {<OpenLayers.Bounds>} null
*/
bounds: null,
/**
* Property: size
* {<OpenLayers.Size>} null
*/
size: null,
/**
* Property: position
* {<OpenLayers.Pixel>} Top Left pixel of the tile
*/
position: null,
/**
* Property: isLoading
* {Boolean} Is the tile loading?
*/
isLoading: false,
/** TBD 3.0 -- remove 'url' from the list of parameters to the constructor.
* there is no need for the base tile class to have a url.
*
* Constructor: OpenLayers.Tile
* Constructor for a new <OpenLayers.Tile> instance.
*
* Parameters:
* layer - {<OpenLayers.Layer>} layer that the tile will go in.
* position - {<OpenLayers.Pixel>}
* bounds - {<OpenLayers.Bounds>}
* url - {<String>}
* size - {<OpenLayers.Size>}
*/
initialize: function(layer, position, bounds, url, size) {
this.layer = layer;
this.position = position.clone();
this.bounds = bounds.clone();
this.url = url;
this.size = size.clone();
//give the tile a unique id based on its BBOX.
this.id = OpenLayers.Util.createUniqueID("Tile_");
this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
},
/**
* Method: unload
* Call immediately before destroying if you are listening to tile
* events, so that counters are properly handled if tile is still
* loading at destroy-time. Will only fire an event if the tile is
* still loading.
*/
unload: function() {
if (this.isLoading) {
this.isLoading = false;
this.events.triggerEvent("unload");
}
},
/**
* APIMethod: destroy
* Nullify references to prevent circular references and memory leaks.
*/
destroy:function() {
this.layer = null;
this.bounds = null;
this.size = null;
this.position = null;
this.events.destroy();
this.events = null;
},
/**
* Method: clone
*
* Parameters:
* obj - {<OpenLayers.Tile>} The tile to be cloned
*
* Returns:
* {<OpenLayers.Tile>} An exact clone of this <OpenLayers.Tile>
*/
clone: function (obj) {
if (obj == null) {
obj = new OpenLayers.Tile(this.layer,
this.position,
this.bounds,
this.url,
this.size);
}
// catch any randomly tagged-on properties
OpenLayers.Util.applyDefaults(obj, this);
return obj;
},
/**
* Method: draw
* Clear whatever is currently in the tile, then return whether or not
* it should actually be re-drawn.
*
* Returns:
* {Boolean} Whether or not the tile should actually be drawn. Note that
* this is not really the best way of doing things, but such is
* the way the code has been developed. Subclasses call this and
* depend on the return to know if they should draw or not.
*/
draw: function() {
var maxExtent = this.layer.maxExtent;
var withinMaxExtent = (maxExtent &&
this.bounds.intersectsBounds(maxExtent, false));
// The only case where we *wouldn't* want to draw the tile is if the
// tile is outside its layer's maxExtent.
this.shouldDraw = (withinMaxExtent || this.layer.displayOutsideMaxExtent);
//clear tile's contents and mark as not drawn
this.clear();
return this.shouldDraw;
},
/**
* Method: moveTo
* Reposition the tile.
*
* Parameters:
* bounds - {<OpenLayers.Bounds>}
* position - {<OpenLayers.Pixel>}
* redraw - {Boolean} Call draw method on tile after moving.
* Default is true
*/
moveTo: function (bounds, position, redraw) {
if (redraw == null) {
redraw = true;
}
this.bounds = bounds.clone();
this.position = position.clone();
if (redraw) {
this.draw();
}
},
/**
* Method: clear
* Clear the tile of any bounds/position-related data so that it can
* be reused in a new location. To be implemented by subclasses.
*/
clear: function() {
// to be implemented by subclasses
},
/**
* Method: getBoundsFromBaseLayer
* Take the pixel locations of the corner of the tile, and pass them to
* the base layer and ask for the location of those pixels, so that
* displaying tiles over Google works fine.
*
* Parameters:
* position - {<OpenLayers.Pixel>}
*
* Returns:
* bounds - {<OpenLayers.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;
},
/**
* Method: showTile
* Show the tile only if it should be drawn.
*/
showTile: function() {
if (this.shouldDraw) {
this.show();
}
},
/**
* Method: show
* Show the tile. To be implemented by subclasses.
*/
show: function() { },
/**
* Method: hide
* Hide the tile. To be implemented by subclasses.
*/
hide: function() { },
CLASS_NAME: "OpenLayers.Tile"
});

View File

@ -0,0 +1,322 @@
/* Copyright (c) 2006-2008 MetaCarta, Inc., published under the Clear BSD
* license. See http://svn.openlayers.org/trunk/openlayers/license.txt for the
* full text of the license. */
/**
* @requires OpenLayers/Console.js
*/
/**
* Namespace: OpenLayers.Tween
*/
OpenLayers.Tween = OpenLayers.Class({
/**
* Constant: INTERVAL
* {int} Interval in milliseconds between 2 steps
*/
INTERVAL: 10,
/**
* APIProperty: easing
* {<OpenLayers.Easing>(Function)} Easing equation used for the animation
* Defaultly set to OpenLayers.Easing.Expo.easeOut
*/
easing: null,
/**
* APIProperty: begin
* {Object} Values to start the animation with
*/
begin: null,
/**
* APIProperty: finish
* {Object} Values to finish the animation with
*/
finish: null,
/**
* APIProperty: duration
* {int} duration of the tween (number of steps)
*/
duration: null,
/**
* APIProperty: callbacks
* {Object} An object with start, eachStep and done properties whose values
* are functions to be call during the animation. They are passed the
* current computed value as argument.
*/
callbacks: null,
/**
* Property: time
* {int} Step counter
*/
time: null,
/**
* Property: interval
* {int} Interval id returned by window.setInterval
*/
interval: null,
/**
* Property: playing
* {Boolean} Tells if the easing is currently playing
*/
playing: false,
/**
* Constructor: OpenLayers.Tween
* Creates a Tween.
*
* Parameters:
* easing - {<OpenLayers.Easing>(Function)} easing function method to use
*/
initialize: function(easing) {
this.easing = (easing) ? easing : OpenLayers.Easing.Expo.easeOut;
},
/**
* APIMethod: start
* Plays the Tween, and calls the callback method on each step
*
* Parameters:
* begin - {Object} values to start the animation with
* finish - {Object} values to finish the animation with
* duration - {int} duration of the tween (number of steps)
* options - {Object} hash of options (for example callbacks (start, eachStep, done))
*/
start: function(begin, finish, duration, options) {
this.playing = true;
this.begin = begin;
this.finish = finish;
this.duration = duration;
this.callbacks = options.callbacks;
this.time = 0;
if (this.interval) {
window.clearInterval(this.interval);
this.interval = null;
}
if (this.callbacks && this.callbacks.start) {
this.callbacks.start.call(this, this.begin);
}
this.interval = window.setInterval(
OpenLayers.Function.bind(this.play, this), this.INTERVAL);
},
/**
* APIMethod: stop
* Stops the Tween, and calls the done callback
* Doesn't do anything if animation is already finished
*/
stop: function() {
if (!this.playing) {
return;
}
if (this.callbacks && this.callbacks.done) {
this.callbacks.done.call(this, this.finish);
}
window.clearInterval(this.interval);
this.interval = null;
this.playing = false;
},
/**
* Method: play
* Calls the appropriate easing method
*/
play: function() {
var value = {};
for (var i in this.begin) {
var b = this.begin[i];
var f = this.finish[i];
if (b == null || f == null || isNaN(b) || isNaN(f)) {
OpenLayers.Console.error('invalid value for Tween');
}
var c = f - b;
value[i] = this.easing.apply(this, [this.time, b, c, this.duration]);
}
this.time++;
if (this.callbacks && this.callbacks.eachStep) {
this.callbacks.eachStep.call(this, value);
}
if (this.time > this.duration) {
if (this.callbacks && this.callbacks.done) {
this.callbacks.done.call(this, this.finish);
this.playing = false;
}
window.clearInterval(this.interval);
this.interval = null;
}
},
/**
* Create empty functions for all easing methods.
*/
CLASS_NAME: "OpenLayers.Tween"
});
/**
* Namespace: OpenLayers.Easing
*
* Credits:
* Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>
*/
OpenLayers.Easing = {
/**
* Create empty functions for all easing methods.
*/
CLASS_NAME: "OpenLayers.Easing"
};
/**
* Namespace: OpenLayers.Easing.Linear
*/
OpenLayers.Easing.Linear = {
/**
* Function: easeIn
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeIn: function(t, b, c, d) {
return c*t/d + b;
},
/**
* Function: easeOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeOut: function(t, b, c, d) {
return c*t/d + b;
},
/**
* Function: easeInOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeInOut: function(t, b, c, d) {
return c*t/d + b;
},
CLASS_NAME: "OpenLayers.Easing.Linear"
};
/**
* Namespace: OpenLayers.Easing.Expo
*/
OpenLayers.Easing.Expo = {
/**
* Function: easeIn
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeIn: function(t, b, c, d) {
return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
},
/**
* Function: easeOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeOut: function(t, b, c, d) {
return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
},
/**
* Function: easeInOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeInOut: function(t, b, c, d) {
if (t==0) return b;
if (t==d) return b+c;
if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
},
CLASS_NAME: "OpenLayers.Easing.Expo"
};
/**
* Namespace: OpenLayers.Easing.Quad
*/
OpenLayers.Easing.Quad = {
/**
* Function: easeIn
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeIn: function(t, b, c, d) {
return c*(t/=d)*t + b;
},
/**
* Function: easeOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeOut: function(t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
},
/**
* Function: easeInOut
*
* Parameters:
* t - {Float} time
* b - {Float} beginning position
* c - {Float} total change
* d - {Float} duration of the transition
*/
easeInOut: function(t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
},
CLASS_NAME: "OpenLayers.Easing.Quad"
};

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,244 @@
/*
* This file has been edited substantially from the Rico-released version by
* the OpenLayers development team.
*
* This file is licensed under the Apache License, Version 2.0.
*/
OpenLayers.Rico.Color = OpenLayers.Class({
initialize: function(red, green, blue) {
this.rgb = { r: red, g : green, b : blue };
},
setRed: function(r) {
this.rgb.r = r;
},
setGreen: function(g) {
this.rgb.g = g;
},
setBlue: function(b) {
this.rgb.b = b;
},
setHue: function(h) {
// get an HSB model, and set the new hue...
var hsb = this.asHSB();
hsb.h = h;
// convert back to RGB...
this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
},
setSaturation: function(s) {
// get an HSB model, and set the new hue...
var hsb = this.asHSB();
hsb.s = s;
// convert back to RGB and set values...
this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
},
setBrightness: function(b) {
// get an HSB model, and set the new hue...
var hsb = this.asHSB();
hsb.b = b;
// convert back to RGB and set values...
this.rgb = OpenLayers.Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
},
darken: function(percent) {
var hsb = this.asHSB();
this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
},
brighten: function(percent) {
var hsb = this.asHSB();
this.rgb = OpenLayers.Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
},
blend: function(other) {
this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
},
isBright: function() {
var hsb = this.asHSB();
return this.asHSB().b > 0.5;
},
isDark: function() {
return ! this.isBright();
},
asRGB: function() {
return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
},
asHex: function() {
return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
},
asHSB: function() {
return OpenLayers.Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
},
toString: function() {
return this.asHex();
}
});
OpenLayers.Rico.Color.createFromHex = function(hexCode) {
if(hexCode.length==4) {
var shortHexCode = hexCode;
var hexCode = '#';
for(var i=1;i<4;i++) {
hexCode += (shortHexCode.charAt(i) +
shortHexCode.charAt(i));
}
}
if ( hexCode.indexOf('#') == 0 ) {
hexCode = hexCode.substring(1);
}
var red = hexCode.substring(0,2);
var green = hexCode.substring(2,4);
var blue = hexCode.substring(4,6);
return new OpenLayers.Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
};
/**
* Factory method for creating a color from the background of
* an HTML element.
*/
OpenLayers.Rico.Color.createColorFromBackground = function(elem) {
var actualColor =
RicoUtil.getElementsComputedStyle(OpenLayers.Util.getElement(elem),
"backgroundColor",
"background-color");
if ( actualColor == "transparent" && elem.parentNode ) {
return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);
}
if ( actualColor == null ) {
return new OpenLayers.Rico.Color(255,255,255);
}
if ( actualColor.indexOf("rgb(") == 0 ) {
var colors = actualColor.substring(4, actualColor.length - 1 );
var colorArray = colors.split(",");
return new OpenLayers.Rico.Color( parseInt( colorArray[0] ),
parseInt( colorArray[1] ),
parseInt( colorArray[2] ) );
}
else if ( actualColor.indexOf("#") == 0 ) {
return OpenLayers.Rico.Color.createFromHex(actualColor);
}
else {
return new OpenLayers.Rico.Color(255,255,255);
}
};
OpenLayers.Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
var red = 0;
var green = 0;
var blue = 0;
if (saturation == 0) {
red = parseInt(brightness * 255.0 + 0.5);
green = red;
blue = red;
}
else {
var h = (hue - Math.floor(hue)) * 6.0;
var f = h - Math.floor(h);
var p = brightness * (1.0 - saturation);
var q = brightness * (1.0 - saturation * f);
var t = brightness * (1.0 - (saturation * (1.0 - f)));
switch (parseInt(h)) {
case 0:
red = (brightness * 255.0 + 0.5);
green = (t * 255.0 + 0.5);
blue = (p * 255.0 + 0.5);
break;
case 1:
red = (q * 255.0 + 0.5);
green = (brightness * 255.0 + 0.5);
blue = (p * 255.0 + 0.5);
break;
case 2:
red = (p * 255.0 + 0.5);
green = (brightness * 255.0 + 0.5);
blue = (t * 255.0 + 0.5);
break;
case 3:
red = (p * 255.0 + 0.5);
green = (q * 255.0 + 0.5);
blue = (brightness * 255.0 + 0.5);
break;
case 4:
red = (t * 255.0 + 0.5);
green = (p * 255.0 + 0.5);
blue = (brightness * 255.0 + 0.5);
break;
case 5:
red = (brightness * 255.0 + 0.5);
green = (p * 255.0 + 0.5);
blue = (q * 255.0 + 0.5);
break;
}
}
return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
};
OpenLayers.Rico.Color.RGBtoHSB = function(r, g, b) {
var hue;
var saturation;
var brightness;
var cmax = (r > g) ? r : g;
if (b > cmax) {
cmax = b;
}
var cmin = (r < g) ? r : g;
if (b < cmin) {
cmin = b;
}
brightness = cmax / 255.0;
if (cmax != 0) {
saturation = (cmax - cmin)/cmax;
} else {
saturation = 0;
}
if (saturation == 0) {
hue = 0;
} else {
var redc = (cmax - r)/(cmax - cmin);
var greenc = (cmax - g)/(cmax - cmin);
var bluec = (cmax - b)/(cmax - cmin);
if (r == cmax) {
hue = bluec - greenc;
} else if (g == cmax) {
hue = 2.0 + redc - bluec;
} else {
hue = 4.0 + greenc - redc;
}
hue = hue / 6.0;
if (hue < 0) {
hue = hue + 1.0;
}
}
return { h : hue, s : saturation, b : brightness };
};

View File

@ -0,0 +1,330 @@
/*
* This file has been edited substantially from the Rico-released
* version by the OpenLayers development team.
*
* Copyright 2005 Sabre Airline Solutions
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the * License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or
* implied. See the License for the specific language governing
* permissions * and limitations under the License.
*
*/
OpenLayers.Rico = new Object();
OpenLayers.Rico.Corner = {
round: function(e, options) {
e = OpenLayers.Util.getElement(e);
this._setOptions(options);
var color = this.options.color;
if ( this.options.color == "fromElement" ) {
color = this._background(e);
}
var bgColor = this.options.bgColor;
if ( this.options.bgColor == "fromParent" ) {
bgColor = this._background(e.offsetParent);
}
this._roundCornersImpl(e, color, bgColor);
},
/** This is a helper function to change the background
* color of <div> that has had Rico rounded corners added.
*
* It seems we cannot just set the background color for the
* outer <div> so each <span> element used to create the
* corners must have its background color set individually.
*
* @param {DOM} theDiv - A child of the outer <div> that was
* supplied to the `round` method.
*
* @param {String} newColor - The new background color to use.
*/
changeColor: function(theDiv, newColor) {
theDiv.style.backgroundColor = newColor;
var spanElements = theDiv.parentNode.getElementsByTagName("span");
for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
spanElements[currIdx].style.backgroundColor = newColor;
}
},
/** This is a helper function to change the background
* opacity of <div> that has had Rico rounded corners added.
*
* See changeColor (above) for algorithm explanation
*
* @param {DOM} theDiv A child of the outer <div> that was
* supplied to the `round` method.
*
* @param {int} newOpacity The new opacity to use (0-1).
*/
changeOpacity: function(theDiv, newOpacity) {
var mozillaOpacity = newOpacity;
var ieOpacity = 'alpha(opacity=' + newOpacity * 100 + ')';
theDiv.style.opacity = mozillaOpacity;
theDiv.style.filter = ieOpacity;
var spanElements = theDiv.parentNode.getElementsByTagName("span");
for (var currIdx = 0; currIdx < spanElements.length; currIdx++) {
spanElements[currIdx].style.opacity = mozillaOpacity;
spanElements[currIdx].style.filter = ieOpacity;
}
},
/** this function takes care of redoing the rico cornering
*
* you can't just call updateRicoCorners() again and pass it a
* new options string. you have to first remove the divs that
* rico puts on top and below the content div.
*
* @param {DOM} theDiv - A child of the outer <div> that was
* supplied to the `round` method.
*
* @param {Object} options - list of options
*/
reRound: function(theDiv, options) {
var topRico = theDiv.parentNode.childNodes[0];
//theDiv would be theDiv.parentNode.childNodes[1]
var bottomRico = theDiv.parentNode.childNodes[2];
theDiv.parentNode.removeChild(topRico);
theDiv.parentNode.removeChild(bottomRico);
this.round(theDiv.parentNode, options);
},
_roundCornersImpl: function(e, color, bgColor) {
if(this.options.border) {
this._renderBorder(e,bgColor);
}
if(this._isTopRounded()) {
this._roundTopCorners(e,color,bgColor);
}
if(this._isBottomRounded()) {
this._roundBottomCorners(e,color,bgColor);
}
},
_renderBorder: function(el,bgColor) {
var borderValue = "1px solid " + this._borderColor(bgColor);
var borderL = "border-left: " + borderValue;
var borderR = "border-right: " + borderValue;
var style = "style='" + borderL + ";" + borderR + "'";
el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
},
_roundTopCorners: function(el, color, bgColor) {
var corner = this._createCorner(bgColor);
for(var i=0 ; i < this.options.numSlices ; i++ ) {
corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));
}
el.style.paddingTop = 0;
el.insertBefore(corner,el.firstChild);
},
_roundBottomCorners: function(el, color, bgColor) {
var corner = this._createCorner(bgColor);
for(var i=(this.options.numSlices-1) ; i >= 0 ; i-- ) {
corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));
}
el.style.paddingBottom = 0;
el.appendChild(corner);
},
_createCorner: function(bgColor) {
var corner = document.createElement("div");
corner.style.backgroundColor = (this._isTransparent() ? "transparent" : bgColor);
return corner;
},
_createCornerSlice: function(color,bgColor, n, position) {
var slice = document.createElement("span");
var inStyle = slice.style;
inStyle.backgroundColor = color;
inStyle.display = "block";
inStyle.height = "1px";
inStyle.overflow = "hidden";
inStyle.fontSize = "1px";
var borderColor = this._borderColor(color,bgColor);
if ( this.options.border && n == 0 ) {
inStyle.borderTopStyle = "solid";
inStyle.borderTopWidth = "1px";
inStyle.borderLeftWidth = "0px";
inStyle.borderRightWidth = "0px";
inStyle.borderBottomWidth = "0px";
inStyle.height = "0px"; // assumes css compliant box model
inStyle.borderColor = borderColor;
}
else if(borderColor) {
inStyle.borderColor = borderColor;
inStyle.borderStyle = "solid";
inStyle.borderWidth = "0px 1px";
}
if ( !this.options.compact && (n == (this.options.numSlices-1)) ) {
inStyle.height = "2px";
}
this._setMargin(slice, n, position);
this._setBorder(slice, n, position);
return slice;
},
_setOptions: function(options) {
this.options = {
corners : "all",
color : "fromElement",
bgColor : "fromParent",
blend : true,
border : false,
compact : false
};
OpenLayers.Util.extend(this.options, options || {});
this.options.numSlices = this.options.compact ? 2 : 4;
if ( this._isTransparent() ) {
this.options.blend = false;
}
},
_whichSideTop: function() {
if ( this._hasString(this.options.corners, "all", "top") ) {
return "";
}
if ( this.options.corners.indexOf("tl") >= 0 && this.options.corners.indexOf("tr") >= 0 ) {
return "";
}
if (this.options.corners.indexOf("tl") >= 0) {
return "left";
} else if (this.options.corners.indexOf("tr") >= 0) {
return "right";
}
return "";
},
_whichSideBottom: function() {
if ( this._hasString(this.options.corners, "all", "bottom") ) {
return "";
}
if ( this.options.corners.indexOf("bl")>=0 && this.options.corners.indexOf("br")>=0 ) {
return "";
}
if(this.options.corners.indexOf("bl") >=0) {
return "left";
} else if(this.options.corners.indexOf("br")>=0) {
return "right";
}
return "";
},
_borderColor : function(color,bgColor) {
if ( color == "transparent" ) {
return bgColor;
} else if ( this.options.border ) {
return this.options.border;
} else if ( this.options.blend ) {
return this._blend( bgColor, color );
} else {
return "";
}
},
_setMargin: function(el, n, corners) {
var marginSize = this._marginSize(n);
var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
if ( whichSide == "left" ) {
el.style.marginLeft = marginSize + "px"; el.style.marginRight = "0px";
}
else if ( whichSide == "right" ) {
el.style.marginRight = marginSize + "px"; el.style.marginLeft = "0px";
}
else {
el.style.marginLeft = marginSize + "px"; el.style.marginRight = marginSize + "px";
}
},
_setBorder: function(el,n,corners) {
var borderSize = this._borderSize(n);
var whichSide = corners == "top" ? this._whichSideTop() : this._whichSideBottom();
if ( whichSide == "left" ) {
el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = "0px";
}
else if ( whichSide == "right" ) {
el.style.borderRightWidth = borderSize + "px"; el.style.borderLeftWidth = "0px";
}
else {
el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
}
if (this.options.border != false) {
el.style.borderLeftWidth = borderSize + "px"; el.style.borderRightWidth = borderSize + "px";
}
},
_marginSize: function(n) {
if ( this._isTransparent() ) {
return 0;
}
var marginSizes = [ 5, 3, 2, 1 ];
var blendedMarginSizes = [ 3, 2, 1, 0 ];
var compactMarginSizes = [ 2, 1 ];
var smBlendedMarginSizes = [ 1, 0 ];
if ( this.options.compact && this.options.blend ) {
return smBlendedMarginSizes[n];
} else if ( this.options.compact ) {
return compactMarginSizes[n];
} else if ( this.options.blend ) {
return blendedMarginSizes[n];
} else {
return marginSizes[n];
}
},
_borderSize: function(n) {
var transparentBorderSizes = [ 5, 3, 2, 1 ];
var blendedBorderSizes = [ 2, 1, 1, 1 ];
var compactBorderSizes = [ 1, 0 ];
var actualBorderSizes = [ 0, 2, 0, 0 ];
if ( this.options.compact && (this.options.blend || this._isTransparent()) ) {
return 1;
} else if ( this.options.compact ) {
return compactBorderSizes[n];
} else if ( this.options.blend ) {
return blendedBorderSizes[n];
} else if ( this.options.border ) {
return actualBorderSizes[n];
} else if ( this._isTransparent() ) {
return transparentBorderSizes[n];
}
return 0;
},
_hasString: function(str) { for(var i=1 ; i<arguments.length ; i++) if (str.indexOf(arguments[i]) >= 0) { return true; } return false; },
_blend: function(c1, c2) { var cc1 = OpenLayers.Rico.Color.createFromHex(c1); cc1.blend(OpenLayers.Rico.Color.createFromHex(c2)); return cc1; },
_background: function(el) { try { return OpenLayers.Rico.Color.createColorFromBackground(el).asHex(); } catch(err) { return "#ffffff"; } },
_isTransparent: function() { return this.options.color == "transparent"; },
_isTopRounded: function() { return this._hasString(this.options.corners, "all", "top", "tl", "tr"); },
_isBottomRounded: function() { return this._hasString(this.options.corners, "all", "bottom", "bl", "br"); },
_hasSingleTextChild: function(el) { return el.childNodes.length == 1 && el.childNodes[0].nodeType == 3; }
};