katalyst-tables 2.2.3 → 2.2.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/controllers/tables/orderable/item_controller.js +12 -2
- data/app/assets/javascripts/controllers/tables/orderable/list_controller.js +97 -40
- data/app/models/concerns/katalyst/tables/collection/core.rb +7 -1
- data/lib/katalyst/tables/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce0864bc72a6abeb1e6d2060d278650cc6788c3afd87b5ab161ed1fafbeb91b6
|
4
|
+
data.tar.gz: 668e674d96f58861e0a84e859c65dd3f9ad4ddd1c47f822f2d3a473b3b74709d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 42004d7e06b23581d04a0e7d381179fa550350d8221127fbd6d15dc9e8b40ff219246baa302e1379c6a7f02abfc3e2b7c955cae7eaa18c9890be7f0bfa60df10
|
7
|
+
data.tar.gz: 066e394af2e31e1ebe060ed39fc67ecf9b80ad880a526c7ef1e233abb1116e9d4f16507fb89f800d755f2ffae7bad9aaeb4cd0ae4fb67724b86f46fa2eb16976
|
@@ -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
|
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
|
-
|
97
|
+
if (this.ticking) return;
|
96
98
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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
|
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.
|
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
|
-
* @
|
246
|
+
* @param callback {OrderableListController~animate} updates the drag item with a relative offset
|
227
247
|
*/
|
228
|
-
|
229
|
-
//
|
230
|
-
|
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
|
-
|
237
|
-
|
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
|
-
|
302
|
+
callback(offset);
|
246
303
|
}
|
247
304
|
}
|
@@ -13,6 +13,12 @@ module Katalyst
|
|
13
13
|
|
14
14
|
include Reducers
|
15
15
|
|
16
|
+
class_methods do
|
17
|
+
def permitted_params
|
18
|
+
attribute_names
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
16
22
|
included do
|
17
23
|
attr_accessor :items
|
18
24
|
|
@@ -48,7 +54,7 @@ module Katalyst
|
|
48
54
|
end
|
49
55
|
|
50
56
|
def with_params(params)
|
51
|
-
self.attributes = params.permit(self.class.
|
57
|
+
self.attributes = params.permit(self.class.permitted_params)
|
52
58
|
|
53
59
|
self
|
54
60
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: katalyst-tables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.2.
|
4
|
+
version: 2.2.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Katalyst Interactive
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-09-
|
11
|
+
date: 2023-09-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: html-attributes-utils
|
@@ -109,7 +109,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
requirements: []
|
112
|
-
rubygems_version: 3.4.
|
112
|
+
rubygems_version: 3.4.20
|
113
113
|
signing_key:
|
114
114
|
specification_version: 4
|
115
115
|
summary: HTML table generator for Rails views
|