X-Git-Url: https://dev.renevier.net/?p=syj.git;a=blobdiff_plain;f=public%2Fjs%2Fsyj.js;h=8f5f509020fd0f6251055213aa3d050169f963fe;hp=e32bc06bc5d45942308a0364fee384f09e09a7de;hb=7504b7ccb77a798b20f4dbb003a90bcaee702124;hpb=549a86ba5724503f5a7768ed87008ab1e2cb5921 diff --git a/public/js/syj.js b/public/js/syj.js index e32bc06..8f5f509 100644 --- a/public/js/syj.js +++ b/public/js/syj.js @@ -1,26 +1,15 @@ -/* This file is part of Syj, Copyright (c) 2010 Arnaud Renevier, +/* This file is part of Syj, Copyright (c) 2010-2011 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); - }) -}); + +"use strict"; // avoid openlayers alerts OpenLayers.Console.userError = function(error) { SYJView.messenger.setMessage(error, "error"); }; +OpenLayers.Layer.Vector.prototype.renderers = ["SVG2", "VML", "Canvas"]; + var SyjSaveUI = { status: "unknown", @@ -29,18 +18,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; @@ -48,7 +25,7 @@ var SyjSaveUI = { this.enableSubmit(); $("geom_title").disabled = false; $("geom_title").activate(); - $("geomform").removeClassName("disabled"); + $$("#geom_accept_container, #geom_title_container").invoke('removeClassName', "disabled"); this.status = "enabled"; return this; }, @@ -60,13 +37,14 @@ var SyjSaveUI = { this.disableSubmit(); $("geom_title").blur(); $("geom_title").disabled = true; - $("geomform").addClassName("disabled"); + $$("#geom_accept_container, #geom_title_container").invoke('addClassName', "disabled"); this.status = "disabled"; return this; }, enableSubmit: function() { $("geom_submit").disabled = false; + $("geom_accept").disabled = false; this.status = "partial"; return this; }, @@ -74,23 +52,92 @@ 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; - }, +var SYJPathLength = (function(){ + return { + update: function() { + var pathLength = 0, unit; + if (SYJView.mode === 'view') { + if (SYJView.viewLayer.features.length) { + pathLength = SYJView.viewLayer.features[0].geometry.getGeodesicLength(Mercator); + } + } else { + pathLength = SYJView.editControl.handler.line.geometry.getGeodesicLength(Mercator); + } - show: function() { - $("edit-btn").show(); - return this; - } -}; + if (pathLength === 0) { + $("path-length").hide(); + return; + } + $("path-length").show(); + + if (pathLength < 1000) { + // precision: 1 cm + pathLength = Math.round(pathLength * 100) / 100; + unit = 'm'; + } else { + // precision: 1 m + pathLength = Math.round(pathLength) / 1000; + unit = 'km'; + } + $("path-length-content").update(pathLength + ' ' + unit); + } + }; +}()); + +var SYJDataUi = (function() { + var deck = null, + infotoggler = null, + getdeck = function() { + if (!deck) { + deck = new Deck("data_controls"); + } + return deck; + }, + getinfotoggler = function() { + if (!infotoggler) { + infotoggler = new Toggler('path-infos-content'); + $("path-infos-toggler").insert({bottom: infotoggler.element}); + var anchor = $("path-infos-anchor"); + var parent = anchor.up('.menu-item'); + if (parent) { + anchor = parent; + } + anchor.observe('click', function(evt) { + evt.stop(); + infotoggler.toggle(evt); + }); + document.observe('toggler:open', function(evt) { + if (evt.memo === infotoggler) { + // XXX: update informations + } + }); + } + return infotoggler; + }; + return { + viewmode: function() { + getdeck().setIndex(0); + if ($("path-infos")) { + getinfotoggler(); + getinfotoggler().close(); + $("path-infos").show(); + } + }, + editmode: function() { + getdeck().setIndex(1); + if ($("path-infos")) { + $("path-infos").hide(); + } + } + }; +}()); OpenLayers.Handler.SyjModifiablePath = OpenLayers.Class(OpenLayers.Handler.ModifiablePath, { mouseup: function(evt) { @@ -225,9 +272,11 @@ 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 = null, hidemessenger; + var externalGraphic, baseURL, baseLayer, layerOptions, hidemessenger; // is svg context, opera does not resolve links with base element is svg context externalGraphic = styleMap.edit.styles.select.defaultStyle.externalGraphic; @@ -243,29 +292,54 @@ var SYJView = { theme: null }); - baseLayer = new OpenLayers.Layer.OSM("OSM", null, { wrapDateLine: true , attribution: SyjStrings.osmAttribution }); + baseLayer = new OpenLayers.Layer.OSM("OSM", [ + 'http://a.tile.openstreetmap.org/${z}/${x}/${y}.png', + 'http://b.tile.openstreetmap.org/${z}/${x}/${y}.png', + 'http://c.tile.openstreetmap.org/${z}/${x}/${y}.png'], + { attribution: SyjStrings.osmAttribution }); 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.clearMessages(); + this.editMode(); + this.mode = 'edit'; + }.bind(this)); + } + + if ($("create-btn")) { + $("create-btn").observe('click', function() { + $("geom_submit").value = SyjStrings.createAction; + this.messenger.clearMessages(); + 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.clearMessages(); + 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,36 +352,132 @@ var SYJView = { this.messenger.hide(); } - extent = null; - if ($("geom_data").value) { - this.viewLayer.addFeatures([this.wkt.read($("geom_data").value)]); - extent = this.viewLayer.getDataExtent(); + if (typeof gInitialGeom !== "undefined" && typeof gInitialGeom.data !== "undefined") { + this.viewLayer.addFeatures([this.wkt.read(gInitialGeom.data)]); // XXX: ie has not guessed height of map main div yet during map // initialisation. Now, it will read it correctly. this.map.updateSize(); + this.map.zoomToExtent(this.viewLayer.getDataExtent()); } else { - extent = new OpenLayers.Bounds(gMaxExtent.minlon, gMaxExtent.minlat, gMaxExtent.maxlon, gMaxExtent.maxlat) - .transform(WGS84, Mercator); + this.initMaPos(gInitialPos); } - this.map.zoomToExtent(extent); + + $("map-overlay").hide(); + $("geom_upload").observe('change', function(evt) { + var file = null, reader = null, readerror = null; + if (window.FileList && window.FileReader) { + file = evt.target.files[0]; + reader = new FileReader(); + readerror = function() { + this.messenger.setMessage(SyjStrings.uploadFileError, "warn"); + }.bind(this); + reader.onload = function(evt) { + var data = null, results = null, engine = null, vector = null, i = 0, format = null, formats = ['KML', 'GPX', 'GeoJSON']; + + $("geom_upload_container").removeClassName("disabled"); + $("geom_upload").disabled = false; + if (evt.error) { + readerror(); + return; + } + data = evt.target.result; + + for (i = 0; i < formats.length; i++) { + format = formats[i]; + engine = new OpenLayers.Format[format]({ internalProjection: Mercator, externalProjection: WGS84 }); + try { + results = engine.read(data); + } catch(e) { + } + if (results && results.length) { + break; + } + } + if (!results || !results.length) { + readerror(); + return; + } + + vector = results[0]; + if (vector.geometry.CLASS_NAME !== "OpenLayers.Geometry.LineString") { + readerror(); + return; + } + // merge linestrings for gpx containting multiple trkseg elements. + if (format === 'GPX') { + for (i = 1; i < results.length; i++) { + vector.geometry.addComponents(results[i].geometry.components); + } + } + this.viewLayer.addFeatures([vector]); + this.map.zoomToExtent(this.viewLayer.getDataExtent()); + + if ($("edit-btn")) { + $("edit-btn").click(); + } else if ($("create-btn")) { + $("create-btn").click(); + } + + if (this.editControl.handler.realPoints.length < 2) { + SyjSaveUI.disable(); + } else { + SyjSaveUI.enable(); + } + + if (vector.data && vector.data.name) { + $("geom_title").value = vector.data.name; + } + }.bind(this); + $("geom_upload_container").addClassName("disabled"); + $("geom_upload").disabled = true; + reader.readAsText(file); + return; + } + $("map-overlay").show(); + SyjSaveUI.enable(); + this.editControl.deactivate(); + }.bind(this)); + document.observe('simplebox:shown', this.observer.bindAsEventListener(this)); + SYJPathLength.update(); + }, + + initMaPos: function (aPos) { + var extent = null, center = null, zoom = 0; + + if (aPos.hasOwnProperty('lon') && aPos.hasOwnProperty('lat') && aPos.hasOwnProperty('zoom')) { + center = new OpenLayers.LonLat(parseFloat(aPos.lon), parseFloat(aPos.lat)).transform(WGS84, Mercator); + zoom = parseInt(aPos.zoom, 10); + } else if (aPos.hasOwnProperty('minlon') && aPos.hasOwnProperty('minlat') + && aPos.hasOwnProperty('maxlon') && aPos.hasOwnProperty('maxlat')) { + extent = new OpenLayers.Bounds(aPos.minlon, aPos.minlat, aPos.maxlon, aPos.maxlat) + .transform(WGS84, Mercator); + } else { + extent = new OpenLayers.Bounds(-160, -70, 160, 70).transform(WGS84, Mercator); + } + + if (extent) { + this.map.zoomToExtent(extent); + } else { + this.map.setCenter(center, zoom); + } }, observer: function(evt) { if (evt.eventName === "simplebox:shown" && evt.memo.element !== $("termsofusearea")) { - this.messenger.hide(); + this.messenger.clearMessages(); } }, 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; @@ -315,19 +485,34 @@ var SYJView = { line.addComponent(realPoints[idx].geometry.clone()); } this.viewLayer.addFeatures(new OpenLayers.Feature.Vector(line)); - handler = this.editControl.handler; + + this.viewMode(); + + if (line.components.length) { + $("geom_data").value = this.wkt.write(new OpenLayers.Feature.Vector(line)); + } else { + $("geom_data").value = ""; + } + + 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.clearMessages(); + 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(); - - $("geom_data").value = this.wkt.write(new OpenLayers.Feature.Vector(line)); - this.needsFormResubmit = false; - SyjSaveUI.disable.bind(SyjSaveUI).defer(); - this.messenger.hide(); - return true; }, editMode: function() { @@ -350,15 +535,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(); } }, @@ -372,12 +561,28 @@ var SYJView = { this.editControl = new OpenLayers.Control.DrawFeature(new OpenLayers.Layer.Vector(), OpenLayers.Handler.SyjModifiablePath, { callbacks: { modify: function(f, line) { - if (this.handler.realPoints.length < 2) { - SyjSaveUI.show().disable(); + SYJPathLength.update(); + + var npoints = this.handler.realPoints.length; + if (npoints === 0) { + $("geom_upload_container").show(); + SYJView.unsavedRoute = null; } else { - SyjSaveUI.show().enable(); + if (!SYJView.unsavedRoute) { + SYJView.unsavedRoute = {}; + } } - } + + if (npoints < 2) { + SyjSaveUI.disable(); + } else { + SyjSaveUI.enable(); + } + }, + create: function(f, line) { + this.messenger.clearMessages(); + $("geom_upload_container").hide(); + }.bind(this) }, handlerOptions: { @@ -395,44 +600,46 @@ var SYJView = { }, saveSuccess: function(transport) { - if (!$("geom_id").value) { - location = "idx/" + transport.responseText; + // server sends and empty response on success. If we get a response, that + // probably means an error or warning has been printed by server. + if (!transport.responseJSON && transport.responseText.length) { + this.saveFailure(null, 500); + return; + } + + 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(); + this.messenger.setMessage(SyjStrings.saveSuccess, "success"); + SYJDataUi.viewmode(); document.title = $('geom_title').value; }, - saveFailure: function(transport) { - var httpCode = 0, message = ""; - - if (transport) { - httpCode = transport.getStatus(); + saveFailure: function(transport, httpCode) { + var message = ""; + if (typeof httpCode === "undefined") { + httpCode = transport? transport.getStatus(): 0; } - message = ""; + switch (httpCode) { case 0: message = SyjStrings.notReachedError; break; case 400: case 404: + message = SyjStrings.requestError; + break; + case 403: + message = ""; + SYJLogin.messenger.setMessage(SyjStrings.loginNeeded, "warn"); + SYJLogin.modalbox.show(); + this.needsFormResubmit = true; + break; case 410: - message = SyjStrings.requestError; // default message - if (transport.responseJSON) { - switch (transport.responseJSON.message) { - case "unreferenced": - message = SyjStrings.unreferencedError; - break; - case "uniquepath": - message = SyjStrings.uniquePathError; - break; - default: - break; - } - } + message = SyjStrings.gonePathError; break; case 500: message = SyjStrings.serverError; @@ -464,7 +671,12 @@ var SYJModalClass = Class.create({ closeMethods: ["onescapekey", "onouterclick", "onbutton"] }); - $(this.type + "_control_anchor").observe("click", function(evt) { + var anchor = $(this.type + '_control_anchor'); + var parent = anchor.up('.menu-item'); + if (parent) { + anchor = parent; + } + anchor.observe("click", function(evt) { this.modalbox.show(); evt.stop(); }.bindAsEventListener(this)); @@ -497,7 +709,7 @@ var SYJModalClass = Class.create({ input = this.area.select('input[type="text"]')[0]; (function () { input.activate(); - }).defer(); + }.defer()); } else { this.modalbox.hide(); } @@ -537,7 +749,7 @@ var SYJModalClass = Class.create({ }, reset: function() { - this.messenger.hide(); + this.messenger.clearMessages(); this.area.select('.message').invoke('setMessageStatus', null); } }); @@ -550,17 +762,27 @@ var SYJUserClass = Class.create(SYJModalClass, { $super(); $("termsofusearea").hide(); - $$("#user_termsofuse_anchor, #geom_termsofuse_anchor").invoke('observe', "click", function(evt) { + var touevt = (function(evt) { + if (evt.type === "keyup" && evt.keyCode !== 32) { // 32 = space + // allow opening box by pressing space + return; + } 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)); + }).bindAsEventListener(this); + + ["click", "keyup"].each(function (evtName) { + $$("#user_termsofuse_anchor, #geom_termsofuse_anchor").invoke('observe', evtName, touevt); + }) $$("#login_area_create > a").invoke('observe', 'click', function(evt) { @@ -568,6 +790,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"); @@ -576,27 +811,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.clearMessages(); + 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; } @@ -633,7 +865,14 @@ var SYJUserClass = Class.create(SYJModalClass, { }, success: function(transport) { - loginMgr.login(); + if (!transport.responseJSON || + typeof transport.responseJSON.pseudo !== "string" + ) { + this.messenger.setMessage(SyjStrings.unknownError, "error"); + return; + } + + LoginMgr.login(transport.responseJSON.pseudo); SYJView.messenger.setMessage(SyjStrings.userSuccess, "success"); this.modalbox.hide(); if (SYJView.needsFormResubmit) { @@ -661,7 +900,7 @@ var SYJUserClass = Class.create(SYJModalClass, { focusInput = $("user_email"); break; case "uniquepseudo": - message = SyjStrings.uniqueUserError; + PseudoChecker.availableMessage(false); focusInput = $("user_pseudo"); break; case "uniqueemail": @@ -673,11 +912,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; } @@ -694,6 +933,7 @@ var SYJLoginClass = Class.create(SYJModalClass, { }, presubmit: function() { + this.messenger.clearMessages(); if (!(this.checkNotEmpty("login_user", SyjStrings.userEmptyWarn))) { return false; } @@ -703,11 +943,15 @@ 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.pseudo, transport.responseJSON.iscreator); + SYJView.messenger.setMessage(SyjStrings.loginSuccess, "success"); this.modalbox.hide(); if (SYJView.needsFormResubmit) { @@ -764,7 +1008,7 @@ var SYJNewpwdClass = Class.create(SYJModalClass, { }); var SYJNewpwd = new SYJNewpwdClass(); -var loginMgr = Object.extend(gLoggedInfo, { +var LoginMgr = Object.extend(gLoggedInfo, { controlsdeck: null, updateUI: function() { @@ -781,26 +1025,283 @@ 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(); + } } }, - login: function(aIsCreator) { + login: function(aPseudo, aIsCreator) { if (typeof aIsCreator === "boolean") { this.iscreator = aIsCreator; } this.logged = true; + $$('.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', aPseudo); + }); + }); this.updateUI(); } }); +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/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); + } +}; + +var Nominatim = (function() { + var presubmit = function() { + var input = $("nominatim-search"); + if (input.value.strip().empty()) { + $("nominatim-message").setMessage(SyjStrings.notEmptyField, "warn"); + input.activate(); + return false; + } + $("nominatim-suggestions").hide(); + $("nominatim-message").hide(); + $("nominatim-throbber").show(); + return true; + }; + + var zoomToExtent = function(bounds) { // we must call map.setCenter with forceZoomChange to true. See ol#2798 + var center = bounds.getCenterLonLat(); + if (this.baseLayer.wrapDateLine) { + var maxExtent = this.getMaxExtent(); + bounds = bounds.clone(); + while (bounds.right < bounds.left) { + bounds.right += maxExtent.getWidth(); + } + center = bounds.getCenterLonLat().wrapDateLine(maxExtent); + } + this.setCenter(center, this.getZoomForExtent(bounds), false, true); + }; + + var success = function(transport) { + $("nominatim-throbber").hide(); + + if (!transport.responseJSON || !transport.responseJSON.length) { + $("nominatim-message").setMessage(SyjStrings.noResult, 'error'); + $("nominatim-search").activate(); + return; + } + + var place = transport.responseJSON[0], + bbox = place.boundingbox; + + if (!bbox || bbox.length !== 4) { + $("nominatim-message").setMessage(SyjStrings.requestError, 'error'); + return; + } + + extent = new OpenLayers.Bounds(bbox[2], bbox[1], bbox[3], bbox[0]).transform(WGS84, Mercator); + zoomToExtent.call(SYJView.map, extent); + + $("nominatim-suggestions-list").update(); + + var clickhandler = function(bbox) { + return function(evt) { + evt.stop(); + var extent = new OpenLayers.Bounds(bbox[2], bbox[1], bbox[3], bbox[0]).transform(WGS84, Mercator); + $("nominatim-suggestions-list").select("li").invoke('removeClassName', 'current'); + evt.target.up('li').addClassName('current'); + SYJView.map.zoomToExtent(extent); + }; + }; + + var i; + for (i = 0; i < transport.responseJSON.length; i++) { + var item = transport.responseJSON[i]; + if (item.display_name && item.boundingbox && item.boundingbox.length === 4) { + var li = new Element("li"); + var anchor = new Element("a", { + href: "", + className: "nominatim-suggestions-link" + }); + + anchor.observe('click', clickhandler(item.boundingbox)); + Element.text(anchor, item.display_name); + + var icon = new Element("img", { + className: "nominatim-suggestions-icon", + src: item.icon || 'icons/world.png' + }); + li.insert(icon).insert(anchor); + $("nominatim-suggestions-list").insert(li); + if ($("nominatim-suggestions-list").childNodes.length >= 6) { + break; + } + } + } + + if ($("nominatim-suggestions-list").childNodes.length > 1) { + var bottomOffset = $('data_controls').measure('height') + 3; + $("nominatim-suggestions").setStyle({ + bottom: (document.viewport.getHeight() - $('data_controls').cumulativeOffset().top + 3).toString() + 'px' + }).show(); + $("nominatim-suggestions-list").select("li:first-child")[0].addClassName('current'); + } else { + $("nominatim-suggestions").hide(); + } + + }; + + var failure = function(transport) { + $("nominatim-throbber").hide(); + + var httpCode = 0, message = SyjStrings.unknownError, input; // default message error + + if (transport) { + httpCode = transport.getStatus(); + } + + switch (httpCode) { + case 0: + message = SyjStrings.notReachedError; + break; + case 400: + case 404: + message = SyjStrings.requestError; + break; + case 500: + message = SyjStrings.serverError; + break; + } + + $("nominatim-message").setMessage(message, 'error'); + }; + + return { + init: function() { + if (!$("nominatim-form")) { + return; + } + $("nominatim-controls").hide(); + $("nominatim-label").observe('click', function(evt) { + $("nominatim-controls").show(); + $("nominatim-search").activate(); + evt.stop(); + }); + + $("nominatim-form").ajaxize({ + presubmit: presubmit, + onSuccess: success, + onFailure: failure + }); + new CloseBtn($("nominatim-suggestions")); + + $$("#nominatim-message, #nominatim-suggestions, #nominatim-throbber").invoke('hide'); + } + }; +}()); + document.observe("dom:loaded", function() { SYJLogin.init(); SYJUser.init(); + SYJDataUi.viewmode(); SYJView.init(); SYJNewpwd.init(); - loginMgr.updateUI(); + LoginMgr.updateUI(); + Nominatim.init(); }); + +window.onbeforeunload = function() { + if (SYJView.unsavedRoute) { + return SyjStrings.unsavedConfirmExit; + } else { + return undefined; + } +};