2018-11-28 17:40:54 +00:00
|
|
|
(function(Modules) {
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
|
|
Modules.TemplateFolderForm = function() {
|
|
|
|
|
|
|
|
|
|
this.start = function(templateFolderForm) {
|
|
|
|
|
this.$form = $(templateFolderForm);
|
|
|
|
|
|
2018-12-05 13:48:07 +00:00
|
|
|
// remove the hidden unknown button - if you've got JS enabled then the action you want to do is implied by
|
|
|
|
|
// which field is visible.
|
|
|
|
|
this.$form.find('button[value=unknown]').remove();
|
|
|
|
|
|
2019-02-13 17:47:24 +00:00
|
|
|
this.$liveRegionCounter = this.$form.find('.selection-counter');
|
2018-11-28 17:40:54 +00:00
|
|
|
|
2019-02-15 11:03:22 +00:00
|
|
|
this.$liveRegionCounter.before(this.nothingSelectedButtons);
|
|
|
|
|
this.$liveRegionCounter.before(this.itemsSelectedButtons);
|
2018-11-28 17:40:54 +00:00
|
|
|
|
|
|
|
|
// all the diff states that we want to show or hide
|
2018-12-04 14:48:39 +00:00
|
|
|
this.states = [
|
2019-01-25 16:47:49 +00:00
|
|
|
{key: 'nothing-selected-buttons', $el: this.$form.find('#nothing_selected'), cancellable: false},
|
|
|
|
|
{key: 'items-selected-buttons', $el: this.$form.find('#items_selected'), cancellable: false},
|
2019-07-11 14:28:13 +01:00
|
|
|
{key: 'move-to-existing-folder', $el: this.$form.find('#move_to_folder_radios'), cancellable: true, setFocus: this.getFocusRoutine('#move_to_folder_radios fieldset', true)},
|
2019-01-29 15:53:59 +00:00
|
|
|
{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)},
|
|
|
|
|
{key: 'add-new-folder', $el: this.$form.find('#add_new_folder_form'), cancellable: true, setFocus: this.getFocusRoutine('#add_new_folder_name', false)},
|
2019-07-11 14:28:13 +01:00
|
|
|
{key: 'add-new-template', $el: this.$form.find('#add_new_template_form'), cancellable: true, setFocus: this.getFocusRoutine('#add_new_template_form fieldset', true)}
|
2018-12-04 14:48:39 +00:00
|
|
|
];
|
2018-11-29 17:39:58 +00:00
|
|
|
|
2018-12-10 16:53:12 +00:00
|
|
|
// cancel/clear buttons only relevant if JS enabled, so
|
2018-12-04 14:48:39 +00:00
|
|
|
this.states.filter(state => state.cancellable).forEach((x) => this.addCancelButton(x));
|
2018-12-10 16:53:12 +00:00
|
|
|
this.states.filter(state => state.key === 'items-selected-buttons').forEach(x => this.addClearButton(x));
|
2018-11-30 12:02:51 +00:00
|
|
|
|
2019-01-17 10:52:13 +00:00
|
|
|
// activate stickiness of elements in each state
|
|
|
|
|
this.activateStickyElements();
|
|
|
|
|
|
2018-11-29 16:20:44 +00:00
|
|
|
// first off show the new template / new folder buttons
|
2019-03-20 14:04:06 +00:00
|
|
|
this._lastState = this.$form.data('prev-state');
|
|
|
|
|
if (this._lastState === undefined) {
|
2019-02-13 16:43:38 +00:00
|
|
|
this.selectActionButtons();
|
2018-12-19 15:24:48 +00:00
|
|
|
} else {
|
2019-03-20 14:04:06 +00:00
|
|
|
this.currentState = this._lastState;
|
2018-12-19 15:24:48 +00:00
|
|
|
this.render();
|
2018-12-05 12:01:02 +00:00
|
|
|
}
|
2018-11-29 16:20:44 +00:00
|
|
|
|
2020-02-06 10:50:57 +00:00
|
|
|
this.$form.on('click', 'button.govuk-button--secondary', (event) => this.actionButtonClicked(event));
|
2018-11-29 16:20:44 +00:00
|
|
|
this.$form.on('change', 'input[type=checkbox]', () => this.templateFolderCheckboxChanged());
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-29 15:53:59 +00:00
|
|
|
this.getFocusRoutine = function (selector, setTabindex) {
|
|
|
|
|
return function () {
|
|
|
|
|
let $el = $(selector);
|
2019-01-30 10:47:26 +00:00
|
|
|
let removeTabindex = (e) => {
|
|
|
|
|
$(e.target)
|
|
|
|
|
.removeAttr('tabindex')
|
|
|
|
|
.off('blur', removeTabindex);
|
|
|
|
|
};
|
2019-01-29 15:53:59 +00:00
|
|
|
|
|
|
|
|
if (setTabindex) {
|
|
|
|
|
$el.attr('tabindex', '-1');
|
2019-01-30 10:47:26 +00:00
|
|
|
$el.on('blur', removeTabindex);
|
2019-01-29 15:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$el.focus();
|
|
|
|
|
};
|
|
|
|
|
};
|
|
|
|
|
|
2019-01-17 10:52:13 +00:00
|
|
|
this.activateStickyElements = function() {
|
2019-01-25 16:47:49 +00:00
|
|
|
var oldClass = 'js-will-stick-at-bottom-when-scrolling';
|
2019-01-17 10:52:13 +00:00
|
|
|
var newClass = 'js-stick-at-bottom-when-scrolling';
|
|
|
|
|
|
|
|
|
|
this.states.forEach(state => {
|
|
|
|
|
state.$el
|
2019-01-25 16:47:49 +00:00
|
|
|
.find('.' + oldClass)
|
2019-01-17 10:52:13 +00:00
|
|
|
.removeClass(oldClass)
|
|
|
|
|
.addClass(newClass);
|
|
|
|
|
});
|
|
|
|
|
};
|
|
|
|
|
|
2018-12-04 14:48:39 +00:00
|
|
|
this.addCancelButton = function(state) {
|
2019-02-01 16:13:04 +00:00
|
|
|
let selector = `[value=${state.key}]`;
|
2019-02-15 16:10:01 +00:00
|
|
|
let $cancel = this.makeButton('Cancel', {
|
|
|
|
|
'onclick': () => {
|
2018-11-30 12:02:51 +00:00
|
|
|
|
2019-02-15 16:10:01 +00:00
|
|
|
// clear existing data
|
|
|
|
|
state.$el.find('input:radio').prop('checked', false);
|
|
|
|
|
state.$el.find('input:text').val('');
|
2018-12-10 16:53:12 +00:00
|
|
|
|
2019-02-15 16:10:01 +00:00
|
|
|
// go back to action buttons
|
|
|
|
|
this.selectActionButtons(selector);
|
|
|
|
|
},
|
|
|
|
|
'cancelSelector': selector,
|
|
|
|
|
'nonvisualText': "this step"
|
|
|
|
|
});
|
2018-11-30 12:02:51 +00:00
|
|
|
|
2018-12-10 17:07:30 +00:00
|
|
|
state.$el.find('[type=submit]').after($cancel);
|
2018-11-30 12:02:51 +00:00
|
|
|
};
|
|
|
|
|
|
2018-12-10 16:53:12 +00:00
|
|
|
this.addClearButton = function(state) {
|
2019-02-13 16:43:38 +00:00
|
|
|
let selector = 'button[value=add-new-template]';
|
2019-02-15 16:10:01 +00:00
|
|
|
let $clear = this.makeButton('Clear', {
|
|
|
|
|
'onclick': () => {
|
2019-02-13 16:43:38 +00:00
|
|
|
|
2019-02-15 16:10:01 +00:00
|
|
|
// uncheck all templates and folders
|
|
|
|
|
this.$form.find('input:checkbox').prop('checked', false);
|
2018-12-10 16:53:12 +00:00
|
|
|
|
2019-02-15 16:10:01 +00:00
|
|
|
// go back to action buttons
|
|
|
|
|
this.selectActionButtons(selector);
|
|
|
|
|
},
|
|
|
|
|
'nonvisualText': "selection"
|
2018-12-10 16:53:12 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
|
|
state.$el.find('.template-list-selected-counter').append($clear);
|
|
|
|
|
};
|
|
|
|
|
|
2019-02-15 16:10:01 +00:00
|
|
|
this.makeButton = (text, opts) => {
|
|
|
|
|
let $btn = $('<a href=""></a>')
|
|
|
|
|
.html(text)
|
2019-12-09 19:09:24 +00:00
|
|
|
.addClass('govuk-link govuk-link--no-visited-state js-cancel')
|
2019-02-15 16:10:01 +00:00
|
|
|
// isn't set if cancelSelector is undefined
|
|
|
|
|
.data('target', opts.cancelSelector || undefined)
|
|
|
|
|
.attr('tabindex', '0')
|
|
|
|
|
.on('click keydown', event => {
|
|
|
|
|
// space, enter or no keyCode (must be mouse input)
|
|
|
|
|
if ([13, 32, undefined].indexOf(event.keyCode) > -1) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
if (opts.hasOwnProperty('onclick')) { opts.onclick(); }
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (opts.hasOwnProperty('nonvisualText')) {
|
2019-10-21 15:18:25 +01:00
|
|
|
$btn.append(`<span class="govuk-visually-hidden"> ${opts.nonvisualText}</span>`);
|
2018-12-10 17:32:36 +00:00
|
|
|
}
|
2019-02-15 16:10:01 +00:00
|
|
|
|
|
|
|
|
return $btn;
|
|
|
|
|
};
|
2018-12-10 16:53:12 +00:00
|
|
|
|
2019-02-01 16:13:04 +00:00
|
|
|
this.selectActionButtons = function (targetSelector) {
|
2018-12-05 12:01:02 +00:00
|
|
|
// If we want to show one of the grey choose actions state, we can pretend we're in the choose actions state,
|
|
|
|
|
// and then pretend a checkbox was clicked to work out whether to show zero or non-zero options.
|
|
|
|
|
// This calls a render at the end
|
|
|
|
|
this.currentState = 'nothing-selected-buttons';
|
|
|
|
|
this.templateFolderCheckboxChanged();
|
2019-02-01 16:13:04 +00:00
|
|
|
if (targetSelector) {
|
|
|
|
|
let setFocus = this.getFocusRoutine(targetSelector, false);
|
|
|
|
|
setFocus();
|
|
|
|
|
}
|
2018-12-05 12:01:02 +00:00
|
|
|
};
|
|
|
|
|
|
2019-03-20 14:04:06 +00:00
|
|
|
// method that checks the state against the last one, used prior to render() to see if needed
|
|
|
|
|
this.stateChanged = function() {
|
|
|
|
|
let changed = this.currentState !== this._lastState;
|
|
|
|
|
|
|
|
|
|
this._lastState = this.currentState;
|
|
|
|
|
return changed;
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-29 17:39:58 +00:00
|
|
|
this.actionButtonClicked = function(event) {
|
|
|
|
|
event.preventDefault();
|
|
|
|
|
this.currentState = $(event.currentTarget).val();
|
|
|
|
|
|
2019-03-20 14:04:06 +00:00
|
|
|
if (this.stateChanged()) {
|
|
|
|
|
this.render();
|
|
|
|
|
}
|
2018-11-29 17:39:58 +00:00
|
|
|
};
|
|
|
|
|
|
2019-02-13 17:47:24 +00:00
|
|
|
this.selectionStatus = {
|
|
|
|
|
'default': 'Nothing selected',
|
|
|
|
|
'selected': numSelected => `${numSelected} selected`,
|
|
|
|
|
'update': numSelected => {
|
2019-02-15 13:49:49 +00:00
|
|
|
let message = (numSelected > 0) ? this.selectionStatus.selected(numSelected) : this.selectionStatus.default;
|
2019-02-13 17:47:24 +00:00
|
|
|
|
2019-02-15 13:49:49 +00:00
|
|
|
$('.template-list-selected-counter__count').html(message);
|
|
|
|
|
this.$liveRegionCounter.html(message);
|
2019-02-13 17:47:24 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2018-11-29 17:39:58 +00:00
|
|
|
this.templateFolderCheckboxChanged = function() {
|
2018-11-29 16:20:44 +00:00
|
|
|
let numSelected = this.countSelectedCheckboxes();
|
|
|
|
|
|
2018-12-04 14:47:05 +00:00
|
|
|
if (this.currentState === 'nothing-selected-buttons' && numSelected !== 0) {
|
2018-11-30 16:29:00 +00:00
|
|
|
// user has just selected first item
|
2018-12-04 14:47:05 +00:00
|
|
|
this.currentState = 'items-selected-buttons';
|
|
|
|
|
} else if (this.currentState === 'items-selected-buttons' && numSelected === 0) {
|
2018-11-30 16:29:00 +00:00
|
|
|
// user has just deselected last item
|
2018-12-04 14:47:05 +00:00
|
|
|
this.currentState = 'nothing-selected-buttons';
|
2018-11-29 16:20:44 +00:00
|
|
|
}
|
2018-11-28 17:40:54 +00:00
|
|
|
|
2019-03-20 14:04:06 +00:00
|
|
|
if (this.stateChanged()) {
|
|
|
|
|
this.render();
|
|
|
|
|
}
|
2018-12-10 16:53:12 +00:00
|
|
|
|
2019-02-13 17:47:24 +00:00
|
|
|
this.selectionStatus.update(numSelected);
|
2018-12-10 16:53:12 +00:00
|
|
|
|
2019-01-03 10:50:05 +00:00
|
|
|
$('.template-list-selected-counter').toggle(this.hasCheckboxes());
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.hasCheckboxes = function() {
|
|
|
|
|
return !!this.$form.find('input:checkbox').length;
|
2018-11-28 17:40:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.countSelectedCheckboxes = function() {
|
2018-11-30 16:29:00 +00:00
|
|
|
return this.$form.find('input:checkbox:checked').length;
|
2018-11-28 17:40:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
this.render = function() {
|
2019-01-29 15:53:59 +00:00
|
|
|
let mode = 'default';
|
|
|
|
|
let currentStateObj = this.states.filter(state => { return (state.key === this.currentState); })[0];
|
2019-01-30 19:12:14 +00:00
|
|
|
|
2018-11-29 17:39:58 +00:00
|
|
|
// detach everything, unless they are the currentState
|
2018-12-04 14:48:39 +00:00
|
|
|
this.states.forEach(
|
2019-02-15 11:03:22 +00:00
|
|
|
state => (state.key === this.currentState ? this.$liveRegionCounter.before(state.$el) : state.$el.detach())
|
2018-11-29 17:39:58 +00:00
|
|
|
);
|
2018-12-13 14:25:22 +00:00
|
|
|
|
2019-01-08 17:30:46 +00:00
|
|
|
// use dialog mode for states which contain more than one form control
|
2019-02-04 15:17:27 +00:00
|
|
|
if (['move-to-existing-folder', 'add-new-template'].indexOf(this.currentState) !== -1) {
|
2019-01-30 19:12:14 +00:00
|
|
|
mode = 'dialog';
|
2019-01-30 11:45:24 +00:00
|
|
|
}
|
2019-01-30 19:12:14 +00:00
|
|
|
GOVUK.stickAtBottomWhenScrolling.setMode(mode);
|
2019-01-30 11:45:24 +00:00
|
|
|
// make sticky JS recalculate its cache of the element's position
|
|
|
|
|
GOVUK.stickAtBottomWhenScrolling.recalculate();
|
2019-02-08 15:22:13 +00:00
|
|
|
|
|
|
|
|
if (currentStateObj && ('setFocus' in currentStateObj)) { currentStateObj.setFocus(); }
|
2018-11-28 17:40:54 +00:00
|
|
|
};
|
|
|
|
|
|
2019-01-08 15:57:55 +00:00
|
|
|
this.nothingSelectedButtons = $(`
|
2019-01-25 16:47:49 +00:00
|
|
|
<div id="nothing_selected">
|
|
|
|
|
<div class="js-stick-at-bottom-when-scrolling">
|
2020-02-06 10:50:57 +00:00
|
|
|
<button class="govuk-button govuk-button--secondary govuk-!-margin-right-3 govuk-!-margin-bottom-1" value="add-new-template">New template</button>
|
|
|
|
|
<button class="govuk-button govuk-button--secondary govuk-!-margin-bottom-1" value="add-new-folder">New folder</button>
|
2019-02-15 13:49:49 +00:00
|
|
|
<div class="template-list-selected-counter">
|
|
|
|
|
<span class="template-list-selected-counter__count" aria-hidden="true">
|
|
|
|
|
${this.selectionStatus.default}
|
|
|
|
|
</span>
|
2019-01-25 16:47:49 +00:00
|
|
|
</div>
|
2018-12-10 16:53:12 +00:00
|
|
|
</div>
|
2018-11-30 16:29:00 +00:00
|
|
|
</div>
|
2019-01-08 15:57:55 +00:00
|
|
|
`).get(0);
|
2018-11-28 17:40:54 +00:00
|
|
|
|
2019-01-08 15:57:55 +00:00
|
|
|
this.itemsSelectedButtons = $(`
|
2019-01-25 16:47:49 +00:00
|
|
|
<div id="items_selected">
|
|
|
|
|
<div class="js-stick-at-bottom-when-scrolling">
|
2020-02-06 10:50:57 +00:00
|
|
|
<button class="govuk-button govuk-button--secondary govuk-!-margin-right-3 govuk-!-margin-bottom-1" value="move-to-existing-folder">Move</button>
|
|
|
|
|
<button class="govuk-button govuk-button--secondary govuk-!-margin-bottom-1" value="move-to-new-folder">Add to new folder</button>
|
2019-02-15 11:03:22 +00:00
|
|
|
<div class="template-list-selected-counter" aria-hidden="true">
|
2019-02-15 13:49:49 +00:00
|
|
|
<span class="template-list-selected-counter__count" aria-hidden="true">
|
|
|
|
|
${this.selectionStatus.selected(1)}
|
|
|
|
|
</span>
|
2019-01-25 16:47:49 +00:00
|
|
|
</div>
|
2018-12-10 16:53:12 +00:00
|
|
|
</div>
|
2018-11-30 16:29:00 +00:00
|
|
|
</div>
|
2019-01-08 15:57:55 +00:00
|
|
|
`).get(0);
|
2018-11-28 17:40:54 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
})(window.GOVUK.Modules);
|