Source: src/js/models/maps/VectorFilter.js

"use strict";

define(["jquery", "underscore", "backbone"], function ($, _, Backbone) {
  /**
   * @classdesc A VectorFilter Model represents one condition used to show or hide
   * specific features of a vector layer on a map. The filter defines rules used to show
   * features conditionally based on properties of the feature. For example, it could
   * specify hiding all vectors for an asset that have an area greater than 10 km2.
   * @classcategory Models/Maps
   * @class VectorFilter
   * @name VectorFilter
   * @extends Backbone.Model
   * @since 2.18.0
   * @constructor
   */
  var VectorFilter = Backbone.Model.extend(
    /** @lends VectorFilter.prototype */ {
      /**
       * The name of this type of model
       * @type {string}
       */
      type: "VectorFilter",

      /**
       * A VectorFilterConfig specifies conditions under which specific features of a
       * vector layer on a map should be visible. The filter defines rules used to show
       * features conditionally based on properties of the feature. For example, it
       * could specify hiding all vectors for an asset that have an area greater than
       * 10km2. This configuration is passed to the {@link VectorFilter} model.
       * @typedef {Object} VectorFilterConfig
       * @name MapConfig#VectorFilterConfig
       * @property {('categorical'|'numeric')} filterType If categorical, then a feature
       * will be visible when its property value exactly matches one of those listed in
       * the values attribute. If numeric, then a feature will be visible when its
       * property value is between the min and max.
       * @property {string} property The property (attribute) of the {@link MapAsset}
       * feature to filter on.
       * @property {(string[]|number[])} values Only used for categorical filters. If
       * the property matches one of the values listed, the feature will be displayed.
       * If the filter type is categorical and no values are set, then features will not
       * be filtered on this property.
       * @property {number} max Only used for numeric filters. The property's value must
       * be less than the value set here for the feature to be visible. If the filter
       * type is numeric, and max is set, then the max is infinite.
       * @property {number} min Only used for numeric filters. The property's value must
       * be greater than the value set here for the feature to be visible. If the filter
       * type is numeric, and min is set, then the min is minus infinity.
       *
       * @example
       * // Only show vectors with an 'area' property set to less than 10
       * {
       *   filterType: 'numeric'
       *   property: 'area'
       *   max: 10
       * }
       *
       * @example
       * // Show only features that have the 'boreal' or 'tropical' property set on their 'forestType' attribute
       * {
       *   filterType: 'categorical'
       *   property: 'forestType'
       *   values: ['boreal', 'tropical']
       * }
       */

      /**
       * Default attributes for VectorFilter models
       * @name VectorFilter#defaults
       * @type {Object}
       * @property {('categorical'|'numeric')} [filterType='categorical'] If
       * categorical, then a feature will be visible when its property value exactly
       * matches one of those listed in the values attribute. If numerical, then a
       * feature will be visible when its property value is between the min and max.
       * @property {string} property The property (attribute) of the feature to filter
       * on.
       * @property {(string[]|number[])} values Only used for categorical filters. If
       * the property matches one of the values listed, the feature will be displayed.
       * If the filter type is categorical and no values are set, then features will not
       * be filtered on this property.
       * @property {number} max Only used for numeric filters. The property's value must
       * be less than the value set here for the feature to be visible. If the filter
       * type is numeric, and max is set, then the max is infinite.
       * @property {number} min Only used for numeric filters. The property's value must
       * be greater than the value set here for the feature to be visible. If the filter
       * type is numeric, and min is set, then the min is minus infinity.
       *
       */
      defaults: function () {
        return {
          filterType: "categorical",
          property: null,
          values: [],
          max: null,
          min: null,
        };
      },

      /**
       * This function checks if a feature is visible based on the filter's rules.
       * @param {Object} properties The properties of the feature to be filtered. (See
       * the 'properties' attribute of {@link Feature#defaults}.)
       * @returns {boolean} Returns true if the feature properties pass this filter
       */
      featureIsVisible: function (properties) {
        try {
          if (!properties) {
            properties = {};
          }
          var visible = true;
          if (this.get("filterType") === "categorical") {
            var values = this.get("values");
            if (values.length > 0) {
              visible = _.contains(values, properties[this.get("property")]);
            }
          } else if (this.get("filterType") === "numeric") {
            var max = this.get("max");
            var min = this.get("min");
            if (max !== null) {
              visible = properties[this.get("property")] < max;
            }
            if (min !== null) {
              visible = properties[this.get("property")] > min && visible;
            }
          }
          return visible;
        } catch (error) {
          console.log(
            "There was an error checking feature visibility in a VectorFilter" +
              ". Error details: " +
              error,
          );
        }
      },

      // /**
      //  * Executed when a new VectorFilter model is created.
      //  * @param {Object} [attributes] The initial values of the attributes, which will
      //  * be set on the model.
      //  * @param {Object} [options] Options for the initialize function.
      //  */
      // initialize: function (attributes, options) {
      //   try {

      //   }
      //   catch (error) {
      //     console.log(
      //       'There was an error initializing a VectorFilter model' +
      //       '. Error details: ' + error
      //     );
      //   }
      // },

      // /**
      //  * Parses the given input into a JSON object to be set on the model.
      //  *
      //  * @param {TODO} input - The raw response object
      //  * @return {TODO} - The JSON object of all the VectorFilter attributes
      //  */
      // parse: function (input) {

      //   try {

      //     var modelJSON = {};

      //     return modelJSON

      //   }
      //   catch (error) {
      //     console.log(
      //       'There was an error parsing a VectorFilter model' +
      //       '. Error details: ' + error
      //     );
      //   }

      // },

      // /**
      //  * Overrides the default Backbone.Model.validate.function() to check if this if
      //  * the values set on this model are valid.
      //  *
      //  * @param {Object} [attrs] - A literal object of model attributes to validate.
      //  * @param {Object} [options] - A literal object of options for this validation
      //  * process
      //  *
      //  * @return {Object} - Returns a literal object with the invalid attributes and
      //  * their corresponding error message, if there are any. If there are no errors,
      //  * returns nothing.
      //  */
      // validate: function (attrs, options) {
      //   try {

      //   }
      //   catch (error) {
      //     console.log(
      //       'There was an error validating a VectorFilter model' +
      //       '. Error details: ' + error
      //     );
      //   }
      // },

      // /**
      //  * Creates a string using the values set on this model's attributes.
      //  * @return {string} The VectorFilter string
      //  */
      // serialize: function () {
      //   try {
      //     var serializedVectorFilter = '';

      //     return serializedVectorFilter;
      //   }
      //   catch (error) {
      //     console.log(
      //       'There was an error serializing a VectorFilter model' +
      //       '. Error details: ' + error
      //     );
      //   }
      // },
    },
  );

  return VectorFilter;
});