diff --git a/src/fetchQueue.js b/src/fetchQueue.js index ed26a5aeb2..0dad6f0435 100644 --- a/src/fetchQueue.js +++ b/src/fetchQueue.js @@ -12,12 +12,13 @@ module.exports = (function () { * tile images, thie number of concurrent requests should be 6 * (number of * subdomains serving tiles). * - * @class geo.fetchQueue + * @class + * @alias geo.fetchQueue * - * @param {Object?} [options] A configuration object for the queue - * @param {Number} [options.size=6] The maximum number of concurrent deferred + * @param {object} [options] A configuration object for the queue. + * @param {number} [options.size=6] The maximum number of concurrent deferred * objects. - * @param {Number} [options.track=600] The number of objects that are tracked + * @param {number} [options.track=600] The number of objects that are tracked * that trigger checking if any of them have been abandoned. The fetch * queue can grow to the greater of this size and the number of items that * are still needed. Setting this to a low number will increase @@ -55,6 +56,7 @@ module.exports = (function () { /** * Get the current queue size. + * @returns {number} The queue size. */ Object.defineProperty(this, 'length', { get: function () { return this._queue.length; } @@ -62,6 +64,7 @@ module.exports = (function () { /** * Get the current number of processing items. + * @returns {number} The number of processing items. */ Object.defineProperty(this, 'processing', { get: function () { return this._processing; } @@ -69,6 +72,8 @@ module.exports = (function () { /** * Remove all items from the queue. + * + * @returns {this} */ this.clear = function () { this._queue = []; @@ -78,12 +83,15 @@ module.exports = (function () { /** * Add a Deferred object to the queue. - * @param {Deferred} defer Deferred object to add to the queue. - * @param {function} callback a function to call when the item's turn is + * + * @param {jQuery.Deferred} defer Deferred object to add to the queue. + * @param {function} callback A function to call when the item's turn is * granted. - * @param {boolean} atEnd if false, add the item to the front of the queue + * @param {boolean} atEnd If falsy, add the item to the front of the queue * if batching is turned off or at the end of the current batch if it is - * turned on. If true, always add the item to the end of the queue. + * turned on. If truthy, always add the item to the end of the queue. + * @returns {jQuery.Deferred} The deferred object that was passed to the + * function. */ this.add = function (defer, callback, atEnd) { if (defer.__fetchQueue) { @@ -114,10 +122,11 @@ module.exports = (function () { /** * Add an item to the queue. If batches are being used, add it at after * other items in the same batch. - * @param {Deferred} defer Deferred object to add to the queue. - * @param {boolean} atEnd if false, add the item to the front of the queue + * + * @param {jQuery.Deferred} defer Deferred object to add to the queue. + * @param {boolean} atEnd If falsy, add the item to the front of the queue * if batching is turned off or at the end of the current batch if it is - * turned on. If true, always add the item to the end of the queue. + * turned on. If truthy, always add the item to the end of the queue. */ this._addToQueue = function (defer, atEnd) { defer.__fetchQueue._batch = this._batch; @@ -137,7 +146,8 @@ module.exports = (function () { /** * Get the position of a deferred object in the queue. - * @param {Deferred} defer Deferred object to get the position of. + * + * @param {jQuery.Deferred} defer Deferred object to get the position of. * @returns {number} -1 if not in the queue, or the position in the queue. */ this.get = function (defer) { @@ -146,8 +156,9 @@ module.exports = (function () { /** * Remove a Deferred object from the queue. - * @param {Deferred} defer Deferred object to add to the queue. - * @returns {bool} true if the object was removed + * + * @param {jQuery.Deferred} defer Deferred object to add to the queue. + * @returns {boolean} `true` if the object was removed. */ this.remove = function (defer) { var pos = $.inArray(defer, this._queue); @@ -160,10 +171,11 @@ module.exports = (function () { /** * Start a new batch or clear using batches. - * @param {boolean} start true to start a new batch, false to turn off - * using batches. Undefined to return the current - * state of batches. - * @return {Number|boolean|Object} the current batch state or this object. + * + * @param {boolean} start Truthy too start a new batch, falsy to turn off + * using batches. `undefined` to return the current state of batches. + * @returns {number|boolean|this} `false` if batches are turned off, the + * batch number if turned on, or `this` if setting the batch. */ this.batch = function (start) { if (start === undefined) { @@ -179,8 +191,8 @@ module.exports = (function () { }; /** - * Check if any items are queued and if there if there are not too many - * deferred objects being processed. If so, process more items. + * Check if any items are queued and if the processing allotment is not + * full. If so, process more items. */ this.next_item = function () { if (m_this._innextitem) { diff --git a/src/imageTile.js b/src/imageTile.js index 5b3815a987..d141a27de6 100644 --- a/src/imageTile.js +++ b/src/imageTile.js @@ -14,22 +14,24 @@ module.exports = (function () { * subclasses may define additional rendering steps to produce the images * before passing them off to the handlers. * - * @class geo.imageTile - * @param {object} spec The tile specification object + * @class + * @alias geo.imageTile + * @extends geo.tile + * @param {object} spec The tile specification. * - * @param {object} spec.index The global position of the tile - * @param {number} spec.index.x The x-coordinate (usually the column number) - * @param {number} spec.index.y The y-coordinate (usually the row number) - * @param {number} spec.index.level The zoom level + * @param {object} spec.index The global position of the tile. + * @param {number} spec.index.x The x-coordinate (usually the column number). + * @param {number} spec.index.y The y-coordinate (usually the row number). + * @param {number} spec.index.level The zoom level. * - * @param {object?} spec.size The size of each tile - * @param {number} [spec.size.x=256] Width in pixels - * @param {number} [spec.size.y=256] Height in pixels + * @param {object?} spec.size The size of each tile. + * @param {number} [spec.size.x=256] Width in pixels. + * @param {number} [spec.size.y=256] Height in pixels. * - * @param {string} spec.url A url to the image - * @param {string} [spec.crossDomain='anonymous'] Image CORS attribute + * @param {string} spec.url A url to the image. + * @param {string} [spec.crossDomain='anonymous'] Image CORS attribute. * - * @param {object} spec.overlap The size of overlap with neighboring tiles + * @param {object} spec.overlap The size of overlap with neighboring tiles. * @param {number} [spec.overlap.x=0] * @param {number} [spec.overlap.y=0] */ @@ -53,6 +55,7 @@ module.exports = (function () { * tile. Note, this method does not gaurantee that the * image data is available. Use the promise interface * to add asyncronous handlers. + * * @returns {Image} */ Object.defineProperty(this, 'image', { @@ -62,7 +65,7 @@ module.exports = (function () { /** * Initiate the image request. * - * @returns {this} The current tile class instance. + * @returns {this} */ this.fetch = function () { var defer; @@ -87,14 +90,16 @@ module.exports = (function () { }; /** - * Set the opacity of the tile to 0 and gradually fade in - * over the given number of milliseconds. This will also - * resolve the embedded promise interface. - * @param {number} duration the duration of the animation in ms - * @returns {this} chainable + * Set the opacity of the tile to 0 and gradually fade in over the given + * number of milliseconds. This will also resolve the embedded promise + * interface. + * + * @param {number} duration The duration of the animation in ms. + * @returns {this} */ this.fadeIn = function (duration) { - var promise = this.fetch(), defer = $.Deferred(); + var promise = this.fetch(), + defer = $.Deferred(); $(this._image).css('display', 'none'); promise.done(function () { $(this._image).fadeIn(duration, function () { diff --git a/src/layer.js b/src/layer.js index 723e5532e9..18d0bd8506 100644 --- a/src/layer.js +++ b/src/layer.js @@ -12,9 +12,35 @@ var rendererForAnnotations = require('./registry').rendererForAnnotations; * @alias geo.layer * @extends geo.sceneObject * @param {object} [arg] Options for the new layer. - * @param {string} arg.attribution An attribution string to display - * @param {number} arg.zIndex The z-index to assign to the layer (defaults - * to the index of the layer inside the map) + * @param {number} [arg.id] The id of the layer. Defaults to a increasing + * sequence. + * @param {geo.map} [arg.map=null] Parent map of the layer. + * @param {string|geo.renderer} [arg.renderer] Renderer to associate with the + * layer. If not specified, either `arg.annotations` or `arg.features` can + * be used to determine the renderer. + * @param {string[]|object} [arg.annotations] A list of annotations that will + * be used on this layer, used to select a renderer. Instead of a list, if + * this is an object, the keys are the annotation names, and the values are + * each a list of modes that will be used with that annotation. See + * `featuresForAnnotations` more details. This is ignored if `arg.renderer` + * is specified. + * @param {string[]} [arg.features] A list of features that will be used on + * this layer, used to select a renderer. Features are the basic feature + * names (e.g., `'quad'`), or the feature name followed by a required + * capability (e.g., `'quad.image'`). This is ignored if `arg.renderer` or + * `arg.annotations` is specified. + * @param {boolean} [arg.active=true] Truthy if the layer has the `active` css + * class and may receive native mouse events. + * @param {string} [arg.attribution] An attribution string to display. + * @param {number} [arg.opacity=1] The layer opacity on a scale of [0-1]. + * @param {string} [arg.name=''] A name for the layer for user convenience. + * @param {boolean} [arg.selectionAPI=true] Truthy if the layer can generate + * selection and other interaction events. + * @param {boolean} [arg.sticky=true] Truthy if the layer should navigate with + * the map. + * @param {boolean} [arg.visible=true] Truthy if the layer is visible. + * @param {number} [arg.zIndex] The z-index to assign to the layer (defaults + * to the index of the layer inside the map). * @returns {geo.layer} */ var layer = function (arg) { @@ -39,7 +65,7 @@ var layer = function (arg) { var m_this = this, s_exit = this._exit, m_id = arg.id === undefined ? layer.newLayerId() : arg.id, - m_name = '', + m_name = arg.name === undefined ? '' : arg.name, m_map = arg.map === undefined ? null : arg.map, m_node = null, m_canvas = null, diff --git a/src/osmLayer.js b/src/osmLayer.js index 0cb5cbc1f8..9a73326a1e 100644 --- a/src/osmLayer.js +++ b/src/osmLayer.js @@ -8,14 +8,17 @@ module.exports = (function () { var quadFeature = require('./quadFeature'); /** - * Create a new instance of osmLayer. + * Create a new instance of osmLayer. This is a `geo.tileLayer` with an + * OSM url and attribution defaults and with the tiles centered on the + * origin. * - * @class geo.osmLayer - * @extends geo.featureLayer + * @class + * @alias geo.osmLayer + * @extends geo.tileLayer * - * @param {object} arg - arg can contain following keys: baseUrl, - * imageFormat (such as png or jpeg), and displayLast - * (to decide whether or not render tiles from last zoom level). + * @param {object} arg + * @param {number} [arg.mapOpacity] If specified, and `arg.opacity` is not + * specified, use this as the layer opacity. */ var osmLayer = function (arg) { @@ -34,13 +37,14 @@ module.exports = (function () { /** * Returns an instantiated imageTile object with the given indices. This - * method always returns a new tile object. Use `_getTileCached` - * to use the caching layer. - * @param {object} index The tile index + * method always returns a new tile object. Use `_getTileCached` to use + * the caching layer. + * + * @param {object} index The tile index. * @param {number} index.x * @param {number} index.y * @param {number} index.level - * @param {object} source The tile index used for constructing the url + * @param {object} source The tile index used for constructing the url. * @param {number} source.x * @param {number} source.y * @param {number} source.level @@ -66,17 +70,10 @@ module.exports = (function () { * This object contains the default options used to initialize the osmLayer. */ osmLayer.defaults = $.extend({}, tileLayer.defaults, { - minLevel: 0, - maxLevel: 18, - tileOverlap: 0, - tileWidth: 256, - tileHeight: 256, tileOffset : function (level) { var s = Math.pow(2, level - 1) * 256; return {x: s, y: s}; }, - wrapX: true, - wrapY: false, url: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', attribution: 'Tile data © ' + 'OpenStreetMap contributors' diff --git a/src/registry.js b/src/registry.js index 0f664c6b3d..c9b934e17b 100644 --- a/src/registry.js +++ b/src/registry.js @@ -109,7 +109,7 @@ util.checkRenderer = function (name, noFallback) { * features. If not, display a warning. This picks the first renderer that * supports all of the listed features. * - * @param {array|undefined} featureList A list of features that will be used + * @param {string[]|undefined} featureList A list of features that will be used * with this renderer. Features are the basic feature names (e.g., * `'quad'`), or the feature name followed by a required capability (e.g., * `'quad.image'`). If more than one feature or more than one capability @@ -273,7 +273,7 @@ util.adjustLayerForRenderer = function (name, layer) { * @param {string} name Name of the layer to register. If the name already * exists, the class creation function is replaced. * @param {function} func Class creation function. - * @param {array} [defaultFeatures] An optional list of feature capabailities + * @param {string[]} [defaultFeatures] An optional list of feature capabilities * that are required to use this layer. */ util.registerLayer = function (name, func, defaultFeatures) { @@ -399,7 +399,7 @@ util.createAnnotation = function (name, options) { /** * Get a list of registered annotation types. * - * @returns {array} A list of registered annotations. + * @returns {string[]} A list of registered annotations. */ util.listAnnotations = function () { return Object.keys(annotations); @@ -408,14 +408,14 @@ util.listAnnotations = function () { /** * Get a list of required features for a set of annotations. * - * @param {array|object|undefined} annotationList A list of annotations that + * @param {string[]|object|undefined} annotationList A list of annotations that * will be used. Instead of a list, if this is an object, the keys are the * annotation names, and the values are each a list of modes that will be * used with that annotation. For example, ['polygon', 'rectangle'] lists * features required to show those annotations in any mode, whereas * {polygon: [annotationState.done], rectangle: [annotationState.done]} only * lists features that are needed to show the completed annotations. - * @returns {array} a list of features needed for the specified annotations. + * @returns {string[]} a list of features needed for the specified annotations. * There may be duplicates in the list. */ util.featuresForAnnotations = function (annotationList) { @@ -447,7 +447,7 @@ util.featuresForAnnotations = function (annotationList) { * annotations. If not, display a warning. This generates a list of required * features, then picks the first renderer that supports all of these features. * - * @param {array|object|undefined} annotationList A list of annotations that + * @param {string[]|object|undefined} annotationList A list of annotations that * will be used with this renderer. Instead of a list, if this is an object, * the keys are the annotation names, and the values are each a list of modes * that will be used with that annotation. See featuresForAnnotations for diff --git a/src/tile.js b/src/tile.js index 815b6eddbc..efde2cfd85 100644 --- a/src/tile.js +++ b/src/tile.js @@ -9,25 +9,27 @@ module.exports = (function () { * is independent of the actual content of the tile, but assumes that * the content is loaded asynchronously via a url. The tile object * has a promise-like interface. For example, - * + * ``` * tile.then(function (data) {...}).catch(function (data) {...}); + * ```. * - * @class geo.tile - * @param {Object} spec The tile specification object + * @class + * @alias geo.tile + * @param {object} spec The tile specification. * - * @param {Object} spec.index The global position of the tile - * @param {Number} spec.index.x The x-coordinate (usually the column number) - * @param {Number} spec.index.y The y-coordinate (usually the row number) + * @param {object} spec.index The global position of the tile. + * @param {number} spec.index.x The x-coordinate (usually the column number). + * @param {number} spec.index.y The y-coordinate (usually the row number). * - * @param {Object} spec.size The size of each tile - * @param {Number} spec.size.x Width (usually in pixels) - * @param {Number} spec.size.y Height (usually in pixels) + * @param {object} spec.size The size of each tile. + * @param {number} spec.size.x Width (usually in pixels). + * @param {number} spec.size.y Height (usually in pixels). * - * @param {Object|String} spec.url A url or jQuery ajax config object + * @param {object|string} spec.url A url or jQuery ajax config object. * - * @param {Object?} spec.overlap The size of overlap with neighboring tiles - * @param {Number} [spec.overlap.x=0] - * @param {Number} [spec.overlap.y=0] + * @param {object?} spec.overlap The size of overlap with neighboring tiles. + * @param {number} [spec.overlap.x=0] + * @param {number} [spec.overlap.y=0] */ var tile = function (spec) { if (!(this instanceof tile)) { @@ -44,6 +46,8 @@ module.exports = (function () { /** * Return the index coordinates. + * + * @returns {object} The index with `x` and `y` properties. */ Object.defineProperty(this, 'index', { get: @@ -51,25 +55,30 @@ module.exports = (function () { }); /** - * Return the tile sizes. + * Return the tile size. + * + * @returns {object} The size with `x` and `y` properties. */ Object.defineProperty(this, 'size', { get: function () { return this._size; } }); /** - * Return the tile overlap sizes. + * Return the tile overlap. + * + * @returns {object} The overlap with `x` and `y` properties. */ Object.defineProperty(this, 'overlap', { get: function () { return this._overlap; } }); /** - * Initiate the ajax request and add a promise interface - * to the tile object. This method exists to allow - * derived classes the ability to override how the tile - * is obtained. For example, imageTile uses an Image - * element rather than $.get. + * Initiate the ajax request and add a promise interface to the tile + * object. This method exists to allow derived classes the ability to + * override how the tile is obtained. For example, imageTile uses an + * Image element rather than $.get. + * + * @returns {this} */ this.fetch = function () { if (!this._fetched) { @@ -93,10 +102,9 @@ module.exports = (function () { * Add a method to be called with the data when the ajax request is * successfully resolved. * - * @param {function?} onSuccess The success handler - * @param {function?} onFailure The failure handler - * @returns {this} Supports chained calling - * + * @param {function?} onSuccess The success handler. + * @param {function?} onFailure The failure handler. + * @returns {this} */ this.then = function (onSuccess, onFailure) { // both fetch and _queueAdd can replace the current then method @@ -118,9 +126,8 @@ module.exports = (function () { /** * Add a method to be called with the data when the ajax fails. * - * @param {function} method The rejection handler - * @returns {this} Supports chained calling - * + * @param {function} method The rejection handler. + * @returns {this} */ this.catch = function (method) { this.then(undefined, method); @@ -128,9 +135,10 @@ module.exports = (function () { }; /** - * Return a unique string representation of the given tile useable - * as a hash key. Possibly extend later to include url information - * to make caches aware of the tile source. + * Return a unique string representation of the given tile useable as a + * hash key. Possibly extend later to include url information to make + * caches aware of the tile source. + * * @returns {string} */ this.toString = function () { @@ -138,11 +146,11 @@ module.exports = (function () { }; /** - * Return the bounds of the tile given an index offset and - * a translation. + * Return the bounds of the tile given an index offset and a translation. * - * @param {object} index The tile index containing (0, 0) - * @param {object} shift The coordinates of (0, 0) inside the tile + * @param {object} index The tile index containing (0, 0). + * @param {object} shift The coordinates of (0, 0) inside the tile. + * @returns {object} An object with `left`, `top`, `right`, `bottom`. */ this.bounds = function (index, shift) { var left, right, bottom, top; @@ -199,22 +207,11 @@ module.exports = (function () { }); /** - * Returns the global image size at this level. - * @returns {number} - */ - Object.defineProperty(this, 'levelSize', { - value: { - width: Math.pow(2, this.index.level || 0) * this.size.x, - height: Math.pow(2, this.index.level || 0) * this.size.y - } - }); - - /** - * Set the opacity of the tile to 0 and gradually fade in - * over the given number of milliseconds. This will also - * resolve the embedded promise interface. - * @param {number} duration the duration of the animation in ms - * @returns {this} chainable + * Set the opacity of the tile to 0 and gradually fade in over the given + * number of milliseconds. This is just a delay. + * + * @param {number} duration The duration of the animation in ms. + * @returns {this} */ this.fadeIn = function (duration) { $.noop(duration); diff --git a/src/tileCache.js b/src/tileCache.js index ff93ebcd6a..6217980871 100644 --- a/src/tileCache.js +++ b/src/tileCache.js @@ -7,10 +7,11 @@ module.exports = (function () { * array keeps track of last access times for each tile to purge old tiles * once the maximum cache size is reached. * - * @class geo.tileCache + * @class + * @alias geo.tileCache * - * @param {object?} [options] A configuratoin object for the cache - * @param {number} [options.size=64] The maximum number of tiles to store + * @param {object} [options] A configuration object for the cache. + * @param {number} [options.size=64] The maximum number of tiles to store. */ var tileCache = function (options) { if (!(this instanceof tileCache)) { @@ -21,6 +22,8 @@ module.exports = (function () { /** * Get/set the maximum cache size. + * @param {number} The new maximum cache size. + * @returns {number} The maximum cache size. */ Object.defineProperty(this, 'size', { get: function () { return this._size; }, @@ -34,6 +37,7 @@ module.exports = (function () { /** * Get the current cache size. + * @returns {number} */ Object.defineProperty(this, 'length', { get: function () { return this._atime.length; } @@ -41,8 +45,9 @@ module.exports = (function () { /** * Get the position of the tile in the access queue. - * @param {string} hash The tile's hash value - * @returns {number} The position in the queue or -1 + * + * @param {string} hash The tile's hash value. + * @returns {number} The position in the queue or -1. */ this._access = function (hash) { return this._atime.indexOf(hash); @@ -50,8 +55,9 @@ module.exports = (function () { /** * Remove a tile from the cache. - * @param {string|geo.tile} tile The tile or its hash - * @returns {bool} true if a tile was removed + * + * @param {string|geo.tile} tile The tile or its hash. + * @returns {booliean} `true` if a tile was removed. */ this.remove = function (tile) { var hash = typeof tile === 'string' ? tile : tile.toString(); @@ -71,6 +77,8 @@ module.exports = (function () { /** * Remove all tiles from the cache. + * + * @returns {this} */ this.clear = function () { this._cache = {}; // The hash -> tile mapping @@ -79,13 +87,12 @@ module.exports = (function () { }; /** - * Get a tile from the cache if it exists, otherwise - * return null. This method also moves the tile to the - * front of the access queue. + * Get a tile from the cache if it exists, otherwise return `null`. This + * method also moves the tile to the front of the access queue. * - * @param {string|geo.tile} hash The tile or the tile hash value - * @param {boolean} noMove if true, don't move the tile to the front of the - * access queue. + * @param {string|geo.tile} hash The tile or the tile hash value. + * @param {boolean} [noMove] If truthy, don't move the tile to the front of + * the access queue. * @returns {geo.tile|null} */ this.get = function (hash, noMove) { @@ -103,8 +110,9 @@ module.exports = (function () { /** * Add a tile to the cache. - * @param {geo.tile} tile - * @param {function} removeFunc if specified and tiles must be purged from + * + * @param {geo.tile} tile The tile to add. + * @param {function} removeFunc If specified and tiles must be purged from * the cache, call this function on each tile before purging. * @param {boolean} noPurge if true, don't purge tiles. */ @@ -124,7 +132,8 @@ module.exports = (function () { /** * Purge tiles from the cache if it is full. - * @param {function} removeFunc if specified and tiles must be purged from + * + * @param {function} removeFunc If specified and tiles must be purged from * the cache, call this function on each tile before purging. */ this.purge = function (removeFunc) { diff --git a/src/tileLayer.js b/src/tileLayer.js index 0f6c70c0ba..396329f831 100644 --- a/src/tileLayer.js +++ b/src/tileLayer.js @@ -78,97 +78,79 @@ module.exports = (function () { } /** - * This method defines a tileLayer, which is an abstract class defining a - * layer divided into tiles of arbitrary data. Notably, this class provides - * the core functionality of the osmLayer, but hooks exist to render tiles - * dynamically from vector data, or to display arbitrary grids of images - * in a custom coordinate system. When multiple zoom levels are present - * in a given dataset, this class assumes that the space occupied by - * tile (i, j) at level z is covered by a 2x2 grid of tiles at zoom - * level z + 1: - * + * This method defines a tileLayer, an abstract class defining a layer + * divided into tiles of arbitrary data. Notably, this class provides the + * core functionality of `geo.osmLayer`, but hooks exist to render tiles more + * generically. When multiple zoom levels are present in a given dataset, + * this class assumes that the space occupied by tile `(i, j)` at level `z` + * is covered by a 2x2 grid of tiles at zoom level `z + 1`: + * ``` * (2i, 2j), (2i, 2j + 1) * (2i + 1, 2j), (2i + 1, 2j + 1) - * + * ``` * The higher level tile set should represent a 2x increase in resolution. * - * Although not currently supported, this class is intended to extend to - * 3D grids of tiles as well where 1 tile is covered by a 2x2x2 grid of - * tiles at the next level. The tiles are assumed to be rectangular, - * identically sized, and aligned with x/y axis of the underlying - * coordinate system. The local coordinate system is in pixels relative - * to the current zoom level and changes when the zoom level crosses an - * integer threshold. - * - * The constructor takes a number of optional parameters that customize - * the display of the tiles. The default values of these options are - * stored as the `defaults` attribution on the constructor. Supporting - * alternate tiling protocols often only requires adjusting these - * defaults. - * - * @class geo.tileLayer + * @class + * @alias geo.tileLayer * @extends geo.featureLayer * @param {object?} options - * @param {number} [options.minLevel=0] The minimum zoom level available - * @param {number} [options.maxLevel=18] The maximum zoom level available - * @param {number} [options.tileOverlap=0] - * Number of pixels of overlap between tiles - * @param {number} [options.tileWidth=256] - * The tile width as displayed without overlap - * @param {number} [options.tileHeight=256] - * The tile height as displayed without overlap - * @param {function} [options.tilesAtZoom=null] - * A function that is given a zoom level and returns {x: (num), y: (num)} - * with the number of tiles at that zoom level. + * @param {number} [options.minLevel=0] The minimum zoom level available. + * @param {number} [options.maxLevel=18] The maximum zoom level available. + * @param {object} [options.tileOverlap] Pixel overlap between tiles. + * @param {number} [options.tileOverlap.x] Horizontal overlap. + * @param {number} [options.tileOverlap.y] Vertical overlap. + * @param {number} [options.tileWidth=256] The tile width without overlap. + * @param {number} [options.tileHeight=256] The tile height without overlap. + * @param {function} [options.tilesAtZoom=null] A function that is given a + * zoom level and returns `{x: (num), y: (num)}` with the number of tiles + * at that zoom level. * @param {number} [options.cacheSize=400] The maximum number of tiles to * cache. The default is 200 if keepLower is false. - * @param {boolean} [options.keepLower=true] - * Keep lower zoom level tiles when showing high zoom level tiles. This - * uses more memory but results in smoother transitions. - * @param {boolean} [options.wrapX=true] Wrap in the x-direction - * @param {boolean} [options.wrapY=false] Wrap in the y-direction - * @param {string|function} [options.url=null] - * A function taking the current tile indices and returning a URL or jquery - * ajax config to be passed to the {geo.tile} constructor. - * Example: - * (x, y, z, subdomains) => "http://example.com/z/y/x.png" + * @param {boolean} [options.keepLower=true] When truthy, keep lower zoom + * level tiles when showing high zoom level tiles. This uses more memory + * but results in smoother transitions. + * @param {boolean} [options.wrapX=true] Wrap in the x-direction. + * @param {boolean} [options.wrapY=false] Wrap in the y-direction. + * @param {string|function} [options.url=null] A function taking the current + * tile indices `(x, y, level, subdomains)` and returning a URL or jquery + * ajax config to be passed to the {geo.tile} constructor. Example: + * ``` + * (x, y, z, subdomains) => "http://example.com/z/y/x.png" + * ``` * If this is a string, a template url with {x}, {y}, {z}, and {s} as - * template variables. {s} picks one of the subdomains parameter. - * @param {string|list} [options.subdomain="abc"] Subdomains to use in + * template variables. {s} picks one of the subdomains parameter and may + * contain a comma-separated list of subdomains. + * @param {string|list} [options.subdomain="abc"] Subdomains to use in * template url strings. If a string, this is converted to a list before * being passed to a url function. * @param {string} [options.baseUrl=null] If defined, use the old-style base * url instead of the options.url parameter. This is functionally the same - * as using a url of baseUrl/{z}/{x}/{y}.(options.imageFormat || png). If - * the specified string does not end in a slash, one is added. - * @param {string} [options.imageFormat='png'] - * This is only used if a baseUrl is specified, in which case it determines - * the image name extension used in the url. - * @param {number} [options.animationDuration=0] - * The number of milliseconds for the tile loading animation to occur. **This - * option is currently buggy because old tiles will purge before the animation - * is complete.** - * @param {string} [options.attribution] - * An attribution to display with the layer (accepts HTML) - * @param {function} [options.tileRounding=Math.round] - * This function determines which tiles will be loaded when the map is at - * a non-integer zoom. For example, `Math.floor`, will use tile level 2 - * when the map is at zoom 2.9. - * @param {function} [options.tileOffset] - * This function takes a zoom level argument and returns, in units of - * pixels, the coordinates of the point (0, 0) at the given zoom level - * relative to the bottom left corner of the domain. - * @param {function} [options.tilesMaxBounds=null] - * This function takes a zoom level argument and returns, in units of - * pixels, the top, left, right, and bottom maximum value for which tiles - * should be drawn at the given zoom level relative to the bottom left - * corner of the domain. This can be used to crop tiles at the edges of - * tile layer. Note that if tiles wrap, only complete tiles in the - * wrapping direction(s) are supported, and this max bounds will probably - * not behave properly. - * @param {boolean} [options.topDown=false] True if the gcs is top-down, + * as using a url of `baseUrl/{z}/{x}/{y}.(options.imageFormat || png)`. + * If the specified string does not end in a slash, one is added. + * @param {string} [options.imageFormat='png'] This is only used if a + * `baseUrl` is specified, in which case it determines the image name + * extension used in the url. + * @param {number} [options.animationDuration=0] The number of milliseconds + * for the tile loading animation to occur. Only some renderers support + * this. + * @param {string} [options.attribution] An attribution to display with the + * layer (accepts HTML). + * @param {function} [options.tileRounding=Math.round] This function + * determines which tiles will be loaded when the map is at a non-integer + * zoom. For example, `Math.floor`, will use tile level 2 when the map is + * at zoom 2.9. + * @param {function} [options.tileOffset] This function takes a zoom level + * argument and returns, in units of pixels, the coordinates of the point + * (0, 0) at the given zoom level relative to the bottom left corner of the + * domain. + * @param {function} [options.tilesMaxBounds=null] This function takes a zoom + * level argument and returns an object with `x` and `y` in pixels which is + * used to crop the last row and column of tiles. Note that if tiles wrap, + * only complete tiles in the wrapping direction(s) are supported, and this + * max bounds will probably not behave properly. + * @param {boolean} [options.topDown=false] True if the gcs is top-down, * false if bottom-up (the ingcs does not matter, only the gcs coordinate - * system). When false, this inverts the gcs y-coordinate when calculating + * system). When falsy, this inverts the gcs y-coordinate when calculating * local coordinates. * @returns {geo.tileLayer} */ @@ -258,25 +240,28 @@ module.exports = (function () { /** * Readonly accessor to the tile cache object. + * @returns {geo.tileCache} */ Object.defineProperty(this, 'cache', {get: function () { return this._cache; }}); /** - * Readonly accessor to the active tile mapping. This is an object containing - * all currently drawn tiles (hash(tile) => tile). + * Readonly accessor to the active tile mapping. This is an object + * containing all currently drawn tiles (hash(tile) => tile). + * @returns {object} */ Object.defineProperty(this, 'activeTiles', {get: function () { return $.extend({}, this._activeTiles); // copy on output }}); /** - * The number of tiles at the given zoom level - * The default implementation just returns `Math.pow(2, z)`. + * The number of tiles at the given zoom level. The default implementation + * just returns `Math.pow(2, z)`. * - * @param {number} level A zoom level - * @returns {{x: nx, y: ny}} The number of tiles in each axis + * @param {number} level A zoom level. + * @returns {object} The number of tiles in each axis in the form + * `{x: nx, y: ny}`. */ this.tilesAtZoom = function (level) { if (this._options.tilesAtZoom) { @@ -290,9 +275,9 @@ module.exports = (function () { * The maximum tile bounds at the given zoom level, or null if no special * tile bounds. * - * @param {number} level A zoom level - * @returns {object} {x: width, y: height} The maximum tile bounds in - * pixels for the specified level, or null if none specified. + * @param {number} level A zoom level. + * @returns {object} The maximum tile bounds in pixels for the specified + * level, or null if none specified (`{x: width, y: height}`). */ this.tilesMaxBounds = function (level) { if (this._options.tilesMaxBounds) { @@ -305,8 +290,8 @@ module.exports = (function () { * Get the crop values for a tile based on the tilesMaxBounds function. * Returns undefined if the tile should not be cropped. * - * @param {object} tile: the tile to compute crop values for. - * @returns {object} either undefined or an object with x and y values + * @param {object} tile The tile to compute crop values for. + * @returns {object} Either `undefined` or an object with `x` and `y` values * which is the size in pixels for the tile. */ this.tileCropFromBounds = function (tile) { @@ -328,10 +313,10 @@ module.exports = (function () { }; /** - * Returns true if the given tile index is valid: - * * min level <= level <= max level - * * 0 <= x <= 2^level - 1 - * * 0 <= y <= 2^level - 1 + * Returns `true` if the given tile index is valid: + * - min level <= level <= max level + * - 0 <= x <= 2^level - 1 + * - 0 <= y <= 2^level - 1 * If the layer wraps, the x and y values may be allowed to extend beyond * these values. * @@ -339,7 +324,7 @@ module.exports = (function () { * @param {number} index.x * @param {number} index.y * @param {number} index.level - * @returns {geo.tile} + * @returns {boolean} */ this.isValid = function (index) { if (!(this._options.minLevel <= index.level && @@ -363,9 +348,11 @@ module.exports = (function () { * Returns the current origin tile and offset at the given zoom level. * This is intended to be cached in the future to optimize coordinate * transformations. + * * @protected * @param {number} level The target zoom level. - * @returns {object} {index: {x, y}, offset: {x, y}} + * @returns {object} The origin and offset in the form + * `{index: {x, y}, offset: {x, y}}`. */ this._origin = function (level) { var origin = this.toLevel(this.toLocal(this.map().origin()), level), @@ -391,8 +378,10 @@ module.exports = (function () { /** * Returns a tile's bounds in its level coordinates. + * * @param {geo.tile} tile The tile to check. - * @returns {object} The tile's bounds. + * @returns {object} The tile's bounds with `left`, `top`, `right`, + * `bottom`. */ this._tileBounds = function (tile) { var origin = this._origin(tile.index.level); @@ -401,11 +390,13 @@ module.exports = (function () { /** * Returns the tile indices at the given point. - * @param {object} point The coordinates in pixels relative to the map origin. + * + * @param {object} point The coordinates in pixels relative to the map + * origin. * @param {number} point.x * @param {number} point.y * @param {number} level The target zoom level. - * @returns {object} The tile indices. + * @returns {object} The tile indices. This has `x` and `y` properties. */ this.tileAtPoint = function (point, level) { var o = this._origin(level); @@ -521,10 +512,10 @@ module.exports = (function () { /** * Returns a string representation of the tile at the given index. * - * Note: This method _must_ return the same string as: - * + * Note: This method **must** return the same string as: + * ``` * tile({index: index}).toString(); - * + * ``` * This method is used as a hashing function for the caching layer. * * @param {object} index The tile index @@ -708,6 +699,7 @@ module.exports = (function () { * This method returns a metric that determines tile loading order. The * default implementation prioritizes tiles that are closer to the center, * or at a lower zoom level. + * * @protected * @param {object} center The center tile. * @param {number} center.x @@ -779,7 +771,7 @@ module.exports = (function () { * @param {number} coord.y The offset in pixels (level 0) from the bottom * edge. * @param {number} level The zoom level of the new coordinates. - * @returns {object} The pixel coordinates. + * @returns {object} The pixel coordinates with `x` and `y`. */ this.toLevel = function (coord, level) { var s = Math.pow(2, level); @@ -790,8 +782,9 @@ module.exports = (function () { }; /** - * Draw the given tile on the active canvas. - * @param {geo.tile} tile The tile to draw + * Draw the given tile on the active canvas + *. + * @param {geo.tile} tile The tile to draw. */ this.drawTile = function (tile) { var hash = tile.toString(); @@ -814,7 +807,7 @@ module.exports = (function () { * this method to draw the tile on a renderer specific context. * * @protected - * @param {geo.tile} tile The tile to draw + * @param {geo.tile} tile The tile to draw. */ this._drawTile = function (tile) { // Make sure this method is not called when there is @@ -865,6 +858,7 @@ module.exports = (function () { /** * Remove the given tile from the canvas and the active cache. + * * @param {geo.tile|string} tile The tile (or hash) to remove. * @returns {geo.tile} The tile removed from the active layer. */ @@ -883,6 +877,7 @@ module.exports = (function () { /** * Remove the given tile from the canvas. This implementation just * finds and removes the element created for the tile. + * * @param {geo.tile|string} tile The tile object to remove. */ this._remove = function (tile) { @@ -903,6 +898,7 @@ module.exports = (function () { /** * Move the given tile to the top on the canvas. + * * @param {geo.tile} tile The tile object to move. */ this._moveToTop = function (tile) { @@ -915,7 +911,6 @@ module.exports = (function () { * * @returns {object} Bounds object with `left`, `right`, `top`, `bottom`, * `scale`, and `level` keys. - * @protected */ this._getViewBounds = function () { var map = this.map(), @@ -943,9 +938,9 @@ module.exports = (function () { * view or the zoom has changed. * * @protected - * @param {number} zoom Tiles (in bounds) at this zoom level will be kept + * @param {number} zoom Tiles in bounds at this zoom level will be kept. * @param {boolean} doneLoading If true, allow purging additional tiles. - * @param {object} bounds view bounds. If not specified, this is + * @param {geo.geoBounds} bounds View bounds. If not specified, this is * obtained from _getViewBounds(). * @returns {this} */ @@ -974,6 +969,7 @@ module.exports = (function () { /** * Remove all active tiles from the canvas. + * * @returns {geo.tile[]} The array of tiles removed. */ this.clear = function () { @@ -994,9 +990,10 @@ module.exports = (function () { }; /** - * Reset the layer to the initial state, clearing the canvas - * and resetting the tile cache. - * @returns {this} Chainable. + * Reset the layer to the initial state, clearing the canvas and resetting + * the tile cache. + * + * @returns {this} */ this.reset = function () { this.clear(); @@ -1005,12 +1002,13 @@ module.exports = (function () { }; /** - * Compute local coordinates from the given world coordinates. The - * tile layer uses units of pixels relative to the world space - * coordinate origin. - * @param {object} pt A point in world space coordinates. + * Compute local coordinates from the given world coordinates. The tile + * layer uses units of pixels relative to the world space coordinate + * origin. + * + * @param {object} pt A point in world space coordinates with `x` and `y`. * @param {number|undefined} zoom If unspecified, use the map zoom. - * @returns {object} Local coordinates. + * @returns {object} Local coordinates with `x` and `y`. */ this.toLocal = function (pt, zoom) { var map = this.map(), @@ -1022,12 +1020,13 @@ module.exports = (function () { }; /** - * Compute world coordinates from the given local coordinates. The - * tile layer uses units of pixels relative to the world space - * coordinate origin. - * @param {object} pt A point in world space coordinates. + * Compute world coordinates from the given local coordinates. The tile + * layer uses units of pixels relative to the world space coordinate + * origin. + * + * @param {object} pt A point in world space coordinates with `x` and `y`. * @param {number|undefined} zoom If unspecified, use the map zoom. - * @returns {object} Local coordinates. + * @returns {object} Local coordinates with `x` and `y`. */ this.fromLocal = function (pt, zoom) { // these need to always use the *layer* unitsPerPixel, or possibly @@ -1052,6 +1051,7 @@ module.exports = (function () { /** * Return the DOM element containing a level specific layer. This will * create the element if it doesn't already exist. + * * @param {number} level The zoom level of the layer to fetch. * @returns {DOM} The layer's DOM element. */ @@ -1072,10 +1072,11 @@ module.exports = (function () { /** * Set sublayer transforms to align them with the given zoom level. + * * @param {number} level The target zoom level. * @param {geo.geoBounds} view The view bounds. The top and left are used * to adjust the offset of tile layers. - * @returns {object} The x and y offsets for the current level. + * @returns {object} The `x` and `y` offsets for the current level. */ this._updateSubLayers = function (level, view) { var canvas = this.canvas(), @@ -1115,10 +1116,11 @@ module.exports = (function () { /** * Update the view according to the map/camera. + * * @param {geo.event} evt The event that triggered the change. Zoom and * rotate events do nothing, since they are always followed by a pan * event which will cause appropriate action. - * @returns {this} Chainable. + * @returns {this} */ this._update = function (evt) { /* Ignore zoom and rotate events, as they are ALWAYS followed by a pan @@ -1251,8 +1253,9 @@ module.exports = (function () { /** * Set a value in the tile tree object indicating that the given area of * the canvas is covered by the tile. + * * @protected - * @param {geo.tile} tile + * @param {geo.tile} tile The tile to add. */ this._setTileTree = function (tile) { if (this._options.keepLower) { @@ -1265,7 +1268,7 @@ module.exports = (function () { }; /** - * Get a value in the tile tree object if it exists or return null. + * Get a value in the tile tree object if it exists or return `null`. * @protected * @param {object} index A tile index object * @param {object} index.level @@ -1290,7 +1293,7 @@ module.exports = (function () { * part of the tile is exposed. * * @protected - * @param {geo.tile} tile + * @param {geo.tile} tile The tile to check. * @returns {geo.tile[]|null} */ this._isCovered = function (tile) { @@ -1343,7 +1346,7 @@ module.exports = (function () { * Returns true if the provided tile is outside of the current view bounds * and can be removed from the canvas. * @protected - * @param {geo.tile} tile + * @param {geo.tile} tile The tile to check. * @param {geo.geoBounds} bounds The view bounds. * @returns {boolean} */ @@ -1362,12 +1365,12 @@ module.exports = (function () { }; /** - * Returns true if the provided tile can be purged from the canvas. This method - * will return `true` if the tile is completely covered by one or more other tiles - * or it is outside of the active view bounds. This method returns the logical and - * of `_isCovered` and `_outOfBounds`. + * Returns true if the provided tile can be purged from the canvas. This + * method will return `true` if the tile is completely covered by one or + * more other tiles or it is outside of the active view bounds. This + * method returns the logical and of `_isCovered` and `_outOfBounds`. * @protected - * @param {geo.tile} tile + * @param {geo.tile} tile The tile to check. * @param {geo.geoBounds} [bounds] The view bounds (if unspecified, assume * global bounds) * @param {number} bounds.level The zoom level the bounds are given as. @@ -1410,7 +1413,7 @@ module.exports = (function () { * @param {object} [pt] The point to convert with `x` and `y`. If * `undefined`, use the center of the display. * @param {number} [zoom] If specified, the zoom level to use. - * @returns {object} The point in level coordinates. + * @returns {object} The point in level coordinates with `x` and `y`. */ this.displayToLevel = function (pt, zoom) { var map = this.map(), @@ -1566,7 +1569,7 @@ module.exports = (function () { tileLayer.defaults = { minLevel: 0, maxLevel: 18, - tileOverlap: 0, + tileOverlap: {x: 0, y: 0}, tileWidth: 256, tileHeight: 256, wrapX: true,