spina-admin-journal 0.6.1 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -48
  3. data/app/assets/config/spina_admin_journal_manifest.js +1 -2
  4. data/app/assets/javascripts/spina/admin/journal/application.js +0 -0
  5. data/app/components/spina/admin/journal/affiliations_list_component.rb +32 -0
  6. data/app/components/spina/admin/journal/application_component.rb +11 -0
  7. data/app/components/spina/admin/journal/articles_list_component.rb +54 -0
  8. data/app/components/spina/admin/journal/authors_list_component.rb +37 -0
  9. data/app/components/spina/admin/journal/authorships_list_component.rb +45 -0
  10. data/app/components/spina/admin/journal/empty_list_component.html.haml +1 -0
  11. data/app/components/spina/admin/journal/empty_list_component.rb +14 -0
  12. data/app/components/spina/admin/journal/form_group_component.html.haml +4 -0
  13. data/app/components/spina/admin/journal/form_group_component.rb +17 -0
  14. data/app/components/spina/admin/journal/institutions_list_component.rb +32 -0
  15. data/app/components/spina/admin/journal/issues_list_component.rb +47 -0
  16. data/app/components/spina/admin/journal/licences_list_component.rb +32 -0
  17. data/app/components/spina/admin/journal/list_component.html.haml +11 -0
  18. data/app/components/spina/admin/journal/list_component.rb +22 -0
  19. data/app/components/spina/admin/journal/list_item_component.html.haml +17 -0
  20. data/app/components/spina/admin/journal/list_item_component.rb +23 -0
  21. data/app/components/spina/admin/journal/volumes_list_component.rb +34 -0
  22. data/app/controllers/spina/admin/journal/application_controller.rb +1 -1
  23. data/app/controllers/spina/admin/journal/articles_controller.rb +18 -24
  24. data/app/controllers/spina/admin/journal/authors_controller.rb +18 -26
  25. data/app/controllers/spina/admin/journal/institutions_controller.rb +13 -5
  26. data/app/controllers/spina/admin/journal/issues_controller.rb +20 -27
  27. data/app/controllers/spina/admin/journal/journals_controller.rb +4 -1
  28. data/app/controllers/spina/admin/journal/licences_controller.rb +8 -4
  29. data/app/controllers/spina/admin/journal/volumes_controller.rb +16 -21
  30. data/app/models/spina/admin/journal/author.rb +1 -0
  31. data/app/models/spina/admin/journal/authorship.rb +9 -0
  32. data/app/views/spina/admin/hooks/journal/_primary_navigation.html.haml +35 -26
  33. data/app/views/spina/admin/journal/articles/_form.html.haml +23 -23
  34. data/app/views/spina/admin/journal/articles/_form_authors.html.haml +3 -15
  35. data/app/views/spina/admin/journal/articles/_form_details.html.haml +37 -56
  36. data/app/views/spina/admin/journal/articles/index.html.haml +7 -17
  37. data/app/views/spina/admin/journal/articles/view_authors.html.haml +2 -0
  38. data/app/views/spina/admin/journal/authors/_form.html.haml +24 -24
  39. data/app/views/spina/admin/journal/authors/_form_affiliation.html.haml +12 -20
  40. data/app/views/spina/admin/journal/authors/_form_articles.html.haml +3 -18
  41. data/app/views/spina/admin/journal/authors/_form_details.html.haml +27 -5
  42. data/app/views/spina/admin/journal/authors/index.html.haml +7 -15
  43. data/app/views/spina/admin/journal/authors/view_articles.html.haml +2 -0
  44. data/app/views/spina/admin/journal/institutions/_form.html.haml +24 -24
  45. data/app/views/spina/admin/journal/institutions/_form_details.html.haml +3 -8
  46. data/app/views/spina/admin/journal/institutions/_form_view_affiliations.html.haml +3 -10
  47. data/app/views/spina/admin/journal/institutions/index.html.haml +7 -15
  48. data/app/views/spina/admin/journal/institutions/view_affiliations.html.haml +2 -0
  49. data/app/views/spina/admin/journal/issues/_form.html.haml +23 -23
  50. data/app/views/spina/admin/journal/issues/_form_articles.html.haml +3 -14
  51. data/app/views/spina/admin/journal/issues/_form_details.html.haml +14 -28
  52. data/app/views/spina/admin/journal/issues/index.html.haml +7 -16
  53. data/app/views/spina/admin/journal/issues/view_articles.html.haml +3 -0
  54. data/app/views/spina/admin/journal/journals/_form.html.haml +22 -30
  55. data/app/views/spina/admin/journal/licences/_form.html.haml +24 -37
  56. data/app/views/spina/admin/journal/licences/index.html.haml +7 -16
  57. data/app/views/spina/admin/journal/volumes/_form.html.haml +25 -12
  58. data/app/views/spina/admin/journal/volumes/_form_details.html.haml +5 -10
  59. data/app/views/spina/admin/journal/volumes/_form_issues.html.haml +2 -13
  60. data/app/views/spina/admin/journal/volumes/index.html.haml +7 -16
  61. data/app/views/spina/admin/journal/volumes/view_issues.html.haml +2 -0
  62. data/app/views/spina/admin/parts/admin/journal/page_ranges/_form.html.haml +3 -4
  63. data/config/locales/en.yml +70 -8
  64. data/config/routes.rb +26 -6
  65. data/db/migrate/20220130171603_add_orcid_to_spina_admin_journal_author.rb +7 -0
  66. data/lib/spina/admin/journal/engine.rb +12 -0
  67. data/lib/spina/admin/journal/version.rb +1 -1
  68. data/lib/spina/admin/journal.rb +1 -0
  69. metadata +55 -65
  70. data/app/assets/javascripts/spina/admin/journal/application.es6 +0 -72
  71. data/app/views/layouts/spina/admin/journal/articles.html.haml +0 -10
  72. data/app/views/layouts/spina/admin/journal/authors.html.haml +0 -10
  73. data/app/views/layouts/spina/admin/journal/institutions.html.haml +0 -10
  74. data/app/views/layouts/spina/admin/journal/issues.html.haml +0 -10
  75. data/app/views/layouts/spina/admin/journal/journals.html.haml +0 -10
  76. data/app/views/layouts/spina/admin/journal/licences.html.haml +0 -10
  77. data/app/views/layouts/spina/admin/journal/volumes.html.haml +0 -10
  78. data/app/views/spina/admin/journal/affiliations/_affiliation.html.haml +0 -8
  79. data/app/views/spina/admin/journal/application/_empty_list.html.haml +0 -3
  80. data/app/views/spina/admin/journal/articles/_article.html.haml +0 -10
  81. data/app/views/spina/admin/journal/authors/_author.html.haml +0 -8
  82. data/app/views/spina/admin/journal/authorships/_authorship.html.haml +0 -9
  83. data/app/views/spina/admin/journal/institutions/_institution.html.haml +0 -9
  84. data/app/views/spina/admin/journal/issues/_issue.html.haml +0 -9
  85. data/app/views/spina/admin/journal/journals/index.html.haml +0 -27
  86. data/app/views/spina/admin/journal/licences/_licence.html.haml +0 -11
  87. data/app/views/spina/admin/journal/volumes/_volume.html.haml +0 -7
  88. data/vendor/assets/javascripts/spina/admin/journal/html5sortable.js +0 -1295
@@ -1,1295 +0,0 @@
1
- /*
2
- * HTML5Sortable package
3
- * https://github.com/lukasoppermann/html5sortable
4
- *
5
- * Maintained by Lukas Oppermann <lukas@vea.re>
6
- *
7
- * Released under the MIT license.
8
- */
9
- var sortable = (function () {
10
- 'use strict';
11
-
12
- /**
13
- * Get or set data on element
14
- * @param {HTMLElement} element
15
- * @param {string} key
16
- * @param {any} value
17
- * @return {*}
18
- */
19
- function addData(element, key, value) {
20
- if (value === undefined) {
21
- return element && element.h5s && element.h5s.data && element.h5s.data[key];
22
- }
23
- else {
24
- element.h5s = element.h5s || {};
25
- element.h5s.data = element.h5s.data || {};
26
- element.h5s.data[key] = value;
27
- }
28
- }
29
- /**
30
- * Remove data from element
31
- * @param {HTMLElement} element
32
- */
33
- function removeData(element) {
34
- if (element.h5s) {
35
- delete element.h5s.data;
36
- }
37
- }
38
-
39
- /* eslint-env browser */
40
- /**
41
- * Filter only wanted nodes
42
- * @param {NodeList|HTMLCollection|Array} nodes
43
- * @param {String} selector
44
- * @returns {Array}
45
- */
46
- var _filter = (function (nodes, selector) {
47
- if (!(nodes instanceof NodeList || nodes instanceof HTMLCollection || nodes instanceof Array)) {
48
- throw new Error('You must provide a nodeList/HTMLCollection/Array of elements to be filtered.');
49
- }
50
- if (typeof selector !== 'string') {
51
- return Array.from(nodes);
52
- }
53
- return Array.from(nodes).filter(function (item) { return item.nodeType === 1 && item.matches(selector); });
54
- });
55
-
56
- /* eslint-env browser */
57
- var stores = new Map();
58
- /**
59
- * Stores data & configurations per Sortable
60
- * @param {Object} config
61
- */
62
- var Store = /** @class */ (function () {
63
- function Store() {
64
- this._config = new Map(); // eslint-disable-line no-undef
65
- this._placeholder = undefined; // eslint-disable-line no-undef
66
- this._data = new Map(); // eslint-disable-line no-undef
67
- }
68
- Object.defineProperty(Store.prototype, "config", {
69
- /**
70
- * get the configuration map of a class instance
71
- * @method config
72
- * @return {object}
73
- */
74
- get: function () {
75
- // transform Map to object
76
- var config = {};
77
- this._config.forEach(function (value, key) {
78
- config[key] = value;
79
- });
80
- // return object
81
- return config;
82
- },
83
- /**
84
- * set the configuration of a class instance
85
- * @method config
86
- * @param {object} config object of configurations
87
- */
88
- set: function (config) {
89
- if (typeof config !== 'object') {
90
- throw new Error('You must provide a valid configuration object to the config setter.');
91
- }
92
- // combine config with default
93
- var mergedConfig = Object.assign({}, config);
94
- // add config to map
95
- this._config = new Map(Object.entries(mergedConfig));
96
- },
97
- enumerable: false,
98
- configurable: true
99
- });
100
- /**
101
- * set individual configuration of a class instance
102
- * @method setConfig
103
- * @param key valid configuration key
104
- * @param value any value
105
- * @return void
106
- */
107
- Store.prototype.setConfig = function (key, value) {
108
- if (!this._config.has(key)) {
109
- throw new Error("Trying to set invalid configuration item: " + key);
110
- }
111
- // set config
112
- this._config.set(key, value);
113
- };
114
- /**
115
- * get an individual configuration of a class instance
116
- * @method getConfig
117
- * @param key valid configuration key
118
- * @return any configuration value
119
- */
120
- Store.prototype.getConfig = function (key) {
121
- if (!this._config.has(key)) {
122
- throw new Error("Invalid configuration item requested: " + key);
123
- }
124
- return this._config.get(key);
125
- };
126
- Object.defineProperty(Store.prototype, "placeholder", {
127
- /**
128
- * get the placeholder for a class instance
129
- * @method placeholder
130
- * @return {HTMLElement|null}
131
- */
132
- get: function () {
133
- return this._placeholder;
134
- },
135
- /**
136
- * set the placeholder for a class instance
137
- * @method placeholder
138
- * @param {HTMLElement} placeholder
139
- * @return {void}
140
- */
141
- set: function (placeholder) {
142
- if (!(placeholder instanceof HTMLElement) && placeholder !== null) {
143
- throw new Error('A placeholder must be an html element or null.');
144
- }
145
- this._placeholder = placeholder;
146
- },
147
- enumerable: false,
148
- configurable: true
149
- });
150
- /**
151
- * set an data entry
152
- * @method setData
153
- * @param {string} key
154
- * @param {any} value
155
- * @return {void}
156
- */
157
- Store.prototype.setData = function (key, value) {
158
- if (typeof key !== 'string') {
159
- throw new Error('The key must be a string.');
160
- }
161
- this._data.set(key, value);
162
- };
163
- /**
164
- * get an data entry
165
- * @method getData
166
- * @param {string} key an existing key
167
- * @return {any}
168
- */
169
- Store.prototype.getData = function (key) {
170
- if (typeof key !== 'string') {
171
- throw new Error('The key must be a string.');
172
- }
173
- return this._data.get(key);
174
- };
175
- /**
176
- * delete an data entry
177
- * @method deleteData
178
- * @param {string} key an existing key
179
- * @return {boolean}
180
- */
181
- Store.prototype.deleteData = function (key) {
182
- if (typeof key !== 'string') {
183
- throw new Error('The key must be a string.');
184
- }
185
- return this._data.delete(key);
186
- };
187
- return Store;
188
- }());
189
- /**
190
- * @param {HTMLElement} sortableElement
191
- * @returns {Class: Store}
192
- */
193
- var store = (function (sortableElement) {
194
- // if sortableElement is wrong type
195
- if (!(sortableElement instanceof HTMLElement)) {
196
- throw new Error('Please provide a sortable to the store function.');
197
- }
198
- // create new instance if not avilable
199
- if (!stores.has(sortableElement)) {
200
- stores.set(sortableElement, new Store());
201
- }
202
- // return instance
203
- return stores.get(sortableElement);
204
- });
205
-
206
- /**
207
- * @param {Array|HTMLElement} element
208
- * @param {Function} callback
209
- * @param {string} event
210
- */
211
- function addEventListener(element, eventName, callback) {
212
- if (element instanceof Array) {
213
- for (var i = 0; i < element.length; ++i) {
214
- addEventListener(element[i], eventName, callback);
215
- }
216
- return;
217
- }
218
- element.addEventListener(eventName, callback);
219
- store(element).setData("event" + eventName, callback);
220
- }
221
- /**
222
- * @param {Array<HTMLElement>|HTMLElement} element
223
- * @param {string} eventName
224
- */
225
- function removeEventListener(element, eventName) {
226
- if (element instanceof Array) {
227
- for (var i = 0; i < element.length; ++i) {
228
- removeEventListener(element[i], eventName);
229
- }
230
- return;
231
- }
232
- element.removeEventListener(eventName, store(element).getData("event" + eventName));
233
- store(element).deleteData("event" + eventName);
234
- }
235
-
236
- /**
237
- * @param {Array<HTMLElement>|HTMLElement} element
238
- * @param {string} attribute
239
- * @param {string} value
240
- */
241
- function addAttribute(element, attribute, value) {
242
- if (element instanceof Array) {
243
- for (var i = 0; i < element.length; ++i) {
244
- addAttribute(element[i], attribute, value);
245
- }
246
- return;
247
- }
248
- element.setAttribute(attribute, value);
249
- }
250
- /**
251
- * @param {Array|HTMLElement} element
252
- * @param {string} attribute
253
- */
254
- function removeAttribute(element, attribute) {
255
- if (element instanceof Array) {
256
- for (var i = 0; i < element.length; ++i) {
257
- removeAttribute(element[i], attribute);
258
- }
259
- return;
260
- }
261
- element.removeAttribute(attribute);
262
- }
263
-
264
- /**
265
- * @param {HTMLElement} element
266
- * @returns {Object}
267
- */
268
- var _offset = (function (element) {
269
- if (!element.parentElement || element.getClientRects().length === 0) {
270
- throw new Error('target element must be part of the dom');
271
- }
272
- var rect = element.getClientRects()[0];
273
- return {
274
- left: rect.left + window.pageXOffset,
275
- right: rect.right + window.pageXOffset,
276
- top: rect.top + window.pageYOffset,
277
- bottom: rect.bottom + window.pageYOffset
278
- };
279
- });
280
-
281
- /**
282
- * Creates and returns a new debounced version of the passed function which will postpone its execution until after wait milliseconds have elapsed
283
- * @param {Function} func to debounce
284
- * @param {number} time to wait before calling function with latest arguments, 0 - no debounce
285
- * @returns {function} - debounced function
286
- */
287
- var _debounce = (function (func, wait) {
288
- if (wait === void 0) { wait = 0; }
289
- var timeout;
290
- return function () {
291
- var args = [];
292
- for (var _i = 0; _i < arguments.length; _i++) {
293
- args[_i] = arguments[_i];
294
- }
295
- clearTimeout(timeout);
296
- timeout = setTimeout(function () {
297
- func.apply(void 0, args);
298
- }, wait);
299
- };
300
- });
301
-
302
- /* eslint-env browser */
303
- /**
304
- * Get position of the element relatively to its sibling elements
305
- * @param {HTMLElement} element
306
- * @returns {number}
307
- */
308
- var _index = (function (element, elementList) {
309
- if (!(element instanceof HTMLElement) || !(elementList instanceof NodeList || elementList instanceof HTMLCollection || elementList instanceof Array)) {
310
- throw new Error('You must provide an element and a list of elements.');
311
- }
312
- return Array.from(elementList).indexOf(element);
313
- });
314
-
315
- /* eslint-env browser */
316
- /**
317
- * Test whether element is in DOM
318
- * @param {HTMLElement} element
319
- * @returns {boolean}
320
- */
321
- var isInDom = (function (element) {
322
- if (!(element instanceof HTMLElement)) {
323
- throw new Error('Element is not a node element.');
324
- }
325
- return element.parentNode !== null;
326
- });
327
-
328
- /* eslint-env browser */
329
- /**
330
- * Insert node before or after target
331
- * @param {HTMLElement} referenceNode - reference element
332
- * @param {HTMLElement} newElement - element to be inserted
333
- * @param {String} position - insert before or after reference element
334
- */
335
- var insertNode = function (referenceNode, newElement, position) {
336
- if (!(referenceNode instanceof HTMLElement) || !(referenceNode.parentElement instanceof HTMLElement)) {
337
- throw new Error('target and element must be a node');
338
- }
339
- referenceNode.parentElement.insertBefore(newElement, (position === 'before' ? referenceNode : referenceNode.nextElementSibling));
340
- };
341
- /**
342
- * Insert before target
343
- * @param {HTMLElement} target
344
- * @param {HTMLElement} element
345
- */
346
- var insertBefore = function (target, element) { return insertNode(target, element, 'before'); };
347
- /**
348
- * Insert after target
349
- * @param {HTMLElement} target
350
- * @param {HTMLElement} element
351
- */
352
- var insertAfter = function (target, element) { return insertNode(target, element, 'after'); };
353
-
354
- /* eslint-env browser */
355
- /**
356
- * Filter only wanted nodes
357
- * @param {HTMLElement} sortableContainer
358
- * @param {Function} customSerializer
359
- * @returns {Array}
360
- */
361
- var _serialize = (function (sortableContainer, customItemSerializer, customContainerSerializer) {
362
- if (customItemSerializer === void 0) { customItemSerializer = function (serializedItem, sortableContainer) { return serializedItem; }; }
363
- if (customContainerSerializer === void 0) { customContainerSerializer = function (serializedContainer) { return serializedContainer; }; }
364
- // check for valid sortableContainer
365
- if (!(sortableContainer instanceof HTMLElement) || !sortableContainer.isSortable === true) {
366
- throw new Error('You need to provide a sortableContainer to be serialized.');
367
- }
368
- // check for valid serializers
369
- if (typeof customItemSerializer !== 'function' || typeof customContainerSerializer !== 'function') {
370
- throw new Error('You need to provide a valid serializer for items and the container.');
371
- }
372
- // get options
373
- var options = addData(sortableContainer, 'opts');
374
- var item = options.items;
375
- // serialize container
376
- var items = _filter(sortableContainer.children, item);
377
- var serializedItems = items.map(function (item) {
378
- return {
379
- parent: sortableContainer,
380
- node: item,
381
- html: item.outerHTML,
382
- index: _index(item, items)
383
- };
384
- });
385
- // serialize container
386
- var container = {
387
- node: sortableContainer,
388
- itemCount: serializedItems.length
389
- };
390
- return {
391
- container: customContainerSerializer(container),
392
- items: serializedItems.map(function (item) { return customItemSerializer(item, sortableContainer); })
393
- };
394
- });
395
-
396
- /* eslint-env browser */
397
- /**
398
- * create a placeholder element
399
- * @param {HTMLElement} sortableElement a single sortable
400
- * @param {string|undefined} placeholder a string representing an html element
401
- * @param {string} placeholderClasses a string representing the classes that should be added to the placeholder
402
- */
403
- var _makePlaceholder = (function (sortableElement, placeholder, placeholderClass) {
404
- var _a;
405
- if (placeholderClass === void 0) { placeholderClass = 'sortable-placeholder'; }
406
- if (!(sortableElement instanceof HTMLElement)) {
407
- throw new Error('You must provide a valid element as a sortable.');
408
- }
409
- // if placeholder is not an element
410
- if (!(placeholder instanceof HTMLElement) && placeholder !== undefined) {
411
- throw new Error('You must provide a valid element as a placeholder or set ot to undefined.');
412
- }
413
- // if no placeholder element is given
414
- if (placeholder === undefined) {
415
- if (['UL', 'OL'].includes(sortableElement.tagName)) {
416
- placeholder = document.createElement('li');
417
- }
418
- else if (['TABLE', 'TBODY'].includes(sortableElement.tagName)) {
419
- placeholder = document.createElement('tr');
420
- // set colspan to always all rows, otherwise the item can only be dropped in first column
421
- placeholder.innerHTML = '<td colspan="100"></td>';
422
- }
423
- else {
424
- placeholder = document.createElement('div');
425
- }
426
- }
427
- // add classes to placeholder
428
- if (typeof placeholderClass === 'string') {
429
- (_a = placeholder.classList).add.apply(_a, placeholderClass.split(' '));
430
- }
431
- return placeholder;
432
- });
433
-
434
- /* eslint-env browser */
435
- /**
436
- * Get height of an element including padding
437
- * @param {HTMLElement} element an dom element
438
- */
439
- var _getElementHeight = (function (element) {
440
- if (!(element instanceof HTMLElement)) {
441
- throw new Error('You must provide a valid dom element');
442
- }
443
- // get calculated style of element
444
- var style = window.getComputedStyle(element);
445
- // get only height if element has box-sizing: border-box specified
446
- if (style.getPropertyValue('box-sizing') === 'border-box') {
447
- return parseInt(style.getPropertyValue('height'), 10);
448
- }
449
- // pick applicable properties, convert to int and reduce by adding
450
- return ['height', 'padding-top', 'padding-bottom']
451
- .map(function (key) {
452
- var int = parseInt(style.getPropertyValue(key), 10);
453
- return isNaN(int) ? 0 : int;
454
- })
455
- .reduce(function (sum, value) { return sum + value; });
456
- });
457
-
458
- /* eslint-env browser */
459
- /**
460
- * Get width of an element including padding
461
- * @param {HTMLElement} element an dom element
462
- */
463
- var _getElementWidth = (function (element) {
464
- if (!(element instanceof HTMLElement)) {
465
- throw new Error('You must provide a valid dom element');
466
- }
467
- // get calculated style of element
468
- var style = window.getComputedStyle(element);
469
- // pick applicable properties, convert to int and reduce by adding
470
- return ['width', 'padding-left', 'padding-right']
471
- .map(function (key) {
472
- var int = parseInt(style.getPropertyValue(key), 10);
473
- return isNaN(int) ? 0 : int;
474
- })
475
- .reduce(function (sum, value) { return sum + value; });
476
- });
477
-
478
- /* eslint-env browser */
479
- /**
480
- * get handle or return item
481
- * @param {Array<HTMLElement>} items
482
- * @param {string} selector
483
- */
484
- var _getHandles = (function (items, selector) {
485
- if (!(items instanceof Array)) {
486
- throw new Error('You must provide a Array of HTMLElements to be filtered.');
487
- }
488
- if (typeof selector !== 'string') {
489
- return items;
490
- }
491
- return items
492
- // remove items without handle from array
493
- .filter(function (item) {
494
- return item.querySelector(selector) instanceof HTMLElement ||
495
- (item.shadowRoot && item.shadowRoot.querySelector(selector) instanceof HTMLElement);
496
- })
497
- // replace item with handle in array
498
- .map(function (item) {
499
- return item.querySelector(selector) || (item.shadowRoot && item.shadowRoot.querySelector(selector));
500
- });
501
- });
502
-
503
- /**
504
- * @param {Event} event
505
- * @returns {HTMLElement}
506
- */
507
- var getEventTarget = (function (event) {
508
- return (event.composedPath && event.composedPath()[0]) || event.target;
509
- });
510
-
511
- /* eslint-env browser */
512
- /**
513
- * defaultDragImage returns the current item as dragged image
514
- * @param {HTMLElement} draggedElement - the item that the user drags
515
- * @param {object} elementOffset - an object with the offsets top, left, right & bottom
516
- * @param {Event} event - the original drag event object
517
- * @return {object} with element, posX and posY properties
518
- */
519
- var defaultDragImage = function (draggedElement, elementOffset, event) {
520
- return {
521
- element: draggedElement,
522
- posX: event.pageX - elementOffset.left,
523
- posY: event.pageY - elementOffset.top
524
- };
525
- };
526
- /**
527
- * attaches an element as the drag image to an event
528
- * @param {Event} event - the original drag event object
529
- * @param {HTMLElement} draggedElement - the item that the user drags
530
- * @param {Function} customDragImage - function to create a custom dragImage
531
- * @return void
532
- */
533
- var setDragImage = (function (event, draggedElement, customDragImage) {
534
- // check if event is provided
535
- if (!(event instanceof Event)) {
536
- throw new Error('setDragImage requires a DragEvent as the first argument.');
537
- }
538
- // check if draggedElement is provided
539
- if (!(draggedElement instanceof HTMLElement)) {
540
- throw new Error('setDragImage requires the dragged element as the second argument.');
541
- }
542
- // set default function of none provided
543
- if (!customDragImage) {
544
- customDragImage = defaultDragImage;
545
- }
546
- // check if setDragImage method is available
547
- if (event.dataTransfer && event.dataTransfer.setDragImage) {
548
- // get the elements offset
549
- var elementOffset = _offset(draggedElement);
550
- // get the dragImage
551
- var dragImage = customDragImage(draggedElement, elementOffset, event);
552
- // check if custom function returns correct values
553
- if (!(dragImage.element instanceof HTMLElement) || typeof dragImage.posX !== 'number' || typeof dragImage.posY !== 'number') {
554
- throw new Error('The customDragImage function you provided must return and object with the properties element[string], posX[integer], posY[integer].');
555
- }
556
- // needs to be set for HTML5 drag & drop to work
557
- event.dataTransfer.effectAllowed = 'copyMove';
558
- // Firefox requires it to use the event target's id for the data
559
- event.dataTransfer.setData('text/plain', getEventTarget(event).id);
560
- // set the drag image on the event
561
- event.dataTransfer.setDragImage(dragImage.element, dragImage.posX, dragImage.posY);
562
- }
563
- });
564
-
565
- /**
566
- * Check if curList accepts items from destList
567
- * @param {sortable} destination the container an item is move to
568
- * @param {sortable} origin the container an item comes from
569
- */
570
- var _listsConnected = (function (destination, origin) {
571
- // check if valid sortable
572
- if (destination.isSortable === true) {
573
- var acceptFrom = store(destination).getConfig('acceptFrom');
574
- // check if acceptFrom is valid
575
- if (acceptFrom !== null && acceptFrom !== false && typeof acceptFrom !== 'string') {
576
- throw new Error('HTML5Sortable: Wrong argument, "acceptFrom" must be "null", "false", or a valid selector string.');
577
- }
578
- if (acceptFrom !== null) {
579
- return acceptFrom !== false && acceptFrom.split(',').filter(function (sel) {
580
- return sel.length > 0 && origin.matches(sel);
581
- }).length > 0;
582
- }
583
- // drop in same list
584
- if (destination === origin) {
585
- return true;
586
- }
587
- // check if lists are connected with connectWith
588
- if (store(destination).getConfig('connectWith') !== undefined && store(destination).getConfig('connectWith') !== null) {
589
- return store(destination).getConfig('connectWith') === store(origin).getConfig('connectWith');
590
- }
591
- }
592
- return false;
593
- });
594
-
595
- /**
596
- * default configurations
597
- */
598
- var defaultConfiguration = {
599
- items: null,
600
- // deprecated
601
- connectWith: null,
602
- // deprecated
603
- disableIEFix: null,
604
- acceptFrom: null,
605
- copy: false,
606
- placeholder: null,
607
- placeholderClass: 'sortable-placeholder',
608
- draggingClass: 'sortable-dragging',
609
- hoverClass: false,
610
- dropTargetContainerClass: false,
611
- debounce: 0,
612
- throttleTime: 100,
613
- maxItems: 0,
614
- itemSerializer: undefined,
615
- containerSerializer: undefined,
616
- customDragImage: null,
617
- orientation: 'vertical'
618
- };
619
-
620
- /**
621
- * make sure a function is only called once within the given amount of time
622
- * @param {Function} fn the function to throttle
623
- * @param {number} threshold time limit for throttling
624
- */
625
- // must use function to keep this context
626
- function _throttle (fn, threshold) {
627
- var _this = this;
628
- if (threshold === void 0) { threshold = 250; }
629
- // check function
630
- if (typeof fn !== 'function') {
631
- throw new Error('You must provide a function as the first argument for throttle.');
632
- }
633
- // check threshold
634
- if (typeof threshold !== 'number') {
635
- throw new Error('You must provide a number as the second argument for throttle.');
636
- }
637
- var lastEventTimestamp = null;
638
- return function () {
639
- var args = [];
640
- for (var _i = 0; _i < arguments.length; _i++) {
641
- args[_i] = arguments[_i];
642
- }
643
- var now = Date.now();
644
- if (lastEventTimestamp === null || now - lastEventTimestamp >= threshold) {
645
- lastEventTimestamp = now;
646
- fn.apply(_this, args);
647
- }
648
- };
649
- }
650
-
651
- /* eslint-env browser */
652
- /**
653
- * enable or disable hoverClass on mouseenter/leave if container Items
654
- * @param {sortable} sortableContainer a valid sortableContainer
655
- * @param {boolean} enable enable or disable event
656
- */
657
- // export default (sortableContainer: sortable, enable: boolean) => {
658
- var enableHoverClass = (function (sortableContainer, enable) {
659
- if (typeof store(sortableContainer).getConfig('hoverClass') === 'string') {
660
- var hoverClasses_1 = store(sortableContainer).getConfig('hoverClass').split(' ');
661
- // add class on hover
662
- if (enable === true) {
663
- addEventListener(sortableContainer, 'mousemove', _throttle(function (event) {
664
- // check of no mouse button was pressed when mousemove started == no drag
665
- if (event.buttons === 0) {
666
- _filter(sortableContainer.children, store(sortableContainer).getConfig('items')).forEach(function (item) {
667
- var _a, _b;
668
- if (item !== event.target) {
669
- (_a = item.classList).remove.apply(_a, hoverClasses_1);
670
- }
671
- else {
672
- (_b = item.classList).add.apply(_b, hoverClasses_1);
673
- }
674
- });
675
- }
676
- }, store(sortableContainer).getConfig('throttleTime')));
677
- // remove class on leave
678
- addEventListener(sortableContainer, 'mouseleave', function () {
679
- _filter(sortableContainer.children, store(sortableContainer).getConfig('items')).forEach(function (item) {
680
- var _a;
681
- (_a = item.classList).remove.apply(_a, hoverClasses_1);
682
- });
683
- });
684
- // remove events
685
- }
686
- else {
687
- removeEventListener(sortableContainer, 'mousemove');
688
- removeEventListener(sortableContainer, 'mouseleave');
689
- }
690
- }
691
- });
692
-
693
- /* eslint-env browser */
694
- /*
695
- * variables global to the plugin
696
- */
697
- var dragging;
698
- var draggingHeight;
699
- var draggingWidth;
700
- /*
701
- * Keeps track of the initialy selected list, where 'dragstart' event was triggered
702
- * It allows us to move the data in between individual Sortable List instances
703
- */
704
- // Origin List - data from before any item was changed
705
- var originContainer;
706
- var originIndex;
707
- var originElementIndex;
708
- var originItemsBeforeUpdate;
709
- // Previous Sortable Container - we dispatch as sortenter event when a
710
- // dragged item enters a sortableContainer for the first time
711
- var previousContainer;
712
- // Destination List - data from before any item was changed
713
- var destinationItemsBeforeUpdate;
714
- /**
715
- * remove event handlers from items
716
- * @param {Array|NodeList} items
717
- */
718
- var _removeItemEvents = function (items) {
719
- removeEventListener(items, 'dragstart');
720
- removeEventListener(items, 'dragend');
721
- removeEventListener(items, 'dragover');
722
- removeEventListener(items, 'dragenter');
723
- removeEventListener(items, 'drop');
724
- removeEventListener(items, 'mouseenter');
725
- removeEventListener(items, 'mouseleave');
726
- };
727
- // Remove container events
728
- var _removeContainerEvents = function (originContainer, previousContainer) {
729
- if (originContainer) {
730
- removeEventListener(originContainer, 'dragleave');
731
- }
732
- if (previousContainer && (previousContainer !== originContainer)) {
733
- removeEventListener(previousContainer, 'dragleave');
734
- }
735
- };
736
- /**
737
- * _getDragging returns the current element to drag or
738
- * a copy of the element.
739
- * Is Copy Active for sortable
740
- * @param {HTMLElement} draggedItem - the item that the user drags
741
- * @param {HTMLElement} sortable a single sortable
742
- */
743
- var _getDragging = function (draggedItem, sortable) {
744
- var ditem = draggedItem;
745
- if (store(sortable).getConfig('copy') === true) {
746
- ditem = draggedItem.cloneNode(true);
747
- addAttribute(ditem, 'aria-copied', 'true');
748
- draggedItem.parentElement.appendChild(ditem);
749
- ditem.style.display = 'none';
750
- ditem.oldDisplay = draggedItem.style.display;
751
- }
752
- return ditem;
753
- };
754
- /**
755
- * Remove data from sortable
756
- * @param {HTMLElement} sortable a single sortable
757
- */
758
- var _removeSortableData = function (sortable) {
759
- removeData(sortable);
760
- removeAttribute(sortable, 'aria-dropeffect');
761
- };
762
- /**
763
- * Remove data from items
764
- * @param {Array<HTMLElement>|HTMLElement} items
765
- */
766
- var _removeItemData = function (items) {
767
- removeAttribute(items, 'aria-grabbed');
768
- removeAttribute(items, 'aria-copied');
769
- removeAttribute(items, 'draggable');
770
- removeAttribute(items, 'role');
771
- };
772
- /**
773
- * find sortable from element. travels up parent element until found or null.
774
- * @param {HTMLElement} element a single sortable
775
- * @param {Event} event - the current event. We need to pass it to be able to
776
- * find Sortable whith shadowRoot (document fragment has no parent)
777
- */
778
- function findSortable(element, event) {
779
- if (event.composedPath) {
780
- return event.composedPath().find(function (el) { return el.isSortable; });
781
- }
782
- while (element.isSortable !== true) {
783
- element = element.parentElement;
784
- }
785
- return element;
786
- }
787
- /**
788
- * Dragging event is on the sortable element. finds the top child that
789
- * contains the element.
790
- * @param {HTMLElement} sortableElement a single sortable
791
- * @param {HTMLElement} element is that being dragged
792
- */
793
- function findDragElement(sortableElement, element) {
794
- var options = addData(sortableElement, 'opts');
795
- var items = _filter(sortableElement.children, options.items);
796
- var itemlist = items.filter(function (ele) {
797
- return ele.contains(element) || (ele.shadowRoot && ele.shadowRoot.contains(element));
798
- });
799
- return itemlist.length > 0 ? itemlist[0] : element;
800
- }
801
- /**
802
- * Destroy the sortable
803
- * @param {HTMLElement} sortableElement a single sortable
804
- */
805
- var _destroySortable = function (sortableElement) {
806
- var opts = addData(sortableElement, 'opts') || {};
807
- var items = _filter(sortableElement.children, opts.items);
808
- var handles = _getHandles(items, opts.handle);
809
- // remove event handlers & data from sortable
810
- removeEventListener(sortableElement, 'dragover');
811
- removeEventListener(sortableElement, 'dragenter');
812
- removeEventListener(sortableElement, 'dragstart');
813
- removeEventListener(sortableElement, 'dragend');
814
- removeEventListener(sortableElement, 'drop');
815
- // remove event data from sortable
816
- _removeSortableData(sortableElement);
817
- // remove event handlers & data from items
818
- removeEventListener(handles, 'mousedown');
819
- _removeItemEvents(items);
820
- _removeItemData(items);
821
- _removeContainerEvents(originContainer, previousContainer);
822
- // clear sortable flag
823
- sortableElement.isSortable = false;
824
- };
825
- /**
826
- * Enable the sortable
827
- * @param {HTMLElement} sortableElement a single sortable
828
- */
829
- var _enableSortable = function (sortableElement) {
830
- var opts = addData(sortableElement, 'opts');
831
- var items = _filter(sortableElement.children, opts.items);
832
- var handles = _getHandles(items, opts.handle);
833
- addAttribute(sortableElement, 'aria-dropeffect', 'move');
834
- addData(sortableElement, '_disabled', 'false');
835
- addAttribute(handles, 'draggable', 'true');
836
- // @todo: remove this fix
837
- // IE FIX for ghost
838
- // can be disabled as it has the side effect that other events
839
- // (e.g. click) will be ignored
840
- if (opts.disableIEFix === false) {
841
- var spanEl = (document || window.document).createElement('span');
842
- if (typeof spanEl.dragDrop === 'function') {
843
- addEventListener(handles, 'mousedown', function () {
844
- if (items.indexOf(this) !== -1) {
845
- this.dragDrop();
846
- }
847
- else {
848
- var parent = this.parentElement;
849
- while (items.indexOf(parent) === -1) {
850
- parent = parent.parentElement;
851
- }
852
- parent.dragDrop();
853
- }
854
- });
855
- }
856
- }
857
- };
858
- /**
859
- * Disable the sortable
860
- * @param {HTMLElement} sortableElement a single sortable
861
- */
862
- var _disableSortable = function (sortableElement) {
863
- var opts = addData(sortableElement, 'opts');
864
- var items = _filter(sortableElement.children, opts.items);
865
- var handles = _getHandles(items, opts.handle);
866
- addAttribute(sortableElement, 'aria-dropeffect', 'none');
867
- addData(sortableElement, '_disabled', 'true');
868
- addAttribute(handles, 'draggable', 'false');
869
- removeEventListener(handles, 'mousedown');
870
- };
871
- /**
872
- * Reload the sortable
873
- * @param {HTMLElement} sortableElement a single sortable
874
- * @description events need to be removed to not be double bound
875
- */
876
- var _reloadSortable = function (sortableElement) {
877
- var opts = addData(sortableElement, 'opts');
878
- var items = _filter(sortableElement.children, opts.items);
879
- var handles = _getHandles(items, opts.handle);
880
- addData(sortableElement, '_disabled', 'false');
881
- // remove event handlers from items
882
- _removeItemEvents(items);
883
- _removeContainerEvents();
884
- removeEventListener(handles, 'mousedown');
885
- // remove event handlers from sortable
886
- removeEventListener(sortableElement, 'dragover');
887
- removeEventListener(sortableElement, 'dragenter');
888
- removeEventListener(sortableElement, 'drop');
889
- };
890
- /**
891
- * Public sortable object
892
- * @param {Array|NodeList} sortableElements
893
- * @param {object|string} options|method
894
- */
895
- function sortable(sortableElements, options) {
896
- // get method string to see if a method is called
897
- var method = String(options);
898
- options = options || {};
899
- // check if the user provided a selector instead of an element
900
- if (typeof sortableElements === 'string') {
901
- sortableElements = document.querySelectorAll(sortableElements);
902
- }
903
- // if the user provided an element, return it in an array to keep the return value consistant
904
- if (sortableElements instanceof HTMLElement) {
905
- sortableElements = [sortableElements];
906
- }
907
- sortableElements = Array.prototype.slice.call(sortableElements);
908
- if (/serialize/.test(method)) {
909
- return sortableElements.map(function (sortableContainer) {
910
- var opts = addData(sortableContainer, 'opts');
911
- return _serialize(sortableContainer, opts.itemSerializer, opts.containerSerializer);
912
- });
913
- }
914
- sortableElements.forEach(function (sortableElement) {
915
- if (/enable|disable|destroy/.test(method)) {
916
- return sortable[method](sortableElement);
917
- }
918
- // log deprecation
919
- ['connectWith', 'disableIEFix'].forEach(function (configKey) {
920
- if (Object.prototype.hasOwnProperty.call(options, configKey) && options[configKey] !== null) {
921
- console.warn("HTML5Sortable: You are using the deprecated configuration \"" + configKey + "\". This will be removed in an upcoming version, make sure to migrate to the new options when updating.");
922
- }
923
- });
924
- // merge options with default options
925
- options = Object.assign({}, defaultConfiguration, store(sortableElement).config, options);
926
- // init data store for sortable
927
- store(sortableElement).config = options;
928
- // set options on sortable
929
- addData(sortableElement, 'opts', options);
930
- // property to define as sortable
931
- sortableElement.isSortable = true;
932
- // reset sortable
933
- _reloadSortable(sortableElement);
934
- // initialize
935
- var listItems = _filter(sortableElement.children, options.items);
936
- // create element if user defined a placeholder element as a string
937
- var customPlaceholder;
938
- if (options.placeholder !== null && options.placeholder !== undefined) {
939
- var tempContainer = document.createElement(sortableElement.tagName);
940
- if (options.placeholder instanceof HTMLElement) {
941
- tempContainer.appendChild(options.placeholder);
942
- }
943
- else {
944
- tempContainer.innerHTML = options.placeholder;
945
- }
946
- customPlaceholder = tempContainer.children[0];
947
- }
948
- // add placeholder
949
- store(sortableElement).placeholder = _makePlaceholder(sortableElement, customPlaceholder, options.placeholderClass);
950
- addData(sortableElement, 'items', options.items);
951
- if (options.acceptFrom) {
952
- addData(sortableElement, 'acceptFrom', options.acceptFrom);
953
- }
954
- else if (options.connectWith) {
955
- addData(sortableElement, 'connectWith', options.connectWith);
956
- }
957
- _enableSortable(sortableElement);
958
- addAttribute(listItems, 'role', 'option');
959
- addAttribute(listItems, 'aria-grabbed', 'false');
960
- // enable hover class
961
- enableHoverClass(sortableElement, true);
962
- /*
963
- Handle drag events on draggable items
964
- Handle is set at the sortableElement level as it will bubble up
965
- from the item
966
- */
967
- addEventListener(sortableElement, 'dragstart', function (e) {
968
- // ignore dragstart events
969
- var target = getEventTarget(e);
970
- if (target.isSortable === true) {
971
- return;
972
- }
973
- e.stopImmediatePropagation();
974
- if ((options.handle && !target.matches(options.handle)) || target.getAttribute('draggable') === 'false') {
975
- return;
976
- }
977
- var sortableContainer = findSortable(target, e);
978
- var dragItem = findDragElement(sortableContainer, target);
979
- // grab values
980
- originItemsBeforeUpdate = _filter(sortableContainer.children, options.items);
981
- originIndex = originItemsBeforeUpdate.indexOf(dragItem);
982
- originElementIndex = _index(dragItem, sortableContainer.children);
983
- originContainer = sortableContainer;
984
- // add transparent clone or other ghost to cursor
985
- setDragImage(e, dragItem, options.customDragImage);
986
- // cache selsection & add attr for dragging
987
- draggingHeight = _getElementHeight(dragItem);
988
- draggingWidth = _getElementWidth(dragItem);
989
- dragItem.classList.add(options.draggingClass);
990
- dragging = _getDragging(dragItem, sortableContainer);
991
- addAttribute(dragging, 'aria-grabbed', 'true');
992
- // dispatch sortstart event on each element in group
993
- sortableContainer.dispatchEvent(new CustomEvent('sortstart', {
994
- detail: {
995
- origin: {
996
- elementIndex: originElementIndex,
997
- index: originIndex,
998
- container: originContainer
999
- },
1000
- item: dragging,
1001
- originalTarget: target
1002
- }
1003
- }));
1004
- });
1005
- /*
1006
- We are capturing targetSortable before modifications with 'dragenter' event
1007
- */
1008
- addEventListener(sortableElement, 'dragenter', function (e) {
1009
- var target = getEventTarget(e);
1010
- var sortableContainer = findSortable(target, e);
1011
- if (sortableContainer && sortableContainer !== previousContainer) {
1012
- destinationItemsBeforeUpdate = _filter(sortableContainer.children, addData(sortableContainer, 'items'))
1013
- .filter(function (item) { return item !== store(sortableElement).placeholder; });
1014
- if (options.dropTargetContainerClass) {
1015
- sortableContainer.classList.add(options.dropTargetContainerClass);
1016
- }
1017
- sortableContainer.dispatchEvent(new CustomEvent('sortenter', {
1018
- detail: {
1019
- origin: {
1020
- elementIndex: originElementIndex,
1021
- index: originIndex,
1022
- container: originContainer
1023
- },
1024
- destination: {
1025
- container: sortableContainer,
1026
- itemsBeforeUpdate: destinationItemsBeforeUpdate
1027
- },
1028
- item: dragging,
1029
- originalTarget: target
1030
- }
1031
- }));
1032
- addEventListener(sortableContainer, 'dragleave', function (e) {
1033
- // TODO: rename outTarget to be more self-explanatory
1034
- // e.fromElement for very old browsers, similar to relatedTarget
1035
- var outTarget = e.relatedTarget || e.fromElement;
1036
- if (!e.currentTarget.contains(outTarget)) {
1037
- if (options.dropTargetContainerClass) {
1038
- sortableContainer.classList.remove(options.dropTargetContainerClass);
1039
- }
1040
- sortableContainer.dispatchEvent(new CustomEvent('sortleave', {
1041
- detail: {
1042
- origin: {
1043
- elementIndex: originElementIndex,
1044
- index: originIndex,
1045
- container: sortableContainer
1046
- },
1047
- item: dragging,
1048
- originalTarget: target
1049
- }
1050
- }));
1051
- }
1052
- });
1053
- }
1054
- previousContainer = sortableContainer;
1055
- });
1056
- /*
1057
- * Dragend Event - https://developer.mozilla.org/en-US/docs/Web/Events/dragend
1058
- * Fires each time dragEvent end, or ESC pressed
1059
- * We are using it to clean up any draggable elements and placeholders
1060
- */
1061
- addEventListener(sortableElement, 'dragend', function (e) {
1062
- if (!dragging) {
1063
- return;
1064
- }
1065
- dragging.classList.remove(options.draggingClass);
1066
- addAttribute(dragging, 'aria-grabbed', 'false');
1067
- if (dragging.getAttribute('aria-copied') === 'true' && addData(dragging, 'dropped') !== 'true') {
1068
- dragging.remove();
1069
- }
1070
- dragging.style.display = dragging.oldDisplay;
1071
- delete dragging.oldDisplay;
1072
- var visiblePlaceholder = Array.from(stores.values()).map(function (data) { return data.placeholder; })
1073
- .filter(function (placeholder) { return placeholder instanceof HTMLElement; })
1074
- .filter(isInDom)[0];
1075
- if (visiblePlaceholder) {
1076
- visiblePlaceholder.remove();
1077
- }
1078
- // dispatch sortstart event on each element in group
1079
- sortableElement.dispatchEvent(new CustomEvent('sortstop', {
1080
- detail: {
1081
- origin: {
1082
- elementIndex: originElementIndex,
1083
- index: originIndex,
1084
- container: originContainer
1085
- },
1086
- item: dragging
1087
- }
1088
- }));
1089
- previousContainer = null;
1090
- dragging = null;
1091
- draggingHeight = null;
1092
- draggingWidth = null;
1093
- });
1094
- /*
1095
- * Drop Event - https://developer.mozilla.org/en-US/docs/Web/Events/drop
1096
- * Fires when valid drop target area is hit
1097
- */
1098
- addEventListener(sortableElement, 'drop', function (e) {
1099
- if (!_listsConnected(sortableElement, dragging.parentElement)) {
1100
- return;
1101
- }
1102
- e.preventDefault();
1103
- e.stopPropagation();
1104
- addData(dragging, 'dropped', 'true');
1105
- // get the one placeholder that is currently visible
1106
- var visiblePlaceholder = Array.from(stores.values()).map(function (data) {
1107
- return data.placeholder;
1108
- })
1109
- // filter only HTMLElements
1110
- .filter(function (placeholder) { return placeholder instanceof HTMLElement; })
1111
- // filter only elements in DOM
1112
- .filter(isInDom)[0];
1113
- // attach element after placeholder
1114
- insertAfter(visiblePlaceholder, dragging);
1115
- // remove placeholder from dom
1116
- visiblePlaceholder.remove();
1117
- /*
1118
- * Fires Custom Event - 'sortstop'
1119
- */
1120
- sortableElement.dispatchEvent(new CustomEvent('sortstop', {
1121
- detail: {
1122
- origin: {
1123
- elementIndex: originElementIndex,
1124
- index: originIndex,
1125
- container: originContainer
1126
- },
1127
- item: dragging
1128
- }
1129
- }));
1130
- var placeholder = store(sortableElement).placeholder;
1131
- var originItems = _filter(originContainer.children, options.items)
1132
- .filter(function (item) { return item !== placeholder; });
1133
- var destinationContainer = this.isSortable === true ? this : this.parentElement;
1134
- var destinationItems = _filter(destinationContainer.children, addData(destinationContainer, 'items'))
1135
- .filter(function (item) { return item !== placeholder; });
1136
- var destinationElementIndex = _index(dragging, Array.from(dragging.parentElement.children)
1137
- .filter(function (item) { return item !== placeholder; }));
1138
- var destinationIndex = _index(dragging, destinationItems);
1139
- if (options.dropTargetContainerClass) {
1140
- destinationContainer.classList.remove(options.dropTargetContainerClass);
1141
- }
1142
- /*
1143
- * When a list item changed container lists or index within a list
1144
- * Fires Custom Event - 'sortupdate'
1145
- */
1146
- if (originElementIndex !== destinationElementIndex || originContainer !== destinationContainer) {
1147
- sortableElement.dispatchEvent(new CustomEvent('sortupdate', {
1148
- detail: {
1149
- origin: {
1150
- elementIndex: originElementIndex,
1151
- index: originIndex,
1152
- container: originContainer,
1153
- itemsBeforeUpdate: originItemsBeforeUpdate,
1154
- items: originItems
1155
- },
1156
- destination: {
1157
- index: destinationIndex,
1158
- elementIndex: destinationElementIndex,
1159
- container: destinationContainer,
1160
- itemsBeforeUpdate: destinationItemsBeforeUpdate,
1161
- items: destinationItems
1162
- },
1163
- item: dragging
1164
- }
1165
- }));
1166
- }
1167
- });
1168
- var debouncedDragOverEnter = _debounce(function (sortableElement, element, pageX, pageY) {
1169
- if (!dragging) {
1170
- return;
1171
- }
1172
- // set placeholder height if forcePlaceholderSize option is set
1173
- if (options.forcePlaceholderSize) {
1174
- store(sortableElement).placeholder.style.height = draggingHeight + 'px';
1175
- store(sortableElement).placeholder.style.width = draggingWidth + 'px';
1176
- }
1177
- // if element the draggedItem is dragged onto is within the array of all elements in list
1178
- // (not only items, but also disabled, etc.)
1179
- if (Array.from(sortableElement.children).indexOf(element) > -1) {
1180
- var thisHeight = _getElementHeight(element);
1181
- var thisWidth = _getElementWidth(element);
1182
- var placeholderIndex = _index(store(sortableElement).placeholder, element.parentElement.children);
1183
- var thisIndex = _index(element, element.parentElement.children);
1184
- // Check if `element` is bigger than the draggable. If it is, we have to define a dead zone to prevent flickering
1185
- if (thisHeight > draggingHeight || thisWidth > draggingWidth) {
1186
- // Dead zone?
1187
- var deadZoneVertical = thisHeight - draggingHeight;
1188
- var deadZoneHorizontal = thisWidth - draggingWidth;
1189
- var offsetTop = _offset(element).top;
1190
- var offsetLeft = _offset(element).left;
1191
- if (placeholderIndex < thisIndex &&
1192
- ((options.orientation === 'vertical' && pageY < offsetTop) ||
1193
- (options.orientation === 'horizontal' && pageX < offsetLeft))) {
1194
- return;
1195
- }
1196
- if (placeholderIndex > thisIndex &&
1197
- ((options.orientation === 'vertical' && pageY > offsetTop + thisHeight - deadZoneVertical) ||
1198
- (options.orientation === 'horizontal' && pageX > offsetLeft + thisWidth - deadZoneHorizontal))) {
1199
- return;
1200
- }
1201
- }
1202
- if (dragging.oldDisplay === undefined) {
1203
- dragging.oldDisplay = dragging.style.display;
1204
- }
1205
- if (dragging.style.display !== 'none') {
1206
- dragging.style.display = 'none';
1207
- }
1208
- // To avoid flicker, determine where to position the placeholder
1209
- // based on where the mouse pointer is relative to the elements
1210
- // vertical center.
1211
- var placeAfter = false;
1212
- try {
1213
- var elementMiddleVertical = _offset(element).top + element.offsetHeight / 2;
1214
- var elementMiddleHorizontal = _offset(element).left + element.offsetWidth / 2;
1215
- placeAfter = (options.orientation === 'vertical' && (pageY >= elementMiddleVertical)) ||
1216
- (options.orientation === 'horizontal' && (pageX >= elementMiddleHorizontal));
1217
- }
1218
- catch (e) {
1219
- placeAfter = placeholderIndex < thisIndex;
1220
- }
1221
- if (placeAfter) {
1222
- insertAfter(element, store(sortableElement).placeholder);
1223
- }
1224
- else {
1225
- insertBefore(element, store(sortableElement).placeholder);
1226
- }
1227
- // get placeholders from all stores & remove all but current one
1228
- Array.from(stores.values())
1229
- // remove empty values
1230
- .filter(function (data) { return data.placeholder !== undefined; })
1231
- // foreach placeholder in array if outside of current sorableContainer -> remove from DOM
1232
- .forEach(function (data) {
1233
- if (data.placeholder !== store(sortableElement).placeholder) {
1234
- data.placeholder.remove();
1235
- }
1236
- });
1237
- }
1238
- else {
1239
- // get all placeholders from store
1240
- var placeholders = Array.from(stores.values())
1241
- .filter(function (data) { return data.placeholder !== undefined; })
1242
- .map(function (data) {
1243
- return data.placeholder;
1244
- });
1245
- // check if element is not in placeholders
1246
- if (placeholders.indexOf(element) === -1 && sortableElement === element && !_filter(element.children, options.items).length) {
1247
- placeholders.forEach(function (element) { return element.remove(); });
1248
- element.appendChild(store(sortableElement).placeholder);
1249
- }
1250
- }
1251
- }, options.debounce);
1252
- // Handle dragover and dragenter events on draggable items
1253
- var onDragOverEnter = function (e) {
1254
- var element = e.target;
1255
- var sortableElement = element.isSortable === true ? element : findSortable(element, e);
1256
- element = findDragElement(sortableElement, element);
1257
- if (!dragging || !_listsConnected(sortableElement, dragging.parentElement) || addData(sortableElement, '_disabled') === 'true') {
1258
- return;
1259
- }
1260
- var options = addData(sortableElement, 'opts');
1261
- if (parseInt(options.maxItems) && _filter(sortableElement.children, addData(sortableElement, 'items')).length >= parseInt(options.maxItems) && dragging.parentElement !== sortableElement) {
1262
- return;
1263
- }
1264
- e.preventDefault();
1265
- e.stopPropagation();
1266
- e.dataTransfer.dropEffect = store(sortableElement).getConfig('copy') === true ? 'copy' : 'move';
1267
- debouncedDragOverEnter(sortableElement, element, e.pageX, e.pageY);
1268
- };
1269
- addEventListener(listItems.concat(sortableElement), 'dragover', onDragOverEnter);
1270
- addEventListener(listItems.concat(sortableElement), 'dragenter', onDragOverEnter);
1271
- });
1272
- return sortableElements;
1273
- }
1274
- sortable.destroy = function (sortableElement) {
1275
- _destroySortable(sortableElement);
1276
- };
1277
- sortable.enable = function (sortableElement) {
1278
- _enableSortable(sortableElement);
1279
- };
1280
- sortable.disable = function (sortableElement) {
1281
- _disableSortable(sortableElement);
1282
- };
1283
- /* START.TESTS_ONLY */
1284
- sortable.__testing = {
1285
- // add internal methods here for testing purposes
1286
- _data: addData,
1287
- _removeItemEvents: _removeItemEvents,
1288
- _removeItemData: _removeItemData,
1289
- _removeSortableData: _removeSortableData,
1290
- _removeContainerEvents: _removeContainerEvents
1291
- };
1292
-
1293
- return sortable;
1294
-
1295
- }());