diff --git a/package.json b/package.json
index 9c2c645ea2..ac72744af4 100644
--- a/package.json
+++ b/package.json
@@ -34,7 +34,8 @@
"react-dom": "^0.14.2",
"react-gemini-scrollbar": "^2.0.1",
"sanitize-html": "^1.11.1",
- "velocity-animate": "^1.2.3"
+ "velocity-animate": "^1.2.3",
+ "velocity-ui-pack": "^1.2.2"
},
"//deps": "The loader packages are here because webpack in a project that depends on us needs them in this package's node_modules folder",
"//depsbuglink": "https://github.com/webpack/webpack/issues/1472",
diff --git a/src/components/structures/login/Registration.js b/src/components/structures/login/Registration.js
index f89d65d740..7b2808c72a 100644
--- a/src/components/structures/login/Registration.js
+++ b/src/components/structures/login/Registration.js
@@ -159,6 +159,15 @@ module.exports = React.createClass({
case "RegistrationForm.ERR_PASSWORD_LENGTH":
errMsg = `Password too short (min ${MIN_PASSWORD_LENGTH}).`;
break;
+ case "RegistrationForm.ERR_EMAIL_INVALID":
+ errMsg = "This doesn't look like a valid email address";
+ break;
+ case "RegistrationForm.ERR_USERNAME_INVALID":
+ errMsg = "User names may only contain letters, numbers, dots, hyphens and underscores.";
+ break;
+ case "RegistrationForm.ERR_USERNAME_BLANK":
+ errMsg = "You need to enter a user name";
+ break;
default:
console.error("Unknown error code: %s", errCode);
errMsg = "An unknown error occurred.";
diff --git a/src/components/views/login/RegistrationForm.js b/src/components/views/login/RegistrationForm.js
index 534464a4ae..d59f6556d7 100644
--- a/src/components/views/login/RegistrationForm.js
+++ b/src/components/views/login/RegistrationForm.js
@@ -17,8 +17,15 @@ limitations under the License.
'use strict';
var React = require('react');
+var Velocity = require('velocity-animate');
+require('velocity-ui-pack');
var sdk = require('../../../index');
+var FIELD_EMAIL = 'field_email';
+var FIELD_USERNAME = 'field_username';
+var FIELD_PASSWORD = 'field_password';
+var FIELD_PASSWORD_CONFIRM = 'field_password_confirm';
+
/**
* A pure UI component which displays a registration form.
*/
@@ -50,31 +57,14 @@ module.exports = React.createClass({
email: this.props.defaultEmail,
username: this.props.defaultUsername,
password: null,
- passwordConfirm: null
+ passwordConfirm: null,
+ fieldValid: {}
};
},
onSubmit: function(ev) {
ev.preventDefault();
- var pwd1 = this.refs.password.value.trim();
- var pwd2 = this.refs.passwordConfirm.value.trim()
-
- var errCode;
- if (!pwd1 || !pwd2) {
- errCode = "RegistrationForm.ERR_PASSWORD_MISSING";
- }
- else if (pwd1 !== pwd2) {
- errCode = "RegistrationForm.ERR_PASSWORD_MISMATCH";
- }
- else if (pwd1.length < this.props.minPasswordLength) {
- errCode = "RegistrationForm.ERR_PASSWORD_LENGTH";
- }
- if (errCode) {
- this.props.onError(errCode);
- return;
- }
-
var promise = this.props.onRegisterClick({
username: this.refs.username.value.trim(),
password: pwd1,
@@ -89,13 +79,110 @@ module.exports = React.createClass({
}
},
+ validateField: function(field_id) {
+ var pwd1 = this.refs.password.value.trim();
+ var pwd2 = this.refs.passwordConfirm.value.trim()
+
+ switch (field_id) {
+ case FIELD_EMAIL:
+ this.markFieldValid(
+ field_id,
+ this.refs.email.value == '' || !!this.refs.email.value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i),
+ "RegistrationForm.ERR_EMAIL_INVALID"
+ );
+ break;
+ case FIELD_USERNAME:
+ // XXX: SPEC-1
+ if (encodeURIComponent(this.refs.username.value) != this.refs.username.value) {
+ this.markFieldValid(
+ field_id,
+ false,
+ "RegistrationForm.ERR_USERNAME_INVALID"
+ );
+ } else if (this.refs.username.value == '') {
+ this.markFieldValid(
+ field_id,
+ false,
+ "RegistrationForm.ERR_USERNAME_BLANK"
+ );
+ } else {
+ this.markFieldValid(field_id, true);
+ }
+ break;
+ case FIELD_PASSWORD:
+ if (pwd1 == '') {
+ this.markFieldValid(
+ field_id,
+ false,
+ "RegistrationForm.ERR_PASSWORD_MISSING"
+ );
+ } else if (pwd1.length < this.props.minPasswordLength) {
+ this.markFieldValid(
+ field_id,
+ false,
+ "RegistrationForm.ERR_PASSWORD_MISSING"
+ );
+ }
+ break;
+ case FIELD_PASSWORD_CONFIRM:
+ if (pwd1 == '') {
+ this.markFieldValid(
+ field_id, false,
+ "RegistrationForm.ERR_PASSWORD_MISSING"
+ );
+ } else if (pwd1 != pwd2) {
+ this.markFieldValid(
+ field_id, false,
+ "RegistrationForm.ERR_PASSWORD_LENGTH"
+ );
+ } else {
+ this.markFieldValid(field_id, true);
+ }
+ break;
+ }
+ },
+
+ markFieldValid: function(field_id, val, error_code) {
+ var fieldValid = this.state.fieldValid;
+ fieldValid[field_id] = val;
+ this.setState({fieldValid: fieldValid});
+ if (!val) {
+ Velocity(this.fieldElementById(field_id), "callout.shake", 300);
+ this.props.onError(error_code);
+ }
+ },
+
+ fieldElementById(field_id) {
+ switch (field_id) {
+ case FIELD_EMAIL:
+ return this.refs.email;
+ case FIELD_USERNAME:
+ return this.refs.username;
+ case FIELD_PASSWORD:
+ return this.refs.password;
+ case FIELD_PASSWORD_CONFIRM:
+ return this.refs.passwordConfirm;
+ }
+ },
+
+ _styleField: function(field_id, baseStyle) {
+ var style = baseStyle || {};
+ if (this.state.fieldValid[field_id] === false) {
+ style['borderColor'] = 'red';
+ }
+ return style;
+ },
+
render: function() {
+ var self = this;
var emailSection, registerButton;
if (this.props.showEmail) {
emailSection = (
+ defaultValue={this.state.email}
+ style={this._styleField(FIELD_EMAIL)}
+ onBlur={function() {self.validateField(FIELD_EMAIL)}} />
);
}
if (this.props.onRegisterClick) {
@@ -111,13 +198,19 @@ module.exports = React.createClass({
{registerButton}