Xinxin Yang's avatar
Xinxin Yang committed
(function(){function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s}return e})()({1:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Events = function () {
  function Events() {
    _classCallCheck(this, Events);

    this._types = {};
    this._seq = 0;
  }

  _createClass(Events, [{
    key: "on",
    value: function on(eventType, listener) {
      var subs = this._types[eventType];
      if (!subs) {
        subs = this._types[eventType] = {};
      }
      var sub = "sub" + this._seq++;
      subs[sub] = listener;
      return sub;
    }

    // Returns false if no match, or string for sub name if matched

  }, {
    key: "off",
    value: function off(eventType, listener) {
      var subs = this._types[eventType];
      if (typeof listener === "function") {
        for (var key in subs) {
          if (subs.hasOwnProperty(key)) {
            if (subs[key] === listener) {
              delete subs[key];
              return key;
            }
          }
        }
        return false;
      } else if (typeof listener === "string") {
        if (subs && subs[listener]) {
          delete subs[listener];
          return listener;
        }
        return false;
      } else {
        throw new Error("Unexpected type for listener");
      }
    }
  }, {
    key: "trigger",
    value: function trigger(eventType, arg, thisObj) {
      var subs = this._types[eventType];
      for (var key in subs) {
        if (subs.hasOwnProperty(key)) {
          subs[key].call(thisObj, arg);
        }
      }
    }
  }]);

  return Events;
}();

exports.default = Events;

},{}],2:[function(require,module,exports){
"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.FilterHandle = undefined;

var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

var _events = require("./events");

var _events2 = _interopRequireDefault(_events);

var _filterset = require("./filterset");

var _filterset2 = _interopRequireDefault(_filterset);

var _group = require("./group");

var _group2 = _interopRequireDefault(_group);

var _util = require("./util");

var util = _interopRequireWildcard(_util);

function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) newObj[key] = obj[key]; } } newObj.default = obj; return newObj; } }

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function getFilterSet(group) {
  var fsVar = group.var("filterset");
  var result = fsVar.get();
  if (!result) {
    result = new _filterset2.default();
    fsVar.set(result);
  }
  return result;
}

var id = 1;
function nextId() {
  return id++;
}

/**
 * Use this class to contribute to, and listen for changes to, the filter set
 * for the given group of widgets. Filter input controls should create one
 * `FilterHandle` and only call {@link FilterHandle#set}. Output widgets that
 * wish to displayed filtered data should create one `FilterHandle` and use
 * the {@link FilterHandle#filteredKeys} property and listen for change
 * events.
 *
 * If two (or more) `FilterHandle` instances in the same webpage share the
 * same group name, they will contribute to a single "filter set". Each
 * `FilterHandle` starts out with a `null` value, which means they take
 * nothing away from the set of data that should be shown. To make a
 * `FilterHandle` actually remove data from the filter set, set its value to
 * an array of keys which should be displayed. Crosstalk will aggregate the
 * various key arrays by finding their intersection; only keys that are
 * present in all non-null filter handles are considered part of the filter
 * set.
 *
 * @param {string} [group] - The name of the Crosstalk group, or if none,
 *   null or undefined (or any other falsy value). This can be changed later
 *   via the {@link FilterHandle#setGroup} method.
 * @param {Object} [extraInfo] - An object whose properties will be copied to
 *   the event object whenever an event is emitted.
 */

var FilterHandle = exports.FilterHandle = function () {
  function FilterHandle(group, extraInfo) {
    _classCallCheck(this, FilterHandle);

    this._eventRelay = new _events2.default();
    this._emitter = new util.SubscriptionTracker(this._eventRelay);

    // Name of the group we're currently tracking, if any. Can change over time.
    this._group = null;
    // The filterSet that we're tracking, if any. Can change over time.
    this._filterSet = null;
    // The Var we're currently tracking, if any. Can change over time.
    this._filterVar = null;
    // The event handler subscription we currently have on var.on("change").
    this._varOnChangeSub = null;

    this._extraInfo = util.extend({ sender: this }, extraInfo);

    this._id = "filter" + nextId();

    this.setGroup(group);
  }

  /**
   * Changes the Crosstalk group membership of this FilterHandle. If `set()` was
   * previously called on this handle, switching groups will clear those keys
   * from the old group's filter set. These keys will not be applied to the new
   * group's filter set either. In other words, `setGroup()` effectively calls
   * `clear()` before switching groups.
   *
   * @param {string} group - The name of the Crosstalk group, or null (or
   *   undefined) to clear the group.
   */


  _createClass(FilterHandle, [{
    key: "setGroup",
    value: function setGroup(group) {
      var _this = this;

      // If group is unchanged, do nothing
      if (this._group === group) return;
      // Treat null, undefined, and other falsy values the same
      if (!this._group && !group) return;

      if (this._filterVar) {
        this._filterVar.off("change", this._varOnChangeSub);
        this.clear();
        this._varOnChangeSub = null;
        this._filterVar = null;
        this._filterSet = null;
      }

      this._group = group;