AppGeo-geo-f763e47/ 0000775 0001750 0001750 00000000000 12005347446 012753 5 ustar david david AppGeo-geo-f763e47/libs/ 0000775 0001750 0001750 00000000000 12005347446 013704 5 ustar david david AppGeo-geo-f763e47/libs/qunit/ 0000775 0001750 0001750 00000000000 12005347446 015044 5 ustar david david AppGeo-geo-f763e47/libs/qunit/qunit.js 0000664 0001750 0001750 00000124411 12005347446 016545 0 ustar david david /** * QUnit v1.4.0 - A JavaScript Unit Testing Framework * * http://docs.jquery.com/QUnit * * Copyright (c) 2012 John Resig, Jörn Zaefferer * Dual licensed under the MIT (MIT-LICENSE.txt) * or GPL (GPL-LICENSE.txt) licenses. */ (function(window) { var defined = { setTimeout: typeof window.setTimeout !== "undefined", sessionStorage: (function() { var x = "qunit-test-string"; try { sessionStorage.setItem(x, x); sessionStorage.removeItem(x); return true; } catch(e) { return false; } }()) }; var testId = 0, toString = Object.prototype.toString, hasOwn = Object.prototype.hasOwnProperty; var Test = function(name, testName, expected, async, callback) { this.name = name; this.testName = testName; this.expected = expected; this.async = async; this.callback = callback; this.assertions = []; }; Test.prototype = { init: function() { var tests = id("qunit-tests"); if (tests) { var b = document.createElement("strong"); b.innerHTML = "Running " + this.name; var li = document.createElement("li"); li.appendChild( b ); li.className = "running"; li.id = this.id = "test-output" + testId++; tests.appendChild( li ); } }, setup: function() { if (this.module != config.previousModule) { if ( config.previousModule ) { runLoggingCallbacks('moduleDone', QUnit, { name: config.previousModule, failed: config.moduleStats.bad, passed: config.moduleStats.all - config.moduleStats.bad, total: config.moduleStats.all } ); } config.previousModule = this.module; config.moduleStats = { all: 0, bad: 0 }; runLoggingCallbacks( 'moduleStart', QUnit, { name: this.module } ); } else if (config.autorun) { runLoggingCallbacks( 'moduleStart', QUnit, { name: this.module } ); } config.current = this; this.testEnvironment = extend({ setup: function() {}, teardown: function() {} }, this.moduleTestEnvironment); runLoggingCallbacks( 'testStart', QUnit, { name: this.testName, module: this.module }); // allow utility functions to access the current test environment // TODO why?? QUnit.current_testEnvironment = this.testEnvironment; if ( !config.pollution ) { saveGlobal(); } if ( config.notrycatch ) { this.testEnvironment.setup.call(this.testEnvironment); return; } try { this.testEnvironment.setup.call(this.testEnvironment); } catch(e) { QUnit.pushFailure( "Setup failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); } }, run: function() { config.current = this; if ( this.async ) { QUnit.stop(); } if ( config.notrycatch ) { this.callback.call(this.testEnvironment); return; } try { this.callback.call(this.testEnvironment); } catch(e) { QUnit.pushFailure( "Died on test #" + (this.assertions.length + 1) + ": " + e.message, extractStacktrace( e, 1 ) ); // else next test will carry the responsibility saveGlobal(); // Restart the tests if they're blocking if ( config.blocking ) { QUnit.start(); } } }, teardown: function() { config.current = this; if ( config.notrycatch ) { this.testEnvironment.teardown.call(this.testEnvironment); return; } else { try { this.testEnvironment.teardown.call(this.testEnvironment); } catch(e) { QUnit.pushFailure( "Teardown failed on " + this.testName + ": " + e.message, extractStacktrace( e, 1 ) ); } } checkPollution(); }, finish: function() { config.current = this; if ( this.expected != null && this.expected != this.assertions.length ) { QUnit.pushFailure( "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); } else if ( this.expected == null && !this.assertions.length ) { QUnit.pushFailure( "Expected at least one assertion, but none were run - call expect(0) to accept zero assertions." ); } var good = 0, bad = 0, li, i, tests = id("qunit-tests"); config.stats.all += this.assertions.length; config.moduleStats.all += this.assertions.length; if ( tests ) { var ol = document.createElement("ol"); for ( i = 0; i < this.assertions.length; i++ ) { var assertion = this.assertions[i]; li = document.createElement("li"); li.className = assertion.result ? "pass" : "fail"; li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); ol.appendChild( li ); if ( assertion.result ) { good++; } else { bad++; config.stats.bad++; config.moduleStats.bad++; } } // store result when possible if ( QUnit.config.reorder && defined.sessionStorage ) { if (bad) { sessionStorage.setItem("qunit-test-" + this.module + "-" + this.testName, bad); } else { sessionStorage.removeItem("qunit-test-" + this.module + "-" + this.testName); } } if (bad === 0) { ol.style.display = "none"; } var b = document.createElement("strong"); b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; var a = document.createElement("a"); a.innerHTML = "Rerun"; a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); addEvent(b, "click", function() { var next = b.nextSibling.nextSibling, display = next.style.display; next.style.display = display === "none" ? "block" : "none"; }); addEvent(b, "dblclick", function(e) { var target = e && e.target ? e.target : window.event.srcElement; if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { target = target.parentNode; } if ( window.location && target.nodeName.toLowerCase() === "strong" ) { window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); } }); li = id(this.id); li.className = bad ? "fail" : "pass"; li.removeChild( li.firstChild ); li.appendChild( b ); li.appendChild( a ); li.appendChild( ol ); } else { for ( i = 0; i < this.assertions.length; i++ ) { if ( !this.assertions[i].result ) { bad++; config.stats.bad++; config.moduleStats.bad++; } } } QUnit.reset(); runLoggingCallbacks( 'testDone', QUnit, { name: this.testName, module: this.module, failed: bad, passed: this.assertions.length - bad, total: this.assertions.length } ); }, queue: function() { var test = this; synchronize(function() { test.init(); }); function run() { // each of these can by async synchronize(function() { test.setup(); }); synchronize(function() { test.run(); }); synchronize(function() { test.teardown(); }); synchronize(function() { test.finish(); }); } // defer when previous test run passed, if storage is available var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-test-" + this.module + "-" + this.testName); if (bad) { run(); } else { synchronize(run, true); } } }; var QUnit = { // call on start of module test to prepend name to all tests module: function(name, testEnvironment) { config.currentModule = name; config.currentModuleTestEnviroment = testEnvironment; }, asyncTest: function(testName, expected, callback) { if ( arguments.length === 2 ) { callback = expected; expected = null; } QUnit.test(testName, expected, callback, true); }, test: function(testName, expected, callback, async) { var name = '' + escapeInnerText(testName) + ''; if ( arguments.length === 2 ) { callback = expected; expected = null; } if ( config.currentModule ) { name = '' + config.currentModule + ": " + name; } if ( !validTest(config.currentModule + ": " + testName) ) { return; } var test = new Test(name, testName, expected, async, callback); test.module = config.currentModule; test.moduleTestEnvironment = config.currentModuleTestEnviroment; test.queue(); }, // Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. expect: function(asserts) { config.current.expected = asserts; }, // Asserts true. // @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); ok: function(result, msg) { if (!config.current) { throw new Error("ok() assertion outside test context, was " + sourceFromStacktrace(2)); } result = !!result; var details = { result: result, message: msg }; msg = escapeInnerText(msg || (result ? "okay" : "failed")); if ( !result ) { var source = sourceFromStacktrace(2); if (source) { details.source = source; msg += '
Source: | ' + escapeInnerText(source) + ' |
---|
Expected: | ' + expected + ' |
---|---|
Result: | ' + actual + ' |
Diff: | ' + QUnit.diff(expected, actual) +' |
Source: | ' + escapeInnerText(source) + ' |
Source: | ' + escapeInnerText(source) + ' |
---|
return type | Number |
---|---|
syntax | $.geo.length( Object shape ( GeoJSON object ) ) |
usage |
|
The length method calculates the length of a basic GeoJSON geometry object and returns it in non-geodetic units. The basic shapes are Point, LineString and Polygon. If you are using geomap with its default map service, the length is in meters because the default projection is web mercator meters.
This function returns 0 for Point objects, the length of LineString objects and the perimeter of Polygon objects.
If the argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.getLength in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.bbox( Object shape ( GeoJSON object ) ) |
usage |
|
The bbox method calculates the smallest box that will contain all the positions in the passed-in shape. The shape can be any GeoJSON geometry object from Point to GeometryCollection.
The GeoJSON spec allows for each geometry type to have a bbox property. The $.geo.bbox method will honor that property and assume it is accurate. It will return the value of that property before attempting to calculate the bbox itself. If you wish to force $.geo.bbox to calculate the bbox, you will have to manually delete the bbox property from the geometry object.
var shape = {
type: "LineString", coordinates: [
[ -71, 40 ], [ -70.5, 41 ]
],
bbox: [ -71, 40, -70.5, 41 ]
};
var bboxFromProperty = $.geo.bbox(shape);
delete shape.bbox;
var calculatedBbox = $.geo.bbox(shape);
If the argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.getEnvelope in JTS.
return type | Array ( GeoJSON Polygon ) |
---|---|
syntax | $.geo.polygonize( Array bbox ( GeoJSON bounding box ) ) |
usage |
|
The polygonize method creates a new Polygon with an outer ring that matches the rectangle covered by the bbox. The Polygon is closed and will have five coordinates.
This function is a simplification/adaptation of the Polygonizer class in JTS. While the JTS object operates on the line work of geometry objects, this function operates on bounding boxes.
The $.geo namespace has a property named proj which is a JavaScript object having four functions: fromGeodetic, fromGeodeticPos, toGeodetic, and toGeodeticPos. These four functions allow all $.geo static bbox/geometry functions, geomap widget properties, geomap widget events & geomap widget methods (collectively referred to as plugin functions from now on) to work in geodetic (lon, lat) coordinates.
Consider the following example:
jQuery Geo will first convert the points to map units, a process called projection. jQuery Geo needs projected coordinates to properly calculate some relationships between shapes. After converting the points, $.geo.distance can then calculate the distance between them. This distance will be in meters because the default map service is web mercator meters.
In order to work directly in map units, you used to have to set $.geo.proj to null. While still valid, you no longer have to do this. You can leave $.geo.proj set to, e.g., web mercator meters and send either projected web mercator GeoJSON geometry objects or geodetic (lon, lat) objects to $.geo functions. The return value will depend on the type of arguments passed.
The geomap widget keeps track of how you set options. For example, if you set the map's center using geodetic coordinates, geodetic coordinates will then be returned when you ask for the center later. They will also be used when the geomap widget triggers events such as bboxchange or shape.
The default $.geo.proj object comes pre-built with functions that quickly convert between geodetic coordinates and web mercator meters so you can start using lon, lat right away with the default OpenStreetMap-based tiles. If your map service uses a different projection you can roll your own $.geo.proj object and continue to have the option to use geodetic coordinates. Read Other projections below for information on how to do that.
The two base functions, fromGeodetic and toGeodetic, can take and return: a single bounding box, a single GeoJSON position (Point.coordinates), an array of GeoJSON positions (MultiPoint.coordinates or LineString.coordinates), an array of arrays of positions (MultiLineString.coordinates or Polygon.coordinates) or an array of arrays of arrays of positions (MultiPolygon.coordinates). In other words, the $.geo.proj functions convert the coordinates property of any of the GeoJSON geometry types. For example, you can use the following to convert the position contained in a GeoJSON point object:
var geodeticPoint = {
type: "Point",
coordinates: [ -73.5100, 41.3500 ]
};
var projectedCoords = $.geo.proj.fromGeodetic( geodeticPoint.coordinates );
However, a LineString's coordinates property is an array of positions which you can also pass to the fromGeodetic method to get an array converted positions
var projectedLineStringCoords = $.geo.proj.fromGeodetic( geodeticLineString.coordinates );
To convert a set of projected GeoJSON positions back to web mercator, call toGeodetic.
var geodeticLineString = {
type: "LineString",
coordinates: $.geo.proj.toGeodetic( projectedLineStringCoords )
};
The $.geo.proj object allows you to use geodetic coordinates with whichever coordinate system or projection you want in any plugin function. If you pass a geodetic Polygon to $.geo.bbox, the returned bounding box will be in geodetic coordinates.
If you are working in a projection other than the default web mercator meters but still wish to use geodetic coordinates, you will have to update the $.geo.proj object so that it can convert between geodetic coordinates and ones in your projection.
However, if you don't need to work in longitude, latitude at all, you can ignore $.geo.proj and use projected coordinates throughout your project. You also still have the option to set $.geo.proj to null for completeness and remind yourself that you are limited to projected coordinates. If you are working in Massachusetts Mainland State Plane meters for example, you can pass a Polygon of that projection to any plugin function and you will get results in that projection. This includes all $.geo functions and geomap options & methods.
$.geo.proj = null; // not required but reminds us that jQuery Geo can't use lon, lat in this project
$('map').geomap( {
tilingScheme: null,
bboxMax: [ 31790, 790195, 337250, 961865 ],
bbox: [ 235644, 894775, 237775, 898523 ],
services: [ /* service object that supports MA State Plane */ ]
} );
jQuery Geo uses the four $.geo.proj functions throughout to convert between geodetic and projected coordinates. However, fromGeodeticPos and toGeodeticPos handle the conversion of individual GeoJSON positions and are used by fromGeodetic and toGeodetic. You can extend $.geo.proj with your own implementations of fromGeodeticPos and toGeodeticPos to change the internal projection used by all plugin functions and still use geodetic (lon, lat) coordinates as arguments and return values.
Please note that you must extend $.geo.proj with new functionality instead of replacing it wholesale with a new object. You need to keep the original fromGeodetic and toGeodetic functions intact.
$.extend($.geo.proj, {
fromGeodeticPos: function( coordinate ) {
var converted = [];
// convert the GeoJSON lon/lat position to MA State Plane
return converted;
},
toGeodeticPos: function( coordinate ) {
var converted = [];
// convert the GeoJSON MA State Plane position to lon/lat
return converted;
}
});
$('map').geomap( {
tilingScheme: null,
// notice that with a custom $.geo.proj object,
// these properties can be in geodetic coordinates
bboxMax: [ -73.5100, 41.3500, -69.8600, 42.8900 ],
bbox: [ -71.098709, 42.330322, -71.072617, 42.351608 ],
// the services option must still be in map coordinates
// see geomap's services property docs for more info
services: [ /* service object that supports MA State Plane */ ]
} );
Implementing custom from/to GeodeticPos functions is currently beyond the scope of this documentation but reading up on Proj4js is a good start.
return type | Number |
---|---|
syntax | $.geo.width( Array bbox ( GeoJSON bounding box ) |
usage |
|
The width method returns the true width of a bbox in non-geodetic units. If you are using geomap with its default map service, the width is in meters because the default projection is web mercator meters.
This function is similar to Envelope.getWidth in JTS.
return type | Number |
---|---|
syntax | $.geo.area( Object shape ( GeoJSON object ) ) |
usage |
|
The area method calculates the area of a basic GeoJSON geometry object and returns it in non-geodetic units. The basic shapes are Point, LineString and Polygon. If you are using geomap with its default map service, the area is in square meters because the default projection is web mercator meters.
While you can pass any basic geometry, this function returns the area of Polygon objects and 0 for objects of other shape types.
If the argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.getArea in JTS.
return type | Number |
---|---|
syntax | $.geo.height( Array bbox ( GeoJSON bounding box ) |
usage |
|
The height method returns the true height of a bbox in non-geodetic map units. If you are using geomap with its default map service, the height is in meters because the default projection is web mercator meters.
This function is similar to Envelope.getHeight in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.recenter( Array bbox ( GeoJSON bounding box ), Array (GeoJSON position) ) |
usage |
|
The recenter method creates a new bbox with the same width and height as the original but moving the center to a new location.
This function is not defined in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.expandBy( Array bbox ( GeoJSON bounding box ), Number dx, Number dy ) |
usage |
|
The expandBy method creates a new bbox with the same center as the original but having a width and height that is modified by the dx and dy arguments respectively.
The dx and dy arguments are non-geodetic map units. If you are using geomap with its default map service, these are in meters because the default projection is web mercator meters. If, for example, you are working in a different projection such as NAD83 / New Jersey feet, this function will expand or contract the bbox by feet.
The dx and dy arguments can be positive, negative or zero and will modify the width or height of the bbox accordingly.
This function is similar to Envelope.expandBy in JTS.
return type | Object ( GeoJSON Point ) |
---|---|
syntax | $.geo.centroid( Object shape ( GeoJSON object ) ) |
usage |
|
The centroid method calculates the center of mass for the passed-in basic GeoJSON geometry object. The basic geometry types are Point, LineString and Polygon.
Technically, only Polygons can be considered to have mass. However, a centroid can be calculated for other geometry types. This method operates on LineStrings as if they were closed polygons and the centroid will likely not lie along the line. The centroid of a Point is a clone of the Point.
If the argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.getCentroid in JTS.
return type | Number |
---|---|
syntax | $.geo.distance( Object shape1 ( GeoJSON object ), Object shape2 ( GeoJSON object ) ) |
usage |
|
The distance method calculates the distance between two basic GeoJSON geometry objects and returns it in non-geodetic units. The basic shapes are Point, LineString and Polygon. If you are using geomap with its default map service, the distance is in meters because the default projection is web mercator meters.
If either argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.distance in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.reaspect( Array bbox ( GeoJSON bounding box ), Number ratio ) |
usage |
|
The reaspect method creates a new bbox with the same center as the original but forcing the ratio of width to height to a specific value.
If the original width is greater than the original height (think a landscape printout) then the width of the new bbox will be the same as the original but the new height will change to fit the ratio. If the original height is greater than the original width (think a portrait printout) then the new bbox height will remain unchanged but the width will to fit the ratio.
This function is not defined in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.scaleBy( Array bbox ( GeoJSON bounding box ), Number scale ) |
usage |
|
The scaleBy method creates a new bbox with the same center as the original but having a width and height that are both multiplied by the scale argument.
The scale argument is a percentage increase or decrease. This means that supplying 2 will increase the size of the bbox by 200%, which if thinking in terms of a map's view, would zoom out. Supplying .5 will decrease the size of the bbox to half its original size.
The scale argument must be greater than zero.
This function is not defined in JTS.
return type | Array ( GeoJSON bounding box ) |
---|---|
syntax | $.geo.include( null | Array bbox ( GeoJSON bounding box ), Array position ( GeoJSON position ) | Array bbox ( GeoJSON bounding box ) ) |
usage |
|
The include method expands a bbox to include either a coordinate or another bbox. The expanded bbox is returned.
If the first argument is null or undefined, the result is a new bbox and will contain the second argument.
For efficency, if the first argument is a valid bbox, it is modified in-place and a reference is returned.
If the second argument is not a coordinate or bbox, this function returns the first argument.
This function is similar to Envelope.expandToInclude in JTS.
return type | Object ( GeoJSON Point ) |
---|---|
syntax | $.geo.pointAlong( Object shape ( GeoJSON object ), Number percentage ) |
usage |
|
The pointAlong method calculates a Point that lies a given fraction along the passed-in basic GeoJSON geometry object. The basic geometry types are Point, LineString and Polygon. A percentage of 0.0 returns the first Point; a percentage of 1.0 returns the last.
Technically, only LineStrings can be used properly in this calculation. However, pointAlong can be calculated for other geometry types. With Point objects, pointAlong will always return a copy of the original Point. For Polygon objects, pointAlong operates on the Polygon's perimeter (outer ring), i.e., myPolygon.coordinates[0]. For Polygons, percentage values of 0.0 and 1.0 will return the same Point.
If the argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to LineSegment.pointAlong in JTS.
The $.geo namespace contains all geometry functions implemented in the plugin and an object having the plugin's four projection functions.
The $.geo namespace has a property named proj which is a JavaScript object having four functions: fromGeodetic, fromGeodeticPos, toGeodetic, and toGeodeticPos. These four functions allow all $.geo static bbox/geometry functions, geomap widget properties, geomap widget events & geomap widget methods (collectively referred to as plugin functions from now on) to work in geodetic (lon, lat) coordinates.
Geometry isn't much fun if you can't do anything with it. These functions help you analyze and manipulate bounding boxes and GeoJSON geometry objects. You call them directly from the $.geo namespace:
$.geo.distance( point1, point2 )
Except for a few name changes and switching from an object-oriented API to a function-based one, jQuery Geo attempts to follow the names and behavior of the Java Topology Suite (JTS), which is the de-facto standard for geometry library APIs. JTS itself is an implementation of the OGC Simple Features specification but has made design decisions that improve the API for developers. The most notable of which is having Envelope (called bbox in jQuery Geo and GeoJSON) be its own class type.
These functions operate on GeoJSON bounding box array, i.e., a JavaScript array having four values:
These functions operate on GeoJSON geometry objects: Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, and GeometryCollection. They do not operate on Feature or FeatureCollection objects, you have to call these functions on the geometry properties of Feature objects.
The geometry functions allow you to analyze relationships between geometries such as their distance apart as well as obtain information about them such as bounding box and center point, called the centroid. This section will eventually expand to cover all of the important spatial operations available in the Java Topology Suite.
return type | Array ( GeoJSON position ) |
---|---|
syntax | $.geo.center( Array bbox ( GeoJSON bounding box ) ) |
usage |
|
The center method calculates the center of a bbox and returns it as a GeoJSON position.
It operates on bounding boxes and should not be confused with the centroid function, which operates on GeoJSON geometry objects.
This function is called Envelope.centre in JTS (I assume because JTS is built in British Columbia).
return type | Boolean |
---|---|
syntax | $.geo.contains( Object shape1 ( GeoJSON object ), Object shape2 ( GeoJSON object ) ) |
usage |
|
The contains method determines if the first basic GeoJSON geometry completely contains a second one. The basic shapes are Point, LineString and Polygon however Point and LineString geometries cannot contain other geometries so the only situation that has a possibility of returning true is when the first argument is a Polygon.
If either argument is not a basic GeoJSON geometry object, this function returns undefined.
This function is similar to Geometry.contains in JTS.
We keep some plugin design decisions here.
The geomap widget uses the same widget factory that all other jQuery UI and jQuery Mobile widgets use. Like jQuery Mobile, we include a copy of jquery.ui.widget.js in the project. While this adds 3k to the final compressed build it allows us to easilly follow the patterns designed by UI and better integrate into the jQuery plugin community.
$.widget( "geo.geomap", { } );
The public properties bbox, bboxMax and center do not always match the internal state of the map widget. In fact internally, geomap only tracks center and pixelSize. The bbox and bboxMax properties are calculated based on the current or max center and pixelSize. In the code, you will see two properties each for each of these. One is public, the other is private. For center, the internal position (_center) is always in internal map units (web mercator meters by default) even if the developer sets the public bbox or center by longitude & latitude.
You may notice that we override jQuery UI's _createWidget function in order to capture the options passed in by the user. Let us know if there's a better way to do that. At the end of _create, we iterate over the passed options and set certain internal state values before creating services and refreshing the map. This insures that we handle supplied bbox or center properly. Since bbox and center can potentially conflict, only supply one. If both are supplied the behavior is technically undefined but currently center will override bbox.
When you append a shape to the map, the geomap widget will cache the shape's bounding box (in non-geodetic coordinates) for faster searches when you call find. When you remove a shape from the map, the cache will be cleared. When you use the $.geo.bbox method on a shape after it has been appended to the map, the cached bounding box will be returned.
// the bbox of an appended shape is cached while it is on the map
var calculatedBbox = $.geo.bbox(shape);
$("#map").geomap("append", shape);
var cachedBbox = $.geo.bbox(shape);
$("#map").geomap("remove", shape);
var calculatedAgain = $.geo.bbox(shape);
jQuery Geo caches the bbox using jQuery's data function under the name geoBbox. Though I can't think of a reason to do so, you can remove this cache by calling removeData directly on the shape object:
$.removeData(shape, "geoBbox");
jQuery Geo's caching will not alter your geometry object so you don't have to worry about unintentionally storing or sending extra data to a server.
Apart from the jQuery UI widget factory, geomap includes a couple external libraries.
We've found this to be a very stable mousewheel special event plugin and are using it to handle mouse wheel interaction. This plugin's license comment and source are included intact in the minified releases of jQuery Geo.
We include parts of Google's excanvas library to support graphic drawing in IE6-8. Only functions required to support jQuery Geo's feature list are included. This library's license comment and source are included intact in the non-minified releases of jQuery Geo. The license comment and partial source are included intact in the minified releases of jQuery Geo.
jQuery Geo includes a snapshot of jsRender, the next-generation templating engine from the jQuery team. This is used for measure text templates and src string templates.
Developers can set the services array used by the geomap widget. When it comes time to draw map images, the geomap widget uses an internal _serviceTypes object. The object contains one property for each service type geomap supports, e.g., tiled and shingled. The type property on each service object determines which serviceType object geomap uses to refresh the service. The following code snippet is a simplification of the relationship.
options: {
services: [
{
"class": "osm",
type: "tiled"
/* ,... */
}
]
},
_serviceTypes: {
tiled: {
refresh: function (map, service) {
}
/* ,... */
}
}
In the future the _serviceTypes property will be public and developers can extend the service types geomap supports.