ui.mouse.js 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. (function($) {
  2. //If the UI scope is not availalable, add it
  3. $.ui = $.ui || {};
  4. //Add methods that are vital for all mouse interaction stuff (plugin registering)
  5. $.extend($.ui, {
  6. plugin: {
  7. add: function(w, c, o, p) {
  8. var a = $.ui[w].prototype; if(!a.plugins[c]) a.plugins[c] = [];
  9. a.plugins[c].push([o,p]);
  10. },
  11. call: function(instance, name, arguments) {
  12. var c = instance.plugins[name]; if(!c) return;
  13. var o = instance.interaction ? instance.interaction.options : instance.options;
  14. var e = instance.interaction ? instance.interaction.element : instance.element;
  15. for (var i = 0; i < c.length; i++) {
  16. if (o[c[i][0]]) c[i][1].apply(e, arguments);
  17. }
  18. }
  19. }
  20. });
  21. $.fn.mouseInteractionDestroy = function() {
  22. this.each(function() {
  23. if($.data(this, "ui-mouse")) $.data(this, "ui-mouse").destroy();
  24. });
  25. }
  26. $.ui.mouseInteraction = function(el,o) {
  27. if(!o) var o = {};
  28. this.element = el;
  29. $.data(this.element, "ui-mouse", this);
  30. this.options = {};
  31. $.extend(this.options, o);
  32. $.extend(this.options, {
  33. handle : o.handle ? ($(o.handle, el)[0] ? $(o.handle, el) : $(el)) : $(el),
  34. helper: o.helper || 'original',
  35. preventionDistance: o.preventionDistance || 0,
  36. dragPrevention: o.dragPrevention ? o.dragPrevention.toLowerCase().split(',') : ['input','textarea','button','select','option'],
  37. cursorAt: { top: ((o.cursorAt && o.cursorAt.top) ? o.cursorAt.top : 0), left: ((o.cursorAt && o.cursorAt.left) ? o.cursorAt.left : 0), bottom: ((o.cursorAt && o.cursorAt.bottom) ? o.cursorAt.bottom : 0), right: ((o.cursorAt && o.cursorAt.right) ? o.cursorAt.right : 0) },
  38. cursorAtIgnore: (!o.cursorAt) ? true : false, //Internal property
  39. appendTo: o.appendTo || 'parent'
  40. })
  41. o = this.options; //Just Lazyness
  42. if(!this.options.nonDestructive && (o.helper == 'clone' || o.helper == 'original')) {
  43. // Let's save the margins for better reference
  44. o.margins = {
  45. top: parseInt($(el).css('marginTop')) || 0,
  46. left: parseInt($(el).css('marginLeft')) || 0,
  47. bottom: parseInt($(el).css('marginBottom')) || 0,
  48. right: parseInt($(el).css('marginRight')) || 0
  49. };
  50. // We have to add margins to our cursorAt
  51. if(o.cursorAt.top != 0) o.cursorAt.top = o.margins.top;
  52. if(o.cursorAt.left != 0) o.cursorAt.left += o.margins.left;
  53. if(o.cursorAt.bottom != 0) o.cursorAt.bottom += o.margins.bottom;
  54. if(o.cursorAt.right != 0) o.cursorAt.right += o.margins.right;
  55. if(o.helper == 'original')
  56. o.wasPositioned = $(el).css('position');
  57. } else {
  58. o.margins = { top: 0, left: 0, right: 0, bottom: 0 };
  59. }
  60. var self = this;
  61. this.mousedownfunc = function(e) { // Bind the mousedown event
  62. return self.click.apply(self, [e]);
  63. }
  64. o.handle.bind('mousedown', this.mousedownfunc);
  65. //Prevent selection of text when starting the drag in IE
  66. if($.browser.msie) $(this.element).attr('unselectable', 'on');
  67. }
  68. $.extend($.ui.mouseInteraction.prototype, {
  69. plugins: {},
  70. currentTarget: null,
  71. lastTarget: null,
  72. timer: null,
  73. slowMode: false,
  74. init: false,
  75. destroy: function() {
  76. this.options.handle.unbind('mousedown', this.mousedownfunc);
  77. },
  78. trigger: function(e) {
  79. return this.click.apply(this, arguments);
  80. },
  81. click: function(e) {
  82. var o = this.options;
  83. window.focus();
  84. if(e.which != 1) return true; //only left click starts dragging
  85. // Prevent execution on defined elements
  86. var targetName = (e.target) ? e.target.nodeName.toLowerCase() : e.srcElement.nodeName.toLowerCase();
  87. for(var i=0;i<o.dragPrevention.length;i++) {
  88. if(targetName == o.dragPrevention[i]) return true;
  89. }
  90. //Prevent execution on condition
  91. if(o.startCondition && !o.startCondition.apply(this, [e])) return true;
  92. var self = this;
  93. this.mouseup = function(e) { return self.stop.apply(self, [e]); }
  94. this.mousemove = function(e) { return self.drag.apply(self, [e]); }
  95. var initFunc = function() { //This function get's called at bottom or after timeout
  96. $(document).bind('mouseup', self.mouseup);
  97. $(document).bind('mousemove', self.mousemove);
  98. self.opos = [e.pageX,e.pageY]; // Get the original mouse position
  99. }
  100. if(o.preventionTimeout) { //use prevention timeout
  101. if(this.timer) clearInterval(this.timer);
  102. this.timer = setTimeout(function() { initFunc(); }, o.preventionTimeout);
  103. return false;
  104. }
  105. initFunc();
  106. return false;
  107. },
  108. start: function(e) {
  109. var o = this.options; var a = this.element;
  110. o.co = $(a).offset(); //get the current offset
  111. this.helper = typeof o.helper == 'function' ? $(o.helper.apply(a, [e,this]))[0] : (o.helper == 'clone' ? $(a).clone()[0] : a);
  112. if(o.appendTo == 'parent') { // Let's see if we have a positioned parent
  113. var cp = a.parentNode;
  114. while (cp) {
  115. if(cp.style && ($(cp).css('position') == 'relative' || $(cp).css('position') == 'absolute')) {
  116. o.pp = cp;
  117. o.po = $(cp).offset();
  118. o.ppOverflow = !!($(o.pp).css('overflow') == 'auto' || $(o.pp).css('overflow') == 'scroll'); //TODO!
  119. break;
  120. }
  121. cp = cp.parentNode ? cp.parentNode : null;
  122. };
  123. if(!o.pp) o.po = { top: 0, left: 0 };
  124. }
  125. this.pos = [this.opos[0],this.opos[1]]; //Use the relative position
  126. this.rpos = [this.pos[0],this.pos[1]]; //Save the absolute position
  127. if(o.cursorAtIgnore) { // If we want to pick the element where we clicked, we borrow cursorAt and add margins
  128. o.cursorAt.left = this.pos[0] - o.co.left + o.margins.left;
  129. o.cursorAt.top = this.pos[1] - o.co.top + o.margins.top;
  130. }
  131. if(o.pp) { // If we have a positioned parent, we pick the draggable relative to it
  132. this.pos[0] -= o.po.left;
  133. this.pos[1] -= o.po.top;
  134. }
  135. this.slowMode = (o.cursorAt && (o.cursorAt.top-o.margins.top > 0 || o.cursorAt.bottom-o.margins.bottom > 0) && (o.cursorAt.left-o.margins.left > 0 || o.cursorAt.right-o.margins.right > 0)) ? true : false; //If cursorAt is within the helper, set slowMode to true
  136. if(!o.nonDestructive) $(this.helper).css('position', 'absolute');
  137. if(o.helper != 'original') $(this.helper).appendTo((o.appendTo == 'parent' ? a.parentNode : o.appendTo)).show();
  138. // Remap right/bottom properties for cursorAt to left/top
  139. if(o.cursorAt.right && !o.cursorAt.left) o.cursorAt.left = this.helper.offsetWidth+o.margins.right+o.margins.left - o.cursorAt.right;
  140. if(o.cursorAt.bottom && !o.cursorAt.top) o.cursorAt.top = this.helper.offsetHeight+o.margins.top+o.margins.bottom - o.cursorAt.bottom;
  141. this.init = true;
  142. if(o._start) o._start.apply(a, [this.helper, this.pos, o.cursorAt, this, e]); // Trigger the start callback
  143. this.helperSize = { width: outerWidth(this.helper), height: outerHeight(this.helper) }; //Set helper size property
  144. return false;
  145. },
  146. stop: function(e) {
  147. var o = this.options; var a = this.element; var self = this;
  148. $(document).unbind('mouseup', self.mouseup);
  149. $(document).unbind('mousemove', self.mousemove);
  150. if(this.init == false) return this.opos = this.pos = null;
  151. if(o._beforeStop) o._beforeStop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]);
  152. if(this.helper != a && !o.beQuietAtEnd) { // Remove helper, if it's not the original node
  153. $(this.helper).remove(); this.helper = null;
  154. }
  155. if(!o.beQuietAtEnd) {
  156. //if(o.wasPositioned) $(a).css('position', o.wasPositioned);
  157. if(o._stop) o._stop.apply(a, [this.helper, this.pos, o.cursorAt, this, e]);
  158. }
  159. this.init = false;
  160. this.opos = this.pos = null;
  161. return false;
  162. },
  163. drag: function(e) {
  164. if (!this.opos || ($.browser.msie && !e.button)) return this.stop.apply(this, [e]); // check for IE mouseup when moving into the document again
  165. var o = this.options;
  166. this.pos = [e.pageX,e.pageY]; //relative mouse position
  167. if(this.rpos && this.rpos[0] == this.pos[0] && this.rpos[1] == this.pos[1]) return false;
  168. this.rpos = [this.pos[0],this.pos[1]]; //absolute mouse position
  169. if(o.pp) { //If we have a positioned parent, use a relative position
  170. this.pos[0] -= o.po.left;
  171. this.pos[1] -= o.po.top;
  172. }
  173. if( (Math.abs(this.rpos[0]-this.opos[0]) > o.preventionDistance || Math.abs(this.rpos[1]-this.opos[1]) > o.preventionDistance) && this.init == false) //If position is more than x pixels from original position, start dragging
  174. this.start.apply(this,[e]);
  175. else {
  176. if(this.init == false) return false;
  177. }
  178. if(o._drag) o._drag.apply(this.element, [this.helper, this.pos, o.cursorAt, this, e]);
  179. return false;
  180. }
  181. });
  182. var num = function(el, prop) {
  183. return parseInt($.css(el.jquery?el[0]:el,prop))||0;
  184. };
  185. function outerWidth(el) {
  186. var $el = $(el), ow = $el.width();
  187. for (var i = 0, props = ['borderLeftWidth', 'paddingLeft', 'paddingRight', 'borderRightWidth']; i < props.length; i++)
  188. ow += num($el, props[i]);
  189. return ow;
  190. }
  191. function outerHeight(el) {
  192. var $el = $(el), oh = $el.width();
  193. for (var i = 0, props = ['borderTopWidth', 'paddingTop', 'paddingBottom', 'borderBottomWidth']; i < props.length; i++)
  194. oh += num($el, props[i]);
  195. return oh;
  196. }
  197. })($);