jquery.draggable.js 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /**
  2. * EasyUI for jQuery 1.5.5.6
  3. *
  4. * Copyright (c) 2009-2018 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 - EasyUI for jQuery
  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. opts.onEndDrag.call(e.data.target, e);
  143. if (opts.revert){
  144. if (checkDrop() == true){
  145. $(e.data.target).css({
  146. position:e.data.startPosition,
  147. left:e.data.startLeft,
  148. top:e.data.startTop
  149. });
  150. } else {
  151. if (proxy){
  152. var left, top;
  153. if (proxy.parent()[0] == document.body){
  154. left = e.data.startX - e.data.offsetWidth;
  155. top = e.data.startY - e.data.offsetHeight;
  156. } else {
  157. left = e.data.startLeft;
  158. top = e.data.startTop;
  159. }
  160. proxy.animate({
  161. left: left,
  162. top: top
  163. }, function(){
  164. removeProxy();
  165. });
  166. } else {
  167. $(e.data.target).animate({
  168. left:e.data.startLeft,
  169. top:e.data.startTop
  170. }, function(){
  171. $(e.data.target).css('position', e.data.startPosition);
  172. });
  173. }
  174. }
  175. } else {
  176. $(e.data.target).css({
  177. position:'absolute',
  178. left:e.data.left,
  179. top:e.data.top
  180. });
  181. checkDrop();
  182. }
  183. opts.onStopDrag.call(e.data.target, e);
  184. clearDragging();
  185. function removeProxy(){
  186. if (proxy){
  187. proxy.remove();
  188. }
  189. state.proxy = null;
  190. }
  191. function checkDrop(){
  192. var dropped = false;
  193. state.droppables.each(function(){
  194. var dropObj = $(this);
  195. if (dropObj.droppable('options').disabled){return;}
  196. var p2 = dropObj.offset();
  197. if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()
  198. && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){
  199. if (opts.revert){
  200. $(e.data.target).css({
  201. position:e.data.startPosition,
  202. left:e.data.startLeft,
  203. top:e.data.startTop
  204. });
  205. }
  206. $(this).triggerHandler('_drop', [e.data.target]);
  207. removeProxy();
  208. dropped = true;
  209. this.entered = false;
  210. return false;
  211. }
  212. });
  213. if (!dropped && !opts.revert){
  214. removeProxy();
  215. }
  216. return dropped;
  217. }
  218. return false;
  219. }
  220. function clearDragging(){
  221. if ($.fn.draggable.timer){
  222. clearTimeout($.fn.draggable.timer);
  223. $.fn.draggable.timer = undefined;
  224. }
  225. $(document).unbind('.draggable');
  226. $.fn.draggable.isDragging = false;
  227. setTimeout(function(){
  228. $('body').css('cursor','');
  229. },100);
  230. }
  231. $.fn.draggable = function(options, param){
  232. if (typeof options == 'string'){
  233. return $.fn.draggable.methods[options](this, param);
  234. }
  235. return this.each(function(){
  236. var opts;
  237. var state = $.data(this, 'draggable');
  238. if (state) {
  239. state.handle.unbind('.draggable');
  240. opts = $.extend(state.options, options);
  241. } else {
  242. opts = $.extend({}, $.fn.draggable.defaults, $.fn.draggable.parseOptions(this), options || {});
  243. }
  244. var handle = opts.handle ? (typeof opts.handle=='string' ? $(opts.handle, this) : opts.handle) : $(this);
  245. $.data(this, 'draggable', {
  246. options: opts,
  247. handle: handle
  248. });
  249. if (opts.disabled) {
  250. $(this).css('cursor', '');
  251. return;
  252. }
  253. handle.unbind('.draggable').bind('mousemove.draggable', {target:this}, function(e){
  254. if ($.fn.draggable.isDragging){return}
  255. var opts = $.data(e.data.target, 'draggable').options;
  256. if (checkArea(e)){
  257. $(this).css('cursor', opts.cursor);
  258. } else {
  259. $(this).css('cursor', '');
  260. }
  261. }).bind('mouseleave.draggable', {target:this}, function(e){
  262. $(this).css('cursor', '');
  263. }).bind('mousedown.draggable', {target:this}, function(e){
  264. if (checkArea(e) == false) return;
  265. $(this).css('cursor', '');
  266. var position = $(e.data.target).position();
  267. var offset = $(e.data.target).offset();
  268. var data = {
  269. startPosition: $(e.data.target).css('position'),
  270. startLeft: position.left,
  271. startTop: position.top,
  272. left: position.left,
  273. top: position.top,
  274. startX: e.pageX,
  275. startY: e.pageY,
  276. width: $(e.data.target).outerWidth(),
  277. height: $(e.data.target).outerHeight(),
  278. offsetWidth: (e.pageX - offset.left),
  279. offsetHeight: (e.pageY - offset.top),
  280. target: e.data.target,
  281. parent: $(e.data.target).parent()[0]
  282. };
  283. $.extend(e.data, data);
  284. var opts = $.data(e.data.target, 'draggable').options;
  285. if (opts.onBeforeDrag.call(e.data.target, e) == false) return;
  286. $(document).bind('mousedown.draggable', e.data, doDown);
  287. $(document).bind('mousemove.draggable', e.data, doMove);
  288. $(document).bind('mouseup.draggable', e.data, doUp);
  289. $.fn.draggable.timer = setTimeout(function(){
  290. $.fn.draggable.isDragging = true;
  291. doDown(e);
  292. }, opts.delay);
  293. return false;
  294. });
  295. // check if the handle can be dragged
  296. function checkArea(e) {
  297. var state = $.data(e.data.target, 'draggable');
  298. var handle = state.handle;
  299. var offset = $(handle).offset();
  300. var width = $(handle).outerWidth();
  301. var height = $(handle).outerHeight();
  302. var t = e.pageY - offset.top;
  303. var r = offset.left + width - e.pageX;
  304. var b = offset.top + height - e.pageY;
  305. var l = e.pageX - offset.left;
  306. return Math.min(t,r,b,l) > state.options.edge;
  307. }
  308. });
  309. };
  310. $.fn.draggable.methods = {
  311. options: function(jq){
  312. return $.data(jq[0], 'draggable').options;
  313. },
  314. proxy: function(jq){
  315. return $.data(jq[0], 'draggable').proxy;
  316. },
  317. enable: function(jq){
  318. return jq.each(function(){
  319. $(this).draggable({disabled:false});
  320. });
  321. },
  322. disable: function(jq){
  323. return jq.each(function(){
  324. $(this).draggable({disabled:true});
  325. });
  326. }
  327. };
  328. $.fn.draggable.parseOptions = function(target){
  329. var t = $(target);
  330. return $.extend({},
  331. $.parser.parseOptions(target, ['cursor','handle','axis',
  332. {'revert':'boolean','deltaX':'number','deltaY':'number','edge':'number','delay':'number'}]), {
  333. disabled: (t.attr('disabled') ? true : undefined)
  334. });
  335. };
  336. $.fn.draggable.defaults = {
  337. proxy:null, // 'clone' or a function that will create the proxy object,
  338. // the function has the source parameter that indicate the source object dragged.
  339. revert:false,
  340. cursor:'move',
  341. deltaX:null,
  342. deltaY:null,
  343. handle: null,
  344. disabled: false,
  345. edge:0,
  346. axis:null, // v or h
  347. delay:100,
  348. onBeforeDrag: function(e){},
  349. onStartDrag: function(e){},
  350. onDrag: function(e){},
  351. onEndDrag: function(e){},
  352. onStopDrag: function(e){}
  353. };
  354. $.fn.draggable.isDragging = false;
  355. })(jQuery);