1
0

mootools-more-1.3.2.1.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. // MooTools: the javascript framework.
  2. // Load this file's selection again by visiting: http://mootools.net/more/5fb29d24c3a346e2b8fcf68d206003a4
  3. // Or build this file again with packager using: packager build More/More More/Fx.Scroll More/Drag
  4. /*
  5. ---
  6. script: More.js
  7. name: More
  8. description: MooTools More
  9. license: MIT-style license
  10. authors:
  11. - Guillermo Rauch
  12. - Thomas Aylott
  13. - Scott Kyle
  14. - Arian Stolwijk
  15. - Tim Wienk
  16. - Christoph Pojer
  17. - Aaron Newton
  18. - Jacob Thornton
  19. requires:
  20. - Core/MooTools
  21. provides: [MooTools.More]
  22. ...
  23. */
  24. MooTools.More = {
  25. 'version': '1.3.2.1',
  26. 'build': 'e586bcd2496e9b22acfde32e12f84d49ce09e59d'
  27. };
  28. /*
  29. ---
  30. script: Fx.Scroll.js
  31. name: Fx.Scroll
  32. description: Effect to smoothly scroll any element, including the window.
  33. license: MIT-style license
  34. authors:
  35. - Valerio Proietti
  36. requires:
  37. - Core/Fx
  38. - Core/Element.Event
  39. - Core/Element.Dimensions
  40. - /MooTools.More
  41. provides: [Fx.Scroll]
  42. ...
  43. */
  44. (function(){
  45. Fx.Scroll = new Class({
  46. Extends: Fx,
  47. options: {
  48. offset: {x: 0, y: 0},
  49. wheelStops: true
  50. },
  51. initialize: function(element, options){
  52. this.element = this.subject = document.id(element);
  53. this.parent(options);
  54. if (typeOf(this.element) != 'element') this.element = document.id(this.element.getDocument().body);
  55. if (this.options.wheelStops){
  56. var stopper = this.element,
  57. cancel = this.cancel.pass(false, this);
  58. this.addEvent('start', function(){
  59. stopper.addEvent('mousewheel', cancel);
  60. }, true);
  61. this.addEvent('complete', function(){
  62. stopper.removeEvent('mousewheel', cancel);
  63. }, true);
  64. }
  65. },
  66. set: function(){
  67. var now = Array.flatten(arguments);
  68. if (Browser.firefox) now = [Math.round(now[0]), Math.round(now[1])]; // not needed anymore in newer firefox versions
  69. this.element.scrollTo(now[0], now[1]);
  70. return this;
  71. },
  72. compute: function(from, to, delta){
  73. return [0, 1].map(function(i){
  74. return Fx.compute(from[i], to[i], delta);
  75. });
  76. },
  77. start: function(x, y){
  78. if (!this.check(x, y)) return this;
  79. var scroll = this.element.getScroll();
  80. return this.parent([scroll.x, scroll.y], [x, y]);
  81. },
  82. calculateScroll: function(x, y){
  83. var element = this.element,
  84. scrollSize = element.getScrollSize(),
  85. scroll = element.getScroll(),
  86. size = element.getSize(),
  87. offset = this.options.offset,
  88. values = {x: x, y: y};
  89. for (var z in values){
  90. if (!values[z] && values[z] !== 0) values[z] = scroll[z];
  91. if (typeOf(values[z]) != 'number') values[z] = scrollSize[z] - size[z];
  92. values[z] += offset[z];
  93. }
  94. return [values.x, values.y];
  95. },
  96. toTop: function(){
  97. return this.start.apply(this, this.calculateScroll(false, 0));
  98. },
  99. toLeft: function(){
  100. return this.start.apply(this, this.calculateScroll(0, false));
  101. },
  102. toRight: function(){
  103. return this.start.apply(this, this.calculateScroll('right', false));
  104. },
  105. toBottom: function(){
  106. return this.start.apply(this, this.calculateScroll(false, 'bottom'));
  107. },
  108. toElement: function(el, axes){
  109. axes = axes ? Array.from(axes) : ['x', 'y'];
  110. var scroll = isBody(this.element) ? {x: 0, y: 0} : this.element.getScroll();
  111. var position = Object.map(document.id(el).getPosition(this.element), function(value, axis){
  112. return axes.contains(axis) ? value + scroll[axis] : false;
  113. });
  114. return this.start.apply(this, this.calculateScroll(position.x, position.y));
  115. },
  116. toElementEdge: function(el, axes, offset){
  117. axes = axes ? Array.from(axes) : ['x', 'y'];
  118. el = document.id(el);
  119. var to = {},
  120. position = el.getPosition(this.element),
  121. size = el.getSize(),
  122. scroll = this.element.getScroll(),
  123. containerSize = this.element.getSize(),
  124. edge = {
  125. x: position.x + size.x,
  126. y: position.y + size.y
  127. };
  128. ['x', 'y'].each(function(axis){
  129. if (axes.contains(axis)){
  130. if (edge[axis] > scroll[axis] + containerSize[axis]) to[axis] = edge[axis] - containerSize[axis];
  131. if (position[axis] < scroll[axis]) to[axis] = position[axis];
  132. }
  133. if (to[axis] == null) to[axis] = scroll[axis];
  134. if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
  135. }, this);
  136. if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
  137. return this;
  138. },
  139. toElementCenter: function(el, axes, offset){
  140. axes = axes ? Array.from(axes) : ['x', 'y'];
  141. el = document.id(el);
  142. var to = {},
  143. position = el.getPosition(this.element),
  144. size = el.getSize(),
  145. scroll = this.element.getScroll(),
  146. containerSize = this.element.getSize();
  147. ['x', 'y'].each(function(axis){
  148. if (axes.contains(axis)){
  149. to[axis] = position[axis] - (containerSize[axis] - size[axis]) / 2;
  150. }
  151. if (to[axis] == null) to[axis] = scroll[axis];
  152. if (offset && offset[axis]) to[axis] = to[axis] + offset[axis];
  153. }, this);
  154. if (to.x != scroll.x || to.y != scroll.y) this.start(to.x, to.y);
  155. return this;
  156. }
  157. });
  158. function isBody(element){
  159. return (/^(?:body|html)$/i).test(element.tagName);
  160. }
  161. })();
  162. /*
  163. ---
  164. script: Drag.js
  165. name: Drag
  166. description: The base Drag Class. Can be used to drag and resize Elements using mouse events.
  167. license: MIT-style license
  168. authors:
  169. - Valerio Proietti
  170. - Tom Occhinno
  171. - Jan Kassens
  172. requires:
  173. - Core/Events
  174. - Core/Options
  175. - Core/Element.Event
  176. - Core/Element.Style
  177. - Core/Element.Dimensions
  178. - /MooTools.More
  179. provides: [Drag]
  180. ...
  181. */
  182. var Drag = new Class({
  183. Implements: [Events, Options],
  184. options: {/*
  185. onBeforeStart: function(thisElement){},
  186. onStart: function(thisElement, event){},
  187. onSnap: function(thisElement){},
  188. onDrag: function(thisElement, event){},
  189. onCancel: function(thisElement){},
  190. onComplete: function(thisElement, event){},*/
  191. snap: 6,
  192. unit: 'px',
  193. grid: false,
  194. style: true,
  195. limit: false,
  196. handle: false,
  197. invert: false,
  198. preventDefault: false,
  199. stopPropagation: false,
  200. modifiers: {x: 'left', y: 'top'}
  201. },
  202. initialize: function(){
  203. var params = Array.link(arguments, {
  204. 'options': Type.isObject,
  205. 'element': function(obj){
  206. return obj != null;
  207. }
  208. });
  209. this.element = document.id(params.element);
  210. this.document = this.element.getDocument();
  211. this.setOptions(params.options || {});
  212. var htype = typeOf(this.options.handle);
  213. this.handles = ((htype == 'array' || htype == 'collection') ? $$(this.options.handle) : document.id(this.options.handle)) || this.element;
  214. this.mouse = {'now': {}, 'pos': {}};
  215. this.value = {'start': {}, 'now': {}};
  216. this.selection = (Browser.ie) ? 'selectstart' : 'mousedown';
  217. if (Browser.ie && !Drag.ondragstartFixed){
  218. document.ondragstart = Function.from(false);
  219. Drag.ondragstartFixed = true;
  220. }
  221. this.bound = {
  222. start: this.start.bind(this),
  223. check: this.check.bind(this),
  224. drag: this.drag.bind(this),
  225. stop: this.stop.bind(this),
  226. cancel: this.cancel.bind(this),
  227. eventStop: Function.from(false)
  228. };
  229. this.attach();
  230. },
  231. attach: function(){
  232. this.handles.addEvent('mousedown', this.bound.start);
  233. return this;
  234. },
  235. detach: function(){
  236. this.handles.removeEvent('mousedown', this.bound.start);
  237. return this;
  238. },
  239. start: function(event){
  240. var options = this.options;
  241. if (event.rightClick) return;
  242. if (options.preventDefault) event.preventDefault();
  243. if (options.stopPropagation) event.stopPropagation();
  244. this.mouse.start = event.page;
  245. this.fireEvent('beforeStart', this.element);
  246. var limit = options.limit;
  247. this.limit = {x: [], y: []};
  248. var z, coordinates;
  249. for (z in options.modifiers){
  250. if (!options.modifiers[z]) continue;
  251. var style = this.element.getStyle(options.modifiers[z]);
  252. // Some browsers (IE and Opera) don't always return pixels.
  253. if (style && !style.match(/px$/)){
  254. if (!coordinates) coordinates = this.element.getCoordinates(this.element.getOffsetParent());
  255. style = coordinates[options.modifiers[z]];
  256. }
  257. if (options.style) this.value.now[z] = (style || 0).toInt();
  258. else this.value.now[z] = this.element[options.modifiers[z]];
  259. if (options.invert) this.value.now[z] *= -1;
  260. this.mouse.pos[z] = event.page[z] - this.value.now[z];
  261. if (limit && limit[z]){
  262. var i = 2;
  263. while (i--){
  264. var limitZI = limit[z][i];
  265. if (limitZI || limitZI === 0) this.limit[z][i] = (typeof limitZI == 'function') ? limitZI() : limitZI;
  266. }
  267. }
  268. }
  269. if (typeOf(this.options.grid) == 'number') this.options.grid = {
  270. x: this.options.grid,
  271. y: this.options.grid
  272. };
  273. var events = {
  274. mousemove: this.bound.check,
  275. mouseup: this.bound.cancel
  276. };
  277. events[this.selection] = this.bound.eventStop;
  278. this.document.addEvents(events);
  279. },
  280. check: function(event){
  281. if (this.options.preventDefault) event.preventDefault();
  282. var distance = Math.round(Math.sqrt(Math.pow(event.page.x - this.mouse.start.x, 2) + Math.pow(event.page.y - this.mouse.start.y, 2)));
  283. if (distance > this.options.snap){
  284. this.cancel();
  285. this.document.addEvents({
  286. mousemove: this.bound.drag,
  287. mouseup: this.bound.stop
  288. });
  289. this.fireEvent('start', [this.element, event]).fireEvent('snap', this.element);
  290. }
  291. },
  292. drag: function(event){
  293. var options = this.options;
  294. if (options.preventDefault) event.preventDefault();
  295. this.mouse.now = event.page;
  296. for (var z in options.modifiers){
  297. if (!options.modifiers[z]) continue;
  298. this.value.now[z] = this.mouse.now[z] - this.mouse.pos[z];
  299. if (options.invert) this.value.now[z] *= -1;
  300. if (options.limit && this.limit[z]){
  301. if ((this.limit[z][1] || this.limit[z][1] === 0) && (this.value.now[z] > this.limit[z][1])){
  302. this.value.now[z] = this.limit[z][1];
  303. } else if ((this.limit[z][0] || this.limit[z][0] === 0) && (this.value.now[z] < this.limit[z][0])){
  304. this.value.now[z] = this.limit[z][0];
  305. }
  306. }
  307. if (options.grid[z]) this.value.now[z] -= ((this.value.now[z] - (this.limit[z][0]||0)) % options.grid[z]);
  308. if (options.style) this.element.setStyle(options.modifiers[z], this.value.now[z] + options.unit);
  309. else this.element[options.modifiers[z]] = this.value.now[z];
  310. }
  311. this.fireEvent('drag', [this.element, event]);
  312. },
  313. cancel: function(event){
  314. this.document.removeEvents({
  315. mousemove: this.bound.check,
  316. mouseup: this.bound.cancel
  317. });
  318. if (event){
  319. this.document.removeEvent(this.selection, this.bound.eventStop);
  320. this.fireEvent('cancel', this.element);
  321. }
  322. },
  323. stop: function(event){
  324. var events = {
  325. mousemove: this.bound.drag,
  326. mouseup: this.bound.stop
  327. };
  328. events[this.selection] = this.bound.eventStop;
  329. this.document.removeEvents(events);
  330. if (event) this.fireEvent('complete', [this.element, event]);
  331. }
  332. });
  333. Element.implement({
  334. makeResizable: function(options){
  335. var drag = new Drag(this, Object.merge({
  336. modifiers: {
  337. x: 'width',
  338. y: 'height'
  339. }
  340. }, options));
  341. this.store('resizer', drag);
  342. return drag.addEvent('drag', function(){
  343. this.fireEvent('resize', drag);
  344. }.bind(this));
  345. }
  346. });