railsblazer 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +0 -0
  4. data/.gitignore +14 -0
  5. data/CHANGELOG.md +247 -0
  6. data/CONTRIBUTING.md +42 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +855 -0
  10. data/Rakefile +1 -0
  11. data/app/assets/fonts/blazer/glyphicons-halflings-regular.eot +0 -0
  12. data/app/assets/fonts/blazer/glyphicons-halflings-regular.svg +288 -0
  13. data/app/assets/fonts/blazer/glyphicons-halflings-regular.ttf +0 -0
  14. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff +0 -0
  15. data/app/assets/fonts/blazer/glyphicons-halflings-regular.woff2 +0 -0
  16. data/app/assets/javascripts/blazer/Chart.js +14145 -0
  17. data/app/assets/javascripts/blazer/Sortable.js +1144 -0
  18. data/app/assets/javascripts/blazer/ace.js +6 -0
  19. data/app/assets/javascripts/blazer/ace/ace.js +11 -0
  20. data/app/assets/javascripts/blazer/ace/ext-language_tools.js +5 -0
  21. data/app/assets/javascripts/blazer/ace/mode-sql.js +1 -0
  22. data/app/assets/javascripts/blazer/ace/snippets/sql.js +1 -0
  23. data/app/assets/javascripts/blazer/ace/snippets/text.js +1 -0
  24. data/app/assets/javascripts/blazer/ace/theme-twilight.js +1 -0
  25. data/app/assets/javascripts/blazer/application.js +79 -0
  26. data/app/assets/javascripts/blazer/bootstrap.js +2366 -0
  27. data/app/assets/javascripts/blazer/chartkick.js +1693 -0
  28. data/app/assets/javascripts/blazer/daterangepicker.js +1505 -0
  29. data/app/assets/javascripts/blazer/fuzzysearch.js +24 -0
  30. data/app/assets/javascripts/blazer/highlight.pack.js +1 -0
  31. data/app/assets/javascripts/blazer/jquery.js +10308 -0
  32. data/app/assets/javascripts/blazer/jquery.stickytableheaders.js +263 -0
  33. data/app/assets/javascripts/blazer/jquery_ujs.js +469 -0
  34. data/app/assets/javascripts/blazer/moment-timezone.js +1007 -0
  35. data/app/assets/javascripts/blazer/moment.js +3043 -0
  36. data/app/assets/javascripts/blazer/queries.js +110 -0
  37. data/app/assets/javascripts/blazer/routes.js +23 -0
  38. data/app/assets/javascripts/blazer/selectize.js +3667 -0
  39. data/app/assets/javascripts/blazer/stupidtable.js +114 -0
  40. data/app/assets/javascripts/blazer/vue.js +7515 -0
  41. data/app/assets/stylesheets/blazer/application.css +198 -0
  42. data/app/assets/stylesheets/blazer/bootstrap.css.erb +6202 -0
  43. data/app/assets/stylesheets/blazer/daterangepicker-bs3.css +375 -0
  44. data/app/assets/stylesheets/blazer/github.css +125 -0
  45. data/app/assets/stylesheets/blazer/selectize.default.css +387 -0
  46. data/app/controllers/blazer/base_controller.rb +113 -0
  47. data/app/controllers/blazer/checks_controller.rb +56 -0
  48. data/app/controllers/blazer/dashboards_controller.rb +105 -0
  49. data/app/controllers/blazer/queries_controller.rb +337 -0
  50. data/app/helpers/blazer/base_helper.rb +57 -0
  51. data/app/mailers/blazer/check_mailer.rb +27 -0
  52. data/app/mailers/blazer/slack_notifier.rb +76 -0
  53. data/app/models/blazer/audit.rb +6 -0
  54. data/app/models/blazer/check.rb +104 -0
  55. data/app/models/blazer/connection.rb +5 -0
  56. data/app/models/blazer/dashboard.rb +13 -0
  57. data/app/models/blazer/dashboard_query.rb +9 -0
  58. data/app/models/blazer/query.rb +40 -0
  59. data/app/models/blazer/record.rb +5 -0
  60. data/app/views/blazer/_nav.html.erb +16 -0
  61. data/app/views/blazer/_variables.html.erb +102 -0
  62. data/app/views/blazer/check_mailer/failing_checks.html.erb +6 -0
  63. data/app/views/blazer/check_mailer/state_change.html.erb +47 -0
  64. data/app/views/blazer/checks/_form.html.erb +79 -0
  65. data/app/views/blazer/checks/edit.html.erb +1 -0
  66. data/app/views/blazer/checks/index.html.erb +43 -0
  67. data/app/views/blazer/checks/new.html.erb +1 -0
  68. data/app/views/blazer/dashboards/_form.html.erb +76 -0
  69. data/app/views/blazer/dashboards/edit.html.erb +1 -0
  70. data/app/views/blazer/dashboards/new.html.erb +1 -0
  71. data/app/views/blazer/dashboards/show.html.erb +47 -0
  72. data/app/views/blazer/queries/_form.html.erb +240 -0
  73. data/app/views/blazer/queries/edit.html.erb +2 -0
  74. data/app/views/blazer/queries/home.html.erb +152 -0
  75. data/app/views/blazer/queries/new.html.erb +2 -0
  76. data/app/views/blazer/queries/run.html.erb +165 -0
  77. data/app/views/blazer/queries/schema.html.erb +20 -0
  78. data/app/views/blazer/queries/show.html.erb +73 -0
  79. data/app/views/layouts/blazer/application.html.erb +24 -0
  80. data/blazer-0.0.1.gem +0 -0
  81. data/blazer.gemspec +27 -0
  82. data/config/routes.rb +16 -0
  83. data/lib/blazer.rb +223 -0
  84. data/lib/blazer/adapters/athena_adapter.rb +128 -0
  85. data/lib/blazer/adapters/base_adapter.rb +53 -0
  86. data/lib/blazer/adapters/bigquery_adapter.rb +68 -0
  87. data/lib/blazer/adapters/cassandra_adapter.rb +59 -0
  88. data/lib/blazer/adapters/drill_adapter.rb +28 -0
  89. data/lib/blazer/adapters/druid_adapter.rb +67 -0
  90. data/lib/blazer/adapters/elasticsearch_adapter.rb +46 -0
  91. data/lib/blazer/adapters/mongodb_adapter.rb +39 -0
  92. data/lib/blazer/adapters/presto_adapter.rb +45 -0
  93. data/lib/blazer/adapters/snowflake_adapter.rb +73 -0
  94. data/lib/blazer/adapters/sql_adapter.rb +182 -0
  95. data/lib/blazer/data_source.rb +195 -0
  96. data/lib/blazer/detect_anomalies.R +19 -0
  97. data/lib/blazer/engine.rb +30 -0
  98. data/lib/blazer/result.rb +170 -0
  99. data/lib/blazer/run_statement.rb +40 -0
  100. data/lib/blazer/run_statement_job.rb +21 -0
  101. data/lib/blazer/version.rb +3 -0
  102. data/lib/generators/blazer/install_generator.rb +39 -0
  103. data/lib/generators/blazer/templates/config.yml.tt +62 -0
  104. data/lib/generators/blazer/templates/install.rb.tt +46 -0
  105. data/lib/tasks/blazer.rake +11 -0
  106. data/railsblazer-0.0.1.gem +0 -0
  107. metadata +234 -0
@@ -0,0 +1,1144 @@
1
+ /**!
2
+ * Sortable
3
+ * @author RubaXa <trash@rubaxa.org>
4
+ * @license MIT
5
+ */
6
+
7
+
8
+ (function (factory) {
9
+ "use strict";
10
+
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";
26
+
27
+ var dragEl,
28
+ ghostEl,
29
+ cloneEl,
30
+ rootEl,
31
+ nextEl,
32
+
33
+ scrollEl,
34
+ scrollParentEl,
35
+
36
+ lastEl,
37
+ lastCSS,
38
+
39
+ oldIndex,
40
+ newIndex,
41
+
42
+ activeGroup,
43
+ autoScroll = {},
44
+
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
+
57
+ supportDraggable = !!('draggable' in document.createElement('div')),
58
+
59
+ _silent = false,
60
+
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
+
125
+ clearInterval(autoScroll.pid);
126
+
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
+
142
+
143
+
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);
152
+
153
+
154
+ // Export instance
155
+ el[expando] = this;
156
+
157
+
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;
240
+
241
+
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
+ }
901
+
902
+ return null;
903
+ }
904
+
905
+
906
+ function _globalDragOver(/**Event*/evt) {
907
+ evt.dataTransfer.dropEffect = 'move';
908
+ evt.preventDefault();
909
+ }
910
+
911
+
912
+ function _on(el, event, fn) {
913
+ el.addEventListener(event, fn, false);
914
+ }
915
+
916
+
917
+ function _off(el, event, fn) {
918
+ el.removeEventListener(event, fn, false);
919
+ }
920
+
921
+
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
+ }
933
+
934
+
935
+ function _css(el, prop, val) {
936
+ var style = el && el.style;
937
+
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
+ }
946
+
947
+ return prop === void 0 ? val : val[prop];
948
+ }
949
+ else {
950
+ if (!(prop in style)) {
951
+ prop = '-webkit-' + prop;
952
+ }
953
+
954
+ style[prop] = val + (typeof val === 'string' ? '' : 'px');
955
+ }
956
+ }
957
+ }
958
+
959
+
960
+ function _find(ctx, tagName, iterator) {
961
+ if (ctx) {
962
+ var list = ctx.getElementsByTagName(tagName), i = 0, n = list.length;
963
+
964
+ if (iterator) {
965
+ for (; i < n; i++) {
966
+ iterator(list[i], i);
967
+ }
968
+ }
969
+
970
+ return list;
971
+ }
972
+
973
+ return [];
974
+ }
975
+
976
+
977
+
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
+
1000
+
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;
1144
+ });