@bennerinformatics/ember-fw-table 2.1.4 → 2.1.6

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 (166) hide show
  1. package/addon/components/fw-table-resort.js +18 -4
  2. package/addon/components/fw-table-sortable.js +23 -0
  3. package/addon/templates/components/fw-table-resort.hbs +3 -0
  4. package/addon/templates/components/fw-table-sortable.hbs +10 -1
  5. package/docs/api.js +61 -0
  6. package/docs/assets/css/custom.css +82 -0
  7. package/docs/assets/css/external-small.png +0 -0
  8. package/docs/assets/css/logo.png +0 -0
  9. package/docs/assets/css/main.css +793 -0
  10. package/docs/assets/css/theme.css +547 -0
  11. package/docs/assets/favicon.ico +0 -0
  12. package/docs/assets/icons/android-icon-144x144.png +0 -0
  13. package/docs/assets/icons/android-icon-192x192.png +0 -0
  14. package/docs/assets/icons/android-icon-36x36.png +0 -0
  15. package/docs/assets/icons/android-icon-48x48.png +0 -0
  16. package/docs/assets/icons/android-icon-72x72.png +0 -0
  17. package/docs/assets/icons/android-icon-96x96.png +0 -0
  18. package/docs/assets/icons/apple-icon-114x114.png +0 -0
  19. package/docs/assets/icons/apple-icon-120x120.png +0 -0
  20. package/docs/assets/icons/apple-icon-144x144.png +0 -0
  21. package/docs/assets/icons/apple-icon-152x152.png +0 -0
  22. package/docs/assets/icons/apple-icon-180x180.png +0 -0
  23. package/docs/assets/icons/apple-icon-57x57.png +0 -0
  24. package/docs/assets/icons/apple-icon-60x60.png +0 -0
  25. package/docs/assets/icons/apple-icon-72x72.png +0 -0
  26. package/docs/assets/icons/apple-icon-76x76.png +0 -0
  27. package/docs/assets/icons/apple-icon-precomposed.png +0 -0
  28. package/docs/assets/icons/apple-icon.png +0 -0
  29. package/docs/assets/icons/browserconfig.xml +2 -0
  30. package/docs/assets/icons/favicon-16x16.png +0 -0
  31. package/docs/assets/icons/favicon-32x32.png +0 -0
  32. package/docs/assets/icons/favicon-96x96.png +0 -0
  33. package/docs/assets/icons/favicon.ico +0 -0
  34. package/docs/assets/icons/manifest.json +41 -0
  35. package/docs/assets/icons/ms-icon-144x144.png +0 -0
  36. package/docs/assets/icons/ms-icon-150x150.png +0 -0
  37. package/docs/assets/icons/ms-icon-310x310.png +0 -0
  38. package/docs/assets/icons/ms-icon-70x70.png +0 -0
  39. package/docs/assets/img/ember-logo.png +0 -0
  40. package/docs/assets/img/fw-logo.png +0 -0
  41. package/docs/assets/img/spinner.gif +0 -0
  42. package/docs/assets/index.html +10 -0
  43. package/docs/assets/js/api-filter.js +56 -0
  44. package/docs/assets/js/api-list.js +255 -0
  45. package/docs/assets/js/api-search.js +98 -0
  46. package/docs/assets/js/apidocs.js +376 -0
  47. package/docs/assets/js/yui-prettify.js +17 -0
  48. package/docs/assets/js/yuidoc-bootstrap.js +274 -0
  49. package/docs/assets/vendor/bootstrap/css/bootstrap.css +6760 -0
  50. package/docs/assets/vendor/bootstrap/css/bootstrap.min.css +6 -0
  51. package/docs/assets/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  52. package/docs/assets/vendor/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
  53. package/docs/assets/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  54. package/docs/assets/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  55. package/docs/assets/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
  56. package/docs/assets/vendor/bootstrap/img/glyphicons-halflings-white.png +0 -0
  57. package/docs/assets/vendor/bootstrap/img/glyphicons-halflings.png +0 -0
  58. package/docs/assets/vendor/bootstrap/js/bootstrap.js +2363 -0
  59. package/docs/assets/vendor/bootstrap/js/bootstrap.min.js +7 -0
  60. package/docs/assets/vendor/font-awesome/css/font-awesome.css +2199 -0
  61. package/docs/assets/vendor/font-awesome/css/font-awesome.min.css +4 -0
  62. package/docs/assets/vendor/font-awesome/fonts/FontAwesome.otf +0 -0
  63. package/docs/assets/vendor/font-awesome/fonts/fontawesome-webfont.eot +0 -0
  64. package/docs/assets/vendor/font-awesome/fonts/fontawesome-webfont.svg +685 -0
  65. package/docs/assets/vendor/font-awesome/fonts/fontawesome-webfont.ttf +0 -0
  66. package/docs/assets/vendor/font-awesome/fonts/fontawesome-webfont.woff +0 -0
  67. package/docs/assets/vendor/font-awesome/fonts/fontawesome-webfont.woff2 +0 -0
  68. package/docs/assets/vendor/github-slugger/slugger.js +59 -0
  69. package/docs/assets/vendor/jquery/jquery.min.js +6 -0
  70. package/docs/assets/vendor/jquery-ui/jquery-ui.min.js +6 -0
  71. package/docs/assets/vendor/prettify/CHANGES.html +130 -0
  72. package/docs/assets/vendor/prettify/COPYING +202 -0
  73. package/docs/assets/vendor/prettify/README.html +203 -0
  74. package/docs/assets/vendor/prettify/prettify-min.css +1 -0
  75. package/docs/assets/vendor/prettify/prettify-min.js +1 -0
  76. package/docs/classes/BaseCells.html +484 -0
  77. package/docs/classes/Export.html +457 -0
  78. package/docs/classes/Format.html +577 -0
  79. package/docs/classes/FwCellAction.html +312 -0
  80. package/docs/classes/FwCellBoolean.html +311 -0
  81. package/docs/classes/FwCellNullable.html +312 -0
  82. package/docs/classes/FwCellPermissionIcon.html +321 -0
  83. package/docs/classes/FwColumnSortable.html +358 -0
  84. package/docs/classes/FwColumnTitle.html +314 -0
  85. package/docs/classes/FwDeleteModal.html +485 -0
  86. package/docs/classes/FwExpandableRow.html +307 -0
  87. package/docs/classes/FwPaginationWrapper.html +2129 -0
  88. package/docs/classes/FwRowToggle.html +355 -0
  89. package/docs/classes/FwRowToggleIndex.html +312 -0
  90. package/docs/classes/FwTableExpandedRow.html +307 -0
  91. package/docs/classes/FwTableResort.html +827 -0
  92. package/docs/classes/FwTableSortable.html +1293 -0
  93. package/docs/classes/Row.html +352 -0
  94. package/docs/classes/Table.html +672 -0
  95. package/docs/classes/TableUtil.html +410 -0
  96. package/docs/classes/index.html +10 -0
  97. package/docs/data.json +2324 -0
  98. package/docs/elements/index.html +10 -0
  99. package/docs/files/addon_classes_Row.js.html +318 -0
  100. package/docs/files/addon_classes_Table.js.html +390 -0
  101. package/docs/files/addon_components_fw-cell-action.js.html +257 -0
  102. package/docs/files/addon_components_fw-cell-boolean.js.html +251 -0
  103. package/docs/files/addon_components_fw-cell-nullable.js.html +253 -0
  104. package/docs/files/addon_components_fw-cell-permission-icon.js.html +266 -0
  105. package/docs/files/addon_components_fw-column-sortable.js.html +281 -0
  106. package/docs/files/addon_components_fw-column-title.js.html +259 -0
  107. package/docs/files/addon_components_fw-delete-modal.js.html +318 -0
  108. package/docs/files/addon_components_fw-expandable-row.js.html +248 -0
  109. package/docs/files/addon_components_fw-pagination-wrapper.js.html +838 -0
  110. package/docs/files/addon_components_fw-row-toggle-index.js.html +252 -0
  111. package/docs/files/addon_components_fw-row-toggle.js.html +270 -0
  112. package/docs/files/addon_components_fw-table-expanded-row.js.html +261 -0
  113. package/docs/files/addon_components_fw-table-expanded-rows.js.html +263 -0
  114. package/docs/files/addon_components_fw-table-resort.js.html +457 -0
  115. package/docs/files/addon_components_fw-table-sortable.js.html +663 -0
  116. package/docs/files/addon_documentation.js.html +301 -0
  117. package/docs/files/addon_initializers_responsive.js.html +253 -0
  118. package/docs/files/addon_utils_base-cells.js.html +313 -0
  119. package/docs/files/addon_utils_export.js.html +316 -0
  120. package/docs/files/addon_utils_formats.js.html +335 -0
  121. package/docs/files/addon_utils_table.js.html +274 -0
  122. package/docs/files/index.html +10 -0
  123. package/docs/index.html +252 -0
  124. package/docs/modules/CellComponents.html +313 -0
  125. package/docs/modules/ColumnComponents.html +284 -0
  126. package/docs/modules/Components.html +285 -0
  127. package/docs/modules/Introduction.html +261 -0
  128. package/docs/modules/Utils.html +285 -0
  129. package/docs/modules/index.html +10 -0
  130. package/package.json +64 -64
  131. package/.yalc/ember-sortable/.huskyrc +0 -5
  132. package/.yalc/ember-sortable/CHANGELOG.md +0 -755
  133. package/.yalc/ember-sortable/CODE_OF_CONDUCT.md +0 -6
  134. package/.yalc/ember-sortable/LICENSE.md +0 -9
  135. package/.yalc/ember-sortable/MIGRATION_GUIDE_MODIFIERS.md +0 -95
  136. package/.yalc/ember-sortable/MIGRATION_GUIDE_V2.md +0 -120
  137. package/.yalc/ember-sortable/Makefile +0 -24
  138. package/.yalc/ember-sortable/README.md +0 -423
  139. package/.yalc/ember-sortable/RELEASE.md +0 -60
  140. package/.yalc/ember-sortable/V2_MIGRATION_RFC.md +0 -1100
  141. package/.yalc/ember-sortable/addon/modifiers/sortable-group.js +0 -754
  142. package/.yalc/ember-sortable/addon/modifiers/sortable-handle.js +0 -29
  143. package/.yalc/ember-sortable/addon/modifiers/sortable-item.js +0 -869
  144. package/.yalc/ember-sortable/addon/services/ember-sortable.js +0 -92
  145. package/.yalc/ember-sortable/addon/system/scroll-container.js +0 -53
  146. package/.yalc/ember-sortable/addon/system/scroll-parent.js +0 -33
  147. package/.yalc/ember-sortable/addon/utils/constant.js +0 -9
  148. package/.yalc/ember-sortable/addon/utils/coordinate.js +0 -34
  149. package/.yalc/ember-sortable/addon/utils/css-calculation.js +0 -20
  150. package/.yalc/ember-sortable/addon/utils/defaults.js +0 -26
  151. package/.yalc/ember-sortable/addon/utils/keyboard.js +0 -32
  152. package/.yalc/ember-sortable/addon-test-support/helpers/drag.js +0 -111
  153. package/.yalc/ember-sortable/addon-test-support/helpers/index.js +0 -4
  154. package/.yalc/ember-sortable/addon-test-support/helpers/reorder.js +0 -41
  155. package/.yalc/ember-sortable/addon-test-support/utils/keyboard.js +0 -32
  156. package/.yalc/ember-sortable/addon-test-support/utils/offset.js +0 -14
  157. package/.yalc/ember-sortable/app/modifiers/sortable-group.js +0 -1
  158. package/.yalc/ember-sortable/app/modifiers/sortable-handle.js +0 -1
  159. package/.yalc/ember-sortable/app/modifiers/sortable-item.js +0 -1
  160. package/.yalc/ember-sortable/app/services/ember-sortable-internal-state.js +0 -1
  161. package/.yalc/ember-sortable/config/environment.js +0 -5
  162. package/.yalc/ember-sortable/demo.gif +0 -0
  163. package/.yalc/ember-sortable/index.js +0 -5
  164. package/.yalc/ember-sortable/package.json +0 -65
  165. package/.yalc/ember-sortable/yalc.sig +0 -1
  166. package/yalc.lock +0 -10
@@ -1,754 +0,0 @@
1
- /* eslint-disable ember/no-computed-properties-in-native-classes */
2
- /* eslint-disable ember/no-incorrect-calls-with-inline-anonymous-functions */
3
- import Modifier from 'ember-modifier';
4
- import { action, computed, set } from '@ember/object';
5
- import {
6
- isDownArrowKey,
7
- isEnterKey,
8
- isEscapeKey,
9
- isLeftArrowKey,
10
- isRightArrowKey,
11
- isSpaceKey,
12
- isUpArrowKey,
13
- } from '../utils/keyboard';
14
- import { ANNOUNCEMENT_ACTION_TYPES } from '../utils/constant';
15
- import { defaultA11yAnnouncementConfig } from '../utils/defaults';
16
- import { next, schedule, scheduleOnce, later } from '@ember/runloop';
17
- import { inject as service } from '@ember/service';
18
- import { registerDestructor, isDestroyed } from '@ember/destroyable';
19
-
20
- const NO_MODEL = {};
21
-
22
- /**
23
- * Modifier to apply a11y support to a group container for the Sortable component
24
- *
25
- * @param {String} [a11yItemName] A name for each model, used for creating more meaningful a11y announcements.
26
- * @param {Object} [a11yAnnouncementConfig] A map of action to function to build meaningful a11y announcements.
27
- * @param {String} [itemVisualClass] A class for styling visual indicators on the yielded `sortable-item`.
28
- * @param {Object} [handleVisualClass] An object for styling visual indicators on the yielded `sortable-handle` on different `move`.
29
- * @param {Function} [onChange] An optional callback for when position rearrangements are confirmed.
30
- *
31
- * @module drag-drop/draggable-group
32
- * @example
33
- * <ol {{sortable-group onChange=this.update a11yAnnouncementConfig=this.myA11yConfig}}>
34
- * {{#each model.items as |item|}}
35
- * <li {{sortable-item model=item}}>
36
- * {{item.name}}
37
- * <span class="handle" {{sortable-handle}}>&varr;</span>
38
- * </li>
39
- * {{/each}}
40
- * </ol>
41
- */
42
- export default class SortableGroupModifier extends Modifier {
43
- /** Primary keyboard utils */
44
- // Tracks the currently selected item
45
- _selectedItem = null;
46
- // Tracks the current move
47
- move = null;
48
- moves = [];
49
-
50
- // Tracks the status of keyboard reorder mode
51
- isKeyboardReorderModeEnabled = false;
52
-
53
- isKeyDownEnabled = false;
54
-
55
- // Tracks if we're still performing a programmatic focus.
56
- isRetainingFocus = false;
57
- /** End of keyboard utils */
58
-
59
- get disabled() {
60
- return this.named.disabled || false;
61
- }
62
-
63
- /** Start of a11y properties */
64
- /**
65
- * @property an object containing different classes for visual indicators
66
- * @type {Object}
67
- * @default null
68
- * @example
69
- * {
70
- * UP: 'up'
71
- * DOWN: 'down',
72
- * LEFT: 'left',
73
- * RIGHT: 'right',
74
- * }
75
- */
76
- get handleVisualClass() {
77
- return this.named.handleVisualClass || NO_MODEL;
78
- }
79
-
80
- /**
81
- * @property an object containing functions for producing screen reader announcements
82
- * @type {Object}
83
- * @example
84
- * {
85
- * MOVE: function() {},
86
- * ACTIVATE: function() {},
87
- * CONFIRM: function() {},
88
- * CANCEL: function() {},
89
- * }
90
- */
91
- get a11yAnnouncementConfig() {
92
- return this.named.a11yAnnouncementConfig || defaultA11yAnnouncementConfig;
93
- }
94
-
95
- get itemVisualClass() {
96
- return this.named.itemVisualClass || 'is-activated';
97
- }
98
-
99
- get a11yItemName() {
100
- return this.named.a11yItemName || 'item';
101
- }
102
- /** End of a11y properties */
103
-
104
- /**
105
- * Make sure that we cancel any ongoing keyboard operation when the focus is lost from the handle.
106
- * Because this can be fired pre-maturely, effectively cancelling before other keyboard operations,
107
- * we need to wait until other operations are completed, so this will cancel properly.
108
- *
109
- * @param {Event} event a DOM event.
110
- */
111
- @action
112
- focusOut() {
113
- if (!this.isRetainingFocus && !this._isElementWithinHandle(document.activeElement)) {
114
- this.cancelKeyboardSelection();
115
- }
116
- }
117
-
118
- /**
119
- * Explanation
120
- * 1. `KeyboardReorderMode` is disabled: users can activate it via ENTER or SPACE.
121
- * 2. `KeyboardReorderMode` is enabled: users can reorder via UP or DOWN arrow keys. TODO: Expand to more keys, e.g LEFT, RIGHT
122
- * 3. `KeyboardReorderMode` is enabled: users can finalize/save the reordering via ENTER or SPACE.
123
- * 4. `KeyboardReorderMode` is enabled: users can discard the reordering via ESC.
124
- *
125
- * @param {Event} event a DOM event
126
- */
127
- @action
128
- keyDown(event) {
129
- if (!this.isKeyDownEnabled) {
130
- return;
131
- }
132
-
133
- // Note: If handle is specified, we need to target the keyDown on the handle
134
- const isKeyboardReorderModeEnabled = this.isKeyboardReorderModeEnabled;
135
- const _selectedItem = this._selectedItem;
136
-
137
- if (!isKeyboardReorderModeEnabled && (isEnterKey(event) || isSpaceKey(event))) {
138
- this._prepareKeyboardReorderMode();
139
- this._announceAction(ANNOUNCEMENT_ACTION_TYPES.ACTIVATE);
140
- this._updateItemVisualIndicators(_selectedItem, true);
141
- this._updateHandleVisualIndicators(_selectedItem, true);
142
-
143
- this.isRetainingFocus = true;
144
-
145
- scheduleOnce('render', () => {
146
- this.element.focus();
147
- this.isRetainingFocus = false;
148
- });
149
-
150
- // Prevent the default scroll
151
- event.preventDefault();
152
- return;
153
- }
154
-
155
- if (isKeyboardReorderModeEnabled) {
156
- this._handleKeyboardReorder(event);
157
- event.preventDefault();
158
- }
159
- }
160
-
161
- /**
162
- * Checks if the given element is a child of a handle.
163
- *
164
- * @param {Element} element a DOM element.
165
- */
166
- _isElementWithinHandle(element) {
167
- return element.closest(`[data-sortable-handle]`);
168
- }
169
-
170
- /**
171
- * Moves an sortedItem from one index to another index, effectively performing an reorder.
172
- *
173
- * @param {Integer} fromIndex the original index
174
- * @param {Integer} toIndex the new index
175
- */
176
- _move(fromIndex, toIndex) {
177
- const direction = this.direction;
178
- const sortedItems = this.sortedItems;
179
- const item = sortedItems[fromIndex];
180
- const nextItem = sortedItems[toIndex];
181
-
182
- // switch direction values to notify sortedItems to update, so it sorts by direction.
183
- let value;
184
- const dimension = direction === 'y' ? 'height' : 'width';
185
- // DOWN or RIGHT
186
- if (toIndex > fromIndex) {
187
- value = item[direction];
188
- set(item, direction, nextItem[direction] + (nextItem[dimension] - item[dimension]));
189
- set(nextItem, direction, value);
190
- // UP or LEFT
191
- } else {
192
- value = nextItem[direction];
193
- set(nextItem, direction, item[direction] + (item[dimension] - nextItem[dimension]));
194
- set(item, direction, value);
195
- }
196
- }
197
-
198
- /**
199
- * Handles all of the keyboard operations, such as
200
- * 1. Keyboard navigation for UP, DOWN, LEFT, RIGHT
201
- * 2. Confirming reorder
202
- * 3. Discard reorder
203
- * 4. Also handles refocusing the element that triggered the interaction.
204
- *
205
- * @param {Event} event a DOM event.
206
- */
207
- _handleKeyboardReorder(event) {
208
- const direction = this.direction;
209
- const selectedItem = this._selectedItem;
210
-
211
- if (direction === 'y' && isDownArrowKey(event)) {
212
- this.moveItem(selectedItem, 1);
213
- } else if (direction === 'y' && isUpArrowKey(event)) {
214
- this.moveItem(selectedItem, -1);
215
- } else if (direction === 'x' && isLeftArrowKey(event)) {
216
- this.moveItem(selectedItem, -1);
217
- } else if (direction === 'x' && isRightArrowKey(event)) {
218
- this.moveItem(selectedItem, 1);
219
- } else if (isEnterKey(event) || isSpaceKey(event)) {
220
- // confirm will reset the selectedItem, so caching it here before we remove it.
221
- const itemElement = selectedItem.element;
222
- this._announceAction(ANNOUNCEMENT_ACTION_TYPES.CONFIRM);
223
- this.confirmKeyboardSelection();
224
-
225
- this.isRetainingFocus = true;
226
- scheduleOnce('render', () => this._focusItem(itemElement));
227
- } else if (isEscapeKey(event)) {
228
- // cancel will reset the selectedItem, so caching it here before we remove it.
229
- const _selectedItemElement = selectedItem.element;
230
- this._announceAction(ANNOUNCEMENT_ACTION_TYPES.CANCEL);
231
- this.cancelKeyboardSelection();
232
-
233
- this.isRetainingFocus = true;
234
- scheduleOnce('render', () => {
235
- const moves = this.moves;
236
- if (moves && moves.length > 0) {
237
- const sortedItems = this.sortedItems;
238
- const itemElement = sortedItems[moves[0].fromIndex].element;
239
- this._focusItem(itemElement);
240
- } else {
241
- this._focusItem(_selectedItemElement);
242
- }
243
- this.isRetainingFocus = false;
244
- });
245
- }
246
- }
247
-
248
- /**
249
- * Moves the item to its new position and adds the move to our history.
250
- *
251
- * @param {SortableItemModifier} item the item to be moved.
252
- * @param {Integer} delta how much to move index-wise.
253
- */
254
- moveItem(item, delta) {
255
- const sortedItems = this.sortedItems;
256
- const moves = this.moves;
257
-
258
- const sortedIndex = sortedItems.indexOf(item);
259
- const newSortedIndex = sortedIndex + delta;
260
-
261
- // If out of bounds, we don't do anything.
262
- if (newSortedIndex < 0 || newSortedIndex >= sortedItems.length) {
263
- return;
264
- }
265
- this._announceAction(ANNOUNCEMENT_ACTION_TYPES.MOVE, delta);
266
- // Guarantees that the before the UI is fully rendered before we move again.
267
- scheduleOnce('render', () => {
268
- this._move(sortedIndex, newSortedIndex);
269
- this._updateHandleVisualIndicators(item, true);
270
-
271
- moves.push([sortedIndex, newSortedIndex]);
272
- });
273
- }
274
-
275
- /**
276
- * Handles all the necessary operations needed for cancelling the current keyboard selection.
277
- * 1. Disables keyboard reorder mode.
278
- * 2. Undo all of the tracked moves.
279
- * 3. Tears down the application container, so we are not focus locked within the application.
280
- * 4. Resets the current selected item.
281
- */
282
- @action
283
- cancelKeyboardSelection() {
284
- const _selectedItem = this._selectedItem;
285
- this._disableKeyboardReorderMode();
286
- // Revert the process by reversing the move.
287
- const moves = this.moves;
288
- while (moves.length > 0) {
289
- const move = moves.pop();
290
- this._move(move[1], move[0]);
291
- }
292
- this._tearDownA11yApplicationContainer();
293
- this._updateItemVisualIndicators(_selectedItem, false);
294
- this._updateHandleVisualIndicators(_selectedItem, false);
295
- this._resetItemSelection();
296
- }
297
-
298
- /**
299
- * Handles all th necessary operations needed for confirming the current keyboard selection.
300
- * 1. Disables keyboard reorder mode.
301
- * 2. Tears down the application container, so we are not focus locked within the container.
302
- * 3. Make sure to update and sync all the internal items and UI.
303
- * 4. Triggers the `onChange` action if provided.
304
- * 5. Resets the currently selected item.
305
- */
306
- confirmKeyboardSelection() {
307
- const _selectedItem = this._selectedItem;
308
- this.moves = [];
309
- this._disableKeyboardReorderMode();
310
- this._tearDownA11yApplicationContainer();
311
- set(_selectedItem, 'wasDropped', true);
312
- this.commit();
313
- this._updateItemVisualIndicators(_selectedItem, false);
314
- this._updateHandleVisualIndicators(_selectedItem, false);
315
- this._resetItemSelection();
316
- }
317
-
318
- /**
319
- * Announces the message constructed from `a11yAnnouncementConfig`.
320
- *
321
- * @param {String} type the action type.
322
- * @param {Number} delta how much distance (item-wise) is being moved.
323
- */
324
- _announceAction(type, delta = null) {
325
- const a11yAnnouncementConfig = this.a11yAnnouncementConfig;
326
- const a11yItemName = this.a11yItemName;
327
-
328
- if (!a11yItemName || !(type in a11yAnnouncementConfig)) {
329
- return;
330
- }
331
-
332
- const sortedItems = this.sortedItems;
333
- const _selectedItem = this._selectedItem;
334
- const index = sortedItems.indexOf(_selectedItem);
335
- const announcer = this.announcer;
336
-
337
- const config = {
338
- a11yItemName,
339
- index: index,
340
- maxLength: sortedItems.length,
341
- direction: this.direction,
342
- delta,
343
- };
344
-
345
- const message = a11yAnnouncementConfig[type](config);
346
- announcer.textContent = message;
347
-
348
- // Reset the message after the message is announced.
349
- later(() => {
350
- announcer.textContent = '';
351
- }, 1000);
352
- }
353
-
354
- /**
355
- * Reset the selected item.
356
- */
357
- _resetItemSelection() {
358
- this._selectedItem = null;
359
- }
360
-
361
- /**
362
- * Updates the selected item's visual indicators.
363
- *
364
- * @param {SortableItemModifier} item the selected item.
365
- * @param {Boolean} isActive to activate or deactivate the class.
366
- */
367
- _updateItemVisualIndicators(item, isActive) {
368
- const itemVisualClass = this.itemVisualClass;
369
-
370
- if (!itemVisualClass || !item) {
371
- return;
372
- }
373
-
374
- if (isActive) {
375
- item.element.classList.add(itemVisualClass);
376
- } else {
377
- item.element.classList.remove(itemVisualClass);
378
- }
379
- }
380
-
381
- /**
382
- * Updates the selected item's handle's visual indicators
383
- *
384
- * @param {SortableItemModifier} item the selected item.
385
- * @param {boolean} isUpdate to update or not update.
386
- */
387
- _updateHandleVisualIndicators(item, isUpdate) {
388
- const handleVisualClass = this.handleVisualClass;
389
-
390
- if (handleVisualClass === NO_MODEL || !item) {
391
- return;
392
- }
393
-
394
- const sortedItems = this.sortedItems;
395
- const direction = this.direction;
396
- const index = sortedItems.indexOf(item);
397
- const handle = item.element.querySelector('[data-sortable-handle');
398
- const visualHandle = handle ? handle : item.element;
399
- const visualKeys = direction === 'y' ? ['UP', 'DOWN'] : ['LEFT', 'RIGHT'];
400
-
401
- visualKeys.forEach((visualKey) => {
402
- visualHandle.classList.remove(handleVisualClass[visualKey]);
403
- });
404
-
405
- if (!isUpdate) {
406
- return;
407
- }
408
-
409
- if (index > 0) {
410
- visualHandle.classList.add(handleVisualClass[visualKeys[0]]);
411
- }
412
-
413
- if (index < sortedItems.length - 1) {
414
- visualHandle.classList.add(handleVisualClass[visualKeys[1]]);
415
- }
416
- }
417
-
418
- /**
419
- * Sets focus on the current item or its handle.
420
- *
421
- * @param {Element} itemElement an DOM element representing an sortable-item.
422
- */
423
- _focusItem(itemElement) {
424
- const handle = itemElement.querySelector('[data-sortable-handle]');
425
- if (handle) {
426
- handle.focus();
427
- } else {
428
- // The consumer did not use a handle, so we set focus back to the item.
429
- itemElement.focus();
430
- }
431
- }
432
-
433
- /**
434
- * Enables keyboard reorder mode.
435
- */
436
- _enableKeyboardReorderMode() {
437
- this.isKeyboardReorderModeEnabled = true;
438
- }
439
-
440
- /**
441
- * Disables keyboard reorder mode
442
- */
443
- _disableKeyboardReorderMode() {
444
- this.isKeyboardReorderModeEnabled = false;
445
- }
446
-
447
- /**
448
- * Sets up the group as an application and make it programmatically focusable.
449
- */
450
- _setupA11yApplicationContainer() {
451
- this.element.setAttribute('role', 'application');
452
- this.element.tabIndex = -1;
453
- }
454
-
455
- /**
456
- * Tears down the `role=application` container.
457
- */
458
- _tearDownA11yApplicationContainer() {
459
- this.element.removeAttribute('role');
460
- this.element.removeAttribute('tabIndex');
461
- }
462
-
463
- _prepareKeyboardReorderMode() {
464
- this._enableKeyboardReorderMode();
465
- this._setupA11yApplicationContainer();
466
- }
467
-
468
- // Begin of API
469
-
470
- /**
471
- @property direction
472
- @type string
473
- @default y
474
- */
475
- get direction() {
476
- return this.named.direction || 'y';
477
- }
478
-
479
- /**
480
- Called when order of items has been changed
481
- @property onChange
482
- @type Function
483
- @param {Object} groupModel group model (omitted if not set)
484
- @param {Object[]} newModel models in their new order
485
- @param {Object} itemModel model just dragged
486
- @default null
487
- */
488
- get onChange() {
489
- return this.named.onChange;
490
- }
491
-
492
- @service('ember-sortable-internal-state')
493
- sortableService;
494
-
495
- /**
496
- * This is the group name used to keep groups separate if there are more than one on the screen at a time.
497
- * If no group is assigned a default is used
498
- *
499
- * @default "_EmberSortableGroup"
500
- * @returns {*|string}
501
- */
502
- get groupName() {
503
- return this.named.groupName || '_EmberSortableGroup';
504
- }
505
-
506
- /**
507
- This is an array of SortableItemModifiers
508
-
509
- @property items
510
- @type SortableItemModifier[]
511
- */
512
- get items() {
513
- return this._groupDef.items;
514
- }
515
- set(items) {
516
- this._groupDef.items = items;
517
- }
518
-
519
- /**
520
- * Announcer element
521
- *
522
- * @type {Element}
523
- */
524
- announcer = null;
525
-
526
- /**
527
- Position for the first item.
528
- If spacing is present, first item's position will have to change as well.
529
- @property firstItemPosition
530
- @type Number
531
- */
532
- @computed('direction', 'sortedItems')
533
- get firstItemPosition() {
534
- const direction = this.direction;
535
- const sortedItems = this.sortedItems;
536
-
537
- return sortedItems[0][`${direction}`] - sortedItems[0].spacing;
538
- }
539
-
540
- /**
541
- An array of DOM elements.
542
- @property sortedItems
543
- @type SortableItemModifier[]
544
- */
545
- get sortedItems() {
546
- const direction = this.direction;
547
- return this.items.sort((a, b) => a[direction] - b[direction]);
548
- }
549
-
550
- /**
551
- * Enables keyboard navigation
552
- */
553
- @action
554
- activateKeyDown(selectedItem) {
555
- this._selectedItem = selectedItem;
556
- this.isKeyDownEnabled = true;
557
- }
558
-
559
- /**
560
- * Disables keyboard navigation
561
- * Currently used to handle keydown events bubbling up from
562
- * elements that aren't meant to invoke keyboard navigation
563
- * by ignoring them.
564
- */
565
- @action
566
- deactivateKeyDown() {
567
- this.isKeyDownEnabled = false;
568
- }
569
-
570
- /**
571
- Register the group with this Sortable.
572
- @method registerGroup
573
- @param {SortableGroupModifier} group
574
- */
575
- @action
576
- registerGroup(group) {
577
- this._group = group;
578
- }
579
-
580
- /**
581
- De-register the group with this Sortable.
582
- @method deregisterGroup
583
- @param {SortableGroupModifier} group
584
- */
585
- @action
586
- deregisterGroup(group) {
587
- if (this._group === group) {
588
- this._group = null;
589
- }
590
- }
591
-
592
- /**
593
- Prepare for sorting.
594
- Main purpose is to stash the current firstItemPosition so
595
- we don’t incur expensive re-layouts.
596
- @method _prepare
597
- */
598
- @action
599
- prepare() {
600
- this._firstItemPosition = this.firstItemPosition;
601
- }
602
-
603
- /**
604
- Update item positions (relatively to the first element position).
605
- @method update
606
- */
607
- @action
608
- update() {
609
- let sortedItems = this.sortedItems;
610
- // Position of the first element
611
- let position = this._firstItemPosition;
612
-
613
- // Just in case we haven’t called prepare first.
614
- if (position === undefined) {
615
- position = this.firstItemPosition;
616
- }
617
-
618
- sortedItems.forEach((item) => {
619
- let dimension;
620
- let direction = this.direction;
621
-
622
- if (!isDestroyed(item) && !item.isDragging) {
623
- set(item, direction, position);
624
- }
625
-
626
- // add additional spacing around active element
627
- if (item.isBusy) {
628
- position += item.spacing * 2;
629
- }
630
-
631
- if (direction === 'x') {
632
- dimension = 'width';
633
- }
634
- if (direction === 'y') {
635
- dimension = 'height';
636
- }
637
-
638
- position += item[dimension];
639
- });
640
- }
641
-
642
- /**
643
- @method _commit
644
- */
645
- @action
646
- commit() {
647
- const items = this.sortedItems;
648
- const itemModels = items.map((item) => item.model);
649
- const draggedItem = items.find((item) => item.wasDropped);
650
- let draggedModel;
651
-
652
- if (draggedItem) {
653
- draggedItem.wasDropped = false; // Reset
654
- draggedModel = draggedItem.model;
655
- }
656
-
657
- this._updateItems();
658
- this._onChange(itemModels, draggedModel);
659
- }
660
-
661
- @action
662
- _onChange(itemModels, draggedModel) {
663
- if (this.onChange) {
664
- this.onChange(itemModels, draggedModel);
665
- }
666
- }
667
-
668
- /**
669
- * Keeps the UI in sync with actual changes.
670
- * Needed for drag and keyboard operations.
671
- */
672
- _updateItems() {
673
- const items = this.sortedItems;
674
-
675
- delete this._firstItemPosition;
676
-
677
- schedule('render', () => {
678
- items.forEach((item) => item.freeze());
679
- });
680
-
681
- schedule('afterRender', () => {
682
- items.forEach((item) => item.reset());
683
- });
684
-
685
- next(() => {
686
- schedule('render', () => {
687
- items.forEach((item) => item.thaw());
688
- });
689
- });
690
- }
691
-
692
- @action
693
- _createAnnouncer() {
694
- const announcer = document.createElement('span');
695
- announcer.setAttribute('aria-live', 'polite');
696
- announcer.classList.add('visually-hidden');
697
- return announcer;
698
- }
699
-
700
- // end of API
701
-
702
- addEventListener() {
703
- this.element.addEventListener('keydown', this.keyDown);
704
- this.element.addEventListener('focusout', this.focusOut);
705
- }
706
-
707
- removeEventListener() {
708
- this.element.removeEventListener('keydown', this.keyDown);
709
- this.element.removeEventListener('focusout', this.focusOut);
710
- }
711
-
712
- element;
713
- didSetup = false;
714
-
715
- constructor(owner, args) {
716
- super(owner, args);
717
- registerDestructor(this, cleanup);
718
- }
719
-
720
- modify(element, _positional, named) {
721
- this.element = element;
722
- this.named = named;
723
-
724
- this.removeEventListener();
725
-
726
- if (!this.didSetup) {
727
- this._groupDef = this.sortableService.fetchGroup(this.groupName);
728
- this.announcer = this._createAnnouncer();
729
- this.element.insertAdjacentElement('afterend', this.announcer);
730
- this.sortableService.registerGroup(this.groupName, this);
731
-
732
- this.didSetup = true;
733
- }
734
-
735
- if (this.disabled) {
736
- return;
737
- }
738
-
739
- this.addEventListener();
740
- }
741
- }
742
-
743
- /**
744
- *
745
- * @param {SortableGroupModifier} instance
746
- */
747
- function cleanup(instance) {
748
- // todo cleanup the announcer
749
- if (instance.announcer.parentNode) {
750
- instance.announcer.parentNode.removeChild(instance.announcer);
751
- }
752
- instance.removeEventListener();
753
- instance.sortableService.deregisterGroup(instance.groupName, instance);
754
- }