ui.droppable.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. (function($) {
  2. //Make nodes selectable by expression
  3. $.extend($.expr[':'], { droppable: "(' '+a.className+' ').indexOf(' ui-droppable ')" });
  4. //Macros for external methods that support chaining
  5. var methods = "destroy,enable,disable".split(",");
  6. for(var i=0;i<methods.length;i++) {
  7. var cur = methods[i], f;
  8. eval('f = function() { var a = arguments; return this.each(function() { if(jQuery(this).is(".ui-droppable")) jQuery.data(this, "ui-droppable")["'+cur+'"](a); }); }');
  9. $.fn["droppable"+cur.substr(0,1).toUpperCase()+cur.substr(1)] = f;
  10. };
  11. //get instance method
  12. $.fn.droppableInstance = function() {
  13. if($(this[0]).is(".ui-droppable")) return $.data(this[0], "ui-droppable");
  14. return false;
  15. };
  16. $.fn.droppable = function(o) {
  17. return this.each(function() {
  18. new $.ui.droppable(this,o);
  19. });
  20. }
  21. $.ui.droppable = function(el,o) {
  22. if(!o) var o = {};
  23. this.element = el; if($.browser.msie) el.droppable = 1;
  24. $.data(el, "ui-droppable", this);
  25. this.options = {};
  26. $.extend(this.options, o);
  27. var accept = o.accept;
  28. $.extend(this.options, {
  29. accept: o.accept && o.accept.constructor == Function ? o.accept : function(d) {
  30. return $(d).is(accept);
  31. },
  32. tolerance: o.tolerance || 'intersect'
  33. });
  34. o = this.options;
  35. var self = this;
  36. this.mouseBindings = [function(e) { return self.move.apply(self, [e]); },function(e) { return self.drop.apply(self, [e]); }];
  37. $(this.element).bind("mousemove", this.mouseBindings[0]);
  38. $(this.element).bind("mouseup", this.mouseBindings[1]);
  39. $.ui.ddmanager.droppables.push({ item: this, over: 0, out: 1 }); // Add the reference and positions to the manager
  40. $(this.element).addClass("ui-droppable");
  41. };
  42. $.extend($.ui.droppable.prototype, {
  43. plugins: {},
  44. prepareCallbackObj: function(c) {
  45. return {
  46. draggable: c,
  47. droppable: this,
  48. element: c.element,
  49. helper: c.helper,
  50. options: this.options
  51. }
  52. },
  53. destroy: function() {
  54. $(this.element).removeClass("ui-droppable").removeClass("ui-droppable-disabled");
  55. $(this.element).unbind("mousemove", this.mouseBindings[0]);
  56. $(this.element).unbind("mouseup", this.mouseBindings[1]);
  57. for(var i=0;i<$.ui.ddmanager.droppables.length;i++) {
  58. if($.ui.ddmanager.droppables[i].item == this) $.ui.ddmanager.droppables.splice(i,1);
  59. }
  60. },
  61. enable: function() {
  62. $(this.element).removeClass("ui-droppable-disabled");
  63. this.disabled = false;
  64. },
  65. disable: function() {
  66. $(this.element).addClass("ui-droppable-disabled");
  67. this.disabled = true;
  68. },
  69. move: function(e) {
  70. if(!$.ui.ddmanager.current) return;
  71. var o = this.options;
  72. var c = $.ui.ddmanager.current;
  73. /* Save current target, if no last target given */
  74. var findCurrentTarget = function(e) {
  75. if(e.currentTarget) return e.currentTarget;
  76. var el = e.srcElement;
  77. do { if(el.droppable) return el; el = el.parentNode; } while (el); //This is only used in IE! references in DOM are evil!
  78. }
  79. if(c && o.accept(c.element)) c.currentTarget = findCurrentTarget(e);
  80. c.drag.apply(c, [e]);
  81. e.stopPropagation ? e.stopPropagation() : e.cancelBubble = true;
  82. },
  83. over: function(e) {
  84. var c = $.ui.ddmanager.current;
  85. if (!c || c.element == this.element) return; // Bail if draggable and droppable are same element
  86. var o = this.options;
  87. if (o.accept(c.element)) {
  88. $.ui.plugin.call(this, 'over', [e, this.prepareCallbackObj(c)]);
  89. $(this.element).triggerHandler("dropover", [e, this.prepareCallbackObj(c)], o.over);
  90. }
  91. },
  92. out: function(e) {
  93. var c = $.ui.ddmanager.current;
  94. if (!c || c.element == this.element) return; // Bail if draggable and droppable are same element
  95. var o = this.options;
  96. if (o.accept(c.element)) {
  97. $.ui.plugin.call(this, 'out', [e, this.prepareCallbackObj(c)]);
  98. $(this.element).triggerHandler("dropout", [e, this.prepareCallbackObj(c)], o.out);
  99. }
  100. },
  101. drop: function(e) {
  102. var c = $.ui.ddmanager.current;
  103. if (!c || c.element == this.element) return; // Bail if draggable and droppable are same element
  104. var o = this.options;
  105. if(o.accept(c.element)) { // Fire callback
  106. if(o.greedy && !c.slowMode) {
  107. if(c.currentTarget == this.element) {
  108. $.ui.plugin.call(this, 'drop', [e, {
  109. draggable: c,
  110. droppable: this,
  111. element: c.element,
  112. helper: c.helper
  113. }]);
  114. $(this.element).triggerHandler("drop", [e, {
  115. draggable: c,
  116. droppable: this,
  117. element: c.element,
  118. helper: c.helper
  119. }], o.drop);
  120. }
  121. } else {
  122. $.ui.plugin.call(this, 'drop', [e, this.prepareCallbackObj(c)]);
  123. $(this.element).triggerHandler("drop", [e, this.prepareCallbackObj(c)], o.drop);
  124. }
  125. }
  126. },
  127. activate: function(e) {
  128. var c = $.ui.ddmanager.current;
  129. $.ui.plugin.call(this, 'activate', [e, this.prepareCallbackObj(c)]);
  130. if(c) $(this.element).triggerHandler("dropactivate", [e, this.prepareCallbackObj(c)], this.options.activate);
  131. },
  132. deactivate: function(e) {
  133. var c = $.ui.ddmanager.current;
  134. $.ui.plugin.call(this, 'deactivate', [e, this.prepareCallbackObj(c)]);
  135. if(c) $(this.element).triggerHandler("dropdeactivate", [e, this.prepareCallbackObj(c)], this.options.deactivate);
  136. }
  137. });
  138. $.ui.intersect = function(oDrag, oDrop, toleranceMode) {
  139. if (!oDrop.offset)
  140. return false;
  141. var x1 = oDrag.rpos[0] - oDrag.options.cursorAt.left + oDrag.options.margins.left, x2 = x1 + oDrag.helperSize.width,
  142. y1 = oDrag.rpos[1] - oDrag.options.cursorAt.top + oDrag.options.margins.top, y2 = y1 + oDrag.helperSize.height;
  143. var l = oDrop.offset.left, r = l + oDrop.item.element.offsetWidth,
  144. t = oDrop.offset.top, b = t + oDrop.item.element.offsetHeight;
  145. switch (toleranceMode) {
  146. case 'fit':
  147. return ( l < x1 && x2 < r
  148. && t < y1 && y2 < b);
  149. break;
  150. case 'intersect':
  151. return ( l < x1 + (oDrag.helperSize.width / 2) // Right Half
  152. && x2 - (oDrag.helperSize.width / 2) < r // Left Half
  153. && t < y1 + (oDrag.helperSize.height / 2) // Bottom Half
  154. && y2 - (oDrag.helperSize.height / 2) < b ); // Top Half
  155. break;
  156. case 'pointer':
  157. return ( l < oDrag.rpos[0] && oDrag.rpos[0] < r
  158. && t < oDrag.rpos[1] && oDrag.rpos[1] < b);
  159. break;
  160. case 'touch':
  161. return ( (l < x1 && x1 < r && t < y1 && y1 < b) // Top-Left Corner
  162. || (l < x1 && x1 < r && t < y2 && y2 < b) // Bottom-Left Corner
  163. || (l < x2 && x2 < r && t < y1 && y1 < b) // Top-Right Corner
  164. || (l < x2 && x2 < r && t < y2 && y2 < b) ); // Bottom-Right Corner
  165. break;
  166. default:
  167. return false;
  168. break;
  169. }
  170. }
  171. })($);