diff --git a/app/assets/javascripts/radioSelect.js b/app/assets/javascripts/radioSelect.js index 8923376ef..35e1ebacf 100644 --- a/app/assets/javascripts/radioSelect.js +++ b/app/assets/javascripts/radioSelect.js @@ -2,89 +2,142 @@ "use strict"; - var render = ($options, $button) => ( - filterOptionVisibility($options) && setButtonState($options, $button) - ); + let states = { + 'initial': Hogan.compile(` +
+ +
+
+ {{#categories}} + + {{/categories}} +
+ `), + 'choose': Hogan.compile(` +
+ +
+
+ {{#choices}} + + {{/choices}} +
+ `), + 'chosen': Hogan.compile(` +
+ +
+
+ {{#choices}} + + {{/choices}} +
+
+ +
+ `) + }; - var filterOptionVisibility = $options => $options - .removeClass('js-visible') - .filter( - (index, element) => (index === 0 || $(element).has(':checked').length) - ) - .addClass('js-visible'); - - var setButtonState = ($options, $button) => $button - .addClass('js-visible') - .prop( - 'value', - $options.has(':checked').find('input').attr('id') === $options.eq(0).find('input').attr('id') ? - 'Later' : 'Choose a different time' + let focusSelected = function() { + setTimeout( + () => $('[type=radio]:checked').parent('label').blur().trigger('focus').addClass('selected'), + 10 ); - - // Workaround because GOV.UK SelectionButtons doesn’t deselect in this case - var deselectUnchecked = $options => $options - .filter( - (index, element) => $(element).not(':has(:checked)') - ).removeClass('selected'); - - var refocus = $element => setTimeout( - () => $element.blur().trigger('focus'), - 10 - ); - - var renderIfComponentLosesFocus = ($options, $button, $focused) => () => - ($focused.attr('type') !== 'radio') && - render($options, $button) && - refocus($focused); // Make sure that window scrolls to focused element + }; Modules.RadioSelect = function() { this.start = function(component) { let $component = $(component); - let $options = $('label', $component); - - $component.append( - $button = $('') - ); - - $button.on('click', () => - $options.addClass('js-visible').has(':checked').focus() && - $button.removeClass('js-visible') - ); - - $component.on('keydown', 'input[type=radio]', function() { - - // intercept keypresses which aren’t enter or space - if (event.which !== 13 && event.which !== 32) { - setTimeout( - renderIfComponentLosesFocus($options, $button, $(document.activeElement)), - 200 - ); - return true; - } - - event.preventDefault(); - - render($options, $button); - refocus($(this)); - + let render = (state, data) => $component.html(states[state].render(data)); + let choices = $('label', $component).toArray().map(function(element) { + let $element = $(element); + return { + 'id': $element.attr('for'), + 'label': $.trim($element.text()), + 'value': $element.find('input').attr('value') + }; }); + let categories = $component.data('categories').split(','); + let name = $component.find('input').eq(0).attr('name'); - $component.on('click', 'input[type=radio]', function(event) { + $component + .on('click', '.js-category-button', function(event) { - deselectUnchecked($options); + event.preventDefault(); + let day = $(this).attr('value'); + render('choose', { + 'choices': choices.filter( + element => element.label.indexOf(day) > -1 + ), + 'name': name + }); + $('.js-option').eq(0).parent('label').trigger('focus'); - // stop click being triggered by keyboard events - if (!event.pageX) return true; + }) + .on('click', '.js-option', function(event) { - render($options, $button); - refocus($(this)); + // stop click being triggered by keyboard events + if (!event.pageX) return true; + event.preventDefault(); + let value = $(this).attr('value'); + render('chosen', { + 'choices': choices.filter( + element => element.value == value + ), + 'name': name + }); + focusSelected(); + + }) + .on('keydown', 'input[type=radio]', function(event) { + + // intercept keypresses which aren’t enter or space + if (event.which !== 13 && event.which !== 32) { + return true; + } + + event.preventDefault(); + let value = $(this).attr('value'); + render('chosen', { + 'choices': choices.filter( + element => element.value == value + ), + 'name': name + }); + focusSelected(); + + }) + .on('click', '.js-reset-button', function(event) { + + event.preventDefault(); + render('initial', { + 'categories': categories, + 'name': name + }); + focusSelected(); + + }); + + render('initial', { + 'categories': categories, + 'name': name }); - render($options, $button); - }; }; diff --git a/app/assets/stylesheets/components/radio-select.scss b/app/assets/stylesheets/components/radio-select.scss index 7462eed1e..c33a985c9 100644 --- a/app/assets/stylesheets/components/radio-select.scss +++ b/app/assets/stylesheets/components/radio-select.scss @@ -6,7 +6,9 @@ vertical-align: top; .block-label { - margin-right: 10px; + margin-right: 5px; + padding-right: $gutter - 10px; + padding-left: 54px - 10px; } } @@ -15,33 +17,12 @@ display: inline-block; vertical-align: top; width: auto; - padding: 20px 30px 15px 30px; + padding: 20px $gutter-half 15px $gutter-half; + margin-right: 5px; } .js-enabled & { - - .block-label { - &:last-child { - margin-bottom: 10px; - } - } - - .block-label, - .tertiary-button { - display: none; - } - - .js-visible { - - display: block; - - &.tertiary-button { - display: inline-block; - } - - } - } } diff --git a/app/main/forms.py b/app/main/forms.py index ccd9fc14a..58dd1ade4 100644 --- a/app/main/forms.py +++ b/app/main/forms.py @@ -342,6 +342,7 @@ class ChooseTimeForm(Form): get_furthest_possible_scheduled_time() ) ] + self.scheduled_for.categories = get_next_days_until(get_furthest_possible_scheduled_time()) scheduled_for = RadioField( 'When should Notify send these messages?', diff --git a/app/templates/components/radios.html b/app/templates/components/radios.html index 3a0f19a7c..c361c443e 100644 --- a/app/templates/components/radios.html +++ b/app/templates/components/radios.html @@ -38,7 +38,7 @@ {% endif %} -
+
{% for option in field %}