Commit a4342070 by AlasdairSwan

ECOM-783 updated logistration in light of redesign

parent 8d577563
......@@ -12,7 +12,7 @@ describe('edx.utils.validate', function () {
EMAIL_ERROR_FRAGMENT = 'formatted',
MIN_ERROR_FRAGMENT = 'least',
MAX_ERROR_FRAGMENT = 'up to',
REQUIRED_ERROR_FRAGMENT = 'empty',
REQUIRED_ERROR_FRAGMENT = 'Please enter your',
CUSTOM_MESSAGE = 'custom message';
var createFixture = function( type, name, required, minlength, maxlength, value ) {
......
......@@ -19,9 +19,9 @@ var edx = edx || {};
msg: {
email: '<li><%- gettext("The email address you\'ve provided isn\'t formatted correctly.") %></li>',
min: '<li><%- _.sprintf(gettext("%(field)s must have at least %(count)d characters."), context) %></li>',
max: '<li><%- _.sprintf(gettext("%(field)s can only contain up to %(count)d characters."), context) %></li>',
required: '<li><%- _.sprintf(gettext("The %(field)s field cannot be empty."), context) %></li>',
min: '<li><%- _.sprintf( gettext("%(field)s must have at least %(count)d characters."), context ) %></li>',
max: '<li><%- _.sprintf( gettext("%(field)s can only contain up to %(count)d characters."), context ) %></li>',
required: '<li><%- _.sprintf( gettext("Please enter your %(field)s."), context ) %></li>',
custom: '<li><%= content %></li>'
},
......
......@@ -120,8 +120,8 @@ class CombinedLoginAndRegisterPage(PageObject):
def is_browser_on_page(self):
"""Check whether the combined login/registration page has loaded. """
return (
self.q(css="#register-option").is_present() and
self.q(css="#login-option").is_present() and
self.q(css="#login-anchor").is_present() and
self.q(css="#register-anchor").is_present() and
self.current_form is not None
)
......@@ -130,7 +130,10 @@ class CombinedLoginAndRegisterPage(PageObject):
old_form = self.current_form
# Toggle the form
self.q(css=".form-toggle:not(:checked)").click()
if old_form == "login":
self.q(css=".form-toggle[data-type='register']").click()
else:
self.q(css=".form-toggle[data-type='login']").click()
# Wait for the form to change before returning
EmptyPromise(
......@@ -157,9 +160,9 @@ class CombinedLoginAndRegisterPage(PageObject):
"""
# Fill in the form
self.q(css="#register-email").fill(email)
self.q(css="#register-password").fill(password)
self.q(css="#register-username").fill(username)
self.q(css="#register-name").fill(full_name)
self.q(css="#register-username").fill(username)
self.q(css="#register-password").fill(password)
if country:
self.q(css="#register-country option[value='{country}']".format(country=country)).click()
if (terms_of_service):
......@@ -168,7 +171,7 @@ class CombinedLoginAndRegisterPage(PageObject):
# Submit it
self.q(css=".register-button").click()
def login(self, email="", password="", remember_me=True):
def login(self, email="", password=""):
"""Fills in and submits the login form.
Requires that the "login" form is visible.
......@@ -179,14 +182,11 @@ class CombinedLoginAndRegisterPage(PageObject):
Keyword Arguments:
email (unicode): The user's email address.
password (unicode): The user's password.
remember_me (boolean): If True, check the "remember me" box.
"""
# Fill in the form
self.q(css="#login-email").fill(email)
self.q(css="#login-password").fill(password)
if remember_me:
self.q(css="#login-remember").click()
# Submit it
self.q(css=".login-button").click()
......@@ -217,6 +217,8 @@ class CombinedLoginAndRegisterPage(PageObject):
# Submit it
self.q(css="button.js-reset").click()
return CombinedLoginAndRegisterPage(self.browser).wait_for_page()
@property
@unguarded
def current_form(self):
......@@ -233,7 +235,7 @@ class CombinedLoginAndRegisterPage(PageObject):
return "register"
elif self.q(css=".login-button").visible:
return "login"
elif self.q(css=".js-reset").visible or self.q(css=".js-reset-success").visible:
elif self.q(css=".js-reset").visible:
return "password-reset"
@property
......
......@@ -218,9 +218,9 @@ class RegisterFromCombinedPageTest(UniqueCourseTest):
# Verify that the expected errors are displayed.
errors = self.register_page.wait_for_errors()
self.assertIn(u'The Username field cannot be empty.', errors)
self.assertIn(u'Please enter your Public username.', errors)
self.assertIn(u'You must agree to the edX Terms of Service and Honor Code.', errors)
self.assertIn(u'The Country field cannot be empty.', errors)
self.assertIn(u'Please select your Country.', errors)
def test_toggle_to_login_form(self):
self.register_page.visit().toggle_form()
......
@shard_1
Feature: LMS.Homepage for web users
In order to get an idea what edX is about
As a an anonymous web user
As an anonymous web user
I want to check the information on the home page
Scenario: User can see the "Login" button
Scenario: User can see the "Sign in" button
Given I visit the homepage
Then I should see a link called "Log in"
Then I should see a link called "Sign in"
Scenario: User can see the "Register Now" button
Given I visit the homepage
......
......@@ -8,7 +8,7 @@ Feature: LMS.Login in as a registered user
Given I am an edX user
And I am an unactivated user
And I visit the homepage
When I click the link with the text "Log in"
When I click the link with the text "Sign in"
And I submit my credentials on the login form
Then I should see the login error message "This account has not been activated"
......@@ -18,15 +18,15 @@ Feature: LMS.Login in as a registered user
Given I am an edX user
And I am an activated user
And I visit the homepage
When I click the link with the text "Log in"
When I click the link with the text "Sign in"
And I submit my credentials on the login form
Then I should be on the dashboard page
Scenario: Logout of a signed in account
Given I am logged in
When I click the dropdown arrow
And I click the link with the text "Log Out"
Then I should see a link with the text "Log in"
And I click the link with the text "Sign out"
Then I should see a link with the text "Sign in"
And I should see that the path is "/"
Scenario: Login with valid redirect
......
......@@ -56,6 +56,7 @@
'string_utils': 'xmodule_js/common_static/js/src/string_utils',
// Manually specify LMS files that are not converted to RequireJS
'history': 'js/vendor/history',
'js/verify_student/photocapture': 'js/verify_student/photocapture',
'js/staff_debug_actions': 'js/staff_debug_actions',
......@@ -372,6 +373,7 @@
'underscore',
'backbone',
'gettext',
'history',
'utility',
'js/student_account/views/LoginView',
'js/student_account/views/PasswordResetView',
......
......@@ -96,13 +96,13 @@ define([
var assertForms = function(visibleType, hiddenType) {
expect($(visibleType)).not.toHaveClass('hidden');
expect($(hiddenType)).toHaveClass('hidden');
expect($('#password-reset-wrapper')).toBeEmpty();
expect($('#password-reset-form')).toHaveClass('hidden');
};
var selectForm = function(type) {
// Create a fake change event to control form toggling
var changeEvent = $.Event('change');
changeEvent.currentTarget = $('#' + type + '-option');
changeEvent.currentTarget = $('.form-toggle[data-type="' + type + '"]');
// Load form corresponding to the change event
view.toggleForm(changeEvent);
......@@ -133,9 +133,7 @@ define([
TemplateHelpers.installTemplate('templates/student_account/form_field');
// Stub analytics tracking
// TODO: use RequireJS to ensure that this is loaded correctly
window.analytics = window.analytics || {};
window.analytics.track = window.analytics.track || function() {};
window.analytics = jasmine.createSpyObj('analytics', ['track', 'page', 'pageview', 'trackLink']);
});
it('can initially display the login form', function() {
......
......@@ -4,12 +4,14 @@ define([
'js/common_helpers/template_helpers',
'js/common_helpers/ajax_helpers',
'js/student_account/models/LoginModel',
'js/student_account/views/LoginView'
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView) {
'js/student_account/views/LoginView',
'js/student_account/models/PasswordResetModel'
], function($, _, TemplateHelpers, AjaxHelpers, LoginModel, LoginView, PasswordResetModel) {
'use strict';
describe('edx.student.account.LoginView', function() {
var model = null,
resetModel = null,
view = null,
requests = null,
authComplete = false,
......@@ -79,10 +81,17 @@ define([
method: FORM_DESCRIPTION.method
});
// Initialize the passwordReset model
resetModel = new PasswordResetModel({}, {
method: 'GET',
url: '#'
});
// Initialize the login view
view = new LoginView({
fields: FORM_DESCRIPTION.fields,
model: model,
resetModel: resetModel,
thirdPartyAuth: THIRD_PARTY_AUTH,
platformName: PLATFORM_NAME
});
......
......@@ -67,7 +67,7 @@ define([
};
beforeEach(function() {
setFixtures('<div id="password-reset-wrapper"></div>');
setFixtures('<div id="password-reset-form" class="form-wrapper hidden"></div>');
TemplateHelpers.installTemplate('templates/student_account/password_reset');
TemplateHelpers.installTemplate('templates/student_account/form_field');
});
......@@ -90,6 +90,12 @@ define([
// Verify that the success message is visible
expect($('.js-reset-success')).not.toHaveClass('hidden');
// Verify that login form has loaded
expect($('#login-form')).not.toHaveClass('hidden');
// Verify that password reset view has been removed
expect($( view.el ).html().length).toEqual(0);
});
it('validates the email field', function() {
......
......@@ -21,7 +21,7 @@ var edx = edx || {};
this.urlRoot = options.url;
},
sync: function(method, model) {
sync: function( method, model ) {
var headers = {
'X-CSRFToken': $.cookie('csrftoken')
};
......
......@@ -6,13 +6,21 @@ var edx = edx || {};
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: {
'change .form-toggle': 'toggleForm'
'click .form-toggle': 'toggleForm'
},
subview: {
......@@ -37,8 +45,15 @@ var edx = edx || {};
currentProvider: null,
providers: []
};
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();
},
......@@ -55,7 +70,6 @@ var edx = edx || {};
postRender: function() {
// Load the default form
this.loadForm( this.activeForm );
this.$header = $(this.el).find('.js-login-register-header');
},
loadForm: function( type ) {
......@@ -72,6 +86,7 @@ var edx = edx || {};
context.subview.login = new edx.student.account.LoginView({
fields: data.fields,
model: model,
resetModel: context.resetModel,
thirdPartyAuth: context.thirdPartyAuth,
platformName: context.platformName
});
......@@ -85,15 +100,16 @@ var edx = edx || {};
},
reset: function( data, context ) {
var model = new edx.student.account.PasswordResetModel({}, {
method: data.method,
url: data.submit_url
});
context.resetModel.ajaxType = data.method;
context.resetModel.urlRoot = data.submit_url;
context.subview.passwordHelp = new edx.student.account.PasswordResetView({
fields: data.fields,
model: model
model: context.resetModel
});
// Listen for 'password-email-sent' event to toggle sub-views
context.listenTo( context.subview.passwordHelp, 'password-email-sent', context.passwordEmailSent );
},
register: function( data, context ) {
......@@ -133,15 +149,20 @@ var edx = edx || {};
});
},
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.$header );
this.element.hide( $(this.el).find('.form-type') );
this.element.hide( $(this.el).find('#login-anchor') );
this.loadForm('reset');
this.element.scrollTop( $('#password-reset-wrapper') );
this.element.scrollTop( $('#password-reset-anchor') );
},
showFormError: function() {
......@@ -149,10 +170,12 @@ var edx = edx || {};
},
toggleForm: function( e ) {
var type = $(e.currentTarget).val(),
var type = $(e.currentTarget).data('type'),
$form = $('#' + type + '-form'),
$anchor = $('#' + type + '-anchor');
e.preventDefault();
window.analytics.track('edx.bi.' + type + '_form.toggled', {
category: 'user-engagement'
});
......@@ -161,9 +184,14 @@ var edx = edx || {};
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, '/account/' + type + '/' );
analytics.page( 'login_and_registration', type );
},
/**
......@@ -291,8 +319,7 @@ var edx = edx || {};
*/
element: {
hide: function( $el ) {
$el.addClass('hidden')
.attr('aria-hidden', true);
$el.addClass('hidden');
},
scrollTop: function( $el ) {
......@@ -303,8 +330,7 @@ var edx = edx || {};
},
show: function( $el ) {
$el.removeClass('hidden')
.attr('aria-hidden', false);
$el.removeClass('hidden');
}
}
});
......
......@@ -98,8 +98,7 @@ var edx = edx || {};
element: {
hide: function( $el ) {
if ( $el ) {
$el.addClass('hidden')
.attr('aria-hidden', true);
$el.addClass('hidden');
}
},
......@@ -112,8 +111,7 @@ var edx = edx || {};
show: function( $el ) {
if ( $el ) {
$el.removeClass('hidden')
.attr('aria-hidden', false);
$el.removeClass('hidden');
}
}
},
......@@ -148,7 +146,6 @@ var edx = edx || {};
},
getFormData: function() {
var obj = {},
$form = this.$form,
elements = $form[0].elements,
......@@ -229,6 +226,15 @@ var edx = edx || {};
} else {
this.toggleErrorMsg( true );
}
this.postFormSubmission();
},
/* Allows extended views to add custom
* code after form submission
*/
postFormSubmission: function() {
return true;
},
toggleErrorMsg: function( show ) {
......
......@@ -27,8 +27,10 @@ var edx = edx || {};
this.providers = data.thirdPartyAuth.providers || [];
this.currentProvider = data.thirdPartyAuth.currentProvider || '';
this.platformName = data.platformName;
this.resetModel = data.resetModel;
this.listenTo( this.model, 'sync', this.saveSuccess );
this.listenTo( this.resetModel, 'sync', this.resetEmail );
},
render: function( html ) {
......@@ -55,6 +57,7 @@ var edx = edx || {};
this.$form = this.$container.find('form');
this.$errors = this.$container.find('.submission-error');
this.$resetSuccess = this.$container.find('.js-reset-success');
this.$authError = this.$container.find('.already-authenticated-msg');
this.$submitButton = this.$container.find(this.submitButton);
......@@ -71,6 +74,16 @@ var edx = edx || {};
event.preventDefault();
this.trigger('password-help');
this.element.hide( this.$resetSuccess );
},
postFormSubmission: function() {
this.element.hide( this.$resetSuccess );
},
resetEmail: function() {
this.element.hide( this.$errors );
this.element.show( this.$resetSuccess );
},
thirdPartyAuth: function( event ) {
......@@ -81,13 +94,15 @@ var edx = edx || {};
}
},
saveSuccess: function () {
saveSuccess: function() {
this.trigger('auth-complete');
this.element.hide( this.$resetSuccess );
},
saveError: function( error ) {
this.errors = ['<li>' + error.responseText + '</li>'];
this.setErrors();
this.element.hide( this.$resetSuccess );
/* If we've gotten a 403 error, it means that we've successfully
* authenticated with a third-party provider, but we haven't
......
......@@ -7,7 +7,7 @@ var edx = edx || {};
edx.student.account = edx.student.account || {};
edx.student.account.PasswordResetView = edx.student.account.FormView.extend({
el: '#password-reset-wrapper',
el: '#password-reset-form',
tpl: '#password_reset-tpl',
......@@ -22,6 +22,8 @@ var edx = edx || {};
submitButton: '.js-reset',
preRender: function() {
this.element.show( $( this.el ) );
this.element.show( $( this.el ).parent() );
this.listenTo( this.model, 'sync', this.saveSuccess );
},
......@@ -35,12 +37,11 @@ var edx = edx || {};
},
saveSuccess: function() {
var $el = $(this.el),
$msg = $el.find('.js-reset-success');
this.trigger('password-email-sent');
this.element.hide( $el.find('#password-reset-form') );
this.element.show( $msg );
this.element.scrollTop( $msg );
// Destroy the view (but not el) and unbind events
this.$el.empty().off();
this.stopListening();
}
});
......
/* History.js v1.8b2 https://github.com/browserstate/history.js */
typeof JSON!="object"&&(JSON={}),function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t=="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];a&&typeof a=="object"&&typeof a.toJSON=="function"&&(a=a.toJSON(e)),typeof rep=="function"&&(a=rep.call(t,e,a));switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a)return"null";gap+=indent,u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1)u[n]=str(n,a)||"null";return i=u.length===0?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+o+"]":"["+u.join(",")+"]",gap=o,i}if(rep&&typeof rep=="object"){s=rep.length;for(n=0;n<s;n+=1)typeof rep[n]=="string"&&(r=rep[n],i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i))}else for(r in a)Object.prototype.hasOwnProperty.call(a,r)&&(i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i));return i=u.length===0?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+o+"}":"{"+u.join(",")+"}",gap=o,i}}typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(e){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(e){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(e,t,n){var r;gap="",indent="";if(typeof n=="number")for(r=0;r<n;r+=1)indent+=" ";else typeof n=="string"&&(indent=n);rep=t;if(!t||typeof t=="function"||typeof t=="object"&&typeof t.length=="number")return str("",{"":e});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i=="object")for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(r=walk(i,n),r!==undefined?i[n]=r:delete i[n]);return reviver.call(e,t,i)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),function(e,t){"use strict";var n=e.History=e.History||{},r=e.jQuery;if(typeof n.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");n.Adapter={bind:function(e,t,n){r(e).bind(t,n)},trigger:function(e,t,n){r(e).trigger(t,n)},extractEventData:function(e,n,r){var i=n&&n.originalEvent&&n.originalEvent[e]||r&&r[e]||t;return i},onDomLoad:function(e){r(e)}},typeof n.init!="undefined"&&n.init()}(window),function(e,t){"use strict";var n=e.document,r=e.setTimeout||r,i=e.clearTimeout||i,s=e.setInterval||s,o=e.History=e.History||{};if(typeof o.initHtml4!="undefined")throw new Error("History.js HTML4 Support has already been loaded...");o.initHtml4=function(){if(typeof o.initHtml4.initialized!="undefined")return!1;o.initHtml4.initialized=!0,o.enabled=!0,o.savedHashes=[],o.isLastHash=function(e){var t=o.getHashByIndex(),n;return n=e===t,n},o.isHashEqual=function(e,t){return e=encodeURIComponent(e).replace(/%25/g,"%"),t=encodeURIComponent(t).replace(/%25/g,"%"),e===t},o.saveHash=function(e){return o.isLastHash(e)?!1:(o.savedHashes.push(e),!0)},o.getHashByIndex=function(e){var t=null;return typeof e=="undefined"?t=o.savedHashes[o.savedHashes.length-1]:e<0?t=o.savedHashes[o.savedHashes.length+e]:t=o.savedHashes[e],t},o.discardedHashes={},o.discardedStates={},o.discardState=function(e,t,n){var r=o.getHashByState(e),i;return i={discardedState:e,backState:n,forwardState:t},o.discardedStates[r]=i,!0},o.discardHash=function(e,t,n){var r={discardedHash:e,backState:n,forwardState:t};return o.discardedHashes[e]=r,!0},o.discardedState=function(e){var t=o.getHashByState(e),n;return n=o.discardedStates[t]||!1,n},o.discardedHash=function(e){var t=o.discardedHashes[e]||!1;return t},o.recycleState=function(e){var t=o.getHashByState(e);return o.discardedState(e)&&delete o.discardedStates[t],!0},o.emulated.hashChange&&(o.hashChangeInit=function(){o.checkerFunction=null;var t="",r,i,u,a,f=Boolean(o.getHash());return o.isInternetExplorer()?(r="historyjs-iframe",i=n.createElement("iframe"),i.setAttribute("id",r),i.setAttribute("src","#"),i.style.display="none",n.body.appendChild(i),i.contentWindow.document.open(),i.contentWindow.document.close(),u="",a=!1,o.checkerFunction=function(){if(a)return!1;a=!0;var n=o.getHash(),r=o.getHash(i.contentWindow.document);return n!==t?(t=n,r!==n&&(u=r=n,i.contentWindow.document.open(),i.contentWindow.document.close(),i.contentWindow.document.location.hash=o.escapeHash(n)),o.Adapter.trigger(e,"hashchange")):r!==u&&(u=r,f&&r===""?o.back():o.setHash(r,!1)),a=!1,!0}):o.checkerFunction=function(){var n=o.getHash()||"";return n!==t&&(t=n,o.Adapter.trigger(e,"hashchange")),!0},o.intervalList.push(s(o.checkerFunction,o.options.hashChangeInterval)),!0},o.Adapter.onDomLoad(o.hashChangeInit)),o.emulated.pushState&&(o.onHashChange=function(t){var n=t&&t.newURL||o.getLocationHref(),r=o.getHashByUrl(n),i=null,s=null,u=null,a;return o.isLastHash(r)?(o.busy(!1),!1):(o.doubleCheckComplete(),o.saveHash(r),r&&o.isTraditionalAnchor(r)?(o.Adapter.trigger(e,"anchorchange"),o.busy(!1),!1):(i=o.extractState(o.getFullUrl(r||o.getLocationHref()),!0),o.isLastSavedState(i)?(o.busy(!1),!1):(s=o.getHashByState(i),a=o.discardedState(i),a?(o.getHashByIndex(-2)===o.getHashByState(a.forwardState)?o.back(!1):o.forward(!1),!1):(o.pushState(i.data,i.title,encodeURI(i.url),!1),!0))))},o.Adapter.bind(e,"hashchange",o.onHashChange),o.pushState=function(t,n,r,i){r=encodeURI(r).replace(/%25/g,"%");if(o.getHashByUrl(r))throw new Error("History.js does not support states with fragment-identifiers (hashes/anchors).");if(i!==!1&&o.busy())return o.pushQueue({scope:o,callback:o.pushState,args:arguments,queue:i}),!1;o.busy(!0);var s=o.createStateObject(t,n,r),u=o.getHashByState(s),a=o.getState(!1),f=o.getHashByState(a),l=o.getHash(),c=o.expectedStateId==s.id;return o.storeState(s),o.expectedStateId=s.id,o.recycleState(s),o.setTitle(s),u===f?(o.busy(!1),!1):(o.saveState(s),c||o.Adapter.trigger(e,"statechange"),!o.isHashEqual(u,l)&&!o.isHashEqual(u,o.getShortUrl(o.getLocationHref()))&&o.setHash(u,!1),o.busy(!1),!0)},o.replaceState=function(t,n,r,i){r=encodeURI(r).replace(/%25/g,"%");if(o.getHashByUrl(r))throw new Error("History.js does not support states with fragment-identifiers (hashes/anchors).");if(i!==!1&&o.busy())return o.pushQueue({scope:o,callback:o.replaceState,args:arguments,queue:i}),!1;o.busy(!0);var s=o.createStateObject(t,n,r),u=o.getHashByState(s),a=o.getState(!1),f=o.getHashByState(a),l=o.getStateByIndex(-2);return o.discardState(a,s,l),u===f?(o.storeState(s),o.expectedStateId=s.id,o.recycleState(s),o.setTitle(s),o.saveState(s),o.Adapter.trigger(e,"statechange"),o.busy(!1)):o.pushState(s.data,s.title,s.url,!1),!0}),o.emulated.pushState&&o.getHash()&&!o.emulated.hashChange&&o.Adapter.onDomLoad(function(){o.Adapter.trigger(e,"hashchange")})},typeof o.init!="undefined"&&o.init()}(window),function(e,t){"use strict";var n=e.console||t,r=e.document,i=e.navigator,s=!1,o=e.setTimeout,u=e.clearTimeout,a=e.setInterval,f=e.clearInterval,l=e.JSON,c=e.alert,h=e.History=e.History||{},p=e.history;try{s=e.sessionStorage,s.setItem("TEST","1"),s.removeItem("TEST")}catch(d){s=!1}l.stringify=l.stringify||l.encode,l.parse=l.parse||l.decode;if(typeof h.init!="undefined")throw new Error("History.js Core has already been loaded...");h.init=function(e){return typeof h.Adapter=="undefined"?!1:(typeof h.initCore!="undefined"&&h.initCore(),typeof h.initHtml4!="undefined"&&h.initHtml4(),!0)},h.initCore=function(d){if(typeof h.initCore.initialized!="undefined")return!1;h.initCore.initialized=!0,h.options=h.options||{},h.options.hashChangeInterval=h.options.hashChangeInterval||100,h.options.safariPollInterval=h.options.safariPollInterval||500,h.options.doubleCheckInterval=h.options.doubleCheckInterval||500,h.options.disableSuid=h.options.disableSuid||!1,h.options.storeInterval=h.options.storeInterval||1e3,h.options.busyDelay=h.options.busyDelay||250,h.options.debug=h.options.debug||!1,h.options.initialTitle=h.options.initialTitle||r.title,h.options.html4Mode=h.options.html4Mode||!1,h.options.delayInit=h.options.delayInit||!1,h.intervalList=[],h.clearAllIntervals=function(){var e,t=h.intervalList;if(typeof t!="undefined"&&t!==null){for(e=0;e<t.length;e++)f(t[e]);h.intervalList=null}},h.debug=function(){(h.options.debug||!1)&&h.log.apply(h,arguments)},h.log=function(){var e=typeof n!="undefined"&&typeof n.log!="undefined"&&typeof n.log.apply!="undefined",t=r.getElementById("log"),i,s,o,u,a;e?(u=Array.prototype.slice.call(arguments),i=u.shift(),typeof n.debug!="undefined"?n.debug.apply(n,[i,u]):n.log.apply(n,[i,u])):i="\n"+arguments[0]+"\n";for(s=1,o=arguments.length;s<o;++s){a=arguments[s];if(typeof a=="object"&&typeof l!="undefined")try{a=l.stringify(a)}catch(f){}i+="\n"+a+"\n"}return t?(t.value+=i+"\n-----\n",t.scrollTop=t.scrollHeight-t.clientHeight):e||c(i),!0},h.getInternetExplorerMajorVersion=function(){var e=h.getInternetExplorerMajorVersion.cached=typeof h.getInternetExplorerMajorVersion.cached!="undefined"?h.getInternetExplorerMajorVersion.cached:function(){var e=3,t=r.createElement("div"),n=t.getElementsByTagName("i");while((t.innerHTML="<!--[if gt IE "+ ++e+"]><i></i><![endif]-->")&&n[0]);return e>4?e:!1}();return e},h.isInternetExplorer=function(){var e=h.isInternetExplorer.cached=typeof h.isInternetExplorer.cached!="undefined"?h.isInternetExplorer.cached:Boolean(h.getInternetExplorerMajorVersion());return e},h.options.html4Mode?h.emulated={pushState:!0,hashChange:!0}:h.emulated={pushState:!Boolean(e.history&&e.history.pushState&&e.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(i.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(i.userAgent)),hashChange:Boolean(!("onhashchange"in e||"onhashchange"in r)||h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8)},h.enabled=!h.emulated.pushState,h.bugs={setHash:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),safariPoll:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),ieDoubleCheck:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<7)},h.isEmptyObject=function(e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},h.cloneObject=function(e){var t,n;return e?(t=l.stringify(e),n=l.parse(t)):n={},n},h.getRootUrl=function(){var e=r.location.protocol+"//"+(r.location.hostname||r.location.host);if(r.location.port||!1)e+=":"+r.location.port;return e+="/",e},h.getBaseHref=function(){var e=r.getElementsByTagName("base"),t=null,n="";return e.length===1&&(t=e[0],n=t.href.replace(/[^\/]+$/,"")),n=n.replace(/\/+$/,""),n&&(n+="/"),n},h.getBaseUrl=function(){var e=h.getBaseHref()||h.getBasePageUrl()||h.getRootUrl();return e},h.getPageUrl=function(){var e=h.getState(!1,!1),t=(e||{}).url||h.getLocationHref(),n;return n=t.replace(/\/+$/,"").replace(/[^\/]+$/,function(e,t,n){return/\./.test(e)?e:e+"/"}),n},h.getBasePageUrl=function(){var e=h.getLocationHref().replace(/[#\?].*/,"").replace(/[^\/]+$/,function(e,t,n){return/[^\/]$/.test(e)?"":e}).replace(/\/+$/,"")+"/";return e},h.getFullUrl=function(e,t){var n=e,r=e.substring(0,1);return t=typeof t=="undefined"?!0:t,/[a-z]+\:\/\//.test(e)||(r==="/"?n=h.getRootUrl()+e.replace(/^\/+/,""):r==="#"?n=h.getPageUrl().replace(/#.*/,"")+e:r==="?"?n=h.getPageUrl().replace(/[\?#].*/,"")+e:t?n=h.getBaseUrl()+e.replace(/^(\.\/)+/,""):n=h.getBasePageUrl()+e.replace(/^(\.\/)+/,"")),n.replace(/\#$/,"")},h.getShortUrl=function(e){var t=e,n=h.getBaseUrl(),r=h.getRootUrl();return h.emulated.pushState&&(t=t.replace(n,"")),t=t.replace(r,"/"),h.isTraditionalAnchor(t)&&(t="./"+t),t=t.replace(/^(\.\/)+/g,"./").replace(/\#$/,""),t},h.getLocationHref=function(e){return e=e||r,e.URL===e.location.href?e.location.href:e.location.href===decodeURIComponent(e.URL)?e.URL:e.location.hash&&decodeURIComponent(e.location.href.replace(/^[^#]+/,""))===e.location.hash?e.location.href:e.URL.indexOf("#")==-1&&e.location.href.indexOf("#")!=-1?e.location.href:e.URL||e.location.href},h.store={},h.idToState=h.idToState||{},h.stateToId=h.stateToId||{},h.urlToId=h.urlToId||{},h.storedStates=h.storedStates||[],h.savedStates=h.savedStates||[],h.normalizeStore=function(){h.store.idToState=h.store.idToState||{},h.store.urlToId=h.store.urlToId||{},h.store.stateToId=h.store.stateToId||{}},h.getState=function(e,t){typeof e=="undefined"&&(e=!0),typeof t=="undefined"&&(t=!0);var n=h.getLastSavedState();return!n&&t&&(n=h.createStateObject()),e&&(n=h.cloneObject(n),n.url=n.cleanUrl||n.url),n},h.getIdByState=function(e){var t=h.extractId(e.url),n;if(!t){n=h.getStateString(e);if(typeof h.stateToId[n]!="undefined")t=h.stateToId[n];else if(typeof h.store.stateToId[n]!="undefined")t=h.store.stateToId[n];else{for(;;){t=(new Date).getTime()+String(Math.random()).replace(/\D/g,"");if(typeof h.idToState[t]=="undefined"&&typeof h.store.idToState[t]=="undefined")break}h.stateToId[n]=t,h.idToState[t]=e}}return t},h.normalizeState=function(e){var t,n;if(!e||typeof e!="object")e={};if(typeof e.normalized!="undefined")return e;if(!e.data||typeof e.data!="object")e.data={};return t={},t.normalized=!0,t.title=e.title||"",t.url=h.getFullUrl(e.url?e.url:h.getLocationHref()),t.hash=h.getShortUrl(t.url),t.data=h.cloneObject(e.data),t.id=h.getIdByState(t),t.cleanUrl=t.url.replace(/\??\&_suid.*/,""),t.url=t.cleanUrl,n=!h.isEmptyObject(t.data),(t.title||n)&&h.options.disableSuid!==!0&&(t.hash=h.getShortUrl(t.url).replace(/\??\&_suid.*/,""),/\?/.test(t.hash)||(t.hash+="?"),t.hash+="&_suid="+t.id),t.hashedUrl=h.getFullUrl(t.hash),(h.emulated.pushState||h.bugs.safariPoll)&&h.hasUrlDuplicate(t)&&(t.url=t.hashedUrl),t},h.createStateObject=function(e,t,n){var r={data:e,title:t,url:n};return r=h.normalizeState(r),r},h.getStateById=function(e){e=String(e);var n=h.idToState[e]||h.store.idToState[e]||t;return n},h.getStateString=function(e){var t,n,r;return t=h.normalizeState(e),n={data:t.data,title:e.title,url:e.url},r=l.stringify(n),r},h.getStateId=function(e){var t,n;return t=h.normalizeState(e),n=t.id,n},h.getHashByState=function(e){var t,n;return t=h.normalizeState(e),n=t.hash,n},h.extractId=function(e){var t,n,r,i;return e.indexOf("#")!=-1?i=e.split("#")[0]:i=e,n=/(.*)\&_suid=([0-9]+)$/.exec(i),r=n?n[1]||e:e,t=n?String(n[2]||""):"",t||!1},h.isTraditionalAnchor=function(e){var t=!/[\/\?\.]/.test(e);return t},h.extractState=function(e,t){var n=null,r,i;return t=t||!1,r=h.extractId(e),r&&(n=h.getStateById(r)),n||(i=h.getFullUrl(e),r=h.getIdByUrl(i)||!1,r&&(n=h.getStateById(r)),!n&&t&&!h.isTraditionalAnchor(e)&&(n=h.createStateObject(null,null,i))),n},h.getIdByUrl=function(e){var n=h.urlToId[e]||h.store.urlToId[e]||t;return n},h.getLastSavedState=function(){return h.savedStates[h.savedStates.length-1]||t},h.getLastStoredState=function(){return h.storedStates[h.storedStates.length-1]||t},h.hasUrlDuplicate=function(e){var t=!1,n;return n=h.extractState(e.url),t=n&&n.id!==e.id,t},h.storeState=function(e){return h.urlToId[e.url]=e.id,h.storedStates.push(h.cloneObject(e)),e},h.isLastSavedState=function(e){var t=!1,n,r,i;return h.savedStates.length&&(n=e.id,r=h.getLastSavedState(),i=r.id,t=n===i),t},h.saveState=function(e){return h.isLastSavedState(e)?!1:(h.savedStates.push(h.cloneObject(e)),!0)},h.getStateByIndex=function(e){var t=null;return typeof e=="undefined"?t=h.savedStates[h.savedStates.length-1]:e<0?t=h.savedStates[h.savedStates.length+e]:t=h.savedStates[e],t},h.getCurrentIndex=function(){var e=null;return h.savedStates.length<1?e=0:e=h.savedStates.length-1,e},h.getHash=function(e){var t=h.getLocationHref(e),n;return n=h.getHashByUrl(t),n},h.unescapeHash=function(e){var t=h.normalizeHash(e);return t=decodeURIComponent(t),t},h.normalizeHash=function(e){var t=e.replace(/[^#]*#/,"").replace(/#.*/,"");return t},h.setHash=function(e,t){var n,i;return t!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.setHash,args:arguments,queue:t}),!1):(h.busy(!0),n=h.extractState(e,!0),n&&!h.emulated.pushState?h.pushState(n.data,n.title,n.url,!1):h.getHash()!==e&&(h.bugs.setHash?(i=h.getPageUrl(),h.pushState(null,null,i+"#"+e,!1)):r.location.hash=e),h)},h.escapeHash=function(t){var n=h.normalizeHash(t);return n=e.encodeURIComponent(n),h.bugs.hashEscape||(n=n.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?")),n},h.getHashByUrl=function(e){var t=String(e).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");return t=h.unescapeHash(t),t},h.setTitle=function(e){var t=e.title,n;t||(n=h.getStateByIndex(0),n&&n.url===e.url&&(t=n.title||h.options.initialTitle));try{r.getElementsByTagName("title")[0].innerHTML=t.replace("<","&lt;").replace(">","&gt;").replace(" & "," &amp; ")}catch(i){}return r.title=t,h},h.queues=[],h.busy=function(e){typeof e!="undefined"?h.busy.flag=e:typeof h.busy.flag=="undefined"&&(h.busy.flag=!1);if(!h.busy.flag){u(h.busy.timeout);var t=function(){var e,n,r;if(h.busy.flag)return;for(e=h.queues.length-1;e>=0;--e){n=h.queues[e];if(n.length===0)continue;r=n.shift(),h.fireQueueItem(r),h.busy.timeout=o(t,h.options.busyDelay)}};h.busy.timeout=o(t,h.options.busyDelay)}return h.busy.flag},h.busy.flag=!1,h.fireQueueItem=function(e){return e.callback.apply(e.scope||h,e.args||[])},h.pushQueue=function(e){return h.queues[e.queue||0]=h.queues[e.queue||0]||[],h.queues[e.queue||0].push(e),h},h.queue=function(e,t){return typeof e=="function"&&(e={callback:e}),typeof t!="undefined"&&(e.queue=t),h.busy()?h.pushQueue(e):h.fireQueueItem(e),h},h.clearQueue=function(){return h.busy.flag=!1,h.queues=[],h},h.stateChanged=!1,h.doubleChecker=!1,h.doubleCheckComplete=function(){return h.stateChanged=!0,h.doubleCheckClear(),h},h.doubleCheckClear=function(){return h.doubleChecker&&(u(h.doubleChecker),h.doubleChecker=!1),h},h.doubleCheck=function(e){return h.stateChanged=!1,h.doubleCheckClear(),h.bugs.ieDoubleCheck&&(h.doubleChecker=o(function(){return h.doubleCheckClear(),h.stateChanged||e(),!0},h.options.doubleCheckInterval)),h},h.safariStatePoll=function(){var t=h.extractState(h.getLocationHref()),n;if(!h.isLastSavedState(t))return n=t,n||(n=h.createStateObject()),h.Adapter.trigger(e,"popstate"),h;return},h.back=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.back,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.back(!1)}),p.go(-1),!0)},h.forward=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.forward,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.forward(!1)}),p.go(1),!0)},h.go=function(e,t){var n;if(e>0)for(n=1;n<=e;++n)h.forward(t);else{if(!(e<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(n=-1;n>=e;--n)h.back(t)}return h};if(h.emulated.pushState){var v=function(){};h.pushState=h.pushState||v,h.replaceState=h.replaceState||v}else h.onPopState=function(t,n){var r=!1,i=!1,s,o;return h.doubleCheckComplete(),s=h.getHash(),s?(o=h.extractState(s||h.getLocationHref(),!0),o?h.replaceState(o.data,o.title,o.url,!1):(h.Adapter.trigger(e,"anchorchange"),h.busy(!1)),h.expectedStateId=!1,!1):(r=h.Adapter.extractEventData("state",t,n)||!1,r?i=h.getStateById(r):h.expectedStateId?i=h.getStateById(h.expectedStateId):i=h.extractState(h.getLocationHref()),i||(i=h.createStateObject(null,null,h.getLocationHref())),h.expectedStateId=!1,h.isLastSavedState(i)?(h.busy(!1),!1):(h.storeState(i),h.saveState(i),h.setTitle(i),h.Adapter.trigger(e,"statechange"),h.busy(!1),!0))},h.Adapter.bind(e,"popstate",h.onPopState),h.pushState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.pushState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.pushState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0},h.replaceState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.replaceState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.replaceState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0};if(s){try{h.store=l.parse(s.getItem("History.store"))||{}}catch(m){h.store={}}h.normalizeStore()}else h.store={},h.normalizeStore();h.Adapter.bind(e,"unload",h.clearAllIntervals),h.saveState(h.storeState(h.extractState(h.getLocationHref(),!0))),s&&(h.onUnload=function(){var e,t,n;try{e=l.parse(s.getItem("History.store"))||{}}catch(r){e={}}e.idToState=e.idToState||{},e.urlToId=e.urlToId||{},e.stateToId=e.stateToId||{};for(t in h.idToState){if(!h.idToState.hasOwnProperty(t))continue;e.idToState[t]=h.idToState[t]}for(t in h.urlToId){if(!h.urlToId.hasOwnProperty(t))continue;e.urlToId[t]=h.urlToId[t]}for(t in h.stateToId){if(!h.stateToId.hasOwnProperty(t))continue;e.stateToId[t]=h.stateToId[t]}h.store=e,h.normalizeStore(),n=l.stringify(e);try{s.setItem("History.store",n)}catch(i){if(i.code!==DOMException.QUOTA_EXCEEDED_ERR)throw i;s.length&&(s.removeItem("History.store"),s.setItem("History.store",n))}},h.intervalList.push(a(h.onUnload,h.options.storeInterval)),h.Adapter.bind(e,"beforeunload",h.onUnload),h.Adapter.bind(e,"unload",h.onUnload));if(!h.emulated.pushState){h.bugs.safariPoll&&h.intervalList.push(a(h.safariStatePoll,h.options.safariPollInterval));if(i.vendor==="Apple Computer, Inc."||(i.appCodeName||"")==="Mozilla")h.Adapter.bind(e,"hashchange",function(){h.Adapter.trigger(e,"popstate")}),h.getHash()&&h.Adapter.onDomLoad(function(){h.Adapter.trigger(e,"hashchange")})}},(!h.options||!h.options.delayInit)&&h.init()}(window)
\ No newline at end of file
......@@ -3,7 +3,6 @@
// }
html, body {
background: $body-bg;
font-family: $sans-serif;
font-size: 1em;
font-style: normal;
......@@ -11,6 +10,14 @@ html, body {
//-webkit-font-smoothing: antialiased;
}
html{
background: white;
}
body {
background: $body-bg;
}
h1, h2, h3, h4, h5, h6 {
color: $base-font-color;
font: normal 1.2em/1.2em $serif;
......
......@@ -68,18 +68,18 @@ $white-t1: rgba($white, 0.25);
$white-t2: rgba($white, 0.5);
$white-t3: rgba($white, 0.75);
$gray: rgb(127,127,127);
$gray-l1: tint($gray,20%);
$gray-l2: tint($gray,40%);
$gray-l3: tint($gray,60%); // #cbcbcb;
$gray-l4: tint($gray,80%); // #e5e5e5;
$gray-l5: tint($gray,90%); // #f2f2f2;
$gray-l6: tint($gray,95%); // #f8f8f8;
$gray-l7: tint($gray,99%);
$gray-d1: shade($gray,20%);
$gray-d2: shade($gray,40%);
$gray-d3: shade($gray,60%);
$gray-d4: shade($gray,80%);
$gray: rgb(127,127,127); // #7f7f7f
$gray-l1: tint($gray,20%); // #989898
$gray-l2: tint($gray,40%); // #b2b2b2
$gray-l3: tint($gray,60%); // #cbcbcb
$gray-l4: tint($gray,80%); // #e5e5e5
$gray-l5: tint($gray,90%); // #f2f2f2
$gray-l6: tint($gray,95%); // #f8f8f8
$gray-l7: tint($gray,99%); // #fdfdfd
$gray-d1: shade($gray,20%); // #656565
$gray-d2: shade($gray,40%); // #4c4c4c
$gray-d3: shade($gray,60%); // #323232
$gray-d4: shade($gray,80%); // #191919
$pink: rgb(182,37,103);
$pink-l1: tint($pink,20%);
......@@ -175,11 +175,13 @@ $m-blue-l2: #42B5E9;
$m-blue-l3: #59BEEC;
$m-blue-l4: tint($m-blue,90%);
$m-blue-l5: tint($m-blue,95%);
$m-blue-l6: #4bb4fb;
$m-blue-d1: #1790C7;
$m-blue-d2: #1580B0;
$m-blue-d3: #126F9A;
$m-blue-d4: #0A4A67;
$m-blue-d5: #009EE7;
$m-blue-d6: #256A97;
$m-blue-t0: rgba($m-blue,0.125);
$m-blue-t1: rgba($m-blue,0.25);
$m-blue-t2: rgba($m-blue,0.50);
......
......@@ -18,6 +18,10 @@
line-height: lh(1);
}
$sm-btn-google: #dd4b39;
$sm-btn-facebook: #3b5998;
$sm-btn-linkedin: #0077b5;
.section-bkg-wrapper {
background: $m-gray-l4;
}
......@@ -27,7 +31,7 @@
@include outer-container;
$grid-columns: 12;
background: white;
min-height: 100%;
width: 100%;
h2 {
......@@ -81,26 +85,84 @@
}
}
.form-toggle {
margin: 0;
form {
border: 1px solid $gray-l4;
border-radius: 5px;
padding: 0 25px;
}
.form-type {
@include box-sizing(border-box);
@include span-columns(12);
padding: 25px 10px;
.section-title {
position: relative;
height: 16px;
margin: 20px 0 10px;
&.lines {
margin-bottom: 20px;
&:nth-of-type(2) {
border-bottom: 1px solid $gray-l4;
&:after {
content: '';
width: 100%;
height: 1px;
background: $gray-l4;
position: absolute;
left: 0;
top: 12px;
z-index: 5;
}
}
h2 {
text-align: center;
.text {
position: relative;
background: white;
padding: 0 10px;
z-index: 10;
text-transform: none;
font-size: 0.7em;
font-weight: 600;
}
}
}
.nav-btn {
margin: 0 28px;
padding: 7px 0;
width: calc( 100% - 56px );
border: 3px solid $m-blue-d5;
border-radius: 5px;
color: $m-blue-d5;
box-shadow: none;
text-shadow: none;
text-transform: none;
background: white;
&:hover {
background: white;
border-color: $m-blue-d6;
color: $m-blue-d6;
}
&:active {
box-shadow: none;
}
}
.form-type {
@include box-sizing(border-box);
width: 330px;
margin: 0 auto;
}
.note {
@extend %t-copy-sub2;
display: block;
font-weight: normal;
color: $gray;
margin-top: 15px;
margin: 10px;
color: $m-gray-l1;
text-align: center;
}
......@@ -118,6 +180,10 @@
margin-bottom: 20px;
}
.password-reset-form {
padding-bottom: 25px;
}
%bold-label {
@include font-size(16);
font-family: $sans-serif;
......@@ -133,8 +199,11 @@
}
.action-label {
@extend %bold-label;
margin-bottom: 20px;
@include font-size(13);
font-family: $sans-serif;
font-weight: regular;
font-style: normal;
text-transform: none;
}
.form-field {
......@@ -142,7 +211,18 @@
clear: both;
position: relative;
width: 100%;
margin: 0 0 $baseline 0;
margin: 0 0 5px 0;
&.select-gender {
margin-right: 20px;
}
&.select-gender,
&.select-year_of_birth {
width: calc( 50% - 10px );
float: left;
clear: none;
}
/** FROM _accounts.scss - start **/
label,
......@@ -153,12 +233,14 @@
font-family: $sans-serif;
font-style: normal;
font-weight: 500;
font-size: 0.8em;
line-height: 1.5em;
color: $base-font-color;
}
label {
@include transition(color 0.15s ease-in-out 0s);
margin: 0 0 ($baseline/4) 0;
margin: 0 0 6px 0;
color: tint($black, 20%);
font-weight: $font-semibold;
......@@ -170,14 +252,23 @@
color: $red;
}
&[for="register-honor_code"] {
display: block;
margin: -30px 5% 15px;
width: 90%;
text-align: center;
}
a {
font-family: $sans-serif;
}
}
.field-link {
position: relative;
color: $link-color-d1;
position: absolute;
top: 0;
right: 0;
color: $m-blue-d5;
font-weight: $font-regular;
text-decoration: none !important; // needed but nasty
font-family: $sans-serif;
......@@ -189,8 +280,8 @@
textarea {
display: block;
width: 100%;
margin: 0;
padding: ($baseline/2) ($baseline*.75);
margin: 0 0 5px;
padding: 0 ($baseline/2);
&.long {
width: 100%;
......@@ -211,8 +302,16 @@
}
}
textarea.long {
height: ($baseline*5);
input {
height: 32px;
}
textarea {
resize: none;
&.long {
height: ($baseline*5);
}
}
select {
......@@ -242,56 +341,122 @@
}
.action-primary {
@extend %m-btn-primary;
width: 100%;
height: 38px;
text-transform: none;
color: white;
background: $m-blue-d5;
border: 3px solid $m-blue-d6;
border-radius: 5px;
box-shadow: none;
font-weight: 600;
text-shadow: none;
&:hover,
&:focus {
background: $m-blue-l6;
}
&:active {
box-shadow: none;
}
}
.login-provider {
@extend %btn-secondary-blue-outline;
width: 100%;
margin-bottom: 20px;
@extend %btn-secondary-grey-outline;
width: 130px;
padding: 0 0 0 40px;
height: 34px;
text-align: left;
text-shadow: none;
text-transform: none;
position: relative;
font-size: 0.8em;
border-color: $lightGrey1;
&:nth-of-type(odd) {
margin-right: 13px;
}
.icon {
color: inherit;
margin-right: $baseline/2;
color: white;
position: absolute;
top: -1px;
left: 0;
width: 30px;
height: 34px;
line-height: 34px;
text-align: center;
}
&:hover,
&:focus {
.icon {
height: 32px;
line-height: 32px;
top: 0;
}
}
&:last-child {
margin-bottom: 20px;
}
&.button-Google:hover,
&.button-Google:focus {
background-color: #dd4b39;
border: 1px solid #A5382B;
}
&.button-Google {
color: $sm-btn-google;
&.button-Google:hover {
box-shadow: 0 2px 1px 0 #8D3024;
}
.icon {
background: $sm-btn-google;
}
&.button-Facebook:hover,
&.button-Facebook:focus {
background-color: #3b5998;
border: 1px solid #263A62;
}
&:hover,
&:focus {
background-color: $sm-btn-google;
border: 1px solid #A5382B;
color: white;
}
&.button-Facebook:hover {
box-shadow: 0 2px 1px 0 #30487C;
&:hover {
box-shadow: 0 2px 1px 0 #8D3024;
}
}
&.button-LinkedIn:hover,
&.button-LinkedIn:focus {
background-color: #0077b5;
border: 1px solid #06527D;
&.button-Facebook {
color: $sm-btn-facebook;
.icon {
background: $sm-btn-facebook;
}
&:hover,
&:focus {
background-color: $sm-btn-facebook;
border: 1px solid #263A62;
color: white;
}
&:hover {
box-shadow: 0 2px 1px 0 #30487C;
}
}
&.button-LinkedIn:hover {
box-shadow: 0 2px 1px 0 #005D8E;
&.button-LinkedIn {
color: $sm-btn-linkedin;
.icon {
background: $sm-btn-linkedin;
}
&:hover,
&:focus {
background-color: $sm-btn-linkedin;
border: 1px solid #06527D;
color: white;
}
&:hover {
box-shadow: 0 2px 1px 0 #005D8E;
}
}
}
......@@ -299,9 +464,9 @@
/** Error Container - from _account.scss **/
.status {
@include box-sizing(border-box);
margin: 0 0 $baseline 0;
margin: 0 0 25px 0;
border-bottom: 3px solid shade($yellow, 10%);
padding: $baseline $baseline;
padding: 25px;
background: tint($yellow,20%);
.message-title {
......@@ -312,15 +477,15 @@
font-weight: 600;
}
.message-copy {
.message-copy,
.message-copy p {
@extend %body-text;
font-family: $sans-serif;
margin: 0 !important;
padding: 0;
list-style: none;
li {
margin: 0 0 ($baseline/4) 0;
margin: 0 0 ($baseline/4) $baseline;
}
}
}
......@@ -353,100 +518,15 @@
}
}
/** RWD **/
@include media( $tablet ) {
$grid-columns: 8;
%inline-form-field-tablet {
clear: none;
display: inline-block;
float: left;
}
.header .headline,
.header .tagline,
@include media( max-width 330px) {
.form-type {
@include span-columns(6);
@include shift(1);
}
.form-toggle {
margin-right: 5px;
}
.form-field {
&.select-gender {
@extend %inline-form-field-tablet;
width: calc( 50% - 10px );
margin-right: 20px;
}
&.select-year_of_birth {
@extend %inline-form-field-tablet;
width: calc( 50% - 10px );
}
.field-link {
position: absolute;
top: 0;
right: 0;
}
}
}
@include media( $desktop ) {
$grid-columns: 12;
%inline-form-field-desktop {
clear: none;
display: inline-block;
float: left;
}
.header .headline,
.header .tagline,
.form-type {
width: 600px;
margin-left: calc( 50% - 300px );
margin-right: calc( 50% - 300px );
}
.form-toggle {
margin-right: 10px;
}
.form-field {
&.select-level_of_education {
@extend %inline-form-field-desktop;
width: 300px;
margin-right: 20px;
}
&.select-gender {
@extend %inline-form-field-desktop;
width: 60px;
margin-right: 20px;
}
&.select-year_of_birth {
@extend %inline-form-field-desktop;
width: 100px;
}
.field-link {
position: absolute;
top: 0;
right: 0;
}
width: 98%;
margin: 0 1%;
}
.login-provider {
@include span-columns(6);
/* Node uses last-child which is not specific enough */
&:nth-of-type(2n) {
margin-right: 0;
}
width: 100%;
margin: 10px 0;
}
}
}
......@@ -97,7 +97,6 @@
header_extra_file = 'theme-head-extra.html'
header_file = 'theme-header.html'
google_analytics_file = 'theme-google-analytics.html'
footer_file = 'theme-footer.html'
style_overrides_file = None
......@@ -111,12 +110,6 @@
google_analytics_file = microsite.get_template_path('google_analytics.html')
if settings.FEATURES['IS_EDX_DOMAIN'] and not is_microsite():
footer_file = microsite.get_template_path('footer-edx-new.html')
else:
footer_file = microsite.get_template_path('footer.html')
style_overrides_file = microsite.get_value('css_overrides_file')
%>
......@@ -136,7 +129,6 @@
<%include file="${google_analytics_file}" />
% if style_overrides_file:
<link rel="stylesheet" type="text/css" href="${static.url(style_overrides_file)}" />
% endif
......@@ -149,18 +141,25 @@
<%include file="mathjax_accessible.html" />
% if not suppress_toplevel_navigation:
<%include file="${header_file}" />
%endif
<div class="content-wrapper" id="content">
${self.body()}
<%block name="bodyextra"/>
</div>
% if not suppress_toplevel_navigation:
<%include file="${footer_file}" />
% endif
<%block name="footer">
## Can be overridden by child templates wanting to hide the footer.
<%
if theme_enabled() and not is_microsite():
footer_file = 'theme-footer.html'
elif settings.FEATURES['IS_EDX_DOMAIN'] and not is_microsite():
footer_file = microsite.get_template_path('footer-edx-new.html')
else:
footer_file = microsite.get_template_path('footer.html')
%>
<%include file="${footer_file}" />
</%block>
</div>
......
......@@ -80,7 +80,7 @@ site_status_msg = get_site_status_msg(course_id)
<li><a href="${marketing_link('FAQ')}">${_("Help")}</a></li>
% endif
</%block>
<li><a href="${reverse('logout')}" role="menuitem">${_("Log Out")}</a></li>
<li><a href="${reverse('logout')}" role="menuitem">${_("Sign out")}</a></li>
</ul>
</li>
</ol>
......@@ -126,9 +126,9 @@ site_status_msg = get_site_status_msg(course_id)
<div class="nav-courseware-02">
% if not settings.FEATURES['DISABLE_LOGIN_BUTTON']:
% if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain:
<a class="cta cta-login nav-courseware-button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Log in")}</a>
<a class="cta cta-login nav-courseware-button" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
% else:
<a class="cta cta-login nav-courseware-button" href="/login${login_query()}">${_("Log in")}</a>
<a class="cta cta-login nav-courseware-button" href="/login${login_query()}">${_("Sign in")}</a>
% endif
% endif
</div>
......
......@@ -75,7 +75,7 @@ site_status_msg = get_site_status_msg(course_id)
<li><a href="${marketing_link('FAQ')}">${_("Help")}</a></li>
% endif
</%block>
<li><a href="${reverse('logout')}" role="menuitem">${_("Log Out")}</a></li>
<li><a href="${reverse('logout')}" role="menuitem">${_("Sign out")}</a></li>
</ul>
</li>
</ol>
......@@ -120,9 +120,9 @@ site_status_msg = get_site_status_msg(course_id)
<li class="nav-courseware-01">
% if not settings.FEATURES['DISABLE_LOGIN_BUTTON']:
% if course and settings.FEATURES.get('RESTRICT_ENROLL_BY_REG_METHOD') and course.enrollment_domain:
<a class="cta cta-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Log in")}</a>
<a class="cta cta-login" href="${reverse('course-specific-login', args=[course.id.to_deprecated_string()])}${login_query()}">${_("Sign in")}</a>
% else:
<a class="cta cta-login" href="/login${login_query()}">${_("Log in")}</a>
<a class="cta cta-login" href="/login${login_query()}">${_("Sign in")}</a>
% endif
% endif
</li>
......
<header class="js-login-register-header header">
<h1 class="headline"><%- gettext("Welcome!") %></h1>
<p class="tagline"><%- gettext("Log in or register to take courses from the world's best universities.") %></p>
</header>
<section id="form-load-fail" class="form-type hidden" aria-hidden="true">
<section id="form-load-fail" class="form-type hidden">
<div class="status submission-error">
<p class="message-copy"><%- gettext("Sorry, we're having some technical problems. Wait a few minutes and try again.") %></p>
</div>
</section>
<% if ( mode === 'login' ) { %>
<section id="register-anchor" class="form-type">
<span>
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
<label for="register-option" class="form-label"><%- gettext("I am a new user") %></label>
</span>
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden" aria-hidden="true<% } %>"></div>
</section>
<% } %>
<section id="login-anchor" class="form-type">
<span>
<input type="radio" name="form" id="login-option" value="login" class="form-toggle" <% if ( mode === 'login' ) { %>checked<% } %>>
<label for="login-option" class="form-label"><%- gettext("I am a returning user") %></label>
</span>
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden" aria-hidden="true<% } %>"></div>
<div id="login-form" class="form-wrapper <% if ( mode !== 'login' ) { %>hidden<% } %>"></div>
</section>
<% if ( mode === 'register' ) { %>
<section id="register-anchor" class="form-type">
<span>
<input type="radio" name="form" id="register-option" value="register" class="form-toggle" <% if ( mode === 'register' ) { %>checked<% } %> >
<label for="register-option" class="form-label"><%- gettext("I am a new user") %></label>
</span>
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden" aria-hidden="true<% } %>"></div>
</section>
<% } %>
<section id="register-anchor" class="form-type">
<div id="register-form" class="form-wrapper <% if ( mode !== 'register' ) { %>hidden<% } %>"></div>
</section>
<div id="password-reset-wrapper"></div>
\ No newline at end of file
<section id="password-reset-anchor" class="form-type">
<div id="password-reset-form" class="form-wrapper hidden" aria-hidden="true"></div>
</section>
......@@ -11,6 +11,11 @@
name="<%= name %>"
class="input-inline"
aria-describedby="<%= form %>-<%= name %>-desc"
<% if ( typeof errorMessages !== 'undefined' ) {
_.each(errorMessages, function( msg, type ) {%>
data-errormsg-<%= type %>="<%= msg %>"
<% });
} %>
<% if ( required ) { %> aria-required="true" required<% } %>>
<% _.each(options, function(el) { %>
<option value="<%= el.value%>"<% if ( el.default ) { %> data-isdefault="true"<% } %>><%= el.name %></option>
......@@ -49,7 +54,7 @@
<% } %>
<% if ( type === 'checkbox' ) { %>
<label for="<%= form %>-<%= name %>" class="inline">
<label for="<%= form %>-<%= name %>">
<%= label %>
<% if ( required && requiredStr ) { %> <%= requiredStr %><% } %>
</label>
......@@ -58,6 +63,4 @@
<% if( form === 'login' && name === 'password' ) { %>
<a href="#" class="forgot-password field-link"><%- gettext("Forgot password?") %></a>
<% } %>
<span id="<%= form %>-<%= name %>-desc" class="desc"><%= instructions %></span>
</p>
<form id="login" class="login-form">
<div class="status already-authenticated-msg hidden" aria-hidden="true">
<% if (context.currentProvider) { %>
<p class="message-copy">
<%- _.sprintf(gettext("You've successfully logged into %(currentProvider)s, but your %(currentProvider)s account isn't linked with an %(platformName)s account. To link your accounts, go to your %(platformName)s dashboard."), context) %>
</p>
<% } %>
<div class="status already-authenticated-msg hidden">
<% if (context.currentProvider) { %>
<p class="message-copy">
<%- _.sprintf( gettext("You've successfully signed into %(currentProvider)s, but your %(currentProvider)s account isn't linked with an %(platformName)s account. To link your accounts, go to your %(platformName)s dashboard."), context ) %>
</p>
<% } %>
</div>
<div class="js-reset-success status submission-success hidden">
<h4 class="message-title"><%- gettext("Password Reset Email Sent") %></h4>
<div class="message-copy">
<p>
<%- gettext("We've sent instructions for resetting your password to the email address you provided.") %>
</p>
</div>
</div>
<div class="status submission-error hidden" aria-live="polite">
<h4 class="message-title"><%- gettext("We couldn't sign you in.") %></h4>
<ul class="message-copy"></ul>
</div>
<form id="login" class="login-form">
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
<h4 class="message-title"><%- gettext("We couldn't log you in.") %></h4>
<ul class="message-copy"></ul>
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("Sign in") %></span>
</h2>
</div>
<%= context.fields %>
<button class="action action-primary action-update js-login login-button"><%- gettext("Log in") %></button>
<button class="action action-primary action-update js-login login-button"><%- gettext("Sign in") %></button>
<div class="login-providers">
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("or sign in with") %></span>
</h2>
</div>
<% _.each( context.providers, function( provider ) {
if ( provider.loginUrl ) { %>
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider login-<%- provider.name %>" data-provider-url="<%- provider.loginUrl %>">
<div class="icon <%- provider.iconClass %>" aria-hidden="true"></div>
<%- provider.name %>
</button>
<% }
}); %>
</div>
</form>
<% _.each( context.providers, function( provider ) {
if ( provider.loginUrl ) { %>
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider login-<%- provider.name %>" data-provider-url="<%- provider.loginUrl %>">
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
<%- _.sprintf(gettext("Log in using %(name)s"), provider) %>
</button>
<% }
}); %>
<div class="toggle-form">
<div class="section-title">
<h2>
<span class="text"><%- _.sprintf( gettext("New to %(platformName)s?"), context ) %></span>
</h2>
</div>
<button class="nav-btn form-toggle" data-type="register"><%- gettext("Create an account") %></button>
</div>
......@@ -3,13 +3,14 @@
<%inherit file="../main.html" />
<%block name="pagetitle">${_("Log in or Register")}</%block>
<%block name="pagetitle">${_("Sign in or Register")}</%block>
<%block name="js_extra">
<script src="${static.url('js/vendor/underscore-min.js')}"></script>
<script src="${static.url('js/vendor/underscore.string.min.js')}"></script>
<script src="${static.url('js/vendor/backbone-min.js')}"></script>
<script src="${static.url('js/vendor/url.min.js')}"></script>
<script src="${static.url('js/vendor/history.js')}"></script>
<%static:js group='student_account'/>
</%block>
......@@ -29,3 +30,10 @@
data-platform-name='${platform_name}'
/>
</div>
% if settings.FEATURES.get('ENABLE_COMBINED_LOGIN_REGISTRATION'):
## This overwrites the "footer" block declared in main.html
## with an empty block, effectively hiding the footer
## from logistration pages.
<%block name="footer"/>
% endif
<header class="header">
<h1 class="headline"><%- gettext("Reset Password") %></h1>
</header>
<div class="status submission-error hidden" aria-live="polite">
<h4 class="message-title"><%- gettext("An error occurred.") %></h4>
<ul class="message-copy"></ul>
</div>
<section class="form-type">
<div id="password-reset-form" class="form-wrapper">
<p class="action-label"><%- gettext("Enter the email address you used to create your account. We'll send you a link you can use to reset your password.") %></p>
<form id="password-reset-form">
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
<h4 class="message-title"><%- gettext("An error occurred.") %></h4>
<ul class="message-copy"></ul>
</div>
<form id="password-reset" class="password-reset-form">
<%= fields %>
<button class="action action-primary action-update js-reset"><%- gettext("Reset password") %></button>
</form>
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("Password assistance") %></span>
</h2>
</div>
<div class="js-reset-success status submission-success hidden" aria-hidden="true">
<h4 class="message-title"><%- gettext("Password Reset Email Sent") %></h4>
<div class="message-copy">
<p>
<%- gettext("We've sent instructions for resetting your password to the email address you provided.") %>
</p>
</div>
</div>
</section>
<p class="action-label"><%- gettext("Please enter your email address below and we will send you instructions for setting a new password.") %></p>
<%= fields %>
<button class="action action-primary action-update js-reset"><%- gettext("Reset my password") %></button>
</form>
<% if (context.currentProvider) { %>
<div class="status" aria-hidden="false">
<p class="message-copy">
<%- _.sprintf(gettext("You've successfully logged into %(currentProvider)s."), context) %>
<%- _.sprintf(gettext("We just need a little more information before you start learning with %(platformName)s."), context) %>
</p>
</div>
<% } else {
_.each( context.providers, function( provider) {
if ( provider.registerUrl ) { %>
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider register-<%- provider.name %>" data-provider-url="<%- provider.registerUrl %>">
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
<%- _.sprintf(gettext("Register using %(name)s"), provider) %>
</button>
<% }
});
} %>
<div class="status submission-error hidden" aria-live="polite">
<h4 class="message-title"><%- gettext("We couldn't create your account.") %></h4>
<ul class="message-copy"></ul>
</div>
<form id="register" autocomplete="off">
<div class="status submission-error hidden" aria-hidden="true" aria-live="polite">
<h4 class="message-title"><%- gettext("We couldn't complete your registration.") %></h4>
<ul class="message-copy"></ul>
<% if (context.currentProvider) { %>
<div class="status" aria-hidden="false">
<p class="message-copy">
<%- _.sprintf( gettext("You've successfully signed into %(currentProvider)s."), context ) %>
<%- _.sprintf( gettext("We just need a little more information before you start learning with %(platformName)s."), context ) %>
</p>
</div>
<% } else { %>
<div class="login-providers">
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("Create an account using") %></span>
</h2>
</div>
<%
_.each( context.providers, function( provider) {
if ( provider.registerUrl ) { %>
<button type="submit" class="button button-primary button-<%- provider.name %> login-provider register-<%- provider.name %>" data-provider-url="<%- provider.registerUrl %>">
<span class="icon <%- provider.iconClass %>" aria-hidden="true"></span>
<%- provider.name %>
</button>
<% }
}); %>
</div>
<% } %>
<div class="section-title lines">
<h2>
<span class="text"><%- gettext("or create a new one here") %></span>
</h2>
</div>
<%= context.fields %>
<button class="action action-primary action-update js-register register-button"><%- gettext("Register") %></button>
<button class="action action-primary action-update js-register register-button"><%- gettext("Create your account") %></button>
<p class="note">* <%- gettext("Required field") %></p>
</form>
<div class="toggle-form">
<div class="section-title">
<h2>
<span class="text"><%- gettext("Already have an account?") %></span>
</h2>
</div>
<button class="nav-btn form-toggle" data-type="login"><%- gettext("Sign in") %></button>
</div>
......@@ -633,17 +633,6 @@ class LoginSessionViewTest(ApiTestCase):
"max_length": account_api.PASSWORD_MAX_LENGTH
},
"errorMessages": {},
},
{
"name": "remember",
"defaultValue": False,
"type": "checkbox",
"required": False,
"label": "Remember me",
"placeholder": "",
"instructions": "",
"restrictions": {},
"errorMessages": {},
}
])
......@@ -847,7 +836,7 @@ class RegistrationViewTest(ApiTestCase):
u"name": u"name",
u"type": u"text",
u"required": True,
u"label": u"Full Name",
u"label": u"Full name",
u"instructions": u"The name that will appear on your certificates",
u"restrictions": {
"max_length": profile_api.FULL_NAME_MAX_LENGTH,
......@@ -861,7 +850,7 @@ class RegistrationViewTest(ApiTestCase):
u"name": u"username",
u"type": u"text",
u"required": True,
u"label": u"Username",
u"label": u"Public username",
u"instructions": u"The name that will identify you in your courses",
u"restrictions": {
"min_length": account_api.USERNAME_MIN_LENGTH,
......@@ -927,7 +916,7 @@ class RegistrationViewTest(ApiTestCase):
u"defaultValue": u"Bob",
u"type": u"text",
u"required": True,
u"label": u"Full Name",
u"label": u"Full name",
u"instructions": u"The name that will appear on your certificates",
u"restrictions": {
"max_length": profile_api.FULL_NAME_MAX_LENGTH
......@@ -943,7 +932,7 @@ class RegistrationViewTest(ApiTestCase):
u"defaultValue": u"Bob123",
u"type": u"text",
u"required": True,
u"label": u"Username",
u"label": u"Public username",
u"placeholder": u"",
u"instructions": u"The name that will identify you in your courses",
u"restrictions": {
......@@ -960,7 +949,7 @@ class RegistrationViewTest(ApiTestCase):
"name": "level_of_education",
"type": "select",
"required": False,
"label": "Highest Level of Education Completed",
"label": "Highest level of education completed",
"options": [
{"value": "", "name": "--", "default": True},
{"value": "p", "name": "Doctorate"},
......@@ -1007,7 +996,7 @@ class RegistrationViewTest(ApiTestCase):
"name": "year_of_birth",
"type": "select",
"required": False,
"label": "Year of Birth",
"label": "Year of birth",
"options": year_options,
}
)
......@@ -1019,7 +1008,7 @@ class RegistrationViewTest(ApiTestCase):
"name": "mailing_address",
"type": "textarea",
"required": False,
"label": "Mailing Address",
"label": "Mailing address",
}
)
......@@ -1030,7 +1019,7 @@ class RegistrationViewTest(ApiTestCase):
"name": "goals",
"type": "textarea",
"required": False,
"label": "If you'd like, tell us why you're interested in {platform_name}".format(
"label": "Tell us why you're interested in {platform_name}".format(
platform_name=settings.PLATFORM_NAME
)
}
......@@ -1063,6 +1052,9 @@ class RegistrationViewTest(ApiTestCase):
"type": "select",
"required": True,
"options": country_options,
"errorMessages": {
"required": "Please select your Country."
},
}
)
......@@ -1222,9 +1214,9 @@ class RegistrationViewTest(ApiTestCase):
"password",
"city",
"country",
"level_of_education",
"gender",
"year_of_birth",
"level_of_education",
"mailing_address",
"goals",
"honor_code",
......
......@@ -112,19 +112,6 @@ class LoginSessionView(APIView):
}
)
# Translators: This phrase appears next to a checkbox on the login form
# which the user can check in order to remain logged in after their
# session ends.
remember_label = _(u"Remember me")
form_desc.add_field(
"remember",
field_type="checkbox",
label=remember_label,
default=False,
required=False,
)
return HttpResponse(form_desc.to_json(), content_type="application/json")
@method_decorator(require_post_params(["email", "password"]))
......@@ -171,9 +158,15 @@ class RegistrationView(APIView):
DEFAULT_FIELDS = ["email", "name", "username", "password"]
EXTRA_FIELDS = [
"city", "country", "level_of_education", "gender",
"year_of_birth", "mailing_address", "goals",
"honor_code", "terms_of_service",
"city",
"country",
"gender",
"year_of_birth",
"level_of_education",
"mailing_address",
"goals",
"honor_code",
"terms_of_service",
]
# This end-point is available to anonymous users,
......@@ -348,7 +341,7 @@ class RegistrationView(APIView):
"""
# Translators: This label appears above a field on the registration form
# meant to hold the user's full name.
name_label = _(u"Full Name")
name_label = _(u"Full name")
# Translators: These instructions appear on the registration form, immediately
# below a field meant to hold the user's full name.
......@@ -376,7 +369,7 @@ class RegistrationView(APIView):
"""
# Translators: This label appears above a field on the registration form
# meant to hold the user's public username.
username_label = _(u"Username")
username_label = _(u"Public username")
# Translators: These instructions appear on the registration form, immediately
# below a field meant to hold the user's public username.
......@@ -432,7 +425,7 @@ class RegistrationView(APIView):
"""
# Translators: This label appears above a dropdown menu on the registration
# form used to select the user's highest completed level of education.
education_level_label = _(u"Highest Level of Education Completed")
education_level_label = _(u"Highest level of education completed")
form_desc.add_field(
"level_of_education",
......@@ -478,7 +471,7 @@ class RegistrationView(APIView):
"""
# Translators: This label appears above a dropdown menu on the registration
# form used to select the user's year of birth.
yob_label = _(u"Year of Birth")
yob_label = _(u"Year of birth")
options = [(unicode(year), unicode(year)) for year in UserProfile.VALID_YEARS]
form_desc.add_field(
......@@ -502,7 +495,7 @@ class RegistrationView(APIView):
"""
# Translators: This label appears above a field on the registration form
# meant to hold the user's mailing address.
mailing_address_label = _(u"Mailing Address")
mailing_address_label = _(u"Mailing address")
form_desc.add_field(
"mailing_address",
......@@ -524,7 +517,7 @@ class RegistrationView(APIView):
# Translators: This phrase appears above a field on the registration form
# meant to hold the user's reasons for registering with edX.
goals_label = _(
u"If you'd like, tell us why you're interested in {platform_name}"
u"Tell us why you're interested in {platform_name}"
).format(platform_name=settings.PLATFORM_NAME)
form_desc.add_field(
......@@ -575,13 +568,19 @@ class RegistrationView(APIView):
(country_code, unicode(country_name))
for country_code, country_name in sorted_countries
]
error_msg = _(u"Please select your Country.")
form_desc.add_field(
"country",
label=country_label,
field_type="select",
options=options,
include_default_option=True,
required=required
required=required,
error_messages={
"required": error_msg
}
)
def _add_honor_code_field(self, form_desc, required=True):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment