//// /// This blob sucks in all the files in uncompressed form for ease of use /// OpenLayers = new Object(); OpenLayers._scriptName = "lib/OpenLayers.js"; OpenLayers._getScriptLocation = function () { var scriptLocation = ""; var SCRIPT_NAME = OpenLayers._scriptName; var scripts = document.getElementsByTagName('script'); for (var i = 0; i < scripts.length; i++) { var src = scripts[i].getAttribute('src'); if (src) { var index = src.lastIndexOf(SCRIPT_NAME); // is it found, at the end of the URL? if ((index > -1) && (index + SCRIPT_NAME.length == src.length)) { scriptLocation = src.slice(0, -SCRIPT_NAME.length); break; } } } return scriptLocation; } /* Prototype JavaScript framework, version 1.4.0 * (c) 2005 Sam Stephenson * * Prototype is freely distributable under the terms of an MIT-style license. * For details, see the Prototype web site: http://prototype.conio.net/ * /*--------------------------------------------------------------------------*/ var Prototype = { Version: '1.4.0', ScriptFragment: '(?:)((\n|\r|.)*?)(?:<\/script>)', emptyFunction: function() {}, K: function(x) {return x} } var Class = { create: function() { return function() { this.initialize.apply(this, arguments); } } } var Abstract = new Object(); Object.extend = function(destination, source) { for (property in source) { destination[property] = source[property]; } return destination; } Object.inspect = function(object) { try { if (object == undefined) return 'undefined'; if (object == null) return 'null'; return object.inspect ? object.inspect() : object.toString(); } catch (e) { if (e instanceof RangeError) return '...'; throw e; } } Function.prototype.bind = function() { var __method = this, args = $A(arguments), object = args.shift(); return function() { return __method.apply(object, args.concat($A(arguments))); } } Function.prototype.bindAsEventListener = function(object) { var __method = this; return function(event) { return __method.call(object, event || window.event); } } Object.extend(Number.prototype, { toColorPart: function() { var digits = this.toString(16); if (this < 16) return '0' + digits; return digits; }, succ: function() { return this + 1; }, times: function(iterator) { $R(0, this, true).each(iterator); return this; } }); var Try = { these: function() { var returnValue; for (var i = 0; i < arguments.length; i++) { var lambda = arguments[i]; try { returnValue = lambda(); break; } catch (e) {} } return returnValue; } } /*--------------------------------------------------------------------------*/ var PeriodicalExecuter = Class.create(); PeriodicalExecuter.prototype = { initialize: function(callback, frequency) { this.callback = callback; this.frequency = frequency; this.currentlyExecuting = false; this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { if (!this.currentlyExecuting) { try { this.currentlyExecuting = true; this.callback(); } finally { this.currentlyExecuting = false; } } } } /*--------------------------------------------------------------------------*/ function $() { var elements = new Array(); for (var i = 0; i < arguments.length; i++) { var element = arguments[i]; if (typeof element == 'string') element = document.getElementById(element); if (arguments.length == 1) return element; elements.push(element); } return elements; } Object.extend(String.prototype, { stripTags: function() { return this.replace(/<\/?[^>]+>/gi, ''); }, stripScripts: function() { return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), ''); }, extractScripts: function() { var matchAll = new RegExp(Prototype.ScriptFragment, 'img'); var matchOne = new RegExp(Prototype.ScriptFragment, 'im'); return (this.match(matchAll) || []).map(function(scriptTag) { return (scriptTag.match(matchOne) || ['', ''])[1]; }); }, evalScripts: function() { return this.extractScripts().map(eval); }, escapeHTML: function() { var div = document.createElement('div'); var text = document.createTextNode(this); div.appendChild(text); return div.innerHTML; }, unescapeHTML: function() { var div = document.createElement('div'); div.innerHTML = this.stripTags(); return div.childNodes[0] ? div.childNodes[0].nodeValue : ''; }, toQueryParams: function() { var pairs = this.match(/^\??(.*)$/)[1].split('&'); return pairs.inject({}, function(params, pairString) { var pair = pairString.split('='); params[pair[0]] = pair[1]; return params; }); }, toArray: function() { return this.split(''); }, camelize: function() { var oStringList = this.split('-'); if (oStringList.length == 1) return oStringList[0]; var camelizedString = this.indexOf('-') == 0 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : 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; }, inspect: function() { return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'"; } }); String.prototype.parseQuery = String.prototype.toQueryParams; var $break = new Object(); var $continue = new Object(); var Enumerable = { each: function(iterator) { var index = 0; try { this._each(function(value) { try { iterator(value, index++); } catch (e) { if (e != $continue) throw e; } }); } catch (e) { if (e != $break) throw e; } }, all: function(iterator) { var result = true; this.each(function(value, index) { result = result && !!(iterator || Prototype.K)(value, index); if (!result) throw $break; }); return result; }, any: function(iterator) { var result = true; this.each(function(value, index) { if (result = !!(iterator || Prototype.K)(value, index)) throw $break; }); return result; }, collect: function(iterator) { var results = []; this.each(function(value, index) { results.push(iterator(value, index)); }); return results; }, detect: function (iterator) { var result; this.each(function(value, index) { if (iterator(value, index)) { result = value; throw $break; } }); return result; }, findAll: function(iterator) { var results = []; this.each(function(value, index) { if (iterator(value, index)) results.push(value); }); return results; }, grep: function(pattern, iterator) { var results = []; this.each(function(value, index) { var stringValue = value.toString(); if (stringValue.match(pattern)) results.push((iterator || Prototype.K)(value, index)); }) return results; }, include: function(object) { var found = false; this.each(function(value) { if (value == object) { found = true; throw $break; } }); return found; }, inject: function(memo, iterator) { this.each(function(value, index) { memo = iterator(memo, value, index); }); return memo; }, invoke: function(method) { var args = $A(arguments).slice(1); return this.collect(function(value) { return value[method].apply(value, args); }); }, max: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value >= (result || value)) result = value; }); return result; }, min: function(iterator) { var result; this.each(function(value, index) { value = (iterator || Prototype.K)(value, index); if (value <= (result || value)) result = value; }); return result; }, partition: function(iterator) { var trues = [], falses = []; this.each(function(value, index) { ((iterator || Prototype.K)(value, index) ? trues : falses).push(value); }); return [trues, falses]; }, pluck: function(property) { var results = []; this.each(function(value, index) { results.push(value[property]); }); return results; }, reject: function(iterator) { var results = []; this.each(function(value, index) { if (!iterator(value, index)) results.push(value); }); return results; }, sortBy: function(iterator) { return this.collect(function(value, index) { return {value: value, criteria: iterator(value, index)}; }).sort(function(left, right) { var a = left.criteria, b = right.criteria; return a < b ? -1 : a > b ? 1 : 0; }).pluck('value'); }, toArray: function() { return this.collect(Prototype.K); }, zip: function() { var iterator = Prototype.K, args = $A(arguments); if (typeof args.last() == 'function') iterator = args.pop(); var collections = [this].concat(args).map($A); return this.map(function(value, index) { iterator(value = collections.pluck(index)); return value; }); }, inspect: function() { return '#'; } } Object.extend(Enumerable, { map: Enumerable.collect, find: Enumerable.detect, select: Enumerable.findAll, member: Enumerable.include, entries: Enumerable.toArray }); var $A = Array.from = function(iterable) { if (!iterable) return []; if (iterable.toArray) { return iterable.toArray(); } else { var results = []; for (var i = 0; i < iterable.length; i++) results.push(iterable[i]); return results; } } Object.extend(Array.prototype, Enumerable); Array.prototype._reverse = Array.prototype.reverse; Object.extend(Array.prototype, { _each: function(iterator) { for (var i = 0; i < this.length; i++) iterator(this[i]); }, clear: function() { this.length = 0; return this; }, first: function() { return this[0]; }, last: function() { return this[this.length - 1]; }, compact: function() { return this.select(function(value) { return value != undefined || value != null; }); }, flatten: function() { return this.inject([], function(array, value) { return array.concat(value.constructor == Array ? value.flatten() : [value]); }); }, without: function() { var values = $A(arguments); return this.select(function(value) { return !values.include(value); }); }, indexOf: function(object) { for (var i = 0; i < this.length; i++) if (this[i] == object) return i; return -1; }, reverse: function(inline) { return (inline !== false ? this : this.toArray())._reverse(); }, shift: function() { var result = this[0]; for (var i = 0; i < this.length - 1; i++) this[i] = this[i + 1]; this.length--; return result; }, inspect: function() { return '[' + this.map(Object.inspect).join(', ') + ']'; } }); var Hash = { _each: function(iterator) { for (key in this) { var value = this[key]; if (typeof value == 'function') continue; var pair = [key, value]; pair.key = key; pair.value = value; iterator(pair); } }, keys: function() { return this.pluck('key'); }, values: function() { return this.pluck('value'); }, merge: function(hash) { return $H(hash).inject($H(this), function(mergedHash, pair) { mergedHash[pair.key] = pair.value; return mergedHash; }); }, toQueryString: function() { return this.map(function(pair) { return pair.map(encodeURIComponent).join('='); }).join('&'); }, inspect: function() { return '#'; } } function $H(object) { var hash = Object.extend({}, object || {}); Object.extend(hash, Enumerable); Object.extend(hash, Hash); return hash; } ObjectRange = Class.create(); Object.extend(ObjectRange.prototype, Enumerable); Object.extend(ObjectRange.prototype, { initialize: function(start, end, exclusive) { this.start = start; this.end = end; this.exclusive = exclusive; }, _each: function(iterator) { var value = this.start; do { iterator(value); value = value.succ(); } while (this.include(value)); }, include: function(value) { if (value < this.start) return false; if (this.exclusive) return value < this.end; return value <= this.end; } }); var $R = function(start, end, exclusive) { return new ObjectRange(start, end, exclusive); } var Ajax = { getTransport: function() { return Try.these( function() {return new ActiveXObject('Msxml2.XMLHTTP')}, function() {return new ActiveXObject('Microsoft.XMLHTTP')}, function() {return new XMLHttpRequest()} ) || false; }, activeRequestCount: 0 } Ajax.Responders = { responders: [], _each: function(iterator) { this.responders._each(iterator); }, register: function(responderToAdd) { if (!this.include(responderToAdd)) this.responders.push(responderToAdd); }, unregister: function(responderToRemove) { this.responders = this.responders.without(responderToRemove); }, dispatch: function(callback, request, transport, json) { this.each(function(responder) { if (responder[callback] && typeof responder[callback] == 'function') { try { responder[callback].apply(responder, [request, transport, json]); } catch (e) {} } }); } }; Object.extend(Ajax.Responders, Enumerable); Ajax.Responders.register({ onCreate: function() { Ajax.activeRequestCount++; }, onComplete: function() { Ajax.activeRequestCount--; } }); Ajax.Base = function() {}; Ajax.Base.prototype = { setOptions: function(options) { this.options = { method: 'post', asynchronous: true, parameters: '' } Object.extend(this.options, options || {}); }, responseIsSuccess: function() { return this.transport.status == undefined || this.transport.status == 0 || (this.transport.status >= 200 && this.transport.status < 300); }, responseIsFailure: function() { return !this.responseIsSuccess(); } } Ajax.Request = Class.create(); Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete']; Ajax.Request.prototype = Object.extend(new Ajax.Base(), { initialize: function(url, options) { this.transport = Ajax.getTransport(); this.setOptions(options); this.request(url); }, request: function(url) { var parameters = this.options.parameters || ''; if (parameters.length > 0) parameters += '&_='; try { this.url = url; if (this.options.method == 'get' && parameters.length > 0) this.url += (this.url.match(/\?/) ? '&' : '?') + parameters; Ajax.Responders.dispatch('onCreate', this, this.transport); this.transport.open(this.options.method, this.url, this.options.asynchronous); if (this.options.asynchronous) { this.transport.onreadystatechange = this.onStateChange.bind(this); setTimeout((function() {this.respondToReadyState(1)}).bind(this), 10); } this.setRequestHeaders(); var body = this.options.postBody ? this.options.postBody : parameters; this.transport.send(this.options.method == 'post' ? body : null); } catch (e) { this.dispatchException(e); } }, setRequestHeaders: function() { var requestHeaders = ['X-Requested-With', 'XMLHttpRequest', 'X-Prototype-Version', Prototype.Version]; if (this.options.method == 'post') { requestHeaders.push('Content-type', 'application/x-www-form-urlencoded'); /* Force "Connection: close" for Mozilla browsers to work around * a bug where XMLHttpReqeuest sends an incorrect Content-length * header. See Mozilla Bugzilla #246651. */ if (this.transport.overrideMimeType) requestHeaders.push('Connection', 'close'); } if (this.options.requestHeaders) requestHeaders.push.apply(requestHeaders, this.options.requestHeaders); for (var i = 0; i < requestHeaders.length; i += 2) this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]); }, onStateChange: function() { var readyState = this.transport.readyState; if (readyState != 1) this.respondToReadyState(this.transport.readyState); }, header: function(name) { try { return this.transport.getResponseHeader(name); } catch (e) {} }, evalJSON: function() { try { return eval(this.header('X-JSON')); } catch (e) {} }, evalResponse: function() { try { return eval(this.transport.responseText); } catch (e) { this.dispatchException(e); } }, respondToReadyState: function(readyState) { var event = Ajax.Request.Events[readyState]; var transport = this.transport, json = this.evalJSON(); if (event == 'Complete') { try { (this.options['on' + this.transport.status] || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')] || Prototype.emptyFunction)(transport, json); } catch (e) { this.dispatchException(e); } if ((this.header('Content-type') || '').match(/^text\/javascript/i)) this.evalResponse(); } try { (this.options['on' + event] || Prototype.emptyFunction)(transport, json); Ajax.Responders.dispatch('on' + event, this, transport, json); } catch (e) { this.dispatchException(e); } /* Avoid memory leak in MSIE: clean up the oncomplete event handler */ if (event == 'Complete') this.transport.onreadystatechange = Prototype.emptyFunction; }, dispatchException: function(exception) { (this.options.onException || Prototype.emptyFunction)(this, exception); Ajax.Responders.dispatch('onException', this, exception); } }); Ajax.Updater = Class.create(); Object.extend(Object.extend(Ajax.Updater.prototype, Ajax.Request.prototype), { initialize: function(container, url, options) { this.containers = { success: container.success ? $(container.success) : $(container), failure: container.failure ? $(container.failure) : (container.success ? null : $(container)) } this.transport = Ajax.getTransport(); this.setOptions(options); var onComplete = this.options.onComplete || Prototype.emptyFunction; this.options.onComplete = (function(transport, object) { this.updateContent(); onComplete(transport, object); }).bind(this); this.request(url); }, updateContent: function() { var receiver = this.responseIsSuccess() ? this.containers.success : this.containers.failure; var response = this.transport.responseText; if (!this.options.evalScripts) response = response.stripScripts(); if (receiver) { if (this.options.insertion) { new this.options.insertion(receiver, response); } else { Element.update(receiver, response); } } if (this.responseIsSuccess()) { if (this.onComplete) setTimeout(this.onComplete.bind(this), 10); } } }); Ajax.PeriodicalUpdater = Class.create(); Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), { initialize: function(container, url, options) { this.setOptions(options); this.onComplete = this.options.onComplete; this.frequency = (this.options.frequency || 2); this.decay = (this.options.decay || 1); this.updater = {}; this.container = container; this.url = url; this.start(); }, start: function() { this.options.onComplete = this.updateComplete.bind(this); this.onTimerEvent(); }, stop: function() { this.updater.onComplete = undefined; clearTimeout(this.timer); (this.onComplete || Prototype.emptyFunction).apply(this, arguments); }, updateComplete: function(request) { if (this.options.decay) { this.decay = (request.responseText == this.lastText ? this.decay * this.options.decay : 1); this.lastText = request.responseText; } this.timer = setTimeout(this.onTimerEvent.bind(this), this.decay * this.frequency * 1000); }, onTimerEvent: function() { this.updater = new Ajax.Updater(this.container, this.url, this.options); } }); document.getElementsByClassName = function(className, parentElement) { var children = ($(parentElement) || document.body).getElementsByTagName('*'); return $A(children).inject([], function(elements, child) { if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)"))) elements.push(child); return elements; }); } /*--------------------------------------------------------------------------*/ if (!window.Element) { var Element = new Object(); } Object.extend(Element, { visible: function(element) { return $(element).style.display != 'none'; }, toggle: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); Element[Element.visible(element) ? 'hide' : 'show'](element); } }, hide: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); element.style.display = 'none'; } }, show: function() { for (var i = 0; i < arguments.length; i++) { var element = $(arguments[i]); element.style.display = ''; } }, remove: function(element) { element = $(element); element.parentNode.removeChild(element); }, update: function(element, html) { $(element).innerHTML = html.stripScripts(); setTimeout(function() {html.evalScripts()}, 10); }, getHeight: function(element) { element = $(element); return element.offsetHeight; }, classNames: function(element) { return new Element.ClassNames(element); }, hasClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).include(className); }, addClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).add(className); }, removeClassName: function(element, className) { if (!(element = $(element))) return; return Element.classNames(element).remove(className); }, // removes whitespace-only text node children cleanWhitespace: function(element) { element = $(element); for (var i = 0; i < element.childNodes.length; i++) { var node = element.childNodes[i]; if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) Element.remove(node); } }, empty: function(element) { return $(element).innerHTML.match(/^\s*$/); }, scrollTo: function(element) { element = $(element); var x = element.x ? element.x : element.offsetLeft, y = element.y ? element.y : element.offsetTop; window.scrollTo(x, y); }, getStyle: function(element, style) { element = $(element); var value = element.style[style.camelize()]; if (!value) { if (document.defaultView && document.defaultView.getComputedStyle) { var css = document.defaultView.getComputedStyle(element, null); value = css ? css.getPropertyValue(style) : null; } else if (element.currentStyle) { value = element.currentStyle[style.camelize()]; } } if (window.opera && ['left', 'top', 'right', 'bottom'].include(style)) if (Element.getStyle(element, 'position') == 'static') value = 'auto'; return value == 'auto' ? null : value; }, setStyle: function(element, style) { element = $(element); for (name in style) element.style[name.camelize()] = style[name]; }, getDimensions: function(element) { element = $(element); if (Element.getStyle(element, 'display') != 'none') return {width: element.offsetWidth, height: element.offsetHeight}; // All *Width and *Height properties give 0 on elements with display none, // so enable the element temporarily var els = element.style; var originalVisibility = els.visibility; var originalPosition = els.position; els.visibility = 'hidden'; els.position = 'absolute'; els.display = ''; var originalWidth = element.clientWidth; var originalHeight = element.clientHeight; els.display = 'none'; els.position = originalPosition; els.visibility = originalVisibility; return {width: originalWidth, height: originalHeight}; }, makePositioned: function(element) { element = $(element); var pos = Element.getStyle(element, 'position'); if (pos == 'static' || !pos) { element._madePositioned = true; element.style.position = 'relative'; // Opera returns the offset relative to the positioning context, when an // element is position relative but top and left have not been defined if (window.opera) { element.style.top = 0; element.style.left = 0; } } }, undoPositioned: function(element) { element = $(element); if (element._madePositioned) { element._madePositioned = undefined; element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = ''; } }, makeClipping: function(element) { element = $(element); if (element._overflow) return; element._overflow = element.style.overflow; if ((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden'; }, undoClipping: function(element) { element = $(element); if (element._overflow) return; element.style.overflow = element._overflow; element._overflow = undefined; } }); var Toggle = new Object(); Toggle.display = Element.toggle; /*--------------------------------------------------------------------------*/ Abstract.Insertion = function(adjacency) { this.adjacency = adjacency; } Abstract.Insertion.prototype = { initialize: function(element, content) { this.element = $(element); this.content = content.stripScripts(); if (this.adjacency && this.element.insertAdjacentHTML) { try { this.element.insertAdjacentHTML(this.adjacency, this.content); } catch (e) { if (this.element.tagName.toLowerCase() == 'tbody') { this.insertContent(this.contentFromAnonymousTable()); } else { throw e; } } } else { this.range = this.element.ownerDocument.createRange(); if (this.initializeRange) this.initializeRange(); this.insertContent([this.range.createContextualFragment(this.content)]); } setTimeout(function() {content.evalScripts()}, 10); }, contentFromAnonymousTable: function() { var div = document.createElement('div'); div.innerHTML = '' + this.content + '
'; return $A(div.childNodes[0].childNodes[0].childNodes); } } var Insertion = new Object(); Insertion.Before = Class.create(); Insertion.Before.prototype = Object.extend(new Abstract.Insertion('beforeBegin'), { initializeRange: function() { this.range.setStartBefore(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.parentNode.insertBefore(fragment, this.element); }).bind(this)); } }); Insertion.Top = Class.create(); Insertion.Top.prototype = Object.extend(new Abstract.Insertion('afterBegin'), { initializeRange: function() { this.range.selectNodeContents(this.element); this.range.collapse(true); }, insertContent: function(fragments) { fragments.reverse(false).each((function(fragment) { this.element.insertBefore(fragment, this.element.firstChild); }).bind(this)); } }); Insertion.Bottom = Class.create(); Insertion.Bottom.prototype = Object.extend(new Abstract.Insertion('beforeEnd'), { initializeRange: function() { this.range.selectNodeContents(this.element); this.range.collapse(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.appendChild(fragment); }).bind(this)); } }); Insertion.After = Class.create(); Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), { initializeRange: function() { this.range.setStartAfter(this.element); }, insertContent: function(fragments) { fragments.each((function(fragment) { this.element.parentNode.insertBefore(fragment, this.element.nextSibling); }).bind(this)); } }); /*--------------------------------------------------------------------------*/ Element.ClassNames = Class.create(); Element.ClassNames.prototype = { initialize: function(element) { this.element = $(element); }, _each: function(iterator) { this.element.className.split(/\s+/).select(function(name) { return name.length > 0; })._each(iterator); }, set: function(className) { this.element.className = className; }, add: function(classNameToAdd) { if (this.include(classNameToAdd)) return; this.set(this.toArray().concat(classNameToAdd).join(' ')); }, remove: function(classNameToRemove) { if (!this.include(classNameToRemove)) return; this.set(this.select(function(className) { return className != classNameToRemove; }).join(' ')); }, toString: function() { return this.toArray().join(' '); } } Object.extend(Element.ClassNames.prototype, Enumerable); var Field = { clear: function() { for (var i = 0; i < arguments.length; i++) $(arguments[i]).value = ''; }, focus: function(element) { $(element).focus(); }, present: function() { for (var i = 0; i < arguments.length; i++) if ($(arguments[i]).value == '') return false; return true; }, select: function(element) { $(element).select(); }, activate: function(element) { element = $(element); element.focus(); if (element.select) element.select(); } } /*--------------------------------------------------------------------------*/ var Form = { serialize: function(form) { var elements = Form.getElements($(form)); var queryComponents = new Array(); for (var i = 0; i < elements.length; i++) { var queryComponent = Form.Element.serialize(elements[i]); if (queryComponent) queryComponents.push(queryComponent); } return queryComponents.join('&'); }, getElements: function(form) { form = $(form); var elements = new Array(); for (tagName in Form.Element.Serializers) { var tagElements = form.getElementsByTagName(tagName); for (var j = 0; j < tagElements.length; j++) elements.push(tagElements[j]); } return elements; }, getInputs: function(form, typeName, name) { form = $(form); var inputs = form.getElementsByTagName('input'); if (!typeName && !name) return inputs; var matchingInputs = new Array(); for (var i = 0; i < inputs.length; i++) { var input = inputs[i]; if ((typeName && input.type != typeName) || (name && input.name != name)) continue; matchingInputs.push(input); } return matchingInputs; }, disable: function(form) { var elements = Form.getElements(form); for (var i = 0; i < elements.length; i++) { var element = elements[i]; element.blur(); element.disabled = 'true'; } }, enable: function(form) { var elements = Form.getElements(form); for (var i = 0; i < elements.length; i++) { var element = elements[i]; element.disabled = ''; } }, findFirstElement: function(form) { return Form.getElements(form).find(function(element) { return element.type != 'hidden' && !element.disabled && ['input', 'select', 'textarea'].include(element.tagName.toLowerCase()); }); }, focusFirstElement: function(form) { Field.activate(Form.findFirstElement(form)); }, reset: function(form) { $(form).reset(); } } Form.Element = { serialize: function(element) { element = $(element); var method = element.tagName.toLowerCase(); var parameter = Form.Element.Serializers[method](element); if (parameter) { var key = encodeURIComponent(parameter[0]); if (key.length == 0) return; if (parameter[1].constructor != Array) parameter[1] = [parameter[1]]; return parameter[1].map(function(value) { return key + '=' + encodeURIComponent(value); }).join('&'); } }, getValue: function(element) { element = $(element); var method = element.tagName.toLowerCase(); var parameter = Form.Element.Serializers[method](element); if (parameter) return parameter[1]; } } Form.Element.Serializers = { input: function(element) { switch (element.type.toLowerCase()) { case 'submit': case 'hidden': case 'password': case 'text': return Form.Element.Serializers.textarea(element); case 'checkbox': case 'radio': return Form.Element.Serializers.inputSelector(element); } return false; }, inputSelector: function(element) { if (element.checked) return [element.name, element.value]; }, textarea: function(element) { return [element.name, element.value]; }, select: function(element) { return Form.Element.Serializers[element.type == 'select-one' ? 'selectOne' : 'selectMany'](element); }, selectOne: function(element) { var value = '', opt, index = element.selectedIndex; if (index >= 0) { opt = element.options[index]; value = opt.value; if (!value && !('value' in opt)) value = opt.text; } return [element.name, value]; }, selectMany: function(element) { var value = new Array(); for (var i = 0; i < element.length; i++) { var opt = element.options[i]; if (opt.selected) { var optValue = opt.value; if (!optValue && !('value' in opt)) optValue = opt.text; value.push(optValue); } } return [element.name, value]; } } /*--------------------------------------------------------------------------*/ var $F = Form.Element.getValue; /*--------------------------------------------------------------------------*/ Abstract.TimedObserver = function() {} Abstract.TimedObserver.prototype = { initialize: function(element, frequency, callback) { this.frequency = frequency; this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); this.registerCallback(); }, registerCallback: function() { setInterval(this.onTimerEvent.bind(this), this.frequency * 1000); }, onTimerEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } } } Form.Element.Observer = Class.create(); Form.Element.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { getValue: function() { return Form.Element.getValue(this.element); } }); Form.Observer = Class.create(); Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { getValue: function() { return Form.serialize(this.element); } }); /*--------------------------------------------------------------------------*/ Abstract.EventObserver = function() {} Abstract.EventObserver.prototype = { initialize: function(element, callback) { this.element = $(element); this.callback = callback; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else this.registerCallback(this.element); }, onElementEvent: function() { var value = this.getValue(); if (this.lastValue != value) { this.callback(this.element, value); this.lastValue = value; } }, registerFormCallbacks: function() { var elements = Form.getElements(this.element); for (var i = 0; i < elements.length; i++) this.registerCallback(elements[i]); }, registerCallback: function(element) { if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': Event.observe(element, 'click', this.onElementEvent.bind(this)); break; case 'password': case 'text': case 'textarea': case 'select-one': case 'select-multiple': Event.observe(element, 'change', this.onElementEvent.bind(this)); break; } } } } Form.Element.EventObserver = Class.create(); Form.Element.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { getValue: function() { return Form.Element.getValue(this.element); } }); Form.EventObserver = Class.create(); Form.EventObserver.prototype = Object.extend(new Abstract.EventObserver(), { getValue: function() { return Form.serialize(this.element); } }); if (!window.Event) { var Event = new Object(); } Object.extend(Event, { KEY_BACKSPACE: 8, KEY_TAB: 9, KEY_RETURN: 13, KEY_ESC: 27, KEY_LEFT: 37, KEY_UP: 38, KEY_RIGHT: 39, KEY_DOWN: 40, KEY_DELETE: 46, element: function(event) { return event.target || event.srcElement; }, isLeftClick: function(event) { return (((event.which) && (event.which == 1)) || ((event.button) && (event.button == 1))); }, pointerX: function(event) { return event.pageX || (event.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft)); }, pointerY: function(event) { return event.pageY || (event.clientY + (document.documentElement.scrollTop || document.body.scrollTop)); }, stop: function(event) { if (event.preventDefault) { event.preventDefault(); event.stopPropagation(); } else { event.returnValue = false; event.cancelBubble = true; } }, // find the first node with the given tagName, starting from the // node the event was triggered on; traverses the DOM upwards findElement: function(event, tagName) { var element = Event.element(event); while (element.parentNode && (!element.tagName || (element.tagName.toUpperCase() != tagName.toUpperCase()))) element = element.parentNode; return element; }, observers: false, _observeAndCache: function(element, name, observer, useCapture) { if (!this.observers) this.observers = []; if (element.addEventListener) { this.observers.push([element, name, observer, useCapture]); element.addEventListener(name, observer, useCapture); } else if (element.attachEvent) { this.observers.push([element, name, observer, useCapture]); element.attachEvent('on' + name, observer); } }, unloadCache: function() { if (!Event.observers) return; for (var i = 0; i < Event.observers.length; i++) { Event.stopObserving.apply(this, Event.observers[i]); Event.observers[i][0] = null; } Event.observers = false; }, observe: function(elementParam, name, observer, useCapture) { var element = $(elementParam); useCapture = useCapture || false; if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.attachEvent)) name = 'keydown'; this._observeAndCache(element, name, observer, useCapture); }, stopObserving: function(elementParam, name, observer, useCapture) { var element = $(elementParam); useCapture = useCapture || false; if (name == 'keypress' && (navigator.appVersion.match(/Konqueror|Safari|KHTML/) || element.detachEvent)) name = 'keydown'; if (element.removeEventListener) { element.removeEventListener(name, observer, useCapture); } else if (element.detachEvent) { element.detachEvent('on' + name, observer); } } }); /* prevent memory leaks in IE */ Event.observe(window, 'unload', Event.unloadCache, false); var Position = { // set to true if needed, warning: firefox performance problems // NOT neeeded for page scrolling, only if draggable contained in // scrollable elements includeScrollOffsets: false, // must be called before calling withinIncludingScrolloffset, every time the // page is scrolled prepare: function() { this.deltaX = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0; this.deltaY = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; }, realOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.scrollTop || 0; valueL += element.scrollLeft || 0; element = element.parentNode; } while (element); return [valueL, valueT]; }, cumulativeOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; } while (element); return [valueL, valueT]; }, positionedOffset: function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; element = element.offsetParent; if (element) { p = Element.getStyle(element, 'position'); if (p == 'relative' || p == 'absolute') break; } } while (element); return [valueL, valueT]; }, offsetParent: function(element) { if (element.offsetParent) return element.offsetParent; if (element == document.body) return element; while ((element = element.parentNode) && element != document.body) if (Element.getStyle(element, 'position') != 'static') return element; return document.body; }, // caches x/y coordinate pair to use with overlap within: function(element, x, y) { if (this.includeScrollOffsets) return this.withinIncludingScrolloffsets(element, x, y); this.xcomp = x; this.ycomp = y; this.offset = this.cumulativeOffset(element); return (y >= this.offset[1] && y < this.offset[1] + element.offsetHeight && x >= this.offset[0] && x < this.offset[0] + element.offsetWidth); }, withinIncludingScrolloffsets: function(element, x, y) { var offsetcache = this.realOffset(element); this.xcomp = x + offsetcache[0] - this.deltaX; this.ycomp = y + offsetcache[1] - this.deltaY; this.offset = this.cumulativeOffset(element); return (this.ycomp >= this.offset[1] && this.ycomp < this.offset[1] + element.offsetHeight && this.xcomp >= this.offset[0] && this.xcomp < this.offset[0] + element.offsetWidth); }, // within must be called directly before overlap: function(mode, element) { if (!mode) return 0; if (mode == 'vertical') return ((this.offset[1] + element.offsetHeight) - this.ycomp) / element.offsetHeight; if (mode == 'horizontal') return ((this.offset[0] + element.offsetWidth) - this.xcomp) / element.offsetWidth; }, clone: function(source, target) { source = $(source); target = $(target); target.style.position = 'absolute'; var offsets = this.cumulativeOffset(source); target.style.top = offsets[1] + 'px'; target.style.left = offsets[0] + 'px'; target.style.width = source.offsetWidth + 'px'; target.style.height = source.offsetHeight + 'px'; }, page: function(forElement) { var valueT = 0, valueL = 0; var element = forElement; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; // Safari fix if (element.offsetParent==document.body) if (Element.getStyle(element,'position')=='absolute') break; } while (element = element.offsetParent); element = forElement; do { valueT -= element.scrollTop || 0; valueL -= element.scrollLeft || 0; } while (element = element.parentNode); return [valueL, valueT]; }, clone: function(source, target) { var options = Object.extend({ setLeft: true, setTop: true, setWidth: true, setHeight: true, offsetTop: 0, offsetLeft: 0 }, arguments[2] || {}) // find page position of source source = $(source); var p = Position.page(source); // find coordinate system to use target = $(target); var delta = [0, 0]; var parent = null; // delta [0,0] will do fine with position: fixed elements, // position:absolute needs offsetParent deltas if (Element.getStyle(target,'position') == 'absolute') { parent = Position.offsetParent(target); delta = Position.page(parent); } // correct by body offsets (fixes Safari) if (parent == document.body) { delta[0] -= document.body.offsetLeft; delta[1] -= document.body.offsetTop; } // set position if(options.setLeft) target.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px'; if(options.setTop) target.style.top = (p[1] - delta[1] + options.offsetTop) + 'px'; if(options.setWidth) target.style.width = source.offsetWidth + 'px'; if(options.setHeight) target.style.height = source.offsetHeight + 'px'; }, absolutize: function(element) { element = $(element); if (element.style.position == 'absolute') return; Position.prepare(); var offsets = Position.positionedOffset(element); var top = offsets[1]; var left = offsets[0]; var width = element.clientWidth; var height = element.clientHeight; element._originalLeft = left - parseFloat(element.style.left || 0); element._originalTop = top - parseFloat(element.style.top || 0); element._originalWidth = element.style.width; element._originalHeight = element.style.height; element.style.position = 'absolute'; element.style.top = top + 'px';; element.style.left = left + 'px';; element.style.width = width + 'px';; element.style.height = height + 'px';; }, relativize: function(element) { element = $(element); if (element.style.position == 'relative') return; Position.prepare(); element.style.position = 'relative'; var top = parseFloat(element.style.top || 0) - (element._originalTop || 0); var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0); element.style.top = top + 'px'; element.style.left = left + 'px'; element.style.height = element._originalHeight; element.style.width = element._originalWidth; } } // Safari returns margins on body which is incorrect if the child is absolutely // positioned. For performance reasons, redefine Position.cumulativeOffset for // KHTML/WebKit only. if (/Konqueror|Safari|KHTML/.test(navigator.userAgent)) { Position.cumulativeOffset = function(element) { var valueT = 0, valueL = 0; do { valueT += element.offsetTop || 0; valueL += element.offsetLeft || 0; if (element.offsetParent == document.body) if (Element.getStyle(element, 'position') == 'absolute') break; element = element.offsetParent; } while (element); return [valueL, valueT]; } } /** * * 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. **/ var Rico = new Object(); Rico.Corner = { round: function(e, options) { var e = $(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
that has had Rico rounded corners added. * * It seems we cannot just set the background color for the * outer
so each element used to create the * corners must have its background color set individually. * * @param {DOM} theDiv - A child of the outer
that was * supplied to the `round` method. * * @param {str} 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
that has had Rico rounded corners added. * * See changeColor (above) for algorithm explanation * * @param {DOM} theDiv A child of the outer
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
that was * supplied to the `round` method. * * @param {Array} 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 = "
" + el.innerHTML + "
" }, _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 } Object.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= 0) return true; return false; }, _blend: function(c1, c2) { var cc1 = Rico.Color.createFromHex(c1); cc1.blend(Rico.Color.createFromHex(c2)); return cc1; }, _background: function(el) { try { return 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; } } Rico.Color = Class.create(); Rico.Color.prototype = { 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 = 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 = 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 = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b ); }, darken: function(percent) { var hsb = this.asHSB(); this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0)); }, brighten: function(percent) { var hsb = this.asHSB(); this.rgb = 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 Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b); }, toString: function() { return this.asHex(); } }; 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 Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) ); } /** * Factory method for creating a color from the background of * an HTML element. */ Rico.Color.createColorFromBackground = function(elem) { var actualColor = RicoUtil.getElementsComputedStyle($(elem), "backgroundColor", "background-color"); if ( actualColor == "transparent" && elem.parentNode ) return Rico.Color.createColorFromBackground(elem.parentNode); if ( actualColor == null ) return new Rico.Color(255,255,255); if ( actualColor.indexOf("rgb(") == 0 ) { var colors = actualColor.substring(4, actualColor.length - 1 ); var colorArray = colors.split(","); return new Rico.Color( parseInt( colorArray[0] ), parseInt( colorArray[1] ), parseInt( colorArray[2] ) ); } else if ( actualColor.indexOf("#") == 0 ) { return Rico.Color.createFromHex(actualColor); } else return new Rico.Color(255,255,255); } 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) }; } 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 }; } /** * @class */ OpenLayers.Util = new Object(); /** * @class This class represents a screen coordinate, in x and y coordinates */ OpenLayers.Pixel = Class.create(); OpenLayers.Pixel.prototype = { /** @type float */ x: 0.0, /** @type float */ y: 0.0, /** * @constructor * * @param {float} x * @param {float} y */ initialize: function(x, y) { this.x = x; this.y = y; }, /** * @return string representation of Pixel. ex: "x=200.4,y=242.2" * @type str */ toString:function() { return ("x=" + this.x + ",y=" + this.y); }, /** * @type OpenLayers.Pixel */ copyOf:function() { return new OpenLayers.Pixel(this.x, this.y); }, /** * @param {OpenLayers.Pixel} px * * @return whether or not the point passed in as parameter is equal to this * @type bool */ equals:function(px) { return ((this.x == px.x) && (this.y == px.y)); }, /** * @param {int} x * @param {int} y * * @return a new Pixel with this pixel's x&y augmented by the * values passed in. * @type OpenLayers.Pixel */ add:function(x, y) { return new OpenLayers.Pixel(this.x + x, this.y + y); }, /** * @param {OpenLayers.Pixel} px * * @return a new Pixel with this pixel's x&y augmented by the * x&y values of the pixel passed in. * @type OpenLayers.Pixel */ offset:function(px) { return this.add(px.x, px.y); }, /** @final @type str */ CLASS_NAME: "OpenLayers.Pixel" }; /** * @class This class represents a width and height pair */ OpenLayers.Size = Class.create(); OpenLayers.Size.prototype = { /** @type float */ w: 0.0, /** @type float */ h: 0.0, /** * @constructor * * @param {float} w * @param {float} h */ initialize: function(w, h) { this.w = w; this.h = h; }, /** * @return String representation of OpenLayers.Size object. * (ex. "w=55,h=66") * @type String */ toString:function() { return ("w=" + this.w + ",h=" + this.h); }, /** * @return New OpenLayers.Size object with the same w and h values * @type OpenLayers.Size */ copyOf:function() { return new OpenLayers.Size(this.w, this.h); }, /** * @param {OpenLayers.Size} sz * @returns Boolean value indicating whether the passed-in OpenLayers.Size * object has the same w and h components as this * * @type bool */ equals:function(sz) { return ((this.w == sz.w) && (this.h == sz.h)); }, /** @final @type String */ CLASS_NAME: "OpenLayers.Size" }; /** * @class This class represents a longitude and latitude pair */ OpenLayers.LonLat = Class.create(); OpenLayers.LonLat.prototype = { /** @type float */ lon: 0.0, /** @type float */ lat: 0.0, /** * @constructor * * @param {float} lon * @param {float} lat */ initialize: function(lon, lat) { this.lon = lon; this.lat = lat; }, /** * @return String representation of OpenLayers.LonLat object. * (ex. "lon=5,lat=42") * @type String */ toString:function() { return ("lon=" + this.lon + ",lat=" + this.lat); }, /** * @return Shortened String representation of OpenLayers.LonLat object. * (ex. "5, 42") * @type String */ toShortString:function() { return (this.lon + ", " + this.lat); }, /** * @return New OpenLayers.LonLat object with the same lon and lat values * @type OpenLayers.LonLat */ copyOf:function() { return new OpenLayers.LonLat(this.lon, this.lat); }, /** * @param {float} lon * @param {float} lat * * @return A new OpenLayers.LonLat object with the lon and lat passed-in * added to this's. * @type OpenLayers.Pixel */ add:function(lon, lat) { return new OpenLayers.LonLat(this.lon + lon, this.lat + lat); }, /** * @param {OpenLayers.LonLat} ll * @returns Boolean value indicating whether the passed-in OpenLayers.LonLat * object has the same lon and lat components as this * * @type bool */ equals:function(ll) { return ((this.lon == ll.lon) && (this.lat == ll.lat)); }, /** @final @type String */ CLASS_NAME: "OpenLayers.LonLat" }; /** Alternative constructor that builds a new OpenLayers.LonLat from a * parameter string * * @constructor * * @param {String} str Comma-separated Lon,Lat coordinate string. * (ex. "5,40") * * @returns New OpenLayers.LonLat object built from the passed-in String. * @type OpenLayers.LonLat */ OpenLayers.LonLat.fromString = function(str) { var pair = str.split(","); return new OpenLayers.LonLat(parseFloat(pair[0]), parseFloat(pair[1])); }; /** * @class This class represents a bounding box. * Data stored as left, bottom, right, top floats */ OpenLayers.Bounds = Class.create(); OpenLayers.Bounds.prototype = { /** @type float */ left: 0.0, /** @type float */ bottom: 0.0, /** @type float */ right: 0.0, /** @type float */ top: 0.0, /** * @constructor * * @param {float} left * @param {float} bottom * @param {float} right * @param {float} top * */ initialize: function(left, bottom, right, top) { this.left = left; this.bottom = bottom; this.right = right; this.top = top; }, /** * @returns A fresh copy of the bounds * @type OpenLayers.Bounds */ copyOf:function() { return new OpenLayers.Bounds(this.left, this.bottom, this.right, this.top); }, /** * @param {OpenLayers.Bounds} bounds * @returns Boolean value indicating whether the passed-in OpenLayers.Bounds * object has the same left, right, top, bottom components as this * * @type bool */ equals:function(bounds) { return ((this.left == bounds.left) && (this.right == bounds.right) && (this.top == bounds.top) && (this.bottom == bounds.bottom)); }, /** * @return String representation of OpenLayers.Bounds object. * (ex."left-bottom=(5,42) right-top=(10,45)") * @type String */ toString:function(){ return ( "left-bottom=(" + this.left + "," + this.bottom + ")" + " right-top=(" + this.right + "," + this.top + ")" ); }, /** * @return Simple String representation of OpenLayers.Bounds object. * (ex. "5,42,10,45") * @type String */ toBBOX:function() { return (this.left + "," + this.bottom + "," + this.right + "," + this.top); }, /** * @returns The width of the bounds * @type float */ getWidth:function() { return (this.right - this.left); }, /** * @returns The height of the bounds * @type float */ getHeight:function() { return (this.top - this.bottom); }, /** * @returns An OpenLayers.Size which represents the size of the box * @type OpenLayers.Size */ getSize:function() { return new OpenLayers.Size(this.getWidth(), this.getHeight()); }, /** * @returns An OpenLayers.Pixel which represents the center of the bounds * @type OpenLayers.Pixel */ getCenterPixel:function() { return new OpenLayers.Pixel( (this.left + this.right) / 2, (this.bottom + this.top) / 2); }, /** * @returns An OpenLayers.LonLat which represents the center of the bounds * @type OpenLayers.LonLat */ getCenterLonLat:function() { return new OpenLayers.LonLat( (this.left + this.right) / 2, (this.bottom + this.top) / 2); }, /** * @param {float} x * @param {float} y * * @returns A new OpenLayers.Bounds whose coordinates are the same as this, * but shifted by the passed-in x and y values * @type OpenLayers.Bounds */ add:function(x, y){ return new OpenLayers.Box(this.left + x, this.bottom + y, this.right + x, this.top + y); }, /** * @param {float} x * @param {float} y * @param {Boolean} inclusive Whether or not to include the border. * Default is true * * @return Whether or not the passed-in coordinates are within this bounds * @type Boolean */ contains:function(x, y, inclusive) { //set default if (inclusive == null) { inclusive = true; } var contains = false; if (inclusive) { contains = ((x >= this.left) && (x <= this.right) && (y >= this.bottom) && (y <= this.top)); } else { contains = ((x > this.left) && (x < this.right) && (y > this.bottom) && (y < this.top)); } return contains; }, /** * @param {OpenLayers.Bounds} bounds * @param {Boolean} partial If true, only part of passed-in * OpenLayers.Bounds needs be within this bounds. * If false, the entire passed-in bounds must be * within. Default is false * @param {Boolean} inclusive Whether or not to include the border. * Default is true * * @return Whether or not the passed-in OpenLayers.Bounds object is * contained within this bounds. * @type Boolean */ containsBounds:function(bounds, partial, inclusive) { //set defaults if (partial == null) { partial = false; } if (inclusive == null) { inclusive = true; } var inLeft; var inTop; var inRight; var inBottom; if (inclusive) { inLeft = (bounds.left >= this.left) && (bounds.left <= this.right); inTop = (bounds.top >= this.bottom) && (bounds.top <= this.top); inRight= (bounds.right >= this.left) && (bounds.right <= this.right); inBottom = (bounds.bottom >= this.bottom) && (bounds.bottom <= this.top); } else { inLeft = (bounds.left > this.left) && (bounds.left < this.right); inTop = (bounds.top > this.bottom) && (bounds.top < this.top); inRight= (bounds.right > this.left) && (bounds.right < this.right); inBottom = (bounds.bottom > this.bottom) && (bounds.bottom < this.top); } return (partial) ? (inTop || inBottom) && (inLeft || inRight ) : (inTop && inLeft && inBottom && inRight); }, /** * @param {OpenLayers.LonLat} lonlat * * @returns The quadrant ("br" "tr" "tl" "bl") of the bounds in which * the coordinate lies. * @type String */ determineQuadrant: function(lonlat) { var quadrant = ""; var center = this.getCenterLonLat(); quadrant += (lonlat.lat < center.lat) ? "b" : "t"; quadrant += (lonlat.lon < center.lon) ? "l" : "r"; return quadrant; }, /** @final @type String */ CLASS_NAME: "OpenLayers.Bounds" }; /** Alternative constructor that builds a new OpenLayers.Bounds from a * parameter string * * @constructor * * @param {String} str Comma-separated bounds string. (ex. "5,42,10,45") * * @returns New OpenLayers.Bounds object built from the passed-in String. * @type OpenLayers.Bounds */ OpenLayers.Bounds.fromString = function(str) { var bounds = str.split(","); return OpenLayers.Bounds.fromArray(bounds); }; /** Alternative constructor that builds a new OpenLayers.Bounds * from an array * * @constructor * * @param {Array} bbox Array of bounds values (ex. [5,42,10,45]) * * @returns New OpenLayers.Bounds object built from the passed-in Array. * @type OpenLayers.Bounds */ OpenLayers.Bounds.fromArray = function(bbox) { return new OpenLayers.Bounds(parseFloat(bbox[0]), parseFloat(bbox[1]), parseFloat(bbox[2]), parseFloat(bbox[3])); }; /** * @param {String} quadrant * * @returns The opposing quadrant ("br" "tr" "tl" "bl"). For Example, if * you pass in "bl" it returns "tr", if you pass in "br" it * returns "tl", etc. * @type String */ OpenLayers.Bounds.oppositeQuadrant = function(quadrant) { var opp = ""; opp += (quadrant.charAt(0) == 't') ? 'b' : 't'; opp += (quadrant.charAt(1) == 'l') ? 'r' : 'l'; return opp; }; // Some other helpful things /** * @param {String} sStart * * @returns Whether or not this string starts with the string passed in. * @type Boolean */ String.prototype.startsWith = function(sStart){ return (this.substr(0,sStart.length) == sStart); }; /** * @returns A trimmed version of the string - all leading and * trailing spaces removed * @type String */ String.prototype.trim = function() { var b = 0; while(this.substr(b,1) == " ") { b++; } var e = this.length - 1; while(this.substr(e,1) == " ") { e--; } return this.substring(b, e+1); }; /** Remove an object from an array. Iterates through the array * to find the item, then removes it. * * @param {Object} item * * @returns A reference to the array * @type Array */ Array.prototype.remove = function(item) { for(var i=0; i < this.length; i++) { if(this[i] == item) { this.splice(i,1); //break;more than once?? } } return this; } /** * @returns A fresh copy of the array * @type Array */ Array.prototype.copyOf = function() { var copy = new Array(); for (var i = 0; i < this.length; i++) { copy[i] = this[i]; } return copy; }; /** * @param {Object} item */ Array.prototype.prepend = function(item) { this.splice(0, 0, item); }; /** * @param {Object} item */ Array.prototype.append = function(item){ this[this.length] = item; }; /** */ Array.prototype.clear = function() { this.length = 0; }; /** * @param {Object} element * * @returns The first index of the element in the array if found. Else returns -1 * @type int */ Array.prototype.indexOf = function(element) { var index = -1; for(var i=0; i < this.length; i++) { if (this[i] == element) { index = i; break; } } return index; } /** * @param {String} id * @param {OpenLayers.Pixel} px * @param {OpenLayers.Size} sz * @param {String} position * @param {String} border * @param {String} overflow */ OpenLayers.Util.modifyDOMElement = function(element, id, px, sz, position, border, overflow) { if (id) { element.id = id; } if (px) { element.style.left = px.x; element.style.top = px.y; } if (sz) { element.style.width = sz.w + "px"; element.style.height = sz.h + "px"; } if (position) { element.style.position = position; } if (border) { element.style.border = border; } if (overflow) { element.style.overflow = overflow; } }; /** * zIndex is NOT set * * @param {String} id * @param {OpenLayers.Pixel} px * @param {OpenLayers.Size} sz * @param {String} imgURL * @param {String} position * @param {String} border * @param {String} overflow * * @returns A DOM Div created with the specified attributes. * @type DOMElement */ OpenLayers.Util.createDiv = function(id, px, sz, imgURL, position, border, overflow) { var dom = document.createElement('div'); //set specific properties dom.style.padding = "0"; dom.style.margin = "0"; dom.style.cursor = "inherit"; if (imgURL) { dom.style.backgroundImage = 'url(' + imgURL + ')'; } //set generic properties if (!id) { id = "OpenLayersDiv" + (Math.random() * 10000 % 10000); } if (!position) { position = "absolute"; } OpenLayers.Util.modifyDOMElement(dom, id, px, sz, position, border, overflow); return dom; }; /** * @param {String} id * @param {OpenLayers.Pixel} px * @param {OpenLayers.Size} sz * @param {String} imgURL * @param {String} position * @param {String} border * * @returns A DOM Image created with the specified attributes. * @type DOMElement */ OpenLayers.Util.createImage = function(id, px, sz, imgURL, position, border) { image = document.createElement("img"); //set special properties image.style.alt = id; image.style.cursor = "inherit"; image.galleryImg = "no"; if (imgURL) { image.src = imgURL; } //set generic properties if (!id) { id = "OpenLayersDiv" + (Math.random() * 10000 % 10000); } if (!position) { position = "relative"; } OpenLayers.Util.modifyDOMElement(image, id, px, sz, position, border); return image; }; OpenLayers.Util.alphaHack = function() { var arVersion = navigator.appVersion.split("MSIE"); var version = parseFloat(arVersion[1]); return ( (document.body.filters) && (version >= 5.5) && (version < 7) ); } /** * @param {DOMElement} div Div containing Alpha-adjusted Image * @param {String} id * @param {OpenLayers.Pixel} px * @param {OpenLayers.Size} sz * @param {String} imgURL * @param {String} position * @param {String} border * @param {String} sizing 'crop', 'scale', or 'image'. Default is "scale" */ OpenLayers.Util.modifyAlphaImageDiv = function(div, id, px, sz, imgURL, position, border, sizing) { OpenLayers.Util.modifyDOMElement(div, id, px, sz); var img = div.childNodes[0]; if (imgURL) { img.src = imgURL; } OpenLayers.Util.modifyDOMElement(img, div.id + "_innerImage", null, sz, "relative", border); if (OpenLayers.Util.alphaHack()) { div.style.display = "inline-block"; if (sizing == null) { sizing = "scale"; } div.style.filter = "progid:DXImageTransform.Microsoft" + ".AlphaImageLoader(src='" + img.src + "', " + "sizingMethod='" + sizing + "')"; img.style.filter = "progid:DXImageTransform.Microsoft" + ".Alpha(opacity=0)"; } }; /** * @param {String} id * @param {OpenLayers.Pixel} px * @param {OpenLayers.Size} sz * @param {String} imgURL * @param {String} position * @param {String} border * @param {String} sizing 'crop', 'scale', or 'image'. Default is "scale" * * @returns A DOM Div created with a DOM Image inside it. If the hack is * needed for transparency in IE, it is added. * @type DOMElement */ OpenLayers.Util.createAlphaImageDiv = function(id, px, sz, imgURL, position, border, sizing) { var div = OpenLayers.Util.createDiv(); var img = OpenLayers.Util.createImage(); div.appendChild(img); OpenLayers.Util.modifyAlphaImageDiv(div, id, px, sz, imgURL, position, border, sizing); return div; }; /** * @param {Object} params * * @returns a concatenation of the properties of an object in * http parameter notation. * (ex. "key1=value1&key2=value2&key3=value3") * @type String */ OpenLayers.Util.getParameterString = function(params) { paramsArray = new Array(); for (var key in params) { var value = params[key]; //skip functions if (typeof value == 'function') continue; paramsArray.push(key + "=" + value); } return paramsArray.join("&"); }; /** * @returns The fully formatted image location string * @type String */ OpenLayers.Util.getImagesLocation = function() { return OpenLayers._getScriptLocation() + "img/"; }; /** Takes a hash and copies any keys that don't exist from * another hash, by analogy with Object.extend() from * Prototype.js. * * @param {Object} to * @param {Object} from * * @type Object */ OpenLayers.Util.applyDefaults = function (to, from) { for (var key in from) { if (to[key] == null) { to[key] = from[key]; } } return to; }; /** These could/should be made namespace aware? * * @param {} p * @param {str} tagName * * @return {Array} */ OpenLayers.Util.getNodes=function(p, tagName) { var nodes = Try.these( function () { return OpenLayers.Util._getNodes(p.documentElement.childNodes, tagName); }, function () { return OpenLayers.Util._getNodes(p.childNodes, tagName); } ); return nodes; }; /** * @param {Array} nodes * @param {str} tagName * * @return {Array} */ OpenLayers.Util._getNodes=function(nodes, tagName) { var retArray = new Array(); for (var i=0;i 0)) { if (!index) { index=0; } if (result[index].childNodes.length > 1) { return result.childNodes[1].nodeValue; } else if (result[index].childNodes.length == 1) { return result[index].firstChild.nodeValue; } } else { return ""; } }; /** * @param {Event} evt * @param {HTMLDivElement} div * * @return {boolean} */ OpenLayers.Util.mouseLeft = function (evt, div) { // start with the element to which the mouse has moved var target = (evt.relatedTarget) ? evt.relatedTarget : evt.toElement; // walk up the DOM tree. while (target != div && target != null) { target = target.parentNode; } // if the target we stop at isn't the div, then we've left the div. return (target != div); }; OpenLayers.ProxyHost = "/viewer/Crossbrowser/blindproxy.py?url="; //OpenLayers.ProxyHost = "examples/proxy.cgi?url="; /** * Ajax reader for OpenLayers * *@uri url to do remote XML http get *@param '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 * */ /** * @param {} request */ OpenLayers.nullHandler = function(request) { // ol.Log.warn("Unhandled request return " + request.statusText); }; /** Background load a document * * @param {String} uri URI of source doc * @param {String} params Params on get (doesnt seem to work) * @param {Object} caller object which gets callbacks * @param {Function} onComplete callback for success * @param {Function} onFailure callback for failure * * Both callbacks optional (though silly) */ OpenLayers.loadURL = function(uri, params, caller, onComplete, onFailure) { if (OpenLayers.ProxyHost && uri.startsWith("http")) { uri = OpenLayers.ProxyHost + escape(uri); if (!params) { params=""; } params += "&cachehack=" + new Date().getTime(); } // ol.Log.debug("loadURL [" + uri + "]"); var success = (onComplete) ? onComplete.bind(caller) : OpenLayers.nullHandler; var failure = (onFailure) ? onFailure.bind(caller) : OpenLayers.nullHandler; // from prototype.js new Ajax.Request(uri, { method: 'get', parameters: params, onComplete: success, onFailure: failure } ); }; /** Parse XML into a doc structure * @param {String} text * * @returns Parsed Ajax Response ?? * @type ? */ 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 = Try.these( function() { var xmldom = new ActiveXObject('Microsoft.XMLDOM'); xmldom.loadXML(text); return xmldom; }, function() { return new DOMParser().parseFromString(text, 'text/xml'); }, function() { var req = new XMLHttpRequest(); req.open("GET", "data:" + "text/xml" + ";charset=utf-8," + encodeURIComponent(text), false); if (req.overrideMimeType) { req.overrideMimeType("text/xml"); } req.send(null); return req.responseXML; } ); return ajaxResponse; };OpenLayers.Events = Class.create(); OpenLayers.Events.prototype = { // Array: supported events BROWSER_EVENTS: [ "mouseover", "mouseout", "mousedown", "mouseup", "mousemove", "click", "dblclick", "resize", "focus", "blur" ], // hash of Array(Function): events listener functions listeners: null, // Object: the code object issuing application events object: null, // DOMElement: the DOM element receiving browser events div: null, // Array: list of support application events eventTypes: null, /** * @param {OpenLayers.Map} map * @param {DOMElement} div */ initialize: function (object, div, eventTypes) { this.listeners = {}; this.object = object; this.div = div; this.eventTypes = eventTypes; if (eventTypes) { for (var i = 0; i < this.eventTypes.length; i++) { // create a listener list for every custom application event this.listeners[ this.eventTypes[i] ] = []; } } for (var i = 0; i < this.BROWSER_EVENTS.length; i++) { var eventType = this.BROWSER_EVENTS[i]; // every browser event has a corresponding application event // (whether it's listened for or not). this.listeners[ eventType ] = []; Event.observe(div, eventType, this.handleBrowserEvent.bindAsEventListener(this)); } // disable dragstart in IE so that mousedown/move/up works normally Event.observe(div, "dragstart", Event.stop); }, /** * @param {str} type * @param {Object} obj * @param {Function} func */ register: function (type, obj, func) { var listeners = this.listeners[type]; listeners.push( func.bindAsEventListener(obj) ); }, remove: function(type) { this.listeners[type].pop(); }, /** * @param {event} evt */ handleBrowserEvent: function (evt) { evt.xy = this.getMousePosition(evt); this.triggerEvent(evt.type, evt) }, /** * @param {event} evt * * @return {OpenLayers.Pixel} */ getMousePosition: function (evt) { if (!this.div.offsets) { this.div.offsets = Position.page(this.div); } return new OpenLayers.Pixel( evt.clientX - this.div.offsets[0], evt.clientY - this.div.offsets[1]); }, /** * @param {str} type * @param {event} evt */ triggerEvent: function (type, evt) { if (evt == null) { evt = {}; } evt.object = this.object; var listeners = this.listeners[type]; for (var i = 0; i < listeners.length; i++) { var callback = listeners[i]; callback(evt); } } }; // @require: OpenLayers/Util.js /** * @class * * */ OpenLayers.Map = Class.create(); OpenLayers.Map.prototype = { // Hash: base z-indexes for different classes of thing Z_INDEX_BASE: { Layer: 100, Popup: 200, Control: 1000 }, // Array: supported application event types EVENT_TYPES: [ "addlayer", "removelayer", "movestart", "move", "moveend", "zoomend", "layerchanged", "popupopen", "popupclose", "addmarker", "removemarker", "clearmarkers", "mouseover", "mouseout", "mousemove", "dragstart", "drag", "dragend" ], // int: zoom levels, used to draw zoom dragging control and limit zooming maxZoomLevel: 16, // OpenLayers.Bounds maxExtent: new OpenLayers.Bounds(-180, -90, 180, 90), /* projection */ projection: "EPSG:4326", // float maxResolution: null, // degrees per pixel // DOMElement: the div that our map lives in div: null, // HTMLDivElement: the map's view port viewPortDiv: null, // HTMLDivElement: the map's layer container layerContainerDiv: null, // Array(OpenLayers.Layer): ordered list of layers in the map layers: null, // Array(OpenLayers.Control) controls: null, // Array(OpenLayers.Popup) popups: null, // OpenLayers.LonLat center: null, // int zoom: null, // OpenLayers.Events events: null, // OpenLayers.Pixel mouseDragStart: null, /** * @param {DOMElement} div */ initialize: function (div, options) { Object.extend(this, options); this.div = div = $(div); // the viewPortDiv is the outermost div we modify var id = div.id + "_OpenLayers_ViewPort"; this.viewPortDiv = OpenLayers.Util.createDiv(id, null, null, null, "relative", null, "hidden"); this.viewPortDiv.style.width = "100%"; this.viewPortDiv.style.height = "100%"; this.div.appendChild(this.viewPortDiv); // the layerContainerDiv is the one that holds all the layers id = div.id + "_OpenLayers_Container"; this.layerContainerDiv = OpenLayers.Util.createDiv(id); this.viewPortDiv.appendChild(this.layerContainerDiv); this.events = new OpenLayers.Events(this, div, this.EVENT_TYPES); this.updateSize(); // make the entire maxExtent fix in zoom level 0 by default if (this.maxResolution == null) { this.maxResolution = Math.max( this.maxExtent.getWidth() / this.size.w, this.maxExtent.getHeight() / this.size.h ); } // update the internal size register whenever the div is resized this.events.register("resize", this, this.updateSize); this.layers = []; if (!this.controls) { this.controls = []; this.addControl(new OpenLayers.Control.MouseDefaults()); this.addControl(new OpenLayers.Control.PanZoom()); } this.popups = new Array(); // always call map.destroy() Event.observe(window, 'unload', this.destroy.bindAsEventListener(this)); }, /** */ destroy:function() { if (this.layers != null) { for(var i=0; i< this.layers.length; i++) { this.layers[i].destroy(); } this.layers = null; } if (this.controls != null) { for(var i=0; i< this.controls.length; i++) { this.controls[i].destroy(); } this.controls = null; } }, /** * @param {OpenLayers.Layer} layer */ addLayer: function (layer, zIndex) { layer.map = this; layer.projection = this.projection; layer.div.style.overflow = ""; if (zIndex) { layer.div.style.zIndex = zIndex; } else { layer.div.style.zIndex = this.Z_INDEX_BASE['Layer'] + this.layers.length; } this.layerContainerDiv.appendChild(layer.div); this.layers.push(layer); this.events.triggerEvent("addlayer"); }, /** * @param {Array(OpenLayers.Layer)} layers */ addLayers: function (layers) { for (var i = 0; i < layers.length; i++) { this.addLayer(layers[i]); } }, /** * @param {OpenLayers.Control} control * @param {OpenLayers.Pixel} px */ addControl: function (control, px) { control.map = this; this.controls.push(control); var div = control.draw(px); if (div) { div.style.zIndex = this.Z_INDEX_BASE['Control'] + this.controls.length; this.viewPortDiv.appendChild( div ); } }, /** * @param {OpenLayers.Popup} popup */ addPopup: function(popup) { popup.map = this; this.popups.push(popup); var popupDiv = popup.draw(); if (popupDiv) { popupDiv.style.zIndex = this.Z_INDEX_BASE['Popup'] + this.popups.length; this.layerContainerDiv.appendChild(popupDiv); } }, /** * @param {OpenLayers.Popup} popup */ removePopup: function(popup) { this.popups.remove(popup); if (popup.div) { this.layerContainerDiv.removeChild(popup.div); } }, /** * @return {float} */ getResolution: function () { // return degrees per pixel return this.maxResolution / Math.pow(2, this.zoom); }, /** * @return {int} */ getZoom: function () { return this.zoom; }, /** * @returns {OpenLayers.Size} */ getSize: function () { return this.size; }, updateSize: function() { this.size = new OpenLayers.Size( this.div.clientWidth, this.div.clientHeight); this.events.div.offsets = null; // Workaround for the fact that hidden elements return 0 for size. if (this.size.w == 0 && this.size.h == 0) { this.size.w = parseInt(this.div.style.width); this.size.h = parseInt(this.div.style.height); } }, /** * @return {OpenLayers.LonLat} */ getCenter: function () { return this.center; }, /** * @return {OpenLayers.Bounds} */ getExtent: function () { if (this.center) { var res = this.getResolution(); var size = this.getSize(); var w_deg = size.w * res; var h_deg = size.h * res; return new OpenLayers.Bounds( this.center.lon - w_deg / 2, this.center.lat - h_deg / 2, this.center.lon + w_deg / 2, this.center.lat + h_deg / 2); } else { return null; } }, /** * @return {OpenLayers.Bounds} */ getFullExtent: function () { return this.maxExtent; }, getZoomLevels: function() { return this.maxZoomLevel; }, /** * @param {OpenLayers.Bounds} bounds * * @return {int} */ getZoomForExtent: function (bounds) { var size = this.getSize(); var width = bounds.getWidth(); var height = bounds.getHeight(); var deg_per_pixel = (width > height ? width / size.w : height / size.h); var zoom = Math.log(this.maxResolution / deg_per_pixel) / Math.log(2); return Math.floor(Math.max(zoom, 0)); }, /** * @param {OpenLayers.Pixel} layerPx * * @returns px translated into screen pixel coordinates * @type OpenLayers.Pixel */ getScreenPxFromLayerPx:function(layerPx) { var screenPx = layerPx.copyOf(); screenPx.x += parseInt(this.layerContainerDiv.style.left); screenPx.y += parseInt(this.layerContainerDiv.style.top); return screenPx; }, /** * @param {OpenLayers.Pixel} screenPx * * @returns px translated into screen pixel coordinates * @type OpenLayers.Pixel */ getLayerPxFromScreenPx:function(screenPx) { var layerPx = screenPx.copyOf(); layerPx.x -= parseInt(this.layerContainerDiv.style.left); layerPx.y -= parseInt(this.layerContainerDiv.style.top); return layerPx; }, /** * @param {OpenLayers.Pixel} px * * @return {OpenLayers.LonLat} */ getLonLatFromLayerPx: function (px) { //adjust for displacement of layerContainerDiv px = this.getScreenPxFromLayerPx(px); return this.getLonLatFromScreenPx(px); }, /** * @param {OpenLayers.Pixel} screenPx * * @returns An OpenLayers.LonLat which is the passed-in screen * OpenLayers.Pixel, translated into lon/lat given the * current extent and resolution * @type OpenLayers.LonLat */ getLonLatFromScreenPx: function (screenPx) { var center = this.getCenter(); //map center lon/lat var res = this.getResolution(); var size = this.getSize(); var delta_x = screenPx.x - (size.w / 2); var delta_y = screenPx.y - (size.h / 2); return new OpenLayers.LonLat(center.lon + delta_x * res , center.lat - delta_y * res); }, /** * @param {OpenLayers.LonLat} lonlat * * @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat, * translated into layer pixels given the current extent * and resolution * @type OpenLayers.Pixel */ getLayerPxFromLonLat: function (lonlat) { //adjust for displacement of layerContainerDiv var px = this.getScreenPxFromLonLat(lonlat); return this.getLayerPxFromScreenPx(px); }, /** * @param {OpenLayers.LonLat} lonlat * * @returns An OpenLayers.Pixel which is the passed-in OpenLayers.LonLat, * translated into screen pixels given the current extent * and resolution * @type OpenLayers.Pixel */ getScreenPxFromLonLat: function (lonlat) { var resolution = this.getResolution(); var extent = this.getExtent(); return new OpenLayers.Pixel( Math.round(1/resolution * (lonlat.lon - extent.left)), Math.round(1/resolution * (extent.top - lonlat.lat)) ); }, /** * @param {OpenLayers.LonLat} lonlat * @param {int} zoom */ setCenter: function (lonlat, zoom) { if (this.center) { // otherwise there's nothing to move yet this.moveLayerContainer(lonlat); } this.center = lonlat.copyOf(); var zoomChanged = null; if (zoom != null && zoom != this.zoom && zoom >= 0 && zoom <= this.getZoomLevels()) { zoomChanged = (this.zoom == null ? 0 : this.zoom); this.zoom = zoom; } this.events.triggerEvent("movestart"); this.moveToNewExtent(zoomChanged); this.events.triggerEvent("moveend"); }, moveToNewExtent: function (zoomChanged) { if (zoomChanged != null) { // reset the layerContainerDiv's location this.layerContainerDiv.style.left = "0px"; this.layerContainerDiv.style.top = "0px"; //redraw popups for (var i = 0; i < this.popups.length; i++) { this.popups[i].updatePosition(); } } var bounds = this.getExtent(); for (var i = 0; i < this.layers.length; i++) { this.layers[i].moveTo(bounds, (zoomChanged != null)); } this.events.triggerEvent("move"); if (zoomChanged != null) this.events.triggerEvent("zoomend", {oldZoom: zoomChanged, newZoom: this.zoom}); }, /** * zoomIn * Increase zoom level by one. */ zoomIn: function() { if (this.zoom != null && this.zoom <= this.getZoomLevels()) { this.zoomTo( this.zoom += 1 ); } }, /** * zoomTo * Set Zoom To int */ zoomTo: function(zoom) { if (zoom >= 0 && zoom <= this.getZoomLevels()) { var oldZoom = this.zoom; this.zoom = zoom; this.moveToNewExtent(oldZoom); } }, /** * zoomOut * Decrease zoom level by one. */ zoomOut: function() { if (this.zoom != null && this.zoom > 0) { this.zoomTo( this.zoom - 1 ); } }, zoomExtent: function() { var fullExtent = this.getFullExtent(); var oldZoom = this.zoom; this.setCenter( new OpenLayers.LonLat((fullExtent.left+fullExtent.right)/2, (fullExtent.bottom+fullExtent.top)/2), 0 ); }, /** * @param {OpenLayers.LonLat} lonlat */ moveLayerContainer: function (lonlat) { var container = this.layerContainerDiv; var resolution = this.getResolution(); var deltaX = Math.round((this.center.lon - lonlat.lon) / resolution); var deltaY = Math.round((this.center.lat - lonlat.lat) / resolution); var offsetLeft = parseInt(container.style.left); var offsetTop = parseInt(container.style.top); container.style.left = (offsetLeft + deltaX) + "px"; container.style.top = (offsetTop - deltaY) + "px"; }, CLASS_NAME: "OpenLayers.Map" }; OpenLayers.Layer = Class.create(); OpenLayers.Layer.prototype = { // str name: null, // DOMElement div: null, /** This variable is set in map.addLayer, not within the layer itself * @type OpenLayers.Map */ map: null, // str -- projection for use in WFS, WMS, etc. projection: null, /** * @param {str} name */ initialize: function(name) { if (arguments.length > 0) { this.name = name; if (this.div == null) { this.div = OpenLayers.Util.createDiv(); this.div.style.width = "100%"; this.div.style.height = "100%"; } } }, /** * Destroy is a destructor: this is to alleviate cyclic references which * the Javascript garbage cleaner can not take care of on its own. */ destroy: function() { this.map = null; }, /** * @params {OpenLayers.Bounds} bound * @params {bool} zoomChanged tells when zoom has changed, as layers have to do some init work in that case. */ moveTo: function (bound,zoomChanged) { // not implemented here return; }, /** * @return {bool} */ getVisibility: function() { return (this.div.style.display != "none"); }, /** * @param {bool} visible */ setVisibility: function(visible) { this.div.style.display = (visible) ? "block" : "none"; if ((visible) && (this.map != null)) { this.moveTo(this.map.getExtent()); } }, /** @final @type String */ CLASS_NAME: "OpenLayers.Layer" }; /** * @class */ OpenLayers.Icon = Class.create(); OpenLayers.Icon.prototype = { /** image url * @type String */ url: null, /** @type OpenLayers.Size */ size:null, /** distance in pixels to offset the image when being rendered * @type OpenLayers.Pixel */ offset: null, /** Function to calculate the offset (based on the size) * @type OpenLayers.Pixel */ calculateOffset: null, /** @type DOMElement */ imageDiv: null, /** @type OpenLayers.Pixel */ px: null, /** * @constructor * * @param {String} url * @param {OpenLayers.Size} size * @param {Function} calculateOffset */ 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(0,0); this.calculateOffset = calculateOffset; this.imageDiv = OpenLayers.Util.createAlphaImageDiv(); }, /** * @returns A fresh copy of the icon. * @type OpenLayers.Icon */ clone: function() { return new OpenLayers.Icon(this.size, this.url, this.offset); }, /** * @param {OpenLayers.Size} size */ setSize: function(size) { if (size != null) { this.size = size; } this.draw(); }, /** * @param {OpenLayers.Pixel} px * * @return A new DOM Image of this icon set at the location passed-in * @type DOMElement */ draw: function(px) { OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, null, this.size, this.url, "absolute"); this.moveTo(px); return this.imageDiv; }, /** * @param {OpenLayers.Pixel} px */ moveTo: function (px) { //if no px passed in, use stored location if (px != null) { this.px = px; } if ((this.px != null) && (this.imageDiv != null)) { if (this.calculateOffset) { this.offset = this.calculateOffset(this.size); } var offsetPx = this.px.offset(this.offset); OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv, null, offsetPx); } }, /** @final @type String */ CLASS_NAME: "OpenLayers.Icon" };/** * @class */ OpenLayers.Marker = Class.create(); OpenLayers.Marker.prototype = { /** @type OpenLayers.Icon */ icon: null, /** location of object * @type OpenLayers.LonLat */ lonlat: null, /** @type OpenLayers.Events*/ events: null, /** @type OpenLayers.Map */ map: null, /** * @constructor * * @param {OpenLayers.Icon} icon * @param {OpenLayers.LonLat lonlat */ initialize: function(lonlat, icon) { this.lonlat = lonlat; this.icon = (icon) ? icon : OpenLayers.Marker.defaultIcon(); this.events = new OpenLayers.Events(this, this.icon.imageDiv, null); }, /** * @param {OpenLayers.Pixel} px * * @return A new DOM Image with this marker´s icon set at the * location passed-in * @type DOMElement */ draw: function(px) { return this.icon.draw(px); }, /** * @param {OpenLayers.Pixel} px */ moveTo: function (px) { if ((px != null) && (this.icon != null)) { this.icon.moveTo(px); } }, /** * @param {float} inflate */ 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); } }, /** @final @type String */ CLASS_NAME: "OpenLayers.Marker" }; /** * @returns A default OpenLayers.Icon to use for a marker * @type OpenLayers.Icon */ 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); }; /** * @class */ OpenLayers.Popup = Class.create(); OpenLayers.Popup.count = 0; OpenLayers.Popup.WIDTH = 200; OpenLayers.Popup.HEIGHT = 200; OpenLayers.Popup.COLOR = "white"; OpenLayers.Popup.OPACITY = 1; OpenLayers.Popup.BORDER = "0px"; OpenLayers.Popup.prototype = { /** @type OpenLayers.Events*/ events: null, /** @type String */ id: "", /** @type OpenLayers.LonLat */ lonlat: null, /** @type DOMElement */ div: null, /** @type OpenLayers.Size*/ size: null, /** @type String */ contentHTML: "", /** @type String */ backgroundColor: "", /** @type float */ opacity: "", /** @type String */ border: "", /** this gets set in Map.js when the popup is added to the map * @type OpenLayers.Map */ map: null, /** * @constructor * * @param {String} id * @param {OpenLayers.LonLat} lonlat * @param {OpenLayers.Size} size * @param {String} contentHTML */ initialize:function(id, lonlat, size, contentHTML) { OpenLayers.Popup.count += 1; this.id = (id != null) ? id : "Popup" + OpenLayers.Popup.count; this.lonlat = lonlat; this.size = (size != null) ? size : new OpenLayers.Size( OpenLayers.Popup.WIDTH, OpenLayers.Popup.HEIGHT); if (contentHTML != null) { this.contentHTML = contentHTML; } this.backgroundColor = OpenLayers.Popup.COLOR; this.opacity = OpenLayers.Popup.OPACITY; this.border = OpenLayers.Popup.BORDER; this.div = OpenLayers.Util.createDiv(this.id + "_div", null, null, null, null, null, "hidden"); this.events = new OpenLayers.Events(this, this.div, null); }, /** */ destroy: function() { if ((this.div) && (this.div.parentNode)) { this.div.parentNode.removeChild(this.div); } this.div = null; this.map = null; }, /** * @param {OpenLayers.Pixel} px * * @returns Reference to a div that contains the drawn popup * @type DOMElement */ draw: function(px) { if (px == null) { if ((this.lonlat != null) && (this.map != null)) { px = this.map.getLayerPxFromLonLat(this.lonlat); } } this.setSize(); this.setBackgroundColor(); this.setOpacity(); this.setBorder(); this.setContentHTML(); this.moveTo(px); return this.div; }, /** * if the popup has a lonlat and its map members set, * then have it move itself to its proper position */ updatePosition: function() { if ((this.lonlat) && (this.map)) { var px = this.map.getLayerPxFromLonLat(this.lonlat); this.moveTo(px); } }, /** * @param {OpenLayers.Pixel} px */ moveTo: function(px) { if ((px != null) && (this.div != null)) { this.div.style.left = px.x + "px"; this.div.style.top = px.y + "px"; } }, /** * @returns Boolean indicating whether or not the popup is visible * @type Boolean */ visible: function() { return Element.visible(this.div); }, /** * */ toggle: function() { Element.toggle(this.div); }, /** * */ show: function() { Element.show(this.div); }, /** * */ hide: function() { Element.hide(this.div); }, /** * @param {OpenLayers.Size} size */ setSize:function(size) { if (size != undefined) { this.size = size; } if (this.div != null) { this.div.style.width = this.size.w; this.div.style.height = this.size.h; } }, /** * @param {String} color */ setBackgroundColor:function(color) { if (color != undefined) { this.backgroundColor = color; } if (this.div != null) { this.div.style.backgroundColor = this.backgroundColor; } }, /** * @param {float} opacity */ setOpacity:function(opacity) { if (opacity != undefined) { this.opacity = opacity; } if (this.div != null) { // for Mozilla and Safari this.div.style.opacity = this.opacity; // for IE this.div.style.filter = 'alpha(opacity=' + this.opacity*100 + ')'; } }, /** * @param {int} border */ setBorder:function(border) { if (border != undefined) { this.border = border; } if (this.div != null) { this.div.style.border = this.border; } }, /** * @param {String} contentHTML */ setContentHTML:function(contentHTML) { if (contentHTML != null) { this.contentHTML = contentHTML; } if (this.div != null) { this.div.innerHTML = this.contentHTML; } }, CLASS_NAME: "OpenLayers.Popup" }; /* * OpenLayers.Tile * * @class 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. */ OpenLayers.Tile = Class.create(); OpenLayers.Tile.prototype = { /** @type OpenLayers.Layer */ layer: null, /** @type String url of the request */ url:null, /** @type OpenLayers.Bounds */ bounds:null, /** @type OpenLayers.Size */ size:null, /** Top Left pixel of the tile * @type OpenLayers.Pixel */ position:null, /** * @constructor * * @param {OpenLayers.Layer} layer * @param {OpenLayers.Pixel} position * @param {OpenLayers.Bounds} bounds * @param {String} url * @param {OpenLayers.Size} size */ initialize: function(layer, position, bounds, url, size) { if (arguments.length > 0) { this.layer = layer; this.position = position; this.bounds = bounds; this.url = url; this.size = size; } }, /** nullify references to prevent circular references and memory leaks */ destroy:function() { this.layer = null; this.bounds = null; this.size = null; }, /** */ draw:function() { // HACK HACK - should we make it a standard to put this sort of warning // message in functions that are supposed to be overridden? // // ol.Log.warn(this.CLASS_NAME + ": draw() not implemented"); }, /** remove this tile from the ds */ remove:function() { }, /** * @type OpenLayers.Pixel */ getPosition: function() { return this.position; }, /** @final @type String */ CLASS_NAME: "OpenLayers.Tile" }; /** * @class */ OpenLayers.Feature = Class.create(); OpenLayers.Feature.prototype= { /** @type OpenLayers.Events */ events:null, /** @type OpenLayers.Layer */ layer: null, /** @type String */ id: null, /** @type OpenLayers.LonLat */ lonlat:null, /** @type Object */ data:null, /** @type OpenLayers.Marker */ marker: null, /** @type OpenLayers.Popup */ popup: null, /** * @constructor * * @param {OpenLayers.Layer} layer * @param {String} id * @param {OpenLayers.LonLat} lonlat * @param {Object} data */ initialize: function(layer, lonlat, data, id) { this.layer = layer; this.lonlat = lonlat; this.data = (data != null) ? data : new Object(); this.id = (id ? id : 'f' + Math.random()); }, /** * */ destroy: function() { this.layer = null; }, /** * @returns 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 * @type OpenLayers.Marker */ createMarker: function() { var marker = null; if (this.lonlat != null) { this.marker = new OpenLayers.Marker(this.lonlat, this.data.icon); } return this.marker; }, /** * */ createPopup: function() { if (this.lonlat != null) { var id = this.id + "_popup"; var anchor = (this.marker) ? this.marker.icon : null; this.popup = new OpenLayers.Popup.AnchoredBubble(id, this.lonlat, this.data.popupSize, this.data.popupContentHTML, anchor); } return this.popup; }, CLASS_NAME: "OpenLayers.Feature" }; /** * @class */ OpenLayers.Feature.WFS = Class.create(); OpenLayers.Feature.WFS.prototype = Object.extend( new OpenLayers.Feature(), { /** * @constructor * * @param {OpenLayers.Layer} layer * @param {XMLNode} xmlNode */ initialize: function(layer, xmlNode) { var newArguments = arguments; if (arguments.length > 0) { var data = this.processXMLNode(xmlNode); newArguments = new Array(layer, data.lonlat, data, data.id) } OpenLayers.Feature.prototype.initialize.apply(this, newArguments); if (arguments.length > 0) { this.createMarker(); this.layer.addMarker(this.marker); } }, /** * @param {XMLNode} xmlNode * * @returns Data Object with 'id', 'lonlat', and private properties set * @type Object */ processXMLNode: function(xmlNode) { //this should be overridden by subclasses // must return an Object with 'id' and 'lonlat' values set }, /** @final @type String */ CLASS_NAME: "OpenLayers.Feature.WFS" }); // @require: OpenLayers/Tile.js /** * @class */ OpenLayers.Tile.Image = Class.create(); OpenLayers.Tile.Image.prototype = Object.extend( new OpenLayers.Tile(), { /** @type DOMElement img */ img:null, /** * @constructor * * @param {OpenLayers.Grid} layer * @param {OpenLayers.Pixel} position * @param {OpenLayers.Bounds} bounds * @param {String} url * @param {OpenLayers.Size} size */ initialize: function(layer, position, bounds, url, size) { OpenLayers.Tile.prototype.initialize.apply(this, arguments); }, /** */ draw:function() { OpenLayers.Tile.prototype.draw.apply(this, arguments); this.img = OpenLayers.Util.createImage(null, this.position, this.size, this.url, "absolute"); }, /** @final @type String */ CLASS_NAME: "OpenLayers.Tile.Image" } ); // @require: OpenLayers/Tile.js /** * @class */ OpenLayers.Tile.WFS = Class.create(); OpenLayers.Tile.WFS.prototype = Object.extend( new OpenLayers.Tile(), { /** @type Array of Function */ handlers: null, /** @type Array(OpenLayers.Feature)*/ features: null, /** * @constructor * * @param {OpenLayers.Layer} layer * @param {OpenLayers.Pixel} position * @param {OpenLayers.Bounds} bounds * @param {String} url * @param {OpenLayers.Size} size */ initialize: function(layer, position, bounds, url, size) { OpenLayers.Tile.prototype.initialize.apply(this, arguments); this.features = new Array(); }, /** */ draw:function() { OpenLayers.Tile.prototype.draw.apply(this, arguments); this.loadFeaturesForRegion(this.requestSuccess); }, /** get the full request string from the ds and the tile params * and call the AJAX loadURL(). * * input are function pointers for what to do on success and failure. * * @param {function} success * @param {function} failure */ loadFeaturesForRegion:function(success, failure) { if (!this.loaded) { if (this.url != "") { // TODO: Hmmm, this stops multiple loads of the data when a // result isn't immediately retrieved, but it's hacky. // Do it better. this.loaded = true; // ol.Log.info("request string: " + this.url); OpenLayers.loadURL(this.url, null, this, success, failure); } } }, /** Return from AJAX request * * @param {} request */ requestSuccess:function(request) { var doc = request.responseXML; if (!doc || request.fileType!="XML") { doc = OpenLayers.parseXMLString(request.responseText); } var resultFeatures = OpenLayers.Util.getNodes(doc, "gml:featureMember"); // ol.Log.info(this.layer.name + " found " + // resultFeatures.length + " features"); //clear old featureList this.features = new Array(); for (var i=0; i < resultFeatures.length; i++) { var feature = new this.layer.featureClass(this.layer, resultFeatures[i]); this.features.append(feature); } }, /** @final @type String */ CLASS_NAME: "OpenLayers.Tile.WFS" } ); // @require: OpenLayers/Layer.js OpenLayers.Layer.Google = Class.create(); OpenLayers.Layer.Google.prototype = Object.extend( new OpenLayers.Layer(), { // gmap stores the Google Map element gmap:null, initialize: function(name) { OpenLayers.Layer.prototype.initialize.apply(this, [name]); this.gmap = new GMap2(this.div); }, moveTo: function() { center = this.map.getCenter(); this.gmap.setCenter( new GLatLng(center.lat, center.lon), this.map.getZoom() ); } }); // @require: OpenLayers/Layer.js // @require: OpenLayers/Util.js OpenLayers.Layer.Grid = Class.create(); OpenLayers.Layer.Grid.TILE_WIDTH = 256; OpenLayers.Layer.Grid.TILE_HEIGHT = 256; OpenLayers.Layer.Grid.prototype = Object.extend( new OpenLayers.Layer(), { // str: url url: null, // hash: params params: null, // tileSize: OpenLayers.Size tileSize: null, // grid: Array(Array()) // this is an array of rows, each row is an array of tiles grid: null, /** * @param {str} name * @param {str} url * @param {hash} params */ initialize: function(name, url, params) { var newArguments = arguments; if (arguments.length > 0) { newArguments = [name]; } OpenLayers.Layer.prototype.initialize.apply(this, newArguments); this.url = url; this.params = params; this.tileSize = new OpenLayers.Size(OpenLayers.Layer.Grid.TILE_WIDTH, OpenLayers.Layer.Grid.TILE_HEIGHT); }, setTileSize: function (size) { this.tileSize = size.copyOf(); }, /** * moveTo * moveTo is a function called whenever the map is moved. All the moving * of actual 'tiles' is done by the map, but moveTo's role is to accept * a bounds and make sure the data that that bounds requires is pre-loaded. * @param {OpenLayers.Bounds} */ moveTo:function(bounds,zoomChanged) { if (!this.getVisibility()) { if (zoomChanged) { this.grid = null; } return; } if (!this.grid || zoomChanged) { this._initTiles(); } else { var i = 0; while (this.getGridBounds().bottom > bounds.bottom) { this.insertRow(false); } while (this.getGridBounds().left > bounds.left) { this.insertColumn(true); } while (this.getGridBounds().top < bounds.top) { this.insertRow(true); } while (this.getGridBounds().right < bounds.right) { this.insertColumn(false); } } }, getGridBounds:function() { var topLeftTile = this.grid[0][0]; var bottomRightTile = this.grid[this.grid.length-1][this.grid[0].length-1]; return new OpenLayers.Bounds(topLeftTile.bounds.left, bottomRightTile.bounds.bottom, bottomRightTile.bounds.right, topLeftTile.bounds.top); }, /** */ _initTiles:function() { //first of all, clear out the main div this.div.innerHTML = ""; //now clear out the old grid and start a new one this.clearGrid(); this.grid = new Array(); var viewSize = this.map.getSize(); var bounds = this.map.getExtent(); var extent = this.map.getFullExtent(); var resolution = this.map.getResolution(); var tilelon = resolution*this.tileSize.w; var tilelat = resolution*this.tileSize.h; var offsetlon = bounds.left - extent.left; var tilecol = Math.floor(offsetlon/tilelon); var tilecolremain = offsetlon/tilelon - tilecol; var tileoffsetx = -tilecolremain * this.tileSize.w; var tileoffsetlon = extent.left + tilecol * tilelon; var offsetlat = bounds.top - (extent.bottom + tilelat); var tilerow = Math.ceil(offsetlat/tilelat); var tilerowremain = tilerow - offsetlat/tilelat; var tileoffsety = -tilerowremain * this.tileSize.h; var tileoffsetlat = extent.bottom + tilerow * tilelat; tileoffsetx = Math.round(tileoffsetx); // heaven help us tileoffsety = Math.round(tileoffsety); this.origin = new OpenLayers.Pixel(tileoffsetx,tileoffsety); var startX = tileoffsetx; var startLon = tileoffsetlon; do { var row = new Array(); this.grid.append(row); tileoffsetlon = startLon; tileoffsetx = startX; do { var tileBounds = new OpenLayers.Bounds(tileoffsetlon, tileoffsetlat, tileoffsetlon+tilelon, tileoffsetlat+tilelat); var tile = this.addTile(tileBounds, new OpenLayers.Pixel(tileoffsetx, tileoffsety) ); row.append(tile); tileoffsetlon += tilelon; tileoffsetx += this.tileSize.w; } while (tileoffsetlon < bounds.right) tileoffsetlat -= tilelat; tileoffsety += this.tileSize.h; } while(tileoffsetlat > bounds.bottom - tilelat) }, /** * @param {bool} prepend - if true, prepend to beginning. * if false, then append to end */ insertRow:function(prepend) { var modelRowIndex = (prepend) ? 0 : (this.grid.length - 1); var modelRow = this.grid[modelRowIndex]; var newRow = new Array(); var resolution = this.map.getResolution(); var deltaY = (prepend) ? -this.tileSize.h : this.tileSize.h; var deltaLat = resolution * -deltaY; for (var i=0; i < modelRow.length; i++) { var modelTile = modelRow[i]; var bounds = modelTile.bounds.copyOf(); var position = modelTile.position.copyOf(); bounds.bottom = bounds.bottom + deltaLat; bounds.top = bounds.top + deltaLat; position.y = position.y + deltaY; var newTile = this.addTile(bounds, position); newRow.append(newTile); } if (newRow.length>0){ if (prepend) { this.grid.prepend(newRow); } else { this.grid.append(newRow); } } }, /** * @param {bool} prepend - if true, prepend to beginning. * if false, then append to end */ insertColumn:function(prepend) { var modelCellIndex; var deltaX = (prepend) ? -this.tileSize.w : this.tileSize.w; var resolution = this.map.getResolution(); var deltaLon = resolution * deltaX; for (var i=0; i 0) { var row = this.grid[0]; while(row.length > 0) { var tile = row[0]; tile.destroy(); row.remove(tile); } this.grid.remove(row); } } } }); // @require: OpenLayers/Layer.js /** * @class */ OpenLayers.Layer.Markers = Class.create(); OpenLayers.Layer.Markers.prototype = Object.extend( new OpenLayers.Layer(), { /** internal marker list * @type Array(OpenLayers.Marker) */ markers: null, /** * @constructor * * @param {String} name */ initialize: function(name) { OpenLayers.Layer.prototype.initialize.apply(this, arguments); this.markers = new Array(); }, /** * @param {OpenLayers.Bounds} bounds * @param {Boolean} zoomChanged */ moveTo: function(bounds, zoomChanged) { if (zoomChanged) { this.redraw(); } }, /** * @param {OpenLayers.Marker} marker */ addMarker: function(marker) { this.markers.append(marker); if (this.map && this.map.getExtent()) { this.drawMarker(marker); } }, /** clear all the marker div's from the layer and then redraw all of them. * Use the map to recalculate new placement of markers. */ redraw: function() { for(i=0; i < this.markers.length; i++) { this.drawMarker(this.markers[i]); } }, /** Calculate the screen pixel location for the marker, create it, and * add it to the layer's div * * @private * * @param {OpenLayers.Marker} marker */ drawMarker: function(marker) { var px = this.map.getLayerPxFromLonLat(marker.lonlat); var markerImg = marker.draw(px); if (!marker.drawn) { this.div.appendChild(markerImg); marker.drawn = true; } }, /** @final @type String */ CLASS_NAME: "OpenLayers.Layer.Markers" }); // @require: OpenLayers/Layer/Markers.js /** * @class */ OpenLayers.Layer.Text = Class.create(); OpenLayers.Layer.Text.prototype = Object.extend( new OpenLayers.Layer.Markers(), { /** store url of text file * @type str */ location:null, /** @type OpenLayers.Feature */ selectedFeature: null, /** * @constructor * * @param {String} name * @param {String} location */ initialize: function(name, location) { OpenLayers.Layer.Markers.prototype.initialize.apply(this, [name]); this.location = location; new Ajax.Request(location, { method: 'get', onComplete:this.parseData.bind(this) } ); }, /** * @param {?} ajaxRequest */ parseData: function(ajaxRequest) { var text = ajaxRequest.responseText; var lines = text.split('\n'); var columns; // length - 1 to allow for trailing new line for (var lcv = 0; lcv < (lines.length - 1); lcv++) { var currLine = lines[lcv].replace(/^\s*/,'').replace(/\s*$/,''); if (currLine.charAt(0) != '#') { /* not a comment */ if (!columns) { //First line is columns columns = currLine.split('\t'); } else { var vals = currLine.split('\t'); var location = new OpenLayers.LonLat(0,0); var title; var url; var icon, iconSize, iconOffset; var set = false; for (var valIndex = 0; valIndex < vals.length; valIndex++) { if (vals[valIndex]) { if (columns[valIndex] == 'point') { var coords = vals[valIndex].split(','); location.lat = parseFloat(coords[0]); location.lon = parseFloat(coords[1]); set = true; } else if (columns[valIndex] == 'lat') { location.lat = parseFloat(vals[valIndex]); set = true; } else if (columns[valIndex] == 'lon') { location.lon = parseFloat(vals[valIndex]); set = true; } else if (columns[valIndex] == 'title') title = vals[valIndex]; else if (columns[valIndex] == 'image' || columns[valIndex] == 'icon') url = vals[valIndex]; else if (columns[valIndex] == 'iconSize') { var size = vals[valIndex].split(','); iconSize = new OpenLayers.Size(parseFloat(size[0]), parseFloat(size[1])); } else if (columns[valIndex] == 'iconOffset') { var offset = vals[valIndex].split(','); iconOffset = new OpenLayers.Pixel(parseFloat(offset[0]), parseFloat(offset[1])); } else if (columns[valIndex] == 'title') { title = vals[valIndex]; } else if (columns[valIndex] == 'description') { description = vals[valIndex]; } } } if (set) { var data = new Object(); if (url != null) { data.icon = new OpenLayers.Icon(url, iconSize, iconOffset); } else { data.icon = OpenLayers.Marker.defaultIcon(); //allows for the case where the image url is not // specified but the size is. use a default icon // but change the size if (iconSize != null) { data.icon.setSize(iconSize); } } if ((title != null) && (description != null)) { data['popupContentHTML'] = '

'+title+'

'+description+'

'; } var feature = new OpenLayers.Feature(this, location, data); var marker = feature.createMarker(); marker.events.register('click', feature, this.markerClick); this.addMarker(marker); } } } } }, /** * @param {Event} evt */ markerClick: function(evt) { sameMarkerClicked = (this == this.layer.selectedFeature); this.layer.selectedFeature = (!sameMarkerClicked) ? this : null; for(var i=0; i < this.layer.map.popups.length; i++) { this.layer.map.removePopup(this.layer.map.popups[i]); } if (!sameMarkerClicked) { this.layer.map.addPopup(this.createPopup()); } Event.stop(evt); } }); // @require: OpenLayers/Layer/Grid.js /** * @class */ OpenLayers.Layer.WMS = Class.create(); OpenLayers.Layer.WMS.prototype = Object.extend( new OpenLayers.Layer.Grid(), { /** @final @type hash */ DEFAULT_PARAMS: { service: "WMS", version: "1.1.1", request: "GetMap", styles: "", exceptions: "application/vnd.ogc.se_inimage", format: "image/jpeg" }, /** * @constructor * * @param {str} name * @param {str} url * @param {hash} params */ initialize: function(name, url, params) { OpenLayers.Layer.Grid.prototype.initialize.apply(this, arguments); OpenLayers.Util.applyDefaults(this.params, this.DEFAULT_PARAMS); }, /** * @param {String} name * @param {hash} params * * @returns A clone of this OpenLayers.Layer.WMS, with the passed-in * parameters merged in. * @type OpenLayers.Layer.WMS */ clone: function (name, params) { var mergedParams = {}; Object.extend(mergedParams, this.params); Object.extend(mergedParams, params); var obj = new OpenLayers.Layer.WMS(name, this.url, mergedParams); obj.setTileSize(this.tileSize); return obj; }, /** * addTile creates a tile, initializes it (via 'draw' in this case), and * adds it to the layer div. * * @param {OpenLayers.Bounds} bounds * * @returns The added OpenLayers.Tile.Image * @type OpenLayers.Tile.Image */ addTile:function(bounds,position) { url = this.getFullRequestString( {bbox:bounds.toBBOX(), width:this.tileSize.w, height:this.tileSize.h}); var tile = new OpenLayers.Tile.Image(this, position, bounds, url, this.tileSize); tile.draw(); this.div.appendChild(tile.img); return tile; }, /** @final @type String */ CLASS_NAME: "OpenLayers.Layer.WMS" }); // @require: OpenLayers/Layer/Grid.js // @require: OpenLayers/Layer/Markers.js /** * @class */ OpenLayers.Layer.WFS = Class.create(); OpenLayers.Layer.WFS.prototype = Object.extend(new OpenLayers.Layer.Grid(), Object.extend(new OpenLayers.Layer.Markers(), { /** @type Object */ featureClass: null, /** @final @type hash */ DEFAULT_PARAMS: { service: "WFS", version: "1.0.0", request: "GetFeature", typename: "docpoint" }, /** * @constructor * * @param {str} name * @param {str} url * @param {hash} params * @param {Object} featureClass */ initialize: function(name, url, params, featureClass) { this.featureClass = featureClass; var newArguments = new Array(); if (arguments.length > 0) { newArguments.push(name, url, params); } OpenLayers.Layer.Grid.prototype.initialize.apply(this, newArguments); OpenLayers.Layer.Markers.prototype.initialize.apply(this, newArguments); if (arguments.length > 0) { OpenLayers.Util.applyDefaults(this.params, this.DEFAULT_PARAMS); } }, /** * @param {OpenLayers.Bounds} bounds * @param {Boolean} zoomChanged */ moveTo: function(bounds, zoomChanged) { OpenLayers.Layer.Grid.prototype.moveTo.apply(this, arguments); OpenLayers.Layer.Markers.prototype.moveTo.apply(this, arguments); }, /** * @param {String} name * @param {hash} params * * @returns A clone of this OpenLayers.Layer.WMS, with the passed-in * parameters merged in. * @type OpenLayers.Layer.WMS */ clone: function (name, params) { var mergedParams = {} Object.extend(mergedParams, this.params); Object.extend(mergedParams, params); var obj = new OpenLayers.Layer.WFS(name, this.url, mergedParams); obj.setTileSize(this.tileSize); return obj; }, /** * addTile creates a tile, initializes it (via 'draw' in this case), and * adds it to the layer div. * * @param {OpenLayers.Bounds} bounds * * @returns The added OpenLayers.Tile.WFS * @type OpenLayers.Tile.WFS */ addTile:function(bounds, position) { url = this.getFullRequestString( { bbox:bounds.toBBOX() }); var tile = new OpenLayers.Tile.WFS(this, position, bounds, url, this.tileSize); tile.draw(); return tile; }, /** @final @type String */ CLASS_NAME: "OpenLayers.Layer.WFS" } ) ); // @require: OpenLayers/Popup.js /** * @class */ OpenLayers.Popup.Anchored = Class.create(); OpenLayers.Popup.Anchored.prototype = Object.extend( new OpenLayers.Popup(), { /** "lr", "ll", "tr", "tl" - relative position of the popup. * @type String */ relativePosition: null, /** Object which must have expose a 'size' (OpenLayers.Size) and * 'offset' (OpenLayers.Pixel) * @type Object */ anchor: null, /** * @constructor * * @param {String} id * @param {OpenLayers.LonLat} lonlat * @param {OpenLayers.Size} size * @param {String} contentHTML * @param {Object} anchor Object which must expose a * - 'size' (OpenLayers.Size) and * - 'offset' (OpenLayers.Pixel) * (this is generally an OpenLayers.Icon) */ initialize:function(id, lonlat, size, contentHTML, anchor) { var newArguments = new Array(id, lonlat, size, contentHTML); OpenLayers.Popup.prototype.initialize.apply(this, newArguments); this.anchor = (anchor != null) ? anchor : { size: new OpenLayers.Size(0,0), offset: new OpenLayers.Pixel(0,0)}; }, /** * @param {OpenLayers.Pixel} px * * @returns Reference to a div that contains the drawn popup * @type DOMElement */ draw: function(px) { if (px == null) { if ((this.lonlat != null) && (this.map != null)) { px = this.map.getLayerPxFromLonLat(this.lonlat); } } //calculate relative position this.relativePosition = this.calculateRelativePosition(px); return OpenLayers.Popup.prototype.draw.apply(this, arguments); }, /** * @private * * @param {OpenLayers.Pixel} px * * @returns The relative position ("br" "tr" "tl "bl") at which the popup * should be placed * @type String */ calculateRelativePosition:function(px) { var lonlat = this.map.getLonLatFromLayerPx(px); var extent = this.map.getExtent(); var quadrant = extent.determineQuadrant(lonlat); return OpenLayers.Bounds.oppositeQuadrant(quadrant); }, /** * @param {OpenLayers.Pixel} px */ moveTo: function(px) { var newPx = this.calculateNewPx(px); var newArguments = new Array(newPx); OpenLayers.Popup.prototype.moveTo.apply(this, newArguments); }, /** * @param {OpenLayers.Size} size */ setSize:function(size) { OpenLayers.Popup.prototype.setSize.apply(this, arguments); if ((this.lonlat) && (this.map)) { var px = this.map.getLayerPxFromLonLat(this.lonlat); this.moveTo(px); } }, /** * @private * * @param {OpenLayers.Pixel} px * * @returns The the new px position of the popup on the screen * relative to the passed-in px * @type OpenLayers.Pixel */ calculateNewPx:function(px) { var newPx = px.offset(this.anchor.offset); var top = (this.relativePosition.charAt(0) == 't'); newPx.y += (top) ? -this.size.h : this.anchor.size.h; var left = (this.relativePosition.charAt(1) == 'l'); newPx.x += (left) ? -this.size.w : this.anchor.size.w; return newPx; }, CLASS_NAME: "OpenLayers.Popup.Anchored" }); // @require: OpenLayers/Popup/Anchored.js /** * @class */ OpenLayers.Popup.AnchoredBubble = Class.create(); //Border space for the rico corners OpenLayers.Popup.AnchoredBubble.CORNER_SIZE = 5; OpenLayers.Popup.AnchoredBubble.prototype = Object.extend( new OpenLayers.Popup.Anchored(), { /** @type DOMElement */ contentDiv:null, /** * @constructor * * @param {String} id * @param {OpenLayers.LonLat} lonlat * @param {OpenLayers.Size} size * @param {String} contentHTML * @param {Object} anchor Object which must expose a * - 'size' (OpenLayers.Size) and * - 'offset' (OpenLayers.Pixel) * (this is generally an OpenLayers.Icon) */ initialize:function(id, lonlat, size, contentHTML, anchor) { OpenLayers.Popup.Anchored.prototype.initialize.apply(this, arguments); }, /** * @param {OpenLayers.Pixel} px * * @returns Reference to a div that contains the drawn popup * @type DOMElement */ draw: function(px) { OpenLayers.Popup.Anchored.prototype.draw.apply(this, arguments); // make the content Div var contentSize = this.size.copyOf(); contentSize.h -= (2 * OpenLayers.Popup.AnchoredBubble.CORNER_SIZE); var id = this.div.id + "-contentDiv"; this.contentDiv = OpenLayers.Util.createDiv(id, null, contentSize, null, "relative", null, "auto"); this.div.appendChild(this.contentDiv); this.setContentHTML(); this.setRicoCorners(true); //set the popup color and opacity this.setBackgroundColor(); this.setOpacity(); return this.div; }, /** * @param {OpenLayers.Size} size */ setSize:function(size) { OpenLayers.Popup.Anchored.prototype.setSize.apply(this, arguments); if (this.contentDiv != null) { var contentSize = this.size.copyOf(); contentSize.h -= (2 * OpenLayers.Popup.AnchoredBubble.CORNER_SIZE); this.contentDiv.style.height = contentSize.h + "px"; //size has changed - must redo corners this.setRicoCorners(false); } }, /** * @param {String} color */ setBackgroundColor:function(color) { if (color != undefined) { this.backgroundColor = color; } if (this.div != null) { if (this.contentDiv != null) { this.div.style.background = "transparent"; Rico.Corner.changeColor(this.contentDiv, this.backgroundColor); } } }, /** * @param {float} opacity */ setOpacity:function(opacity) { if (opacity != undefined) { this.opacity = opacity; } if (this.div != null) { if (this.contentDiv != null) { Rico.Corner.changeOpacity(this.contentDiv, this.opacity); } } }, /** Bubble Popups can not have a border * * @param {int} border */ setBorder:function(border) { this.border = 0; }, /** * @param {String} contentHTML */ setContentHTML:function(contentHTML) { if (contentHTML != null) { this.contentHTML = contentHTML; } if (this.contentDiv != null) { this.contentDiv.innerHTML = this.contentHTML; } }, /** * @private * * @param {Boolean} firstTime Is this the first time the corners are being * rounded? * * update the rico corners according to the popup's * current relative postion */ setRicoCorners:function(firstTime) { var corners = this.getCornersToRound(this.relativePosition); var options = {corners: corners, color: this.backgroundColor, bgColor: "transparent", blend: false}; if (firstTime) { Rico.Corner.round(this.div, options); } else { Rico.Corner.reRound(this.contentDiv, options); //set the popup color and opacity this.setBackgroundColor(); this.setOpacity(); } }, /** * @private * * @returns The proper corners string ("tr tl bl br") for rico * to round * @type String */ getCornersToRound:function() { var corners = ['tl', 'tr', 'bl', 'br']; //we want to round all the corners _except_ the opposite one. var corner = OpenLayers.Bounds.oppositeQuadrant(this.relativePosition); corners.remove(corner); return corners.join(" "); }, CLASS_NAME: "OpenLayers.Popup.AnchoredBubble" }); /** * @class */ OpenLayers.Control = Class.create(); OpenLayers.Control.prototype = { /** this gets set in the addControl() function in OpenLayers.Map * @type OpenLayers.Map */ map: null, /** @type DOMElement */ div: null, /** @type OpenLayers.Pixel */ position: null, /** * @constructor */ initialize: function (options) { Object.extend(this, options); }, /** * @param {OpenLayers.Pixel} px * * @returns A reference to the DIV DOMElement containing the control * @type DOMElement */ draw: function (px) { if (this.div == null) { this.div = OpenLayers.Util.createDiv(); } if (px != null) { this.position = px.copyOf(); } this.moveTo(this.position); return this.div; }, /** * @param {OpenLayers.Pixel} px */ moveTo: function (px) { if ((px != null) && (this.div != null)) { this.div.style.left = px.x + "px"; this.div.style.top = px.x + "px"; } }, /** */ destroy: function () { // eliminate circular references this.map = null; }, /** @final @type String */ CLASS_NAME: "OpenLayers.Control" }; // @require: OpenLayers/Control.js OpenLayers.Control.MouseDefaults = Class.create(); OpenLayers.Control.MouseDefaults.prototype = Object.extend( new OpenLayers.Control(), { initialize: function() { OpenLayers.Control.prototype.initialize.apply(this, arguments); }, draw: function() { this.map.events.register( "dblclick", this, this.defaultDblClick ); this.map.events.register( "mousedown", this, this.defaultMouseDown ); this.map.events.register( "mouseup", this, this.defaultMouseUp ); this.map.events.register( "mousemove", this, this.defaultMouseMove ); this.map.events.register( "mouseout", this, this.defaultMouseOut ); }, /** * @param {Event} evt */ defaultDblClick: function (evt) { var newCenter = this.map.getLonLatFromScreenPx( evt.xy ); this.map.setCenter(newCenter, this.map.zoom + 1); }, /** * @param {Event} evt */ defaultMouseDown: function (evt) { this.mouseDragStart = evt.xy.copyOf(); if (evt.shiftKey) { this.map.div.style.cursor = "crosshair"; this.zoomBox = OpenLayers.Util.createDiv('zoomBox', this.mouseDragStart, null, null, "absolute", "2px solid red"); this.zoomBox.style.backgroundColor = "white"; this.zoomBox.style.filter = "alpha(opacity=50)"; // IE this.zoomBox.style.opacity = "0.50"; this.zoomBox.style.zIndex = this.map.Z_INDEX_BASE["Popup"] - 1; this.map.viewPortDiv.appendChild(this.zoomBox); } else { this.map.div.style.cursor = "move"; } Event.stop(evt); }, /** * @param {Event} evt */ defaultMouseMove: function (evt) { if (this.mouseDragStart != null) { if (this.zoomBox) { var deltaX = Math.abs(this.mouseDragStart.x - evt.xy.x); var deltaY = Math.abs(this.mouseDragStart.y - evt.xy.y); this.zoomBox.style.width = deltaX+"px"; this.zoomBox.style.height = deltaY+"px"; if (evt.xy.x < this.mouseDragStart.x) { this.zoomBox.style.left = evt.xy.x+"px"; } if (evt.xy.y < this.mouseDragStart.y) { this.zoomBox.style.top = evt.xy.y+"px"; } } else { var deltaX = this.mouseDragStart.x - evt.xy.x; var deltaY = this.mouseDragStart.y - evt.xy.y; var size = this.map.getSize(); var newXY = new OpenLayers.Pixel(size.w / 2 + deltaX, size.h / 2 + deltaY); var newCenter = this.map.getLonLatFromScreenPx( newXY ); this.map.setCenter(newCenter); this.mouseDragStart = evt.xy.copyOf(); } } }, /** * @param {Event} evt */ defaultMouseUp: function (evt) { if (this.zoomBox) { var start = this.map.getLonLatFromScreenPx( this.mouseDragStart ); var end = this.map.getLonLatFromScreenPx( evt.xy ); var top = Math.max(start.lat, end.lat); var bottom = Math.min(start.lat, end.lat); var left = Math.min(start.lon, end.lon); var right = Math.max(start.lon, end.lon); var bounds = new OpenLayers.Bounds(left, bottom, right, top); var zoom = this.map.getZoomForExtent(bounds); this.map.setCenter(new OpenLayers.LonLat( (start.lon + end.lon) / 2, (start.lat + end.lat) / 2 ), zoom); this.map.viewPortDiv.removeChild(document.getElementById("zoomBox")); this.zoomBox = null; } this.mouseDragStart = null; this.map.div.style.cursor = "default"; }, defaultMouseOut: function (evt) { if (this.mouseDragStart != null && OpenLayers.Util.mouseLeft(evt, this.map.div)) { this.defaultMouseUp(evt); } } }); // @require: OpenLayers/Control.js OpenLayers.Control.KeyboardDefaults = Class.create(); OpenLayers.Control.KeyboardDefaults.prototype = Object.extend( new OpenLayers.Control(), { initialize: function() { OpenLayers.Control.prototype.initialize.apply(this, arguments); }, draw: function() { Event.observe(document, 'keypress', this.defaultKeyDown.bind(this.map)); }, /** * @param {Event} evt */ defaultKeyDown: function (evt) { var i = 0; switch(evt.keyCode) { case Event.KEY_LEFT: var resolution = this.getResolution(); var center = this.getCenter(); this.setCenter( new OpenLayers.LonLat(center.lon - (resolution * 50), center.lat) ); Event.stop(evt); break; case Event.KEY_RIGHT: var resolution = this.getResolution(); var center = this.getCenter(); this.setCenter( new OpenLayers.LonLat(center.lon + (resolution * 50), center.lat) ); Event.stop(evt); break; case Event.KEY_UP: var resolution = this.getResolution(); var center = this.getCenter(); this.setCenter( new OpenLayers.LonLat(center.lon, center.lat + (resolution * 50)) ); Event.stop(evt); break; case Event.KEY_DOWN: var resolution = this.getResolution(); var center = this.getCenter(); this.setCenter( new OpenLayers.LonLat(center.lon, center.lat - (resolution * 50)) ); Event.stop(evt); break; } } }); // @require: OpenLayers/Control.js // // default zoom/pan controls // OpenLayers.Control.PanZoom = Class.create(); OpenLayers.Control.PanZoom.X = 4; OpenLayers.Control.PanZoom.Y = 4; OpenLayers.Control.PanZoom.prototype = Object.extend( new OpenLayers.Control(), { /** @type Array(...) */ buttons: null, initialize: function() { OpenLayers.Control.prototype.initialize.apply(this, arguments); this.position = new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X, OpenLayers.Control.PanZoom.Y); }, /** * @param {OpenLayers.Pixel} px */ draw: function(px) { // initialize our internal div OpenLayers.Control.prototype.draw.apply(this, arguments); px = this.position; // place the controls this.buttons = new Array(); var sz = new OpenLayers.Size(18,18); var centered = new OpenLayers.Pixel(px.x+sz.w/2, px.y); this._addButton("panup", "north-mini.png", centered, sz); px.y = centered.y+sz.h; this._addButton("panleft", "west-mini.png", px, sz); this._addButton("panright", "east-mini.png", px.add(sz.w, 0), sz); this._addButton("pandown", "south-mini.png", centered.add(0, sz.h*2), sz); this._addButton("zoomin", "zoom-plus-mini.png", centered.add(0, sz.h*3+5), sz); this._addButton("zoomworld", "zoom-world-mini.png", centered.add(0, sz.h*4+5), sz); this._addButton("zoomout", "zoom-minus-mini.png", centered.add(0, sz.h*5+5), sz); return this.div; }, _addButton:function(id, img, xy, sz) { var imgLocation = OpenLayers.Util.getImagesLocation() + img; // var btn = new ol.AlphaImage("_"+id, imgLocation, xy, sz); var btn = OpenLayers.Util.createAlphaImageDiv( "OpenLayers_Control_PanZoom_" + id, xy, sz, imgLocation, "absolute"); //we want to add the outer div this.div.appendChild(btn); btn.onmousedown = this.buttonDown.bindAsEventListener(btn); btn.ondblclick = this.doubleClick.bindAsEventListener(btn); btn.action = id; btn.map = this.map; //we want to remember/reference the outer div this.buttons.push(btn); return btn; }, doubleClick: function (evt) { Event.stop(evt); }, buttonDown: function (evt) { switch (this.action) { case "panup": var resolution = this.map.getResolution(); var center = this.map.getCenter(); this.map.setCenter( new OpenLayers.LonLat(center.lon, center.lat + (resolution * 50)) ); break; case "pandown": var resolution = this.map.getResolution(); var center = this.map.getCenter(); this.map.setCenter( new OpenLayers.LonLat(center.lon, center.lat - (resolution * 50)) ); break; case "panleft": var resolution = this.map.getResolution(); var center = this.map.getCenter(); this.map.setCenter( new OpenLayers.LonLat(center.lon - (resolution * 50), center.lat) ); break; case "panright": var resolution = this.map.getResolution(); var center = this.map.getCenter(); this.map.setCenter( new OpenLayers.LonLat(center.lon + (resolution * 50), center.lat) ); break; case "zoomin": this.map.zoomIn(); break; case "zoomout": this.map.zoomOut(); break; case "zoomworld": this.map.zoomExtent(); break; } Event.stop(evt); }, destroy: function() { OpenLayers.Control.prototype.destroy.apply(this, arguments); for(i=0; i 0 && (evt.clientY - offsets[1]) < parseInt(this.zoombarDiv.style.height) - 2) { var newTop = parseInt(this.slider.style.top) - deltaY; this.slider.style.top = newTop+"px"; } this.mouseDragStart = evt.xy.copyOf(); } Event.stop(evt); }, /* * @param evt * Perform cleanup when a mouseup event is received -- discover new zoom level * and switch to it. */ zoomBarUp:function(evt) { if (this.zoomStart) { this.div.style.cursor="default"; this.map.events.remove("mousemove"); this.map.events.remove("mouseup"); var deltaY = this.zoomStart.y - evt.xy.y this.map.zoomTo(this.map.zoom + Math.round(deltaY/this.zoomStopHeight)); this.moveZoomBar(); this.mouseDragStart = null; Event.stop(evt); } }, /* * Change the location of the slider to match the current zoom level. */ moveZoomBar:function() { var newTop = (this.map.getZoomLevels() - this.map.getZoom()) * this.zoomStopHeight + this.startTop + 1; this.slider.style.top = newTop + "px"; }, CLASS_NAME: "OpenLayers.Control.PanZoomBar" }); // @require: OpenLayers/Control.js /** * @class */ OpenLayers.Control.LayerSwitcher = Class.create(); /** color used in the UI to show a layer is active/displayed * * @final * @type String */ OpenLayers.Control.LayerSwitcher.ACTIVE_COLOR = "darkblue"; /** color used in the UI to show a layer is deactivated/hidden * * @final * @type String */ OpenLayers.Control.LayerSwitcher.NONACTIVE_COLOR = "lightblue"; OpenLayers.Control.LayerSwitcher.prototype = Object.extend( new OpenLayers.Control(), { /** @type String */ activeColor: "", /** @type String */ nonActiveColor: "", /** @type String */ mode: "checkbox", /** * @constructor */ initialize: function(options) { this.activeColor = OpenLayers.Control.LayerSwitcher.ACTIVE_COLOR; this.nonActiveColor = OpenLayers.Control.LayerSwitcher.NONACTIVE_COLOR; this.backdrops = []; OpenLayers.Control.prototype.initialize.apply(this, arguments); }, /** * @returns A reference to the DIV DOMElement containing the switcher tabs * @type DOMElement */ draw: function() { // initialize our internal div OpenLayers.Control.prototype.draw.apply(this); this.div.style.position = "absolute"; this.div.style.top = "10px"; this.div.style.right = "0px"; this.div.style.left = ""; this.div.style.fontFamily = "sans-serif"; this.div.style.color = "white"; this.div.style.fontWeight = "bold"; this.div.style.marginTop = "3px"; this.div.style.marginLeft = "3px"; this.div.style.marginBottom = "3px"; this.div.style.fontSize="smaller"; this.div.style.width = "10em"; this.map.events.register("addlayer", this, this.redraw); return this.redraw(); }, /** * @returns A reference to the DIV DOMElement containing the switcher tabs * @type DOMElement */ redraw: function() { //clear out previous incarnation of LayerSwitcher tabs this.div.innerHTML = ""; var visible = false; for( var i = 0; i < this.map.layers.length; i++) { if (visible && this.mode == "radio") { this.map.layers[i].setVisibility(false); } else { visible = this.map.layers[i].getVisibility(); } this.addTab(this.map.layers[i]); } return this.div; }, /** * @param {event} evt */ singleClick: function(evt) { var div = Event.element(evt); var layer = div.layer; if (this.mode == "radio") { for(var i=0; i < this.backdrops.length; i++) { this.setTabActivation(this.backdrops[i], false); this.backdrops[i].layer.setVisibility(false); } this.setTabActivation(div, true); layer.setVisibility(true); } else { var visible = layer.getVisibility(); this.setTabActivation(div, !visible); layer.setVisibility(!visible); } Event.stop(evt); }, /** * @param {event} evt */ doubleClick: function(evt) { Event.stop(evt); }, /** * @private * * @param {OpenLayers.Layer} layer */ addTab: function(layer) { // Outer DIV - for Rico Corners // var backdropLabelOuter = document.createElement('div'); backdropLabelOuter.id = "LayerSwitcher_" + layer.name + "_Tab"; backdropLabelOuter.style.marginTop = "4px"; backdropLabelOuter.style.marginBottom = "4px"; // Inner Label - for Rico Corners // var backdropLabel = document.createElement('p'); backdropLabel.innerHTML = layer.name; backdropLabel.style.marginTop = "0px"; backdropLabel.style.marginBottom = "0px"; backdropLabel.style.paddingLeft = "10px"; backdropLabel.style.paddingRight = "10px"; // add reference to layer onto the div for use in event handlers backdropLabel.layer = layer; // set event handlers backdropLabel.ondblclick = this.doubleClick.bindAsEventListener(this); backdropLabel.onmousedown = this.singleClick.bindAsEventListener(this); // add label to div backdropLabelOuter.appendChild(backdropLabel); this.backdrops.append(backdropLabel); // add div to main LayerSwitcher Div this.div.appendChild(backdropLabelOuter); Rico.Corner.round(backdropLabelOuter, {corners: "tl bl", bgColor: "transparent", color: "white", blend: false}); this.setTabActivation(backdropLabel, layer.getVisibility()); }, /** * @private * * @param {DOMElement} div * @param {Boolean} activate */ setTabActivation:function(div, activate) { var color = (activate) ? this.activeColor : this.nonActiveColor; Rico.Corner.changeColor(div, color); }, /** @final @type String */ CLASS_NAME: "OpenLayers.Control.LayerSwitcher" });