Source: core/_EventsMixin.js

/**
 * Copyright (C) 2005-2016 Alfresco Software Limited.
 *
 * This file is part of Alfresco
 *
 * Alfresco is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Alfresco is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
 */

/**
 * <p>Provides Core event handlers for other widgets to use.</p>
 *
 * <p>Scroll and Resize events are rate limited: handlers listening to those emitted events
 * will not be triggered every time the browser triggers the corresponding event. This is to
 * provide optimised handlers that don't run too frequently.</p>
 *
 * @example <caption>Sample call</caption>
 * constructor: function() {
 *    this.publishScrollEvents(this.domNode);
 *    this.alfSubscribe(this.eventsScrollTopic, lang.hitch(this, this.onScroll));
 * }
 *
 * <p>If your handler needs EVERY browser event, then you're best off subscribing to those
 * events directly</p>
 *
 * @example <caption>Manual subscription</caption>
 * on(window, "scroll", lang.hitch(this, this.onScroll));
 *
 * @module alfresco/core/_EventsMixin
 * @mixes module:alfresco/core/Core
 * @author Martin Doyle
 */
define(["alfresco/core/Core",
        "alfresco/core/topics",
        "alfresco/util/functionUtils", 
        "dojo/_base/declare", 
        "dojo/_base/lang", 
        "dojo/on"], 
        function(AlfCore, topics, funcUtils, declare, lang, on) {

   return declare([AlfCore], {

      /**
       * This topic is used to subscribe to rate limited scroll events.
       *
       * @event eventsScrollTopic
       * @instance
       * @type {String}
       * @default
       */
      eventsScrollTopic: "ALF_EVENTS_SCROLL",

      /**
       * This topic is used to subscribe to rate limited resize events.
       *
       * @event eventsResizeTopic
       * @instance
       * @type {String}
       * @default
       */
      eventsResizeTopic: "ALF_EVENTS_RESIZE",

      /**
       * Debounce a simple topic publish
       *
       * @instance
       * @param {String} topic The topic to be published
       * @param {object} [payload] The payload to publish on the supplied topic
       * @param {boolean} [global] Indicates that the pub/sub scope should not be applied
       * @param {boolean} [parentScope] Indicates that the pub/sub scope inherited from the parent should be applied
       * @param {Object} [args] Can take any of the optional arguments from the
       *                        [functionUtils debounce method]{@link module:alfresco/util/functionUtils#debounce}
       * @return {Object} An object containing a remove() function which will clear any outstanding publish
       */
      debouncedPublish: function alfresco_core__EventsMixin__debouncedPublish(topic, payload, global, parentScope, args) {
         var publishFunc = lang.hitch(this, this.alfPublish, topic, payload, global, parentScope),
            debounceArgs = lang.mixin({
               name: topic,
               func: publishFunc
            }, args || {});
         return funcUtils.debounce(debounceArgs);
      },

      /**
       * Throttle a simple topic publish
       *
       * @instance
       * @param {String} topic The topic to be published
       * @param {object} [payload] The payload to publish on the supplied topic
       * @param {boolean} [global] Indicates that the pub/sub scope should not be applied
       * @param {boolean} [parentScope] Indicates that the pub/sub scope inherited from the parent should be applied
       * @param {Object} [args] Can take any of the optional arguments from the
       *                        [functionUtils throttle method]{@link module:alfresco/util/functionUtils#throttle}
       * @return {Object} An object containing a remove() function which will clear any outstanding publish
       */
      throttledPublish: function alfresco_core__EventsMixin__throttledPublish(topic, payload, global, parentScope, args) {
         var publishFunc = lang.hitch(this, this.alfPublish, topic, payload, global, parentScope),
            throttleArgs = lang.mixin({
               name: topic,
               func: publishFunc
            }, args || {});
         return funcUtils.throttle(throttleArgs);
      },

      /**
       * When a scroll event happens on the specified node (defaults to window), then publish
       * to the [scroll topic]{@link module:alfresco/core/_EventsMixin#eventsScrollTopic}.
       *
       * @instance
       * @param {Object} [scrollNode=window] The scroll node
       * @return {Object} The scroll-listener, which contains a remove() function which can be called to release the listener
       */
      publishScrollEvents: function alfresco_core__EventsMixin__publishScrollEvents(scrollNode) {
         var nodeToMonitor = scrollNode || window,
            scrollListener = on(nodeToMonitor, "scroll", lang.hitch(this, this.throttledPublish, this.eventsScrollTopic, {
               node: nodeToMonitor
            }));
         this.own && this.own(scrollListener);
         return scrollListener;
      },

      /**
       * When a resize event happens on the window, then publish
       * to the [resize topic]{@link module:alfresco/core/_EventsMixin#eventsResizeTopic}.
       *
       * @instance
       * @param {Object} [nodeToMonitor=window] The node to monitor for resizes
       * @return {Object} The resize-listener, which contains a remove() function which can be called to release the listener
       */
      publishResizeEvents: function alfresco_core__EventsMixin__publishResizeEvents(nodeToMonitor) {
         var resizeAction = lang.hitch(this, this.throttledPublish, this.eventsResizeTopic, {
               node: nodeToMonitor
            }),
            resizeListener,
            resizeSubscription;
         if (nodeToMonitor === window) {
            resizeListener = on(window, "resize", resizeAction);
            this.own && this.own(resizeListener);
         } else {
            resizeSubscription = this.alfSubscribe(topics.NODE_RESIZED, lang.hitch(this, function(payload) {
               var resizedNode = payload.node,
                  testNode = nodeToMonitor;
               while (testNode && testNode !== resizedNode) {
                  testNode = testNode.parentNode;
               }
               if (testNode === resizedNode) {
                  // If the node-to-monitor is, or is a descendant of, the resized node, trigger a resize event
                  resizeAction();
               }
            }), true);
            resizeListener = {
               remove: lang.hitch(this, function() {
                  this.alfUnsubscribe(resizeSubscription);
               })
            };
         }
         return resizeListener;
      }
   });
});