diff options
3 files changed, 106 insertions, 0 deletions
diff --git a/app/assets/javascripts/behaviors/requires_input.js.coffee b/app/assets/javascripts/behaviors/requires_input.js.coffee new file mode 100644 index 00000000000..8318fe435b3 --- /dev/null +++ b/app/assets/javascripts/behaviors/requires_input.js.coffee @@ -0,0 +1,39 @@ +# Requires Input behavior +# +# When called on a form with input fields with the `required` attribute, the +# form's submit button will be disabled until all required fields have values. +# +#= require extensions/jquery +# +# ### Example Markup +# +# <form class="js-requires-input"> +# <input type="text" required="required"> +# <input type="submit" value="Submit"> +# </form> +# +$.fn.requiresInput = -> + $form = $(this) + $button = $('button[type=submit], input[type=submit]', $form) + + required = '[required=required]' + fieldSelector = "input#{required}, select#{required}, textarea#{required}" + + requireInput = -> + # Collect the input values of *all* required fields + values = _.map $(fieldSelector, $form), (field) -> field.value + + # Disable the button if any required fields are empty + if values.length && _.any(values, _.isEmpty) + $button.disable() + else + $button.enable() + + # Set initial button state + requireInput() + + $form.on 'change input', fieldSelector, requireInput + +# Triggered on standard document `ready` and on Turbolinks `page:load` events +$(document).on 'ready page:load', -> + $('form.js-requires-input').requiresInput() diff --git a/spec/javascripts/behaviors/requires_input_spec.js.coffee b/spec/javascripts/behaviors/requires_input_spec.js.coffee new file mode 100644 index 00000000000..61a17632173 --- /dev/null +++ b/spec/javascripts/behaviors/requires_input_spec.js.coffee @@ -0,0 +1,49 @@ +#= require behaviors/requires_input + +describe 'requiresInput', -> + fixture.preload('behaviors/requires_input.html') + + beforeEach -> + fixture.load('behaviors/requires_input.html') + + it 'disables submit when any field is required', -> + $('.js-requires-input').requiresInput() + + expect($('.submit')).toBeDisabled() + + it 'enables submit when no field is required', -> + $('*[required=required]').removeAttr('required') + + $('.js-requires-input').requiresInput() + + expect($('.submit')).not.toBeDisabled() + + it 'enables submit when all required fields are pre-filled', -> + $('*[required=required]').remove() + + $('.js-requires-input').requiresInput() + + expect($('.submit')).not.toBeDisabled() + + it 'enables submit when all required fields receive input', -> + $('.js-requires-input').requiresInput() + + $('#required1').val('input1').change() + expect($('.submit')).toBeDisabled() + + $('#optional1').val('input1').change() + expect($('.submit')).toBeDisabled() + + $('#required2').val('input2').change() + $('#required3').val('input3').change() + $('#required4').val('input4').change() + $('#required5').val('1').change() + + expect($('.submit')).not.toBeDisabled() + + it 'is called on page:load event', -> + spy = spyOn($.fn, 'requiresInput') + + $(document).trigger('page:load') + + expect(spy).toHaveBeenCalled() diff --git a/spec/javascripts/fixtures/behaviors/requires_input.html.haml b/spec/javascripts/fixtures/behaviors/requires_input.html.haml new file mode 100644 index 00000000000..c3f905e912e --- /dev/null +++ b/spec/javascripts/fixtures/behaviors/requires_input.html.haml @@ -0,0 +1,18 @@ +%form.js-requires-input + %input{type: 'text', id: 'required1', required: 'required'} + %input{type: 'text', id: 'required2', required: 'required'} + %input{type: 'text', id: 'required3', required: 'required', value: 'Pre-filled'} + %input{type: 'text', id: 'optional1'} + + %textarea{id: 'required4', required: 'required'} + %textarea{id: 'optional2'} + + %select{id: 'required5', required: 'required'} + %option Zero + %option{value: '1'} One + %select{id: 'optional3', required: 'required'} + %option Zero + %option{value: '1'} One + + %button.submit{type: 'submit', value: 'Submit'} + %input.submit{type: 'submit', value: 'Submit'} |