API Docs for: 3.10.3
Show:

File: dd/js/scroll.js

  1.  
  2. /**
  3. * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
  4. * This class should not be called on it's own, it's designed to be a plugin.
  5. * @module dd
  6. * @submodule dd-scroll
  7. */
  8. /**
  9. * Base scroller class used to create the Plugin.DDNodeScroll and Plugin.DDWinScroll.
  10. * This class should not be called on it's own, it's designed to be a plugin.
  11. * @class Scroll
  12. * @extends Base
  13. * @namespace DD
  14. * @constructor
  15. */
  16.  
  17. var S = function() {
  18. S.superclass.constructor.apply(this, arguments);
  19.  
  20. },
  21. WS, NS,
  22. HOST = 'host',
  23. BUFFER = 'buffer',
  24. PARENT_SCROLL = 'parentScroll',
  25. WINDOW_SCROLL = 'windowScroll',
  26. SCROLL_TOP = 'scrollTop',
  27. SCROLL_LEFT = 'scrollLeft',
  28. OFFSET_WIDTH = 'offsetWidth',
  29. OFFSET_HEIGHT = 'offsetHeight';
  30.  
  31.  
  32. S.ATTRS = {
  33. /**
  34. * Internal config option to hold the node that we are scrolling. Should not be set by the developer.
  35. * @attribute parentScroll
  36. * @type Node
  37. */
  38. parentScroll: {
  39. value: false,
  40. setter: function(node) {
  41. if (node) {
  42. return node;
  43. }
  44. return false;
  45. }
  46. },
  47. /**
  48. * The number of pixels from the edge of the screen to turn on scrolling. Default: 30
  49. * @attribute buffer
  50. * @type Number
  51. */
  52. buffer: {
  53. value: 30,
  54. validator: Y.Lang.isNumber
  55. },
  56. /**
  57. * The number of milliseconds delay to pass to the auto scroller. Default: 235
  58. * @attribute scrollDelay
  59. * @type Number
  60. */
  61. scrollDelay: {
  62. value: 235,
  63. validator: Y.Lang.isNumber
  64. },
  65. /**
  66. * The host we are plugged into.
  67. * @attribute host
  68. * @type Object
  69. */
  70. host: {
  71. value: null
  72. },
  73. /**
  74. * Turn on window scroll support, default: false
  75. * @attribute windowScroll
  76. * @type Boolean
  77. */
  78. windowScroll: {
  79. value: false,
  80. validator: Y.Lang.isBoolean
  81. },
  82. /**
  83. * Allow vertical scrolling, default: true.
  84. * @attribute vertical
  85. * @type Boolean
  86. */
  87. vertical: {
  88. value: true,
  89. validator: Y.Lang.isBoolean
  90. },
  91. /**
  92. * Allow horizontal scrolling, default: true.
  93. * @attribute horizontal
  94. * @type Boolean
  95. */
  96. horizontal: {
  97. value: true,
  98. validator: Y.Lang.isBoolean
  99. }
  100. };
  101.  
  102. Y.extend(S, Y.Base, {
  103. /**
  104. * Tells if we are actively scrolling or not.
  105. * @private
  106. * @property _scrolling
  107. * @type Boolean
  108. */
  109. _scrolling: null,
  110. /**
  111. * Cache of the Viewport dims.
  112. * @private
  113. * @property _vpRegionCache
  114. * @type Object
  115. */
  116. _vpRegionCache: null,
  117. /**
  118. * Cache of the dragNode dims.
  119. * @private
  120. * @property _dimCache
  121. * @type Object
  122. */
  123. _dimCache: null,
  124. /**
  125. * Holder for the Timer object returned from Y.later.
  126. * @private
  127. * @property _scrollTimer
  128. * @type {Y.later}
  129. */
  130. _scrollTimer: null,
  131. /**
  132. * Sets the _vpRegionCache property with an Object containing the dims from the viewport.
  133. * @private
  134. * @method _getVPRegion
  135. */
  136. _getVPRegion: function() {
  137. var r = {},
  138. n = this.get(PARENT_SCROLL),
  139. b = this.get(BUFFER),
  140. ws = this.get(WINDOW_SCROLL),
  141. xy = ((ws) ? [] : n.getXY()),
  142. w = ((ws) ? 'winWidth' : OFFSET_WIDTH),
  143. h = ((ws) ? 'winHeight' : OFFSET_HEIGHT),
  144. t = ((ws) ? n.get(SCROLL_TOP) : xy[1]),
  145. l = ((ws) ? n.get(SCROLL_LEFT) : xy[0]);
  146.  
  147. r = {
  148. top: t + b,
  149. right: (n.get(w) + l) - b,
  150. bottom: (n.get(h) + t) - b,
  151. left: l + b
  152. };
  153. this._vpRegionCache = r;
  154. return r;
  155. },
  156. initializer: function() {
  157. var h = this.get(HOST);
  158. h.after('drag:start', Y.bind(this.start, this));
  159. h.after('drag:end', Y.bind(this.end, this));
  160. h.on('drag:align', Y.bind(this.align, this));
  161.  
  162. //TODO - This doesn't work yet??
  163. Y.one('win').on('scroll', Y.bind(function() {
  164. this._vpRegionCache = null;
  165. }, this));
  166. },
  167. /**
  168. * Check to see if we need to fire the scroll timer. If scroll timer is running this will scroll the window.
  169. * @private
  170. * @method _checkWinScroll
  171. * @param {Boolean} move Should we move the window. From Y.later
  172. */
  173. _checkWinScroll: function(move) {
  174. var r = this._getVPRegion(),
  175. ho = this.get(HOST),
  176. ws = this.get(WINDOW_SCROLL),
  177. xy = ho.lastXY,
  178. scroll = false,
  179. b = this.get(BUFFER),
  180. win = this.get(PARENT_SCROLL),
  181. sTop = win.get(SCROLL_TOP),
  182. sLeft = win.get(SCROLL_LEFT),
  183. w = this._dimCache.w,
  184. h = this._dimCache.h,
  185. bottom = xy[1] + h,
  186. top = xy[1],
  187. right = xy[0] + w,
  188. left = xy[0],
  189. nt = top,
  190. nl = left,
  191. st = sTop,
  192. sl = sLeft;
  193.  
  194. if (this.get('horizontal')) {
  195. if (left <= r.left) {
  196. scroll = true;
  197. nl = xy[0] - ((ws) ? b : 0);
  198. sl = sLeft - b;
  199. }
  200. if (right >= r.right) {
  201. scroll = true;
  202. nl = xy[0] + ((ws) ? b : 0);
  203. sl = sLeft + b;
  204. }
  205. }
  206. if (this.get('vertical')) {
  207. if (bottom >= r.bottom) {
  208. scroll = true;
  209. nt = xy[1] + ((ws) ? b : 0);
  210. st = sTop + b;
  211.  
  212. }
  213. if (top <= r.top) {
  214. scroll = true;
  215. nt = xy[1] - ((ws) ? b : 0);
  216. st = sTop - b;
  217. }
  218. }
  219.  
  220. if (st < 0) {
  221. st = 0;
  222. nt = xy[1];
  223. }
  224.  
  225. if (sl < 0) {
  226. sl = 0;
  227. nl = xy[0];
  228. }
  229.  
  230. if (nt < 0) {
  231. nt = xy[1];
  232. }
  233. if (nl < 0) {
  234. nl = xy[0];
  235. }
  236. if (move) {
  237. ho.actXY = [nl, nt];
  238. ho._alignNode([nl, nt], true); //We are srolling..
  239. xy = ho.actXY;
  240. ho.actXY = [nl, nt];
  241. ho._moveNode({ node: win, top: st, left: sl});
  242. if (!st && !sl) {
  243. this._cancelScroll();
  244. }
  245. } else {
  246. if (scroll) {
  247. this._initScroll();
  248. } else {
  249. this._cancelScroll();
  250. }
  251. }
  252. },
  253. /**
  254. * Cancel a previous scroll timer and init a new one.
  255. * @private
  256. * @method _initScroll
  257. */
  258. _initScroll: function() {
  259. this._cancelScroll();
  260. this._scrollTimer = Y.Lang.later(this.get('scrollDelay'), this, this._checkWinScroll, [true], true);
  261.  
  262. },
  263. /**
  264. * Cancel a currently running scroll timer.
  265. * @private
  266. * @method _cancelScroll
  267. */
  268. _cancelScroll: function() {
  269. this._scrolling = false;
  270. if (this._scrollTimer) {
  271. this._scrollTimer.cancel();
  272. delete this._scrollTimer;
  273. }
  274. },
  275. /**
  276. * Called from the drag:align event to determine if we need to scroll.
  277. * @method align
  278. */
  279. align: function(e) {
  280. if (this._scrolling) {
  281. this._cancelScroll();
  282. e.preventDefault();
  283. }
  284. if (!this._scrolling) {
  285. this._checkWinScroll();
  286. }
  287. },
  288. /**
  289. * Set the cache of the dragNode dims.
  290. * @private
  291. * @method _setDimCache
  292. */
  293. _setDimCache: function() {
  294. var node = this.get(HOST).get('dragNode');
  295. this._dimCache = {
  296. h: node.get(OFFSET_HEIGHT),
  297. w: node.get(OFFSET_WIDTH)
  298. };
  299. },
  300. /**
  301. * Called from the drag:start event
  302. * @method start
  303. */
  304. start: function() {
  305. this._setDimCache();
  306. },
  307. /**
  308. * Called from the drag:end event
  309. * @method end
  310. */
  311. end: function() {
  312. this._dimCache = null;
  313. this._cancelScroll();
  314. }
  315. });
  316.  
  317. Y.namespace('Plugin');
  318.  
  319.  
  320. /**
  321. * Extends the Scroll class to make the window scroll while dragging.
  322. * @class DDWindowScroll
  323. * @extends Scroll
  324. * @namespace Plugin
  325. * @constructor
  326. */
  327. WS = function() {
  328. WS.superclass.constructor.apply(this, arguments);
  329. };
  330. WS.ATTRS = Y.merge(S.ATTRS, {
  331. /**
  332. * Turn on window scroll support, default: true
  333. * @attribute windowScroll
  334. * @type Boolean
  335. */
  336. windowScroll: {
  337. value: true,
  338. setter: function(scroll) {
  339. if (scroll) {
  340. this.set(PARENT_SCROLL, Y.one('win'));
  341. }
  342. return scroll;
  343. }
  344. }
  345. });
  346. Y.extend(WS, S, {
  347. //Shouldn't have to do this..
  348. initializer: function() {
  349. this.set('windowScroll', this.get('windowScroll'));
  350. }
  351. });
  352. /**
  353. * The Scroll instance will be placed on the Drag instance under the winscroll namespace.
  354. * @property NS
  355. * @default winscroll
  356. * @readonly
  357. * @protected
  358. * @static
  359. * @type {String}
  360. */
  361. WS.NAME = WS.NS = 'winscroll';
  362. Y.Plugin.DDWinScroll = WS;
  363.  
  364.  
  365. /**
  366. * Extends the Scroll class to make a parent node scroll while dragging.
  367. * @class DDNodeScroll
  368. * @extends Scroll
  369. * @namespace Plugin
  370. * @constructor
  371. */
  372. NS = function() {
  373. NS.superclass.constructor.apply(this, arguments);
  374.  
  375. };
  376. NS.ATTRS = Y.merge(S.ATTRS, {
  377. /**
  378. * The node we want to scroll. Used to set the internal parentScroll attribute.
  379. * @attribute node
  380. * @type Node
  381. */
  382. node: {
  383. value: false,
  384. setter: function(node) {
  385. var n = Y.one(node);
  386. if (!n) {
  387. if (node !== false) {
  388. Y.error('DDNodeScroll: Invalid Node Given: ' + node);
  389. }
  390. } else {
  391. this.set(PARENT_SCROLL, n);
  392. }
  393. return n;
  394. }
  395. }
  396. });
  397. Y.extend(NS, S, {
  398. //Shouldn't have to do this..
  399. initializer: function() {
  400. this.set('node', this.get('node'));
  401. }
  402. });
  403. /**
  404. * The NodeScroll instance will be placed on the Drag instance under the nodescroll namespace.
  405. * @property NS
  406. * @default nodescroll
  407. * @readonly
  408. * @protected
  409. * @static
  410. * @type {String}
  411. */
  412. NS.NAME = NS.NS = 'nodescroll';
  413. Y.Plugin.DDNodeScroll = NS;
  414.  
  415. Y.DD.Scroll = S;
  416.  
  417.  
  418.