aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorDennis Eriksen <dennis.se@gmail.com>2013-03-20 12:43:33 +0100
committerDennis Eriksen <dennis.se@gmail.com>2013-03-20 12:43:33 +0100
commit266767e6b31d4799b218a7dc9ffd0d6f2eca92a8 (patch)
treee3e68b3acdfb276cadcc23d0028a6c1dd3bc8f21
parentEdited "Sign in" button - for fun (diff)
downloadDivid-266767e6b31d4799b218a7dc9ffd0d6f2eca92a8.tar.gz
login screen
-rw-r--r--public/css/login.css138
-rw-r--r--public/js/controllers/homeController.js67
-rw-r--r--public/js/controllers/loginController.js14
-rw-r--r--public/js/controllers/signupController.js9
-rw-r--r--public/js/form-validators/accountValidator.js80
-rw-r--r--public/js/form-validators/emailValidator.js39
-rw-r--r--public/js/form-validators/loginValidator.js29
-rw-r--r--public/js/form-validators/resetValidator.js37
-rw-r--r--public/js/views/home.js49
-rw-r--r--public/js/views/login.js51
-rw-r--r--public/js/views/reset.js27
-rw-r--r--public/js/views/signup.js39
-rw-r--r--views/login.ejs63
13 files changed, 631 insertions, 11 deletions
diff --git a/public/css/login.css b/public/css/login.css
new file mode 100644
index 0000000..5709783
--- /dev/null
+++ b/public/css/login.css
@@ -0,0 +1,138 @@
+body {
+ margin: 0;
+ padding: 0;
+ height: 100%;
+ background: #f2f9fe;
+ background: -moz-radial-gradient(center, ellipse cover, #f2f9fe 0%, #d6f0fd 100%);
+/* FF3.6+ */
+ background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, #f2f9fe), color-stop(100%, #d6f0fd));
+/* Chrome,Safari4+ */
+ background: -webkit-radial-gradient(center, ellipse cover, #f2f9fe 0%, #d6f0fd 100%);
+/* Chrome10+,Safari5.1+ */
+ background: -o-radial-gradient(center, ellipse cover, #f2f9fe 0%, #d6f0fd 100%);
+/* Opera 12+ */
+ background: -ms-radial-gradient(center, ellipse cover, #f2f9fe 0%, #d6f0fd 100%);
+/* IE10+ */
+ background: radial-gradient(center, ellipse cover, #f2f9fe 0%, #d6f0fd 100%);
+/* W3C */
+}
+#login-container {
+ width: 340px;
+ margin: 160px auto;
+}
+#login-container label {
+ margin: 15px 0 5px 5px;
+}
+#login-container button {
+ width: 150px;
+ padding: 6px 40px 6px 40px;
+ float: left;
+ margin-top: 15px;
+}
+#login-container .checkbox {
+ margin: 23px 0 0 180px;
+}
+#login-container .btm-links {
+ text-align: center;
+ margin-top: 10px;
+}
+#login-container #create-account {
+ float: right;
+ margin-right: 13px;
+}
+#login-container #forgot-password {
+ float: left;
+ margin-left: 10px;
+}
+#account-form-container {
+ width: 460px;
+ margin: 100px auto;
+}
+#country-list {
+ width: 280px;
+}
+.modal-form-errors li {
+ color: #808080;
+ text-shadow: -1px 1px 0 #fff;
+ -moz-text-shadow: -1px 1px 0 #fff;
+ -webkit-text-shadow: -1px 1px 0 #fff;
+ color: #d8000c;
+}
+.modal-single-input {
+ width: 452px;
+ margin: -200px 0 0 -232px;
+}
+.modal-single-input form {
+ color: #808080;
+ text-shadow: -1px 1px 0 #fff;
+ -moz-text-shadow: -1px 1px 0 #fff;
+ -webkit-text-shadow: -1px 1px 0 #fff;
+ margin-bottom: 0;
+}
+.modal-single-input form button {
+ width: 80px;
+ top: 213px;
+ position: absolute;
+}
+.modal-single-input form #cancel {
+ right: 110px;
+}
+.modal-single-input form #submit {
+ right: 18px;
+}
+.modal-single-input .modal-body {
+ height: 140px;
+ overflow: hidden;
+ padding-bottom: 0;
+}
+.modal-single-input .modal-footer {
+ height: 20px;
+}
+.modal-alert {
+ width: 310px;
+ margin: -200px 0 0 -150px;
+}
+#btn-logout {
+ width: 100px;
+ top: 1px;
+ right: 8px;
+ position: absolute;
+}
+#print {
+ padding: 20px;
+}
+#four04 {
+ padding: 20px;
+}
+.clear-fix {
+ clear: both;
+}
+.well {
+ margin-left: 0;
+ border: 1px solid #ccc;
+}
+.form-horizontal .control-label {
+ width: 80px;
+}
+.form-horizontal .controls {
+ margin-left: 120px;
+}
+.form-horizontal .form-actions {
+ padding: 17px 0 0 270px;
+}
+label {
+ color: #808080;
+ text-shadow: -1px 1px 0 #fff;
+ -moz-text-shadow: -1px 1px 0 #fff;
+ -webkit-text-shadow: -1px 1px 0 #fff;
+}
+.subheading {
+ color: #808080;
+ text-shadow: -1px 1px 0 #fff;
+ -moz-text-shadow: -1px 1px 0 #fff;
+ -webkit-text-shadow: -1px 1px 0 #fff;
+ margin-top: 3px;
+}
+button i {
+ padding-left: 8px;
+}
diff --git a/public/js/controllers/homeController.js b/public/js/controllers/homeController.js
new file mode 100644
index 0000000..9894d0e
--- /dev/null
+++ b/public/js/controllers/homeController.js
@@ -0,0 +1,67 @@
+
+function HomeController()
+{
+
+// bind event listeners to button clicks //
+ var that = this;
+
+// handle user logout //
+ $('#btn-logout').click(function(){ that.attemptLogout(); });
+
+// confirm account deletion //
+ $('#account-form-btn1').click(function(){$('.modal-confirm').modal('show')});
+
+// handle account deletion //
+ $('.modal-confirm .submit').click(function(){ that.deleteAccount(); });
+
+ this.deleteAccount = function()
+ {
+ $('.modal-confirm').modal('hide');
+ var that = this;
+ $.ajax({
+ url: '/delete',
+ type: 'POST',
+ data: { id: $('#userId').val()},
+ success: function(data){
+ that.showLockedAlert('Your account has been deleted.<br>Redirecting you back to the homepage.');
+ },
+ error: function(jqXHR){
+ console.log(jqXHR.responseText+' :: '+jqXHR.statusText);
+ }
+ });
+ }
+
+ this.attemptLogout = function()
+ {
+ var that = this;
+ $.ajax({
+ url: "/home",
+ type: "POST",
+ data: {logout : true},
+ success: function(data){
+ that.showLockedAlert('You are now logged out.<br>Redirecting you back to the homepage.');
+ },
+ error: function(jqXHR){
+ console.log(jqXHR.responseText+' :: '+jqXHR.statusText);
+ }
+ });
+ }
+
+ this.showLockedAlert = function(msg){
+ $('.modal-alert').modal({ show : false, keyboard : false, backdrop : 'static' });
+ $('.modal-alert .modal-header h3').text('Success!');
+ $('.modal-alert .modal-body p').html(msg);
+ $('.modal-alert').modal('show');
+ $('.modal-alert button').click(function(){window.location.href = '/';})
+ setTimeout(function(){window.location.href = '/';}, 3000);
+ }
+}
+
+HomeController.prototype.onUpdateSuccess = function()
+{
+ $('.modal-alert').modal({ show : false, keyboard : true, backdrop : true });
+ $('.modal-alert .modal-header h3').text('Success!');
+ $('.modal-alert .modal-body p').html('Your account has been updated.');
+ $('.modal-alert').modal('show');
+ $('.modal-alert button').off('click');
+}
diff --git a/public/js/controllers/loginController.js b/public/js/controllers/loginController.js
new file mode 100644
index 0000000..a894aed
--- /dev/null
+++ b/public/js/controllers/loginController.js
@@ -0,0 +1,14 @@
+
+function LoginController()
+{
+
+// bind event listeners to button clicks //
+
+ $('#login-form #forgot-password').click(function(){ $('#get-credentials').modal('show');});
+
+// automatically toggle focus between the email modal window and the login form //
+
+ $('#get-credentials').on('shown', function(){ $('#email-tf').focus(); });
+ $('#get-credentials').on('hidden', function(){ $('#user-tf').focus(); });
+
+} \ No newline at end of file
diff --git a/public/js/controllers/signupController.js b/public/js/controllers/signupController.js
new file mode 100644
index 0000000..97d20e6
--- /dev/null
+++ b/public/js/controllers/signupController.js
@@ -0,0 +1,9 @@
+
+function SignupController()
+{
+// redirect to homepage when cancel button is clicked //
+ $('#account-form-btn1').click(function(){ window.location.href = '/';});
+
+// redirect to homepage on new account creation, add short delay so user can read alert window //
+ $('.modal-alert #ok').click(function(){ setTimeout(function(){window.location.href = '/';}, 300)});
+} \ No newline at end of file
diff --git a/public/js/form-validators/accountValidator.js b/public/js/form-validators/accountValidator.js
new file mode 100644
index 0000000..6de2dfc
--- /dev/null
+++ b/public/js/form-validators/accountValidator.js
@@ -0,0 +1,80 @@
+
+function AccountValidator(){
+
+// build array maps of the form inputs & control groups //
+
+ this.formFields = [$('#name-tf'), $('#email-tf'), $('#user-tf'), $('#pass-tf')];
+ this.controlGroups = [$('#name-cg'), $('#email-cg'), $('#user-cg'), $('#pass-cg')];
+
+// bind the form-error modal window to this controller to display any errors //
+
+ this.alert = $('.modal-form-errors');
+ this.alert.modal({ show : false, keyboard : true, backdrop : true});
+
+ this.validateName = function(s)
+ {
+ return s.length >= 3;
+ }
+
+ this.validatePassword = function(s)
+ {
+ // if user is logged in and hasn't changed their password, return ok
+ if ($('#userId').val() && s===''){
+ return true;
+ } else{
+ return s.length >= 6;
+ }
+ }
+
+ this.validateEmail = function(e)
+ {
+ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ return re.test(e);
+ }
+
+ this.showErrors = function(a)
+ {
+ $('.modal-form-errors .modal-body p').text('Please correct the following problems :');
+ var ul = $('.modal-form-errors .modal-body ul');
+ ul.empty();
+ for (var i=0; i < a.length; i++) ul.append('<li>'+a[i]+'</li>');
+ this.alert.modal('show');
+ }
+
+}
+
+AccountValidator.prototype.showInvalidEmail = function()
+{
+ this.controlGroups[1].addClass('error');
+ this.showErrors(['That email address is already in use.']);
+}
+
+AccountValidator.prototype.showInvalidUserName = function()
+{
+ this.controlGroups[2].addClass('error');
+ this.showErrors(['That username is already in use.']);
+}
+
+AccountValidator.prototype.validateForm = function()
+{
+ var e = [];
+ for (var i=0; i < this.controlGroups.length; i++) this.controlGroups[i].removeClass('error');
+ if (this.validateName(this.formFields[0].val()) == false) {
+ this.controlGroups[0].addClass('error'); e.push('Please Enter Your Name');
+ }
+ if (this.validateEmail(this.formFields[1].val()) == false) {
+ this.controlGroups[1].addClass('error'); e.push('Please Enter A Valid Email');
+ }
+ if (this.validateName(this.formFields[2].val()) == false) {
+ this.controlGroups[2].addClass('error');
+ e.push('Please Choose A Username');
+ }
+ if (this.validatePassword(this.formFields[3].val()) == false) {
+ this.controlGroups[3].addClass('error');
+ e.push('Password Should Be At Least 6 Characters');
+ }
+ if (e.length) this.showErrors(e);
+ return e.length === 0;
+}
+
+ \ No newline at end of file
diff --git a/public/js/form-validators/emailValidator.js b/public/js/form-validators/emailValidator.js
new file mode 100644
index 0000000..5a87c04
--- /dev/null
+++ b/public/js/form-validators/emailValidator.js
@@ -0,0 +1,39 @@
+
+function EmailValidator(){
+
+// bind this to _local for anonymous functions //
+
+ var _local = this;
+
+// modal window to allow users to request credentials by email //
+ _local.retrievePassword = $('#get-credentials');
+ _local.retrievePassword.modal({ show : false, keyboard : true, backdrop : true });
+ _local.retrievePasswordAlert = $('#get-credentials .alert');
+ _local.retrievePassword.on('show', function(){ $('#get-credentials-form').resetForm(); _local.retrievePasswordAlert.hide();});
+
+}
+
+EmailValidator.prototype.validateEmail = function(e)
+{
+ var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
+ return re.test(e);
+}
+
+EmailValidator.prototype.showEmailAlert = function(m)
+{
+ this.retrievePasswordAlert.attr('class', 'alert alert-error');
+ this.retrievePasswordAlert.html(m);
+ this.retrievePasswordAlert.show();
+}
+
+EmailValidator.prototype.hideEmailAlert = function()
+{
+ this.retrievePasswordAlert.hide();
+}
+
+EmailValidator.prototype.showEmailSuccess = function(m)
+{
+ this.retrievePasswordAlert.attr('class', 'alert alert-success');
+ this.retrievePasswordAlert.html(m);
+ this.retrievePasswordAlert.fadeIn(500);
+} \ No newline at end of file
diff --git a/public/js/form-validators/loginValidator.js b/public/js/form-validators/loginValidator.js
new file mode 100644
index 0000000..066e822
--- /dev/null
+++ b/public/js/form-validators/loginValidator.js
@@ -0,0 +1,29 @@
+
+function LoginValidator(){
+
+// bind a simple alert window to this controller to display any errors //
+
+ this.loginErrors = $('.modal-alert');
+ this.loginErrors.modal({ show : false, keyboard : true, backdrop : true });
+
+ this.showLoginError = function(t, m)
+ {
+ $('.modal-alert .modal-header h3').text(t);
+ $('.modal-alert .modal-body p').text(m);
+ this.loginErrors.modal('show');
+ }
+
+}
+
+LoginValidator.prototype.validateForm = function()
+{
+ if ($('#user-tf').val() == ''){
+ this.showLoginError('Whoops!', 'Please enter a valid username');
+ return false;
+ } else if ($('#pass-tf').val() == ''){
+ this.showLoginError('Whoops!', 'Please enter a valid password');
+ return false;
+ } else{
+ return true;
+ }
+} \ No newline at end of file
diff --git a/public/js/form-validators/resetValidator.js b/public/js/form-validators/resetValidator.js
new file mode 100644
index 0000000..71c8792
--- /dev/null
+++ b/public/js/form-validators/resetValidator.js
@@ -0,0 +1,37 @@
+
+function ResetValidator(){
+
+// modal window to allow users to reset their password //
+ this.setPassword = $('#set-password');
+ this.setPassword.modal({ show : false, keyboard : false, backdrop : 'static' });
+ this.setPasswordAlert = $('#set-password .alert');
+}
+
+ResetValidator.prototype.validatePassword = function(s)
+{
+ if (s.length >= 6){
+ return true;
+ } else{
+ this.showAlert('Password Should Be At Least 6 Characters');
+ return false;
+ }
+}
+
+ResetValidator.prototype.showAlert = function(m)
+{
+ this.setPasswordAlert.attr('class', 'alert alert-error');
+ this.setPasswordAlert.html(m);
+ this.setPasswordAlert.show();
+}
+
+ResetValidator.prototype.hideAlert = function()
+{
+ this.setPasswordAlert.hide();
+}
+
+ResetValidator.prototype.showSuccess = function(m)
+{
+ this.setPasswordAlert.attr('class', 'alert alert-success');
+ this.setPasswordAlert.html(m);
+ this.setPasswordAlert.fadeIn(500);
+} \ No newline at end of file
diff --git a/public/js/views/home.js b/public/js/views/home.js
new file mode 100644
index 0000000..eda246a
--- /dev/null
+++ b/public/js/views/home.js
@@ -0,0 +1,49 @@
+
+$(document).ready(function(){
+
+ var hc = new HomeController();
+ var av = new AccountValidator();
+
+ $('#account-form').ajaxForm({
+ beforeSubmit : function(formData, jqForm, options){
+ if (av.validateForm() == false){
+ return false;
+ } else{
+ // push the disabled username field onto the form data array //
+ formData.push({name:'user', value:$('#user-tf').val()})
+ return true;
+ }
+ },
+ success : function(responseText, status, xhr, $form){
+ if (status == 'success') hc.onUpdateSuccess();
+ },
+ error : function(e){
+ if (e.responseText == 'email-taken'){
+ av.showInvalidEmail();
+ } else if (e.responseText == 'username-taken'){
+ av.showInvalidUserName();
+ }
+ }
+ });
+ $('#name-tf').focus();
+ $('#github-banner').css('top', '41px');
+
+// customize the account settings form //
+
+ $('#account-form h1').text('Account Settings');
+ $('#account-form #sub1').text('Here are the current settings for your account.');
+ $('#user-tf').attr('disabled', 'disabled');
+ $('#account-form-btn1').html('Delete');
+ $('#account-form-btn1').addClass('btn-danger');
+ $('#account-form-btn2').html('Update');
+
+// setup the confirm window that displays when the user chooses to delete their account //
+
+ $('.modal-confirm').modal({ show : false, keyboard : true, backdrop : true });
+ $('.modal-confirm .modal-header h3').text('Delete Account');
+ $('.modal-confirm .modal-body p').html('Are you sure you want to delete your account?');
+ $('.modal-confirm .cancel').html('Cancel');
+ $('.modal-confirm .submit').html('Delete');
+ $('.modal-confirm .submit').addClass('btn-danger');
+
+}) \ No newline at end of file
diff --git a/public/js/views/login.js b/public/js/views/login.js
new file mode 100644
index 0000000..27fe31d
--- /dev/null
+++ b/public/js/views/login.js
@@ -0,0 +1,51 @@
+
+$(document).ready(function(){
+
+ var lv = new LoginValidator();
+ var lc = new LoginController();
+
+// main login form //
+
+ $('#login-form').ajaxForm({
+ beforeSubmit : function(formData, jqForm, options){
+ if (lv.validateForm() == false){
+ return false;
+ } else{
+ // append 'remember-me' option to formData to write local cookie //
+ formData.push({name:'remember-me', value:$("input:checkbox:checked").length == 1})
+ return true;
+ }
+ },
+ success : function(responseText, status, xhr, $form){
+ if (status == 'success') window.location.href = '/home';
+ },
+ error : function(e){
+ lv.showLoginError('Login Failure', 'Please check your username and/or password');
+ }
+ });
+ $('#user-tf').focus();
+
+// login retrieval form via email //
+
+ var ev = new EmailValidator();
+
+ $('#get-credentials-form').ajaxForm({
+ url: '/lost-password',
+ beforeSubmit : function(formData, jqForm, options){
+ if (ev.validateEmail($('#email-tf').val())){
+ ev.hideEmailAlert();
+ return true;
+ } else{
+ ev.showEmailAlert("<b> Error!</b> Please enter a valid email address");
+ return false;
+ }
+ },
+ success : function(responseText, status, xhr, $form){
+ ev.showEmailSuccess("Check your email on how to reset your password.");
+ },
+ error : function(){
+ ev.showEmailAlert("Sorry. There was a problem, please try again later.");
+ }
+ });
+
+}) \ No newline at end of file
diff --git a/public/js/views/reset.js b/public/js/views/reset.js
new file mode 100644
index 0000000..c6a6166
--- /dev/null
+++ b/public/js/views/reset.js
@@ -0,0 +1,27 @@
+
+$(document).ready(function(){
+
+ var rv = new ResetValidator();
+
+ $('#set-password-form').ajaxForm({
+ beforeSubmit : function(formData, jqForm, options){;
+ rv.hideAlert();
+ if (rv.validatePassword($('#pass-tf').val()) == false){
+ return false;
+ } else{
+ return true;
+ }
+ },
+ success : function(responseText, status, xhr, $form){
+ rv.showSuccess("Your password has been reset.");
+ setTimeout(function(){ window.location.href = '/'; }, 3000);
+ },
+ error : function(){
+ rv.showAlert("I'm sorry something went wrong, please try again.");
+ }
+ });
+
+ $('#set-password').modal('show');
+ $('#set-password').on('shown', function(){ $('#pass-tf').focus(); })
+
+}); \ No newline at end of file
diff --git a/public/js/views/signup.js b/public/js/views/signup.js
new file mode 100644
index 0000000..52de197
--- /dev/null
+++ b/public/js/views/signup.js
@@ -0,0 +1,39 @@
+
+$(document).ready(function(){
+
+ var av = new AccountValidator();
+ var sc = new SignupController();
+
+ $('#account-form').ajaxForm({
+ beforeSubmit : function(formData, jqForm, options){
+ return av.validateForm();
+ },
+ success : function(responseText, status, xhr, $form){
+ if (status == 'success') $('.modal-alert').modal('show');
+ },
+ error : function(e){
+ if (e.responseText == 'email-taken'){
+ av.showInvalidEmail();
+ } else if (e.responseText == 'username-taken'){
+ av.showInvalidUserName();
+ }
+ }
+ });
+ $('#name-tf').focus();
+
+// customize the account signup form //
+
+ $('#account-form h1').text('Signup');
+ $('#account-form #sub1').text('Please tell us a little about yourself');
+ $('#account-form #sub2').text('Choose your username & password');
+ $('#account-form-btn1').html('Cancel');
+ $('#account-form-btn2').html('Submit');
+ $('#account-form-btn2').addClass('btn-primary');
+
+// setup the alert that displays when an account is successfully created //
+
+ $('.modal-alert').modal({ show : false, keyboard : false, backdrop : 'static' });
+ $('.modal-alert .modal-header h3').text('Success!');
+ $('.modal-alert .modal-body p').html('Your account has been created.</br>Click OK to return to the login page.');
+
+}) \ No newline at end of file
diff --git a/views/login.ejs b/views/login.ejs
index b938624..2997d9e 100644
--- a/views/login.ejs
+++ b/views/login.ejs
@@ -1,19 +1,60 @@
<% include header %>
+ <link rel="stylesheet" href="/css/login.css" />
</head>
<body>
+<div id="login-container">
+ <form method="post" id="login-form" class="well span4">
+ <h1>Hello!</h1>
+ <p class="subheading">Please Login To Your Account</p>
+ <label>Username </label>
+ <input type="text" name="user" id="user-tf" class="span4 required">
+ <label>Password</label>
+ <input type="password" name="pass" id="pass-tf" class="span4 required">
+ <button type="submit" id="btn-login" class="btn btn-primary"><i class="icon-lock icon-white"></i>Sign in</button>
+ <label id="remember-me" class="checkbox">Remember Me
+ <input type="checkbox" checked="checked">
+ </label>
+ <div class="clear-fix"></div>
+ <hr>
+ <div class="btm-links"><a href="#" id="forgot-password">Forgot Your Password? </a><a href="/signup" id="create-account">Create An Account</a></div>
+ </form>
+</div>
+<div class="modal-alert modal hide fade">
+ <div class="modal-header">
+ <button data-dismiss="modal" class="close">x</button>
+ <h3></h3>
+ </div>
+ <div class="modal-body">
+ <p></p>
+ </div>
+ <div class="modal-footer">
+ <button data-dismiss="modal" id="ok" class="btn btn-warning">OK</button>
+ </div>
+</div>
+<div id="get-credentials" class="modal-single-input modal hide fade">
+ <div class="modal-header">
+ <button data-dismiss="modal" class="close">x</button>
+ <h3>Retrieve Password</h3>
+ </div>
+ <div class="modal-body">
+ <form method="post" id="get-credentials-form" class="well span5">
+ <p>Please enter the email address associated with your account</p>
+ <input type="text" name="email" id="email-tf" class="span5 required">
+ <button type="submit" id="submit" class="btn btn-primary">Submit</button>
+ <button data-dismiss="modal" id="cancel" class="btn">Cancel</button>
+ <div class="alert alert-error hide"></div>
+ <button data-dismiss="alert" class="close"></button>
+ </form>
+ </div>
+ <div class="modal-footer"></div>
+</div>
- <div class="container">
- <form class="form-signin">
- <h2 class="form-signin-heading">Please sign in</h2>
- <input type="text" class="input-block-level" placeholder="Email address">
- <input type="password" class="input-block-level" placeholder="Password">
- <label class="checkbox">
- <input type="checkbox" value="remember-me"> Remember me
- </label>
- <button class="btn btn-primary" type="submit">Sign in</button>
- </form>
- </div> <!-- /container -->
+<script src="/js/views/login.js"></script>
+<script src="/js/jquery.form.js"></script>
+<script src="/js/controllers/loginController.js"></script>
+<script src="/js/form-validators/loginValidator.js"></script>
+<script src="/js/form-validators/emailValidator.js"></script>
<% include footer %>