@fr0st/ui-sortable 2.0.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.
- package/LICENSE +21 -0
- package/README.md +37 -0
- package/dist/frost-ui-sortable.js +327 -0
- package/dist/frost-ui-sortable.js.map +1 -0
- package/dist/frost-ui-sortable.min.js +1 -0
- package/dist/frost-ui-sortable.min.js.map +1 -0
- package/package.json +44 -0
- package/src/index.js +34 -0
- package/src/prototype/events.js +154 -0
- package/src/prototype/helpers.js +80 -0
- package/src/sortable.js +62 -0
- package/src/wrapper.js +3 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 elusivecodes
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# FrostUI Sortable
|
|
2
|
+
|
|
3
|
+
**FrostUI Sortable** is a free, open-source Sortable component for *JavaScript*.
|
|
4
|
+
|
|
5
|
+
It is built on top of the [FrostUI](https://github.com/elusivecodes/FrostUI) library.
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
## Table Of Contents
|
|
9
|
+
- [Installation](#installation)
|
|
10
|
+
- [Usage](#usage)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
**Dependencies**
|
|
17
|
+
|
|
18
|
+
- [fQuery](https://github.com/elusivecodes/fQuery)
|
|
19
|
+
- [FrostUI](https://github.com/elusivecodes/FrostUI)
|
|
20
|
+
|
|
21
|
+
**CSS**
|
|
22
|
+
|
|
23
|
+
```html
|
|
24
|
+
<link rel="stylesheet" href="/path/to/frost-ui.min.css" />
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
**JS**
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<script type="text/javascript" src="/path/to/frost-ui-bundle.min.js"></script>
|
|
31
|
+
<script type="text/javascript" src="/path/to/frost-ui-sortable.min.js"></script>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
## Usage
|
|
36
|
+
|
|
37
|
+
Check the demo folder for examples. Full documentation and website coming soon™.
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
(function (global, factory) {
|
|
2
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@fr0st/ui'), require('@fr0st/query')) :
|
|
3
|
+
typeof define === 'function' && define.amd ? define(['exports', '@fr0st/ui', '@fr0st/query'], factory) :
|
|
4
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.UI = global.UI || {}, global.UI, global.fQuery));
|
|
5
|
+
})(this, (function (exports, ui, $) { 'use strict';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Sortable Class
|
|
9
|
+
* @class
|
|
10
|
+
*/
|
|
11
|
+
class Sortable extends ui.BaseComponent {
|
|
12
|
+
/**
|
|
13
|
+
* New Sortable constructor.
|
|
14
|
+
* @param {HTMLElement} node The input node.
|
|
15
|
+
* @param {object} [options] The options to create the Sortable with.
|
|
16
|
+
*/
|
|
17
|
+
constructor(node, options) {
|
|
18
|
+
super(node, options);
|
|
19
|
+
|
|
20
|
+
this._selector = this._options.items;
|
|
21
|
+
if (this._options.handle) {
|
|
22
|
+
this._selector += ' ' + this._options.handle;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
this._enabled = !this._options.disabled;
|
|
26
|
+
|
|
27
|
+
this._refreshCursors();
|
|
28
|
+
this._events();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Disable the Sortable.
|
|
33
|
+
*/
|
|
34
|
+
disable() {
|
|
35
|
+
this._enabled = false;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Dispose the Sortable.
|
|
40
|
+
*/
|
|
41
|
+
dispose() {
|
|
42
|
+
$.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');
|
|
43
|
+
$.removeEvent(this._node, 'receive.ui.sortable');
|
|
44
|
+
|
|
45
|
+
this._target = null;
|
|
46
|
+
this._currentSortable = null;
|
|
47
|
+
|
|
48
|
+
super.dispose();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Enable the Sortable.
|
|
53
|
+
*/
|
|
54
|
+
enable() {
|
|
55
|
+
this._enabled = true;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Get the Sortable item elements.
|
|
60
|
+
* @return {array} The Sortable item elements.
|
|
61
|
+
*/
|
|
62
|
+
items() {
|
|
63
|
+
return $.find(this._options.items, this._node);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Attach events for the Sortable.
|
|
69
|
+
*/
|
|
70
|
+
function _events() {
|
|
71
|
+
const downEvent = (e) => {
|
|
72
|
+
if (
|
|
73
|
+
e.button ||
|
|
74
|
+
!this._enabled ||
|
|
75
|
+
$.is(e.currentTarget, this._options.cancel) ||
|
|
76
|
+
$.getDataset(this._node, 'uiDragging')
|
|
77
|
+
) {
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (e.type === 'mousedown') {
|
|
82
|
+
e.preventDefault();
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
this._target = this._options.handle ?
|
|
86
|
+
this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :
|
|
87
|
+
e.currentTarget;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const moveEvent = (e) => {
|
|
91
|
+
this._pos = ui.getPosition(e);
|
|
92
|
+
|
|
93
|
+
if (!$.getDataset(this._node, 'uiDragging')) {
|
|
94
|
+
$.setDataset(this._node, { uiDragging: true });
|
|
95
|
+
|
|
96
|
+
this._startIndex = $.index(this._target);
|
|
97
|
+
this._currentIndex = this._startIndex;
|
|
98
|
+
|
|
99
|
+
$.triggerEvent(this._node, 'sort.ui.sortable', {
|
|
100
|
+
detail: {
|
|
101
|
+
target: this._target,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
if (this._options.helperClass) {
|
|
106
|
+
$.addClass(this._target, this._options.helperClass);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
this._currentSortable = this._node;
|
|
110
|
+
|
|
111
|
+
if (this._options.scroll) {
|
|
112
|
+
this._checkScroll();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
let nearestSortable = this._node;
|
|
117
|
+
|
|
118
|
+
if (this._options.connectWith) {
|
|
119
|
+
const connected = $.find(this._options.connectWith)
|
|
120
|
+
.filter((node) => {
|
|
121
|
+
const sortable = this.constructor.init(node);
|
|
122
|
+
|
|
123
|
+
return sortable._options.dropOnEmpty || sortable.items().length;
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
if (connected.length) {
|
|
127
|
+
nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const nearestItems = $.isSame(this._node, nearestSortable) ?
|
|
132
|
+
this.items() :
|
|
133
|
+
this.constructor.init(nearestSortable).items();
|
|
134
|
+
|
|
135
|
+
const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });
|
|
136
|
+
|
|
137
|
+
if (!nearestItem) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
this._updateTarget(nearestItem, this._pos.x, this._pos.y);
|
|
142
|
+
|
|
143
|
+
const newIndex = $.index(this._target);
|
|
144
|
+
|
|
145
|
+
if (!$.isSame(nearestSortable, this._currentSortable)) {
|
|
146
|
+
$.triggerEvent(this._currentSortable, 'send.ui.sortable', {
|
|
147
|
+
detail: {
|
|
148
|
+
target: this._target,
|
|
149
|
+
},
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
$.triggerEvent(nearestSortable, 'receive.ui.sortable', {
|
|
153
|
+
detail: {
|
|
154
|
+
target: this._target,
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
} else if (this._currentIndex !== newIndex) {
|
|
158
|
+
$.triggerEvent(nearestSortable, 'sorting.ui.sortable', {
|
|
159
|
+
detail: {
|
|
160
|
+
target: this._target,
|
|
161
|
+
},
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
this._currentIndex = newIndex;
|
|
166
|
+
this._currentSortable = nearestSortable;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
const upEvent = (e) => {
|
|
170
|
+
if (!$.getDataset(this._node, 'uiDragging')) {
|
|
171
|
+
this._target = null;
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
if (e.type === 'mouseup') {
|
|
176
|
+
e.preventDefault();
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
$.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {
|
|
180
|
+
detail: {
|
|
181
|
+
target: this._target,
|
|
182
|
+
},
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
if (this._options.helperClass) {
|
|
186
|
+
$.removeClass(this._target, this._options.helperClass);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {
|
|
190
|
+
$.triggerEvent(this._currentSortable, 'update.ui.sortable', {
|
|
191
|
+
detail: {
|
|
192
|
+
target: this._target,
|
|
193
|
+
},
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
$.removeDataset(this._node, 'uiDragging');
|
|
198
|
+
|
|
199
|
+
if (this._checkScrollTimer) {
|
|
200
|
+
clearTimeout(this._checkScrollTimer);
|
|
201
|
+
this._checkScrollTimer = null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
this._target = null;
|
|
205
|
+
this._currentSortable = null;
|
|
206
|
+
this._currentIndex = null;
|
|
207
|
+
this._startIndex = null;
|
|
208
|
+
};
|
|
209
|
+
|
|
210
|
+
const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
|
|
211
|
+
|
|
212
|
+
$.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);
|
|
213
|
+
|
|
214
|
+
$.addEvent(this._node, 'receive.ui.sortable', (_) => {
|
|
215
|
+
this._refreshCursors();
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Check for window scroll.
|
|
221
|
+
*/
|
|
222
|
+
function _checkScroll() {
|
|
223
|
+
$.hide(this._target);
|
|
224
|
+
|
|
225
|
+
const originalX = $.getScrollX(window);
|
|
226
|
+
const originalY = $.getScrollY(window);
|
|
227
|
+
|
|
228
|
+
let offsetX = originalX;
|
|
229
|
+
let offsetY = originalY;
|
|
230
|
+
|
|
231
|
+
if (this._pos.y < originalY + this._options.scrollSensitivity) {
|
|
232
|
+
offsetY = Math.max(0, originalY - this._options.scrollSpeed);
|
|
233
|
+
} else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {
|
|
234
|
+
const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });
|
|
235
|
+
offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
if (this._pos.x < originalX + this._options.scrollSensitivity) {
|
|
239
|
+
offsetX = Math.max(0, originalX - this._options.scrollSpeed);
|
|
240
|
+
} else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {
|
|
241
|
+
const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });
|
|
242
|
+
offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (offsetX !== originalX || offsetY !== originalY) {
|
|
246
|
+
$.setStyle(':root', { scrollBehavior: 'initial' });
|
|
247
|
+
$.setScroll(document, offsetX, offsetY);
|
|
248
|
+
$.setStyle(':root', { scrollBehavior: '' });
|
|
249
|
+
|
|
250
|
+
this._pos.x += offsetX - originalX;
|
|
251
|
+
this._pos.y += offsetY - originalY;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
$.show(this._target);
|
|
255
|
+
|
|
256
|
+
this._checkScrollTimer = setTimeout((_) => {
|
|
257
|
+
this._checkScroll();
|
|
258
|
+
}, 0);
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Refresh Sortable item cursors.
|
|
262
|
+
*/
|
|
263
|
+
function _refreshCursors() {
|
|
264
|
+
const elements = $.find(this._selector, this._node);
|
|
265
|
+
|
|
266
|
+
$.setStyle(elements, { cursor: this._options.cursor });
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Update the target element.
|
|
270
|
+
* @param {HTMLElement} nearestItem The current nearest item.
|
|
271
|
+
* @param {number} x The mouse X position.
|
|
272
|
+
* @param {number} y The mouse Y position.
|
|
273
|
+
*/
|
|
274
|
+
function _updateTarget(nearestItem, x, y) {
|
|
275
|
+
const nearestCenter = $.center(nearestItem, { offset: true });
|
|
276
|
+
const targetCenter = $.center(this._target, { offset: true });
|
|
277
|
+
|
|
278
|
+
let method;
|
|
279
|
+
if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {
|
|
280
|
+
method = y < nearestCenter.y ?
|
|
281
|
+
'before' :
|
|
282
|
+
'after';
|
|
283
|
+
} else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {
|
|
284
|
+
method = x < nearestCenter.x ?
|
|
285
|
+
'before' :
|
|
286
|
+
'after';
|
|
287
|
+
} else {
|
|
288
|
+
method = x < nearestCenter.x && y < nearestCenter.y ?
|
|
289
|
+
'before' :
|
|
290
|
+
'after';
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
$[method](nearestItem, this._target);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Sortable default options
|
|
297
|
+
Sortable.defaults = {
|
|
298
|
+
appendTo: 'body',
|
|
299
|
+
axis: null,
|
|
300
|
+
cancel: 'input, textarea, button, select, option',
|
|
301
|
+
connectWith: null,
|
|
302
|
+
cursor: 'auto',
|
|
303
|
+
disabled: false,
|
|
304
|
+
dropOnEmpty: true,
|
|
305
|
+
handle: null,
|
|
306
|
+
helperClass: 'bg-body-tertiary',
|
|
307
|
+
items: ':scope > li',
|
|
308
|
+
scroll: true,
|
|
309
|
+
scrollSensitivity: 20,
|
|
310
|
+
scrollSpeed: 5,
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// Sortable prototype
|
|
314
|
+
const proto = Sortable.prototype;
|
|
315
|
+
|
|
316
|
+
proto._checkScroll = _checkScroll;
|
|
317
|
+
proto._events = _events;
|
|
318
|
+
proto._refreshCursors = _refreshCursors;
|
|
319
|
+
proto._updateTarget = _updateTarget;
|
|
320
|
+
|
|
321
|
+
// Sortable init
|
|
322
|
+
ui.initComponent('sortable', Sortable);
|
|
323
|
+
|
|
324
|
+
exports.Sortable = Sortable;
|
|
325
|
+
|
|
326
|
+
}));
|
|
327
|
+
//# sourceMappingURL=frost-ui-sortable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"frost-ui-sortable.js","sources":["../src/sortable.js","../src/prototype/events.js","../src/prototype/helpers.js","../src/index.js"],"sourcesContent":["import $ from '@fr0st/query';\nimport { BaseComponent } from '@fr0st/ui';\n\n/**\n * Sortable Class\n * @class\n */\nexport default class Sortable extends BaseComponent {\n /**\n * New Sortable constructor.\n * @param {HTMLElement} node The input node.\n * @param {object} [options] The options to create the Sortable with.\n */\n constructor(node, options) {\n super(node, options);\n\n this._selector = this._options.items;\n if (this._options.handle) {\n this._selector += ' ' + this._options.handle;\n }\n\n this._enabled = !this._options.disabled;\n\n this._refreshCursors();\n this._events();\n }\n\n /**\n * Disable the Sortable.\n */\n disable() {\n this._enabled = false;\n }\n\n /**\n * Dispose the Sortable.\n */\n dispose() {\n $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this._node, 'receive.ui.sortable');\n\n this._target = null;\n this._currentSortable = null;\n\n super.dispose();\n }\n\n /**\n * Enable the Sortable.\n */\n enable() {\n this._enabled = true;\n }\n\n /**\n * Get the Sortable item elements.\n * @return {array} The Sortable item elements.\n */\n items() {\n return $.find(this._options.items, this._node);\n }\n}\n","import $ from '@fr0st/query';\nimport { getPosition } from '@fr0st/ui';\n\n/**\n * Attach events for the Sortable.\n */\nexport function _events() {\n const downEvent = (e) => {\n if (\n e.button ||\n !this._enabled ||\n $.is(e.currentTarget, this._options.cancel) ||\n $.getDataset(this._node, 'uiDragging')\n ) {\n return false;\n }\n\n if (e.type === 'mousedown') {\n e.preventDefault();\n }\n\n this._target = this._options.handle ?\n this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :\n e.currentTarget;\n };\n\n const moveEvent = (e) => {\n this._pos = getPosition(e);\n\n if (!$.getDataset(this._node, 'uiDragging')) {\n $.setDataset(this._node, { uiDragging: true });\n\n this._startIndex = $.index(this._target);\n this._currentIndex = this._startIndex;\n\n $.triggerEvent(this._node, 'sort.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.addClass(this._target, this._options.helperClass);\n }\n\n this._currentSortable = this._node;\n\n if (this._options.scroll) {\n this._checkScroll();\n }\n }\n\n let nearestSortable = this._node;\n\n if (this._options.connectWith) {\n const connected = $.find(this._options.connectWith)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable._options.dropOnEmpty || sortable.items().length;\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });\n }\n }\n\n const nearestItems = $.isSame(this._node, nearestSortable) ?\n this.items() :\n this.constructor.init(nearestSortable).items();\n\n const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });\n\n if (!nearestItem) {\n return;\n }\n\n this._updateTarget(nearestItem, this._pos.x, this._pos.y);\n\n const newIndex = $.index(this._target);\n\n if (!$.isSame(nearestSortable, this._currentSortable)) {\n $.triggerEvent(this._currentSortable, 'send.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n $.triggerEvent(nearestSortable, 'receive.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n } else if (this._currentIndex !== newIndex) {\n $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n this._currentIndex = newIndex;\n this._currentSortable = nearestSortable;\n };\n\n const upEvent = (e) => {\n if (!$.getDataset(this._node, 'uiDragging')) {\n this._target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.removeClass(this._target, this._options.helperClass);\n }\n\n if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {\n $.triggerEvent(this._currentSortable, 'update.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n $.removeDataset(this._node, 'uiDragging');\n\n if (this._checkScrollTimer) {\n clearTimeout(this._checkScrollTimer);\n this._checkScrollTimer = null;\n }\n\n this._target = null;\n this._currentSortable = null;\n this._currentIndex = null;\n this._startIndex = null;\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);\n\n $.addEvent(this._node, 'receive.ui.sortable', (_) => {\n this._refreshCursors();\n });\n};\n","import $ from '@fr0st/query';\n\n/**\n * Check for window scroll.\n */\nexport function _checkScroll() {\n $.hide(this._target);\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this._pos.y < originalY + this._options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this._options.scrollSpeed);\n } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);\n }\n\n if (this._pos.x < originalX + this._options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this._options.scrollSpeed);\n } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);\n }\n\n if (offsetX !== originalX || offsetY !== originalY) {\n $.setStyle(':root', { scrollBehavior: 'initial' });\n $.setScroll(document, offsetX, offsetY);\n $.setStyle(':root', { scrollBehavior: '' });\n\n this._pos.x += offsetX - originalX;\n this._pos.y += offsetY - originalY;\n }\n\n $.show(this._target);\n\n this._checkScrollTimer = setTimeout((_) => {\n this._checkScroll();\n }, 0);\n};\n\n/**\n * Refresh Sortable item cursors.\n */\nexport function _refreshCursors() {\n const elements = $.find(this._selector, this._node);\n\n $.setStyle(elements, { cursor: this._options.cursor });\n};\n\n/**\n * Update the target element.\n * @param {HTMLElement} nearestItem The current nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n */\nexport function _updateTarget(nearestItem, x, y) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const targetCenter = $.center(this._target, { offset: true });\n\n let method;\n if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n method = y < nearestCenter.y ?\n 'before' :\n 'after';\n } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n method = x < nearestCenter.x ?\n 'before' :\n 'after';\n } else {\n method = x < nearestCenter.x && y < nearestCenter.y ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this._target);\n};\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\nimport { _events } from './prototype/events.js';\nimport { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';\n\n// Sortable default options\nSortable.defaults = {\n appendTo: 'body',\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n};\n\n// Sortable prototype\nconst proto = Sortable.prototype;\n\nproto._checkScroll = _checkScroll;\nproto._events = _events;\nproto._refreshCursors = _refreshCursors;\nproto._updateTarget = _updateTarget;\n\n// Sortable init\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n"],"names":["BaseComponent","getPosition","initComponent"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports,require("@fr0st/ui"),require("@fr0st/query")):"function"==typeof define&&define.amd?define(["exports","@fr0st/ui","@fr0st/query"],e):e((t="undefined"!=typeof globalThis?globalThis:t||self).UI=t.UI||{},t.UI,t.fQuery)}(this,(function(t,e,s){"use strict";class i extends e.BaseComponent{constructor(t,e){super(t,e),this._selector=this._options.items,this._options.handle&&(this._selector+=" "+this._options.handle),this._enabled=!this._options.disabled,this._refreshCursors(),this._events()}disable(){this._enabled=!1}dispose(){s.removeEventDelegate(this._node,"mousedown.ui.sortable touchstart.ui.sortable"),s.removeEvent(this._node,"receive.ui.sortable"),this._target=null,this._currentSortable=null,super.dispose()}enable(){this._enabled=!0}items(){return s.find(this._options.items,this._node)}}i.defaults={appendTo:"body",axis:null,cancel:"input, textarea, button, select, option",connectWith:null,cursor:"auto",disabled:!1,dropOnEmpty:!0,handle:null,helperClass:"bg-body-tertiary",items:":scope > li",scroll:!0,scrollSensitivity:20,scrollSpeed:5};const o=i.prototype;o._checkScroll=function(){s.hide(this._target);const t=s.getScrollX(window),e=s.getScrollY(window);let i=t,o=e;if(this._pos.y<e+this._options.scrollSensitivity)o=Math.max(0,e-this._options.scrollSpeed);else if(this._pos.y>e+s.height(window)-this._options.scrollSensitivity){const t=s.height(document,{boxSize:s.SCROLL_BOX});o=Math.min(t,e+this._options.scrollSpeed)}if(this._pos.x<t+this._options.scrollSensitivity)i=Math.max(0,t-this._options.scrollSpeed);else if(this._pos.x>t+s.width(window)-this._options.scrollSensitivity){const e=s.width(document,{boxSize:s.SCROLL_BOX});i=Math.min(e,t+this._options.scrollSpeed)}i===t&&o===e||(s.setStyle(":root",{scrollBehavior:"initial"}),s.setScroll(document,i,o),s.setStyle(":root",{scrollBehavior:""}),this._pos.x+=i-t,this._pos.y+=o-e),s.show(this._target),this._checkScrollTimer=setTimeout((t=>{this._checkScroll()}),0)},o._events=function(){const t=s.mouseDragFactory((t=>{if(t.button||!this._enabled||s.is(t.currentTarget,this._options.cancel)||s.getDataset(this._node,"uiDragging"))return!1;"mousedown"===t.type&&t.preventDefault(),this._target=this._options.handle?this.items().find((e=>s.hasDescendent(e,t.currentTarget))):t.currentTarget}),(t=>{this._pos=e.getPosition(t),s.getDataset(this._node,"uiDragging")||(s.setDataset(this._node,{uiDragging:!0}),this._startIndex=s.index(this._target),this._currentIndex=this._startIndex,s.triggerEvent(this._node,"sort.ui.sortable",{detail:{target:this._target}}),this._options.helperClass&&s.addClass(this._target,this._options.helperClass),this._currentSortable=this._node,this._options.scroll&&this._checkScroll());let i=this._node;if(this._options.connectWith){const t=s.find(this._options.connectWith).filter((t=>{const e=this.constructor.init(t);return e._options.dropOnEmpty||e.items().length}));t.length&&(i=s.nearestTo([this._node,...t],this._pos.x,this._pos.y,{offset:!0}))}const o=s.isSame(this._node,i)?this.items():this.constructor.init(i).items(),r=s.nearestTo(o,this._pos.x,this._pos.y,{offset:!0});if(!r)return;this._updateTarget(r,this._pos.x,this._pos.y);const n=s.index(this._target);s.isSame(i,this._currentSortable)?this._currentIndex!==n&&s.triggerEvent(i,"sorting.ui.sortable",{detail:{target:this._target}}):(s.triggerEvent(this._currentSortable,"send.ui.sortable",{detail:{target:this._target}}),s.triggerEvent(i,"receive.ui.sortable",{detail:{target:this._target}})),this._currentIndex=n,this._currentSortable=i}),(t=>{s.getDataset(this._node,"uiDragging")?("mouseup"===t.type&&t.preventDefault(),s.triggerEvent(this._currentSortable,"sorted.ui.sortable",{detail:{target:this._target}}),this._options.helperClass&&s.removeClass(this._target,this._options.helperClass),this._currentIndex===this._startIndex&&s.isSame(this._currentSortable,this._node)||s.triggerEvent(this._currentSortable,"update.ui.sortable",{detail:{target:this._target}}),s.removeDataset(this._node,"uiDragging"),this._checkScrollTimer&&(clearTimeout(this._checkScrollTimer),this._checkScrollTimer=null),this._target=null,this._currentSortable=null,this._currentIndex=null,this._startIndex=null):this._target=null}));s.addEventDelegate(this._node,"mousedown.ui.sortable touchstart.ui.sortable",this._selector,t),s.addEvent(this._node,"receive.ui.sortable",(t=>{this._refreshCursors()}))},o._refreshCursors=function(){const t=s.find(this._selector,this._node);s.setStyle(t,{cursor:this._options.cursor})},o._updateTarget=function(t,e,i){const o=s.center(t,{offset:!0}),r=s.center(this._target,{offset:!0});let n;n="y"===this._options.axis||o.x===r.x?i<o.y?"before":"after":"x"===this._options.axis||o.y===r.y?e<o.x?"before":"after":e<o.x&&i<o.y?"before":"after",s[n](t,this._target)},e.initComponent("sortable",i),t.Sortable=i}));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["Sortable","BaseComponent","constructor","node","options","super","this","_selector","_options","items","handle","_enabled","disabled","_refreshCursors","_events","disable","dispose","$","removeEventDelegate","_node","removeEvent","_target","_currentSortable","enable","find","defaults","appendTo","axis","cancel","connectWith","cursor","dropOnEmpty","helperClass","scroll","scrollSensitivity","scrollSpeed","proto","prototype","_checkScroll","hide","originalX","getScrollX","window","originalY","getScrollY","offsetX","offsetY","_pos","y","Math","max","height","docHeight","document","boxSize","SCROLL_BOX","min","x","width","docWidth","setStyle","scrollBehavior","setScroll","show","_checkScrollTimer","setTimeout","_","dragEvent","mouseDragFactory","e","button","is","currentTarget","getDataset","type","preventDefault","hasDescendent","getPosition","setDataset","uiDragging","_startIndex","index","_currentIndex","triggerEvent","detail","target","addClass","nearestSortable","connected","filter","sortable","init","length","nearestTo","offset","nearestItems","isSame","nearestItem","_updateTarget","newIndex","removeClass","removeDataset","clearTimeout","addEventDelegate","addEvent","elements","nearestCenter","center","targetCenter","method","initComponent"],"sources":["../src/sortable.js","../src/index.js","../src/prototype/helpers.js","../src/prototype/events.js"],"sourcesContent":["import $ from '@fr0st/query';\nimport { BaseComponent } from '@fr0st/ui';\n\n/**\n * Sortable Class\n * @class\n */\nexport default class Sortable extends BaseComponent {\n /**\n * New Sortable constructor.\n * @param {HTMLElement} node The input node.\n * @param {object} [options] The options to create the Sortable with.\n */\n constructor(node, options) {\n super(node, options);\n\n this._selector = this._options.items;\n if (this._options.handle) {\n this._selector += ' ' + this._options.handle;\n }\n\n this._enabled = !this._options.disabled;\n\n this._refreshCursors();\n this._events();\n }\n\n /**\n * Disable the Sortable.\n */\n disable() {\n this._enabled = false;\n }\n\n /**\n * Dispose the Sortable.\n */\n dispose() {\n $.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');\n $.removeEvent(this._node, 'receive.ui.sortable');\n\n this._target = null;\n this._currentSortable = null;\n\n super.dispose();\n }\n\n /**\n * Enable the Sortable.\n */\n enable() {\n this._enabled = true;\n }\n\n /**\n * Get the Sortable item elements.\n * @return {array} The Sortable item elements.\n */\n items() {\n return $.find(this._options.items, this._node);\n }\n}\n","import { initComponent } from '@fr0st/ui';\nimport Sortable from './sortable.js';\nimport { _events } from './prototype/events.js';\nimport { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';\n\n// Sortable default options\nSortable.defaults = {\n appendTo: 'body',\n axis: null,\n cancel: 'input, textarea, button, select, option',\n connectWith: null,\n cursor: 'auto',\n disabled: false,\n dropOnEmpty: true,\n handle: null,\n helperClass: 'bg-body-tertiary',\n items: ':scope > li',\n scroll: true,\n scrollSensitivity: 20,\n scrollSpeed: 5,\n};\n\n// Sortable prototype\nconst proto = Sortable.prototype;\n\nproto._checkScroll = _checkScroll;\nproto._events = _events;\nproto._refreshCursors = _refreshCursors;\nproto._updateTarget = _updateTarget;\n\n// Sortable init\ninitComponent('sortable', Sortable);\n\nexport default Sortable;\n","import $ from '@fr0st/query';\n\n/**\n * Check for window scroll.\n */\nexport function _checkScroll() {\n $.hide(this._target);\n\n const originalX = $.getScrollX(window);\n const originalY = $.getScrollY(window);\n\n let offsetX = originalX;\n let offsetY = originalY;\n\n if (this._pos.y < originalY + this._options.scrollSensitivity) {\n offsetY = Math.max(0, originalY - this._options.scrollSpeed);\n } else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {\n const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });\n offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);\n }\n\n if (this._pos.x < originalX + this._options.scrollSensitivity) {\n offsetX = Math.max(0, originalX - this._options.scrollSpeed);\n } else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {\n const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });\n offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);\n }\n\n if (offsetX !== originalX || offsetY !== originalY) {\n $.setStyle(':root', { scrollBehavior: 'initial' });\n $.setScroll(document, offsetX, offsetY);\n $.setStyle(':root', { scrollBehavior: '' });\n\n this._pos.x += offsetX - originalX;\n this._pos.y += offsetY - originalY;\n }\n\n $.show(this._target);\n\n this._checkScrollTimer = setTimeout((_) => {\n this._checkScroll();\n }, 0);\n};\n\n/**\n * Refresh Sortable item cursors.\n */\nexport function _refreshCursors() {\n const elements = $.find(this._selector, this._node);\n\n $.setStyle(elements, { cursor: this._options.cursor });\n};\n\n/**\n * Update the target element.\n * @param {HTMLElement} nearestItem The current nearest item.\n * @param {number} x The mouse X position.\n * @param {number} y The mouse Y position.\n */\nexport function _updateTarget(nearestItem, x, y) {\n const nearestCenter = $.center(nearestItem, { offset: true });\n const targetCenter = $.center(this._target, { offset: true });\n\n let method;\n if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {\n method = y < nearestCenter.y ?\n 'before' :\n 'after';\n } else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {\n method = x < nearestCenter.x ?\n 'before' :\n 'after';\n } else {\n method = x < nearestCenter.x && y < nearestCenter.y ?\n 'before' :\n 'after';\n }\n\n $[method](nearestItem, this._target);\n};\n","import $ from '@fr0st/query';\nimport { getPosition } from '@fr0st/ui';\n\n/**\n * Attach events for the Sortable.\n */\nexport function _events() {\n const downEvent = (e) => {\n if (\n e.button ||\n !this._enabled ||\n $.is(e.currentTarget, this._options.cancel) ||\n $.getDataset(this._node, 'uiDragging')\n ) {\n return false;\n }\n\n if (e.type === 'mousedown') {\n e.preventDefault();\n }\n\n this._target = this._options.handle ?\n this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :\n e.currentTarget;\n };\n\n const moveEvent = (e) => {\n this._pos = getPosition(e);\n\n if (!$.getDataset(this._node, 'uiDragging')) {\n $.setDataset(this._node, { uiDragging: true });\n\n this._startIndex = $.index(this._target);\n this._currentIndex = this._startIndex;\n\n $.triggerEvent(this._node, 'sort.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.addClass(this._target, this._options.helperClass);\n }\n\n this._currentSortable = this._node;\n\n if (this._options.scroll) {\n this._checkScroll();\n }\n }\n\n let nearestSortable = this._node;\n\n if (this._options.connectWith) {\n const connected = $.find(this._options.connectWith)\n .filter((node) => {\n const sortable = this.constructor.init(node);\n\n return sortable._options.dropOnEmpty || sortable.items().length;\n });\n\n if (connected.length) {\n nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });\n }\n }\n\n const nearestItems = $.isSame(this._node, nearestSortable) ?\n this.items() :\n this.constructor.init(nearestSortable).items();\n\n const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });\n\n if (!nearestItem) {\n return;\n }\n\n this._updateTarget(nearestItem, this._pos.x, this._pos.y);\n\n const newIndex = $.index(this._target);\n\n if (!$.isSame(nearestSortable, this._currentSortable)) {\n $.triggerEvent(this._currentSortable, 'send.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n $.triggerEvent(nearestSortable, 'receive.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n } else if (this._currentIndex !== newIndex) {\n $.triggerEvent(nearestSortable, 'sorting.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n this._currentIndex = newIndex;\n this._currentSortable = nearestSortable;\n };\n\n const upEvent = (e) => {\n if (!$.getDataset(this._node, 'uiDragging')) {\n this._target = null;\n return;\n }\n\n if (e.type === 'mouseup') {\n e.preventDefault();\n }\n\n $.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n\n if (this._options.helperClass) {\n $.removeClass(this._target, this._options.helperClass);\n }\n\n if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {\n $.triggerEvent(this._currentSortable, 'update.ui.sortable', {\n detail: {\n target: this._target,\n },\n });\n }\n\n $.removeDataset(this._node, 'uiDragging');\n\n if (this._checkScrollTimer) {\n clearTimeout(this._checkScrollTimer);\n this._checkScrollTimer = null;\n }\n\n this._target = null;\n this._currentSortable = null;\n this._currentIndex = null;\n this._startIndex = null;\n };\n\n const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);\n\n $.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);\n\n $.addEvent(this._node, 'receive.ui.sortable', (_) => {\n this._refreshCursors();\n });\n};\n"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fr0st/ui-sortable",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"description": "FrostUI-Sortable is a free, open-source Sortable component for Javascript.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"ui",
|
|
7
|
+
"component",
|
|
8
|
+
"sortable",
|
|
9
|
+
"front-end",
|
|
10
|
+
"web"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/elusivecodes/FrostUI-Sortable",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/elusivecodes/FrostUI-Sortable/issues",
|
|
15
|
+
"email": "elusivecodes@gmail.com"
|
|
16
|
+
},
|
|
17
|
+
"main": "src/index.js",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"/LICENSE",
|
|
22
|
+
"/README.md",
|
|
23
|
+
"src"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "npm run js-compile && npm run js-minify",
|
|
27
|
+
"js-compile": "rollup --config",
|
|
28
|
+
"js-lint": "eslint --ext .js .",
|
|
29
|
+
"js-minify": "terser --compress passes=2 --mangle --source-map \"content=dist/frost-ui-sortable.js.map\" --output dist/frost-ui-sortable.min.js dist/frost-ui-sortable.js"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/elusivecodes/FrostUI-Sortable.git"
|
|
34
|
+
},
|
|
35
|
+
"author": "Elusive",
|
|
36
|
+
"license": "MIT",
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"@rollup/plugin-node-resolve": "^15.0.2",
|
|
39
|
+
"eslint": "^8.41.0",
|
|
40
|
+
"eslint-config-google": "^0.14.0",
|
|
41
|
+
"rollup": "^3.23.0",
|
|
42
|
+
"terser": "^5.17.6"
|
|
43
|
+
}
|
|
44
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { initComponent } from '@fr0st/ui';
|
|
2
|
+
import Sortable from './sortable.js';
|
|
3
|
+
import { _events } from './prototype/events.js';
|
|
4
|
+
import { _checkScroll, _refreshCursors, _updateTarget } from './prototype/helpers.js';
|
|
5
|
+
|
|
6
|
+
// Sortable default options
|
|
7
|
+
Sortable.defaults = {
|
|
8
|
+
appendTo: 'body',
|
|
9
|
+
axis: null,
|
|
10
|
+
cancel: 'input, textarea, button, select, option',
|
|
11
|
+
connectWith: null,
|
|
12
|
+
cursor: 'auto',
|
|
13
|
+
disabled: false,
|
|
14
|
+
dropOnEmpty: true,
|
|
15
|
+
handle: null,
|
|
16
|
+
helperClass: 'bg-body-tertiary',
|
|
17
|
+
items: ':scope > li',
|
|
18
|
+
scroll: true,
|
|
19
|
+
scrollSensitivity: 20,
|
|
20
|
+
scrollSpeed: 5,
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// Sortable prototype
|
|
24
|
+
const proto = Sortable.prototype;
|
|
25
|
+
|
|
26
|
+
proto._checkScroll = _checkScroll;
|
|
27
|
+
proto._events = _events;
|
|
28
|
+
proto._refreshCursors = _refreshCursors;
|
|
29
|
+
proto._updateTarget = _updateTarget;
|
|
30
|
+
|
|
31
|
+
// Sortable init
|
|
32
|
+
initComponent('sortable', Sortable);
|
|
33
|
+
|
|
34
|
+
export default Sortable;
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import $ from '@fr0st/query';
|
|
2
|
+
import { getPosition } from '@fr0st/ui';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Attach events for the Sortable.
|
|
6
|
+
*/
|
|
7
|
+
export function _events() {
|
|
8
|
+
const downEvent = (e) => {
|
|
9
|
+
if (
|
|
10
|
+
e.button ||
|
|
11
|
+
!this._enabled ||
|
|
12
|
+
$.is(e.currentTarget, this._options.cancel) ||
|
|
13
|
+
$.getDataset(this._node, 'uiDragging')
|
|
14
|
+
) {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
if (e.type === 'mousedown') {
|
|
19
|
+
e.preventDefault();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this._target = this._options.handle ?
|
|
23
|
+
this.items().find((node) => $.hasDescendent(node, e.currentTarget)) :
|
|
24
|
+
e.currentTarget;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
const moveEvent = (e) => {
|
|
28
|
+
this._pos = getPosition(e);
|
|
29
|
+
|
|
30
|
+
if (!$.getDataset(this._node, 'uiDragging')) {
|
|
31
|
+
$.setDataset(this._node, { uiDragging: true });
|
|
32
|
+
|
|
33
|
+
this._startIndex = $.index(this._target);
|
|
34
|
+
this._currentIndex = this._startIndex;
|
|
35
|
+
|
|
36
|
+
$.triggerEvent(this._node, 'sort.ui.sortable', {
|
|
37
|
+
detail: {
|
|
38
|
+
target: this._target,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (this._options.helperClass) {
|
|
43
|
+
$.addClass(this._target, this._options.helperClass);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this._currentSortable = this._node;
|
|
47
|
+
|
|
48
|
+
if (this._options.scroll) {
|
|
49
|
+
this._checkScroll();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let nearestSortable = this._node;
|
|
54
|
+
|
|
55
|
+
if (this._options.connectWith) {
|
|
56
|
+
const connected = $.find(this._options.connectWith)
|
|
57
|
+
.filter((node) => {
|
|
58
|
+
const sortable = this.constructor.init(node);
|
|
59
|
+
|
|
60
|
+
return sortable._options.dropOnEmpty || sortable.items().length;
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
if (connected.length) {
|
|
64
|
+
nearestSortable = $.nearestTo([this._node, ...connected], this._pos.x, this._pos.y, { offset: true });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const nearestItems = $.isSame(this._node, nearestSortable) ?
|
|
69
|
+
this.items() :
|
|
70
|
+
this.constructor.init(nearestSortable).items();
|
|
71
|
+
|
|
72
|
+
const nearestItem = $.nearestTo(nearestItems, this._pos.x, this._pos.y, { offset: true });
|
|
73
|
+
|
|
74
|
+
if (!nearestItem) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this._updateTarget(nearestItem, this._pos.x, this._pos.y);
|
|
79
|
+
|
|
80
|
+
const newIndex = $.index(this._target);
|
|
81
|
+
|
|
82
|
+
if (!$.isSame(nearestSortable, this._currentSortable)) {
|
|
83
|
+
$.triggerEvent(this._currentSortable, 'send.ui.sortable', {
|
|
84
|
+
detail: {
|
|
85
|
+
target: this._target,
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
$.triggerEvent(nearestSortable, 'receive.ui.sortable', {
|
|
90
|
+
detail: {
|
|
91
|
+
target: this._target,
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
} else if (this._currentIndex !== newIndex) {
|
|
95
|
+
$.triggerEvent(nearestSortable, 'sorting.ui.sortable', {
|
|
96
|
+
detail: {
|
|
97
|
+
target: this._target,
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
this._currentIndex = newIndex;
|
|
103
|
+
this._currentSortable = nearestSortable;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
const upEvent = (e) => {
|
|
107
|
+
if (!$.getDataset(this._node, 'uiDragging')) {
|
|
108
|
+
this._target = null;
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (e.type === 'mouseup') {
|
|
113
|
+
e.preventDefault();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
$.triggerEvent(this._currentSortable, 'sorted.ui.sortable', {
|
|
117
|
+
detail: {
|
|
118
|
+
target: this._target,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
if (this._options.helperClass) {
|
|
123
|
+
$.removeClass(this._target, this._options.helperClass);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (this._currentIndex !== this._startIndex || !$.isSame(this._currentSortable, this._node)) {
|
|
127
|
+
$.triggerEvent(this._currentSortable, 'update.ui.sortable', {
|
|
128
|
+
detail: {
|
|
129
|
+
target: this._target,
|
|
130
|
+
},
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
$.removeDataset(this._node, 'uiDragging');
|
|
135
|
+
|
|
136
|
+
if (this._checkScrollTimer) {
|
|
137
|
+
clearTimeout(this._checkScrollTimer);
|
|
138
|
+
this._checkScrollTimer = null;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
this._target = null;
|
|
142
|
+
this._currentSortable = null;
|
|
143
|
+
this._currentIndex = null;
|
|
144
|
+
this._startIndex = null;
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
const dragEvent = $.mouseDragFactory(downEvent, moveEvent, upEvent);
|
|
148
|
+
|
|
149
|
+
$.addEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable', this._selector, dragEvent);
|
|
150
|
+
|
|
151
|
+
$.addEvent(this._node, 'receive.ui.sortable', (_) => {
|
|
152
|
+
this._refreshCursors();
|
|
153
|
+
});
|
|
154
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import $ from '@fr0st/query';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check for window scroll.
|
|
5
|
+
*/
|
|
6
|
+
export function _checkScroll() {
|
|
7
|
+
$.hide(this._target);
|
|
8
|
+
|
|
9
|
+
const originalX = $.getScrollX(window);
|
|
10
|
+
const originalY = $.getScrollY(window);
|
|
11
|
+
|
|
12
|
+
let offsetX = originalX;
|
|
13
|
+
let offsetY = originalY;
|
|
14
|
+
|
|
15
|
+
if (this._pos.y < originalY + this._options.scrollSensitivity) {
|
|
16
|
+
offsetY = Math.max(0, originalY - this._options.scrollSpeed);
|
|
17
|
+
} else if (this._pos.y > originalY + $.height(window) - this._options.scrollSensitivity) {
|
|
18
|
+
const docHeight = $.height(document, { boxSize: $.SCROLL_BOX });
|
|
19
|
+
offsetY = Math.min(docHeight, originalY + this._options.scrollSpeed);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (this._pos.x < originalX + this._options.scrollSensitivity) {
|
|
23
|
+
offsetX = Math.max(0, originalX - this._options.scrollSpeed);
|
|
24
|
+
} else if (this._pos.x > originalX + $.width(window) - this._options.scrollSensitivity) {
|
|
25
|
+
const docWidth = $.width(document, { boxSize: $.SCROLL_BOX });
|
|
26
|
+
offsetX = Math.min(docWidth, originalX + this._options.scrollSpeed);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (offsetX !== originalX || offsetY !== originalY) {
|
|
30
|
+
$.setStyle(':root', { scrollBehavior: 'initial' });
|
|
31
|
+
$.setScroll(document, offsetX, offsetY);
|
|
32
|
+
$.setStyle(':root', { scrollBehavior: '' });
|
|
33
|
+
|
|
34
|
+
this._pos.x += offsetX - originalX;
|
|
35
|
+
this._pos.y += offsetY - originalY;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
$.show(this._target);
|
|
39
|
+
|
|
40
|
+
this._checkScrollTimer = setTimeout((_) => {
|
|
41
|
+
this._checkScroll();
|
|
42
|
+
}, 0);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Refresh Sortable item cursors.
|
|
47
|
+
*/
|
|
48
|
+
export function _refreshCursors() {
|
|
49
|
+
const elements = $.find(this._selector, this._node);
|
|
50
|
+
|
|
51
|
+
$.setStyle(elements, { cursor: this._options.cursor });
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Update the target element.
|
|
56
|
+
* @param {HTMLElement} nearestItem The current nearest item.
|
|
57
|
+
* @param {number} x The mouse X position.
|
|
58
|
+
* @param {number} y The mouse Y position.
|
|
59
|
+
*/
|
|
60
|
+
export function _updateTarget(nearestItem, x, y) {
|
|
61
|
+
const nearestCenter = $.center(nearestItem, { offset: true });
|
|
62
|
+
const targetCenter = $.center(this._target, { offset: true });
|
|
63
|
+
|
|
64
|
+
let method;
|
|
65
|
+
if (this._options.axis === 'y' || nearestCenter.x === targetCenter.x) {
|
|
66
|
+
method = y < nearestCenter.y ?
|
|
67
|
+
'before' :
|
|
68
|
+
'after';
|
|
69
|
+
} else if (this._options.axis === 'x' || nearestCenter.y === targetCenter.y) {
|
|
70
|
+
method = x < nearestCenter.x ?
|
|
71
|
+
'before' :
|
|
72
|
+
'after';
|
|
73
|
+
} else {
|
|
74
|
+
method = x < nearestCenter.x && y < nearestCenter.y ?
|
|
75
|
+
'before' :
|
|
76
|
+
'after';
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
$[method](nearestItem, this._target);
|
|
80
|
+
};
|
package/src/sortable.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import $ from '@fr0st/query';
|
|
2
|
+
import { BaseComponent } from '@fr0st/ui';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Sortable Class
|
|
6
|
+
* @class
|
|
7
|
+
*/
|
|
8
|
+
export default class Sortable extends BaseComponent {
|
|
9
|
+
/**
|
|
10
|
+
* New Sortable constructor.
|
|
11
|
+
* @param {HTMLElement} node The input node.
|
|
12
|
+
* @param {object} [options] The options to create the Sortable with.
|
|
13
|
+
*/
|
|
14
|
+
constructor(node, options) {
|
|
15
|
+
super(node, options);
|
|
16
|
+
|
|
17
|
+
this._selector = this._options.items;
|
|
18
|
+
if (this._options.handle) {
|
|
19
|
+
this._selector += ' ' + this._options.handle;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
this._enabled = !this._options.disabled;
|
|
23
|
+
|
|
24
|
+
this._refreshCursors();
|
|
25
|
+
this._events();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Disable the Sortable.
|
|
30
|
+
*/
|
|
31
|
+
disable() {
|
|
32
|
+
this._enabled = false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Dispose the Sortable.
|
|
37
|
+
*/
|
|
38
|
+
dispose() {
|
|
39
|
+
$.removeEventDelegate(this._node, 'mousedown.ui.sortable touchstart.ui.sortable');
|
|
40
|
+
$.removeEvent(this._node, 'receive.ui.sortable');
|
|
41
|
+
|
|
42
|
+
this._target = null;
|
|
43
|
+
this._currentSortable = null;
|
|
44
|
+
|
|
45
|
+
super.dispose();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Enable the Sortable.
|
|
50
|
+
*/
|
|
51
|
+
enable() {
|
|
52
|
+
this._enabled = true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Get the Sortable item elements.
|
|
57
|
+
* @return {array} The Sortable item elements.
|
|
58
|
+
*/
|
|
59
|
+
items() {
|
|
60
|
+
return $.find(this._options.items, this._node);
|
|
61
|
+
}
|
|
62
|
+
}
|
package/src/wrapper.js
ADDED