jquery.grab.js 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. jQuery grab
  3. https://github.com/jussi-kalliokoski/jQuery.grab
  4. Ported from Jin.js::gestures
  5. https://github.com/jussi-kalliokoski/jin.js/
  6. Created by Jussi Kalliokoski
  7. Licensed under MIT License.
  8. Includes fix for IE
  9. */
  10. (function($){
  11. var extend = $.extend,
  12. mousedown = 'mousedown',
  13. mousemove = 'mousemove',
  14. mouseup = 'mouseup',
  15. touchstart = 'touchstart',
  16. touchmove = 'touchmove',
  17. touchend = 'touchend',
  18. touchcancel = 'touchcancel';
  19. function unbind(elem, type, func){
  20. if (type.substr(0,5) !== 'touch'){ // A temporary fix for IE8 data passing problem in Jin.
  21. return $(elem).unbind(type, func);
  22. }
  23. var fnc, i;
  24. for (i=0; i<bind._binds.length; i++){
  25. if (bind._binds[i].elem === elem && bind._binds[i].type === type && bind._binds[i].func === func){
  26. if (document.addEventListener){
  27. elem.removeEventListener(type, bind._binds[i].fnc, false);
  28. } else {
  29. elem.detachEvent('on'+type, bind._binds[i].fnc);
  30. }
  31. bind._binds.splice(i--, 1);
  32. }
  33. }
  34. }
  35. function bind(elem, type, func, pass){
  36. if (type.substr(0,5) !== 'touch'){ // A temporary fix for IE8 data passing problem in Jin.
  37. return $(elem).bind(type, pass, func);
  38. }
  39. var fnc, i;
  40. if (bind[type]){
  41. return bind[type].bind(elem, type, func, pass);
  42. }
  43. fnc = function(e){
  44. if (!e){ // Fix some ie bugs...
  45. e = window.event;
  46. }
  47. if (!e.stopPropagation){
  48. e.stopPropagation = function(){ this.cancelBubble = true; };
  49. }
  50. e.data = pass;
  51. func.call(elem, e);
  52. };
  53. if (document.addEventListener){
  54. elem.addEventListener(type, fnc, false);
  55. } else {
  56. elem.attachEvent('on' + type, fnc);
  57. }
  58. bind._binds.push({elem: elem, type: type, func: func, fnc: fnc});
  59. }
  60. function grab(elem, options)
  61. {
  62. var data = {
  63. move: {x: 0, y: 0},
  64. offset: {x: 0, y: 0},
  65. position: {x: 0, y: 0},
  66. start: {x: 0, y: 0},
  67. affects: document.documentElement,
  68. stopPropagation: false,
  69. preventDefault: true,
  70. touch: true // Implementation unfinished, and doesn't support multitouch
  71. };
  72. extend(data, options);
  73. data.element = elem;
  74. bind(elem, mousedown, mouseDown, data);
  75. if (data.touch){
  76. bind(elem, touchstart, touchStart, data);
  77. }
  78. }
  79. function ungrab(elem){
  80. unbind(elem, mousedown, mousedown);
  81. }
  82. function mouseDown(e){
  83. e.data.position.x = e.pageX;
  84. e.data.position.y = e.pageY;
  85. e.data.start.x = e.pageX;
  86. e.data.start.y = e.pageY;
  87. e.data.event = e;
  88. if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)){
  89. return;
  90. }
  91. if (e.preventDefault && e.data.preventDefault){
  92. e.preventDefault();
  93. }
  94. if (e.stopPropagation && e.data.stopPropagation){
  95. e.stopPropagation();
  96. }
  97. bind(e.data.affects, mousemove, mouseMove, e.data);
  98. bind(e.data.affects, mouseup, mouseUp, e.data);
  99. }
  100. function mouseMove(e){
  101. if (e.preventDefault && e.data.preventDefault){
  102. e.preventDefault();
  103. }
  104. if (e.stopPropagation && e.data.preventDefault){
  105. e.stopPropagation();
  106. }
  107. e.data.move.x = e.pageX - e.data.position.x;
  108. e.data.move.y = e.pageY - e.data.position.y;
  109. e.data.position.x = e.pageX;
  110. e.data.position.y = e.pageY;
  111. e.data.offset.x = e.pageX - e.data.start.x;
  112. e.data.offset.y = e.pageY - e.data.start.y;
  113. e.data.event = e;
  114. if (e.data.onmove){
  115. e.data.onmove.call(e.data.element, e.data);
  116. }
  117. }
  118. function mouseUp(e){
  119. if (e.preventDefault && e.data.preventDefault){
  120. e.preventDefault();
  121. }
  122. if (e.stopPropagation && e.data.stopPropagation){
  123. e.stopPropagation();
  124. }
  125. unbind(e.data.affects, mousemove, mouseMove);
  126. unbind(e.data.affects, mouseup, mouseUp);
  127. e.data.event = e;
  128. if (e.data.onfinish){
  129. e.data.onfinish.call(e.data.element, e.data);
  130. }
  131. }
  132. function touchStart(e){
  133. e.data.position.x = e.touches[0].pageX;
  134. e.data.position.y = e.touches[0].pageY;
  135. e.data.start.x = e.touches[0].pageX;
  136. e.data.start.y = e.touches[0].pageY;
  137. e.data.event = e;
  138. if (e.data.onstart && e.data.onstart.call(e.data.element, e.data)){
  139. return;
  140. }
  141. if (e.preventDefault && e.data.preventDefault){
  142. e.preventDefault();
  143. }
  144. if (e.stopPropagation && e.data.stopPropagation){
  145. e.stopPropagation();
  146. }
  147. bind(e.data.affects, touchmove, touchMove, e.data);
  148. bind(e.data.affects, touchend, touchEnd, e.data);
  149. }
  150. function touchMove(e){
  151. if (e.preventDefault && e.data.preventDefault){
  152. e.preventDefault();
  153. }
  154. if (e.stopPropagation && e.data.stopPropagation){
  155. e.stopPropagation();
  156. }
  157. e.data.move.x = e.touches[0].pageX - e.data.position.x;
  158. e.data.move.y = e.touches[0].pageY - e.data.position.y;
  159. e.data.position.x = e.touches[0].pageX;
  160. e.data.position.y = e.touches[0].pageY;
  161. e.data.offset.x = e.touches[0].pageX - e.data.start.x;
  162. e.data.offset.y = e.touches[0].pageY - e.data.start.y;
  163. e.data.event = e;
  164. if (e.data.onmove){
  165. e.data.onmove.call(e.data.elem, e.data);
  166. }
  167. }
  168. function touchEnd(e){
  169. if (e.preventDefault && e.data.preventDefault){
  170. e.preventDefault();
  171. }
  172. if (e.stopPropagation && e.data.stopPropagation){
  173. e.stopPropagation();
  174. }
  175. unbind(e.data.affects, touchmove, touchMove);
  176. unbind(e.data.affects, touchend, touchEnd);
  177. e.data.event = e;
  178. if (e.data.onfinish){
  179. e.data.onfinish.call(e.data.element, e.data);
  180. }
  181. }
  182. bind._binds = [];
  183. $.fn.grab = function(a, b){
  184. return this.each(function(){
  185. return grab(this, a, b);
  186. });
  187. };
  188. $.fn.ungrab = function(a){
  189. return this.each(function(){
  190. return ungrab(this, a);
  191. });
  192. };
  193. })(jQuery);