comparison vakata-jstree-3.3.5/src/jstree.dnd.js @ 1:32210899a3dd draft

planemo upload commit 841d8b22bf9f1aaed6bfe8344b60617f45b275b2-dirty
author mingchen0919
date Sun, 30 Dec 2018 12:45:56 -0500
parents
children
comparison
equal deleted inserted replaced
0:6f94b4b9de44 1:32210899a3dd
1 /**
2 * ### Drag'n'drop plugin
3 *
4 * Enables dragging and dropping of nodes in the tree, resulting in a move or copy operations.
5 */
6 /*globals jQuery, define, exports, require, document */
7 (function (factory) {
8 "use strict";
9 if (typeof define === 'function' && define.amd) {
10 define('jstree.dnd', ['jquery','jstree'], factory);
11 }
12 else if(typeof exports === 'object') {
13 factory(require('jquery'), require('jstree'));
14 }
15 else {
16 factory(jQuery, jQuery.jstree);
17 }
18 }(function ($, jstree, undefined) {
19 "use strict";
20
21 if($.jstree.plugins.dnd) { return; }
22
23 /**
24 * stores all defaults for the drag'n'drop plugin
25 * @name $.jstree.defaults.dnd
26 * @plugin dnd
27 */
28 $.jstree.defaults.dnd = {
29 /**
30 * a boolean indicating if a copy should be possible while dragging (by pressint the meta key or Ctrl). Defaults to `true`.
31 * @name $.jstree.defaults.dnd.copy
32 * @plugin dnd
33 */
34 copy : true,
35 /**
36 * a number indicating how long a node should remain hovered while dragging to be opened. Defaults to `500`.
37 * @name $.jstree.defaults.dnd.open_timeout
38 * @plugin dnd
39 */
40 open_timeout : 500,
41 /**
42 * a function invoked each time a node is about to be dragged, invoked in the tree's scope and receives the nodes about to be dragged as an argument (array) and the event that started the drag - return `false` to prevent dragging
43 * @name $.jstree.defaults.dnd.is_draggable
44 * @plugin dnd
45 */
46 is_draggable : true,
47 /**
48 * a boolean indicating if checks should constantly be made while the user is dragging the node (as opposed to checking only on drop), default is `true`
49 * @name $.jstree.defaults.dnd.check_while_dragging
50 * @plugin dnd
51 */
52 check_while_dragging : true,
53 /**
54 * a boolean indicating if nodes from this tree should only be copied with dnd (as opposed to moved), default is `false`
55 * @name $.jstree.defaults.dnd.always_copy
56 * @plugin dnd
57 */
58 always_copy : false,
59 /**
60 * when dropping a node "inside", this setting indicates the position the node should go to - it can be an integer or a string: "first" (same as 0) or "last", default is `0`
61 * @name $.jstree.defaults.dnd.inside_pos
62 * @plugin dnd
63 */
64 inside_pos : 0,
65 /**
66 * when starting the drag on a node that is selected this setting controls if all selected nodes are dragged or only the single node, default is `true`, which means all selected nodes are dragged when the drag is started on a selected node
67 * @name $.jstree.defaults.dnd.drag_selection
68 * @plugin dnd
69 */
70 drag_selection : true,
71 /**
72 * controls whether dnd works on touch devices. If left as boolean true dnd will work the same as in desktop browsers, which in some cases may impair scrolling. If set to boolean false dnd will not work on touch devices. There is a special third option - string "selected" which means only selected nodes can be dragged on touch devices.
73 * @name $.jstree.defaults.dnd.touch
74 * @plugin dnd
75 */
76 touch : true,
77 /**
78 * controls whether items can be dropped anywhere on the node, not just on the anchor, by default only the node anchor is a valid drop target. Works best with the wholerow plugin. If enabled on mobile depending on the interface it might be hard for the user to cancel the drop, since the whole tree container will be a valid drop target.
79 * @name $.jstree.defaults.dnd.large_drop_target
80 * @plugin dnd
81 */
82 large_drop_target : false,
83 /**
84 * controls whether a drag can be initiated from any part of the node and not just the text/icon part, works best with the wholerow plugin. Keep in mind it can cause problems with tree scrolling on mobile depending on the interface - in that case set the touch option to "selected".
85 * @name $.jstree.defaults.dnd.large_drag_target
86 * @plugin dnd
87 */
88 large_drag_target : false,
89 /**
90 * controls whether use HTML5 dnd api instead of classical. That will allow better integration of dnd events with other HTML5 controls.
91 * @reference http://caniuse.com/#feat=dragndrop
92 * @name $.jstree.defaults.dnd.use_html5
93 * @plugin dnd
94 */
95 use_html5: false
96 };
97 var drg, elm;
98 // TODO: now check works by checking for each node individually, how about max_children, unique, etc?
99 $.jstree.plugins.dnd = function (options, parent) {
100 this.init = function (el, options) {
101 parent.init.call(this, el, options);
102 this.settings.dnd.use_html5 = this.settings.dnd.use_html5 && ('draggable' in document.createElement('span'));
103 };
104 this.bind = function () {
105 parent.bind.call(this);
106
107 this.element
108 .on(this.settings.dnd.use_html5 ? 'dragstart.jstree' : 'mousedown.jstree touchstart.jstree', this.settings.dnd.large_drag_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
109 if(this.settings.dnd.large_drag_target && $(e.target).closest('.jstree-node')[0] !== e.currentTarget) {
110 return true;
111 }
112 if(e.type === "touchstart" && (!this.settings.dnd.touch || (this.settings.dnd.touch === 'selected' && !$(e.currentTarget).closest('.jstree-node').children('.jstree-anchor').hasClass('jstree-clicked')))) {
113 return true;
114 }
115 var obj = this.get_node(e.target),
116 mlt = this.is_selected(obj) && this.settings.dnd.drag_selection ? this.get_top_selected().length : 1,
117 txt = (mlt > 1 ? mlt + ' ' + this.get_string('nodes') : this.get_text(e.currentTarget));
118 if(this.settings.core.force_text) {
119 txt = $.vakata.html.escape(txt);
120 }
121 if(obj && obj.id && obj.id !== $.jstree.root && (e.which === 1 || e.type === "touchstart" || e.type === "dragstart") &&
122 (this.settings.dnd.is_draggable === true || ($.isFunction(this.settings.dnd.is_draggable) && this.settings.dnd.is_draggable.call(this, (mlt > 1 ? this.get_top_selected(true) : [obj]), e)))
123 ) {
124 drg = { 'jstree' : true, 'origin' : this, 'obj' : this.get_node(obj,true), 'nodes' : mlt > 1 ? this.get_top_selected() : [obj.id] };
125 elm = e.currentTarget;
126 if (this.settings.dnd.use_html5) {
127 $.vakata.dnd._trigger('start', e, { 'helper': $(), 'element': elm, 'data': drg });
128 } else {
129 this.element.trigger('mousedown.jstree');
130 return $.vakata.dnd.start(e, drg, '<div id="jstree-dnd" class="jstree-' + this.get_theme() + ' jstree-' + this.get_theme() + '-' + this.get_theme_variant() + ' ' + ( this.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ) + '"><i class="jstree-icon jstree-er"></i>' + txt + '<ins class="jstree-copy" style="display:none;">+</ins></div>');
131 }
132 }
133 }, this));
134 if (this.settings.dnd.use_html5) {
135 this.element
136 .on('dragover.jstree', function (e) {
137 e.preventDefault();
138 $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
139 return false;
140 })
141 //.on('dragenter.jstree', this.settings.dnd.large_drop_target ? '.jstree-node' : '.jstree-anchor', $.proxy(function (e) {
142 // e.preventDefault();
143 // $.vakata.dnd._trigger('move', e, { 'helper': $(), 'element': elm, 'data': drg });
144 // return false;
145 // }, this))
146 .on('drop.jstree', $.proxy(function (e) {
147 e.preventDefault();
148 $.vakata.dnd._trigger('stop', e, { 'helper': $(), 'element': elm, 'data': drg });
149 return false;
150 }, this));
151 }
152 };
153 this.redraw_node = function(obj, deep, callback, force_render) {
154 obj = parent.redraw_node.apply(this, arguments);
155 if (obj && this.settings.dnd.use_html5) {
156 if (this.settings.dnd.large_drag_target) {
157 obj.setAttribute('draggable', true);
158 } else {
159 var i, j, tmp = null;
160 for(i = 0, j = obj.childNodes.length; i < j; i++) {
161 if(obj.childNodes[i] && obj.childNodes[i].className && obj.childNodes[i].className.indexOf("jstree-anchor") !== -1) {
162 tmp = obj.childNodes[i];
163 break;
164 }
165 }
166 if(tmp) {
167 tmp.setAttribute('draggable', true);
168 }
169 }
170 }
171 return obj;
172 };
173 };
174
175 $(function() {
176 // bind only once for all instances
177 var lastmv = false,
178 laster = false,
179 lastev = false,
180 opento = false,
181 marker = $('<div id="jstree-marker">&#160;</div>').hide(); //.appendTo('body');
182
183 $(document)
184 .on('dnd_start.vakata.jstree', function (e, data) {
185 lastmv = false;
186 lastev = false;
187 if(!data || !data.data || !data.data.jstree) { return; }
188 marker.appendTo('body'); //.show();
189 })
190 .on('dnd_move.vakata.jstree', function (e, data) {
191 var isDifferentNode = data.event.target !== lastev.target;
192 if(opento) {
193 if (!data.event || data.event.type !== 'dragover' || isDifferentNode) {
194 clearTimeout(opento);
195 }
196 }
197 if(!data || !data.data || !data.data.jstree) { return; }
198
199 // if we are hovering the marker image do nothing (can happen on "inside" drags)
200 if(data.event.target.id && data.event.target.id === 'jstree-marker') {
201 return;
202 }
203 lastev = data.event;
204
205 var ins = $.jstree.reference(data.event.target),
206 ref = false,
207 off = false,
208 rel = false,
209 tmp, l, t, h, p, i, o, ok, t1, t2, op, ps, pr, ip, tm, is_copy, pn;
210 // if we are over an instance
211 if(ins && ins._data && ins._data.dnd) {
212 marker.attr('class', 'jstree-' + ins.get_theme() + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ));
213 is_copy = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)));
214 data.helper
215 .children().attr('class', 'jstree-' + ins.get_theme() + ' jstree-' + ins.get_theme() + '-' + ins.get_theme_variant() + ' ' + ( ins.settings.core.themes.responsive ? ' jstree-dnd-responsive' : '' ))
216 .find('.jstree-copy').first()[ is_copy ? 'show' : 'hide' ]();
217
218 // if are hovering the container itself add a new root node
219 //console.log(data.event);
220 if( (data.event.target === ins.element[0] || data.event.target === ins.get_container_ul()[0]) && ins.get_container_ul().children().length === 0) {
221 ok = true;
222 for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
223 ok = ok && ins.check( (data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey)) ) ? "copy_node" : "move_node"), (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), $.jstree.root, 'last', { 'dnd' : true, 'ref' : ins.get_node($.jstree.root), 'pos' : 'i', 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) });
224 if(!ok) { break; }
225 }
226 if(ok) {
227 lastmv = { 'ins' : ins, 'par' : $.jstree.root, 'pos' : 'last' };
228 marker.hide();
229 data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
230 if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
231 data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
232 }
233 return;
234 }
235 }
236 else {
237 // if we are hovering a tree node
238 ref = ins.settings.dnd.large_drop_target ? $(data.event.target).closest('.jstree-node').children('.jstree-anchor') : $(data.event.target).closest('.jstree-anchor');
239 if(ref && ref.length && ref.parent().is('.jstree-closed, .jstree-open, .jstree-leaf')) {
240 off = ref.offset();
241 rel = (data.event.pageY !== undefined ? data.event.pageY : data.event.originalEvent.pageY) - off.top;
242 h = ref.outerHeight();
243 if(rel < h / 3) {
244 o = ['b', 'i', 'a'];
245 }
246 else if(rel > h - h / 3) {
247 o = ['a', 'i', 'b'];
248 }
249 else {
250 o = rel > h / 2 ? ['i', 'a', 'b'] : ['i', 'b', 'a'];
251 }
252 $.each(o, function (j, v) {
253 switch(v) {
254 case 'b':
255 l = off.left - 6;
256 t = off.top;
257 p = ins.get_parent(ref);
258 i = ref.parent().index();
259 break;
260 case 'i':
261 ip = ins.settings.dnd.inside_pos;
262 tm = ins.get_node(ref.parent());
263 l = off.left - 2;
264 t = off.top + h / 2 + 1;
265 p = tm.id;
266 i = ip === 'first' ? 0 : (ip === 'last' ? tm.children.length : Math.min(ip, tm.children.length));
267 break;
268 case 'a':
269 l = off.left - 6;
270 t = off.top + h;
271 p = ins.get_parent(ref);
272 i = ref.parent().index() + 1;
273 break;
274 }
275 ok = true;
276 for(t1 = 0, t2 = data.data.nodes.length; t1 < t2; t1++) {
277 op = data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? "copy_node" : "move_node";
278 ps = i;
279 if(op === "move_node" && v === 'a' && (data.data.origin && data.data.origin === ins) && p === ins.get_parent(data.data.nodes[t1])) {
280 pr = ins.get_node(p);
281 if(ps > $.inArray(data.data.nodes[t1], pr.children)) {
282 ps -= 1;
283 }
284 }
285 ok = ok && ( (ins && ins.settings && ins.settings.dnd && ins.settings.dnd.check_while_dragging === false) || ins.check(op, (data.data.origin && data.data.origin !== ins ? data.data.origin.get_node(data.data.nodes[t1]) : data.data.nodes[t1]), p, ps, { 'dnd' : true, 'ref' : ins.get_node(ref.parent()), 'pos' : v, 'origin' : data.data.origin, 'is_multi' : (data.data.origin && data.data.origin !== ins), 'is_foreign' : (!data.data.origin) }) );
286 if(!ok) {
287 if(ins && ins.last_error) { laster = ins.last_error(); }
288 break;
289 }
290 }
291 if(v === 'i' && ref.parent().is('.jstree-closed') && ins.settings.dnd.open_timeout) {
292 if (!data.event || data.event.type !== 'dragover' || isDifferentNode) {
293 if (opento) { clearTimeout(opento); }
294 opento = setTimeout((function (x, z) { return function () { x.open_node(z); }; }(ins, ref)), ins.settings.dnd.open_timeout);
295 }
296 }
297 if(ok) {
298 pn = ins.get_node(p, true);
299 if (!pn.hasClass('.jstree-dnd-parent')) {
300 $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
301 pn.addClass('jstree-dnd-parent');
302 }
303 lastmv = { 'ins' : ins, 'par' : p, 'pos' : v === 'i' && ip === 'last' && i === 0 && !ins.is_loaded(tm) ? 'last' : i };
304 marker.css({ 'left' : l + 'px', 'top' : t + 'px' }).show();
305 data.helper.find('.jstree-icon').first().removeClass('jstree-er').addClass('jstree-ok');
306 if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
307 data.event.originalEvent.dataTransfer.dropEffect = is_copy ? 'copy' : 'move';
308 }
309 laster = {};
310 o = true;
311 return false;
312 }
313 });
314 if(o === true) { return; }
315 }
316 }
317 }
318 $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
319 lastmv = false;
320 data.helper.find('.jstree-icon').removeClass('jstree-ok').addClass('jstree-er');
321 if (data.event.originalEvent && data.event.originalEvent.dataTransfer) {
322 data.event.originalEvent.dataTransfer.dropEffect = 'none';
323 }
324 marker.hide();
325 })
326 .on('dnd_scroll.vakata.jstree', function (e, data) {
327 if(!data || !data.data || !data.data.jstree) { return; }
328 marker.hide();
329 lastmv = false;
330 lastev = false;
331 data.helper.find('.jstree-icon').first().removeClass('jstree-ok').addClass('jstree-er');
332 })
333 .on('dnd_stop.vakata.jstree', function (e, data) {
334 $('.jstree-dnd-parent').removeClass('jstree-dnd-parent');
335 if(opento) { clearTimeout(opento); }
336 if(!data || !data.data || !data.data.jstree) { return; }
337 marker.hide().detach();
338 var i, j, nodes = [];
339 if(lastmv) {
340 for(i = 0, j = data.data.nodes.length; i < j; i++) {
341 nodes[i] = data.data.origin ? data.data.origin.get_node(data.data.nodes[i]) : data.data.nodes[i];
342 }
343 lastmv.ins[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (data.event.metaKey || data.event.ctrlKey))) ? 'copy_node' : 'move_node' ](nodes, lastmv.par, lastmv.pos, false, false, false, data.data.origin);
344 }
345 else {
346 i = $(data.event.target).closest('.jstree');
347 if(i.length && laster && laster.error && laster.error === 'check') {
348 i = i.jstree(true);
349 if(i) {
350 i.settings.core.error.call(this, laster);
351 }
352 }
353 }
354 lastev = false;
355 lastmv = false;
356 })
357 .on('keyup.jstree keydown.jstree', function (e, data) {
358 data = $.vakata.dnd._get();
359 if(data && data.data && data.data.jstree) {
360 if (e.type === "keyup" && e.which === 27) {
361 if (opento) { clearTimeout(opento); }
362 lastmv = false;
363 laster = false;
364 lastev = false;
365 opento = false;
366 marker.hide().detach();
367 $.vakata.dnd._clean();
368 } else {
369 data.helper.find('.jstree-copy').first()[ data.data.origin && (data.data.origin.settings.dnd.always_copy || (data.data.origin.settings.dnd.copy && (e.metaKey || e.ctrlKey))) ? 'show' : 'hide' ]();
370 if(lastev) {
371 lastev.metaKey = e.metaKey;
372 lastev.ctrlKey = e.ctrlKey;
373 $.vakata.dnd._trigger('move', lastev);
374 }
375 }
376 }
377 });
378 });
379
380 // helpers
381 (function ($) {
382 $.vakata.html = {
383 div : $('<div />'),
384 escape : function (str) {
385 return $.vakata.html.div.text(str).html();
386 },
387 strip : function (str) {
388 return $.vakata.html.div.empty().append($.parseHTML(str)).text();
389 }
390 };
391 // private variable
392 var vakata_dnd = {
393 element : false,
394 target : false,
395 is_down : false,
396 is_drag : false,
397 helper : false,
398 helper_w: 0,
399 data : false,
400 init_x : 0,
401 init_y : 0,
402 scroll_l: 0,
403 scroll_t: 0,
404 scroll_e: false,
405 scroll_i: false,
406 is_touch: false
407 };
408 $.vakata.dnd = {
409 settings : {
410 scroll_speed : 10,
411 scroll_proximity : 20,
412 helper_left : 5,
413 helper_top : 10,
414 threshold : 5,
415 threshold_touch : 10
416 },
417 _trigger : function (event_name, e, data) {
418 if (data === undefined) {
419 data = $.vakata.dnd._get();
420 }
421 data.event = e;
422 $(document).triggerHandler("dnd_" + event_name + ".vakata", data);
423 },
424 _get : function () {
425 return {
426 "data" : vakata_dnd.data,
427 "element" : vakata_dnd.element,
428 "helper" : vakata_dnd.helper
429 };
430 },
431 _clean : function () {
432 if(vakata_dnd.helper) { vakata_dnd.helper.remove(); }
433 if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
434 vakata_dnd = {
435 element : false,
436 target : false,
437 is_down : false,
438 is_drag : false,
439 helper : false,
440 helper_w: 0,
441 data : false,
442 init_x : 0,
443 init_y : 0,
444 scroll_l: 0,
445 scroll_t: 0,
446 scroll_e: false,
447 scroll_i: false,
448 is_touch: false
449 };
450 $(document).off("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag);
451 $(document).off("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop);
452 },
453 _scroll : function (init_only) {
454 if(!vakata_dnd.scroll_e || (!vakata_dnd.scroll_l && !vakata_dnd.scroll_t)) {
455 if(vakata_dnd.scroll_i) { clearInterval(vakata_dnd.scroll_i); vakata_dnd.scroll_i = false; }
456 return false;
457 }
458 if(!vakata_dnd.scroll_i) {
459 vakata_dnd.scroll_i = setInterval($.vakata.dnd._scroll, 100);
460 return false;
461 }
462 if(init_only === true) { return false; }
463
464 var i = vakata_dnd.scroll_e.scrollTop(),
465 j = vakata_dnd.scroll_e.scrollLeft();
466 vakata_dnd.scroll_e.scrollTop(i + vakata_dnd.scroll_t * $.vakata.dnd.settings.scroll_speed);
467 vakata_dnd.scroll_e.scrollLeft(j + vakata_dnd.scroll_l * $.vakata.dnd.settings.scroll_speed);
468 if(i !== vakata_dnd.scroll_e.scrollTop() || j !== vakata_dnd.scroll_e.scrollLeft()) {
469 /**
470 * triggered on the document when a drag causes an element to scroll
471 * @event
472 * @plugin dnd
473 * @name dnd_scroll.vakata
474 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
475 * @param {DOM} element the DOM element being dragged
476 * @param {jQuery} helper the helper shown next to the mouse
477 * @param {jQuery} event the element that is scrolling
478 */
479 $.vakata.dnd._trigger("scroll", vakata_dnd.scroll_e);
480 }
481 },
482 start : function (e, data, html) {
483 if(e.type === "touchstart" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
484 e.pageX = e.originalEvent.changedTouches[0].pageX;
485 e.pageY = e.originalEvent.changedTouches[0].pageY;
486 e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
487 }
488 if(vakata_dnd.is_drag) { $.vakata.dnd.stop({}); }
489 try {
490 e.currentTarget.unselectable = "on";
491 e.currentTarget.onselectstart = function() { return false; };
492 if(e.currentTarget.style) {
493 e.currentTarget.style.touchAction = "none";
494 e.currentTarget.style.msTouchAction = "none";
495 e.currentTarget.style.MozUserSelect = "none";
496 }
497 } catch(ignore) { }
498 vakata_dnd.init_x = e.pageX;
499 vakata_dnd.init_y = e.pageY;
500 vakata_dnd.data = data;
501 vakata_dnd.is_down = true;
502 vakata_dnd.element = e.currentTarget;
503 vakata_dnd.target = e.target;
504 vakata_dnd.is_touch = e.type === "touchstart";
505 if(html !== false) {
506 vakata_dnd.helper = $("<div id='vakata-dnd'></div>").html(html).css({
507 "display" : "block",
508 "margin" : "0",
509 "padding" : "0",
510 "position" : "absolute",
511 "top" : "-2000px",
512 "lineHeight" : "16px",
513 "zIndex" : "10000"
514 });
515 }
516 $(document).on("mousemove.vakata.jstree touchmove.vakata.jstree", $.vakata.dnd.drag);
517 $(document).on("mouseup.vakata.jstree touchend.vakata.jstree", $.vakata.dnd.stop);
518 return false;
519 },
520 drag : function (e) {
521 if(e.type === "touchmove" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
522 e.pageX = e.originalEvent.changedTouches[0].pageX;
523 e.pageY = e.originalEvent.changedTouches[0].pageY;
524 e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
525 }
526 if(!vakata_dnd.is_down) { return; }
527 if(!vakata_dnd.is_drag) {
528 if(
529 Math.abs(e.pageX - vakata_dnd.init_x) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold) ||
530 Math.abs(e.pageY - vakata_dnd.init_y) > (vakata_dnd.is_touch ? $.vakata.dnd.settings.threshold_touch : $.vakata.dnd.settings.threshold)
531 ) {
532 if(vakata_dnd.helper) {
533 vakata_dnd.helper.appendTo("body");
534 vakata_dnd.helper_w = vakata_dnd.helper.outerWidth();
535 }
536 vakata_dnd.is_drag = true;
537 $(vakata_dnd.target).one('click.vakata', false);
538 /**
539 * triggered on the document when a drag starts
540 * @event
541 * @plugin dnd
542 * @name dnd_start.vakata
543 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
544 * @param {DOM} element the DOM element being dragged
545 * @param {jQuery} helper the helper shown next to the mouse
546 * @param {Object} event the event that caused the start (probably mousemove)
547 */
548 $.vakata.dnd._trigger("start", e);
549 }
550 else { return; }
551 }
552
553 var d = false, w = false,
554 dh = false, wh = false,
555 dw = false, ww = false,
556 dt = false, dl = false,
557 ht = false, hl = false;
558
559 vakata_dnd.scroll_t = 0;
560 vakata_dnd.scroll_l = 0;
561 vakata_dnd.scroll_e = false;
562 $($(e.target).parentsUntil("body").addBack().get().reverse())
563 .filter(function () {
564 return (/^auto|scroll$/).test($(this).css("overflow")) &&
565 (this.scrollHeight > this.offsetHeight || this.scrollWidth > this.offsetWidth);
566 })
567 .each(function () {
568 var t = $(this), o = t.offset();
569 if(this.scrollHeight > this.offsetHeight) {
570 if(o.top + t.height() - e.pageY < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; }
571 if(e.pageY - o.top < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; }
572 }
573 if(this.scrollWidth > this.offsetWidth) {
574 if(o.left + t.width() - e.pageX < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; }
575 if(e.pageX - o.left < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; }
576 }
577 if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
578 vakata_dnd.scroll_e = $(this);
579 return false;
580 }
581 });
582
583 if(!vakata_dnd.scroll_e) {
584 d = $(document); w = $(window);
585 dh = d.height(); wh = w.height();
586 dw = d.width(); ww = w.width();
587 dt = d.scrollTop(); dl = d.scrollLeft();
588 if(dh > wh && e.pageY - dt < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = -1; }
589 if(dh > wh && wh - (e.pageY - dt) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_t = 1; }
590 if(dw > ww && e.pageX - dl < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = -1; }
591 if(dw > ww && ww - (e.pageX - dl) < $.vakata.dnd.settings.scroll_proximity) { vakata_dnd.scroll_l = 1; }
592 if(vakata_dnd.scroll_t || vakata_dnd.scroll_l) {
593 vakata_dnd.scroll_e = d;
594 }
595 }
596 if(vakata_dnd.scroll_e) { $.vakata.dnd._scroll(true); }
597
598 if(vakata_dnd.helper) {
599 ht = parseInt(e.pageY + $.vakata.dnd.settings.helper_top, 10);
600 hl = parseInt(e.pageX + $.vakata.dnd.settings.helper_left, 10);
601 if(dh && ht + 25 > dh) { ht = dh - 50; }
602 if(dw && hl + vakata_dnd.helper_w > dw) { hl = dw - (vakata_dnd.helper_w + 2); }
603 vakata_dnd.helper.css({
604 left : hl + "px",
605 top : ht + "px"
606 });
607 }
608 /**
609 * triggered on the document when a drag is in progress
610 * @event
611 * @plugin dnd
612 * @name dnd_move.vakata
613 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
614 * @param {DOM} element the DOM element being dragged
615 * @param {jQuery} helper the helper shown next to the mouse
616 * @param {Object} event the event that caused this to trigger (most likely mousemove)
617 */
618 $.vakata.dnd._trigger("move", e);
619 return false;
620 },
621 stop : function (e) {
622 if(e.type === "touchend" && e.originalEvent && e.originalEvent.changedTouches && e.originalEvent.changedTouches[0]) {
623 e.pageX = e.originalEvent.changedTouches[0].pageX;
624 e.pageY = e.originalEvent.changedTouches[0].pageY;
625 e.target = document.elementFromPoint(e.originalEvent.changedTouches[0].pageX - window.pageXOffset, e.originalEvent.changedTouches[0].pageY - window.pageYOffset);
626 }
627 if(vakata_dnd.is_drag) {
628 /**
629 * triggered on the document when a drag stops (the dragged element is dropped)
630 * @event
631 * @plugin dnd
632 * @name dnd_stop.vakata
633 * @param {Mixed} data any data supplied with the call to $.vakata.dnd.start
634 * @param {DOM} element the DOM element being dragged
635 * @param {jQuery} helper the helper shown next to the mouse
636 * @param {Object} event the event that caused the stop
637 */
638 if (e.target !== vakata_dnd.target) {
639 $(vakata_dnd.target).off('click.vakata');
640 }
641 $.vakata.dnd._trigger("stop", e);
642 }
643 else {
644 if(e.type === "touchend" && e.target === vakata_dnd.target) {
645 var to = setTimeout(function () { $(e.target).click(); }, 100);
646 $(e.target).one('click', function() { if(to) { clearTimeout(to); } });
647 }
648 }
649 $.vakata.dnd._clean();
650 return false;
651 }
652 };
653 }($));
654
655 // include the dnd plugin by default
656 // $.jstree.defaults.plugins.push("dnd");
657 }));