jquery.draggable.js 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. /**
  2. * jQuery EasyUI 1.5.2
  3. *
  4. * Copyright (c) 2009-2017 www.jeasyui.com. All rights reserved.
  5. *
  6. * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
  7. * To use it on other terms please contact us: info@jeasyui.com
  8. *
  9. */
  10. /**
  11. * draggable - jQuery EasyUI
  12. *
  13. */
  14. (function($){
  15. function drag(e){
  16. var state = $.data(e.data.target, 'draggable');
  17. var opts = state.options;
  18. var proxy = state.proxy;
  19. var dragData = e.data;
  20. var left = dragData.startLeft + e.pageX - dragData.startX;
  21. var top = dragData.startTop + e.pageY - dragData.startY;
  22. if (proxy){
  23. if (proxy.parent()[0] == document.body){
  24. if (opts.deltaX != null && opts.deltaX != undefined){
  25. left = e.pageX + opts.deltaX;
  26. } else {
  27. left = e.pageX - e.data.offsetWidth;
  28. }
  29. if (opts.deltaY != null && opts.deltaY != undefined){
  30. top = e.pageY + opts.deltaY;
  31. } else {
  32. top = e.pageY - e.data.offsetHeight;
  33. }
  34. } else {
  35. if (opts.deltaX != null && opts.deltaX != undefined){
  36. left += e.data.offsetWidth + opts.deltaX;
  37. }
  38. if (opts.deltaY != null && opts.deltaY != undefined){
  39. top += e.data.offsetHeight + opts.deltaY;
  40. }
  41. }
  42. }
  43. if (e.data.parent != document.body) {
  44. left += $(e.data.parent).scrollLeft();
  45. top += $(e.data.parent).scrollTop();
  46. }
  47. if (opts.axis == 'h') {
  48. dragData.left = left;
  49. } else if (opts.axis == 'v') {
  50. dragData.top = top;
  51. } else {
  52. dragData.left = left;
  53. dragData.top = top;
  54. }
  55. }
  56. function applyDrag(e){
  57. var state = $.data(e.data.target, 'draggable');
  58. var opts = state.options;
  59. var proxy = state.proxy;
  60. if (!proxy){
  61. proxy = $(e.data.target);
  62. }
  63. proxy.css({
  64. left:e.data.left,
  65. top:e.data.top
  66. });
  67. $('body').css('cursor', opts.cursor);
  68. }
  69. function doDown(e){
  70. if (!$.fn.draggable.isDragging){return false;}
  71. var state = $.data(e.data.target, 'draggable');
  72. var opts = state.options;
  73. var droppables = $('.droppable:visible').filter(function(){
  74. return e.data.target != this;
  75. }).filter(function(){
  76. var accept = $.data(this, 'droppable').options.accept;
  77. if (accept){
  78. return $(accept).filter(function(){
  79. return this == e.data.target;
  80. }).length > 0;
  81. } else {
  82. return true;
  83. }
  84. });
  85. state.droppables = droppables;
  86. var proxy = state.proxy;
  87. if (!proxy){
  88. if (opts.proxy){
  89. if (opts.proxy == 'clone'){
  90. proxy = $(e.data.target).clone().insertAfter(e.data.target);
  91. } else {
  92. proxy = opts.proxy.call(e.data.target, e.data.target);
  93. }
  94. state.proxy = proxy;
  95. } else {
  96. proxy = $(e.data.target);
  97. }
  98. }
  99. proxy.css('position', 'absolute');
  100. drag(e);
  101. applyDrag(e);
  102. opts.onStartDrag.call(e.data.target, e);
  103. return false;
  104. }
  105. function doMove(e){
  106. if (!$.fn.draggable.isDragging){return false;}
  107. var state = $.data(e.data.target, 'draggable');
  108. drag(e);
  109. if (state.options.onDrag.call(e.data.target, e) != false){
  110. applyDrag(e);
  111. }
  112. var source = e.data.target;
  113. state.droppables.each(function(){
  114. var dropObj = $(this);
  115. if (dropObj.droppable('options').disabled){return;}
  116. var p2 = dropObj.offset();
  117. if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()
  118. && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){
  119. if (!this.entered){
  120. $(this).trigger('_dragenter', [source]);
  121. this.entered = true;
  122. }
  123. $(this).trigger('_dragover', [source]);
  124. } else {
  125. if (this.entered){
  126. $(this).trigger('_dragleave', [source]);
  127. this.entered = false;
  128. }
  129. }
  130. });
  131. return false;
  132. }
  133. function doUp(e){
  134. if (!$.fn.draggable.isDragging){
  135. clearDragging();
  136. return false;
  137. }
  138. doMove(e);
  139. var state = $.data(e.data.target, 'draggable');
  140. var proxy = state.proxy;
  141. var opts = state.options;
  142. if (opts.revert){
  143. if (checkDrop() == true){
  144. $(e.data.target).css({
  145. position:e.data.startPosition,
  146. left:e.data.startLeft,
  147. top:e.data.startTop
  148. });
  149. } else {
  150. if (proxy){
  151. var left, top;
  152. if (proxy.parent()[0] == document.body){
  153. left = e.data.startX - e.data.offsetWidth;
  154. top = e.data.startY - e.data.offsetHeight;
  155. } else {
  156. left = e.data.startLeft;
  157. top = e.data.startTop;
  158. }
  159. proxy.animate({
  160. left: left,
  161. top: top
  162. }, function(){
  163. removeProxy();
  164. });
  165. } else {
  166. $(e.data.target).animate({
  167. left:e.data.startLeft,
  168. top:e.data.startTop
  169. }, function(){
  170. $(e.data.target).css('position', e.data.startPosition);
  171. });
  172. }
  173. }
  174. } else {
  175. $(e.data.target).css({
  176. position:'absolute',
  177. left:e.data.left,
  178. top:e.data.top
  179. });
  180. checkDrop();
  181. }
  182. opts.onStopDrag.call(e.data.target, e);
  183. clearDragging();
  184. function removeProxy(){
  185. if (proxy){
  186. proxy.remove();
  187. }
  188. state.proxy = null;
  189. }
  190. function checkDrop(){
  191. var dropped = false;
  192. state.droppables.each(function(){
  193. var dropObj = $(this);
  194. if (dropObj.droppable('options').disabled){return;}
  195. var p2 = dropObj.offset();
  196. if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()
  197. && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){
  198. if (opts.revert){
  199. $(e.data.target).css({
  200. position:e.data.startPosition,
  201. left:e.data.startLeft,
  202. top:e.data.startTop
  203. });
  204. }
  205. $(this).trigger('_drop', [e.data.target]);
  206. removeProxy();
  207. dropped = true;
  208. this.entered = false;
  209. return false;
  210. }
  211. });
  212. if (!dropped && !opts.revert){
  213. removeProxy();
  214. }
  215. return dropped;
  216. }
  217. return false;
  218. }
  219. function clearDragging(){
  220. if ($.fn.draggable.timer){
  221. clearTimeout($.fn.draggable.timer);
  222. $.fn.draggable.timer = undefined;
  223. }
  224. $(document).unbind('.draggable');
  225. $.fn.draggable.isDragging = false;
  226. setTimeout(function(){
  227. $('body').css('cursor','');
  228. },100);
  229. }
  230. $.fn.draggable = function(options, param){
  231. if (typeof options == 'string'){
  232. return $.fn.draggable.methods[options](this, param);
  233. }
  234. return this.each(function(){
  235. var opts;
  236. var state = $.data(this, 'draggable');
  237. if (state) {
  238. state.handle.unbind('.draggable');
  239. opts = $.extend(state.options, options);
  240. } else {
  241. opts = $.extend({}, $.fn.draggable.defaults, $.fn.draggable.parseOptions(this), options || {});
  242. }
  243. var handle = opts.handle ? (typeof opts.handle=='string' ? $(opts.handle, this) : opts.handle) : $(this);
  244. $.data(this, 'draggable', {
  245. options: opts,
  246. handle: handle
  247. });
  248. if (opts.disabled) {
  249. $(this).css('cursor', '');
  250. return;
  251. }
  252. handle.unbind('.draggable').bind('mousemove.draggable', {target:this}, function(e){
  253. if ($.fn.draggable.isDragging){return}
  254. var opts = $.data(e.data.target, 'draggable').options;
  255. if (checkArea(e)){
  256. $(this).css('cursor', opts.cursor);
  257. } else {
  258. $(this).css('cursor', '');
  259. }
  260. }).bind('mouseleave.draggable', {target:this}, function(e){
  261. $(this).css('cursor', '');
  262. }).bind('mousedown.draggable', {target:this}, function(e){
  263. if (checkArea(e) == false) return;
  264. $(this).css('cursor', '');
  265. var position = $(e.data.target).position();
  266. var offset = $(e.data.target).offset();
  267. var data = {
  268. startPosition: $(e.data.target).css('position'),
  269. startLeft: position.left,
  270. startTop: position.top,
  271. left: position.left,
  272. top: position.top,
  273. startX: e.pageX,
  274. startY: e.pageY,
  275. width: $(e.data.target).outerWidth(),
  276. height: $(e.data.target).outerHeight(),
  277. offsetWidth: (e.pageX - offset.left),
  278. offsetHeight: (e.pageY - offset.top),
  279. target: e.data.target,
  280. parent: $(e.data.target).parent()[0]
  281. };
  282. $.extend(e.data, data);
  283. var opts = $.data(e.data.target, 'draggable').options;
  284. if (opts.onBeforeDrag.call(e.data.target, e) == false) return;
  285. $(document).bind('mousedown.draggable', e.data, doDown);
  286. $(document).bind('mousemove.draggable', e.data, doMove);
  287. $(document).bind('mouseup.draggable', e.data, doUp);
  288. $.fn.draggable.timer = setTimeout(function(){
  289. $.fn.draggable.isDragging = true;
  290. doDown(e);
  291. }, opts.delay);
  292. return false;
  293. });
  294. // check if the handle can be dragged
  295. function checkArea(e) {
  296. var state = $.data(e.data.target, 'draggable');
  297. var handle = state.handle;
  298. var offset = $(handle).offset();
  299. var width = $(handle).outerWidth();
  300. var height = $(handle).outerHeight();
  301. var t = e.pageY - offset.top;
  302. var r = offset.left + width - e.pageX;
  303. var b = offset.top + height - e.pageY;
  304. var l = e.pageX - offset.left;
  305. return Math.min(t,r,b,l) > state.options.edge;
  306. }
  307. });
  308. };
  309. $.fn.draggable.methods = {
  310. options: function(jq){
  311. return $.data(jq[0], 'draggable').options;
  312. },
  313. proxy: function(jq){
  314. return $.data(jq[0], 'draggable').proxy;
  315. },
  316. enable: function(jq){
  317. return jq.each(function(){
  318. $(this).draggable({disabled:false});
  319. });
  320. },
  321. disable: function(jq){
  322. return jq.each(function(){
  323. $(this).draggable({disabled:true});
  324. });
  325. }
  326. };
  327. $.fn.draggable.parseOptions = function(target){
  328. var t = $(target);
  329. return $.extend({},
  330. $.parser.parseOptions(target, ['cursor','handle','axis',
  331. {'revert':'boolean','deltaX':'number','deltaY':'number','edge':'number','delay':'number'}]), {
  332. disabled: (t.attr('disabled') ? true : undefined)
  333. });
  334. };
  335. $.fn.draggable.defaults = {
  336. proxy:null, // 'clone' or a function that will create the proxy object,
  337. // the function has the source parameter that indicate the source object dragged.
  338. revert:false,
  339. cursor:'move',
  340. deltaX:null,
  341. deltaY:null,
  342. handle: null,
  343. disabled: false,
  344. edge:0,
  345. axis:null, // v or h
  346. delay:100,
  347. onBeforeDrag: function(e){},
  348. onStartDrag: function(e){},
  349. onDrag: function(e){},
  350. onStopDrag: function(e){}
  351. };
  352. $.fn.draggable.isDragging = false;
  353. })(jQuery);