-
Notifications
You must be signed in to change notification settings - Fork 54
[Delivers #98157690] add client-side form validation #658
Changes from all commits
e805393
e4a43ba
7cdcfc1
3658745
a3e6943
d07709e
17498ef
d01bb77
5c91863
9e2f9d1
28c5be4
3ed73af
420e262
7dc2719
4997b09
7c9c68d
3b8b95a
d872a35
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,6 +53,7 @@ gem 'workflow' | |
group :test, :development do | ||
gem 'bullet', require: false # use BULLET_ENABLED=true | ||
gem 'database_cleaner' | ||
gem 'konacha' | ||
gem 'pry-byebug' | ||
gem 'pry-rails' | ||
gem 'rspec-rails' | ||
|
@@ -61,6 +62,7 @@ end | |
|
||
group :development do | ||
gem 'guard-rspec', require: false | ||
gem 'guard-shell', require: false | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. seems like this is specific to a particular dev setup and not needed in the Gemfile.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Mind if we have that discussion separately? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure! |
||
gem 'mail_view' | ||
gem 'railroady' | ||
gem 'letter_opener' | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,3 +15,8 @@ guard :rspec, cmd: 'bin/rspec' do | |
# Capybara features specs | ||
watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$}) { |m| "spec/features/#{m[1]}_spec.rb" } | ||
end | ||
|
||
guard :shell do | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not using guard locally - I am fine with keeping this (and guard-shell) gem locally, but just an FYI that it isn't necessary for all (read: my) dev environments |
||
watch(%r{^app/assets/javascripts/(.+)\.js(\.coffee)?$}) { |m| `bin/rake konacha:run SPEC=#{m[1]}_spec` } | ||
watch(%r{^spec/javascripts/(.+)\.js(\.coffee)?$}) { |m| `bin/rake konacha:run SPEC=#{m[1]}` } | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
class @FieldFilter | ||
constructor: (@$fieldOrWrappers) -> | ||
|
||
isInput: -> | ||
@$fieldOrWrappers.is(':input') | ||
|
||
toggleVisibility: (showOrHide) -> | ||
# https://www.paciellogroup.com/blog/2012/05/html5-accessibility-chops-hidden-and-aria-hidden/ | ||
@$fieldOrWrappers.attr('aria-hidden', !showOrHide) | ||
|
||
toggleEnabled: (enableOrDisable) -> | ||
@$fieldOrWrappers.attr('disabled', !enableOrDisable) | ||
|
||
toggleChildInputs: (enableOrDisable) -> | ||
@$fieldOrWrappers.find(':input').attr('disabled', !enableOrDisable) | ||
|
||
toggle: (showOrHide) -> | ||
@toggleVisibility(showOrHide) | ||
|
||
# hidden inputs need to be disabled, so they aren't submitted with the form | ||
if @isInput() | ||
@toggleEnabled(showOrHide) | ||
else | ||
@toggleChildInputs(showOrHide) | ||
|
||
show: -> | ||
@toggle(true) | ||
|
||
hide: -> | ||
@toggle(false) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,45 +1,28 @@ | ||
class Filter | ||
constructor: ($root, @key) -> | ||
@$ = (selector) -> $root.find(selector) | ||
class @Filter | ||
constructor: (@$root, @$control) -> | ||
key = @$control.data('filter-control') | ||
val = @$control.val() | ||
@set = new FilterSet(@$root, key, val) | ||
|
||
addInput: ($el) -> | ||
$el.click () => @filter($el) | ||
# Initial state | ||
if $el.is(":checked") | ||
@filter($el) | ||
isSelected: -> | ||
@$control.is(':checked') | ||
|
||
addRadios: () -> | ||
@$("input:radio[data-filter-control=#{ @key }]").each (idx, control) => | ||
@addInput($(control)) | ||
update: -> | ||
if @isSelected() | ||
@set.show() | ||
else | ||
@set.hide() | ||
|
||
addChkBoxes: () -> | ||
@$("input:checkbox[data-filter-control=#{ @key }]").each (idx, control) => | ||
@addInput($(control)) | ||
|
||
filter: ($el) -> | ||
value = $el.val() | ||
if !$el.is(":checked") | ||
value = "!" + value | ||
@$("[data-filter-key=#{ @key }]").each (idx, el) -> | ||
hidden = el.getAttribute("data-filter-value") != value | ||
el.setAttribute("aria-hidden", hidden.toString()) | ||
|
||
hideAll: () -> | ||
@$("[data-filter-key=#{ @key }]").attr("aria-hidden", true) | ||
enable: -> | ||
@update() | ||
@$control.change => @update() | ||
|
||
@generateIn = ($scope) -> | ||
filters = {} | ||
$scope.find("[data-filter-control]").each (idx, el) -> | ||
key = el.getAttribute('data-filter-control') | ||
if !filters.hasOwnProperty(key) | ||
filters[key] = new Filter($scope, key) | ||
filters | ||
$scope.find('[data-filter-control]').map (idx, control) -> | ||
new Filter($scope, $(control)) | ||
|
||
$ -> | ||
# @todo - better scope | ||
$scope = $(document) | ||
$scope = $(document.body) | ||
filters = Filter.generateIn($scope) | ||
for key, filter of filters | ||
filter.hideAll() | ||
filter.addRadios() | ||
filter.addChkBoxes() | ||
for filter in filters | ||
filter.enable() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
class @FilterSet | ||
constructor: (@$root, @key, @val) -> | ||
|
||
$: (selector) -> | ||
@$root.find(selector) | ||
|
||
children: -> | ||
@$("[data-filter-key=#{ @key }][data-filter-value=#{ @val }]") | ||
|
||
cousins: -> | ||
@$("[data-filter-key=#{ @key }][data-filter-value!=#{ @val }]") | ||
|
||
showChildren: -> | ||
filter = new FieldFilter(@children()) | ||
filter.show() | ||
|
||
hideCousins: -> | ||
filter = new FieldFilter(@cousins()) | ||
filter.hide() | ||
|
||
show: -> | ||
@showChildren() | ||
@hideCousins() | ||
|
||
hide: -> | ||
filter = new FieldFilter(@children()) | ||
filter.hide() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,10 @@ class Selectizer | |
@$el = $(el) | ||
@dataAttr = @$el.attr('data-attr') || 'default_field' | ||
|
||
# `required` inputs don't work with Selectize | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think linking to the gh issue is great for documenation; summary of gh issue not necesssary There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not necessary, but I think it's helpful in this case. |
||
# https://github.com/brianreavis/selectize.js/issues/733 | ||
@$el.removeAttr('required') | ||
|
||
isFreeForm: -> | ||
@$el.is('input') | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
if defined?(Konacha) | ||
Konacha.configure do |config| | ||
require 'capybara/poltergeist' | ||
config.driver = :poltergeist | ||
end | ||
end |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -79,7 +79,7 @@ have it in your PATH. This is used for javascript and interface testing. | |
### Running the entire suite once | ||
|
||
```bash | ||
rake | ||
./bin/rake | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. rake is so much easier to type! what about including There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
...but it doesn't run via Spring, which makes the startup significantly faster. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
👍 |
||
``` | ||
|
||
### Running tests as corresponding files are changed | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#= require jquery | ||
#= require field_filter | ||
|
||
describe 'FieldFilter', -> | ||
describe '#show()', -> | ||
it "enables inputs", -> | ||
$input = $('<input disabled="disabled">') | ||
|
||
filter = new FieldFilter($input) | ||
filter.show() | ||
|
||
expect($input.is(':disabled')).to.be.false | ||
|
||
it "enables text areas", -> | ||
$textarea = $('<textarea disabled="disabled">') | ||
|
||
filter = new FieldFilter($textarea) | ||
filter.show() | ||
|
||
expect($textarea.is(':disabled')).to.be.false | ||
|
||
it "enables nested inputs", -> | ||
$content = $('<div><input disabled="disabled"></div>') | ||
|
||
filter = new FieldFilter($content) | ||
filter.show() | ||
|
||
$input = $content.find('input') | ||
expect($input.is(':disabled')).to.be.false | ||
|
||
it "enables nested text areas", -> | ||
$content = $('<div><textarea disabled="disabled"></div>') | ||
|
||
filter = new FieldFilter($content) | ||
filter.show() | ||
|
||
$textarea = $content.find('textarea') | ||
expect($textarea.is(':disabled')).to.be.false | ||
|
||
describe '#hide()', -> | ||
it "disables inputs", -> | ||
$input = $('<input>') | ||
|
||
filter = new FieldFilter($input) | ||
filter.hide() | ||
|
||
expect($input.is(':disabled')).to.be.true | ||
|
||
it "disables text areas", -> | ||
$textarea = $('<textarea>') | ||
|
||
filter = new FieldFilter($textarea) | ||
filter.hide() | ||
|
||
expect($textarea.is(':disabled')).to.be.true | ||
|
||
it "disables nested inputs", -> | ||
$content = $('<div><input></div>') | ||
|
||
filter = new FieldFilter($content) | ||
filter.hide() | ||
|
||
$input = $content.find('input') | ||
expect($input.is(':disabled')).to.be.true | ||
|
||
it "disables nested text areas", -> | ||
$content = $('<div><textarea></div>') | ||
|
||
filter = new FieldFilter($content) | ||
filter.hide() | ||
|
||
$textarea = $content.find('textarea') | ||
expect($textarea.is(':disabled')).to.be.true |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
niiiice