Source: Locator.js

/**
 * @module nyc/Locator
 */

import EventHandling from 'nyc/EventHandling'

import nyc from 'nyc'

const proj4 = nyc.proj4

/**
 * @desc An abstract class for geocoding and geolocating
 * @public
 * @abstract
 * @class
 * @extends {module:nyc/EventHandling~EventHandling}
 * @fires module:nyc/Locator~Locator#geocoded
 * @fires module:nyc/Locator~Locator#geolocated
 * @fires module:nyc/Locator~Locator#ambiguous
 * @fires module:nyc/Locator~Locator#error
 */
class Locator extends EventHandling {
  /**
   * @desc Creates an instance of Locator
   * @access protected
   * @param {module:nyc/Locator~Locator.Options} options Construction options
   */
  constructor(options) {
    super()
    /**
     * @desc The geocder
     * @public
     * @member {module:nyc/Geocoder~Geocoder}
     */
    this.geocoder = options.geocoder
    /**
     * @desc The epsg code
     * @public
     * @member {string}
     */
    this.projection = options.projection || 'EPSG:3857'
    this.hookupEvents()
  }
  /**
   * @desc Get a distance for an accuracy enumerator based on the projections
   * @public
   * @method
   * @return {number} The meters per map unit
   */
  metersPerUnit() {
    return proj4.defs[this.projection].to_meter
  }
  /**
   * @desc Get a distance for an accuracy enumerator based on the Locator projection
   * @access protected
   * @method
   * @param {module:nyc/Locator~Locator.Accuracy} accuracy Locator accuracy
   * @return {number} The accurcy in map units
   */
  accuracyDistance(accuracy) {
    if (this.projection === 'EPSG:3857') {
      return accuracy
    }
    return accuracy / this.metersPerUnit()
  }
  /**
   * @desc Geocode an input string representing a location
   * @public
   * @abstract
   * @method
   * @param {string} input The value to geocode
   */
  search(input) {
    this.geocoder.search(input)
  }
  /**
   * @desc Locate once using device geolocation
    * @public
    * @abstract
    * @method
    */
  locate() {
    throw 'Not implemented'
  }
  /**
   * @desc Track using device geolocation
   * @public
   * @abstract
   * @method
   * @param {boolean} track Track or not
   */
  track() {
    throw 'Not implemented'
  }
  /**
   * @private
   * @method
   * @param {Object} event The event object
   */
  proxyEvent(event) {
    this.trigger(event.type, event)
  }
  /**
   * @private
   * @method
   */
  hookupEvents() {
    this.geocoder.on('geocoded', this.proxyEvent, this)
    this.geocoder.on('ambiguous', this.proxyEvent, this)
    this.geocoder.on('error', this.proxyEvent, this)
  }
}

/**
 * @desc Constructor options for {@link module:nyc/Locator~Locator}
 * @public
 * @typedef {Object}
 * @property {module:nyc/Geocoder~Geocoder} geocoder A geocoder
 * @property {string} [projection=EPSG:3857] The EPSG code of the projection for output geometries (i.e. EPSG:2263)
 */
Locator.Options

/**
 * @desc Enumeration for approximate Geocoder accuracy in meters
 * @public
 * @enum {number}
 */
Locator.Accuracy = {
  /**
   * @desc High accuracy
   */
  HIGH: 0,
  /**
   * @desc Medium accuracy
   */
  MEDIUM: 50,
  /**
   * @desc Low accuracy
   */
  LOW: 500,
  /**
   * @desc ZIP Code accuracy
   */
  ZIP_CODE: 1000
}

/**
 * @desc Object type to hold data about a successful result of a geocoder search or device geolocation
 * @public
 * @typedef {Object}
 * @property {string} name The formatted name of the geocoded location
 * @property {string} type The event type
 * @property {(Array<number>|undefined)} coordinate The geocoded location coordinate
 * @property {number} accuracy The accuracy of the geocoded location in meters or units of a specified projection
 * @property {string} type They type of result (geocoded or geolocated)
 * @property {boolean=} zip Is this the geocoded location a ZIP Code center point
 * @property {Object=} geometry A geoJSON representation of the geocoded location coordinates
 * @property {Object=} data Additional properties provided by the geocoder
 */
Locator.Result

/**
 * @desc Object type to hold data about possible locations resulting from a search request
 * @public
 * @typedef {Object}
 * @property {string} input The input string on which the geocoding attempt was made
 * @property {string} type The event type
 * @property {Array<module:nyc/Locator~Locator.Result>} possible An array of possible results to the request
 */
Locator.Ambiguous

/**
 * @desc The result of a search request
 * @event module:nyc/Locator~Locator#geocoded
 * @type {module:nyc/Locator~Locator.Location}
 */

/**
 * @desc The result of a locate request
 * @event module:nyc/Locator~Locator#geolocated
 * @type {module:nyc/Locator~Locator.Location}
 */

/**
 * @desc The result of an inconclusive search request
 * @event module:nyc/Locator~Locator#ambiguous
 * @type {module:nyc/Locator~Locator.Ambiguous}
 */

/**
 * @desc The error object from a locate request error
 * @event module:nyc/Locator~Locator#error
 * @type {Object}
 */

export default Locator