ECOM-369 added registration view and front end validation
This commit is contained in:
71
common/static/js/spec_helpers/edx.utils.validate.js
Normal file
71
common/static/js/spec_helpers/edx.utils.validate.js
Normal file
@@ -0,0 +1,71 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function( $, _ ) {
|
||||
'use strict';
|
||||
|
||||
edx.utils = edx.utils || {};
|
||||
|
||||
var utils = (function(){
|
||||
var _fn = {
|
||||
validate: {
|
||||
|
||||
field: function( el ) {
|
||||
var $el = $(el);
|
||||
|
||||
return _fn.validate.required( $el ) &&
|
||||
_fn.validate.charLength( $el ) &&
|
||||
_fn.validate.email.valid( $el );
|
||||
},
|
||||
|
||||
charLength: function( $el ) {
|
||||
// Cannot assume there will be both min and max
|
||||
var min = $el.attr('minlength') || 0,
|
||||
max = $el.attr('maxlength') || false,
|
||||
chars = $el.val().length,
|
||||
within = false;
|
||||
|
||||
// if max && min && within the range
|
||||
if ( min <= chars && ( max && chars <= max ) ) {
|
||||
within = true;
|
||||
} else if ( min <= chars && !max ) {
|
||||
within = true;
|
||||
}
|
||||
|
||||
return within;
|
||||
},
|
||||
|
||||
required: function( $el ) {
|
||||
return $el.attr('required') ? $el.val() : true;
|
||||
},
|
||||
|
||||
email: {
|
||||
// This is the same regex used to validate email addresses in Django 1.4
|
||||
regex: new RegExp(
|
||||
[
|
||||
'(^[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+(\\.[-!#$%&\'*+/=?^_`{}|~0-9A-Z]+)*',
|
||||
'|^"([\\001-\\010\\013\\014\\016-\\037!#-\\[\\]-\\177]|\\\\[\\001-\\011\\013\\014\\016-\\177])*"',
|
||||
')@((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\\.)+[A-Z]{2,6}\\.?$)',
|
||||
'|\\[(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)(\\.(25[0-5]|2[0-4]\\d|[0-1]?\\d?\\d)){3}\\]$'
|
||||
].join(''), 'i'
|
||||
),
|
||||
|
||||
valid: function( $el ) {
|
||||
return $el.data('email') ? _fn.validate.email.format( $el.val() ) : true;
|
||||
},
|
||||
|
||||
format: function( str ) {
|
||||
return _fn.validate.email.regex.test( str );
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
validate: _fn.validate.field
|
||||
};
|
||||
|
||||
})();
|
||||
|
||||
edx.utils.validate = utils.validate
|
||||
|
||||
})( jQuery, _ );
|
||||
@@ -1026,8 +1026,11 @@ instructor_dash_js = sorted(rooted_glob(PROJECT_ROOT / 'static', 'coffee/src/ins
|
||||
# These are not courseware, so they do not need many of the courseware-specific
|
||||
# JavaScript modules.
|
||||
student_account_js = [
|
||||
'js/common_helpers/edx.utils.validate.js',
|
||||
'js/student_account/models/LoginModel.js',
|
||||
'js/student_account/models/RegisterModel.js',
|
||||
'js/student_account/views/LoginView.js',
|
||||
'js/student_account/views/RegisterView.js',
|
||||
'js/student_account/views/AccessView.js',
|
||||
'js/student_account/accessApp.js',
|
||||
]
|
||||
|
||||
60
lms/static/js/student_account/models/RegisterModel.js
Normal file
60
lms/static/js/student_account/models/RegisterModel.js
Normal file
@@ -0,0 +1,60 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.RegisterModel = Backbone.Model.extend({
|
||||
|
||||
defaults: {
|
||||
email: '',
|
||||
name: '',
|
||||
username: '',
|
||||
password: '',
|
||||
level_of_education: '',
|
||||
gender: '',
|
||||
year_of_birth: '',
|
||||
mailing_address: '',
|
||||
goals: '',
|
||||
termsofservice: false
|
||||
},
|
||||
|
||||
urlRoot: '',
|
||||
|
||||
initialize: function( obj ) {
|
||||
this.urlRoot = obj.url;
|
||||
},
|
||||
|
||||
sync: function(method, model) {
|
||||
var headers = {
|
||||
'X-CSRFToken': $.cookie('csrftoken')
|
||||
};
|
||||
|
||||
$.ajax({
|
||||
url: model.urlRoot,
|
||||
type: 'POST',
|
||||
data: model.attributes,
|
||||
headers: headers
|
||||
})
|
||||
.done(function() {
|
||||
var query = window.location.search,
|
||||
url = '/dashboard';
|
||||
|
||||
// model.trigger('sync');
|
||||
|
||||
// If query string in url go back to that page
|
||||
if ( query.length > 1 ) {
|
||||
url = query.substring( query.indexOf('=') + 1 );
|
||||
}
|
||||
|
||||
window.location.href = url;
|
||||
})
|
||||
.fail( function( error ) {
|
||||
console.log('RegisterModel.save() FAILURE!!!!!');
|
||||
model.trigger('error', error);
|
||||
});
|
||||
}
|
||||
});
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
@@ -44,6 +44,9 @@ var edx = edx || {};
|
||||
if ( type === 'login' ) {
|
||||
console.log('load login');
|
||||
return new edx.student.account.LoginView();
|
||||
} else if ( type === 'register' ) {
|
||||
console.log('load register');
|
||||
return new edx.student.account.RegisterView();
|
||||
}
|
||||
|
||||
// return new app.LoginView({
|
||||
|
||||
@@ -42,8 +42,10 @@ var edx = edx || {};
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var $container = $(this.el);
|
||||
|
||||
this.$form = $(this.el).find('form');
|
||||
this.$form = $container.find('form');
|
||||
this.$errors = $container.find('.error-msg');
|
||||
},
|
||||
|
||||
getInitialData: function() {
|
||||
@@ -81,10 +83,6 @@ var edx = edx || {};
|
||||
fieldTpl = this.fieldTpl;
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
if ( data[i].name === 'password' ) {
|
||||
data[i].type = 'password';
|
||||
}
|
||||
|
||||
html.push( _.template( fieldTpl, $.extend( data[i], {
|
||||
form: 'login'
|
||||
}) ) );
|
||||
@@ -110,17 +108,17 @@ var edx = edx || {};
|
||||
key = $el.attr('name') || false;
|
||||
|
||||
if ( key ) {
|
||||
// if ( this.validate( elements[i] ) ) {
|
||||
if ( this.validate( elements[i] ) ) {
|
||||
obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val();
|
||||
// $el.css('border', '1px solid #ccc');
|
||||
// } else {
|
||||
// errors.push( key );
|
||||
// $el.css('border', '2px solid red');
|
||||
// }
|
||||
$el.css('border', '1px solid #ccc');
|
||||
} else {
|
||||
errors.push( key );
|
||||
$el.css('border', '2px solid red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//this.errors = errors;
|
||||
this.errors = errors;
|
||||
|
||||
return obj;
|
||||
},
|
||||
@@ -150,10 +148,14 @@ var edx = edx || {};
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
if ( show ) {
|
||||
console.log('show');
|
||||
this.$errors.removeClass('hidden');
|
||||
} else {
|
||||
console.log('hide');
|
||||
this.$errors.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
validate: function( $el ) {
|
||||
return edx.utils.validate( $el );
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
157
lms/static/js/student_account/views/RegisterView.js
Normal file
157
lms/static/js/student_account/views/RegisterView.js
Normal file
@@ -0,0 +1,157 @@
|
||||
var edx = edx || {};
|
||||
|
||||
(function($, _, Backbone, gettext) {
|
||||
'use strict';
|
||||
|
||||
edx.student = edx.student || {};
|
||||
edx.student.account = edx.student.account || {};
|
||||
|
||||
edx.student.account.RegisterView = Backbone.View.extend({
|
||||
tagName: 'form',
|
||||
|
||||
el: '#register-form',
|
||||
|
||||
tpl: $('#register-tpl').html(),
|
||||
|
||||
fieldTpl: $('#form_field-tpl').html(),
|
||||
|
||||
events: {
|
||||
'click .js-register': 'submitForm'
|
||||
},
|
||||
|
||||
errors: [],
|
||||
|
||||
$form: {},
|
||||
|
||||
initialize: function( obj ) {
|
||||
this.getInitialData();
|
||||
},
|
||||
|
||||
// Renders the form.
|
||||
render: function( html ) {
|
||||
var fields = html || '';
|
||||
|
||||
$(this.el).html( _.template( this.tpl, {
|
||||
fields: fields
|
||||
}));
|
||||
|
||||
this.postRender();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
postRender: function() {
|
||||
var $container = $(this.el);
|
||||
|
||||
this.$form = $container.find('form');
|
||||
this.$errors = $container.find('.error-msg');
|
||||
},
|
||||
|
||||
getInitialData: function() {
|
||||
var that = this;
|
||||
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
dataType: 'json',
|
||||
url: '/user_api/v1/account/registration/',
|
||||
success: function( data ) {
|
||||
console.log(data);
|
||||
that.buildForm( data.fields );
|
||||
that.initModel( data.submit_url, data.method );
|
||||
},
|
||||
error: function( jqXHR, textStatus, errorThrown ) {
|
||||
console.log('fail ', errorThrown);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
initModel: function( url, method ) {
|
||||
this.model = new edx.student.account.RegisterModel({
|
||||
url: url
|
||||
});
|
||||
|
||||
this.listenTo( this.model, 'error', function( error ) {
|
||||
console.log(error.status, ' error: ', error.responseText);
|
||||
});
|
||||
},
|
||||
|
||||
buildForm: function( data ) {
|
||||
var html = [],
|
||||
i,
|
||||
len = data.length,
|
||||
fieldTpl = this.fieldTpl;
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
html.push( _.template( fieldTpl, $.extend( data[i], {
|
||||
form: 'register'
|
||||
}) ) );
|
||||
}
|
||||
|
||||
this.render( html.join('') );
|
||||
},
|
||||
|
||||
getFormData: function() {
|
||||
|
||||
var obj = {},
|
||||
$form = this.$form,
|
||||
elements = $form[0].elements,
|
||||
i,
|
||||
len = elements.length,
|
||||
$el,
|
||||
key = '',
|
||||
errors = [];
|
||||
|
||||
for ( i=0; i<len; i++ ) {
|
||||
|
||||
$el = $( elements[i] );
|
||||
key = $el.attr('name') || false;
|
||||
|
||||
if ( key ) {
|
||||
if ( this.validate( elements[i] ) ) {
|
||||
obj[key] = $el.attr('type') === 'checkbox' ? $el.is(':checked') : $el.val();
|
||||
$el.css('border', '1px solid #ccc');
|
||||
} else {
|
||||
errors.push( key );
|
||||
$el.css('border', '2px solid red');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.errors = errors;
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
submitForm: function( event ) {
|
||||
var data = this.getFormData();
|
||||
|
||||
event.preventDefault();
|
||||
console.log(data);
|
||||
// console.log(this.model);
|
||||
|
||||
if ( !this.errors.length ) {
|
||||
console.log('save me');
|
||||
this.model.set( data );
|
||||
console.log(this.model);
|
||||
this.model.save();
|
||||
this.toggleErrorMsg( false );
|
||||
} else {
|
||||
console.log('here are the errors ', this.errors);
|
||||
this.toggleErrorMsg( true );
|
||||
}
|
||||
},
|
||||
|
||||
toggleErrorMsg: function( show ) {
|
||||
if ( show ) {
|
||||
this.$errors.removeClass('hidden');
|
||||
} else {
|
||||
this.$errors.addClass('hidden');
|
||||
}
|
||||
},
|
||||
|
||||
validate: function( $el ) {
|
||||
return edx.utils.validate( $el );
|
||||
}
|
||||
});
|
||||
|
||||
})(jQuery, _, Backbone, gettext);
|
||||
@@ -3,7 +3,7 @@
|
||||
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
|
||||
<label for"register-option">I am a new user</label>
|
||||
</h2>
|
||||
<div id="register-form" class="form-wrapper <% if ( mode === 'register' ) { %>hidden<% } %>"></div>
|
||||
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden<% } %>"></div>
|
||||
</section>
|
||||
|
||||
<section class="form-type">
|
||||
|
||||
@@ -10,11 +10,25 @@
|
||||
<a href="#" class="forgot-password">Forgot password?</a>
|
||||
<% } %>
|
||||
|
||||
<input id="<%= form %>-<%= name %>" type="<%= type %>" name="<%= name %>" aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%= restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %>
|
||||
<% if ( required ) { %> required<% } %>
|
||||
/>
|
||||
<% if ( type === 'select' ) { %>
|
||||
<select id="<%= form %>-<%= name %>" name="<%= name %>" aria-describedby="<%= form %>-<%= name %>-desc">
|
||||
<% _.each(options, function(el) { %>
|
||||
<option value="<%= el.value%>"><%= el.name %></option>
|
||||
<% }); %>
|
||||
</select>
|
||||
<% } else if ( type === 'textarea' ) { %>
|
||||
<textarea id="<%= form %>-<%= name %>" type="<%= type %>" name="<%= name %>" aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%= restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %>
|
||||
<% if ( required ) { %> required<% } %> >
|
||||
</textarea>
|
||||
<% } else { %>
|
||||
<input id="<%= form %>-<%= name %>" type="<%= type %>" name="<%= name %>" aria-describedby="<%= form %>-<%= name %>-desc"
|
||||
<% if ( restrictions.min_length ) { %> minlength="<%= restrictions.min_length %>"<% } %>
|
||||
<% if ( restrictions.max_length ) { %> maxlength="<%= restrictions.max_length %>"<% } %>
|
||||
<% if ( required ) { %> required<% } %>
|
||||
/>
|
||||
<% } %>
|
||||
|
||||
<% if ( type === 'checkbox' ) { %>
|
||||
<label for="<%= form %>-<%= name %>">
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
<form id="login">
|
||||
<div class="error-msg hidden">
|
||||
<h4>We couldn't log you in.</h4>
|
||||
<div class="errors">
|
||||
<p>Email or password is incorrent. <a href="#">Forgot password?</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<%= fields %>
|
||||
<button class="action action-primary action-update js-login">Log in</button>
|
||||
<button type="submit" class="button button-primary button-facebook"><span class="icon icon-facebook"></span>Sign in with Facebook</button>
|
||||
|
||||
@@ -12,16 +12,16 @@
|
||||
</%block>
|
||||
|
||||
<%block name="header_extras">
|
||||
% for template_name in ["account", "access", "form_field", "login"]:
|
||||
% for template_name in ["account", "access", "form_field", "login", "register"]:
|
||||
<script type="text/template" id="${template_name}-tpl">
|
||||
<%static:include path="student_account/${template_name}.underscore" />
|
||||
</script>
|
||||
% endfor
|
||||
</%block>
|
||||
|
||||
<h1>Login and Registration!</h1>
|
||||
<h1>Welcome!</h1>
|
||||
|
||||
<p>This is a placeholder for the combined login and registration form.</p>
|
||||
<p>Please log in to continue</p>
|
||||
|
||||
## TODO: Use JavaScript to populate this div with
|
||||
## the actual registration/login forms (loaded asynchronously from the user API)
|
||||
|
||||
15
lms/templates/student_account/register.underscore
Normal file
15
lms/templates/student_account/register.underscore
Normal file
@@ -0,0 +1,15 @@
|
||||
<form id="register">
|
||||
<div class="error-msg hidden">
|
||||
<h4>An error occured in your registration.</h4>
|
||||
<div class="errors">
|
||||
<p>Please enter a valid password</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" class="button button-primary button-facebook"><span class="icon icon-facebook"></span>Sign up with Facebook</button>
|
||||
<button type="submit" class="button button-primary button-google"><span class="icon icon-google-plus"></span>Sign up with Google</button>
|
||||
<%= fields %>
|
||||
<input id="register-termsofservice" type="checkbox" name="termsofservice">
|
||||
<label for="register-termsofservice">I agree to the <a href="#">Terms of Service and Honor Code</a> *</label>
|
||||
<button class="action action-primary action-update js-register">Create My edX Account</button>
|
||||
</form>
|
||||
Reference in New Issue
Block a user