1 /* This file is part of Syj, Copyright (c) 2010 Arnaud Renevier,
2 and is published under the AGPL license. */
3 Element.addMethods('input', {
4 observe : Element.Methods.observe.wrap(function(proceed, element, eventName, handler) {
5 if (eventName === "contentchange") {
6 proceed(element, 'keyup', function(evt) {
7 if (evt.keyCode == 13) {
10 handler.apply(null, arguments);
12 proceed(element, 'paste', handler);
13 return proceed(element, 'change', handler);
15 return proceed(element, eventName, handler);
19 // avoid openlayers alerts
20 OpenLayers.Console.userError = function(error) {
21 SYJView.messenger.setMessage(error, "error");
28 $("geom_title").observe('contentchange', this.enableSubmit.bindAsEventListener(this));
33 $("geom_submit").blur();
34 $("geom_title").blur();
45 if (this.status === "enabled") {
49 $("geom_title").disabled = false;
50 $("geom_title").focus();
51 $("geom_title").select();
52 $("geomform").removeClassName("disabled");
53 this.status = "enabled";
58 if (this.status === "disabled") {
62 $("geom_title").blur();
63 $("geom_title").disabled = true;
64 $("geomform").addClassName("disabled");
65 this.status = "disabled";
69 enableSubmit: function() {
70 $("geom_submit").disabled = false;
71 this.status = "partial";
75 disableSubmit: function() {
76 $("geom_submit").blur();
77 $("geom_submit").disabled = true;
78 this.status = "partial";
100 OpenLayers.Handler.SyjModifiablePath = OpenLayers.Class(OpenLayers.Handler.ModifiablePath, {
101 mouseup: function(evt) {
102 // do not add a point when navigating
103 var mapControls = this.control.map.controls, idx, ctrl;
105 for (idx = mapControls.length; idx-->0; ) {
106 ctrl = mapControls[idx];
107 if (this.isCtrlNavigationActive(ctrl, evt)) {
111 return OpenLayers.Handler.ModifiablePath.prototype.mouseup.apply(this, arguments);
114 addPoints: function(pixel) {
115 // redraw before last point. As we have a special style for last point, we
116 // need to redraw before last point after adding a new point (otherwise, it
117 // keeps special style forever)
118 var oldpoint = this.point;
119 OpenLayers.Handler.ModifiablePath.prototype.addPoints.apply(this, arguments);
120 this.layer.drawFeature(oldpoint);
123 isCtrlNavigationActive: function(ctrl, evt) {
124 var tolerance = 4, xDiff, yDiff;
126 if (!(ctrl instanceof OpenLayers.Control.Navigation)) {
131 ctrl.zoomBox.active &&
132 ctrl.zoomBox.handler &&
133 ctrl.zoomBox.handler.active &&
134 ctrl.zoomBox.handler.dragHandler &&
135 ctrl.zoomBox.handler.dragHandler.start) {
140 !ctrl.dragPan.active ||
141 !ctrl.dragPan.handler ||
142 !ctrl.dragPan.handler.started ||
143 !ctrl.dragPan.handler.start) {
147 // if mouse moved 4 or less pixels, consider it has not moved.
150 xDiff = evt.xy.x - ctrl.dragPan.handler.start.x;
151 yDiff = evt.xy.y - ctrl.dragPan.handler.start.y;
153 if (Math.sqrt(Math.pow(xDiff,2) + Math.pow(yDiff,2)) <= tolerance) {
159 finalize: function(cancel) {
160 // do nothing. We don't want to finalize path
165 edit: new OpenLayers.StyleMap({
166 "default": new OpenLayers.Style({
167 pointRadius: "${radius}", // sized according to type attribute
168 fillColor: "#ffcc66",
169 strokeColor: "#ff9933",
171 strokeOpacity: "${opacity}",
172 fillOpacity: "${opacity}"
176 radius: function(feature) {
179 if (!(feature.geometry instanceof OpenLayers.Geometry.Point)) {
182 if (feature.type === "middle") {
185 features = feature.layer.features;
186 if (OpenLayers.Util.indexOf(features, feature) === 0) {
188 } else if (OpenLayers.Util.indexOf(features, feature) === features.length - 1) {
193 opacity: function (feature) {
194 if (feature.type === "middle") {
203 "select": new OpenLayers.Style({
204 externalGraphic: "icons/delete.png",
208 "select_for_canvas": new OpenLayers.Style({
210 fillColor: "lightblue"
215 view: new OpenLayers.StyleMap({
216 "default": new OpenLayers.Style({
224 var WGS84 = new OpenLayers.Projection("EPSG:4326");
225 var Mercator = new OpenLayers.Projection("EPSG:900913");
231 wkt: new OpenLayers.Format.WKT({ internalProjection: Mercator, externalProjection: WGS84 }),
232 needsFormResubmit: false,
235 var externalGraphic, baseURL, baseLayer, layerOptions, extent = null, hidemessenger;
237 // is svg context, opera does not resolve links with base element is svg context
238 externalGraphic = styleMap.edit.styles.select.defaultStyle.externalGraphic;
239 baseURL = document.getElementsByTagName("base")[0].href;
240 styleMap.edit.styles.select.defaultStyle.externalGraphic = baseURL + externalGraphic;
242 this.map = new OpenLayers.Map('map', {
244 new OpenLayers.Control.Navigation(),
245 new OpenLayers.Control.PanZoom(),
246 new OpenLayers.Control.Attribution()
251 baseLayer = new OpenLayers.Layer.OSM("OSM", null, { wrapDateLine: true , attribution: SyjStrings.osmAttribution });
253 layerOptions = {format: OpenLayers.Format.WKT,
255 styleMap: styleMap.view};
256 if (gLoggedInfo.ownername) {
257 layerOptions.attribution = SyjStrings.routeBy + ' ' + '<strong>' + gLoggedInfo.ownername + '</strong>';
260 this.viewLayer = new OpenLayers.Layer.Vector("View Layer", layerOptions);
261 this.map.addLayers([baseLayer, this.viewLayer]);
263 $("edit-btn").observe('click', (function() {
264 this.messenger.hide();
267 SyjEditUI.init().hide();
269 $("geomform").ajaxize({
270 presubmit: this.prepareForm.bind(this),
271 onSuccess: this.saveSuccess.bind(this),
272 onFailure: this.saveFailure.bind(this)
274 SyjSaveUI.init().hide();
276 this.messenger = $('message');
277 hidemessenger = this.messenger.empty();
278 new CloseBtn(this.messenger, {
284 this.messenger.hide();
288 if ($("geom_data").value) {
289 this.viewLayer.addFeatures([this.wkt.read($("geom_data").value)]);
290 extent = this.viewLayer.getDataExtent();
291 // XXX: ie has not guessed height of map main div yet during map
292 // initialisation. Now, it will read it correctly.
293 this.map.updateSize();
296 extent = new OpenLayers.Bounds(gMaxExtent.minlon, gMaxExtent.minlat, gMaxExtent.maxlon, gMaxExtent.maxlat)
297 .transform(WGS84, Mercator);
300 this.map.zoomToExtent(extent);
301 document.observe('simplebox:shown', this.observer.bindAsEventListener(this));
304 observer: function(evt) {
305 if (evt.eventName === "simplebox:shown" && evt.memo.element !== $("termsofusearea")) {
306 this.messenger.hide();
310 prepareForm: function(form) {
311 var line, realPoints, idx, handler;
313 line = new OpenLayers.Geometry.LineString();
314 realPoints = this.editControl.handler.realPoints;
315 for (idx = 0; idx < realPoints.length; idx++) {
316 line.addComponent(realPoints[idx].geometry.clone());
318 this.viewLayer.addFeatures(new OpenLayers.Feature.Vector(line));
319 handler = this.editControl.handler;
320 OpenLayers.Handler.ModifiablePath.prototype.finalize.apply(handler, arguments);
321 // we need to recreate them on next createFeature; otherwise
322 // they'll reference destroyed features
323 delete(handler.handlers.drag);
324 delete(handler.handlers.feature);
325 this.editControl.deactivate();
327 $("geom_data").value = this.wkt.write(new OpenLayers.Feature.Vector(line));
328 this.needsFormResubmit = false;
329 SyjSaveUI.disable.bind(SyjSaveUI).defer();
330 this.messenger.hide();
333 editMode: function() {
334 var components, point0, point, pixels, pixel, idx;
336 this.initEditControl();
338 this.editControl.activate();
339 if (this.viewLayer.features.length) {
340 components = this.viewLayer.features[0].geometry.components;
341 point0 = components[0];
343 pixel = this.map.getPixelFromLonLat(new OpenLayers.LonLat(point0.x, point0.y));
344 this.editControl.handler.createFeature(pixel);
345 this.editControl.handler.lastUp = pixel;
347 for (idx = 1; idx < components.length; idx++) {
348 point = components[idx];
349 pixels.push(this.map.getPixelFromLonLat(new OpenLayers.LonLat(point.x, point.y)));
351 this.editControl.handler.addPoints(pixels);
355 this.viewLayer.destroyFeatures();
358 if (this.editControl.handler.realPoints && this.editControl.handler.realPoints.length >= 2) {
359 SyjSaveUI.show().disableSubmit();
361 SyjSaveUI.show().disable();
365 initEditControl: function() {
368 if (this.editControl) {
372 this.editControl = new OpenLayers.Control.DrawFeature(new OpenLayers.Layer.Vector(), OpenLayers.Handler.SyjModifiablePath, {
374 modify: function(f, line) {
375 if (this.handler.realPoints.length < 2) {
376 SyjSaveUI.show().disable();
378 SyjSaveUI.show().enable();
385 styleMap: styleMap.edit
389 this.map.addControl(this.editControl);
390 if (this.editControl.layer.renderer instanceof OpenLayers.Renderer.Canvas) {
391 // using externalGraphic with canvas renderer is definitively too buggy
392 styles = this.editControl.handler.layerOptions.styleMap.styles;
393 styles.select = styles.select_for_canvas;
397 saveSuccess: function(transport) {
398 if (!$("geom_id").value) {
399 location = "idx/" + transport.responseText;
402 this.messenger.setMessage(SyjStrings.saveSuccess, "success");
406 document.title = $('geom_title').value;
409 saveFailure: function(transport) {
410 var httpCode = 0, message = "";
413 httpCode = transport.getStatus();
418 message = SyjStrings.notReachedError;
423 message = SyjStrings.requestError; // default message
424 if (transport.responseJSON) {
425 switch (transport.responseJSON.message) {
427 message = SyjStrings.unreferencedError;
430 message = SyjStrings.uniquePathError;
439 this.needsFormResubmit = true;
440 if (loginMgr.hasAlreadyConnected()) {
441 SYJLogin.messenger.setMessage(SyjStrings.cookiesNeeded, "warn");
443 SYJLogin.messenger.setMessage(SyjStrings.loginNeeded, "warn");
445 SYJLogin.modalbox.show();
448 message = SyjStrings.serverError;
449 this.needsFormResubmit = true;
452 message = SyjStrings.unknownError;
457 // is some cases, we let the user resubmit, in some other cases, he
458 // needs to modify the path before submitting again
459 if (this.needsFormResubmit) {
463 this.messenger.setMessage(message, "error");
467 var SYJModalClass = Class.create({
471 this.area = $(this.type + '_area');
472 this.messenger = $(this.type + "_message");
473 this.modalbox = new SimpleBox(this.area, {
474 closeMethods: ["onescapekey", "onouterclick", "onbutton"]
477 $(this.type + "_control_anchor").observe("click", function(evt) {
478 this.modalbox.show();
480 }.bindAsEventListener(this));
482 document.observe('simplebox:shown', this.observer.bindAsEventListener(this));
483 document.observe('simplebox:hidden', this.observer.bindAsEventListener(this));
485 $(this.type + "form").ajaxize({
486 presubmit: this.presubmit.bind(this),
487 onSuccess: this.success.bind(this),
488 onFailure: this.failure.bind(this)
492 checkNotEmpty: function(input, message) {
493 if ($(input).value.strip().empty()) {
494 this.messenger.setMessage(message, "warn");
495 $(input).highlight('#F08080').focus();
501 observer: function(evt) {
502 var simplebox, input;
504 if (evt.eventName === "simplebox:shown" && evt.memo.element !== $("termsofusearea")) {
505 simplebox = evt.memo;
506 if (simplebox === this.modalbox) {
507 input = this.area.select('input[type="text"]')[0];
513 this.modalbox.hide();
516 } else if (evt.eventName === "simplebox:hidden" && evt.memo.element !== $("termsofusearea")) {
517 simplebox = evt.memo;
518 if (simplebox === this.modalbox) {
524 failure: function(transport) {
525 var httpCode = 0, message = SyjStrings.unknownError, input; // default message error
528 httpCode = transport.getStatus();
533 message = SyjStrings.notReachedError;
538 message = SyjStrings.requestError;
541 message = SyjStrings.serverError;
545 this.messenger.setMessage(message, "error");
546 input = this.area.select('input[type="text"]')[0];
547 input.highlight('#F08080').focus();
552 this.messenger.hide();
553 this.area.select('.message').invoke('setMessageStatus', null);
557 var SYJUserClass = Class.create(SYJModalClass, {
561 init: function($super) {
563 $("termsofusearea").hide();
565 $("user_termsofuse_anchor").observe("click", function(evt) {
567 $("termsofusearea").show();
568 $("termsofuseiframe").setAttribute("src", evt.target.href);
569 this.toubox = new SimpleBox($("termsofusearea"), {
570 closeMethods: ["onescapekey", "onouterclick", "onbutton"]
575 }.bindAsEventListener(this));
577 $$("#login_area_create > a").invoke('observe', 'click',
579 this.modalbox.show();
581 }.bindAsEventListener(this));
583 $("user_password").observe('contentchange', function(evt) {
584 if (evt.target.value.length < 6) {
585 $("user_password-desc").setMessageStatus("warn");
587 $("user_password-desc").setMessageStatus("success");
589 }.bindAsEventListener(this));
592 presubmit: function() {
593 if (!(this.checkNotEmpty("user_pseudo", SyjStrings.userEmptyWarn))) {
597 if (!($("user_pseudo").value.match(/^[a-zA-Z0-9_.]+$/))) {
598 this.messenger.setMessage(SyjStrings.invalidPseudo, "warn");
599 $("user_pseudo").highlight('#F08080').focus();
600 $("user_pseudo").select();
604 if (!(this.checkNotEmpty("user_password", SyjStrings.passwordEmptyWarn))) {
608 if ($("user_password").value.length < 6) {
609 $("user_password-desc").setMessageStatus("warn");
610 $("user_password").highlight('#F08080').focus();
611 $("user_password").select();
615 if ($("user_password").value !== $("user_password_confirm").value) {
616 this.messenger.setMessage(SyjStrings.passwordNoMatchWarn, "warn");
617 $("user_password").highlight('#F08080').focus();
618 $("user_password").select();
622 if (!(this.checkNotEmpty("user_email", SyjStrings.emailEmptyWarn))) {
626 if (!$("user_accept").checked) {
627 this.messenger.setMessage(SyjStrings.acceptTermsofuseWarn, "warn");
628 $("user_accept").highlight('#F08080').focus();
636 success: function(transport) {
638 SYJView.messenger.setMessage(SyjStrings.userSuccess, "success");
639 this.modalbox.hide();
640 if (SYJView.needsFormResubmit) {
641 SYJView.messenger.addMessage(SyjStrings.canResubmit);
642 $("geom_submit").focus();
646 failure: function($super, transport) {
647 var httpCode = 0, focusInput = null, message = "";
650 httpCode = transport.getStatus();
658 if (transport.responseJSON) {
659 switch (transport.responseJSON.message) {
661 message = SyjStrings.emailInvalidWarn;
662 focusInput = $("user_email");
665 message = SyjStrings.uniqueUserError;
666 focusInput = $("user_pseudo");
669 message = SyjStrings.uniqueEmailError;
670 focusInput = $("user_email");
678 this.messenger.setMessage(message, "error");
680 focusInput.highlight('#F08080').focus();
689 var SYJUser = new SYJUserClass();
691 var SYJLoginClass = Class.create(SYJModalClass, {
694 init: function($super) {
698 presubmit: function() {
699 if (!(this.checkNotEmpty("login_user", SyjStrings.userEmptyWarn))) {
707 success: function(transport) {
708 if (transport.responseText === "1") {
709 loginMgr.login(true);
713 SYJView.messenger.setMessage(SyjStrings.loginSuccess, "success");
714 this.modalbox.hide();
715 if (SYJView.needsFormResubmit) {
716 SYJView.messenger.addMessage(SyjStrings.canResubmit);
717 $("geom_submit").focus();
721 failure: function($super, transport) {
722 var httpCode = 0, focusInput = null, message = "";
725 httpCode = transport.getStatus();
733 message = SyjStrings.loginFailure;
734 focusInput = $("login_user");
739 this.messenger.setMessage(message, "error");
741 focusInput.highlight('#F08080').focus();
750 var SYJLogin = new SYJLoginClass();
752 var SYJNewpwdClass = Class.create(SYJModalClass, {
755 presubmit: function() {
756 if (!(this.checkNotEmpty("newpwd_email", SyjStrings.emailEmptyWarn))) {
762 success: function(transport) {
763 SYJView.messenger.setMessage(SyjStrings.newpwdSuccess, "success");
764 this.modalbox.hide();
768 var SYJNewpwd = new SYJNewpwdClass();
770 var loginMgr = Object.extend(gLoggedInfo, {
773 updateUI: function() {
774 if (!this.controlsdeck) {
775 this.controlsdeck = new Deck("login_controls");
778 this.controlsdeck.setIndex(1);
780 this.controlsdeck.setIndex(0);
784 $("data_controls").show();
786 $("data_controls").hide();
790 login: function(aIsOwner) {
791 if (typeof aIsOwner === "boolean") {
792 this.isowner = aIsOwner;
799 // needed in case of 403 errors: if user has already connected successfully
800 // before, it probably means he has cookies disabled
801 hasAlreadyConnected: function() {
802 return (this.connections >= 1);
806 document.observe("dom:loaded", function() {