1 /* Copyright (c) 2009 Arnaud Renevier, Inc, published under the modified BSD
5 * Fix canvas rendering engine race condition. See js/syp.js for more explanation.
7 OpenLayers.Renderer.Canvas.prototype = OpenLayers.Util.extend({
10 }, OpenLayers.Renderer.Canvas.prototype);
11 OpenLayers.Renderer.Canvas.prototype.oldRedraw = OpenLayers.Renderer.Canvas.prototype.redraw;
12 OpenLayers.Renderer.Canvas.prototype.redraw = function() {
13 if (this.imagesLoading > 0) {
14 this.needsRedraw = true;
17 OpenLayers.Renderer.Canvas.prototype.oldRedraw.apply(this, arguments);
19 OpenLayers.Renderer.Canvas.prototype.drawExternalGraphic = function(pt, style) {
20 var img = new Image();
21 img.src = style.externalGraphic;
23 if(style.graphicTitle) {
24 img.title=style.graphicTitle;
27 var width = style.graphicWidth || style.graphicHeight;
28 var height = style.graphicHeight || style.graphicWidth;
29 width = width ? width : style.pointRadius*2;
30 height = height ? height : style.pointRadius*2;
31 var xOffset = (style.graphicXOffset != undefined) ?
32 style.graphicXOffset : -(0.5 * width);
33 var yOffset = (style.graphicYOffset != undefined) ?
34 style.graphicYOffset : -(0.5 * height);
35 var opacity = style.graphicOpacity || style.fillOpacity;
37 var context = { img: img,
42 canvas: this.canvas };
46 img.onerror = function() {
48 if ((self.imagesLoading == 0) && (self.needsRedraw)) {
49 self.needsRedraw = false;
53 img.onload = OpenLayers.Function.bind( function() {
55 if ((self.imagesLoading == 0) && (self.needsRedraw)) {
56 self.needsRedraw = false;
59 this.canvas.drawImage(this.img, this.x,
60 this.y, this.width, this.height);
64 // drag feature with tolerance
65 OpenLayers.Control.SypDragFeature = OpenLayers.Class (OpenLayers.Control.DragFeature, {
71 downFeature: function(pixel) {
72 OpenLayers.Control.DragFeature.prototype.downFeature.apply(this, arguments);
73 this.dragStart = (new Date()).getTime();
74 this.startPixel = pixel;
77 doneDragging: function(pixel) {
78 OpenLayers.Control.DragFeature.prototype.doneDragging.apply(this, arguments);
80 var passesTimeTolerance =
81 (new Date()).getTime() > this.dragStart + this.timeTolerance;
83 var xDiff = this.startPixel.x - pixel.x;
84 var yDiff = this.startPixel.y - pixel.y;
86 var passesPixelTolerance =
87 Math.sqrt(Math.pow(xDiff,2) + Math.pow(yDiff,2)) > this.pixelTolerance;
89 if(passesTimeTolerance && passesPixelTolerance){
90 this.onComplete(this.feature, pixel);
92 var feature = this.feature;
93 var res = this.map.getResolution();
94 this.feature.geometry.move(res * (this.startPixel.x - this.lastPixel.x),
95 res * (this.lastPixel.y - this.startPixel.y));
96 this.layer.drawFeature(this.feature);
98 this.layer.drawFeature(this.feature, "select");
101 moveFeature: function(pixel) {
102 OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this, arguments);
103 this.layer.drawFeature(this.feature, "temporary");
106 overFeature: function (feature) {
107 // can only drag and drop currently selected feature
108 if (feature != Admin.currentFeature) {
111 OpenLayers.Control.DragFeature.prototype.overFeature.apply(this, arguments);
114 CLASS_NAME: "OpenLayers.Control.SypDragFeature"
119 ICON: "media/marker-normal.png",
120 SELECT_ICON: "media/marker-selected.png",
121 TEMPORARY_ICON: "media/marker-temp.png",
128 selFeatureControl: null,
129 moveFeatureControl: null,
130 addFeatureControl: null,
132 currentFeature: null,
133 currentFeatureLocation: null,
136 this.map = new OpenLayers.Map ("map", {
138 new OpenLayers.Control.Navigation (),
139 new OpenLayers.Control.PanZoom ()
141 projection: new OpenLayers.Projection("EPSG:900913"),
142 displayProjection: new OpenLayers.Projection("EPSG:4326")
145 this.baseLayer = this.createBaseLayer ();
146 this.map.addLayer(this.baseLayer);
148 this.map.setCenter(new OpenLayers.LonLat(0, 0), 0);
149 if (sypSettings.loggedUser) {
150 this.dataLayer = this.createDataLayer (sypSettings.loggedUser);
151 this.map.addLayer(this.dataLayer);
157 this.addFeatureControl.deactivate();
158 this.moveFeatureControl.deactivate();
159 this.selFeatureControl.activate();
160 this.checkForFeatures();
161 $("#newfeature_button").show().val(SypStrings.AddItem);
162 $("#newfeature_button").unbind("click").click(function () {
163 Admin.addNewFeature();
167 createBaseLayer: function () {
168 return new OpenLayers.Layer.OSM("OSM");
171 createDataLayer: function (user) {
172 var styleMap = new OpenLayers.StyleMap (
174 externalGraphic: this.Markers.ICON,
175 graphicHeight: this.Markers.HEIGHT || 32
178 externalGraphic: this.Markers.TEMPORARY_ICON,
179 graphicHeight: this.Markers.HEIGHT || 32
182 externalGraphic: this.Markers.SELECT_ICON,
183 graphicHeight: this.Markers.HEIGHT || 32
186 var layer = new OpenLayers.Layer.GML("KML", "items.php?from_user=" + encodeURIComponent(user),
189 format: OpenLayers.Format.KML,
190 projection: this.map.displayProjection,
191 eventListeners: { scope: this,
192 loadend: this.dataLayerEndLoad
197 this.selFeatureControl = this.createSelectFeatureControl(layer)
198 this.map.addControl(this.selFeatureControl);
199 this.moveFeatureControl = this.createMoveFeatureControl(layer)
200 this.map.addControl(this.moveFeatureControl);
201 this.addFeatureControl = this.createNewfeatureControl();
202 this.map.addControl(this.addFeatureControl);
207 createMoveFeatureControl: function (layer) {
208 var control = new OpenLayers.Control.SypDragFeature(
214 createSelectFeatureControl: function (layer) {
215 var control = new OpenLayers.Control.SelectFeature(
217 onSelect: OpenLayers.Function.bind(this.onFeatureSelect, this)
222 createNewfeatureControl: function () {
223 var control = new OpenLayers.Control ();
224 var handler = new OpenLayers.Handler.Click(control, {
225 'click': OpenLayers.Function.bind(FeatureMgr.add, FeatureMgr)
227 control.handler = handler;
231 onFeatureSelect: function (feature) {
232 this.showEditor(feature);
234 this.selFeatureControl.deactivate();
235 this.moveFeatureControl.activate();
238 closeEditor: function() {
239 if ($("#editor").css("display") == "none") {
242 if (this.currentFeature && this.currentFeature.layer) {
243 this.selFeatureControl.unselect(this.currentFeature);
245 this.currentFeature = null;
246 this.currentFeatureLocation = null;
247 $("#img").removeAttr('src');
248 $("#img").parent().html($("#img").parent().html());
249 $("#img").parent().show();
250 $("#title, #description").val("");
252 // do it once before hidding and once after hidding to work in all cases
253 $("#title, #description").val("");
254 $("#image_file").parent().html($("#image_file").parent().html());
255 $(document).unbind("keydown");
256 this.checkForFeatures();
260 showEditor: function (feature) {
261 $("#newfeature_button").hide();
269 $(document).unbind("keydown").keydown(function(e) {
270 if (e.keyCode == 27) {
271 Admin.cancelCurrentFeature()
275 this.currentFeature = feature;
276 this.currentFeatureLocation = new OpenLayers.Pixel(feature.geometry.x, feature.geometry.y);
278 $("#instructions").text(SypStrings.DragDropHowto);
279 $("#title").val(feature.attributes.name);
280 var fullDesc = $(feature.attributes.description).parent();
281 $("#description").val(fullDesc.find('p').text());
282 var src = fullDesc.find('img').attr('src');
284 $("#img").parent().show();
285 $("#img").attr('src', src);
286 $("#image_file").parent().hide();
287 $("#image_delete").show();
289 $("#img").parent().hide();
290 $("#image_file").parent().show();
291 $("#image_delete").hide();
293 $("#title").select().focus();
296 dataLayerEndLoad: function() {
297 // only set zoom extent once
298 this.dataLayer.events.unregister('loadend', this, this.dataLayerEndLoad);
299 this.dataLayer.events.register('loadend', this, this.checkForFeatures);
301 if (!this.checkForFeatures()) {
306 var orig = this.Utils.mbr (this.dataLayer);
307 var centerBounds = new OpenLayers.Bounds();
309 var mapProj = map.getProjectionObject();
310 var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
312 var bottomLeft = new OpenLayers.LonLat(orig[0],orig[1]);
313 bottomLeft = bottomLeft.transform(sypOrigProj, mapProj);
314 var topRight = new OpenLayers.LonLat(orig[2],orig[3])
315 topRight = topRight.transform(sypOrigProj, mapProj);
317 centerBounds.extend(bottomLeft);
318 centerBounds.extend(topRight);
319 map.zoomToExtent(centerBounds);
322 checkForFeatures: function () {
323 var features = this.dataLayer.features;
324 if (features.length != 0) {
325 $("#instructions").text(SypStrings.SelectHowto);
327 return !!features.length;
330 addNewFeature: function () {
334 $(document).unbind("keydown");
337 $(document).unbind("keydown").keydown(function(e) {
338 if (e.keyCode == 27) {
344 $("#newfeature_button").val(SypStrings.Cancel);
345 $("#newfeature_button").unbind("click").click(cancel);
347 $("#instructions").text(SypStrings.AddHowto);
348 this.selFeatureControl.deactivate();
349 this.addFeatureControl.activate();
353 cancelCurrentFeature: function() {
354 if (AjaxMgr.running) {
357 var feature = this.currentFeature;
360 FeatureMgr.move (feature, this.currentFeatureLocation);
362 this.dataLayer.removeFeatures([feature]);
369 reloadLayer: function (layer) {
370 layer.destroyFeatures();
371 layer.loaded = false;
376 /* minimum bounds rectangle containing all feature locations.
377 * FIXME: if two features are close, but separated by 180th meridian,
378 * their mbr will span the whole earth. Actually, 179° lon and -170°
379 * lon are considerated very near.
381 mbr: function (layer) {
385 var mapProj = map.getProjectionObject();
386 var sypOrigProj = new OpenLayers.Projection("EPSG:4326");
388 for (var i =0; i < layer.features.length; i++) {
389 if (layer.features[i].cluster) {
390 features = features.concat(layer.features[i].cluster);
392 features = features.concat(layer.features);
401 if (features.length == 0) {
402 // keep default values
403 } else if (features.length == 1) {
404 // in case there's only one feature, we show an area of at least
406 var pos = features[0].geometry.getBounds().getCenterLonLat().clone();
407 var lonlat = pos.transform(mapProj, sypOrigProj);
409 minlon = Math.max (lonlat.lon - 2, -180);
410 maxlon = Math.min (lonlat.lon + 2, 180);
411 minlat = Math.max (lonlat.lat - 2, -90);
412 maxlat = Math.min (lonlat.lat + 2, 90);
414 for (var i = 0; i < features.length; i++) {
415 var pos = features[i].geometry.getBounds().getCenterLonLat().clone();
416 var lonlat = pos.transform(mapProj, sypOrigProj);
417 minlon = Math.min (lonlat.lon, minlon);
418 minlat = Math.min (lonlat.lat, minlat);
419 maxlon = Math.max (lonlat.lon, maxlon);
420 maxlat = Math.max (lonlat.lat, maxlat);
424 return [minlon, minlat, maxlon, maxlat];
429 escapeHTML: function (str) {
434 replace(/&/gm, '&').
435 replace(/'/gm, ''').
436 replace(/"/gm, '"').
437 replace(/>/gm, '>').
438 replace(/</gm, '<');
441 startsWith: function (str, prefix) {
442 return (str.slice(0, prefix.length) == prefix);
445 indexOf: function (array, item) {
446 if (array.indexOf !== undefined) {
447 return array.indexOf(item);
449 return OpenLayers.Util.indexOf(array, item);
462 var pos = map.getLonLatFromViewPortPx(evt.xy);
463 feature = this.update (null, pos, "", "", "");
464 Admin.addFeatureControl.deactivate();
465 Admin.selFeatureControl.select(feature);
468 move: function (feature, aLocation) {
469 if (!feature || !aLocation) {
472 var curLoc = feature.geometry;
473 feature.geometry.move(aLocation.x - curLoc.x, aLocation.y - curLoc.y);
474 feature.layer.drawFeature(feature);
477 update: function(feature, lonlat, imgurl, title, description) {
478 var point = new OpenLayers.Geometry.Point(lonlat.lon, lonlat.lat);
480 feature = new OpenLayers.Feature.Vector(point);
481 Admin.dataLayer.addFeatures([feature]);
483 this.move (feature, point);
485 feature.attributes.name = title;
486 feature.attributes.description = "<p>" + Admin.Utils.escapeHTML(description) + "</p>"
487 + "<img src=\"" + imgurl + "\">"
491 del: function (feature) {
492 var form = $("#feature_delete");
493 form.find('input[name="fid"]').val(feature.fid);
496 oncomplete: OpenLayers.Function.bind(this.ajaxReply, this),
497 throbberid: "editor_throbber"
501 save: function (feature) {
502 var x = feature.geometry.x;
503 var y = feature.geometry.y;
505 var mapProj = feature.layer.map.getProjectionObject();
506 var lonlat = new OpenLayers.LonLat(x, y).
508 new OpenLayers.Projection("EPSG:4326"));
509 var form = $("#feature_update");
510 form.find('input[name="lon"]').val(lonlat.lon);
511 form.find('input[name="lat"]').val(lonlat.lat);
512 form.find('input[name="fid"]').val(feature.fid);
513 form.find('input[name="keep_img"]').val(
514 $("#img").attr("src") ? "yes": "no"
518 form.find('input[name="request"]').val("update");
520 form.find('input[name="request"]').val("add");
524 oncomplete: OpenLayers.Function.bind(this.ajaxReply, this),
525 throbberid: "editor_throbber"
529 ajaxReply: function (data) {
531 this.commError(SypStrings.ServerError);
535 var xml = new OpenLayers.Format.XML().read(data);
536 if (!xml.documentElement) {
537 this.commError(SypStrings.UnconsistentError);
542 switch (xml.documentElement.nodeName.toLowerCase()) {
544 switch (xml.documentElement.getAttribute("reason")) {
547 $("#cookie_warning").show();
549 Admin.cancelCurrentFeature();
554 this.commError(SypStrings.ServerError);
558 this.commError(SypStrings.UnreferencedError);
559 Admin.reloadLayer(Admin.dataLayer);
563 this.commError(SypStrings.NochangeError);
567 this.commError(SypStrings.RequestError);
571 this.commError(SypStrings.ToobigError);
572 $("#image_file").parent().html($("#image_file").parent().html());
573 $("#image_file").focus();
576 this.commError(SypStrings.NotimageError);
577 $("#image_file").parent().html($("#image_file").parent().html());
578 $("#image_file").focus();
581 this.commError(SypStrings.UnconsistentError);
587 switch (xml.documentElement.getAttribute("request")) {
589 this.commSuccess(SypStrings.DelSucces);
590 var someFeature = false;
592 $.each($(xml).find("FEATURE,feature"), function () {
594 var id = parseFloat($(this).find("ID:first,id:first").text());
595 if ((id === null) || isNaN (id)) {
598 var features = Admin.dataLayer.features;
599 for (var idx = 0; idx < features.length; idx++) {
600 if (features[idx].fid == id) {
601 Admin.dataLayer.removeFeatures([features[idx]]);
605 if (someFeature == false) {
606 this.commError(SypStrings.UnconsistentError);
613 var someFeature = false;
615 $.each($(xml).find("FEATURE,feature"), function () {
617 var id = parseFloat($(this).find("ID:first,id:first").text());
618 if ((id === null) || isNaN (id)) {
622 var lon = parseFloat($(this).find("LON:first,lon:first").text());
623 if ((typeof (lon) != "number") || isNaN (lon) ||
624 (lon < -180) || (lon > 180)) {
628 var lat = parseFloat($(this).find("LAT:first,lat:first").text());
629 if ((typeof (lat) != "number") || isNaN (lat) ||
630 (lat < -90) || (lat > 90)) {
634 var mapProj = Admin.map.getProjectionObject();
635 var lonlat = new OpenLayers.LonLat (lon, lat).
636 transform( new OpenLayers.Projection("EPSG:4326"), mapProj);
638 var imgurl = $(this).find("IMGURL:first,imgurl:first").text();
639 var title = $(this).find("HEADING:first,heading:first").text();
640 var description = $(this).find("DESCRIPTION:first,description:first").text();
642 feature = self.update (Admin.currentFeature, lonlat, imgurl, title, description);
646 if (someFeature == false) {
647 this.commError(SypStrings.UnconsistentError);
649 this.commSuccess(SypStrings.UpdateSucces);
655 this.commError(SypStrings.UnconsistentError);
660 this.commError(SypStrings.UnconsistentError);
665 commSuccess: function (message) {
666 $("#server_comm").text(message);
667 $("#server_comm").removeClass("error success").addClass("success");
670 commError: function (message) {
671 $("#server_comm").text(message);
672 $("#server_comm").removeClass("error success").addClass("error");
676 /* maintains a queue of ajax queries, so I'm sure they all execute in the same
677 * order they were defined */
683 add: function(query) {
684 this._queue.push(query);
685 if (this._queue.length > 1) {
688 this._runQuery(query);
692 _runQuery: function(query) {
694 $('#api_frame').one("load", function() {
695 self.running = false;
697 if (query.throbberid) {
698 $("#" + query.throbberid).css("visibility", "hidden");
700 if (typeof (query.oncomplete) == "function") {
703 if (this.contentDocument) {
704 body = this.contentDocument.body;
705 } else if (this.contentWindow) {
706 body = this.contentWindow.document.body;
708 body = document.frames[this.id].document.body;
712 query.oncomplete(body.innerHTML);
714 query.oncomplete(null);
718 query.form.attr("action", "api.php");
719 query.form.attr("target", "api_frame");
720 query.form.attr("method", "post");
722 query.form.get(0).submit();
723 if (query.throbberid) {
724 $("#" + query.throbberid).css("visibility", "visible");
726 if (typeof (query.onsend) == "function") {
731 _reqEnd: function() {
733 if (this._queue.length > 0) {
734 this._reqEnd(this._queue[0]);
742 $("#login_form").submit(this.submit);
743 $("#user").focus().select();
748 $("#login_area").show();
749 $("#password").val("");
750 $("#user").val(sypSettings.loggedUser).focus().select();
753 submit: function () {
755 pwdMgr.commError("");
757 form: $("#login_form"),
758 throbberid: "pwd_throbber",
760 $("#login_error").hide();
762 // we need a timeout; otherwise those fields will not be submitted
763 window.setTimeout(function() {
764 // removes focus from #password before disabling it. Otherwise, opera
765 // prevents re-focusing it after re-enabling it.
766 $("#user, #password").blur();
767 $("#login_submit, #user, #password").attr("disabled", "disabled");
770 oncomplete: OpenLayers.Function.bind(pwdMgr.ajaxReply, pwdMgr)
777 ajaxReply: function (data) {
778 // here, we need a timeout because onsend timeout sometimes has not been triggered yet
779 window.setTimeout(function() {
780 $("#login_submit, #user, #password").removeAttr("disabled");
784 this.commError(SypStrings.ServerError);
785 $("#login_error").show();
786 window.setTimeout(function() {
787 $("#user").focus().select();
792 var xml = new OpenLayers.Format.XML().read(data);
793 if (!xml.documentElement) {
794 this.commError(SypStrings.UnconsistentError);
795 $("#login_error").show();
796 window.setTimeout(function() {
797 $("#user").focus().select();
801 switch (xml.documentElement.nodeName.toLowerCase()) {
803 switch (xml.documentElement.getAttribute("reason")) {
805 this.commError(SypStrings.ServerError);
808 this.commError(SypStrings.UnauthorizedError);
811 this.commError(SypStrings.RequestError);
814 this.commError(SypStrings.UnconsistentError);
817 $("#login_error").show();
818 window.setTimeout(function() {
819 $("#user").focus().select();
823 $("#login_area").hide();
825 user = $(xml).find("USER,user").text();
826 sypSettings.loggedUser = user;
828 if (sypSettings.loggedUser == "admin") {
832 if (Admin.selFeatureControl) {
833 Admin.selFeatureControl.destroy();
835 if (Admin.moveFeatureControl) {
836 Admin.moveFeatureControl.destroy();
838 if (Admin.addFeatureControl) {
839 Admin.addFeatureControl.destroy();
841 if (Admin.dataLayer) {
842 Admin.dataLayer.destroy();
845 Admin.dataLayer = Admin.createDataLayer(user);
846 Admin.map.addLayer(Admin.dataLayer);
851 this.commError(SypStrings.UnconsistentError);
856 commError: function (message) {
857 $("#login_error").text(message);
859 $("#login_error").show();
861 $("#login_error").hide();
867 _adduserDisplayed: false,
868 _changepassDisplayed: false,
871 $("#user_close").unbind("click").click(function () {
875 $("#change_pass").unbind("click").click(function() {
876 userMgr.toggleChangePass();
879 $("#changepass").unbind("submit").submit(function() {
881 userMgr.changepass();
886 if (sypSettings.loggedUser != "admin") {
890 $("#add_user").show();
891 $("#add_user").unbind("click").click(function () {
892 userMgr.toggleAddUser();
895 $("#newuser").unbind("submit").submit(function() {
904 disableForms: function() {
905 $("#newuser_name, #newuser_password, #newuser_password_confirm, #newuser_submit").attr("disabled", "disabled");
906 $("#pass_current, #pass_new, #pass_new_confirm, #pass_submit").attr("disabled", "disabled");
909 enableForms: function() {
910 $("#newuser_name, #newuser_password, #newuser_password_confirm, #newuser_submit").removeAttr("disabled");
911 $("#pass_current, #pass_new, #pass_new_confirm, #pass_submit").removeAttr("disabled");
914 resetForms: function() {
915 $("#newuser_name, #newuser_password, #newuser_password_confirm").val("");
916 $("#pass_current, #pass_new, #pass_new_confirm").val("");
921 $("#add_user").unbind("click");
922 $("#add_user").hide();
923 $("#change_pass").unbind("click");
924 $("#user_close").unbind("click");
925 $("#newuser").unbind("submit");
926 $("#changepass").unbind("submit");
930 this.closeChangePass();
934 toggleChangePass: function() {
935 if (this._changepassDisplayed) {
936 this.closeChangePass();
938 this.showChangePass();
942 showChangePass: function() {
943 if (!Admin.cancelCurrentFeature()) {
948 $(document).unbind("keydown").keydown(function(e) {
949 if (e.keyCode == 27) {
950 userMgr.closeChangePass()
957 $("#user_area, #changepass").show();
960 // XXX: setTimeout needed because otherwise, map becomes hidden in IE. Why ??
961 window.setTimeout(function() {
962 $("#pass_current").focus();
965 this._changepassDisplayed = true;
968 closeChangePass: function() {
969 if (!this._changepassDisplayed) {
972 $("#user_area, #changepass").hide();
973 $(document).unbind("keydown");
974 this._changepassDisplayed = false;
977 changepass: function() {
978 var newpass = $("#pass_new").val();
979 var newpass_confirm = $("#pass_new_confirm").val();
980 if (newpass != newpass_confirm) {
981 this.commError(SypStrings.userPasswordmatchError);
982 $("#pass_new").focus().select();
987 this.commError(SypStrings.emptyPasswordError);
988 $("#pass_new").focus().select();
992 var curpass = $("#pass_current").val();
993 if (newpass == curpass) {
994 this.commError(SypStrings.changeSamePass);
995 $("#pass_new").focus().select();
1002 form: $("#changepass"),
1003 oncomplete: OpenLayers.Function.bind(this.ajaxReply, this),
1004 throbberid: "user_throbber",
1005 onsend: function() {
1006 // we need a timeout; otherwise those fields will not be submitted
1007 window.setTimeout(function() {
1008 // removes focus from #password before disabling it. Otherwise, opera
1009 // prevents re-focusing it after re-enabling it.
1010 $("#pass_current, #pass_new, #pass_new_confirm").blur();
1011 userMgr.disableForms();
1017 toggleAddUser: function() {
1018 if (this._adduserDisplayed) {
1019 this.closeAddUser();
1025 showAddUser: function() {
1026 if (!Admin.cancelCurrentFeature()) {
1030 this.closeChangePass();
1032 $(document).unbind("keydown").keydown(function(e) {
1033 if (e.keyCode == 27) {
1034 userMgr.closeAddUser()
1039 $("#user_area, #newuser").show();
1044 // XXX: setTimeout needed because otherwise, map becomes hidden in IE. Why ??
1045 window.setTimeout(function() {
1046 $("#newuser_name").focus();
1049 this._adduserDisplayed = true;
1052 closeAddUser: function() {
1053 if (!this._adduserDisplayed) {
1056 $("#user_area, #newuser").hide();
1057 $(document).unbind("keydown");
1058 this._adduserDisplayed = false;
1062 var newuser_name = $("#newuser_name").val();
1063 if (!newuser_name) {
1064 this.commError(SypStrings.newUserNonameError);
1065 $("#newuser_name").focus();
1069 var newuser_pass = $("#newuser_password").val();
1070 var newuser_pass_confirm = $("#newuser_password_confirm").val();
1071 if (newuser_pass != newuser_pass_confirm) {
1072 this.commError(SypStrings.userPasswordmatchError);
1073 $("#newuser_password").focus().select();
1077 if (!newuser_pass) {
1078 this.commError(SypStrings.emptyPasswordError);
1079 $("#pass_new").focus().select();
1086 form: $("#newuser"),
1087 oncomplete: OpenLayers.Function.bind(this.ajaxReply, this),
1088 throbberid: "user_throbber",
1089 onsend: function() {
1090 // we need a timeout; otherwise those fields will not be submitted
1091 window.setTimeout(function() {
1092 // removes focus from #password before disabling it. Otherwise, opera
1093 // prevents re-focusing it after re-enabling it.
1094 $("#newuser_name, #newuser_password, #newuser_password_confirm").blur();
1095 userMgr.disableForms();
1101 ajaxReply: function (data) {
1103 // here, we need a timeout because onsend timeout sometimes has not been triggered yet
1105 window.setTimeout(function() {
1108 this.commError(SypStrings.ServerError);
1112 var xml = new OpenLayers.Format.XML().read(data);
1113 if (!xml.documentElement) {
1114 // here, we need a timeout because onsend timeout sometimes has not been triggered yet
1116 window.setTimeout(function() {
1119 this.commError(SypStrings.UnconsistentError);
1123 var needFormEnabling = true;
1126 switch (xml.documentElement.nodeName.toLowerCase()) {
1128 switch (xml.documentElement.getAttribute("reason")) {
1129 case "unauthorized":
1131 $("#cookie_warning").show();
1136 this.commError(SypStrings.ServerError);
1137 if (this._adduserDisplayed) {
1138 focusEl = $("#newuser_name");
1139 } else if (this._changepassDisplayed) {
1140 focusEl = $("#pass_current");
1144 this.commError(SypStrings.RequestError);
1145 if (this._adduserDisplayed) {
1146 focusEl = $("#newuser_name");
1147 } else if (this._changepassDisplayed) {
1148 focusEl = $("#pass_current");
1152 this.commError(SypStrings.changePassBadPass);
1153 focusEl = $("#pass_current");
1155 case "newuser_exists":
1156 this.commError(SypStrings.newUserExistsError);
1157 focusEl = $("#newuser_name");
1160 this.commError(SypStrings.UnconsistentError);
1161 if (this._adduserDisplayed) {
1162 focusEl = $("#newuser_name");
1163 } else if (this._changepassDisplayed) {
1164 focusEl = $("#pass_current");
1170 switch (xml.documentElement.getAttribute("request")) {
1172 this.commSuccess(SypStrings.newUserSuccess);
1173 needFormEnabling = false;
1176 this.commSuccess(SypStrings.changePassSuccess);
1177 needFormEnabling = false;
1180 this.commError(SypStrings.UnconsistentError);
1181 focusEl = $("newuser_name");
1186 this.commError(SypStrings.UnconsistentError);
1187 focusEl = $("newuser_name");
1191 if (needFormEnabling) {
1192 // here, we need a timeout because onsend timeout sometimes has not been triggered yet
1194 window.setTimeout(function() {
1197 focusEl.select().focus();
1202 focusEl.focus().select();
1208 commSuccess: function (message) {
1209 $("#user_comm").text(message);
1210 $("#user_comm").removeClass("error success").addClass("success");
1213 commError: function (message) {
1214 $("#user_comm").text(message);
1215 $("#user_comm").removeClass("error success").addClass("error");
1219 $(window).load(function () {
1220 // if using .ready, ie triggers an error when trying to access
1221 // document.namespaces
1223 $("#newfeature_button").click(function () {
1224 Admin.addNewFeature();
1226 $("#editor_close").click(function () {
1227 Admin.cancelCurrentFeature()
1229 $("#feature_update").submit(function() {
1231 FeatureMgr.save(Admin.currentFeature);
1235 $("#feature_delete").submit(function() {
1237 FeatureMgr.del(Admin.currentFeature);
1241 $("#image_delete").click(function() {
1242 $("#img").removeAttr('src');
1243 // needs to rebuild element otherwise some browsers still
1245 $("#img").parent().html($("#img").parent().html());
1246 $("#img").parent().hide();
1247 $("#image_delete").hide();
1248 $("#image_file").parent().show();