A data item in a {@link CatalogGroup}.

@alias CatalogItem
@constructor
@extends CatalogMember
@abstract

@param {Terria} terria The Terria instance.
977232
function(terria) {
  CatalogMember.call(this, terria);

  this._enabledDate = undefined;
  this._shownDate = undefined;
  this._loadForEnablePromise = undefined;
  this._lastLoadInfluencingValues = undefined;

  // The catalog item to show in the Now Viewing when this item is enabled, instead of this item.
  // If undefined, this item itself is shown.
  this.nowViewingCatalogItem = undefined;

  // The catalog item that created this one.  Usually this is undefined, but may be defined if
  // the {@see CatalogItem} in the catalog acts like a factory to produce a different catalog item for the
  // {@see NowViewing}, rather than being added to the {@see NowViewing} itself.  In that scenario, this
  // property on the item in the now viewing would be a reference to the item in the catalog.
  // @type {CatalogItem}
  this.creatorCatalogItem = undefined;

  /**
   * The index of the item in the Now Viewing list.  Setting this property does not automatically change the order.
   * This property is used intenally to save/restore the Now Viewing order and is not intended for general use.
   * @private
   * @type {Number}
   */
  this.nowViewingIndex = undefined;

  /**
   * Gets or sets the geographic rectangle (extent or bounding box) containing this data item.  This property is observable.
   * @type {Rectangle}
   */
  this.rectangle = undefined;

  /**
   * Gets or sets the URL of this data.  This property is observable.
   * @type {String}
   */
  this.url = undefined;

  /**
   * Gets or sets a description of the custodian of this data item.
   * This property is an HTML string that must be sanitized before display to the user.
   * This property is observable.
   * @type {String}
   */
  this.dataCustodian = undefined;

  /**
   * Gets or sets an attribution displayed on the map when this catalog item is enabled.
   * This property is observable.
   * @type {Credit}
   */
  this.attribution = undefined;

  /**
   * Gets or sets the URL from which this data item's metadata description can be retrieved, or undefined if
   * metadata is not available for this data item.  The format of the metadata depends on the type of data item.
   * For example, Web Map Service (WMS) data items provide their metadata via their GetCapabilities document.
   * This property is observable.
   * @type {String}
   */
  this.metadataUrl = undefined;

  /**
   * Gets or sets a value indicating whether this data item is enabled.  An enabled data item appears in the
   * "Now Viewing" pane, but is not necessarily shown on the map.  This property is observable.
   * @type {Boolean}
   */
  this.isEnabled = false;

  /**
   * Gets or sets a value indicating whether this data item is currently shown on the map.  In order to be shown,
   * the item must also be enabled.  This property is observable.
   * @type {Boolean}
   */
  this.isShown = false;

  /**
   * Gets or sets a value indicating whether the legend for this data item is currently visible.
   * This property is observable.
   * @type {Boolean}
   */
  this.isLegendVisible = true;

  /**
   * Gets or sets a flag which determines whether the legend comes before (false) or after (true) the display variable choice.
   * Default false.
   * @type {Boolean}
   */
  this.displayChoicesBeforeLegend = false;

  /**
   * Gets or sets the clock parameters for this data item.  If this property is undefined, this data item
   * does not have any time-varying data.  This property is observable.
   * @type {DataSourceClock}
   */
  this.clock = undefined;

  /**
   * Gets or sets a value indicating whether this data source is currently loading.  This property is observable.
   * @type {Boolean}
   */
  this.isLoading = false;

  /*
   * Gets or sets a value indicating whether this data source can be enabled via a checkbox in the Data Catalog Tab.
   * This property is observable.
   * @type {Boolean}
   */
  this.isEnableable = true;

  /**
   * Gets or sets a value indicating whether this data source can be shown on the map (as opposed to a time-series dataset,
   * for instance, which can only be shown in a chart).
   * This property is observable.
   * @type {Boolean}
   */
  this.isMappable = true;

  /**
   * Gets or sets a value indicating whether this data source should show an info icon. This property is observable.
   * @type {Boolean}
   */
  this.showsInfo = true;

  /**
   * Gets or sets a message to show when this item is enabled for the first time in order to call attention to the Now Viewing panel.
   * @type {String}
   */
  this.nowViewingMessage = undefined;

  /**
   * Gets or sets a template to display message in a info box.
   * May be a string or an object with template, name and/or partials properties.
   * @type {String|Object}
   */
  this.featureInfoTemplate = undefined;

  /**
   * The maximum number of features whose information can be shown at one time in the Feature Info Panel, from this item.
   * Defaults to terria.configParameters.defaultMaximumShownFeatureInfos
   * @type {Number}
   */
  this.maximumShownFeatureInfos =
    terria.configParameters.defaultMaximumShownFeatureInfos;

  /**
   * Gets or sets a value indicating whether the map will automatically zoom to this catalog item when it is enabled.
   *
   * Note that within a single init source:
   *
   * * Catalog items with both `isEnabled` and `zoomOnEnable` set to true will override the top-level `initialCamera` property.
   * * If multiple catalog items have both `isEnabled` and `zoomOnEnable` set to true, it is undefined which one will affect the camera.
   *
   * In the case of multiple init sources, however, the camera will reflect whatever happens in the _last_ init source, whether
   * it is a result of a `zoomOnEnable` or an `initialCamera`,
   * @type {Boolean}
   * @default false
   */
  this.zoomOnEnable = false;

  /**
   * Options for formatting current time and timeline tic labels. Options are:
   *    currentTime   // Current time in time slider will be shown in this format. For example "mmmm yyyy" for Jan 2016.
   *    timelineTic   // Timeline tics will have this label. For example "yyyy" will cause each tic to be labelled with the year.
   * @type {Object}
   */
  this.dateFormat = {};

  /**
   * Gets or sets a flag indicating whether imagery should be displayed using this item's own clock (currentTime, multiplier),
   * or, if false, the terria clock (whose current time is shown in the timeline UI). Default false.
   * This property is observable.
   * @type {Boolean}
   */
  this.useOwnClock = false;

  /**
   * Gets or sets a flag indicating whether the preview on the Add Data panel should be disabled. This is useful when
   * the preview will be very slow to load.
   */
  this.disablePreview = false;

  // _currentTime is effectively a view of clock.currentTime. It is defined as a separate state (mirror state) so that
  // it can be an independent knockout observable with all of the machinary that implies for free, without tracking a sub
  // property of a cesium primitive (namely clock.currentTime) which seems kind of nasty.
  this._currentTime = undefined;
  this._legendUrl = undefined;
  this._legendUrls = undefined;
  this._dataUrl = undefined;
  this._dataUrlType = undefined;

  knockout.track(this, [
    "rectangle",
    "dataCustodian",
    "attribution",
    "metadataUrl",
    "isEnabled",
    "isShown",
    "isLegendVisible",
    "clock",
    "_currentTime",
    "isLoading",
    "isMappable",
    "nowViewingMessage",
    "zoomOnEnable",
    "isEnableable",
    "showsInfo",
    "nowViewingMessage",
    "url",
    "_legendUrl",
    "_legendUrls",
    "_dataUrl",
    "_dataUrlType",
    "nowViewingCatalogItem",
    "useOwnClock",
    "disablePreview"
  ]);

  var evaluatingLegendUrl = false;

  /**
   * Gets or sets the URLs of the legends to show when this catalog item is enabled.
   * @member {LegendUrl} legendUrls
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "legendUrls", {
    get: function() {
      if (!defined(this._legendUrls) || this._legendUrls.length === 0) {
        var legendUrl = evaluatingLegendUrl ? undefined : this.legendUrl;
        if (
          defined(legendUrl) &&
          defined(legendUrl.url) &&
          legendUrl.url.length > 0
        ) {
          return [legendUrl];
        }
      }
      return this._legendUrls;
    },
    set: function(value) {
      this._legendUrls = value;
      this._legendUrl = undefined;
    }
  });

  /**
   * Gets or sets the URL of the legend to show when this catalog item is enabled.  If there is more than one
   * legend URL, this property returns the first one.
   * @member {LegendUrl} legendUrl
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "legendUrl", {
    get: function() {
      evaluatingLegendUrl = true;
      try {
        if (defined(this._legendUrl)) {
          return this._legendUrl;
        } else {
          var legendUrls = this.legendUrls;
          if (defined(legendUrls)) {
            return this.legendUrls[0];
          }
          return undefined;
        }
      } finally {
        evaluatingLegendUrl = false;
      }
    },
    set: function(value) {
      this._legendUrl = value;
      this._legendUrls = undefined;
    }
  });

  /**
   * Gets or sets the URL from which this data item's raw data can be retrieved, or undefined if raw data for
   * this data item is not available.  This property is observable.
   * @member {String} dataUrl
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "dataUrl", {
    get: function() {
      // dataUrl is derived from url if not explicitly specified.
      if (defined(this._dataUrl)) {
        return this._dataUrl;
      }

      return this.url;
    },
    set: function(value) {
      this._dataUrl = value;
    }
  });

  /**
   * Gets or sets the type of the {@link CatalogItem#dataUrl}, or undefined if raw data for this data
   * source is not available.  This property is observable.
   * Valid values are:
   *  * `direct` - A direct link to the data.
   *  * `wfs` - A Web Feature Service (WFS) base URL.  If {@link CatalogItem#dataUrl} is not
   *            specified, the base URL will be this data item's URL.
   *  * `wfs-complete` - A complete, ready-to-use link to download features from a WFS server.
   *  * `none` - There is no data link.
   * @member {String} dataUrlType
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "dataUrlType", {
    get: function() {
      if (defined(this._dataUrlType)) {
        return this._dataUrlType;
      } else {
        return "direct";
      }
    },
    set: function(value) {
      this._dataUrlType = value;
    }
  });

  /**
   * Gets / sets the CatalogItems current time.
   *
   * This property is an observable version of clock.currentTime, they will always have the same value.
   *
   * When setting the currentTime through this property the correct clock (terria.clock or this.clock) is updated
   * depending on whether .useOwnClock is true or false so that the catalog items state will reflect the new time
   * correctly.
   *
   * The get component of this property is effectively an interface adapter for clock.definitionChanged which changes
   * the structure from an Event when the current time changes to a knockout property which can be observed.
   *
   * @member {JulianDate} currentTime
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "currentTime", {
    get: function() {
      return this._currentTime;
    },
    set: function(value) {
      // Note: We don't explicitly need to set this._currentTime since our other machinery regarding updating
      // this._currentTime should take care of this.
      if (this.useOwnClock) {
        updateCurrentTime(this, value);
      } else {
        this.terria.clock.currentTime = JulianDate.clone(value);
        this.terria.clock.tick();
      }
    }
  });

  /**
   * Gets the CatalogItems current time as the discrete time that the CatalogItem has information for.
   * Returns undefined if the clock is beyond the range of the intervals specified by the layer.
   * Returns undefined if it is not possible to query the time (i.e. the item doesn't have a clock, availableDates or
   * intervals).
   *
   * See also clampedDiscreteTime if you want the discrete time that is clamped to the first / last value if the current
   * time is beyond the range of the intervals specified by the item.
   *
   * @member {Date} discreteTime
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "discreteTime", {
    get: function() {
      return timeAtIndex(this, getCurrentIndex(this));
    }
  });

  /**
   * Gets the CatalogItems current time as the discrete time that the CatalogItem has information for.
   * Returns the nearest time in-range if the clock is beyond the range of the intervals specified by the layer.
   * Returns undefined if it is not possible to query the time (i.e. the item doesn't have a clock, availableDates or
   * intervals).
   *
   * See also discreteTime if you want the discrete time that is undefined if the current time is beyond the range of
   * the intervals specified by the item.
   *
   * @member {Date} clampedDiscreteTime
   * @memberOf CatalogItem.prototype
   */
  knockout.defineProperty(this, "clampedDiscreteTime", {
    get: function() {
      if (defined(this.discreteTime)) {
        return this.discreteTime;
      }

      if (!hasValidCurrentTimeAndIntervals(this)) {
        return undefined;
      }

      if (timeIsBeforeStart(this, this.currentTime)) {
        return timeAtIndex(this, 0);
      }

      if (timeIsAfterStop(this, this.currentTime)) {
        return timeAtIndex(this, this.intervals.length - 1);
      }

      return undefined;
    }
  });

  // A property which defines when we are using the terria clock.
  // We define this as a knockout property so that we can watch for changes to the propery triggered by observables
  // that it depends on and update the subscription (watcher) on the terria.clock when the state changes.
  knockout.defineProperty(this, "_mirroringTerriaClock", {
    get: function() {
      return this.isEnabled && !this.useOwnClock && defined(this.clock);
    }
  });

  // A property which defines when the clock is defined.
  // We define this as a knockout property so that we can watch for all changes to the propery including when
  // .clock is overriden from derrived classes (and not just base CatalogItem.clock).
  knockout.defineProperty(this, "_clockDefined", {
    get: function() {
      return defined(this.clock);
    }
  });

  knockout.getObservable(this, "_clockDefined").subscribe(function(newValue) {
    clockChanged(this);
  }, this);

  knockout.getObservable(this, "isEnabled").subscribe(function(newValue) {
    isEnabledChanged(this);
  }, this);

  knockout.getObservable(this, "isShown").subscribe(function(newValue) {
    isShownChanged(this);
  }, this);

  knockout
    .getObservable(this, "_mirroringTerriaClock")
    .subscribe(function(newValue) {
      updateTerriaClockWatcher(this);
    }, this);

  knockout.getObservable(this, "useOwnClock").subscribe(function(newValue) {
    useOwnClockChanged(this);
  }, this);
}
1014327
function (groupKey, itemKey, itemIndex) {
                    this._lastFocusedItemKey = itemKey;
                    this._lastFocusedItemIndex = itemIndex;
                    itemIndex = "" + itemIndex;
                    this._itemToIndex[itemKey] = itemIndex;
                    this._groupToItem[groupKey] = itemKey;
                }
402199
function (item, itemIndex, then, complete, arrayWeTraverse) {
            $assert (item === data[itemIndex])
            $assert (itemIndex === currentIndex++)
            $assert (arrayWeTraverse === data)

            $assert (_.isFunction (then))
            $assert (_.isFunction (complete))

            then () }
1227586
function(terria) {
  CatalogItem.call(this, terria);

  this._imageryLayer = undefined;
  this._clock = undefined;
  this._currentIntervalIndex = -1;
  this._currentInterval = undefined;
  this._nextIntervalIndex = undefined;
  this._nextInterval = undefined;
  this._nextLayer = undefined;

  /**
   * Gets or sets the opacity (alpha) of the data item, where 0.0 is fully transparent and 1.0 is
   * fully opaque.  This property is observable.
   * @type {Number}
   * @default 0.6
   */
  this.opacity = 0.6;

  /**
   * Gets or sets a value indicating whether a 404 response code when requesting a tile should be
   * treated as an error.  If false, 404s are assumed to just be missing tiles and need not be
   * reported to the user.
   * @type {Boolean}
   * @default false
   */
  this.treat404AsError = false;

  /**
   * Gets or sets a value indicating whether a 403 response code when requesting a tile should be
   * treated as an error.  If false, 403s are assumed to just be missing tiles and need not be
   * reported to the user.
   * @type {Boolean}
   * @default false
   */
  this.treat403AsError = true;

  /**
   * Gets or sets a value indicating whether non-specific (no HTTP status code) tile errors should be ignored. This is a
   * last resort, for dealing with odd cases such as data sources that return non-images (eg XML) with a 200 status code.
   * No error messages will be shown to the user.
   * @type {Boolean}
   * @default false
   */
  this.ignoreUnknownTileErrors = false;

  /**
   * Keeps the layer on top of all other imagery layers.  This property is observable.
   * @type {Boolean}
   * @default false
   */
  this.keepOnTop = false;

  /**
   * Gets or sets a value indicating whether this dataset should be clipped to the {@link CatalogItem#rectangle}.
   * If true, no part of the dataset will be displayed outside the rectangle.  This property is true by default,
   * leading to better performance and avoiding tile request errors that might occur when requesting tiles outside the
   * server-specified rectangle.  However, it may also cause features to be cut off in some cases, such as if a server
   * reports an extent that does not take into account that the representation of features sometimes require a larger
   * spatial extent than the features themselves.  For example, if a point feature on the edge of the extent is drawn
   * as a circle with a radius of 5 pixels, half of that circle will be cut off.
   * @type {Boolean}
   * @default false
   */
  this.clipToRectangle = true;

  /**
   * Gets or sets a value indicating whether tiles of this catalog item are required to be loaded before terrain
   * tiles to which they're attached can be rendered.  This should usually be set to true for base layers and
   * false for all others.
   * @type {Boolean}
   * @default false
   */
  this.isRequiredForRendering = false;

  /**
   * Options for the value of the animation timeline at start. Valid options in config file are:
   *     initialTimeSource: "present"                            // closest to today's date
   *     initialTimeSource: "start"                              // start of time range of animation
   *     initialTimeSource: "end"                                // end of time range of animation
   *     initialTimeSource: An ISO8601 date e.g. "2015-08-08"    // specified date or nearest if date is outside range
   * @type {String}
   */
  this.initialTimeSource = undefined;

  /**
   * Gets or sets which side of the splitter (if present) to display this imagery layer on.  Defaults to both sides.
   * This property is observable.
   * @type {ImagerySplitDirection}
   */
  this.splitDirection = ImagerySplitDirection.NONE; // NONE means show on both sides of the splitter, if there is one.

  /**
   * Whether to show imagery availability on charts.
   * @type {Boolean}
   * @default false
   */
  this.showOnChart = false;

  /**
   * Whether this layer is sufficient to warrant a chart.
   * @type {Boolean}
   * @default false
   */
  this.dontChartAlone = false;

  /**
   * Gets or sets the name of a property in a feature returned from this layer's feature query service
   * that indicates the times at which this layer covers this position. For example, historical and
   * near-real-time satellite imagery often comes as daily swaths, with a given area on the globe
   * potentially only covered every number of days.
   * @type {String}
   */
  this.featureTimesProperty = undefined;

  this._allIntervals = undefined;

  this.intervalFilterFeature = undefined;
  this._intervalFilterCoordinates = undefined;

  // Need to track initialTimeSource so we can set it in the specs after setting intervals, and then have the current time update (via the clock property).
  knockout.track(this, [
    "_clock",
    "opacity",
    "treat404AsError",
    "ignoreUnknownTileErrors",
    "intervals",
    "clipToRectangle",
    "splitDirection",
    "initialTimeSource",
    "showOnChart",
    "dontChartAlone",
    "featureTimesProperty",
    "_allIntervals",
    "intervalFilterFeature",
    "_intervalFilterCoordinates"
  ]);

  overrideProperty(this, "_filteredIntervals", {
    get: function() {
      if (!defined(this.intervalFilterFeature)) {
        return undefined;
      }

      const featureTimesProperty = this.intervalFilterFeature.properties[
        this.featureTimesProperty
      ];
      if (!defined(featureTimesProperty)) {
        return undefined;
      }

      const featureTimes = featureTimesProperty.getValue(this.currentTime);
      return new TimeIntervalCollection(
        featureTimes.map(time => {
          return this._allIntervals.findIntervalContainingDate(
            JulianDate.fromIso8601(time)
          );
        })
      );
    }
  });

  /**
   * Gets or sets the {@link TimeIntervalCollection} defining the intervals of distinct imagery.  If this catalog item
   * is not time-dynamic, property is undefined.  This property is observable.
   * @type {TimeIntervalCollection}
   * @default undefined
   * @member {TimeIntervalCollection} intervals
   * @memberOf ImageryLayerCatalogItem.prototype
   */
  overrideProperty(this, "intervals", {
    get: function() {
      if (defined(this._filteredIntervals)) {
        return this._filteredIntervals;
      }
      return this._allIntervals;
    },
    set: function(value) {
      this._allIntervals = value;
    }
  });

  overrideProperty(this, "clock", {
    get: function() {
      var clock = this._clock;
      if (!clock && this.intervals && this.intervals.length > 0) {
        var startTime = this.intervals.start;
        var stopTime = this.intervals.stop;

        // Average about 5 seconds per interval.
        var totalDuration = JulianDate.secondsDifference(stopTime, startTime);
        var numIntervals = this.intervals.length;
        var averageDuration = totalDuration / numIntervals;
        var timePerSecond = averageDuration / 5;

        clock = new DataSourceClock();
        clock.startTime = startTime;
        clock.stopTime = stopTime;
        clock.multiplier = timePerSecond;

        setClockCurrentTime(clock, this.initialTimeSource);

        this._clock = clock;
      }
      return clock;
    },
    set: function(value) {
      this._clock = value;
    }
  });

  /**
   * Gets javascript dates describing the discrete datetimes (or intervals) available for this item.
   * By declaring this as a knockout defined property, it is cached.
   * @member {Date[]} availableDates
   * @memberOf ImageryLayerCatalogItem.prototype
   */
  knockout.defineProperty(
    this,
    "availableDates",
    {
      get: function() {
        const intervals = this.intervals;
        if (defined(intervals)) {
          // Only show the start of each interval. If only time instants were given, this is the instant.
          const datetimes = [];
          for (let i = 0; i < intervals.length; i++) {
            datetimes.push(JulianDate.toDate(intervals.get(i).start));
          }
          return datetimes;
        }
        return [];
      }
    },
    this
  );

  overrideProperty(this, "xAxis", {
    get: function() {
      if (this.showOnChart) {
        return new TableColumn("Date", this.availableDates, {
          type: VarType.TIME,
          units: "Date"
        });
      } else {
        return undefined;
      }
    }
  });

  knockout.getObservable(this, "opacity").subscribe(function() {
    updateOpacity(this);
  }, this);

  knockout.getObservable(this, "splitDirection").subscribe(function() {
    updateSplitDirection(this);
  }, this);
}
667580
function(terria, url) {
  DataSourceCatalogItem.call(this, terria);

  this._dataSource = undefined;

  this.url = url;

  /**
   * Gets or sets the CZML data, represented as a binary Blob, JSON object or array literal, or a Promise for one of those things.
   * If this property is set, {@link CatalogItem#url} is ignored.
   * This property is observable.
   * @type {Blob|Object|Promise|Array}
   */
  this.data = undefined;

  /**
   * Gets or sets the URL from which the {@link CzmlCatalogItem#data} was obtained.  This will be used
   * to resolve any resources linked in the CZML file, if any.
   * @type {String}
   */
  this.dataSourceUrl = undefined;

  knockout.track(this, ["data", "dataSourceUrl"]);
}
542964
function (type, item) {
        switch(type) {
            case simpleTypes.undefined:
            case simpleTypes.null:
                return true;
            case simpleTypes.string:
                if (item.trim().length === 0) {
                    return true;
                }
                return false;
            case simpleTypes.object:
                return (Object.keys(item).length === 0);
            case simpleTypes.array:
                return (item.length === 0);
            default:
                return false;
        };
    }
625629
function pullcatalog(opts, cb) {
  opts.path = APIM_CATALOG_ENDP +
              '?' + // filter parms
              APIM_CLIENT_ID_EQ + opts.clientid + '&' +
              APIM_TYPE_EQ + APIM_TYPE_FILTER;
  opts.prefix = 'catalogs-';
  opts.suffix = '.json';
  fetch(opts, function(err, result) {
    if (err) {
      cb(err);
    } else if (typeof result === 'object') {
      response.catalogs = result.file;
      var models = [];
      models.push(new ModelType('products', 'products-', APIM_PRODUCTS_ENDP));
      models.push(new ModelType('apis', 'apis-', APIM_APIS_ENDP));
      models.push(new ModelType('subscriptions', 'subs-', APIM_SUBS_ENDP));
      models.push(new ModelType('tlsprofiles', 'tlsprofs-', APIM_TLS_ENDP));
      models.push(new ModelType('registries', 'registries-', APIM_REGISTRIES_ENDP));
      models.forEach(
        function(model) {
          response[model.name] = [];
        }
      );
      var catalogsJSON;
      try {
        catalogsJSON = JSON.parse(result.contents);
      } catch (e) {
        cb(e);
        return;
      }
      var catalogs = [];
      catalogsJSON.forEach(function(obj) {
        catalogs.push({
          org: obj.organization.id,
          cat: obj.id });
      });
      cb(null, catalogs, models);
    } else {
      var error = new Error('Unexpected type returned from catalog fetch');
      cb(error);
    }
  });
}
195968
function(terria) {
  CatalogGroup.call(this, terria, "csw");

  /**
   * Gets or sets the URL of the CSW server.  This property is observable.
   * @type {String}
   */
  this.url = "";

  /**
   * Gets or sets the template XML string to POST to the CSW server to query for catalog items.  If this property is undefined,
   * {@link CswCatalogGroup.defaultGetRecordsTemplate} is used.  The XML string should have a `{startPosition}` placeholder to be
   * replaced with the next start position in order to allow incremental paging of results.
   * This property is observable.
   * @type {String}
   */
  this.getRecordsTemplate = undefined;

  /**
   * True to allow WMS resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   * @default true
   */
  this.includeWms = true;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the URI is a WMS resource.
   * @type {RegExp}
   */
  this.wmsResourceFormat = /\bwms\b/i;

  /**
   * True to allow KML resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   * @default false
   */
  this.includeKml = false;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the resource is a KML resource.
   * @type {RegExp}
   */
  this.kmlResourceFormat = /\bkml\b/i;

  /**
   * True to allow CSV resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   */
  this.includeCsv = false;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the resource is a CSV resource.
   * @type {RegExp}
   */
  this.csvResourceFormat = /\bcsv-geo-/i;

  /**
   * True to allow ESRI Map resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   * @default false
   */
  this.includeEsriMapServer = false;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the resource is an Esri MapServer resource.
   * @type {RegExp}
   */
  this.esriMapServerResourceFormat = /\besri rest\b/i;

  /**
   * True to allow GeoJSON resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   * @default false
   */
  this.includeGeoJson = false;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the resource is a GeoJSON resource.
   * @type {RegExp}
   */
  this.geoJsonResourceFormat = /\bgeojson\b/i;

  /**
   * Gets or sets a list of key value pairs that will be used to group resources returned from the catalog. The keys are used to match elements in the metadata and the values are used as names for the groups of resources to be created.
   * @type {RegExp}
   */
  this.metadataGroups = [];

  /**
   * Gets or sets a description of a domain that will be pulled from the CSW service and used to define the metadataGroups. The domain is obtained by querying the CSW server for a particular property - the values of the property form the domain, the values are assumed to define a hierarchy eg. Wave Models | Wave Energy Flux - which is a two level hierarchy of groups that will be used to classify metadata records.
   * @type {Object}
   */
  this.domainSpecification = undefined;

  /**
   * True to allow OGC:WPS service resources to be added to the catalog; otherwise, false.
   * @type {Boolean}
   * @default false
   */
  this.includeWps = false;

  /**
   * Gets or sets a regular expression that, when it matches the protocol attribute of a URI element of a record, indicates that the resource is a WPS resource.
   * @type {RegExp}
   */
  this.wpsResourceFormat = /\bwps\b/i;

  /**
   * Gets or sets a hash of properties that will be set on the item created from the CKAN resource.
   * For example, { "treat404AsError": false }
   * @type {Object}
   */
  this.itemProperties = undefined;

  knockout.track(this, [
    "url",
    "getRecordsParameters",
    "includeWms",
    "includeKml",
    "includeCsv",
    "includeEsriMapServer",
    "includeGeoJson",
    "includeWps",
    "itemProperties"
  ]);
}
463821
function ItemsItem() {
    /**
     * The id value
     * @member
     */
    this.id = null;
    /**
     * The sku value
     * @member
     */
    this.sku = null;
    /**
     * The title value
     * @member
     */
    this.title = null;
    /**
     * The quantity value
     * @member
     */
    this.quantity = null;
    /**
     * The price value
     * @member
     */
    this.price = null;
    /**
     * The formattedPrice value
     * @member
     */
    this.formattedPrice = null;
    /**
     * The currency value
     * @member
     */
    this.currency = null;
    /**
     * The productLink value
     * @member
     */
    this.productLink = null;
    /**
     * The weight value
     * @member
     */
    this.weight = null;
    /**
     * The formattedWeight value
     * @member
     */
    this.formattedWeight = null;
    /**
     * The media of value
     * @member
     * @type { Media }
     */
    this.media = Object.create(Media.prototype);

}
1078851
function addSharedMembers(terria, initSources) {
  const catalogForSharing = flattenCatalog(
    terria.catalog.serializeToJson({
      itemFilter: combineFilters([CatalogMember.itemFilters.noLocalData]),
      propertyFilter: combineFilters([
        CatalogMember.propertyFilters.sharedOnly,
        function(property) {
          return property !== "name";
        }
      ])
    })
  )
    .filter(function(item) {
      return item.isEnabled || item.isOpen;
    })
    .reduce(function(soFar, item) {
      soFar[item.id] = item;
      item.id = undefined;
      return soFar;
    }, {});

  // Eliminate open groups without all ancestors open
  Object.keys(catalogForSharing).forEach(key => {
    const item = catalogForSharing[key];
    const isGroupWithClosedParent =
      item.isOpen &&
      item.parents.some(parentId => !catalogForSharing[parentId]);

    if (isGroupWithClosedParent) {
      catalogForSharing[key] = undefined;
    }
  });

  if (Object.keys(catalogForSharing).length > 0) {
    initSources.push({
      sharedCatalogMembers: catalogForSharing
    });
  }
}
21333
function(terria) {
  CatalogItem.call(this, terria);

  /**
   * Gets or sets additional options to pass to Cesium's Cesium3DTileset constructor.
   * @type {Object}
   */
  this.options = undefined;

  /**
   * Gets or sets the ID of the Cesium Ion asset to access. If this property is set, the {@link Cesium3DTilesCatalogItem#url}
   * property is ignored.
   * @type {Number}
   */
  this.ionAssetId = undefined;

  /**
   * Gets or sets the Cesium Ion access token to use to access the tileset. If not specified, the token specified
   * using the `cesiumIonAccessToken` property in `config.json` is used. This property is ignored if
   * {@link Cesium3DTilesCatalogItem#ionAssetId} is not set.
   * @type {String}
   */
  this.ionAccessToken = undefined;

  /**
   * Gets or sets the Cesium Ion access token to use to access the tileset. If not specified, the default Ion
   * server, `https://api.cesium.com/`, is used. This property is ignored if
   * {@link Cesium3DTilesCatalogItem#ionAssetId} is not set.
   * @type {String}
   */
  this.ionServer = undefined;

  this._tileset = undefined;
}
512885
function forEachItemGroup (callback) {
        this.items.each(function (item) {
            if (ItemGroup.isItemGroup(item)) {
                item.forEachItemGroup(callback);
                callback(item, this); // eslint-disable-line callback-return
            }
        }, this);
    }
312704
function WebProcessingServiceCatalogItem(terria) {
  CatalogItem.call(this, terria);

  this._geoJsonItem = undefined;

  /**
   * Gets or sets the parameters to the WPS function.
   * All parameter names must be entered in lowercase in order to be consistent with references in TerrisJS code.
   * @type {FunctionParameter[]}
   */
  this.parameters = undefined;

  /**
   * Gets or sets the values of the parameters that were used to invoke this function.
   * @type {Object}
   */
  this.parameterValues = undefined;

  /**
   * Gets or sets the URL of the WPS completed response.  This property is ignored if
   * {@link WebProcessingServiceCatalogItem#wpsResponse} is defined.  This property is observable.
   * @type {String}
   */
  this.wpsResponseUrl = undefined;

  /**
   * Gets or sets the completed WPS response, as either XML or the result of passing the
   * XML through {@link xml2json}.
   * @type {Object|Document}
   */
  this.wpsResponse = undefined;

  knockout.track(this, ["wpsResponseUrl", "wpsResponse"]);
}
587940
function mapItemScheme (e) {
      var itemName = {
        'CategoryScheme': 'Category',
        'Hierarchy': 'HierarchicalCode',
        'Codelist': 'Code',
        'ConceptScheme': 'Concept',
        'AgencyScheme': 'Agency'
      }[e.localName];

      var itemScheme = mapMaintainableArtefact(e);
      itemScheme.isPartial = toBoolean(getAttrValue(e, 'isPartial'));
    itemScheme.leveled = toBoolean(getAttrValue(e, 'leveled')); // Hierarchy

    var itemURN = [
    'urn:sdmx:org.sdmx.infomodel',
    '.', itemScheme.package,
    '', itemName,
    '=', itemScheme.agencyID,
    ':', itemScheme.id,
    '(', itemScheme.version, ')'
    ].join('');

    function mapItems (node, hierarchy) {
      var items = _getChildrenNS(node, itemName);
      if (items.length === 0) return undefined;

      function mapItem (e) {
        var item = mapVersionableArtefact(e); // HierarchicalCode = versionable
        item.agencyID = itemScheme.agencyID;
        item.maintainableParentID = itemScheme.id;
        item.maintainableParentVersion = itemScheme.version;

        if (item.urn === undefined) {
          item.urn = itemURN + hierarchy + '.' + item.id;
        }

        item.parent = mapLocalReference(_getFirstChildNS(e, 'parent'));
        item.items = mapItems(e, hierarchy + '.' + item.id);

        if (e.localName === 'Concept') {
          item.isoConceptReference = mapISOConceptReference(_getFirstChildNS(e, 'ISOConceptReference'));
          item.coreRepresentation = mapRepresentation(_getFirstChildNS(e, 'CoreRepresentation'));
        }

        if (e.localName === 'HierarchicalCode') {
          item.code = mapReference(_getFirstChildNS(e, 'Code'), 'code', 'code');
        }

        return item;
      }

      return items.map(mapItem);
    }

    itemScheme.items = mapItems(e, '');

    return itemScheme;
  }
715591
function (type, data) {
    if (!_.isString(type)) {
      console.warn('Action types are required when calling dispatcher.dispatch()');
      return;
    }

    this.dispatcher.dispatch({
      type: type,
      data: data
    });
  }
319102
function(terria) {
  this._terria = terria;
  this._eventSubscriptions = new EventHelper();

  /**
   * Gets the list of items that we are "now viewing".  It is recommended that you use
   * the methods on this instance instead of manipulating the list of items directly.
   * This property is observable.
   * @type {CatalogItem[]}
   */
  this.items = [];

  knockout.track(this, ["items"]);

  this.showNowViewingRequested = new CesiumEvent();

  this._eventSubscriptions.add(
    this.terria.beforeViewerChanged,
    function() {
      beforeViewerChanged(this);
    },
    this
  );

  this._eventSubscriptions.add(
    this.terria.afterViewerChanged,
    function() {
      afterViewerChanged(this);
    },
    this
  );
}
30782
function Item(item, options) {
  Base.call(this, options);
  this.define('collection', this.options.collection);

  if (typeof item === 'object') {
    this.visit('set', item);
  }
}