From b6d14dc19dd350a807826e3e097738a36613e083 Mon Sep 17 00:00:00 2001 From: Azul Date: Tue, 8 Apr 2014 11:49:14 +0200 Subject: moving users: app and test files --- app/assets/javascripts/users.js | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 app/assets/javascripts/users.js (limited to 'app/assets/javascripts/users.js') diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js new file mode 100644 index 0000000..8486756 --- /dev/null +++ b/app/assets/javascripts/users.js @@ -0,0 +1,132 @@ +(function() { + // + // LOCAL FUNCTIONS + // + + var poll_users, + prevent_default, + form_failed, + form_passed, + clear_errors, + update_user; + + prevent_default = function(event) { + return event.preventDefault(); + }; + + poll_users = function(query, process) { + return $.get("/1/users.json", { + query: query + }).done(process); + }; + + clear_errors = function() { + return $('#messages').empty(); + }; + + update_user = function(submitEvent) { + var form = submitEvent.target; + var token = form.dataset.token; + var url = form.action; + var req = $.ajax({ + url: url, + type: 'PUT', + headers: { Authorization: 'Token token="' + token + '"' }, + data: $(form).serialize() + }); + req.done( function() { + $(form).find('input[type="submit"]').button('reset'); + }); + }; + + markAsSubmitted = function(submitEvent) { + var form = submitEvent.target; + $(form).addClass('submitted') + // bootstrap loading state: + $(form).find('input[type="submit"]').button('loading'); + }; + + resetButtons = function(submitEvent) { + var form = $('form.submitted') + // bootstrap loading state: + $(form).find('input[type="submit"]').button('reset'); + $(form).removeClass('submitted') + }; + + // + // PUBLIC FUNCTIONS + // + + srp.session = new srp.Session(); + + srp.signedUp = function() { + return srp.login(); + }; + + srp.loggedIn = function() { + return window.location = '/'; + }; + + srp.updated = function() { + return window.location = '/users/' + srp.session.id(); + }; + + // + // if a json request returns an error, this function gets called and + // decorates the appropriate fields with the error messages. + // + srp.error = function(message) { + clear_errors(); + var errors = extractErrors(message); + displayErrors(errors); + resetButtons(); + } + + function extractErrors(message) { + if ($.isPlainObject(message) && message.errors) { + return message.errors; + } else { + return { + base: (message.error || JSON.stringify(message)) + }; + } + } + + function displayErrors(errors) { + for (var field in errors) { + var error = errors[field]; + if (field === 'base') { + alert_message(error); + } else { + displayFieldError(field, error); + } + } + } + + function displayFieldError(field, error) { + var element = $('form input[name$="[' + field + ']"]'); + if (element) { + element.trigger('element:validate:fail.ClientSideValidations', error).data('valid', false); + } + }; + + // + // INIT + // + + $(document).ready(function() { + $('form').submit(markAsSubmitted); + $('#new_user').submit(prevent_default); + $('#new_user').submit(srp.signup); + $('#new_session').submit(prevent_default); + $('#new_session').submit(srp.login); + $('#update_login_and_password').submit(prevent_default); + $('#update_login_and_password').submit(srp.update); + $('#update_pgp_key').submit(prevent_default); + $('#update_pgp_key').submit(update_user); + return $('#user-typeahead').typeahead({ + source: poll_users + }); + }); + +}).call(this); -- cgit v1.2.3 From e727d211630591a3aaed5eba0eb50c7d4964b6f8 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 23 Apr 2014 16:54:40 +0200 Subject: ensure buttons are properly loading... and reset --- app/assets/javascripts/users.js | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) (limited to 'app/assets/javascripts/users.js') diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js index 8486756..4a86ef5 100644 --- a/app/assets/javascripts/users.js +++ b/app/assets/javascripts/users.js @@ -35,24 +35,10 @@ data: $(form).serialize() }); req.done( function() { - $(form).find('input[type="submit"]').button('reset'); + $(form).find('.btn[type="submit"]').button('reset'); }); }; - - markAsSubmitted = function(submitEvent) { - var form = submitEvent.target; - $(form).addClass('submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('loading'); - }; - - resetButtons = function(submitEvent) { - var form = $('form.submitted') - // bootstrap loading state: - $(form).find('input[type="submit"]').button('reset'); - $(form).removeClass('submitted') - }; - + // // PUBLIC FUNCTIONS // @@ -79,7 +65,7 @@ clear_errors(); var errors = extractErrors(message); displayErrors(errors); - resetButtons(); + $('.btn[type="submit"]').button('reset'); } function extractErrors(message) { @@ -115,7 +101,6 @@ // $(document).ready(function() { - $('form').submit(markAsSubmitted); $('#new_user').submit(prevent_default); $('#new_user').submit(srp.signup); $('#new_session').submit(prevent_default); -- cgit v1.2.3 From a2909d781a790e47acbdbb8b4560177100ad9942 Mon Sep 17 00:00:00 2001 From: Azul Date: Fri, 25 Apr 2014 16:51:03 +0200 Subject: basic password validation without client side gem The client_side_validations gem is not maintained anymore and the validations were not working lately. So instead of trying to fix it I started working on independent validations for the password as it can't be validated on the server due to SRP. So far these validations are very primitive. They require 8 characters length and a matching confirmation. --- app/assets/javascripts/users.js | 80 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 9 deletions(-) (limited to 'app/assets/javascripts/users.js') diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js index 4a86ef5..fa20399 100644 --- a/app/assets/javascripts/users.js +++ b/app/assets/javascripts/users.js @@ -1,13 +1,24 @@ (function() { + + + var settings = { + "error_class":"help-inline", + "error_tag":"span", + "wrapper_error_class":"error", + "wrapper_tag":"div", + "wrapper_class":"control-group" + } + // // LOCAL FUNCTIONS // - var poll_users, - prevent_default, - form_failed, - form_passed, + var poll_users, + prevent_default, clear_errors, + clear_field_errors, + validate_password_confirmation, + validate_password_length, update_user; prevent_default = function(event) { @@ -24,6 +35,10 @@ return $('#messages').empty(); }; + clear_field_errors = function() { + return $(settings.error_tag + '.' + settings.error_class).remove(); + }; + update_user = function(submitEvent) { var form = submitEvent.target; var token = form.dataset.token; @@ -38,7 +53,34 @@ $(form).find('.btn[type="submit"]').button('reset'); }); }; - + + validate_password_confirmation = function(submitEvent) { + var form = submitEvent.target; + var password = $(form).find('input#srp_password').val(); + var confirmation = $(form).find('input#srp_password_confirmation').val(); + if (password === confirmation) { + return true; + } + else { + displayFieldError("password_confirmation", "does not match."); + submitEvent.stopImmediatePropagation() + return false; + } + }; + + validate_password_length = function(submitEvent) { + var form = submitEvent.target; + var password = $(form).find('input#srp_password').val(); + if (password.length > 7) { + return true; + } + else { + displayFieldError("password", "needs to be at least 8 characters long."); + submitEvent.stopImmediatePropagation() + return false; + } + }; + // // PUBLIC FUNCTIONS // @@ -90,18 +132,38 @@ } function displayFieldError(field, error) { + var message = $.isArray(error) ? error[0] : error; var element = $('form input[name$="[' + field + ']"]'); if (element) { - element.trigger('element:validate:fail.ClientSideValidations', error).data('valid', false); + addError(element, settings, message); } }; - // - // INIT - // + function addError(element, settings, message) { + var errorElement, wrapper; + + errorElement = element.parent().find("" + settings.error_tag + "." + settings.error_class); + wrapper = element.closest(settings.wrapper_tag + '.' + settings.wrapper_class); + if (errorElement[0] == null) { + errorElement = $("<" + settings.error_tag + "/>", { + "class": settings.error_class, + text: message + }); + element.after(errorElement); + } + wrapper.addClass(settings.wrapper_error_class); + return errorElement.text(message); + } + +// +// INIT +// $(document).ready(function() { $('#new_user').submit(prevent_default); + $('#new_user').submit(clear_field_errors); + $('#new_user').submit(validate_password_length); + $('#new_user').submit(validate_password_confirmation); $('#new_user').submit(srp.signup); $('#new_session').submit(prevent_default); $('#new_session').submit(srp.login); -- cgit v1.2.3 From 3952a7dfcd13993bd51ac7dc07cb3a01b4658e25 Mon Sep 17 00:00:00 2001 From: Azul Date: Wed, 30 Apr 2014 16:35:39 +0200 Subject: hide srp forms when no js is available Hiding them using two mechanisms in case one fails: .hidden class - bootstrap hides them then style='display:none' - so they are hidden even if css load fails --- app/assets/javascripts/users.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app/assets/javascripts/users.js') diff --git a/app/assets/javascripts/users.js b/app/assets/javascripts/users.js index fa20399..e6c2fcc 100644 --- a/app/assets/javascripts/users.js +++ b/app/assets/javascripts/users.js @@ -160,6 +160,8 @@ // $(document).ready(function() { + $('.hidden.js-show').removeClass('hidden'); + $('.js-show').show(); $('#new_user').submit(prevent_default); $('#new_user').submit(clear_field_errors); $('#new_user').submit(validate_password_length); -- cgit v1.2.3