Example provided by Juliana Williams and Andreas Neumann (see history at the end of the page)
This SVG file structure and related ECMAScripts should assist authors of "SVG only" webmapping applications in creating 2D map navigation tools. For an introduction on why you should at the current time consider writing SVG only webmapping applications, see the selectionList tutorial.
The SVG File and ECMAScripts are free to use. If you do any substantial improvements, please send back your improvements to the author. The GUI elements of carto.net are licensed under the terms of the LGPL license and you need to distribute the license with your code. Additionally, you should create a link to carto.net in your project's "about page" or impressum. If you plan to use the GUI elements in a commercial product, please check back with the author of the GUI elements to investigate arrangements. The original URL for the navigation tools is https://old.carto.net/papers/svg/navigationTools/.
Documentation
Features
- zoom in and zoom out with buttons and fixed steps
- continuous zooming with zoom slider
- button to go back to full view
- button for re-defining map center in main map
- manual zooming with dragging a rectangle in the main map
- manual panning with mouse-down and dragging in the main map
- linked reference map shows current map extent and allows repositioning
- coordinate display
- display of map extent (width and height)
- zoom or pan modes for repeatedly using the same mode
- the new map extent can be set by script (method of the map object)
- history of map extents is tracked, user can go back and forth in list of previous map extents
- cursors give feedback to user-actions, e.g. indicate zoom or pan mode (note: does not work in ASV3)
- a crosshair can highlight point positions in both the main map and the reference map
- various tests: point within map extent, rectangle within map extent, rectangle overlaps with map extent
Dependencies on external files and functions
- navigation.js:
- all of the objects and functions in this file are necessary
- mapApp.js:
- all of the objects and functions in this file are necessary
- helper_functions.js:
- all the global variables at the top of the file
- function toPolarDir()
- function toPolarDist()
- function toRectX()
- function toRectY()
- function leftOfTest()
- function intersect2lines()
- function formatNumberString()
- function statusChange()
- function scaleObject()
- function getTransformToRootElement()
- timer.js:
- all of the objects and functions in this file are necessary
- slider.js:
- all of the objects and functions in this file are necessary
- button.js:
- all of the objects and functions in this file are necessary
- checkbox_and_radiobutton.js:
- all of the objects and functions in this file are necessary
Additional Requirements
Note that any map data that you use in this environment has to be y-axis inverted. In typical GIS situations higher y(or up)-values are farer to the north (top) whereas in SVG its the opposite. Changing your data is relatively easy: use the original coordinate system and multiply each up-value with minus 1. Our Shapefile to SVG converter does this inversion for you, so does postgis.refractions.net Postgis. It is not recommended to flip the entire map using a transform attribute, since you would also flip text labels.
Step by Step Instructions
Step 1: Copy of the initial file structure
Copy all of the above .js files to your local disc. Additionally, copy the files index.svg, relief.jpg and relief_small.jpg (data source: Yosemite National Park website) to your local disc to get a working starter copy. You may later delete the .jpg files after you added your own data. Next, adjust the relative paths to the external javascript files in the script-tags (after the svg-root element) in the file index.svg. We will use the file 'index.svg' as a starter to fill in our own data. Please do not remove any elements containing id's in this file. Otherwise the scripts aren't guaranteed to work any more. Most Elements without an id-attribute are optional and may be removed. Now, open the file 'index.svg' and make sure the prototype works with the initial settings (Yosemite National Park).
Step 2: Adjust the coordinate systems
The file index.svg uses 3 different coordinate systems. The outermost coordinate system is device oriented (screen pixels) and should be adjusted to your needs. It is defined in the svg root element (line 4) in the viewBox attribute. (If you don't know the concept of the viewBox coordinate systems, please check with the www.w3.org/TR/SVG11/coords.html#ViewBoxAttribute SVG specification, chapter 7.7) In the same element we define the width and height to 100% and disable zooming and panning (zoomAndPan="disable"), since these functions will be replaced by our own functions. If you design for regular desktops, we recommend that you more or less keep the screen oriented coordinate system as we defined it in the svg root element. Please note, if you considerably change the screen oriented coordinate system, you will also need to adjust the size of the symbols later in the file to reflect your coordinate system changes.
Figure 1: Nested coordinate system principle
The second coordinate system is the coordinate system of the main map window. We define it within a nested <svg /> element. This coordinate system is defined in "real world" units, e.g. meters or degrees. In our example we defined the coordinate system in meters, reflecting UTM zone 11 coordinates. Note that in our viewBox coordinate system the y-axis is inverted, since map coordinate systems usually run opposite to the SVG coordinate system. For your own map, search for the line starting with <svg id="mainMap" ... and adjust the viewBox, width, height, x and y attributes to reflect your coordinate system and placement of the map within your screen coordinate system. Please note, that for the script to work correctly, we assume that the ratio of the outer width and height of the mainMap is the same as the width and height defined in the viewBox in real world coordinates.
The third coordinate system is internally the same as the main map window coordinate system, which means that the viewBox attribute of the referenceMap should be the same as in the mainMap. Search for the line starting with <svg id="referenceMap" ... and adjust the x, y, width, height and viewBox attributes to match your layout and map coordinate system.
Please note that the script is designed in a way that you need to first define the maximum viewBox. If you want to initally start the application with an already zoomed in viewBox, you should still fill in the full values in the initial SVG file and later call the mainMap.setNewViewBox() method as described below.
Step 3: Adding static geometry to the map and reference map
In order to verify that our tool works correctly, it is useful to add some simple base geometry (raster or vector) both to our main map and the reference map. The geometry within the reference map should be very basic and generalized and serves only as a basic orientation. It should be small in filesize and need not be very accurate. Within the main map, you may place single elements (e.g. image or path) or whole groups within the group with the id "mainMapGroup". Please do not place them outside of this group or the panning tool will not work. You should bear in mind, that our coordinate system inverts the y-axis. If you convert from GIS data you should add a minus sign in front of the y-coordinates. Our Arcview Shapefile to SVG converter does this for you. Alternatively, to quickly see any results, you could use a georeferenced raster image (jpeg or png) as it can be exported from any GIS system. You may consult the existing geometry in our Yosemite map as a reference. In order to toggle layer visibility, it is necessary to set a unique id to the group or elements within the main maps. (see step 6)
Step 4: Adjusting the init function in the javascript
Next we'll have a look into the script section of the file index.svg. The two global variable definitions as listed here need to stay there, otherwise the script is not guaranteed to work. Within the init function, the two lines var dynamicLayers = new Array(); and var digiLayers = new Array(); need to stay there. These are currently empty arrays that can later be used, if you want to add dynamic layers (loaded from a database) or editable layers for digitizing. Currently, we'll leave them as empty arrays, that are handed over to the map object (mainMap) defined in the next line. The map object holds various data on the map and also enables the zooming and panning tools. As parameters we send the following data:
Constructor of map object in order of the parameters to be passed over:
- mapName (string): id of the mainMap (nested svg)
- maxWidth (number, viewBox coordinates): maximum mapWidth defined in the inner viewBox coordinates (map units)
- minWidth (number, viewBox coordinates): minimum mapWidth defined in the inner viewBox coordinates (map units)
- zoomFact (number): a zoomStep factor (between 0 and 1), the zoomStep factor defines how much we'll zoom in and out when pressing the plus/minus buttons. A value of 0.6 means, that after zooming in, the next map extent is 60% of the previous extent.
- nrDecimals (number, integer): the number of decimals to be displayed or used during digitizing
- epsg (number, integer): the epsg projection nr of the map, this can be used to build URL strings for loading data from OGC services or spatial databases, you can use any number if you don't plan to use the epsg code
- units (string): a string containing the map units (e.g. "m" for meters or String.fromCharCode(176) for degrees). You may hand over an empty string ("") if you don't want to display the map units
- unitsFactor (number): a factor that can be used to add a factor when outputting coordinates on mouse move, can be used e.g. to convert feet to meter or vice versa. Use a factor of 1 if you don't use different units
- showCoords (boolean): true|false, defines whether you want to use the showCoordinates function to display coordinates on mouse-move
- coordXId (string): the id of the text element for displaying the east values
- coordYId (string): the id of the text element for displaying the north values
- dynamicLayers (Array of strings): an array containing group ids of dynamic layers to be loaded from a database; you may hand over an empty array, if you do not want to load data from databases
- digiLayers (Array of strings): an array containing digitizing layers (currently empty)
- activeDigiLayer (string): the id of the active digitizing layer (currently an empty string)
- zoomRectAttribs (Array of literals with presentation attributes): presentation attributes defining the look of the zoom rectangle used in manual zooming; note that stroke-width and stroke-dasharray attributes are interpreted relative to the current map width, note that the syntax of the stroke-dasharray attribute is very strict (stricter than the specification, only "," are allowed as separators) since we use a relative primitive split mechanism for splitting the values; example: var zoomRectStyles = {"fill":"none","stroke":"crimson","stroke-width":0.002,"stroke-dasharray":"0.012,0.002"};
- highlightAttribs (Array of literals with presentation attributes): presentation attributes defining the look of the crosshair lines for highlighting point features; should at least contain a stroke and stroke-width attribute, note that stroke-width and stroke-dasharray attributes are interpreted relative to the current map width, note that the syntax of the stroke-dasharray attribute is very strict (stricter than the specification, only "," are allowed as separators) since we use a relative primitive split mechanism for splitting the values; example: var highlightStyles = {"stroke":"crimson","stroke-width":0.002};
- dragRectAttribs (Array of literals with presentation attributes): presentation attributes defining the look of the dragable rectangle indicating the current map extent in the reference map; should at least contain either a stroke or fill attribute, note that stroke-width and stroke-dasharray attributes are interpreted relative to the current map width, note that the syntax of the stroke-dasharray attribute is very strict (stricter than the specification, only "," are allowed as separators) since we use a relative primitive split mechanism for splitting the values; example: var dragRectStyles = {"fill":"lightskyblue","fill-opacity":0.5};
- refmapName (string): the id of the linked reference map
- dragSymbol (string): the id of the symbol element that is displayed when the user zooms in very far, when reaching a certain threshold level this symbol is displayed in addition to the rectangle (that would be probably too small to be salient)
- symbolThreshold (number, viewBox units): the threshold value defined in viewBox units (width of the drag rectangle), if the drag rectangle is smaller than this treshold, the dragSymbol will be displayed
Example:
//define some styles for the map object
var zoomRectStyles = {"fill":"none","stroke":"crimson","stroke-width":0.002,"stroke-dasharray":"0.012,0.002"};
var highlightStyles = {"stroke":"crimson","stroke-width":0.002};
var dragRectStyles = {"fill":"lightskyblue","fill-opacity":0.5};
myMainMap = new map("mainMap",64000,640,0.6,0,26911,"m",1,true,"coordX","coordY",dynamicLayers,digiLayers,"",zoomRectStyles,highlightStyles,dragRectStyles,"referenceMap","myDragCrossSymbol",4750);
In the next line we'll invoke the zoomSlider. We add the slider object instance as a property of the myMapApp object instance to avoid more global variables. We'll hand over the following parameters:
Constructor of slider object in order of the parameters to be passed over:
- x1: x coordinate of the slider start point
- y1: y coordinate of the slider start point
- value1: the value of the slider start point (the minimum width at maximal zoom in)
- x2: x coordinate of the slider end point
- y2: y coordinate of the slider end point
- value2: the value of the slider end point (the maximum width at full view)
- startVal: the slider start value (in our case myMainMap.origWidth)
- sliderGroupId: the id of the group where we will place the slider (in our case mapZoomSlider, part of the group containing the navigation tools)
- sliderColor: the color of the slider line (defined verbally or in rgb)
- visSliderWidth: the width of the slider line
- invisSliderWidth: the width of an invisible slider line receiving the slider events (for very thin slider lines, the width should be considerably bigger)
- sliderSymb: the id of a slider symbol (in our case "sliderSymbol")
- functionToCall: the function or object to be called when the slider value was changed (in our case the "myMapApp.refMapDragger" object instance)
- mouseMoveBool: a boolean flag indicating if we want instant feedback while moving the slider or no (in our case true).
Example:
myMapApp.zoomSlider = new slider(710,70,myMainMap.minWidth,710,170,myMainMap.maxWidth,myMainMap.maxWidth,
"mapZoomSlider","dimgray",2,10,"sliderSymbol","myRefMapDragger.resizeDragger",true);
Next you need to reposition or adapt your navigation tool buttons to fit in your map layout. All buttons make use of the button object. They are created per script. Some of the buttons are implemented as simple "button" objects, some of them are "switchbutton" objects. For details of the button properties and methods please see the following documentation. You can adapt the look and feel of the button and symbol instances using presentation attributes or CSS styles. All symbol definitions are implemented with <symbols /> (residing in the <defs /> section). Each button also needs an empty group in the DOM hierarchy where the new button geometry can be appended. This empty group needs a unique id which has to match the parameter one in the button constructor. In our example, look for the group after the XML comment line <!-- this group holds symbol instances for navigation tools -->. To reposition all buttons as a whole group you may add transform attributes on the parent group of the button groups (e.g. transform="translate(10 10)"). Please note that you should change the button settings with care. You should only adapt the position, width and styles of the button, and not the related function calls or ids, otherwise the navigation functions won't work. If you want to delete one button, it is better to set the display or visibility of that group to "none" or "invisible", otherwise you would have to modify the navigation scripts.
myMapApp.buttons = new Array();
This line creates a new array in our global "myMapApp" object instance to hold all references to the zoom and pan buttons.
Constructor of button object see button documentation.
Example:
//button styles, adopt the style settings to match your needs
var buttonTextStyles = {"font-family":"Arial,Helvetica","fill":"dimgray","font-size":10};
var buttonStyles = {"fill":"white"};
var shadeLightStyles = {"fill":"rgb(235,235,235)"};
var shadeDarkStyles = {"fill":"dimgray"};
//button instance creation
myMapApp.buttons["zoomIn"] = new button("zoomIn","zoomIn",zoomImageButtons,"rect",undefined,"magnifyerZoomIn",705,47,20,20,buttonTextStyles,buttonStyles,shadeLightStyles,shadeDarkStyles,1);
Note that we use both button and switchbutton objects that have slightly different constructors and behaviour. Note the way how we create the Array of Literals defining the presentation attributes of the button look.
myMainMap.checkButtons();
After creating the buttons we call the .checkButtons() method of the myMainMap object instance. This method analyzes the current map extents and disables/enables buttons. In some situations buttons should not be active. As an example, if the map is in full view, the "zoomOut", "panManual" and "recenterMap" buttons are deactivated. This method is called after each change of the map extent.
The last line calls the function loadProjectSpecific(). This function is always called, after resetting the map extent, e.g. after zooming and panning. In this function you can react to the changed map extent. In our example we reset the numbers indicating width and height of the map extent and change the line-width of the national park boundary to a fraction of 0.005 of the current map extent. If you remove the park boundary from the mainMap layers, you should also remove the last line in this function, otherwise you will get error messages. If you dynamically load map layers from databases or webservices, you can use this function to update the map geometry. This is described in the tutorial Dynamic Loading of Vector Geodata for SVG Mapping Applications Using Postgis, PHP and getURL()/XMLHttpRequest().
You should now test the functionality of the zoom and pan tools again. If you receive error messages, or something behaves strange, please check back with the instructions above.
Step 5: Adjusting checkBoxes to toggle layer visibility
In a next step we want to toggle the visibility of our map layers. Within "index.svg" search for the section containing the checkboxes. You should find something similar to the following:
<!-- control map layer visibility with checkBoxes -->
<g transform="translate(590 225)" id="checkBoxes">
<text font-family="Arial,Helvetica" fill="dimgray" font-size="18px" font-weight="bold" x="-10" y="0" pointer-events="none">Map Layer Controls</text>
<!-- the checkbox geometries will be added here -->
</g>
This is the group where you should place the checkBoxes that will be created by script. Of course you should adjust the transform attribute of the group element. Next, have a look at the script section (function init) and look for the following lines:
//create checkbox array
myMapApp.checkBoxes = new Array();
//labeltext styles
var labeltextStyles = {"font-family":"Arial,Helvetica","fill":"dimgray","font-size":15};
//create individual checkboxes
myMapApp.checkBoxes["park_boundary"] = new checkBox("park_boundary","checkBoxes",0,20,"checkBoxRect","checkBoxCross",true,"Park Boundary",labeltextStyles,12,6,undefined,toggleMapLayer);
myMapApp.checkBoxes["ShadedRelief"] = new checkBox("ShadedRelief","checkBoxes",200,20,"checkBoxRect","checkBoxCross",true,"Shaded Relief",labeltextStyles,12,6,undefined,toggleMapLayer);
First, you create an array for checkBox elements in the global myMapApp object instance. Next you define the styles, similar to what we have discussed above, and finally you add checkBox instances following the instructions at the checkbox and radiobutton tutorial.
Step 6: Final layout and styling
In this last step you need to work on the styling of the map layout. Simply replace all the fill, stroke, opacity, font-attributes, etc. as you like. Next to these XML attributes you might want to adjust positions of layout elements and add map titles, imprint, data sources, etc. Note that it is easier to move elements in groups, e.g. <g transform="translate(50 100)"> For positioning elements and testing the functionality of the navigation tools it is recommended to use xml.apache.org/batik Apache Batik since it displays the viewBox coordinates in the status bar of the squiggle browser. Additionally, it offers usually more meaningful error messages than other browsers and it features a js script debugger.
Constructors
See in the section above (step 4).
Selected Useful Methods of the map Object and Other Functions
- .setNewViewBox(xmin,ymin,xmax,ymax,history):
resets the map extent to your new given map extent. As parameters you define the two corners as number values. Note that you should use the map coordinate system (most of the time positive values, on the northern hemisphere), which means that ymin is "bottom of the map" and "ymax" is "top of the map". If your defined rectangle does not match the ratio of the map it will be changed to fully contain your given rectangle and match the given width/height ratio of the main map. The method changes the map extent of the mainMap and also resets the position of the dragging rectangle in the reference map. The last parameter (history) takes the values true|false and indicates whether that given map extent should be stored in the history of map extents.
- .calcCoord(evt):
calculates map coordinates from the original evt.clientX/evt.clientY coordinates. As parameters you pass over the evt object that also holds the coordinate values where the evt occured. The result is a literal containing the east value ("x") and the north value ("y").
- .pointTestWithin(xcoor,ycoor):
checks if the given coordinate is within the current map extent, returns a boolean value (true|false). Note that the ycoor should be given in the original map coordinate system, not in the inverted one. It will be inverted internally in the method to match the viewBox coordinate system.
- .bboxTestWithin(SVGRect):
checks if the given SVGRect is completely within the current map extent, returns a boolean value (true|false). The parameter is of type SVGRect, it can be returned e.g. by calling the method element.getBBox(). The SVGRect has to be in the same coordinate system like the content of myMainMap.
- .bboxTestOverlaps(SVGRect):
checks if the given SVGRect overlaps with the current map extent, returns a boolean value (true|false). The parameter is of type SVGRect, it can be returned e.g. by calling the method element.getBBox(). The SVGRect has to be in the same coordinate system like the content of myMainMap.
- .highlightPosition(xcoor,ycoor,hlOverview):
highlights the given coordinate in the main map and reference map by placing a crosshair with the given presentation attributes. The third parameter is of type boolean (true|false) and defines whether the location should be highlighted in the reference map or not. The highlight cross disappears with the next zoom or pan action or if you call the method .hideHighlightCross().
- .hideHighlightCross():
hides the crosshair in the mainMap and referenceMap
- .backwardExtent():
goes back to the previous map extent stored in the map extent history array, only reacts if we aren't already at the first entry in the array
- .forwardExtent():
goes forward to the next map extent stored in the map extent history array, only reacts if we aren't already at the last entry in the array
- checkButtons():
analyzes current map extent and changes activation state of zoom and pan buttons. Normally you should not need this method, unless you purposly change the button state from another script
- stopNavModes():
stops active navigation modes and goes back to the default info mode where zooming and panning is deactivated
- .cleanUp():
removes all temporarily added elements and event listeners from the main map and linked reference map. This method can be useful if you switch between different views/settings, e.g. country/continent/world, where you have to reset values and re-initialize the map object and dragObj.
showExtent() is a standalone function that alerts the current map extent. In our example this function is attached to the tiny rectangle in the lower right corner of the mainMap. Clicking on that rectangle activates this function. This function is dependent on the existance of the "myMainMap" instance of the "map" object.
loadProjectSpecific() is a standalone function that is always called when the map extent changes. It can be used to adjust dependent map elements accordingly or restyle them in dependency of the current map width.
Useful Properties of the Map Object
- .curxOrig:
holds the x value of the upper left corner of the current map extent
- .curyOrig:
holds the y value of the upper left corner of the current map extent
- .curWidth:
holds the width of the current map extent; this value can e.g. be used to resymbolize stroke width and text-sizes after resetting the map extent. The function loadProjectSpecific() could be used for that purpose, because it is called every time the map extent changes.
- .maxWidth:
holds the maximum width of the map when in full view
- .minWidth:
holds the minimum width of the map when fully zoomed in
- .nrDecimals:
holds the number of decimal places after the comma for the display of coordinates or accuracy, when in digitizing mode
- .pixSize:
holds the size of one unit of the screen oriented coordinate system within the mainMap coordinate system
- .timestamp:
holds a timestamp containing the time when the user last zoomed or panned. This is useful for dynamic data-loading in conjunction with .getUrl()
- .nrLayerToLoad:
is an associative array containing the number of dynamic layers to load. key in the array is the current timestamp, value is the number of dynamic layers still to be loaded. Value is zero if all layers are loaded. This variable can be useful if you want to start a certain action only after all dynamic layers are loaded.
- .epsg:
the epsg projection nr of the map, this can be used to build URL strings for loading data from OGC services, such as WMS or spatial databases.
- .navStatus:
indicates the current zoom/pan mode. Possible values are: info (zoom and pan deactivated), zoomManual (manual zoom mode), panmanual (in manual pan mode), panmanualActive (currently in active panning mode), recenter (in map recentering mode)
- units:
a string value containing the current map units (e.g. "m" or "ft")
- unitsFactor:
a factor to convert map units to output units to be used in the coordinate calculations (e.g. to convert "m" to "ft" or vice versa)
- highlightVisible:
a boolean value (true|false) that indicates whether the highlight cross is visible or not
Current Limitations
- Currently, there is no automatic adaption of the main map to the window size
- Currently, the main map and the reference map must have the same width/height ratio and need to exactly share the coordinate systems
Version history
- 1.0: initial version
- 1.01 (2005-02-15): added cleanUp() method to map and dragObj object. Some fixes in the documentation.
- 1.02 (2005-02-20): fixed problem if user used a double click at buttons instead of a single click. The second click of a double click is now ignored, using the evt.detail property.
- 1.03 (2005-02-22): introduced timestamp and nrLayerToLoad array for dynamic loading (getUrl).
- 1.04 (2005-09-12): introduced a few changes with coordinate calculation to support MozillaSVG, the changes require you to also upgrade the mapApp.js file, introduced epsg and unitsFactor property based on a suggestion by Bruce Rindahl
- 1.1 (2005-10-05): introduced button object (see button.js file), introduced zoom and pan "modes" for repeated actions in the same mode, introduced history of map extents with the ability to go back and forth in the list of previous map extents, some internal changes in the code (e.g. less global variables), added experimental support for the batik SVG 1.2 "static" attribute to improve performance while panning the map, introduced cursors to give better feedback to user actions
- 1.1.1 (2005-10-24): replaced all "class" and "style" attributes with simple XML attributes to make the example render in SVG viewers that don't support CSS
- 1.1.2 (2006-02-21): fixed a small problem with the event handling in the overview map, navigation tools now run fine with Opera9+ as well
- 1.2 (2006-05-08): dragObj is now called directly from the map object (please remove it from the initialization function of previous versions), new constructor parameters, added method .pointTestWithin(xcoor,ycoor), added method .highlightPosition(xcoor,ycoor,hlOverview) and method .hideHighlightCross(); drag rectangle and drag symbol are now automatically added (please remove them from previous projects if you defined them in your svg file), event listeners are now automatically added to the reference map (please remove previous event handler attributes from your project, otherwise functions will fire twice); the previous primitive checkbox object is now replaced with the more sophisticated checkbox object available from the carto.net SVG GUI section; updated and improved documentation
- 1.2.1 (2006-05-13): fixed a bug in the documentation, fixed a severe bug in the helper_functions.js file, functions dd2dms() and dms2dd(); thanks Bruce Rindahl for bug-reporting and providing fixes
- 1.2.2 (2006-06-08): fixed a bug in the .stopNavModes() function that would prevent entering info mode after pressing the info button
- 1.2.3 (2006-06-19): changed the behaviour of the highlightCross, the highlightCross is now automatically hidden after each zoom and pan; highlightCross in main map now correctly disappears if coordinate outside of main map; fixed a bug when repeatedly starting the same mode
- 1.2.4 (2006-08-10): added methods .bboxTestWithin(bbox) and .bboxTestOverlaps(bbox); updated the slider object in index.svg
- 1.3 (2007-04-19): added evt.preventDefault() in dragObj.prototype.handleEvent to prevent that a potential raster image is dragged in the reference map (applies to Apple Safari); manual zoom rectangle can now be drawn in all directions; the behavior of small manual zoom rectangles was slightly changed
- 1.3.1 (2007-05-07): corrected a bug where coordinate display still happened when the mouse cursor was above the reference map, even when the map object instance had the showCoords property set to false