@ministryofjustice/frontend 3.4.0 → 3.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/moj/all.jquery.js +13378 -0
  2. package/moj/all.jquery.min.js +1 -144
  3. package/moj/all.js +2266 -2551
  4. package/moj/all.mjs +126 -0
  5. package/moj/components/add-another/add-another.js +110 -100
  6. package/moj/components/add-another/add-another.mjs +106 -0
  7. package/moj/components/alert/alert.js +319 -211
  8. package/moj/components/alert/alert.mjs +251 -0
  9. package/moj/components/alert/alert.spec.helper.js +12 -5
  10. package/moj/components/alert/alert.spec.helper.mjs +66 -0
  11. package/moj/components/button-menu/button-menu.js +302 -292
  12. package/moj/components/button-menu/button-menu.mjs +329 -0
  13. package/moj/components/date-picker/date-picker.js +850 -842
  14. package/moj/components/date-picker/date-picker.mjs +961 -0
  15. package/moj/components/filter-toggle-button/filter-toggle-button.js +98 -88
  16. package/moj/components/filter-toggle-button/filter-toggle-button.mjs +93 -0
  17. package/moj/components/form-validator/form-validator.js +195 -155
  18. package/moj/components/form-validator/form-validator.mjs +168 -0
  19. package/moj/components/multi-file-upload/multi-file-upload.js +158 -137
  20. package/moj/components/multi-file-upload/multi-file-upload.mjs +219 -0
  21. package/moj/components/multi-select/multi-select.js +75 -65
  22. package/moj/components/multi-select/multi-select.mjs +77 -0
  23. package/moj/components/password-reveal/password-reveal.js +40 -30
  24. package/moj/components/password-reveal/password-reveal.mjs +35 -0
  25. package/moj/components/rich-text-editor/rich-text-editor.js +92 -80
  26. package/moj/components/rich-text-editor/rich-text-editor.mjs +157 -0
  27. package/moj/components/search-toggle/search-toggle.js +55 -45
  28. package/moj/components/search-toggle/search-toggle.mjs +54 -0
  29. package/moj/components/sortable-table/sortable-table.js +141 -141
  30. package/moj/components/sortable-table/sortable-table.mjs +138 -0
  31. package/moj/helpers/_links.scss +1 -1
  32. package/moj/helpers.js +171 -152
  33. package/moj/helpers.mjs +123 -0
  34. package/moj/moj-frontend.min.js +1 -144
  35. package/moj/version.js +11 -1
  36. package/moj/version.mjs +3 -0
  37. package/package.json +13 -1
  38. package/moj/all.spec.js +0 -24
  39. package/moj/components/add-another/add-another.spec.js +0 -165
  40. package/moj/components/alert/alert.spec.js +0 -229
  41. package/moj/components/button-menu/button-menu.spec.js +0 -360
  42. package/moj/components/date-picker/date-picker.spec.js +0 -1178
  43. package/moj/components/filter-toggle-button/filter-toggle-button.spec.js +0 -302
  44. package/moj/components/multi-file-upload/multi-file-upload.spec.js +0 -510
  45. package/moj/components/multi-select/multi-select.spec.js +0 -128
  46. package/moj/components/password-reveal/password-reveal.spec.js +0 -57
  47. package/moj/components/search-toggle/search-toggle.spec.js +0 -129
  48. package/moj/components/sortable-table/sortable-table.spec.js +0 -362
  49. package/moj/helpers.spec.js +0 -235
  50. package/moj/namespace.js +0 -2
package/moj/all.mjs ADDED
@@ -0,0 +1,126 @@
1
+ import { AddAnother } from './components/add-another/add-another.mjs';
2
+ import { Alert } from './components/alert/alert.mjs';
3
+ import { ButtonMenu } from './components/button-menu/button-menu.mjs';
4
+ import { DatePicker } from './components/date-picker/date-picker.mjs';
5
+ export { FilterToggleButton } from './components/filter-toggle-button/filter-toggle-button.mjs';
6
+ export { MultiFileUpload } from './components/multi-file-upload/multi-file-upload.mjs';
7
+ import { MultiSelect } from './components/multi-select/multi-select.mjs';
8
+ import { PasswordReveal } from './components/password-reveal/password-reveal.mjs';
9
+ import { RichTextEditor } from './components/rich-text-editor/rich-text-editor.mjs';
10
+ import { SearchToggle } from './components/search-toggle/search-toggle.mjs';
11
+ import { SortableTable } from './components/sortable-table/sortable-table.mjs';
12
+ import { nodeListForEach } from './helpers.mjs';
13
+ export { version } from './version.mjs';
14
+
15
+ /* eslint-disable no-new */
16
+
17
+
18
+ function initAll(options) {
19
+ // Set the options to an empty object by default if no options are passed.
20
+ options = typeof options !== 'undefined' ? options : {};
21
+
22
+ // Allow the user to initialise MOJ Frontend in only certain sections of the page
23
+ // Defaults to the entire document if nothing is set.
24
+ const scope = typeof options.scope !== 'undefined' ? options.scope : document;
25
+
26
+ const $addAnothers = scope.querySelectorAll('[data-module="moj-add-another"]');
27
+
28
+ nodeListForEach($addAnothers, function ($addAnother) {
29
+ new AddAnother($addAnother);
30
+ });
31
+
32
+ const $multiSelects = scope.querySelectorAll(
33
+ '[data-module="moj-multi-select"]'
34
+ );
35
+
36
+ nodeListForEach($multiSelects, function ($multiSelect) {
37
+ new MultiSelect({
38
+ container: $multiSelect.querySelector(
39
+ $multiSelect.getAttribute('data-multi-select-checkbox')
40
+ ),
41
+ checkboxes: $multiSelect.querySelectorAll(
42
+ 'tbody .govuk-checkboxes__input'
43
+ ),
44
+ id_prefix: $multiSelect.getAttribute('data-multi-select-idprefix')
45
+ });
46
+ });
47
+
48
+ const $passwordReveals = scope.querySelectorAll(
49
+ '[data-module="moj-password-reveal"]'
50
+ );
51
+
52
+ nodeListForEach($passwordReveals, function ($passwordReveal) {
53
+ new PasswordReveal($passwordReveal);
54
+ });
55
+
56
+ const $richTextEditors = scope.querySelectorAll(
57
+ '[data-module="moj-rich-text-editor"]'
58
+ );
59
+
60
+ nodeListForEach($richTextEditors, function ($richTextEditor) {
61
+ const options = {
62
+ textarea: window.jQuery($richTextEditor)
63
+ };
64
+
65
+ const toolbarAttr = $richTextEditor.getAttribute(
66
+ 'data-moj-rich-text-editor-toolbar'
67
+ );
68
+
69
+ if (toolbarAttr) {
70
+ const toolbar = toolbarAttr.split(',');
71
+
72
+ options.toolbar = {};
73
+
74
+ for (const item in toolbar) {
75
+ options.toolbar[toolbar[item]] = true;
76
+ }
77
+ }
78
+
79
+ new RichTextEditor(options);
80
+ });
81
+
82
+ const $searchToggles = scope.querySelectorAll(
83
+ '[data-module="moj-search-toggle"]'
84
+ );
85
+
86
+ nodeListForEach($searchToggles, function ($searchToggle) {
87
+ new SearchToggle({
88
+ toggleButton: {
89
+ container: window.jQuery($searchToggle.querySelector('.moj-search-toggle__toggle')),
90
+ text: $searchToggle.getAttribute('data-moj-search-toggle-text')
91
+ },
92
+ search: {
93
+ container: window.jQuery($searchToggle.querySelector('.moj-search'))
94
+ }
95
+ });
96
+ });
97
+
98
+ const $sortableTables = scope.querySelectorAll(
99
+ '[data-module="moj-sortable-table"]'
100
+ );
101
+
102
+ nodeListForEach($sortableTables, function ($table) {
103
+ new SortableTable({
104
+ table: $table
105
+ });
106
+ });
107
+
108
+ const $datepickers = scope.querySelectorAll('[data-module="moj-date-picker"]');
109
+
110
+ nodeListForEach($datepickers, function ($datepicker) {
111
+ new DatePicker($datepicker, {}).init();
112
+ });
113
+
114
+ const $buttonMenus = scope.querySelectorAll('[data-module="moj-button-menu"]');
115
+
116
+ nodeListForEach($buttonMenus, function ($buttonmenu) {
117
+ new ButtonMenu($buttonmenu, {}).init();
118
+ });
119
+
120
+ const $alerts = scope.querySelectorAll('[data-module="moj-alert"]');
121
+ nodeListForEach($alerts, function ($alert) {
122
+ new Alert($alert, {}).init();
123
+ });
124
+ }
125
+
126
+ export { AddAnother, Alert, ButtonMenu, DatePicker, MultiSelect, PasswordReveal, RichTextEditor, SearchToggle, SortableTable, initAll };
@@ -1,104 +1,114 @@
1
- MOJFrontend.AddAnother = function (container) {
2
- this.container = $(container)
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.MOJFrontend = global.MOJFrontend || {}));
5
+ })(this, (function (exports) { 'use strict';
3
6
 
4
- if (this.container.data('moj-add-another-initialised')) {
5
- return
6
- }
7
+ function AddAnother(container) {
8
+ this.container = window.jQuery(container);
7
9
 
8
- this.container.data('moj-add-another-initialised', true)
9
-
10
- this.container.on(
11
- 'click',
12
- '.moj-add-another__remove-button',
13
- $.proxy(this, 'onRemoveButtonClick')
14
- )
15
- this.container.on(
16
- 'click',
17
- '.moj-add-another__add-button',
18
- $.proxy(this, 'onAddButtonClick')
19
- )
20
- this.container
21
- .find('.moj-add-another__add-button, moj-add-another__remove-button')
22
- .prop('type', 'button')
23
- }
24
-
25
- MOJFrontend.AddAnother.prototype.onAddButtonClick = function (e) {
26
- const item = this.getNewItem()
27
- this.updateAttributes(this.getItems().length, item)
28
- this.resetItem(item)
29
- const firstItem = this.getItems().first()
30
- if (!this.hasRemoveButton(firstItem)) {
31
- this.createRemoveButton(firstItem)
32
- }
33
- this.getItems().last().after(item)
34
- item.find('input, textarea, select').first().focus()
35
- }
36
-
37
- MOJFrontend.AddAnother.prototype.hasRemoveButton = function (item) {
38
- return item.find('.moj-add-another__remove-button').length
39
- }
40
-
41
- MOJFrontend.AddAnother.prototype.getItems = function () {
42
- return this.container.find('.moj-add-another__item')
43
- }
44
-
45
- MOJFrontend.AddAnother.prototype.getNewItem = function () {
46
- const item = this.getItems().first().clone()
47
- if (!this.hasRemoveButton(item)) {
48
- this.createRemoveButton(item)
49
- }
50
- return item
51
- }
52
-
53
- MOJFrontend.AddAnother.prototype.updateAttributes = function (index, item) {
54
- item.find('[data-name]').each(function (i, el) {
55
- const originalId = el.id
56
-
57
- el.name = $(el)
58
- .attr('data-name')
59
- .replace(/%index%/, index)
60
- el.id = $(el)
61
- .attr('data-id')
62
- .replace(/%index%/, index)
63
-
64
- const label =
65
- $(el).siblings('label')[0] ||
66
- $(el).parents('label')[0] ||
67
- item.find(`[for="${originalId}"]`)[0]
68
- label.htmlFor = el.id
69
- })
70
- }
71
-
72
- MOJFrontend.AddAnother.prototype.createRemoveButton = function (item) {
73
- item.append(
74
- '<button type="button" class="govuk-button govuk-button--secondary moj-add-another__remove-button">Remove</button>'
75
- )
76
- }
77
-
78
- MOJFrontend.AddAnother.prototype.resetItem = function (item) {
79
- item.find('[data-name], [data-id]').each(function (index, el) {
80
- if (el.type === 'checkbox' || el.type === 'radio') {
81
- el.checked = false
82
- } else {
83
- el.value = ''
10
+ if (this.container.data('moj-add-another-initialised')) {
11
+ return
84
12
  }
85
- })
86
- }
87
-
88
- MOJFrontend.AddAnother.prototype.onRemoveButtonClick = function (e) {
89
- $(e.currentTarget).parents('.moj-add-another__item').remove()
90
- const items = this.getItems()
91
- if (items.length === 1) {
92
- items.find('.moj-add-another__remove-button').remove()
13
+
14
+ this.container.data('moj-add-another-initialised', true);
15
+
16
+ this.container.on(
17
+ 'click',
18
+ '.moj-add-another__remove-button',
19
+ window.jQuery.proxy(this, 'onRemoveButtonClick')
20
+ );
21
+ this.container.on(
22
+ 'click',
23
+ '.moj-add-another__add-button',
24
+ window.jQuery.proxy(this, 'onAddButtonClick')
25
+ );
26
+ this.container
27
+ .find('.moj-add-another__add-button, moj-add-another__remove-button')
28
+ .prop('type', 'button');
93
29
  }
94
- items.each(
95
- $.proxy(function (index, el) {
96
- this.updateAttributes(index, $(el))
97
- }, this)
98
- )
99
- this.focusHeading()
100
- }
101
-
102
- MOJFrontend.AddAnother.prototype.focusHeading = function () {
103
- this.container.find('.moj-add-another__heading').get(0).focus()
104
- }
30
+
31
+ AddAnother.prototype.onAddButtonClick = function (e) {
32
+ const item = this.getNewItem();
33
+ this.updateAttributes(this.getItems().length, item);
34
+ this.resetItem(item);
35
+ const firstItem = this.getItems().first();
36
+ if (!this.hasRemoveButton(firstItem)) {
37
+ this.createRemoveButton(firstItem);
38
+ }
39
+ this.getItems().last().after(item);
40
+ item.find('input, textarea, select').first().focus();
41
+ };
42
+
43
+ AddAnother.prototype.hasRemoveButton = function (item) {
44
+ return item.find('.moj-add-another__remove-button').length
45
+ };
46
+
47
+ AddAnother.prototype.getItems = function () {
48
+ return this.container.find('.moj-add-another__item')
49
+ };
50
+
51
+ AddAnother.prototype.getNewItem = function () {
52
+ const item = this.getItems().first().clone();
53
+ if (!this.hasRemoveButton(item)) {
54
+ this.createRemoveButton(item);
55
+ }
56
+ return item
57
+ };
58
+
59
+ AddAnother.prototype.updateAttributes = function (index, item) {
60
+ item.find('[data-name]').each(function (i, el) {
61
+ const originalId = el.id;
62
+
63
+ el.name = window.jQuery(el)
64
+ .attr('data-name')
65
+ .replace(/%index%/, index);
66
+ el.id = window.jQuery(el)
67
+ .attr('data-id')
68
+ .replace(/%index%/, index);
69
+
70
+ const label =
71
+ window.jQuery(el).siblings('label')[0] ||
72
+ window.jQuery(el).parents('label')[0] ||
73
+ item.find(`[for="${originalId}"]`)[0];
74
+ label.htmlFor = el.id;
75
+ });
76
+ };
77
+
78
+ AddAnother.prototype.createRemoveButton = function (item) {
79
+ item.append(
80
+ '<button type="button" class="govuk-button govuk-button--secondary moj-add-another__remove-button">Remove</button>'
81
+ );
82
+ };
83
+
84
+ AddAnother.prototype.resetItem = function (item) {
85
+ item.find('[data-name], [data-id]').each(function (index, el) {
86
+ if (el.type === 'checkbox' || el.type === 'radio') {
87
+ el.checked = false;
88
+ } else {
89
+ el.value = '';
90
+ }
91
+ });
92
+ };
93
+
94
+ AddAnother.prototype.onRemoveButtonClick = function (e) {
95
+ window.jQuery(e.currentTarget).parents('.moj-add-another__item').remove();
96
+ const items = this.getItems();
97
+ if (items.length === 1) {
98
+ items.find('.moj-add-another__remove-button').remove();
99
+ }
100
+ items.each(
101
+ window.jQuery.proxy(function (index, el) {
102
+ this.updateAttributes(index, window.jQuery(el));
103
+ }, this)
104
+ );
105
+ this.focusHeading();
106
+ };
107
+
108
+ AddAnother.prototype.focusHeading = function () {
109
+ this.container.find('.moj-add-another__heading').get(0).focus();
110
+ };
111
+
112
+ exports.AddAnother = AddAnother;
113
+
114
+ }));
@@ -0,0 +1,106 @@
1
+ function AddAnother(container) {
2
+ this.container = window.jQuery(container);
3
+
4
+ if (this.container.data('moj-add-another-initialised')) {
5
+ return
6
+ }
7
+
8
+ this.container.data('moj-add-another-initialised', true);
9
+
10
+ this.container.on(
11
+ 'click',
12
+ '.moj-add-another__remove-button',
13
+ window.jQuery.proxy(this, 'onRemoveButtonClick')
14
+ );
15
+ this.container.on(
16
+ 'click',
17
+ '.moj-add-another__add-button',
18
+ window.jQuery.proxy(this, 'onAddButtonClick')
19
+ );
20
+ this.container
21
+ .find('.moj-add-another__add-button, moj-add-another__remove-button')
22
+ .prop('type', 'button');
23
+ }
24
+
25
+ AddAnother.prototype.onAddButtonClick = function (e) {
26
+ const item = this.getNewItem();
27
+ this.updateAttributes(this.getItems().length, item);
28
+ this.resetItem(item);
29
+ const firstItem = this.getItems().first();
30
+ if (!this.hasRemoveButton(firstItem)) {
31
+ this.createRemoveButton(firstItem);
32
+ }
33
+ this.getItems().last().after(item);
34
+ item.find('input, textarea, select').first().focus();
35
+ };
36
+
37
+ AddAnother.prototype.hasRemoveButton = function (item) {
38
+ return item.find('.moj-add-another__remove-button').length
39
+ };
40
+
41
+ AddAnother.prototype.getItems = function () {
42
+ return this.container.find('.moj-add-another__item')
43
+ };
44
+
45
+ AddAnother.prototype.getNewItem = function () {
46
+ const item = this.getItems().first().clone();
47
+ if (!this.hasRemoveButton(item)) {
48
+ this.createRemoveButton(item);
49
+ }
50
+ return item
51
+ };
52
+
53
+ AddAnother.prototype.updateAttributes = function (index, item) {
54
+ item.find('[data-name]').each(function (i, el) {
55
+ const originalId = el.id;
56
+
57
+ el.name = window.jQuery(el)
58
+ .attr('data-name')
59
+ .replace(/%index%/, index);
60
+ el.id = window.jQuery(el)
61
+ .attr('data-id')
62
+ .replace(/%index%/, index);
63
+
64
+ const label =
65
+ window.jQuery(el).siblings('label')[0] ||
66
+ window.jQuery(el).parents('label')[0] ||
67
+ item.find(`[for="${originalId}"]`)[0];
68
+ label.htmlFor = el.id;
69
+ });
70
+ };
71
+
72
+ AddAnother.prototype.createRemoveButton = function (item) {
73
+ item.append(
74
+ '<button type="button" class="govuk-button govuk-button--secondary moj-add-another__remove-button">Remove</button>'
75
+ );
76
+ };
77
+
78
+ AddAnother.prototype.resetItem = function (item) {
79
+ item.find('[data-name], [data-id]').each(function (index, el) {
80
+ if (el.type === 'checkbox' || el.type === 'radio') {
81
+ el.checked = false;
82
+ } else {
83
+ el.value = '';
84
+ }
85
+ });
86
+ };
87
+
88
+ AddAnother.prototype.onRemoveButtonClick = function (e) {
89
+ window.jQuery(e.currentTarget).parents('.moj-add-another__item').remove();
90
+ const items = this.getItems();
91
+ if (items.length === 1) {
92
+ items.find('.moj-add-another__remove-button').remove();
93
+ }
94
+ items.each(
95
+ window.jQuery.proxy(function (index, el) {
96
+ this.updateAttributes(index, window.jQuery(el));
97
+ }, this)
98
+ );
99
+ this.focusHeading();
100
+ };
101
+
102
+ AddAnother.prototype.focusHeading = function () {
103
+ this.container.find('.moj-add-another__heading').get(0).focus();
104
+ };
105
+
106
+ export { AddAnother };