Fork me on GitHub
Show:

File: ../src/maps/markercollections/markercollection.js

define([
  'aeris/util',
  'aeris/maps/extensions/mapobjectcollection',
  'aeris/togglecollectionbehavior',
  'aeris/maps/extensions/strategyobject',
  'aeris/maps/markers/marker',
  'aeris/maps/markercollections/config/clusterstyles',
  'aeris/maps/strategy/markers/markercluster'
], function(_, MapObjectCollection, ToggleCollectionBehavior, StrategyObject, Marker, clusterStyles, MarkerClusterStrategy) {
  /**
   * A collection of {aeris.maps.markers.Marker} objects.
   *
   * By default, marker collections are rendered using a clustering strategy (eg MarkerClustererPlus for google maps).
   *
   * A MarkerCollection is a type of {aeris.ViewCollection}, which means that it can bind its attributes to a data collection ({aeris.Collection} or {Backbone.Collection}). Any changes, additions, or deletions to the bound data collection will be reflected in the marker collection.
   *
   * See {aeris.maps.markers.Marker} documentation for more information on transforming raw data into marker attributes. Note that `attributeTransforms` can be set directly on the MarkerCollection object using the `modelOptions` option:
   *
   * <code class="example">
   *    var markers = new aeris.maps.markercollections.MarkerCollection(null, {
   *      modelOptions: {
   *        attributeTransforms: {
   *          // ...
   *        }
   *      }
   *    });
   * </code>
   *
   * @class aeris.maps.markercollections.MarkerCollection
   * @extends aeris.maps.extensions.MapObjectCollection
   * @publicApi
   *
   * @uses aeris.maps.extensions.StrategyObject
   * @uses aeris.ToggleCollectionBehavior
   *
   * @constructor
   *
   * @param {Array.<aeris.maps.markers.Marker>=} opt_markers Markers to add to the collection.
   *
   * @param {Object=} opt_options
   * @param {Function=} opt_options.model Constructor for an {aeris.maps.markers.Marker} object.
   *                                  to use as a model for the collection.
   * @param {function():aeris.maps.AbstractStrategy=} opt_options.clusterStrategy Strategy for rendering marker clusters.
   * @param {aeris.maps.markercollections.options.ClusterStyles=} opt_options.clusterStyles
   * @param {Object=} opt_options.clusterOptions Options to pass onto the marker clusterer view.
   * @param {Boolean=} opt_options.cluster Whether to cluster markers. Default is true.
   * @param {string|aeris.maps.AbstractStrategy=} opt_options.strategy
  */
  var MarkerCollection = function(opt_markers, opt_options) {
    var options = _.defaults(opt_options || {}, {
      model: Marker,
      clusterStrategy: MarkerClusterStrategy,
      clusterStyles: {},
      clusterOptions: {},
      cluster: true,
      strategy: null
    });

    // Set default styles
    options.clusterStyles = _.defaults(options.clusterStyles, {
      defaultStyles: clusterStyles.defaultStyles
    });

    /**
     * @property clusterStyles_
     * @private
     * @type {aeris.maps.markercollections.options.ClusterStyles}
    */
    this.clusterStyles_ = options.clusterStyles;

    /**
     * @property clusterStrategy_
     * @private
     * @type {function():aeris.maps.AbstractStrategy}
    */
    this.clusterStrategy_ = options.clusterStrategy;

    /**
     * @property clusterOptions_
     * @private
     * @type {Object}
    */
    this.clusterOptions_ = options.clusterOptions;


    /**
     * Whether a clustering strategy
     * is currently active.
     *
     * @property isClustering_
     * @private
     * @type {Boolean}
    */
    this.isClustering_ = false;

    MapObjectCollection.call(this, opt_markers, options);
    ToggleCollectionBehavior.call(this);
    StrategyObject.call(this, {
      strategy: options.strategy
    });

    // Start up clustering
    if (options.cluster) {
      this.startClustering();
    }
  };
  _.inherits(MarkerCollection, MapObjectCollection);
  _.extend(MarkerCollection.prototype, StrategyObject.prototype);
  _.extend(MarkerCollection.prototype, ToggleCollectionBehavior.prototype);

  /**
   * Returns a copy of the
   * cluster styles for the specified
   * cluster group.
   *
   * @param {string=} opt_group Defaults to 'defaultStyles.'.
   * @return {Object} Cluster styles object.
   * @method getClusterStyle
   */
  MarkerCollection.prototype.getClusterStyle = function(opt_group) {
    var styles = this.clusterStyles_[opt_group] || this.clusterStyles_['defaultStyles'];

    return styles.slice(0);
  };


  /**
   * @method getClusterOptions
   * @return {Object}
   */
  MarkerCollection.prototype.getClusterOptions = function() {
    return _.clone(this.clusterOptions_);
  };


  /**
   * Starts up the strategy defined
   * by this.clusterStrategy_.
   * @method startClustering
   */
  MarkerCollection.prototype.startClustering = function() {
    this.setStrategy(this.clusterStrategy_);

    // Sometimes re-starting clustering
    // causes some non-clustered markers not to show.
    // This fixes that.
    var map = this.getMap();
    this.setMap(null);
    this.setMap(map);

    this.isClustering_ = true;
  };


  /**
   * Destroys the clustering strategy
   * started up by #startClustering.
   * @method stopClustering
   */
  MarkerCollection.prototype.stopClustering = function() {
    if (this.isClustering_) {
      this.removeStrategy();
    }
  };


  return _.expose(MarkerCollection, 'aeris.maps.markercollections.MarkerCollection');
});
/**
 * Style setting for marker clusters,
 * organized by marker type.
 *
 * Example:
 *  {
 *    snow: [
 *      {url: 'snow1.png', height: 10, width: 10},
 *      {url: 'snow2.png', height: 20, width: 20},
 *    ],
 *    rain: [
 *      {url: 'rain1.png', height: 10, width: 10},
 *      {url: 'rain2.png', height: 20, width: 20},
 *    ]
 *
 *    // Default styles for markers which do not implement
 *    // a getType method.
 *    defaultStyles: [ ... ]
 *
 *  }
 *
 * In order for markers to be clustered by type, each marker must
 * implement a `getType` method. Otherwise, markers will be styled using the
 * `defaultStyles` styles.
 *
 * See http://google-maps-utility-library-v3.googlecode.com/svn/trunk/markerclustererplus/docs/reference.html
 *  "class ClusterIconStyle" for acceptable style options.
 *
 * @class aeris.maps.markercollections.options.ClusterStyles
 * @static
*/