diff --git a/app/assets/javascripts/templateFolderForm.js b/app/assets/javascripts/templateFolderForm.js index aa2a1d4c3..943d136d0 100644 --- a/app/assets/javascripts/templateFolderForm.js +++ b/app/assets/javascripts/templateFolderForm.js @@ -17,18 +17,59 @@ // all the diff states that we want to show or hide this.states = [ - {key: 'nothing-selected-buttons', $el: this.$form.find('#nothing_selected'), cancellable: false}, - {key: 'items-selected-buttons', $el: this.$form.find('#items_selected'), cancellable: false}, - {key: 'move-to-existing-folder', $el: this.$form.find('#move_to_folder_radios'), cancellable: true, setFocus: this.getFocusRoutine('#move_to_folder_radios fieldset', true), action: 'move to folder'}, - {key: 'move-to-new-folder', $el: this.$form.find('#move_to_new_folder_form'), cancellable: true, setFocus: this.getFocusRoutine('#move_to_new_folder_name', false), action: 'move to new folder'}, - {key: 'add-new-folder', $el: this.$form.find('#add_new_folder_form'), cancellable: true, setFocus: this.getFocusRoutine('#add_new_folder_name', false), action: 'new folder'}, - {key: 'add-new-template', $el: this.$form.find('#add_new_template_form'), cancellable: true, setFocus: this.getFocusRoutine('#add_new_template_form fieldset', true), action: 'new template'} + { + key: 'nothing-selected-buttons', + $el: this.$form.find('#nothing_selected'), + cancellable: false + }, + { + key: 'items-selected-buttons', + $el: this.$form.find('#items_selected'), + cancellable: false + }, + { + key: 'move-to-existing-folder', + $el: this.$form.find('#move_to_folder_radios'), + cancellable: true, + setFocus: () => $('#move_to_folder_radios').focus(), + action: 'move to folder', + description: 'Press move to confirm or cancel to close' + }, + { + key: 'move-to-new-folder', + $el: this.$form.find('#move_to_new_folder_form'), + cancellable: true, + setFocus: () => $('#move_to_new_folder_form').focus(), + action: 'move to new folder', + description: 'Press add to new folder to confirm name or cancel to close' + }, + { + key: 'add-new-folder', + $el: this.$form.find('#add_new_folder_form'), + cancellable: true, + setFocus: () => $('#add_new_folder_form').focus(), + action: 'new folder', + description: 'Press add new folder to confirm name or cancel to close' + }, + { + key: 'add-new-template', + $el: this.$form.find('#add_new_template_form'), + cancellable: true, + setFocus: () => $('#add_new_template_form').focus(), + action: 'new template', + description: 'Press continue to confirm selection or cancel to close' + } ]; // cancel/clear buttons only relevant if JS enabled, so this.states.filter(state => state.cancellable).forEach((x) => this.addCancelButton(x)); this.states.filter(state => state.key === 'items-selected-buttons').forEach(x => this.addClearButton(x)); + // make elements focusabled + this.states.filter(state => state.setFocus).forEach(x => x.$el.attr('tabindex', '0')); + + this.addDescriptionsToStates(); + // activate stickiness of elements in each state this.activateStickyElements(); @@ -45,22 +86,16 @@ this.$form.on('change', 'input[type=checkbox]', () => this.templateFolderCheckboxChanged()); }; - this.getFocusRoutine = function (selector, setTabindex) { - return function () { - let $el = $(selector); - let removeTabindex = (e) => { - $(e.target) - .removeAttr('tabindex') - .off('blur', removeTabindex); - }; + this.addDescriptionsToStates = function () { + let id, description; - if (setTabindex) { - $el.attr('tabindex', '-1'); - $el.on('blur', removeTabindex); - } - - $el.focus(); - }; + $.each(this.states.filter(state => 'description' in state), (idx, state) => { + id = `${state.key}__description`; + description = `
${state.description}
`; + state.$el + .prepend(description) + .attr('aria-describedby', id); + }); }; this.activateStickyElements = function() { @@ -140,8 +175,7 @@ this.currentState = 'nothing-selected-buttons'; this.templateFolderCheckboxChanged(); if (targetSelector) { - let setFocus = this.getFocusRoutine(targetSelector, false); - setFocus(); + $(targetSelector).focus(); } }; @@ -240,6 +274,7 @@ this.render = function() { let mode = 'default'; let currentStateObj = this.states.filter(state => { return (state.key === this.currentState); })[0]; + let scrollTop; // detach everything, unless they are the currentState this.states.forEach( @@ -254,7 +289,11 @@ // make sticky JS recalculate its cache of the element's position GOVUK.stickAtBottomWhenScrolling.recalculate(); - if (currentStateObj && ('setFocus' in currentStateObj)) { currentStateObj.setFocus(); } + if (currentStateObj && ('setFocus' in currentStateObj)) { + scrollTop = $(window).scrollTop(); + currentStateObj.setFocus(); + $(window).scrollTop(scrollTop); + } }; this.nothingSelectedButtons = $(` diff --git a/app/assets/stylesheets/components/message.scss b/app/assets/stylesheets/components/message.scss index 2cd63fdbf..58341ba31 100644 --- a/app/assets/stylesheets/components/message.scss +++ b/app/assets/stylesheets/components/message.scss @@ -176,6 +176,17 @@ $message-type-bottom-spacing: govuk-spacing(4); } +.sticky-template-form { + + padding: govuk-spacing(3); + margin: govuk-spacing(3) * -1; + + &:focus { + outline: none; + } + +} + .folder-heading { .govuk-grid-row & { diff --git a/app/templates/views/templates/_move_to.html b/app/templates/views/templates/_move_to.html index e07939738..5392abd87 100644 --- a/app/templates/views/templates/_move_to.html +++ b/app/templates/views/templates/_move_to.html @@ -5,7 +5,7 @@ {% if templates_and_folders_form.move_to.choices and template_list.templates_to_show %} -