X-Git-Url: https://dev.renevier.net/?a=blobdiff_plain;f=public%2Fjs%2Fsyj.js;h=39ecd4f90bdf86b8321054ead2e08f823a28612d;hb=6cc4b3cd4538430770c935bd3192f1f72d75d96b;hp=4b7f01d9a39dda1f010856080f130cc806577a0f;hpb=1d1b5940442782d78f796d8608e63328e2e8783b;p=syj.git diff --git a/public/js/syj.js b/public/js/syj.js index 4b7f01d..39ecd4f 100644 --- a/public/js/syj.js +++ b/public/js/syj.js @@ -1,20 +1,5 @@ /* This file is part of Syj, Copyright (c) 2010 Arnaud Renevier, and is published under the AGPL license. */ -Element.addMethods('input', { - observe : Element.Methods.observe.wrap(function(proceed, element, eventName, handler) { - if (eventName === "contentchange") { - proceed(element, 'keyup', function(evt) { - if (evt.keyCode === 13) { - return; - } - handler.apply(null, arguments); - }); - proceed(element, 'paste', handler); - return proceed(element, 'change', handler); - } - return proceed(element, eventName, handler); - }) -}); // avoid openlayers alerts OpenLayers.Console.userError = function(error) { @@ -29,18 +14,6 @@ var SyjSaveUI = { return this; }, - hide: function() { - $("geom_submit").blur(); - $("geom_title").blur(); - $("geomform").hide(); - return this; - }, - - show: function() { - $("geomform").show(); - return this; - }, - enable: function() { if (this.status === "enabled") { return this; @@ -67,6 +40,7 @@ var SyjSaveUI = { enableSubmit: function() { $("geom_submit").disabled = false; + $("geom_accept").disabled = false; this.status = "partial"; return this; }, @@ -74,23 +48,30 @@ var SyjSaveUI = { disableSubmit: function() { $("geom_submit").blur(); $("geom_submit").disabled = true; + $("geom_accept").blur(); + $("geom_accept").disabled = true; this.status = "partial"; return this; } }; -var SyjEditUI = { - hide: function() { - $("edit-btn").blur(); - $("edit-btn").hide(); - return this; - }, - - show: function() { - $("edit-btn").show(); - return this; - } -}; +var SYJDataUi = (function() { + var deck = null, + getdeck = function() { + if (!deck) { + deck = new Deck("data_controls"); + } + return deck; + }; + return { + viewmode: function() { + getdeck().setIndex(0); + }, + editmode: function() { + getdeck().setIndex(1); + } + }; +}()); OpenLayers.Handler.SyjModifiablePath = OpenLayers.Class(OpenLayers.Handler.ModifiablePath, { mouseup: function(evt) { @@ -225,6 +206,8 @@ var SYJView = { map: null, wkt: new OpenLayers.Format.WKT({ internalProjection: Mercator, externalProjection: WGS84 }), needsFormResubmit: false, + unsavedRoute: null, + mode: 'view', init: function() { var externalGraphic, baseURL, baseLayer, layerOptions, extent, hidemessenger; @@ -247,25 +230,46 @@ var SYJView = { layerOptions = {format: OpenLayers.Format.WKT, projection: WGS84, - styleMap: styleMap.view}; - if (gLoggedInfo.creatorname) { - layerOptions.attribution = SyjStrings.routeBy + ' ' + '' + gLoggedInfo.creatorname + ''; - } + styleMap: styleMap.view, + attribution: SyjStrings.geomAttribution }; this.viewLayer = new OpenLayers.Layer.Vector("View Layer", layerOptions); this.map.addLayers([baseLayer, this.viewLayer]); - $("edit-btn").observe('click', (function() { - this.messenger.hide(); - this.editMode(); - }).bind(this)); + if ($("edit-btn")) { + $("edit-btn").observe('click', function() { + $("geom_submit").value = SyjStrings.editAction; + this.messenger.hide(); + this.editMode(); + this.mode = 'edit'; + }.bind(this)); + } + + if ($("create-btn")) { + $("create-btn").observe('click', function() { + $("geom_submit").value = SyjStrings.createAction; + this.messenger.hide(); + this.editMode(); + this.mode = 'create'; + }.bind(this)); + } + + if ($("clone-btn")) { + $("clone-btn").observe('click', function() { + $("geom_submit").value = SyjStrings.cloneAction; + $("geom_title").value = ""; + this.messenger.hide(); + this.editMode(); + this.mode = 'create'; + }.bind(this)); + } $("geomform").ajaxize({ presubmit: this.prepareForm.bind(this), onSuccess: this.saveSuccess.bind(this), onFailure: this.saveFailure.bind(this) }); - SyjSaveUI.init().hide(); + SyjSaveUI.init(); this.messenger = $('message'); hidemessenger = this.messenger.empty(); @@ -278,8 +282,8 @@ var SYJView = { this.messenger.hide(); } - if ($("geom_data").value) { - this.viewLayer.addFeatures([this.wkt.read($("geom_data").value)]); + if (typeof gInitialGeom !== "undefined" && typeof gInitialGeom.data !== "undefined") { + this.viewLayer.addFeatures([this.wkt.read(gInitialGeom.data)]); extent = this.viewLayer.getDataExtent(); // XXX: ie has not guessed height of map main div yet during map // initialisation. Now, it will read it correctly. @@ -299,14 +303,14 @@ var SYJView = { }, prepareForm: function(form) { - if (!loginMgr.logged && !$("geom_accept").checked) { + if (!LoginMgr.logged && !$("geom_accept").checked) { this.messenger.setMessage(SyjStrings.acceptTermsofuseWarn, "warn"); $("geom_accept_container").highlight('#F08080'); $("geom_accept").activate(); return false; } - var line, realPoints, idx, handler; + var line, realPoints, idx; line = new OpenLayers.Geometry.LineString(); realPoints = this.editControl.handler.realPoints; @@ -314,21 +318,31 @@ var SYJView = { line.addComponent(realPoints[idx].geometry.clone()); } this.viewLayer.addFeatures(new OpenLayers.Feature.Vector(line)); - handler = this.editControl.handler; - OpenLayers.Handler.ModifiablePath.prototype.finalize.apply(handler, arguments); - // we need to recreate them on next createFeature; otherwise - // they'll reference destroyed features - delete(handler.handlers.drag); - delete(handler.handlers.feature); - this.editControl.deactivate(); + + this.viewMode(); $("geom_data").value = this.wkt.write(new OpenLayers.Feature.Vector(line)); + if (this.mode === "edit" && typeof gLoggedInfo.pathid !== "undefined") { + $("geomform").setAttribute("action", "path/" + gLoggedInfo.pathid.toString() + '/update'); + } else { + $("geomform").setAttribute("action", "path"); + } this.needsFormResubmit = false; SyjSaveUI.disable.bind(SyjSaveUI).defer(); this.messenger.hide(); return true; }, + viewMode: function() { + var handler = this.editControl.handler; + OpenLayers.Handler.ModifiablePath.prototype.finalize.apply(handler, arguments); + // we need to recreate them on next createFeature; otherwise + // they'll reference destroyed features + delete(handler.handlers.drag); + delete(handler.handlers.feature); + this.editControl.deactivate(); + }, + editMode: function() { var components, point0, point, pixels, pixel, idx; @@ -349,15 +363,19 @@ var SYJView = { } this.editControl.handler.addPoints(pixels); } + this.unsavedRoute = { + features: this.viewLayer.features.invoke('clone'), + title: $("geom_title").value + }; } this.viewLayer.destroyFeatures(); - SyjEditUI.hide(); + SYJDataUi.editmode(); if (this.editControl.handler.realPoints && this.editControl.handler.realPoints.length >= 2) { - SyjSaveUI.show().disableSubmit(); + SyjSaveUI.disableSubmit(); } else { - SyjSaveUI.show().disable(); + SyjSaveUI.disable(); } }, @@ -371,10 +389,13 @@ var SYJView = { this.editControl = new OpenLayers.Control.DrawFeature(new OpenLayers.Layer.Vector(), OpenLayers.Handler.SyjModifiablePath, { callbacks: { modify: function(f, line) { + if (!SYJView.unsavedRoute) { + SYJView.unsavedRoute = {}; + } if (this.handler.realPoints.length < 2) { - SyjSaveUI.show().disable(); + SyjSaveUI.disable(); } else { - SyjSaveUI.show().enable(); + SyjSaveUI.enable(); } } }, @@ -391,17 +412,40 @@ var SYJView = { styles = this.editControl.handler.layerOptions.styleMap.styles; styles.select = styles.select_for_canvas; } + new CloseBtn($("geomform"), { + style : { + marginRight: "-40px", + marginTop: "-20px" + }, + callback: function(form) { + this.viewMode(); + this.mode = 'view'; + SYJDataUi.viewmode(); + this.messenger.hide(); + + if (this.unsavedRoute && typeof this.unsavedRoute.features !== "undefined") { + this.viewLayer.addFeatures(this.unsavedRoute.features); + } + if (this.unsavedRoute && typeof this.unsavedRoute.title !== "undefined") { + $("geom_title").value = this.unsavedRoute.title; + } else { + $("geom_title").value = ""; + } + this.unsavedRoute = null; + }.bind(this) + }); }, saveSuccess: function(transport) { + this.unsavedRoute = null; + if (transport.responseJSON && (typeof transport.responseJSON.redirect === "string")) { location = transport.responseJSON.redirect; return; } this.messenger.setMessage(SyjStrings.saveSuccess, "success"); - SyjSaveUI.hide(); - SyjEditUI.show(); + SYJDataUi.viewmode(); document.title = $('geom_title').value; }, @@ -555,13 +599,15 @@ var SYJUserClass = Class.create(SYJModalClass, { $$("#user_termsofuse_anchor, #geom_termsofuse_anchor").invoke('observe', "click", function(evt) { if (!this.toubox) { - $("termsofusearea").show(); - $("termsofuseiframe").setAttribute("src", evt.target.href); this.toubox = new SimpleBox($("termsofusearea"), { closeMethods: ["onescapekey", "onouterclick", "onbutton"] }); } this.toubox.show(); + if (!$("termsofuseiframe").getAttribute("src")) { + $("termsofusearea").show(); + $("termsofuseiframe").setAttribute("src", evt.target.href); + } evt.stop(); }.bindAsEventListener(this)); @@ -571,6 +617,19 @@ var SYJUserClass = Class.create(SYJModalClass, { evt.stop(); }.bindAsEventListener(this)); + $("user_pseudo-desc").hide(); + $("user_pseudo").observe('contentchange', function(evt) { + var value = evt.target.value; + PseudoChecker.reset(); + if (value && !(value.match(/^[a-zA-Z0-9_.]+$/))) { + $("user_pseudo-desc").show().setMessageStatus("warn"); + } else { + $("user_pseudo-desc").hide(); + } + }).timedobserve(function() { + PseudoChecker.check(); + }); + $("user_password").observe('contentchange', function(evt) { if (evt.target.value.length < 6) { $("user_password-desc").setMessageStatus("warn"); @@ -579,27 +638,24 @@ var SYJUserClass = Class.create(SYJModalClass, { } }.bindAsEventListener(this)); - $("account-info").hide(); - $("account-info-bullet").observe('click', function(evt) { - var elt = $("account-info"); - if (elt.visible()) { - evt.target.src = "icons/bullet_arrow_right.png"; - elt.hide(); - } else { - evt.target.src = "icons/bullet_arrow_down.png"; - elt.show(); - } - evt.stop(); - }); + $('account-create-anchor').insert({after: new Toggler('account-info').element}); }, presubmit: function() { + this.messenger.hide(); + PseudoChecker.reset(); if (!(this.checkNotEmpty("user_pseudo", SyjStrings.userEmptyWarn))) { return false; } if (!($("user_pseudo").value.match(/^[a-zA-Z0-9_.]+$/))) { - this.messenger.setMessage(SyjStrings.invalidPseudo, "warn"); + $("user_pseudo-desc").show().setMessageStatus("warn"); + $("user_pseudo").highlight('#F08080').activate(); + return false; + } + + if (PseudoChecker.exists[$("user_pseudo").value]) { + PseudoChecker.availableMessage(false); $("user_pseudo").highlight('#F08080').activate(); return false; } @@ -636,7 +692,7 @@ var SYJUserClass = Class.create(SYJModalClass, { }, success: function(transport) { - loginMgr.login(); + LoginMgr.login(); SYJView.messenger.setMessage(SyjStrings.userSuccess, "success"); this.modalbox.hide(); if (SYJView.needsFormResubmit) { @@ -664,7 +720,7 @@ var SYJUserClass = Class.create(SYJModalClass, { focusInput = $("user_email"); break; case "uniquepseudo": - message = SyjStrings.uniqueUserError; + PseudoChecker.availableMessage(false); focusInput = $("user_pseudo"); break; case "uniqueemail": @@ -676,11 +732,11 @@ var SYJUserClass = Class.create(SYJModalClass, { break; } - if (message) { - this.messenger.setMessage(message, "error"); - if (focusInput) { - focusInput.highlight('#F08080').activate(); + if (focusInput) { + if (message) { + this.messenger.setMessage(message, "error"); } + focusInput.highlight('#F08080').activate(); return; } @@ -697,6 +753,7 @@ var SYJLoginClass = Class.create(SYJModalClass, { }, presubmit: function() { + this.messenger.hide(); if (!(this.checkNotEmpty("login_user", SyjStrings.userEmptyWarn))) { return false; } @@ -706,11 +763,21 @@ var SYJLoginClass = Class.create(SYJModalClass, { }, success: function(transport) { - if (transport.responseText === "1") { - loginMgr.login(true); - } else { - loginMgr.login(); + if (!transport.responseJSON || + typeof transport.responseJSON.iscreator !== "boolean" || + typeof transport.responseJSON.pseudo !== "string" + ) { + this.messenger.setMessage(SyjStrings.unknownError, "error"); + return; } + LoginMgr.login(transport.responseJSON.iscreator); + $$('.logged-pseudo').each(function(elt) { + $A(elt.childNodes).filter(function(node) { + return (node.nodeType === 3 || node.tagName.toLowerCase() === 'br'); + }).each(function(node) { + node.nodeValue = node.nodeValue.replace('%s', transport.responseJSON.pseudo); + }); + }); SYJView.messenger.setMessage(SyjStrings.loginSuccess, "success"); this.modalbox.hide(); if (SYJView.needsFormResubmit) { @@ -767,7 +834,7 @@ var SYJNewpwdClass = Class.create(SYJModalClass, { }); var SYJNewpwd = new SYJNewpwdClass(); -var loginMgr = Object.extend(gLoggedInfo, { +var LoginMgr = Object.extend(gLoggedInfo, { controlsdeck: null, updateUI: function() { @@ -784,10 +851,12 @@ var loginMgr = Object.extend(gLoggedInfo, { $$(".logged-show").invoke('hide'); } - if (this.iscreator) { - $("data_controls").show(); - } else { - $("data_controls").hide(); + if ($("edit-btn")) { + if (this.iscreator && SYJView.mode === 'view') { + $("edit-btn").show(); + } else { + $("edit-btn").hide(); + } } }, @@ -800,10 +869,112 @@ var loginMgr = Object.extend(gLoggedInfo, { } }); +var PseudoChecker = { + req: null, + exists: {}, + currentvalue: null, + messageelt: null, + throbber: null, + + message: function(str, status, throbber) { + var row; + if (!this.messageelt) { + row = new Element('tr'); + // we can't use row.update('
') + // because gecko would mangle the s + row.insert(new Element('td')) + .insert((new Element('td')).update(new Element('div'))); + + $("user_pseudo").up('tr').insert({after: row}); + this.messageelt = new Element('span'); + this.throbber = new Element("img", { src: "icons/pseudo-throbber.gif"}); + row.down('div').insert(this.throbber).insert(this.messageelt); + } + if (throbber) { + this.throbber.show(); + } else { + this.throbber.hide(); + } + this.messageelt.up().setStyle({visibility: ''}); + this.messageelt.className = status; + this.messageelt.update(str); + }, + + availableMessage: function(available) { + var message = available ? SyjStrings.availablePseudo: SyjStrings.unavailablePseudo, + status = available ? "success": "warn"; + this.message(message, status, false); + }, + + reset: function() { + if (this.req) { + this.req.abort(); + this.req = this.currentvalue = null; + } + if (this.messageelt) { + this.messageelt.up().setStyle({visibility: 'hidden'}); + } + }, + + check: function() { + var pseudo = $("user_pseudo").value; + + this.reset(); + + if (!pseudo || !(pseudo.match(/^[a-zA-Z0-9_.]+$/))) { + return; + } + + if (typeof this.exists[pseudo] === "boolean") { + this.reset(); + this.availableMessage(!this.exists[pseudo]); + return; + } + + this.message(SyjStrings.pseudoChecking, "", true); + + this.currentvalue = pseudo; + this.req = new Ajax.TimedRequest('userexists/' + encodeURIComponent(pseudo), 20, { + onFailure: this.failure.bind(this), + onSuccess: this.success.bind(this) + }); + }, + + failure: function(transport) { + var httpCode = 0, value = this.currentvalue; + + if (transport) { + httpCode = transport.getStatus(); + } + this.reset(); + if (httpCode === 404) { + this.exists[value] = false; + this.availableMessage(true); + } + + }, + + success: function(transport) { + var httpCode = transport.getStatus(), value = this.currentvalue; + this.reset(); + this.exists[value] = true; + this.availableMessage(false); + } +}; + + document.observe("dom:loaded", function() { SYJLogin.init(); SYJUser.init(); + SYJDataUi.viewmode(); SYJView.init(); SYJNewpwd.init(); - loginMgr.updateUI(); + LoginMgr.updateUI(); }); +window.onbeforeunload = function() { + if (SYJView.unsavedRoute) { + return SyjStrings.unsavedConfirmExit; + } else { + return undefined; + } +};