]> git.openstreetmap.org Git - rails.git/commitdiff
Merge branch 'master' into openstreetbugs
authorTom Hughes <tom@compton.nu>
Sat, 10 Mar 2012 15:30:25 +0000 (15:30 +0000)
committerTom Hughes <tom@compton.nu>
Sat, 10 Mar 2012 15:30:25 +0000 (15:30 +0000)
Conflicts:
config/routes.rb
db/structure.sql

59 files changed:
Gemfile
Gemfile.lock
app/assets/images/closed_note_marker.png [new file with mode: 0644]
app/assets/images/new_note_marker.png [new file with mode: 0644]
app/assets/images/open_note_marker.png [new file with mode: 0644]
app/assets/javascripts/notes.js [new file with mode: 0644]
app/assets/stylesheets/common.css.scss
app/assets/stylesheets/large.css
app/assets/stylesheets/notes.css [new file with mode: 0644]
app/controllers/browse_controller.rb
app/controllers/note_controller.rb [new file with mode: 0644]
app/helpers/application_helper.rb
app/models/note.rb [new file with mode: 0644]
app/models/note_comment.rb [new file with mode: 0644]
app/models/notifier.rb
app/models/user.rb
app/views/browse/_map.html.erb
app/views/browse/note.html.erb [new file with mode: 0644]
app/views/note/_description.html.erb [new file with mode: 0644]
app/views/note/_note.gpx.builder [new file with mode: 0644]
app/views/note/_note.json.jsonify [new file with mode: 0644]
app/views/note/_note.rss.builder [new file with mode: 0644]
app/views/note/_note.xml.builder [new file with mode: 0644]
app/views/note/_notes_paging_nav.html.erb [new file with mode: 0644]
app/views/note/_user.html.erb [new file with mode: 0644]
app/views/note/list.gpx.builder [new file with mode: 0644]
app/views/note/list.json.jsonify [new file with mode: 0644]
app/views/note/list.rss.builder [new file with mode: 0644]
app/views/note/list.xml.builder [new file with mode: 0644]
app/views/note/mine.html.erb [new file with mode: 0644]
app/views/note/read.gpx.builder [new file with mode: 0644]
app/views/note/read.json.jsonify [new file with mode: 0644]
app/views/note/read.rss.builder [new file with mode: 0644]
app/views/note/read.xml.builder [new file with mode: 0644]
app/views/note/rss.rss.builder [new file with mode: 0644]
app/views/notifier/note_comment_notification.html.erb [new file with mode: 0644]
app/views/site/index.html.erb
app/views/user/view.html.erb
config/example.application.yml
config/initializers/mime_types.rb
config/locales/de.yml
config/locales/en.yml
config/openlayers.cfg
config/routes.rb
db/migrate/053_add_map_bug_tables.rb [new file with mode: 0644]
db/migrate/054_refactor_map_bug_tables.rb [new file with mode: 0644]
db/migrate/055_change_map_bug_comment_type.rb [new file with mode: 0644]
db/migrate/056_add_date_closed.rb [new file with mode: 0644]
db/migrate/057_add_map_bug_comment_event.rb [new file with mode: 0644]
db/migrate/20110508145337_cleanup_bug_tables.rb [new file with mode: 0644]
db/migrate/20110521142405_rename_bugs_to_notes.rb [new file with mode: 0644]
db/structure.sql
lib/bounding_box.rb
lib/geo_record.rb
lib/migrate.rb
test/fixtures/note_comments.yml [new file with mode: 0644]
test/fixtures/notes.yml [new file with mode: 0644]
test/functional/note_controller_test.rb [new file with mode: 0644]
vendor/assets/openlayers/OpenLayers.js

diff --git a/Gemfile b/Gemfile
index c1bb2f50b0ea194666fe2c26ab10a92ef302dafe..65de156e17b6a1d3b327663079f55faa44f63c0a 100644 (file)
--- a/Gemfile
+++ b/Gemfile
@@ -21,6 +21,7 @@ gem 'composite_primary_keys', '>= 5.0.0'
 gem 'http_accept_language', '>= 1.0.2'
 gem 'paperclip', '~> 2.0'
 gem 'deadlock_retry', '>= 1.2.0'
+gem 'jsonify-rails'
 
 # Character conversion support for ruby 1.8
 gem 'iconv', :platforms => :ruby_18
index 4709cd1957672fdf359c91764acaeadc7f8b2456..e212d100374d22d9a3c1c61dc04ded678984ccda 100644 (file)
@@ -61,9 +61,14 @@ GEM
       railties (>= 3.2.0, < 5.0)
       thor (~> 0.14)
     json (1.6.5)
+    jsonify (0.3.1)
+      multi_json (~> 1.0)
+    jsonify-rails (0.3.1)
+      actionpack
+      jsonify (>= 0.3.1)
     libv8 (3.3.10.4)
     libxml-ruby (2.2.2)
-    mail (2.4.1)
+    mail (2.4.3)
       i18n (>= 0.4.0)
       mime-types (~> 1.16)
       treetop (~> 1.4.8)
@@ -91,7 +96,7 @@ GEM
     pg (0.13.2)
     polyglot (0.3.3)
     rack (1.4.1)
-    rack-cache (1.1)
+    rack-cache (1.2)
       rack (>= 0.4)
     rack-openid (1.3.1)
       rack (>= 1.1.0)
@@ -141,7 +146,7 @@ GEM
     treetop (1.4.10)
       polyglot
       polyglot (>= 0.3.1)
-    tzinfo (0.3.31)
+    tzinfo (0.3.32)
     uglifier (1.2.3)
       execjs (>= 0.3.0)
       multi_json (>= 1.0.2)
@@ -160,6 +165,7 @@ DEPENDENCIES
   httpclient
   iconv
   jquery-rails
+  jsonify-rails
   libxml-ruby (>= 2.0.5)
   memcached (>= 1.4.1)
   oauth-plugin (>= 0.4.0.pre7)
diff --git a/app/assets/images/closed_note_marker.png b/app/assets/images/closed_note_marker.png
new file mode 100644 (file)
index 0000000..bf6d6bb
Binary files /dev/null and b/app/assets/images/closed_note_marker.png differ
diff --git a/app/assets/images/new_note_marker.png b/app/assets/images/new_note_marker.png
new file mode 100644 (file)
index 0000000..671cf42
Binary files /dev/null and b/app/assets/images/new_note_marker.png differ
diff --git a/app/assets/images/open_note_marker.png b/app/assets/images/open_note_marker.png
new file mode 100644 (file)
index 0000000..a580316
Binary files /dev/null and b/app/assets/images/open_note_marker.png differ
diff --git a/app/assets/javascripts/notes.js b/app/assets/javascripts/notes.js
new file mode 100644 (file)
index 0000000..626a169
--- /dev/null
@@ -0,0 +1,854 @@
+/*
+        Dervied from the OpenStreetBugs client, which is available
+        under the following license.
+
+        This OpenStreetBugs client is free software: you can redistribute it
+        and/or modify it under the terms of the GNU Affero General Public License
+        as published by the Free Software Foundation, either version 3 of the
+        License, or (at your option) any later version.
+
+        This file is distributed in the hope that it will be useful, but
+        WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+        or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public
+        License <http://www.gnu.org/licenses/> for more details.
+*/
+
+OpenLayers.Layer.Notes = new OpenLayers.Class(OpenLayers.Layer.Markers, {
+    /**
+     * The URL of the OpenStreetMap API.
+     *
+     * @var String
+     */
+    serverURL : "/api/0.6/",
+
+    /**
+     * Associative array (index: note ID) that is filled with the notes
+     * loaded in this layer.
+     *
+     * @var String
+     */
+    notes : { },
+
+    /**
+     * The username to be used to change or create notes on OpenStreetMap.
+     *
+     * @var String
+     */
+    username : "NoName",
+
+    /**
+     * The icon to be used for an open note.
+     *
+     * @var OpenLayers.Icon
+     */
+    iconOpen : new OpenLayers.Icon("/images/open_note_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
+
+    /**
+     * The icon to be used for a closed note.
+     *
+     * @var OpenLayers.Icon
+     */
+    iconClosed : new OpenLayers.Icon("/images/closed_note_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
+
+    /**
+     * The icon to be used when adding a new note.
+     *
+     * @var OpenLayers.Icon
+     */
+    iconNew : new OpenLayers.Icon("/images/new_note_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
+
+    /**
+     * The projection of the coordinates sent by the OpenStreetMap API.
+     *
+     * @var OpenLayers.Projection
+     */
+    apiProjection : new OpenLayers.Projection("EPSG:4326"),
+
+    /**
+     * If this is set to true, the user may not commit comments or close notes.
+     *
+     * @var Boolean
+     */
+    readonly : false,
+
+    /**
+     * When the layer is hidden, all open popups are stored in this
+     * array in order to be re-opened again when the layer is made
+     * visible again.
+     */
+    reopenPopups : [ ],
+
+    /**
+     * A URL to append lon=123&lat=123&zoom=123 for the Permalinks.
+     *
+     * @var String
+     */
+    permalinkURL : "http://www.openstreetmap.org/",
+
+    /**
+     * A CSS file to be included. Set to null if you don’t need this.
+     *
+     * @var String
+     */
+    theme : "/stylesheets/notes.css",
+
+    /**
+     * @param String name
+     */
+    initialize: function(name, options) {
+        OpenLayers.Layer.Markers.prototype.initialize.apply(this, [
+            name,
+            OpenLayers.Util.extend({
+                opacity: 0.7,
+                projection: new OpenLayers.Projection("EPSG:4326") }, options)
+        ]);
+
+        putAJAXMarker.layers.push(this);
+        this.events.addEventType("markerAdded");
+
+        this.events.register("visibilitychanged", this, this.updatePopupVisibility);
+        this.events.register("visibilitychanged", this, this.loadNotes);
+
+        if (this.theme) {
+            // check existing links for equivalent url
+            var addNode = true;
+            var nodes = document.getElementsByTagName('link');
+            for (var i = 0, len = nodes.length; i < len; ++i) {
+                if (OpenLayers.Util.isEquivalentUrl(nodes.item(i).href, this.theme)) {
+                    addNode = false;
+                    break;
+                }
+            }
+            // only add a new node if one with an equivalent url hasn't already
+            // been added
+            if (addNode) {
+                var cssNode = document.createElement('link');
+                cssNode.setAttribute('rel', 'stylesheet');
+                cssNode.setAttribute('type', 'text/css');
+                cssNode.setAttribute('href', this.theme);
+                document.getElementsByTagName('head')[0].appendChild(cssNode);
+            }
+        }
+    },
+
+    /**
+     * Called automatically called when the layer is added to a map.
+     * Initialises the automatic note loading in the visible bounding box.
+     */
+    afterAdd: function() {
+        var ret = OpenLayers.Layer.Markers.prototype.afterAdd.apply(this, arguments);
+
+        this.map.events.register("moveend", this, this.loadNotes);
+        this.loadNotes();
+
+        return ret;
+    },
+
+    /**
+     * At the moment the OpenStreetMap API responses to requests using
+     * JavaScript code. This way the Same Origin Policy can be worked
+     * around. Unfortunately, this makes communicating with the API a
+     * bit too asynchronous, at the moment there is no way to tell to
+     * which request the API actually responses.
+     *
+     * This method creates a new script HTML element that imports the
+     * API request URL. The API JavaScript response then executes the
+     * global functions provided below.
+     *
+     * @param String url The URL this.serverURL + url is requested.
+     */
+    apiRequest: function(url) {
+        var script = document.createElement("script");
+        script.type = "text/javascript";
+        script.src = this.serverURL + url + "&nocache="+(new Date()).getTime();
+        document.body.appendChild(script);
+    },
+
+    /**
+     * Is automatically called when the visibility of the layer
+     * changes. When the layer is hidden, all visible popups are
+     * closed and their visibility is saved. When the layer is made
+     * visible again, these popups are re-opened.
+     */
+    updatePopupVisibility: function() {
+        if (this.getVisibility()) {
+            for (var i =0 ; i < this.reopenPopups.length; i++)
+                this.reopenPopups[i].show();
+
+            this.reopenPopups = [ ];
+        } else {
+            for (var i = 0; i < this.markers.length; i++) {
+                if (this.markers[i].feature.popup &&
+                    this.markers[i].feature.popup.visible()) {
+                    this.markers[i].feature.popup.hide();
+                    this.reopenPopups.push(this.markers[i].feature.popup);
+                }
+            }
+        }
+    },
+
+    /**
+     * Sets the user name to be used for interactions with OpenStreetMap.
+     */
+    setUserName: function(username) {
+        if (this.username == username)
+            return;
+
+        this.username = username;
+
+        for (var i = 0; i < this.markers.length; i++) {
+            var popup = this.markers[i].feature.popup;
+
+            if (popup) {
+                var els = popup.contentDom.getElementsByTagName("input");
+
+                for (var j = 0; j < els.length; j++) {
+                    if (els[j].className == "username")
+                        els[j].value = username;
+                }
+            }
+        }
+    },
+
+    /**
+     * Returns the currently set username or “NoName” if none is set.
+     */
+    getUserName: function() {
+        if(this.username)
+            return this.username;
+        else
+            return "NoName";
+    },
+
+    /**
+     * Loads the notes in the current bounding box. Is automatically
+     * called by an event handler ("moveend" event) that is created in
+     * the afterAdd() method.
+     */
+    loadNotes: function() {
+        var bounds = this.map.getExtent();
+
+        if (bounds && this.getVisibility()) {
+            bounds.transform(this.map.getProjectionObject(), this.apiProjection);
+
+            this.apiRequest("notes"
+                            + "?bbox=" + this.round(bounds.left, 5)
+                            + "," + this.round(bounds.bottom, 5)
+                            + "," + this.round(bounds.right, 5)
+                            + "," + this.round(bounds.top, 5));
+        }
+    },
+
+    /**
+     * Rounds the given number to the given number of digits after the
+     * floating point.
+     *
+     * @param Number number
+     * @param Number digits
+     * @return Number
+     */
+    round: function(number, digits) {
+        var scale = Math.pow(10, digits);
+
+        return Math.round(number * scale) / scale;
+    },
+
+    /**
+     * Adds an OpenLayers.Marker representing a note to the map. Is
+     * usually called by loadNotes().
+     *
+     * @param Number id The note ID
+     */
+    createMarker: function(id) {
+        if (this.notes[id]) {
+            if (this.notes[id].popup && !this.notes[id].popup.visible())
+                this.setPopupContent(this.notes[id].popup, id);
+
+            if (this.notes[id].closed != putAJAXMarker.notes[id][2])
+                this.notes[id].destroy();
+            else
+                return;
+        }
+
+        var lonlat = putAJAXMarker.notes[id][0].clone().transform(this.apiProjection, this.map.getProjectionObject());
+        var comments = putAJAXMarker.notes[id][1];
+        var closed = putAJAXMarker.notes[id][2];
+        var icon = closed ? this.iconClosed : this.iconOpen;
+
+        var feature = new OpenLayers.Feature(this, lonlat, {
+            icon: icon.clone(),
+            autoSize: true
+        });
+        feature.popupClass = OpenLayers.Popup.FramedCloud.Notes;
+        feature.noteId = id;
+        feature.closed = closed;
+        this.notes[id] = feature;
+
+        var marker = feature.createMarker();
+        marker.feature = feature;
+        marker.events.register("click", feature, this.markerClick);
+        //marker.events.register("mouseover", feature, this.markerMouseOver);
+        //marker.events.register("mouseout", feature, this.markerMouseOut);
+        this.addMarker(marker);
+
+        this.events.triggerEvent("markerAdded");
+    },
+
+    /**
+     * Recreates the content of the popup of a marker.
+     *
+     * @param OpenLayers.Popup popup
+     * @param Number id The note ID
+     */
+    setPopupContent: function(popup, id) {
+        var el1,el2,el3;
+        var layer = this;
+
+        var newContent = document.createElement("div");
+
+        el1 = document.createElement("h3");
+        el1.appendChild(document.createTextNode(putAJAXMarker.notes[id][2] ? i18n("javascripts.note.closed") : i18n("javascripts.note.open")));
+
+        el1.appendChild(document.createTextNode(" ["));
+        el2 = document.createElement("a");
+        el2.href = "/browse/note/" + id;
+        el2.onclick = function() {
+            layer.map.setCenter(putAJAXMarker.notes[id][0].clone().transform(layer.apiProjection, layer.map.getProjectionObject()), 15);
+        };
+        el2.appendChild(document.createTextNode(i18n("javascripts.note.details")));
+        el1.appendChild(el2);
+        el1.appendChild(document.createTextNode("]"));
+
+        if (this.permalinkURL) {
+            el1.appendChild(document.createTextNode(" ["));
+            el2 = document.createElement("a");
+            el2.href = this.permalinkURL + (this.permalinkURL.indexOf("?") == -1 ? "?" : "&") + "lon="+putAJAXMarker.notes[id][0].lon+"&lat="+putAJAXMarker.notes[id][0].lat+"&zoom=15";
+            el2.appendChild(document.createTextNode(i18n("javascripts.note.permalink")));
+            el1.appendChild(el2);
+            el1.appendChild(document.createTextNode("]"));
+        }
+        newContent.appendChild(el1);
+
+        var containerDescription = document.createElement("div");
+        newContent.appendChild(containerDescription);
+
+        var containerChange = document.createElement("div");
+        newContent.appendChild(containerChange);
+
+        var displayDescription = function() {
+            containerDescription.style.display = "block";
+            containerChange.style.display = "none";
+            popup.updateSize();
+        };
+        var displayChange = function() {
+            containerDescription.style.display = "none";
+            containerChange.style.display = "block";
+            popup.updateSize();
+        };
+        displayDescription();
+
+        el1 = document.createElement("dl");
+        for (var i = 0; i < putAJAXMarker.notes[id][1].length; i++) {
+            el2 = document.createElement("dt");
+            el2.className = (i == 0 ? "note-description" : "note-comment");
+            el2.appendChild(document.createTextNode(i == 0 ? i18n("javascripts.note.description") : i18n("javascripts.note.comment")));
+            el1.appendChild(el2);
+            el2 = document.createElement("dd");
+            el2.className = (i == 0 ? "note-description" : "note-comment");
+            el2.appendChild(document.createTextNode(putAJAXMarker.notes[id][1][i]));
+            el1.appendChild(el2);
+            if (i == 0) {
+                el2 = document.createElement("br");
+                el1.appendChild(el2);
+            };
+        }
+        containerDescription.appendChild(el1);
+
+        if (putAJAXMarker.notes[id][2]) {
+            el1 = document.createElement("p");
+            el1.className = "note-fixed";
+            el2 = document.createElement("em");
+            el2.appendChild(document.createTextNode(i18n("javascripts.note.render_warning")));
+            el1.appendChild(el2);
+            containerDescription.appendChild(el1);
+        } else if (!this.readonly) {
+            el1 = document.createElement("div");
+            el2 = document.createElement("input");
+            el2.setAttribute("type", "button");
+            el2.onclick = function() {
+                displayChange();
+            };
+            el2.value = i18n("javascripts.note.update");
+            el1.appendChild(el2);
+            containerDescription.appendChild(el1);
+
+            var el_form = document.createElement("form");
+            el_form.onsubmit = function() {
+                if (inputComment.value.match(/^\s*$/))
+                    return false;
+                layer.submitComment(id, inputComment.value);
+                layer.hidePopup(popup);
+                return false;
+            };
+
+            el1 = document.createElement("dl");
+            el2 = document.createElement("dt");
+            el2.appendChild(document.createTextNode(i18n("javascripts.note.nickname")));
+            el1.appendChild(el2);
+            el2 = document.createElement("dd");
+            var inputUsername = document.createElement("input");
+            var inputUsername = document.createElement("input");;
+            if (typeof loginName === "undefined") {
+                inputUsername.value = this.username;
+            } else {
+                inputUsername.value = loginName;
+                inputUsername.setAttribute("disabled", "true");
+            }
+            inputUsername.className = "username";
+            inputUsername.onkeyup = function() {
+                layer.setUserName(inputUsername.value);
+            };
+            el2.appendChild(inputUsername);
+            el3 = document.createElement("a");
+            el3.setAttribute("href", "login");
+            el3.className = "hide_if_logged_in";
+            el3.appendChild(document.createTextNode(i18n("javascripts.note.login")));
+            el2.appendChild(el3)
+            el1.appendChild(el2);
+
+            el2 = document.createElement("dt");
+            el2.appendChild(document.createTextNode(i18n("javascripts.note.comment")));
+            el1.appendChild(el2);
+            el2 = document.createElement("dd");
+            var inputComment = document.createElement("textarea");
+            inputComment.setAttribute("cols",40);
+            inputComment.setAttribute("rows",3);
+
+            el2.appendChild(inputComment);
+            el1.appendChild(el2);
+
+            el_form.appendChild(el1);
+
+            el1 = document.createElement("ul");
+            el1.className = "buttons";
+            el2 = document.createElement("li");
+            el3 = document.createElement("input");
+            el3.setAttribute("type", "button");
+            el3.onclick = function() {
+                this.form.onsubmit();
+                return false;
+            };
+            el3.value = i18n("javascripts.note.add_comment");
+            el2.appendChild(el3);
+            el1.appendChild(el2);
+
+            el2 = document.createElement("li");
+            el3 = document.createElement("input");
+            el3.setAttribute("type", "button");
+            el3.onclick = function() {
+                this.form.onsubmit();
+                layer.closeNote(id);
+                popup.hide();
+                return false;
+            };
+            el3.value = i18n("javascripts.note.close");
+            el2.appendChild(el3);
+            el1.appendChild(el2);
+            el_form.appendChild(el1);
+            containerChange.appendChild(el_form);
+
+            el1 = document.createElement("div");
+            el2 = document.createElement("input");
+            el2.setAttribute("type", "button");
+            el2.onclick = function(){ displayDescription(); };
+            el2.value = i18n("javascripts.note.cancel");
+            el1.appendChild(el2);
+            containerChange.appendChild(el1);
+        }
+
+        popup.setContentHTML(newContent);
+    },
+
+    /**
+     * Creates a new note.
+     *
+     * @param OpenLayers.LonLat lonlat The coordinates in the API projection.
+     * @param String description
+     */
+    createNote: function(lonlat, description) {
+        this.apiRequest("note/create"
+                        + "?lat=" + encodeURIComponent(lonlat.lat)
+                        + "&lon=" + encodeURIComponent(lonlat.lon)
+                        + "&text=" + encodeURIComponent(description)
+                        + "&name=" + encodeURIComponent(this.getUserName())
+                        + "&format=js");
+    },
+
+    /**
+     * Adds a comment to a note.
+     *
+     * @param Number id
+     * @param String comment
+     */
+    submitComment: function(id, comment) {
+        this.apiRequest("note/" + encodeURIComponent(id) + "/comment"
+                        + "?text=" + encodeURIComponent(comment)
+                        + "&name=" + encodeURIComponent(this.getUserName())
+                        + "&format=js");
+    },
+
+    /**
+     * Marks a note as fixed.
+     *
+     * @param Number id
+     */
+    closeNote: function(id) {
+        this.apiRequest("note/" + encodeURIComponent(id) + "/close"
+                        + "?format=js");
+    },
+
+    /**
+     * Removes the content of a marker popup (to reduce the amount of
+     * needed resources).
+     *
+     * @param OpenLayers.Popup popup
+     */
+    resetPopupContent: function(popup) {
+        if (popup)
+            popup.setContentHTML(document.createElement("div"));
+    },
+
+    /**
+     * Makes the popup of the given marker visible. Makes sure that
+     * the popup content is created if it does not exist yet.
+     *
+     * @param OpenLayers.Feature feature
+     */
+    showPopup: function(feature) {
+        var popup = feature.popup;
+
+        if (!popup) {
+            popup = feature.createPopup(true);
+
+            popup.events.register("close", this, function() {
+                this.resetPopupContent(popup);
+            });
+        }
+
+        this.setPopupContent(popup, feature.noteId);
+
+        if (!popup.map)
+            this.map.addPopup(popup);
+
+        popup.updateSize();
+
+        if (!popup.visible())
+            popup.show();
+    },
+
+    /**
+     * Hides the popup of the given marker.
+     *
+     * @param OpenLayers.Feature feature
+     */
+    hidePopup: function(feature) {
+        if (feature.popup && feature.popup.visible()) {
+            feature.popup.hide();
+            feature.popup.events.triggerEvent("close");
+        }
+    },
+
+    /**
+     * Is run on the “click” event of a marker in the context of its
+     * OpenLayers.Feature. Toggles the visibility of the popup.
+     */
+    markerClick: function(e) {
+        var feature = this;
+
+        if (feature.popup && feature.popup.visible())
+            feature.layer.hidePopup(feature);
+        else
+            feature.layer.showPopup(feature);
+
+        OpenLayers.Event.stop(e);
+    },
+
+    /**
+     * Is run on the “mouseover” event of a marker in the context of
+     * its OpenLayers.Feature. Makes the popup visible.
+     */
+    markerMouseOver: function(e) {
+        var feature = this;
+
+        feature.layer.showPopup(feature);
+
+        OpenLayers.Event.stop(e);
+    },
+
+    /**
+     * Is run on the “mouseout” event of a marker in the context of
+     * its OpenLayers.Feature. Hides the popup (if it has not been
+     * clicked).
+     */
+    markerMouseOut: function(e) {
+        var feature = this;
+
+        if (feature.popup && feature.popup.visible())
+            feature.layer.hidePopup(feature);
+
+        OpenLayers.Event.stop(e);
+    },
+
+    /**
+     * Add a new note.
+     */
+    addNote: function(lonlat) {
+        var layer = this;
+        var map = this.map;
+        var lonlatApi = lonlat.clone().transform(map.getProjectionObject(), this.apiProjection);
+        var feature = new OpenLayers.Feature(this, lonlat, { icon: this.iconNew.clone(), autoSize: true });
+        feature.popupClass = OpenLayers.Popup.FramedCloud.Notes;
+        var marker = feature.createMarker();
+        marker.feature = feature;
+        this.addMarker(marker);
+
+
+        /** Implement a drag and drop for markers */
+        /* TODO: veryfy that the scoping of variables works correctly everywhere */
+        var dragging = false;
+        var dragMove = function(e) {
+            lonlat = map.getLonLatFromViewPortPx(e.xy);
+            lonlatApi = lonlat.clone().transform(map.getProjectionObject(), map.noteLayer.apiProjection);
+            marker.moveTo(map.getLayerPxFromViewPortPx(e.xy));
+            marker.popup.moveTo(map.getLayerPxFromViewPortPx(e.xy));
+            marker.popup.updateRelativePosition();
+            return false;
+        };
+        var dragComplete = function(e) {
+            map.events.unregister("mousemove", map, dragMove);
+            map.events.unregister("mouseup", map, dragComplete);
+            dragMove(e);
+            dragging = false;
+            return false;
+        };
+
+        marker.events.register("mouseover", this, function() {
+            map.viewPortDiv.style.cursor = "move";
+        });
+        marker.events.register("mouseout", this, function() {
+            if (!dragging)
+                map.viewPortDiv.style.cursor = "default";
+        });
+        marker.events.register("mousedown", this, function() {
+            dragging = true;
+            map.events.register("mousemove", map, dragMove);
+            map.events.register("mouseup", map, dragComplete);
+            return false;
+        });
+
+        var newContent = document.createElement("div");
+        var el1,el2,el3;
+        el1 = document.createElement("h3");
+        el1.appendChild(document.createTextNode(i18n("javascripts.note.create_title")));
+        newContent.appendChild(el1);
+        newContent.appendChild(document.createTextNode(i18n("javascripts.note.create_help1")));
+        newContent.appendChild(document.createElement("br"));
+        newContent.appendChild(document.createTextNode(i18n("javascripts.note.create_help2")));
+        newContent.appendChild(document.createElement("br"));
+        newContent.appendChild(document.createElement("br"));
+
+        var el_form = document.createElement("form");
+
+        el1 = document.createElement("dl");
+        el2 = document.createElement("dt");
+        el2.appendChild(document.createTextNode(i18n("javascripts.note.nickname")));
+        el1.appendChild(el2);
+        el2 = document.createElement("dd");
+        var inputUsername = document.createElement("input");;
+        if (typeof loginName === 'undefined') {
+            inputUsername.value = this.username;
+        } else {
+            inputUsername.value = loginName;
+            inputUsername.setAttribute('disabled','true');
+        }
+        inputUsername.className = "username";
+
+        inputUsername.onkeyup = function() {
+            this.setUserName(inputUsername.value);
+        };
+        el2.appendChild(inputUsername);
+        el3 = document.createElement("a");
+        el3.setAttribute("href","login");
+        el3.className = "hide_if_logged_in";
+        el3.appendChild(document.createTextNode(i18n("javascripts.note.login")));
+        el2.appendChild(el3);
+        el1.appendChild(el2);
+        el2 = document.createElement("br");
+        el1.appendChild(el2);
+
+        el2 = document.createElement("dt");
+        el2.appendChild(document.createTextNode(i18n("javascripts.note.description")));
+        el1.appendChild(el2);
+        el2 = document.createElement("dd");
+        var inputDescription = document.createElement("textarea");
+        inputDescription.setAttribute("cols",40);
+        inputDescription.setAttribute("rows",3);
+        el2.appendChild(inputDescription);
+        el1.appendChild(el2);
+        el_form.appendChild(el1);
+
+        el1 = document.createElement("div");
+        el2 = document.createElement("input");
+        el2.setAttribute("type", "button");
+        el2.value = i18n("javascripts.note.report");
+        el2.onclick = function() {
+            layer.createNote(lonlatApi, inputDescription.value);
+            marker.feature = null;
+            feature.destroy();
+            return false;
+        };
+        el1.appendChild(el2);
+        el2 = document.createElement("input");
+        el2.setAttribute("type", "button");
+        el2.value = i18n("javascripts.note.cancel");
+        el2.onclick = function(){ feature.destroy(); };
+        el1.appendChild(el2);
+        el_form.appendChild(el1);
+        newContent.appendChild(el_form);
+
+        el2 = document.createElement("hr");
+        el1.appendChild(el2);
+        el2 = document.createElement("a");
+        el2.setAttribute("href","edit");
+        el2.appendChild(document.createTextNode(i18n("javascripts.note.edityourself")));
+        el1.appendChild(el2);
+
+        feature.data.popupContentHTML = newContent;
+        var popup = feature.createPopup(true);
+        popup.events.register("close", this, function() {
+            feature.destroy();
+        });
+        map.addPopup(popup);
+        popup.updateSize();
+        marker.popup = popup;
+    },
+
+    CLASS_NAME: "OpenLayers.Layer.Notes"
+});
+
+
+/**
+ * This class changes the usual OpenLayers.Popup.FramedCloud class by
+ * using a DOM element instead of an innerHTML string as content for
+ * the popup.  This is necessary for creating valid onclick handlers
+ * that still work with multiple Notes layer objects.
+ */
+OpenLayers.Popup.FramedCloud.Notes = new OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
+    contentDom : null,
+    autoSize : true,
+
+    /**
+     * See OpenLayers.Popup.FramedCloud.initialize() for
+     * parameters. As fourth parameter, pass a DOM node instead of a
+     * string.
+     */
+    initialize: function() {
+        this.displayClass = this.displayClass + " " + this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
+
+        var args = new Array(arguments.length);
+        for(var i=0; i<arguments.length; i++)
+            args[i] = arguments[i];
+
+        // Unset original contentHTML parameter
+        args[3] = null;
+
+        var closeCallback = arguments[6];
+
+        // Add close event trigger to the closeBoxCallback parameter
+        args[6] = function(e){ if(closeCallback) closeCallback(); else this.hide(); OpenLayers.Event.stop(e); this.events.triggerEvent("close"); };
+
+        OpenLayers.Popup.FramedCloud.prototype.initialize.apply(this, args);
+
+        this.events.addEventType("close");
+
+        this.setContentHTML(arguments[3]);
+    },
+
+    /**
+     * Like OpenLayers.Popup.FramedCloud.setContentHTML(), but takes a
+     * DOM element as parameter.
+     */
+    setContentHTML: function(contentDom) {
+        if(contentDom != null)
+            this.contentDom = contentDom;
+
+        if(this.contentDiv == null || this.contentDom == null || this.contentDom == this.contentDiv.firstChild)
+            return;
+
+        while(this.contentDiv.firstChild)
+            this.contentDiv.removeChild(this.contentDiv.firstChild);
+
+        this.contentDiv.appendChild(this.contentDom);
+
+        // Copied from OpenLayers.Popup.setContentHTML():
+        if(this.autoSize)
+        {
+            this.registerImageListeners();
+            this.updateSize();
+        }
+    },
+
+    destroy: function() {
+        this.contentDom = null;
+        OpenLayers.Popup.FramedCloud.prototype.destroy.apply(this, arguments);
+    },
+
+    CLASS_NAME: "OpenLayers.Popup.FramedCloud.Notes"
+});
+
+
+/**
+ * This global function is executed by the OpenStreetMap API getBugs script.
+ *
+ * Each Notes layer adds itself to the putAJAXMarker.layer array. The
+ * putAJAXMarker() function executes the createMarker() method on each
+ * layer in that array each time it is called. This has the
+ * side-effect that notes displayed in one map on a page are already
+ * loaded on the other map as well.
+ */
+function putAJAXMarker(id, lon, lat, text, closed)
+{
+    var comments = text.split(/<hr \/>/);
+    for(var i=0; i<comments.length; i++)
+        comments[i] = comments[i].replace(/&quot;/g, "\"").replace(/&lt;/g, "<").replace(/&gt;/g, ">").replace(/&amp;/g, "&");
+    putAJAXMarker.notes[id] = [
+        new OpenLayers.LonLat(lon, lat),
+        comments,
+        closed
+    ];
+    for(var i=0; i<putAJAXMarker.layers.length; i++)
+        putAJAXMarker.layers[i].createMarker(id);
+}
+
+/**
+ * This global function is executed by the OpenStreetMap API. The
+ * “create note”, “comment” and “close note” scripts execute it to give
+ * information about their success.
+ *
+ * In case of success, this function is called without a parameter, in
+ * case of an error, the error message is passed. This is lousy
+ * workaround to make it any functional at all, the OSB API is likely
+ * to be extended later (then it will provide additional information
+ * such as the ID of a created note and similar).
+ */
+function osbResponse(error)
+{
+    if(error)
+        alert("Error: "+error);
+
+    for(var i=0; i<putAJAXMarker.layers.length; i++)
+        putAJAXMarker.layers[i].loadNotes();
+}
+
+putAJAXMarker.layers = [ ];
+putAJAXMarker.notes = { };
index 12a5a808998d059acaee68c3d8086128bccc8655..42b5f539737624b23c6f7acac32477f6901749ae 100644 (file)
@@ -642,6 +642,23 @@ table.browse_details th {
   white-space: nowrap;
 }
 
+td.browse_comments {
+  padding: 0px;
+}
+
+td.browse_comments table {
+  border-collapse: collapse;
+}
+
+td.browse_comments table td {
+  padding-bottom: 10px;
+}
+
+td.browse_comments table td span.by {
+  font-size: small;
+  color: #999999;
+}
+
 #browse_map {
   width: 250px;
 }
index 196b61c01149b2b18bf2b5b7b1f0cdc858d7772e..2cf195632dda1d0dc533812df5c1291ca729f0f9 100644 (file)
@@ -17,3 +17,9 @@
 .olControlPanZoom {
   display: none;
 }
+
+/* Rules for map bug reporting */
+
+#reportbuganchor { 
+  font-size: 150%;
+}
diff --git a/app/assets/stylesheets/notes.css b/app/assets/stylesheets/notes.css
new file mode 100644 (file)
index 0000000..ee6198b
--- /dev/null
@@ -0,0 +1,42 @@
+.olPopupFramedCloudNotes dl {
+    margin: 0px;
+    padding: 0px;
+}
+
+.olPopupFramedCloudNotes dt {
+    margin: 0px;
+    padding: 0px;
+    font-weight: bold;
+    float: left;
+    clear: left;
+}
+
+.olPopupFramedCloudNotes dt:after {
+    content: ": ";
+}
+
+.olPopupFramedCloudNotes dt {
+    margin-right: 1ex;
+}
+
+.olPopupFramedCloudNotes dd {
+    margin: 0px;
+    padding: 0px;
+}
+
+.olPopupFramedCloudNotes ul.buttons {
+    list-style-type: none;
+    padding: 0px;
+    margin: 0px;
+}
+
+.olPopupFramedCloudNotes ul.buttons li {
+    display: inline;
+    margin: 0px;
+    padding: 0px;
+}
+
+.olPopupFramedCloudNotes h3 {
+    font-size: 1.2em;
+    margin: 0.2em 0em 0.7em 0em;
+}
index 2a7e2c5f70ed74c09ee1c0abef9c127461bffd65..33bdd6630276ca128a1a5c45571bda1ef6662fd7 100644 (file)
@@ -79,4 +79,13 @@ class BrowseController < ApplicationController
   rescue ActiveRecord::RecordNotFound
     render :action => "not_found", :status => :not_found
   end
+
+  def note
+    @type = "note"
+    @note = Note.find(params[:id])
+    @next = Note.find(:first, :order => "id ASC", :conditions => [ "status != 'hidden' AND id > :id", { :id => @note.id }] )
+    @prev = Note.find(:first, :order => "id DESC", :conditions => [ "status != 'hidden' AND id < :id", { :id => @note.id }] )
+  rescue ActiveRecord::RecordNotFound
+    render :action => "not_found", :status => :not_found
+  end
 end
diff --git a/app/controllers/note_controller.rb b/app/controllers/note_controller.rb
new file mode 100644 (file)
index 0000000..1eb0350
--- /dev/null
@@ -0,0 +1,330 @@
+class NoteController < ApplicationController
+
+  layout 'site', :only => [:mine]
+
+  before_filter :check_api_readable
+  before_filter :authorize_web, :only => [:create, :close, :update, :delete, :mine]
+  before_filter :check_api_writable, :only => [:create, :close, :update, :delete]
+  before_filter :set_locale, :only => [:mine]
+  after_filter :compress_output
+  around_filter :api_call_handle_error, :api_call_timeout
+
+  ##
+  # Return a list of notes in a given area
+  def list
+    # Figure out the bbox - we prefer a bbox argument but also
+    # support the old, deprecated, method with four arguments
+    if params[:bbox]
+      bbox = BoundingBox.from_bbox_params(params)
+    else
+      raise OSM::APIBadUserInput.new("No l was given") unless params[:l]
+      raise OSM::APIBadUserInput.new("No r was given") unless params[:r]
+      raise OSM::APIBadUserInput.new("No b was given") unless params[:b]
+      raise OSM::APIBadUserInput.new("No t was given") unless params[:t]
+
+      bbox = BoundingBox.from_lrbt_params(params)
+    end
+
+    # Get any conditions that need to be applied
+    notes = closed_condition(Note.scoped)
+
+    # Check that the boundaries are valid
+    bbox.check_boundaries
+
+    # Check the the bounding box is not too big
+    bbox.check_size(MAX_NOTE_REQUEST_AREA)
+
+    # Find the notes we want to return
+    @notes = notes.bbox(bbox).order("updated_at DESC").limit(result_limit).preload(:comments)
+
+    # Render the result
+    respond_to do |format|
+      format.rss
+      format.xml
+      format.json
+      format.gpx
+    end
+  end
+
+  ##
+  # Create a new note
+  def create
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No lat was given") unless params[:lat]
+    raise OSM::APIBadUserInput.new("No lon was given") unless params[:lon]
+    raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
+
+    # Extract the arguments
+    lon = params[:lon].to_f
+    lat = params[:lat].to_f
+    comment = params[:text]
+    name = params[:name]
+
+    # Include in a transaction to ensure that there is always a note_comment for every note
+    Note.transaction do
+      # Create the note
+      @note = Note.create(:lat => lat, :lon => lon)
+      raise OSM::APIBadUserInput.new("The note is outside this world") unless @note.in_world?
+
+      #TODO: move this into a helper function
+      begin
+        url = "http://nominatim.openstreetmap.org/reverse?lat=" + lat.to_s + "&lon=" + lon.to_s + "&zoom=16" 
+        response = REXML::Document.new(Net::HTTP.get(URI.parse(url))) 
+               
+        if result = response.get_text("reversegeocode/result") 
+          @note.nearby_place = result.to_s 
+        else 
+          @note.nearby_place = "unknown"
+        end
+      rescue Exception => err
+        @note.nearby_place = "unknown"
+      end
+
+      # Save the note
+      @note.save!
+
+      # Add a comment to the note
+      add_comment(@note, comment, name, "opened")
+    end
+
+    # Send an OK response
+    render_ok
+  end
+
+  ##
+  # Add a comment to an existing note
+  def update
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+    raise OSM::APIBadUserInput.new("No text was given") unless params[:text]
+
+    # Extract the arguments
+    id = params[:id].to_i
+    comment = params[:text]
+    name = params[:name] or "NoName"
+
+    # Find the note and check it is valid
+    note = Note.find(id)
+    raise OSM::APINotFoundError unless note
+    raise OSM::APIAlreadyDeletedError unless note.visible?
+
+    # Add a comment to the note
+    Note.transaction do
+      add_comment(note, comment, name, "commented")
+    end
+
+    # Send an OK response
+    render_ok
+  end
+
+  ##
+  # Close a note
+  def close
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+
+    # Extract the arguments
+    id = params[:id].to_i
+    name = params[:name]
+
+    # Find the note and check it is valid
+    note = Note.find_by_id(id)
+    raise OSM::APINotFoundError unless note
+    raise OSM::APIAlreadyDeletedError unless note.visible?
+
+    # Close the note and add a comment
+    Note.transaction do
+      note.close
+
+      add_comment(note, nil, name, "closed")
+    end
+
+    # Send an OK response
+    render_ok
+  end 
+
+  ##
+  # Get a feed of recent notes and comments
+  def rss
+    # Get any conditions that need to be applied
+    notes = closed_condition(Note.scoped)
+
+    # Process any bbox
+    if params[:bbox]
+      bbox = BoundingBox.from_bbox_params(params)
+
+      bbox.check_boundaries
+      bbox.check_size(MAX_NOTE_REQUEST_AREA)
+
+      notes = notes.bbox(bbox)
+    end
+
+    # Find the comments we want to return
+    @comments = NoteComment.where(:note_id => notes).order("created_at DESC").limit(result_limit).preload(:note)
+
+    # Render the result
+    respond_to do |format|
+      format.rss
+    end
+  end
+
+  ##
+  # Read a note
+  def read
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+
+    # Find the note and check it is valid
+    @note = Note.find(params[:id])
+    raise OSM::APINotFoundError unless @note
+    raise OSM::APIAlreadyDeletedError unless @note.visible?
+    
+    # Render the result
+    respond_to do |format|
+      format.xml
+      format.rss
+      format.json
+      format.gpx
+    end
+  end
+
+  ##
+  # Delete (hide) a note
+  def delete
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No id was given") unless params[:id]
+
+    # Extract the arguments
+    id = params[:id].to_i
+    name = params[:name]
+
+    # Find the note and check it is valid
+    note = Note.find(id)
+    raise OSM::APINotFoundError unless note
+    raise OSM::APIAlreadyDeletedError unless note.visible?
+
+    # Mark the note as hidden
+    Note.transaction do
+      note.status = "hidden"
+      note.save
+
+      add_comment(note, nil, name, "hidden")
+    end
+
+    # Render the result
+    render :text => "ok\n", :content_type => "text/html" 
+  end
+
+  ##
+  # Return a list of notes matching a given string
+  def search
+    # Check the arguments are sane
+    raise OSM::APIBadUserInput.new("No query string was given") unless params[:q]
+
+    # Get any conditions that need to be applied
+    @notes = closed_condition(Note.scoped)
+    @notes = @notes.joins(:comments).where("note_comments.body ~ ?", params[:q])
+
+    # Find the notes we want to return
+    @notes = @notes.order("updated_at DESC").limit(result_limit).preload(:comments)
+
+    # Render the result
+    respond_to do |format|
+      format.rss { render :action => :list }
+      format.xml { render :action => :list }
+      format.json { render :action => :list }
+      format.gpx { render :action => :list }
+    end
+  end
+
+  ##
+  # Display a list of notes by a specified user
+  def mine
+    if params[:display_name] 
+      if @this_user = User.active.find_by_display_name(params[:display_name])
+        @title =  t 'note.mine.title', :user => @this_user.display_name 
+        @heading =  t 'note.mine.heading', :user => @this_user.display_name 
+        @description = t 'note.mine.description', :user => render_to_string(:partial => "user", :object => @this_user)
+        @page = (params[:page] || 1).to_i 
+        @page_size = 10
+        @notes = @this_user.notes.order("updated_at DESC").offset((@page - 1) * @page_size).limit(@page_size).preload(:comments => :author)
+      else
+        @title = t 'user.no_such_user.title' 
+        @not_found_user = params[:display_name] 
+
+        render :template => 'user/no_such_user', :status => :not_found 
+      end 
+    end
+  end
+
+private 
+  #------------------------------------------------------------ 
+  # utility functions below. 
+  #------------------------------------------------------------   
+  ##
+  # Render an OK response
+  def render_ok
+    if params[:format] == "js"
+      render :text => "osbResponse();", :content_type => "text/javascript" 
+    else
+      render :text => "ok " + @note.id.to_s + "\n", :content_type => "text/plain" if @note
+      render :text => "ok\n", :content_type => "text/plain" unless @note
+    end
+  end
+
+  ##
+  # Get the maximum number of results to return
+  def result_limit
+    if params[:limit] and params[:limit].to_i > 0 and params[:limit].to_i < 10000
+      params[:limit].to_i
+    else
+      100
+    end
+  end
+
+  ##
+  # Generate a condition to choose which bugs we want based
+  # on their status and the user's request parameters
+  def closed_condition(notes)
+    if params[:closed]
+      closed_since = params[:closed].to_i
+    else
+      closed_since = 7
+    end
+       
+    if closed_since < 0
+      notes = notes.where("status != 'hidden'")
+    elsif closed_since > 0
+      notes = notes.where("(status = 'open' OR (status = 'closed' AND closed_at > '#{Time.now - closed_since.days}'))")
+    else
+      notes = notes.where("status = 'open'")
+    end
+
+    return notes
+  end
+
+  ##
+  # Add a comment to a note
+  def add_comment(note, text, name, event)
+    name = "NoName" if name.nil?
+
+    attributes = { :visible => true, :event => event, :body => text }
+
+    if @user  
+      attributes[:author_id] = @user.id
+      attributes[:author_name] = @user.display_name
+    else  
+      attributes[:author_ip] = request.remote_ip
+      attributes[:author_name] = name + " (a)"
+    end
+
+    note.comments.create(attributes, :without_protection => true)
+
+    note.comments.map { |c| c.author }.uniq.each do |user|
+      if user and user != @user
+        Notifier.deliver_note_comment_notification(comment, user)
+      end
+    end
+  end
+end
index ce0c5d67bb68d37945d0d42213e92d3ef1f08373..f4b900017d4c8408d8a5e5f633bba9e96da15613 100644 (file)
@@ -125,6 +125,18 @@ module ApplicationHelper
     end
   end
 
+  def friendly_date(date)
+    content_tag(:span, time_ago_in_words(date), :title => l(date, :format => :friendly))
+  end
+
+  def note_author(object, link_options = {})
+    if object.author.nil?
+      h(object.author_name)
+    else
+      link_to h(object.author_name), link_options.merge({:controller => "user", :action => "view", :display_name => object.author_name})
+    end
+  end
+
 private
 
   def javascript_strings_for_key(key)
diff --git a/app/models/note.rb b/app/models/note.rb
new file mode 100644 (file)
index 0000000..c32b167
--- /dev/null
@@ -0,0 +1,81 @@
+class Note < ActiveRecord::Base
+  include GeoRecord
+
+  has_many :comments, :class_name => "NoteComment",
+                      :foreign_key => :note_id,
+                      :order => :created_at,
+                      :conditions => { :visible => true }
+
+  validates_presence_of :id, :on => :update
+  validates_uniqueness_of :id
+  validates_numericality_of :latitude, :only_integer => true
+  validates_numericality_of :longitude, :only_integer => true
+  validates_presence_of :closed_at if :status == "closed"
+  validates_inclusion_of :status, :in => ["open", "closed", "hidden"]
+  validate :validate_position
+
+  attr_accessible :lat, :lon
+
+  after_initialize :set_defaults
+
+  # Sanity check the latitude and longitude and add an error if it's broken
+  def validate_position
+    errors.add(:base, "Note is not in the world") unless in_world?
+  end
+
+  # Close a note
+  def close
+    self.status = "closed"
+    self.closed_at = Time.now.getutc
+    self.save
+  end
+
+  # Return a flattened version of the comments for a note
+  def flatten_comment(separator_char, upto_timestamp = :nil)
+    resp = ""
+    comment_no = 1
+    self.comments.each do |comment|
+      next if upto_timestamp != :nil and comment.created_at > upto_timestamp
+      resp += (comment_no == 1 ? "" : separator_char)
+      resp += comment.body if comment.body
+      resp += " [ " 
+      resp += comment.author_name if comment.author_name
+      resp += " " + comment.created_at.to_s + " ]"
+      comment_no += 1
+    end
+
+    return resp
+  end
+
+  # Check if a note is visible
+  def visible?
+    return status != "hidden"
+  end
+
+  # Return the author object, derived from the first comment
+  def author
+    self.comments.first.author
+  end
+
+  # Return the author IP address, derived from the first comment
+  def author_ip
+    self.comments.first.author_ip
+  end
+
+  # Return the author id, derived from the first comment
+  def author_id
+    self.comments.first.author_id
+  end
+
+  # Return the author name, derived from the first comment
+  def author_name
+    self.comments.first.author_name
+  end
+
+private
+
+  # Fill in default values for new notes
+  def set_defaults
+    self.status = "open" unless self.attribute_present?(:status)
+  end
+end
diff --git a/app/models/note_comment.rb b/app/models/note_comment.rb
new file mode 100644 (file)
index 0000000..bcbcf79
--- /dev/null
@@ -0,0 +1,21 @@
+class NoteComment < ActiveRecord::Base
+  belongs_to :note, :foreign_key => :note_id
+  belongs_to :author, :class_name => "User", :foreign_key => :author_id
+
+  validates_presence_of :id, :on => :update
+  validates_uniqueness_of :id
+  validates_presence_of :note_id
+  validates_associated :note
+  validates_presence_of :visible
+  validates_associated :author
+  validates_inclusion_of :event, :in => [ "opened", "closed", "reopened", "commented", "hidden" ]
+
+  # Return the author name
+  def author_name
+    if self.author_id.nil?
+      self.read_attribute(:author_name)
+    else
+      self.author.display_name
+    end
+  end
+end
index 343c3db2292fd9fd7625abe9b87889671e6d6f50..2fb00c96f8f52255e1c1e5f8ff4f12baebca76ad 100644 (file)
@@ -114,6 +114,22 @@ class Notifier < ActionMailer::Base
          :subject => I18n.t('notifier.friend_notification.subject', :user => friend.befriender.display_name, :locale => @locale)
   end
 
+  def note_comment_notification(comment, recipient)
+    common_headers recipient
+    owner = (recipient == comment.note.author);
+    subject I18n.t('notifier.note_plain.subject_own', :commenter => comment.author_name) if owner
+    subject I18n.t('notifier.note_plain.subject_other', :commenter => comment.author_name) unless owner
+
+    body :nodeurl => url_for(:host => SERVER_URL,
+                             :controller => "browse",
+                             :action => "note",
+                             :id => comment.note_id),
+         :place => comment.note.nearby_place,
+         :comment => comment.body,
+         :owner => owner,
+         :commenter => comment.author_name
+  end
+
 private
 
   def from_address(name, type, id, digest)
index 0c9e76d54999685bd920542c4daf0aa42d64cbf6..51bc52f3c0cc994974cb234141e797266dbf7b3c 100644 (file)
@@ -12,6 +12,8 @@ class User < ActiveRecord::Base
   has_many :tokens, :class_name => "UserToken"
   has_many :preferences, :class_name => "UserPreference"
   has_many :changesets, :order => 'created_at DESC'
+  has_many :note_comments, :foreign_key => :author_id
+  has_many :notes, :through => :note_comments
 
   has_many :client_applications
   has_many :oauth_tokens, :class_name => "OauthToken", :order => "authorized_at desc", :include => [:client_application]
index 6df060d5cf0b6f2b26eaf58c3dfc63337fd32ac8..d3af9bc156e0f448c490fcd8750dd91cf1d341c7 100644 (file)
@@ -5,14 +5,18 @@
 </iframe>
 
 <div id="browse_map">
-  <% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible %>
+  <% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible? %>
   <div id="small_map">
   </div>
   <span id="loading"><%= t 'browse.map.loading' %></span>
+  <% if map.instance_of? Note -%>
+  <%= link_to(t("browse.map.larger.area"), { :controller => :site, :action => :index, :notes => "yes" }, { :id => "area_larger_map", :class => "geolink bbox" }) %>
+  <% else -%>
   <%= link_to(t("browse.map.larger.area"), { :controller => :site, :action => :index, :box => "yes" }, { :id => "area_larger_map", :class => "geolink bbox" }) %>
+  <% end -%>
   <br />
   <%= link_to(t("browse.map.edit.area"), { :controller => :site, :action => :edit }, { :id => "area_edit", :class => "geolink bbox" }) %>
-  <% unless map.instance_of? Changeset %>
+  <% unless map.instance_of? Changeset or map.instance_of? Note %>
     <br />
     <%= link_to("", { :controller => :site, :action => :index }, { :id => "object_larger_map", :class => "geolink object" }) %>
     <br />
@@ -39,7 +43,7 @@
   </ul>
 </div>
 
-<% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible %>
+<% if map.instance_of? Changeset or (map.instance_of? Node and map.version > 1) or map.visible? %>
   <script type="text/javascript">
     OpenLayers.Lang.setCode("<%= I18n.locale.to_s %>");
 
         });
         <% end -%>
 
-        updatelinks(centre.lon, centre.lat, 16, null, minlon, minlat, maxlon, maxlat);
-      <% else -%>
+        updatelinks(centre.lon, centre.lat, 16, null, minlon, minlat, maxlon, maxlat)
+      <% elsif map.instance_of? Note %>
+        var centre = new OpenLayers.LonLat(<%= map.lon %>, <%= map.lat %>);
+
+        setMapCenter(centre, 16);
+        addMarkerToMap(centre);
+
+        var bbox = getMapExtent();
+
+        $("#loading").hide();
+        $("#browse_map .geolink").show();
+
+        $("#remote_area_edit").click(function (event) {
+          return remoteEditHandler(event, bbox);
+        });
+
+        <% if preferred_editor == "remote" -%>
+        $("#area_edit").click(function (event) {
+          return remoteEditHandler(event, bbox);
+        });
+        <% end -%>
+
+        updatelinks(centre.lon, centre.lat, 16, null, bbox.left, bbox.bottom, bbox.right, bbox.top)
+      <% else %>
         var obj_type = "<%= map.class.name.downcase %>";
         var obj_id = <%= map.id %>;
         var obj_version = <%= map.version %>;
diff --git a/app/views/browse/note.html.erb b/app/views/browse/note.html.erb
new file mode 100644 (file)
index 0000000..59c96c4
--- /dev/null
@@ -0,0 +1,58 @@
+<%= render :partial => "navigation" %>
+
+<h2>
+  <%= image_tag "#{@note.status}_note_marker.png", :alt => @note.status %>
+  <%= t "browse.note.#{@note.status}_title", :note_name => @note.id %>
+</h2>
+
+<%= render :partial => "map", :object => @note %>
+
+<table class="browse_details">
+
+  <tr>
+    <th><%= t "browse.note.opened" %></th>
+    <td><%= t "browse.note.at_by", :when => friendly_date(@note.created_at), :user => note_author(@note) %></td>
+  </tr>  
+
+  <% if @note.status == "closed" %>
+    <tr>
+      <th><%= t "browse.note.closed" %></th>
+      <td><%= t "browse.note.at_by", :when => friendly_date(@note.closed_at), :user => note_author(@note.comments.last) %></td>
+    </tr>  
+  <% elsif @note.comments.length > 1 %>
+    <tr>
+      <th><%= t "browse.note.last_modified" %></th>
+      <td><%= t "browse.note.at_by", :when => friendly_date(@note.updated_at), :user => note_author(@note.comments.last) %></td>
+    </tr>  
+  <% end %>
+
+  <tr>
+    <th><%= t "browse.note.description" %></th>
+    <td><%= h(@note.comments.first.body) %></td>
+  </tr>
+
+  <tr>
+    <th><%= t "browse.node_details.coordinates" %></th>
+    <td><div class="geo"><%= link_to ("<span class='latitude'>#{number_with_delimiter(@note.lat)}</span>, <span class='longitude'>#{number_with_delimiter(@note.lon)}</span>"), {:controller => 'site', :action => 'index', :lat => h(@note.lat), :lon => h(@note.lon), :zoom => "18"} %></div></td>
+  </tr>
+
+  <% if @note.comments.length > 1 %>
+    <tr valign="top">
+      <th><%= t "browse.note.comments" %></th>
+      <td class="browse_comments">
+        <table>
+          <% @note.comments[1..-1].each do |comment| %>
+            <tr>
+              <td>
+                <%= h(comment.body) %>
+                <br />
+                <span class="by"><%= t "browse.note.at_by", :when => friendly_date(comment.created_at), :user => note_author(comment) %></span>
+              </td>
+            </tr>
+          <% end %>
+        </table>
+      </td>
+    </tr>
+  <% end %>
+
+</table>
diff --git a/app/views/note/_description.html.erb b/app/views/note/_description.html.erb
new file mode 100644 (file)
index 0000000..596d632
--- /dev/null
@@ -0,0 +1,8 @@
+<div>
+  <% description.comments.each do |comment| -%>
+  <div class="note-comment" style="margin-top: 5px">
+    <div class="note-comment-description" style="font-size: smaller; color: #999999"><%= t "note.description.#{comment.event}_at_by", :when => friendly_date(comment.created_at), :user => note_author(comment, :only_path => false) %></div>
+    <div class="note-comment-text"><%= comment.body %></div>
+  </div>
+  <% end -%>
+</div>
diff --git a/app/views/note/_note.gpx.builder b/app/views/note/_note.gpx.builder
new file mode 100644 (file)
index 0000000..4b9aa98
--- /dev/null
@@ -0,0 +1,15 @@
+xml.wpt("lon" => note.lon, "lat" => note.lat) do
+  xml.desc do
+    xml.cdata! render(:partial => "description", :object => note, :formats => [ :html ])
+  end
+
+  xml.extension do
+    if note.status = "open"
+      xml.closed "0"
+    else
+      xml.closed "1"
+    end
+
+    xml.id note.id
+  end
+end
diff --git a/app/views/note/_note.json.jsonify b/app/views/note/_note.json.jsonify
new file mode 100644 (file)
index 0000000..ba9ccd9
--- /dev/null
@@ -0,0 +1,22 @@
+json.type "Feature"
+
+json.geometry do
+  json.type "Point"
+  json.coordinates [ note.lon, note.lat ]              
+end
+
+json.properties do
+  json.id note.id
+  json.date_created note.created_at
+  json.nearby  note.nearby_place
+  json.status note.status
+  json.closed_at note.closed_at if note.status == "closed"
+
+  json.comments(note.comments) do |comment|
+    json.date comment.created_at
+    json.uid comment.author_id unless comment.author_id.nil?
+    json.user comment.author_name
+    json.action comment.event
+    json.text comment.body unless comment.body.nil?
+  end
+end
diff --git a/app/views/note/_note.rss.builder b/app/views/note/_note.rss.builder
new file mode 100644 (file)
index 0000000..90d5757
--- /dev/null
@@ -0,0 +1,18 @@
+xml.item do
+  if note.status == "closed"
+    xml.title t('note.rss.closed', :place => note.nearby_place)        
+  elsif note.comments.length > 1
+    xml.title t('note.rss.comment', :place => note.nearby_place)
+  else
+    xml.title t('note.rss.new', :place => note.nearby_place)
+  end
+
+  xml.link url_for(:controller => "browse", :action => "note", :id => note.id, :only_path => false)
+  xml.guid url_for(:controller => "note", :action => "read", :id => note.id, :only_path => false)
+  xml.description render(:partial => "description", :object => note, :formats => [ :html ])
+  xml.author note.author_name
+  xml.pubDate note.updated_at.to_s(:rfc822)
+  xml.geo :lat, note.lat
+  xml.geo :long, note.lon
+  xml.georss :point, "#{note.lat} #{note.lon}"
+end
diff --git a/app/views/note/_note.xml.builder b/app/views/note/_note.xml.builder
new file mode 100644 (file)
index 0000000..2a2b2ff
--- /dev/null
@@ -0,0 +1,21 @@
+xml.note("lon" => note.lon, "lat" => note.lat) do
+  xml.id note.id
+  xml.date_created note.created_at
+  xml.nearby note.nearby_place
+  xml.status note.status
+
+  if note.status == "closed"
+    xml.date_closed note.closed_at
+  end
+
+  xml.comments do
+    note.comments.each do |comment|
+      xml.comment do
+        xml.date comment.created_at
+        xml.uid comment.author_id unless comment.author_id.nil?
+        xml.user comment.author_name
+        xml.text comment.body
+      end      
+    end
+  end
+end
diff --git a/app/views/note/_notes_paging_nav.html.erb b/app/views/note/_notes_paging_nav.html.erb
new file mode 100644 (file)
index 0000000..108cbb3
--- /dev/null
@@ -0,0 +1,17 @@
+<p>
+
+<% if @page > 1 %>
+<%= link_to t('changeset.changeset_paging_nav.previous'), params.merge({ :page => @page - 1 }) %>
+<% else %>
+<%= t('changeset.changeset_paging_nav.previous') %>
+<% end %>
+
+| <%= t('changeset.changeset_paging_nav.showing_page', :page => @page) %> |
+
+<% if @notes.size < @page_size %>
+<%= t('changeset.changeset_paging_nav.next') %>
+<% else %>
+<%= link_to t('changeset.changeset_paging_nav.next'), params.merge({ :page => @page + 1 }) %>
+<% end %>
+
+</p>
diff --git a/app/views/note/_user.html.erb b/app/views/note/_user.html.erb
new file mode 100644 (file)
index 0000000..0e95076
--- /dev/null
@@ -0,0 +1 @@
+<%= link_to user.display_name, :controller => "user", :action => "view", :display_name => user.display_name %>
diff --git a/app/views/note/list.gpx.builder b/app/views/note/list.gpx.builder
new file mode 100644 (file)
index 0000000..7a30460
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct!
+
+xml.gpx("version" => "1.1", 
+        "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
+        "xsi:schemaLocation" => "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd") do
+  xml << render(:partial => "note", :collection => @notes)
+end
diff --git a/app/views/note/list.json.jsonify b/app/views/note/list.json.jsonify
new file mode 100644 (file)
index 0000000..cb75d41
--- /dev/null
@@ -0,0 +1,5 @@
+json.type "FeatureCollection"
+
+json.features(@notes) do |note|
+  json.ingest! render(:partial => "note", :object => note)
+end
diff --git a/app/views/note/list.rss.builder b/app/views/note/list.rss.builder
new file mode 100644 (file)
index 0000000..d6ee2bb
--- /dev/null
@@ -0,0 +1,13 @@
+xml.instruct!
+
+xml.rss("version" => "2.0", 
+        "xmlns:geo" => "http://www.w3.org/2003/01/geo/wgs84_pos#",
+        "xmlns:georss" => "http://www.georss.org/georss") do
+  xml.channel do
+    xml.title t('note.rss.title')
+    xml.description t('note.rss.description_area', :min_lat => @min_lat, :min_lon => @min_lon, :max_lat => @max_lat, :max_lon => @max_lon )
+    xml.link url_for(:controller => "site", :action => "index", :only_path => false)
+
+    xml << render(:partial => "note", :collection => @notes)
+  end
+end
diff --git a/app/views/note/list.xml.builder b/app/views/note/list.xml.builder
new file mode 100644 (file)
index 0000000..38b239a
--- /dev/null
@@ -0,0 +1,3 @@
+xml.instruct!
+
+xml << render(:partial => "note", :collection => @notes)
diff --git a/app/views/note/mine.html.erb b/app/views/note/mine.html.erb
new file mode 100644 (file)
index 0000000..50c15cd
--- /dev/null
@@ -0,0 +1,37 @@
+<h1><%= @heading %></h1>
+<p><%= raw @description %></p>
+
+<%= render :partial => 'notes_paging_nav' %>
+
+<table id="note_list" cellpadding="3">
+  <tr>
+    <th></th>
+    <th><%= t'note.mine.id' %></th>
+    <th><%= t'changeset.changesets.user' %></th>
+    <th><%= t'changeset.changesets.comment' %></th>
+    <th><%= t'changeset.changesets.saved_at' %></th>
+    <th><%= t'note.mine.last_changed' %></th>
+  </tr>
+<% @notes.each do |note| -%>
+  <tr<% if note.author != @user2 %> bgcolor="#EEEEEE"<% end %>>
+    <td>
+      <% if note.status == "closed" %>
+        <%= image_tag("closed_note_marker.png", :alt => 'closed') %>
+      <% else %>
+        <%= image_tag("open_note_marker.png", :alt => 'open') %>
+      <% end %>
+    </td>
+    <td><%= link_to note.id.to_s, :controller => "browse", :action => "note", :id => note.id %></td>
+    <% if note.author.nil? %> 
+      <td> <%= note.author_name %> </td> 
+    <% else %> 
+      <td><%= link_to h(note.author_name), :controller => "user", :action => "view", :display_name => note.author_name %></td>
+    <% end %>
+    <td> <%= htmlize note.comments.first.body  %> </td>        
+    <td><%= l note.created_at %></td>
+    <td><%= l note.updated_at %></td>
+  </tr>
+<% end -%>
+</table>
+
+<%= render :partial => 'notes_paging_nav' %>
diff --git a/app/views/note/read.gpx.builder b/app/views/note/read.gpx.builder
new file mode 100644 (file)
index 0000000..e54d772
--- /dev/null
@@ -0,0 +1,7 @@
+xml.instruct!
+
+xml.gpx("version" => "1.1", 
+        "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
+        "xsi:schemaLocation" => "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd") do
+  xml << render(:partial => "note", :object => @note)
+end
diff --git a/app/views/note/read.json.jsonify b/app/views/note/read.json.jsonify
new file mode 100644 (file)
index 0000000..3e5685f
--- /dev/null
@@ -0,0 +1 @@
+json.ingest! render(:partial => "note", :object => @note)
diff --git a/app/views/note/read.rss.builder b/app/views/note/read.rss.builder
new file mode 100644 (file)
index 0000000..e566ff0
--- /dev/null
@@ -0,0 +1,13 @@
+xml.instruct!
+
+xml.rss("version" => "2.0", 
+        "xmlns:geo" => "http://www.w3.org/2003/01/geo/wgs84_pos#",
+        "xmlns:georss" => "http://www.georss.org/georss") do
+  xml.channel do
+    xml.title t('note.rss.title')
+    xml.description t('note.rss.description_item', :id => @note.id)
+    xml.link url_for(:controller => "site", :action => "index", :only_path => false)
+
+    xml << render(:partial => "note", :object => @note)
+  end
+end
diff --git a/app/views/note/read.xml.builder b/app/views/note/read.xml.builder
new file mode 100644 (file)
index 0000000..cfb28c2
--- /dev/null
@@ -0,0 +1,3 @@
+xml.instruct!
+
+xml << render(:partial => "note", :object => @note)
diff --git a/app/views/note/rss.rss.builder b/app/views/note/rss.rss.builder
new file mode 100644 (file)
index 0000000..d22d673
--- /dev/null
@@ -0,0 +1,46 @@
+xml.instruct!
+
+xml.rss("version" => "2.0", 
+        "xmlns:geo" => "http://www.w3.org/2003/01/geo/wgs84_pos#",
+        "xmlns:georss" => "http://www.georss.org/georss") do
+  xml.channel do
+    xml.title t('note.rss.title')
+    xml.description t('note.rss.description_area', :min_lat => @min_lat, :min_lon => @min_lon, :max_lat => @max_lat, :max_lon => @max_lon )
+    xml.link url_for(:controller => "site", :action => "index", :only_path => false)
+
+    @comments.each do |comment|
+      xml.item do
+        if comment.event == "closed"
+          xml.title t('note.rss.closed', :place => comment.note.nearby_place)  
+        elsif comment.event == "commented"
+          xml.title t('note.rss.comment', :place => comment.note.nearby_place)
+        elsif comment.event == "opened"
+          xml.title t('note.rss.new', :place => comment.note.nearby_place)
+        else
+          xml.title "unknown event"
+        end
+        
+        xml.link url_for(:controller => "browse", :action => "note", :id => comment.note.id, :only_path => false)
+        xml.guid url_for(:controller => "browse", :action => "note", :id => comment.note.id, :only_path => false)
+
+        description_text = ""
+
+        if comment.event == "commented" and not comment.nil?
+          description_text += "<b>Comment:</b><br>"
+          description_text += htmlize(comment.body)
+          description_text += "<br>"
+        end
+
+        description_text += "<b>Full note:</b><br>"
+        description_text += comment.note.flatten_comment("<br>", comment.created_at)
+
+        xml.description description_text 
+        xml.author comment.author_name
+        xml.pubDate comment.created_at.to_s(:rfc822)
+        xml.geo :lat, comment.note.lat
+        xml.geo :long, comment.note.lon
+        xml.georss :point, "#{comment.note.lat} #{comment.note.lon}"
+      end
+    end
+  end
+end
diff --git a/app/views/notifier/note_comment_notification.html.erb b/app/views/notifier/note_comment_notification.html.erb
new file mode 100644 (file)
index 0000000..fade148
--- /dev/null
@@ -0,0 +1,15 @@
+<%= t 'notifier.note_plain.greeting' %>
+
+<% if @owner %>
+<%= t 'notifier.note_plain.your_note', :commenter => @commenter, :place => @place %>
+<% else %>
+<%= t 'notifier.note_plain.commented_note', :commenter => @commenter, :place => @place %>
+<% end %>
+
+==
+<%= @comment %>
+==
+
+<%= t 'notifier.note_plain.details', :URL => @noteurl %>
+
+
index 0c47227f8ebd420066da62691ff3ea175813a1f8..88489610994ac6c5934a60264729d0554105119c 100644 (file)
@@ -20,6 +20,7 @@
   <div id="permalink">
     <a href="/" id="permalinkanchor" class="geolink llz layers object"><%= t 'site.index.permalink' %></a>
     <a href="/" id="shortlinkanchor"><%= t 'site.index.shortlink' %></a>
+    <a href="#" id="createnoteanchor">Report a problem</a>     
   </div>
 </div>
 
@@ -131,6 +132,10 @@ end
 
   OpenLayers.Lang.setCode("<%= I18n.locale.to_s %>");
 
+  <% if @user %>
+    var loginName = "<%= @user.display_name %>"
+  <% end %>
+
   function mapInit(){
     map = createMap("map");
 
@@ -138,6 +143,65 @@ end
       map.dataLayer = new OpenLayers.Layer("<%= I18n.t 'browse.start_rjs.data_layer_name' %>", { "visibility": false });
       map.dataLayer.events.register("visibilitychanged", map.dataLayer, toggleData);
       map.addLayer(map.dataLayer);
+
+      map.noteLayer = new OpenLayers.Layer.Vector("Notes", {
+          visibility: false,
+          projection: new OpenLayers.Projection("EPSG:4326"),
+          styleMap: new OpenLayers.StyleMap(new OpenLayers.Style({
+              graphicWidth: 22,
+              graphicHeight: 22,
+              graphicOpacity: 0.7,
+              graphicXOffset: -11,
+              graphicYOffset: -11
+          }, {
+              rules: [
+                  new OpenLayers.Rule({
+                      filter: new OpenLayers.Filter.Comparison({
+                          type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                          property: "status",
+                          value: "open"
+                      }),
+                      symbolizer: {
+                          externalGraphic: "<%= image_path 'open_note_marker.png' %>"
+                      }
+                  }),
+                  new OpenLayers.Rule({
+                      filter: new OpenLayers.Filter.Comparison({
+                          type: OpenLayers.Filter.Comparison.EQUAL_TO,
+                          property: "status",
+                          value: "closed"
+                      }),
+                      symbolizer: {
+                          externalGraphic: "<%= image_path 'closed_note_marker.png' %>"
+                      }
+                 })
+              ]
+          })),
+          strategies: [
+              new OpenLayers.Strategy.BBOX()
+          ],
+          protocol: new OpenLayers.Protocol.HTTP({
+              url: "<%= url_for :controller => :note, :action => :list, :format => :json %>",
+              format: new OpenLayers.Format.GeoJSON(),
+              callback: noteCallback
+          })
+      });
+      map.noteLayer.events.register("featureselected", map, noteSelected);
+      map.noteLayer.events.register("featureunselected", map, noteUnselected);
+      map.addLayer(map.noteLayer);
+
+      map.noteControl = new OpenLayers.Control.SelectFeature(map.noteLayer, {
+          autoActivate: true
+      });
+      map.addControl(map.noteControl);
+
+      <% if params[:notes] == "yes" -%>
+      map.noteLayer.setVisibility(true);
+      <% end -%>
+
+      $("#createnoteanchor").click(addNote);
+
+      map.events.register("zoomend", map, allowNoteReports);
     <% end %>
 
     <% unless object_zoom %>
@@ -265,6 +329,46 @@ end
     <% end %>
   }
 
+  function noteCallback(scope, response) {
+    for (var f = 0; f < response.features.length; f++) {
+      var feature = response.features[f];
+    }
+  }
+
+  function noteSelected(o) {
+    var feature = o.feature;
+    var location = feature.geometry.getBounds().getCenterLonLat();
+
+    feature.popup = new OpenLayers.Popup.FramedCloud(
+      feature.attributes.id, location, null,
+      "<p>" + feature.attributes.id + "</p>",
+      null, true, function (e) { map.noteControl.unselect(feature) }
+    );
+
+    map.addPopup(feature.popup);
+//    feature.popup.show();
+  }
+
+  function noteUnselected(o) {
+    var feature = o.feature;
+
+    map.removePopup(feature.popup);
+    delete feature.popup;
+  }
+
+  function addNote() {
+    map.noteLayer.setVisibility(true);
+    map.noteLayer.addNote(map.getCenter());
+  }
+
+  function allowNoteReports() { 
+    if (map.getZoom() > 11) {
+      $("#createnoteanchor").show();
+    } else {
+      $("#createnoteanchor").hide();
+    }
+  }
+
   $(document).ready(mapInit);
   $(document).ready(installEditHandler);
   $(document).ready(handleResize);
index b323ff1580d5901c7d1ffff86ac1645baddf8dbb..834a8528f0c63683edbfd18e499b9d269620e55e 100644 (file)
@@ -25,7 +25,9 @@
     |
     <%= link_to t('user.view.my edits'), :controller => 'changeset', :action => 'list', :display_name => @user.display_name %>
     |
-    <%= link_to t('user.view.my traces'), :controller => 'trace', :action=>'mine' %>
+    <%= link_to t('user.view.my traces'), :controller => 'trace', :action=> 'mine' %>
+    |
+    <%= link_to t('user.view.my notes'), :controller => 'note', :action=> 'mine' %>
     |
     <%= link_to t('user.view.my settings'), :controller => 'user', :action => 'account', :display_name => @user.display_name %>
     |
@@ -47,6 +49,8 @@
     |
     <%= link_to t('user.view.traces'), :controller => 'trace', :action => 'list', :display_name => @this_user.display_name %>
     |
+    <%= link_to t('user.view.notes'), :controller => 'note', :action=> 'mine' %>
+    |
     <% if @user and @user.is_friends_with?(@this_user) %>
       <%= link_to t('user.view.remove as friend'), :controller => 'user', :action => 'remove_friend', :display_name => @this_user.display_name %>
     <% else %>
index 420278a1f87d9e8d5c6c89e5f7b990e89004364a..501b3d2ad4bdbbc64d94faded0b929d7ac304d17 100644 (file)
@@ -24,6 +24,8 @@ defaults: &defaults
   max_number_of_nodes: 50000
   # Maximum number of nodes that can be in a way (checked on save)
   max_number_of_way_nodes: 2000
+  # The maximum area you're allowed to request notes from, in square degrees
+  max_note_request_area: 25
   # Zoom level to use for postcode results from the geocoder
   postcode_zoom: 15
   # Zoom level to use for geonames results from the geocoder
index c676f6e46c50aa019fcb728a648bd0998d8ec89e..be247274f290811f0ccf61b7dee2b6a488343bc9 100644 (file)
@@ -4,3 +4,4 @@
 # Mime::Type.register "text/richtext", :rtf
 # Mime::Type.register_alias "text/html", :iphone
 Mime::Type.register "application/x-amf", :amf
+Mime::Type.register "application/gpx+xml", :gpx
index 49b8357421b911834e11ddd00f65303ae7400754..3f196feed4903937415de292298c00da4af875e0 100644 (file)
@@ -930,6 +930,22 @@ de:
       history_disabled_tooltip: Reinzoomen um Änderungen für diesen Bereich anzuzeigen
       history_tooltip: Änderungen für diesen Bereich anzeigen
       history_zoom_alert: Du musst näher heranzoomen, um die Chronik zu sehen
+    osb:
+      Fixed Error: Behobener Fehler
+      Unresolved Error: Offener Fehler
+      Description: Beschreibung
+      Comment: Kommentar
+      Has been fixed: Der Fehler wurde bereits behoben. Es kann jedoch bis zu einigen Tagen dauern, bis die Kartenansicht aktualisiert wird.
+      Comment/Close: Kommentieren/Schließen
+      Nickname: Benutzername
+      Add comment: Kommentar hinzufügen
+      Mark as fixed: Als behoben markieren
+      Cancel: Abbrechen
+      Create OpenStreetBug: OpenStreetBug melden
+      Create bug: Bug anlegen
+      Bug description: Fehlerbeschreibung
+      Create: Anlegeeen
+      Permalink: Permalink
   layouts: 
     community_blogs: Blogs
     community_blogs_title: Blogs von Mitwirkenden bei OpenStreetMap
index c431de33e6821e31f6f049da4cda5a8268e86a8b..3e9908bb562b31bdda3fd5c5e44fac7f8b5e007b 100644 (file)
@@ -121,6 +121,8 @@ en:
         next_relation_tooltip: "Next relation"
         prev_changeset_tooltip: "Previous changeset"
         next_changeset_tooltip: "Next changeset"
+        prev_note_tooltip: "Previous note"
+        next_note_tooltip: "Next note"
     changeset_details:
       created_at: "Created at:"
       closed_at: "Closed at:"
@@ -282,6 +284,15 @@ en:
       download_xml: "Download XML"
       view_history: "view history"
       edit: "edit"
+    note:
+      open_title: "Unresolved issue: %{note_name}"
+      closed_title: "Resolved issue: %{note_name}"
+      opened: "Opened:"
+      last_modified: "Last modified:"
+      closed: "Closed:"
+      at_by: "%{when} ago by %{user}"
+      description: "Description:"
+      comments: "Comments:"
   changeset:
     changeset_paging_nav:
       showing_page: "Showing page %{page}"
@@ -1194,6 +1205,13 @@ en:
       greeting: "Hi,"
       hopefully_you: "Someone (possibly you) has asked for the password to be reset on this email address's openstreetmap.org account."
       click_the_link: "If this is you, please click the link below to reset your password."
+    note_plain:
+      subject_own: "[OpenStreetMap] %{commenter} has commented on one of your notes"
+      subject_other: "[OpenStreetMap] %{commenter} has commented on a note you are interested in"
+      greeting: "Hi,"
+      your_note: "%{commenter} has left a comment on one of your map notes near %{place}."
+      commented_note: "%{commenter} has left a comment on a map note you have commented on. The note is near %{place}."
+      details: "More details about the note can be found at %{URL}."
   message:
     inbox:
       title: "Inbox"
@@ -1669,6 +1687,7 @@ en:
       new diary entry: new diary entry
       my edits: my edits
       my traces: my traces
+      my notes: my map notes
       my settings: my settings
       my comments: my comments
       oauth settings: oauth settings
@@ -1678,6 +1697,7 @@ en:
       diary: diary
       edits: edits
       traces: traces
+      notes: map notes
       remove as friend: remove as friend
       add as friend: add as friend
       mapper since: "Mapper since:"
@@ -1938,6 +1958,25 @@ en:
       back: "View all blocks"
       revoker: "Revoker:"
       needs_view: "The user needs to log in before this block will be cleared."
+  note:
+    description:
+      opened_at_by: "Created %{when} ago by %{user}"
+      commented_at_by: "Updated %{when} ago by %{user}"
+      closed_at_by: "Resolved %{when} ago by %{user}"
+      reopened_at_by: "Reactivated %{when} ago by %{user}"
+    rss:
+      title: "OpenStreetMap Notes"
+      description_area: "A list of notes, reported, commented on or closed in your area [(%{min_lat}|%{min_lon}) -- (%{max_lat}|%{max_lon})]"
+      description_item: "An rss feed for note %{id}"
+      closed: "closed note (near %{place})"
+      new: "new note (near %{place})"
+      comment: "new comment (near %{place})"
+    mine:
+      title: "Notes submitted or commented on by %{user}"
+      heading: "%{user}'s notes"
+      description: "Notes submitted or commented on by %{user}"
+      id: "Id"
+      last_changed: "Last changed"
   javascripts:
     map:
       base:
@@ -1954,3 +1993,23 @@ en:
       history_tooltip: View edits for this area
       history_disabled_tooltip: Zoom in to view edits for this area
       history_zoom_alert: You must zoom in to view edits for this area
+    note:
+      closed: Closed Note
+      open: Open Note
+      details: Details
+      permalink: Permalink
+      description: Description
+      comment: Comment
+      render_warning: This error has been fixed already. However, it might take a couple of days before the map image is updated.
+      update: Update
+      nickname: Nickname
+      login: Login
+      add_comment: Add Comment
+      close: Close
+      cancel: Cancel
+      create: Create Note
+      create_title: Report a problem with the map
+      create_help1: Please drag the marker to the location of the problem
+      create_help2: and descripe it as accurate as possible
+      report: Report Problem
+      edityourself: You can also edit the map directly your self
index cb02728e31e3139eb9a22f4df09dc3fc4023c53b..eb3be435f5e8bb32f333e939cd0ede69004fafc9 100644 (file)
@@ -29,12 +29,15 @@ OpenLayers/Layer/Vector.js
 OpenLayers/Tile.js
 OpenLayers/Tile/Image.js
 OpenLayers/Feature/Vector.js
+OpenLayers/Format/GeoJSON.js
 OpenLayers/Format/GML.js
 OpenLayers/Format/OSM.js
 OpenLayers/Geometry/Point.js
 OpenLayers/Geometry/LinearRing.js
 OpenLayers/Handler/Point.js
 OpenLayers/Handler/RegularPolygon.js
+OpenLayers/Strategy/BBOX.js
+OpenLayers/Protocol/HTTP.js
 OpenLayers/Renderer.js
 OpenLayers/Renderer/Canvas.js
 OpenLayers/Renderer/SVG.js
index 5952bae52cc4f320deb2eb9869bf9e0aac6dfa5d..e466fc3627d807d5635256c0de2b4f86efbc7faa 100644 (file)
@@ -69,11 +69,25 @@ OpenStreetMap::Application.routes.draw do
   match 'api/0.6/gpx/:id/data' => 'trace#api_data', :via => :get
   
   # AMF (ActionScript) API
-
   match 'api/0.6/amf/read' => 'amf#amf_read', :via => :post
   match 'api/0.6/amf/write' => 'amf#amf_write', :via => :post
   match 'api/0.6/swf/trackpoints' => 'swf#trackpoints', :via => :get
 
+  # Map notes API
+  match 'api/0.6/notes' => 'note#list', :format => :xml
+  match 'api/0.6/notes/search' => 'note#search', :format => :xml
+  match 'api/0.6/notes/rss'  => 'note#rss', :format => :rss
+  match 'api/0.6/note/create' => 'note#create'
+  match 'api/0.6/note/:id/comment' => 'note#update', :id => /\d+/
+  match 'api/0.6/note/:id/close' => 'note#close', :id => /\d+/
+  match 'api/0.6/note/:id' => 'note#read', :via => :get, :id => /\d+/, :format => :xml
+  match 'api/0.6/note/:id' => 'note#delete', :via => :delete, :id => /\d+/
+  match 'api/0.6/notes/addPOIexec' => 'note#create'
+  match 'api/0.6/notes/closePOIexec' => 'note#close'
+  match 'api/0.6/notes/editPOIexec' => 'note#update'
+  match 'api/0.6/notes/getGPX' => 'note#list', :format => :gpx
+  match 'api/0.6/notes/getRSSfeed' => 'note#rss', :format => :rss
+
   # Data browsing
   match '/browse/start' => 'browse#start', :via => :get
   match '/browse/way/:id' => 'browse#way', :via => :get, :id => /\d+/
@@ -83,8 +97,10 @@ OpenStreetMap::Application.routes.draw do
   match '/browse/relation/:id' => 'browse#relation', :via => :get, :id => /\d+/
   match '/browse/relation/:id/history' => 'browse#relation_history', :via => :get, :id => /\d+/
   match '/browse/changeset/:id' => 'browse#changeset', :via => :get, :as => :changeset, :id => /\d+/
+  match '/browse/note/:id' => 'browse#note', :via => :get, :id => /\d+/
   match '/user/:display_name/edits' => 'changeset#list', :via => :get
   match '/user/:display_name/edits/feed' => 'changeset#feed', :via => :get, :format => :atom
+  match '/user/:display_name/notes' => 'note#mine', :via => :get
   match '/browse/friends' => 'changeset#list', :via => :get, :friends => true, :as => "friend_changesets"
   match '/browse/nearby' => 'changeset#list', :via => :get, :nearby => true, :as => "nearby_changesets"
   match '/browse/changesets' => 'changeset#list', :via => :get
diff --git a/db/migrate/053_add_map_bug_tables.rb b/db/migrate/053_add_map_bug_tables.rb
new file mode 100644 (file)
index 0000000..8d444a4
--- /dev/null
@@ -0,0 +1,33 @@
+require 'lib/migrate'
+
+class AddMapBugTables < ActiveRecord::Migration
+  def self.up
+    create_enumeration :map_bug_status_enum, ["open", "closed", "hidden"]
+
+    create_table :map_bugs do |t|
+      t.column :id, :bigint, :null => false 
+      t.integer :latitude, :null => false 
+      t.integer :longitude, :null => false 
+      t.column :tile, :bigint, :null => false
+      t.datetime :last_changed, :null => false
+      t.datetime :date_created, :null => false 
+      t.string :nearby_place 
+      t.string :text
+      t.column :status, :map_bug_status_enum, :null => false
+    end
+
+    add_index :map_bugs, [:tile, :status], :name => "map_bugs_tile_idx"
+    add_index :map_bugs, [:last_changed], :name => "map_bugs_changed_idx"
+    add_index :map_bugs, [:date_created], :name => "map_bugs_created_idx"
+  end
+
+  def self.down
+    remove_index :map_bugs, :name => "map_bugs_tile_idx"
+    remove_index :map_bugs, :name => "map_bugs_changed_idx"
+    remove_index :map_bugs, :name => "map_bugs_created_idx"
+
+    drop_table :map_bugs
+
+    drop_enumeration :map_bug_status_enum
+  end
+end
diff --git a/db/migrate/054_refactor_map_bug_tables.rb b/db/migrate/054_refactor_map_bug_tables.rb
new file mode 100644 (file)
index 0000000..6d259d2
--- /dev/null
@@ -0,0 +1,34 @@
+require 'lib/migrate'
+
+class RefactorMapBugTables < ActiveRecord::Migration
+  def self.up
+    create_table :map_bug_comment do |t|
+      t.column :id, :bigint, :null => false
+      t.column :bug_id, :bigint, :null => false
+      t.boolean :visible, :null => false 
+      t.datetime :date_created, :null => false
+      t.string :commenter_name
+      t.string :commenter_ip
+      t.column :commenter_id, :bigint
+      t.string :comment
+    end
+
+    remove_column :map_bugs, :text 
+
+    add_index :map_bug_comment, [:bug_id], :name => "map_bug_comment_id_idx"
+
+    add_foreign_key :map_bug_comment, [:bug_id], :map_bugs, [:id]
+    add_foreign_key :map_bug_comment, [:commenter_id], :users, [:id]
+  end
+
+  def self.down
+    remove_foreign_key :map_bug_comment, [:commenter_id]
+    remove_foreign_key :map_bug_comment, [:bug_id]
+
+    remove_index :map_bugs, :name => "map_bug_comment_id_idx"
+
+    add_column :map_bugs, :text, :string
+
+    drop_table :map_bug_comment
+  end
+end
diff --git a/db/migrate/055_change_map_bug_comment_type.rb b/db/migrate/055_change_map_bug_comment_type.rb
new file mode 100644 (file)
index 0000000..2a64bf2
--- /dev/null
@@ -0,0 +1,11 @@
+require 'lib/migrate'
+
+class ChangeMapBugCommentType < ActiveRecord::Migration
+  def self.up
+    change_column :map_bug_comment, :comment, :text
+  end
+
+  def self.down
+    change_column :map_bug_comment, :comment, :string
+  end
+end
diff --git a/db/migrate/056_add_date_closed.rb b/db/migrate/056_add_date_closed.rb
new file mode 100644 (file)
index 0000000..c5aa2c2
--- /dev/null
@@ -0,0 +1,11 @@
+require 'lib/migrate'
+
+class AddDateClosed < ActiveRecord::Migration
+  def self.up
+    add_column :map_bugs, :date_closed, :timestamp
+  end
+
+  def self.down
+    remove_column :map_bugs, :date_closed 
+  end
+end
diff --git a/db/migrate/057_add_map_bug_comment_event.rb b/db/migrate/057_add_map_bug_comment_event.rb
new file mode 100644 (file)
index 0000000..c13c1f9
--- /dev/null
@@ -0,0 +1,15 @@
+require 'lib/migrate'
+
+class AddMapBugCommentEvent < ActiveRecord::Migration
+  def self.up
+    create_enumeration :map_bug_event_enum, ["opened", "closed", "reopened", "commented", "hidden"]
+
+    add_column :map_bug_comment, :event, :map_bug_event_enum
+  end
+
+  def self.down
+    remove_column :map_bug_comment, :event
+
+    drop_enumeration :map_bug_event_enum
+  end
+end
diff --git a/db/migrate/20110508145337_cleanup_bug_tables.rb b/db/migrate/20110508145337_cleanup_bug_tables.rb
new file mode 100644 (file)
index 0000000..e7dfcb7
--- /dev/null
@@ -0,0 +1,25 @@
+class CleanupBugTables < ActiveRecord::Migration
+  def self.up
+    rename_column :map_bugs, :date_created, :created_at
+    rename_column :map_bugs, :last_changed, :updated_at
+    rename_column :map_bugs, :date_closed, :closed_at
+
+    rename_column :map_bug_comment, :date_created, :created_at
+    rename_column :map_bug_comment, :commenter_name, :author_name
+    rename_column :map_bug_comment, :commenter_ip, :author_ip
+    rename_column :map_bug_comment, :commenter_id, :author_id
+    rename_column :map_bug_comment, :comment, :body
+  end
+
+  def self.down
+    rename_column :map_bug_comment, :body, :comment
+    rename_column :map_bug_comment, :author_id, :commenter_id
+    rename_column :map_bug_comment, :author_ip, :commenter_ip
+    rename_column :map_bug_comment, :author_name, :commenter_name
+    rename_column :map_bug_comment, :created_at, :date_created
+
+    rename_column :map_bugs, :closed_at, :date_closed
+    rename_column :map_bugs, :updated_at, :last_changed
+    rename_column :map_bugs, :created_at, :date_created
+  end
+end
diff --git a/db/migrate/20110521142405_rename_bugs_to_notes.rb b/db/migrate/20110521142405_rename_bugs_to_notes.rb
new file mode 100644 (file)
index 0000000..240d447
--- /dev/null
@@ -0,0 +1,55 @@
+require 'lib/migrate'
+
+class RenameBugsToNotes < ActiveRecord::Migration
+  def self.up
+    rename_enumeration "map_bug_status_enum", "note_status_enum"
+    rename_enumeration "map_bug_event_enum", "note_event_enum"
+
+    rename_table :map_bugs, :notes
+    rename_sequence :notes, "map_bugs_id_seq", "notes_id_seq"
+    rename_index :notes, "map_bugs_pkey", "notes_pkey"
+    rename_index :notes, "map_bugs_changed_idx", "notes_updated_at_idx"
+    rename_index :notes, "map_bugs_created_idx", "notes_created_at_idx"
+    rename_index :notes, "map_bugs_tile_idx", "notes_tile_status_idx"
+
+    remove_foreign_key :map_bug_comment, [:bug_id], :map_bugs, [:id]
+    rename_column :map_bug_comment, :author_id, :commenter_id
+    remove_foreign_key :map_bug_comment, [:commenter_id], :users, [:id]
+    rename_column :map_bug_comment, :commenter_id, :author_id
+
+    rename_table :map_bug_comment, :note_comments
+    rename_column :note_comments, :bug_id, :note_id
+    rename_sequence :note_comments, "map_bug_comment_id_seq", "note_comments_id_seq"
+    rename_index :note_comments, "map_bug_comment_pkey", "note_comments_pkey"
+    rename_index :note_comments, "map_bug_comment_id_idx", "note_comments_note_id_idx"
+
+    add_foreign_key :note_comments, [:note_id], :notes, [:id]
+    add_foreign_key :note_comments, [:author_id], :users, [:id]
+  end
+
+  def self.down
+    remove_foreign_key :note_comments, [:author_id], :users, [:id]
+    remove_foreign_key :note_comments, [:note_id], :notes, [:id]
+
+    rename_index :note_comments, "note_comments_note_id_idx", "map_bug_comment_id_idx"
+    rename_index :notes, "note_comments_pkey", "map_bug_comment_pkey"
+    rename_column :note_comments, :note_id, :bug_id
+    rename_sequence :note_comments, "note_comments_id_seq", "map_bug_comment_id_seq"
+    rename_table :note_comments, :map_bug_comment
+
+    rename_column :map_bug_comment, :author_id, :commenter_id
+    add_foreign_key :map_bug_comment, [:commenter_id], :users, [:id]
+    rename_column :map_bug_comment, :commenter_id, :author_id
+    add_foreign_key :map_bug_comment, [:bug_id], :notes, [:id]
+
+    rename_index :notes, "notes_tile_status_idx", "map_bugs_tile_idx"
+    rename_index :notes, "notes_created_at_idx", "map_bugs_created_idx"
+    rename_index :notes, "notes_updated_at_idx", "map_bugs_changed_idx"
+    rename_index :notes, "notes_pkey", "map_bugs_pkey"
+    rename_sequence :notes, "notes_id_seq", "map_bugs_id_seq"
+    rename_table :notes, :map_bugs
+
+    rename_enumeration "note_event_enum", "map_bug_event_enum"
+    rename_enumeration "note_status_enum", "map_bug_status_enum"
+  end
+end
index 981ad1e16c4c3f29ac3a814d0cc90c307714cac1..0cd89a11dc89def7f34b474cbb2c2188f66a4d7a 100644 (file)
@@ -38,16 +38,6 @@ COMMENT ON EXTENSION btree_gist IS 'support for indexing common datatypes in GiS
 
 SET search_path = public, pg_catalog;
 
---
--- Name: format_enum; Type: TYPE; Schema: public; Owner: -
---
-
-CREATE TYPE format_enum AS ENUM (
-    'html',
-    'markdown'
-);
-
-
 --
 -- Name: gpx_visibility_enum; Type: TYPE; Schema: public; Owner: -
 --
@@ -60,6 +50,30 @@ CREATE TYPE gpx_visibility_enum AS ENUM (
 );
 
 
+--
+-- Name: note_event_enum; Type: TYPE; Schema: public; Owner: -
+--
+
+CREATE TYPE note_event_enum AS ENUM (
+    'opened',
+    'closed',
+    'reopened',
+    'commented',
+    'hidden'
+);
+
+
+--
+-- Name: note_status_enum; Type: TYPE; Schema: public; Owner: -
+--
+
+CREATE TYPE note_status_enum AS ENUM (
+    'open',
+    'closed',
+    'hidden'
+);
+
+
 --
 -- Name: nwr_enum; Type: TYPE; Schema: public; Owner: -
 --
@@ -100,7 +114,7 @@ CREATE TYPE user_status_enum AS ENUM (
 
 CREATE FUNCTION maptile_for_point(bigint, bigint, integer) RETURNS integer
     LANGUAGE c STRICT
-    AS '/srv/www/master.osm.compton.nu/db/functions/libpgosm.so', 'maptile_for_point';
+    AS '/srv/www/openstreetbugs.osm.compton.nu/db/functions/libpgosm.so', 'maptile_for_point';
 
 
 --
@@ -109,7 +123,7 @@ CREATE FUNCTION maptile_for_point(bigint, bigint, integer) RETURNS integer
 
 CREATE FUNCTION tile_for_point(integer, integer) RETURNS bigint
     LANGUAGE c STRICT
-    AS '/srv/www/master.osm.compton.nu/db/functions/libpgosm.so', 'tile_for_point';
+    AS '/srv/www/openstreetbugs.osm.compton.nu/db/functions/libpgosm.so', 'tile_for_point';
 
 
 --
@@ -118,7 +132,7 @@ CREATE FUNCTION tile_for_point(integer, integer) RETURNS bigint
 
 CREATE FUNCTION xid_to_int4(xid) RETURNS integer
     LANGUAGE c IMMUTABLE STRICT
-    AS '/srv/www/master.osm.compton.nu/db/functions/libpgosm.so', 'xid_to_int4';
+    AS '/srv/www/openstreetbugs.osm.compton.nu/db/functions/libpgosm.so', 'xid_to_int4';
 
 
 SET default_tablespace = '';
@@ -695,6 +709,78 @@ CREATE TABLE nodes (
 );
 
 
+--
+-- Name: note_comments; Type: TABLE; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE TABLE note_comments (
+    id integer NOT NULL,
+    note_id bigint NOT NULL,
+    visible boolean NOT NULL,
+    created_at timestamp without time zone NOT NULL,
+    author_name character varying(255),
+    author_ip character varying(255),
+    author_id bigint,
+    body text,
+    event note_event_enum
+);
+
+
+--
+-- Name: note_comments_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE note_comments_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: note_comments_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE note_comments_id_seq OWNED BY note_comments.id;
+
+
+--
+-- Name: notes; Type: TABLE; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE TABLE notes (
+    id integer NOT NULL,
+    latitude integer NOT NULL,
+    longitude integer NOT NULL,
+    tile bigint NOT NULL,
+    updated_at timestamp without time zone NOT NULL,
+    created_at timestamp without time zone NOT NULL,
+    nearby_place character varying(255),
+    status note_status_enum NOT NULL,
+    closed_at timestamp without time zone
+);
+
+
+--
+-- Name: notes_id_seq; Type: SEQUENCE; Schema: public; Owner: -
+--
+
+CREATE SEQUENCE notes_id_seq
+    START WITH 1
+    INCREMENT BY 1
+    NO MINVALUE
+    NO MAXVALUE
+    CACHE 1;
+
+
+--
+-- Name: notes_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
+--
+
+ALTER SEQUENCE notes_id_seq OWNED BY notes.id;
+
+
 --
 -- Name: oauth_nonces; Type: TABLE; Schema: public; Owner: -; Tablespace: 
 --
@@ -991,9 +1077,9 @@ CREATE TABLE users (
     status user_status_enum DEFAULT 'pending'::user_status_enum NOT NULL,
     terms_agreed timestamp without time zone,
     consider_pd boolean DEFAULT false NOT NULL,
+    openid_url character varying(255),
     preferred_editor character varying(255),
     terms_seen boolean DEFAULT false NOT NULL,
-    openid_url character varying(255),
     image_fingerprint character varying(255)
 );
 
@@ -1145,6 +1231,20 @@ ALTER TABLE ONLY gpx_files ALTER COLUMN id SET DEFAULT nextval('gpx_files_id_seq
 ALTER TABLE ONLY messages ALTER COLUMN id SET DEFAULT nextval('messages_id_seq'::regclass);
 
 
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY note_comments ALTER COLUMN id SET DEFAULT nextval('note_comments_id_seq'::regclass);
+
+
+--
+-- Name: id; Type: DEFAULT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY notes ALTER COLUMN id SET DEFAULT nextval('notes_id_seq'::regclass);
+
+
 --
 -- Name: id; Type: DEFAULT; Schema: public; Owner: -
 --
@@ -1362,6 +1462,22 @@ ALTER TABLE ONLY nodes
     ADD CONSTRAINT nodes_pkey PRIMARY KEY (node_id, version);
 
 
+--
+-- Name: note_comments_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 
+--
+
+ALTER TABLE ONLY note_comments
+    ADD CONSTRAINT note_comments_pkey PRIMARY KEY (id);
+
+
+--
+-- Name: notes_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 
+--
+
+ALTER TABLE ONLY notes
+    ADD CONSTRAINT notes_pkey PRIMARY KEY (id);
+
+
 --
 -- Name: oauth_nonces_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: 
 --
@@ -1712,6 +1828,34 @@ CREATE INDEX nodes_tile_idx ON nodes USING btree (tile);
 CREATE INDEX nodes_timestamp_idx ON nodes USING btree ("timestamp");
 
 
+--
+-- Name: note_comments_note_id_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE INDEX note_comments_note_id_idx ON note_comments USING btree (note_id);
+
+
+--
+-- Name: notes_created_at_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE INDEX notes_created_at_idx ON notes USING btree (created_at);
+
+
+--
+-- Name: notes_tile_status_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE INDEX notes_tile_status_idx ON notes USING btree (tile, status);
+
+
+--
+-- Name: notes_updated_at_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: 
+--
+
+CREATE INDEX notes_updated_at_idx ON notes USING btree (updated_at);
+
+
 --
 -- Name: points_gpxid_idx; Type: INDEX; Schema: public; Owner: -; Tablespace: 
 --
@@ -2045,6 +2189,22 @@ ALTER TABLE ONLY nodes
     ADD CONSTRAINT nodes_changeset_id_fkey FOREIGN KEY (changeset_id) REFERENCES changesets(id);
 
 
+--
+-- Name: note_comments_author_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY note_comments
+    ADD CONSTRAINT note_comments_author_id_fkey FOREIGN KEY (author_id) REFERENCES users(id);
+
+
+--
+-- Name: note_comments_note_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
+--
+
+ALTER TABLE ONLY note_comments
+    ADD CONSTRAINT note_comments_note_id_fkey FOREIGN KEY (note_id) REFERENCES notes(id);
+
+
 --
 -- Name: oauth_tokens_client_application_id_fkey; Type: FK CONSTRAINT; Schema: public; Owner: -
 --
@@ -2205,6 +2365,10 @@ INSERT INTO schema_migrations (version) VALUES ('20101114011429');
 
 INSERT INTO schema_migrations (version) VALUES ('20110322001319');
 
+INSERT INTO schema_migrations (version) VALUES ('20110508145337');
+
+INSERT INTO schema_migrations (version) VALUES ('20110521142405');
+
 INSERT INTO schema_migrations (version) VALUES ('20110925112722');
 
 INSERT INTO schema_migrations (version) VALUES ('20111116184519');
@@ -2289,6 +2453,16 @@ INSERT INTO schema_migrations (version) VALUES ('51');
 
 INSERT INTO schema_migrations (version) VALUES ('52');
 
+INSERT INTO schema_migrations (version) VALUES ('53');
+
+INSERT INTO schema_migrations (version) VALUES ('54');
+
+INSERT INTO schema_migrations (version) VALUES ('55');
+
+INSERT INTO schema_migrations (version) VALUES ('56');
+
+INSERT INTO schema_migrations (version) VALUES ('57');
+
 INSERT INTO schema_migrations (version) VALUES ('6');
 
 INSERT INTO schema_migrations (version) VALUES ('7');
index e560dbefa6c7f3e4c1c7bdf975b0a26917bd953a..38b994d26a6e11233983adcf6cbd730e5198af70 100644 (file)
@@ -37,6 +37,13 @@ public
     from_bbox_array(bbox_array)
   end
 
+  def self.from_lrbt_params(params)
+    if params[:l] and params[:b] and params[:t] and params[:t]
+      bbox_array = [params[:l], params[:b], params[:r], params[:t]]
+    end
+    from_bbox_array(bbox_array)
+  end
+
   def expand!(bbox, margin = 0)
     update!(bbox) unless complete?
     # only try to expand the bbox if there is a value for every coordinate
@@ -71,10 +78,10 @@ public
     self
   end
 
-  def check_size
+  def check_size(max_area = MAX_REQUEST_AREA)
     # check the bbox isn't too large
-    if area > MAX_REQUEST_AREA
-      raise OSM::APIBadBoundingBox.new("The maximum bbox size is " + MAX_REQUEST_AREA.to_s +
+    if area > max_area
+      raise OSM::APIBadBoundingBox.new("The maximum bbox size is " + max_area.to_s +
         ", and your request was too large. Either request a smaller area, or use planet.osm")
     end
     self
index 0d010eb869b6f6116c5024e2fa8bff300acf8d68..0c261dc69c8d3330f5ad4ea17b603e8a848dd9e1 100644 (file)
@@ -45,4 +45,3 @@ private
     180/Math::PI * Math.log(Math.tan(Math::PI/4+a*(Math::PI/180)/2))
   end
 end
-
index 7549add2abfb7e5623a23dbd26f8981c0e4ab6a2..75e047815a073004eb8f5c7fc8467f1840a9f944 100644 (file)
@@ -87,18 +87,23 @@ module ActiveRecord
         @enumerations ||= Hash.new
       end
 
-      def create_enumeration (enumeration_name, values)
+      def create_enumeration(enumeration_name, values)
         enumerations[enumeration_name] = values
-        execute "create type #{enumeration_name} as enum ('#{values.join '\',\''}')"
+        execute "CREATE TYPE #{enumeration_name} AS ENUM ('#{values.join '\',\''}')"
       end
 
-      def drop_enumeration (enumeration_name)
-        execute "drop type #{enumeration_name}"
+      def drop_enumeration(enumeration_name)
+        execute "DROP TYPE #{enumeration_name}"
         enumerations.delete(enumeration_name)
       end
 
+      def rename_enumeration(old_name, new_name)
+        execute "ALTER TYPE #{quote_table_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
+      end
+
       def alter_primary_key(table_name, new_columns)
-        execute "alter table #{table_name} drop constraint #{table_name}_pkey; alter table #{table_name} add primary key (#{new_columns.join(',')})"
+        execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{table_name}_pkey"
+        execute "ALTER TABLE #{table_name} ADD PRIMARY KEY (#{new_columns.join(',')})"
       end
 
       def interval_constant(interval)
@@ -125,6 +130,14 @@ module ActiveRecord
 
         execute "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} USING #{index_method} (#{quoted_column_names})"
       end
+
+      def rename_index(table_name, old_name, new_name)
+        execute "ALTER INDEX #{quote_table_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
+      end
+
+      def rename_sequence(table_name, old_name, new_name)
+        execute "ALTER SEQUENCE #{quote_table_name(old_name)} RENAME TO #{quote_table_name(new_name)}"
+      end
     end
   end
 end
diff --git a/test/fixtures/note_comments.yml b/test/fixtures/note_comments.yml
new file mode 100644 (file)
index 0000000..e078b99
--- /dev/null
@@ -0,0 +1,117 @@
+t1:
+  id: 1
+  note_id: 1
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'This is the initial description of the note 1'
+
+t2:
+  id: 2
+  note_id: 2
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'This is the initial description of the note 2'
+
+t3:
+  id: 3
+  note_id: 2
+  visible: true
+  created_at: 2007-02-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'This is an additional comment for note 2'
+
+t4:
+  id: 4
+  note_id: 3
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'This is the initial comment for note 3'
+
+t5:
+  id: 5
+  note_id: 4
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'Spam for note 4'
+
+t6:
+  id: 6
+  note_id: 5
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'Valid comment for note 5'
+
+t7:
+  id: 7
+  note_id: 5
+  visible: false
+  created_at: 2007-02-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'Spam for note 5'
+
+t8:
+  id: 8
+  note_id: 5
+  visible: true
+  created_at: 2007-02-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'Another valid comment for note 5'
+
+t9:
+  id: 9
+  note_id: 6
+  visible: true
+  created_at: 2007-01-01 00:00:00
+  event: opened
+  author_id: 1
+  body: 'This is a note with from a logged-in user'
+
+t10:
+  id: 10
+  note_id: 6
+  visible: true
+  created_at: 2007-02-01 00:00:00
+  event: commented
+  author_id: 4
+  body: 'A comment from another logged-in user'
+
+t11:
+  id: 11
+  note_id: 7
+  visible: true
+  event: opened
+  created_at: 2007-01-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'Initial note description'
+
+t12:
+  id: 12
+  note_id: 7
+  visible: true
+  event: commented
+  created_at: 2007-02-01 00:00:00
+  author_name: 'testname'
+  author_ip: '192.168.1.1'
+  body: 'A comment description'
+
+t13:
+  id: 13
+  note_id: 7
+  visible: true
+  event: closed
+  created_at: 2007-03-01 00:00:00
+  author_id: 4
diff --git a/test/fixtures/notes.yml b/test/fixtures/notes.yml
new file mode 100644 (file)
index 0000000..ffecba8
--- /dev/null
@@ -0,0 +1,67 @@
+# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
+<% SCALE = 10000000 unless defined?(SCALE) %>
+
+open_note:
+  id: 1
+  latitude: <%= 1*SCALE %>
+  longitude: <%= 1*SCALE %>
+  status: open
+  tile: <%= QuadTile.tile_for_point(1,1) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-01-01 00:00:00
+
+open_note_with_comment:
+  id: 2
+  latitude: <%= 1.1*SCALE %>
+  longitude: <%= 1.1*SCALE %>
+  status: open
+  tile: <%= QuadTile.tile_for_point(1.1,1.1) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-02-01 00:00:00
+
+closed_note_with_comment:
+  id: 3
+  latitude: <%= 1.2*SCALE %>
+  longitude: <%= 1.2*SCALE %>
+  status: closed
+  tile: <%= QuadTile.tile_for_point(1.2,1.2) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-03-01 00:00:00
+  closed_at:  2007-03-01 00:00:00
+
+hidden_note_with_comment:
+  id: 4
+  latitude: <%= 1.3*SCALE %>
+  longitude: <%= 1.3*SCALE %>
+  status: hidden
+  tile: <%= QuadTile.tile_for_point(1.3,1.3) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-03-01 00:00:00
+
+note_with_hidden_comment:
+  id: 5
+  latitude: <%= 1.4*SCALE %>
+  longitude: <%= 1.4*SCALE %>
+  status: open
+  tile: <%= QuadTile.tile_for_point(1.4,1.4) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-03-01 00:00:00
+
+note_with_comments_by_users:
+  id: 6
+  latitude: <%= 1.5*SCALE %>
+  longitude: <%= 1.5*SCALE %>
+  status: open
+  tile: <%= QuadTile.tile_for_point(1.5,1.5) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-03-01 00:00:00
+
+note_closed_by_user:
+  id: 7
+  latitude: <%= 1.6*SCALE %>
+  longitude: <%= 1.6*SCALE %>
+  status: closed
+  tile: <%= QuadTile.tile_for_point(1.6,1.6) %>
+  created_at: 2007-01-01 00:00:00
+  updated_at: 2007-03-01 00:00:00
+  closed_at:  2007-03-01 00:00:00
diff --git a/test/functional/note_controller_test.rb b/test/functional/note_controller_test.rb
new file mode 100644 (file)
index 0000000..033cef8
--- /dev/null
@@ -0,0 +1,336 @@
+require File.dirname(__FILE__) + '/../test_helper'
+
+class NoteControllerTest < ActionController::TestCase
+  fixtures :users, :notes, :note_comments
+
+  def test_note_create_success
+    assert_difference('Note.count') do
+      assert_difference('NoteComment.count') do
+        post :create, {:lat => -1.0, :lon => -1.0, :name => "new_tester", :text => "This is a comment"}
+      end
+    end
+    assert_response :success
+    id = @response.body.sub(/ok/,"").to_i
+
+    get :read, {:id => id, :format => 'json'}
+    assert_response :success
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "Feature", js["type"]
+    assert_equal "Point", js["geometry"]["type"]
+    assert_equal [-1.0, -1.0], js["geometry"]["coordinates"]
+    assert_equal id, js["properties"]["id"]
+    assert_equal "open", js["properties"]["status"]
+    assert_equal 1, js["properties"]["comments"].count
+    assert_equal "opened", js["properties"]["comments"].last["action"]
+    assert_equal "This is a comment", js["properties"]["comments"].last["text"]
+    assert_equal "new_tester (a)", js["properties"]["comments"].last["user"]
+  end
+
+  def test_note_create_fail
+    assert_no_difference('Note.count') do
+      assert_no_difference('NoteComment.count') do
+        post :create, {:lon => -1.0, :name => "new_tester", :text => "This is a comment"}
+      end
+    end
+    assert_response :bad_request
+
+    assert_no_difference('Note.count') do
+      assert_no_difference('NoteComment.count') do
+        post :create, {:lat => -1.0, :name => "new_tester", :text => "This is a comment"}
+      end
+    end
+    assert_response :bad_request
+
+    assert_no_difference('Note.count') do
+      assert_no_difference('NoteComment.count') do
+        post :create, {:lat => -1.0, :lon => -1.0, :name => "new_tester"}
+      end
+    end
+    assert_response :bad_request
+
+    assert_no_difference('Note.count') do
+      assert_no_difference('NoteComment.count') do
+        post :create, {:lat => -100.0, :lon => -1.0, :name => "new_tester", :text => "This is a comment"}
+      end
+    end
+    assert_response :bad_request
+
+    assert_no_difference('Note.count') do
+      assert_no_difference('NoteComment.count') do
+        post :create, {:lat => -1.0, :lon => -200.0, :name => "new_tester", :text => "This is a comment"}
+      end
+    end
+    assert_response :bad_request
+  end
+
+  def test_note_comment_create_success
+    assert_difference('NoteComment.count') do
+      post :update, {:id => notes(:open_note_with_comment).id, :name => "new_tester2", :text => "This is an additional comment"}
+    end
+    assert_response :success
+
+    get :read, {:id => notes(:open_note_with_comment).id, :format => 'json'}
+    assert_response :success
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "Feature", js["type"]
+    assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
+    assert_equal "open", js["properties"]["status"]
+    assert_equal 3, js["properties"]["comments"].count
+    assert_equal "commented", js["properties"]["comments"].last["action"]
+    assert_equal "This is an additional comment", js["properties"]["comments"].last["text"]
+    assert_equal "new_tester2 (a)", js["properties"]["comments"].last["user"]
+  end
+
+  def test_note_comment_create_fail
+    assert_no_difference('NoteComment.count') do
+      post :update, {:name => "new_tester2", :text => "This is an additional comment"}
+    end
+    assert_response :bad_request
+
+    assert_no_difference('NoteComment.count') do
+      post :update, {:id => notes(:open_note_with_comment).id, :name => "new_tester2"}
+    end
+    assert_response :bad_request
+
+    assert_no_difference('NoteComment.count') do
+      post :update, {:id => 12345, :name => "new_tester2", :text => "This is an additional comment"}
+    end
+    assert_response :not_found
+
+    assert_no_difference('NoteComment.count') do
+      post :update, {:id => notes(:hidden_note_with_comment).id, :name => "new_tester2", :text => "This is an additional comment"}
+    end
+    assert_response :gone
+  end
+
+  def test_note_close_success
+    post :close, {:id => notes(:open_note_with_comment).id}
+    assert_response :success
+
+    get :read, {:id => notes(:open_note_with_comment).id, :format => 'json'}
+    assert_response :success
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "Feature", js["type"]
+    assert_equal notes(:open_note_with_comment).id, js["properties"]["id"]
+    assert_equal "closed", js["properties"]["status"]
+    assert_equal 3, js["properties"]["comments"].count
+    assert_equal "closed", js["properties"]["comments"].last["action"]
+    assert_equal nil, js["properties"]["comments"].last["text"]
+    assert_equal "NoName (a)", js["properties"]["comments"].last["user"]
+  end
+
+  def test_note_close_fail
+    post :close
+    assert_response :bad_request
+
+    post :close, {:id => 12345}
+    assert_response :not_found
+
+    post :close, {:id => notes(:hidden_note_with_comment).id}
+    assert_response :gone
+  end
+
+  def test_note_read_success
+#    get :read, {:id => notes(:open_note).id}
+#    assert_response :success      
+#    assert_equal "application/xml", @response.content_type
+
+    get :read, {:id => notes(:open_note).id, :format => "xml"}
+    assert_response :success
+    assert_equal "application/xml", @response.content_type
+
+    get :read, {:id => notes(:open_note).id, :format => "rss"}
+    assert_response :success
+    assert_equal "application/rss+xml", @response.content_type
+
+    get :read, {:id => notes(:open_note).id, :format => "json"}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+
+    get :read, {:id => notes(:open_note).id, :format => "gpx"}
+    assert_response :success
+    assert_equal "application/gpx+xml", @response.content_type
+  end
+
+  def test_note_read_hidden_comment
+    get :read, {:id => notes(:note_with_hidden_comment).id, :format => 'json'}
+    assert_response :success
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal notes(:note_with_hidden_comment).id, js["properties"]["id"]
+    assert_equal 2, js["properties"]["comments"].count
+    assert_equal "Valid comment for note 5", js["properties"]["comments"][0]["text"]
+    assert_equal "Another valid comment for note 5", js["properties"]["comments"][1]["text"]
+  end
+
+  def test_note_read_fail
+    post :read
+    assert_response :bad_request
+
+    get :read, {:id => 12345}
+    assert_response :not_found
+
+    get :read, {:id => notes(:hidden_note_with_comment).id}
+    assert_response :gone
+  end
+
+  def test_note_delete_success
+    delete :delete, {:id => notes(:open_note_with_comment).id}
+    assert_response :success
+
+    get :read, {:id => notes(:open_note_with_comment).id, :format => 'json'}
+    assert_response :gone
+  end
+
+  def test_note_delete_fail
+    delete :delete
+    assert_response :bad_request
+
+    delete :delete, {:id => 12345}
+    assert_response :not_found
+
+    delete :delete, {:id => notes(:hidden_note_with_comment).id}
+    assert_response :gone
+  end
+
+  def test_get_notes_success
+#    get :list, {:bbox => '1,1,1.2,1.2'}
+#    assert_response :success
+#    assert_equal "text/javascript", @response.content_type
+
+    get :list, {:bbox => '1,1,1.2,1.2', :format => 'rss'}
+    assert_response :success
+    assert_equal "application/rss+xml", @response.content_type
+
+    get :list, {:bbox => '1,1,1.2,1.2', :format => 'json'}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+
+    get :list, {:bbox => '1,1,1.2,1.2', :format => 'xml'}
+    assert_response :success
+    assert_equal "application/xml", @response.content_type
+
+    get :list, {:bbox => '1,1,1.2,1.2', :format => 'gpx'}
+    assert_response :success
+    assert_equal "application/gpx+xml", @response.content_type
+  end
+
+  def test_get_notes_large_area
+#    get :list, {:bbox => '-2.5,-2.5,2.5,2.5'}
+#    assert_response :success
+
+#    get :list, {:l => '-2.5', :b => '-2.5', :r => '2.5', :t => '2.5'}
+#    assert_response :success
+
+    get :list, {:bbox => '-10,-10,12,12'}
+    assert_response :bad_request
+
+    get :list, {:l => '-10', :b => '-10', :r => '12', :t => '12'}
+    assert_response :bad_request
+  end
+
+  def test_get_notes_closed
+    get :list, {:bbox => '1,1,1.7,1.7', :closed => '7', :format => 'json'}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "FeatureCollection", js["type"]
+    assert_equal 4, js["features"].count
+
+    get :list, {:bbox => '1,1,1.7,1.7', :closed => '0', :format => 'json'}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "FeatureCollection", js["type"]
+    assert_equal 4, js["features"].count
+
+    get :list, {:bbox => '1,1,1.7,1.7', :closed => '-1', :format => 'json'}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+    js = ActiveSupport::JSON.decode(@response.body)
+    assert_not_nil js
+    assert_equal "FeatureCollection", js["type"]
+    assert_equal 6, js["features"].count
+  end
+
+  def test_get_notes_bad_params
+    get :list, {:bbox => '-2.5,-2.5,2.5'}
+    assert_response :bad_request
+
+    get :list, {:bbox => '-2.5,-2.5,2.5,2.5,2.5'}
+    assert_response :bad_request
+
+    get :list, {:b => '-2.5', :r => '2.5', :t => '2.5'}
+    assert_response :bad_request
+
+    get :list, {:l => '-2.5', :r => '2.5', :t => '2.5'}
+    assert_response :bad_request
+
+    get :list, {:l => '-2.5', :b => '-2.5', :t => '2.5'}
+    assert_response :bad_request
+
+    get :list, {:l => '-2.5', :b => '-2.5', :r => '2.5'}
+    assert_response :bad_request
+  end
+
+  def test_search_success
+#    get :search, {:q => 'note 1'}
+#    assert_response :success
+#    assert_equal "text/javascript", @response.content_type
+
+    get :search, {:q => 'note 1', :format => 'xml'}
+    assert_response :success
+    assert_equal "application/xml", @response.content_type
+
+    get :search, {:q => 'note 1', :format => 'json'}
+    assert_response :success
+    assert_equal "application/json", @response.content_type
+
+    get :search, {:q => 'note 1', :format => 'rss'}
+    assert_response :success
+    assert_equal "application/rss+xml", @response.content_type
+
+    get :search, {:q => 'note 1', :format => 'gpx'}
+    assert_response :success
+    assert_equal "application/gpx+xml", @response.content_type
+  end
+
+  def test_search_bad_params
+    get :search
+    assert_response :bad_request
+  end
+
+  def test_rss_success
+#    get :rss
+#    assert_response :success
+#    assert_equal "application/rss+xml", @response.content_type
+
+#    get :rss, {:bbox=>'1,1,1.2,1.2'}
+#    assert_response :success  
+#    assert_equal "application/rss+xml", @response.content_type
+  end
+
+  def test_rss_fail
+    get :rss, {:bbox=>'1,1,1.2'}
+    assert_response :bad_request
+
+    get :rss, {:bbox=>'1,1,1.2,1.2,1.2'}
+    assert_response :bad_request
+  end
+
+  def test_user_notes_success
+    get :mine, {:display_name=>'test'}
+    assert_response :success
+
+    get :mine, {:display_name=>'pulibc_test2'}
+    assert_response :success
+
+    get :mine, {:display_name=>'non-existent'}
+    assert_response :not_found 
+  end
+end
index 97ce903c13db7125dff658c32a58b93947033551..5c254b4fddca9caeb1fb0beae70ebe530e7f97a6 100644 (file)
@@ -920,20 +920,9 @@ if(this.wrapDateLine){var wrappingOptions={'rightTolerance':this.getResolution()
 return bounds;},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,markers:null,drawn:false,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);this.markers=[];},destroy:function(){this.clearMarkers();this.markers=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.markers.length;i<len;i++){this.markers[i].setOpacity(this.opacity);}}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(zoomChanged||!this.drawn){for(var i=0,len=this.markers.length;i<len;i++){this.drawMarker(this.markers[i]);}
 this.drawn=true;}},addMarker:function(marker){this.markers.push(marker);if(this.opacity!=null){marker.setOpacity(this.opacity);}
 if(this.map&&this.map.getExtent()){marker.map=this.map;this.drawMarker(marker);}},removeMarker:function(marker){if(this.markers&&this.markers.length){OpenLayers.Util.removeItem(this.markers,marker);marker.erase();}},clearMarkers:function(){if(this.markers!=null){while(this.markers.length>0){this.removeMarker(this.markers[0]);}}},drawMarker:function(marker){var px=this.map.getLayerPxFromLonLat(marker.lonlat);if(px==null){marker.display(false);}else{if(!marker.isDrawn()){var markerImg=marker.draw(px);this.div.appendChild(markerImg);}else if(marker.icon){marker.icon.moveTo(px);}}},getDataExtent:function(){var maxExtent=null;if(this.markers&&(this.markers.length>0)){var maxExtent=new OpenLayers.Bounds();for(var i=0,len=this.markers.length;i<len;i++){var marker=this.markers[i];maxExtent.extend(marker.lonlat);}}
-return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Lang.it={'unhandledRequest':"Codice di ritorno della richiesta ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Livello base",'readNotImplemented':"Lettura non implementata.",'writeNotImplemented':"Scrittura non implementata.",'noFID':"Impossibile aggiornare un elemento grafico che non abbia il FID.",'errorLoadingGML':"Errore nel caricamento del file GML ${url}",'browserNotSupported':"Il tuo browser non supporta il rendering vettoriale. I renderizzatore attualemnte supportati sono:\n${renderers}",'componentShouldBe':"addFeatures : il componente dovrebbe essere di tipo ${geomType}",'getFeatureError':"getFeatureFromEvent chiamata su di un livello senza renderizzatore. Ciò significa che "+"il livello è stato cancellato, ma non i gestori associati ad esso.",'minZoomLevelError':"La proprietà minZoomLevel è da utilizzare solamente "+"con livelli che abbiano FixedZoomLevels. Il fatto che "+"questo livello wfs controlli la proprietà minZoomLevel è "+"un retaggio del passato. Non possiamo comunque rimuoverla "+"senza rompere le vecchie applicazioni che dipendono su di essa."+"Quindi siamo costretti a deprecarla -- minZoomLevel "+"e sarà rimossa dalla vesione 3.0. Si prega di utilizzare i "+"settaggi di risoluzione min/max come descritto qui: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transazione WFS: SUCCESS ${response}",'commitFailed':"Transazione WFS: FAILED ${response}",'googleWarning':"Il livello Google non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria Google Maps "+"non è stata inclusa nella pagina, oppure non contiene la "+"corretta API key per il tuo sito.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>clicca qui</a>",'getLayerWarning':"Il livello ${layerType} non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria ${layerLib} "+"non è stata inclusa nella pagina.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>clicca qui</a>",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Stai cercando di aggiungere il livello: ${layerName} alla mappa, ma tale livello è già stato aggiunto.",'reprojectDeprecated':"Stai utilizzando l'opzione 'reproject' sul livello ${layerName}. "+"Questa opzione è deprecata: il suo utilizzo è stato introdotto per"+"supportare il disegno dei dati sopra mappe commerciali, ma tale "+"funzionalità dovrebbe essere ottenuta tramite l'utilizzo della proiezione "+"Spherical Mercator. Per maggiori informazioni consultare qui "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Questo metodo è stato deprecato e sarà rimosso dalla versione 3.0. "+"Si prega di utilizzare il metodo ${newMethod} in alternativa.",'boundsAddError':"Devi specificare i valori di x e y alla funzione add.",'lonlatAddError':"Devi specificare i valori di lon e lat alla funzione add.",'pixelAddError':"Devi specificare i valori di x e y alla funzione add.",'unsupportedGeometryType':"Tipo di geometria non supportata: ${geomType}",'end':''};OpenLayers.Lang["oc"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requèsta pas gerida, retorna ${statusText}",'Permalink':"Permaligam",'Overlays':"Calques",'Base Layer':"Calc de basa",'readNotImplemented':"Lectura pas implementada.",'writeNotImplemented':"Escritura pas implementada.",'noFID':"Impossible de metre a jorn un objècte sens identificant (fid).",'errorLoadingGML':"Error al cargament del fichièr GML ${url}",'browserNotSupported':"Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",'componentShouldBe':"addFeatures : lo compausant deuriá èsser de tipe ${geomType}",'getFeatureError':"getFeatureFromEvent es estat apelat sus un calc sens renderer. Aquò significa generalament qu\'avètz destruch aqueste jaç, mas qu\'avètz conservat un handler que li èra associat.",'minZoomLevelError':"La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà, la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaccion WFS : SUCCES ${response}",'commitFailed':"Transaccion WFS : FRACAS ${response}",'googleWarning':"Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'getLayerWarning':"Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una  BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquí, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala ~ 1 : ${scaleDenom}",'W':"O",'E':"È",'N':"N",'S':"S",'layerAlreadyAdded':"Avètz ensajat d\'apondre a la carta lo calc : ${layerName}, mas ja es present",'reprojectDeprecated':"Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça.",'boundsAddError':"Vos cal passar las doas valors x e y a la foncion add.",'lonlatAddError':"Vos cal passar las doas valors lon e lat a la foncion add.",'pixelAddError':"Vos cal passar las doas valors x e y a la foncion add.",'unsupportedGeometryType':"Tipe de geometria pas suportat : ${geomType}",'filterEvaluateNotImplemented':"evaluar es pas encara estat implementat per aqueste tipe de filtre."});OpenLayers.Lang["gsw"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nit behandleti Aafrogsruckmäldig ${statusText}",'Permalink':"Permalink",'Overlays':"Iberlagerige",'Base Layer':"Grundcharte",'readNotImplemented':"Läse nit implementiert.",'writeNotImplemented':"Schrybe nit implementiert.",'noFID':"E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",'errorLoadingGML':"Fähler bim Lade vu dr GML-Datei ${url}",'browserNotSupported':"Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",'componentShouldBe':"addFeatures : Komponänt sott dr Typ ${geomType} syy",'getFeatureError':"getFeatureFromEvent isch uf eme Layer ohni Renderer ufgruefe wore. Des heisst normalerwys, ass Du e Layer kaputt gmacht hesch, aber nit dr Handler, wu derzue ghert.",'minZoomLevelError':"D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge.  Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transaktion: ERFOLGRYCH ${response}",'commitFailed':"WFS-Transaktion: FÄHLGSCHLAA ${response}",'googleWarning':"Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'getLayerWarning':"Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Du hesch versuecht dää Layer in d Charte yyzfiege: ${layerName}, aber är isch schoi yygfiegt",'reprojectDeprecated':"Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go   Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}.",'boundsAddError':"Du muesch e x-Wärt un e y-Wärt yygee bi dr Zuefieg-Funktion",'lonlatAddError':"Du meusch e Lengi- un e Breiti-Grad yygee bi dr Zuefieg-Funktion.",'pixelAddError':"Du muesch x- un y-Wärt aagee bi dr Zuefieg-Funktion.",'unsupportedGeometryType':"Nit unterstitze Geometrii-Typ: ${geomType}",'filterEvaluateNotImplemented':"evaluiere isch nit implemäntiert in däm Filtertyp."});OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{'click':{'in':'click','out':'clickout'},'mousemove':{'in':'over','out':'out'},'dblclick':{'in':'dblclick','out':null},'mousedown':{'in':null,'out':null},'mouseup':{'in':null,'out':null},'touchstart':{'in':'click','out':'clickout'}},feature:null,lastFeature:null,down:null,up:null,touch:false,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
-return OpenLayers.Event.isMultiTouch(evt)?true:this.mousedown(evt);},touchmove:function(evt){OpenLayers.Event.stop(evt);},mousedown:function(evt){this.down=evt.xy;return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;}
-this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
-var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick"||type=="touchstart");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
-if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
-if(this.feature){if(type==="touchstart"){OpenLayers.Event.stop(evt);}
-var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
-this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
-this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
-this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
-return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
-Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
-return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.touch=false;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
-return deactivated;},handleMapEvents:function(evt){if(evt.type=="removelayer"||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);}
+return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Lang.it={'unhandledRequest':"Codice di ritorno della richiesta ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Livello base",'readNotImplemented':"Lettura non implementata.",'writeNotImplemented':"Scrittura non implementata.",'noFID':"Impossibile aggiornare un elemento grafico che non abbia il FID.",'errorLoadingGML':"Errore nel caricamento del file GML ${url}",'browserNotSupported':"Il tuo browser non supporta il rendering vettoriale. I renderizzatore attualemnte supportati sono:\n${renderers}",'componentShouldBe':"addFeatures : il componente dovrebbe essere di tipo ${geomType}",'getFeatureError':"getFeatureFromEvent chiamata su di un livello senza renderizzatore. Ciò significa che "+"il livello è stato cancellato, ma non i gestori associati ad esso.",'minZoomLevelError':"La proprietà minZoomLevel è da utilizzare solamente "+"con livelli che abbiano FixedZoomLevels. Il fatto che "+"questo livello wfs controlli la proprietà minZoomLevel è "+"un retaggio del passato. Non possiamo comunque rimuoverla "+"senza rompere le vecchie applicazioni che dipendono su di essa."+"Quindi siamo costretti a deprecarla -- minZoomLevel "+"e sarà rimossa dalla vesione 3.0. Si prega di utilizzare i "+"settaggi di risoluzione min/max come descritto qui: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transazione WFS: SUCCESS ${response}",'commitFailed':"Transazione WFS: FAILED ${response}",'googleWarning':"Il livello Google non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria Google Maps "+"non è stata inclusa nella pagina, oppure non contiene la "+"corretta API key per il tuo sito.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>clicca qui</a>",'getLayerWarning':"Il livello ${layerType} non è riuscito a caricare correttamente.<br><br>"+"Per evitare questo messaggio, seleziona un nuovo BaseLayer "+"nel selettore di livelli nell'angolo in alto a destra.<br><br>"+"Più precisamente, ciò accade perchè la libreria ${layerLib} "+"non è stata inclusa nella pagina.<br><br>"+"Sviluppatori: Per aiuto su come farlo funzionare correttamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>clicca qui</a>",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Stai cercando di aggiungere il livello: ${layerName} alla mappa, ma tale livello è già stato aggiunto.",'reprojectDeprecated':"Stai utilizzando l'opzione 'reproject' sul livello ${layerName}. "+"Questa opzione è deprecata: il suo utilizzo è stato introdotto per"+"supportare il disegno dei dati sopra mappe commerciali, ma tale "+"funzionalità dovrebbe essere ottenuta tramite l'utilizzo della proiezione "+"Spherical Mercator. Per maggiori informazioni consultare qui "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Questo metodo è stato deprecato e sarà rimosso dalla versione 3.0. "+"Si prega di utilizzare il metodo ${newMethod} in alternativa.",'boundsAddError':"Devi specificare i valori di x e y alla funzione add.",'lonlatAddError':"Devi specificare i valori di lon e lat alla funzione add.",'pixelAddError':"Devi specificare i valori di x e y alla funzione add.",'unsupportedGeometryType':"Tipo di geometria non supportata: ${geomType}",'end':''};OpenLayers.Lang["oc"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requèsta pas gerida, retorna ${statusText}",'Permalink':"Permaligam",'Overlays':"Calques",'Base Layer':"Calc de basa",'readNotImplemented':"Lectura pas implementada.",'writeNotImplemented':"Escritura pas implementada.",'noFID':"Impossible de metre a jorn un objècte sens identificant (fid).",'errorLoadingGML':"Error al cargament del fichièr GML ${url}",'browserNotSupported':"Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",'componentShouldBe':"addFeatures : lo compausant deuriá èsser de tipe ${geomType}",'getFeatureError':"getFeatureFromEvent es estat apelat sus un calc sens renderer. Aquò significa generalament qu\'avètz destruch aqueste jaç, mas qu\'avètz conservat un handler que li èra associat.",'minZoomLevelError':"La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà, la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaccion WFS : SUCCES ${response}",'commitFailed':"Transaccion WFS : FRACAS ${response}",'googleWarning':"Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'getLayerWarning':"Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una  BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquí, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala ~ 1 : ${scaleDenom}",'W':"O",'E':"È",'N':"N",'S':"S",'layerAlreadyAdded':"Avètz ensajat d\'apondre a la carta lo calc : ${layerName}, mas ja es present",'reprojectDeprecated':"Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça.",'boundsAddError':"Vos cal passar las doas valors x e y a la foncion add.",'lonlatAddError':"Vos cal passar las doas valors lon e lat a la foncion add.",'pixelAddError':"Vos cal passar las doas valors x e y a la foncion add.",'unsupportedGeometryType':"Tipe de geometria pas suportat : ${geomType}",'filterEvaluateNotImplemented':"evaluar es pas encara estat implementat per aqueste tipe de filtre."});OpenLayers.Lang["gsw"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nit behandleti Aafrogsruckmäldig ${statusText}",'Permalink':"Permalink",'Overlays':"Iberlagerige",'Base Layer':"Grundcharte",'readNotImplemented':"Läse nit implementiert.",'writeNotImplemented':"Schrybe nit implementiert.",'noFID':"E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",'errorLoadingGML':"Fähler bim Lade vu dr GML-Datei ${url}",'browserNotSupported':"Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",'componentShouldBe':"addFeatures : Komponänt sott dr Typ ${geomType} syy",'getFeatureError':"getFeatureFromEvent isch uf eme Layer ohni Renderer ufgruefe wore. Des heisst normalerwys, ass Du e Layer kaputt gmacht hesch, aber nit dr Handler, wu derzue ghert.",'minZoomLevelError':"D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge.  Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transaktion: ERFOLGRYCH ${response}",'commitFailed':"WFS-Transaktion: FÄHLGSCHLAA ${response}",'googleWarning':"Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'getLayerWarning':"Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Du hesch versuecht dää Layer in d Charte yyzfiege: ${layerName}, aber är isch schoi yygfiegt",'reprojectDeprecated':"Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go   Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}.",'boundsAddError':"Du muesch e x-Wärt un e y-Wärt yygee bi dr Zuefieg-Funktion",'lonlatAddError':"Du meusch e Lengi- un e Breiti-Grad yygee bi dr Zuefieg-Funktion.",'pixelAddError':"Du muesch x- un y-Wärt aagee bi dr Zuefieg-Funktion.",'unsupportedGeometryType':"Nit unterstitze Geometrii-Typ: ${geomType}",'filterEvaluateNotImplemented':"evaluiere isch nit implemäntiert in däm Filtertyp."});OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;}
+return false;},deactivate:function(){if(this.active){this.active=false;return true;}
+return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);}
 this.setDefaultStyle(style||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();this.rules[i]=null;}
 this.rules=null;this.defaultStyle=null;},createSymbolizer:function(feature){var style=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),feature);var rules=this.rules;var rule,context;var elseRules=[];var appliedRules=false;for(var i=0,len=rules.length;i<len;i++){rule=rules[i];var applies=rule.evaluate(feature);if(applies){if(rule instanceof OpenLayers.Rule&&rule.elseFilter){elseRules.push(rule);}else{appliedRules=true;this.applySymbolizer(rule,style,feature);}}}
 if(appliedRules==false&&elseRules.length>0){appliedRules=true;for(var i=0,len=elseRules.length;i<len;i++){this.applySymbolizer(elseRules[i],style,feature);}}
@@ -947,7 +936,34 @@ return style;},findPropertyStyles:function(){var propertyStyles={};var style=thi
 return propertyStyles;},addPropertyStyles:function(propertyStyles,symbolizer){var property;for(var key in symbolizer){property=symbolizer[key];if(typeof property=="string"&&property.match(/\$\{\w+\}/)){propertyStyles[key]=true;}}
 return propertyStyles;},addRules:function(rules){Array.prototype.push.apply(this.rules,rules);this.propertyStyles=this.findPropertyStyles();},setDefaultStyle:function(style){this.defaultStyle=style;this.propertyStyles=this.findPropertyStyles();},getSymbolizerPrefix:function(geometry){var prefixes=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=prefixes.length;i<len;i++){if(geometry.CLASS_NAME.indexOf(prefixes[i])!=-1){return prefixes[i];}}},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.rules){options.rules=[];for(var i=0,len=this.rules.length;i<len;++i){options.rules.push(this.rules[i].clone());}}
 options.context=this.context&&OpenLayers.Util.extend({},this.context);var defaultStyle=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(defaultStyle,options);},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(value,context,feature,property){if(typeof value=="string"&&value.indexOf("${")!=-1){value=OpenLayers.String.format(value,context,[feature,property]);value=(isNaN(value)||!value)?value:parseFloat(value);}
-return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),"select":new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),"temporary":new OpenLayers.Style(OpenLayers.Feature.Vector.style["temporary"]),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
+return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.Filter=OpenLayers.Class({initialize:function(options){OpenLayers.Util.extend(this,options);},destroy:function(){},evaluate:function(context){return true;},clone:function(){return null;},CLASS_NAME:"OpenLayers.Filter"});OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){var intersect=false;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(feature.geometry){var geom=this.value;if(this.value.CLASS_NAME=="OpenLayers.Bounds"){geom=this.value.toGeometry();}
+if(feature.geometry.intersects(geom)){intersect=true;}}
+break;default:OpenLayers.Console.error(OpenLayers.i18n("filterEvaluateNotImplemented"));break;}
+return intersect;},clone:function(){var options=OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(options);},CLASS_NAME:"OpenLayers.Filter.Spatial"});OpenLayers.Filter.Spatial.BBOX="BBOX";OpenLayers.Filter.Spatial.INTERSECTS="INTERSECTS";OpenLayers.Filter.Spatial.DWITHIN="DWITHIN";OpenLayers.Filter.Spatial.WITHIN="WITHIN";OpenLayers.Filter.Spatial.CONTAINS="CONTAINS";OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,scope:this});this.layer.events.on({"refresh":this.update,scope:this});if(this.layer.visibility===true&&this.layer.inRange===true){this.update();}else{this.layer.events.on({"visibilitychanged":this.update,scope:this});}}
+return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,"refresh":this.update,"visibilitychanged":this.update,scope:this});}
+return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if(mapBounds!==null&&((options&&options.force)||this.invalidBounds(mapBounds))){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead(options);}},getMapBounds:function(){if(this.layer.map===null){return null;}
+var bounds=this.layer.map.getExtent();if(bounds&&!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);}
+return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));}
+return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
+var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(options){if(this.response){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");}
+this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read(OpenLayers.Util.applyDefaults({filter:this.createFilter(),callback:this.merge,scope:this},options));},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});}
+return filter;},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}}
+this.layer.addFeatures(features);}
+this.response=null;this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Handler.Feature=OpenLayers.Class(OpenLayers.Handler,{EVENTMAP:{'click':{'in':'click','out':'clickout'},'mousemove':{'in':'over','out':'out'},'dblclick':{'in':'dblclick','out':null},'mousedown':{'in':null,'out':null},'mouseup':{'in':null,'out':null},'touchstart':{'in':'click','out':'clickout'}},feature:null,lastFeature:null,down:null,up:null,touch:false,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},touchstart:function(evt){if(!this.touch){this.touch=true;this.map.events.un({mousedown:this.mousedown,mouseup:this.mouseup,mousemove:this.mousemove,click:this.click,dblclick:this.dblclick,scope:this});}
+return OpenLayers.Event.isMultiTouch(evt)?true:this.mousedown(evt);},touchmove:function(evt){OpenLayers.Event.stop(evt);},mousedown:function(evt){this.down=evt.xy;return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;}
+this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
+var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick"||type=="touchstart");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
+if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
+if(this.feature){if(type==="touchstart"){OpenLayers.Event.stop(evt);}
+var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
+this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
+this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
+return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
+Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.touch=false;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
+return deactivated;},handleMapEvents:function(evt){if(evt.type=="removelayer"||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){this.styles={"default":new OpenLayers.Style(OpenLayers.Feature.Vector.style["default"]),"select":new OpenLayers.Style(OpenLayers.Feature.Vector.style["select"]),"temporary":new OpenLayers.Style(OpenLayers.Feature.Vector.style["temporary"]),"delete":new OpenLayers.Style(OpenLayers.Feature.Vector.style["delete"])};if(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
 OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();}
 this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();}
 if(!this.styles[intent]){intent="default";}
@@ -1111,7 +1127,11 @@ OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments);},onD
 layer.drawFeature(this.handles[i],this.renderIntent);}},transformFeature:function(mods){if(!this._setfeature){this.scale*=(mods.scale||1);this.ratio*=(mods.ratio||1);var oldRotation=this.rotation;this.rotation=(this.rotation+(mods.rotation||0))%360;if(this.events.triggerEvent("beforetransform",mods)!==false){var feature=this.feature;var geom=feature.geometry;var center=this.center;geom.rotate(-oldRotation,center);if(mods.scale||mods.ratio){geom.resize(mods.scale,center,mods.ratio);}else if(mods.center){feature.move(mods.center.getBounds().getCenterLonLat());}
 geom.rotate(this.rotation,center);this.layer.drawFeature(feature);feature.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",mods);}}
 this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles();},destroy:function(){var geom;for(var i=0;i<8;++i){geom=this.box.geometry.components[i];geom._handle.destroy();geom._handle=null;geom._rotationHandle&&geom._rotationHandle.destroy();geom._rotationHandle=null;}
-this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Lang["ia"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Le responsa a un requesta non esseva maneate: ${statusText}",'Permalink':"Permaligamine",'Overlays':"Superpositiones",'Base Layer':"Strato de base",'readNotImplemented':"Lectura non implementate.",'writeNotImplemented':"Scriptura non implementate.",'noFID':"Non pote actualisar un elemento sin FID.",'errorLoadingGML':"Error al cargamento del file GML ${url}",'browserNotSupported':"Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",'componentShouldBe':"addFeatures: le componente debe esser del typo ${geomType}",'getFeatureError':"getFeatureFromEvent ha essite appellate in un strato sin renditor. Isto significa generalmente que tu ha destruite un strato, ma lassava un gestor associate con illo.",'minZoomLevelError':"Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS: SUCCESSO ${response}",'commitFailed':"Transaction WFS: FALLEVA ${response}",'googleWarning':"Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",'getLayerWarning':"Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'W':"W",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Tu tentava adder le strato: ${layerName} al carta, ma illo es ja presente",'reprojectDeprecated':"Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco.",'boundsAddError':"Tu debe passar le duo valores x e y al function add.",'lonlatAddError':"Tu debe passar le duo valores lon e lat al function add.",'pixelAddError':"Tu debe passar le duo valores x e y al function add.",'unsupportedGeometryType':"Typo de geometria non supportate: ${geomType}",'filterEvaluateNotImplemented':"\"evaluate\" non es implementate pro iste typo de filtro."});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxOffsets:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask});},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv('zoomBox',new OpenLayers.Pixel(-9999,-9999));this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.eventsDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.eventsDiv,"olDrawBox");},moveBox:function(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);var offset=this.getBoxOffsets();this.zoomBox.style.width=(deltaX+offset.width+1)+"px";this.zoomBox.style.height=(deltaY+offset.height+1)+"px";this.zoomBox.style.left=(xy.x<startX?startX-deltaX-offset.left:startX-offset.left)+"px";this.zoomBox.style.top=(xy.y<startY?startY-deltaY-offset.top:startY-offset.top)+"px";},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
+this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(options){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this);},evaluate:function(context){var i,len;switch(this.type){case OpenLayers.Filter.Logical.AND:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==false){return false;}}
+return true;case OpenLayers.Filter.Logical.OR:for(i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==true){return true;}}
+return false;case OpenLayers.Filter.Logical.NOT:return(!this.filters[0].evaluate(context));}
+return undefined;},clone:function(){var filters=[];for(var i=0,len=this.filters.length;i<len;++i){filters.push(this.filters[i].clone());}
+return new OpenLayers.Filter.Logical({type:this.type,filters:filters});},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Lang["ia"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Le responsa a un requesta non esseva maneate: ${statusText}",'Permalink':"Permaligamine",'Overlays':"Superpositiones",'Base Layer':"Strato de base",'readNotImplemented':"Lectura non implementate.",'writeNotImplemented':"Scriptura non implementate.",'noFID':"Non pote actualisar un elemento sin FID.",'errorLoadingGML':"Error al cargamento del file GML ${url}",'browserNotSupported':"Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",'componentShouldBe':"addFeatures: le componente debe esser del typo ${geomType}",'getFeatureError':"getFeatureFromEvent ha essite appellate in un strato sin renditor. Isto significa generalmente que tu ha destruite un strato, ma lassava un gestor associate con illo.",'minZoomLevelError':"Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS: SUCCESSO ${response}",'commitFailed':"Transaction WFS: FALLEVA ${response}",'googleWarning':"Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",'getLayerWarning':"Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Scala = 1 : ${scaleDenom}",'W':"W",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Tu tentava adder le strato: ${layerName} al carta, ma illo es ja presente",'reprojectDeprecated':"Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco.",'boundsAddError':"Tu debe passar le duo valores x e y al function add.",'lonlatAddError':"Tu debe passar le duo valores lon e lat al function add.",'pixelAddError':"Tu debe passar le duo valores x e y al function add.",'unsupportedGeometryType':"Typo de geometria non supportate: ${geomType}",'filterEvaluateNotImplemented':"\"evaluate\" non es implementate pro iste typo de filtro."});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxOffsets:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);this.dragHandler=new OpenLayers.Handler.Drag(this,{down:this.startBox,move:this.moveBox,out:this.removeBox,up:this.endBox},{keyMask:this.keyMask});},destroy:function(){OpenLayers.Handler.prototype.destroy.apply(this,arguments);if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.callback("start",[]);this.zoomBox=OpenLayers.Util.createDiv('zoomBox',new OpenLayers.Pixel(-9999,-9999));this.zoomBox.className=this.boxDivClassName;this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.eventsDiv.appendChild(this.zoomBox);OpenLayers.Element.addClass(this.map.eventsDiv,"olDrawBox");},moveBox:function(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);var offset=this.getBoxOffsets();this.zoomBox.style.width=(deltaX+offset.width+1)+"px";this.zoomBox.style.height=(deltaY+offset.height+1)+"px";this.zoomBox.style.left=(xy.x<startX?startX-deltaX-offset.left:startX-offset.left)+"px";this.zoomBox.style.top=(xy.y<startY?startY-deltaY-offset.top:startY-offset.top)+"px";},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
 this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.eventsDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxOffsets=null;OpenLayers.Element.removeClass(this.map.eventsDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){if(this.dragHandler.deactivate()){if(this.zoomBox){this.removeBox();}}
 return true;}else{return false;}},getBoxOffsets:function(){if(!this.boxOffsets){var testDiv=document.createElement("div");testDiv.style.position="absolute";testDiv.style.border="1px solid black";testDiv.style.width="3px";document.body.appendChild(testDiv);var w3cBoxModel=testDiv.clientWidth==3;document.body.removeChild(testDiv);var left=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"));var right=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"));var top=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"));var bottom=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"));this.boxOffsets={left:left,right:right,top:top,bottom:bottom,width:w3cBoxModel===false?left+right:0,height:w3cBoxModel===false?top+bottom:0};}
 return this.boxOffsets;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,alwaysZoom:false,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);}
@@ -1239,9 +1259,78 @@ if(this.imageDiv!=null){if(this.px==null){this.display(false);}else{if(this.calc
 var offsetPx=this.px.offset(this.offset);OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,offsetPx);}}},display:function(display){this.imageDiv.style.display=(display)?"":"none";},isDrawn:function(){var isDrawn=(this.imageDiv&&this.imageDiv.parentNode&&(this.imageDiv.parentNode.nodeType!=11));return isDrawn;},CLASS_NAME:"OpenLayers.Icon"});OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(lonlat,icon){this.lonlat=lonlat;var newIcon=(icon)?icon:OpenLayers.Marker.defaultIcon();if(this.icon==null){this.icon=newIcon;}else{this.icon.url=newIcon.url;this.icon.size=newIcon.size;this.icon.offset=newIcon.offset;this.icon.calculateOffset=newIcon.calculateOffset;}
 this.events=new OpenLayers.Events(this,this.icon.imageDiv,null);},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;if(this.icon!=null){this.icon.destroy();this.icon=null;}},draw:function(px){return this.icon.draw(px);},erase:function(){if(this.icon!=null){this.icon.erase();}},moveTo:function(px){if((px!=null)&&(this.icon!=null)){this.icon.moveTo(px);}
 this.lonlat=this.map.getLonLatFromLayerPx(px);},isDrawn:function(){var isDrawn=(this.icon&&this.icon.isDrawn());return isDrawn;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
-return onScreen;},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);}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){var url=OpenLayers.Util.getImageLocation("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);};OpenLayers.Lang["ru"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Необработанный запрос вернул ${statusText}",'Permalink':"Постоянная ссылка",'Overlays':"Слои",'Base Layer':"Основной слой",'readNotImplemented':"Чтение не реализовано.",'writeNotImplemented':"Запись не реализована.",'noFID':"Невозможно обновить объект, для которого нет FID.",'errorLoadingGML':"Ошибка при загрузке файла GML ${url}",'browserNotSupported':"Ваш браузер не поддерживает векторную графику. На данный момент поддерживаются:\n${renderers}",'componentShouldBe':"addFeatures: компонент должен быть ${geomType}",'getFeatureError':"getFeatureFromEvent вызван для слоя без рендерера. Обычно это говорит о том, что вы уничтожили слой, но оставили связанный с ним обработчик.",'minZoomLevelError':"Свойство minZoomLevel предназначено только для использования со слоями, являющимися потомками FixedZoomLevels. То, что этот WFS-слой проверяется на minZoomLevel — реликт прошлого. Однако мы не можем удалить эту функцию, так как, возможно, от неё зависят некоторые основанные на OpenLayers приложения. Функция объявлена устаревшей — проверка minZoomLevel будет удалена в 3.0. Пожалуйста, используйте вместо неё настройку мин/макс разрешения, описанную здесь: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Транзакция WFS: УСПЕШНО ${response}",'commitFailed':"Транзакция WFS: ОШИБКА ${response}",'googleWarning':"Слой Google не удалось нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека Google Maps не была включена или не содержит корректного API-ключа для вашего сайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'getLayerWarning':"Слой ${layerType} не удалось нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Масштаб = 1 : ${scaleDenom}",'W':"З",'E':"В",'N':"С",'S':"Ю",'layerAlreadyAdded':"Вы попытались добавить слой «${layerName}» на карту, но он уже был добавлен",'reprojectDeprecated':"Вы используете опцию \'reproject\' для слоя ${layerName}. Эта опция является устаревшей: ее использование предполагалось для поддержки показа данных поверх коммерческих базовых карт, но теперь этот функционал несёт встроенная поддержка сферической проекции Меркатора. Больше сведений доступно на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Этот метод считается устаревшим и будет удалён в версии 3.0. Пожалуйста, пользуйтесь ${newMethod}.",'boundsAddError':"Функции add надо передавать оба значения, x и y.",'lonlatAddError':"Функции add надо передавать оба значения, lon и lat.",'pixelAddError':"Функции add надо передавать оба значения, x и y.",'unsupportedGeometryType':"Неподдерживаемый тип геометрии: ${geomType}",'filterEvaluateNotImplemented':"evaluate не реализовано для фильтра данного типа."});OpenLayers.Lang["nn"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Skala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du freista å leggja til laget «${layerName}» på kartet, men det har alt vorte lagt til.",'boundsAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen.",'lonlatAddError':"Du er nøydd til å gje både lon- og lat-verdiar til «add»-funksjonen.",'pixelAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen."});OpenLayers.Lang["fi"]=OpenLayers.Util.applyDefaults({'Permalink':"Ikilinkki",'Overlays':"Kerrokset",'Base Layer':"Peruskerros",'W':"L",'E':"I",'N':"P",'S':"E"});OpenLayers.Lang.es={'unhandledRequest':"Respuesta a petición no gestionada ${statusText}",'Permalink':"Enlace permanente",'Overlays':"Capas superpuestas",'Base Layer':"Capa Base",'readNotImplemented':"Lectura no implementada.",'writeNotImplemented':"Escritura no implementada.",'noFID':"No se puede actualizar un elemento para el que no existe FID.",'errorLoadingGML':"Error cargando el fichero GML ${url}",'browserNotSupported':"Su navegador no soporta renderización vectorial. Los renderizadores soportados actualmente son:\n${renderers}",'componentShouldBe':"addFeatures : el componente debe ser del tipo ${geomType}",'getFeatureError':"getFeatureFromEvent se ha llamado desde una capa sin renderizador. Esto normalmente quiere decir que "+"se ha destruido una capa, pero no el manejador asociado a ella.",'minZoomLevelError':"La propiedad minZoomLevel debe sólo utilizarse "+"con las capas que tienen FixedZoomLevels. El hecho de que "+"una capa wfs compruebe minZoomLevel es una reliquia del "+"pasado. Sin embargo, no podemos eliminarla sin discontinuar "+"probablemente las aplicaciones OL que puedan depender de ello. "+"Así pues estamos haciéndolo obsoleto --la comprobación "+"minZoomLevel se eliminará en la versión 3.0. Utilice el ajuste "+"de resolution min/max en su lugar, tal como se describe aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLÓ ${response}",'googleWarning':"La capa Google no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de la biblioteca de "+"Google Maps no fue correctamente incluido en su página, o no "+"contiene la clave del API correcta para su sitio.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>haga clic aquí</a>",'getLayerWarning':"La capa ${layerType} no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de "+"la biblioteca ${layerLib} "+"no fue correctamente incluido en su página.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>haga clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','layerAlreadyAdded':"Intentó añadir la capa: ${layerName} al mapa, pero ya había sido añadida previamente",'reprojectDeprecated':"Está usando la opción 'reproject' en la capa "+"${layerName}. Esta opción es obsoleta: su uso fue diseñado "+"para soportar la visualización de datos sobre mapas base comerciales, "+"pero ahora esa funcionalidad debería conseguirse mediante el soporte "+"de la proyección Spherical Mercator. Más información disponible en "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método es obsoleto y se eliminará en la versión 3.0. "+"Por favor utilice el método ${newMethod} en su lugar.",'boundsAddError':"Debe proporcionar los valores x e y a la función add.",'lonlatAddError':"Debe proporcionar los valores lon y lat a la función add.",'pixelAddError':"Debe proporcionar los valores x e y a la función add.",'unsupportedGeometryType':"Tipo de geometría no soportada: ${geomType}",'filterEvaluateNotImplemented':"evaluate no está implementado para este tipo de filtro.",'end':''};OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);}
+return onScreen;},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);}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){var url=OpenLayers.Util.getImageLocation("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);};OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:"    ",space:" ",newline:"\n",level:0,pretty:false,nativeJSON:(function(){return!!(window.JSON&&typeof JSON.parse=="function"&&typeof JSON.stringify=="function");})(),read:function(json,filter){var object;if(this.nativeJSON){object=JSON.parse(json,filter);}else try{if(/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){object=eval('('+json+')');if(typeof filter==='function'){function walk(k,v){if(v&&typeof v==='object'){for(var i in v){if(v.hasOwnProperty(i)){v[i]=walk(i,v[i]);}}}
+return filter(k,v);}
+object=walk('',object);}}}catch(e){}
+if(this.keepData){this.data=object;}
+return object;},write:function(value,pretty){this.pretty=!!pretty;var json=null;var type=typeof value;if(this.serialize[type]){try{json=(!this.pretty&&this.nativeJSON)?JSON.stringify(value):this.serialize[type].apply(this,[value]);}catch(err){OpenLayers.Console.error("Trouble serializing: "+err);}}
+return json;},writeIndent:function(){var pieces=[];if(this.pretty){for(var i=0;i<this.level;++i){pieces.push(this.indent);}}
+return pieces.join('');},writeNewline:function(){return(this.pretty)?this.newline:'';},writeSpace:function(){return(this.pretty)?this.space:'';},serialize:{'object':function(object){if(object==null){return"null";}
+if(object.constructor==Date){return this.serialize.date.apply(this,[object]);}
+if(object.constructor==Array){return this.serialize.array.apply(this,[object]);}
+var pieces=['{'];this.level+=1;var key,keyJSON,valueJSON;var addComma=false;for(key in object){if(object.hasOwnProperty(key)){keyJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[key,this.pretty]);valueJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[object[key],this.pretty]);if(keyJSON!=null&&valueJSON!=null){if(addComma){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),keyJSON,':',this.writeSpace(),valueJSON);addComma=true;}}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),'}');return pieces.join('');},'array':function(array){var json;var pieces=['['];this.level+=1;for(var i=0,len=array.length;i<len;++i){json=OpenLayers.Format.JSON.prototype.write.apply(this,[array[i],this.pretty]);if(json!=null){if(i>0){pieces.push(',');}
+pieces.push(this.writeNewline(),this.writeIndent(),json);}}
+this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),']');return pieces.join('');},'string':function(string){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};if(/["\\\x00-\x1f]/.test(string)){return'"'+string.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;}
+c=b.charCodeAt();return'\\u00'+
+Math.floor(c/16).toString(16)+
+(c%16).toString(16);})+'"';}
+return'"'+string+'"';},'number':function(number){return isFinite(number)?String(number):"null";},'boolean':function(bool){return String(bool);},'date':function(date){function format(number){return(number<10)?'0'+number:number;}
+return'"'+date.getFullYear()+'-'+
+format(date.getMonth()+1)+'-'+
+format(date.getDate())+'T'+
+format(date.getHours())+':'+
+format(date.getMinutes())+':'+
+format(date.getSeconds())+'"';}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:false,read:function(json,type,filter){type=(type)?type:"FeatureCollection";var results=null;var obj=null;if(typeof json=="string"){obj=OpenLayers.Format.JSON.prototype.read.apply(this,[json,filter]);}else{obj=json;}
+if(!obj){OpenLayers.Console.error("Bad JSON: "+json);}else if(typeof(obj.type)!="string"){OpenLayers.Console.error("Bad GeoJSON - no type: "+json);}else if(this.isValidType(obj,type)){switch(type){case"Geometry":try{results=this.parseGeometry(obj);}catch(err){OpenLayers.Console.error(err);}
+break;case"Feature":try{results=this.parseFeature(obj);results.type="Feature";}catch(err){OpenLayers.Console.error(err);}
+break;case"FeatureCollection":results=[];switch(obj.type){case"Feature":try{results.push(this.parseFeature(obj));}catch(err){results=null;OpenLayers.Console.error(err);}
+break;case"FeatureCollection":for(var i=0,len=obj.features.length;i<len;++i){try{results.push(this.parseFeature(obj.features[i]));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;default:try{var geom=this.parseGeometry(obj);results.push(new OpenLayers.Feature.Vector(geom));}catch(err){results=null;OpenLayers.Console.error(err);}}
+break;}}
+return results;},isValidType:function(obj,type){var valid=false;switch(type){case"Geometry":if(OpenLayers.Util.indexOf(["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","Box","GeometryCollection"],obj.type)==-1){OpenLayers.Console.error("Unsupported geometry type: "+
+obj.type);}else{valid=true;}
+break;case"FeatureCollection":valid=true;break;default:if(obj.type==type){valid=true;}else{OpenLayers.Console.error("Cannot convert types from "+
+obj.type+" to "+type);}}
+return valid;},parseFeature:function(obj){var feature,geometry,attributes,bbox;attributes=(obj.properties)?obj.properties:{};bbox=(obj.geometry&&obj.geometry.bbox)||obj.bbox;try{geometry=this.parseGeometry(obj.geometry);}catch(err){throw err;}
+feature=new OpenLayers.Feature.Vector(geometry,attributes);if(bbox){feature.bounds=OpenLayers.Bounds.fromArray(bbox);}
+if(obj.id){feature.fid=obj.id;}
+return feature;},parseGeometry:function(obj){if(obj==null){return null;}
+var geometry,collection=false;if(obj.type=="GeometryCollection"){if(!(OpenLayers.Util.isArray(obj.geometries))){throw"GeometryCollection must have geometries array: "+obj;}
+var numGeom=obj.geometries.length;var components=new Array(numGeom);for(var i=0;i<numGeom;++i){components[i]=this.parseGeometry.apply(this,[obj.geometries[i]]);}
+geometry=new OpenLayers.Geometry.Collection(components);collection=true;}else{if(!(OpenLayers.Util.isArray(obj.coordinates))){throw"Geometry must have coordinates array: "+obj;}
+if(!this.parseCoords[obj.type.toLowerCase()]){throw"Unsupported geometry type: "+obj.type;}
+try{geometry=this.parseCoords[obj.type.toLowerCase()].apply(this,[obj.coordinates]);}catch(err){throw err;}}
+if(this.internalProjection&&this.externalProjection&&!collection){geometry.transform(this.externalProjection,this.internalProjection);}
+return geometry;},parseCoords:{"point":function(array){if(this.ignoreExtraDims==false&&array.length!=2){throw"Only 2D points are supported: "+array;}
+return new OpenLayers.Geometry.Point(array[0],array[1]);},"multipoint":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.MultiPoint(points);},"linestring":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
+points.push(p);}
+return new OpenLayers.Geometry.LineString(points);},"multilinestring":function(array){var lines=[];var l=null;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+lines.push(l);}
+return new OpenLayers.Geometry.MultiLineString(lines);},"polygon":function(array){var rings=[];var r,l;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
+r=new OpenLayers.Geometry.LinearRing(l.components);rings.push(r);}
+return new OpenLayers.Geometry.Polygon(rings);},"multipolygon":function(array){var polys=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["polygon"].apply(this,[array[i]]);}catch(err){throw err;}
+polys.push(p);}
+return new OpenLayers.Geometry.MultiPolygon(polys);},"box":function(array){if(array.length!=2){throw"GeoJSON box coordinates must have 2 elements";}
+return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(array[0][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[0][1])])]);}},write:function(obj,pretty){var geojson={"type":null};if(OpenLayers.Util.isArray(obj)){geojson.type="FeatureCollection";var numFeatures=obj.length;geojson.features=new Array(numFeatures);for(var i=0;i<numFeatures;++i){var element=obj[i];if(!element instanceof OpenLayers.Feature.Vector){var msg="FeatureCollection only supports collections "+"of features: "+element;throw msg;}
+geojson.features[i]=this.extract.feature.apply(this,[element]);}}else if(obj.CLASS_NAME.indexOf("OpenLayers.Geometry")==0){geojson=this.extract.geometry.apply(this,[obj]);}else if(obj instanceof OpenLayers.Feature.Vector){geojson=this.extract.feature.apply(this,[obj]);if(obj.layer&&obj.layer.projection){geojson.crs=this.createCRSObject(obj);}}
+return OpenLayers.Format.JSON.prototype.write.apply(this,[geojson,pretty]);},createCRSObject:function(object){var proj=object.layer.projection.toString();var crs={};if(proj.match(/epsg:/i)){var code=parseInt(proj.substring(proj.indexOf(":")+1));if(code==4326){crs={"type":"name","properties":{"name":"urn:ogc:def:crs:OGC:1.3:CRS84"}};}else{crs={"type":"name","properties":{"name":"EPSG:"+code}};}}
+return crs;},extract:{'feature':function(feature){var geom=this.extract.geometry.apply(this,[feature.geometry]);var json={"type":"Feature","properties":feature.attributes,"geometry":geom};if(feature.fid!=null){json.id=feature.fid;}
+return json;},'geometry':function(geometry){if(geometry==null){return null;}
+if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
+var geometryType=geometry.CLASS_NAME.split('.')[2];var data=this.extract[geometryType.toLowerCase()].apply(this,[geometry]);var json;if(geometryType=="Collection"){json={"type":"GeometryCollection","geometries":data};}else{json={"type":geometryType,"coordinates":data};}
+return json;},'point':function(point){return[point.x,point.y];},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push(this.extract.point.apply(this,[multipoint.components[i]]));}
+return array;},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
+return array;},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[multilinestring.components[i]]));}
+return array;},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[polygon.components[i]]));}
+return array;},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push(this.extract.polygon.apply(this,[multipolygon.components[i]]));}
+return array;},'collection':function(collection){var len=collection.components.length;var array=new Array(len);for(var i=0;i<len;++i){array[i]=this.extract.geometry.apply(this,[collection.components[i]]);}
+return array;}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Lang["nn"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Skala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du freista å leggja til laget «${layerName}» på kartet, men det har alt vorte lagt til.",'boundsAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen.",'lonlatAddError':"Du er nøydd til å gje både lon- og lat-verdiar til «add»-funksjonen.",'pixelAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen."});OpenLayers.Lang["fi"]=OpenLayers.Util.applyDefaults({'Permalink':"Ikilinkki",'Overlays':"Kerrokset",'Base Layer':"Peruskerros",'W':"L",'E':"I",'N':"P",'S':"E"});OpenLayers.Lang.es={'unhandledRequest':"Respuesta a petición no gestionada ${statusText}",'Permalink':"Enlace permanente",'Overlays':"Capas superpuestas",'Base Layer':"Capa Base",'readNotImplemented':"Lectura no implementada.",'writeNotImplemented':"Escritura no implementada.",'noFID':"No se puede actualizar un elemento para el que no existe FID.",'errorLoadingGML':"Error cargando el fichero GML ${url}",'browserNotSupported':"Su navegador no soporta renderización vectorial. Los renderizadores soportados actualmente son:\n${renderers}",'componentShouldBe':"addFeatures : el componente debe ser del tipo ${geomType}",'getFeatureError':"getFeatureFromEvent se ha llamado desde una capa sin renderizador. Esto normalmente quiere decir que "+"se ha destruido una capa, pero no el manejador asociado a ella.",'minZoomLevelError':"La propiedad minZoomLevel debe sólo utilizarse "+"con las capas que tienen FixedZoomLevels. El hecho de que "+"una capa wfs compruebe minZoomLevel es una reliquia del "+"pasado. Sin embargo, no podemos eliminarla sin discontinuar "+"probablemente las aplicaciones OL que puedan depender de ello. "+"Así pues estamos haciéndolo obsoleto --la comprobación "+"minZoomLevel se eliminará en la versión 3.0. Utilice el ajuste "+"de resolution min/max en su lugar, tal como se describe aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLÓ ${response}",'googleWarning':"La capa Google no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de la biblioteca de "+"Google Maps no fue correctamente incluido en su página, o no "+"contiene la clave del API correcta para su sitio.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>haga clic aquí</a>",'getLayerWarning':"La capa ${layerType} no pudo ser cargada correctamente.<br><br>"+"Para evitar este mensaje, seleccione una nueva Capa Base "+"en el selector de capas en la esquina superior derecha.<br><br>"+"Probablemente, esto se debe a que el script de "+"la biblioteca ${layerLib} "+"no fue correctamente incluido en su página.<br><br>"+"Desarrolladores: Para ayudar a hacer funcionar esto correctamente, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>haga clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','layerAlreadyAdded':"Intentó añadir la capa: ${layerName} al mapa, pero ya había sido añadida previamente",'reprojectDeprecated':"Está usando la opción 'reproject' en la capa "+"${layerName}. Esta opción es obsoleta: su uso fue diseñado "+"para soportar la visualización de datos sobre mapas base comerciales, "+"pero ahora esa funcionalidad debería conseguirse mediante el soporte "+"de la proyección Spherical Mercator. Más información disponible en "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método es obsoleto y se eliminará en la versión 3.0. "+"Por favor utilice el método ${newMethod} en su lugar.",'boundsAddError':"Debe proporcionar los valores x e y a la función add.",'lonlatAddError':"Debe proporcionar los valores lon y lat a la función add.",'pixelAddError':"Debe proporcionar los valores x e y a la función add.",'unsupportedGeometryType':"Tipo de geometría no soportada: ${geomType}",'filterEvaluateNotImplemented':"evaluate no está implementado para este tipo de filtro.",'end':''};OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);}
 return extent;},getLonLatFromViewPortPx:function(viewPortPx){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments);},getViewPortPxFromLonLat:function(lonlat){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments);},initMercatorParameters:function(){this.RESOLUTIONS=[];var maxResolution=156543.03390625;for(var zoom=0;zoom<=this.MAX_ZOOM_LEVEL;++zoom){this.RESOLUTIONS[zoom]=maxResolution/Math.pow(2,zoom);}
-this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:function(lon,lat){var x=lon*20037508.34/180;var y=Math.log(Math.tan((90+lat)*Math.PI/360))/(Math.PI/180);y=y*20037508.34/180;return new OpenLayers.LonLat(x,y);},inverseMercator:function(x,y){var lon=(x/20037508.34)*180;var lat=(y/20037508.34)*180;lat=180/Math.PI*(2*Math.atan(Math.exp(lat*Math.PI/180))-Math.PI/2);return new OpenLayers.LonLat(lon,lat);},projectForward:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.forwardMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;},projectInverse:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.inverseMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;}};(function(){var codes=["EPSG:900913","EPSG:3857","EPSG:102113","EPSG:102100"];var add=OpenLayers.Projection.addTransform;var merc=OpenLayers.Layer.SphericalMercator;var same=OpenLayers.Projection.nullTransform;var i,len,code,other,j;for(i=0,len=codes.length;i<len;++i){code=codes[i];add("EPSG:4326",code,merc.projectForward);add(code,"EPSG:4326",merc.projectInverse);for(j=i+1;j<len;++j){other=codes[j];add(code,other,same);add(other,code,same);}}})();OpenLayers.Lang["hsb"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Wotmołwa njewobdźěłaneho naprašowanja ${statusText}",'Permalink':"Trajny wotkaz",'Overlays':"Naworštowanja",'Base Layer':"Zakładna runina",'readNotImplemented':"Čitanje njeimplementowane.",'writeNotImplemented':"Pisanje njeimplementowane.",'noFID':"Funkcija, za kotruž FID njeje, njeda so aktualizować.",'errorLoadingGML':"Zmylk při začitowanju dataje ${url}",'browserNotSupported':"Twój wobhladowak wektorowe rysowanje njepodpěruje. Tuchwilu podpěrowane rysowaki su:\n${renderers}",'componentShouldBe':"addFeatures: komponenta měła ${geomType} być",'getFeatureError':"getFeatureFromEvent bu na woršće bjez rysowak zawołany. To zwjetša woznamjenja, zo sy worštu zničił, ale nic wobdźěłak, kotryž je z njej zwjazany.",'minZoomLevelError':"Kajkosć minZoomLevel je jenož za wužiwanje z worštami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta woršta wfs za minZoomLevel přepruwuje, je relikt zańdźenosće. Njemóžemy wšak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazěruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- přepruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. Prošu wužij město toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transakcija: WUSPĚŠNA ${response}",'commitFailed':"WFS-Transakcija: NJEPORADŹENA ${response}",'googleWarning':"Woršta Google njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapřijaty pak njewobsahuje korektny kluč API za twoje sydło.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'getLayerWarning':"Woršta ${layerType} njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapřijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měritko = 1 : ${scaleDenom}",'W':"Z",'E':"W",'N':"S",'S':"J",'layerAlreadyAdded':"Sy spytał runinu ${layerName} karće dodać, ale je so hižo dodała",'reprojectDeprecated':"Wužiwaš opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bě myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpěrało, ale funkcionalnosć měła so nětko z pomocu Sperical Mercator docpěć. Dalše informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",'methodDeprecated':"Tuta metoda je so njeschwaliła a budźe so w 3.0 wotstronjeć. Prošu wužij ${newMethod} město toho.",'boundsAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'lonlatAddError':"Dyrbiš hódnotu lon kaž tež lat funkciji \"add\" přepodać.",'pixelAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'unsupportedGeometryType':"Njepodpěrowany geometrijowy typ: ${geomType}",'filterEvaluateNotImplemented':"wuhódnoćenje njeje za tutón filtrowy typ implementowany."});OpenLayers.Lang["de"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehandelte Anfragerückmeldung ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Grundkarte",'readNotImplemented':"Lesen nicht implementiert.",'writeNotImplemented':"Schreiben nicht implementiert.",'noFID':"Ein Feature, für das keine FID existiert, kann nicht aktualisiert werden.",'errorLoadingGML':"Fehler beim Laden der GML-Datei ${url}",'browserNotSupported':"Ihr Browser unterstützt keine Vektordarstellung. Aktuell unterstützte Renderer:\n${renderers}",'componentShouldBe':"addFeatures: Komponente muss vom Typ ${geomType} sein",'getFeatureError':"getFeatureFromEvent wurde vom einem Layer ohne Renderer aufgerufen. Dies bedeutet normalerweise, dass ein Layer entfernt wurde, aber nicht Handler, die auf ihn verweisen.",'minZoomLevelError':"Die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft ist nur für die Verwendung mit \x3ccode\x3eFixedZoomLevels\x3c/code\x3e-untergeordneten Layers vorgesehen. Das dieser \x3ctt\x3ewfs\x3c/tt\x3e-Layer die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft überprüft ist ein Relikt der Vergangenheit. Wir können diese Überprüfung nicht entfernen, ohne das OL basierende Applikationen nicht mehr funktionieren. Daher markieren wir es als veraltet - die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Überprüfung wird in Version 3.0 entfernt werden. Bitte verwenden Sie stattdessen die Min-/Max-Lösung, wie sie unter http://trac.openlayers.org/wiki/SettingZoomLevels beschrieben ist.",'commitSuccess':"WFS-Transaktion: Erfolgreich ${response}",'commitFailed':"WFS-Transaktion: Fehlgeschlagen ${response}",'googleWarning':"Der Google-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der Google-Maps-Bibliothek nicht eingebunden wurde oder keinen gültigen API-Schlüssel für Ihre URL enthält.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden des Google-Layers",'getLayerWarning':"Der ${layerType}-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der \'${layerLib}\'-Bibliothek nicht eingebunden wurde.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden von Layern",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Sie versuchen den Layer „${layerName}“ zur Karte hinzuzufügen, er wurde aber bereits hinzugefügt",'reprojectDeprecated':"Sie verwenden die „Reproject“-Option des Layers ${layerName}. Diese Option ist veraltet: Sie wurde entwickelt um die Anzeige von Daten auf kommerziellen Basiskarten zu unterstützen, aber diese Funktion sollte jetzt durch Unterstützung der „Spherical Mercator“ erreicht werden. Weitere Informationen sind unter http://trac.openlayers.org/wiki/SphericalMercator verfügbar.",'methodDeprecated':"Die Methode ist veraltet und wird in 3.0 entfernt. Bitte verwende stattdessen ${newMethod}.",'boundsAddError':"Beide Werte (x und y) müssen der add-Funktion übergeben werden.",'lonlatAddError':"Beide Werte (lon und lat) müssen der add-Funktion übergeben werden.",'pixelAddError':"Beide Werte (x und y) müssen der add-Funktion übergeben werden.",'unsupportedGeometryType':"Nicht unterstützter Geometrie-Typ: ${geomType}",'filterEvaluateNotImplemented':"„evaluate“ ist für diesen Filter-Typ nicht implementiert."});OpenLayers.Lang['da-DK']={'unhandledRequest':"En ikke håndteret forespørgsel returnerede ${statusText}",'Permalink':"Permalink",'Overlays':"Kortlag",'Base Layer':"Baggrundslag",'readNotImplemented':"Læsning er ikke implementeret.",'writeNotImplemented':"Skrivning er ikke implementeret.",'noFID':"Kan ikke opdateret en feature (et objekt) der ikke har et FID.",'errorLoadingGML':"Fejlede under indlæsning af GML fil ${url}",'browserNotSupported':"Din browser understøtter ikke vektor visning. Følgende vektor visninger understøttes:\n${renderers}",'componentShouldBe':"addFeatures : komponenten skal være en ${geomType}",'getFeatureError':"getFeatureFromEvent blev kaldt på et lag uden en visning. Dette betyder som regel at du "+"har destrueret et lag, men ikke de håndteringer der var tilknyttet.",'minZoomLevelError':"Egenskaben minZoomLevel er kun beregnet til brug "+"med FixedZoomLevels. At dette WFS lag kontrollerer "+"minZoomLevel egenskaben, er et levn fra en tidligere "+"version. Vi kan desværre ikke fjerne dette uden at risikere "+"at ødelægge eksisterende OL baserede programmer der "+" benytter denne funktionalitet. "+"Egenskaben bør derfor ikke anvendes, og minZoomLevel "+"kontrollen herunder vil blive fjernet i version 3.0. "+"Benyt istedet min/max opløsnings indstillingerne, som "+"er beskrevet her: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS transaktion: LYKKEDES ${response}",'commitFailed':"WFS transaktion: MISLYKKEDES ${response}",'googleWarning':"Google laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at Google Maps bibliotekts "+"scriptet ikke er inkluderet, eller ikke indeholder den "+"korrkte API nøgle for dit site.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>klik her</a>",'getLayerWarning':"${layerType}-laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at ${layerLib} bibliotekts "+"scriptet ikke er inkluderet.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>klik her</a>",'Scale = 1 : ${scaleDenom}':"Målforhold = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du har forsøgt at tilføje laget: ${layerName} til kortet, men det er allerede tilføjet",'reprojectDeprecated':"Du anvender indstillingen 'reproject' på laget ${layerName}."+"Denne indstilling bør ikke længere anvendes. Den var beregnet "+"til at vise data ovenpå kommercielle grundkort, men den funktionalitet "+"bør nu opnås ved at anvende Spherical Mercator understøttelsen. "+"Mere information er tilgængelig her: "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Denne funktion bør ikke længere anvendes, og vil blive fjernet i version 3.0. "+"Anvend venligst funktionen ${newMethod} istedet.",'boundsAddError':"Du skal angive både x og y værdier i kaldet til add funktionen.",'lonlatAddError':"Du skal angive både lon og lat værdier i kaldet til add funktionen.",'pixelAddError':"Du skal angive både x og y værdier i kaldet til add funktionen.",'unsupportedGeometryType':"Geometri typen: ${geomType} er ikke understøttet.",'filterEvaluateNotImplemented':"evaluering er ikke implementeret for denne filter type."};OpenLayers.Lang["hu"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nem kezelt kérés visszatérése ${statusText}",'Permalink':"Permalink",'Overlays':"Rávetítések",'Base Layer':"Alapréteg",'readNotImplemented':"Olvasás nincs végrehajtva.",'writeNotImplemented':"Írás nincs végrehajtva.",'noFID':"Nem frissíthető olyan jellemző, amely nem rendelkezik FID-del.",'errorLoadingGML':"Hiba GML-fájl betöltésekor ${url}",'browserNotSupported':"A böngészője nem támogatja a vektoros renderelést. A jelenleg támogatott renderelők:\n${renderers}",'componentShouldBe':"addFeatures : az összetevőnek ilyen típusúnak kell lennie: ${geomType}",'getFeatureError':"getFeatureFromEvent réteget hívott meg renderelő nélkül. Ez rendszerint azt jelenti, hogy megsemmisített egy fóliát, de néhány ahhoz társított kezelőt nem.",'minZoomLevelError':"A minZoomLevel tulajdonságot csak a következővel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölőnégyzetei már a múlté. Mi azonban nem távolíthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettől függő OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenítjük -- a minZoomLevel az alul levő jelölőnégyzet a 3.0-s verzióból el lesz távolítva. Kérjük, helyette használja a  min/max felbontás beállítást, amelyről az alábbi helyen talál leírást: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS tranzakció: SIKERES ${response}",'commitFailed':"WFS tranzakció: SIKERTELEN ${response}",'googleWarning':"A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelő API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'getLayerWarning':"A(z) ${layerType} fólia nem töltődött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Lépték = 1 : ${scaleDenom}",'W':"Ny",'E':"K",'N':"É",'S':"D",'layerAlreadyAdded':"Megpróbálta hozzáadni a(z) ${layerName} fóliát a térképhez, de az már hozzá van adva",'reprojectDeprecated':"Ön a \'reproject\' beállítást használja a(z) ${layerName} fólián. Ez a beállítás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenítésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhető el. További információ az alábbi helyen érhető el: http://trac.openlayers.org/wiki/SphericalMercator",'methodDeprecated':"Ez a módszer érvénytelenítve lett és a 3.0-s verzióból el lesz távolítva. Használja a(z) ${newMethod} módszert helyette.",'boundsAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'lonlatAddError':"A hossz. és szél. értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'pixelAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'unsupportedGeometryType':"Nem támogatott geometriatípus: ${geomType}",'filterEvaluateNotImplemented':"ennél a szűrőtípusnál kiértékelés nem hajtódik végre."});OpenLayers.Lang["zh-TW"]={'unhandledRequest':"未處理的請求,傳回值為 ${statusText}。",'Permalink':"永久連結",'Overlays':"額外圖層",'Base Layer':"基礎圖層",'readNotImplemented':"沒有實作讀取的功能。",'writeNotImplemented':"沒有實作寫入的功能。",'noFID':"因為沒有 FID 所以無法更新 feature。",'errorLoadingGML':"讀取GML檔案 ${url} 錯誤。",'browserNotSupported':"您的瀏覽器未支援向量渲染. 目前支援的渲染方式是:\n${renderers}",'componentShouldBe':"addFeatures : 元件應該為 ${geomType}",'getFeatureError':"getFeatureFromEvent 在一個沒有被渲染的圖層裡被呼叫。這通常意味著您 "+"摧毀了一個圖層,但並未摧毀相關的handler。",'minZoomLevelError':"minZoomLevel 屬性僅適合用在 "+"FixedZoomLevels-descendent 類型的圖層. 這個"+"wfs layer 的 minZoomLevel 是過去所遺留下來的,"+"然而我們不能移除它而不讓它將"+"過去的程式相容性給破壞掉。"+"因此我們將會迴避使用它 -- minZoomLevel "+"會在3.0被移除,請改"+"用在這邊描述的 min/max resolution 設定: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: 成功 ${response}",'commitFailed':"WFS Transaction: 失敗 ${response}",'googleWarning':"The Google Layer 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 Google Maps 的函式庫"+"腳本沒有被正確的置入,或沒有包含 "+"您網站上正確的 API key <br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>請按這裡</a>",'getLayerWarning':"${layerType} 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 ${layerLib} 的函式庫"+"腳本沒有被正確的置入。<br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>請按這裡</a>",'Scale = 1 : ${scaleDenom}':"Scale = 1 : ${scaleDenom}",'layerAlreadyAdded':"你試著新增圖層: ${layerName} 到地圖上,但圖層之前就已經被新增了。",'reprojectDeprecated':"你正使用 'reproject' 這個選項 "+"在 ${layerName} 層。這個選項已經不再使用:"+"它的使用原本是設計用來支援在商業地圖上秀出資料,"+"但這個功能已經被"+"Spherical Mercator所取代。更多的資訊可以在 "+"http://trac.openlayers.org/wiki/SphericalMercator 找到。",'methodDeprecated':"這個方法已經不再使用且在3.0將會被移除,"+"請使用 ${newMethod} 來代替。",'boundsAddError':"您必須傳入 x 跟 y 兩者的值進 add 函數。",'lonlatAddError':"您必須傳入 lon 跟 lat 兩者的值進 add 函數。",'pixelAddError':"您必須傳入 x 跟 y 兩者的值進 add 函數。",'unsupportedGeometryType':"未支援的幾何型別: ${geomType}。",'end':''};OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,EVENT_TYPES:["featureadded"],multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){this.EVENT_TYPES=OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;}
+this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:function(lon,lat){var x=lon*20037508.34/180;var y=Math.log(Math.tan((90+lat)*Math.PI/360))/(Math.PI/180);y=y*20037508.34/180;return new OpenLayers.LonLat(x,y);},inverseMercator:function(x,y){var lon=(x/20037508.34)*180;var lat=(y/20037508.34)*180;lat=180/Math.PI*(2*Math.atan(Math.exp(lat*Math.PI/180))-Math.PI/2);return new OpenLayers.LonLat(lon,lat);},projectForward:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.forwardMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;},projectInverse:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.inverseMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;}};(function(){var codes=["EPSG:900913","EPSG:3857","EPSG:102113","EPSG:102100"];var add=OpenLayers.Projection.addTransform;var merc=OpenLayers.Layer.SphericalMercator;var same=OpenLayers.Projection.nullTransform;var i,len,code,other,j;for(i=0,len=codes.length;i<len;++i){code=codes[i];add("EPSG:4326",code,merc.projectForward);add(code,"EPSG:4326",merc.projectInverse);for(j=i+1;j<len;++j){other=codes[j];add(code,other,same);add(other,code,same);}}})();OpenLayers.Lang["ru"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Необработанный запрос вернул ${statusText}",'Permalink':"Постоянная ссылка",'Overlays':"Слои",'Base Layer':"Основной слой",'readNotImplemented':"Чтение не реализовано.",'writeNotImplemented':"Запись не реализована.",'noFID':"Невозможно обновить объект, для которого нет FID.",'errorLoadingGML':"Ошибка при загрузке файла GML ${url}",'browserNotSupported':"Ваш браузер не поддерживает векторную графику. На данный момент поддерживаются:\n${renderers}",'componentShouldBe':"addFeatures: компонент должен быть ${geomType}",'getFeatureError':"getFeatureFromEvent вызван для слоя без рендерера. Обычно это говорит о том, что вы уничтожили слой, но оставили связанный с ним обработчик.",'minZoomLevelError':"Свойство minZoomLevel предназначено только для использования со слоями, являющимися потомками FixedZoomLevels. То, что этот WFS-слой проверяется на minZoomLevel — реликт прошлого. Однако мы не можем удалить эту функцию, так как, возможно, от неё зависят некоторые основанные на OpenLayers приложения. Функция объявлена устаревшей — проверка minZoomLevel будет удалена в 3.0. Пожалуйста, используйте вместо неё настройку мин/макс разрешения, описанную здесь: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Транзакция WFS: УСПЕШНО ${response}",'commitFailed':"Транзакция WFS: ОШИБКА ${response}",'googleWarning':"Слой Google не удалось нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека Google Maps не была включена или не содержит корректного API-ключа для вашего сайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'getLayerWarning':"Слой ${layerType} не удалось нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Масштаб = 1 : ${scaleDenom}",'W':"З",'E':"В",'N':"С",'S':"Ю",'layerAlreadyAdded':"Вы попытались добавить слой «${layerName}» на карту, но он уже был добавлен",'reprojectDeprecated':"Вы используете опцию \'reproject\' для слоя ${layerName}. Эта опция является устаревшей: ее использование предполагалось для поддержки показа данных поверх коммерческих базовых карт, но теперь этот функционал несёт встроенная поддержка сферической проекции Меркатора. Больше сведений доступно на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Этот метод считается устаревшим и будет удалён в версии 3.0. Пожалуйста, пользуйтесь ${newMethod}.",'boundsAddError':"Функции add надо передавать оба значения, x и y.",'lonlatAddError':"Функции add надо передавать оба значения, lon и lat.",'pixelAddError':"Функции add надо передавать оба значения, x и y.",'unsupportedGeometryType':"Неподдерживаемый тип геометрии: ${geomType}",'filterEvaluateNotImplemented':"evaluate не реализовано для фильтра данного типа."});OpenLayers.Lang["hsb"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Wotmołwa njewobdźěłaneho naprašowanja ${statusText}",'Permalink':"Trajny wotkaz",'Overlays':"Naworštowanja",'Base Layer':"Zakładna runina",'readNotImplemented':"Čitanje njeimplementowane.",'writeNotImplemented':"Pisanje njeimplementowane.",'noFID':"Funkcija, za kotruž FID njeje, njeda so aktualizować.",'errorLoadingGML':"Zmylk při začitowanju dataje ${url}",'browserNotSupported':"Twój wobhladowak wektorowe rysowanje njepodpěruje. Tuchwilu podpěrowane rysowaki su:\n${renderers}",'componentShouldBe':"addFeatures: komponenta měła ${geomType} być",'getFeatureError':"getFeatureFromEvent bu na woršće bjez rysowak zawołany. To zwjetša woznamjenja, zo sy worštu zničił, ale nic wobdźěłak, kotryž je z njej zwjazany.",'minZoomLevelError':"Kajkosć minZoomLevel je jenož za wužiwanje z worštami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta woršta wfs za minZoomLevel přepruwuje, je relikt zańdźenosće. Njemóžemy wšak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazěruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- přepruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. Prošu wužij město toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transakcija: WUSPĚŠNA ${response}",'commitFailed':"WFS-Transakcija: NJEPORADŹENA ${response}",'googleWarning':"Woršta Google njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapřijaty pak njewobsahuje korektny kluč API za twoje sydło.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'getLayerWarning':"Woršta ${layerType} njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapřijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měritko = 1 : ${scaleDenom}",'W':"Z",'E':"W",'N':"S",'S':"J",'layerAlreadyAdded':"Sy spytał runinu ${layerName} karće dodać, ale je so hižo dodała",'reprojectDeprecated':"Wužiwaš opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bě myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpěrało, ale funkcionalnosć měła so nětko z pomocu Sperical Mercator docpěć. Dalše informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",'methodDeprecated':"Tuta metoda je so njeschwaliła a budźe so w 3.0 wotstronjeć. Prošu wužij ${newMethod} město toho.",'boundsAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'lonlatAddError':"Dyrbiš hódnotu lon kaž tež lat funkciji \"add\" přepodać.",'pixelAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'unsupportedGeometryType':"Njepodpěrowany geometrijowy typ: ${geomType}",'filterEvaluateNotImplemented':"wuhódnoćenje njeje za tutón filtrowy typ implementowany."});OpenLayers.Lang["de"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehandelte Anfragerückmeldung ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Grundkarte",'readNotImplemented':"Lesen nicht implementiert.",'writeNotImplemented':"Schreiben nicht implementiert.",'noFID':"Ein Feature, für das keine FID existiert, kann nicht aktualisiert werden.",'errorLoadingGML':"Fehler beim Laden der GML-Datei ${url}",'browserNotSupported':"Ihr Browser unterstützt keine Vektordarstellung. Aktuell unterstützte Renderer:\n${renderers}",'componentShouldBe':"addFeatures: Komponente muss vom Typ ${geomType} sein",'getFeatureError':"getFeatureFromEvent wurde vom einem Layer ohne Renderer aufgerufen. Dies bedeutet normalerweise, dass ein Layer entfernt wurde, aber nicht Handler, die auf ihn verweisen.",'minZoomLevelError':"Die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft ist nur für die Verwendung mit \x3ccode\x3eFixedZoomLevels\x3c/code\x3e-untergeordneten Layers vorgesehen. Das dieser \x3ctt\x3ewfs\x3c/tt\x3e-Layer die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Eigenschaft überprüft ist ein Relikt der Vergangenheit. Wir können diese Überprüfung nicht entfernen, ohne das OL basierende Applikationen nicht mehr funktionieren. Daher markieren wir es als veraltet - die \x3ccode\x3eminZoomLevel\x3c/code\x3e-Überprüfung wird in Version 3.0 entfernt werden. Bitte verwenden Sie stattdessen die Min-/Max-Lösung, wie sie unter http://trac.openlayers.org/wiki/SettingZoomLevels beschrieben ist.",'commitSuccess':"WFS-Transaktion: Erfolgreich ${response}",'commitFailed':"WFS-Transaktion: Fehlgeschlagen ${response}",'googleWarning':"Der Google-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der Google-Maps-Bibliothek nicht eingebunden wurde oder keinen gültigen API-Schlüssel für Ihre URL enthält.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden des Google-Layers",'getLayerWarning':"Der ${layerType}-Layer konnte nicht korrekt geladen werden.\x3cbr\x3e\x3cbr\x3eUm diese Meldung nicht mehr zu erhalten, wählen Sie einen anderen Hintergrundlayer aus dem LayerSwitcher in der rechten oberen Ecke.\x3cbr\x3e\x3cbr\x3eSehr wahrscheinlich tritt dieser Fehler auf, weil das Skript der \'${layerLib}\'-Bibliothek nicht eingebunden wurde.\x3cbr\x3e\x3cbr\x3eEntwickler: Besuche \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edas Wiki\x3c/a\x3e für Hilfe zum korrekten Einbinden von Layern",'Scale = 1 : ${scaleDenom}':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Sie versuchen den Layer „${layerName}“ zur Karte hinzuzufügen, er wurde aber bereits hinzugefügt",'reprojectDeprecated':"Sie verwenden die „Reproject“-Option des Layers ${layerName}. Diese Option ist veraltet: Sie wurde entwickelt um die Anzeige von Daten auf kommerziellen Basiskarten zu unterstützen, aber diese Funktion sollte jetzt durch Unterstützung der „Spherical Mercator“ erreicht werden. Weitere Informationen sind unter http://trac.openlayers.org/wiki/SphericalMercator verfügbar.",'methodDeprecated':"Die Methode ist veraltet und wird in 3.0 entfernt. Bitte verwende stattdessen ${newMethod}.",'boundsAddError':"Beide Werte (x und y) müssen der add-Funktion übergeben werden.",'lonlatAddError':"Beide Werte (lon und lat) müssen der add-Funktion übergeben werden.",'pixelAddError':"Beide Werte (x und y) müssen der add-Funktion übergeben werden.",'unsupportedGeometryType':"Nicht unterstützter Geometrie-Typ: ${geomType}",'filterEvaluateNotImplemented':"„evaluate“ ist für diesen Filter-Typ nicht implementiert."});OpenLayers.Lang['da-DK']={'unhandledRequest':"En ikke håndteret forespørgsel returnerede ${statusText}",'Permalink':"Permalink",'Overlays':"Kortlag",'Base Layer':"Baggrundslag",'readNotImplemented':"Læsning er ikke implementeret.",'writeNotImplemented':"Skrivning er ikke implementeret.",'noFID':"Kan ikke opdateret en feature (et objekt) der ikke har et FID.",'errorLoadingGML':"Fejlede under indlæsning af GML fil ${url}",'browserNotSupported':"Din browser understøtter ikke vektor visning. Følgende vektor visninger understøttes:\n${renderers}",'componentShouldBe':"addFeatures : komponenten skal være en ${geomType}",'getFeatureError':"getFeatureFromEvent blev kaldt på et lag uden en visning. Dette betyder som regel at du "+"har destrueret et lag, men ikke de håndteringer der var tilknyttet.",'minZoomLevelError':"Egenskaben minZoomLevel er kun beregnet til brug "+"med FixedZoomLevels. At dette WFS lag kontrollerer "+"minZoomLevel egenskaben, er et levn fra en tidligere "+"version. Vi kan desværre ikke fjerne dette uden at risikere "+"at ødelægge eksisterende OL baserede programmer der "+" benytter denne funktionalitet. "+"Egenskaben bør derfor ikke anvendes, og minZoomLevel "+"kontrollen herunder vil blive fjernet i version 3.0. "+"Benyt istedet min/max opløsnings indstillingerne, som "+"er beskrevet her: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS transaktion: LYKKEDES ${response}",'commitFailed':"WFS transaktion: MISLYKKEDES ${response}",'googleWarning':"Google laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at Google Maps bibliotekts "+"scriptet ikke er inkluderet, eller ikke indeholder den "+"korrkte API nøgle for dit site.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>klik her</a>",'getLayerWarning':"${layerType}-laget kunne ikke indlæses.<br><br>"+"For at fjerne denne besked, vælg et nyt bagrundskort i "+"lagskifteren i øverste højre hjørne.<br><br>"+"Fejlen skyldes formentlig at ${layerLib} bibliotekts "+"scriptet ikke er inkluderet.<br><br>"+"Udviklere: For hjælp til at få dette til at fungere, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>klik her</a>",'Scale = 1 : ${scaleDenom}':"Målforhold = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du har forsøgt at tilføje laget: ${layerName} til kortet, men det er allerede tilføjet",'reprojectDeprecated':"Du anvender indstillingen 'reproject' på laget ${layerName}."+"Denne indstilling bør ikke længere anvendes. Den var beregnet "+"til at vise data ovenpå kommercielle grundkort, men den funktionalitet "+"bør nu opnås ved at anvende Spherical Mercator understøttelsen. "+"Mere information er tilgængelig her: "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Denne funktion bør ikke længere anvendes, og vil blive fjernet i version 3.0. "+"Anvend venligst funktionen ${newMethod} istedet.",'boundsAddError':"Du skal angive både x og y værdier i kaldet til add funktionen.",'lonlatAddError':"Du skal angive både lon og lat værdier i kaldet til add funktionen.",'pixelAddError':"Du skal angive både x og y værdier i kaldet til add funktionen.",'unsupportedGeometryType':"Geometri typen: ${geomType} er ikke understøttet.",'filterEvaluateNotImplemented':"evaluering er ikke implementeret for denne filter type."};OpenLayers.Lang["hu"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nem kezelt kérés visszatérése ${statusText}",'Permalink':"Permalink",'Overlays':"Rávetítések",'Base Layer':"Alapréteg",'readNotImplemented':"Olvasás nincs végrehajtva.",'writeNotImplemented':"Írás nincs végrehajtva.",'noFID':"Nem frissíthető olyan jellemző, amely nem rendelkezik FID-del.",'errorLoadingGML':"Hiba GML-fájl betöltésekor ${url}",'browserNotSupported':"A böngészője nem támogatja a vektoros renderelést. A jelenleg támogatott renderelők:\n${renderers}",'componentShouldBe':"addFeatures : az összetevőnek ilyen típusúnak kell lennie: ${geomType}",'getFeatureError':"getFeatureFromEvent réteget hívott meg renderelő nélkül. Ez rendszerint azt jelenti, hogy megsemmisített egy fóliát, de néhány ahhoz társított kezelőt nem.",'minZoomLevelError':"A minZoomLevel tulajdonságot csak a következővel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölőnégyzetei már a múlté. Mi azonban nem távolíthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettől függő OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenítjük -- a minZoomLevel az alul levő jelölőnégyzet a 3.0-s verzióból el lesz távolítva. Kérjük, helyette használja a  min/max felbontás beállítást, amelyről az alábbi helyen talál leírást: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS tranzakció: SIKERES ${response}",'commitFailed':"WFS tranzakció: SIKERTELEN ${response}",'googleWarning':"A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelő API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'getLayerWarning':"A(z) ${layerType} fólia nem töltődött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Lépték = 1 : ${scaleDenom}",'W':"Ny",'E':"K",'N':"É",'S':"D",'layerAlreadyAdded':"Megpróbálta hozzáadni a(z) ${layerName} fóliát a térképhez, de az már hozzá van adva",'reprojectDeprecated':"Ön a \'reproject\' beállítást használja a(z) ${layerName} fólián. Ez a beállítás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenítésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhető el. További információ az alábbi helyen érhető el: http://trac.openlayers.org/wiki/SphericalMercator",'methodDeprecated':"Ez a módszer érvénytelenítve lett és a 3.0-s verzióból el lesz távolítva. Használja a(z) ${newMethod} módszert helyette.",'boundsAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'lonlatAddError':"A hossz. és szél. értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'pixelAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'unsupportedGeometryType':"Nem támogatott geometriatípus: ${geomType}",'filterEvaluateNotImplemented':"ennél a szűrőtípusnál kiértékelés nem hajtódik végre."});OpenLayers.Lang["zh-TW"]={'unhandledRequest':"未處理的請求,傳回值為 ${statusText}。",'Permalink':"永久連結",'Overlays':"額外圖層",'Base Layer':"基礎圖層",'readNotImplemented':"沒有實作讀取的功能。",'writeNotImplemented':"沒有實作寫入的功能。",'noFID':"因為沒有 FID 所以無法更新 feature。",'errorLoadingGML':"讀取GML檔案 ${url} 錯誤。",'browserNotSupported':"您的瀏覽器未支援向量渲染. 目前支援的渲染方式是:\n${renderers}",'componentShouldBe':"addFeatures : 元件應該為 ${geomType}",'getFeatureError':"getFeatureFromEvent 在一個沒有被渲染的圖層裡被呼叫。這通常意味著您 "+"摧毀了一個圖層,但並未摧毀相關的handler。",'minZoomLevelError':"minZoomLevel 屬性僅適合用在 "+"FixedZoomLevels-descendent 類型的圖層. 這個"+"wfs layer 的 minZoomLevel 是過去所遺留下來的,"+"然而我們不能移除它而不讓它將"+"過去的程式相容性給破壞掉。"+"因此我們將會迴避使用它 -- minZoomLevel "+"會在3.0被移除,請改"+"用在這邊描述的 min/max resolution 設定: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: 成功 ${response}",'commitFailed':"WFS Transaction: 失敗 ${response}",'googleWarning':"The Google Layer 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 Google Maps 的函式庫"+"腳本沒有被正確的置入,或沒有包含 "+"您網站上正確的 API key <br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>請按這裡</a>",'getLayerWarning':"${layerType} 圖層無法被正確的載入。<br><br>"+"要迴避這個訊息, 請在右上角的圖層改變器裡,"+"選一個新的基礎圖層。<br><br>"+"很有可能是因為 ${layerLib} 的函式庫"+"腳本沒有被正確的置入。<br><br>"+"開發者: 要幫助這個行為正確完成,"+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>請按這裡</a>",'Scale = 1 : ${scaleDenom}':"Scale = 1 : ${scaleDenom}",'layerAlreadyAdded':"你試著新增圖層: ${layerName} 到地圖上,但圖層之前就已經被新增了。",'reprojectDeprecated':"你正使用 'reproject' 這個選項 "+"在 ${layerName} 層。這個選項已經不再使用:"+"它的使用原本是設計用來支援在商業地圖上秀出資料,"+"但這個功能已經被"+"Spherical Mercator所取代。更多的資訊可以在 "+"http://trac.openlayers.org/wiki/SphericalMercator 找到。",'methodDeprecated':"這個方法已經不再使用且在3.0將會被移除,"+"請使用 ${newMethod} 來代替。",'boundsAddError':"您必須傳入 x 跟 y 兩者的值進 add 函數。",'lonlatAddError':"您必須傳入 lon 跟 lat 兩者的值進 add 函數。",'pixelAddError':"您必須傳入 x 跟 y 兩者的值進 add 函數。",'unsupportedGeometryType':"未支援的幾何型別: ${geomType}。",'end':''};OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,EVENT_TYPES:["featureadded"],multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){this.EVENT_TYPES=OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;}
 var sketchStyle=this.layer.styleMap&&this.layer.styleMap.styles.temporary;if(sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":sketchStyle})});}
 this.handler=new handler(this,this.callbacks,this.handlerOptions);},drawFeature:function(geometry){var feature=new OpenLayers.Feature.Vector(geometry);var proceed=this.layer.events.triggerEvent("sketchcomplete",{feature:feature});if(proceed!==false){feature.state=OpenLayers.State.INSERT;this.layer.addFeatures([feature]);this.featureAdded(feature);this.events.triggerEvent("featureadded",{feature:feature});}},insertXY:function(x,y){if(this.handler&&this.handler.line){this.handler.insertXY(x,y);}},insertDeltaXY:function(dx,dy){if(this.handler&&this.handler.line){this.handler.insertDeltaXY(dx,dy);}},insertDirectionLength:function(direction,length){if(this.handler&&this.handler.line){this.handler.insertDirectionLength(direction,length);}},insertDeflectionLength:function(deflection,length){if(this.handler&&this.handler.line){this.handler.insertDeflectionLength(deflection,length);}},undo:function(){return this.handler.undo&&this.handler.undo();},redo:function(){return this.handler.redo&&this.handler.redo();},finishSketch:function(){this.handler.finishGeometry();},cancel:function(){this.handler.cancel();},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Lang["pt-br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"A requisição retornou um erro não tratado: ${statusText}",'Permalink':"Link para essa página",'Overlays':"Camadas de Sobreposição",'Base Layer':"Camada Base",'readNotImplemented':"Leitura não implementada.",'writeNotImplemented':"Escrita não implementada.",'noFID':"Não é possível atualizar uma feição que não tenha um FID.",'errorLoadingGML':"Erro ao carregar o arquivo GML ${url}",'browserNotSupported':"Seu navegador não suporta renderização de vetores. Os renderizadores suportados atualmente são:\n${renderers}",'componentShouldBe':"addFeatures: o componente deve ser do tipo ${geomType}",'getFeatureError':"getFeatureFromEvent foi executado mas nenhum renderizador foi encontrado. Isso pode indicar que você destruiu uma camana, mas não o handler associado a ela.",'minZoomLevelError':"A propriedade minZoomLevel é de uso restrito das camadas descendentes de FixedZoomLevels. A verificação dessa propriedade pelas camadas wfs é um resíduo do passado. Não podemos, entretanto não é possível removê-la sem possívelmente quebrar o funcionamento de aplicações OL que possuem depência com ela. Portanto estamos tornando seu uso obsoleto -- a verificação desse atributo será removida na versão 3.0. Ao invés, use as opções de resolução min/max como descrito em: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transação WFS : SUCESSO ${response}",'commitFailed':"Transação WFS : ERRO ${response}",'googleWarning':"Não foi possível carregar a camada Google corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca do Google Maps não foi incluído, ou porque ele não contém a chave correta da API para o seu site.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",'getLayerWarning':"Não foi possível carregar a camada ${layerType} corretamente.\x3cbr\x3e\x3cbr\x3ePara se livrar dessa mensagem, selecione uma nova Camada Base, na ferramenta de alternação de camadas localização do canto superior direito.\x3cbr\x3e\x3cbr\x3eMuito provavelmente, isso foi causado porque o script da biblioteca ${layerLib} não foi incluído corretamente.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: Para obter ajuda em solucionar esse problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ecliquem aqui\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"L",'N':"N",'S':"S",'layerAlreadyAdded':"Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já foi adicionada",'reprojectDeprecated':"Você está usando a opção \'reproject\' na camada ${layerName}. Essa opção está obsoleta: seu uso foi projetado para suportar a visualização de dados sobre bases de mapas comerciais, entretanto essa funcionalidade deve agora ser alcançada usando o suporte à projeção Mercator. Mais informação está disponível em: http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Esse método está obsoleto e será removido na versão 3.0. Ao invés, por favor use ${newMethod}.",'boundsAddError':"Você deve informar ambos os valores x e y para a função add.",'lonlatAddError':"Você deve informar ambos os valores lon e lat para a função add.",'pixelAddError':"Você deve informar ambos os valores x e y para a função add.",'unsupportedGeometryType':"Tipo geométrico não suportado: ${geomType}.",'filterEvaluateNotImplemented':"evaluete não está implementado para este tipo de filtro."});OpenLayers.Lang["zh-CN"]={'unhandledRequest':"未处理的请求,返回值为 ${statusText}",'Permalink':"永久链接",'Overlays':"叠加层",'Base Layer':"基础图层",'readNotImplemented':"读取功能没有实现。",'writeNotImplemented':"写入功能没有实现。",'noFID':"无法更新feature,缺少FID。",'errorLoadingGML':"加载GML文件 ${url} 出现错误。",'browserNotSupported':"你使用的浏览器不支持矢量渲染。当前支持的渲染方式包括:\n${renderers}",'componentShouldBe':"addFeatures : 组件类型应该是 ${geomType}",'getFeatureError':"getFeatureFromEvent方法在一个没有渲染器的图层上被调用。 这通常意味着您"+"销毁了一个图层,但并未销毁其关联的handler。",'minZoomLevelError':"minZoomLevel属性仅适合用于"+"使用了固定缩放级别的图层。这个 "+"wfs 图层检查 minZoomLevel 是过去遗留下来的。"+"然而,我们不能移除它,"+"而破坏依赖于它的基于OL的应用程序。"+"因此,我们废除了它 -- minZoomLevel "+"将会在3.0中被移除。请改用 "+"min/max resolution 设置,参考:"+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: 成功。 ${response}",'commitFailed':"WFS Transaction: 失败。 ${response}",'googleWarning':"Google图层不能正确加载。<br><br>"+"要消除这个信息,请在右上角的"+"图层控制面板中选择其他的基础图层。<br><br>"+"这种情况很可能是没有正确的包含Google地图脚本库,"+"或者是没有包含在你的站点上"+"使用的正确的Google Maps API密匙。<br><br>"+"开发者:获取使其正确工作的帮助信息,"+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>点击这里</a>",'getLayerWarning':"${layerType} 图层不能正确加载。<br><br>"+"要消除这个信息,请在右上角的"+"图层控制面板中选择其他的基础图层。<br><br>"+"这种情况很可能是没有正确的包含"+"${layerLib} 脚本库。<br><br>"+"开发者:获取使其正确工作的帮助信息,"+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>点击这里</a>",'Scale = 1 : ${scaleDenom}':"比例尺 = 1 : ${scaleDenom}",'layerAlreadyAdded':"你尝试添加图层: ${layerName} 到地图中,但是它之前就已经被添加。",'reprojectDeprecated':"你正在使用 ${layerName} 图层上的'reproject'选项。"+"这个选项已经不再使用:"+"它是被设计用来支持显示商业的地图数据,"+"不过现在该功能可以通过使用Spherical Mercator来实现。"+"更多信息可以参阅"+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"该方法已经不再被支持,并且将在3.0中被移除。"+"请使用 ${newMethod} 方法来替代。",'boundsAddError':"您必须传递 x 和 y 两个参数值到 add 方法。",'lonlatAddError':"您必须传递 lon 和 lat 两个参数值到 add 方法。",'pixelAddError':"您必须传递 x and y 两个参数值到 add 方法。",'unsupportedGeometryType':"不支持的几何体类型: ${geomType}",'end':''};OpenLayers.Lang["pt"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Servidor devolveu erro não contemplado ${statusText}",'Permalink':"Ligação permanente",'Overlays':"Sobreposições",'Base Layer':"Camada Base",'readNotImplemented':"Leitura não implementada.",'writeNotImplemented':"Escrita não implementada.",'noFID':"Não é possível atualizar um elemento para a qual não há FID.",'errorLoadingGML':"Erro ao carregar ficheiro GML ${url}",'browserNotSupported':"O seu navegador não suporta renderização vetorial. Actualmente os renderizadores suportados são:\n${renderers}",'componentShouldBe':"addFeatures: componente deve ser um(a) ${geomType}",'getFeatureError':"getFeatureFromEvent foi chamado numa camada sem renderizador. Isto normalmente significa que destruiu uma camada, mas não um manipulador \'\'(handler)\'\' que lhe está associado.",'minZoomLevelError':"A propriedade minZoomLevel só deve ser usada com as camadas descendentes da FixedZoomLevels. A verificação da propriedade por esta camada wfs é uma relíquia do passado. No entanto, não podemos removê-la sem correr o risco de afectar aplicações OL que dependam dela. Portanto, estamos a torná-la obsoleta -- a verificação minZoomLevel será removida na versão 3.0. Em vez dela, por favor, use as opções de resolução min/max descritas aqui: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacção WFS: SUCESSO ${response}",'commitFailed':"Transacção WFS: FALHOU ${response}",'googleWarning':"A Camada Google não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara deixar de receber esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca do Google Maps não foi incluído ou não contém a chave API correcta para o seu sítio.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'getLayerWarning':"A camada ${layerType} não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara desactivar esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca ${layerLib} não foi incluído correctamente.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já tinha sido adicionada antes",'reprojectDeprecated':"Está usando a opção \'reproject\' na camada ${layerName}. Esta opção é obsoleta: foi concebida para permitir a apresentação de dados sobre mapas-base comerciais, mas esta funcionalidade é agora suportada pelo Mercator Esférico. Mais informação está disponível em http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método foi declarado obsoleto e será removido na versão 3.0. Por favor, use ${newMethod} em vez disso.",'boundsAddError':"Você deve passar tanto o valor x como o y à função de adição.",'lonlatAddError':"Você deve passar tanto o valor lon como o lat à função de adição.",'pixelAddError':"Você deve passar tanto o valor x como o y à função de adição.",'unsupportedGeometryType':"Tipo de geometria não suportado: ${geomType}",'filterEvaluateNotImplemented':"avaliar não está implementado para este tipo de filtro."});OpenLayers.Symbolizer.Point=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Point"});OpenLayers.Symbolizer.Line=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Line"});OpenLayers.Symbolizer.Polygon=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Polygon"});OpenLayers.Symbolizer.Text=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Text"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:false,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(options){this.symbolizer={};OpenLayers.Util.extend(this,options);if(this.symbolizers){delete this.symbolizer;}
 this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i in this.symbolizer){this.symbolizer[i]=null;}
@@ -1258,7 +1347,19 @@ return true;},touchend:function(evt){if(this.started){this.started=false;this.pi
 return true;},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.pinching=false;activated=true;}
 return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.started=false;this.pinching=false;this.start=null;this.last=null;deactivated=true;}
 return deactivated;},getDistance:function(touches){var t0=touches[0];var t1=touches[1];return Math.sqrt(Math.pow(t0.clientX-t1.clientX,2)+
-Math.pow(t0.clientY-t1.clientY,2));},getPinchData:function(evt){var distance=this.getDistance(evt.touches);var scale=distance/this.start.distance;return{distance:distance,delta:this.last.distance-distance,scale:scale};},CLASS_NAME:"OpenLayers.Handler.Pinch"});OpenLayers.Lang['lt']=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neapdorota užklausa gražino ${statusText}",'Permalink':"Pastovi nuoroda",'Overlays':"Papildomi sluoksniai",'Base Layer':"Pagrindinis sluoksnis",'readNotImplemented':"Skaitymas nėra įgyvendintas.",'writeNotImplemented':"Rašymas nėra įgyvendintas.",'noFID':"Negaliu atnaujinti objekto, kuris neturi FID.",'errorLoadingGML':"Klaida užkraunant GML failą ${url}",'browserNotSupported':"Jūsų naršyklė nemoka parodyti vektorių. Šiuo metu galima naudotis tokiais rodymo varikliais:\n{renderers}",'componentShouldBe':"addFeatures : komponentas turi būti ${geomType}",'getFeatureError':"getFeatureFromEvent buvo iškviestas sluoksniui, kuris neturi priskirto paišymo variklio. Tai paprastai nutinka, kai jūs pašalinate sluoksnį, bet paliekate su juo susijusį [handler]",'commitSuccess':"WFS Tranzakcija: PAVYKO ${response}",'commitFailed':"WFS Tranzakcija: ŽLUGO ${response}",'Scale = 1 : ${scaleDenom}':"Mastelis = 1 : ${scaleDenom}",'W':'V','E':'R','N':'Š','S':'P','Graticule':'Tinklelis','layerAlreadyAdded':"Bandėte pridėti prie žemėlapio sluoksnį ${layerName}, tačiau jis jau yra pridėtas",'methodDeprecated':"Šis metodas yra pasenęs ir 3.0 versijoje bus pašalintas. "+"Prašome naudoti ${newMethod}.",'boundsAddError':"Add funkcijai reikia pateikti tiek x, tiek y reikšmes.",'lonlatAddError':"Add funkcijai reikia pateikti tiek lon, tiek lat reikšmes",'pixelAddError':"Add funkcijai būtina perduoti tiek x, tiek y reikšmes.",'unsupportedGeometryType':"Nepalaikomas geometrijos tipas: ${geomType}",'end':''});OpenLayers.Lang.ca={'unhandledRequest':"Resposta a petició no gestionada ${statusText}",'Permalink':"Enllaç permanent",'Overlays':"Capes addicionals",'Base Layer':"Capa Base",'readNotImplemented':"Lectura no implementada.",'writeNotImplemented':"Escriptura no implementada.",'noFID':"No es pot actualitzar un element per al que no existeix FID.",'errorLoadingGML':"Error carregant el fitxer GML ${url}",'browserNotSupported':"El seu navegador no suporta renderització vectorial. Els renderitzadors suportats actualment són:\n${renderers}",'componentShouldBe':"addFeatures : el component ha de ser de tipus ${geomType}",'getFeatureError':"getFeatureFromEvent ha estat cridat des d'una capa sense renderizador. Això normalment vol dir que "+"s'ha eliminat una capa, però no el handler associat a ella.",'minZoomLevelError':"La propietat minZoomLevel s'ha d'utilitzar només "+"amb les capes que tenen FixedZoomLevels. El fet que "+"una capa wfs comprovi minZoomLevel és una relíquia del "+"passat. No podem, però, eliminar-la sense trencar "+"les aplicacions d'OpenLayers que en puguin dependre. "+"Així doncs estem fent-la obsoleta -- la comprovació "+"minZoomLevel s'eliminarà a la versió 3.0. Feu servir "+"els paràmetres min/max resolution en substitució, tal com es descriu aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacció WFS: CORRECTA ${response}",'commitFailed':"Transacció WFS: HA FALLAT ${response}",'googleWarning':"La capa Google no s'ha pogut carregar correctament.<br><br>"+"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca de "+"Google Maps no ha estat inclòs a la vostra pàgina, o no "+"conté la clau de l'API correcta per a la vostra adreça.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>féu clic aquí</a>",'getLayerWarning':"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca "+"${layerLib} "+"no ha estat inclòs a la vostra pàgina.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>féu clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','layerAlreadyAdded':"Heu intentat afegir la capa: ${layerName} al mapa, però ja ha estat afegida anteriorment",'reprojectDeprecated':"Esteu fent servir l'opció 'reproject' a la capa "+"${layerName}. Aquesta opció és obsoleta: el seu ús fou concebut "+"per suportar la visualització de dades sobre mapes base comercials, "+"però ara aquesta funcionalitat s'hauria d'assolir mitjançant el suport "+"de la projecció Spherical Mercator. Més informació disponible a "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aquest mètode és obsolet i s'eliminarà a la versió 3.0. "+"Si us plau feu servir em mètode alternatiu ${newMethod}.",'boundsAddError':"Ha de proporcionar els valors x i y a la funció add.",'lonlatAddError':"Ha de proporcionar els valors lon i lat a la funció add.",'pixelAddError':"Ha de proporcionar els valors x i y a la funció add.",'unsupportedGeometryType':"Tipus de geometria no suportada: ${geomType}",'filterEvaluateNotImplemented':"evaluate no està implementat per aquest tipus de filtre.",'end':''};OpenLayers.Lang["id"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Permintaan yang tak tertangani menghasilkan ${statusText}",'Permalink':"Pranala permanen",'Overlays':"Hamparan",'Base Layer':"Lapisan Dasar",'readNotImplemented':"Membaca tidak diterapkan.",'writeNotImplemented':"Menyimpan tidak diterapkan.",'noFID':"Tidak dapat memperbarui fitur yang tidak memiliki FID.",'errorLoadingGML':"Kesalahan dalam memuat berkas GML ${url}",'browserNotSupported':"Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",'componentShouldBe':"addFeatures : komponen harus berupa ${geomType}",'getFeatureError':"getFeatureFromEvent diterapkan pada lapisan tanpa penggambar. Ini biasanya berarti Anda menghapus sebuah lapisan, tetapi tidak menghapus penangan yang terkait dengannya.",'minZoomLevelError':"Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaksi: BERHASIL ${respon}",'commitFailed':"WFS Transaksi: GAGAL ${respon}",'googleWarning':"Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'getLayerWarning':"Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Sekala = 1 : ${scaleDenom}",'W':"B",'E':"T",'N':"U",'S':"S",'layerAlreadyAdded':"Anda mencoba menambahkan lapisan: ${layerName} ke dalam peta, tapi lapisan itu telah ditambahkan",'reprojectDeprecated':"Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}.",'boundsAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'lonlatAddError':"Anda harus memberikan kedua nilai lon dan lat ke fungsi penambah.",'pixelAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'unsupportedGeometryType':"Tipe geometri tak didukung: ${geomType}",'filterEvaluateNotImplemented':"evaluasi tidak tersedia untuk tipe filter ini."});OpenLayers.Lang["fur"]=OpenLayers.Util.applyDefaults({'Permalink':"Leam Permanent",'Overlays':"Livei parsore",'Base Layer':"Livel di base",'browserNotSupported':"Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",'Scale = 1 : ${scaleDenom}':"Scjale = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S"});OpenLayers.Format.GML=OpenLayers.Class(OpenLayers.Format.XML,{featureNS:"http://mapserver.gis.umn.edu/mapserver",featurePrefix:"feature",featureName:"featureMember",layerName:"features",geometryName:"geometry",collectionName:"FeatureCollection",gmlns:"http://www.opengis.net/gml",extractAttributes:true,xy:true,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)};OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
+Math.pow(t0.clientY-t1.clientY,2));},getPinchData:function(evt){var distance=this.getDistance(evt.touches);var scale=distance/this.start.distance;return{distance:distance,delta:this.last.distance-distance,scale:scale};},CLASS_NAME:"OpenLayers.Handler.Pinch"});OpenLayers.Lang['lt']=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neapdorota užklausa gražino ${statusText}",'Permalink':"Pastovi nuoroda",'Overlays':"Papildomi sluoksniai",'Base Layer':"Pagrindinis sluoksnis",'readNotImplemented':"Skaitymas nėra įgyvendintas.",'writeNotImplemented':"Rašymas nėra įgyvendintas.",'noFID':"Negaliu atnaujinti objekto, kuris neturi FID.",'errorLoadingGML':"Klaida užkraunant GML failą ${url}",'browserNotSupported':"Jūsų naršyklė nemoka parodyti vektorių. Šiuo metu galima naudotis tokiais rodymo varikliais:\n{renderers}",'componentShouldBe':"addFeatures : komponentas turi būti ${geomType}",'getFeatureError':"getFeatureFromEvent buvo iškviestas sluoksniui, kuris neturi priskirto paišymo variklio. Tai paprastai nutinka, kai jūs pašalinate sluoksnį, bet paliekate su juo susijusį [handler]",'commitSuccess':"WFS Tranzakcija: PAVYKO ${response}",'commitFailed':"WFS Tranzakcija: ŽLUGO ${response}",'Scale = 1 : ${scaleDenom}':"Mastelis = 1 : ${scaleDenom}",'W':'V','E':'R','N':'Š','S':'P','Graticule':'Tinklelis','layerAlreadyAdded':"Bandėte pridėti prie žemėlapio sluoksnį ${layerName}, tačiau jis jau yra pridėtas",'methodDeprecated':"Šis metodas yra pasenęs ir 3.0 versijoje bus pašalintas. "+"Prašome naudoti ${newMethod}.",'boundsAddError':"Add funkcijai reikia pateikti tiek x, tiek y reikšmes.",'lonlatAddError':"Add funkcijai reikia pateikti tiek lon, tiek lat reikšmes",'pixelAddError':"Add funkcijai būtina perduoti tiek x, tiek y reikšmes.",'unsupportedGeometryType':"Nepalaikomas geometrijos tipas: ${geomType}",'end':''});OpenLayers.Lang.ca={'unhandledRequest':"Resposta a petició no gestionada ${statusText}",'Permalink':"Enllaç permanent",'Overlays':"Capes addicionals",'Base Layer':"Capa Base",'readNotImplemented':"Lectura no implementada.",'writeNotImplemented':"Escriptura no implementada.",'noFID':"No es pot actualitzar un element per al que no existeix FID.",'errorLoadingGML':"Error carregant el fitxer GML ${url}",'browserNotSupported':"El seu navegador no suporta renderització vectorial. Els renderitzadors suportats actualment són:\n${renderers}",'componentShouldBe':"addFeatures : el component ha de ser de tipus ${geomType}",'getFeatureError':"getFeatureFromEvent ha estat cridat des d'una capa sense renderizador. Això normalment vol dir que "+"s'ha eliminat una capa, però no el handler associat a ella.",'minZoomLevelError':"La propietat minZoomLevel s'ha d'utilitzar només "+"amb les capes que tenen FixedZoomLevels. El fet que "+"una capa wfs comprovi minZoomLevel és una relíquia del "+"passat. No podem, però, eliminar-la sense trencar "+"les aplicacions d'OpenLayers que en puguin dependre. "+"Així doncs estem fent-la obsoleta -- la comprovació "+"minZoomLevel s'eliminarà a la versió 3.0. Feu servir "+"els paràmetres min/max resolution en substitució, tal com es descriu aquí: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacció WFS: CORRECTA ${response}",'commitFailed':"Transacció WFS: HA FALLAT ${response}",'googleWarning':"La capa Google no s'ha pogut carregar correctament.<br><br>"+"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca de "+"Google Maps no ha estat inclòs a la vostra pàgina, o no "+"conté la clau de l'API correcta per a la vostra adreça.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>féu clic aquí</a>",'getLayerWarning':"Per evitar aquest missatge, seleccioneu una nova Capa Base "+"al gestor de capes de la cantonada superior dreta.<br><br>"+"Probablement això és degut a que l'script de la biblioteca "+"${layerLib} "+"no ha estat inclòs a la vostra pàgina.<br><br>"+"Desenvolupadors: Per obtenir consells sobre com fer anar això, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>féu clic aquí</a>",'Scale = 1 : ${scaleDenom}':"Escala = 1 : ${scaleDenom}",'W':'O','E':'E','N':'N','S':'S','Graticule':'Retícula','layerAlreadyAdded':"Heu intentat afegir la capa: ${layerName} al mapa, però ja ha estat afegida anteriorment",'reprojectDeprecated':"Esteu fent servir l'opció 'reproject' a la capa "+"${layerName}. Aquesta opció és obsoleta: el seu ús fou concebut "+"per suportar la visualització de dades sobre mapes base comercials, "+"però ara aquesta funcionalitat s'hauria d'assolir mitjançant el suport "+"de la projecció Spherical Mercator. Més informació disponible a "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aquest mètode és obsolet i s'eliminarà a la versió 3.0. "+"Si us plau feu servir em mètode alternatiu ${newMethod}.",'boundsAddError':"Ha de proporcionar els valors x i y a la funció add.",'lonlatAddError':"Ha de proporcionar els valors lon i lat a la funció add.",'pixelAddError':"Ha de proporcionar els valors x i y a la funció add.",'unsupportedGeometryType':"Tipus de geometria no suportada: ${geomType}",'filterEvaluateNotImplemented':"evaluate no està implementat per aquest tipus de filtre.",'end':''};OpenLayers.Lang["id"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Permintaan yang tak tertangani menghasilkan ${statusText}",'Permalink':"Pranala permanen",'Overlays':"Hamparan",'Base Layer':"Lapisan Dasar",'readNotImplemented':"Membaca tidak diterapkan.",'writeNotImplemented':"Menyimpan tidak diterapkan.",'noFID':"Tidak dapat memperbarui fitur yang tidak memiliki FID.",'errorLoadingGML':"Kesalahan dalam memuat berkas GML ${url}",'browserNotSupported':"Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",'componentShouldBe':"addFeatures : komponen harus berupa ${geomType}",'getFeatureError':"getFeatureFromEvent diterapkan pada lapisan tanpa penggambar. Ini biasanya berarti Anda menghapus sebuah lapisan, tetapi tidak menghapus penangan yang terkait dengannya.",'minZoomLevelError':"Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaksi: BERHASIL ${respon}",'commitFailed':"WFS Transaksi: GAGAL ${respon}",'googleWarning':"Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'getLayerWarning':"Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Sekala = 1 : ${scaleDenom}",'W':"B",'E':"T",'N':"U",'S':"S",'layerAlreadyAdded':"Anda mencoba menambahkan lapisan: ${layerName} ke dalam peta, tapi lapisan itu telah ditambahkan",'reprojectDeprecated':"Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}.",'boundsAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'lonlatAddError':"Anda harus memberikan kedua nilai lon dan lat ke fungsi penambah.",'pixelAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'unsupportedGeometryType':"Tipe geometri tak didukung: ${geomType}",'filterEvaluateNotImplemented':"evaluasi tidak tersedia untuk tipe filter ini."});OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:true,lowerBoundary:null,upperBoundary:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);if(this.type===OpenLayers.Filter.Comparison.LIKE&&options.matchCase===undefined){this.matchCase=null;}},evaluate:function(context){if(context instanceof OpenLayers.Feature.Vector){context=context.attributes;}
+var result=false;var got=context[this.property];var exp;switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()==exp.toUpperCase());}else{result=(got==exp);}
+break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()!=exp.toUpperCase());}else{result=(got!=exp);}
+break;case OpenLayers.Filter.Comparison.LESS_THAN:result=got<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:result=got>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;}
+return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){var msg="'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison";OpenLayers.Console.error(msg);return null;}
+wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(),this);},CLASS_NAME:"OpenLayers.Filter.Comparison"});OpenLayers.Filter.Comparison.EQUAL_TO="==";OpenLayers.Filter.Comparison.NOT_EQUAL_TO="!=";OpenLayers.Filter.Comparison.LESS_THAN="<";OpenLayers.Filter.Comparison.GREATER_THAN=">";OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO="<=";OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO=">=";OpenLayers.Filter.Comparison.BETWEEN="..";OpenLayers.Filter.Comparison.LIKE="~";OpenLayers.Format.QueryStringFilter=(function(){var cmpToStr={};cmpToStr[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";cmpToStr[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN]="lt";cmpToStr[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";cmpToStr[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";cmpToStr[OpenLayers.Filter.Comparison.LIKE]="ilike";function regex2value(value){value=value.replace(/%/g,"\\%");value=value.replace(/\\\\\.(\*)?/g,function($0,$1){return $1?$0:"\\\\_";});value=value.replace(/\\\\\.\*/g,"\\\\%");value=value.replace(/(\\)?\.(\*)?/g,function($0,$1,$2){return $1||$2?$0:"_";});value=value.replace(/(\\)?\.\*/g,function($0,$1){return $1?$0:"%";});value=value.replace(/\\\./g,".");value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"*";});return value;}
+return OpenLayers.Class(OpenLayers.Format,{wildcarded:false,srsInBBOX:false,write:function(filter,params){params=params||{};var className=filter.CLASS_NAME;var filterType=className.substring(className.lastIndexOf(".")+1);switch(filterType){case"Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:params.bbox=filter.value.toArray();if(this.srsInBBOX&&filter.projection){params.bbox.push(filter.projection.getCode());}
+break;case OpenLayers.Filter.Spatial.DWITHIN:params.tolerance=filter.distance;case OpenLayers.Filter.Spatial.WITHIN:params.lon=filter.value.x;params.lat=filter.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+filter.type);}
+break;case"Comparison":var op=cmpToStr[filter.type];if(op!==undefined){var value=filter.value;if(filter.type==OpenLayers.Filter.Comparison.LIKE){value=regex2value(value);if(this.wildcarded){value="%"+value+"%";}}
+params[filter.property+"__"+op]=value;params.queryable=params.queryable||[];params.queryable.push(filter.property);}else{OpenLayers.Console.warn("Unknown comparison filter type "+filter.type);}
+break;case"Logical":if(filter.type===OpenLayers.Filter.Logical.AND){for(var i=0,len=filter.filters.length;i<len;i++){params=this.write(filter.filters[i],params);}}else{OpenLayers.Console.warn("Unsupported logical filter type "+filter.type);}
+break;default:OpenLayers.Console.warn("Unknown filter type "+filterType);}
+return params;},CLASS_NAME:"OpenLayers.Format.QueryStringFilter"});})();OpenLayers.Lang["fur"]=OpenLayers.Util.applyDefaults({'Permalink':"Leam Permanent",'Overlays':"Livei parsore",'Base Layer':"Livel di base",'browserNotSupported':"Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",'Scale = 1 : ${scaleDenom}':"Scjale = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S"});OpenLayers.Lang["km"]=OpenLayers.Util.applyDefaults({'Permalink':"តំណភ្ជាប់អចិន្ត្រៃយ៍",'Base Layer':"ស្រទាប់បាត​",'errorLoadingGML':"កំហុសកំឡុងពេលផ្ទុកឯកសារ GML ${url}",'Scale = 1 : ${scaleDenom}':"មាត្រដ្ឋាន = ១ ៖ ${scaleDenom}"});OpenLayers.Format.GML=OpenLayers.Class(OpenLayers.Format.XML,{featureNS:"http://mapserver.gis.umn.edu/mapserver",featurePrefix:"feature",featureName:"featureMember",layerName:"features",geometryName:"geometry",collectionName:"FeatureCollection",gmlns:"http://www.opengis.net/gml",extractAttributes:true,xy:true,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)};OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
 var featureNodes=this.getElementsByTagNameNS(data.documentElement,this.gmlns,this.featureName);var features=[];for(var i=0;i<featureNodes.length;i++){var feature=this.parseFeature(featureNodes[i]);if(feature){features.push(feature);}}
 return features;},parseFeature:function(node){var order=["MultiPolygon","Polygon","MultiLineString","LineString","MultiPoint","Point","Envelope"];var type,nodeList,geometry,parser;for(var i=0;i<order.length;++i){type=order[i];nodeList=this.getElementsByTagNameNS(node,this.gmlns,type);if(nodeList.length>0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));}
 break;}}
@@ -1316,7 +1417,20 @@ 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};};OpenLayers.Lang["ja"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"未処理の要求は ${statusText} を返します",'Permalink':"パーマリンク",'Overlays':"オーバーレイ",'Base Layer':"基底レイヤー",'readNotImplemented':"読み込みは実装されていません。",'writeNotImplemented':"書き込みは実装されていません。",'noFID':"FID のない地物は更新できません。",'errorLoadingGML':"GML ファイル ${url} の読み込みエラー",'browserNotSupported':"あなたのブラウザはベクターグラフィックスの描写に対応していません。現時点で対応しているソフトウェアは以下のものです。\n${renderers}",'componentShouldBe':"addFeatures: 要素は ${geomType} であるべきです",'getFeatureError':"getFeatureFromEvent がレンダラーのないレイヤーから呼ばれました。通常、これはあなたがレイヤーを、それに関連づけられたいくつかのハンドラを除いて、破壊してしまったことを意味します。",'minZoomLevelError':"minZoomLevel プロパティは FixedZoomLevels を継承するレイヤーでの使用のみを想定しています。この minZoomLevel に対する WFS レイヤーの検査は歴史的なものです。しかしながら、この検査を除去するとそれに依存する OpenLayers ベースのアプリケーションを破壊してしまう可能性があります。よって廃止が予定されており、この minZoomLevel 検査はバージョン3.0で除去されます。代わりに、http://trac.openlayers.org/wiki/SettingZoomLevels で解説されている、最小および最大解像度設定を使用してください。",'commitSuccess':"WFS トランザクション: 成功 ${response}",'commitFailed':"WFS トランザクション: 失敗 ${response}",'googleWarning':"Google レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは Google マップ用ライブラリのスクリプトが組み込まれていないか、あなたのサイトに対応する正しい API キーが設定されていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'getLayerWarning':"${layerType} レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは ${layerLib} ライブラリのスクリプトが正しく組み込まれていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'Scale = 1 : ${scaleDenom}':"縮尺 = 1 : ${scaleDenom}",'W':"西",'E':"東",'N':"北",'S':"南",'layerAlreadyAdded':"あなたは「${layerName}」を地図に追加しようと試みましたが、そのレイヤーは既に追加されています",'reprojectDeprecated':"あなたは「${layerName}」レイヤーで reproject オプションを使っています。このオプションは商用の基底地図上に情報を表示する目的で設計されましたが、現在ではその機能は Spherical Mercator サポートを利用して実現されており、このオプションの使用は非推奨です。追加の情報は http://trac.openlayers.org/wiki/SphericalMercator で入手できます。",'methodDeprecated':"このメソッドは廃止が予定されており、バージョン3.0で除去されます。代わりに ${newMethod} を使用してください。",'boundsAddError':"x と y 両方の値を add 関数に渡さなければなりません。",'lonlatAddError':"lon と lat 両方の値を add 関数に渡さなければなりません。",'pixelAddError':"x と y の値両方を add 関数に渡さなければなりません。",'unsupportedGeometryType':"未対応の形状型: ${geomType}",'filterEvaluateNotImplemented':"このフィルター型について evaluate は実装されていません。"});OpenLayers.Lang["nds"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehannelt Trüchmellels för de Anfraag ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Achtergrundkoort",'readNotImplemented':"Lesen is nich inricht.",'writeNotImplemented':"Schrieven is nich inricht.",'noFID':"En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",'errorLoadingGML':"Fehler bi’t Laden vun de GML-Datei ${url}",'browserNotSupported':"Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",'componentShouldBe':"addFeatures : Kumponent schull man den Typ ${geomType} hebben",'getFeatureError':"getFeatureFromEvent is von en Laag ahn Render opropen worrn. Dat bedüüdt normalerwies, dat en Laag wegmaakt worrn is, aver nich de Handler, de dor op verwiest.",'commitSuccess':"WFS-Transakschoon: hett klappt ${response}",'commitFailed':"WFS-Transakschoon: hett nich klappt ${response}",'Scale = 1 : ${scaleDenom}':"Skaal = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du versöchst de Laag „${layerName}“ to de Koort totofögen, man de is al toföögt",'methodDeprecated':"Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för.",'boundsAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'lonlatAddError':"De Weert lon un lat, de mööt all beid an de add-Funkschoon övergeven warrn.",'pixelAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'unsupportedGeometryType':"Nich ünnerstütt Geometrie-Typ: ${geomType}"});OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;}
+return{h:hue,s:saturation,b:brightness};};OpenLayers.Lang["ja"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"未処理の要求は ${statusText} を返します",'Permalink':"パーマリンク",'Overlays':"オーバーレイ",'Base Layer':"基底レイヤー",'readNotImplemented':"読み込みは実装されていません。",'writeNotImplemented':"書き込みは実装されていません。",'noFID':"FID のない地物は更新できません。",'errorLoadingGML':"GML ファイル ${url} の読み込みエラー",'browserNotSupported':"あなたのブラウザはベクターグラフィックスの描写に対応していません。現時点で対応しているソフトウェアは以下のものです。\n${renderers}",'componentShouldBe':"addFeatures: 要素は ${geomType} であるべきです",'getFeatureError':"getFeatureFromEvent がレンダラーのないレイヤーから呼ばれました。通常、これはあなたがレイヤーを、それに関連づけられたいくつかのハンドラを除いて、破壊してしまったことを意味します。",'minZoomLevelError':"minZoomLevel プロパティは FixedZoomLevels を継承するレイヤーでの使用のみを想定しています。この minZoomLevel に対する WFS レイヤーの検査は歴史的なものです。しかしながら、この検査を除去するとそれに依存する OpenLayers ベースのアプリケーションを破壊してしまう可能性があります。よって廃止が予定されており、この minZoomLevel 検査はバージョン3.0で除去されます。代わりに、http://trac.openlayers.org/wiki/SettingZoomLevels で解説されている、最小および最大解像度設定を使用してください。",'commitSuccess':"WFS トランザクション: 成功 ${response}",'commitFailed':"WFS トランザクション: 失敗 ${response}",'googleWarning':"Google レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは Google マップ用ライブラリのスクリプトが組み込まれていないか、あなたのサイトに対応する正しい API キーが設定されていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'getLayerWarning':"${layerType} レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは ${layerLib} ライブラリのスクリプトが正しく組み込まれていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'Scale = 1 : ${scaleDenom}':"縮尺 = 1 : ${scaleDenom}",'W':"西",'E':"東",'N':"北",'S':"南",'layerAlreadyAdded':"あなたは「${layerName}」を地図に追加しようと試みましたが、そのレイヤーは既に追加されています",'reprojectDeprecated':"あなたは「${layerName}」レイヤーで reproject オプションを使っています。このオプションは商用の基底地図上に情報を表示する目的で設計されましたが、現在ではその機能は Spherical Mercator サポートを利用して実現されており、このオプションの使用は非推奨です。追加の情報は http://trac.openlayers.org/wiki/SphericalMercator で入手できます。",'methodDeprecated':"このメソッドは廃止が予定されており、バージョン3.0で除去されます。代わりに ${newMethod} を使用してください。",'boundsAddError':"x と y 両方の値を add 関数に渡さなければなりません。",'lonlatAddError':"lon と lat 両方の値を add 関数に渡さなければなりません。",'pixelAddError':"x と y の値両方を add 関数に渡さなければなりません。",'unsupportedGeometryType':"未対応の形状型: ${geomType}",'filterEvaluateNotImplemented':"このフィルター型について evaluate は実装されていません。"});OpenLayers.Lang["nds"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehannelt Trüchmellels för de Anfraag ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Achtergrundkoort",'readNotImplemented':"Lesen is nich inricht.",'writeNotImplemented':"Schrieven is nich inricht.",'noFID':"En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",'errorLoadingGML':"Fehler bi’t Laden vun de GML-Datei ${url}",'browserNotSupported':"Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",'componentShouldBe':"addFeatures : Kumponent schull man den Typ ${geomType} hebben",'getFeatureError':"getFeatureFromEvent is von en Laag ahn Render opropen worrn. Dat bedüüdt normalerwies, dat en Laag wegmaakt worrn is, aver nich de Handler, de dor op verwiest.",'commitSuccess':"WFS-Transakschoon: hett klappt ${response}",'commitFailed':"WFS-Transakschoon: hett nich klappt ${response}",'Scale = 1 : ${scaleDenom}':"Skaal = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du versöchst de Laag „${layerName}“ to de Koort totofögen, man de is al toföögt",'methodDeprecated':"Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för.",'boundsAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'lonlatAddError':"De Weert lon un lat, de mööt all beid an de add-Funkschoon övergeven warrn.",'pixelAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'unsupportedGeometryType':"Nich ünnerstütt Geometrie-Typ: ${geomType}"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
+OpenLayers.Handler.Drag.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.Drag.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;}
+return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();}
+if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}}
+this.layer=null;this.feature=null;deactivated=true;}
+return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.map.getLonLatFromPixel(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();}
+if(this.persist){this.clear();}
+this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.map.getLonLatFromPixel(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));}
+this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;}
+this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);}
+this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);}
+this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];}
+for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);}
+if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Renderer.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;}
 if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);var style=document.createStyleSheet();var shapes=['shape','rect','oval','fill','stroke','imagedata','group','textbox'];for(var i=0,len=shapes.length;i<len;i++){style.addRule('olv\\:'+shapes[i],"behavior: url(#default#VML); "+"position: absolute; display: inline-block;");}}
 OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);},supported:function(){return!!(document.namespaces);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=(extent.left/resolution)|0;var top=(extent.top/resolution-this.size.h)|0;if(resolutionChanged||!this.offset){this.offset={x:left,y:top};left=0;top=0;}else{left=left-this.offset.x;top=top-this.offset.y;}
 var org=left+" "+top;this.root.coordorigin=org;var roots=[this.root,this.vectorRoot,this.textRoot];var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];var size=this.size.w+" "+this.size.h;root.coordsize=size;}
@@ -1365,20 +1479,23 @@ layer&&layer.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.ap
 var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
 var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var pathitems=["m"];for(var i=0;i<symbol.length;i=i+2){var x=symbol[i];var y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);pathitems.push(x);pathitems.push(y);if(i==0){pathitems.push("l");}}
 pathitems.push("x e");var path=pathitems.join(" ");var diff=(symbolExtent.getWidth()-symbolExtent.getHeight())/2;if(diff>0){symbolExtent.bottom=symbolExtent.bottom-diff;symbolExtent.top=symbolExtent.top+diff;}else{symbolExtent.left=symbolExtent.left+diff;symbolExtent.right=symbolExtent.right-diff;}
-cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Lang["vi"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Không xử lý được phản hồi ${statusText} cho yêu cầu",'Permalink':"Liên kết thường trực",'Overlays':"Lấp bản đồ",'Base Layer':"Lớp nền",'readNotImplemented':"Chưa hỗ trợ chức năng đọc.",'writeNotImplemented':"Chưa hỗ trợ chức năng viết.",'noFID':"Không thể cập nhật tính năng thiếu FID.",'errorLoadingGML':"Lỗi tải tập tin GML tại ${url}",'browserNotSupported':"Trình duyệt của bạn không hỗ trợ chức năng vẽ bằng vectơ. Hiện hỗ trợ các bộ kết xuất:\n${renderers}",'componentShouldBe':"addFeatures: bộ phận cần phải là ${geomType}",'getFeatureError':"getFeatureFromEvent được gọi từ lớp không có bộ kết xuất. Thường thì có lẽ lớp bị xóa nhưng một phần xử lý của nó vẫn còn.",'minZoomLevelError':"Chỉ nên sử dụng thuộc tính minZoomLevel với các lớp FixedZoomLevels-descendent. Việc lớp wfs này tìm cho minZoomLevel là di tích còn lại từ xưa. Tuy nhiên, nếu chúng tôi dời nó thì sẽ vỡ các chương trình OpenLayers mà dựa trên nó. Bởi vậy chúng tôi phản đối sử dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dời vào phiên bản 3.0. Xin sử dụng thiết lập độ phân tích tối thiểu / tối đa thay thế, theo hướng dẫn này: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Giao dịch WFS: THÀNH CÔNG ${response}",'commitFailed':"Giao dịch WFS: THẤT BẠI ${response}",'googleWarning':"Không thể tải lớp Google đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp với website của bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'getLayerWarning':"Không thể tải lớp ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'Scale = 1 : ${scaleDenom}':"Tỷ lệ = 1 : ${scaleDenom}",'W':"T",'E':"Đ",'N':"B",'S':"N",'layerAlreadyAdded':"Bạn muốn thêm lớp ${layerName} vào bản đồ, nhưng lớp này đã được thêm",'reprojectDeprecated':"Bạn đang áp dụng chế độ “reproject” vào lớp ${layerName}. Chế độ này đã bị phản đối: nó có mục đích hỗ trợ lấp dữ liệu trên các nền bản đồ thương mại; nên thực hiện hiệu ứng đó dùng tính năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",'methodDeprecated':"Phương thức này đã bị phản đối và sẽ bị dời vào phiên bản 3.0. Xin hãy sử dụng ${newMethod} thay thế.",'boundsAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'lonlatAddError':"Cần phải cho cả giá trị lon và lat vào hàm add.",'pixelAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'unsupportedGeometryType':"Không hỗ trợ kiểu địa lý: ${geomType}",'filterEvaluateNotImplemented':"chưa hỗ trợ evaluate cho loại bộ lọc này."});OpenLayers.Lang["km"]=OpenLayers.Util.applyDefaults({'Permalink':"តំណភ្ជាប់អចិន្ត្រៃយ៍",'Base Layer':"ស្រទាប់បាត​",'errorLoadingGML':"កំហុសកំឡុងពេលផ្ទុកឯកសារ GML ${url}",'Scale = 1 : ${scaleDenom}':"មាត្រដ្ឋាន = ១ ៖ ${scaleDenom}"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
-OpenLayers.Handler.Drag.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.Drag.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;}
-return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();}
-if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}}
-this.layer=null;this.feature=null;deactivated=true;}
-return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.map.getLonLatFromPixel(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();}
-if(this.persist){this.clear();}
-this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.map.getLonLatFromPixel(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));}
-this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;}
-this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);}
-this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);}
-this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];}
-for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);}
-if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Lang["bg"]=OpenLayers.Util.applyDefaults({'Permalink':"Постоянна препратка",'Base Layer':"Основен слой",'errorLoadingGML':"Грешка при зареждане на GML файл ${url}",'Scale = 1 : ${scaleDenom}':"Мащаб = 1 : ${scaleDenom}",'layerAlreadyAdded':"Опитахте да добавите слой ${layerName} в картата, но той вече е добавен",'methodDeprecated':"Този метод е остарял и ще бъде премахват в 3.0. Вместо него използвайте ${newMethod}."});OpenLayers.Lang["hr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nepodržani zahtjev ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Osnovna karta",'readNotImplemented':"Čitanje nije implementirano.",'writeNotImplemented':"Pisanje nije implementirano.",'noFID':"Ne mogu ažurirati značajku za koju ne postoji FID.",'errorLoadingGML':"Greška u učitavanju GML datoteke ${url}",'browserNotSupported':"Vaš preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",'componentShouldBe':"addFeatures : komponenta bi trebala biti ${geomType}",'getFeatureError':"getFeatureFromEvent je pozvao Layer bez renderera. Ovo obično znači da ste uništiili Layer, a ne neki Handler koji je povezan s njim.",'commitSuccess':"WFS Transakcija: USPJEŠNA ${response}",'commitFailed':"WFS Transakcija: NEUSPJEŠNA ${response}",'Scale = 1 : ${scaleDenom}':"Mjerilo = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokušali ste dodati layer:  ${layerName} na kartu, ali je već dodan",'methodDeprecated':"Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}.",'boundsAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'lonlatAddError':"Morate dati obje vrijednosti , (lon i lat) da bi dodali funkciju.",'pixelAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'unsupportedGeometryType':"Nepodržani tip geometrije: ${geomType}"});OpenLayers.Lang["be-tarask"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Неапрацаваны вынік запыту ${statusText}",'Permalink':"Сталая спасылка",'Overlays':"Слаі",'Base Layer':"Базавы слой",'readNotImplemented':"Функцыянальнасьць чытаньня ня створаная.",'writeNotImplemented':"Функцыянальнасьць запісу ня створаная.",'noFID':"Немагчыма абнавіць магчымасьць, для якога не існуе FID.",'errorLoadingGML':"Памылка загрузкі файла GML ${url}",'browserNotSupported':"Ваш браўзэр не падтрымлівае вэктарную графіку. У цяперашні момант падтрымліваюцца: ${renderers}",'componentShouldBe':"addFeatures : кампанэнт павінен быць ${geomType}",'getFeatureError':"getFeatureFromEvent выкліканы для слоя бяз рэндэру. Звычайна гэта азначае, што Вы зьнішчылі слой, але пакінулі зьвязаны зь ім апрацоўшчык.",'minZoomLevelError':"Уласьцівасьць minZoomLevel прызначана толькі для выкарыстаньня са слаямі вытворнымі ад FixedZoomLevels. Тое, што  гэты wfs-слой правяраецца на minZoomLevel — рэха прошлага. Але мы ня можам выдаліць гэтую магчымасьць, таму што ад яе залежаць некаторыя заснаваныя на OL дастасаваньні. Тым ня менш, праверка minZoomLevel будзе выдаленая ў вэрсіі 3.0. Калі ласка, выкарыстоўваеце замест яе ўстаноўкі мінімальнага/максымальнага памераў, як апісана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-транзакцыя: ПОСЬПЕХ ${response}",'commitFailed':"WFS-транзакцыя: ПАМЫЛКА ${response}",'googleWarning':"Не атрымалася загрузіць слой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3e Хутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі Google Maps ня быў уключаныя альбо не ўтрымлівае слушны API-ключ для Вашага сайта.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'getLayerWarning':"Немагчыма загрузіць слой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі ${layerLib} ня быў слушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Маштаб = 1 : ${scaleDenom}",'W':"З",'E':"У",'N':"Пн",'S':"Пд",'layerAlreadyAdded':"Вы паспрабавалі дадаць слой ${layerName} на мапу, але ён ужо дададзены",'reprojectDeprecated':"Вы выкарыстоўваеце ўстаноўку \'reproject\' для слоя ${layerName}. Гэтая ўстаноўка зьяўляецца састарэлай: яна выкарыстоўвалася для падтрымкі паказу зьвестак на камэрцыйных базавых мапах, але гэта функцыя цяпер рэалізаваная ў убудаванай падтрымцы сфэрычнай праекцыі Мэркатара. Дадатковая інфармацыя ёсьць на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Гэты мэтад састарэлы і будзе выдалены ў вэрсіі 3.0. Калі ласка, замест яго выкарыстоўвайце ${newMethod}.",'boundsAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'lonlatAddError':"Вам неабходна падаць абодва значэньні lon і lat для функцыі складаньня.",'pixelAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'unsupportedGeometryType':"Тып геамэтрыі не падтрымліваецца: ${geomType}",'filterEvaluateNotImplemented':"evaluate не рэалізаваны для гэтага тыпу фільтру."});OpenLayers.Lang["cs-CZ"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nezpracovaná návratová hodnota ${statusText}",'Permalink':"Trvalý odkaz",'Overlays':"Překryvné vrstvy",'Base Layer':"Podkladové vrstvy",'readNotImplemented':"Read není implementováno.",'writeNotImplemented':"Write není implementováno.",'noFID':"Nelze aktualizovat prvek, pro který neexistuje FID.",'errorLoadingGML':"Chyba při načítání souboru GML ${url}",'browserNotSupported':"Váš prohlížeč nepodporuje vykreslování vektorů. Momentálně podporované nástroje jsou::\n${renderers}",'componentShouldBe':"addFeatures : komponenta by měla být ${geomType}",'getFeatureError':"getFeatureFromEvent bylo zavoláno na vrstvě, která nemá vykreslovač. To obyčejně znamená, že jste odstranil vrstvu, ale ne rutinu s ní asociovanou.",'minZoomLevelError':"Vlastnost minZoomLevel by se měla používat pouze s potomky FixedZoomLevels vrstvami. To znamená, že vrstva wfs kontroluje, zda-li minZoomLevel není zbytek z minulosti.Nelze to ovšem vyjmout bez možnosti, že bychom rozbili aplikace postavené na OL, které by na tom mohly záviset. Proto tuto vlastnost nedoporučujeme používat --  kontrola minZoomLevel bude odstraněna ve verzi 3.0. Použijte prosím raději nastavení min/max podle příkaldu popsaného na: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: ÚSPĚCH ${response}",'commitFailed':"WFS Transaction: CHYBA ${response}",'googleWarning':"Nepodařilo se správně načíst vrstvu Google.\x3cbr\x3e\x3cbr\x3eAbyste se zbavili této zprávy, zvolte jinou základní vrstvu v přepínači vrstev.\x3cbr\x3e\x3cbr\x3eTo se většinou stává, pokud nebyl načten skript, nebo neobsahuje správný klíč pro API pro tuto stránku.\x3cbr\x3e\x3cbr\x3eVývojáři: Pro pomoc, aby tohle fungovalo , \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklikněte sem\x3c/a\x3e",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.\x3cbr\x3e\x3cbr\x3eTo get rid of this message, select a new BaseLayer in the layer switcher in the upper-right corner.\x3cbr\x3e\x3cbr\x3eMost likely, this is because the ${layerLib} library script was either not correctly included.\x3cbr\x3e\x3cbr\x3eDevelopers: For help getting this working correctly, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měřítko = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokusili jste se přidat vrstvu: ${layerName} do mapy, ale tato vrstva je již v mapě přítomna.",'reprojectDeprecated':"Použil jste volbu \'reproject\' ve vrstvě ${layerName}. Tato volba není doporučená: byla zde proto, aby bylo možno zobrazovat data z okomerčních serverů, ale tato funkce je nyní zajištěna pomocí podpory Spherical Mercator. Více informací naleznete na http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Tato metoda je zavržená a bude ve verzi 3.0 odstraněna. Prosím, použijte raději ${newMethod}.",'boundsAddError':"Pro přídavnou funkci musíte zadat obě souřadnice x a y.",'lonlatAddError':"Pro přídavnou funkci musíte zadat obě souřadnice lon a lat.",'pixelAddError':"Pro přídavnou funkci musíte zadat obě souřadnice x a y.",'unsupportedGeometryType':"Nepodporovaný typ geometrie: ${geomType}"});OpenLayers.Lang["br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Distro evel reked anveret ${statusText}",'Permalink':"Peurliamm",'Overlays':"Gwiskadoù",'Base Layer':"Gwiskad diazez",'readNotImplemented':"N\'eo ket emplementet al lenn.",'writeNotImplemented':"N\'eo ket emplementet ar skrivañ.",'noFID':"N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",'errorLoadingGML':"Fazi e-ser kargañ ar restr GML ${url}",'browserNotSupported':"N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",'componentShouldBe':"addFeatures : bez\' e tlefe ar parzh besañ eus ar seurt ${geomType}",'getFeatureError':"Galvet eo bet getFeatureFromEvent called war ur gwiskad hep daskorer. Kement-se a dalvez ez eus bet freuzet ur gwiskad hag hoc\'h eus miret un embreger bennak stag outañ.",'minZoomLevelError':"Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Treuzgread WFS : MAT EO ${response}",'commitFailed':"Treuzgread WFS Transaction: C\'HWITET ${response}",'googleWarning':"N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'getLayerWarning':"N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Skeul = 1 : ${scaleDenom}",'W':"K",'E':"R",'N':"N",'S':"S",'layerAlreadyAdded':"Klasket hoc\'h eus ouzhpennañ ar gwiskad : ${layerName} d\'ar gartenn, met ouzhpennet e oa bet c\'hoazh",'reprojectDeprecated':"Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas.",'boundsAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'lonlatAddError':"Rekis eo tremen an div dalvoudenn hedred ha ledred d\'an arc\'hwel add.",'pixelAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'unsupportedGeometryType':"Seurt mentoniezh anskoret : ${geomType}",'filterEvaluateNotImplemented':"N\'eo ket bet emplementet ar priziañ evit seurt siloù c\'hoazh."});OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,containerOrigin:null,pinchOrigin:null,currentCenter:null,autoActivate:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions);},activate:function(){var activated=OpenLayers.Control.prototype.activate.apply(this,arguments);if(activated){this.map.events.on({moveend:this.updateContainerOrigin,scope:this});this.updateContainerOrigin();}
+cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Lang["vi"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Không xử lý được phản hồi ${statusText} cho yêu cầu",'Permalink':"Liên kết thường trực",'Overlays':"Lấp bản đồ",'Base Layer':"Lớp nền",'readNotImplemented':"Chưa hỗ trợ chức năng đọc.",'writeNotImplemented':"Chưa hỗ trợ chức năng viết.",'noFID':"Không thể cập nhật tính năng thiếu FID.",'errorLoadingGML':"Lỗi tải tập tin GML tại ${url}",'browserNotSupported':"Trình duyệt của bạn không hỗ trợ chức năng vẽ bằng vectơ. Hiện hỗ trợ các bộ kết xuất:\n${renderers}",'componentShouldBe':"addFeatures: bộ phận cần phải là ${geomType}",'getFeatureError':"getFeatureFromEvent được gọi từ lớp không có bộ kết xuất. Thường thì có lẽ lớp bị xóa nhưng một phần xử lý của nó vẫn còn.",'minZoomLevelError':"Chỉ nên sử dụng thuộc tính minZoomLevel với các lớp FixedZoomLevels-descendent. Việc lớp wfs này tìm cho minZoomLevel là di tích còn lại từ xưa. Tuy nhiên, nếu chúng tôi dời nó thì sẽ vỡ các chương trình OpenLayers mà dựa trên nó. Bởi vậy chúng tôi phản đối sử dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dời vào phiên bản 3.0. Xin sử dụng thiết lập độ phân tích tối thiểu / tối đa thay thế, theo hướng dẫn này: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Giao dịch WFS: THÀNH CÔNG ${response}",'commitFailed':"Giao dịch WFS: THẤT BẠI ${response}",'googleWarning':"Không thể tải lớp Google đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp với website của bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'getLayerWarning':"Không thể tải lớp ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'Scale = 1 : ${scaleDenom}':"Tỷ lệ = 1 : ${scaleDenom}",'W':"T",'E':"Đ",'N':"B",'S':"N",'layerAlreadyAdded':"Bạn muốn thêm lớp ${layerName} vào bản đồ, nhưng lớp này đã được thêm",'reprojectDeprecated':"Bạn đang áp dụng chế độ “reproject” vào lớp ${layerName}. Chế độ này đã bị phản đối: nó có mục đích hỗ trợ lấp dữ liệu trên các nền bản đồ thương mại; nên thực hiện hiệu ứng đó dùng tính năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",'methodDeprecated':"Phương thức này đã bị phản đối và sẽ bị dời vào phiên bản 3.0. Xin hãy sử dụng ${newMethod} thay thế.",'boundsAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'lonlatAddError':"Cần phải cho cả giá trị lon và lat vào hàm add.",'pixelAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'unsupportedGeometryType':"Không hỗ trợ kiểu địa lý: ${geomType}",'filterEvaluateNotImplemented':"chưa hỗ trợ evaluate cho loại bộ lọc này."});OpenLayers.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:true,defaultFilter:null,initialize:function(options){options=options||{};OpenLayers.Util.extend(this,options);this.options=options;},mergeWithDefaultFilter:function(filter){var merged;if(filter&&this.defaultFilter){merged=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,filter]});}else{merged=filter||this.defaultFilter||undefined;}
+return merged;},destroy:function(){this.options=null;this.format=null;},read:function(options){options=options||{};options.filter=this.mergeWithDefaultFilter(options.filter);},create:function(){},update:function(){},"delete":function(){},commit:function(){},abort:function(response){},createCallback:function(method,response,options){return OpenLayers.Function.bind(function(){method.apply(this,[response,options]);},this);},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:true,features:null,reqFeatures:null,priv:null,error:null,initialize:function(options){OpenLayers.Util.extend(this,options);},success:function(){return this.code>0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:false,wildcarded:false,srsInBBOX:false,initialize:function(options){options=options||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);if(!this.filterToParams&&OpenLayers.Format.QueryStringFilter){var format=new OpenLayers.Format.QueryStringFilter({wildcarded:this.wildcarded,srsInBBOX:this.srsInBBOX});this.filterToParams=function(filter,params){return format.write(filter,params);}}},destroy:function(){this.params=null;this.headers=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=options||{};options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);options=OpenLayers.Util.applyDefaults(options,this.options);if(options.filter&&this.filterToParams){options.params=this.filterToParams(options.filter,options.params);}
+var readWithPOST=(options.readWithPOST!==undefined)?options.readWithPOST:this.readWithPOST;var resp=new OpenLayers.Protocol.Response({requestType:"read"});if(readWithPOST){resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,resp,options),data:OpenLayers.Util.getParameterString(options.params),headers:{"Content-Type":"application/x-www-form-urlencoded"}});}else{resp.priv=OpenLayers.Request.GET({url:options.url,callback:this.createCallback(this.handleRead,resp,options),params:options.params,headers:options.headers});}
+return resp;},handleRead:function(resp,options){this.handleResponse(resp,options);},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:features,requestType:"create"});resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleCreate,resp,options),headers:options.headers,data:this.format.write(features)});return resp;},handleCreate:function(resp,options){this.handleResponse(resp,options);},update:function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"update"});resp.priv=OpenLayers.Request.PUT({url:url,callback:this.createCallback(this.handleUpdate,resp,options),headers:options.headers,data:this.format.write(feature)});return resp;},handleUpdate:function(resp,options){this.handleResponse(resp,options);},"delete":function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"delete"});resp.priv=OpenLayers.Request.DELETE({url:url,callback:this.createCallback(this.handleDelete,resp,options),headers:options.headers});return resp;},handleDelete:function(resp,options){this.handleResponse(resp,options);},handleResponse:function(resp,options){var request=resp.priv;if(options.callback){if(request.status>=200&&request.status<300){if(resp.requestType!="delete"){resp.features=this.parseFeatures(request);}
+resp.code=OpenLayers.Protocol.Response.SUCCESS;}else{resp.code=OpenLayers.Protocol.Response.FAILURE;}
+options.callback.call(options.scope,resp);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
+if(!doc||doc.length<=0){return null;}
+return this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=[],nResponses=0;var types={};types[OpenLayers.State.INSERT]=[];types[OpenLayers.State.UPDATE]=[];types[OpenLayers.State.DELETE]=[];var feature,list,requestFeatures=[];for(var i=0,len=features.length;i<len;++i){feature=features[i];list=types[feature.state];if(list){list.push(feature);requestFeatures.push(feature);}}
+var nRequests=(types[OpenLayers.State.INSERT].length>0?1:0)+
+types[OpenLayers.State.UPDATE].length+
+types[OpenLayers.State.DELETE].length;var success=true;var finalResponse=new OpenLayers.Protocol.Response({reqFeatures:requestFeatures});function insertCallback(response){var len=response.features?response.features.length:0;var fids=new Array(len);for(var i=0;i<len;++i){fids[i]=response.features[i].fid;}
+finalResponse.insertIds=fids;callback.apply(this,[response]);}
+function callback(response){this.callUserCallback(response,options);success=success&&response.success();nResponses++;if(nResponses>=nRequests){if(options.callback){finalResponse.code=success?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.apply(options.scope,[finalResponse]);}}}
+var queue=types[OpenLayers.State.INSERT];if(queue.length>0){resp.push(this.create(queue,OpenLayers.Util.applyDefaults({callback:insertCallback,scope:this},options.create)));}
+queue=types[OpenLayers.State.UPDATE];for(var i=queue.length-1;i>=0;--i){resp.push(this.update(queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options.update)));}
+queue=types[OpenLayers.State.DELETE];for(var i=queue.length-1;i>=0;--i){resp.push(this["delete"](queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options["delete"])));}
+return resp;},abort:function(response){if(response){response.priv.abort();}},callUserCallback:function(resp,options){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}},CLASS_NAME:"OpenLayers.Protocol.HTTP"});OpenLayers.Lang["bg"]=OpenLayers.Util.applyDefaults({'Permalink':"Постоянна препратка",'Base Layer':"Основен слой",'errorLoadingGML':"Грешка при зареждане на GML файл ${url}",'Scale = 1 : ${scaleDenom}':"Мащаб = 1 : ${scaleDenom}",'layerAlreadyAdded':"Опитахте да добавите слой ${layerName} в картата, но той вече е добавен",'methodDeprecated':"Този метод е остарял и ще бъде премахват в 3.0. Вместо него използвайте ${newMethod}."});OpenLayers.Lang["hr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nepodržani zahtjev ${statusText}",'Permalink':"Permalink",'Overlays':"Overlays",'Base Layer':"Osnovna karta",'readNotImplemented':"Čitanje nije implementirano.",'writeNotImplemented':"Pisanje nije implementirano.",'noFID':"Ne mogu ažurirati značajku za koju ne postoji FID.",'errorLoadingGML':"Greška u učitavanju GML datoteke ${url}",'browserNotSupported':"Vaš preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",'componentShouldBe':"addFeatures : komponenta bi trebala biti ${geomType}",'getFeatureError':"getFeatureFromEvent je pozvao Layer bez renderera. Ovo obično znači da ste uništiili Layer, a ne neki Handler koji je povezan s njim.",'commitSuccess':"WFS Transakcija: USPJEŠNA ${response}",'commitFailed':"WFS Transakcija: NEUSPJEŠNA ${response}",'Scale = 1 : ${scaleDenom}':"Mjerilo = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokušali ste dodati layer:  ${layerName} na kartu, ali je već dodan",'methodDeprecated':"Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}.",'boundsAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'lonlatAddError':"Morate dati obje vrijednosti , (lon i lat) da bi dodali funkciju.",'pixelAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'unsupportedGeometryType':"Nepodržani tip geometrije: ${geomType}"});OpenLayers.Lang["be-tarask"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Неапрацаваны вынік запыту ${statusText}",'Permalink':"Сталая спасылка",'Overlays':"Слаі",'Base Layer':"Базавы слой",'readNotImplemented':"Функцыянальнасьць чытаньня ня створаная.",'writeNotImplemented':"Функцыянальнасьць запісу ня створаная.",'noFID':"Немагчыма абнавіць магчымасьць, для якога не існуе FID.",'errorLoadingGML':"Памылка загрузкі файла GML ${url}",'browserNotSupported':"Ваш браўзэр не падтрымлівае вэктарную графіку. У цяперашні момант падтрымліваюцца: ${renderers}",'componentShouldBe':"addFeatures : кампанэнт павінен быць ${geomType}",'getFeatureError':"getFeatureFromEvent выкліканы для слоя бяз рэндэру. Звычайна гэта азначае, што Вы зьнішчылі слой, але пакінулі зьвязаны зь ім апрацоўшчык.",'minZoomLevelError':"Уласьцівасьць minZoomLevel прызначана толькі для выкарыстаньня са слаямі вытворнымі ад FixedZoomLevels. Тое, што  гэты wfs-слой правяраецца на minZoomLevel — рэха прошлага. Але мы ня можам выдаліць гэтую магчымасьць, таму што ад яе залежаць некаторыя заснаваныя на OL дастасаваньні. Тым ня менш, праверка minZoomLevel будзе выдаленая ў вэрсіі 3.0. Калі ласка, выкарыстоўваеце замест яе ўстаноўкі мінімальнага/максымальнага памераў, як апісана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-транзакцыя: ПОСЬПЕХ ${response}",'commitFailed':"WFS-транзакцыя: ПАМЫЛКА ${response}",'googleWarning':"Не атрымалася загрузіць слой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3e Хутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі Google Maps ня быў уключаныя альбо не ўтрымлівае слушны API-ключ для Вашага сайта.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'getLayerWarning':"Немагчыма загрузіць слой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі ${layerLib} ня быў слушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Маштаб = 1 : ${scaleDenom}",'W':"З",'E':"У",'N':"Пн",'S':"Пд",'layerAlreadyAdded':"Вы паспрабавалі дадаць слой ${layerName} на мапу, але ён ужо дададзены",'reprojectDeprecated':"Вы выкарыстоўваеце ўстаноўку \'reproject\' для слоя ${layerName}. Гэтая ўстаноўка зьяўляецца састарэлай: яна выкарыстоўвалася для падтрымкі паказу зьвестак на камэрцыйных базавых мапах, але гэта функцыя цяпер рэалізаваная ў убудаванай падтрымцы сфэрычнай праекцыі Мэркатара. Дадатковая інфармацыя ёсьць на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Гэты мэтад састарэлы і будзе выдалены ў вэрсіі 3.0. Калі ласка, замест яго выкарыстоўвайце ${newMethod}.",'boundsAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'lonlatAddError':"Вам неабходна падаць абодва значэньні lon і lat для функцыі складаньня.",'pixelAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'unsupportedGeometryType':"Тып геамэтрыі не падтрымліваецца: ${geomType}",'filterEvaluateNotImplemented':"evaluate не рэалізаваны для гэтага тыпу фільтру."});OpenLayers.Lang["cs-CZ"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nezpracovaná návratová hodnota ${statusText}",'Permalink':"Trvalý odkaz",'Overlays':"Překryvné vrstvy",'Base Layer':"Podkladové vrstvy",'readNotImplemented':"Read není implementováno.",'writeNotImplemented':"Write není implementováno.",'noFID':"Nelze aktualizovat prvek, pro který neexistuje FID.",'errorLoadingGML':"Chyba při načítání souboru GML ${url}",'browserNotSupported':"Váš prohlížeč nepodporuje vykreslování vektorů. Momentálně podporované nástroje jsou::\n${renderers}",'componentShouldBe':"addFeatures : komponenta by měla být ${geomType}",'getFeatureError':"getFeatureFromEvent bylo zavoláno na vrstvě, která nemá vykreslovač. To obyčejně znamená, že jste odstranil vrstvu, ale ne rutinu s ní asociovanou.",'minZoomLevelError':"Vlastnost minZoomLevel by se měla používat pouze s potomky FixedZoomLevels vrstvami. To znamená, že vrstva wfs kontroluje, zda-li minZoomLevel není zbytek z minulosti.Nelze to ovšem vyjmout bez možnosti, že bychom rozbili aplikace postavené na OL, které by na tom mohly záviset. Proto tuto vlastnost nedoporučujeme používat --  kontrola minZoomLevel bude odstraněna ve verzi 3.0. Použijte prosím raději nastavení min/max podle příkaldu popsaného na: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: ÚSPĚCH ${response}",'commitFailed':"WFS Transaction: CHYBA ${response}",'googleWarning':"Nepodařilo se správně načíst vrstvu Google.\x3cbr\x3e\x3cbr\x3eAbyste se zbavili této zprávy, zvolte jinou základní vrstvu v přepínači vrstev.\x3cbr\x3e\x3cbr\x3eTo se většinou stává, pokud nebyl načten skript, nebo neobsahuje správný klíč pro API pro tuto stránku.\x3cbr\x3e\x3cbr\x3eVývojáři: Pro pomoc, aby tohle fungovalo , \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklikněte sem\x3c/a\x3e",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.\x3cbr\x3e\x3cbr\x3eTo get rid of this message, select a new BaseLayer in the layer switcher in the upper-right corner.\x3cbr\x3e\x3cbr\x3eMost likely, this is because the ${layerLib} library script was either not correctly included.\x3cbr\x3e\x3cbr\x3eDevelopers: For help getting this working correctly, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Měřítko = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokusili jste se přidat vrstvu: ${layerName} do mapy, ale tato vrstva je již v mapě přítomna.",'reprojectDeprecated':"Použil jste volbu \'reproject\' ve vrstvě ${layerName}. Tato volba není doporučená: byla zde proto, aby bylo možno zobrazovat data z okomerčních serverů, ale tato funkce je nyní zajištěna pomocí podpory Spherical Mercator. Více informací naleznete na http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Tato metoda je zavržená a bude ve verzi 3.0 odstraněna. Prosím, použijte raději ${newMethod}.",'boundsAddError':"Pro přídavnou funkci musíte zadat obě souřadnice x a y.",'lonlatAddError':"Pro přídavnou funkci musíte zadat obě souřadnice lon a lat.",'pixelAddError':"Pro přídavnou funkci musíte zadat obě souřadnice x a y.",'unsupportedGeometryType':"Nepodporovaný typ geometrie: ${geomType}"});OpenLayers.Lang["br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Distro evel reked anveret ${statusText}",'Permalink':"Peurliamm",'Overlays':"Gwiskadoù",'Base Layer':"Gwiskad diazez",'readNotImplemented':"N\'eo ket emplementet al lenn.",'writeNotImplemented':"N\'eo ket emplementet ar skrivañ.",'noFID':"N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",'errorLoadingGML':"Fazi e-ser kargañ ar restr GML ${url}",'browserNotSupported':"N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",'componentShouldBe':"addFeatures : bez\' e tlefe ar parzh besañ eus ar seurt ${geomType}",'getFeatureError':"Galvet eo bet getFeatureFromEvent called war ur gwiskad hep daskorer. Kement-se a dalvez ez eus bet freuzet ur gwiskad hag hoc\'h eus miret un embreger bennak stag outañ.",'minZoomLevelError':"Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Treuzgread WFS : MAT EO ${response}",'commitFailed':"Treuzgread WFS Transaction: C\'HWITET ${response}",'googleWarning':"N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'getLayerWarning':"N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'Scale = 1 : ${scaleDenom}':"Skeul = 1 : ${scaleDenom}",'W':"K",'E':"R",'N':"N",'S':"S",'layerAlreadyAdded':"Klasket hoc\'h eus ouzhpennañ ar gwiskad : ${layerName} d\'ar gartenn, met ouzhpennet e oa bet c\'hoazh",'reprojectDeprecated':"Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas.",'boundsAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'lonlatAddError':"Rekis eo tremen an div dalvoudenn hedred ha ledred d\'an arc\'hwel add.",'pixelAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'unsupportedGeometryType':"Seurt mentoniezh anskoret : ${geomType}",'filterEvaluateNotImplemented':"N\'eo ket bet emplementet ar priziañ evit seurt siloù c\'hoazh."});OpenLayers.Control.PinchZoom=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,containerOrigin:null,pinchOrigin:null,currentCenter:null,autoActivate:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.handler=new OpenLayers.Handler.Pinch(this,{start:this.pinchStart,move:this.pinchMove,done:this.pinchDone},this.handlerOptions);},activate:function(){var activated=OpenLayers.Control.prototype.activate.apply(this,arguments);if(activated){this.map.events.on({moveend:this.updateContainerOrigin,scope:this});this.updateContainerOrigin();}
 return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.apply(this,arguments);if(this.map&&this.map.events){this.map.events.un({moveend:this.updateContainerOrigin,scope:this});}
 return deactivated;},updateContainerOrigin:function(){var container=this.map.layerContainerDiv;this.containerOrigin={x:parseInt(container.style.left,10),y:parseInt(container.style.top,10)};},pinchStart:function(evt,pinchData){this.pinchOrigin=evt.xy;this.currentCenter=evt.xy;},pinchMove:function(evt,pinchData){var scale=pinchData.scale;var containerOrigin=this.containerOrigin;var pinchOrigin=this.pinchOrigin;var current=evt.xy;var dx=Math.round((current.x-pinchOrigin.x)+(scale-1)*(containerOrigin.x-pinchOrigin.x));var dy=Math.round((current.y-pinchOrigin.y)+(scale-1)*(containerOrigin.y-pinchOrigin.y));this.applyTransform("translate("+dx+"px, "+dy+"px) scale("+scale+")");this.currentCenter=current;},applyTransform:function(transform){var style=this.map.layerContainerDiv.style;style['-webkit-transform']=transform;style['-moz-transform']=transform;},pinchDone:function(evt,start,last){this.applyTransform("");var zoom=this.map.getZoomForResolution(this.map.getResolution()/last.scale,true);if(zoom!==this.map.getZoom()||!this.currentCenter.equals(this.pinchOrigin)){var resolution=this.map.getResolutionForZoom(zoom);var location=this.map.getLonLatFromPixel(this.pinchOrigin);var zoomPixel=this.currentCenter;var size=this.map.getSize();location.lon+=resolution*((size.w/2)-zoomPixel.x);location.lat-=resolution*((size.h/2)-zoomPixel.y);this.map.setCenter(location,zoom);}},CLASS_NAME:"OpenLayers.Control.PinchZoom"});OpenLayers.Lang["io"]=OpenLayers.Util.applyDefaults({'Scale = 1 : ${scaleDenom}':"Skalo = 1 : ${scaleDenom}"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{roundedCorner:true,roundedCornerColor:"darkblue",layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[];},destroy:function(){OpenLayers.Event.stopObservingElement(this.div);OpenLayers.Event.stopObservingElement(this.minimizeDiv);OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);this.map.events.on({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();if(!this.outsideViewport){this.minimizeControl();}
 this.redraw();return this.div;},clearLayersArray:function(layersType){var layers=this[layersType+"Layers"];if(layers){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];OpenLayers.Event.stopObservingElement(layer.inputElem);OpenLayers.Event.stopObservingElement(layer.labelSpan);}}