JAVASCRIPT   38

hoverintent.js

Guest on 12th August 2021 06:55:41 PM

  1. /******************************************************************************/
  2.  
  3. /*!
  4.  * hoverIntent v1.8.1  // jQuery v1.9.1+
  5.  * http://cherne.net/brian/resources/jquery.hoverIntent.html
  6.  *
  7.  * You may use hoverIntent under the terms of the MIT license. Basically that
  8.  * means you are free to use hoverIntent as long as this header is left intact.
  9.  * Copyright  Brian Cherne
  10.  */
  11.  
  12. ;(function(factory) {
  13.     'use strict';
  14.     if (typeof define === 'function' && define.amd) {
  15.         define(['jquery'], factory);
  16.     } else if (jQuery && !jQuery.fn.hoverIntent) {
  17.         factory(jQuery);
  18.     }
  19. })(function($) {
  20.     'use strict';
  21.  
  22.     // default configuration values
  23.     var _cfg = {
  24.         interval: 100,
  25.         sensitivity: 6,
  26.         timeout: 0
  27.     };
  28.  
  29.     // counter used to generate an ID for each instance
  30.     var INSTANCE_COUNT = 0;
  31.  
  32.     // current X and Y position of mouse, updated during mousemove tracking (shared across instances)
  33.     var cX, cY;
  34.  
  35.     // saves the current pointer position coordinated based on the given mouse event
  36.     var track = function(ev) {
  37.         cX = ev.pageX;
  38.         cY = ev.pageY;
  39.     };
  40.  
  41.     // compares current and previous mouse positions
  42.     var compare = function(ev,$el,s,cfg) {
  43.         // compare mouse positions to see if pointer has slowed enough to trigger `over` function
  44.         if ( Math.sqrt( (s.pX-cX)*(s.pX-cX) + (s.pY-cY)*(s.pY-cY) ) < cfg.sensitivity ) {
  45.             $el.off('mousemove.hoverIntent'+s.namespace,track);
  46.             delete s.timeoutId;
  47.             // set hoverIntent state as active for this element (so `out` handler can eventually be called)
  48.             s.isActive = true;
  49.             // clear coordinate data
  50.             delete s.pX; delete s.pY;
  51.             return cfg.over.apply($el[0],[ev]);
  52.         } else {
  53.             // set previous coordinates for next comparison
  54.             s.pX = cX; s.pY = cY;
  55.             // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
  56.             s.timeoutId = setTimeout( function(){compare(ev, $el, s, cfg);} , cfg.interval );
  57.         }
  58.     };
  59.  
  60.     // triggers given `out` function at configured `timeout` after a mouseleave and clears state
  61.     var delay = function(ev,$el,s,out) {
  62.         delete $el.data('hoverIntent')[s.id];
  63.         return out.apply($el[0],[ev]);
  64.     };
  65.  
  66.     $.fn.hoverIntent = function(handlerIn,handlerOut,selector) {
  67.         // instance ID, used as a key to store and retrieve state information on an element
  68.         var instanceId = INSTANCE_COUNT++;
  69.  
  70.         // extend the default configuration and parse parameters
  71.         var cfg = $.extend({}, _cfg);
  72.         if ( $.isPlainObject(handlerIn) ) {
  73.             cfg = $.extend(cfg, handlerIn );
  74.         } else if ($.isFunction(handlerOut)) {
  75.             cfg = $.extend(cfg, { over: handlerIn, out: handlerOut, selector: selector } );
  76.         } else {
  77.             cfg = $.extend(cfg, { over: handlerIn, out: handlerIn, selector: handlerOut } );
  78.         }
  79.  
  80.         // A private function for handling mouse 'hovering'
  81.         var handleHover = function(e) {
  82.             // cloned event to pass to handlers (copy required for event object to be passed in IE)
  83.             var ev = $.extend({},e);
  84.  
  85.             // the current target of the mouse event, wrapped in a jQuery object
  86.             var $el = $(this);
  87.  
  88.             // read hoverIntent data from element (or initialize if not present)
  89.             var hoverIntentData = $el.data('hoverIntent');
  90.             if (!hoverIntentData) { $el.data('hoverIntent', (hoverIntentData = {})); }
  91.  
  92.             // read per-instance state from element (or initialize if not present)
  93.             var state = hoverIntentData[instanceId];
  94.             if (!state) { hoverIntentData[instanceId] = state = { id: instanceId }; }
  95.  
  96.             // state properties:
  97.             // id = instance ID, used to clean up data
  98.             // timeoutId = timeout ID, reused for tracking mouse position and delaying "out" handler
  99.             // isActive = plugin state, true after `over` is called just until `out` is called
  100.             // pX, pY = previously-measured pointer coordinates, updated at each polling interval
  101.             // namespace = string used as namespace for per-instance event management
  102.  
  103.             // clear any existing timeout
  104.             if (state.timeoutId) { state.timeoutId = clearTimeout(state.timeoutId); }
  105.  
  106.             // event namespace, used to register and unregister mousemove tracking
  107.             var namespace = state.namespace = '.hoverIntent'+instanceId;
  108.  
  109.             // handle the event, based on its type
  110.             if (e.type === 'mouseenter') {
  111.                 // do nothing if already active
  112.                 if (state.isActive) { return; }
  113.                 // set "previous" X and Y position based on initial entry point
  114.                 state.pX = ev.pageX; state.pY = ev.pageY;
  115.                 // update "current" X and Y position based on mousemove
  116.                 $el.on('mousemove.hoverIntent'+namespace,track);
  117.                 // start polling interval (self-calling timeout) to compare mouse coordinates over time
  118.                 state.timeoutId = setTimeout( function(){compare(ev,$el,state,cfg);} , cfg.interval );
  119.             } else { // "mouseleave"
  120.                 // do nothing if not already active
  121.                 if (!state.isActive) { return; }
  122.                 // unbind expensive mousemove event
  123.                 $el.off('mousemove.hoverIntent'+namespace,track);
  124.                 // if hoverIntent state is true, then call the mouseOut function after the specified delay
  125.                 state.timeoutId = setTimeout( function(){delay(ev,$el,state,cfg.out);} , cfg.timeout );
  126.             }
  127.         };
  128.  
  129.         // listen for mouseenter and mouseleave
  130.         return this.on({'mouseenter.hoverIntent':handleHover,'mouseleave.hoverIntent':handleHover}, cfg.selector);
  131.     };
  132. });

Raw Paste


Login or Register to edit or fork this paste. It's free.