Files
edx-platform/lms/static/js/student_account/views/AccessView.js
Renzo Lucioni 8f974ea901 Merge pull request #6815 from edx/renzo/enable-logistration
Make logistration generally available if feature flag is enabled
2015-01-30 15:15:56 -05:00

332 lines
12 KiB
JavaScript

var edx = edx || {};
(function($, _, _s, Backbone, gettext) {
'use strict';
edx.student = edx.student || {};
edx.student.account = edx.student.account || {};
// Bind to StateChange Event
History.Adapter.bind( window, 'statechange', function() {
/* Note: We are using History.getState() for legacy browser (IE) support
* using History.js plugin instead of the native event.state
*/
var State = History.getState();
});
edx.student.account.AccessView = Backbone.View.extend({
el: '#login-and-registration-container',
tpl: '#access-tpl',
events: {
'click .form-toggle': 'toggleForm'
},
subview: {
login: {},
register: {},
passwordHelp: {}
},
// The form currently loaded
activeForm: '',
initialize: function( obj ) {
/* Mix non-conflicting functions from underscore.string
* (all but include, contains, and reverse) into the
* Underscore namespace
*/
_.mixin( _s.exports() );
this.tpl = $(this.tpl).html();
this.activeForm = obj.mode || 'login';
this.thirdPartyAuth = obj.thirdPartyAuth || {
currentProvider: null,
providers: []
};
this.formDescriptions = {
login: obj.loginFormDesc,
register: obj.registrationFormDesc,
reset: obj.passwordResetFormDesc
};
this.platformName = obj.platformName;
// The login view listens for 'sync' events from the reset model
this.resetModel = new edx.student.account.PasswordResetModel({}, {
method: 'GET',
url: '#'
});
this.render();
},
render: function() {
$(this.el).html( _.template( this.tpl, {
mode: this.activeForm
}));
this.postRender();
return this;
},
postRender: function() {
// Load the default form
this.loadForm( this.activeForm );
},
loadForm: function( type ) {
var loadFunc = _.bind( this.load[type], this );
loadFunc( this.formDescriptions[type] );
},
load: {
login: function( data ) {
var model = new edx.student.account.LoginModel({}, {
method: data.method,
url: data.submit_url
});
this.subview.login = new edx.student.account.LoginView({
fields: data.fields,
model: model,
resetModel: this.resetModel,
thirdPartyAuth: this.thirdPartyAuth,
platformName: this.platformName
});
// Listen for 'password-help' event to toggle sub-views
this.listenTo( this.subview.login, 'password-help', this.resetPassword );
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this.listenTo( this.subview.login, 'auth-complete', this.authComplete );
},
reset: function( data ) {
this.resetModel.ajaxType = data.method;
this.resetModel.urlRoot = data.submit_url;
this.subview.passwordHelp = new edx.student.account.PasswordResetView({
fields: data.fields,
model: this.resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
this.listenTo( this.subview.passwordHelp, 'password-email-sent', this.passwordEmailSent );
// Focus on the form
$('.password-reset-form').focus();
},
register: function( data ) {
var model = new edx.student.account.RegisterModel({}, {
method: data.method,
url: data.submit_url
});
this.subview.register = new edx.student.account.RegisterView({
fields: data.fields,
model: model,
thirdPartyAuth: this.thirdPartyAuth,
platformName: this.platformName
});
// Listen for 'auth-complete' event so we can enroll/redirect the user appropriately.
this.listenTo( this.subview.register, 'auth-complete', this.authComplete );
}
},
passwordEmailSent: function() {
this.element.hide( $(this.el).find('#password-reset-anchor') );
this.element.show( $('#login-anchor') );
this.element.scrollTop( $('#login-anchor') );
},
resetPassword: function() {
window.analytics.track('edx.bi.password_reset_form.viewed', {
category: 'user-engagement'
});
this.element.hide( $(this.el).find('#login-anchor') );
this.loadForm('reset');
this.element.scrollTop( $('#password-reset-anchor') );
},
toggleForm: function( e ) {
var type = $(e.currentTarget).data('type'),
$form = $('#' + type + '-form'),
$anchor = $('#' + type + '-anchor'),
queryParams = url('?'),
queryStr = queryParams.length > 0 ? '?' + queryParams : '';
e.preventDefault();
window.analytics.track('edx.bi.' + type + '_form.toggled', {
category: 'user-engagement'
});
if ( !this.form.isLoaded( $form ) ) {
this.loadForm( type );
}
this.element.hide( $(this.el).find('.submission-success') );
this.element.hide( $(this.el).find('.form-wrapper') );
this.element.show( $form );
this.element.scrollTop( $anchor );
// Update url without reloading page
History.pushState( null, document.title, '/' + type + queryStr );
analytics.page( 'login_and_registration', type );
// Focus on the form
document.getElementById(type).focus();
},
/**
* Once authentication has completed successfully, a user may need to:
*
* - Enroll in a course.
* - Update email opt-in preferences
*
* These actions are delegated from the authComplete function to additional
* functions requiring authentication.
*
*/
authComplete: function() {
var emailOptIn = edx.student.account.EmailOptInInterface,
queryParams = this.queryParams();
// Set the email opt in preference.
if (!_.isUndefined(queryParams.emailOptIn) && queryParams.enrollmentAction) {
emailOptIn.setPreference(
decodeURIComponent(queryParams.courseId),
queryParams.emailOptIn,
this
).always(this.enrollment);
} else {
this.enrollment();
}
},
/**
* Designed to be invoked after authentication has completed. This function enrolls
* the student as requested.
*
* - Enroll in a course.
* - Add a course to the shopping cart.
* - Be redirected to the dashboard / track selection page / shopping cart.
*
* This handler is triggered upon successful authentication,
* either from the login or registration form. It checks
* query string params, performs enrollment/shopping cart actions,
* then redirects the user to the next page.
*
* The optional query string params are:
*
* ?next: If provided, redirect to this page upon successful auth.
* Django uses this when an unauthenticated user accesses a view
* decorated with @login_required.
*
* ?enrollment_action: Can be either "enroll" or "add_to_cart".
* If you provide this param, you must also provide a `course_id` param;
* otherwise, no action will be taken.
*
* ?course_id: The slash-separated course ID to enroll in or add to the cart.
*
*/
enrollment: function() {
var enrollment = edx.student.account.EnrollmentInterface,
shoppingcart = edx.student.account.ShoppingCartInterface,
redirectUrl = '/dashboard',
queryParams = this.queryParams();
if ( queryParams.enrollmentAction === 'enroll' && queryParams.courseId) {
/*
If we need to enroll in a course, mark as enrolled.
The enrollment interface will redirect the student once enrollment completes.
*/
enrollment.enroll( decodeURIComponent( queryParams.courseId ) );
} else if ( queryParams.enrollmentAction === 'add_to_cart' && queryParams.courseId) {
/*
If this is a paid course, add it to the shopping cart and redirect
the user to the "view cart" page.
*/
shoppingcart.addCourseToCart( decodeURIComponent( queryParams.courseId ) );
} else {
/*
Otherwise, redirect the user to the next page
Check for forwarding url and ensure that it isn't external.
If not, use the default forwarding URL.
*/
if ( !_.isNull( queryParams.next ) ) {
var next = decodeURIComponent( queryParams.next );
// Ensure that the URL is internal for security reasons
if ( !window.isExternal( next ) ) {
redirectUrl = next;
}
}
this.redirect( redirectUrl );
}
},
/**
* Redirect to a URL. Mainly useful for mocking out in tests.
* @param {string} url The URL to redirect to.
*/
redirect: function( url ) {
window.location.href = url;
},
/**
* Retrieve query params that we use post-authentication
* to decide whether to enroll a student in a course, add
* an item to the cart, or redirect.
*
* @return {object} The query params. If any param is not
* provided, it will default to null.
*/
queryParams: function() {
return {
next: $.url( '?next' ),
enrollmentAction: $.url( '?enrollment_action' ),
courseId: $.url( '?course_id' ),
emailOptIn: $.url( '?email_opt_in')
};
},
form: {
isLoaded: function( $form ) {
return $form.html().length > 0;
}
},
/* Helper method to toggle display
* including accessibility considerations
*/
element: {
hide: function( $el ) {
$el.addClass('hidden');
},
scrollTop: function( $el ) {
// Scroll to top of selected element
$('html,body').animate({
scrollTop: $el.offset().top
},'slow');
},
show: function( $el ) {
$el.removeClass('hidden');
}
}
});
})(jQuery, _, _.str, Backbone, gettext);