draggable.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. /**
  2. * draggable - jQuery EasyUI
  3. *
  4. * Licensed under the GPL:
  5. * http://www.gnu.org/licenses/gpl.txt
  6. *
  7. * Copyright 2010 stworthy [ stworthy@gmail.com ]
  8. */
  9. (function($){
  10. function drag(e){
  11. var opts = $.data(e.data.target, 'draggable').options;
  12. var dragData = e.data;
  13. var left = dragData.startLeft + e.pageX - dragData.startX;
  14. var top = dragData.startTop + e.pageY - dragData.startY;
  15. if (opts.deltaX != null && opts.deltaX != undefined){
  16. left = e.pageX + opts.deltaX;
  17. }
  18. if (opts.deltaY != null && opts.deltaY != undefined){
  19. top = e.pageY + opts.deltaY;
  20. }
  21. if (e.data.parnet != document.body) {
  22. if ($.boxModel == true) {
  23. left += $(e.data.parent).scrollLeft();
  24. top += $(e.data.parent).scrollTop();
  25. }
  26. }
  27. if (opts.axis == 'h') {
  28. dragData.left = left;
  29. } else if (opts.axis == 'v') {
  30. dragData.top = top;
  31. } else {
  32. dragData.left = left;
  33. dragData.top = top;
  34. }
  35. }
  36. function applyDrag(e){
  37. var opts = $.data(e.data.target, 'draggable').options;
  38. var proxy = $.data(e.data.target, 'draggable').proxy;
  39. if (proxy){
  40. proxy.css('cursor', opts.cursor);
  41. } else {
  42. proxy = $(e.data.target);
  43. $.data(e.data.target, 'draggable').handle.css('cursor', opts.cursor);
  44. }
  45. proxy.css({
  46. left:e.data.left,
  47. top:e.data.top
  48. });
  49. }
  50. function doDown(e){
  51. var opts = $.data(e.data.target, 'draggable').options;
  52. var droppables = $('.droppable').filter(function(){
  53. return e.data.target != this;
  54. }).filter(function(){
  55. var accept = $.data(this, 'droppable').options.accept;
  56. if (accept){
  57. return $(accept).filter(function(){
  58. return this == e.data.target;
  59. }).length > 0;
  60. } else {
  61. return true;
  62. }
  63. });
  64. $.data(e.data.target, 'draggable').droppables = droppables;
  65. var proxy = $.data(e.data.target, 'draggable').proxy;
  66. if (!proxy){
  67. if (opts.proxy){
  68. if (opts.proxy == 'clone'){
  69. proxy = $(e.data.target).clone().insertAfter(e.data.target);
  70. } else {
  71. proxy = opts.proxy.call(e.data.target, e.data.target);
  72. }
  73. $.data(e.data.target, 'draggable').proxy = proxy;
  74. } else {
  75. proxy = $(e.data.target);
  76. }
  77. }
  78. proxy.css('position', 'absolute');
  79. drag(e);
  80. applyDrag(e);
  81. opts.onStartDrag.call(e.data.target, e);
  82. return false;
  83. }
  84. function doMove(e){
  85. drag(e);
  86. if ($.data(e.data.target, 'draggable').options.onDrag.call(e.data.target, e) != false){
  87. applyDrag(e);
  88. }
  89. var source = e.data.target;
  90. $.data(e.data.target, 'draggable').droppables.each(function(){
  91. var dropObj = $(this);
  92. var p2 = $(this).offset();
  93. if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()
  94. && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){
  95. if (!this.entered){
  96. $(this).trigger('_dragenter', [source]);
  97. this.entered = true;
  98. }
  99. $(this).trigger('_dragover', [source]);
  100. } else {
  101. if (this.entered){
  102. $(this).trigger('_dragleave', [source]);
  103. this.entered = false;
  104. }
  105. }
  106. });
  107. return false;
  108. }
  109. function doUp(e){
  110. drag(e);
  111. var proxy = $.data(e.data.target, 'draggable').proxy;
  112. var opts = $.data(e.data.target, 'draggable').options;
  113. if (opts.revert){
  114. if (checkDrop() == true){
  115. removeProxy();
  116. $(e.data.target).css({
  117. position:e.data.startPosition,
  118. left:e.data.startLeft,
  119. top:e.data.startTop
  120. });
  121. } else {
  122. if (proxy){
  123. proxy.animate({
  124. left:e.data.startLeft,
  125. top:e.data.startTop
  126. }, function(){
  127. removeProxy();
  128. });
  129. } else {
  130. $(e.data.target).animate({
  131. left:e.data.startLeft,
  132. top:e.data.startTop
  133. }, function(){
  134. $(e.data.target).css('position', e.data.startPosition);
  135. });
  136. }
  137. }
  138. } else {
  139. $(e.data.target).css({
  140. position:'absolute',
  141. left:e.data.left,
  142. top:e.data.top
  143. });
  144. removeProxy();
  145. checkDrop();
  146. }
  147. opts.onStopDrag.call(e.data.target, e);
  148. function removeProxy(){
  149. if (proxy){
  150. proxy.remove();
  151. }
  152. $.data(e.data.target, 'draggable').proxy = null;
  153. }
  154. function checkDrop(){
  155. var dropped = false;
  156. $.data(e.data.target, 'draggable').droppables.each(function(){
  157. var dropObj = $(this);
  158. var p2 = $(this).offset();
  159. if (e.pageX > p2.left && e.pageX < p2.left + dropObj.outerWidth()
  160. && e.pageY > p2.top && e.pageY < p2.top + dropObj.outerHeight()){
  161. if (opts.revert){
  162. $(e.data.target).css({
  163. position:e.data.startPosition,
  164. left:e.data.startLeft,
  165. top:e.data.startTop
  166. });
  167. }
  168. $(this).trigger('_drop', [e.data.target]);
  169. dropped = true;
  170. this.entered = false;
  171. }
  172. });
  173. return dropped;
  174. }
  175. $(document).unbind('.draggable');
  176. return false;
  177. }
  178. $.fn.draggable = function(options){
  179. if (typeof options == 'string'){
  180. switch(options){
  181. case 'options':
  182. return $.data(this[0], 'draggable').options;
  183. case 'proxy':
  184. return $.data(this[0], 'draggable').proxy;
  185. case 'enable':
  186. return this.each(function(){
  187. $(this).draggable({disabled:false});
  188. });
  189. case 'disable':
  190. return this.each(function(){
  191. $(this).draggable({disabled:true});
  192. });
  193. }
  194. }
  195. return this.each(function(){
  196. // $(this).css('position','absolute');
  197. var opts;
  198. var state = $.data(this, 'draggable');
  199. if (state) {
  200. state.handle.unbind('.draggable');
  201. opts = $.extend(state.options, options);
  202. } else {
  203. opts = $.extend({}, $.fn.draggable.defaults, options || {});
  204. }
  205. if (opts.disabled == true) {
  206. $(this).css('cursor', 'default');
  207. return;
  208. }
  209. var handle = null;
  210. if (typeof opts.handle == 'undefined' || opts.handle == null){
  211. handle = $(this);
  212. } else {
  213. handle = (typeof opts.handle == 'string' ? $(opts.handle, this) : handle);
  214. }
  215. $.data(this, 'draggable', {
  216. options: opts,
  217. handle: handle
  218. });
  219. // bind mouse event using event namespace draggable
  220. handle.bind('mousedown.draggable', {target:this}, onMouseDown);
  221. handle.bind('mousemove.draggable', {target:this}, onMouseMove);
  222. function onMouseDown(e) {
  223. if (checkArea(e) == false) return;
  224. var position = $(e.data.target).position();
  225. var data = {
  226. startPosition: $(e.data.target).css('position'),
  227. startLeft: position.left,
  228. startTop: position.top,
  229. left: position.left,
  230. top: position.top,
  231. startX: e.pageX,
  232. startY: e.pageY,
  233. target: e.data.target,
  234. parent: $(e.data.target).parent()[0]
  235. };
  236. $(document).bind('mousedown.draggable', data, doDown);
  237. $(document).bind('mousemove.draggable', data, doMove);
  238. $(document).bind('mouseup.draggable', data, doUp);
  239. }
  240. function onMouseMove(e) {
  241. if (checkArea(e)){
  242. $(this).css('cursor', opts.cursor);
  243. } else {
  244. $(this).css('cursor', 'default');
  245. }
  246. }
  247. // check if the handle can be dragged
  248. function checkArea(e) {
  249. var offset = $(handle).offset();
  250. var width = $(handle).outerWidth();
  251. var height = $(handle).outerHeight();
  252. var t = e.pageY - offset.top;
  253. var r = offset.left + width - e.pageX;
  254. var b = offset.top + height - e.pageY;
  255. var l = e.pageX - offset.left;
  256. return Math.min(t,r,b,l) > opts.edge;
  257. }
  258. });
  259. };
  260. $.fn.draggable.defaults = {
  261. proxy:null, // 'clone' or a function that will create the proxy object,
  262. // the function has the source parameter that indicate the source object dragged.
  263. revert:false,
  264. cursor:'move',
  265. deltaX:null,
  266. deltaY:null,
  267. handle: null,
  268. disabled: false,
  269. edge:0,
  270. axis:null, // v or h
  271. onStartDrag: function(e){},
  272. onDrag: function(e){},
  273. onStopDrag: function(e){}
  274. };
  275. })(jQuery);