Re:main.js

From disqus.com, 2 Months ago, written in JavaScript, viewed 3 times. This paste is a reply to Re:marionette.overrides.js from disqus.com - view diff
URL https://pastebin.freepbx.org/view/c8d58e59 Embed
Download Paste or View Raw
  1. /**
  2.  * Library which triggers Backbone events based on element visibility.
  3.  *
  4.  * Main method wraps any element or {@link ElementContainer|view with an el property}
  5.  * to make the library aware of it. This returns an event-aware
  6.  * wrapper. The following events are supported:
  7.  *
  8.  * - enter
  9.  * - exit
  10.  * - visible
  11.  * - invisible
  12.  *
  13.  * Enter and exit are called when an element's visibility changes, while
  14.  * visible and invisible are called per (throttled) scroll event.
  15.  *
  16.  * Visibility can also be manually checked at any time using
  17.  * {@link module:stance~isVisible|isVisible}.
  18.  *
  19.  * The library will cache element offsets and sizes.
  20.  * To invalidate a measurement call {@link module:stance~invalidate|invalidate}
  21.  * on the wrapper, or call the main {@link module:stance.invalidate|invalidate}
  22.  * to clear all cached measurements.
  23.  *
  24.  * To stop tracking an element, simply remove any bound events.
  25.  *
  26.  * The {@link ElementContainer|view} that is wrapped can also affect visibility
  27.  * measurements via two properties, topEdgeOffset and bottomEdgeOffset.
  28.  *
  29.  * Examples, use cases
  30.  * -------------------
  31.  *
  32.  *  - You have a view and you want to do something once the first time
  33.  *    it comes into the viewport:
  34.  *
  35.  *      view.listenToOnce(stance(view), 'visible', function () {
  36.  *          // Do something like kick off an analytics tracking request
  37.  *      });
  38.  *
  39.  *  -- NOTE: as the 'visible' event is bound to scroll, it will only fire
  40.  *     if the user scrolls.
  41.  *
  42.  * @module stance
  43.  */
  44.  
  45. define('stance/main',[
  46.     'core/Events',
  47.     'core/utils/function/debounce',
  48.     'core/utils/function/throttle',
  49.     'core/utils/object/extend',
  50.  
  51.     './tracking',
  52. ],
  53. function (
  54.     Events,
  55.     debounce,
  56.     throttle,
  57.     extend,
  58.  
  59.     tracking
  60. ) {
  61.     'use strict';
  62.  
  63.     /**
  64.      * An object which has a .el property, such as a Backbone View.
  65.      *
  66.      * @typedef ElementContainer
  67.      * @property {HTMLElement} el - The element to measure.
  68.      * @property {?(number|function)} topEdgeOffset - Amount to adjust the
  69.      *   top "visible" edge of the element by. Positive numbers decrease the
  70.      *   apparent size of the element.
  71.      * @property {?(number|?function)} bottomEdgeOffset - Amount to adjust the
  72.      *   bottom "visible" edge of the element by. Positive numbers decrease the
  73.      *   apparent size of the element.
  74.      */
  75.  
  76.     /**
  77.      * An html element or a container of an html element.
  78.      *
  79.      * @typedef Element-like
  80.      * @type {external:HTMLElement|ElementContainer}
  81.      */
  82.  
  83.     /**
  84.      * Wrap element or container to track its visibility.
  85.      * @class
  86.      * @function
  87.      * @implements {Events}
  88.      * @param {Element-like} obj - The element or view to measure.
  89.      * @property {Element-like} obj
  90.      * @property {boolean} lastVisible - Last known visibility of element.
  91.      * @returns {Stance}
  92.      */
  93.     function Stance(obj) {
  94.         // Create new instance if not invoked as constructor
  95.         if (!(this instanceof Stance))
  96.             return new Stance(obj);
  97.         this.obj = obj;
  98.         this.lastVisible = false;
  99.     }
  100.  
  101.     // Debounce the processing of events when we attach
  102.     // new handlers.
  103.     var _debouncedProcessEvents = debounce(function () {
  104.         tracking.processEvents(tracking.lastPos);
  105.     }, 250);
  106.  
  107.     extend(Stance.prototype, Events, {
  108.         on: function (name) {
  109.             // We only need to update tracking if the event binding is
  110.             // entirely new, ie. if the event is not bound yet.
  111.             // This must be checked before _events has been updated
  112.             var needSort = !(this._events && this._events[name]);
  113.  
  114.             var ret = Events.on.apply(this, arguments);
  115.  
  116.             // updateTracking must be called after _events has been updated
  117.             if (needSort)
  118.                 tracking.updateTracking(this);
  119.  
  120.             _debouncedProcessEvents();
  121.             return ret;
  122.         },
  123.  
  124.         off: function (name) {
  125.             var ret = Events.off.apply(this, arguments);
  126.  
  127.             // If the event is entirely unbound, update tracking.
  128.             // updateTracking must be called after _events has been updated
  129.             if (!(this._events && this._events[name]))
  130.                 tracking.updateTracking(this);
  131.  
  132.             return ret;
  133.         },
  134.  
  135.         /**
  136.          * Get the modified offset for this element, retrieving the cached version if possible.
  137.          *
  138.          * @returns {?FullOffset}
  139.          */
  140.         offset: function () {
  141.             return tracking.getElementOffset(this.obj);
  142.         },
  143.  
  144.         /**
  145.          * Decide if the element is visible.
  146.          * Returns null if element visibility cannot be determined.
  147.          *
  148.          * An element's visibility can be affected by the container's
  149.          * topEdgeOffset and bottomEdgeOffset properties.
  150.          *
  151.          * An element is visible if:
  152.          *
  153.          * 1. The top of the element is below the top of the viewport
  154.          *    and its modified top edge is above the bottom of the viewport.
  155.          * 2. The bottom of the element is above the bottom of the viewport
  156.          *    and its modified bottom edge is below the top of the viewport.
  157.          *
  158.          * @param {ViewportPos} [pos] - Viewport position to calculate for.
  159.          *   If omitted it will default to the last value passed to the scroll handler
  160.          * @returns {?boolean} Visibility, or null if indeterminate.
  161.          */
  162.         isVisible: function (pos) {
  163.             pos = pos || tracking.lastPos;
  164.  
  165.             if (!pos)
  166.                 return null;
  167.  
  168.             var screenTop = pos.top;
  169.             var screenBottom = screenTop + pos.height;
  170.             var offset = this.offset();
  171.  
  172.             if (!offset)
  173.                 return false;
  174.  
  175.             // See main function comment for a summary of this check
  176.             return (offset.offsetTop >= screenTop && offset.visibleTop < screenBottom) ||
  177.                 (offset.offsetTop + offset.height <= screenBottom && offset.visibleBottom > screenTop);
  178.         },
  179.  
  180.         /**
  181.          * Invalidate the last cached offset for this element.
  182.          *
  183.          * @returns {Stance} this
  184.          */
  185.         invalidate: function () {
  186.             tracking.clearCache(this.obj);
  187.  
  188.             return this;
  189.         },
  190.     });
  191.  
  192.     extend(Stance, {
  193.         /**
  194.          * Clear cached measurements.
  195.          *
  196.          * @todo TODO: Duplicates instance functionality, should this
  197.          *   function accept a parameter at all?
  198.          * @function
  199.          * @static
  200.          * @param {Element-like} [obj] - Element or container to clear cached
  201.          *   measurements for. If omitted, entire cache will be cleared.
  202.          */
  203.         invalidate: tracking.clearCache,
  204.  
  205.         /**
  206.          * @typedef ViewportPos
  207.          * @property {number} top - Top edge of viewport relative to document.
  208.          * @property {number} height - Height of viewport.
  209.          */
  210.  
  211.         /**
  212.          * Notify the library that a scroll event has occurred.
  213.          *
  214.          * Immediately calls all applicable event handlers.
  215.          *
  216.          * @function
  217.          * @static
  218.          * @param {ViewportPos} pos - Scroll information.
  219.          */
  220.         scroll: tracking.processEvents,
  221.  
  222.  
  223.         _windowScrollHandlerBound: false,
  224.         _ignoreCache: false,
  225.  
  226.         /**
  227.          * Window scroll event handler. Automatically bound on load.
  228.          *
  229.          * @private
  230.          * @static
  231.          * @function
  232.          */
  233.         _windowScrollHandler: throttle(function () {
  234.             if (Stance._ignoreCache)
  235.                 Stance.invalidate();
  236.  
  237.             // Trigger library scroll events
  238.             tracking.processEvents({
  239.                 top: window.pageYOffset,
  240.                 height: window.document.documentElement.clientHeight,
  241.             });
  242.         }, 250),
  243.  
  244.         /**
  245.          * Listen for window scroll and resize events.
  246.          *
  247.          * @static
  248.          * @param {boolean} ignoreCache - If provided, will determine if the scroll handler
  249.          *                                invalidates the position cache on each scroll event.
  250.          */
  251.         bindWindowEvents: function (ignoreCache) {
  252.             if (this._windowScrollHandlerBound)
  253.                 return;
  254.  
  255.             if (typeof ignoreCache !== 'undefined')
  256.                 Stance._ignoreCache = ignoreCache;
  257.  
  258.             window.addEventListener('scroll', this._windowScrollHandler);
  259.             window.addEventListener('resize', this._windowScrollHandler);
  260.  
  261.             this._windowScrollHandlerBound = true;
  262.  
  263.             // Set our initial `lastPos` values and process any already bound
  264.             // scroll events.
  265.             this._windowScrollHandler();
  266.         },
  267.  
  268.         /**
  269.          * Stop listening for window scroll and resize events.
  270.          *
  271.          * @static
  272.          */
  273.         unbindWindowEvents: function () {
  274.             Stance._ignoreCache = false;
  275.  
  276.             window.removeEventListener('scroll', this._windowScrollHandler);
  277.             window.removeEventListener('resize', this._windowScrollHandler);
  278.  
  279.             this._windowScrollHandlerBound = false;
  280.         },
  281.     });
  282.  
  283.     return Stance;
  284. });
  285.  
  286. define('stance', ['stance/main'], function (main) { return main; });
  287.  
  288. // https://c.disquscdn.com/next/next-core/core/stance/main.js
  289.  

Replies to Re:main.js rss

Title Name Language When
Re:tracking.js disqus.com javascript 2 Months ago.

Reply to "Re:main.js"

Here you can reply to the paste above