registration: As-you-type username availability check.

This commit is contained in:
Max Goodman
2012-09-10 14:26:23 -07:00
parent 93a8d567ae
commit ae040dd405
4 changed files with 87 additions and 2 deletions

View File

@@ -147,6 +147,15 @@ class ApiController(RedditController, OAuth2ResourceController):
else:
return {}
@json_validate(user=VUname("user"))
@api_doc(api_section.users, extensions=["json"])
def GET_username_available(self, responder, user):
"""
Check whether a username is available for registration.
"""
if not (responder.has_errors("user", errors.BAD_USERNAME)):
return bool(user)
@validatedForm(VCaptcha(),
name=VRequired('name', errors.NO_NAME),
email=ValidEmails('email', num = 1),

View File

@@ -2149,6 +2149,29 @@ li.searchfacet {
#passform h1 {margin-bottom: 0px}
#passform p {margin-bottom: 5px; font-size: small}
.register-form .name-entry * {
vertical-align: middle;
}
.notice-taken, .notice-available {
display: none;
margin-left: 6px;
line-height: 16px;
}
.register-form.name-taken .notice-taken, .register-form.name-available .notice-available {
display: inline-block;
}
.register-form .name-entry .throbber {
display: none;
margin-left: 5px;
}
.register-form.name-checking .name-entry .throbber {
display: inline-block;
}
/* cover */
.cover {
position: fixed;
@@ -4826,7 +4849,9 @@ dd { margin-left: 20px; }
.icon-menu .reddit-modqueue:before,
.giftgold a:before,
.gold-form h1.goldgift:before,
.users-online:before {
.users-online:before,
.notice-taken:before,
.notice-available:before {
height: 16px;
width: 16px;
display: block;
@@ -4905,6 +4930,18 @@ dd { margin-left: 20px; }
background-image: url(../online.png); /* SPRITE */
}
.notice-taken:before, .notice-available:before {
margin-right: 3px;
}
.notice-taken:before {
background-image: url(../icon-circle-exclamation.png); /* SPRITE */
}
.notice-available:before {
background-image: url(../icon-circle-check.png); /* SPRITE */
}
.linkinfo {
padding: 5px;
border: 1px solid #5f99cf;

View File

@@ -207,8 +207,44 @@ r.ui.LoginForm.prototype = $.extend(new r.ui.Form(), {
r.ui.RegisterForm = function() {
r.ui.Form.apply(this, arguments)
this.checkUsernameDebounced = _.debounce($.proxy(this, 'checkUsername'), 500)
this.$user = this.$el.find('[name="user"]')
this.$user.on('keyup', $.proxy(this, 'usernameChanged'))
}
r.ui.RegisterForm.prototype = $.extend(new r.ui.Form(), {
usernameChanged: function() {
var name = this.$user.val()
if (name == this._priorName) {
return
} else {
this._priorName = name
}
this.$el.find('.error.field-user').hide()
this.$el.removeClass('name-available name-taken')
this.checkUsernameDebounced(name)
this.$el.toggleClass('name-checking', !!name)
},
checkUsername: function(name) {
if (name) {
$.ajax({
url: '/api/username_available.json',
data: {user: name},
success: $.proxy(this, 'displayUsernameStatus'),
complete: $.proxy(function() { this.$el.removeClass('name-checking') }, this)
})
}
},
displayUsernameStatus: function(result) {
if (result.json && result.json.errors) {
this.showErrors(result.json.errors)
} else {
this.$el.addClass(result ? 'name-available' : 'name-taken')
}
},
_submit: function() {
r.login.post(this, 'register', $.proxy(this, 'handleResult'))
},

View File

@@ -62,11 +62,14 @@
%endif
<div>
<ul>
<li>
<li class="name-entry">
<label for="user_${op}">${_('username')}:</label>
<input value="${user}" name="user" id="user_${op}"
type="text" maxlength="20" tabindex="${tabindex}" autofocus />
%if register:
<span class="throbber"></span>
<span class="notice-taken">${_('try another')}</span>
<span class="notice-available">${_('available!')}</span>
${error_field("BAD_USERNAME", "user", kind="span")}
${error_field("USERNAME_TAKEN", "user", kind="span")}
${error_field("USERNAME_TAKEN_DEL", "user", kind="span")}