sql-jarvis 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +25 -1
  3. data/LICENSE.txt +1 -1
  4. data/README.md +153 -52
  5. data/app/assets/fonts/blazer/glyphicons-halflings-regular.eot +0 -0
  6. data/app/assets/fonts/blazer/glyphicons-halflings-regular.svg +0 -0
  7. data/app/assets/fonts/blazer/glyphicons-halflings-regular.ttf +0 -0
  8. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff +0 -0
  9. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff2 +0 -0
  10. data/app/assets/images/blazer/favicon.png +0 -0
  11. data/app/assets/javascripts/blazer/Chart.js +4195 -3884
  12. data/app/assets/javascripts/blazer/Sortable.js +1493 -1097
  13. data/app/assets/javascripts/blazer/ace/ace.js +21294 -4
  14. data/app/assets/javascripts/blazer/ace/ext-language_tools.js +1991 -3
  15. data/app/assets/javascripts/blazer/ace/mode-sql.js +110 -1
  16. data/app/assets/javascripts/blazer/ace/snippets/sql.js +40 -1
  17. data/app/assets/javascripts/blazer/ace/snippets/text.js +14 -1
  18. data/app/assets/javascripts/blazer/ace/theme-twilight.js +116 -1
  19. data/app/assets/javascripts/blazer/application.js +4 -3
  20. data/app/assets/javascripts/blazer/bootstrap.js +623 -612
  21. data/app/assets/javascripts/blazer/chartkick.js +1769 -1248
  22. data/app/assets/javascripts/blazer/daterangepicker.js +263 -115
  23. data/app/assets/javascripts/blazer/highlight.min.js +3 -0
  24. data/app/assets/javascripts/blazer/{jquery_ujs.js → jquery-ujs.js} +161 -75
  25. data/app/assets/javascripts/blazer/jquery.js +9506 -9450
  26. data/app/assets/javascripts/blazer/jquery.stickytableheaders.js +321 -259
  27. data/app/assets/javascripts/blazer/moment-timezone-with-data.js +1212 -0
  28. data/app/assets/javascripts/blazer/queries.js +1 -1
  29. data/app/assets/javascripts/blazer/routes.js +3 -0
  30. data/app/assets/javascripts/blazer/selectize.js +3828 -3604
  31. data/app/assets/javascripts/blazer/stupidtable.js +255 -88
  32. data/app/assets/javascripts/blazer/vue.js +8015 -4583
  33. data/app/assets/stylesheets/blazer/application.css +41 -5
  34. data/app/assets/stylesheets/blazer/bootstrap.css.erb +879 -325
  35. data/app/assets/stylesheets/blazer/daterangepicker.css +269 -0
  36. data/app/assets/stylesheets/blazer/selectize.default.css +26 -10
  37. data/app/controllers/blazer/base_controller.rb +7 -0
  38. data/app/controllers/blazer/checks_controller.rb +1 -1
  39. data/app/controllers/blazer/dashboards_controller.rb +0 -4
  40. data/app/controllers/blazer/queries_controller.rb +20 -12
  41. data/app/helpers/blazer/base_helper.rb +1 -1
  42. data/app/mailers/blazer/slack_notifier.rb +76 -0
  43. data/app/models/blazer/check.rb +9 -0
  44. data/app/views/blazer/_nav.html.erb +0 -1
  45. data/app/views/blazer/_variables.html.erb +41 -19
  46. data/app/views/blazer/checks/_form.html.erb +16 -8
  47. data/app/views/blazer/checks/edit.html.erb +2 -0
  48. data/app/views/blazer/checks/index.html.erb +33 -4
  49. data/app/views/blazer/checks/new.html.erb +2 -0
  50. data/app/views/blazer/dashboards/_form.html.erb +4 -4
  51. data/app/views/blazer/dashboards/edit.html.erb +2 -0
  52. data/app/views/blazer/dashboards/new.html.erb +2 -0
  53. data/app/views/blazer/dashboards/show.html.erb +7 -3
  54. data/app/views/blazer/queries/_form.html.erb +11 -6
  55. data/app/views/blazer/queries/docs.html.erb +131 -0
  56. data/app/views/blazer/queries/home.html.erb +12 -3
  57. data/app/views/blazer/queries/run.html.erb +36 -6
  58. data/app/views/blazer/queries/schema.html.erb +46 -8
  59. data/app/views/blazer/queries/show.html.erb +4 -4
  60. data/app/views/layouts/blazer/application.html.erb +3 -3
  61. data/config/routes.rb +5 -1
  62. data/lib/blazer.rb +32 -13
  63. data/lib/blazer/adapters/athena_adapter.rb +1 -1
  64. data/lib/blazer/adapters/elasticsearch_adapter.rb +14 -17
  65. data/lib/blazer/adapters/mongodb_adapter.rb +1 -1
  66. data/lib/blazer/adapters/sql_adapter.rb +7 -1
  67. data/lib/blazer/engine.rb +4 -0
  68. data/lib/blazer/result.rb +62 -29
  69. data/lib/blazer/run_statement_job.rb +6 -9
  70. data/lib/blazer/version.rb +1 -1
  71. data/lib/generators/blazer/templates/config.yml.tt +13 -2
  72. data/lib/generators/blazer/templates/install.rb.tt +1 -0
  73. data/lib/tasks/blazer.rake +1 -0
  74. metadata +33 -37
  75. data/.gitattributes +0 -1
  76. data/.github/ISSUE_TEMPLATE.md +0 -7
  77. data/.gitignore +0 -14
  78. data/Gemfile +0 -7
  79. data/Rakefile +0 -1
  80. data/app/assets/javascripts/blazer/highlight.pack.js +0 -1
  81. data/app/assets/javascripts/blazer/moment-timezone.js +0 -1007
  82. data/app/assets/stylesheets/blazer/daterangepicker-bs3.css +0 -375
  83. data/blazer.gemspec +0 -30
@@ -1,1144 +1,1540 @@
1
1
  /**!
2
2
  * Sortable
3
- * @author RubaXa <trash@rubaxa.org>
3
+ * @author RubaXa <trash@rubaxa.org>
4
4
  * @license MIT
5
5
  */
6
6
 
7
+ (function sortableModule(factory) {
8
+ "use strict";
9
+
10
+ if (typeof define === "function" && define.amd) {
11
+ define(factory);
12
+ }
13
+ else if (typeof module != "undefined" && typeof module.exports != "undefined") {
14
+ module.exports = factory();
15
+ }
16
+ else {
17
+ /* jshint sub:true */
18
+ window["Sortable"] = factory();
19
+ }
20
+ })(function sortableFactory() {
21
+ "use strict";
22
+
23
+ if (typeof window === "undefined" || !window.document) {
24
+ return function sortableError() {
25
+ throw new Error("Sortable.js requires a window with a document");
26
+ };
27
+ }
28
+
29
+ var dragEl,
30
+ parentEl,
31
+ ghostEl,
32
+ cloneEl,
33
+ rootEl,
34
+ nextEl,
35
+ lastDownEl,
36
+
37
+ scrollEl,
38
+ scrollParentEl,
39
+ scrollCustomFn,
40
+
41
+ lastEl,
42
+ lastCSS,
43
+ lastParentCSS,
44
+
45
+ oldIndex,
46
+ newIndex,
47
+
48
+ activeGroup,
49
+ putSortable,
50
+
51
+ autoScroll = {},
52
+
53
+ tapEvt,
54
+ touchEvt,
55
+
56
+ moved,
57
+
58
+ /** @const */
59
+ R_SPACE = /\s+/g,
60
+ R_FLOAT = /left|right|inline/,
61
+
62
+ expando = 'Sortable' + (new Date).getTime(),
63
+
64
+ win = window,
65
+ document = win.document,
66
+ parseInt = win.parseInt,
67
+ setTimeout = win.setTimeout,
68
+
69
+ $ = win.jQuery || win.Zepto,
70
+ Polymer = win.Polymer,
71
+
72
+ captureMode = false,
73
+ passiveMode = false,
74
+
75
+ supportDraggable = ('draggable' in document.createElement('div')),
76
+ supportCssPointerEvents = (function (el) {
77
+ // false when IE11
78
+ if (!!navigator.userAgent.match(/(?:Trident.*rv[ :]?11\.|msie)/i)) {
79
+ return false;
80
+ }
81
+ el = document.createElement('x');
82
+ el.style.cssText = 'pointer-events:auto';
83
+ return el.style.pointerEvents === 'auto';
84
+ })(),
85
+
86
+ _silent = false,
87
+
88
+ abs = Math.abs,
89
+ min = Math.min,
90
+
91
+ savedInputChecked = [],
92
+ touchDragOverListeners = [],
93
+
94
+ _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
95
+ // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
96
+ if (rootEl && options.scroll) {
97
+ var _this = rootEl[expando],
98
+ el,
99
+ rect,
100
+ sens = options.scrollSensitivity,
101
+ speed = options.scrollSpeed,
102
+
103
+ x = evt.clientX,
104
+ y = evt.clientY,
105
+
106
+ winWidth = window.innerWidth,
107
+ winHeight = window.innerHeight,
108
+
109
+ vx,
110
+ vy,
111
+
112
+ scrollOffsetX,
113
+ scrollOffsetY
114
+ ;
115
+
116
+ // Delect scrollEl
117
+ if (scrollParentEl !== rootEl) {
118
+ scrollEl = options.scroll;
119
+ scrollParentEl = rootEl;
120
+ scrollCustomFn = options.scrollFn;
121
+
122
+ if (scrollEl === true) {
123
+ scrollEl = rootEl;
124
+
125
+ do {
126
+ if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
127
+ (scrollEl.offsetHeight < scrollEl.scrollHeight)
128
+ ) {
129
+ break;
130
+ }
131
+ /* jshint boss:true */
132
+ } while (scrollEl = scrollEl.parentNode);
133
+ }
134
+ }
135
+
136
+ if (scrollEl) {
137
+ el = scrollEl;
138
+ rect = scrollEl.getBoundingClientRect();
139
+ vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
140
+ vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
141
+ }
142
+
143
+
144
+ if (!(vx || vy)) {
145
+ vx = (winWidth - x <= sens) - (x <= sens);
146
+ vy = (winHeight - y <= sens) - (y <= sens);
147
+
148
+ /* jshint expr:true */
149
+ (vx || vy) && (el = win);
150
+ }
151
+
152
+
153
+ if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
154
+ autoScroll.el = el;
155
+ autoScroll.vx = vx;
156
+ autoScroll.vy = vy;
157
+
158
+ clearInterval(autoScroll.pid);
159
+
160
+ if (el) {
161
+ autoScroll.pid = setInterval(function () {
162
+ scrollOffsetY = vy ? vy * speed : 0;
163
+ scrollOffsetX = vx ? vx * speed : 0;
164
+
165
+ if ('function' === typeof(scrollCustomFn)) {
166
+ return scrollCustomFn.call(_this, scrollOffsetX, scrollOffsetY, evt);
167
+ }
168
+
169
+ if (el === win) {
170
+ win.scrollTo(win.pageXOffset + scrollOffsetX, win.pageYOffset + scrollOffsetY);
171
+ } else {
172
+ el.scrollTop += scrollOffsetY;
173
+ el.scrollLeft += scrollOffsetX;
174
+ }
175
+ }, 24);
176
+ }
177
+ }
178
+ }
179
+ }, 30),
180
+
181
+ _prepareGroup = function (options) {
182
+ function toFn(value, pull) {
183
+ if (value === void 0 || value === true) {
184
+ value = group.name;
185
+ }
186
+
187
+ if (typeof value === 'function') {
188
+ return value;
189
+ } else {
190
+ return function (to, from) {
191
+ var fromGroup = from.options.group.name;
192
+
193
+ return pull
194
+ ? value
195
+ : value && (value.join
196
+ ? value.indexOf(fromGroup) > -1
197
+ : (fromGroup == value)
198
+ );
199
+ };
200
+ }
201
+ }
202
+
203
+ var group = {};
204
+ var originalGroup = options.group;
205
+
206
+ if (!originalGroup || typeof originalGroup != 'object') {
207
+ originalGroup = {name: originalGroup};
208
+ }
209
+
210
+ group.name = originalGroup.name;
211
+ group.checkPull = toFn(originalGroup.pull, true);
212
+ group.checkPut = toFn(originalGroup.put);
213
+ group.revertClone = originalGroup.revertClone;
214
+
215
+ options.group = group;
216
+ }
217
+ ;
218
+
219
+ // Detect support a passive mode
220
+ try {
221
+ window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
222
+ get: function () {
223
+ // `false`, because everything starts to work incorrectly and instead of d'n'd,
224
+ // begins the page has scrolled.
225
+ passiveMode = false;
226
+ captureMode = {
227
+ capture: false,
228
+ passive: passiveMode
229
+ };
230
+ }
231
+ }));
232
+ } catch (err) {}
233
+
234
+ /**
235
+ * @class Sortable
236
+ * @param {HTMLElement} el
237
+ * @param {Object} [options]
238
+ */
239
+ function Sortable(el, options) {
240
+ if (!(el && el.nodeType && el.nodeType === 1)) {
241
+ throw 'Sortable: `el` must be HTMLElement, and not ' + {}.toString.call(el);
242
+ }
243
+
244
+ this.el = el; // root element
245
+ this.options = options = _extend({}, options);
246
+
247
+
248
+ // Export instance
249
+ el[expando] = this;
250
+
251
+ // Default options
252
+ var defaults = {
253
+ group: Math.random(),
254
+ sort: true,
255
+ disabled: false,
256
+ store: null,
257
+ handle: null,
258
+ scroll: true,
259
+ scrollSensitivity: 30,
260
+ scrollSpeed: 10,
261
+ draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
262
+ ghostClass: 'sortable-ghost',
263
+ chosenClass: 'sortable-chosen',
264
+ dragClass: 'sortable-drag',
265
+ ignore: 'a, img',
266
+ filter: null,
267
+ preventOnFilter: true,
268
+ animation: 0,
269
+ setData: function (dataTransfer, dragEl) {
270
+ dataTransfer.setData('Text', dragEl.textContent);
271
+ },
272
+ dropBubble: false,
273
+ dragoverBubble: false,
274
+ dataIdAttr: 'data-id',
275
+ delay: 0,
276
+ forceFallback: false,
277
+ fallbackClass: 'sortable-fallback',
278
+ fallbackOnBody: false,
279
+ fallbackTolerance: 0,
280
+ fallbackOffset: {x: 0, y: 0},
281
+ supportPointer: Sortable.supportPointer !== false
282
+ };
283
+
284
+
285
+ // Set default options
286
+ for (var name in defaults) {
287
+ !(name in options) && (options[name] = defaults[name]);
288
+ }
289
+
290
+ _prepareGroup(options);
291
+
292
+ // Bind all private methods
293
+ for (var fn in this) {
294
+ if (fn.charAt(0) === '_' && typeof this[fn] === 'function') {
295
+ this[fn] = this[fn].bind(this);
296
+ }
297
+ }
298
+
299
+ // Setup drag mode
300
+ this.nativeDraggable = options.forceFallback ? false : supportDraggable;
301
+
302
+ // Bind events
303
+ _on(el, 'mousedown', this._onTapStart);
304
+ _on(el, 'touchstart', this._onTapStart);
305
+ options.supportPointer && _on(el, 'pointerdown', this._onTapStart);
306
+
307
+ if (this.nativeDraggable) {
308
+ _on(el, 'dragover', this);
309
+ _on(el, 'dragenter', this);
310
+ }
311
+
312
+ touchDragOverListeners.push(this._onDragOver);
313
+
314
+ // Restore sorting
315
+ options.store && this.sort(options.store.get(this));
316
+ }
317
+
318
+
319
+ Sortable.prototype = /** @lends Sortable.prototype */ {
320
+ constructor: Sortable,
321
+
322
+ _onTapStart: function (/** Event|TouchEvent */evt) {
323
+ var _this = this,
324
+ el = this.el,
325
+ options = this.options,
326
+ preventOnFilter = options.preventOnFilter,
327
+ type = evt.type,
328
+ touch = evt.touches && evt.touches[0],
329
+ target = (touch || evt).target,
330
+ originalTarget = evt.target.shadowRoot && (evt.path && evt.path[0]) || target,
331
+ filter = options.filter,
332
+ startIndex;
333
+
334
+ _saveInputCheckedState(el);
335
+
336
+
337
+ // Don't trigger start event when an element is been dragged, otherwise the evt.oldindex always wrong when set option.group.
338
+ if (dragEl) {
339
+ return;
340
+ }
341
+
342
+ if (/mousedown|pointerdown/.test(type) && evt.button !== 0 || options.disabled) {
343
+ return; // only left button or enabled
344
+ }
345
+
346
+ // cancel dnd if original target is content editable
347
+ if (originalTarget.isContentEditable) {
348
+ return;
349
+ }
350
+
351
+ target = _closest(target, options.draggable, el);
352
+
353
+ if (!target) {
354
+ return;
355
+ }
356
+
357
+ if (lastDownEl === target) {
358
+ // Ignoring duplicate `down`
359
+ return;
360
+ }
361
+
362
+ // Get the index of the dragged element within its parent
363
+ startIndex = _index(target, options.draggable);
364
+
365
+ // Check filter
366
+ if (typeof filter === 'function') {
367
+ if (filter.call(this, evt, target, this)) {
368
+ _dispatchEvent(_this, originalTarget, 'filter', target, el, el, startIndex);
369
+ preventOnFilter && evt.preventDefault();
370
+ return; // cancel dnd
371
+ }
372
+ }
373
+ else if (filter) {
374
+ filter = filter.split(',').some(function (criteria) {
375
+ criteria = _closest(originalTarget, criteria.trim(), el);
376
+
377
+ if (criteria) {
378
+ _dispatchEvent(_this, criteria, 'filter', target, el, el, startIndex);
379
+ return true;
380
+ }
381
+ });
382
+
383
+ if (filter) {
384
+ preventOnFilter && evt.preventDefault();
385
+ return; // cancel dnd
386
+ }
387
+ }
388
+
389
+ if (options.handle && !_closest(originalTarget, options.handle, el)) {
390
+ return;
391
+ }
392
+
393
+ // Prepare `dragstart`
394
+ this._prepareDragStart(evt, touch, target, startIndex);
395
+ },
396
+
397
+ _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target, /** Number */startIndex) {
398
+ var _this = this,
399
+ el = _this.el,
400
+ options = _this.options,
401
+ ownerDocument = el.ownerDocument,
402
+ dragStartFn;
403
+
404
+ if (target && !dragEl && (target.parentNode === el)) {
405
+ tapEvt = evt;
406
+
407
+ rootEl = el;
408
+ dragEl = target;
409
+ parentEl = dragEl.parentNode;
410
+ nextEl = dragEl.nextSibling;
411
+ lastDownEl = target;
412
+ activeGroup = options.group;
413
+ oldIndex = startIndex;
414
+
415
+ this._lastX = (touch || evt).clientX;
416
+ this._lastY = (touch || evt).clientY;
417
+
418
+ dragEl.style['will-change'] = 'all';
419
+
420
+ dragStartFn = function () {
421
+ // Delayed drag has been triggered
422
+ // we can re-enable the events: touchmove/mousemove
423
+ _this._disableDelayedDrag();
424
+
425
+ // Make the element draggable
426
+ dragEl.draggable = _this.nativeDraggable;
427
+
428
+ // Chosen item
429
+ _toggleClass(dragEl, options.chosenClass, true);
430
+
431
+ // Bind the events: dragstart/dragend
432
+ _this._triggerDragStart(evt, touch);
433
+
434
+ // Drag start event
435
+ _dispatchEvent(_this, rootEl, 'choose', dragEl, rootEl, rootEl, oldIndex);
436
+ };
437
+
438
+ // Disable "draggable"
439
+ options.ignore.split(',').forEach(function (criteria) {
440
+ _find(dragEl, criteria.trim(), _disableDraggable);
441
+ });
442
+
443
+ _on(ownerDocument, 'mouseup', _this._onDrop);
444
+ _on(ownerDocument, 'touchend', _this._onDrop);
445
+ _on(ownerDocument, 'touchcancel', _this._onDrop);
446
+ _on(ownerDocument, 'selectstart', _this);
447
+ options.supportPointer && _on(ownerDocument, 'pointercancel', _this._onDrop);
448
+
449
+ if (options.delay) {
450
+ // If the user moves the pointer or let go the click or touch
451
+ // before the delay has been reached:
452
+ // disable the delayed drag
453
+ _on(ownerDocument, 'mouseup', _this._disableDelayedDrag);
454
+ _on(ownerDocument, 'touchend', _this._disableDelayedDrag);
455
+ _on(ownerDocument, 'touchcancel', _this._disableDelayedDrag);
456
+ _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
457
+ _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
458
+ options.supportPointer && _on(ownerDocument, 'pointermove', _this._disableDelayedDrag);
459
+
460
+ _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
461
+ } else {
462
+ dragStartFn();
463
+ }
464
+
465
+
466
+ }
467
+ },
468
+
469
+ _disableDelayedDrag: function () {
470
+ var ownerDocument = this.el.ownerDocument;
471
+
472
+ clearTimeout(this._dragStartTimer);
473
+ _off(ownerDocument, 'mouseup', this._disableDelayedDrag);
474
+ _off(ownerDocument, 'touchend', this._disableDelayedDrag);
475
+ _off(ownerDocument, 'touchcancel', this._disableDelayedDrag);
476
+ _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
477
+ _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
478
+ _off(ownerDocument, 'pointermove', this._disableDelayedDrag);
479
+ },
480
+
481
+ _triggerDragStart: function (/** Event */evt, /** Touch */touch) {
482
+ touch = touch || (evt.pointerType == 'touch' ? evt : null);
483
+
484
+ if (touch) {
485
+ // Touch device support
486
+ tapEvt = {
487
+ target: dragEl,
488
+ clientX: touch.clientX,
489
+ clientY: touch.clientY
490
+ };
491
+
492
+ this._onDragStart(tapEvt, 'touch');
493
+ }
494
+ else if (!this.nativeDraggable) {
495
+ this._onDragStart(tapEvt, true);
496
+ }
497
+ else {
498
+ _on(dragEl, 'dragend', this);
499
+ _on(rootEl, 'dragstart', this._onDragStart);
500
+ }
501
+
502
+ try {
503
+ if (document.selection) {
504
+ // Timeout neccessary for IE9
505
+ _nextTick(function () {
506
+ document.selection.empty();
507
+ });
508
+ } else {
509
+ window.getSelection().removeAllRanges();
510
+ }
511
+ } catch (err) {
512
+ }
513
+ },
514
+
515
+ _dragStarted: function () {
516
+ if (rootEl && dragEl) {
517
+ var options = this.options;
518
+
519
+ // Apply effect
520
+ _toggleClass(dragEl, options.ghostClass, true);
521
+ _toggleClass(dragEl, options.dragClass, false);
522
+
523
+ Sortable.active = this;
524
+
525
+ // Drag start event
526
+ _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, rootEl, oldIndex);
527
+ } else {
528
+ this._nulling();
529
+ }
530
+ },
531
+
532
+ _emulateDragOver: function () {
533
+ if (touchEvt) {
534
+ if (this._lastX === touchEvt.clientX && this._lastY === touchEvt.clientY) {
535
+ return;
536
+ }
537
+
538
+ this._lastX = touchEvt.clientX;
539
+ this._lastY = touchEvt.clientY;
540
+
541
+ if (!supportCssPointerEvents) {
542
+ _css(ghostEl, 'display', 'none');
543
+ }
544
+
545
+ var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
546
+ var parent = target;
547
+ var i = touchDragOverListeners.length;
548
+
549
+ if (target && target.shadowRoot) {
550
+ target = target.shadowRoot.elementFromPoint(touchEvt.clientX, touchEvt.clientY);
551
+ parent = target;
552
+ }
553
+
554
+ if (parent) {
555
+ do {
556
+ if (parent[expando]) {
557
+ while (i--) {
558
+ touchDragOverListeners[i]({
559
+ clientX: touchEvt.clientX,
560
+ clientY: touchEvt.clientY,
561
+ target: target,
562
+ rootEl: parent
563
+ });
564
+ }
565
+
566
+ break;
567
+ }
568
+
569
+ target = parent; // store last element
570
+ }
571
+ /* jshint boss:true */
572
+ while (parent = parent.parentNode);
573
+ }
574
+
575
+ if (!supportCssPointerEvents) {
576
+ _css(ghostEl, 'display', '');
577
+ }
578
+ }
579
+ },
580
+
581
+
582
+ _onTouchMove: function (/**TouchEvent*/evt) {
583
+ if (tapEvt) {
584
+ var options = this.options,
585
+ fallbackTolerance = options.fallbackTolerance,
586
+ fallbackOffset = options.fallbackOffset,
587
+ touch = evt.touches ? evt.touches[0] : evt,
588
+ dx = (touch.clientX - tapEvt.clientX) + fallbackOffset.x,
589
+ dy = (touch.clientY - tapEvt.clientY) + fallbackOffset.y,
590
+ translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
591
+
592
+ // only set the status to dragging, when we are actually dragging
593
+ if (!Sortable.active) {
594
+ if (fallbackTolerance &&
595
+ min(abs(touch.clientX - this._lastX), abs(touch.clientY - this._lastY)) < fallbackTolerance
596
+ ) {
597
+ return;
598
+ }
599
+
600
+ this._dragStarted();
601
+ }
602
+
603
+ // as well as creating the ghost element on the document body
604
+ this._appendGhost();
605
+
606
+ moved = true;
607
+ touchEvt = touch;
608
+
609
+ _css(ghostEl, 'webkitTransform', translate3d);
610
+ _css(ghostEl, 'mozTransform', translate3d);
611
+ _css(ghostEl, 'msTransform', translate3d);
612
+ _css(ghostEl, 'transform', translate3d);
613
+
614
+ evt.preventDefault();
615
+ }
616
+ },
617
+
618
+ _appendGhost: function () {
619
+ if (!ghostEl) {
620
+ var rect = dragEl.getBoundingClientRect(),
621
+ css = _css(dragEl),
622
+ options = this.options,
623
+ ghostRect;
624
+
625
+ ghostEl = dragEl.cloneNode(true);
626
+
627
+ _toggleClass(ghostEl, options.ghostClass, false);
628
+ _toggleClass(ghostEl, options.fallbackClass, true);
629
+ _toggleClass(ghostEl, options.dragClass, true);
630
+
631
+ _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
632
+ _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
633
+ _css(ghostEl, 'width', rect.width);
634
+ _css(ghostEl, 'height', rect.height);
635
+ _css(ghostEl, 'opacity', '0.8');
636
+ _css(ghostEl, 'position', 'fixed');
637
+ _css(ghostEl, 'zIndex', '100000');
638
+ _css(ghostEl, 'pointerEvents', 'none');
639
+
640
+ options.fallbackOnBody && document.body.appendChild(ghostEl) || rootEl.appendChild(ghostEl);
641
+
642
+ // Fixing dimensions.
643
+ ghostRect = ghostEl.getBoundingClientRect();
644
+ _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
645
+ _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
646
+ }
647
+ },
648
+
649
+ _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
650
+ var _this = this;
651
+ var dataTransfer = evt.dataTransfer;
652
+ var options = _this.options;
653
+
654
+ _this._offUpEvents();
655
+
656
+ if (activeGroup.checkPull(_this, _this, dragEl, evt)) {
657
+ cloneEl = _clone(dragEl);
658
+
659
+ cloneEl.draggable = false;
660
+ cloneEl.style['will-change'] = '';
661
+
662
+ _css(cloneEl, 'display', 'none');
663
+ _toggleClass(cloneEl, _this.options.chosenClass, false);
664
+
665
+ // #1143: IFrame support workaround
666
+ _this._cloneId = _nextTick(function () {
667
+ rootEl.insertBefore(cloneEl, dragEl);
668
+ _dispatchEvent(_this, rootEl, 'clone', dragEl);
669
+ });
670
+ }
671
+
672
+ _toggleClass(dragEl, options.dragClass, true);
673
+
674
+ if (useFallback) {
675
+ if (useFallback === 'touch') {
676
+ // Bind touch events
677
+ _on(document, 'touchmove', _this._onTouchMove);
678
+ _on(document, 'touchend', _this._onDrop);
679
+ _on(document, 'touchcancel', _this._onDrop);
680
+
681
+ if (options.supportPointer) {
682
+ _on(document, 'pointermove', _this._onTouchMove);
683
+ _on(document, 'pointerup', _this._onDrop);
684
+ }
685
+ } else {
686
+ // Old brwoser
687
+ _on(document, 'mousemove', _this._onTouchMove);
688
+ _on(document, 'mouseup', _this._onDrop);
689
+ }
690
+
691
+ _this._loopId = setInterval(_this._emulateDragOver, 50);
692
+ }
693
+ else {
694
+ if (dataTransfer) {
695
+ dataTransfer.effectAllowed = 'move';
696
+ options.setData && options.setData.call(_this, dataTransfer, dragEl);
697
+ }
698
+
699
+ _on(document, 'drop', _this);
700
+
701
+ // #1143: Бывает элемент с IFrame внутри блокирует `drop`,
702
+ // поэтому если вызвался `mouseover`, значит надо отменять весь d'n'd.
703
+ // Breaking Chrome 62+
704
+ // _on(document, 'mouseover', _this);
705
+
706
+ _this._dragStartId = _nextTick(_this._dragStarted);
707
+ }
708
+ },
709
+
710
+ _onDragOver: function (/**Event*/evt) {
711
+ var el = this.el,
712
+ target,
713
+ dragRect,
714
+ targetRect,
715
+ revert,
716
+ options = this.options,
717
+ group = options.group,
718
+ activeSortable = Sortable.active,
719
+ isOwner = (activeGroup === group),
720
+ isMovingBetweenSortable = false,
721
+ canSort = options.sort;
722
+
723
+ if (evt.preventDefault !== void 0) {
724
+ evt.preventDefault();
725
+ !options.dragoverBubble && evt.stopPropagation();
726
+ }
727
+
728
+ if (dragEl.animated) {
729
+ return;
730
+ }
731
+
732
+ moved = true;
733
+
734
+ if (activeSortable && !options.disabled &&
735
+ (isOwner
736
+ ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
737
+ : (
738
+ putSortable === this ||
739
+ (
740
+ (activeSortable.lastPullMode = activeGroup.checkPull(this, activeSortable, dragEl, evt)) &&
741
+ group.checkPut(this, activeSortable, dragEl, evt)
742
+ )
743
+ )
744
+ ) &&
745
+ (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
746
+ ) {
747
+ // Smart auto-scrolling
748
+ _autoScroll(evt, options, this.el);
749
+
750
+ if (_silent) {
751
+ return;
752
+ }
753
+
754
+ target = _closest(evt.target, options.draggable, el);
755
+ dragRect = dragEl.getBoundingClientRect();
756
+
757
+ if (putSortable !== this) {
758
+ putSortable = this;
759
+ isMovingBetweenSortable = true;
760
+ }
761
+
762
+ if (revert) {
763
+ _cloneHide(activeSortable, true);
764
+ parentEl = rootEl; // actualization
765
+
766
+ if (cloneEl || nextEl) {
767
+ rootEl.insertBefore(dragEl, cloneEl || nextEl);
768
+ }
769
+ else if (!canSort) {
770
+ rootEl.appendChild(dragEl);
771
+ }
772
+
773
+ return;
774
+ }
775
+
776
+
777
+ if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
778
+ (el === evt.target) && (_ghostIsLast(el, evt))
779
+ ) {
780
+ //assign target only if condition is true
781
+ if (el.children.length !== 0 && el.children[0] !== ghostEl && el === evt.target) {
782
+ target = el.lastElementChild;
783
+ }
784
+
785
+ if (target) {
786
+ if (target.animated) {
787
+ return;
788
+ }
789
+
790
+ targetRect = target.getBoundingClientRect();
791
+ }
792
+
793
+ _cloneHide(activeSortable, isOwner);
794
+
795
+ if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt) !== false) {
796
+ if (!dragEl.contains(el)) {
797
+ el.appendChild(dragEl);
798
+ parentEl = el; // actualization
799
+ }
800
+
801
+ this._animate(dragRect, dragEl);
802
+ target && this._animate(targetRect, target);
803
+ }
804
+ }
805
+ else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
806
+ if (lastEl !== target) {
807
+ lastEl = target;
808
+ lastCSS = _css(target);
809
+ lastParentCSS = _css(target.parentNode);
810
+ }
811
+
812
+ targetRect = target.getBoundingClientRect();
813
+
814
+ var width = targetRect.right - targetRect.left,
815
+ height = targetRect.bottom - targetRect.top,
816
+ floating = R_FLOAT.test(lastCSS.cssFloat + lastCSS.display)
817
+ || (lastParentCSS.display == 'flex' && lastParentCSS['flex-direction'].indexOf('row') === 0),
818
+ isWide = (target.offsetWidth > dragEl.offsetWidth),
819
+ isLong = (target.offsetHeight > dragEl.offsetHeight),
820
+ halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
821
+ nextSibling = target.nextElementSibling,
822
+ after = false
823
+ ;
824
+
825
+ if (floating) {
826
+ var elTop = dragEl.offsetTop,
827
+ tgTop = target.offsetTop;
828
+
829
+ if (elTop === tgTop) {
830
+ after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
831
+ }
832
+ else if (target.previousElementSibling === dragEl || dragEl.previousElementSibling === target) {
833
+ after = (evt.clientY - targetRect.top) / height > 0.5;
834
+ } else {
835
+ after = tgTop > elTop;
836
+ }
837
+ } else if (!isMovingBetweenSortable) {
838
+ after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
839
+ }
840
+
841
+ var moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect, evt, after);
842
+
843
+ if (moveVector !== false) {
844
+ if (moveVector === 1 || moveVector === -1) {
845
+ after = (moveVector === 1);
846
+ }
847
+
848
+ _silent = true;
849
+ setTimeout(_unsilent, 30);
850
+
851
+ _cloneHide(activeSortable, isOwner);
852
+
853
+ if (!dragEl.contains(el)) {
854
+ if (after && !nextSibling) {
855
+ el.appendChild(dragEl);
856
+ } else {
857
+ target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
858
+ }
859
+ }
860
+
861
+ parentEl = dragEl.parentNode; // actualization
862
+
863
+ this._animate(dragRect, dragEl);
864
+ this._animate(targetRect, target);
865
+ }
866
+ }
867
+ }
868
+ },
869
+
870
+ _animate: function (prevRect, target) {
871
+ var ms = this.options.animation;
872
+
873
+ if (ms) {
874
+ var currentRect = target.getBoundingClientRect();
875
+
876
+ if (prevRect.nodeType === 1) {
877
+ prevRect = prevRect.getBoundingClientRect();
878
+ }
879
+
880
+ _css(target, 'transition', 'none');
881
+ _css(target, 'transform', 'translate3d('
882
+ + (prevRect.left - currentRect.left) + 'px,'
883
+ + (prevRect.top - currentRect.top) + 'px,0)'
884
+ );
885
+
886
+ target.offsetWidth; // repaint
887
+
888
+ _css(target, 'transition', 'all ' + ms + 'ms');
889
+ _css(target, 'transform', 'translate3d(0,0,0)');
890
+
891
+ clearTimeout(target.animated);
892
+ target.animated = setTimeout(function () {
893
+ _css(target, 'transition', '');
894
+ _css(target, 'transform', '');
895
+ target.animated = false;
896
+ }, ms);
897
+ }
898
+ },
899
+
900
+ _offUpEvents: function () {
901
+ var ownerDocument = this.el.ownerDocument;
902
+
903
+ _off(document, 'touchmove', this._onTouchMove);
904
+ _off(document, 'pointermove', this._onTouchMove);
905
+ _off(ownerDocument, 'mouseup', this._onDrop);
906
+ _off(ownerDocument, 'touchend', this._onDrop);
907
+ _off(ownerDocument, 'pointerup', this._onDrop);
908
+ _off(ownerDocument, 'touchcancel', this._onDrop);
909
+ _off(ownerDocument, 'pointercancel', this._onDrop);
910
+ _off(ownerDocument, 'selectstart', this);
911
+ },
912
+
913
+ _onDrop: function (/**Event*/evt) {
914
+ var el = this.el,
915
+ options = this.options;
916
+
917
+ clearInterval(this._loopId);
918
+ clearInterval(autoScroll.pid);
919
+ clearTimeout(this._dragStartTimer);
920
+
921
+ _cancelNextTick(this._cloneId);
922
+ _cancelNextTick(this._dragStartId);
923
+
924
+ // Unbind events
925
+ _off(document, 'mouseover', this);
926
+ _off(document, 'mousemove', this._onTouchMove);
927
+
928
+ if (this.nativeDraggable) {
929
+ _off(document, 'drop', this);
930
+ _off(el, 'dragstart', this._onDragStart);
931
+ }
932
+
933
+ this._offUpEvents();
934
+
935
+ if (evt) {
936
+ if (moved) {
937
+ evt.preventDefault();
938
+ !options.dropBubble && evt.stopPropagation();
939
+ }
940
+
941
+ ghostEl && ghostEl.parentNode && ghostEl.parentNode.removeChild(ghostEl);
942
+
943
+ if (rootEl === parentEl || Sortable.active.lastPullMode !== 'clone') {
944
+ // Remove clone
945
+ cloneEl && cloneEl.parentNode && cloneEl.parentNode.removeChild(cloneEl);
946
+ }
947
+
948
+ if (dragEl) {
949
+ if (this.nativeDraggable) {
950
+ _off(dragEl, 'dragend', this);
951
+ }
952
+
953
+ _disableDraggable(dragEl);
954
+ dragEl.style['will-change'] = '';
955
+
956
+ // Remove class's
957
+ _toggleClass(dragEl, this.options.ghostClass, false);
958
+ _toggleClass(dragEl, this.options.chosenClass, false);
959
+
960
+ // Drag stop event
961
+ _dispatchEvent(this, rootEl, 'unchoose', dragEl, parentEl, rootEl, oldIndex);
962
+
963
+ if (rootEl !== parentEl) {
964
+ newIndex = _index(dragEl, options.draggable);
965
+
966
+ if (newIndex >= 0) {
967
+ // Add event
968
+ _dispatchEvent(null, parentEl, 'add', dragEl, parentEl, rootEl, oldIndex, newIndex);
969
+
970
+ // Remove event
971
+ _dispatchEvent(this, rootEl, 'remove', dragEl, parentEl, rootEl, oldIndex, newIndex);
972
+
973
+ // drag from one list and drop into another
974
+ _dispatchEvent(null, parentEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
975
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
976
+ }
977
+ }
978
+ else {
979
+ if (dragEl.nextSibling !== nextEl) {
980
+ // Get the index of the dragged element within its parent
981
+ newIndex = _index(dragEl, options.draggable);
982
+
983
+ if (newIndex >= 0) {
984
+ // drag & drop within the same list
985
+ _dispatchEvent(this, rootEl, 'update', dragEl, parentEl, rootEl, oldIndex, newIndex);
986
+ _dispatchEvent(this, rootEl, 'sort', dragEl, parentEl, rootEl, oldIndex, newIndex);
987
+ }
988
+ }
989
+ }
990
+
991
+ if (Sortable.active) {
992
+ /* jshint eqnull:true */
993
+ if (newIndex == null || newIndex === -1) {
994
+ newIndex = oldIndex;
995
+ }
996
+
997
+ _dispatchEvent(this, rootEl, 'end', dragEl, parentEl, rootEl, oldIndex, newIndex);
998
+
999
+ // Save sorting
1000
+ this.save();
1001
+ }
1002
+ }
1003
+
1004
+ }
1005
+
1006
+ this._nulling();
1007
+ },
1008
+
1009
+ _nulling: function() {
1010
+ rootEl =
1011
+ dragEl =
1012
+ parentEl =
1013
+ ghostEl =
1014
+ nextEl =
1015
+ cloneEl =
1016
+ lastDownEl =
1017
+
1018
+ scrollEl =
1019
+ scrollParentEl =
1020
+
1021
+ tapEvt =
1022
+ touchEvt =
1023
+
1024
+ moved =
1025
+ newIndex =
1026
+
1027
+ lastEl =
1028
+ lastCSS =
1029
+
1030
+ putSortable =
1031
+ activeGroup =
1032
+ Sortable.active = null;
1033
+
1034
+ savedInputChecked.forEach(function (el) {
1035
+ el.checked = true;
1036
+ });
1037
+ savedInputChecked.length = 0;
1038
+ },
1039
+
1040
+ handleEvent: function (/**Event*/evt) {
1041
+ switch (evt.type) {
1042
+ case 'drop':
1043
+ case 'dragend':
1044
+ this._onDrop(evt);
1045
+ break;
1046
+
1047
+ case 'dragover':
1048
+ case 'dragenter':
1049
+ if (dragEl) {
1050
+ this._onDragOver(evt);
1051
+ _globalDragOver(evt);
1052
+ }
1053
+ break;
1054
+
1055
+ case 'mouseover':
1056
+ this._onDrop(evt);
1057
+ break;
1058
+
1059
+ case 'selectstart':
1060
+ evt.preventDefault();
1061
+ break;
1062
+ }
1063
+ },
1064
+
1065
+
1066
+ /**
1067
+ * Serializes the item into an array of string.
1068
+ * @returns {String[]}
1069
+ */
1070
+ toArray: function () {
1071
+ var order = [],
1072
+ el,
1073
+ children = this.el.children,
1074
+ i = 0,
1075
+ n = children.length,
1076
+ options = this.options;
1077
+
1078
+ for (; i < n; i++) {
1079
+ el = children[i];
1080
+ if (_closest(el, options.draggable, this.el)) {
1081
+ order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
1082
+ }
1083
+ }
1084
+
1085
+ return order;
1086
+ },
1087
+
1088
+
1089
+ /**
1090
+ * Sorts the elements according to the array.
1091
+ * @param {String[]} order order of the items
1092
+ */
1093
+ sort: function (order) {
1094
+ var items = {}, rootEl = this.el;
1095
+
1096
+ this.toArray().forEach(function (id, i) {
1097
+ var el = rootEl.children[i];
1098
+
1099
+ if (_closest(el, this.options.draggable, rootEl)) {
1100
+ items[id] = el;
1101
+ }
1102
+ }, this);
1103
+
1104
+ order.forEach(function (id) {
1105
+ if (items[id]) {
1106
+ rootEl.removeChild(items[id]);
1107
+ rootEl.appendChild(items[id]);
1108
+ }
1109
+ });
1110
+ },
1111
+
1112
+
1113
+ /**
1114
+ * Save the current sorting
1115
+ */
1116
+ save: function () {
1117
+ var store = this.options.store;
1118
+ store && store.set(this);
1119
+ },
1120
+
1121
+
1122
+ /**
1123
+ * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
1124
+ * @param {HTMLElement} el
1125
+ * @param {String} [selector] default: `options.draggable`
1126
+ * @returns {HTMLElement|null}
1127
+ */
1128
+ closest: function (el, selector) {
1129
+ return _closest(el, selector || this.options.draggable, this.el);
1130
+ },
1131
+
1132
+
1133
+ /**
1134
+ * Set/get option
1135
+ * @param {string} name
1136
+ * @param {*} [value]
1137
+ * @returns {*}
1138
+ */
1139
+ option: function (name, value) {
1140
+ var options = this.options;
1141
+
1142
+ if (value === void 0) {
1143
+ return options[name];
1144
+ } else {
1145
+ options[name] = value;
1146
+
1147
+ if (name === 'group') {
1148
+ _prepareGroup(options);
1149
+ }
1150
+ }
1151
+ },
1152
+
1153
+
1154
+ /**
1155
+ * Destroy
1156
+ */
1157
+ destroy: function () {
1158
+ var el = this.el;
1159
+
1160
+ el[expando] = null;
1161
+
1162
+ _off(el, 'mousedown', this._onTapStart);
1163
+ _off(el, 'touchstart', this._onTapStart);
1164
+ _off(el, 'pointerdown', this._onTapStart);
1165
+
1166
+ if (this.nativeDraggable) {
1167
+ _off(el, 'dragover', this);
1168
+ _off(el, 'dragenter', this);
1169
+ }
1170
+
1171
+ // Remove draggable attributes
1172
+ Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
1173
+ el.removeAttribute('draggable');
1174
+ });
1175
+
1176
+ touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
1177
+
1178
+ this._onDrop();
1179
+
1180
+ this.el = el = null;
1181
+ }
1182
+ };
1183
+
1184
+
1185
+ function _cloneHide(sortable, state) {
1186
+ if (sortable.lastPullMode !== 'clone') {
1187
+ state = true;
1188
+ }
1189
+
1190
+ if (cloneEl && (cloneEl.state !== state)) {
1191
+ _css(cloneEl, 'display', state ? 'none' : '');
1192
+
1193
+ if (!state) {
1194
+ if (cloneEl.state) {
1195
+ if (sortable.options.group.revertClone) {
1196
+ rootEl.insertBefore(cloneEl, nextEl);
1197
+ sortable._animate(dragEl, cloneEl);
1198
+ } else {
1199
+ rootEl.insertBefore(cloneEl, dragEl);
1200
+ }
1201
+ }
1202
+ }
1203
+
1204
+ cloneEl.state = state;
1205
+ }
1206
+ }
7
1207
 
8
- (function (factory) {
9
- "use strict";
10
1208
 
11
- if (typeof define === "function" && define.amd) {
12
- define(factory);
13
- }
14
- else if (typeof module != "undefined" && typeof module.exports != "undefined") {
15
- module.exports = factory();
16
- }
17
- else if (typeof Package !== "undefined") {
18
- Sortable = factory(); // export for Meteor.js
19
- }
20
- else {
21
- /* jshint sub:true */
22
- window["Sortable"] = factory();
23
- }
24
- })(function () {
25
- "use strict";
1209
+ function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
1210
+ if (el) {
1211
+ ctx = ctx || document;
26
1212
 
27
- var dragEl,
28
- ghostEl,
29
- cloneEl,
30
- rootEl,
31
- nextEl,
1213
+ do {
1214
+ if ((selector === '>*' && el.parentNode === ctx) || _matches(el, selector)) {
1215
+ return el;
1216
+ }
1217
+ /* jshint boss:true */
1218
+ } while (el = _getParentOrHost(el));
1219
+ }
32
1220
 
33
- scrollEl,
34
- scrollParentEl,
35
-
36
- lastEl,
37
- lastCSS,
38
-
39
- oldIndex,
40
- newIndex,
41
-
42
- activeGroup,
43
- autoScroll = {},
1221
+ return null;
1222
+ }
44
1223
 
45
- tapEvt,
46
- touchEvt,
47
-
48
- /** @const */
49
- RSPACE = /\s+/g,
50
-
51
- expando = 'Sortable' + (new Date).getTime(),
52
-
53
- win = window,
54
- document = win.document,
55
- parseInt = win.parseInt,
56
1224
 
57
- supportDraggable = !!('draggable' in document.createElement('div')),
1225
+ function _getParentOrHost(el) {
1226
+ var parent = el.host;
58
1227
 
59
- _silent = false,
1228
+ return (parent && parent.nodeType) ? parent : el.parentNode;
1229
+ }
60
1230
 
61
- abs = Math.abs,
62
- slice = [].slice,
63
-
64
- touchDragOverListeners = [],
65
-
66
- _autoScroll = _throttle(function (/**Event*/evt, /**Object*/options, /**HTMLElement*/rootEl) {
67
- // Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=505521
68
- if (rootEl && options.scroll) {
69
- var el,
70
- rect,
71
- sens = options.scrollSensitivity,
72
- speed = options.scrollSpeed,
73
-
74
- x = evt.clientX,
75
- y = evt.clientY,
76
-
77
- winWidth = window.innerWidth,
78
- winHeight = window.innerHeight,
79
-
80
- vx,
81
- vy
82
- ;
83
-
84
- // Delect scrollEl
85
- if (scrollParentEl !== rootEl) {
86
- scrollEl = options.scroll;
87
- scrollParentEl = rootEl;
88
-
89
- if (scrollEl === true) {
90
- scrollEl = rootEl;
91
-
92
- do {
93
- if ((scrollEl.offsetWidth < scrollEl.scrollWidth) ||
94
- (scrollEl.offsetHeight < scrollEl.scrollHeight)
95
- ) {
96
- break;
97
- }
98
- /* jshint boss:true */
99
- } while (scrollEl = scrollEl.parentNode);
100
- }
101
- }
102
-
103
- if (scrollEl) {
104
- el = scrollEl;
105
- rect = scrollEl.getBoundingClientRect();
106
- vx = (abs(rect.right - x) <= sens) - (abs(rect.left - x) <= sens);
107
- vy = (abs(rect.bottom - y) <= sens) - (abs(rect.top - y) <= sens);
108
- }
109
-
110
-
111
- if (!(vx || vy)) {
112
- vx = (winWidth - x <= sens) - (x <= sens);
113
- vy = (winHeight - y <= sens) - (y <= sens);
114
-
115
- /* jshint expr:true */
116
- (vx || vy) && (el = win);
117
- }
118
-
119
-
120
- if (autoScroll.vx !== vx || autoScroll.vy !== vy || autoScroll.el !== el) {
121
- autoScroll.el = el;
122
- autoScroll.vx = vx;
123
- autoScroll.vy = vy;
124
1231
 
125
- clearInterval(autoScroll.pid);
1232
+ function _globalDragOver(/**Event*/evt) {
1233
+ if (evt.dataTransfer) {
1234
+ evt.dataTransfer.dropEffect = 'move';
1235
+ }
1236
+ evt.preventDefault();
1237
+ }
126
1238
 
127
- if (el) {
128
- autoScroll.pid = setInterval(function () {
129
- if (el === win) {
130
- win.scrollTo(win.pageXOffset + vx * speed, win.pageYOffset + vy * speed);
131
- } else {
132
- vy && (el.scrollTop += vy * speed);
133
- vx && (el.scrollLeft += vx * speed);
134
- }
135
- }, 24);
136
- }
137
- }
138
- }
139
- }, 30)
140
- ;
141
1239
 
1240
+ function _on(el, event, fn) {
1241
+ el.addEventListener(event, fn, captureMode);
1242
+ }
142
1243
 
143
1244
 
144
- /**
145
- * @class Sortable
146
- * @param {HTMLElement} el
147
- * @param {Object} [options]
148
- */
149
- function Sortable(el, options) {
150
- this.el = el; // root element
151
- this.options = options = _extend({}, options);
1245
+ function _off(el, event, fn) {
1246
+ el.removeEventListener(event, fn, captureMode);
1247
+ }
152
1248
 
153
1249
 
154
- // Export instance
155
- el[expando] = this;
1250
+ function _toggleClass(el, name, state) {
1251
+ if (el) {
1252
+ if (el.classList) {
1253
+ el.classList[state ? 'add' : 'remove'](name);
1254
+ }
1255
+ else {
1256
+ var className = (' ' + el.className + ' ').replace(R_SPACE, ' ').replace(' ' + name + ' ', ' ');
1257
+ el.className = (className + (state ? ' ' + name : '')).replace(R_SPACE, ' ');
1258
+ }
1259
+ }
1260
+ }
156
1261
 
157
1262
 
158
- // Default options
159
- var defaults = {
160
- group: Math.random(),
161
- sort: true,
162
- disabled: false,
163
- store: null,
164
- handle: null,
165
- scroll: true,
166
- scrollSensitivity: 30,
167
- scrollSpeed: 10,
168
- draggable: /[uo]l/i.test(el.nodeName) ? 'li' : '>*',
169
- ghostClass: 'sortable-ghost',
170
- ignore: 'a, img',
171
- filter: null,
172
- animation: 0,
173
- setData: function (dataTransfer, dragEl) {
174
- dataTransfer.setData('Text', dragEl.textContent);
175
- },
176
- dropBubble: false,
177
- dragoverBubble: false,
178
- dataIdAttr: 'data-id',
179
- delay: 0
180
- };
181
-
182
-
183
- // Set default options
184
- for (var name in defaults) {
185
- !(name in options) && (options[name] = defaults[name]);
186
- }
187
-
188
-
189
- var group = options.group;
190
-
191
- if (!group || typeof group != 'object') {
192
- group = options.group = { name: group };
193
- }
194
-
195
-
196
- ['pull', 'put'].forEach(function (key) {
197
- if (!(key in group)) {
198
- group[key] = true;
199
- }
200
- });
201
-
202
-
203
- options.groups = ' ' + group.name + (group.put.join ? ' ' + group.put.join(' ') : '') + ' ';
204
-
205
-
206
- // Bind all private methods
207
- for (var fn in this) {
208
- if (fn.charAt(0) === '_') {
209
- this[fn] = _bind(this, this[fn]);
210
- }
211
- }
212
-
213
-
214
- // Bind events
215
- _on(el, 'mousedown', this._onTapStart);
216
- _on(el, 'touchstart', this._onTapStart);
217
-
218
- _on(el, 'dragover', this);
219
- _on(el, 'dragenter', this);
220
-
221
- touchDragOverListeners.push(this._onDragOver);
222
-
223
- // Restore sorting
224
- options.store && this.sort(options.store.get(this));
225
- }
226
-
227
-
228
- Sortable.prototype = /** @lends Sortable.prototype */ {
229
- constructor: Sortable,
230
-
231
- _onTapStart: function (/** Event|TouchEvent */evt) {
232
- var _this = this,
233
- el = this.el,
234
- options = this.options,
235
- type = evt.type,
236
- touch = evt.touches && evt.touches[0],
237
- target = (touch || evt).target,
238
- originalTarget = target,
239
- filter = options.filter;
1263
+ function _css(el, prop, val) {
1264
+ var style = el && el.style;
240
1265
 
1266
+ if (style) {
1267
+ if (val === void 0) {
1268
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1269
+ val = document.defaultView.getComputedStyle(el, '');
1270
+ }
1271
+ else if (el.currentStyle) {
1272
+ val = el.currentStyle;
1273
+ }
241
1274
 
242
- if (type === 'mousedown' && evt.button !== 0 || options.disabled) {
243
- return; // only left button or enabled
244
- }
245
-
246
- target = _closest(target, options.draggable, el);
247
-
248
- if (!target) {
249
- return;
250
- }
251
-
252
- // get the index of the dragged element within its parent
253
- oldIndex = _index(target);
254
-
255
- // Check filter
256
- if (typeof filter === 'function') {
257
- if (filter.call(this, evt, target, this)) {
258
- _dispatchEvent(_this, originalTarget, 'filter', target, el, oldIndex);
259
- evt.preventDefault();
260
- return; // cancel dnd
261
- }
262
- }
263
- else if (filter) {
264
- filter = filter.split(',').some(function (criteria) {
265
- criteria = _closest(originalTarget, criteria.trim(), el);
266
-
267
- if (criteria) {
268
- _dispatchEvent(_this, criteria, 'filter', target, el, oldIndex);
269
- return true;
270
- }
271
- });
272
-
273
- if (filter) {
274
- evt.preventDefault();
275
- return; // cancel dnd
276
- }
277
- }
278
-
279
-
280
- if (options.handle && !_closest(originalTarget, options.handle, el)) {
281
- return;
282
- }
283
-
284
-
285
- // Prepare `dragstart`
286
- this._prepareDragStart(evt, touch, target);
287
- },
288
-
289
- _prepareDragStart: function (/** Event */evt, /** Touch */touch, /** HTMLElement */target) {
290
- var _this = this,
291
- el = _this.el,
292
- options = _this.options,
293
- ownerDocument = el.ownerDocument,
294
- dragStartFn;
295
-
296
- if (target && !dragEl && (target.parentNode === el)) {
297
- tapEvt = evt;
298
-
299
- rootEl = el;
300
- dragEl = target;
301
- nextEl = dragEl.nextSibling;
302
- activeGroup = options.group;
303
-
304
- dragStartFn = function () {
305
- // Delayed drag has been triggered
306
- // we can re-enable the events: touchmove/mousemove
307
- _this._disableDelayedDrag();
308
-
309
- // Make the element draggable
310
- dragEl.draggable = true;
311
-
312
- // Disable "draggable"
313
- options.ignore.split(',').forEach(function (criteria) {
314
- _find(dragEl, criteria.trim(), _disableDraggable);
315
- });
316
-
317
- // Bind the events: dragstart/dragend
318
- _this._triggerDragStart(touch);
319
- };
320
-
321
- _on(ownerDocument, 'mouseup', _this._onDrop);
322
- _on(ownerDocument, 'touchend', _this._onDrop);
323
- _on(ownerDocument, 'touchcancel', _this._onDrop);
324
-
325
- if (options.delay) {
326
- // If the user moves the pointer before the delay has been reached:
327
- // disable the delayed drag
328
- _on(ownerDocument, 'mousemove', _this._disableDelayedDrag);
329
- _on(ownerDocument, 'touchmove', _this._disableDelayedDrag);
330
-
331
- _this._dragStartTimer = setTimeout(dragStartFn, options.delay);
332
- } else {
333
- dragStartFn();
334
- }
335
- }
336
- },
337
-
338
- _disableDelayedDrag: function () {
339
- var ownerDocument = this.el.ownerDocument;
340
-
341
- clearTimeout(this._dragStartTimer);
342
-
343
- _off(ownerDocument, 'mousemove', this._disableDelayedDrag);
344
- _off(ownerDocument, 'touchmove', this._disableDelayedDrag);
345
- },
346
-
347
- _triggerDragStart: function (/** Touch */touch) {
348
- if (touch) {
349
- // Touch device support
350
- tapEvt = {
351
- target: dragEl,
352
- clientX: touch.clientX,
353
- clientY: touch.clientY
354
- };
355
-
356
- this._onDragStart(tapEvt, 'touch');
357
- }
358
- else if (!supportDraggable) {
359
- this._onDragStart(tapEvt, true);
360
- }
361
- else {
362
- _on(dragEl, 'dragend', this);
363
- _on(rootEl, 'dragstart', this._onDragStart);
364
- }
365
-
366
- try {
367
- if (document.selection) {
368
- document.selection.empty();
369
- } else {
370
- window.getSelection().removeAllRanges();
371
- }
372
- } catch (err) {
373
- }
374
- },
375
-
376
- _dragStarted: function () {
377
- if (rootEl && dragEl) {
378
- // Apply effect
379
- _toggleClass(dragEl, this.options.ghostClass, true);
380
-
381
- Sortable.active = this;
382
-
383
- // Drag start event
384
- _dispatchEvent(this, rootEl, 'start', dragEl, rootEl, oldIndex);
385
- }
386
- },
387
-
388
- _emulateDragOver: function () {
389
- if (touchEvt) {
390
- _css(ghostEl, 'display', 'none');
391
-
392
- var target = document.elementFromPoint(touchEvt.clientX, touchEvt.clientY),
393
- parent = target,
394
- groupName = ' ' + this.options.group.name + '',
395
- i = touchDragOverListeners.length;
396
-
397
- if (parent) {
398
- do {
399
- if (parent[expando] && parent[expando].options.groups.indexOf(groupName) > -1) {
400
- while (i--) {
401
- touchDragOverListeners[i]({
402
- clientX: touchEvt.clientX,
403
- clientY: touchEvt.clientY,
404
- target: target,
405
- rootEl: parent
406
- });
407
- }
408
-
409
- break;
410
- }
411
-
412
- target = parent; // store last element
413
- }
414
- /* jshint boss:true */
415
- while (parent = parent.parentNode);
416
- }
417
-
418
- _css(ghostEl, 'display', '');
419
- }
420
- },
421
-
422
-
423
- _onTouchMove: function (/**TouchEvent*/evt) {
424
- if (tapEvt) {
425
- var touch = evt.touches ? evt.touches[0] : evt,
426
- dx = touch.clientX - tapEvt.clientX,
427
- dy = touch.clientY - tapEvt.clientY,
428
- translate3d = evt.touches ? 'translate3d(' + dx + 'px,' + dy + 'px,0)' : 'translate(' + dx + 'px,' + dy + 'px)';
429
-
430
- touchEvt = touch;
431
-
432
- _css(ghostEl, 'webkitTransform', translate3d);
433
- _css(ghostEl, 'mozTransform', translate3d);
434
- _css(ghostEl, 'msTransform', translate3d);
435
- _css(ghostEl, 'transform', translate3d);
436
-
437
- evt.preventDefault();
438
- }
439
- },
440
-
441
-
442
- _onDragStart: function (/**Event*/evt, /**boolean*/useFallback) {
443
- var dataTransfer = evt.dataTransfer,
444
- options = this.options;
445
-
446
- this._offUpEvents();
447
-
448
- if (activeGroup.pull == 'clone') {
449
- cloneEl = dragEl.cloneNode(true);
450
- _css(cloneEl, 'display', 'none');
451
- rootEl.insertBefore(cloneEl, dragEl);
452
- }
453
-
454
- if (useFallback) {
455
- var rect = dragEl.getBoundingClientRect(),
456
- css = _css(dragEl),
457
- ghostRect;
458
-
459
- ghostEl = dragEl.cloneNode(true);
460
-
461
- _css(ghostEl, 'top', rect.top - parseInt(css.marginTop, 10));
462
- _css(ghostEl, 'left', rect.left - parseInt(css.marginLeft, 10));
463
- _css(ghostEl, 'width', rect.width);
464
- _css(ghostEl, 'height', rect.height);
465
- _css(ghostEl, 'opacity', '0.8');
466
- _css(ghostEl, 'position', 'fixed');
467
- _css(ghostEl, 'zIndex', '100000');
468
-
469
- rootEl.appendChild(ghostEl);
470
-
471
- // Fixing dimensions.
472
- ghostRect = ghostEl.getBoundingClientRect();
473
- _css(ghostEl, 'width', rect.width * 2 - ghostRect.width);
474
- _css(ghostEl, 'height', rect.height * 2 - ghostRect.height);
475
-
476
- if (useFallback === 'touch') {
477
- // Bind touch events
478
- _on(document, 'touchmove', this._onTouchMove);
479
- _on(document, 'touchend', this._onDrop);
480
- _on(document, 'touchcancel', this._onDrop);
481
- } else {
482
- // Old brwoser
483
- _on(document, 'mousemove', this._onTouchMove);
484
- _on(document, 'mouseup', this._onDrop);
485
- }
486
-
487
- this._loopId = setInterval(this._emulateDragOver, 150);
488
- }
489
- else {
490
- if (dataTransfer) {
491
- dataTransfer.effectAllowed = 'move';
492
- options.setData && options.setData.call(this, dataTransfer, dragEl);
493
- }
494
-
495
- _on(document, 'drop', this);
496
- }
497
-
498
- setTimeout(this._dragStarted, 0);
499
- },
500
-
501
- _onDragOver: function (/**Event*/evt) {
502
- var el = this.el,
503
- target,
504
- dragRect,
505
- revert,
506
- options = this.options,
507
- group = options.group,
508
- groupPut = group.put,
509
- isOwner = (activeGroup === group),
510
- canSort = options.sort;
511
-
512
- if (evt.preventDefault !== void 0) {
513
- evt.preventDefault();
514
- !options.dragoverBubble && evt.stopPropagation();
515
- }
516
-
517
- if (activeGroup && !options.disabled &&
518
- (isOwner
519
- ? canSort || (revert = !rootEl.contains(dragEl)) // Reverting item into the original list
520
- : activeGroup.pull && groupPut && (
521
- (activeGroup.name === group.name) || // by Name
522
- (groupPut.indexOf && ~groupPut.indexOf(activeGroup.name)) // by Array
523
- )
524
- ) &&
525
- (evt.rootEl === void 0 || evt.rootEl === this.el) // touch fallback
526
- ) {
527
- // Smart auto-scrolling
528
- _autoScroll(evt, options, this.el);
529
-
530
- if (_silent) {
531
- return;
532
- }
533
-
534
- target = _closest(evt.target, options.draggable, el);
535
- dragRect = dragEl.getBoundingClientRect();
536
-
537
-
538
- if (revert) {
539
- _cloneHide(true);
540
-
541
- if (cloneEl || nextEl) {
542
- rootEl.insertBefore(dragEl, cloneEl || nextEl);
543
- }
544
- else if (!canSort) {
545
- rootEl.appendChild(dragEl);
546
- }
547
-
548
- return;
549
- }
550
-
551
-
552
- if ((el.children.length === 0) || (el.children[0] === ghostEl) ||
553
- (el === evt.target) && (target = _ghostInBottom(el, evt))
554
- ) {
555
- if (target) {
556
- if (target.animated) {
557
- return;
558
- }
559
- targetRect = target.getBoundingClientRect();
560
- }
561
-
562
- _cloneHide(isOwner);
563
-
564
- if (_onMove(rootEl, el, dragEl, dragRect, target, targetRect) !== false) {
565
- el.appendChild(dragEl);
566
- this._animate(dragRect, dragEl);
567
- target && this._animate(targetRect, target);
568
- }
569
- }
570
- else if (target && !target.animated && target !== dragEl && (target.parentNode[expando] !== void 0)) {
571
- if (lastEl !== target) {
572
- lastEl = target;
573
- lastCSS = _css(target);
574
- }
575
-
576
-
577
- var targetRect = target.getBoundingClientRect(),
578
- width = targetRect.right - targetRect.left,
579
- height = targetRect.bottom - targetRect.top,
580
- floating = /left|right|inline/.test(lastCSS.cssFloat + lastCSS.display),
581
- isWide = (target.offsetWidth > dragEl.offsetWidth),
582
- isLong = (target.offsetHeight > dragEl.offsetHeight),
583
- halfway = (floating ? (evt.clientX - targetRect.left) / width : (evt.clientY - targetRect.top) / height) > 0.5,
584
- nextSibling = target.nextElementSibling,
585
- moveVector = _onMove(rootEl, el, dragEl, dragRect, target, targetRect),
586
- after
587
- ;
588
-
589
- if (moveVector !== false) {
590
- _silent = true;
591
- setTimeout(_unsilent, 30);
592
-
593
- _cloneHide(isOwner);
594
-
595
- if (moveVector === 1 || moveVector === -1) {
596
- after = (moveVector === 1);
597
- }
598
- else if (floating) {
599
- after = (target.previousElementSibling === dragEl) && !isWide || halfway && isWide;
600
- } else {
601
- after = (nextSibling !== dragEl) && !isLong || halfway && isLong;
602
- }
603
-
604
- if (after && !nextSibling) {
605
- el.appendChild(dragEl);
606
- } else {
607
- target.parentNode.insertBefore(dragEl, after ? nextSibling : target);
608
- }
609
-
610
- this._animate(dragRect, dragEl);
611
- this._animate(targetRect, target);
612
- }
613
- }
614
- }
615
- },
616
-
617
- _animate: function (prevRect, target) {
618
- var ms = this.options.animation;
619
-
620
- if (ms) {
621
- var currentRect = target.getBoundingClientRect();
622
-
623
- _css(target, 'transition', 'none');
624
- _css(target, 'transform', 'translate3d('
625
- + (prevRect.left - currentRect.left) + 'px,'
626
- + (prevRect.top - currentRect.top) + 'px,0)'
627
- );
628
-
629
- target.offsetWidth; // repaint
630
-
631
- _css(target, 'transition', 'all ' + ms + 'ms');
632
- _css(target, 'transform', 'translate3d(0,0,0)');
633
-
634
- clearTimeout(target.animated);
635
- target.animated = setTimeout(function () {
636
- _css(target, 'transition', '');
637
- _css(target, 'transform', '');
638
- target.animated = false;
639
- }, ms);
640
- }
641
- },
642
-
643
- _offUpEvents: function () {
644
- var ownerDocument = this.el.ownerDocument;
645
-
646
- _off(document, 'touchmove', this._onTouchMove);
647
- _off(ownerDocument, 'mouseup', this._onDrop);
648
- _off(ownerDocument, 'touchend', this._onDrop);
649
- _off(ownerDocument, 'touchcancel', this._onDrop);
650
- },
651
-
652
- _onDrop: function (/**Event*/evt) {
653
- var el = this.el,
654
- options = this.options;
655
-
656
- clearInterval(this._loopId);
657
- clearInterval(autoScroll.pid);
658
- clearTimeout(this._dragStartTimer);
659
-
660
- // Unbind events
661
- _off(document, 'drop', this);
662
- _off(document, 'mousemove', this._onTouchMove);
663
- _off(el, 'dragstart', this._onDragStart);
664
-
665
- this._offUpEvents();
666
-
667
- if (evt) {
668
- evt.preventDefault();
669
- !options.dropBubble && evt.stopPropagation();
670
-
671
- ghostEl && ghostEl.parentNode.removeChild(ghostEl);
672
-
673
- if (dragEl) {
674
- _off(dragEl, 'dragend', this);
675
-
676
- _disableDraggable(dragEl);
677
- _toggleClass(dragEl, this.options.ghostClass, false);
678
-
679
- if (rootEl !== dragEl.parentNode) {
680
- newIndex = _index(dragEl);
681
-
682
- // drag from one list and drop into another
683
- _dispatchEvent(null, dragEl.parentNode, 'sort', dragEl, rootEl, oldIndex, newIndex);
684
- _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
685
-
686
- // Add event
687
- _dispatchEvent(null, dragEl.parentNode, 'add', dragEl, rootEl, oldIndex, newIndex);
688
-
689
- // Remove event
690
- _dispatchEvent(this, rootEl, 'remove', dragEl, rootEl, oldIndex, newIndex);
691
- }
692
- else {
693
- // Remove clone
694
- cloneEl && cloneEl.parentNode.removeChild(cloneEl);
695
-
696
- if (dragEl.nextSibling !== nextEl) {
697
- // Get the index of the dragged element within its parent
698
- newIndex = _index(dragEl);
699
-
700
- // drag & drop within the same list
701
- _dispatchEvent(this, rootEl, 'update', dragEl, rootEl, oldIndex, newIndex);
702
- _dispatchEvent(this, rootEl, 'sort', dragEl, rootEl, oldIndex, newIndex);
703
- }
704
- }
705
-
706
- if (Sortable.active) {
707
- // Drag end event
708
- _dispatchEvent(this, rootEl, 'end', dragEl, rootEl, oldIndex, newIndex);
709
-
710
- // Save sorting
711
- this.save();
712
- }
713
- }
714
-
715
- // Nulling
716
- rootEl =
717
- dragEl =
718
- ghostEl =
719
- nextEl =
720
- cloneEl =
721
-
722
- scrollEl =
723
- scrollParentEl =
724
-
725
- tapEvt =
726
- touchEvt =
727
-
728
- lastEl =
729
- lastCSS =
730
-
731
- activeGroup =
732
- Sortable.active = null;
733
- }
734
- },
735
-
736
-
737
- handleEvent: function (/**Event*/evt) {
738
- var type = evt.type;
739
-
740
- if (type === 'dragover' || type === 'dragenter') {
741
- if (dragEl) {
742
- this._onDragOver(evt);
743
- _globalDragOver(evt);
744
- }
745
- }
746
- else if (type === 'drop' || type === 'dragend') {
747
- this._onDrop(evt);
748
- }
749
- },
750
-
751
-
752
- /**
753
- * Serializes the item into an array of string.
754
- * @returns {String[]}
755
- */
756
- toArray: function () {
757
- var order = [],
758
- el,
759
- children = this.el.children,
760
- i = 0,
761
- n = children.length,
762
- options = this.options;
763
-
764
- for (; i < n; i++) {
765
- el = children[i];
766
- if (_closest(el, options.draggable, this.el)) {
767
- order.push(el.getAttribute(options.dataIdAttr) || _generateId(el));
768
- }
769
- }
770
-
771
- return order;
772
- },
773
-
774
-
775
- /**
776
- * Sorts the elements according to the array.
777
- * @param {String[]} order order of the items
778
- */
779
- sort: function (order) {
780
- var items = {}, rootEl = this.el;
781
-
782
- this.toArray().forEach(function (id, i) {
783
- var el = rootEl.children[i];
784
-
785
- if (_closest(el, this.options.draggable, rootEl)) {
786
- items[id] = el;
787
- }
788
- }, this);
789
-
790
- order.forEach(function (id) {
791
- if (items[id]) {
792
- rootEl.removeChild(items[id]);
793
- rootEl.appendChild(items[id]);
794
- }
795
- });
796
- },
797
-
798
-
799
- /**
800
- * Save the current sorting
801
- */
802
- save: function () {
803
- var store = this.options.store;
804
- store && store.set(this);
805
- },
806
-
807
-
808
- /**
809
- * For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
810
- * @param {HTMLElement} el
811
- * @param {String} [selector] default: `options.draggable`
812
- * @returns {HTMLElement|null}
813
- */
814
- closest: function (el, selector) {
815
- return _closest(el, selector || this.options.draggable, this.el);
816
- },
817
-
818
-
819
- /**
820
- * Set/get option
821
- * @param {string} name
822
- * @param {*} [value]
823
- * @returns {*}
824
- */
825
- option: function (name, value) {
826
- var options = this.options;
827
-
828
- if (value === void 0) {
829
- return options[name];
830
- } else {
831
- options[name] = value;
832
- }
833
- },
834
-
835
-
836
- /**
837
- * Destroy
838
- */
839
- destroy: function () {
840
- var el = this.el;
841
-
842
- el[expando] = null;
843
-
844
- _off(el, 'mousedown', this._onTapStart);
845
- _off(el, 'touchstart', this._onTapStart);
846
-
847
- _off(el, 'dragover', this);
848
- _off(el, 'dragenter', this);
849
-
850
- // Remove draggable attributes
851
- Array.prototype.forEach.call(el.querySelectorAll('[draggable]'), function (el) {
852
- el.removeAttribute('draggable');
853
- });
854
-
855
- touchDragOverListeners.splice(touchDragOverListeners.indexOf(this._onDragOver), 1);
856
-
857
- this._onDrop();
858
-
859
- this.el = el = null;
860
- }
861
- };
862
-
863
-
864
- function _cloneHide(state) {
865
- if (cloneEl && (cloneEl.state !== state)) {
866
- _css(cloneEl, 'display', state ? 'none' : '');
867
- !state && cloneEl.state && rootEl.insertBefore(cloneEl, dragEl);
868
- cloneEl.state = state;
869
- }
870
- }
871
-
872
-
873
- function _bind(ctx, fn) {
874
- var args = slice.call(arguments, 2);
875
- return fn.bind ? fn.bind.apply(fn, [ctx].concat(args)) : function () {
876
- return fn.apply(ctx, args.concat(slice.call(arguments)));
877
- };
878
- }
879
-
880
-
881
- function _closest(/**HTMLElement*/el, /**String*/selector, /**HTMLElement*/ctx) {
882
- if (el) {
883
- ctx = ctx || document;
884
- selector = selector.split('.');
885
-
886
- var tag = selector.shift().toUpperCase(),
887
- re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
888
-
889
- do {
890
- if (
891
- (tag === '>*' && el.parentNode === ctx) || (
892
- (tag === '' || el.nodeName.toUpperCase() == tag) &&
893
- (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
894
- )
895
- ) {
896
- return el;
897
- }
898
- }
899
- while (el !== ctx && (el = el.parentNode));
900
- }
1275
+ return prop === void 0 ? val : val[prop];
1276
+ }
1277
+ else {
1278
+ if (!(prop in style)) {
1279
+ prop = '-webkit-' + prop;
1280
+ }
901
1281
 
902
- return null;
903
- }
1282
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
1283
+ }
1284
+ }
1285
+ }
904
1286
 
905
1287
 
906
- function _globalDragOver(/**Event*/evt) {
907
- evt.dataTransfer.dropEffect = 'move';
908
- evt.preventDefault();
909
- }
1288
+ function _find(ctx, tagName, iterator) {
1289
+ if (ctx) {
1290
+ var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
910
1291
 
1292
+ if (iterator) {
1293
+ for (; i < n; i++) {
1294
+ iterator(list[i], i);
1295
+ }
1296
+ }
911
1297
 
912
- function _on(el, event, fn) {
913
- el.addEventListener(event, fn, false);
914
- }
1298
+ return list;
1299
+ }
915
1300
 
1301
+ return [];
1302
+ }
916
1303
 
917
- function _off(el, event, fn) {
918
- el.removeEventListener(event, fn, false);
919
- }
920
1304
 
921
1305
 
922
- function _toggleClass(el, name, state) {
923
- if (el) {
924
- if (el.classList) {
925
- el.classList[state ? 'add' : 'remove'](name);
926
- }
927
- else {
928
- var className = (' ' + el.className + ' ').replace(RSPACE, ' ').replace(' ' + name + ' ', ' ');
929
- el.className = (className + (state ? ' ' + name : '')).replace(RSPACE, ' ');
930
- }
931
- }
932
- }
1306
+ function _dispatchEvent(sortable, rootEl, name, targetEl, toEl, fromEl, startIndex, newIndex) {
1307
+ sortable = (sortable || rootEl[expando]);
933
1308
 
1309
+ var evt = document.createEvent('Event'),
1310
+ options = sortable.options,
1311
+ onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
934
1312
 
935
- function _css(el, prop, val) {
936
- var style = el && el.style;
1313
+ evt.initEvent(name, true, true);
937
1314
 
938
- if (style) {
939
- if (val === void 0) {
940
- if (document.defaultView && document.defaultView.getComputedStyle) {
941
- val = document.defaultView.getComputedStyle(el, '');
942
- }
943
- else if (el.currentStyle) {
944
- val = el.currentStyle;
945
- }
1315
+ evt.to = toEl || rootEl;
1316
+ evt.from = fromEl || rootEl;
1317
+ evt.item = targetEl || rootEl;
1318
+ evt.clone = cloneEl;
946
1319
 
947
- return prop === void 0 ? val : val[prop];
948
- }
949
- else {
950
- if (!(prop in style)) {
951
- prop = '-webkit-' + prop;
952
- }
1320
+ evt.oldIndex = startIndex;
1321
+ evt.newIndex = newIndex;
953
1322
 
954
- style[prop] = val + (typeof val === 'string' ? '' : 'px');
955
- }
956
- }
957
- }
1323
+ rootEl.dispatchEvent(evt);
958
1324
 
1325
+ if (options[onName]) {
1326
+ options[onName].call(sortable, evt);
1327
+ }
1328
+ }
959
1329
 
960
- function _find(ctx, tagName, iterator) {
961
- if (ctx) {
962
- var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
963
1330
 
964
- if (iterator) {
965
- for (; i < n; i++) {
966
- iterator(list[i], i);
967
- }
968
- }
969
-
970
- return list;
971
- }
972
-
973
- return [];
974
- }
1331
+ function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect, originalEvt, willInsertAfter) {
1332
+ var evt,
1333
+ sortable = fromEl[expando],
1334
+ onMoveFn = sortable.options.onMove,
1335
+ retVal;
975
1336
 
1337
+ evt = document.createEvent('Event');
1338
+ evt.initEvent('move', true, true);
976
1339
 
1340
+ evt.to = toEl;
1341
+ evt.from = fromEl;
1342
+ evt.dragged = dragEl;
1343
+ evt.draggedRect = dragRect;
1344
+ evt.related = targetEl || toEl;
1345
+ evt.relatedRect = targetRect || toEl.getBoundingClientRect();
1346
+ evt.willInsertAfter = willInsertAfter;
1347
+
1348
+ fromEl.dispatchEvent(evt);
1349
+
1350
+ if (onMoveFn) {
1351
+ retVal = onMoveFn.call(sortable, evt, originalEvt);
1352
+ }
1353
+
1354
+ return retVal;
1355
+ }
977
1356
 
978
- function _dispatchEvent(sortable, rootEl, name, targetEl, fromEl, startIndex, newIndex) {
979
- var evt = document.createEvent('Event'),
980
- options = (sortable || rootEl[expando]).options,
981
- onName = 'on' + name.charAt(0).toUpperCase() + name.substr(1);
982
-
983
- evt.initEvent(name, true, true);
984
-
985
- evt.to = rootEl;
986
- evt.from = fromEl || rootEl;
987
- evt.item = targetEl || rootEl;
988
- evt.clone = cloneEl;
989
-
990
- evt.oldIndex = startIndex;
991
- evt.newIndex = newIndex;
992
-
993
- rootEl.dispatchEvent(evt);
994
-
995
- if (options[onName]) {
996
- options[onName].call(sortable, evt);
997
- }
998
- }
999
1357
 
1358
+ function _disableDraggable(el) {
1359
+ el.draggable = false;
1360
+ }
1000
1361
 
1001
- function _onMove(fromEl, toEl, dragEl, dragRect, targetEl, targetRect) {
1002
- var evt,
1003
- sortable = fromEl[expando],
1004
- onMoveFn = sortable.options.onMove,
1005
- retVal;
1006
-
1007
- if (onMoveFn) {
1008
- evt = document.createEvent('Event');
1009
- evt.initEvent('move', true, true);
1010
-
1011
- evt.to = toEl;
1012
- evt.from = fromEl;
1013
- evt.dragged = dragEl;
1014
- evt.draggedRect = dragRect;
1015
- evt.related = targetEl || toEl;
1016
- evt.relatedRect = targetRect || toEl.getBoundingClientRect();
1017
-
1018
- retVal = onMoveFn.call(sortable, evt);
1019
- }
1020
-
1021
- return retVal;
1022
- }
1023
-
1024
-
1025
- function _disableDraggable(el) {
1026
- el.draggable = false;
1027
- }
1028
-
1029
-
1030
- function _unsilent() {
1031
- _silent = false;
1032
- }
1033
-
1034
-
1035
- /** @returns {HTMLElement|false} */
1036
- function _ghostInBottom(el, evt) {
1037
- var lastEl = el.lastElementChild,
1038
- rect = lastEl.getBoundingClientRect();
1039
-
1040
- return (evt.clientY - (rect.top + rect.height) > 5) && lastEl; // min delta
1041
- }
1042
-
1043
-
1044
- /**
1045
- * Generate id
1046
- * @param {HTMLElement} el
1047
- * @returns {String}
1048
- * @private
1049
- */
1050
- function _generateId(el) {
1051
- var str = el.tagName + el.className + el.src + el.href + el.textContent,
1052
- i = str.length,
1053
- sum = 0;
1054
-
1055
- while (i--) {
1056
- sum += str.charCodeAt(i);
1057
- }
1058
-
1059
- return sum.toString(36);
1060
- }
1061
-
1062
- /**
1063
- * Returns the index of an element within its parent
1064
- * @param el
1065
- * @returns {number}
1066
- * @private
1067
- */
1068
- function _index(/**HTMLElement*/el) {
1069
- var index = 0;
1070
- while (el && (el = el.previousElementSibling)) {
1071
- if (el.nodeName.toUpperCase() !== 'TEMPLATE') {
1072
- index++;
1073
- }
1074
- }
1075
- return index;
1076
- }
1077
-
1078
- function _throttle(callback, ms) {
1079
- var args, _this;
1080
-
1081
- return function () {
1082
- if (args === void 0) {
1083
- args = arguments;
1084
- _this = this;
1085
-
1086
- setTimeout(function () {
1087
- if (args.length === 1) {
1088
- callback.call(_this, args[0]);
1089
- } else {
1090
- callback.apply(_this, args);
1091
- }
1092
-
1093
- args = void 0;
1094
- }, ms);
1095
- }
1096
- };
1097
- }
1098
-
1099
- function _extend(dst, src) {
1100
- if (dst && src) {
1101
- for (var key in src) {
1102
- if (src.hasOwnProperty(key)) {
1103
- dst[key] = src[key];
1104
- }
1105
- }
1106
- }
1107
-
1108
- return dst;
1109
- }
1110
-
1111
-
1112
- // Export utils
1113
- Sortable.utils = {
1114
- on: _on,
1115
- off: _off,
1116
- css: _css,
1117
- find: _find,
1118
- bind: _bind,
1119
- is: function (el, selector) {
1120
- return !!_closest(el, selector, el);
1121
- },
1122
- extend: _extend,
1123
- throttle: _throttle,
1124
- closest: _closest,
1125
- toggleClass: _toggleClass,
1126
- index: _index
1127
- };
1128
-
1129
-
1130
- Sortable.version = '1.2.1';
1131
-
1132
-
1133
- /**
1134
- * Create sortable instance
1135
- * @param {HTMLElement} el
1136
- * @param {Object} [options]
1137
- */
1138
- Sortable.create = function (el, options) {
1139
- return new Sortable(el, options);
1140
- };
1141
-
1142
- // Export
1143
- return Sortable;
1362
+
1363
+ function _unsilent() {
1364
+ _silent = false;
1365
+ }
1366
+
1367
+
1368
+ /** @returns {HTMLElement|false} */
1369
+ function _ghostIsLast(el, evt) {
1370
+ var lastEl = el.lastElementChild,
1371
+ rect = lastEl.getBoundingClientRect();
1372
+
1373
+ // 5 — min delta
1374
+ // abs — нельзя добавлять, а то глюки при наведении сверху
1375
+ return (evt.clientY - (rect.top + rect.height) > 5) ||
1376
+ (evt.clientX - (rect.left + rect.width) > 5);
1377
+ }
1378
+
1379
+
1380
+ /**
1381
+ * Generate id
1382
+ * @param {HTMLElement} el
1383
+ * @returns {String}
1384
+ * @private
1385
+ */
1386
+ function _generateId(el) {
1387
+ var str = el.tagName + el.className + el.src + el.href + el.textContent,
1388
+ i = str.length,
1389
+ sum = 0;
1390
+
1391
+ while (i--) {
1392
+ sum += str.charCodeAt(i);
1393
+ }
1394
+
1395
+ return sum.toString(36);
1396
+ }
1397
+
1398
+ /**
1399
+ * Returns the index of an element within its parent for a selected set of
1400
+ * elements
1401
+ * @param {HTMLElement} el
1402
+ * @param {selector} selector
1403
+ * @return {number}
1404
+ */
1405
+ function _index(el, selector) {
1406
+ var index = 0;
1407
+
1408
+ if (!el || !el.parentNode) {
1409
+ return -1;
1410
+ }
1411
+
1412
+ while (el && (el = el.previousElementSibling)) {
1413
+ if ((el.nodeName.toUpperCase() !== 'TEMPLATE') && (selector === '>*' || _matches(el, selector))) {
1414
+ index++;
1415
+ }
1416
+ }
1417
+
1418
+ return index;
1419
+ }
1420
+
1421
+ function _matches(/**HTMLElement*/el, /**String*/selector) {
1422
+ if (el) {
1423
+ selector = selector.split('.');
1424
+
1425
+ var tag = selector.shift().toUpperCase(),
1426
+ re = new RegExp('\\s(' + selector.join('|') + ')(?=\\s)', 'g');
1427
+
1428
+ return (
1429
+ (tag === '' || el.nodeName.toUpperCase() == tag) &&
1430
+ (!selector.length || ((' ' + el.className + ' ').match(re) || []).length == selector.length)
1431
+ );
1432
+ }
1433
+
1434
+ return false;
1435
+ }
1436
+
1437
+ function _throttle(callback, ms) {
1438
+ var args, _this;
1439
+
1440
+ return function () {
1441
+ if (args === void 0) {
1442
+ args = arguments;
1443
+ _this = this;
1444
+
1445
+ setTimeout(function () {
1446
+ if (args.length === 1) {
1447
+ callback.call(_this, args[0]);
1448
+ } else {
1449
+ callback.apply(_this, args);
1450
+ }
1451
+
1452
+ args = void 0;
1453
+ }, ms);
1454
+ }
1455
+ };
1456
+ }
1457
+
1458
+ function _extend(dst, src) {
1459
+ if (dst && src) {
1460
+ for (var key in src) {
1461
+ if (src.hasOwnProperty(key)) {
1462
+ dst[key] = src[key];
1463
+ }
1464
+ }
1465
+ }
1466
+
1467
+ return dst;
1468
+ }
1469
+
1470
+ function _clone(el) {
1471
+ if (Polymer && Polymer.dom) {
1472
+ return Polymer.dom(el).cloneNode(true);
1473
+ }
1474
+ else if ($) {
1475
+ return $(el).clone(true)[0];
1476
+ }
1477
+ else {
1478
+ return el.cloneNode(true);
1479
+ }
1480
+ }
1481
+
1482
+ function _saveInputCheckedState(root) {
1483
+ var inputs = root.getElementsByTagName('input');
1484
+ var idx = inputs.length;
1485
+
1486
+ while (idx--) {
1487
+ var el = inputs[idx];
1488
+ el.checked && savedInputChecked.push(el);
1489
+ }
1490
+ }
1491
+
1492
+ function _nextTick(fn) {
1493
+ return setTimeout(fn, 0);
1494
+ }
1495
+
1496
+ function _cancelNextTick(id) {
1497
+ return clearTimeout(id);
1498
+ }
1499
+
1500
+ // Fixed #973:
1501
+ _on(document, 'touchmove', function (evt) {
1502
+ if (Sortable.active) {
1503
+ evt.preventDefault();
1504
+ }
1505
+ });
1506
+
1507
+ // Export utils
1508
+ Sortable.utils = {
1509
+ on: _on,
1510
+ off: _off,
1511
+ css: _css,
1512
+ find: _find,
1513
+ is: function (el, selector) {
1514
+ return !!_closest(el, selector, el);
1515
+ },
1516
+ extend: _extend,
1517
+ throttle: _throttle,
1518
+ closest: _closest,
1519
+ toggleClass: _toggleClass,
1520
+ clone: _clone,
1521
+ index: _index,
1522
+ nextTick: _nextTick,
1523
+ cancelNextTick: _cancelNextTick
1524
+ };
1525
+
1526
+
1527
+ /**
1528
+ * Create sortable instance
1529
+ * @param {HTMLElement} el
1530
+ * @param {Object} [options]
1531
+ */
1532
+ Sortable.create = function (el, options) {
1533
+ return new Sortable(el, options);
1534
+ };
1535
+
1536
+
1537
+ // Export
1538
+ Sortable.version = '1.7.0';
1539
+ return Sortable;
1144
1540
  });