diff --git a/browserid/compress.sh b/browserid/compress.sh index 8166eeaafec334165353393eb6f98286989f1c82..6872fe9fb50fcb37d9a78df5dd951f5f80003809 100755 --- a/browserid/compress.sh +++ b/browserid/compress.sh @@ -44,7 +44,7 @@ echo '' cd ../js # re-minimize everything together -cat jquery-1.6.2.min.js json2.js browserid.js ../dialog/resources/underscore-min.js ../dialog/resources/storage.js ../dialog/resources/browserid-network.js ../dialog/resources/browserid-identities.js ../dialog/resources/tooltip.js pages/index.js pages/add_email_address.js pages/verify_email_address.js pages/manage_account.js pages/signin.js pages/signup.js pages/forgot.js > lib.js +cat jquery-1.6.2.min.js json2.js browserid.js ../dialog/resources/underscore-min.js ../dialog/resources/storage.js ../dialog/resources/browserid-network.js ../dialog/resources/browserid-identities.js ../dialog/resources/tooltip.js ../dialog/resources/validation.js pages/index.js pages/add_email_address.js pages/verify_email_address.js pages/manage_account.js pages/signin.js pages/signup.js pages/forgot.js > lib.js $UGLIFY < lib.js > lib.min.js cd ../css diff --git a/browserid/static/dialog/controllers/authenticate_controller.js b/browserid/static/dialog/controllers/authenticate_controller.js index 2c1f2145493ac3f5210e7658de404cb8f3dbc911..1472bf4a3e0a56991ed888ba1f71cf1d854acf97 100644 --- a/browserid/static/dialog/controllers/authenticate_controller.js +++ b/browserid/static/dialog/controllers/authenticate_controller.js @@ -39,7 +39,8 @@ var ANIMATION_TIME = 250, bid = BrowserID, - identities = bid.Identities; + identities = bid.Identities, + validation = bid.Validation; function checkEmail(el, event) { var email = $("#email").val(), @@ -47,7 +48,7 @@ cancelEvent(event); - if(!self.validateEmail(email)) { + if(!validation.email(email)) { return; } @@ -67,7 +68,7 @@ cancelEvent(event); - if(!self.validateEmail(email)) { + if(!validation.email(email)) { return; } @@ -91,12 +92,7 @@ cancelEvent(event); - if(!self.validateEmail(email)) { - return; - } - - if(!pass) { - bid.Tooltip.showTooltip("#password_required"); + if(!validation.emailAndPassword(email, pass)) { return; } diff --git a/browserid/static/dialog/controllers/page_controller.js b/browserid/static/dialog/controllers/page_controller.js index a63ea765c773d47204be28d0e671e12b18dc1bf0..aee8e85b1005e935fed0c8e3bad4b572a5092b30 100644 --- a/browserid/static/dialog/controllers/page_controller.js +++ b/browserid/static/dialog/controllers/page_controller.js @@ -41,21 +41,6 @@ identities = bid.Identities; - function validateEmail(email) { - var valid = true; - - if(!email) { - bid.Tooltip.showTooltip("#email_required"); - valid = false; - } - else if(!bid.verifyEmail(email)) { - bid.Tooltip.showTooltip("#email_format"); - valid = false; - } - - return valid; - } - $.Controller.extend("PageController", { }, { init: function(options) { @@ -165,9 +150,7 @@ event.preventDefault(); event.stopPropagation(); this.close("start"); - }, - - validateEmail: validateEmail + } }); }()); diff --git a/browserid/static/dialog/controllers/pickemail_controller.js b/browserid/static/dialog/controllers/pickemail_controller.js index caf7f1e732a44eaf735272bf772a60e6b01bc628..fc4cb138e1c654a0cf42aebc51aa2d96806cf4e4 100644 --- a/browserid/static/dialog/controllers/pickemail_controller.js +++ b/browserid/static/dialog/controllers/pickemail_controller.js @@ -123,7 +123,7 @@ cancelEvent(event); - if(!self.validateEmail(email)) { + if(!bid.Validation.email(email)) { return; } diff --git a/browserid/static/dialog/css/popup.css b/browserid/static/dialog/css/popup.css index b95a704b08bfdf92e4594f8fed4c1250a963883d..fcd2eb0d195274dd8093d743dc27482030bd0721 100644 --- a/browserid/static/dialog/css/popup.css +++ b/browserid/static/dialog/css/popup.css @@ -504,10 +504,12 @@ html[xmlns] .cf { margin: 1em 0 .5em; padding: 0 1em; line-height: 18px; + min-height: 110px; } .pickemail .inputs { height: 110px; + min-height: 0; overflow-y: auto; } diff --git a/browserid/static/dialog/dialog.js b/browserid/static/dialog/dialog.js index b163ea65e7a40f5dd986644ccaa53b6cbd91db03..061ffa15f97389721b438a9908391395fa04ed7a 100644 --- a/browserid/static/dialog/dialog.js +++ b/browserid/static/dialog/dialog.js @@ -54,6 +54,7 @@ steal.plugins( 'browserid', 'storage', 'tooltip', + 'validation', 'browserid-extensions', 'browserid-network', 'browserid-identities', diff --git a/browserid/static/dialog/resources/browserid.js b/browserid/static/dialog/resources/browserid.js index ad6c7d8de2e010aeb9168400a98d27140d5dffc9..6bc596beb7a51a075dce8b6de7670f7ac18a0e47 100644 --- a/browserid/static/dialog/resources/browserid.js +++ b/browserid/static/dialog/resources/browserid.js @@ -39,11 +39,4 @@ window.BrowserID = window.BrowserID || {}; - window.BrowserID.verifyEmail = function(address) { - // gotten from http://blog.gerv.net/2011/05/html5_email_address_regexp/ - // changed the requirement that there must be a ldh-str because BrowserID - // is only used on internet based networks. - return /^[\w.!#$%&'*+\-/=?\^`{|}~]+@[a-z0-9-]+(\.[a-z0-9-]+)+$/.test(address); - }; - }()); diff --git a/browserid/static/dialog/resources/validation.js b/browserid/static/dialog/resources/validation.js new file mode 100644 index 0000000000000000000000000000000000000000..371f60e4c539dfe3620507eae56ecca511510486 --- /dev/null +++ b/browserid/static/dialog/resources/validation.js @@ -0,0 +1,88 @@ +/*globals BrowserID: true */ +BrowserID.Validation = (function() { + var bid = BrowserID, + tooltip = bid.Tooltip; + + bid.verifyEmail = function(address) { + // gotten from http://blog.gerv.net/2011/05/html5_email_address_regexp/ + // changed the requirement that there must be a ldh-str because BrowserID + // is only used on internet based networks. + return /^[\w.!#$%&'*+\-/=?\^`{|}~]+@[a-z0-9-]+(\.[a-z0-9-]+)+$/.test(address); + }; + + + function validateEmail(email) { + var valid = false; + + if (!email) { + tooltip.showTooltip("#email_required"); + } + else if (!bid.verifyEmail(email)) { + tooltip.showTooltip("#email_format"); + } + else { + valid = true; + } + + return valid; + } + + function validateEmailAndPassword(email, password) { + var valid = validateEmail(email); + + if (valid) { + valid = passwordExists(password); + } + + return valid; + } + + function passwordExists(password) { + var valid = !!password; + + if (!valid) { + tooltip.showTooltip("#password_required"); + } + + return valid; + } + + function passwordLength(password) { + var valid = password && (password.length >= 8); + + if(!valid) { + tooltip.showTooltip("#password_too_short"); + } + + return valid; + } + + function validationPasswordExists(vpass) { + var valid = !!vpass; + + if(!valid) { + tooltip.showTooltip("#vpassword_required"); + } + + return valid; + } + + function passwordAndValidationPassword(pass, vpass) { + var valid = passwordExists(pass) && passwordLength(pass) && validationPasswordExists(vpass); + + if (valid && pass !== vpass) { + valid = false; + tooltip.showTooltip("#passwords_no_match"); + } + + return valid; + } + + return { + email: validateEmail, + emailAndPassword: validateEmailAndPassword, + passwordAndValidationPassword: passwordAndValidationPassword + }; + +}()); + diff --git a/browserid/static/dialog/test/qunit/browserid_unit_test.js b/browserid/static/dialog/test/qunit/browserid_unit_test.js index 14348486a2a4d8589db6218d6c9afe90172603b1..5755fabc56122270993a990e6bea620d0c424eb5 100644 --- a/browserid/static/dialog/test/qunit/browserid_unit_test.js +++ b/browserid/static/dialog/test/qunit/browserid_unit_test.js @@ -39,31 +39,6 @@ steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid", fu module("browserid-unit"); - var bid = BrowserID; - - test("email address x@y.z is valid", function() { - ok(bid.verifyEmail("x@y.z"), "x@y.z is valid"); - }); - - test("email address x@y.z.w is valid", function() { - ok(bid.verifyEmail("x@y.z.w"), "x@y.z.w is valid"); - }); - - test("email address x.v@y.z.w is valid", function() { - ok(bid.verifyEmail("x.v@y.z.w"), "x.v@y.z.w is valid"); - }); - - test("email address x_v@y.z.w is valid", function() { - ok(bid.verifyEmail("x_v@y.z.w"), "x_v@y.z.w is valid"); - }); - - test("email address x is not valid", function() { - equal(bid.verifyEmail("x"), false, "x is not valid"); - }); - - test("email address x@y is not valid", function() { - equal(bid.verifyEmail("x@y"), false, "x@y is not valid"); - }); }); diff --git a/browserid/static/dialog/test/qunit/qunit.js b/browserid/static/dialog/test/qunit/qunit.js index 1faf4244f4b001658ce9191b1ccb1c4edfdb5591..b66d55a29bc6c2832dcd2775d20bffdabe59586e 100644 --- a/browserid/static/dialog/test/qunit/qunit.js +++ b/browserid/static/dialog/test/qunit/qunit.js @@ -1,8 +1,11 @@ steal("/dialog/resources/browserid.js", "/dialog/resources/storage.js", + "/dialog/resources/tooltip.js", + "/dialog/resources/validation.js", "/dialog/resources/underscore-min.js") .plugins("funcunit/qunit") .then("browserid_unit_test") - .then("browserid-storage_unit_test") + .then("validation_unit_test") + .then("storage_unit_test") .then("browserid-network_test") .then("browserid-identities_unit_test") diff --git a/browserid/static/dialog/test/qunit/browserid-storage_unit_test.js b/browserid/static/dialog/test/qunit/storage_unit_test.js similarity index 100% rename from browserid/static/dialog/test/qunit/browserid-storage_unit_test.js rename to browserid/static/dialog/test/qunit/storage_unit_test.js diff --git a/browserid/static/dialog/test/qunit/validation_unit_test.js b/browserid/static/dialog/test/qunit/validation_unit_test.js new file mode 100644 index 0000000000000000000000000000000000000000..5a0be014fb44be2d3ead64b13b6f5126a564d17c --- /dev/null +++ b/browserid/static/dialog/test/qunit/validation_unit_test.js @@ -0,0 +1,181 @@ +/*jshint browsers:true, forin: true, laxbreak: true */ +/*global steal: true, test: true, start: true, stop: true, module: true, ok: true, equal: true, BrowserID: true */ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla BrowserID. + * + * The Initial Developer of the Original Code is Mozilla. + * Portions created by the Initial Developer are Copyright (C) 2011 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ +steal.plugins("jquery", "funcunit/qunit").then("/dialog/resources/browserid", function() { + "use strict"; + + var bid = BrowserID, + validation = bid.Validation, + tooltipShown, + origShowTooltip; + + function showTooltip(el) { + tooltipShown = true; + } + + module("validation-unit", { + setup: function() { + origShowTooltip = bid.Tooltip.showTooltip; + bid.Tooltip.showTooltip = showTooltip; + tooltipShown = false; + }, + + teardown: function() { + bid.Tooltip.showTooltip = origShowTooltip; + } + }); + + test("email address x@y.z is valid", function() { + ok(bid.verifyEmail("x@y.z"), "x@y.z is valid"); + }); + + test("email address x@y.z.w is valid", function() { + ok(bid.verifyEmail("x@y.z.w"), "x@y.z.w is valid"); + }); + + test("email address x.v@y.z.w is valid", function() { + ok(bid.verifyEmail("x.v@y.z.w"), "x.v@y.z.w is valid"); + }); + + test("email address x_v@y.z.w is valid", function() { + ok(bid.verifyEmail("x_v@y.z.w"), "x_v@y.z.w is valid"); + }); + + test("email address x is not valid", function() { + equal(bid.verifyEmail("x"), false, "x is not valid"); + }); + + test("email address x@y is not valid", function() { + equal(bid.verifyEmail("x@y"), false, "x@y is not valid"); + }); + + test("email address x@y. is not valid", function() { + equal(bid.verifyEmail("x@y."), false, "x@y. is not valid"); + }); + + + + test("email with valid email", function() { + var valid = validation.email("testuser@testuser.com"); + + ok(valid, "valid email is valid"); + equal(tooltipShown, false, "valid email shows no tooltip"); + }); + + test("email with empty email", function() { + var valid = validation.email(""); + + equal(valid, valid, "missing email is missing"); + equal(tooltipShown, true, "missing email shows no tooltip"); + }); + + test("email with invalid email", function() { + var valid = validation.email("testuser@testuser"); + + equal(valid, valid, "invalid email is invalid"); + equal(tooltipShown, true, "invalid email shows no tooltip"); + }); + + + test("validateEmailAndPassword with valid email and password", function() { + var valid = validation.emailAndPassword("testuser@testuser.com", "password"); + + ok(valid, "valid email and password are valid"); + equal(tooltipShown, false, "valid email and password shows no tooltip"); + }); + + test("validateEmailAndPassword with empty email", function() { + var valid = validation.emailAndPassword("", "password"); + + equal(valid, false, "empty email is invalid"); + equal(tooltipShown, true, "empty email shows tooltip"); + }); + + test("validateEmailAndPassword with invalid email", function() { + var valid = validation.emailAndPassword("testuser", "password"); + + equal(valid, false, "invalid email is invalid"); + equal(tooltipShown, true, "invalid email shows tooltip"); + }); + + test("validateEmailAndPassword with empty password", function() { + var valid = validation.emailAndPassword("testuser@testuser.com", ""); + + equal(valid, false, "empty password is invalid"); + equal(tooltipShown, true, "empty password shows tooltip"); + }); + + + test("passwordAndValidationPassword with empty password", function() { + var valid = validation.passwordAndValidationPassword("", "password"); + + equal(valid, false, "empty password is invalid"); + equal(tooltipShown, true, "empty password shows tooltip"); + }); + + + test("passwordAndValidationPassword with too short password", function() { + var valid = validation.passwordAndValidationPassword("pass", "password"); + + equal(valid, false, "too short password is invalid"); + equal(tooltipShown, true, "too short password shows tooltip"); + }); + + test("passwordAndValidationPassword with empty validation password", function() { + var valid = validation.passwordAndValidationPassword("password", ""); + + equal(valid, false, "empty validation password is invalid"); + equal(tooltipShown, true, "empty validation password shows tooltip"); + }); + + + test("passwordAndValidationPassword with different validation password", function() { + var valid = validation.passwordAndValidationPassword("password", "pass"); + + equal(valid, false, "different password is invalid"); + equal(tooltipShown, true, "different password shows tooltip"); + }); + + test("passwordAndValidationPassword all valid", function() { + var valid = validation.passwordAndValidationPassword("password", "password"); + + equal(valid, true, "passwords valid"); + equal(tooltipShown, false, "tooltip not shown"); + }); + +}); + + diff --git a/browserid/static/js/pages/signin.js b/browserid/static/js/pages/signin.js index 1afb9d305374daaf9bccbf6507a9abfb3bd1c840..4eca01bd74779481a34a6554104850d85366261f 100644 --- a/browserid/static/js/pages/signin.js +++ b/browserid/static/js/pages/signin.js @@ -37,7 +37,11 @@ (function() { "use strict"; - BrowserID.signIn = function () { + var bid = BrowserID, + network = bid.Network, + validation = bid.Validation; + + bid.signIn = function () { $("form input[autofocus]").focus(); $("#signUpForm").bind("submit", function(event) { @@ -45,18 +49,22 @@ var email = $("#email").val(), password = $("#password").val(); - - BrowserID.Network.authenticate(email, password, function onSuccess(authenticated) { - if (authenticated) { - document.location = "/"; - } - else { - // bad authentication - $(".notifications .notification.doh").fadeIn(); - } - }, function onFailure() { - // Wah wah. Network error - }); + + var valid = validation.emailAndPassword(email, password); + + if (valid) { + network.authenticate(email, password, function onSuccess(authenticated) { + if (authenticated) { + document.location = "/"; + } + else { + // bad authentication + $(".notifications .notification.doh").fadeIn(); + } + }, function onFailure() { + // Wah wah. Network error + }); + } }); }; }()); diff --git a/browserid/static/js/pages/signup.js b/browserid/static/js/pages/signup.js index 7cf7a3cf11cb1e462b8db1df8b3b7762adfca247..b834fcb7046f6f1bd3e9172bf22d722b181bd72e 100644 --- a/browserid/static/js/pages/signup.js +++ b/browserid/static/js/pages/signup.js @@ -37,8 +37,11 @@ (function() { "use strict"; - BrowserID.signUp = function () { - var ANIMATION_SPEED = 250; + var bid = BrowserID, + identities = bid.Identities, + ANIMATION_SPEED = 250; + + bid.signUp = function () { function replaceWithMessage(selector) { $('.forminputs').fadeOut(ANIMATION_SPEED, function() { @@ -56,8 +59,6 @@ $(function () { - var identities = BrowserID.Identities; - $("form input[autofocus]").focus(); $("#email").bind("keyup", function(event) { @@ -69,7 +70,13 @@ $("#signUpForm").bind("submit", function(event) { event.preventDefault(); - var email = $("#email").val(); + var email = $("#email").val(), + valid = bid.Validation.email(email); + + if (!valid) { + return; + } + identities.emailRegistered(email, function(registered) { if (!registered) { identities.createUser(email, function onSuccess(keypair) { diff --git a/browserid/static/js/pages/verify_email_address.js b/browserid/static/js/pages/verify_email_address.js index d4355614066107055f57fcdc97d5ca1a3a152048..07642d077dc1639d25939d9e7510d3f6abc8a578 100644 --- a/browserid/static/js/pages/verify_email_address.js +++ b/browserid/static/js/pages/verify_email_address.js @@ -45,37 +45,14 @@ $("#signUpForm").remove(); } - function validate(pass, vpass) { - var valid = false; - - if(!pass) { - tooltip.showTooltip("#password_required"); - } - else if(pass.length < 8) { - tooltip.showTooltip("#password_too_short"); - } - else if(!vpass) { - tooltip.showTooltip("#vpassword_required"); - } - else if(pass !== vpass) { - tooltip.showTooltip("#passwords_no_match"); - } - else { - valid = true; - } - - return valid; - } - bid.verifyEmailAddress = function(token) { $("#signUpForm").submit(function(event) { event.preventDefault(); - var email = $("#email").val(), - pass = $("#password").val(), + var pass = $("#password").val(), vpass = $("#vpassword").val(); - var valid = validate(pass, vpass); + var valid = bid.Validation.passwordAndValidationPassword(pass, vpass); if (valid) { bid.Network.completeUserRegistration(token, pass, function onSuccess(registered) { diff --git a/browserid/views/layout.ejs b/browserid/views/layout.ejs index 490e5c4659b8b1b4c5cbf9ffd30e9edfb0f7076f..1aa89ac022eb3f4cba986dc6aa5c4bbf76b84b37 100644 --- a/browserid/views/layout.ejs +++ b/browserid/views/layout.ejs @@ -23,6 +23,7 @@ <script src="/dialog/resources/browserid-network.js" type="text/javascript"></script> <script src="/dialog/resources/browserid-identities.js" type="text/javascript"></script> <script src="/dialog/resources/tooltip.js" type="text/javascript"></script> + <script src="/dialog/resources/validation.js" type="text/javascript"></script> <script src="/js/pages/add_email_address.js" type="text/javascript"></script> <script src="/js/pages/verify_email_address.js" type="text/javascript"></script> <script src="/js/pages/forgot.js" type="text/javascript"></script> diff --git a/browserid/views/signin.ejs b/browserid/views/signin.ejs index 10f279a20d053739045245e3267a73def64e40ef..54089605e911f90aa02d54fbdd087e51f17f8548 100644 --- a/browserid/views/signin.ejs +++ b/browserid/views/signin.ejs @@ -1,7 +1,7 @@ <div id="vAlign"> <div id="signUpFormWrap"> <!-- XXX this form submits to nowhere --> - <form id="signUpForm" class="cf authform"> + <form id="signUpForm" class="cf authform" novalidate> <h1 class="serif">Sign In</h1> <ul class="notifications"> @@ -11,7 +11,15 @@ <ul class="inputs"> <li> <label class="serif" for="email">Email Address</label> - <input class="sans" id="email" autofocus placeholder="Your Email" type="email" required x-moz-errormessage="Enter the email address you created your account with" tabindex="1"> + <input class="sans" id="email" autofocus placeholder="Your Email" type="email" tabindex="1"> + + <div id="email_format" class="tooltip" for="email"> + This field must be an email address. + </div> + + <div id="email_required" class="tooltip" for="email"> + The email field is required. + </div> </li> <li> <label class="serif half" for="password">Password</label> @@ -19,7 +27,11 @@ <!-- XXX: this needs to be fixed --> <a class="forgot" href="/forgot" tabindex="4">forgot your password?</a> </div> - <input class="sans" id="password" placeholder="Your Password" type="password" required x-moz-errormessage="Oops! We need your password to sign you in" tabindex="2" maxlength="80"> + <input class="sans" id="password" placeholder="Your Password" type="password" tabindex="2" maxlength="80"> + + <div id="password_required" class="tooltip" for="password"> + The password field is required. + </div> </li> </ul> diff --git a/browserid/views/signup.ejs b/browserid/views/signup.ejs index e16483caea3370c3c8495960c9632a1a70ba2755..29a6f662fbeba3818ed61d68d665b5386ce15b33 100644 --- a/browserid/views/signup.ejs +++ b/browserid/views/signup.ejs @@ -1,7 +1,7 @@ <div id="vAlign"> <div id="signUpFormWrap"> <!-- XXX this form submits to nowhere --> - <form id="signUpForm" class="cf authform"> + <form id="signUpForm" class="cf authform" novalidate> <h1 class="serif">Create Account</h1> <ul class="notifications"> @@ -13,7 +13,15 @@ <ul class="inputs forminputs"> <li> <label class="serif" for="email">Email Address</label> - <input class="sans" id="email" autofocus required placeholder="Your Email" type="email" x-moz-errormessage="Please enter the email address you would like to use"> + <input class="sans" id="email" autofocus placeholder="Your Email" type="email" /> + + <div id="email_format" class="tooltip" for="email"> + This field must be an email address. + </div> + + <div id="email_required" class="tooltip" for="email"> + The email field is required. + </div> </li> </ul>