API Docs for: 3.8.0
Show:

File: slider/js/clickable-rail.js

  1. /**
  2.  * Adds support for mouse interaction with the Slider rail triggering thumb
  3.  * movement.
  4.  *
  5.  * @module slider
  6.  * @submodule clickable-rail
  7.  */

  8. /**
  9.  * Slider extension that allows clicking on the Slider's rail element,
  10.  * triggering the thumb to align with the location of the click.
  11.  *
  12.  * @class ClickableRail
  13.  */
  14. function ClickableRail() {
  15.     this._initClickableRail();
  16. }

  17. Y.ClickableRail = Y.mix(ClickableRail, {

  18.     // Prototype methods added to host class
  19.     prototype: {

  20.         /**
  21.          * Initializes the internal state and sets up events.
  22.          *
  23.          * @method _initClickableRail
  24.          * @protected
  25.          */
  26.         _initClickableRail: function () {
  27.             this._evtGuid = this._evtGuid || (Y.guid() + '|');

  28.             /**
  29.              * Broadcasts when the rail has received a mousedown event and
  30.              * triggers the thumb positioning.  Use
  31.              * <code>e.preventDefault()</code> or
  32.              * <code>set(&quot;clickableRail&quot;, false)</code> to prevent
  33.              * the thumb positioning.
  34.              *
  35.              * @event railMouseDown
  36.              * @preventable _defRailMouseDownFn
  37.              */
  38.             this.publish('railMouseDown', {
  39.                 defaultFn: this._defRailMouseDownFn
  40.             });

  41.             this.after('render', this._bindClickableRail);
  42.             this.on('destroy', this._unbindClickableRail);
  43.         },

  44.         /**
  45.          * Attaches DOM event subscribers to support rail interaction.
  46.          *
  47.          * @method _bindClickableRail
  48.          * @protected
  49.          */
  50.         _bindClickableRail: function () {
  51.             this._dd.addHandle(this.rail);

  52.             this.rail.on(this._evtGuid + Y.DD.Drag.START_EVENT,
  53.                 Y.bind(this._onRailMouseDown, this));
  54.         },

  55.         /**
  56.          * Detaches DOM event subscribers for cleanup/destruction cycle.
  57.          *
  58.          * @method _unbindClickableRail
  59.          * @protected
  60.          */
  61.         _unbindClickableRail: function () {
  62.             if (this.get('rendered')) {
  63.                 var contentBox = this.get('contentBox'),
  64.                     rail = contentBox.one('.' + this.getClassName('rail'));

  65.                 rail.detach(this.evtGuid + '*');
  66.             }
  67.         },

  68.         /**
  69.          * Dispatches the railMouseDown event.
  70.          *
  71.          * @method _onRailMouseDown
  72.          * @param e {DOMEvent} the mousedown event object
  73.          * @protected
  74.          */
  75.         _onRailMouseDown: function (e) {
  76.             if (this.get('clickableRail') && !this.get('disabled')) {
  77.                 this.fire('railMouseDown', { ev: e });
  78.                 this.thumb.focus();
  79.             }
  80.         },

  81.         /**
  82.          * Default behavior for the railMouseDown event.  Centers the thumb at
  83.          * the click location and passes control to the DDM to behave as though
  84.          * the thumb itself were clicked in preparation for a drag operation.
  85.          *
  86.          * @method _defRailMouseDownFn
  87.          * @param e {Event} the EventFacade for the railMouseDown custom event
  88.          * @protected
  89.          */
  90.         _defRailMouseDownFn: function (e) {
  91.             e = e.ev;

  92.             // Logic that determines which thumb should be used is abstracted
  93.             // to someday support multi-thumb sliders
  94.             var dd     = this._resolveThumb(e),
  95.                 i      = this._key.xyIndex,
  96.                 length = parseFloat(this.get('length'), 10),
  97.                 thumb,
  98.                 thumbSize,
  99.                 xy;
  100.                
  101.             if (dd) {
  102.                 thumb = dd.get('dragNode');
  103.                 thumbSize = parseFloat(thumb.getStyle(this._key.dim), 10);

  104.                 // Step 1. Allow for aligning to thumb center or edge, etc
  105.                 xy = this._getThumbDestination(e, thumb);

  106.                 // Step 2. Remove page offsets to give just top/left style val
  107.                 xy = xy[ i ] - this.rail.getXY()[i];

  108.                 // Step 3. Constrain within the rail in case of attempt to
  109.                 // center the thumb when clicking on the end of the rail
  110.                 xy = Math.min(
  111.                         Math.max(xy, 0),
  112.                         (length - thumbSize));

  113.                 this._uiMoveThumb(xy, { source: 'rail' });

  114.                 // Set e.target for DD's IE9 patch which calls
  115.                 // e.target._node.setCapture() to allow imgs to be dragged.
  116.                 // Without this, setCapture is called from the rail and rail
  117.                 // clicks on other Sliders may have their thumb movements
  118.                 // overridden by a different Slider (the thumb on the wrong
  119.                 // Slider moves).
  120.                 e.target = this.thumb.one('img') || this.thumb;

  121.                 // Delegate to DD's natural behavior
  122.                 dd._handleMouseDownEvent(e);

  123.                 // TODO: this won't trigger a slideEnd if the rail is clicked
  124.                 // check if dd._move(e); dd._dragThreshMet = true; dd.start();
  125.                 // will do the trick.  Is that even a good idea?
  126.             }
  127.         },

  128.         /**
  129.          * Resolves which thumb to actuate if any.  Override this if you want to
  130.          * support multiple thumbs.  By default, returns the Drag instance for
  131.          * the thumb stored by the Slider.
  132.          *
  133.          * @method _resolveThumb
  134.          * @param e {DOMEvent} the mousedown event object
  135.          * @return {DD.Drag} the Drag instance that should be moved
  136.          * @protected
  137.          */
  138.         _resolveThumb: function (e) {
  139.             /* Temporary workaround
  140.             var primaryOnly = this._dd.get('primaryButtonOnly'),
  141.                 validClick  = !primaryOnly || e.button <= 1;

  142.             return (validClick) ? this._dd : null;
  143.              */
  144.             return this._dd;
  145.         },

  146.         /**
  147.          * Calculates the top left position the thumb should be moved to to
  148.          * align the click XY with the center of the specified node.
  149.          *
  150.          * @method _getThumbDestination
  151.          * @param e {DOMEvent} The mousedown event object
  152.          * @param node {Node} The node to position
  153.          * @return {Array} the [top, left] pixel position of the destination
  154.          * @protected
  155.          */
  156.         _getThumbDestination: function (e, node) {
  157.             var offsetWidth  = node.get('offsetWidth'),
  158.                 offsetHeight = node.get('offsetHeight');

  159.             // center
  160.             return [
  161.                 (e.pageX - Math.round((offsetWidth  / 2))),
  162.                 (e.pageY - Math.round((offsetHeight / 2)))
  163.             ];
  164.         }

  165.     },

  166.     // Static properties added onto host class
  167.     ATTRS: {
  168.         /**
  169.          * Enable or disable clickable rail support.
  170.          *
  171.          * @attribute clickableRail
  172.          * @type {Boolean}
  173.          * @default true
  174.          */
  175.         clickableRail: {
  176.             value: true,
  177.             validator: Y.Lang.isBoolean
  178.         }
  179.     }

  180. }, true);

  181.