2 Dervied from the OpenStreetBugs client, which is available
3 under the following license.
5 This OpenStreetBugs client is free software: you can redistribute it
6 and/or modify it under the terms of the GNU Affero General Public License
7 as published by the Free Software Foundation, either version 3 of the
8 License, or (at your option) any later version.
10 This file is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
13 License <http://www.gnu.org/licenses/> for more details.
16 OpenLayers.Layer.Notes = new OpenLayers.Class(OpenLayers.Layer.Markers, {
18 * The URL of the OpenStreetMap API.
22 serverURL : "/api/0.6/",
25 * Associative array (index: note ID) that is filled with the notes
26 * loaded in this layer.
33 * The username to be used to change or create notes on OpenStreetMap.
40 * The icon to be used for an open note.
42 * @var OpenLayers.Icon
44 iconOpen : new OpenLayers.Icon("/images/open_note_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
47 * The icon to be used for a closed note.
49 * @var OpenLayers.Icon
51 iconClosed : new OpenLayers.Icon("/images/closed_note_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
54 * The projection of the coordinates sent by the OpenStreetMap API.
56 * @var OpenLayers.Projection
58 apiProjection : new OpenLayers.Projection("EPSG:4326"),
61 * If this is set to true, the user may not commit comments or close notes.
68 * When the layer is hidden, all open popups are stored in this
69 * array in order to be re-opened again when the layer is made
75 * A URL to append lon=123&lat=123&zoom=123 for the Permalinks.
79 permalinkURL : "http://www.openstreetmap.org/",
82 * A CSS file to be included. Set to null if you don’t need this.
86 theme : "/stylesheets/notes.css",
91 initialize: function(name, options) {
92 OpenLayers.Layer.Markers.prototype.initialize.apply(this, [
94 OpenLayers.Util.extend({
96 projection: new OpenLayers.Projection("EPSG:4326") }, options)
99 putAJAXMarker.layers.push(this);
100 this.events.addEventType("markerAdded");
102 this.events.register("visibilitychanged", this, this.updatePopupVisibility);
103 this.events.register("visibilitychanged", this, this.loadNotes);
106 // check existing links for equivalent url
108 var nodes = document.getElementsByTagName('link');
109 for (var i = 0, len = nodes.length; i < len; ++i) {
110 if (OpenLayers.Util.isEquivalentUrl(nodes.item(i).href, this.theme)) {
115 // only add a new node if one with an equivalent url hasn't already
118 var cssNode = document.createElement('link');
119 cssNode.setAttribute('rel', 'stylesheet');
120 cssNode.setAttribute('type', 'text/css');
121 cssNode.setAttribute('href', this.theme);
122 document.getElementsByTagName('head')[0].appendChild(cssNode);
128 * Called automatically called when the layer is added to a map.
129 * Initialises the automatic note loading in the visible bounding box.
131 afterAdd: function() {
132 var ret = OpenLayers.Layer.Markers.prototype.afterAdd.apply(this, arguments);
134 this.map.events.register("moveend", this, this.loadNotes);
141 * At the moment the OpenStreetMap API responses to requests using
142 * JavaScript code. This way the Same Origin Policy can be worked
143 * around. Unfortunately, this makes communicating with the API a
144 * bit too asynchronous, at the moment there is no way to tell to
145 * which request the API actually responses.
147 * This method creates a new script HTML element that imports the
148 * API request URL. The API JavaScript response then executes the
149 * global functions provided below.
151 * @param String url The URL this.serverURL + url is requested.
153 apiRequest: function(url) {
154 var script = document.createElement("script");
155 script.type = "text/javascript";
156 script.src = this.serverURL + url + "&nocache="+(new Date()).getTime();
157 document.body.appendChild(script);
161 * Is automatically called when the visibility of the layer
162 * changes. When the layer is hidden, all visible popups are
163 * closed and their visibility is saved. When the layer is made
164 * visible again, these popups are re-opened.
166 updatePopupVisibility: function() {
167 if (this.getVisibility()) {
168 for (var i =0 ; i < this.reopenPopups.length; i++)
169 this.reopenPopups[i].show();
171 this.reopenPopups = [ ];
173 for (var i = 0; i < this.markers.length; i++) {
174 if (this.markers[i].feature.popup &&
175 this.markers[i].feature.popup.visible()) {
176 this.markers[i].feature.popup.hide();
177 this.reopenPopups.push(this.markers[i].feature.popup);
184 * Sets the user name to be used for interactions with OpenStreetMap.
186 setUserName: function(username) {
187 if (this.username == username)
190 this.username = username;
192 for (var i = 0; i < this.markers.length; i++) {
193 var popup = this.markers[i].feature.popup;
196 var els = popup.contentDom.getElementsByTagName("input");
198 for (var j = 0; j < els.length; j++) {
199 if (els[j].className == "username")
200 els[j].value = username;
207 * Returns the currently set username or “NoName” if none is set.
209 getUserName: function() {
211 return this.username;
217 * Loads the notes in the current bounding box. Is automatically
218 * called by an event handler ("moveend" event) that is created in
219 * the afterAdd() method.
221 loadNotes: function() {
222 var bounds = this.map.getExtent();
224 if (bounds && this.getVisibility()) {
225 bounds.transform(this.map.getProjectionObject(), this.apiProjection);
227 this.apiRequest("notes"
228 + "?bbox=" + this.round(bounds.left, 5)
229 + "," + this.round(bounds.bottom, 5)
230 + "," + this.round(bounds.right, 5)
231 + "," + this.round(bounds.top, 5));
236 * Rounds the given number to the given number of digits after the
239 * @param Number number
240 * @param Number digits
243 round: function(number, digits) {
244 var scale = Math.pow(10, digits);
246 return Math.round(number * scale) / scale;
250 * Adds an OpenLayers.Marker representing a note to the map. Is
251 * usually called by loadNotes().
253 * @param Number id The note ID
255 createMarker: function(id) {
256 if (this.notes[id]) {
257 if (this.notes[id].popup && !this.notes[id].popup.visible())
258 this.setPopupContent(this.notes[id].popup, id);
260 if (this.notes[id].closed != putAJAXMarker.notes[id][2])
261 this.notes[id].destroy();
266 var lonlat = putAJAXMarker.notes[id][0].clone().transform(this.apiProjection, this.map.getProjectionObject());
267 var comments = putAJAXMarker.notes[id][1];
268 var closed = putAJAXMarker.notes[id][2];
269 var icon = closed ? this.iconClosed : this.iconOpen;
271 var feature = new OpenLayers.Feature(this, lonlat, {
275 feature.popupClass = OpenLayers.Popup.FramedCloud.Notes;
277 feature.closed = closed;
278 this.notes[id] = feature;
280 var marker = feature.createMarker();
281 marker.feature = feature;
282 marker.events.register("click", feature, this.markerClick);
283 //marker.events.register("mouseover", feature, this.markerMouseOver);
284 //marker.events.register("mouseout", feature, this.markerMouseOut);
285 this.addMarker(marker);
287 this.events.triggerEvent("markerAdded");
291 * Recreates the content of the popup of a marker.
293 * @param OpenLayers.Popup popup
294 * @param Number id The note ID
296 setPopupContent: function(popup, id) {
300 var newContent = document.createElement("div");
302 el1 = document.createElement("h3");
303 el1.appendChild(document.createTextNode(putAJAXMarker.notes[id][2] ? i18n("javascripts.note.closed") : i18n("javascripts.note.open")));
305 el1.appendChild(document.createTextNode(" ["));
306 el2 = document.createElement("a");
307 el2.href = "/browse/note/" + id;
308 el2.onclick = function() {
309 layer.map.setCenter(putAJAXMarker.notes[id][0].clone().transform(layer.apiProjection, layer.map.getProjectionObject()), 15);
311 el2.appendChild(document.createTextNode(i18n("javascripts.note.details")));
312 el1.appendChild(el2);
313 el1.appendChild(document.createTextNode("]"));
315 if (this.permalinkURL) {
316 el1.appendChild(document.createTextNode(" ["));
317 el2 = document.createElement("a");
318 el2.href = this.permalinkURL + (this.permalinkURL.indexOf("?") == -1 ? "?" : "&") + "lon="+putAJAXMarker.notes[id][0].lon+"&lat="+putAJAXMarker.notes[id][0].lat+"&zoom=15";
319 el2.appendChild(document.createTextNode(i18n("javascripts.note.permalink")));
320 el1.appendChild(el2);
321 el1.appendChild(document.createTextNode("]"));
323 newContent.appendChild(el1);
325 var containerDescription = document.createElement("div");
326 newContent.appendChild(containerDescription);
328 var containerChange = document.createElement("div");
329 newContent.appendChild(containerChange);
331 var displayDescription = function() {
332 containerDescription.style.display = "block";
333 containerChange.style.display = "none";
336 var displayChange = function() {
337 containerDescription.style.display = "none";
338 containerChange.style.display = "block";
341 displayDescription();
343 el1 = document.createElement("dl");
344 for (var i = 0; i < putAJAXMarker.notes[id][1].length; i++) {
345 el2 = document.createElement("dt");
346 el2.className = (i == 0 ? "note-description" : "note-comment");
347 el2.appendChild(document.createTextNode(i == 0 ? i18n("javascripts.note.description") : i18n("javascripts.note.comment")));
348 el1.appendChild(el2);
349 el2 = document.createElement("dd");
350 el2.className = (i == 0 ? "note-description" : "note-comment");
351 el2.appendChild(document.createTextNode(putAJAXMarker.notes[id][1][i]));
352 el1.appendChild(el2);
354 el2 = document.createElement("br");
355 el1.appendChild(el2);
358 containerDescription.appendChild(el1);
360 if (putAJAXMarker.notes[id][2]) {
361 el1 = document.createElement("p");
362 el1.className = "note-fixed";
363 el2 = document.createElement("em");
364 el2.appendChild(document.createTextNode(i18n("javascripts.note.render_warning")));
365 el1.appendChild(el2);
366 containerDescription.appendChild(el1);
367 } else if (!this.readonly) {
368 el1 = document.createElement("div");
369 el2 = document.createElement("input");
370 el2.setAttribute("type", "button");
371 el2.onclick = function() {
374 el2.value = i18n("javascripts.note.update");
375 el1.appendChild(el2);
376 containerDescription.appendChild(el1);
378 var el_form = document.createElement("form");
379 el_form.onsubmit = function() {
380 if (inputComment.value.match(/^\s*$/))
382 layer.submitComment(id, inputComment.value);
383 layer.hidePopup(popup);
387 el1 = document.createElement("dl");
388 el2 = document.createElement("dt");
389 el2.appendChild(document.createTextNode(i18n("javascripts.note.nickname")));
390 el1.appendChild(el2);
391 el2 = document.createElement("dd");
392 var inputUsername = document.createElement("input");
393 var inputUsername = document.createElement("input");;
394 if (typeof loginName === "undefined") {
395 inputUsername.value = this.username;
397 inputUsername.value = loginName;
398 inputUsername.setAttribute("disabled", "true");
400 inputUsername.className = "username";
401 inputUsername.onkeyup = function() {
402 layer.setUserName(inputUsername.value);
404 el2.appendChild(inputUsername);
405 el3 = document.createElement("a");
406 el3.setAttribute("href", "login");
407 el3.className = "hide_if_logged_in";
408 el3.appendChild(document.createTextNode(i18n("javascripts.note.login")));
410 el1.appendChild(el2);
412 el2 = document.createElement("dt");
413 el2.appendChild(document.createTextNode(i18n("javascripts.note.comment")));
414 el1.appendChild(el2);
415 el2 = document.createElement("dd");
416 var inputComment = document.createElement("textarea");
417 inputComment.setAttribute("cols",40);
418 inputComment.setAttribute("rows",3);
420 el2.appendChild(inputComment);
421 el1.appendChild(el2);
423 el_form.appendChild(el1);
425 el1 = document.createElement("ul");
426 el1.className = "buttons";
427 el2 = document.createElement("li");
428 el3 = document.createElement("input");
429 el3.setAttribute("type", "button");
430 el3.onclick = function() {
431 this.form.onsubmit();
434 el3.value = i18n("javascripts.note.add_comment");
435 el2.appendChild(el3);
436 el1.appendChild(el2);
438 el2 = document.createElement("li");
439 el3 = document.createElement("input");
440 el3.setAttribute("type", "button");
441 el3.onclick = function() {
442 this.form.onsubmit();
447 el3.value = i18n("javascripts.note.close");
448 el2.appendChild(el3);
449 el1.appendChild(el2);
450 el_form.appendChild(el1);
451 containerChange.appendChild(el_form);
453 el1 = document.createElement("div");
454 el2 = document.createElement("input");
455 el2.setAttribute("type", "button");
456 el2.onclick = function(){ displayDescription(); };
457 el2.value = i18n("javascripts.note.cancel");
458 el1.appendChild(el2);
459 containerChange.appendChild(el1);
462 popup.setContentHTML(newContent);
466 * Creates a new note.
468 * @param OpenLayers.LonLat lonlat The coordinates in the API projection.
469 * @param String description
471 createNote: function(lonlat, description) {
472 this.apiRequest("note/create"
473 + "?lat=" + encodeURIComponent(lonlat.lat)
474 + "&lon=" + encodeURIComponent(lonlat.lon)
475 + "&text=" + encodeURIComponent(description)
476 + "&name=" + encodeURIComponent(this.getUserName())
481 * Adds a comment to a note.
484 * @param String comment
486 submitComment: function(id, comment) {
487 this.apiRequest("note/" + encodeURIComponent(id) + "/comment"
488 + "?text=" + encodeURIComponent(comment)
489 + "&name=" + encodeURIComponent(this.getUserName())
494 * Marks a note as fixed.
498 closeNote: function(id) {
499 this.apiRequest("note/" + encodeURIComponent(id) + "/close"
504 * Removes the content of a marker popup (to reduce the amount of
507 * @param OpenLayers.Popup popup
509 resetPopupContent: function(popup) {
511 popup.setContentHTML(document.createElement("div"));
515 * Makes the popup of the given marker visible. Makes sure that
516 * the popup content is created if it does not exist yet.
518 * @param OpenLayers.Feature feature
520 showPopup: function(feature) {
521 var popup = feature.popup;
524 popup = feature.createPopup(true);
526 popup.events.register("close", this, function() {
527 this.resetPopupContent(popup);
531 this.setPopupContent(popup, feature.noteId);
534 this.map.addPopup(popup);
538 if (!popup.visible())
543 * Hides the popup of the given marker.
545 * @param OpenLayers.Feature feature
547 hidePopup: function(feature) {
548 if (feature.popup && feature.popup.visible()) {
549 feature.popup.hide();
550 feature.popup.events.triggerEvent("close");
555 * Is run on the “click” event of a marker in the context of its
556 * OpenLayers.Feature. Toggles the visibility of the popup.
558 markerClick: function(e) {
561 if (feature.popup && feature.popup.visible())
562 feature.layer.hidePopup(feature);
564 feature.layer.showPopup(feature);
566 OpenLayers.Event.stop(e);
570 * Is run on the “mouseover” event of a marker in the context of
571 * its OpenLayers.Feature. Makes the popup visible.
573 markerMouseOver: function(e) {
576 feature.layer.showPopup(feature);
578 OpenLayers.Event.stop(e);
582 * Is run on the “mouseout” event of a marker in the context of
583 * its OpenLayers.Feature. Hides the popup (if it has not been
586 markerMouseOut: function(e) {
589 if (feature.popup && feature.popup.visible())
590 feature.layer.hidePopup(feature);
592 OpenLayers.Event.stop(e);
595 CLASS_NAME: "OpenLayers.Layer.Notes"
599 * An OpenLayers control to create new notes on mouse clicks on the
600 * map. Add an instance of this to your map using the
601 * OpenLayers.Map.addControl() method and activate() it.
603 OpenLayers.Control.Notes = new OpenLayers.Class(OpenLayers.Control, {
604 title : null, // See below because of translation call
607 * The icon to be used for the temporary markers that the “create
608 * note” popup belongs to..
610 * @var OpenLayers.Icon
612 icon : new OpenLayers.Icon("/images/icon_note_add.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
615 * An instance of the Notes layer that this control shall be
616 * connected to. Is set in the constructor.
618 * @var OpenLayers.Layer.Notes
623 * @param OpenLayers.Layer.Notes noteLayer The Notes layer that this control will be connected to.
625 initialize: function(noteLayer, options) {
626 this.noteLayer = noteLayer;
628 this.title = i18n("javascripts.note.create");
630 OpenLayers.Control.prototype.initialize.apply(this, [ options ]);
632 this.events.register("activate", this, function() {
633 if(!this.noteLayer.getVisibility())
634 this.noteLayer.setVisibility(true);
637 this.noteLayer.events.register("visibilitychanged", this, function() {
638 if(this.active && !this.noteLayer.getVisibility())
639 this.noteLayer.setVisibility(true);
643 destroy: function() {
645 this.handler.destroy();
648 OpenLayers.Control.prototype.destroy.apply(this, arguments);
652 this.handler = new OpenLayers.Handler.Click(this, {'click': this.click}, { 'single': true, 'double': false, 'pixelTolerance': 0, 'stopSingle': false, 'stopDouble': false });
656 * Map clicking event handler. Adds a temporary marker with a
657 * popup to the map, the popup contains the form to add a note.
660 var lonlat = this.map.getLonLatFromViewPortPx(e.xy);
661 this.addTemporaryMarker(lonlat);
664 addTemporaryMarker: function(lonlat) {
665 if(!this.map) return true;
668 var map = control.map;
669 var lonlatApi = lonlat.clone().transform(map.getProjectionObject(), this.noteLayer.apiProjection);
670 var feature = new OpenLayers.Feature(this.noteLayer, lonlat, { icon: this.icon.clone(), autoSize: true });
671 feature.popupClass = OpenLayers.Popup.FramedCloud.Notes;
672 var marker = feature.createMarker();
673 marker.feature = feature;
674 this.noteLayer.addMarker(marker);
677 /** Implement a drag and drop for markers */
678 /* TODO: veryfy that the scoping of variables works correctly everywhere */
679 var dragging = false;
680 var dragMove = function(e) {
681 lonlat = map.getLonLatFromViewPortPx(e.xy);
682 lonlatApi = lonlat.clone().transform(map.getProjectionObject(), map.noteLayer.apiProjection);
683 marker.moveTo(map.getLayerPxFromViewPortPx(e.xy));
684 marker.popup.moveTo(map.getLayerPxFromViewPortPx(e.xy));
685 marker.popup.updateRelativePosition();
688 var dragComplete = function(e) {
689 map.events.unregister("mousemove", map, dragMove);
690 map.events.unregister("mouseup", map, dragComplete);
696 marker.events.register("mouseover", this, function() {
697 map.viewPortDiv.style.cursor = "move";
699 marker.events.register("mouseout", this, function() {
701 map.viewPortDiv.style.cursor = "default";
703 marker.events.register("mousedown", this, function() {
705 map.events.register("mousemove", map, dragMove);
706 map.events.register("mouseup", map, dragComplete);
710 var newContent = document.createElement("div");
712 el1 = document.createElement("h3");
713 el1.appendChild(document.createTextNode(i18n("javascripts.note.create_title")));
714 newContent.appendChild(el1);
715 newContent.appendChild(document.createTextNode(i18n("javascripts.note.create_help1")));
716 newContent.appendChild(document.createElement("br"));
717 newContent.appendChild(document.createTextNode(i18n("javascripts.note.create_help2")));
718 newContent.appendChild(document.createElement("br"));
719 newContent.appendChild(document.createElement("br"));
721 var el_form = document.createElement("form");
723 el1 = document.createElement("dl");
724 el2 = document.createElement("dt");
725 el2.appendChild(document.createTextNode(i18n("javascripts.note.nickname")));
726 el1.appendChild(el2);
727 el2 = document.createElement("dd");
728 var inputUsername = document.createElement("input");;
729 if (typeof loginName === 'undefined') {
730 inputUsername.value = this.noteLayer.username;
732 inputUsername.value = loginName;
733 inputUsername.setAttribute('disabled','true');
735 inputUsername.className = "username";
737 inputUsername.onkeyup = function(){ control.noteLayer.setUserName(inputUsername.value); };
738 el2.appendChild(inputUsername);
739 el3 = document.createElement("a");
740 el3.setAttribute("href","login");
741 el3.className = "hide_if_logged_in";
742 el3.appendChild(document.createTextNode(i18n("javascripts.note.login")));
743 el2.appendChild(el3);
744 el1.appendChild(el2);
745 el2 = document.createElement("br");
746 el1.appendChild(el2);
748 el2 = document.createElement("dt");
749 el2.appendChild(document.createTextNode(i18n("javascripts.note.description")));
750 el1.appendChild(el2);
751 el2 = document.createElement("dd");
752 var inputDescription = document.createElement("textarea");
753 inputDescription.setAttribute("cols",40);
754 inputDescription.setAttribute("rows",3);
755 el2.appendChild(inputDescription);
756 el1.appendChild(el2);
757 el_form.appendChild(el1);
759 el1 = document.createElement("div");
760 el2 = document.createElement("input");
761 el2.setAttribute("type", "button");
762 el2.value = i18n("javascripts.note.report");
763 el2.onclick = function() { control.noteLayer.createNote(lonlatApi, inputDescription.value); marker.feature = null; feature.destroy(); return false; };
764 el1.appendChild(el2);
765 el2 = document.createElement("input");
766 el2.setAttribute("type", "button");
767 el2.value = i18n("javascripts.note.cancel");
768 el2.onclick = function(){ feature.destroy(); };
769 el1.appendChild(el2);
770 el_form.appendChild(el1);
771 newContent.appendChild(el_form);
773 el2 = document.createElement("hr");
774 el1.appendChild(el2);
775 el2 = document.createElement("a");
776 el2.setAttribute("href","edit");
777 el2.appendChild(document.createTextNode(i18n("javascripts.note.edityourself")));
778 el1.appendChild(el2);
780 feature.data.popupContentHTML = newContent;
781 var popup = feature.createPopup(true);
782 popup.events.register("close", this, function(){ feature.destroy(); });
785 marker.popup = popup;
788 CLASS_NAME: "OpenLayers.Control.Notes"
793 * This class changes the usual OpenLayers.Popup.FramedCloud class by
794 * using a DOM element instead of an innerHTML string as content for
795 * the popup. This is necessary for creating valid onclick handlers
796 * that still work with multiple Notes layer objects.
798 OpenLayers.Popup.FramedCloud.Notes = new OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
803 * See OpenLayers.Popup.FramedCloud.initialize() for
804 * parameters. As fourth parameter, pass a DOM node instead of a
807 initialize: function() {
808 this.displayClass = this.displayClass + " " + this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
810 var args = new Array(arguments.length);
811 for(var i=0; i<arguments.length; i++)
812 args[i] = arguments[i];
814 // Unset original contentHTML parameter
817 var closeCallback = arguments[6];
819 // Add close event trigger to the closeBoxCallback parameter
820 args[6] = function(e){ if(closeCallback) closeCallback(); else this.hide(); OpenLayers.Event.stop(e); this.events.triggerEvent("close"); };
822 OpenLayers.Popup.FramedCloud.prototype.initialize.apply(this, args);
824 this.events.addEventType("close");
826 this.setContentHTML(arguments[3]);
830 * Like OpenLayers.Popup.FramedCloud.setContentHTML(), but takes a
831 * DOM element as parameter.
833 setContentHTML: function(contentDom) {
834 if(contentDom != null)
835 this.contentDom = contentDom;
837 if(this.contentDiv == null || this.contentDom == null || this.contentDom == this.contentDiv.firstChild)
840 while(this.contentDiv.firstChild)
841 this.contentDiv.removeChild(this.contentDiv.firstChild);
843 this.contentDiv.appendChild(this.contentDom);
845 // Copied from OpenLayers.Popup.setContentHTML():
848 this.registerImageListeners();
853 destroy: function() {
854 this.contentDom = null;
855 OpenLayers.Popup.FramedCloud.prototype.destroy.apply(this, arguments);
858 CLASS_NAME: "OpenLayers.Popup.FramedCloud.Notes"
863 * This global function is executed by the OpenStreetMap API getBugs script.
865 * Each Notes layer adds itself to the putAJAXMarker.layer array. The
866 * putAJAXMarker() function executes the createMarker() method on each
867 * layer in that array each time it is called. This has the
868 * side-effect that notes displayed in one map on a page are already
869 * loaded on the other map as well.
871 function putAJAXMarker(id, lon, lat, text, closed)
873 var comments = text.split(/<hr \/>/);
874 for(var i=0; i<comments.length; i++)
875 comments[i] = comments[i].replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
876 putAJAXMarker.notes[id] = [
877 new OpenLayers.LonLat(lon, lat),
881 for(var i=0; i<putAJAXMarker.layers.length; i++)
882 putAJAXMarker.layers[i].createMarker(id);
886 * This global function is executed by the OpenStreetMap API. The
887 * “create note”, “comment” and “close note” scripts execute it to give
888 * information about their success.
890 * In case of success, this function is called without a parameter, in
891 * case of an error, the error message is passed. This is lousy
892 * workaround to make it any functional at all, the OSB API is likely
893 * to be extended later (then it will provide additional information
894 * such as the ID of a created note and similar).
896 function osbResponse(error)
899 alert("Error: "+error);
901 for(var i=0; i<putAJAXMarker.layers.length; i++)
902 putAJAXMarker.layers[i].loadNotes();
905 putAJAXMarker.layers = [ ];
906 putAJAXMarker.notes = { };