2 This OpenStreetBugs client is free software: you can redistribute it
3 and/or modify it under the terms of the GNU Affero General Public License
4 as published by the Free Software Foundation, either version 3 of the
5 License, or (at your option) any later version.
7 This file is distributed in the hope that it will be useful, but
8 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
10 License <http://www.gnu.org/licenses/> for more details.
14 * A fully functional OpenStreetBugs layer. See http://openstreetbugs.schokokeks.org/.
15 * Even though the OpenStreetBugs API originally does not intend this, you can create multiple instances of this Layer and add them to different maps (or to one single map for whatever crazy reason) without problems.
18 OpenLayers.Layer.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Layer.Markers, {
20 * The URL of the OpenStreetBugs API.
23 serverURL : "http://openstreetbugs.schokokeks.org/api/0.1/",
26 * Associative array (index: bug ID) that is filled with the bugs loaded in this layer
32 * The username to be used to change or create bugs on OpenStreetBugs
38 * The icon to be used for an open bug
39 * @var OpenLayers.Icon
41 iconOpen : new OpenLayers.Icon("http://openstreetbugs.schokokeks.org/client/open_bug_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
44 * The icon to be used for a closed bug
45 * @var OpenLayers.Icon
47 iconClosed : new OpenLayers.Icon("http://openstreetbugs.schokokeks.org/client/closed_bug_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
50 * The projection of the coordinates sent by the OpenStreetBugs API.
51 * @var OpenLayers.Projection
53 apiProjection : new OpenLayers.Projection("EPSG:4326"),
56 * If this is set to true, the user may not commit comments or close bugs.
62 * 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.
67 * The user name will be saved in a cookie if this isn’t set to false.
73 * The lifetime of the user name cookie in days.
76 cookieLifetime : 1000,
79 * The path where the cookie will be available on this server.
85 * A URL to append lon=123&lat=123&zoom=123 for the Permalinks.
88 permalinkURL : "http://www.openstreetmap.org/",
91 * A CSS file to be included. Set to null if you don’t need this.
94 theme : "http://osm.cdauth.de/map/openstreetbugs.css",
99 initialize : function(name, options)
101 OpenLayers.Layer.Markers.prototype.initialize.apply(this, [ name, OpenLayers.Util.extend({ opacity: 0.7, projection: new OpenLayers.Projection("EPSG:4326") }, options) ]);
102 putAJAXMarker.layers.push(this);
103 this.events.addEventType("markerAdded");
105 this.events.register("visibilitychanged", this, this.updatePopupVisibility);
106 this.events.register("visibilitychanged", this, this.loadBugs);
108 var cookies = document.cookie.split(/;\s*/);
109 for(var i=0; i<cookies.length; i++)
111 var cookie = cookies[i].split("=");
112 if(cookie[0] == "osbUsername")
114 this.username = decodeURIComponent(cookie[1]);
119 /* Copied from OpenLayers.Map */
121 // check existing links for equivalent url
123 var nodes = document.getElementsByTagName('link');
124 for(var i=0, len=nodes.length; i<len; ++i) {
125 if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,
131 // only add a new node if one with an equivalent url hasn't already
134 var cssNode = document.createElement('link');
135 cssNode.setAttribute('rel', 'stylesheet');
136 cssNode.setAttribute('type', 'text/css');
137 cssNode.setAttribute('href', this.theme);
138 document.getElementsByTagName('head')[0].appendChild(cssNode);
144 * Is automatically called when the layer is added to an OpenLayers.Map. Initialises the automatic bug loading in the visible bounding box.
146 afterAdd : function()
148 var ret = OpenLayers.Layer.Markers.prototype.afterAdd.apply(this, arguments);
150 this.map.events.register("moveend", this, this.loadBugs);
157 * At the moment the OSB 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.
158 * 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.
159 * @param String url The URL this.serverURL + url is requested.
161 apiRequest : function(url) {
162 var script = document.createElement("script");
163 script.type = "text/javascript";
164 script.src = this.serverURL + url + "&nocache="+(new Date()).getTime();
165 document.body.appendChild(script);
169 * Is automatically called when the visibility of the layer changes. When the layer is hidden, all visible popups
170 * are closed and their visibility is saved. When the layer is made visible again, these popups are re-opened.
172 updatePopupVisibility : function()
174 if(this.getVisibility())
176 for(var i=0; i<this.reopenPopups.length; i++)
177 this.reopenPopups[i].show();
178 this.reopenPopups = [ ];
182 for(var i=0; i<this.markers.length; i++)
184 if(this.markers[i].feature.popup && this.markers[i].feature.popup.visible())
186 this.markers[i].feature.popup.hide();
187 this.reopenPopups.push(this.markers[i].feature.popup);
194 * Sets the user name to be used for interactions with OpenStreetBugs.
196 setUserName : function(username)
198 if(this.username == username)
201 this.username = username;
205 var cookie = "osbUsername="+encodeURIComponent(username);
206 if(this.cookieLifetime)
207 cookie += ";expires="+(new Date((new Date()).getTime() + this.cookieLifetime*86400000)).toGMTString();
209 cookie += ";path="+this.cookiePath;
210 document.cookie = cookie;
213 for(var i=0; i<this.markers.length; i++)
215 if(!this.markers[i].feature.popup) continue;
216 var els = this.markers[i].feature.popup.contentDom.getElementsByTagName("input");
217 for(var j=0; j<els.length; j++)
219 if(els[j].className != "osbUsername") continue;
220 els[j].value = username;
226 * Returns the currently set username or “NoName” if none is set.
229 getUserName : function()
232 return this.username;
238 * Loads the bugs in the current bounding box. Is automatically called by an event handler ("moveend" event) that is created in the afterAdd() method.
240 loadBugs : function()
242 if(!this.getVisibility())
245 var bounds = this.map.getExtent();
246 if(!bounds) return false;
247 bounds.transform(this.map.getProjectionObject(), this.apiProjection);
249 this.apiRequest("bugs"
250 + "?bbox="+this.round(bounds.left, 5)
251 + ","+this.round(bounds.bottom, 5)
252 + ","+this.round(bounds.right, 5)
253 + ","+this.round(bounds.top, 5));
257 * Rounds the given number to the given number of digits after the floating point.
258 * @param Number number
259 * @param Number digits
262 round : function(number, digits)
264 var factor = Math.pow(10, digits);
265 return Math.round(number*factor)/factor;
269 * Adds an OpenLayers.Marker representing a bug to the map. Is usually called by loadBugs().
270 * @param Number id The bug ID
272 createMarker: function(id)
276 if(this.bugs[id].popup && !this.bugs[id].popup.visible())
277 this.setPopupContent(id);
278 if(this.bugs[id].closed != putAJAXMarker.bugs[id][2])
279 this.bugs[id].destroy();
284 var lonlat = putAJAXMarker.bugs[id][0].clone().transform(this.apiProjection, this.map.getProjectionObject());
285 var comments = putAJAXMarker.bugs[id][1];
286 var closed = putAJAXMarker.bugs[id][2];
287 var feature = new OpenLayers.Feature(this, lonlat, { icon: (closed ? this.iconClosed : this.iconOpen).clone(), autoSize: true });
288 feature.popupClass = OpenLayers.Popup.FramedCloud.OpenStreetBugs;
290 feature.closed = closed;
292 var marker = feature.createMarker();
293 marker.feature = feature;
294 marker.events.register("click", feature, this.markerClick);
295 marker.events.register("mouseover", feature, this.markerMouseOver);
296 marker.events.register("mouseout", feature, this.markerMouseOut);
297 this.addMarker(marker);
299 this.bugs[id] = feature;
300 this.events.triggerEvent("markerAdded");
304 * Recreates the content of the popup of a marker.
305 * @param Number id The bug ID
308 setPopupContent: function(id) {
309 if(!this.bugs[id].popup)
315 var newContent = document.createElement("div");
317 el1 = document.createElement("h3");
318 el1.appendChild(document.createTextNode(closed ? OpenLayers.i18n("Fixed Error") : OpenLayers.i18n("Unresolved Error")));
320 el1.appendChild(document.createTextNode(" ["));
321 el2 = document.createElement("a");
322 el2.href = "/browse/bug/" + id;
323 el2.onclick = function(){ layer.map.setCenter(putAJAXMarker.bugs[id][0].clone().transform(layer.apiProjection, layer.map.getProjectionObject()), 15); };
324 el2.appendChild(document.createTextNode(OpenLayers.i18n("Details")));
325 el1.appendChild(el2);
326 el1.appendChild(document.createTextNode("]"));
328 if(this.permalinkURL)
330 el1.appendChild(document.createTextNode(" ["));
331 el2 = document.createElement("a");
332 el2.href = this.permalinkURL + (this.permalinkURL.indexOf("?") == -1 ? "?" : "&") + "lon="+putAJAXMarker.bugs[id][0].lon+"&lat="+putAJAXMarker.bugs[id][0].lat+"&zoom=15";
333 el2.appendChild(document.createTextNode(OpenLayers.i18n("Permalink")));
334 el1.appendChild(el2);
335 el1.appendChild(document.createTextNode("]"));
337 newContent.appendChild(el1);
339 var containerDescription = document.createElement("div");
340 newContent.appendChild(containerDescription);
342 var containerChange = document.createElement("div");
343 newContent.appendChild(containerChange);
345 var displayDescription = function(){
346 containerDescription.style.display = "block";
347 containerChange.style.display = "none";
348 layer.bugs[id].popup.updateSize();
350 var displayChange = function(){
351 containerDescription.style.display = "none";
352 containerChange.style.display = "block";
353 layer.bugs[id].popup.updateSize();
355 displayDescription();
357 el1 = document.createElement("dl");
358 for(var i=0; i<putAJAXMarker.bugs[id][1].length; i++)
360 el2 = document.createElement("dt");
361 el2.className = (i == 0 ? "osb-description" : "osb-comment");
362 el2.appendChild(document.createTextNode(i == 0 ? OpenLayers.i18n("Description") : OpenLayers.i18n("Comment")));
363 el1.appendChild(el2);
364 el2 = document.createElement("dd");
365 el2.className = (i == 0 ? "osb-description" : "osb-comment");
366 el2.appendChild(document.createTextNode(putAJAXMarker.bugs[id][1][i]));
367 el1.appendChild(el2);
369 containerDescription.appendChild(el1);
371 if(putAJAXMarker.bugs[id][2])
373 el1 = document.createElement("p");
374 el1.className = "osb-fixed";
375 el2 = document.createElement("em");
376 el2.appendChild(document.createTextNode(OpenLayers.i18n("Has been fixed.")));
377 el1.appendChild(el2);
378 containerDescription.appendChild(el1);
380 else if(!this.readonly)
382 el1 = document.createElement("div");
383 el2 = document.createElement("input");
384 el2.setAttribute("type", "button");
385 el2.onclick = function(){ displayChange(); };
386 el2.value = OpenLayers.i18n("Comment/Close");
387 el1.appendChild(el2);
388 containerDescription.appendChild(el1);
390 var el_form = document.createElement("form");
391 el_form.onsubmit = function(){ if(inputComment.value.match(/^\s*$/)) return false; layer.submitComment(id, inputComment.value); layer.hidePopup(id); return false; };
393 el1 = document.createElement("dl");
394 el2 = document.createElement("dt");
395 el2.appendChild(document.createTextNode(OpenLayers.i18n("Nickname")));
396 el1.appendChild(el2);
397 el2 = document.createElement("dd");
398 var inputUsername = document.createElement("input");
399 var inputUsername = document.createElement("input");;
400 if (typeof loginName === 'undefined') {
401 inputUsername.value = this.username;
403 inputUsername.value = loginName;
404 inputUsername.setAttribute('disabled','true');
406 inputUsername.className = "osbUsername";
407 inputUsername.onkeyup = function(){ layer.setUserName(inputUsername.value); };
408 el2.appendChild(inputUsername);
409 el3 = document.createElement("a");
410 el3.setAttribute("href","login");
411 el3.className = "hide_if_logged_in";
412 el3.appendChild(document.createTextNode(OpenLayers.i18n("Login")));
414 el1.appendChild(el2);
416 el2 = document.createElement("dt");
417 el2.appendChild(document.createTextNode(OpenLayers.i18n("Comment")));
418 el1.appendChild(el2);
419 el2 = document.createElement("dd");
420 var inputComment = document.createElement("textarea");
421 inputComment.setAttribute("cols",40);
422 el2.appendChild(inputComment);
423 el1.appendChild(el2);
425 el_form.appendChild(el1);
427 el1 = document.createElement("ul");
428 el1.className = "buttons";
429 el2 = document.createElement("li");
430 el3 = document.createElement("input");
431 el3.setAttribute("type", "submit");
432 el3.value = OpenLayers.i18n("Add comment");
433 el2.appendChild(el3);
434 el1.appendChild(el2);
436 el2 = document.createElement("li");
437 el3 = document.createElement("input");
438 el3.setAttribute("type", "button");
439 el3.onclick = function(){ this.form.onsubmit(); layer.closeBug(id); layer.bugs[id].popup.hide(); return false; };
440 el3.value = OpenLayers.i18n("Mark as fixed");
441 el2.appendChild(el3);
442 el1.appendChild(el2);
443 el_form.appendChild(el1);
444 containerChange.appendChild(el_form);
446 el1 = document.createElement("div");
447 el2 = document.createElement("input");
448 el2.setAttribute("type", "button");
449 el2.onclick = function(){ displayDescription(); };
450 el2.value = OpenLayers.i18n("Cancel");
451 el1.appendChild(el2);
452 containerChange.appendChild(el1);
455 this.bugs[id].popup.setContentHTML(newContent);
460 * @param OpenLayers.LonLat lonlat The coordinates in the API projection.
461 * @param String description
463 createBug: function(lonlat, description) {
464 this.apiRequest("bug/create"
465 + "?lat="+encodeURIComponent(lonlat.lat)
466 + "&lon="+encodeURIComponent(lonlat.lon)
467 + "&text="+encodeURIComponent(description)
468 + "&name="+encodeURIComponent(this.getUserName())
475 * Adds a comment to a bug.
477 * @param String comment
479 submitComment: function(id, comment) {
480 this.apiRequest("bug/"+encodeURIComponent(id)+"/comment"
481 + "?text="+encodeURIComponent(comment)
482 + "&name="+encodeURIComponent(this.getUserName())
488 * Marks a bug as fixed.
491 closeBug: function(id) {
492 this.apiRequest("bug/"+encodeURIComponent(id)+"/close"
498 * Removes the content of a marker popup (to reduce the amount of needed resources).
501 resetPopupContent: function(id) {
502 if(!this.bugs[id].popup)
505 this.bugs[id].popup.setContentHTML(document.createElement("div"));
509 * Makes the popup of the given marker visible. Makes sure that the popup content is created if it does not exist yet.
512 showPopup: function(id) {
514 if(!this.bugs[id].popup)
516 add = this.bugs[id].createPopup(true);
517 add.events.register("close", this, function(){ this.resetPopupContent(id); if(this.bugs[id].osbClicked) this.bugs[id].osbClicked = false; });
519 else if(this.bugs[id].popup.visible())
522 this.setPopupContent(id);
524 this.map.addPopup(add);
525 this.bugs[id].popup.show();
526 this.bugs[id].popup.updateSize();
530 * Hides the popup of the given marker.
533 hidePopup: function(id) {
534 if(!this.bugs[id].popup || !this.bugs[id].popup.visible())
537 this.bugs[id].popup.hide();
538 this.bugs[id].popup.events.triggerEvent("close");
542 * Is run on the “click” event of a marker in the context of its OpenLayers.Feature. Toggles the visibility of the popup.
544 markerClick: function(e) {
545 var feature = this; // Context is the feature
547 feature.osbClicked = !feature.osbClicked;
548 if(feature.osbClicked)
549 feature.layer.showPopup(feature.osbId);
551 feature.layer.hidePopup(feature.osbId);
552 OpenLayers.Event.stop(e);
556 * Is run on the “mouseover” event of a marker in the context of its OpenLayers.Feature. Makes the popup visible.
558 markerMouseOver: function(e) {
559 var feature = this; // Context is the feature
561 feature.layer.showPopup(feature.osbId);
562 OpenLayers.Event.stop(e);
566 * 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).
568 markerMouseOut: function(e) {
569 var feature = this; // Context is the feature
571 if(!feature.osbClicked)
572 feature.layer.hidePopup(feature.osbId);
573 OpenLayers.Event.stop(e);
576 CLASS_NAME: "OpenLayers.Layer.OpenStreetBugs"
580 * An OpenLayers control to create new bugs on mouse clicks on the map. Add an instance of this to your map using
581 * the OpenLayers.Map.addControl() method and activate() it.
584 OpenLayers.Control.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Control, {
585 title : null, // See below because of translation call
588 * The icon to be used for the temporary markers that the “create bug” popup belongs to.
589 * @var OpenLayers.Icon
591 icon : new OpenLayers.Icon("http://openstreetbugs.schokokeks.org/client/icon_error_add.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
594 * An instance of the OpenStreetBugs layer that this control shall be connected to. Is set in the constructor.
595 * @var OpenLayers.Layer.OpenStreetBugs
600 * @param OpenLayers.Layer.OpenStreetBugs osbLayer The OpenStreetBugs layer that this control will be connected to.
602 initialize: function(osbLayer, options) {
603 this.osbLayer = osbLayer;
605 this.title = OpenLayers.i18n("Create OpenStreetBug");
607 OpenLayers.Control.prototype.initialize.apply(this, [ options ]);
609 this.events.register("activate", this, function() {
610 if(!this.osbLayer.getVisibility())
611 this.osbLayer.setVisibility(true);
614 this.osbLayer.events.register("visibilitychanged", this, function() {
615 if(this.active && !this.osbLayer.getVisibility())
616 this.osbLayer.setVisibility(true);
620 destroy: function() {
622 this.handler.destroy();
625 OpenLayers.Control.prototype.destroy.apply(this, arguments);
629 this.handler = new OpenLayers.Handler.Click(this, {'click': this.click}, { 'single': true, 'double': false, 'pixelTolerance': 0, 'stopSingle': false, 'stopDouble': false });
633 * Map clicking event handler. Adds a temporary marker with a popup to the map, the popup contains the form to add a bug.
636 if(!this.map) return true;
639 var lonlat = this.map.getLonLatFromViewPortPx(e.xy);
640 var lonlatApi = lonlat.clone().transform(this.map.getProjectionObject(), this.osbLayer.apiProjection);
641 var feature = new OpenLayers.Feature(this.osbLayer, lonlat, { icon: this.icon.clone(), autoSize: true });
642 feature.popupClass = OpenLayers.Popup.FramedCloud.OpenStreetBugs;
643 var marker = feature.createMarker();
644 marker.feature = feature;
645 this.osbLayer.addMarker(marker);
647 var newContent = document.createElement("div");
649 el1 = document.createElement("h3");
650 el1.appendChild(document.createTextNode(OpenLayers.i18n("Create bug")));
651 newContent.appendChild(el1);
653 var el_form = document.createElement("form");
654 el_form.onsubmit = function() { control.osbLayer.createBug(lonlatApi, inputDescription.value); marker.feature = null; feature.destroy(); return false; };
656 el1 = document.createElement("dl");
657 el2 = document.createElement("dt");
658 el2.appendChild(document.createTextNode(OpenLayers.i18n("Nickname")));
659 el1.appendChild(el2);
660 el2 = document.createElement("dd");
661 var inputUsername = document.createElement("input");;
662 if (typeof loginName === 'undefined') {
663 inputUsername.value = this.osbLayer.username;
665 inputUsername.value = loginName;
666 inputUsername.setAttribute('disabled','true');
668 inputUsername.className = "osbUsername";
670 inputUsername.onkeyup = function(){ control.osbLayer.setUserName(inputUsername.value); };
671 el2.appendChild(inputUsername);
672 el3 = document.createElement("a");
673 el3.setAttribute("href","login");
674 el3.className = "hide_if_logged_in";
675 el3.appendChild(document.createTextNode(OpenLayers.i18n("Login")));
676 el2.appendChild(el3);
677 el1.appendChild(el2);
679 el2 = document.createElement("dt");
680 el2.appendChild(document.createTextNode(OpenLayers.i18n("Bug description")));
681 el1.appendChild(el2);
682 el2 = document.createElement("dd");
683 var inputDescription = document.createElement("textarea");
684 inputDescription.setAttribute("cols",40);
685 el2.appendChild(inputDescription);
686 el1.appendChild(el2);
687 el_form.appendChild(el1);
689 el1 = document.createElement("div");
690 el2 = document.createElement("input");
691 el2.setAttribute("type", "submit");
692 el2.value = OpenLayers.i18n("Create");
693 el1.appendChild(el2);
694 el_form.appendChild(el1);
695 newContent.appendChild(el_form);
697 feature.data.popupContentHTML = newContent;
698 var popup = feature.createPopup(true);
699 popup.events.register("close", this, function(){ feature.destroy(); });
700 this.map.addPopup(popup);
704 CLASS_NAME: "OpenLayers.Control.OpenStreetBugs"
709 * This class changes the usual OpenLayers.Popup.FramedCloud class by using a DOM element instead of an innerHTML string as content for the popup.
710 * This is necessary for creating valid onclick handlers that still work with multiple OpenStreetBugs layer objects.
713 OpenLayers.Popup.FramedCloud.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
718 * See OpenLayers.Popup.FramedCloud.initialize() for parameters. As fourth parameter, pass a DOM node instead of a string.
720 initialize: function() {
721 this.displayClass = this.displayClass + " " + this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
723 var args = new Array(arguments.length);
724 for(var i=0; i<arguments.length; i++)
725 args[i] = arguments[i];
727 // Unset original contentHTML parameter
730 var closeCallback = arguments[6];
732 // Add close event trigger to the closeBoxCallback parameter
733 args[6] = function(e){ if(closeCallback) closeCallback(); else this.hide(); OpenLayers.Event.stop(e); this.events.triggerEvent("close"); };
735 OpenLayers.Popup.FramedCloud.prototype.initialize.apply(this, args);
737 this.events.addEventType("close");
739 this.setContentHTML(arguments[3]);
743 * Like OpenLayers.Popup.FramedCloud.setContentHTML(), but takes a DOM element as parameter.
745 setContentHTML: function(contentDom) {
746 if(contentDom != null)
747 this.contentDom = contentDom;
749 if(this.contentDiv == null || this.contentDom == null || this.contentDom == this.contentDiv.firstChild)
752 while(this.contentDiv.firstChild)
753 this.contentDiv.removeChild(this.contentDiv.firstChild);
755 this.contentDiv.appendChild(this.contentDom);
757 // Copied from OpenLayers.Popup.setContentHTML():
760 this.registerImageListeners();
765 destroy: function() {
766 this.contentDom = null;
767 OpenLayers.Popup.FramedCloud.prototype.destroy.apply(this, arguments);
770 CLASS_NAME: "OpenLayers.Popup.FramedCloud.OpenStreetBugs"
774 * Necessary improvement to the translate function: Fall back to default language if translated string is not
775 * available (see http://trac.openlayers.org/ticket/2308).
778 OpenLayers.i18n = OpenLayers.Lang.translate = function(key, context) {
779 var message = OpenLayers.Lang[OpenLayers.Lang.getCode()][key];
782 if(OpenLayers.Lang[OpenLayers.Lang.defaultCode][key])
783 message = OpenLayers.Lang[OpenLayers.Lang.defaultCode][key];
788 message = OpenLayers.String.format(message, context);
793 * This global function is executed by the OpenStreetBugs API getBugs script.
794 * Each OpenStreetBugs layer adds itself to the putAJAXMarker.layer array. The putAJAXMarker() function executes the createMarker() method
795 * on each layer in that array each time it is called. This has the side-effect that bugs displayed in one map on a page are already loaded
796 * on the other map as well.
799 function putAJAXMarker(id, lon, lat, text, closed)
801 var comments = text.split(/<hr \/>/);
802 for(var i=0; i<comments.length; i++)
803 comments[i] = comments[i].replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
804 putAJAXMarker.bugs[id] = [
805 new OpenLayers.LonLat(lon, lat),
809 for(var i=0; i<putAJAXMarker.layers.length; i++)
810 putAJAXMarker.layers[i].createMarker(id);
814 * This global function is executed by the OpenStreetBugs API. The “create bug”, “comment” and “close bug” scripts execute it to give information about their success.
815 * 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 bug and similar).
818 function osbResponse(error)
821 alert("Error: "+error);
823 for(var i=0; i<putAJAXMarker.layers.length; i++)
824 putAJAXMarker.layers[i].loadBugs();
827 putAJAXMarker.layers = [ ];
828 putAJAXMarker.bugs = { };
833 OpenLayers.Lang.en = OpenLayers.Util.extend(OpenLayers.Lang.en, {
834 "Fixed Error" : "Fixed Error",
835 "Unresolved Error" : "Unresolved Error",
836 "Description" : "Description",
837 "Comment" : "Comment",
838 "Has been fixed." : "This error has been fixed already. However, it might take a couple of days before the map image is updated.",
839 "Comment/Close" : "Comment/Close",
840 "Nickname" : "Nickname",
841 "Add comment" : "Add comment",
842 "Mark as fixed" : "Mark as fixed",
844 "Create OpenStreetBug" : "Create OpenStreetBug",
845 "Create bug" : "Create bug",
846 "Bug description" : "Bug description",
848 "Permalink" : "Permalink",
852 OpenLayers.Lang.de = OpenLayers.Util.extend(OpenLayers.Lang.de, {
853 "Fixed Error" : "Behobener Fehler",
854 "Unresolved Error" : "Offener Fehler",
855 "Description" : "Beschreibung",
856 "Comment" : "Kommentar",
857 "Has been fixed." : "Der Fehler wurde bereits behoben. Es kann jedoch bis zu einigen Tagen dauern, bis die Kartenansicht aktualisiert wird.",
858 "Comment/Close" : "Kommentieren/Schließen",
859 "Nickname" : "Benutzername",
860 "Add comment" : "Kommentar hinzufügen",
861 "Mark as fixed" : "Als behoben markieren",
862 "Cancel" : "Abbrechen",
863 "Create OpenStreetBug" : "OpenStreetBug melden",
864 "Create bug" : "Bug anlegen",
865 "Bug description" : "Fehlerbeschreibung",
866 "Create" : "Anlegen",
867 "Permalink" : "Permalink",
871 OpenLayers.Lang.fr = OpenLayers.Util.extend(OpenLayers.Lang.fr, {
872 "Fixed Error" : "Erreur corrigée",
873 "Unresolved Error" : "Erreur non corrigée",
874 "Description" : "Description",
875 "Comment" : "Commentaire",
876 "Has been fixed." : "Cette erreur a déjà été corrigée. Cependant, il peut être nécessaire d'attendre quelques jours avant que l'image de la carte ne soit mise à jour.",
877 "Comment/Close" : "Commenter/Fermer",
878 "Nickname" : "Surnom",
879 "Add comment" : "Ajouter un commentaire",
880 "Mark as fixed" : "Marquer comme corrigé",
881 "Cancel" : "Annuler",
882 "Create OpenStreetBug" : "Créer OpenStreetBug",
883 "Create bug" : "Ajouter un bug",
884 "Bug description" : "Description du bug",
886 "Permalink" : "Lien permanent",
890 OpenLayers.Lang.nl = OpenLayers.Util.extend(OpenLayers.Lang.nl, {
891 "Fixed Error" : "Fout verholpen",
892 "Unresolved Error" : "Openstaande fout",
893 "Description" : "Beschrijving",
894 "Comment" : "Kommentaar",
895 "Has been fixed." : "De fout is al eerder opgelost. Het kan echter nog een paar dagen duren voordat het kaartmateriaal geactualiseerd is.",
896 "Comment/Close" : "Bekommentariëren/Sluiten",
897 "Nickname" : "Gebruikersnaam",
898 "Add comment" : "Kommentaar toevoegen",
899 "Mark as fixed" : "Als opgelost aanmerken",
900 "Cancel" : "Afbreken",
901 "Create OpenStreetBug" : "OpenStreetBug melden",
902 "Create bug" : "Bug melden",
903 "Bug description" : "Foutomschrijving",
904 "Create" : "Aanmaken",
905 "Permalink" : "Permalink",
909 OpenLayers.Lang.it = OpenLayers.Util.extend(OpenLayers.Lang.it, {
910 "Fixed Error" : "Sbaglio coretto",
911 "Unresolved Error" : "Sbaglio non coretto",
912 "Description" : "Descrizione",
913 "Comment" : "Commento",
914 "Has been fixed." : "Questo sbaglio è già coretto. Forse ci metto qualche giorni per aggiornare anche i quadri.",
915 "Comment/Close" : "Commenta/Chiude",
917 "Add comment" : "Aggiunge commento",
918 "Mark as fixed" : "Marca che è coretto",
919 "Cancel" : "Annulla",
920 "Create OpenStreetBug" : "Aggiunge OpenStreetBug",
921 "Create bug" : "Aggiunge un sbaglio",
922 "Bug description" : "Descrizione del sbaglio",
923 "Create" : "Aggiunge",
924 "Permalink" : "Permalink",
928 OpenLayers.Lang.ro = OpenLayers.Util.extend(OpenLayers.Lang.ro, {
929 "Fixed Error" : "Eroare rezolvată",
930 "Unresolved Error" : "Eroare nerezolvată",
931 "Description" : "Descriere",
932 "Comment" : "Comentariu",
933 "Has been fixed." : "Această eroare a fost rezolvată. Totuși este posibil să dureze câteva zile până când imaginea hărții va fi actualizată.",
934 "Comment/Close" : "Comentariu/Închide",
936 "Add comment" : "Adaugă comentariu",
937 "Mark as fixed" : "Marchează ca rezolvată",
938 "Cancel" : "Anulează",
939 "Create OpenStreetBug" : "Crează OpenStreetBug",
940 "Create bug" : "Adaugă eroare",
941 "Bug description" : "Descrierea erorii",
943 "Permalink" : "Permalink",