katalyst-tables 2.2.3 → 2.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8224ebb910f428c3f7750ae6e79c92f21440f5546a2baaede473bb286f217a82
4
- data.tar.gz: 6be02c8a263dda22b7faae734cb20e8cec5879db532adb50f257bd502fa51265
3
+ metadata.gz: 450377488700ebc511da5b3d515c217811ef60ce631df86edf62778ef8a3c5c9
4
+ data.tar.gz: 90040f0e73ad2858fd6b683b8046c9726d6a9223676edafc555dadf3e416e97b
5
5
  SHA512:
6
- metadata.gz: 61052d361a93ab2675274f9ed3b3f59e0acd08519261cf016c4db55006097d72f78114ba489e5eed9d066a82aa6bbaa9dd00675d378e24c996a5ccba775bce75
7
- data.tar.gz: e411c014472cd5d34338ad0a02d869d69352fd4c6abe70c68ead05d75b3d2f0f52bf11c263031cd6606d27d09c7565e76770eee0b9149b58ef5e91ec383d86bf
6
+ metadata.gz: 65cb752a4d5ad8620572f123f960b8378e31b5775b34b84bcc7787cd5d89234a5fee3ef2e5d850d19a4c422278aaed74eab8fddf254a92445c11d1e9f17296af
7
+ data.tar.gz: c72888fbed46322cc3adf8bb4a562079699ccacea0fac36a8b85879ddf4378c252f7090c35206b4ac0e7696b2d67e7baadd455c279be9e813efc81103efe7724
@@ -5,16 +5,22 @@ export default class OrderableRowController extends Controller {
5
5
  params: Object,
6
6
  };
7
7
 
8
+ connect() {
9
+ // index from server may be inconsistent with the visual ordering,
10
+ // especially if this is a new node. Use positional indexes instead,
11
+ // as these are the values we will send on save.
12
+ this.index = domIndex(this.row);
13
+ }
14
+
8
15
  paramsValueChanged(params) {
9
16
  this.id = params.id_value;
10
- this.index = params.index_value;
11
17
  }
12
18
 
13
19
  dragUpdate(offset) {
14
20
  this.dragOffset = offset;
15
21
  this.row.style.position = "relative";
16
22
  this.row.style.top = offset + "px";
17
- this.row.style.zIndex = 1;
23
+ this.row.style.zIndex = "1";
18
24
  this.row.toggleAttribute("dragging", true);
19
25
  }
20
26
 
@@ -98,3 +104,7 @@ export default class OrderableRowController extends Controller {
98
104
  return this.element.parentElement;
99
105
  }
100
106
  }
107
+
108
+ function domIndex(element) {
109
+ return Array.from(element.parentElement.children).indexOf(element);
110
+ }
@@ -10,6 +10,7 @@ export default class OrderableListController extends Controller {
10
10
 
11
11
  document.addEventListener("mousemove", this.mousemove);
12
12
  document.addEventListener("mouseup", this.mouseup);
13
+ window.addEventListener("scroll", this.scroll, true);
13
14
 
14
15
  this.element.style.position = "relative";
15
16
  }
@@ -20,6 +21,7 @@ export default class OrderableListController extends Controller {
20
21
 
21
22
  document.removeEventListener("mousemove", this.mousemove);
22
23
  document.removeEventListener("mouseup", this.mouseup);
24
+ window.removeEventListener("scroll", this.scroll, true);
23
25
 
24
26
  this.element.removeAttribute("style");
25
27
  this.tablesOrderableItemOutlets.forEach((item) => item.reset());
@@ -84,7 +86,7 @@ export default class OrderableListController extends Controller {
84
86
 
85
87
  this.startDragging(new DragState(this.element, event, target.id));
86
88
 
87
- this.#updateDragItem(event);
89
+ this.dragState.updateCursor(this.element, target.row, event, this.animate);
88
90
  }
89
91
 
90
92
  mousemove = (event) => {
@@ -92,13 +94,33 @@ export default class OrderableListController extends Controller {
92
94
 
93
95
  event.preventDefault(); // prevent build-in drag
94
96
 
95
- const dragItem = this.#updateDragItem(event);
97
+ if (this.ticking) return;
96
98
 
97
- // Visually updates the position of all items in the list relative to the
98
- // dragged item. No actual changes to orderings at this stage.
99
- this.#currentItems.forEach((item, index) => {
100
- if (item === dragItem) return;
101
- item.updateVisually(index);
99
+ this.ticking = true;
100
+
101
+ window.requestAnimationFrame(() => {
102
+ this.ticking = false;
103
+ this.dragState.updateCursor(
104
+ this.element,
105
+ this.dragItem.row,
106
+ event,
107
+ this.animate,
108
+ );
109
+ });
110
+ };
111
+
112
+ scroll = (event) => {
113
+ if (!this.isDragging || this.ticking) return;
114
+
115
+ this.ticking = true;
116
+
117
+ window.requestAnimationFrame(() => {
118
+ this.ticking = false;
119
+ this.dragState.updateScroll(
120
+ this.element,
121
+ this.dragItem.row,
122
+ this.animate,
123
+ );
102
124
  });
103
125
  };
104
126
 
@@ -128,6 +150,27 @@ export default class OrderableListController extends Controller {
128
150
 
129
151
  //region Helpers
130
152
 
153
+ /**
154
+ * Updates the position of the drag item with a relative offset. Updates
155
+ * other items relative to the new position of the drag item, as required.
156
+ *
157
+ * @callback {OrderableListController~animate}
158
+ * @param {number} offset
159
+ */
160
+ animate = (offset) => {
161
+ const dragItem = this.dragItem;
162
+
163
+ // Visually update the dragItem so it follows the cursor
164
+ dragItem.dragUpdate(offset);
165
+
166
+ // Visually updates the position of all items in the list relative to the
167
+ // dragged item. No actual changes to orderings at this stage.
168
+ this.#currentItems.forEach((item, index) => {
169
+ if (item === dragItem) return;
170
+ item.updateVisually(index);
171
+ });
172
+ };
173
+
131
174
  get isDragging() {
132
175
  return !!this.dragState;
133
176
  }
@@ -155,7 +198,7 @@ export default class OrderableListController extends Controller {
155
198
  /**
156
199
  * Returns the item outlet that was clicked on, if any.
157
200
  *
158
- * @param event {HTMLElement} the clicked ordinal cell
201
+ * @param element {HTMLElement} the clicked ordinal cell
159
202
  * @returns {OrderableRowController}
160
203
  */
161
204
  #targetItem(element) {
@@ -164,17 +207,6 @@ export default class OrderableListController extends Controller {
164
207
  );
165
208
  }
166
209
 
167
- #updateDragItem(event) {
168
- const offset = this.dragState.itemOffset(
169
- this.element,
170
- this.dragItem.row,
171
- event,
172
- );
173
- const item = this.dragItem;
174
- item.dragUpdate(offset);
175
- return item;
176
- }
177
-
178
210
  //endregion
179
211
  }
180
212
 
@@ -195,23 +227,11 @@ class DragState {
195
227
  * @param id {String} the id of the element being dragged
196
228
  */
197
229
  constructor(list, event, id) {
198
- // calculate the offset top of the tbody element relative to offsetParent
199
- const offsetParent = list.offsetParent;
200
- let offsetTop = event.offsetY;
201
- let current = event.target;
202
- while (current && current !== offsetParent) {
203
- offsetTop += current.offsetTop;
204
- current = current.offsetParent;
205
- }
206
-
207
- // page offset is the offset of the tbody element relative to the page
208
- this.pageOffset = event.pageY - offsetTop + list.offsetTop;
209
-
210
230
  // cursor offset is the offset of the cursor relative to the drag item
211
231
  this.cursorOffset = event.offsetY;
212
232
 
213
233
  // initial offset is the offset position of the drag item at drag start
214
- this.initialOffset = event.target.offsetTop - list.offsetTop;
234
+ this.initialPosition = event.target.offsetTop - list.offsetTop;
215
235
 
216
236
  // id of the item being dragged
217
237
  this.targetId = id;
@@ -223,25 +243,62 @@ class DragState {
223
243
  * @param list {HTMLElement} the list controller's element (tbody)
224
244
  * @param row {HTMLElement} the row being dragged
225
245
  * @param event {MouseEvent} the current event
226
- * @returns {number} relative offset for the item being dragged
246
+ * @param callback {OrderableListController~animate} updates the drag item with a relative offset
227
247
  */
228
- itemOffset(list, row, event) {
229
- // cursor position relative to the list
230
- const cursorPosition = event.pageY - this.pageOffset;
248
+ updateCursor(list, row, event, callback) {
249
+ // Calculate and store the list offset relative to the viewport
250
+ // This value is cached so we can calculate the outcome of any scroll events
251
+ this.listOffset = list.getBoundingClientRect().top;
252
+
253
+ // Calculate the position of the cursor relative to the list.
254
+ // Accounts for scroll offsets by using the item's bounding client rect.
255
+ const cursorPosition = event.clientY - this.listOffset;
231
256
 
232
- // item position relative to the list
257
+ // intended item position relative to the list, from cursor position
233
258
  let itemPosition = cursorPosition - this.cursorOffset;
234
259
 
260
+ this.#updateItemPosition(list, row, itemPosition, callback);
261
+ }
262
+
263
+ /**
264
+ * Animates the item's position as the list scrolls. Requires a previous call
265
+ * to set the scroll offset.
266
+ *
267
+ * @param list {HTMLElement} the list controller's element (tbody)
268
+ * @param row {HTMLElement} the row being dragged
269
+ * @param callback {OrderableListController~animate} updates the drag item with a relative offset
270
+ */
271
+ updateScroll(list, row, callback) {
272
+ const previousScrollOffset = this.listOffset;
273
+
274
+ // Calculate and store the list offset relative to the viewport
275
+ // This value is cached so we can calculate the outcome of any scroll events
276
+ this.listOffset = list.getBoundingClientRect().top;
277
+
278
+ // Calculate the change in scroll offset since the last update
279
+ const scrollDelta = previousScrollOffset - this.listOffset;
280
+
281
+ // intended item position relative to the list, from cursor position
282
+ const position = this.position + scrollDelta;
283
+
284
+ this.#updateItemPosition(list, row, position, callback);
285
+ }
286
+
287
+ #updateItemPosition(list, row, position, callback) {
235
288
  // ensure itemPosition is within the bounds of the list (tbody)
236
- itemPosition = Math.max(itemPosition, 0);
237
- itemPosition = Math.min(itemPosition, list.offsetHeight - row.offsetHeight);
289
+ position = Math.max(position, 0);
290
+ position = Math.min(position, list.offsetHeight - row.offsetHeight);
291
+
292
+ // cache the item's position relative to the list for use in scroll events
293
+ this.position = position;
238
294
 
239
295
  // Item has position: relative, so we want to calculate the amount to move
240
296
  // the item relative to it's DOM position to represent how much it has been
241
297
  // dragged by.
298
+ const offset = position - this.initialPosition;
242
299
 
243
300
  // Convert itemPosition from offset relative to list to offset relative to
244
301
  // its position within the DOM (if it hadn't moved).
245
- return itemPosition - this.initialOffset;
302
+ callback(offset);
246
303
  }
247
304
  }
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Katalyst
4
4
  module Tables
5
- VERSION = "2.2.3"
5
+ VERSION = "2.2.4"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: katalyst-tables
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.3
4
+ version: 2.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Katalyst Interactive