modestmaps-js-3.3.6/ 0000775 0000000 0000000 00000000000 12102272605 0014306 5 ustar 00root root 0000000 0000000 modestmaps-js-3.3.6/.gitignore 0000664 0000000 0000000 00000000031 12102272605 0016270 0 ustar 00root root 0000000 0000000 node_modules
.swp
.*.swp
modestmaps-js-3.3.6/CHANGELOG 0000664 0000000 0000000 00000027230 12102272605 0015524 0 ustar 00root root 0000000 0000000 Modest Maps JS Changelog.
Following the semantic versioning recommendation best we can:
"Consider a version format of X.Y.Z (Major.Minor.Patch).
Bug fixes not affecting the API increment the patch version,
backwards compatible API additions/changes increment the
minor version, and backwards incompatible API changes increment
the major version." -- http://semver.org/
v3.3.6
- .enable() and .disable() return the layer object as expected
- `setCenter()` now correctly calls enforceLimits so that `locationPoint`
is immediately accurate.
- Examples fixes
- Now builds with uglifyjs instead of YUICompressor
v3.3.5
- Fixes rounding bug in MapProvider's `sourceCoordinate`
v3.3.4
- Layers no longer copy their CSS properties from their parent nodes,
so that parent node CSS can be changed with properties like `clip` and
`opacity` without this having per-zoom-level effects.
v3.3.3
- Fixes empty gif image
v3.3.2
- Fixes problem with parent tiles by again assigning the element to have an
empty image as its src.
v3.3.1
- Fixes bug where Layer.draw would try to draw even if not attached to a map.
v3.3.0
- Adds `.enable()` and `.disable()` methods to layers, and
`.enableLayer()`/`.enableLayerAt()` and `.disableLayer()`/`.disableLayerAt()`
to the map object.
v3.2.1
- Fixes bug in the MM.MapProvider.sourceCoordinate where tiles containing
areas within the tile limits were not loaded at lower zoom levels
v3.2.0
- Adds named layers: a third parameter to MM.Layer and MM.TemplatedLayer
that sets the `.name` property of a layer. The layer name can be used
with the new `map.getLayer()` method, which returns the first layer
matching that name, and `map.removeLayer()`, which now accepts either the
literal layer object or the layer name as its one argument.
- Tests have moved from `/test/browser` to just `/test`
v3.1.3
- Explicitly set the size of tiles to the `tileSize` parameter in the Map
object in order to support tiles that are not 256x256
v3.1.2
- Fixes a bug in the TouchHandler leading to inaccurate movement
when on scalable devices like iPhones and not at native screen resolution.
v3.1.1
- Fixes a bug in the `MM.Map` constructor which prevent `null` or
`undefined` being passed as the layers parameter. This makes it easier
to call `MM.Map` with only one argument - the div.
v3.1.0
- `map.setZoomRange()` returns the map object to allow it to be chained
with other calls. It previously returned undefined.
v3.0.0
- Instead of a tile URL or element, the message of the `requesterror` event
will be an object with `url` and `element` members relating to the source
element and its url / href
v2.0.2
- Allows `touchstart` events to propagate to handlers instead of stopping
them at the TouchHandler level. This allows libraries that have elements
on the map that rely on `click` events to work. This does not fix the
problem of allowing scrollable elements in the map element.
v2.0.1
- Fixing negative coordinate wrapping, identified at https://github.com/mapbox/tilemill/issues/1395
v2.0.0
- Two breaking changes:
- requesterror now calls its callbacks with the img element, like
requestcomplete, not img.src as before
- TemplatedMapLayer renamed to Template, refs #14
v1.1.3
- Fix Location.bearing method
v1.1.2
- Update addMap API to better deal with layers that do deferred
`draw` calls - it now requests a redraw if the map has a center
v1.1.1
- Fix TouchHandler refactor
v1.1.0
- Revert futuristic layer-tile handling to cross-browser version
that touches all tiles on all moves.
v1.0.3
- Fixes insertLayerAt behavior with indexes within the layers array.
Adds associated tests.
v1.0.2
- Removes cache infrastructure
- Rewrites handlers to remove bind usage, now depends on browser cache
- Adds MM.Location.bearing
v1.0.0-beta1
- Fixes coordLimits enforcement
- Removes TilePaintingProvider and auto-casting to it in setProvider,
updating all examples.
v1.0.0 (dev)
- `map.setSize` now only accepts an object of the form `{x: 0, y: 0}` or a
`MM.Point` object, and it calls its callback with a `MM.Point` argument.
- `map.roundZoom` added to the map to allow for the old behavior of
`map.setExtent` if desired.
- Maps now include `MM.TouchHandler()` by default for touch-device compatibility
- `MM.MouseWheelHandler()` now supports a second argument, `precise`, which,
when true, will allow intermediate zooms.
- MouseWheel events are now normalized to take advantage of acceleration and
avoid browser bugs.
- `map.setExtent()` now accepts either an array of `MM.Location` objects or an
`MM.MapExtent` object, which it converts to an array of locations with
`extent.toArray()`.
- the `MM.Hash` event handler can set a map's center and zoom from the URL hash
(`#{zoom}/{lat}/{lon}`) and update the hash when it changes. A standalone
class is provided in `examples/hash/modestmaps.hash.js`.
- `MM.TemplatedMapProvider()` now supports quadkey coordinate substitutions in
URL templates with "{Q}" instead of the TMS-style "{Z}", "{X}" and "{Y}".
- `MM.TemplatedMapProvider()` also supports Microsoft-style URL templates,
which specify subdomain, zoom and quadkey placeholders with "{subdomains}",
"{zoom}" and "{quadkey}", respectively.
v0.21.0
- Returns `this` from `map.addCallback()`, `map.removeCallback()`,
and `map.dispatchCallback()`
v0.20.0
- Adds `map.destroy()` method, and in that process, allows all
handlers to be removable with a `.remove()` function.
v0.19.1
- Removes unused 'parent' argument to `com.modestmaps.RequestManager`
v0.19.0
- Adds a second parameter to `map.setExtent()` which, if true,
allows the extent set to place the map at a non-integer zoom level.
By default, `setEvent` will behave as before.
v0.18.5
- Address issue where display:none on parent affects size detection
(thanks @tmcw)
- Remove arbitary default map size - parent size is used always unless
dimensions are specified. Use setSize to override at any time.
v0.18.4
- Fix Location.interpolate between the same location
- Fix DragHandler - remove inertia code
v0.18.3
- enforce limits when zooming and panning so that map functions are correct
when returning and before the deferred draw call using getFrame
v0.18.2
- revert to @tmcw's original getFrame (simpler version broke in Chrome)
v0.18.1
- revert Coordinate.toKey to string joining
- fix up utils.js functions so that tests run again
- modify double-tap thresholds and adjust onPinched behavior
- a few more cleanups in TouchHandler (mainly to use MM.Point functions)
v0.18.0
- many tiny formatting/syntax fixes; thx JSHint!
- MM.moveElement is used for tile positioning
- MM.moveElement detects and uses CSS transforms wherever possible
- MM.bind is used for function binding instead of awkward closures
- MM.getFrame is used to request redraws
- MM.getFrame uses provisional requestAnimationFrame implementations if possible
- TouchHandler is in the default build of modestmaps.js
- Coordinate.toKey() is clever again ;)
Thanks to @tmcw for the majority of these contributions. They were contributed
on a branch, hence only one minor version number bump. As far as we know this
should all be backwards compatible. If we're mistaken, please file an issue at
https://github.com/stamen/modestmaps-js/issues
Note also that we've now got fairly decent node.js support for the core MM.js
classes, and there's an example of how to use Modest Maps with node-canvas to
render static map images from a tiled data source. "npm install modestmaps" for
node.js fans :)
v0.17.0
- Mouse handlers refactor: while MouseHandler is still available for adding
all handlers to the map, double-click, zoomwheel, and drag handlers are
available individually.
- Broken images that result from image loading errors are no longer added to
the map.
v0.16.1
- Unimplemented abstract methods throw exceptions instead of calling `alert()`
v0.16.0
- added MapProvider.setZoomRange for @straup
v0.15.2
- misc syntax fixes and improve parseInt/radix correctness, from @tmcw
v0.15.1
- switched to document fragment for loadingBay, from @tmcw
v0.15.0
- added method chaining from @tmcw
v0.14.3
- improve redraw behavior by ensuring layer is visible in getTileComplete
- use a closure in v0.14.2's setTimeout to ensure proper 'this'
v0.14.2
- add setTimeout to processQueue to avoid stack overflow/recursion
bug in IE 7/8 (https://github.com/stamen/modestmaps-js/issues/12)
thanks @yhahn!
v0.14.1
- reinstated display of children for missing tiles, except when if
map.enablePyramidLoading is set to true
v0.14.0
- added map.enablePyramidLoading flag for pyramid loading (off by default)
- fixed Coordinate.prototype.toKey (back to string join to avoid collisions)
v0.13.5
- changed the order of initialization so that event handlers go last
(this is so that attributes like layerParent are in place for complex
event handlers like anyzoom.js... handlers can also use callbacks now)
2011-01-03 note:
- broke modestmap.js file into src folder, now building with Makefile
- no functionality change to modestmaps.js (just whitespace changes)
v0.13.4
- changed to img.style.width instead of img.width, for ipads (see examples/touch/test.html)
v0.13.3
- stubbed out tilePadding into Map.draw
v0.13.2
- removing magic numbers from Mercator projection for parity with Python version
v0.13.1
- rejiggered the Map's draw function to be a bit clearer
- removed superfluous layer.coordinate (internal only)
v0.13.0
- factored image loading out into a separate RequestManager
- cleaned up RequestManager to be less tile-centric, more img-centric
v0.12.0
- made callback handling more modular
v0.11.2
- re-instated zoom level check for setExtent (fixes bug where locations are all the same)
v0.11.1
- moved to cssText for long CSS inits
v0.11.0
- added 'drawn' callback
- added removeCallback
- correctly following semver.org now, incrementing minor version!
v0.10.4
- modified queue sorting to support pyramid loading
- stubbed out pyramid loading
- tidied up draw code to be clearer (wantedTiles --> validTileKeys)
v0.10.3
- added Point.distance and Point.interpolate
- added Location.distance and Location.interpolate
v0.10.2
- tweak to sorting function that appears to fix an issue in IE8
v0.10.1
- fixed tile sorting for in-between zoom levels
- fixed tile position in onload handler
v0.10.0
- tidied up initial coord/position maths, now supports arbitrary zoom levels (with seams)
v0.9.5
v0.9.4
- changes to MapProvider.sourceCoordinate to support non-Mercator bounds
v0.9.3
- added inner and outer limits to providers and enforcing min/max zoom in Map.draw()
- changed zoomByAbout to use zoomBy (and draw/enforceLimits) before applying panBy
v0.9.2
- fixed bug that could break zooming if setCenterZoom was called with a string
v0.9.1
- removed assumption that layers go from 0 to 20
v0.9.0
- added rational version numbering
May 2010, pre-semver
+ added setSize and setProvider methods (fixed the latter so that all loads are canceled)
+ optional interaction (factored out mouse handling... enables touch or keyboard later)
+ made a touch handler for iphads
+ made a TemplatedMapProvider
+ made a demo that accepts a URL template for a map provider
+ started to work towards jslint conformance
+ started to move to 80 character line length where practical
+ made a demo with two maps, synchronized
+ jslint fixes, 80 char lines, better sorting, removed createOverlay
+ templated providers wrap around in longitude by default
+ added a demo keyboard handler
+ positioning single tiles in onload instead of redrawing everything
+ added a zoom box demo
+ make sure the cache gets cleared after a while (BIG FEATURE)
+ don't load above/below north/south poles (for default mercator maps)
+ added a random subdomain helper to templated providers
modestmaps-js-3.3.6/Makefile 0000664 0000000 0000000 00000001543 12102272605 0015751 0 ustar 00root root 0000000 0000000 NODE_PATH ?= ./node_modules
JS_COMPILER = $(NODE_PATH)/uglify-js/bin/uglifyjs
JS_FILES = \
src/start.js \
src/utils.js \
src/point.js \
src/coordinate.js \
src/location.js \
src/extent.js \
src/transformation.js \
src/projection.js \
src/provider.js \
src/mouse.js \
src/touch.js \
src/callbacks.js \
src/requests.js \
src/layer.js \
src/map.js \
src/convenience.js \
src/end.js
VERSION = `cat VERSION`
all: update-version modestmaps.js modestmaps.min.js
modestmaps.min.js: modestmaps.js
rm -f modestmaps.min.js
$(JS_COMPILER) modestmaps.js > modestmaps.min.js
modestmaps.js: $(JS_FILES) Makefile
rm -f modestmaps.js
cat $(JS_FILES) | perl -pi -e "s/{VERSION}/$(VERSION)/g" > modestmaps.js
update-version:
perl -pi -e "s/\"version\": \"[^\"]+/\"version\": \"$(VERSION)/g" package.json
clean:
rm -f modestmaps.js
rm -f modestmaps.min.js
modestmaps-js-3.3.6/README.md 0000664 0000000 0000000 00000002161 12102272605 0015565 0 ustar 00root root 0000000 0000000 Modest Maps JS is a BSD-licensed display and interaction library for tile-based
maps in Javascript.
Our intent is to provide a minimal, extensible, customizable, and free display
library for discriminating designers and developers who want to use interactive
maps in their own projects. Modest Maps provides a core set of features in a
tight, clean package, with plenty of hooks for additional functionality.
# [Documentation](https://github.com/modestmaps/modestmaps-js/wiki)
## Building
This package includes a copy of [YUICompressor](http://developer.yahoo.com/yui/compressor/),
which requires a version of Java on your system. To create a new build of
Modest Maps (only necessary for development), run `make` from the root
directory.
## Developing with npm:
Modest Maps includes a `package.json` file to guide usage of its code on the
server-side, and to handle certain dependencies.
To install developer dependencies - needed for documentation and tests -
you'll need [npm](http://npmjs.org/):
npm install --dev
## Tests
Tests require `expresso` to be installed by `npm`, as noted above. To run tests,
make tests
modestmaps-js-3.3.6/VERSION 0000664 0000000 0000000 00000000006 12102272605 0015352 0 ustar 00root root 0000000 0000000 3.3.6
modestmaps-js-3.3.6/doc/ 0000775 0000000 0000000 00000000000 12102272605 0015053 5 ustar 00root root 0000000 0000000 modestmaps-js-3.3.6/doc/.gitignore 0000664 0000000 0000000 00000000022 12102272605 0017035 0 ustar 00root root 0000000 0000000 api.html
toc.html
modestmaps-js-3.3.6/doc/Makefile 0000664 0000000 0000000 00000000535 12102272605 0016516 0 ustar 00root root 0000000 0000000 # to install marked: `npm install marked`
MARKED ?= ../node_modules/marked/bin/marked --gfm
VERSION = `cat ../VERSION`
all: index.html
index.html: toc.html api.html
cat start.html toc.html middle.html api.html end.html \
| perl -pi -e "s/{VERSION}/$(VERSION)/g" > $@
%.html: %.md
$(MARKED) $< > $@
clean:
rm -f index.html toc.html api.html
modestmaps-js-3.3.6/doc/api.md 0000664 0000000 0000000 00000136170 12102272605 0016156 0 ustar 00root root 0000000 0000000 # modestmaps.js
Modest Maps is a bare-bones geographic map display and interaction library. It was designed and conceived by [Tom Carden], tweaked by [Michal Migurski], and is maintained and hacked on primarily by [Tom MacWright] and [Shawn Allen].
[Tom Carden]: http://www.tom-carden.co.uk/
[Michal Migurski]: http://mike.teczno.com/
[Tom MacWright]: http://macwright.org/
[Shawn Allen]: http://github.com/shawnbot
## Getting the Source
You can get modestmaps.js by cloning [the github repo](https://github.com/modestmaps/modestmaps-js/) or downloading it:
* [modestmaps.js-v{VERSION}.zip](https://github.com/modestmaps/modestmaps-js/zipball/v{VERSION}) (zip archive)
* [modestmaps.js](../modestmaps.js) (source JavaScript, 100K)
* [modestmaps.min.js](../modestmaps.min.js) (minified JavaScript, 36K)
After you've downloaded it, you can include by putting this `
```
## Quick Start
### Making a Map
Making a map is easy. First, you'll need a place for your map in the HTML:
```
` elements have no intrinsic height, so if you don't provide dimensions you'll need to provide the map's parent height in CSS (either inline or in a stylesheet).
#### eventHandlers
An optional array of interaction event handlers, which should implement the [EventHandler interface](#EventHandler-Interface). If no handlers are provided (`eventHandlers === undefined`), the map is initialized with [mouse](#MouseHandler) and [touch](#TouchHandler) handlers.
For instance, to create a map without scroll wheel zooming (which is enabled by default), you can provide [drag](#DragHandler), and [double-click](#DoubleClickHandler) handlers:
```
var map = new MM.Map("map", [], null, [
new MM.DragHandler(),
new MM.DoubleClickHandler()
]);
```
The [touch](#TouchHandler) handler provides panning and zooming in touch-enabled browsers:
```
var map = new MM.Map("map", [], null, [
new MM.TouchHandler()
]);
```
To initialize the map without any interaction handlers, specify **eventHandlers** as `null` or an empty array (`[]`).
### getCenter `map.getCenter()`
Get the map's center **location**.
```
var center = map.getCenter();
console.log("center latitude:", center.lat, "+ longitude:", center.lon);
```
### setCenter `map.setCenter(location)`
Set the map's center **location**.
```
var center = new MM.Location(37.764, -122.419);
map.setCenter(center);
```
### getZoom `map.getZoom()`
Get the map's **zoom level**.
```
var zoom = map.getZoom();
console.log("zoom level:", zoom);
```
### setZoom `map.setZoom(zoom)`
Set the map's **zoom level**.
```
map.setZoom(17);
```
### setCenterZoom `map.setCenterZoom(location, zoom)`
Set the map's center **location** and **zoom level**.
```
map.setCenterZoom(new MM.Location(37.764, -122.419), 17);
```
### getExtent `map.getExtent()`
Get the visible extent (bounds) of the map as an [Extent](#Extent) object.
```
var extent = map.getExtent();
console.log("northwest location:", extent.northWest());
console.log("southeast location:", extent.southEast());
```
### setExtent `map.setExtent(extent [, precise])`
Modify the center and zoom of the map so that the provided **extent** is visible. If **precise** is `true`, resulting zoom levels may be fractional. (By default, the map's zoom level is rounded down to keep tile images from blurring.)
```
var extent = new MM.Extent(
new MM.Location(55.679, 12.584),
new MM.Location(55.668, 12.607)
);
map.setExtent(extent, true);
```
NOTE: For historical reasons, **setExtent** also accepts an array of [Location](#Location) objects, which are converted using [Extent.fromArray](#Extent.fromArray).
### zoomIn `map.zoomIn()`
Increase the map's zoom level by one.
### zoomOut `map.zoomOut()`
Decrease the map's zoom level by one.
### zoomBy `map.zoomBy(zoomOffset)`
Zoom the map by the provided **offset**. Positive offsets zoom in; negative offsets zoom out.
```
// this is the equivalent of calling map.zoomIn() twice:
map.zoomBy(2);
```
### zoomByAbout `map.zoomByAbout(zoomOffset, point)`
Zoom the map by the provided **zoom offset** from a **point** on the screen in pixels. Positive offsets zoom in; negative offsets zoom out. This function is used by [DoubleClickHandler](#DoubleClickHandler) to zoom in on the point where the map is double-clicked.
```
// zoom in on the upper left corner
var point = new MM.Point(0, 0);
map.zoomByAbout(1, point);
```
### panBy `map.panBy(x, y)`
Pan the map by the specified **x** and **y** distance in pixels. Positive values move the map right and down, respectively; negative values move the map left and up.
```
// pan 500 pixels to the right
map.panBy(500, 0);
// pan 200 pixels up
map.panBy(0, -200);
```
### panLeft `map.panLeft()`
### panRight `map.panRight()`
### panUp `map.panUp()`
### panDown `map.panDown()`
Pan the map to the left, right, up or down by 100 pixels. To vary the offset distance, use [panBy](#Map.panBy).
### getLayers `map.getLayers()`
Get a copy of the map's layers array.
```
var layers = map.getLayers();
var base = layers[0];
```
### getLayerAt `map.getLayerAt(index)`
Get the layer at a specific **index**. The first layer is at index `0`, the second at `1`, etc.
```
var map = new MM.Map(...);
var base = map.getLayerAt(0);
base.parent.id = "base";
```
### addLayer `map.addLayer(layer)`
Add **layer** to the map's [layer stack](#Map.layers)]. This triggers a [redraw](#Map.redraw).
```
var layer = new MM.TemplatedLayer("http://tile.stamen.com/toner-lines/{Z}/{X}/{Y}.png");
map.addLayer(layer);
```
### removeLayer `map.removeLayer(layer)`
Remove **layer** from the map's [layer stack](#Map.layers).
### setLayerAt `map.setLayerAt(index, newLayer)`
Replace the existing layer at **index** with the **new layer**.
```
var layer = new MM.TemplatedLayer("http://tile.stamen.com/toner/{Z}/{X}/{Y}.png");
map.setLayerAt(0, layer);
```
### insertLayerAt `map.insertLayerAt(index, layer)`
Insert a **layer** at the provided **index**.
```
// let's assume the map has 2 layers already
var layer = new MM.TemplatedLayer("http://tile.stamen.com/toner-lines/{Z}/{X}/{Y}.png");
map.insertLayerAt(1, layer);
// (now it has 3, with our new layer at index 1)
```
### removeLayerAt `map.removeLayerAt(index)`
Remove the layer at the provided index.
```
// remove the second layer
map.removeLayerAt(1);
```
### swapLayersAt `map.swapLayersAt(indexA, indexB)`
Swap the z-index (order) or the layers at **indexA** and **indexB**.
```
// swap the bottom and top layers
var bottom = 0,
top = map.getLayers().length - 1;
map.swapLayersAt(bottom, top);
```
### pointLocation `map.pointLocation(screenPoint)`
Convert a **point on the screen** to a [location](#Location) (a point on the Earth).
### pointCoordinate `map.pointCoordinate(screenPoint)`
Convert a **point on the screen** to a [tile coordinate](#Coordinate).
### locationPoint `locationPoint(location)`
Convert a **location** (a point on the Earth) to a [point](#Point) on the screen.
### locationCoordinate `map.locationCoordinate(location)`
Convert a **location** (a point on the Earth) to a [tile coordinate](#Coordinate).
### coordinateLocation `map.coordinateLocation(coord)`
Convert a [tile coordinate](#Coordinate) to a [location](#Location) (a point on the Earth).
### coordinatePoint `map.coordinatePoint(coord)`
Convert a [tile coordinate](#Coordinate) to a [point](#Point) on the screen.
### setZoomRange `map.setZoomRange(minZoom, maxZoom)`
Set the map's **minimum** and **maximum** zoom levels. This function modifies the zoom levels of the map's [coordLimits](#Map.coordLimits).
### setSize `map.setSize(dimensions)`
Set the map's **dimensions** in pixels. If the map's [autoSize](#Map.autoSize) flag is `true`, setting the size manually sets **autoSize** to `false` and prevents further automatic resizing.
```
map.setSize(new MM.Point(640, 480));
```
NOTE: The map's current size is available in its [dimensions](#Map.dimensions) property.
### addCallback `map.addCallback(eventType, callback)`
Add a **callback function** (listener) to the map for a specific **event type**. Callback functions always receive the map instance as their first argument; additional arguments differ by event type. See the [events list](#Map-events) for supported types.
```
function onPanned(map, offset) {
console.log("panned by", offset[0], offset[1]);
}
map.addCallback("panned", onPanned);
```
You can remove callbacks with [removeCallback](#Map.removeCallback).
### removeCallback `map.removeCallback(eventType, callback)`
Remove a **callback function** (listener) for the given **event type**. You can add callbacks with [addCallback](#Map.addCallback).
```
map.removeCallback("panned", onPanned);
```
### draw `map.draw()`
Redraw the map and its layers. First, the map enforces its [coordLimits](#Map.coordLimits) on its center and zoom. If [autoSize](#Map.autoSize) is `true`, the map's dimensions are recalculated from its [parent](#Map.parent). Lastly, each of the map's layers is [drawn](#Layer.draw).
### requestRedraw `map.requestRedraw()`
Request a "lazy" call to [draw](#Map.draw) in 1 second. This is useful if you're responding to lots of user input and know that you'll need to redraw the map *eventually*, but not immediately.
Multiple calls to **requestRedraw** within 1 second of one another will be ignored, so this is a perfectly reasonable thing to do:
```
setInterval(function() {
map.requestRedraw();
}, 100);
```
## Hybrid Methods
Hybrid methods behave differently depending on whether they receive arguments: The "getter" form (with no arguments) returns the current value, and the "setter" form sets it to the value provided then returns `this`, which makes function chaining possible (a la [jQuery](http://jquery.com), [d3](http://d3js.com), and [Polymaps](http://polymaps.org)).
### center `map.center([location])`
[Get](#Map.getCenter) or [set](#Map.setCenter) the map's center **location**.
```
var center = map.center();
center.lat += .1;
map.center(center);
```
### zoom `map.zoom([level])`
[Get](#Map.getZoom) or [set](#Map.setZoom) the map's **zoom level**.
```
var zoom = map.zoom();
zoom -= 3;
map.zoom(zoom);
```
### extent `map.extent([locationsOrExtent [, precise]])`
[Get](#Map.getZoom) or [set](#Map.setZoom) the map's extent. If **precise** is `true`, resulting zoom levels may be fractional.
```
// get the extent, check if it contains a location…
var extent = map.extent(),
loc = new MM.Location(37.764, -122.419);
if (!extent.containsLocation(loc)) {
// then enclose the location and set the map's new extent
extent.encloseLocation(loc);
map.extent(extent);
}
```
## Map Properties
### autoSize `map.autoSize`
The **autoSize** property is set to `true` if no dimensions are provided in the [constructor](#Map). When **autoSize** is `true`, the map's dimensions are recalculated (and the map is [redrawn](#Map.draw)) [on window resize](https://developer.mozilla.org/en/DOM/window.onresize).
### coordinate `map.coordinate`
The map's current center [coordinate](#Coordinate).
### coordLimits `map.coordLimits`
An array specifying the map's coordinate bounds, in which the first element defines the top left (northwest) and outermost zoom level, and the second defines the bottom right (southwest) and innermost zoom.
You can adjust the minimum and maximum zoom levels of the map without affecting the bounds with [setZoomRange](#Map.setZoomRange).
### dimensions `map.dimensions`
The map's current dimensions, expressed as a [Point](#Point).
```
// the bottom right screen coordinate is also its southeast point
var southEast = map.pointLocation(map.dimensions);
```
### parent `map.parent`
The map's parent (container) DOM element.
```
map.parent.style.backgroundColor = "green";
```
### projection `map.projection`
The map's projection, also known as Coordinate Reference System (CRS) or Spatial Reference System (SRS).
### tileSize `map.tileSize`
The pixel dimensions of the map's individual image tiles, expressed as a [Point](#Point). By default, tiles are **256** pixels square.
```
// you can use the tile size to estimate the number of tiles visible
// at any given moment:
var maxRows = Math.ceil(map.dimensions.x / map.tileSize.x);
var maxCols = Math.ceil(map.dimensions.y / map.tileSize.y);
var maxTiles = maxRows * maxCols;
console.log("max tiles:", maxTiles);
```
## Map Events
Map events are triggered when the map moves (either in response to a direct function call or indirectly, through user interaction with an event handlers) or is [drawn](#Map.draw). You can start and stop listening for map events with [addCallback](#Map.addCallback) and [removeCallback](#Map.removeCallback):
```
function onDrawn(map) {
console.log("map drawn!");
}
// After this, the onDrawn will be called whenever the map changes.
map.addCallback("drawn", onZoomed);
// Later, remove the callback.
map.removeCallback("drawn", onZoomed);
```
### "zoomed" `function(map, zoomOffset) { ... }`
Fires when the **map's** zoom level changes, usually in response to [zoomBy](#Map.zoomBy) or [zoomByAbout](#Map.zoomByAbout). Note that the **zoom offset** is the *difference* between the last zoom level and the new zoom level. You can query the map's current zoom level (rather than the offset) with [getZoom](#Map.getZoom).
```
map.addCallback("zoomed", function(map, zoomOffset) {
console.log("map zoomed by:", zoomOffset);
});
```
### "panned" `function(map, panOffset) { ... }`
Fires when the **map** is panned, and receives the **pan offset** (delta) in pixels as a two-element array (`[dx, dy]`).
```
map.addCallback("panned", function(map, panOffset) {
var dx = panOffset[0],
dy = panOffset[1];
console.log("map panned by x:", dx, "y:", dy);
});
```
### "resized" `function(map, dimensions) { ... }`
Fires when the **map** is resized, and receives the map's new **dimensions** as a [Point](#Point) object.
```
map.addCallback("panned", function(map, dimensions) {
console.log("map dimensions:", dimensions.x, "y:", dimensions.y);
});
```
### "extentset" `function(map, locationsOrExtent) { ... }`
Fires whenever the **map's** full extent is set, and receives the [Extent](#Extent) or array of [Location](#Location) objects provided to [setExtent](#Map.setExtent) or [extent](#Map.extent).
```
map.addCallback("extentset", function(map, extent) {
// convert to an Extent instance if it's a Location array
if (extent instanceof Array) {
extent = MM.Extent.fromArray(extent);
}
console.log("map extent:", extent);
});
```
### "drawn" `function(map) { ... }`
Fires whenever the **map** is [redrawn](#Map.draw).
```
map.addCallback("drawn", function(map) {
console.log("map drawn!");
});
```
## MM.Location
Location objects represent [geographic coordinates](http://en.wikipedia.org/wiki/Geographic_coordinate_system) on the Earth's surface, expressed as degrees *latitude* and *longitude*. The constructor takes these two values as its arguments:
```
new MM.Location(latitude, longitude)
```
Locations are most often used when [getting](#Map.getCenter) and [setting](#Map.setCenter) the center of a [map](#Map). You can read the latitude and longitude of a Location by accessing its `lat` and `lon` properties, respectively:
```
var center = map.getCenter(),
latitude = center.lat,
longitude = center.lon;
```
Note that the [Map](#Map) class doesn't store any references to Location objects internally. Both the [getCenter](#Map.getCenter) and [setCenter](#Map.setCenter) methods convert between geographic and [tile coordinate](#Coordinate) systems, and return copies of objects rather than references. This means that changing the `lat` and `lon` properties of a Location object returned from **getCenter** won't change the map's center; you have to call **setCenter** with the modified Location object.
### lat `location.lat`
The location's **latitude**, or distance from the Earth's [equator](http://en.wikipedia.org/wiki/Prime_meridian) in degrees. `-90` is at the bottom of the globe (the south pole in Antarctica), `0` is at the equator, and `90` is at the top (the north pole in the Arctic Ocean).
**NOTE:** Because ModestMaps uses a [spherical Mercator projection](http://en.wikipedia.org/wiki/Mercator_projection), points at Earth's extreme north and south poles become infinitely large and impossible to model. This limits the effective range of web maps to `±85º`, depending on zoom level. Setting a map's center to a Location with a latitude outside of this range will most likely have undesired consequences.
### lon `location.lon`
The location's **longitude**, or distance from the [prime meridian](http://en.wikipedia.org/wiki/Prime_meridian) in degrees. Positive values are east of the prime meridian (towards Asia); negative values are west (towards North America). `±180` degrees is near the [international date line](http://en.wikipedia.org/wiki/International_Date_Line). Longitude values outside of the `[-180, 180]` range "wrap", so a longitude of `190` degrees may be converted to `-170` in certain calculations.
### Location.fromString `MM.Location.fromString(str)`
Parse a string in the format `"lat,lon"` into a new Location object.
### Location.distance `MM.Location.distance(a, b, earthRadius)`
Get the physical distance (along a [great circle](http://en.wikipedia.org/wiki/Great_circle)) between locations **a** and **b**, assuming an optional **Earth radius**:
* `6378000` meters (the default)
* `3963.1` "statute" miles
* `3443.9` nautical miles
* `6378` kilometers
### Location.interpolate `MM.Location.interpolate(a, b, t)`
Interpolate along a [great circle](http://en.wikipedia.org/wiki/Great_circle) between locations **a** and **b** at bias point **t** (a number between 0 and 1).
### Location.bearing `MM.Location.bearing(a, b)`
Determine the direction in degrees between locations **a** and **b**. Note that bearing direction is not constant along significant [great cirlce](http://en.wikipedia.org/wiki/Great_circle) arcs.
### A warning about the `location` variable name
Because browsers reserve the `window.location` variable for [information](https://developer.mozilla.org/en/DOM/window.location) about the current page location, we suggest using variable names other than `location` to avoid namespace conflicts. `center` and `loc` are good alternatives.
## MM.Extent
Extent objects represent rectangular geographic bounding boxes, and are identified by their `north`, `south`, `east` and `west` bounds. North and south bounds are expressed as degrees [latitude](#Location.lat); east and west bounds are degrees [longitude](#Location.lon). The constructor takes two forms:
```
new MM.Extent(north, west, south, east)
```
Create an extent bounded by **north**, **west**, **south** and **east** edges.
```
new MM.Extent(northWest, southEast)
```
Create an extent containing both **northWest** and **southEast** [locations](#Location).
### north `extent.north`
The northern edge of the extent. The [constructor](#Extent) compares northern and southern values and selects the higher of the two as its `north`.
### south `extent.south`
The southern edge of the extent. The [constructor](#Extent) compares northern and southern values and selects the lower of the two as its `south`.
### east `extent.east`
The eastern edge of the extent. The [constructor](#Extent) compares eastern and western values and selects the higher of the two as its `east`.
### west `extent.west`
The western edge of the extent. The [constructor](#Extent) compares eastern and western bounds and selects the lower of the two values as its `west`.
### northWest `extent.northWest()`
Get the extent's northwest corner as a [Location](#Location).
### northEast `extent.northEast()`
Get the extent's northeast corner as a [Location](#Location).
### southEast `extent.southEast()`
Get the extent's southeast corner as a [Location](#Location).
### southWest `extent.southWest()`
Get the extent's southwest corner as a [Location](#Location).
### center `extent.center()`
Get the extent's center as a [Location](#Location).
### containsLocation `extent.containsLocation(lcoation)`
Returns `true` if the **location** falls within the **extent**, otherwise `false`.
```
var extent = new MM.Extent(37.8, -122.5, 37.6, -122.3);
var sf = new MM.Location(37.764, -122.419);
var oakland = new MM.Location(37.804, -122.271);
extent.containsLocation(sf); // true
extent.containsLocation(oakland); // false
```
### encloseLocation `extent.encloseLocation(location)`
Update the bounds of **extent** to include the provided **location**.
```
var extent = new MM.Extent(37.8, -122.5, 37.6, -122.3);
var oakland = new MM.Location(37.804, -122.271);
extent.encloseLocation(oakland);
extent.containsLocation(oakland); // true
```
### encloseLocations `extent.encloseLocations(locations)`
Update the bounds of **extent** to include the provided **locations** (an array of [Location](#Location) objects).
### encloseExtent `extent.encloseExtent(otherExtent)`
Update the bounds of **extent** to include the bounds of the **other extent**.
### setFromLocations `extent.setFromLocations(locations)`
Reset the bounds of the **extent** and enclose the provided **locations**.
### copy `extent.copy()`
Copy the **extent** and its `north`, `south`, `east` and `west` values.
### toArray `extent.toArray()`
Returns a two-element array containing the **extent**'s [northwest](#Extent.northWest) and [southeast](#Extent.southEast) locations.
### Extent.fromString `MM.Extent.fromString(str)`
Parse a string in the format `"north,west,south,east"` into a new Extent object.
### Extent.fromArray `MM.Extent.fromArray(locations)`
Create a new Extent object from an array of [Location](#Location) objects.
## MM.Point
Point objects represent *x* and *y* coordinates on the screen, such as a [map's dimensions](#Map.dimensions) and the position of mouse or touch interactions.
```
new MM.Point(x, y)
```
Create a new Point object with **x** and **y** coordinates. `parseFloat()` is used to convert string values to numbers. The resulting object has `x` and `y` properties.
Point objects can be used with [pointLocation](#Map.pointLocation) to determine the [geographic coordinates](#Location) of a point on the screen inside a map. For instance:
```
// define the map's dimensions
var size = new MM.Point(640, 480);
// create a map without any layers or event handlers
var map = new MM.Map("map", [], size, []);
// zoom to San Francisco
map.setCenterZoom(new MM.Location(37.764, -122.419), 8);
// get the geographic coordinates of the bottom right corner
var southEast = map.pointLocation(size);
```
And vice-versa, you can use [locationPoint](#Map.locationPoint) to get the screen position of a geographic coordinate:
```
var oakland = new MM.Location(37.804, -122.271);
var point = map.locationPoint(oakland);
// do something with point.x and point.y
```
### Point.distance `MM.Point.distance(a, b)`
Compute the [Euclidian distance](http://en.wikipedia.org/wiki/Euclidean_distance) between two Point objects.
### Point.interpolate `MM.Point.interpolate(a, b, t)`
Compute the point on a straight line between points **a** and **b** at normal distance **t**, a number between `0` and `1`. (If `t == .5` the point will be halfway between **a** and **b**.)
## MM.Coordinate
Coordinate objects are used internally by ModestMaps to model the surface of the Earth in [Google's spherical Mercator projection](http://en.wikipedia.org/wiki/Google_Maps#Map_projection), which flattens the globe into a square, or *tile*. Coordinate objects represent points within that tile at different `zoom` levels, with `column` and `row` properties indicating their *x* and *y* positions, respectively. Each round number column and row within a zoom level represents a 256-pixel square image displayed in a ModestMaps [tile layer](#Layer).
```
new Coordinate(row, column, zoom)
```
### zoom `coordinate.zoom`
Coordinates are always expressed relative to a specific **zoom** level. At zoom `0`, the Earth fits into a single square tile, `Coordinate(0, 0, 0)`. With each increase in zoom, every tile is divided into 4 parts, so at zoom level `1` the Earth becomes 4 tiles; at zoom level `2` it becomes 16. Coordinates can be converted to different zoom levels with [zoomTo](#Coordinate.zoomTo).
### column `coordinate.column`
A Coordinate's `column` represents a tile's relative *x* position at its zoom level. At zoom `0` there is one column. With each increase in zoom, the number of columns doubles, so at zoom `1` there are two (`0 >= column < 2`), at zoom `2` there are four (`0 >= column < 4`), and so on.
### row `coordinate.row`
A Coordinate's `row` represents a tile's relative *y* position at its zoom level. At zoom `0` there is only one tile. With each increase in zoom, the number of rows doubles, so at zoom `1` there are two (`0 >= row < 2`), at zoom `2` there are four (`0 >= row < 4`), and so on.
### copy `coordinate.copy()`
Copy the **coordinate**'s `zoom`, `row` and `column` properties into a new **Coordinate** object.
### container `coordinate.container()`
Create a Coordinate object that contains **coordinate** by flooring its `zoom`, `column` and `row` properties. This is the actual "tile" coordinate.
### zoomTo `coordinate.zoomTo(zoom)`
Copy **coordinate** and adjust its `row` and `column` properties to match the new **zoom** level.
### zoomBy `coordinate.zoomBy(zoomOffset)`
Zoom **coordinate** by the the specified **zoom offset** and return a new Coordinate object.
### up `coordinate.up()`
Get the Coordinate above **coordinate**.
### right `coordinate.right()`
Get the Coordinate to the right of **coordinate**.
### down `coordinate.down()`
Get the Coordinate below **coordinate**.
### left `coordinate.left()`
Get the Coordinate to the left of **coordinate**.
### toKey `coordinate.toKey()`
Generate a string key for the **coordinate**, e.g. `"(1,1,5)"` (`"zoom,row,column"`).
### toString `coordinate.toString()`
Format the **coordinate** as a human-readable string, e.g. `"(5,4 @ 1)"` (`("row,column @ zoom")`)
### Pre-projecting
Coordinate are also useful for "pre-projecting" [locations](#Location). Because conversions between screen and geographic coordinates are more computationally expensive than conversions between screen and tile coordinates, you may wish to do the [Location to Coordinate](#Map.locationCoordinate) conversion once then do [Coordinate to Point](#Map.coordinatePoint) conversions subsequently. For example:
```
var map = new MM.Map("map", …);
var sfLocation = new MM.Location(37.764, -122.419);
var sfCoordinate = map.locationCoordinate(sfLocation);
// assuming there is an "sf" element, with CSS positon: absolute
var marker = map.parent.appendChild(document.getElementById("sf"));
map.addCallback("drawn", function() {
var point = map.coordinatePoint(sfCoordinate);
marker.style.left = point.x + "px";
marker.style.top = point.y + "px";
});
```
In this example, `map.coordinatePoint(sfCoordinate)` will be much faster than calling `map.locationPoint(sfLocation)` each time the map is redrawn. You probably won't notice the performance gain with one marker, but you certainly will with hundreds.
## MM.TemplatedLayer
The **TemplatedLayer** class provides a simple interface for making layers with templated tile URLs.
```
new MM.TemplatedLayer(templateURL [, subdomains])
```
Create a layer in which each tile image's URL is a variation of the **URL template** and optional list of **subdomains**.
You can learn more about templated tile URLs in the [Template](#Template) reference. Here are some examples:
```
var toner = new MM.TemplatedLayer("http://tile.stamen.com/toner/{Z}/{X}/{Y}.png");
var bing = new MM.TemplatedLayer("http://ecn.t0.tiles.virtualearth.net/tiles/r{Q}?" +
"g=689&mkt=en-us&lbl=l1&stl=h");
var osm = new MM.TemplatedLayer("http://tile.openstreetmap.org/{Z}/{X}/{Y}.png");
```
## MM.Layer
Map layers are where map imagery (including but not limited to tiles) gets rendered. The **Layer** class does all of the heavy lifting to determine which tiles are visible at any given moment, loads them if necessary, then adds them to the DOM and positions them on screen.
```
new MM.Layer(provider [, parent])
```
Create a new map layer that uses a **provider**, optionally specifying a custom **parent** element (or container). A layer's **provider** is an instance of the [MapProvider](#MapProvider) class, which converts [tile coordinates](#Coordinate) into image URLs. This example provides [Placehold.it](http://placehold.it/) URLs that list the tile coordinates:
```
var provider = new MM.MapProvider(function(coord) {
return "http://placehold.it/256x256&text=" +
[coord.zoom, coord.column, coord.row].join("/");
});
var layer = new MM.Layer(provider);
map.addLayer(layer);
```
The [Template](#Template) class simplifies generating image URLs for tile servers with popular template formats.
### getProvider `layer.getProvider()`
Get the layer's current provider.
### setProvider `layer.setProvider()`
Set the layer's current provider.
### destroy `layer.destroy()`
Destroy the layer, removing all of its tiles from memory and removing its **parent** element from the map.
### draw `layer.draw()`
Redraw the layer by loading, unloading, adding, removing, and repositioning tile images as appropriate. Changing the provider triggers a **draw**.
### requestRedraw `layer.requestRedraw()`
Request a layer redraw in 1 second. This works just like [Map.redraw](#Map.redraw).
## MM.MapProvider
Map providers convert [tile coordinates](#Coordinate) to image URLs. If your image tiles come in either [XYZ](#TemplateProvider-XYZ) or [quadkey](#TemplateProvider-Quadkey) formats, you should use the [TemplateProvider](#TemplateProvider) class.
```
new MM.MapProvider(getTileUrl)
```
**MapProvider** is an abstract class, meaning that it is meant to be [extended](#MM.extend). The constructor takes a function as its only argument, which is expected to return an image URL (or `null`) for a given [tile coordinate](#Coordinate). This example emulates the behavior of [Template](#Template) using a static URL template:
```
var provider = new MM.MapProvider(function(coord) {
return "http://tile.stamen.com/toner/{Z}/{X}/{Y}.png"
.replace("{Z}", coord.zoom)
.replace("{X}", coord.column)
.replace("{Y}", coord.row);
});
// Coordinate(row, col, zoom)
provider.getTile(new MM.Coordinate(1, 2, 3));
// returns: "http://tile.stamen.com/toner/3/2/1.png"
```
Map providers expose the following interface to [Layer](#Layer) objects:
### getTile `provider.getTile(tileCoord)`
Generates a tile URL or DOM element for the given **tile coordinate**. If the returned value is a string, an `
![]()
` element is created. Otherwise, if truthy, the return value is assumed to be a DOM element.
For instance, you could create a map provider that generates `