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 /** This version has been adapted from the original javascript library to fit the openstreetmap rails_port implementation */
20 OpenLayers.Layer.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Layer.Markers, {
22 * The URL of the OpenStreetBugs API.
25 serverURL : "/api/0.6/",
28 * Associative array (index: bug ID) that is filled with the bugs loaded in this layer
34 * The username to be used to change or create bugs on OpenStreetBugs
40 * The icon to be used for an open bug
41 * @var OpenLayers.Icon
43 iconOpen : new OpenLayers.Icon("/images/open_bug_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
46 * The icon to be used for a closed bug
47 * @var OpenLayers.Icon
49 iconClosed : new OpenLayers.Icon("/images/closed_bug_marker.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
52 * The projection of the coordinates sent by the OpenStreetBugs API.
53 * @var OpenLayers.Projection
55 apiProjection : new OpenLayers.Projection("EPSG:4326"),
58 * If this is set to true, the user may not commit comments or close bugs.
64 * 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.
69 * The user name will be saved in a cookie if this isn’t set to false.
75 * The lifetime of the user name cookie in days.
78 cookieLifetime : 1000,
81 * The path where the cookie will be available on this server.
87 * A URL to append lon=123&lat=123&zoom=123 for the Permalinks.
90 permalinkURL : "http://www.openstreetmap.org/",
93 * A CSS file to be included. Set to null if you don’t need this.
96 theme : "http://osm.cdauth.de/map/openstreetbugs.css",
101 initialize : function(name, options)
103 OpenLayers.Layer.Markers.prototype.initialize.apply(this, [ name, OpenLayers.Util.extend({ opacity: 0.7, projection: new OpenLayers.Projection("EPSG:4326") }, options) ]);
104 putAJAXMarker.layers.push(this);
105 this.events.addEventType("markerAdded");
107 this.events.register("visibilitychanged", this, this.updatePopupVisibility);
108 this.events.register("visibilitychanged", this, this.loadBugs);
110 var cookies = document.cookie.split(/;\s*/);
111 for(var i=0; i<cookies.length; i++)
113 var cookie = cookies[i].split("=");
114 if(cookie[0] == "osbUsername")
116 this.username = decodeURIComponent(cookie[1]);
121 /* Copied from OpenLayers.Map */
123 // check existing links for equivalent url
125 var nodes = document.getElementsByTagName('link');
126 for(var i=0, len=nodes.length; i<len; ++i) {
127 if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,
133 // only add a new node if one with an equivalent url hasn't already
136 var cssNode = document.createElement('link');
137 cssNode.setAttribute('rel', 'stylesheet');
138 cssNode.setAttribute('type', 'text/css');
139 cssNode.setAttribute('href', this.theme);
140 document.getElementsByTagName('head')[0].appendChild(cssNode);
146 * Is automatically called when the layer is added to an OpenLayers.Map. Initialises the automatic bug loading in the visible bounding box.
148 afterAdd : function()
150 var ret = OpenLayers.Layer.Markers.prototype.afterAdd.apply(this, arguments);
152 this.map.events.register("moveend", this, this.loadBugs);
159 * 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.
160 * 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.
161 * @param String url The URL this.serverURL + url is requested.
163 apiRequest : function(url) {
164 var script = document.createElement("script");
165 script.type = "text/javascript";
166 script.src = this.serverURL + url + "&nocache="+(new Date()).getTime();
167 document.body.appendChild(script);
171 * Is automatically called when the visibility of the layer changes. When the layer is hidden, all visible popups
172 * are closed and their visibility is saved. When the layer is made visible again, these popups are re-opened.
174 updatePopupVisibility : function()
176 if(this.getVisibility())
178 for(var i=0; i<this.reopenPopups.length; i++)
179 this.reopenPopups[i].show();
180 this.reopenPopups = [ ];
184 for(var i=0; i<this.markers.length; i++)
186 if(this.markers[i].feature.popup && this.markers[i].feature.popup.visible())
188 this.markers[i].feature.popup.hide();
189 this.reopenPopups.push(this.markers[i].feature.popup);
196 * Sets the user name to be used for interactions with OpenStreetBugs.
198 setUserName : function(username)
200 if(this.username == username)
203 this.username = username;
207 var cookie = "osbUsername="+encodeURIComponent(username);
208 if(this.cookieLifetime)
209 cookie += ";expires="+(new Date((new Date()).getTime() + this.cookieLifetime*86400000)).toGMTString();
211 cookie += ";path="+this.cookiePath;
212 document.cookie = cookie;
215 for(var i=0; i<this.markers.length; i++)
217 if(!this.markers[i].feature.popup) continue;
218 var els = this.markers[i].feature.popup.contentDom.getElementsByTagName("input");
219 for(var j=0; j<els.length; j++)
221 if(els[j].className != "osbUsername") continue;
222 els[j].value = username;
228 * Returns the currently set username or “NoName” if none is set.
231 getUserName : function()
234 return this.username;
240 * Loads the bugs in the current bounding box. Is automatically called by an event handler ("moveend" event) that is created in the afterAdd() method.
242 loadBugs : function()
244 if(!this.getVisibility())
247 var bounds = this.map.getExtent();
248 if(!bounds) return false;
249 bounds.transform(this.map.getProjectionObject(), this.apiProjection);
251 this.apiRequest("notes"
252 + "?bbox="+this.round(bounds.left, 5)
253 + ","+this.round(bounds.bottom, 5)
254 + ","+this.round(bounds.right, 5)
255 + ","+this.round(bounds.top, 5));
259 * Rounds the given number to the given number of digits after the floating point.
260 * @param Number number
261 * @param Number digits
264 round : function(number, digits)
266 var factor = Math.pow(10, digits);
267 return Math.round(number*factor)/factor;
271 * Adds an OpenLayers.Marker representing a bug to the map. Is usually called by loadBugs().
272 * @param Number id The bug ID
274 createMarker: function(id)
278 if(this.bugs[id].popup && !this.bugs[id].popup.visible())
279 this.setPopupContent(id);
280 if(this.bugs[id].closed != putAJAXMarker.bugs[id][2])
281 this.bugs[id].destroy();
286 var lonlat = putAJAXMarker.bugs[id][0].clone().transform(this.apiProjection, this.map.getProjectionObject());
287 var comments = putAJAXMarker.bugs[id][1];
288 var closed = putAJAXMarker.bugs[id][2];
289 var feature = new OpenLayers.Feature(this, lonlat, { icon: (closed ? this.iconClosed : this.iconOpen).clone(), autoSize: true });
290 feature.popupClass = OpenLayers.Popup.FramedCloud.OpenStreetBugs;
292 feature.closed = closed;
294 var marker = feature.createMarker();
295 marker.feature = feature;
296 marker.events.register("click", feature, this.markerClick);
297 //marker.events.register("mouseover", feature, this.markerMouseOver);
298 //marker.events.register("mouseout", feature, this.markerMouseOut);
299 this.addMarker(marker);
301 this.bugs[id] = feature;
302 this.events.triggerEvent("markerAdded");
306 * Recreates the content of the popup of a marker.
307 * @param Number id The bug ID
310 setPopupContent: function(id) {
311 if(!this.bugs[id].popup)
317 var newContent = document.createElement("div");
319 el1 = document.createElement("h3");
320 el1.appendChild(document.createTextNode(putAJAXMarker.bugs[id][2] ? i18n("javascripts.osb.Fixed Error") : i18n("javascripts.osb.Unresolved Error")));
322 el1.appendChild(document.createTextNode(" ["));
323 el2 = document.createElement("a");
324 el2.href = "/browse/note/" + id;
325 el2.onclick = function(){ layer.map.setCenter(putAJAXMarker.bugs[id][0].clone().transform(layer.apiProjection, layer.map.getProjectionObject()), 15); };
326 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Details")));
327 el1.appendChild(el2);
328 el1.appendChild(document.createTextNode("]"));
330 if(this.permalinkURL)
332 el1.appendChild(document.createTextNode(" ["));
333 el2 = document.createElement("a");
334 el2.href = this.permalinkURL + (this.permalinkURL.indexOf("?") == -1 ? "?" : "&") + "lon="+putAJAXMarker.bugs[id][0].lon+"&lat="+putAJAXMarker.bugs[id][0].lat+"&zoom=15";
335 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Permalink")));
336 el1.appendChild(el2);
337 el1.appendChild(document.createTextNode("]"));
339 newContent.appendChild(el1);
341 var containerDescription = document.createElement("div");
342 newContent.appendChild(containerDescription);
344 var containerChange = document.createElement("div");
345 newContent.appendChild(containerChange);
347 var displayDescription = function(){
348 containerDescription.style.display = "block";
349 containerChange.style.display = "none";
350 layer.bugs[id].popup.updateSize();
352 var displayChange = function(){
353 containerDescription.style.display = "none";
354 containerChange.style.display = "block";
355 layer.bugs[id].popup.updateSize();
357 displayDescription();
359 el1 = document.createElement("dl");
360 for(var i=0; i<putAJAXMarker.bugs[id][1].length; i++)
362 el2 = document.createElement("dt");
363 el2.className = (i == 0 ? "osb-description" : "osb-comment");
364 el2.appendChild(document.createTextNode(i == 0 ? i18n("javascripts.osb.Description") : i18n("javascripts.osb.Comment")));
365 el1.appendChild(el2);
366 el2 = document.createElement("dd");
367 el2.className = (i == 0 ? "osb-description" : "osb-comment");
368 el2.appendChild(document.createTextNode(putAJAXMarker.bugs[id][1][i]));
369 el1.appendChild(el2);
370 if (i == 0) { el2 = document.createElement("br"); el1.appendChild(el2);};
372 containerDescription.appendChild(el1);
374 if(putAJAXMarker.bugs[id][2])
376 el1 = document.createElement("p");
377 el1.className = "osb-fixed";
378 el2 = document.createElement("em");
379 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Has been fixed")));
380 el1.appendChild(el2);
381 containerDescription.appendChild(el1);
383 else if(!this.readonly)
385 el1 = document.createElement("div");
386 el2 = document.createElement("input");
387 el2.setAttribute("type", "button");
388 el2.onclick = function(){ displayChange(); };
389 el2.value = i18n("javascripts.osb.Comment/Close");
390 el1.appendChild(el2);
391 containerDescription.appendChild(el1);
393 var el_form = document.createElement("form");
394 el_form.onsubmit = function(){ if(inputComment.value.match(/^\s*$/)) return false; layer.submitComment(id, inputComment.value); layer.hidePopup(id); return false; };
396 el1 = document.createElement("dl");
397 el2 = document.createElement("dt");
398 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Nickname")));
399 el1.appendChild(el2);
400 el2 = document.createElement("dd");
401 var inputUsername = document.createElement("input");
402 var inputUsername = document.createElement("input");;
403 if (typeof loginName === 'undefined') {
404 inputUsername.value = this.username;
406 inputUsername.value = loginName;
407 inputUsername.setAttribute('disabled','true');
409 inputUsername.className = "osbUsername";
410 inputUsername.onkeyup = function(){ layer.setUserName(inputUsername.value); };
411 el2.appendChild(inputUsername);
412 el3 = document.createElement("a");
413 el3.setAttribute("href","login");
414 el3.className = "hide_if_logged_in";
415 el3.appendChild(document.createTextNode(i18n("javascripts.osb.Login")));
417 el1.appendChild(el2);
419 el2 = document.createElement("dt");
420 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Comment")));
421 el1.appendChild(el2);
422 el2 = document.createElement("dd");
423 var inputComment = document.createElement("textarea");
424 inputComment.setAttribute("cols",40);
425 inputComment.setAttribute("rows",3);
427 el2.appendChild(inputComment);
428 el1.appendChild(el2);
430 el_form.appendChild(el1);
432 el1 = document.createElement("ul");
433 el1.className = "buttons";
434 el2 = document.createElement("li");
435 el3 = document.createElement("input");
436 el3.setAttribute("type", "button");
437 el3.onclick = function(){ this.form.onsubmit(); return false; };
438 el3.value = i18n("javascripts.osb.Add comment");
439 el2.appendChild(el3);
440 el1.appendChild(el2);
442 el2 = document.createElement("li");
443 el3 = document.createElement("input");
444 el3.setAttribute("type", "button");
445 el3.onclick = function(){ this.form.onsubmit(); layer.closeBug(id); layer.bugs[id].popup.hide(); return false; };
446 el3.value = i18n("javascripts.osb.Mark as fixed");
447 el2.appendChild(el3);
448 el1.appendChild(el2);
449 el_form.appendChild(el1);
450 containerChange.appendChild(el_form);
452 el1 = document.createElement("div");
453 el2 = document.createElement("input");
454 el2.setAttribute("type", "button");
455 el2.onclick = function(){ displayDescription(); };
456 el2.value = i18n("javascripts.osb.Cancel");
457 el1.appendChild(el2);
458 containerChange.appendChild(el1);
461 this.bugs[id].popup.setContentHTML(newContent);
466 * @param OpenLayers.LonLat lonlat The coordinates in the API projection.
467 * @param String description
469 createBug: function(lonlat, description) {
470 this.apiRequest("note/create"
471 + "?lat="+encodeURIComponent(lonlat.lat)
472 + "&lon="+encodeURIComponent(lonlat.lon)
473 + "&text="+encodeURIComponent(description)
474 + "&name="+encodeURIComponent(this.getUserName())
480 * Adds a comment to a bug.
482 * @param String comment
484 submitComment: function(id, comment) {
485 this.apiRequest("note/"+encodeURIComponent(id)+"/comment"
486 + "?text="+encodeURIComponent(comment)
487 + "&name="+encodeURIComponent(this.getUserName())
493 * Marks a bug as fixed.
496 closeBug: function(id) {
497 this.apiRequest("note/"+encodeURIComponent(id)+"/close"
503 * Removes the content of a marker popup (to reduce the amount of needed resources).
506 resetPopupContent: function(id) {
507 if(!this.bugs[id].popup)
510 this.bugs[id].popup.setContentHTML(document.createElement("div"));
514 * Makes the popup of the given marker visible. Makes sure that the popup content is created if it does not exist yet.
517 showPopup: function(id) {
519 if(!this.bugs[id].popup)
521 add = this.bugs[id].createPopup(true);
522 add.events.register("close", this, function(){ this.resetPopupContent(id); if(this.bugs[id].osbClicked) this.bugs[id].osbClicked = false; });
524 else if(this.bugs[id].popup.visible())
527 this.setPopupContent(id);
529 this.map.addPopup(add);
530 this.bugs[id].popup.show();
531 this.bugs[id].popup.updateSize();
535 * Hides the popup of the given marker.
538 hidePopup: function(id) {
539 if(!this.bugs[id].popup || !this.bugs[id].popup.visible())
542 this.bugs[id].popup.hide();
543 this.bugs[id].popup.events.triggerEvent("close");
547 * Is run on the “click” event of a marker in the context of its OpenLayers.Feature. Toggles the visibility of the popup.
549 markerClick: function(e) {
550 var feature = this; // Context is the feature
552 feature.osbClicked = !feature.osbClicked;
553 if(feature.osbClicked)
554 feature.layer.showPopup(feature.osbId);
556 feature.layer.hidePopup(feature.osbId);
557 OpenLayers.Event.stop(e);
561 * Is run on the “mouseover” event of a marker in the context of its OpenLayers.Feature. Makes the popup visible.
563 markerMouseOver: function(e) {
564 var feature = this; // Context is the feature
566 feature.layer.showPopup(feature.osbId);
567 OpenLayers.Event.stop(e);
571 * 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).
573 markerMouseOut: function(e) {
574 var feature = this; // Context is the feature
576 if(!feature.osbClicked)
577 feature.layer.hidePopup(feature.osbId);
578 OpenLayers.Event.stop(e);
581 CLASS_NAME: "OpenLayers.Layer.OpenStreetBugs"
585 * An OpenLayers control to create new bugs on mouse clicks on the map. Add an instance of this to your map using
586 * the OpenLayers.Map.addControl() method and activate() it.
589 OpenLayers.Control.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Control, {
590 title : null, // See below because of translation call
593 * The icon to be used for the temporary markers that the “create bug” popup belongs to.
594 * @var OpenLayers.Icon
596 icon : new OpenLayers.Icon("/images/icon_error_add.png", new OpenLayers.Size(22, 22), new OpenLayers.Pixel(-11, -11)),
599 * An instance of the OpenStreetBugs layer that this control shall be connected to. Is set in the constructor.
600 * @var OpenLayers.Layer.OpenStreetBugs
605 * @param OpenLayers.Layer.OpenStreetBugs osbLayer The OpenStreetBugs layer that this control will be connected to.
607 initialize: function(osbLayer, options) {
608 this.osbLayer = osbLayer;
610 this.title = i18n("javascripts.osb.Create OpenStreetBug");
612 OpenLayers.Control.prototype.initialize.apply(this, [ options ]);
614 this.events.register("activate", this, function() {
615 if(!this.osbLayer.getVisibility())
616 this.osbLayer.setVisibility(true);
619 this.osbLayer.events.register("visibilitychanged", this, function() {
620 if(this.active && !this.osbLayer.getVisibility())
621 this.osbLayer.setVisibility(true);
625 destroy: function() {
627 this.handler.destroy();
630 OpenLayers.Control.prototype.destroy.apply(this, arguments);
634 this.handler = new OpenLayers.Handler.Click(this, {'click': this.click}, { 'single': true, 'double': false, 'pixelTolerance': 0, 'stopSingle': false, 'stopDouble': false });
638 * Map clicking event handler. Adds a temporary marker with a popup to the map, the popup contains the form to add a bug.
641 var lonlat = this.map.getLonLatFromViewPortPx(e.xy);
642 this.addTemporaryMarker(lonlat);
645 addTemporaryMarker: function(lonlat) {
646 if(!this.map) return true;
650 var lonlatApi = lonlat.clone().transform(this.map.getProjectionObject(), this.osbLayer.apiProjection);
651 var feature = new OpenLayers.Feature(this.osbLayer, lonlat, { icon: this.icon.clone(), autoSize: true });
652 feature.popupClass = OpenLayers.Popup.FramedCloud.OpenStreetBugs;
653 var marker = feature.createMarker();
654 marker.feature = feature;
655 this.osbLayer.addMarker(marker);
658 /** Implement a drag and drop for markers */
659 /* TODO: veryfy that the scoping of variables works correctly everywhere */
660 var dragging = false;
661 var dragFunction = function(e) {
662 map.events.unregister("mouseup",map,dragFunction);
663 lonlat = map.getLonLatFromViewPortPx(e.xy);
664 lonlatApi = lonlat.clone().transform(map.getProjectionObject(), map.osbLayer.apiProjection);
665 marker.moveTo(map.getLayerPxFromViewPortPx(e.xy));
666 marker.popup.moveTo(map.getLayerPxFromViewPortPx(e.xy));
667 marker.popup.updateRelativePosition();
672 marker.events.register("mouseover", this,
673 function(){ document.getElementById("OpenLayers.Map_18_OpenLayers_Container").style.cursor = "move"; });
674 marker.events.register("mouseout", this,
675 function(){ if (!dragging) {document.getElementById("OpenLayers.Map_18_OpenLayers_Container").style.cursor = "default"; }});
676 marker.events.register("mousedown", this,
677 function() { dragging = true; map.events.register("mouseup",map, dragFunction); return false;});
680 var newContent = document.createElement("div");
682 el1 = document.createElement("h3");
683 el1.appendChild(document.createTextNode(i18n("javascripts.osb.Create bug")));
684 newContent.appendChild(el1);
685 newContent.appendChild(document.createTextNode(i18n("javascripts.osb.draghelp1")));
686 newContent.appendChild(document.createElement("br"));
687 newContent.appendChild(document.createTextNode(i18n("javascripts.osb.draghelp2")));
688 newContent.appendChild(document.createElement("br"));
689 newContent.appendChild(document.createElement("br"));
691 var el_form = document.createElement("form");
693 el1 = document.createElement("dl");
694 el2 = document.createElement("dt");
695 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Nickname")));
696 el1.appendChild(el2);
697 el2 = document.createElement("dd");
698 var inputUsername = document.createElement("input");;
699 if (typeof loginName === 'undefined') {
700 inputUsername.value = this.osbLayer.username;
702 inputUsername.value = loginName;
703 inputUsername.setAttribute('disabled','true');
705 inputUsername.className = "osbUsername";
707 inputUsername.onkeyup = function(){ control.osbLayer.setUserName(inputUsername.value); };
708 el2.appendChild(inputUsername);
709 el3 = document.createElement("a");
710 el3.setAttribute("href","login");
711 el3.className = "hide_if_logged_in";
712 el3.appendChild(document.createTextNode(i18n("javascripts.osb.Login")));
713 el2.appendChild(el3);
714 el1.appendChild(el2);
715 el2 = document.createElement("br");
716 el1.appendChild(el2);
718 el2 = document.createElement("dt");
719 el2.appendChild(document.createTextNode(i18n("javascripts.osb.Bug description")));
720 el1.appendChild(el2);
721 el2 = document.createElement("dd");
722 var inputDescription = document.createElement("textarea");
723 inputDescription.setAttribute("cols",40);
724 inputDescription.setAttribute("rows",3);
725 el2.appendChild(inputDescription);
726 el1.appendChild(el2);
727 el_form.appendChild(el1);
729 el1 = document.createElement("div");
730 el2 = document.createElement("input");
731 el2.setAttribute("type", "button");
732 el2.value = i18n("javascripts.osb.Create");
733 el2.onclick = function() { control.osbLayer.createBug(lonlatApi, inputDescription.value); marker.feature = null; feature.destroy(); return false; };
734 el1.appendChild(el2);
735 el2 = document.createElement("input");
736 el2.setAttribute("type", "button");
737 el2.value = i18n("javascripts.osb.Cancel");
738 el2.onclick = function(){ feature.destroy(); };
739 el1.appendChild(el2);
740 el_form.appendChild(el1);
741 newContent.appendChild(el_form);
743 el2 = document.createElement("hr");
744 el1.appendChild(el2);
745 el2 = document.createElement("a");
746 el2.setAttribute("href","edit");
747 el2.appendChild(document.createTextNode(i18n("javascripts.osb.edityourself")));
748 el1.appendChild(el2);
750 feature.data.popupContentHTML = newContent;
751 var popup = feature.createPopup(true);
752 popup.events.register("close", this, function(){ feature.destroy(); });
753 this.map.addPopup(popup);
755 marker.popup = popup;
758 CLASS_NAME: "OpenLayers.Control.OpenStreetBugs"
763 * This class changes the usual OpenLayers.Popup.FramedCloud class by using a DOM element instead of an innerHTML string as content for the popup.
764 * This is necessary for creating valid onclick handlers that still work with multiple OpenStreetBugs layer objects.
767 OpenLayers.Popup.FramedCloud.OpenStreetBugs = new OpenLayers.Class(OpenLayers.Popup.FramedCloud, {
772 * See OpenLayers.Popup.FramedCloud.initialize() for parameters. As fourth parameter, pass a DOM node instead of a string.
774 initialize: function() {
775 this.displayClass = this.displayClass + " " + this.CLASS_NAME.replace("OpenLayers.", "ol").replace(/\./g, "");
777 var args = new Array(arguments.length);
778 for(var i=0; i<arguments.length; i++)
779 args[i] = arguments[i];
781 // Unset original contentHTML parameter
784 var closeCallback = arguments[6];
786 // Add close event trigger to the closeBoxCallback parameter
787 args[6] = function(e){ if(closeCallback) closeCallback(); else this.hide(); OpenLayers.Event.stop(e); this.events.triggerEvent("close"); };
789 OpenLayers.Popup.FramedCloud.prototype.initialize.apply(this, args);
791 this.events.addEventType("close");
793 this.setContentHTML(arguments[3]);
797 * Like OpenLayers.Popup.FramedCloud.setContentHTML(), but takes a DOM element as parameter.
799 setContentHTML: function(contentDom) {
800 if(contentDom != null)
801 this.contentDom = contentDom;
803 if(this.contentDiv == null || this.contentDom == null || this.contentDom == this.contentDiv.firstChild)
806 while(this.contentDiv.firstChild)
807 this.contentDiv.removeChild(this.contentDiv.firstChild);
809 this.contentDiv.appendChild(this.contentDom);
811 // Copied from OpenLayers.Popup.setContentHTML():
814 this.registerImageListeners();
819 destroy: function() {
820 this.contentDom = null;
821 OpenLayers.Popup.FramedCloud.prototype.destroy.apply(this, arguments);
824 CLASS_NAME: "OpenLayers.Popup.FramedCloud.OpenStreetBugs"
829 * This global function is executed by the OpenStreetBugs API getBugs script.
830 * Each OpenStreetBugs layer adds itself to the putAJAXMarker.layer array. The putAJAXMarker() function executes the createMarker() method
831 * 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
832 * on the other map as well.
835 function putAJAXMarker(id, lon, lat, text, closed)
837 var comments = text.split(/<hr \/>/);
838 for(var i=0; i<comments.length; i++)
839 comments[i] = comments[i].replace(/"/g, "\"").replace(/</g, "<").replace(/>/g, ">").replace(/&/g, "&");
840 putAJAXMarker.bugs[id] = [
841 new OpenLayers.LonLat(lon, lat),
845 for(var i=0; i<putAJAXMarker.layers.length; i++)
846 putAJAXMarker.layers[i].createMarker(id);
850 * 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.
851 * 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).
854 function osbResponse(error)
857 alert("Error: "+error);
859 for(var i=0; i<putAJAXMarker.layers.length; i++)
860 putAJAXMarker.layers[i].loadBugs();
863 putAJAXMarker.layers = [ ];
864 putAJAXMarker.bugs = { };
866 function deactivateControl() {
867 map.osbControl.deactivate();
868 document.getElementById("OpenLayers.Map_18_OpenLayers_Container").style.cursor = "default";
876 OpenLayers.Lang.en = OpenLayers.Util.extend(OpenLayers.Lang.en, {
877 "Fixed Error" : "Fixed Error",
878 "Unresolved Error" : "Unresolved Error",
879 "Description" : "Description",
880 "Comment" : "Comment",
881 "Has been fixed." : "This error has been fixed already. However, it might take a couple of days before the map image is updated.",
882 "Comment/Close" : "Comment/Close",
883 "Nickname" : "Nickname",
884 "Add comment" : "Add comment",
885 "Mark as fixed" : "Mark as fixed",
887 "Create OpenStreetBug" : "Create OpenStreetBug",
888 "Create bug" : "Create bug",
889 "Bug description" : "Bug description",
891 "Permalink" : "Permalink",
895 OpenLayers.Lang.de = OpenLayers.Util.extend(OpenLayers.Lang.de, {
896 "Fixed Error" : "Behobener Fehler",
897 "Unresolved Error" : "Offener Fehler",
898 "Description" : "Beschreibung",
899 "Comment" : "Kommentar",
900 "Has been fixed." : "Der Fehler wurde bereits behoben. Es kann jedoch bis zu einigen Tagen dauern, bis die Kartenansicht aktualisiert wird.",
901 "Comment/Close" : "Kommentieren/Schließen",
902 "Nickname" : "Benutzername",
903 "Add comment" : "Kommentar hinzufügen",
904 "Mark as fixed" : "Als behoben markieren",
905 "Cancel" : "Abbrechen",
906 "Create OpenStreetBug" : "OpenStreetBug melden",
907 "Create bug" : "Bug anlegen",
908 "Bug description" : "Fehlerbeschreibung",
909 "Create" : "Anlegen",
910 "Permalink" : "Permalink",
914 OpenLayers.Lang.fr = OpenLayers.Util.extend(OpenLayers.Lang.fr, {
915 "Fixed Error" : "Erreur corrigée",
916 "Unresolved Error" : "Erreur non corrigée",
917 "Description" : "Description",
918 "Comment" : "Commentaire",
919 "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.",
920 "Comment/Close" : "Commenter/Fermer",
921 "Nickname" : "Surnom",
922 "Add comment" : "Ajouter un commentaire",
923 "Mark as fixed" : "Marquer comme corrigé",
924 "Cancel" : "Annuler",
925 "Create OpenStreetBug" : "Créer OpenStreetBug",
926 "Create bug" : "Ajouter un bug",
927 "Bug description" : "Description du bug",
929 "Permalink" : "Lien permanent",
933 OpenLayers.Lang.nl = OpenLayers.Util.extend(OpenLayers.Lang.nl, {
934 "Fixed Error" : "Fout verholpen",
935 "Unresolved Error" : "Openstaande fout",
936 "Description" : "Beschrijving",
937 "Comment" : "Kommentaar",
938 "Has been fixed." : "De fout is al eerder opgelost. Het kan echter nog een paar dagen duren voordat het kaartmateriaal geactualiseerd is.",
939 "Comment/Close" : "Bekommentariëren/Sluiten",
940 "Nickname" : "Gebruikersnaam",
941 "Add comment" : "Kommentaar toevoegen",
942 "Mark as fixed" : "Als opgelost aanmerken",
943 "Cancel" : "Afbreken",
944 "Create OpenStreetBug" : "OpenStreetBug melden",
945 "Create bug" : "Bug melden",
946 "Bug description" : "Foutomschrijving",
947 "Create" : "Aanmaken",
948 "Permalink" : "Permalink",
952 OpenLayers.Lang.it = OpenLayers.Util.extend(OpenLayers.Lang.it, {
953 "Fixed Error" : "Sbaglio coretto",
954 "Unresolved Error" : "Sbaglio non coretto",
955 "Description" : "Descrizione",
956 "Comment" : "Commento",
957 "Has been fixed." : "Questo sbaglio è già coretto. Forse ci metto qualche giorni per aggiornare anche i quadri.",
958 "Comment/Close" : "Commenta/Chiude",
960 "Add comment" : "Aggiunge commento",
961 "Mark as fixed" : "Marca che è coretto",
962 "Cancel" : "Annulla",
963 "Create OpenStreetBug" : "Aggiunge OpenStreetBug",
964 "Create bug" : "Aggiunge un sbaglio",
965 "Bug description" : "Descrizione del sbaglio",
966 "Create" : "Aggiunge",
967 "Permalink" : "Permalink",
971 OpenLayers.Lang.ro = OpenLayers.Util.extend(OpenLayers.Lang.ro, {
972 "Fixed Error" : "Eroare rezolvată",
973 "Unresolved Error" : "Eroare nerezolvată",
974 "Description" : "Descriere",
975 "Comment" : "Comentariu",
976 "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ă.",
977 "Comment/Close" : "Comentariu/Închide",
979 "Add comment" : "Adaugă comentariu",
980 "Mark as fixed" : "Marchează ca rezolvată",
981 "Cancel" : "Anulează",
982 "Create OpenStreetBug" : "Crează OpenStreetBug",
983 "Create bug" : "Adaugă eroare",
984 "Bug description" : "Descrierea erorii",
986 "Permalink" : "Permalink",