]> dev.renevier.net Git - syj.git/commitdiff
ajax for account creation to known if a pseudo is available
authorarno <arno@renevier.net>
Thu, 12 Aug 2010 13:20:03 +0000 (15:20 +0200)
committerarno <arno@renevier.net>
Fri, 13 Aug 2010 11:55:04 +0000 (13:55 +0200)
COPYING.TXT
application/configs/application.ini
application/controllers/IdxController.php
application/controllers/UserController.php
application/forms/User.php
application/languages/lang_en.po
application/languages/lang_fr.po
application/models/UserMapper.php
public/icons/pseudo-throbber.gif [new file with mode: 0644]
public/js/syj.js
public/js/utils.js

index 5106604cc429dc39671a46fac9ca3f753f938847..b8188b7eb877708de5f339868b44ccd90f544d42 100644 (file)
@@ -7,6 +7,9 @@
   Creative Commons Attribution 2.5 License. See
   http://www.famfamfam.com/lab/icons/silk/ for more informations.
 
+- pseudo-throbber.gif files has been generated with http://ajaxload.info/
+  generator and is free for use.
+
 
 
 ===============================================================================
index 5c375932e0c12f42c255530ef7831cac26a6eea7..d6158be036b7914b70c94a9202bbb7eb7a121b5a 100644 (file)
@@ -66,6 +66,10 @@ resources.router.routes.login.defaults.action = "login"
 resources.router.routes.user.route = "user/"
 resources.router.routes.user.defaults.controller = "user"
 resources.router.routes.user.defaults.action = "user"
+; userexists/
+resources.router.routes.userexists.route = "userexists/:name"
+resources.router.routes.userexists.defaults.controller = "user"
+resources.router.routes.userexists.defaults.action = "exists"
 ; logout/
 resources.router.routes.logout.route = "logout/"
 resources.router.routes.logout.defaults.controller = "login"
index 527f77e9a7a555956daa2f865eb0d7ef8229a37f..9dc4300fbd634c2de2c77ea6e9d776b51d9eae90 100644 (file)
@@ -97,14 +97,15 @@ class IdxController extends Zend_Controller_Action
             'acceptTermsofuseWarn' => __("You must accept terms of use"),
             'emailEmptyWarn' => __("you must enter an email"),
             'emailInvalidWarn' => __("invalid email"),
-            'invalidPseudo' => __("pseudo must only contain letters, digits, dots or underscores"),
-            'uniqueUserError' => __("unavailable pseudo"),
             'uniqueEmailError' => __("an user is already registered with this email"),
             'userSuccess' => __("Account created"),
             'newpwdSuccess' => __("A link to reset your password has been emailed to you"),
             'canResubmit' => __("Now, you can retry to save"),
             'routeBy' => __("route by"),
-            'osmAttribution' => __("Map by <a href='http://openstreetmap.org/'>OpenStreetMap</a>")
+            'osmAttribution' => __("Map by <a href='http://openstreetmap.org/'>OpenStreetMap</a>"),
+            'pseudoChecking' => __("checking availibilty"),
+            'availablePseudo' => __("available pseudo"),
+            'unavailablePseudo' => __("unavailable pseudo"),
             );
     }
 
index 2bd41d3106b78bbecf9c7d03c6001e255ba853a8..f802b16b66d85eba8c80dd595eebf8d71a4dd60d 100644 (file)
@@ -5,6 +5,21 @@
 class UserController extends Zend_Controller_Action
 {
 
+    public function existsAction() {
+        $name = $this->getRequest()->getUserParam('name');
+
+        $userMapper = new Syj_Model_UserMapper();
+        $user = new Syj_Model_User();
+
+        if ($userMapper->findByPseudo($name, $user)) {
+            $this->_helper->SyjApi->setCode(200);
+        } else {
+            // opera needs some body content with 404 code, otherwise, it
+            // reports a xmlhttprequest.status of 0
+            $this->_helper->SyjApi->setCode(404)->setBody(' ');
+        }
+    }
+
     public function userAction() {
         $formData = $this->_helper->SyjPostData->getPostData('Syj_Form_User');
 
index 40bd5185a9764885cdc088bc5fb03b8d7ee513c0..34a5608701348a72385aba9821a65d4de0753fff 100644 (file)
@@ -7,9 +7,11 @@ class Syj_Form_User extends Syj_Form_TableAbstract
     public function init() {
         $translator = $this->getTranslator();
 
+        $desc = $translator->translate("only letters, numbers, underscores or dots");
         $name = array('Text', 'user_pseudo', array(
             'label' => __("user name"),
-            'attribs' => array('maxlength' => '20'),
+            'attribs' => array('maxlength' => '20', 'autocomplete' => 'off'),
+            'description' => $desc,
             'validators' => array(new Zend_Validate_StringLength(0, 20),
                                  new Zend_Validate_Regex('/^[a-zA-Z0-9_\.]+$/')),
             'required' => true
index 298af293e57269c0e2a990528c7a0a3b386759b5..fed1b8b965f49f6b88735100970f21f4ea0262e2 100644 (file)
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: syj\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-08-11 21:44+0200\n"
+"POT-Creation-Date: 2010-08-12 14:16+0200\n"
 "PO-Revision-Date: \n"
 "Last-Translator: arno <arno@renevier.net>\n"
 "Language-Team: arno <arno@renevier.net>\n"
@@ -110,7 +110,7 @@ msgid "Sources of the software running the website are <a href=\"http://dev.rene
 msgstr "Sources of the software running the website are <a href=\"http://dev.renevier.net/?p=syj.git\">publicly available</a> under a agpl license. The map used to display the routes comes from <a href=\"http://www.openstreetmap.org/\">openstreetmap</a>."
 
 #: application/views/scripts/newpwd/success.phtml:4
-#: application/controllers/IdxController.php:103
+#: application/controllers/IdxController.php:101
 msgid "A link to reset your password has been emailed to you"
 msgstr "A link to reset your password has been emailed to you"
 
@@ -415,7 +415,7 @@ msgstr "Oups, something went wrong"
 #: application/controllers/TermsofuseController.php:12
 #: application/layouts/scripts/footer.phtml:85
 #: application/forms/Geom.php:24
-#: application/forms/User.php:41
+#: application/forms/User.php:43
 msgid "terms of use"
 msgstr "terms of use"
 
@@ -467,7 +467,7 @@ msgid "Wrong password"
 msgstr "Wrong password"
 
 #: application/controllers/AccountController.php:44
-#: application/controllers/IdxController.php:101
+#: application/controllers/IdxController.php:99
 msgid "an user is already registered with this email"
 msgstr "an user is already registered with this email"
 
@@ -479,7 +479,7 @@ msgstr "Password do not match"
 
 #: application/controllers/AccountController.php:73
 #: application/forms/Account.php:33
-#: application/forms/User.php:18
+#: application/forms/User.php:20
 #, php-format
 msgid "At least %d characters"
 msgstr "At least %d characters"
@@ -520,30 +520,34 @@ msgstr "you must enter an email"
 msgid "invalid email"
 msgstr "invalid email"
 
-#: application/controllers/IdxController.php:99
-msgid "pseudo must only contain letters, digits, dots or underscores"
-msgstr "pseudo must only contain letters, digits, dots or underscores"
-
 #: application/controllers/IdxController.php:100
-msgid "unavailable pseudo"
-msgstr "unavailable pseudo"
-
-#: application/controllers/IdxController.php:102
 msgid "Account created"
 msgstr "Account created"
 
-#: application/controllers/IdxController.php:104
+#: application/controllers/IdxController.php:102
 msgid "Now, you can retry to save"
 msgstr "Now, you can retry to save"
 
-#: application/controllers/IdxController.php:105
+#: application/controllers/IdxController.php:103
 msgid "route by"
 msgstr "route by"
 
-#: application/controllers/IdxController.php:106
+#: application/controllers/IdxController.php:104
 msgid "Map by <a href='http://openstreetmap.org/'>OpenStreetMap</a>"
 msgstr "Map by <a href='http://openstreetmap.org/'>OpenStreetMap</a>"
 
+#: application/controllers/IdxController.php:105
+msgid "checking availibilty"
+msgstr "checking availibilty"
+
+#: application/controllers/IdxController.php:106
+msgid "available pseudo"
+msgstr "available pseudo"
+
+#: application/controllers/IdxController.php:107
+msgid "unavailable pseudo"
+msgstr "unavailable pseudo"
+
 #: application/layouts/scripts/footer.phtml:28
 msgid "contact"
 msgstr "contact"
@@ -554,7 +558,7 @@ msgstr "user"
 
 #: application/forms/Login.php:10
 #: application/forms/Account.php:35
-#: application/forms/User.php:21
+#: application/forms/User.php:23
 msgid "password"
 msgstr "password"
 
@@ -591,7 +595,7 @@ msgid "optional title for this journey"
 msgstr "optional title for this journey"
 
 #: application/forms/Geom.php:25
-#: application/forms/User.php:42
+#: application/forms/User.php:44
 #, php-format
 msgid "I've read and accepted %s"
 msgstr "I've read and accepted %s"
@@ -602,13 +606,13 @@ msgid "save"
 msgstr "save"
 
 #: application/forms/Account.php:27
-#: application/forms/User.php:34
+#: application/forms/User.php:36
 #: application/forms/Newpwd.php:28
 msgid "email"
 msgstr "email"
 
 #: application/forms/Account.php:42
-#: application/forms/User.php:28
+#: application/forms/User.php:30
 msgid "confirm password"
 msgstr "confirm password"
 
@@ -620,15 +624,19 @@ msgstr "current password"
 msgid "modify my informations"
 msgstr "modify my informations"
 
-#: application/forms/User.php:11
+#: application/forms/User.php:10
+msgid "only letters, numbers, underscores or dots"
+msgstr "only letters, numbers, underscores or dots"
+
+#: application/forms/User.php:12
 msgid "user name"
 msgstr "user name"
 
-#: application/forms/User.php:35
+#: application/forms/User.php:37
 msgid "After creating your account, you will receive a confirmation email. You have 7 days to confirm otherwise, your account and your routes will all be deleted."
 msgstr "After creating your account, you will receive a confirmation email. You have 7 days to confirm otherwise, your account and your routes will all be deleted."
 
-#: application/forms/User.php:54
+#: application/forms/User.php:56
 msgid "create account"
 msgstr "create account"
 
@@ -659,6 +667,12 @@ msgstr "Someone, probably you, has registered an account %s with email address %
 msgid "To cancel account creation, press following button. The account and all its data will be deleted."
 msgstr "To cancel account creation, press following button. The account and all its data will be deleted."
 
+#~ msgid "pseudo available"
+#~ msgstr "pseudo available"
+#~ msgid "pseudo not available"
+#~ msgstr "pseudo not available"
+#~ msgid "pseudo must only contain letters, digits, dots or underscores"
+#~ msgstr "pseudo must only contain letters, digits, dots or underscores"
 #~ msgid "route has been deleted from the server."
 #~ msgstr "route has been deleted from the server."
 #~ msgid "You need to login before retrying to save"
index 37c6d6282e01ebe1a0057ea228433a19b27c9526..541112dca685bca5e00d329a19eb0e7cdbd9c55f 100644 (file)
@@ -2,7 +2,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: syj\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2010-08-11 21:44+0200\n"
+"POT-Creation-Date: 2010-08-12 14:16+0200\n"
 "PO-Revision-Date: \n"
 "Last-Translator: arno <arno@renevier.net>\n"
 "Language-Team: arno <arno@renevier.net>\n"
@@ -110,7 +110,7 @@ msgid "Sources of the software running the website are <a href=\"http://dev.rene
 msgstr "Les sources du logiciel qui fait tourner le site web sont <a href=\"http://dev.renevier.net/?p=syj.git\">disponibles publiquement</a> sous une licence agpl. La carte utilisée pour l'affichage des itinéraires vient d'<a href=\"http://www.openstreetmap.org/\">openstreetmap</a>."
 
 #: application/views/scripts/newpwd/success.phtml:4
-#: application/controllers/IdxController.php:103
+#: application/controllers/IdxController.php:101
 msgid "A link to reset your password has been emailed to you"
 msgstr "Un email contenant un lien pour réinitialiser votre mot de passe vous a été envoyé"
 
@@ -417,7 +417,7 @@ msgstr "Oups, il y a eu un souci"
 #: application/controllers/TermsofuseController.php:12
 #: application/layouts/scripts/footer.phtml:85
 #: application/forms/Geom.php:24
-#: application/forms/User.php:41
+#: application/forms/User.php:43
 msgid "terms of use"
 msgstr "conditions d'utilisation"
 
@@ -469,7 +469,7 @@ msgid "Wrong password"
 msgstr "Mauvais mot de passe"
 
 #: application/controllers/AccountController.php:44
-#: application/controllers/IdxController.php:101
+#: application/controllers/IdxController.php:99
 msgid "an user is already registered with this email"
 msgstr "il y'a déjà un utilisateur enregistré avec cet email"
 
@@ -481,7 +481,7 @@ msgstr "Les mots de passe ne correspondent pas"
 
 #: application/controllers/AccountController.php:73
 #: application/forms/Account.php:33
-#: application/forms/User.php:18
+#: application/forms/User.php:20
 #, php-format
 msgid "At least %d characters"
 msgstr "Au moins %d caractères"
@@ -522,30 +522,34 @@ msgstr "vous devez entrer un email"
 msgid "invalid email"
 msgstr "email invalide"
 
-#: application/controllers/IdxController.php:99
-msgid "pseudo must only contain letters, digits, dots or underscores"
-msgstr "le pseudo ne peut contenir que des lettres, des chiffres, des points ou des soulignés"
-
 #: application/controllers/IdxController.php:100
-msgid "unavailable pseudo"
-msgstr "pseudo non disponible"
-
-#: application/controllers/IdxController.php:102
 msgid "Account created"
 msgstr "Compte créé"
 
-#: application/controllers/IdxController.php:104
+#: application/controllers/IdxController.php:102
 msgid "Now, you can retry to save"
 msgstr "Maintenant, vous pouvez réessayer de sauvegarder"
 
-#: application/controllers/IdxController.php:105
+#: application/controllers/IdxController.php:103
 msgid "route by"
 msgstr "tracé par"
 
-#: application/controllers/IdxController.php:106
+#: application/controllers/IdxController.php:104
 msgid "Map by <a href='http://openstreetmap.org/'>OpenStreetMap</a>"
 msgstr "Carte par <a href='http://openstreetmap.org/'>OpenStreetMap</a>"
 
+#: application/controllers/IdxController.php:105
+msgid "checking availibilty"
+msgstr "vérification de la disponibilité"
+
+#: application/controllers/IdxController.php:106
+msgid "available pseudo"
+msgstr "pseudo disponible"
+
+#: application/controllers/IdxController.php:107
+msgid "unavailable pseudo"
+msgstr "pseudo non disponible"
+
 #: application/layouts/scripts/footer.phtml:28
 msgid "contact"
 msgstr "contact"
@@ -556,7 +560,7 @@ msgstr "utilisateur"
 
 #: application/forms/Login.php:10
 #: application/forms/Account.php:35
-#: application/forms/User.php:21
+#: application/forms/User.php:23
 msgid "password"
 msgstr "mot de passe"
 
@@ -593,7 +597,7 @@ msgid "optional title for this journey"
 msgstr "titre facultatif pour ce trajet"
 
 #: application/forms/Geom.php:25
-#: application/forms/User.php:42
+#: application/forms/User.php:44
 #, php-format
 msgid "I've read and accepted %s"
 msgstr "J'ai lu et accepté les %s"
@@ -604,13 +608,13 @@ msgid "save"
 msgstr "enregistrer"
 
 #: application/forms/Account.php:27
-#: application/forms/User.php:34
+#: application/forms/User.php:36
 #: application/forms/Newpwd.php:28
 msgid "email"
 msgstr "email"
 
 #: application/forms/Account.php:42
-#: application/forms/User.php:28
+#: application/forms/User.php:30
 msgid "confirm password"
 msgstr "confirmation du mot de passe"
 
@@ -622,15 +626,19 @@ msgstr "mot de passe actuel"
 msgid "modify my informations"
 msgstr "modifier mes informations"
 
-#: application/forms/User.php:11
+#: application/forms/User.php:10
+msgid "only letters, numbers, underscores or dots"
+msgstr "seulement des lettres, des chiffres, des soulignés ou des points"
+
+#: application/forms/User.php:12
 msgid "user name"
 msgstr "nom d'utilisateur"
 
-#: application/forms/User.php:35
+#: application/forms/User.php:37
 msgid "After creating your account, you will receive a confirmation email. You have 7 days to confirm otherwise, your account and your routes will all be deleted."
 msgstr "Après la création de votre compte, vous recevrez un mail de confirmation. Vous avez 7 jours pour confirmer sinon, votre compte et tous vos tracés seront supprimés."
 
-#: application/forms/User.php:54
+#: application/forms/User.php:56
 msgid "create account"
 msgstr "créer le compte"
 
@@ -661,6 +669,14 @@ msgstr "Quelqu'un, probablement vous, a enregistré un compte %s avec l'adresse
 msgid "To cancel account creation, press following button. The account and all its data will be deleted."
 msgstr "Pour annuler la création du compte, pressez le bouton suivant. Le compte ainsi que toutes ses données seront supprimés."
 
+#~ msgid "pseudo available"
+#~ msgstr "pseudo disponible"
+#~ msgid "pseudo not available"
+#~ msgstr "pseudo non disponible"
+#~ msgid "pseudo must only contain letters, digits, dots or underscores"
+#~ msgstr ""
+#~ "le pseudo ne peut contenir que des lettres, des chiffres, des points ou "
+#~ "des soulignés"
 #~ msgid "You need to login before retrying to save"
 #~ msgstr "Vous devez vous connecter avant de réesayer de sauvegarder"
 #~ msgid "You need to have cookies enabled to login to SYJ"
index 67faea8e20a69f64c303258c8385c0d3de3b6604..3fc84aa237ee4a832855a807b8611350cd52a66e 100644 (file)
@@ -24,6 +24,17 @@ class Syj_Model_UserMapper
         return true;
     }
 
+    public function findByPseudo($pseudo, Syj_Model_User $user) {
+        $table = $this->getDbTable();
+        $select = $table->select()->where('pseudo = ?', (string)$pseudo);
+        $row = $table->fetchRow($select);
+        if (!$row) {
+            return false;
+        }
+        $this->_itemFromRow($user, $row);
+        return true;
+    }
+
     public function findByEmail($email, Syj_Model_User $user) {
         $table = $this->getDbTable();
         $select = $table->select()->where('email = ?', (string)$email);
diff --git a/public/icons/pseudo-throbber.gif b/public/icons/pseudo-throbber.gif
new file mode 100644 (file)
index 0000000..b61abe6
Binary files /dev/null and b/public/icons/pseudo-throbber.gif differ
index 4b7f01d9a39dda1f010856080f130cc806577a0f..44dd2ff6d4aba093b7b363fe6594e7f5ac095553 100644 (file)
@@ -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) {
@@ -299,7 +284,7 @@ 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();
@@ -571,6 +556,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");
@@ -594,12 +592,20 @@ var SYJUserClass = Class.create(SYJModalClass, {
     },
 
     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 +642,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 +670,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 +682,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 +703,7 @@ var SYJLoginClass = Class.create(SYJModalClass, {
     },
 
     presubmit: function() {
+        this.messenger.hide();
         if (!(this.checkNotEmpty("login_user", SyjStrings.userEmptyWarn))) {
             return false;
         }
@@ -707,9 +714,9 @@ var SYJLoginClass = Class.create(SYJModalClass, {
 
     success: function(transport) {
         if (transport.responseText === "1") {
-            loginMgr.login(true);
+            LoginMgr.login(true);
         } else {
-            loginMgr.login();
+            LoginMgr.login();
         }
         SYJView.messenger.setMessage(SyjStrings.loginSuccess, "success");
         this.modalbox.hide();
@@ -767,7 +774,7 @@ var SYJNewpwdClass = Class.create(SYJModalClass, {
 });
 var SYJNewpwd = new SYJNewpwdClass();
 
-var loginMgr = Object.extend(gLoggedInfo, {
+var LoginMgr = Object.extend(gLoggedInfo, {
     controlsdeck: null,
 
     updateUI: function() {
@@ -800,10 +807,104 @@ 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('<td></td><td><div></div></td>')
+            // because gecko would mangle the <td>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();
     SYJView.init();
     SYJNewpwd.init();
-    loginMgr.updateUI();
+    LoginMgr.updateUI();
 });
index b1dd910ccaee06c62f78b0528ddc3716e5670354..f5817d491a2087f3198089e5dad1d0d77bc87a18 100644 (file)
@@ -85,8 +85,12 @@ Ajax.TimedRequest = Class.create(Ajax.Request, {
 
     initialize: function($super, url, delay, options) {
         this.delay = delay;
+        if (!options) {
+            options = {};
+        }
 
-        options.onSuccess = options.onSuccess.wrap(function(proceed, transport, json) {
+        options.onSuccess = options.onSuccess &&
+            options.onSuccess.wrap(function(proceed, transport, json) {
             if (this.timeout) {
                 window.clearTimeout(this.timeout);
                 this.timeout = null;
@@ -98,7 +102,8 @@ Ajax.TimedRequest = Class.create(Ajax.Request, {
             }
         }).bind(this);
 
-        options.onFailure = options.onFailure.wrap(function(proceed, transport, json) {
+        options.onFailure = options.onFailure &&
+            options.onFailure.wrap(function(proceed, transport, json) {
             if (this.timeout) {
                 window.clearTimeout(this.timeout);
                 this.timeout = null;
@@ -111,7 +116,9 @@ Ajax.TimedRequest = Class.create(Ajax.Request, {
 
     request: function($super, url) {
         this.timeout = (function() {
-            this.options.onFailure(null);
+            if (this.options.onFailure) {
+                this.options.onFailure(null);
+            }
             this.abort();
         }).bind(this).delay(this.delay);
         $super(url);
@@ -223,6 +230,52 @@ Element.addMethods(['input', 'textarea'], {
             after: new Element("div", {className: 'error'}).update(errorMessage)
         });
         return false;
+    },
+
+    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);
+    }),
+
+    timedobserve: function(element, callback, delay) {
+        var timeout = null, initialvalue = element.value;
+
+        if (typeof delay !== "number") {
+            delay = 0.5;
+        }
+        delay = delay * 1000;
+
+        var canceltimer = function() {
+            if (timeout) {
+                clearTimeout(timeout);
+                timeout = null;
+            }
+        };
+        var resettimer = function() {
+            canceltimer();
+            timeout = setTimeout(triggercallback, delay);
+        };
+        var triggercallback = function() {
+            canceltimer();
+            if (initialvalue !== element.value) {
+                initialvalue = element.value;
+                callback.call(element);
+            }
+        };
+
+        element.observe('blur', triggercallback).
+             observe('keyup', resettimer).
+             observe('paste', resettimer);
+        return element;
     }
 });