diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..f52a3b4
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,12 @@
+# This file is for unifying the coding style for different editors and IDEs
+# editorconfig.org
+
+root = true
+
+[*]
+indent_size = 2
+indent_style = space
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
\ No newline at end of file
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..e9e08c4
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,5 @@
+tests/redist/
+examples/redist/
+build/
+dist/
+node_modules/
\ No newline at end of file
diff --git a/.eslintrc.json b/.eslintrc.json
new file mode 100644
index 0000000..6fd9c6d
--- /dev/null
+++ b/.eslintrc.json
@@ -0,0 +1,21 @@
+{
+ "root": true,
+ "extends": ["eslint:recommended", "jquery", "prettier"],
+ "plugins": ["html"],
+ "reportUnusedDisableDirectives": true,
+ "parserOptions": {
+ "ecmaVersion": 5,
+ "sourceType": "script"
+ },
+ "env": {
+ "browser": true,
+ "jquery": true
+ },
+ "globals": {},
+ "rules": {
+ "one-var": ["error", { "var": "consecutive" }],
+ "strict": ["error", "function"],
+ "no-nested-ternary": 0,
+ "camelcase": 0
+ }
+}
diff --git a/.gitattributes b/.gitattributes
index f5cdc18..386f838 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1,49 +1,49 @@
-*.doc diff=astextplain
-*.DOC diff=astextplain
-*.docx diff=astextplain
-*.DOCX diff=astextplain
-*.dot diff=astextplain
-*.DOT diff=astextplain
-*.pdf diff=astextplain
-*.PDF diff=astextplain
-*.rtf diff=astextplain
-*.RTF diff=astextplain
-
-*.jpg binary
-*.png binary
-*.gif binary
-
-*.cs -text diff=csharp
-*.vb -text
-*.c -text
-*.cpp -text
-*.cxx -text
-*.h -text
-*.hxx -text
-*.py -text
-*.rb -text
-*.java -text
-*.html -text
-*.htm -text
-*.css -text
-*.scss -text
-*.sass -text
-*.less -text
-*.js -text
-*.lisp -text
-*.clj -text
-*.sql -text
-*.php -text
-*.lua -text
-*.m -text
-*.asm -text
-*.erl -text
-*.fs -text
-*.fsx -text
-*.hs -text
-
-*.csproj -text merge=union
-*.vbproj -text merge=union
-*.fsproj -text merge=union
-*.dbproj -text merge=union
-*.sln -text merge=union
+*.doc diff=astextplain
+*.DOC diff=astextplain
+*.docx diff=astextplain
+*.DOCX diff=astextplain
+*.dot diff=astextplain
+*.DOT diff=astextplain
+*.pdf diff=astextplain
+*.PDF diff=astextplain
+*.rtf diff=astextplain
+*.RTF diff=astextplain
+
+*.jpg binary
+*.png binary
+*.gif binary
+
+*.cs -text diff=csharp
+*.vb -text
+*.c -text
+*.cpp -text
+*.cxx -text
+*.h -text
+*.hxx -text
+*.py -text
+*.rb -text
+*.java -text
+*.html -text
+*.htm -text
+*.css -text
+*.scss -text
+*.sass -text
+*.less -text
+*.js -text
+*.lisp -text
+*.clj -text
+*.sql -text
+*.php -text
+*.lua -text
+*.m -text
+*.asm -text
+*.erl -text
+*.fs -text
+*.fsx -text
+*.hs -text
+
+*.csproj -text merge=union
+*.vbproj -text merge=union
+*.fsproj -text merge=union
+*.dbproj -text merge=union
+*.sln -text merge=union
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index 0df677a..1ad4534 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -4,7 +4,6 @@ about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
-
---
@@ -26,4 +26,4 @@ Demonstrate the code is solid. Example: The exact commands you ran and their out
**Closing issues**
-Put `Closes #XXXX` in your comment to auto-close the issue that your PR fixes/addresses.
\ No newline at end of file
+Put `Closes #XXXX` in your comment to auto-close the issue that your PR fixes/addresses.
diff --git a/.prettierrc.json b/.prettierrc.json
new file mode 100644
index 0000000..32ebab4
--- /dev/null
+++ b/.prettierrc.json
@@ -0,0 +1,4 @@
+{
+ "singleQuote": true,
+ "trailingComma": "none"
+}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c77d2de..fd912da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,290 +1,292 @@
-# Changelog
-
-## Roadmap
-
-* Return promises from asynchronous events rather than requiring callbacks like "onConfigured"
-* Return a non-jQuery object exposing the imagemapster API to simplify coding against it
-* Detect input device actively to determine when highlight effect should be enabled
-* Rewrite in ES6/Typescript
-* Update to modern build system (e.g. rollup/weback/etc.)
-* Create React component
-* Migrate to modern testframework
-* Update website and host on Github
-
-## Version 2.0.0 (planned)
-* **Breaking Change** - [Issue 70](https://github.com/jamietre/ImageMapster/issues/70) Respect target attribute for AREA elements with href.
-
-## Version 1.3.2 (planned)
-* [Issue 328](https://github.com/jamietre/ImageMapster/issues/328) Fix tracking internal map_cache on unbind
-
-## Version 1.3.1 - 2021.01.10
-* Publish to NPM
-
-## Version 1.3.0 - 2021.01.10
-
-* [Issue 273](https://github.com/jamietre/ImageMapster/issues/273) Add NPM support
-* [Issue 318](https://github.com/jamietre/ImageMapster/issues/318) Update to conform with jQuery 3.5.1 (latest release)
-* [Issue 319](https://github.com/jamietre/ImageMapster/issues/319) Fix Passive Event Listeners for touchstart/touchend
-* [Issue 320](https://github.com/jamietre/ImageMapster/issues/320) Support UMD and improve build system
-
-## Version 1.2.14 - 2021.01.06
-
-* [Issue 148](https://github.com/jamietre/ImageMapster/issues/148) Enable mouseover events when touchscreen found
-* [PR 248](https://github.com/jamietre/ImageMapster/pull/248) Add touchstart/touchend support
-* [Issue 284](https://github.com/jamietre/ImageMapster/issues/284) Fix size not a function as of jQuery 3.0
-* [PR 263](https://github.com/jamietre/ImageMapster/pull/263) Fix EDGE issue when no map data found
-* [Issue 311](https://github.com/jamietre/ImageMapster/issues/311) Update /dist with latest code
-* [Issue 312](https://github.com/jamietre/ImageMapster/issues/312) Fix tests
-* [Issue 313](https://github.com/jamietre/ImageMapster/issues/313) Fix events not be cleared
-* [Issue 314](https://github.com/jamietre/ImageMapster/issues/314) Eliminate when.js dependency from distribution
-* [Issue 316](https://github.com/jamietre/ImageMapster/issues/316) Fix AltImage
-* [Issue 317](https://github.com/jamietre/ImageMapster/issues/317) Fix USA Example
-
-## Version 1.2.13
-
-* Fix problem with mouseoutdelay=01
-
-## Version 1.2.12
-
-* Fix issue with $.inArray on IE8
-* Fix problem with boundList when using "set" to toggle a multiple areas at once (from 1.2.11 issue - not quite fixed)
-
-## Version 1.2.11
-
-* Fix problem de-selecting boundlist when using "set" to toggle
-
-## Version 1.2.10
-
-* [Issue 120](https://github.com/jamietre/ImageMapster/issues/114) 1.2.9 broke IE9
-
-## Version 1.2.9
-
-* [Issue 114](https://github.com/jamietre/ImageMapster/issues/114) Fix jQuery 1.9 compatibility problem
-
-## Version 1.2.8
-
-* [Issue 108](https://github.com/jamietre/ImageMapster/issues/108) Opacity of tooltip container not preserved
-* [Issue 107](https://github.com/jamietre/ImageMapster/issues/107) mouseoutDelay broken
-
-## Version 1.2.7
-
-* [Issue 95](https://github.com/jamietre/ImageMapster/issues/95) SingleSelect broken in 1.2.6.099
-* [Issue 87](https://github.com/jamietre/ImageMapster/issues/87) Resize callback not working
-* [Issue 84](https://github.com/jamietre/ImageMapster/issues/84) Mouseover events not completely suppressed on mobile
-* Tooltip enhancements: tooltips can be called against arbitrary elements.
-* AltImage enhancements: see below
-
-*tooltip-enhancements branch*
-
-* [Issue 72](https://github.com/jamietre/ImageMapster/issues/72): `scaleMap` not working propery when using bootstrap (css on `body` causing incorrect evaluation of native image size)
-* Enhanced tooltip API to allow creating arbitrary tool tips bound to any area, or at an arbitrary position.
-
-*altimage-enhancements branch*
-
-* Add `altImages` option that accepts an option defining aliases to alternate images. The name of each property is an alias that can be specified as a valid `altImage` option value elsewhere
-
-Example use of this option:
-
-
-
- altImages: {
- roadmap: 'images/usamap-roads.png',
- elevation: 'images/uasmap-elevation.png'
- }
-
-then:
-
- $('img').mapster('set',true,'AZ', {
- altImage: 'roadmap'
- });
-
-
-The aliases can also be used in the initial configuration options, both globally and for specific areas.
-
-
-## Version 1.2.6 - 2012.07.13
-
-Bug Fixes:
-
-* [Issue #69](https://github.com/jamietre/ImageMapster/issues/69) `fill` setting not being honored sometimes in IE6-8
-* [Issue #68](https://github.com/jamietre/ImageMapster/issues/68) Accept `areas` array with dangling commas
-
-## Version 1.2.5 - 2012.06.19
-
-
-
-Bug fixes:
-
-* [Issue #59](https://github.com/jamietre/ImageMapster/issues/59), [Issue #55](https://github.com/jamietre/ImageMapster/issues/55) Opacity/fade effects not working right in IE8
-* [Issue #58](https://github.com/jamietre/ImageMapster/issues/58) Resize not changing CSS for the `div` contiainer around the image elements
-* [Issue #53](https://github.com/jamietre/ImageMapster/issues/53) Not working in Google Chrome with Adblock plugin
-* [Issue #44](https://github.com/jamietre/ImageMapster/issues/44) Incorrect opacity with altImage
-* [Issue #36](https://github.com/jamietre/ImageMapster/issues/36) Resize firing callback before resize is finished
-* Rebind not cleaning up resources properly
-* Offset 1 pixel strokes by 0.5 px to prevent the fuzzies
-* Ignore UI events during resize - can cause problems if highlights are activated during an effect
-
-
-Features:
-
-* [Issue #52](https://github.com/jamietre/ImageMapster/issues/52) Add "clickNavigate" feature to allow basic imagemap functionality
-* Add "highlight" option to programatically set/unset the highlight effect (as if a user just moused over an area vs. clicked)
-* Detect touchscreen devices and disable "mouseover"
-* [Issue #11](https://github.com/jamietre/ImageMapster/issues/11) Detect excanvas automatically and force into IE mode if present
-
-Notes
-
-* refactor into modular architecture
-* tighten up tooltip code a little
-* Removed "attrmatches" jQuery selector exetnsion, recoded as a function, removed from tests
-* Queue all methods (highlight, data, tooltip) so configuration delays don't cause problems
-* Unbind "load" event explicitly from images added.
-* Add dynamic images to DOM instead of loading through Javascript
-* Ignore missing keys on some operations to increase stability with bad data
-* Trim results of string splits so spaces don't cause problems
-* Yet more tweaking of image loading detection
-* Refactor "graphics" into an object and instantiate for each instance. "load" callbacks were changing event order, resulting in the single instance getting wires crossed. Isolated
-each map instance completely, problem solved.
-* Fix canvases re-ordered after first selection making effect sometimes inconsistent
-* Fix resize bug when area groups are used
-
-## Version 1.2.4 - 2011.09.27
-
-* [Issue #14](https://github.com/jamietre/ImageMapster/issues/14) Resize bug in IE <9 fixed
-
-## Version 1.2.3
-
-* Resize with multiple images affecting other images - fixed
-
-## Version 1.2.2 - 2011.09.22
-
-* masks not working in Firefox 6.0 only. behavior of context.globalCompositeOperation='source-out' and
- save/restore somehow changed in ff6. updated code to not depend (possibly) on idiosyncracies of chrome
- and ie9. honestly not sure why it worked before as it appears I may have been doing something wrong,
- but the code is more explicit now and it works across all browsers.
-
-## Version 1.2.1
-
-* Click callback "this" is not set - fixed
-* Replace u.isFunction with $.isFunction to save a few bytes
-
-## Version 1.2
-
-* fixed fader problem for old IE (again, really this time)
-* allow selecting includeKeys areas from staticState areas
-* test browser features for filter vs. opacity
-* "resize" option
-* improve startup speed by eliminating need for setTimeout callback
-* address startup bug when images aren't loaded and there are lots of images
-* fixed exception when "set" with no data for key
-* bug when multiple images bound on same page * another IE tweak: blur() on mouseover/click to remove browser-rendered border around area
-* force "border=0" on image to ensure consistent display across bind/unbind in IE
-* Fixed broken "onMouseover" option, added tests for onMouseover/onMouseout.
-* many performance improvements, tests, refactoring some old inefficient code.
-* fix css flickering when debinding/rebinding in HTML5 browsers
-* add "scaleMap" option to automatically resize image maps when a bound image is resized dynamically. Enabled by default if an image is displayed at a size other than its native size.
-
-## Version 1.1.3
-
-* revised "highlight" method API (previously undocumented). Added tests & documented.
-* added a generic prototype for parsing method data to improve consistency & stability
-* added tests for tooltip external & event bound invocation
-* added invoking tooltip from area, e.g. $('some-area').mapster('tooltip')
-* added invoking tooltip from key, e.g. .mapster('tooltip',key);
-* Bug fix for get_options, showToolTip (related)
-* Bug fix - area id 0 on VML rendereding deselection causes all selections to disappear (introduced in beta 2)
-* Changed "get" to return true "selected" state and not "isSelected()" which includes staticState items in selected.
-* Bug fix - stroke sometimes rendered improperly when using render-specific options
-* change onClick handler to BEFORE action, permit canceling of action by returning false
-* refactor into mostly OO design - functional design was getting unwieldy.
-* fix bugs related to cascading of "staticState" options
-* add "snapshot" option
-* check for existing wrapper, skip if it already exists
-* remove map data when unbinding+preserveState -- it should act as if not there
-* IE performance improvements (optimizing rendering code a little bit)
-
-## Version 1.1.2 - 2011.06-15
-
-* minor bugfix release
-
-## Version 1.1.1 - 2011.06.03
-
-* Performance improvement: cache area groups on map binding to eliminate need for attribute selector
-* Significant enhancement to permit complex area grouping and area exclusions (masks):
- * added: mapKey can contain multiple keys, allowing an area to be a member of multiple groups
- * added: "noHrefIsMask" option to determine "nohref" attribute treatment
- * added: "isMask" option (area-specific)
- * added: "includeKeys" option (area-specific)
-* added: 'highlight' method to enable highlighting of areas from code
-* bufgix: fading didn't work in IE6-7, some Operas. Should work in all browsers except IE8 now.
-* bugfix: ignore areas with no mapkey when it is provided
-* bugfix: not binding properly when no mapkey provided
-
-## Version 1.1
-
-* added: per-action options (highlight, select)
-* fixed some memory leaks
-* minor performance improvements
-* cleanup in VML mode
-* fix IE9 canvas support (fader problem)
-* fix flickering on fades when moving quickly
-* add altImage options
-* added onConfigured callback
-* fixed problems with cleanup (not removing wrap)
-* added failure timeout for configure
-
-## Version 1.0.10 - 2011.05.12
-
-* ignore errors when binding mapster to invalid elements
-* minor performance improvements
-* fixed command queue problem (broke in 1.0.9) for commands issued after bind, but before image is ready
-* enhanced tests
-
-## Version 1.0.9 - 2011.05.10
-
-* added "unbind" option to remove mapster from an image
-* add 'options' option
-* add 'rebind' option
-* add isDeselectable option
-* handle exceptions better (when acting on unbound images)
-* add 'get' method to retrieve selections
-* add unbind options
-* clear command queue after processing
-
-## Version 1.0.8 - 2011.05.05
-
-* Handle problem when "img.complete" is not true at config time and "set" commands are issued after initial config call but before config is complete. Queue any "set" commands and process them after the timer callback.
-* Pass listTarget to onClick callback even when !isSelectable (previously passed null)
-* Pass ref to toolTip element on callback
-* Don't show tooltip again if the one for an area is already displayed
-* Add singleSelect option - clears any other selected item when a new item is selected
-
-## Version 1.0.6 - 2011.04.27
-
-* Problem when not using mapKey
-* staticState=false not working
-
-## Version 1.0.5 - 2011.04.26
-
-* Corrected jquery attribute selector (not using quote marks)
-* added area persistence behavior options
-* tooltips not working in Firefox - bug in area data management. Deprecated use of jquery.data for passing area-specific options, added "areas" option to replace
-* fixed "showToolTip" default property name (was showToolTips) - should have had no effect
-
-## Version 1.0.4 - 2011.04.20
-
-* allow using jQuery object for toolTip text
-* happy earth day
-
-## Version 1.0.3
-
-* missing preventDefault on click (post refactor issue)
-
-## Version 1.0.2
-
-* fixed tooltip in IE6
-
-## Version 1.0.0 - 2011.04.19 - **first official release**
-
-* refactored from remaining old to use a clean namespace
-* added simple mouseover dialog
+# Changelog
+
+## Roadmap
+
+- Return promises from asynchronous events rather than requiring callbacks like "onConfigured"
+- Return a non-jQuery object exposing the imagemapster API to simplify coding against it
+- Detect input device actively to determine when highlight effect should be enabled
+- Rewrite in ES6/Typescript
+- Update to modern build system (e.g. rollup/weback/etc.)
+- Create React component
+- Migrate to modern testframework
+- Update website and host on Github
+
+## Version 2.0.0 (planned)
+
+- **Breaking Change** - [Issue 70](https://github.com/jamietre/ImageMapster/issues/70) Respect target attribute for AREA elements with href.
+
+## Version 1.3.2 (planned)
+
+- [Issue 327](https://github.com/jamietre/ImageMapster/issues/327) Add linter & format files
+- [Issue 328](https://github.com/jamietre/ImageMapster/issues/328) Fix tracking internal map_cache on unbind
+- [Issue 330](https://github.com/jamietre/ImageMapster/issues/330) Fix shapes example rectangle responds to mouseevents
+
+## Version 1.3.1 - 2021.01.10
+
+- Publish to NPM
+
+## Version 1.3.0 - 2021.01.10
+
+- [Issue 273](https://github.com/jamietre/ImageMapster/issues/273) Add NPM support
+- [Issue 318](https://github.com/jamietre/ImageMapster/issues/318) Update to conform with jQuery 3.5.1 (latest release)
+- [Issue 319](https://github.com/jamietre/ImageMapster/issues/319) Fix Passive Event Listeners for touchstart/touchend
+- [Issue 320](https://github.com/jamietre/ImageMapster/issues/320) Support UMD and improve build system
+
+## Version 1.2.14 - 2021.01.06
+
+- [Issue 148](https://github.com/jamietre/ImageMapster/issues/148) Enable mouseover events when touchscreen found
+- [PR 248](https://github.com/jamietre/ImageMapster/pull/248) Add touchstart/touchend support
+- [Issue 284](https://github.com/jamietre/ImageMapster/issues/284) Fix size not a function as of jQuery 3.0
+- [PR 263](https://github.com/jamietre/ImageMapster/pull/263) Fix EDGE issue when no map data found
+- [Issue 311](https://github.com/jamietre/ImageMapster/issues/311) Update /dist with latest code
+- [Issue 312](https://github.com/jamietre/ImageMapster/issues/312) Fix tests
+- [Issue 313](https://github.com/jamietre/ImageMapster/issues/313) Fix events not be cleared
+- [Issue 314](https://github.com/jamietre/ImageMapster/issues/314) Eliminate when.js dependency from distribution
+- [Issue 316](https://github.com/jamietre/ImageMapster/issues/316) Fix AltImage
+- [Issue 317](https://github.com/jamietre/ImageMapster/issues/317) Fix USA Example
+
+## Version 1.2.13
+
+- Fix problem with mouseoutdelay=01
+
+## Version 1.2.12
+
+- Fix issue with $.inArray on IE8
+- Fix problem with boundList when using "set" to toggle a multiple areas at once (from 1.2.11 issue - not quite fixed)
+
+## Version 1.2.11
+
+- Fix problem de-selecting boundlist when using "set" to toggle
+
+## Version 1.2.10
+
+- [Issue 120](https://github.com/jamietre/ImageMapster/issues/114) 1.2.9 broke IE9
+
+## Version 1.2.9
+
+- [Issue 114](https://github.com/jamietre/ImageMapster/issues/114) Fix jQuery 1.9 compatibility problem
+
+## Version 1.2.8
+
+- [Issue 108](https://github.com/jamietre/ImageMapster/issues/108) Opacity of tooltip container not preserved
+- [Issue 107](https://github.com/jamietre/ImageMapster/issues/107) mouseoutDelay broken
+
+## Version 1.2.7
+
+- [Issue 95](https://github.com/jamietre/ImageMapster/issues/95) SingleSelect broken in 1.2.6.099
+- [Issue 87](https://github.com/jamietre/ImageMapster/issues/87) Resize callback not working
+- [Issue 84](https://github.com/jamietre/ImageMapster/issues/84) Mouseover events not completely suppressed on mobile
+- Tooltip enhancements: tooltips can be called against arbitrary elements.
+- AltImage enhancements: see below
+
+_tooltip-enhancements branch_
+
+- [Issue 72](https://github.com/jamietre/ImageMapster/issues/72): `scaleMap` not working propery when using bootstrap (css on `body` causing incorrect evaluation of native image size)
+- Enhanced tooltip API to allow creating arbitrary tool tips bound to any area, or at an arbitrary position.
+
+_altimage-enhancements branch_
+
+- Add `altImages` option that accepts an option defining aliases to alternate images. The name of each property is an alias that can be specified as a valid `altImage` option value elsewhere
+
+Example use of this option:
+
+```js
+altImages: {
+ roadmap: 'images/usamap-roads.png',
+ elevation: 'images/uasmap-elevation.png'
+}
+```
+
+then:
+
+```js
+$('img').mapster('set', true, 'AZ', {
+ altImage: 'roadmap'
+});
+```
+
+The aliases can also be used in the initial configuration options, both globally and for specific areas.
+
+## Version 1.2.6 - 2012.07.13
+
+Bug Fixes:
+
+- [Issue #69](https://github.com/jamietre/ImageMapster/issues/69) `fill` setting not being honored sometimes in IE6-8
+- [Issue #68](https://github.com/jamietre/ImageMapster/issues/68) Accept `areas` array with dangling commas
+
+## Version 1.2.5 - 2012.06.19
+
+Bug fixes:
+
+- [Issue #59](https://github.com/jamietre/ImageMapster/issues/59), [Issue #55](https://github.com/jamietre/ImageMapster/issues/55) Opacity/fade effects not working right in IE8
+- [Issue #58](https://github.com/jamietre/ImageMapster/issues/58) Resize not changing CSS for the `div` contiainer around the image elements
+- [Issue #53](https://github.com/jamietre/ImageMapster/issues/53) Not working in Google Chrome with Adblock plugin
+- [Issue #44](https://github.com/jamietre/ImageMapster/issues/44) Incorrect opacity with altImage
+- [Issue #36](https://github.com/jamietre/ImageMapster/issues/36) Resize firing callback before resize is finished
+- Rebind not cleaning up resources properly
+- Offset 1 pixel strokes by 0.5 px to prevent the fuzzies
+- Ignore UI events during resize - can cause problems if highlights are activated during an effect
+
+Features:
+
+- [Issue #52](https://github.com/jamietre/ImageMapster/issues/52) Add "clickNavigate" feature to allow basic imagemap functionality
+- Add "highlight" option to programatically set/unset the highlight effect (as if a user just moused over an area vs. clicked)
+- Detect touchscreen devices and disable "mouseover"
+- [Issue #11](https://github.com/jamietre/ImageMapster/issues/11) Detect excanvas automatically and force into IE mode if present
+
+Notes
+
+- refactor into modular architecture
+- tighten up tooltip code a little
+- Removed "attrmatches" jQuery selector exetnsion, recoded as a function, removed from tests
+- Queue all methods (highlight, data, tooltip) so configuration delays don't cause problems
+- Unbind "load" event explicitly from images added.
+- Add dynamic images to DOM instead of loading through Javascript
+- Ignore missing keys on some operations to increase stability with bad data
+- Trim results of string splits so spaces don't cause problems
+- Yet more tweaking of image loading detection
+- Refactor "graphics" into an object and instantiate for each instance. "load" callbacks were changing event order, resulting in the single instance getting wires crossed. Isolated
+ each map instance completely, problem solved.
+- Fix canvases re-ordered after first selection making effect sometimes inconsistent
+- Fix resize bug when area groups are used
+
+## Version 1.2.4 - 2011.09.27
+
+- [Issue #14](https://github.com/jamietre/ImageMapster/issues/14) Resize bug in IE <9 fixed
+
+## Version 1.2.3
+
+- Resize with multiple images affecting other images - fixed
+
+## Version 1.2.2 - 2011.09.22
+
+- masks not working in Firefox 6.0 only. behavior of context.globalCompositeOperation='source-out' and
+ save/restore somehow changed in ff6. updated code to not depend (possibly) on idiosyncracies of chrome
+ and ie9. honestly not sure why it worked before as it appears I may have been doing something wrong,
+ but the code is more explicit now and it works across all browsers.
+
+## Version 1.2.1
+
+- Click callback "this" is not set - fixed
+- Replace u.isFunction with $.isFunction to save a few bytes
+
+## Version 1.2
+
+- fixed fader problem for old IE (again, really this time)
+- allow selecting includeKeys areas from staticState areas
+- test browser features for filter vs. opacity
+- "resize" option
+- improve startup speed by eliminating need for setTimeout callback
+- address startup bug when images aren't loaded and there are lots of images
+- fixed exception when "set" with no data for key
+- bug when multiple images bound on same page \* another IE tweak: blur() on mouseover/click to remove browser-rendered border around area
+- force "border=0" on image to ensure consistent display across bind/unbind in IE
+- Fixed broken "onMouseover" option, added tests for onMouseover/onMouseout.
+- many performance improvements, tests, refactoring some old inefficient code.
+- fix css flickering when debinding/rebinding in HTML5 browsers
+- add "scaleMap" option to automatically resize image maps when a bound image is resized dynamically. Enabled by default if an image is displayed at a size other than its native size.
+
+## Version 1.1.3
+
+- revised "highlight" method API (previously undocumented). Added tests & documented.
+- added a generic prototype for parsing method data to improve consistency & stability
+- added tests for tooltip external & event bound invocation
+- added invoking tooltip from area, e.g. $('some-area').mapster('tooltip')
+- added invoking tooltip from key, e.g. .mapster('tooltip',key);
+- Bug fix for get_options, showToolTip (related)
+- Bug fix - area id 0 on VML rendereding deselection causes all selections to disappear (introduced in beta 2)
+- Changed "get" to return true "selected" state and not "isSelected()" which includes staticState items in selected.
+- Bug fix - stroke sometimes rendered improperly when using render-specific options
+- change onClick handler to BEFORE action, permit canceling of action by returning false
+- refactor into mostly OO design - functional design was getting unwieldy.
+- fix bugs related to cascading of "staticState" options
+- add "snapshot" option
+- check for existing wrapper, skip if it already exists
+- remove map data when unbinding+preserveState -- it should act as if not there
+- IE performance improvements (optimizing rendering code a little bit)
+
+## Version 1.1.2 - 2011.06-15
+
+- minor bugfix release
+
+## Version 1.1.1 - 2011.06.03
+
+- Performance improvement: cache area groups on map binding to eliminate need for attribute selector
+- Significant enhancement to permit complex area grouping and area exclusions (masks):
+ - added: mapKey can contain multiple keys, allowing an area to be a member of multiple groups
+ - added: "noHrefIsMask" option to determine "nohref" attribute treatment
+ - added: "isMask" option (area-specific)
+ - added: "includeKeys" option (area-specific)
+- added: 'highlight' method to enable highlighting of areas from code
+- bufgix: fading didn't work in IE6-7, some Operas. Should work in all browsers except IE8 now.
+- bugfix: ignore areas with no mapkey when it is provided
+- bugfix: not binding properly when no mapkey provided
+
+## Version 1.1
+
+- added: per-action options (highlight, select)
+- fixed some memory leaks
+- minor performance improvements
+- cleanup in VML mode
+- fix IE9 canvas support (fader problem)
+- fix flickering on fades when moving quickly
+- add altImage options
+- added onConfigured callback
+- fixed problems with cleanup (not removing wrap)
+- added failure timeout for configure
+
+## Version 1.0.10 - 2011.05.12
+
+- ignore errors when binding mapster to invalid elements
+- minor performance improvements
+- fixed command queue problem (broke in 1.0.9) for commands issued after bind, but before image is ready
+- enhanced tests
+
+## Version 1.0.9 - 2011.05.10
+
+- added "unbind" option to remove mapster from an image
+- add 'options' option
+- add 'rebind' option
+- add isDeselectable option
+- handle exceptions better (when acting on unbound images)
+- add 'get' method to retrieve selections
+- add unbind options
+- clear command queue after processing
+
+## Version 1.0.8 - 2011.05.05
+
+- Handle problem when "img.complete" is not true at config time and "set" commands are issued after initial config call but before config is complete. Queue any "set" commands and process them after the timer callback.
+- Pass listTarget to onClick callback even when !isSelectable (previously passed null)
+- Pass ref to toolTip element on callback
+- Don't show tooltip again if the one for an area is already displayed
+- Add singleSelect option - clears any other selected item when a new item is selected
+
+## Version 1.0.6 - 2011.04.27
+
+- Problem when not using mapKey
+- staticState=false not working
+
+## Version 1.0.5 - 2011.04.26
+
+- Corrected jquery attribute selector (not using quote marks)
+- added area persistence behavior options
+- tooltips not working in Firefox - bug in area data management. Deprecated use of jquery.data for passing area-specific options, added "areas" option to replace
+- fixed "showToolTip" default property name (was showToolTips) - should have had no effect
+
+## Version 1.0.4 - 2011.04.20
+
+- allow using jQuery object for toolTip text
+- happy earth day
+
+## Version 1.0.3
+
+- missing preventDefault on click (post refactor issue)
+
+## Version 1.0.2
+
+- fixed tooltip in IE6
+
+## Version 1.0.0 - 2011.04.19 - **first official release**
+
+- refactored from remaining old to use a clean namespace
+- added simple mouseover dialog
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index edf4ed8..58c165f 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation.
Examples of behavior that contributes to creating a positive environment
include:
-* Using welcoming and inclusive language
-* Being respectful of differing viewpoints and experiences
-* Gracefully accepting constructive criticism
-* Focusing on what is best for the community
-* Showing empathy towards other community members
+- Using welcoming and inclusive language
+- Being respectful of differing viewpoints and experiences
+- Gracefully accepting constructive criticism
+- Focusing on what is best for the community
+- Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
-* The use of sexualized language or imagery and unwelcome sexual attention or
- advances
-* Trolling, insulting/derogatory comments, and personal or political attacks
-* Public or private harassment
-* Publishing others' private information, such as a physical or electronic
- address, without explicit permission
-* Other conduct which could reasonably be considered inappropriate in a
- professional setting
+- The use of sexualized language or imagery and unwelcome sexual attention or
+ advances
+- Trolling, insulting/derogatory comments, and personal or political attacks
+- Public or private harassment
+- Publishing others' private information, such as a physical or electronic
+ address, without explicit permission
+- Other conduct which could reasonably be considered inappropriate in a
+ professional setting
## Our Responsibilities
@@ -73,4 +73,4 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.ht
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
-https://www.contributor-covenant.org/faq.
\ No newline at end of file
+https://www.contributor-covenant.org/faq.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index cda21e4..4e7e9f8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,7 +2,7 @@
:+1::tada: First off, thanks for taking the time to contribute! :tada::+1:
-The following is a set of guidelines for contributing to ImageMapster.
+The following is a set of guidelines for contributing to ImageMapster.
Please take a moment to review this document in order to make the contribution process easy and effective for everyone involved. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
@@ -28,13 +28,13 @@ Guidelines for bug reports:
A good bug report shouldn't leave others needing to chase you up for more information. Please try to be as detailed as possible in your report. What is your environment? What steps will reproduce the issue? What browser(s) and OS experience the problem? Do other browsers show the bug differently? What would you expect to be the outcome? All these details will help people to fix any potential bugs.
-Once you have established that there is a potential issue, please use the [bug report](https://github.com/jamietre/ImageMapster/issues/new?template=bug_report.md) issue template and supply all requested information. If the required information is not provided, your issue will be marked with the 'needs author feedback' label and closed until there is enough information for the team to evaluate/reproduce.
+Once you have established that there is a potential issue, please use the [bug report](https://github.com/jamietre/ImageMapster/issues/new?template=bug_report.md) issue template and supply all requested information. If the required information is not provided, your issue will be marked with the 'needs author feedback' label and closed until there is enough information for the team to evaluate/reproduce.
## Feature requests
Feature requests are welcome. But take a moment to find out whether your idea fits with the scope and aims of the project.
-Please use the [feature request](https://github.com/jamietre/ImageMapster/issues/new?template=feature_request.md) issue template and supply all requested information. If the required information is not provided, your issue will be marked with the 'needs author feedback' label and closed until there is enough information to evaluate your proposal.
+Please use the [feature request](https://github.com/jamietre/ImageMapster/issues/new?template=feature_request.md) issue template and supply all requested information. If the required information is not provided, your issue will be marked with the 'needs author feedback' label and closed until there is enough information to evaluate your proposal.
## Pull requests
@@ -44,7 +44,7 @@ Please use the [pull request](https://github.com/jamietre/ImageMapster/pulls/new
**Please ask first** before embarking on any significant pull request (e.g. implementing features or refactoring code), otherwise you risk spending a lot of time working on something that the project's maintainers might not want to merge into the project.
-In lieu of a formal style-guide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. If the type of unit test required to support your pull request is not supported by the current test framework (iqTest), please add an example covering the functionality. Please make sure your changes build by running `grunt build` as described in the [development section](README.md#development) of the [Readme](README.md).
+In lieu of a formal style-guide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality. If the type of unit test required to support your pull request is not supported by the current test framework (iqTest), please add an example covering the functionality. Please make sure your changes build by running `grunt build` as described in the [development section](README.md#development) of the [Readme](README.md).
## License
diff --git a/README.md b/README.md
index 36a8946..f49de0c 100644
--- a/README.md
+++ b/README.md
@@ -1,188 +1,196 @@
-# ImageMapster: A jQuery Plugin to make image maps useful
-
-[](https://github.com/jamietre/ImageMapster/blob/master/LICENSE)
-[](https://GitHub.com/jamietre/ImageMapster/releases/)
-[](https://GitHub.com/jamietre/ImageMapster/releases/)
-[](https://www.npmjs.com/package/imagemapster)
-[](https://www.jsdelivr.com/package/npm/imagemapster)
-[](https://cdnjs.com/libraries/imagemapster)
-
-ImageMapster activates the areas in HTML imagemaps so you can highlight and select them. It has lots of other features for manual control, tooltips, resizing, and more. It is designed to be compatible with every common platform, and is tested with Internet Explorer 6-10, Firefox 3.0+, Safari, Opera, and Chrome. It works on mobile devices and doesn't use Flash.
-
-## Release Information
-
-See the [change log](https://github.com/jamietre/ImageMapster/blob/master/CHANGELOG.md) for details on the release history and roadmap.
-
-Read the [release notes](http://blog.outsharked.com/2012/06/imagemapster-125-released.html) for 1.2.5, the last significant feature update.
-
-## Getting Started
-
-### Installation
-
-#### NPM
-This package can be installed via NPM:
-
-```sh
-npm install jquery imagemapster --save
-```
-
-#### Browser
-
-Download the latest version of ImageMapster from the [Releases](https://github.com/jamietre/ImageMapster/releases) page and include in your webpage:
-
-```html
-
-
-```
-
-Alternatively, you can include ImageMapster from one of the following CDNs:
-
-1. [jsDelivr](https://www.jsdelivr.com/package/npm/imagemapster) - https://www.jsdelivr.com/package/npm/imagemapster
-2. [cdnjs](https://cdnjs.com/libraries/imagemapster) - https://cdnjs.com/libraries/imagemapster
-
-### Usage
-
-Activate all image maps on the page with default options: on mouseover areas are highlighted with a gray fill with no border, and clicking an area causes it to become selected.
-
-```js
-$('img').mapster();
-```
-
-Activate image maps with some specific options.
-
-```js
-$('img').mapster( {
- fillColor: 'ff0000',
- stroke: true,
- singleSelect: true
-});
-```
-
-#### Methods
-
-There are lots of ways to manipulate the imagemap from Javascript. Here area a few, see the [ImageMapster web site](http://www.outsharked.com/imagemapster) for complete documentation.
-
-**select**: Cause an area to become "selected"
-
-```js
-$('area').mapster('select');
-```
-
-Programatically select elements from the image map. The programmatic selection/deselection methods will not honor the staticState property.
-
-**deselect**: Cause an area to become "selected"
-
-```js
-$('area').mapster('deselect');
-```
-
-**set**: select or deselect an element. If `selected` is true, the area is selected, if false, it is deselected.
-
-```js
-$('area').mapster('set',selected);
-```
-
-You can also select or deselect areas using a their `mapKey`. This is an attribute on each area in your HTML that identifies it. You define a mapKey using a configuration option: `mapKey: 'data-key'`.
-
-```js
-$('img').mapster('set',true,'key1,key2');
-```
-
-If two areas share the same value for the `mapKey` they will be automatically grouped together when activated. You can also use the values of the mapKey to select areas from code.
-
-You can pass options to change the rendering effects when using set as the last parameter:
-
-```js
-$('img').mapster('set',true,'key', {fillColor: 'ff0000'} );
-```
-
-MapKeys can contain more than one value. The first value always defines groups when you mouse over. Other values can be used to create logical groups. For example:
-
-```html
-
-
-
-
-
-
-
-
-
-
-```
-
-```js
-$('#usamap').mapster( { mapKey: 'data-key' } );
-```
-
-Mousing over each state would cause just that state to be higlighted. You can also select other logical groups from code code:
-
-```js
-// select all New England states
-$('img').mapster('set',true,'new-england');
-
-// select just Maine, New Hampshire & Vermont
-$('img').mapster('set',true,'really-cold');
-```
-
-Groups created this way are *independent* of the primary group. If you select "new-england" from code, you can't unselect just "MA" by clicking on it. You would have to unselect "new-england" from code.
-
-To simply indentify a set of areas to turn on or off, but not treat them as a logical group, you can use CSS classes and select areas directly, or use the keys
option to identify the primary keys associated with a group (see documentation).
-
-#### Options
-
-Please see the [ImageMapster web site](http://www.outsharked.com/imagemapster/default.aspx?docs.html) for complete documentation.
-
-## Examples
-
-ImageMapster includes several examples. To view the examples:
-
-1. Clone the repo
-2. Install NPM dependencies - `npm install`
-3. Open [index.html](examples/index.html) directly from your file system in a browser
-
-## Zepto Compatibility
-
-Newer versions of Zepto don't seem to work any more (as of 1.2.5). I didn't want this to hold up the ever-delayed release even further so I didn't figure out why.
-
-In theory it should work; you need to use the "jquery.imagemapster.zepto.js" build. This patches a few holes in Zepto that ImageMapster needs. It is safe to use the zepto version with jQuery.
-
-To generate a Zepto build of ImageMapster:
-
-1. Clone the repository
-2. Install NPM dependencies - `npm install`
-3. Generate a full build - `npm run fullbuild`
-
-## Find out More
-
-Please see how to obtain [ImageMapster Support](SUPPORT.md).
-
-## Contributing
-
-Please see our [Contributing Guidelines](CONTRIBUTING.md).
-
-## Development
-
-### Build
-
-The source code is broken into several modules to make management easier and to make it possible to create feature-targeted builds. ImageMapster is built using grunt and can be invoked as follows:
-
-1. Clone the repo
-2. Install NPM dependencies - `npm install`
-3. Install [Grunt Cli](https://gruntjs.com/getting-started) - `npm install -g grunt-cli`
-4. Generate a Build:
- - Release Build (compressed/uncompressed/sourcemap for jQuery) - `grunt build`
- - Full Release Build (compressed/uncompressed/sourcemap for jQuery & Zepto) - `grunt fullbuild`
- - jQuery Dev Build (uncompressed only) - `grunt jquery`
- - Zepto Dev Build (uncompressed only) - `grunt zepto`
-
-### Debug
-
-1. Clone the repo
-2. Install NPM dependencies - `npm install`
-3. Install [Grunt Cli](https://gruntjs.com/getting-started) - `npm install -g grunt-cli`
-4. Run the debug task - `grunt debug`
-
-## License
-
-Copyright © 2011-21 [James Treworgy](https://github.com/jamietre). Licensed under the [MIT License](LICENSE).
\ No newline at end of file
+# ImageMapster: A jQuery Plugin to make image maps useful
+
+[](https://github.com/jamietre/ImageMapster/blob/master/LICENSE)
+[](https://GitHub.com/jamietre/ImageMapster/releases/)
+[](https://GitHub.com/jamietre/ImageMapster/releases/)
+[](https://www.npmjs.com/package/imagemapster)
+[](https://www.jsdelivr.com/package/npm/imagemapster)
+[](https://cdnjs.com/libraries/imagemapster)
+[](https://github.com/prettier/prettier)
+
+ImageMapster activates the areas in HTML imagemaps so you can highlight and select them. It has lots of other features for manual control, tooltips, resizing, and more. It is designed to be compatible with every common platform, and is tested with Internet Explorer 6-10, Firefox 3.0+, Safari, Opera, and Chrome. It works on mobile devices and doesn't use Flash.
+
+## Release Information
+
+See the [change log](https://github.com/jamietre/ImageMapster/blob/master/CHANGELOG.md) for details on the release history and roadmap.
+
+Read the [release notes](http://blog.outsharked.com/2012/06/imagemapster-125-released.html) for 1.2.5, the last significant feature update.
+
+## Getting Started
+
+### Installation
+
+#### NPM
+
+This package can be installed via NPM:
+
+```sh
+npm install jquery imagemapster --save
+```
+
+#### Browser
+
+Download the latest version of ImageMapster from the [Releases](https://github.com/jamietre/ImageMapster/releases) page and include in your webpage:
+
+```html
+
+
+```
+
+Alternatively, you can include ImageMapster from one of the following CDNs:
+
+1. [jsDelivr](https://www.jsdelivr.com/package/npm/imagemapster) - https://www.jsdelivr.com/package/npm/imagemapster
+2. [cdnjs](https://cdnjs.com/libraries/imagemapster) - https://cdnjs.com/libraries/imagemapster
+
+### Usage
+
+Activate all image maps on the page with default options: on mouseover areas are highlighted with a gray fill with no border, and clicking an area causes it to become selected.
+
+```js
+$('img').mapster();
+```
+
+Activate image maps with some specific options.
+
+```js
+$('img').mapster({
+ fillColor: 'ff0000',
+ stroke: true,
+ singleSelect: true
+});
+```
+
+#### Methods
+
+There are lots of ways to manipulate the imagemap from Javascript. Here area a few, see the [ImageMapster web site](http://www.outsharked.com/imagemapster) for complete documentation.
+
+**select**: Cause an area to become "selected"
+
+```js
+$('area').mapster('select');
+```
+
+Programatically select elements from the image map. The programmatic selection/deselection methods will not honor the staticState property.
+
+**deselect**: Cause an area to become "selected"
+
+```js
+$('area').mapster('deselect');
+```
+
+**set**: select or deselect an element. If `selected` is true, the area is selected, if false, it is deselected.
+
+```js
+$('area').mapster('set', selected);
+```
+
+You can also select or deselect areas using a their `mapKey`. This is an attribute on each area in your HTML that identifies it. You define a mapKey using a configuration option: `mapKey: 'data-key'`.
+
+```js
+$('img').mapster('set', true, 'key1,key2');
+```
+
+If two areas share the same value for the `mapKey` they will be automatically grouped together when activated. You can also use the values of the mapKey to select areas from code.
+
+You can pass options to change the rendering effects when using set as the last parameter:
+
+```js
+$('img').mapster('set', true, 'key', { fillColor: 'ff0000' });
+```
+
+MapKeys can contain more than one value. The first value always defines groups when you mouse over. Other values can be used to create logical groups. For example:
+
+```html
+
+
+
+
+
+
+
+
+
+
+```
+
+```js
+$('#usamap').mapster({ mapKey: 'data-key' });
+```
+
+Mousing over each state would cause just that state to be higlighted. You can also select other logical groups from code code:
+
+```js
+// select all New England states
+$('img').mapster('set', true, 'new-england');
+
+// select just Maine, New Hampshire & Vermont
+$('img').mapster('set', true, 'really-cold');
+```
+
+Groups created this way are _independent_ of the primary group. If you select "new-england" from code, you can't unselect just "MA" by clicking on it. You would have to unselect "new-england" from code.
+
+To simply indentify a set of areas to turn on or off, but not treat them as a logical group, you can use CSS classes and select areas directly, or use the keys
option to identify the primary keys associated with a group (see documentation).
+
+#### Options
+
+Please see the [ImageMapster web site](http://www.outsharked.com/imagemapster/default.aspx?docs.html) for complete documentation.
+
+## Examples
+
+ImageMapster includes several examples. To view the examples:
+
+1. Clone the repo
+2. Open [index.html](examples/index.html) directly from your file system in a browser
+
+## Zepto Compatibility
+
+Newer versions of Zepto don't seem to work any more (as of 1.2.5). I didn't want this to hold up the ever-delayed release even further so I didn't figure out why.
+
+In theory it should work; you need to use the "jquery.imagemapster.zepto.js" build. This patches a few holes in Zepto that ImageMapster needs. It is safe to use the zepto version with jQuery.
+
+To generate a Zepto build of ImageMapster:
+
+1. Clone the repository
+2. Install NPM dependencies - `npm install`
+3. Generate a full build - `npm run fullbuild`
+
+## Find out More
+
+Please see how to obtain [ImageMapster Support](SUPPORT.md).
+
+## Contributing
+
+Please see our [Contributing Guidelines](CONTRIBUTING.md).
+
+## Development
+
+### Build
+
+The source code is broken into several modules to make management easier and to make it possible to create feature-targeted builds. ImageMapster is built using grunt and can be invoked as follows:
+
+1. Clone the repo
+2. Install NPM dependencies - `npm install`
+3. Install [Grunt Cli](https://gruntjs.com/getting-started) - `npm install -g grunt-cli`
+4. Generate a Build:
+ - Release Build (compressed/uncompressed/sourcemap for jQuery) - `grunt build`
+ - Full Release Build (compressed/uncompressed/sourcemap for jQuery & Zepto) - `grunt fullbuild`
+ - jQuery Dev Build (uncompressed only) - `grunt jquery`
+ - Zepto Dev Build (uncompressed only) - `grunt zepto`
+
+### Debug
+
+1. Clone the repo
+2. Install NPM dependencies - `npm install`
+3. Install [Grunt Cli](https://gruntjs.com/getting-started) - `npm install -g grunt-cli`
+4. Run the debug task - `grunt debug`
+
+## License
+
+Copyright © 2011-21 [James Treworgy](https://github.com/jamietre). Licensed under the [MIT License](LICENSE).
diff --git a/SUPPORT.md b/SUPPORT.md
index 93a2095..6bbfc0f 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -2,7 +2,7 @@
**Please do not use the issue tracker for personal support requests.**
-Have questions? Looking for support for ImageMapster?
+Have questions? Looking for support for ImageMapster?
- There are lots of examples and documentation on the [ImageMapster web site](http://www.outsharked.com/imagemapster).
@@ -10,10 +10,10 @@ Have questions? Looking for support for ImageMapster?
- Take a look at [ImageMapster questions on StackOverflow](http://stackoverflow.com/search?q=imagemapster); there are quite a few. Maybe someone's asked the same question already.
-- There are also some very detailed discussions in the [GitHub issues](https://github.com/jamietre/imagemapster/issues?direction=desc&labels=support&page=1&sort=created&state=closed) section that I've flagged as "support". The issues section is no longer the way to request support but these issues can provide valuable insight.
+- There are also some very detailed discussions in the [GitHub issues](https://github.com/jamietre/imagemapster/issues?direction=desc&labels=support&page=1&sort=created&state=closed) section that I've flagged as "support". The issues section is no longer the way to request support but these issues can provide valuable insight.
-- You can also check the [feedback](http://www.outsharked.com/imagemapster/default.aspx?feedback.html) page on the project web site.
+- You can also check the [feedback](http://www.outsharked.com/imagemapster/default.aspx?feedback.html) page on the project web site.
-- You can review the [source code on GitHub](https://github.com/jamietre/ImageMapster).
+- You can review the [source code on GitHub](https://github.com/jamietre/ImageMapster).
-If you identify a bug, please file a [bug report](https://github.com/jamietre/ImageMapster/issues/new?template=bug_report.md) and if you'd like to see a new feature, please file a [feature request](https://github.com/jamietre/ImageMapster/issues/new?template=feature_request.md)!
\ No newline at end of file
+If you identify a bug, please file a [bug report](https://github.com/jamietre/ImageMapster/issues/new?template=bug_report.md) and if you'd like to see a new feature, please file a [feature request](https://github.com/jamietre/ImageMapster/issues/new?template=feature_request.md)!
diff --git a/bower.json b/bower.json
index 31b5487..dcdc6f7 100644
--- a/bower.json
+++ b/bower.json
@@ -20,9 +20,7 @@
"resize",
"tooltip"
],
- "authors": [
- "James Treworgy "
- ],
+ "authors": ["James Treworgy "],
"license": "MIT",
"ignore": [
"**/.*",
diff --git a/dist/jquery.imagemapster.js b/dist/jquery.imagemapster.js
index 9be343e..3231b28 100644
--- a/dist/jquery.imagemapster.js
+++ b/dist/jquery.imagemapster.js
@@ -5,3484 +5,3713 @@
* License: MIT
*/
(function (factory) {
- if (typeof define === 'function' && define.amd) {
- // AMD. Register as an anonymous module.
- define(['jquery'], factory);
- } else if (typeof module === 'object' && module.exports) {
- // Node/CommonJS
- module.exports = function( root, jQuery ) {
- if ( jQuery === undefined ) {
- // require('jQuery') returns a factory that requires window to
- // build a jQuery instance, we normalize how we use modules
- // that require this pattern but the window provided is a noop
- // if it's defined (how jquery works)
- if ( typeof window !== 'undefined' ) {
- jQuery = require('jquery');
- }
- else {
- jQuery = require('jquery')(root);
- }
- }
- factory(jQuery);
- return jQuery;
- };
- } else {
- // Browser globals
- factory(jQuery);
- }
-}(function (jQuery) {
- (function ($) {
- // Test via a getter in the options object to see if the passive property is accessed
- var supportsPassive = false;
- try {
- var opts = Object.defineProperty({}, 'passive', {
- get: function() {
- supportsPassive = true;
- }
- });
- window.addEventListener("testPassive.mapster", function() {}, opts);
- window.removeEventListener("testPassive.mapster", function() {}, opts);
- } catch (e) {}
-
- if (supportsPassive) {
- // In order to not interrupt scrolling on touch devices
- // we commit to not calling preventDefault from within listeners
- // There is a plan to handle this natively in jQuery 4.0 but for
- // now we are on our own.
- // TODO: Migrate to jQuery 4.0 approach if/when released
- // https://www.chromestatus.com/feature/5745543795965952
- // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
- // https://github.com/jquery/jquery/issues/2871#issuecomment-175175180
- // https://jsbin.com/bupesajoza/edit?html,js,output
- var setupListener = function(ns, type, listener) {
- if (ns.includes("noPreventDefault")) {
- this.addEventListener(type, listener, { passive: true });
- } else {
- console.warn("non-passive events - listener not added");
- return false;
- }
- };
-
- // special events for noPreventDefault
- $.event.special.touchstart = {
- setup: function (_, ns, listener) {
- return setupListener(ns, "touchstart", listener);
- }
- };
- $.event.special.touchend = {
- setup: function (_, ns, listener) {
- return setupListener(ns, "touchend", listener);
- }
- };
- }
-}(jQuery));
-
-/* ImageMapster core */
-
-/*jslint laxbreak: true, evil: true, unparam: true */
-
-/*global jQuery: true, Zepto: true */
-
-
-(function ($) {
- var mapster_version = '1.3.2-beta.0';
-
- // all public functions in $.mapster.impl are methods
- $.fn.mapster = function (method) {
- var m = $.mapster.impl;
- if ($.mapster.utils.isFunction(m[method])) {
- return m[method].apply(this, Array.prototype.slice.call(arguments, 1));
- } else if (typeof method === 'object' || !method) {
- return m.bind.apply(this, arguments);
- } else {
- $.error('Method ' + method + ' does not exist on jQuery.mapster');
- }
- };
-
- $.mapster = {
- version: mapster_version,
- render_defaults: {
- isSelectable: true,
- isDeselectable: true,
- fade: false,
- fadeDuration: 150,
- fill: true,
- fillColor: '000000',
- fillColorMask: 'FFFFFF',
- fillOpacity: 0.7,
- highlight: true,
- stroke: false,
- strokeColor: 'ff0000',
- strokeOpacity: 1,
- strokeWidth: 1,
- includeKeys: '',
- altImage: null,
- altImageId: null, // used internally
- altImages: {}
- },
- defaults: {
- clickNavigate: false,
- wrapClass: null,
- wrapCss: null,
- onGetList: null,
- sortList: false,
- listenToList: false,
- mapKey: '',
- mapValue: '',
- singleSelect: false,
- listKey: 'value',
- listSelectedAttribute: 'selected',
- listSelectedClass: null,
- onClick: null,
- onMouseover: null,
- onMouseout: null,
- mouseoutDelay: 0,
- onStateChange: null,
- boundList: null,
- onConfigured: null,
- configTimeout: 30000,
- noHrefIsMask: true,
- scaleMap: true,
- safeLoad: false,
- areas: []
- },
- shared_defaults: {
- render_highlight: { fade: true },
- render_select: { fade: false },
- staticState: null,
- selected: null
- },
- area_defaults:
- {
- includeKeys: '',
- isMask: false
- },
- canvas_style: {
- position: 'absolute',
- left: 0,
- top: 0,
- padding: 0,
- border: 0
- },
- hasCanvas: null,
- map_cache: [],
- hooks: {},
- addHook: function(name,callback) {
- this.hooks[name]=(this.hooks[name]||[]).push(callback);
- },
- callHooks: function(name,context) {
- $.each(this.hooks[name]||[],function(i,e) {
- e.apply(context);
- });
- },
- utils: {
- when: {
- all: function(deferredArray) {
- return Promise.all(deferredArray);
- },
- defer: function() {
- // Deferred is frequently referred to as an anti-pattern largely
- // due to error handling, however to avoid reworking existing
- // APIs and support backwards compat, creating a "deferred"
- // polyfill via native promise
- var Deferred = function() {
- this.promise = new Promise((function(resolve, reject) {
- this.resolve = resolve;
- this.reject = reject;
- }).bind(this));
-
- this.then = this.promise.then.bind(this.promise);
- this.catch = this.promise.catch.bind(this.promise);
- };
- return new Deferred();
- }
- },
- defer: function() {
- return this.when.defer();
- },
- // extends the constructor, returns a new object prototype. Does not refer to the
- // original constructor so is protected if the original object is altered. This way you
- // can "extend" an object by replacing it with its subclass.
- subclass: function(BaseClass, constr) {
- var Subclass=function() {
- var me=this,
- args=Array.prototype.slice.call(arguments,0);
- me.base = BaseClass.prototype;
- me.base.init = function() {
- BaseClass.prototype.constructor.apply(me,args);
- };
- constr.apply(me,args);
- };
- Subclass.prototype = new BaseClass();
- Subclass.prototype.constructor=Subclass;
- return Subclass;
- },
- asArray: function (obj) {
- return obj.constructor === Array ?
- obj : this.split(obj);
- },
- // clean split: no padding or empty elements
- split: function (text,cb) {
- var i,el, arr = text.split(',');
- for (i = 0; i < arr.length; i++) {
- // backwards compat for $.trim which would return empty string on null
- // which theoertically should not happen here
- el = arr[i] ? arr[i].trim() : '';
- if (el==='') {
- arr.splice(i,1);
- } else {
- arr[i] = cb ? cb(el):el;
- }
- }
- return arr;
- },
- // similar to $.extend but does not add properties (only updates), unless the
- // first argument is an empty object, then all properties will be copied
- updateProps: function (_target, _template) {
- var onlyProps,
- target = _target || {},
- template = $.isEmptyObject(target) ? _template : _target;
-
- //if (template) {
- onlyProps = [];
- $.each(template, function (prop) {
- onlyProps.push(prop);
- });
- //}
-
- $.each(Array.prototype.slice.call(arguments, 1), function (i, src) {
- $.each(src || {}, function (prop) {
- if (!onlyProps || $.inArray(prop, onlyProps) >= 0) {
- var p = src[prop];
-
- if ($.isPlainObject(p)) {
- // not recursive - only copies 1 level of subobjects, and always merges
- target[prop] = $.extend(target[prop] || {}, p);
- } else if (p && p.constructor === Array) {
- target[prop] = p.slice(0);
- } else if (typeof p !== 'undefined') {
- target[prop] = src[prop];
- }
-
- }
- });
- });
- return target;
- },
- isElement: function (o) {
- return (typeof HTMLElement === "object" ? o instanceof HTMLElement :
- o && typeof o === "object" && o.nodeType === 1 && typeof o.nodeName === "string");
- },
- /**
- * Basic indexOf implementation for IE7-8. Though we use $.inArray, some jQuery versions will try to
- * use a prototpye on the calling object, defeating the purpose of using $.inArray in the first place.
- *
- * This will be replaced with the array prototype if it's available.
- *
- * @param {Array} arr The array to search
- * @param {Object} target The item to search for
- * @return {Number} The index of the item, or -1 if not found
- */
- indexOf: function(arr,target){
- if (Array.prototype.indexOf) {
- return Array.prototype.indexOf.call(arr, target);
- } else {
- for(var i=0; i endOp - 0.01) ? endOp : op + (endOp / cbIntervals);
-
- u.setOpacity(obj, op);
- if (op < endOp) {
- setTimeout(function () {
- fade_func(el, op, endOp, duration);
- }, 15);
- }
- };
- return fade_func;
- } ())
- },
- getBoundList: function (opts, key_list) {
- if (!opts.boundList) {
- return null;
- }
- var index, key, result = $(), list = $.mapster.utils.split(key_list);
- opts.boundList.each(function (i,e) {
- for (index = 0; index < list.length; index++) {
- key = list[index];
- if ($(e).is('[' + opts.listKey + '="' + key + '"]')) {
- result = result.add(e);
- }
- }
- });
- return result;
- },
- // Causes changes to the bound list based on the user action (select or deselect)
- // area: the jQuery area object
- // returns the matching elements from the bound list for the first area passed (normally only one should be passed, but
- // a list can be passed
- setBoundListProperties: function (opts, target, selected) {
- target.each(function (i,e) {
- if (opts.listSelectedClass) {
- if (selected) {
- $(e).addClass(opts.listSelectedClass);
- } else {
- $(e).removeClass(opts.listSelectedClass);
- }
- }
- if (opts.listSelectedAttribute) {
- $(e).prop(opts.listSelectedAttribute, selected);
- }
- });
- },
- getMapDataIndex: function (obj) {
- var img, id;
- switch (obj.tagName && obj.tagName.toLowerCase()) {
- case 'area':
- id = $(obj).parent().attr('name');
- img = $("img[usemap='#" + id + "']")[0];
- break;
- case 'img':
- img = obj;
- break;
- }
- return img ?
- this.utils.indexOfProp(this.map_cache, 'image', img) : -1;
- },
- getMapData: function (obj) {
- var index = this.getMapDataIndex(obj.length ? obj[0]:obj);
- if (index >= 0) {
- return index >= 0 ? this.map_cache[index] : null;
- }
- },
- /**
- * Queue a command to be run after the active async operation has finished
- * @param {MapData} map_data The target MapData object
- * @param {jQuery} that jQuery object on which the command was invoked
- * @param {string} command the ImageMapster method name
- * @param {object[]} args arguments passed to the method
- * @return {bool} true if the command was queued, false if not (e.g. there was no need to)
- */
- queueCommand: function (map_data, that, command, args) {
- if (!map_data) {
- return false;
- }
- if (!map_data.complete || map_data.currentAction) {
- map_data.commands.push(
- {
- that: that,
- command: command,
- args: args
- });
- return true;
- }
- return false;
- },
- unload: function () {
- this.impl.unload();
- this.utils = null;
- this.impl = null;
- $.fn.mapster = null;
- $.mapster = null;
- $('*').off();
- }
- };
-
- // Config for object prototypes
- // first: use only first object (for things that should not apply to lists)
- /// calls back one of two fuinctions, depending on whether an area was obtained.
- // opts: {
- // name: 'method name',
- // key: 'key,
- // args: 'args'
- //
- //}
- // name: name of method (required)
- // args: arguments to re-call with
- // Iterates through all the objects passed, and determines whether it's an area or an image, and calls the appropriate
- // callback for each. If anything is returned from that callback, the process is stopped and that data return. Otherwise,
- // the object itself is returned.
-
- var m = $.mapster,
- u = m.utils,
- ap = Array.prototype;
-
-
- // jQuery's width() and height() are broken on IE9 in some situations. This tries everything.
- $.each(["width","height"],function(i,e) {
- var capProp = e.substr(0,1).toUpperCase() + e.substr(1);
- // when jqwidth parm is passed, it also checks the jQuery width()/height() property
- // the issue is that jQUery width() can report a valid size before the image is loaded in some browsers
- // without it, we can read zero even when image is loaded in other browsers if its not visible
- // we must still check because stuff like adblock can temporarily block it
- // what a goddamn headache
- u["img"+capProp]=function(img,jqwidth) {
- return (jqwidth ? $(img)[e]() : 0) ||
- img[e] || img["natural"+capProp] || img["client"+capProp] || img["offset"+capProp];
- };
-
- });
-
- /**
- * The Method object encapsulates the process of testing an ImageMapster method to see if it's being
- * invoked on an image, or an area; then queues the command if the MapData is in an active state.
- *
- * @param {[jQuery]} that The target of the invocation
- * @param {[function]} func_map The callback if the target is an imagemap
- * @param {[function]} func_area The callback if the target is an area
- * @param {[object]} opt Options: { key: a map key if passed explicitly
- * name: the command name, if it can be queued,
- * args: arguments to the method
- * }
- */
-
- m.Method = function (that, func_map, func_area, opts) {
- var me = this;
- me.name = opts.name;
- me.output = that;
- me.input = that;
- me.first = opts.first || false;
- me.args = opts.args ? ap.slice.call(opts.args, 0) : [];
- me.key = opts.key;
- me.func_map = func_map;
- me.func_area = func_area;
- //$.extend(me, opts);
- me.name = opts.name;
- me.allowAsync = opts.allowAsync || false;
- };
- m.Method.prototype = {
- constructor: m.Method,
- go: function () {
- var i, data, ar, len, result, src = this.input,
- area_list = [],
- me = this;
-
- len = src.length;
- for (i = 0; i < len; i++) {
- data = $.mapster.getMapData(src[i]);
- if (data) {
- if (!me.allowAsync && m.queueCommand(data, me.input, me.name, me.args)) {
- if (this.first) {
- result = '';
- }
- continue;
- }
-
- ar = data.getData(src[i].nodeName === 'AREA' ? src[i] : this.key);
- if (ar) {
- if ($.inArray(ar, area_list) < 0) {
- area_list.push(ar);
- }
- } else {
- result = this.func_map.apply(data, me.args);
- }
- if (this.first || typeof result !== 'undefined') {
- break;
- }
- }
- }
- // if there were areas, call the area function for each unique group
- $(area_list).each(function (i,e) {
- result = me.func_area.apply(e, me.args);
- });
-
- if (typeof result !== 'undefined') {
- return result;
- } else {
- return this.output;
- }
- }
- };
-
- $.mapster.impl = (function () {
- var me = {},
- addMap= function (map_data) {
- return m.map_cache.push(map_data) - 1;
- },
- removeMap = function (map_data) {
- m.map_cache.splice(map_data.index, 1);
- for (var i = m.map_cache.length - 1; i >= map_data.index; i--) {
- m.map_cache[i].index--;
- }
- };
-
-
- /**
- * Test whether the browser supports VML. Credit: google.
- * http://stackoverflow.com/questions/654112/how-do-you-detect-support-for-vml-or-svg-in-a-browser
- *
- * @return {bool} true if vml is supported, false if not
- */
-
- function hasVml() {
- var a = $('
').appendTo('body');
- a.html(' ');
-
- var b = a[0].firstChild;
- b.style.behavior = "url(#default#VML)";
- var has = b ? typeof b.adj === "object" : true;
- a.remove();
- return has;
- }
-
- /**
- * Return a reference to the IE namespaces object, if available, or an empty object otherwise
- * @return {obkect} The document.namespaces object.
- */
- function namespaces() {
- return typeof(document.namespaces)==='object' ?
- document.namespaces :
- null;
- }
-
- /**
- * Test for the presence of HTML5 Canvas support. This also checks to see if excanvas.js has been
- * loaded and is faking it; if so, we assume that canvas is not supported.
- *
- * @return {bool} true if HTML5 canvas support, false if not
- */
-
- function hasCanvas() {
- var d = namespaces();
- // when g_vml_ is present, then we can be sure excanvas is active, meaning there's not a real canvas.
-
- return d && d.g_vml_ ?
- false :
- $(' ')[0].getContext ?
- true :
- false;
- }
-
- /**
- * Merge new area data into existing area options on a MapData object. Used for rebinding.
- *
- * @param {[MapData]} map_data The MapData object
- * @param {[object[]]} areas areas array to merge
- */
-
- function merge_areas(map_data, areas) {
- var ar, index,
- map_areas = map_data.options.areas;
-
- if (areas) {
- $.each(areas, function (i, e) {
-
- // Issue #68 - ignore invalid data in areas array
-
- if (!e || !e.key) {
- return;
- }
-
- index = u.indexOfProp(map_areas, "key", e.key);
-
- if (index >= 0) {
- $.extend(map_areas[index], e);
- }
- else {
- map_areas.push(e);
- }
- ar = map_data.getDataForKey(e.key);
- if (ar) {
- $.extend(ar.options, e);
- }
- });
- }
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof module === 'object' && module.exports) {
+ // Node/CommonJS
+ module.exports = function( root, jQuery ) {
+ if ( jQuery === undefined ) {
+ // require('jQuery') returns a factory that requires window to
+ // build a jQuery instance, we normalize how we use modules
+ // that require this pattern but the window provided is a noop
+ // if it's defined (how jquery works)
+ if ( typeof window !== 'undefined' ) {
+ jQuery = require('jquery');
}
- function merge_options(map_data, options) {
- var temp_opts = u.updateProps({}, options);
- delete temp_opts.areas;
-
- u.updateProps(map_data.options, temp_opts);
-
- merge_areas(map_data, options.areas);
- // refresh the area_option template
- u.updateProps(map_data.area_options, map_data.options);
- }
-
- // Most methods use the "Method" object which handles figuring out whether it's an image or area called and
- // parsing key parameters. The constructor wants:
- // this, the jQuery object
- // a function that is called when an image was passed (with a this context of the MapData)
- // a function that is called when an area was passed (with a this context of the AreaData)
- // options: first = true means only the first member of a jQuery object is handled
- // key = the key parameters passed
- // defaultReturn: a value to return other than the jQuery object (if its not chainable)
- // args: the arguments
- // Returns a comma-separated list of user-selected areas. "staticState" areas are not considered selected for the purposes of this method.
-
- me.get = function (key) {
- var md = m.getMapData(this);
- if (!(md && md.complete)) {
- throw("Can't access data until binding complete.");
- }
-
- return (new m.Method(this,
- function () {
- // map_data return
- return this.getSelected();
- },
- function () {
- return this.isSelected();
- },
- { name: 'get',
- args: arguments,
- key: key,
- first: true,
- allowAsync: true,
- defaultReturn: ''
- }
- )).go();
- };
- me.data = function (key) {
- return (new m.Method(this,
- null,
- function () {
- return this;
- },
- { name: 'data',
- args: arguments,
- key: key
- }
- )).go();
- };
-
-
- // Set or return highlight state.
- // $(img).mapster('highlight') -- return highlighted area key, or null if none
- // $(area).mapster('highlight') -- highlight an area
- // $(img).mapster('highlight','area_key') -- highlight an area
- // $(img).mapster('highlight',false) -- remove highlight
- me.highlight = function (key) {
- return (new m.Method(this,
- function () {
- if (key === false) {
- this.ensureNoHighlight();
- } else {
- var id = this.highlightId;
- return id >= 0 ? this.data[id].key : null;
- }
- },
- function () {
- this.highlight();
- },
- { name: 'highlight',
- args: arguments,
- key: key,
- first: true
- }
- )).go();
- };
- // Return the primary keys for an area or group key.
- // $(area).mapster('key')
- // includes all keys (not just primary keys)
- // $(area).mapster('key',true)
- // $(img).mapster('key','group-key')
-
- // $(img).mapster('key','group-key', true)
- me.keys = function(key,all) {
- var keyList=[],
- md = m.getMapData(this);
-
- if (!(md && md.complete)) {
- throw("Can't access data until binding complete.");
- }
-
-
- function addUniqueKeys(ad) {
- var areas,keys=[];
- if (!all) {
- keys.push(ad.key);
- } else {
- areas=ad.areas();
- $.each(areas,function(i,e) {
- keys=keys.concat(e.keys);
- });
- }
- $.each(keys,function(i,e) {
- if ($.inArray(e,keyList)<0) {
- keyList.push(e);
- }
- });
- }
-
- if (!(md && md.complete)) {
- return '';
- }
- if (typeof key === 'string') {
- if (all) {
- addUniqueKeys(md.getDataForKey(key));
- } else {
- keyList=[md.getKeysForGroup(key)];
- }
- } else {
- all = key;
- this.each(function(i,e) {
- if (e.nodeName==='AREA') {
- addUniqueKeys(md.getDataForArea(e));
- }
- });
- }
- return keyList.join(',');
-
-
- };
- me.select = function () {
- me.set.call(this, true);
- };
- me.deselect = function () {
- me.set.call(this, false);
- };
-
- /**
- * Select or unselect areas. Areas can be identified by a single string key, a comma-separated list of keys,
- * or an array of strings.
- *
- *
- * @param {boolean} selected Determines whether areas are selected or deselected
- * @param {string|string[]} key A string, comma-separated string, or array of strings indicating
- * the areas to select or deselect
- * @param {object} options Rendering options to apply when selecting an area
- */
-
- me.set = function (selected, key, options) {
- var lastMap, map_data, opts=options,
- key_list, area_list; // array of unique areas passed
-
- function setSelection(ar) {
- var newState = selected;
- if (ar) {
- switch (selected) {
- case true:
- ar.select(opts); break;
- case false:
- ar.deselect(true); break;
- default:
- newState = ar.toggle(opts); break;
- }
- return newState;
- }
- }
- function addArea(ar) {
- if (ar && $.inArray(ar, area_list) < 0) {
- area_list.push(ar);
- key_list+=(key_list===''?'':',')+ar.key;
- }
- }
- // Clean up after a group that applied to the same map
- function finishSetForMap(map_data) {
- $.each(area_list, function (i, el) {
- var newState = setSelection(el);
- if (map_data.options.boundList) {
- m.setBoundListProperties(map_data.options, m.getBoundList(map_data.options, key_list), newState);
- }
- });
- if (!selected) {
- map_data.removeSelectionFinish();
- }
-
- }
-
- this.filter('img,area').each(function (i,e) {
- var keys;
- map_data = m.getMapData(e);
-
- if (map_data !== lastMap) {
- if (lastMap) {
- finishSetForMap(lastMap);
- }
-
- area_list = [];
- key_list='';
- }
-
- if (map_data) {
-
- keys = '';
- if (e.nodeName.toUpperCase()==='IMG') {
- if (!m.queueCommand(map_data, $(e), 'set', [selected, key, opts])) {
- if (key instanceof Array) {
- if (key.length) {
- keys = key.join(",");
- }
- }
- else {
- keys = key;
- }
-
- if (keys) {
- $.each(u.split(keys), function (i,key) {
- addArea(map_data.getDataForKey(key.toString()));
- lastMap = map_data;
- });
- }
- }
- } else {
- opts=key;
- if (!m.queueCommand(map_data, $(e), 'set', [selected, opts])) {
- addArea(map_data.getDataForArea(e));
- lastMap = map_data;
- }
-
- }
- }
- });
-
- if (map_data) {
- finishSetForMap(map_data);
- }
-
-
- return this;
- };
- me.unbind = function (preserveState) {
- return (new m.Method(this,
- function () {
- this.clearEvents();
- this.clearMapData(preserveState);
- removeMap(this);
- },
- null,
- { name: 'unbind',
- args: arguments
- }
- )).go();
- };
-
-
- // refresh options and update selection information.
- me.rebind = function (options) {
- return (new m.Method(this,
- function () {
- var me=this;
-
- me.complete=false;
- me.configureOptions(options);
- me.bindImages().then(function() {
- me.buildDataset(true);
- me.complete=true;
- });
- //this.redrawSelections();
- },
- null,
- {
- name: 'rebind',
- args: arguments
- }
- )).go();
- };
- // get options. nothing or false to get, or "true" to get effective options (versus passed options)
- me.get_options = function (key, effective) {
- var eff = u.isBool(key) ? key : effective; // allow 2nd parm as "effective" when no key
- return (new m.Method(this,
- function () {
- var opts = $.extend({}, this.options);
- if (eff) {
- opts.render_select = u.updateProps(
- {},
- m.render_defaults,
- opts,
- opts.render_select);
-
- opts.render_highlight = u.updateProps(
- {},
- m.render_defaults,
- opts,
- opts.render_highlight);
- }
- return opts;
- },
- function () {
- return eff ? this.effectiveOptions() : this.options;
- },
- {
- name: 'get_options',
- args: arguments,
- first: true,
- allowAsync: true,
- key: key
- }
- )).go();
- };
-
- // set options - pass an object with options to set,
- me.set_options = function (options) {
- return (new m.Method(this,
- function () {
- merge_options(this, options);
- },
- null,
- {
- name: 'set_options',
- args: arguments
- }
- )).go();
- };
- me.unload = function () {
- var i;
- for (i = m.map_cache.length - 1; i >= 0; i--) {
- if (m.map_cache[i]) {
- me.unbind.call($(m.map_cache[i].image));
- }
- }
- me.graphics = null;
- };
-
- me.snapshot = function () {
- return (new m.Method(this,
- function () {
- $.each(this.data, function (i, e) {
- e.selected = false;
- });
-
- this.base_canvas = this.graphics.createVisibleCanvas(this);
- $(this.image).before(this.base_canvas);
- },
- null,
- { name: 'snapshot' }
- )).go();
- };
-
- // do not queue this function
-
- me.state = function () {
- var md, result = null;
- $(this).each(function (i,e) {
- if (e.nodeName === 'IMG') {
- md = m.getMapData(e);
- if (md) {
- result = md.state();
- }
- return false;
- }
- });
- return result;
- };
-
- me.bind = function (options) {
-
- return this.each(function (i,e) {
- var img, map, usemap, md;
-
- // save ref to this image even if we can't access it yet. commands will be queued
- img = $(e);
-
- md = m.getMapData(e);
-
- // if already bound completely, do a total rebind
-
- if (md) {
- me.unbind.apply(img);
- if (!md.complete) {
- // will be queued
- img.on();
- return true;
- }
- md = null;
- }
-
- // ensure it's a valid image
- // jQuery bug with Opera, results in full-url#usemap being returned from jQuery's attr.
- // So use raw getAttribute instead.
-
- usemap = this.getAttribute('usemap');
- map = usemap && $('map[name="' + usemap.substr(1) + '"]');
- if (!(img.is('img') && usemap && map.length > 0)) {
- return true;
- }
-
- // sorry - your image must have border:0, things are too unpredictable otherwise.
- img.css('border', 0);
-
- if (!md) {
- md = new m.MapData(this, options);
-
- md.index = addMap(md);
- md.map = map;
- md.bindImages().then(function() {
- md.initialize();
- });
- }
- });
- };
-
- me.init = function (useCanvas) {
- var style, shapes;
-
- // for testing/debugging, use of canvas can be forced by initializing
- // manually with "true" or "false". But generally we test for it.
-
- m.hasCanvas = function() {
- if (!u.isBool(m.hasCanvas.value)) {
- m.hasCanvas.value = u.isBool(useCanvas) ?
- useCanvas :
- hasCanvas();
- }
- return m.hasCanvas.value;
- };
-
- m.hasVml = function() {
- if (!u.isBool(m.hasVml.value)) {
- // initialize VML the first time we detect its presence.
- var d = namespaces();
-
- if (d && !d.v) {
- d.add("v", "urn:schemas-microsoft-com:vml");
- style = document.createStyleSheet();
- shapes = ['shape', 'rect', 'oval', 'circ', 'fill', 'stroke', 'imagedata', 'group', 'textbox'];
- $.each(shapes,
- function (i, el) {
- style.addRule('v\\:' + el, "behavior: url(#default#VML); antialias:true");
- });
- }
- m.hasVml.value = hasVml();
- }
-
- return m.hasVml.value;
- };
-
- $.extend(m.defaults, m.render_defaults,m.shared_defaults);
- $.extend(m.area_defaults, m.render_defaults,m.shared_defaults);
-
- };
- me.test = function (obj) {
- return eval(obj);
- };
- return me;
- } ());
-
- $.mapster.impl.init();
-
-
-} (jQuery));
-
-/* graphics.js
- Graphics object handles all rendering.
-*/
-(function ($) {
- var p, m=$.mapster,
- u=m.utils,
- canvasMethods,
- vmlMethods;
-
- /**
- * Implemenation to add each area in an AreaData object to the canvas
- * @param {Graphics} graphics The target graphics object
- * @param {AreaData} areaData The AreaData object (a collection of area elements and metadata)
- * @param {object} options Rendering options to apply when rendering this group of areas
- */
- function addShapeGroupImpl(graphics, areaData, options) {
- var me = graphics,
- md = me.map_data,
- isMask = options.isMask;
-
- // first get area options. Then override fade for selecting, and finally merge in the
- // "select" effect options.
-
- $.each(areaData.areas(), function (i,e) {
- options.isMask = isMask || (e.nohref && md.options.noHrefIsMask);
- me.addShape(e, options);
- });
-
- // it's faster just to manipulate the passed options isMask property and restore it, than to
- // copy the object each time
-
- options.isMask=isMask;
-
- }
-
- /**
- * Convert a hex value to decimal
- * @param {string} hex A hexadecimal toString
- * @return {int} Integer represenation of the hex string
- */
-
- function hex_to_decimal(hex) {
- return Math.max(0, Math.min(parseInt(hex, 16), 255));
- }
- function css3color(color, opacity) {
- return 'rgba(' + hex_to_decimal(color.substr(0, 2)) + ','
- + hex_to_decimal(color.substr(2, 2)) + ','
- + hex_to_decimal(color.substr(4, 2)) + ',' + opacity + ')';
- }
- /**
- * An object associated with a particular map_data instance to manage renderin.
- * @param {MapData} map_data The MapData object bound to this instance
- */
-
- m.Graphics = function (map_data) {
- //$(window).unload($.mapster.unload);
- // create graphics functions for canvas and vml browsers. usage:
- // 1) init with map_data, 2) call begin with canvas to be used (these are separate b/c may not require canvas to be specified
- // 3) call add_shape_to for each shape or mask, 4) call render() to finish
-
- var me = this;
- me.active = false;
- me.canvas = null;
- me.width = 0;
- me.height = 0;
- me.shapes = [];
- me.masks = [];
- me.map_data = map_data;
- };
-
- p = m.Graphics.prototype= {
- constructor: m.Graphics,
-
- /**
- * Initiate a graphics request for a canvas
- * @param {Element} canvas The canvas element that is the target of this operation
- * @param {string} [elementName] The name to assign to the element (VML only)
- */
-
- begin: function(canvas, elementName) {
- var c = $(canvas);
-
- this.elementName = elementName;
- this.canvas = canvas;
-
- this.width = c.width();
- this.height = c.height();
- this.shapes = [];
- this.masks = [];
- this.active = true;
-
- },
-
- /**
- * Add an area to be rendered to this canvas.
- * @param {MapArea} mapArea The MapArea object to render
- * @param {object} options An object containing any rendering options that should override the
- * defaults for the area
- */
-
- addShape: function(mapArea, options) {
- var addto = options.isMask ? this.masks : this.shapes;
- addto.push({ mapArea: mapArea, options: options });
- },
-
- /**
- * Create a canvas that is sized and styled for the MapData object
- * @param {MapData} mapData The MapData object that will receive this new canvas
- * @return {Element} A canvas element
- */
-
- createVisibleCanvas: function (mapData) {
- return $(this.createCanvasFor(mapData))
- .addClass('mapster_el')
- .css(m.canvas_style)[0];
- },
-
- /**
- * Add a group of shapes from an AreaData object to the canvas
- *
- * @param {AreaData} areaData An AreaData object (a set of area elements)
- * @param {string} mode The rendering mode, "select" or "highlight". This determines the target
- * canvas and which default options to use.
- * @param {striong} options Rendering options
- */
-
- addShapeGroup: function (areaData, mode,options) {
- // render includeKeys first - because they could be masks
- var me = this,
- list, name, canvas,
- map_data = this.map_data,
- opts = areaData.effectiveRenderOptions(mode);
-
- if (options) {
- $.extend(opts,options);
- }
-
- if (mode === 'select') {
- name = "static_" + areaData.areaId.toString();
- canvas = map_data.base_canvas;
- } else {
- canvas = map_data.overlay_canvas;
- }
-
- me.begin(canvas, name);
-
- if (opts.includeKeys) {
- list = u.split(opts.includeKeys);
- $.each(list, function (i,e) {
- var areaData = map_data.getDataForKey(e.toString());
- addShapeGroupImpl(me,areaData, areaData.effectiveRenderOptions(mode));
- });
- }
-
- addShapeGroupImpl(me,areaData, opts);
- me.render();
- if (opts.fade) {
-
- // fading requires special handling for IE. We must access the fill elements directly. The fader also has to deal with
- // the "opacity" attribute (not css)
-
- u.fader(m.hasCanvas() ?
- canvas :
- $(canvas).find('._fill').not('.mapster_mask'),
- 0,
- m.hasCanvas() ?
- 1 :
- opts.fillOpacity,
- opts.fadeDuration);
-
- }
-
- }
-
- // These prototype methods are implementation dependent
- };
-
- function noop() {}
-
-
- // configure remaining prototype methods for ie or canvas-supporting browser
-
- canvasMethods = {
- renderShape: function (context, mapArea, offset) {
- var i,
- c = mapArea.coords(null,offset);
-
- switch (mapArea.shape) {
- case 'rect':
- context.rect(c[0], c[1], c[2] - c[0], c[3] - c[1]);
- break;
- case 'poly':
- context.moveTo(c[0], c[1]);
-
- for (i = 2; i < mapArea.length; i += 2) {
- context.lineTo(c[i], c[i + 1]);
- }
- context.lineTo(c[0], c[1]);
- break;
- case 'circ':
- case 'circle':
- context.arc(c[0], c[1], c[2], 0, Math.PI * 2, false);
- break;
- }
- },
- addAltImage: function (context, image, mapArea, options) {
- context.beginPath();
-
- this.renderShape(context, mapArea);
- context.closePath();
- context.clip();
-
- context.globalAlpha = options.altImageOpacity || options.fillOpacity;
-
- context.drawImage(image, 0, 0, mapArea.owner.scaleInfo.width, mapArea.owner.scaleInfo.height);
- },
- render: function () {
- // firefox 6.0 context.save() seems to be broken. to work around, we have to draw the contents on one temp canvas,
- // the mask on another, and merge everything. ugh. fixed in 1.2.2. unfortunately this is a lot more code for masks,
- // but no other way around it that i can see.
-
- var maskCanvas, maskContext,
- me = this,
- md = me.map_data,
- hasMasks = me.masks.length,
- shapeCanvas = me.createCanvasFor(md),
- shapeContext = shapeCanvas.getContext('2d'),
- context = me.canvas.getContext('2d');
-
- if (hasMasks) {
- maskCanvas = me.createCanvasFor(md);
- maskContext = maskCanvas.getContext('2d');
- maskContext.clearRect(0, 0, maskCanvas.width, maskCanvas.height);
-
- $.each(me.masks, function (i,e) {
- maskContext.save();
- maskContext.beginPath();
- me.renderShape(maskContext, e.mapArea);
- maskContext.closePath();
- maskContext.clip();
- maskContext.lineWidth = 0;
- maskContext.fillStyle = '#000';
- maskContext.fill();
- maskContext.restore();
- });
-
- }
-
- $.each(me.shapes, function (i,s) {
- shapeContext.save();
- if (s.options.fill) {
- if (s.options.altImageId) {
- me.addAltImage(shapeContext, md.images[s.options.altImageId], s.mapArea, s.options);
- } else {
- shapeContext.beginPath();
- me.renderShape(shapeContext, s.mapArea);
- shapeContext.closePath();
- //shapeContext.clip();
- shapeContext.fillStyle = css3color(s.options.fillColor, s.options.fillOpacity);
- shapeContext.fill();
- }
- }
- shapeContext.restore();
- });
-
-
- // render strokes at end since masks get stroked too
-
- $.each(me.shapes.concat(me.masks), function (i,s) {
- var offset = s.options.strokeWidth === 1 ? 0.5 : 0;
- // offset applies only when stroke width is 1 and stroke would render between pixels.
-
- if (s.options.stroke) {
- shapeContext.save();
- shapeContext.strokeStyle = css3color(s.options.strokeColor, s.options.strokeOpacity);
- shapeContext.lineWidth = s.options.strokeWidth;
-
- shapeContext.beginPath();
-
- me.renderShape(shapeContext, s.mapArea, offset);
- shapeContext.closePath();
- shapeContext.stroke();
- shapeContext.restore();
- }
- });
-
- if (hasMasks) {
- // render the new shapes against the mask
-
- maskContext.globalCompositeOperation = "source-out";
- maskContext.drawImage(shapeCanvas, 0, 0);
-
- // flatten into the main canvas
- context.drawImage(maskCanvas, 0, 0);
- } else {
- context.drawImage(shapeCanvas, 0, 0);
- }
-
- me.active = false;
- return me.canvas;
- },
-
- // create a canvas mimicing dimensions of an existing element
- createCanvasFor: function (md) {
- return $(' ')[0];
- },
- clearHighlight: function () {
- var c = this.map_data.overlay_canvas;
- c.getContext('2d').clearRect(0, 0, c.width, c.height);
- },
- // Draw all items from selected_list to a new canvas, then swap with the old one. This is used to delete items when using canvases.
- refreshSelections: function () {
- var canvas_temp, map_data = this.map_data;
- // draw new base canvas, then swap with the old one to avoid flickering
- canvas_temp = map_data.base_canvas;
-
- map_data.base_canvas = this.createVisibleCanvas(map_data);
- $(map_data.base_canvas).hide();
- $(canvas_temp).before(map_data.base_canvas);
-
- map_data.redrawSelections();
-
- $(map_data.base_canvas).show();
- $(canvas_temp).remove();
- }
- };
-
- vmlMethods = {
-
- renderShape: function (mapArea, options, cssclass) {
- var me = this, fill,stroke, e, t_fill, el_name, el_class, template, c = mapArea.coords();
- el_name = me.elementName ? 'name="' + me.elementName + '" ' : '';
- el_class = cssclass ? 'class="' + cssclass + '" ' : '';
-
- t_fill = ' ';
-
-
- stroke = options.stroke ?
- ' strokeweight=' + options.strokeWidth + ' stroked="t" strokecolor="#' +
- options.strokeColor + '"' :
- ' stroked="f"';
-
- fill = options.fill ?
- ' filled="t"' :
- ' filled="f"';
-
- switch (mapArea.shape) {
- case 'rect':
- template = '' + t_fill + ' ';
- break;
- case 'poly':
- template = '' + t_fill + ' ';
- break;
- case 'circ':
- case 'circle':
- template = '' + t_fill + ' ';
- break;
- }
- e = $(template);
- $(me.canvas).append(e);
-
- return e;
- },
- render: function () {
- var opts, me = this;
-
- $.each(this.shapes, function (i,e) {
- me.renderShape(e.mapArea, e.options);
- });
-
- if (this.masks.length) {
- $.each(this.masks, function (i,e) {
- opts = u.updateProps({},
- e.options, {
- fillOpacity: 1,
- fillColor: e.options.fillColorMask
- });
- me.renderShape(e.mapArea, opts, 'mapster_mask');
- });
- }
-
- this.active = false;
- return this.canvas;
- },
-
- createCanvasFor: function (md) {
- var w = md.scaleInfo.width,
- h = md.scaleInfo.height;
- return $(' ')[0];
- },
-
- clearHighlight: function () {
- $(this.map_data.overlay_canvas).children().remove();
- },
- // remove single or all selections
- removeSelections: function (area_id) {
- if (area_id >= 0) {
- $(this.map_data.base_canvas).find('[name="static_' + area_id.toString() + '"]').remove();
- }
- else {
- $(this.map_data.base_canvas).children().remove();
- }
- }
-
- };
-
- // for all methods with two implemenatations, add a function that will automatically replace itself with the correct
- // method on first invocation
-
- $.each(['renderShape',
- 'addAltImage',
- 'render',
- 'createCanvasFor',
- 'clearHighlight',
- 'removeSelections',
- 'refreshSelections'],
- function(i,e) {
- p[e]=(function(method) {
- return function() {
- p[method] = (m.hasCanvas() ?
- canvasMethods[method] :
- vmlMethods[method]) || noop;
-
- return p[method].apply(this,arguments);
- };
- }(e));
- });
-
-
-} (jQuery));
-
-/* mapimage.js
- the MapImage object, repesents an instance of a single bound imagemap
+ else {
+ jQuery = require('jquery')(root);
+ }
+ }
+ factory(jQuery);
+ return jQuery;
+ };
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function (jQuery) {
+ /*
+ jqueryextensions.js
+ Extend/intercept jquery behavior
*/
(function ($) {
-
- var m = $.mapster,
- u = m.utils,
- ap=[];
- /**
- * An object encapsulating all the images used by a MapData.
- */
-
- m.MapImages = function(owner) {
- this.owner = owner;
- this.clear();
+ 'use strict';
+
+ // Test via a getter in the options object to see if the passive property is accessed
+ var supportsPassive = false;
+ try {
+ var opts = Object.defineProperty({}, 'passive', {
+ get: function () {
+ supportsPassive = true;
+ return true;
+ }
+ });
+ window.addEventListener('testPassive.mapster', function () {}, opts);
+ window.removeEventListener('testPassive.mapster', function () {}, opts);
+ } catch (e) {
+ // intentionally ignored
+ }
+
+ if (supportsPassive) {
+ // In order to not interrupt scrolling on touch devices
+ // we commit to not calling preventDefault from within listeners
+ // There is a plan to handle this natively in jQuery 4.0 but for
+ // now we are on our own.
+ // TODO: Migrate to jQuery 4.0 approach if/when released
+ // https://www.chromestatus.com/feature/5745543795965952
+ // https://github.com/WICG/EventListenerOptions/blob/gh-pages/explainer.md
+ // https://github.com/jquery/jquery/issues/2871#issuecomment-175175180
+ // https://jsbin.com/bupesajoza/edit?html,js,output
+ var setupListener = function (ns, type, listener) {
+ if (ns.includes('noPreventDefault')) {
+ window.addEventListener(type, listener, { passive: true });
+ } else {
+ console.warn('non-passive events - listener not added');
+ return false;
+ }
};
+ // special events for noPreventDefault
+ $.event.special.touchstart = {
+ setup: function (_, ns, listener) {
+ return setupListener(ns, 'touchstart', listener);
+ }
+ };
+ $.event.special.touchend = {
+ setup: function (_, ns, listener) {
+ return setupListener(ns, 'touchend', listener);
+ }
+ };
+ }
+})(jQuery);
- m.MapImages.prototype = {
- constructor: m.MapImages,
-
- /* interface to make this array-like */
-
- slice: function() {
- return ap.slice.apply(this,arguments);
- },
- splice: function() {
- ap.slice.apply(this.status,arguments);
- var result= ap.slice.apply(this,arguments);
- return result;
- },
-
- /**
- * a boolean value indicates whether all images are done loading
- * @return {bool} true when all are done
- */
- complete: function() {
- return $.inArray(false, this.status) < 0;
- },
-
- /**
- * Save an image in the images array and return its index
- * @param {Image} image An Image object
- * @return {int} the index of the image
- */
+/*
+ core.js
+ ImageMapster core
+*/
- _add: function(image) {
- var index = ap.push.call(this,image)-1;
- this.status[index] = false;
- return index;
- },
+(function ($) {
+ 'use strict';
- /**
- * Return the index of an Image within the images array
- * @param {Image} img An Image
- * @return {int} the index within the array, or -1 if it was not found
- */
+ var mapster_version = '1.3.2-beta.0';
- indexOf: function(image) {
- return u.indexOf(this,image);
+ // all public functions in $.mapster.impl are methods
+ $.fn.mapster = function (method) {
+ var m = $.mapster.impl;
+ if ($.mapster.utils.isFunction(m[method])) {
+ return m[method].apply(this, Array.prototype.slice.call(arguments, 1));
+ } else if (typeof method === 'object' || !method) {
+ return m.bind.apply(this, arguments);
+ } else {
+ $.error('Method ' + method + ' does not exist on jQuery.mapster');
+ }
+ };
+
+ $.mapster = {
+ version: mapster_version,
+ render_defaults: {
+ isSelectable: true,
+ isDeselectable: true,
+ fade: false,
+ fadeDuration: 150,
+ fill: true,
+ fillColor: '000000',
+ fillColorMask: 'FFFFFF',
+ fillOpacity: 0.7,
+ highlight: true,
+ stroke: false,
+ strokeColor: 'ff0000',
+ strokeOpacity: 1,
+ strokeWidth: 1,
+ includeKeys: '',
+ altImage: null,
+ altImageId: null, // used internally
+ altImages: {}
+ },
+ defaults: {
+ clickNavigate: false,
+ wrapClass: null,
+ wrapCss: null,
+ onGetList: null,
+ sortList: false,
+ listenToList: false,
+ mapKey: '',
+ mapValue: '',
+ singleSelect: false,
+ listKey: 'value',
+ listSelectedAttribute: 'selected',
+ listSelectedClass: null,
+ onClick: null,
+ onMouseover: null,
+ onMouseout: null,
+ mouseoutDelay: 0,
+ onStateChange: null,
+ boundList: null,
+ onConfigured: null,
+ configTimeout: 30000,
+ noHrefIsMask: true,
+ scaleMap: true,
+ safeLoad: false,
+ areas: []
+ },
+ shared_defaults: {
+ render_highlight: { fade: true },
+ render_select: { fade: false },
+ staticState: null,
+ selected: null
+ },
+ area_defaults: {
+ includeKeys: '',
+ isMask: false
+ },
+ canvas_style: {
+ position: 'absolute',
+ left: 0,
+ top: 0,
+ padding: 0,
+ border: 0
+ },
+ hasCanvas: null,
+ map_cache: [],
+ hooks: {},
+ addHook: function (name, callback) {
+ this.hooks[name] = (this.hooks[name] || []).push(callback);
+ },
+ callHooks: function (name, context) {
+ $.each(this.hooks[name] || [], function (_, e) {
+ e.apply(context);
+ });
+ },
+ utils: {
+ when: {
+ all: function (deferredArray) {
+ // TODO: Promise breaks ES5 support
+ // eslint-disable-next-line no-undef
+ return Promise.all(deferredArray);
},
-
- /**
- * Clear this object and reset it to its initial state after binding.
- */
-
- clear: function() {
- var me=this;
-
- if (me.ids && me.ids.length>0) {
- $.each(me.ids,function(i,e) {
- delete me[e];
- });
+ defer: function () {
+ // Deferred is frequently referred to as an anti-pattern largely
+ // due to error handling, however to avoid reworking existing
+ // APIs and support backwards compat, creating a "deferred"
+ // polyfill via native promise
+ var Deferred = function () {
+ // TODO: Promise breaks ES5 support
+ // eslint-disable-next-line no-undef
+ this.promise = new Promise(
+ function (resolve, reject) {
+ this.resolve = resolve;
+ this.reject = reject;
+ }.bind(this)
+ );
+
+ this.then = this.promise.then.bind(this.promise);
+ this.catch = this.promise.catch.bind(this.promise);
+ };
+ return new Deferred();
+ }
+ },
+ defer: function () {
+ return this.when.defer();
+ },
+ // extends the constructor, returns a new object prototype. Does not refer to the
+ // original constructor so is protected if the original object is altered. This way you
+ // can "extend" an object by replacing it with its subclass.
+ subclass: function (BaseClass, constr) {
+ var Subclass = function () {
+ var me = this,
+ args = Array.prototype.slice.call(arguments, 0);
+ me.base = BaseClass.prototype;
+ me.base.init = function () {
+ BaseClass.prototype.constructor.apply(me, args);
+ };
+ constr.apply(me, args);
+ };
+ Subclass.prototype = new BaseClass();
+ Subclass.prototype.constructor = Subclass;
+ return Subclass;
+ },
+ asArray: function (obj) {
+ return obj.constructor === Array ? obj : this.split(obj);
+ },
+ // clean split: no padding or empty elements
+ split: function (text, cb) {
+ var i,
+ el,
+ arr = text.split(',');
+ for (i = 0; i < arr.length; i++) {
+ // backwards compat for $.trim which would return empty string on null
+ // which theoertically should not happen here
+ el = arr[i] ? arr[i].trim() : '';
+ if (el === '') {
+ arr.splice(i, 1);
+ } else {
+ arr[i] = cb ? cb(el) : el;
+ }
+ }
+ return arr;
+ },
+ // similar to $.extend but does not add properties (only updates), unless the
+ // first argument is an empty object, then all properties will be copied
+ updateProps: function (_target, _template) {
+ var onlyProps,
+ target = _target || {},
+ template = $.isEmptyObject(target) ? _template : _target;
+
+ //if (template) {
+ onlyProps = [];
+ $.each(template, function (prop) {
+ onlyProps.push(prop);
+ });
+ //}
+
+ $.each(Array.prototype.slice.call(arguments, 1), function (_, src) {
+ $.each(src || {}, function (prop) {
+ if (!onlyProps || $.inArray(prop, onlyProps) >= 0) {
+ var p = src[prop];
+
+ if ($.isPlainObject(p)) {
+ // not recursive - only copies 1 level of subobjects, and always merges
+ target[prop] = $.extend(target[prop] || {}, p);
+ } else if (p && p.constructor === Array) {
+ target[prop] = p.slice(0);
+ } else if (typeof p !== 'undefined') {
+ target[prop] = src[prop];
+ }
}
-
- /**
- * A list of the cross-reference IDs bound to this object
- * @type {string[]}
- */
-
- me.ids=[];
-
- /**
- * Length property for array-like behavior, set to zero when initializing. Array prototype
- * methods will update it after that.
- *
- * @type {int}
- */
-
- me.length=0;
-
- /**
- * the loaded status of the corresponding image
- * @type {boolean[]}
- */
-
- me.status=[];
-
-
- // actually erase the images
-
- me.splice(0);
-
- },
-
- /**
- * Bind an image to the map and add it to the queue to be loaded; return an ID that
- * can be used to reference the
- *
- * @param {Image|string} image An Image object or a URL to an image
- * @param {string} [id] An id to refer to this image
- * @returns {int} an ID referencing the index of the image object in
- * map_data.images
- */
-
- add: function(image,id) {
- var index,src,me = this;
-
- if (!image) { return; }
-
- if (typeof image === 'string') {
- src = image;
- image = me[src];
- if (typeof image==='object') {
- return me.indexOf(image);
- }
-
- image = $(' ')
- .addClass('mapster_el')
- .hide();
-
- index=me._add(image[0]);
-
- image
- .on('load',function(e) {
- me.imageLoaded.call(me,e);
- })
- .on('error',function(e) {
- me.imageLoadError.call(me,e);
- });
-
- image.attr('src', src);
- } else {
-
- // use attr because we want the actual source, not the resolved path the browser will return directly calling image.src
-
- index=me._add($(image)[0]);
+ });
+ });
+ return target;
+ },
+ isElement: function (o) {
+ return typeof HTMLElement === 'object'
+ ? o instanceof HTMLElement
+ : o &&
+ typeof o === 'object' &&
+ o.nodeType === 1 &&
+ typeof o.nodeName === 'string';
+ },
+ /**
+ * Basic indexOf implementation for IE7-8. Though we use $.inArray, some jQuery versions will try to
+ * use a prototpye on the calling object, defeating the purpose of using $.inArray in the first place.
+ *
+ * This will be replaced with the array prototype if it's available.
+ *
+ * @param {Array} arr The array to search
+ * @param {Object} target The item to search for
+ * @return {Number} The index of the item, or -1 if not found
+ */
+ indexOf: function (arr, target) {
+ if (Array.prototype.indexOf) {
+ return Array.prototype.indexOf.call(arr, target);
+ } else {
+ for (var i = 0; i < arr.length; i++) {
+ if (arr[i] === target) {
+ return i;
}
- if (id) {
- if (this[id]) {
- throw(id+" is already used or is not available as an altImage alias.");
- }
- me.ids.push(id);
- me[id]=me[index];
+ }
+ return -1;
+ }
+ },
+
+ // finds element of array or object with a property "prop" having value "val"
+ // if prop is not defined, then just looks for property with value "val"
+ indexOfProp: function (obj, prop, val) {
+ var result = obj.constructor === Array ? -1 : null;
+ $.each(obj, function (i, e) {
+ if (e && (prop ? e[prop] : e) === val) {
+ result = i;
+ return false;
+ }
+ });
+ return result;
+ },
+ // returns "obj" if true or false, or "def" if not true/false
+ boolOrDefault: function (obj, def) {
+ return this.isBool(obj) ? obj : def || false;
+ },
+ isBool: function (obj) {
+ return typeof obj === 'boolean';
+ },
+ isUndef: function (obj) {
+ return typeof obj === 'undefined';
+ },
+ isFunction: function (obj) {
+ return typeof obj === 'function';
+ },
+ // evaluates "obj", if function, calls it with args
+ // (todo - update this to handle variable lenght/more than one arg)
+ ifFunction: function (obj, that, args) {
+ if (this.isFunction(obj)) {
+ obj.call(that, args);
+ }
+ },
+ size: function (image, raw) {
+ var u = $.mapster.utils;
+ return {
+ width: raw
+ ? image.width || image.naturalWidth
+ : u.imgWidth(image, true),
+ height: raw
+ ? image.height || image.naturalHeight
+ : u.imgHeight(image, true),
+ complete: function () {
+ return !!this.height && !!this.width;
+ }
+ };
+ },
+
+ /**
+ * Set the opacity of the element. This is an IE<8 specific function for handling VML.
+ * When using VML we must override the "setOpacity" utility function (monkey patch ourselves).
+ * jQuery does not deal with opacity correctly for VML elements. This deals with that.
+ *
+ * @param {Element} el The DOM element
+ * @param {double} opacity A value between 0 and 1 inclusive.
+ */
+
+ setOpacity: function (el, opacity) {
+ if ($.mapster.hasCanvas()) {
+ el.style.opacity = opacity;
+ } else {
+ $(el).each(function (_, e) {
+ if (typeof e.opacity !== 'undefined') {
+ e.opacity = opacity;
+ } else {
+ $(e).css('opacity', opacity);
}
- return index;
- },
-
- /**
- * Bind the images in this object,
- * @param {boolean} retry when true, indicates that the function is calling itself after failure
- * @return {Promise} a promise that resolves when the images have finished loading
- */
-
- bind: function(retry) {
- var me = this,
- promise,
- triesLeft = me.owner.options.configTimeout / 200,
-
- /* A recursive function to continue checking that the images have been
- loaded until a timeout has elapsed */
-
- check=function() {
- var i;
-
- // refresh status of images
-
- i=me.length;
-
- while (i-->0) {
- if (!me.isLoaded(i)) {
- break;
- }
- }
-
- // check to see if every image has already been loaded
-
- if (me.complete()) {
- me.resolve();
- } else {
- // to account for failure of onLoad to fire in rare situations
- if (triesLeft-- > 0) {
- me.imgTimeout=window.setTimeout(function() {
- check.call(me,true);
- }, 50);
- } else {
- me.imageLoadError.call(me);
- }
- }
-
- };
-
- promise = me.deferred=u.defer();
-
- check();
- return promise;
- },
-
- resolve: function() {
- var me=this,
- resolver=me.deferred;
-
- if (resolver) {
- // Make a copy of the resolver before calling & removing it to ensure
- // it is not called twice
- me.deferred=null;
- resolver.resolve();
+ });
+ }
+ },
+
+ // fade "el" from opacity "op" to "endOp" over a period of time "duration"
+
+ fader: (function () {
+ var elements = {},
+ lastKey = 0,
+ fade_func = function (el, op, endOp, duration) {
+ var index,
+ cbIntervals = duration / 15,
+ obj,
+ u = $.mapster.utils;
+
+ if (typeof el === 'number') {
+ obj = elements[el];
+ if (!obj) {
+ return;
+ }
+ } else {
+ index = u.indexOfProp(elements, null, el);
+ if (index) {
+ delete elements[index];
+ }
+ elements[++lastKey] = obj = el;
+ el = lastKey;
}
- },
-
- /**
- * Event handler for image onload
- * @param {object} e jQuery event data
- */
- imageLoaded: function(e) {
- var me=this,
- index = me.indexOf(e.target);
+ endOp = endOp || 1;
- if (index>=0) {
+ op =
+ op + endOp / cbIntervals > endOp - 0.01
+ ? endOp
+ : op + endOp / cbIntervals;
- me.status[index] = true;
- if ($.inArray(false, me.status) < 0) {
- me.resolve();
- }
- }
- },
-
- /**
- * Event handler for onload error
- * @param {object} e jQuery event data
- */
-
- imageLoadError: function(e) {
- clearTimeout(this.imgTimeout);
- this.triesLeft=0;
- var err = e ? 'The image ' + e.target.src + ' failed to load.' :
- 'The images never seemed to finish loading. You may just need to increase the configTimeout if images could take a long time to load.';
- throw err;
- },
- /**
- * Test if the image at specificed index has finished loading
- * @param {int} index The image index
- * @return {boolean} true if loaded, false if not
- */
-
- isLoaded: function(index) {
- var img,
- me=this,
- status=me.status;
-
- if (status[index]) { return true; }
- img = me[index];
-
- if (typeof img.complete !== 'undefined') {
- status[index]=img.complete;
- } else {
- status[index]=!!u.imgWidth(img);
+ u.setOpacity(obj, op);
+ if (op < endOp) {
+ setTimeout(function () {
+ fade_func(el, op, endOp, duration);
+ }, 15);
}
- // if complete passes, the image is loaded, but may STILL not be available because of stuff like adblock.
- // make sure it is.
-
- return status[index];
+ };
+ return fade_func;
+ })()
+ },
+ getBoundList: function (opts, key_list) {
+ if (!opts.boundList) {
+ return null;
+ }
+ var index,
+ key,
+ result = $(),
+ list = $.mapster.utils.split(key_list);
+ opts.boundList.each(function (_, e) {
+ for (index = 0; index < list.length; index++) {
+ key = list[index];
+ if ($(e).is('[' + opts.listKey + '="' + key + '"]')) {
+ result = result.add(e);
+ }
}
- };
- } (jQuery));
-
-/* mapdata.js
- the MapData object, repesents an instance of a single bound imagemap
-*/
-
-
-(function ($) {
-
- var m = $.mapster,
- u = m.utils;
-
+ });
+ return result;
+ },
+ // Causes changes to the bound list based on the user action (select or deselect)
+ // area: the jQuery area object
+ // returns the matching elements from the bound list for the first area passed (normally only one should be passed, but
+ // a list can be passed
+ setBoundListProperties: function (opts, target, selected) {
+ target.each(function (_, e) {
+ if (opts.listSelectedClass) {
+ if (selected) {
+ $(e).addClass(opts.listSelectedClass);
+ } else {
+ $(e).removeClass(opts.listSelectedClass);
+ }
+ }
+ if (opts.listSelectedAttribute) {
+ $(e).prop(opts.listSelectedAttribute, selected);
+ }
+ });
+ },
+ getMapDataIndex: function (obj) {
+ var img, id;
+ switch (obj.tagName && obj.tagName.toLowerCase()) {
+ case 'area':
+ id = $(obj).parent().attr('name');
+ img = $("img[usemap='#" + id + "']")[0];
+ break;
+ case 'img':
+ img = obj;
+ break;
+ }
+ return img ? this.utils.indexOfProp(this.map_cache, 'image', img) : -1;
+ },
+ getMapData: function (obj) {
+ var index = this.getMapDataIndex(obj.length ? obj[0] : obj);
+ if (index >= 0) {
+ return index >= 0 ? this.map_cache[index] : null;
+ }
+ },
/**
- * Set default values for MapData object properties
- * @param {MapData} me The MapData object
+ * Queue a command to be run after the active async operation has finished
+ * @param {MapData} map_data The target MapData object
+ * @param {jQuery} that jQuery object on which the command was invoked
+ * @param {string} command the ImageMapster method name
+ * @param {object[]} args arguments passed to the method
+ * @return {bool} true if the command was queued, false if not (e.g. there was no need to)
*/
-
- function initializeDefaults(me) {
- $.extend(me,{
- complete: false, // (bool) when configuration is complete
- map: null, // ($) the image map
- base_canvas: null, // (canvas|var) where selections are rendered
- overlay_canvas: null, // (canvas|var) where highlights are rendered
- commands: [], // {} commands that were run before configuration was completed (b/c images weren't loaded)
- data: [], // MapData[] area groups
- mapAreas: [], // MapArea[] list. AreaData entities contain refs to this array, so options are stored with each.
- _xref: {}, // (int) xref of mapKeys to data[]
- highlightId: -1, // (int) the currently highlighted element.
- currentAreaId: -1,
- _tooltip_events: [], // {} info on events we bound to a tooltip container, so we can properly unbind them
- scaleInfo: null, // {} info about the image size, scaling, defaults
- index: -1, // index of this in map_cache - so we have an ID to use for wraper div
- activeAreaEvent: null
+ queueCommand: function (map_data, that, command, args) {
+ if (!map_data) {
+ return false;
+ }
+ if (!map_data.complete || map_data.currentAction) {
+ map_data.commands.push({
+ that: that,
+ command: command,
+ args: args
});
+ return true;
+ }
+ return false;
+ },
+ unload: function () {
+ this.impl.unload();
+ this.utils = null;
+ this.impl = null;
+ $.fn.mapster = null;
+ $.mapster = null;
+ $('*').off();
}
+ };
+
+ // Config for object prototypes
+ // first: use only first object (for things that should not apply to lists)
+ /// calls back one of two fuinctions, depending on whether an area was obtained.
+ // opts: {
+ // name: 'method name',
+ // key: 'key,
+ // args: 'args'
+ //
+ //}
+ // name: name of method (required)
+ // args: arguments to re-call with
+ // Iterates through all the objects passed, and determines whether it's an area or an image, and calls the appropriate
+ // callback for each. If anything is returned from that callback, the process is stopped and that data return. Otherwise,
+ // the object itself is returned.
+
+ var m = $.mapster,
+ u = m.utils,
+ ap = Array.prototype;
+
+ // jQuery's width() and height() are broken on IE9 in some situations. This tries everything.
+ $.each(['width', 'height'], function (_, e) {
+ var capProp = e.substr(0, 1).toUpperCase() + e.substr(1);
+ // when jqwidth parm is passed, it also checks the jQuery width()/height() property
+ // the issue is that jQUery width() can report a valid size before the image is loaded in some browsers
+ // without it, we can read zero even when image is loaded in other browsers if its not visible
+ // we must still check because stuff like adblock can temporarily block it
+ // what a goddamn headache
+ u['img' + capProp] = function (img, jqwidth) {
+ return (
+ (jqwidth ? $(img)[e]() : 0) ||
+ img[e] ||
+ img['natural' + capProp] ||
+ img['client' + capProp] ||
+ img['offset' + capProp]
+ );
+ };
+ });
+
+ /**
+ * The Method object encapsulates the process of testing an ImageMapster method to see if it's being
+ * invoked on an image, or an area; then queues the command if the MapData is in an active state.
+ *
+ * @param {[jQuery]} that The target of the invocation
+ * @param {[function]} func_map The callback if the target is an imagemap
+ * @param {[function]} func_area The callback if the target is an area
+ * @param {[object]} opt Options: { key: a map key if passed explicitly
+ * name: the command name, if it can be queued,
+ * args: arguments to the method
+ * }
+ */
+
+ m.Method = function (that, func_map, func_area, opts) {
+ var me = this;
+ me.name = opts.name;
+ me.output = that;
+ me.input = that;
+ me.first = opts.first || false;
+ me.args = opts.args ? ap.slice.call(opts.args, 0) : [];
+ me.key = opts.key;
+ me.func_map = func_map;
+ me.func_area = func_area;
+ //$.extend(me, opts);
+ me.name = opts.name;
+ me.allowAsync = opts.allowAsync || false;
+ };
+ m.Method.prototype = {
+ constructor: m.Method,
+ go: function () {
+ var i,
+ data,
+ ar,
+ len,
+ result,
+ src = this.input,
+ area_list = [],
+ me = this;
+
+ len = src.length;
+ for (i = 0; i < len; i++) {
+ data = $.mapster.getMapData(src[i]);
+ if (data) {
+ if (
+ !me.allowAsync &&
+ m.queueCommand(data, me.input, me.name, me.args)
+ ) {
+ if (this.first) {
+ result = '';
+ }
+ continue;
+ }
- /**
- * Return an array of all image-containing options from an options object;
- * that is, containers that may have an "altImage" property
- *
- * @param {object} obj An options object
- * @return {object[]} An array of objects
- */
- function getOptionImages(obj) {
- return [obj, obj.render_highlight, obj.render_select];
+ ar = data.getData(src[i].nodeName === 'AREA' ? src[i] : this.key);
+ if (ar) {
+ if ($.inArray(ar, area_list) < 0) {
+ area_list.push(ar);
+ }
+ } else {
+ result = this.func_map.apply(data, me.args);
+ }
+ if (this.first || typeof result !== 'undefined') {
+ break;
+ }
+ }
+ }
+ // if there were areas, call the area function for each unique group
+ $(area_list).each(function (_, e) {
+ result = me.func_area.apply(e, me.args);
+ });
+
+ if (typeof result !== 'undefined') {
+ return result;
+ } else {
+ return this.output;
+ }
}
+ };
+
+ $.mapster.impl = (function () {
+ var me = {},
+ addMap = function (map_data) {
+ return m.map_cache.push(map_data) - 1;
+ },
+ removeMap = function (map_data) {
+ m.map_cache.splice(map_data.index, 1);
+ for (var i = m.map_cache.length - 1; i >= map_data.index; i--) {
+ m.map_cache[i].index--;
+ }
+ };
/**
- * Parse all the altImage references, adding them to the library so they can be preloaded
- * and aliased.
+ * Test whether the browser supports VML. Credit: google.
+ * http://stackoverflow.com/questions/654112/how-do-you-detect-support-for-vml-or-svg-in-a-browser
*
- * @param {MapData} me The MapData object on which to operate
+ * @return {bool} true if vml is supported, false if not
*/
- function configureAltImages(me)
- {
- var opts = me.options,
- mi = me.images;
-
- // add alt images
-
- if (m.hasCanvas()) {
- // map altImage library first
- $.each(opts.altImages || {}, function(i,e) {
- mi.add(e,i);
- });
-
- // now find everything else
-
- $.each([opts].concat(opts.areas),function(i,e) {
- $.each(getOptionImages(e),function(i2,e2) {
- if (e2 && e2.altImage) {
- e2.altImageId=mi.add(e2.altImage);
- }
- });
- });
- }
+ function hasVml() {
+ var a = $('
').appendTo('body');
+ a.html(' ');
- // set area_options
- me.area_options = u.updateProps({}, // default options for any MapArea
- m.area_defaults,
- opts);
+ var b = a[0].firstChild;
+ b.style.behavior = 'url(#default#VML)';
+ var has = b ? typeof b.adj === 'object' : true;
+ a.remove();
+ return has;
}
/**
- * Queue a mouse move action based on current delay settings
- * (helper for mouseover/mouseout handlers)
- *
- * @param {MapData} me The MapData context
- * @param {number} delay The number of milliseconds to delay the action
- * @param {AreaData} area AreaData affected
- * @param {Deferred} deferred A deferred object to return (instead of a new one)
- * @return {Promise} A promise that resolves when the action is completed
+ * Return a reference to the IE namespaces object, if available, or an empty object otherwise
+ * @return {obkect} The document.namespaces object.
*/
- function queueMouseEvent(me,delay,area, deferred) {
-
- deferred = deferred || u.when.defer();
-
- function cbFinal(areaId) {
- if (me.currentAreaId!==areaId && me.highlightId>=0) {
- deferred.resolve();
- }
- }
- if (me.activeAreaEvent) {
- window.clearTimeout(me.activeAreaEvent);
- me.activeAreaEvent=0;
- }
- if (delay<0) {
- deferred.reject();
- } else {
- if (area.owner.currentAction || delay) {
- me.activeAreaEvent = window.setTimeout((function() {
- return function() {
- queueMouseEvent(me,0,area,deferred);
- };
- }(area)),
- delay || 100);
- } else {
- cbFinal(area.areaId);
- }
- }
- return deferred;
+ function namespaces() {
+ return typeof document.namespaces === 'object'
+ ? document.namespaces
+ : null;
}
- /**
- * Mousedown event. This is captured only to prevent browser from drawing an outline around an
- * area when it's clicked.
+ /**
+ * Test for the presence of HTML5 Canvas support. This also checks to see if excanvas.js has been
+ * loaded and is faking it; if so, we assume that canvas is not supported.
*
- * @param {EventData} e jQuery event data
+ * @return {bool} true if HTML5 canvas support, false if not
*/
- function mousedown(e) {
- if (!m.hasCanvas()) {
- this.blur();
- }
- e.preventDefault();
+ function hasCanvas() {
+ var d = namespaces();
+ // when g_vml_ is present, then we can be sure excanvas is active, meaning there's not a real canvas.
+
+ return d && d.g_vml_
+ ? false
+ : $(' ')[0].getContext
+ ? true
+ : false;
}
/**
- * Mouseover event. Handle highlight rendering and client callback on mouseover
+ * Merge new area data into existing area options on a MapData object. Used for rebinding.
*
- * @param {MapData} me The MapData context
- * @param {EventData} e jQuery event data
- * @return {[type]} [description]
+ * @param {[MapData]} map_data The MapData object
+ * @param {[object[]]} areas areas array to merge
*/
- function mouseover(me,e) {
- var arData = me.getAllDataForArea(this),
- ar=arData.length ? arData[0] : null;
+ function merge_areas(map_data, areas) {
+ var ar,
+ index,
+ map_areas = map_data.options.areas;
- // mouseover events are ignored entirely while resizing, though we do care about mouseout events
- // and must queue the action to keep things clean.
+ if (areas) {
+ $.each(areas, function (_, e) {
+ // Issue #68 - ignore invalid data in areas array
- if (!ar || ar.isNotRendered() || ar.owner.currentAction) {
+ if (!e || !e.key) {
return;
- }
+ }
+
+ index = u.indexOfProp(map_areas, 'key', e.key);
+
+ if (index >= 0) {
+ $.extend(map_areas[index], e);
+ } else {
+ map_areas.push(e);
+ }
+ ar = map_data.getDataForKey(e.key);
+ if (ar) {
+ $.extend(ar.options, e);
+ }
+ });
+ }
+ }
+ function merge_options(map_data, options) {
+ var temp_opts = u.updateProps({}, options);
+ delete temp_opts.areas;
- if (me.currentAreaId === ar.areaId) {
- return;
- }
- if (me.highlightId !== ar.areaId) {
- me.clearEffects();
+ u.updateProps(map_data.options, temp_opts);
- ar.highlight();
+ merge_areas(map_data, options.areas);
+ // refresh the area_option template
+ u.updateProps(map_data.area_options, map_data.options);
+ }
- if (me.options.showToolTip) {
- $.each(arData,function(i,e) {
- if (e.effectiveOptions().toolTip) {
- e.showToolTip();
- }
- });
- }
+ // Most methods use the "Method" object which handles figuring out whether it's an image or area called and
+ // parsing key parameters. The constructor wants:
+ // this, the jQuery object
+ // a function that is called when an image was passed (with a this context of the MapData)
+ // a function that is called when an area was passed (with a this context of the AreaData)
+ // options: first = true means only the first member of a jQuery object is handled
+ // key = the key parameters passed
+ // defaultReturn: a value to return other than the jQuery object (if its not chainable)
+ // args: the arguments
+ // Returns a comma-separated list of user-selected areas. "staticState" areas are not considered selected for the purposes of this method.
+
+ me.get = function (key) {
+ var md = m.getMapData(this);
+ if (!(md && md.complete)) {
+ throw "Can't access data until binding complete.";
+ }
+
+ return new m.Method(
+ this,
+ function () {
+ // map_data return
+ return this.getSelected();
+ },
+ function () {
+ return this.isSelected();
+ },
+ {
+ name: 'get',
+ args: arguments,
+ key: key,
+ first: true,
+ allowAsync: true,
+ defaultReturn: ''
}
+ ).go();
+ };
+ me.data = function (key) {
+ return new m.Method(
+ this,
+ null,
+ function () {
+ return this;
+ },
+ { name: 'data', args: arguments, key: key }
+ ).go();
+ };
- me.currentAreaId = ar.areaId;
-
- if (u.isFunction(me.options.onMouseover)) {
- me.options.onMouseover.call(this,
- {
- e: e,
- options:ar.effectiveOptions(),
- key: ar.key,
- selected: ar.isSelected()
- });
+ // Set or return highlight state.
+ // $(img).mapster('highlight') -- return highlighted area key, or null if none
+ // $(area).mapster('highlight') -- highlight an area
+ // $(img).mapster('highlight','area_key') -- highlight an area
+ // $(img).mapster('highlight',false) -- remove highlight
+ me.highlight = function (key) {
+ return new m.Method(
+ this,
+ function () {
+ if (key === false) {
+ this.ensureNoHighlight();
+ } else {
+ var id = this.highlightId;
+ return id >= 0 ? this.data[id].key : null;
+ }
+ },
+ function () {
+ this.highlight();
+ },
+ { name: 'highlight', args: arguments, key: key, first: true }
+ ).go();
+ };
+ // Return the primary keys for an area or group key.
+ // $(area).mapster('key')
+ // includes all keys (not just primary keys)
+ // $(area).mapster('key',true)
+ // $(img).mapster('key','group-key')
+
+ // $(img).mapster('key','group-key', true)
+ me.keys = function (key, all) {
+ var keyList = [],
+ md = m.getMapData(this);
+
+ if (!(md && md.complete)) {
+ throw "Can't access data until binding complete.";
+ }
+
+ function addUniqueKeys(ad) {
+ var areas,
+ keys = [];
+ if (!all) {
+ keys.push(ad.key);
+ } else {
+ areas = ad.areas();
+ $.each(areas, function (_, e) {
+ keys = keys.concat(e.keys);
+ });
}
- }
+ $.each(keys, function (_, e) {
+ if ($.inArray(e, keyList) < 0) {
+ keyList.push(e);
+ }
+ });
+ }
+
+ if (!(md && md.complete)) {
+ return '';
+ }
+ if (typeof key === 'string') {
+ if (all) {
+ addUniqueKeys(md.getDataForKey(key));
+ } else {
+ keyList = [md.getKeysForGroup(key)];
+ }
+ } else {
+ all = key;
+ this.each(function (_, e) {
+ if (e.nodeName === 'AREA') {
+ addUniqueKeys(md.getDataForArea(e));
+ }
+ });
+ }
+ return keyList.join(',');
+ };
+ me.select = function () {
+ me.set.call(this, true);
+ };
+ me.deselect = function () {
+ me.set.call(this, false);
+ };
/**
- * Mouseout event.
+ * Select or unselect areas. Areas can be identified by a single string key, a comma-separated list of keys,
+ * or an array of strings.
+ *
*
- * @param {MapData} me The MapData context
- * @param {EventData} e jQuery event data
- * @return {[type]} [description]
+ * @param {boolean} selected Determines whether areas are selected or deselected
+ * @param {string|string[]} key A string, comma-separated string, or array of strings indicating
+ * the areas to select or deselect
+ * @param {object} options Rendering options to apply when selecting an area
*/
- function mouseout(me,e) {
- var newArea,
- ar = me.getDataForArea(this),
- opts = me.options;
-
-
- if (me.currentAreaId<0 || !ar) {
- return;
+ me.set = function (selected, key, options) {
+ var lastMap,
+ map_data,
+ opts = options,
+ key_list,
+ area_list; // array of unique areas passed
+
+ function setSelection(ar) {
+ var newState = selected;
+ if (ar) {
+ switch (selected) {
+ case true:
+ ar.select(opts);
+ break;
+ case false:
+ ar.deselect(true);
+ break;
+ default:
+ newState = ar.toggle(opts);
+ break;
+ }
+ return newState;
}
-
- newArea=me.getDataForArea(e.relatedTarget);
-
- if (newArea === ar) {
- return;
+ }
+ function addArea(ar) {
+ if (ar && $.inArray(ar, area_list) < 0) {
+ area_list.push(ar);
+ key_list += (key_list === '' ? '' : ',') + ar.key;
}
-
- me.currentAreaId = -1;
- ar.area=null;
-
- queueMouseEvent(me,opts.mouseoutDelay,ar)
- .then(me.clearEffects);
-
- if (u.isFunction(opts.onMouseout)) {
- opts.onMouseout.call(this,
- {
- e: e,
- options: opts,
- key: ar.key,
- selected: ar.isSelected()
- });
+ }
+ // Clean up after a group that applied to the same map
+ function finishSetForMap(map_data) {
+ $.each(area_list, function (_, el) {
+ var newState = setSelection(el);
+ if (map_data.options.boundList) {
+ m.setBoundListProperties(
+ map_data.options,
+ m.getBoundList(map_data.options, key_list),
+ newState
+ );
+ }
+ });
+ if (!selected) {
+ map_data.removeSelectionFinish();
}
+ }
- }
-
- /**
- * Clear any active tooltip or highlight
- *
- * @param {MapData} me The MapData context
- * @param {EventData} e jQuery event data
- * @return {[type]} [description]
- */
-
- function clearEffects(me) {
- var opts = me.options;
+ this.filter('img,area').each(function (_, e) {
+ var keys;
+ map_data = m.getMapData(e);
- me.ensureNoHighlight();
+ if (map_data !== lastMap) {
+ if (lastMap) {
+ finishSetForMap(lastMap);
+ }
- if (opts.toolTipClose
- && $.inArray('area-mouseout', opts.toolTipClose) >= 0
- && me.activeToolTip)
- {
- me.clearToolTip();
+ area_list = [];
+ key_list = '';
}
- }
-
- /**
- * Mouse click event handler
- *
- * @param {MapData} me The MapData context
- * @param {EventData} e jQuery event data
- * @return {[type]} [description]
- */
-
- function click(me,e) {
- var selected, list, list_target, newSelectionState, canChangeState, cbResult,
- that = this,
- ar = me.getDataForArea(this),
- opts = me.options;
-
- function clickArea(ar) {
- var areaOpts,target;
- canChangeState = (ar.isSelectable() &&
- (ar.isDeselectable() || !ar.isSelected()));
-
- if (canChangeState) {
- newSelectionState = !ar.isSelected();
- } else {
- newSelectionState = ar.isSelected();
- }
-
- list_target = m.getBoundList(opts, ar.key);
-
- if (u.isFunction(opts.onClick))
- {
- cbResult= opts.onClick.call(that,
- {
- e: e,
- listTarget: list_target,
- key: ar.key,
- selected: newSelectionState
- });
- if (u.isBool(cbResult)) {
- if (!cbResult) {
- return false;
- }
- target = $(ar.area).attr('href');
- if (target!=='#') {
- window.location.href=target;
- return false;
- }
+ if (map_data) {
+ keys = '';
+ if (e.nodeName.toUpperCase() === 'IMG') {
+ if (!m.queueCommand(map_data, $(e), 'set', [selected, key, opts])) {
+ if (key instanceof Array) {
+ if (key.length) {
+ keys = key.join(',');
}
- }
-
- if (canChangeState) {
- selected = ar.toggle();
- }
-
- if (opts.boundList && opts.boundList.length > 0) {
- m.setBoundListProperties(opts, list_target, ar.isSelected());
- }
-
- areaOpts = ar.effectiveOptions();
- if (areaOpts.includeKeys) {
- list = u.split(areaOpts.includeKeys);
- $.each(list, function (i, e) {
- var ar = me.getDataForKey(e.toString());
- if (!ar.options.isMask) {
- clickArea(ar);
- }
+ } else {
+ keys = key;
+ }
+
+ if (keys) {
+ $.each(u.split(keys), function (_, key) {
+ addArea(map_data.getDataForKey(key.toString()));
+ lastMap = map_data;
});
+ }
+ }
+ } else {
+ opts = key;
+ if (!m.queueCommand(map_data, $(e), 'set', [selected, opts])) {
+ addArea(map_data.getDataForArea(e));
+ lastMap = map_data;
}
+ }
}
+ });
- mousedown.call(this,e);
+ if (map_data) {
+ finishSetForMap(map_data);
+ }
- if (opts.clickNavigate && ar.href) {
- window.location.href=ar.href;
- return;
- }
+ return this;
+ };
+ me.unbind = function (preserveState) {
+ return new m.Method(
+ this,
+ function () {
+ this.clearEvents();
+ this.clearMapData(preserveState);
+ removeMap(this);
+ },
+ null,
+ { name: 'unbind', args: arguments }
+ ).go();
+ };
- if (ar && !ar.owner.currentAction) {
- opts = me.options;
- clickArea(ar);
+ // refresh options and update selection information.
+ me.rebind = function (options) {
+ return new m.Method(
+ this,
+ function () {
+ var me = this;
+
+ me.complete = false;
+ me.configureOptions(options);
+ me.bindImages().then(function () {
+ me.buildDataset(true);
+ me.complete = true;
+ });
+ //this.redrawSelections();
+ },
+ null,
+ {
+ name: 'rebind',
+ args: arguments
}
- }
-
- /**
- * Prototype for a MapData object, representing an ImageMapster bound object
- * @param {Element} image an IMG element
- * @param {object} options ImageMapster binding options
- */
- m.MapData = function (image, options)
- {
- var me = this;
-
- // (Image) main map image
+ ).go();
+ };
+ // get options. nothing or false to get, or "true" to get effective options (versus passed options)
+ me.get_options = function (key, effective) {
+ var eff = u.isBool(key) ? key : effective; // allow 2nd parm as "effective" when no key
+ return new m.Method(
+ this,
+ function () {
+ var opts = $.extend({}, this.options);
+ if (eff) {
+ opts.render_select = u.updateProps(
+ {},
+ m.render_defaults,
+ opts,
+ opts.render_select
+ );
+
+ opts.render_highlight = u.updateProps(
+ {},
+ m.render_defaults,
+ opts,
+ opts.render_highlight
+ );
+ }
+ return opts;
+ },
+ function () {
+ return eff ? this.effectiveOptions() : this.options;
+ },
+ {
+ name: 'get_options',
+ args: arguments,
+ first: true,
+ allowAsync: true,
+ key: key
+ }
+ ).go();
+ };
- me.image = image;
+ // set options - pass an object with options to set,
+ me.set_options = function (options) {
+ return new m.Method(
+ this,
+ function () {
+ merge_options(this, options);
+ },
+ null,
+ {
+ name: 'set_options',
+ args: arguments
+ }
+ ).go();
+ };
+ me.unload = function () {
+ var i;
+ for (i = m.map_cache.length - 1; i >= 0; i--) {
+ if (m.map_cache[i]) {
+ me.unbind.call($(m.map_cache[i].image));
+ }
+ }
+ me.graphics = null;
+ };
- me.images = new m.MapImages(me);
- me.graphics = new m.Graphics(me);
+ me.snapshot = function () {
+ return new m.Method(
+ this,
+ function () {
+ $.each(this.data, function (_, e) {
+ e.selected = false;
+ });
- // save the initial style of the image for unbinding. This is problematic, chrome
- // duplicates styles when assigning, and cssText is apparently not universally supported.
- // Need to do something more robust to make unbinding work universally.
+ this.base_canvas = this.graphics.createVisibleCanvas(this);
+ $(this.image).before(this.base_canvas);
+ },
+ null,
+ { name: 'snapshot' }
+ ).go();
+ };
- me.imgCssText = image.style.cssText || null;
+ // do not queue this function
+
+ me.state = function () {
+ var md,
+ result = null;
+ $(this).each(function (_, e) {
+ if (e.nodeName === 'IMG') {
+ md = m.getMapData(e);
+ if (md) {
+ result = md.state();
+ }
+ return false;
+ }
+ });
+ return result;
+ };
- initializeDefaults(me);
+ me.bind = function (options) {
+ return this.each(function (_, e) {
+ var img, map, usemap, md;
- me.configureOptions(options);
+ // save ref to this image even if we can't access it yet. commands will be queued
+ img = $(e);
- // create context-bound event handlers from our private functions
+ md = m.getMapData(e);
- me.mouseover = function(e) { mouseover.call(this,me,e); };
- me.mouseout = function(e) { mouseout.call(this,me,e); };
- me.click = function(e) { click.call(this,me,e); };
- me.clearEffects = function(e) { clearEffects.call(this,me,e); };
- };
+ // if already bound completely, do a total rebind
- m.MapData.prototype = {
- constructor: m.MapData,
+ if (md) {
+ me.unbind.apply(img);
+ if (!md.complete) {
+ // will be queued
+ img.on();
+ return true;
+ }
+ md = null;
+ }
- /**
- * Set target.options from defaults + options
- * @param {[type]} target The target
- * @param {[type]} options The options to merge
- */
+ // ensure it's a valid image
+ // jQuery bug with Opera, results in full-url#usemap being returned from jQuery's attr.
+ // So use raw getAttribute instead.
- configureOptions: function(options) {
- this.options= u.updateProps({}, m.defaults, options);
- },
+ usemap = this.getAttribute('usemap');
+ map = usemap && $('map[name="' + usemap.substr(1) + '"]');
+ if (!(img.is('img') && usemap && map.length > 0)) {
+ return true;
+ }
- /**
- * Ensure all images are loaded
- * @return {Promise} A promise that resolves when the images have finished loading (or fail)
- */
+ // sorry - your image must have border:0, things are too unpredictable otherwise.
+ img.css('border', 0);
- bindImages: function() {
- var me=this,
- mi = me.images;
+ if (!md) {
+ md = new m.MapData(this, options);
- // reset the images if this is a rebind
+ md.index = addMap(md);
+ md.map = map;
+ md.bindImages().then(function () {
+ md.initialize();
+ });
+ }
+ });
+ };
- if (mi.length>2) {
- mi.splice(2);
- } else if (mi.length===0) {
+ me.init = function (useCanvas) {
+ var style, shapes;
- // add the actual main image
- mi.add(me.image);
- // will create a duplicate of the main image, we need this to get raw size info
- mi.add(me.image.src);
- }
+ // for testing/debugging, use of canvas can be forced by initializing
+ // manually with "true" or "false". But generally we test for it.
- configureAltImages(me);
+ m.hasCanvas = function () {
+ if (!u.isBool(m.hasCanvas.value)) {
+ m.hasCanvas.value = u.isBool(useCanvas) ? useCanvas : hasCanvas();
+ }
+ return m.hasCanvas.value;
+ };
+
+ m.hasVml = function () {
+ if (!u.isBool(m.hasVml.value)) {
+ // initialize VML the first time we detect its presence.
+ var d = namespaces();
+
+ if (d && !d.v) {
+ d.add('v', 'urn:schemas-microsoft-com:vml');
+ style = document.createStyleSheet();
+ shapes = [
+ 'shape',
+ 'rect',
+ 'oval',
+ 'circ',
+ 'fill',
+ 'stroke',
+ 'imagedata',
+ 'group',
+ 'textbox'
+ ];
+ $.each(shapes, function (_, el) {
+ style.addRule(
+ 'v\\:' + el,
+ 'behavior: url(#default#VML); antialias:true'
+ );
+ });
+ }
+ m.hasVml.value = hasVml();
+ }
- return me.images.bind();
- },
+ return m.hasVml.value;
+ };
- /**
- * Test whether an async action is currently in progress
- * @return {Boolean} true or false indicating state
- */
+ $.extend(m.defaults, m.render_defaults, m.shared_defaults);
+ $.extend(m.area_defaults, m.render_defaults, m.shared_defaults);
+ };
+ me.test = function (obj) {
+ return eval(obj);
+ };
+ return me;
+ })();
- isActive: function() {
- return !this.complete || this.currentAction;
- },
+ $.mapster.impl.init();
+})(jQuery);
- /**
- * Return an object indicating the various states. This isn't really used by
- * production code.
- *
- * @return {object} An object with properties for various states
- */
-
- state: function () {
- return {
- complete: this.complete,
- resizing: this.currentAction==='resizing',
- zoomed: this.zoomed,
- zoomedArea: this.zoomedArea,
- scaleInfo: this.scaleInfo
- };
- },
+/*
+ graphics.js
+ Graphics object handles all rendering.
+*/
- /**
- * Get a unique ID for the wrapper of this imagemapster
- * @return {string} A string that is unique to this image
- */
+(function ($) {
+ 'use strict';
+
+ var p,
+ m = $.mapster,
+ u = m.utils,
+ canvasMethods,
+ vmlMethods;
+
+ /**
+ * Implemenation to add each area in an AreaData object to the canvas
+ * @param {Graphics} graphics The target graphics object
+ * @param {AreaData} areaData The AreaData object (a collection of area elements and metadata)
+ * @param {object} options Rendering options to apply when rendering this group of areas
+ */
+ function addShapeGroupImpl(graphics, areaData, options) {
+ var me = graphics,
+ md = me.map_data,
+ isMask = options.isMask;
+
+ // first get area options. Then override fade for selecting, and finally merge in the
+ // "select" effect options.
+
+ $.each(areaData.areas(), function (_, e) {
+ options.isMask = isMask || (e.nohref && md.options.noHrefIsMask);
+ me.addShape(e, options);
+ });
- wrapId: function () {
- return 'mapster_wrap_' + this.index;
- },
- _idFromKey: function (key) {
- return typeof key === "string" && this._xref.hasOwnProperty(key) ?
- this._xref[key] : -1;
- },
+ // it's faster just to manipulate the passed options isMask property and restore it, than to
+ // copy the object each time
+
+ options.isMask = isMask;
+ }
+
+ /**
+ * Convert a hex value to decimal
+ * @param {string} hex A hexadecimal toString
+ * @return {int} Integer represenation of the hex string
+ */
+
+ function hex_to_decimal(hex) {
+ return Math.max(0, Math.min(parseInt(hex, 16), 255));
+ }
+ function css3color(color, opacity) {
+ return (
+ 'rgba(' +
+ hex_to_decimal(color.substr(0, 2)) +
+ ',' +
+ hex_to_decimal(color.substr(2, 2)) +
+ ',' +
+ hex_to_decimal(color.substr(4, 2)) +
+ ',' +
+ opacity +
+ ')'
+ );
+ }
+ /**
+ * An object associated with a particular map_data instance to manage renderin.
+ * @param {MapData} map_data The MapData object bound to this instance
+ */
+
+ m.Graphics = function (map_data) {
+ //$(window).unload($.mapster.unload);
+ // create graphics functions for canvas and vml browsers. usage:
+ // 1) init with map_data, 2) call begin with canvas to be used (these are separate b/c may not require canvas to be specified
+ // 3) call add_shape_to for each shape or mask, 4) call render() to finish
+
+ var me = this;
+ me.active = false;
+ me.canvas = null;
+ me.width = 0;
+ me.height = 0;
+ me.shapes = [];
+ me.masks = [];
+ me.map_data = map_data;
+ };
+
+ p = m.Graphics.prototype = {
+ constructor: m.Graphics,
- /**
- * Return a comma-separated string of all selected keys
- * @return {string} CSV of all keys that are currently selected
- */
+ /**
+ * Initiate a graphics request for a canvas
+ * @param {Element} canvas The canvas element that is the target of this operation
+ * @param {string} [elementName] The name to assign to the element (VML only)
+ */
- getSelected: function () {
- var result = '';
- $.each(this.data, function (i,e) {
- if (e.isSelected()) {
- result += (result ? ',' : '') + this.key;
- }
- });
- return result;
- },
+ begin: function (canvas, elementName) {
+ var c = $(canvas);
- /**
- * Get an array of MapAreas associated with a specific AREA based on the keys for that area
- * @param {Element} area An HTML AREA
- * @param {number} atMost A number limiting the number of areas to be returned (typically 1 or 0 for no limit)
- * @return {MapArea[]} Array of MapArea objects
- */
-
- getAllDataForArea:function (area,atMost) {
- var i,ar, result,
- me=this,
- key = $(area).filter('area').attr(me.options.mapKey);
-
- if (key) {
- result=[];
- key = u.split(key);
-
- for (i=0;i<(atMost || key.length);i++) {
- ar = me.data[me._idFromKey(key[i])];
- if (ar){
- ar.area=area.length ? area[0]:area;
- // set the actual area moused over/selected
- // TODO: this is a brittle model for capturing which specific area - if this method was not used,
- // ar.area could have old data. fix this.
- result.push(ar);
- }
- }
- }
+ this.elementName = elementName;
+ this.canvas = canvas;
- return result;
- },
- getDataForArea: function(area) {
- var ar=this.getAllDataForArea(area,1);
- return ar ? ar[0] || null : null;
- },
- getDataForKey: function (key) {
- return this.data[this._idFromKey(key)];
- },
+ this.width = c.width();
+ this.height = c.height();
+ this.shapes = [];
+ this.masks = [];
+ this.active = true;
+ },
- /**
- * Get the primary keys associated with an area group.
- * If this is a primary key, it will be returned.
- *
- * @param {string key An area key
- * @return {string} A CSV of area keys
- */
-
- getKeysForGroup: function(key) {
- var ar=this.getDataForKey(key);
-
- return !ar ? '':
- ar.isPrimary ?
- ar.key :
- this.getPrimaryKeysForMapAreas(ar.areas()).join(',');
- },
+ /**
+ * Add an area to be rendered to this canvas.
+ * @param {MapArea} mapArea The MapArea object to render
+ * @param {object} options An object containing any rendering options that should override the
+ * defaults for the area
+ */
- /**
- * given an array of MapArea object, return an array of its unique primary keys
- * @param {MapArea[]} areas The areas to analyze
- * @return {string[]} An array of unique primary keys
- */
+ addShape: function (mapArea, options) {
+ var addto = options.isMask ? this.masks : this.shapes;
+ addto.push({ mapArea: mapArea, options: options });
+ },
- getPrimaryKeysForMapAreas: function(areas)
- {
- var keys=[];
- $.each(areas,function(i,e) {
- if ($.inArray(e.keys[0],keys)<0) {
- keys.push(e.keys[0]);
- }
- });
- return keys;
- },
- getData: function (obj) {
- if (typeof obj === 'string') {
- return this.getDataForKey(obj);
- } else if (obj && obj.mapster || u.isElement(obj)) {
- return this.getDataForArea(obj);
- } else {
- return null;
- }
- },
- // remove highlight if present, raise event
- ensureNoHighlight: function () {
- var ar;
- if (this.highlightId >= 0) {
- this.graphics.clearHighlight();
- ar = this.data[this.highlightId];
- ar.changeState('highlight', false);
- this.setHighlightId(-1);
- }
- },
- setHighlightId: function(id) {
- this.highlightId = id;
- },
+ /**
+ * Create a canvas that is sized and styled for the MapData object
+ * @param {MapData} mapData The MapData object that will receive this new canvas
+ * @return {Element} A canvas element
+ */
- /**
- * Clear all active selections on this map
- */
+ createVisibleCanvas: function (mapData) {
+ return $(this.createCanvasFor(mapData))
+ .addClass('mapster_el')
+ .css(m.canvas_style)[0];
+ },
- clearSelections: function () {
- $.each(this.data, function (i,e) {
- if (e.selected) {
- e.deselect(true);
- }
- });
- this.removeSelectionFinish();
+ /**
+ * Add a group of shapes from an AreaData object to the canvas
+ *
+ * @param {AreaData} areaData An AreaData object (a set of area elements)
+ * @param {string} mode The rendering mode, "select" or "highlight". This determines the target
+ * canvas and which default options to use.
+ * @param {striong} options Rendering options
+ */
- },
+ addShapeGroup: function (areaData, mode, options) {
+ // render includeKeys first - because they could be masks
+ var me = this,
+ list,
+ name,
+ canvas,
+ map_data = this.map_data,
+ opts = areaData.effectiveRenderOptions(mode);
+
+ if (options) {
+ $.extend(opts, options);
+ }
+
+ if (mode === 'select') {
+ name = 'static_' + areaData.areaId.toString();
+ canvas = map_data.base_canvas;
+ } else {
+ canvas = map_data.overlay_canvas;
+ }
+
+ me.begin(canvas, name);
+
+ if (opts.includeKeys) {
+ list = u.split(opts.includeKeys);
+ $.each(list, function (_, e) {
+ var areaData = map_data.getDataForKey(e.toString());
+ addShapeGroupImpl(
+ me,
+ areaData,
+ areaData.effectiveRenderOptions(mode)
+ );
+ });
+ }
+
+ addShapeGroupImpl(me, areaData, opts);
+ me.render();
+ if (opts.fade) {
+ // fading requires special handling for IE. We must access the fill elements directly. The fader also has to deal with
+ // the "opacity" attribute (not css)
+
+ u.fader(
+ m.hasCanvas()
+ ? canvas
+ : $(canvas).find('._fill').not('.mapster_mask'),
+ 0,
+ m.hasCanvas() ? 1 : opts.fillOpacity,
+ opts.fadeDuration
+ );
+ }
+ }
- /**
- * Set area options from an array of option data.
- *
- * @param {object[]} areas An array of objects containing area-specific options
- */
+ // These prototype methods are implementation dependent
+ };
+
+ function noop() {}
+
+ // configure remaining prototype methods for ie or canvas-supporting browser
+
+ canvasMethods = {
+ renderShape: function (context, mapArea, offset) {
+ var i,
+ c = mapArea.coords(null, offset);
+
+ switch (mapArea.shape) {
+ case 'rect':
+ context.rect(c[0], c[1], c[2] - c[0], c[3] - c[1]);
+ break;
+ case 'poly':
+ context.moveTo(c[0], c[1]);
+
+ for (i = 2; i < mapArea.length; i += 2) {
+ context.lineTo(c[i], c[i + 1]);
+ }
+ context.lineTo(c[0], c[1]);
+ break;
+ case 'circ':
+ case 'circle':
+ context.arc(c[0], c[1], c[2], 0, Math.PI * 2, false);
+ break;
+ }
+ },
+ addAltImage: function (context, image, mapArea, options) {
+ context.beginPath();
+
+ this.renderShape(context, mapArea);
+ context.closePath();
+ context.clip();
+
+ context.globalAlpha = options.altImageOpacity || options.fillOpacity;
+
+ context.drawImage(
+ image,
+ 0,
+ 0,
+ mapArea.owner.scaleInfo.width,
+ mapArea.owner.scaleInfo.height
+ );
+ },
+ render: function () {
+ // firefox 6.0 context.save() seems to be broken. to work around, we have to draw the contents on one temp canvas,
+ // the mask on another, and merge everything. ugh. fixed in 1.2.2. unfortunately this is a lot more code for masks,
+ // but no other way around it that i can see.
+
+ var maskCanvas,
+ maskContext,
+ me = this,
+ md = me.map_data,
+ hasMasks = me.masks.length,
+ shapeCanvas = me.createCanvasFor(md),
+ shapeContext = shapeCanvas.getContext('2d'),
+ context = me.canvas.getContext('2d');
+
+ if (hasMasks) {
+ maskCanvas = me.createCanvasFor(md);
+ maskContext = maskCanvas.getContext('2d');
+ maskContext.clearRect(0, 0, maskCanvas.width, maskCanvas.height);
+
+ $.each(me.masks, function (_, e) {
+ maskContext.save();
+ maskContext.beginPath();
+ me.renderShape(maskContext, e.mapArea);
+ maskContext.closePath();
+ maskContext.clip();
+ maskContext.lineWidth = 0;
+ maskContext.fillStyle = '#000';
+ maskContext.fill();
+ maskContext.restore();
+ });
+ }
+
+ $.each(me.shapes, function (_, s) {
+ shapeContext.save();
+ if (s.options.fill) {
+ if (s.options.altImageId) {
+ me.addAltImage(
+ shapeContext,
+ md.images[s.options.altImageId],
+ s.mapArea,
+ s.options
+ );
+ } else {
+ shapeContext.beginPath();
+ me.renderShape(shapeContext, s.mapArea);
+ shapeContext.closePath();
+ //shapeContext.clip();
+ shapeContext.fillStyle = css3color(
+ s.options.fillColor,
+ s.options.fillOpacity
+ );
+ shapeContext.fill();
+ }
+ }
+ shapeContext.restore();
+ });
- setAreaOptions: function (areas) {
- var i, area_options, ar;
- areas = areas || [];
+ // render strokes at end since masks get stroked too
- // refer by: map_data.options[map_data.data[x].area_option_id]
+ $.each(me.shapes.concat(me.masks), function (_, s) {
+ var offset = s.options.strokeWidth === 1 ? 0.5 : 0;
+ // offset applies only when stroke width is 1 and stroke would render between pixels.
- for (i = areas.length - 1; i >= 0; i--) {
- area_options = areas[i];
- if (area_options) {
- ar = this.getDataForKey(area_options.key);
- if (ar) {
- u.updateProps(ar.options, area_options);
+ if (s.options.stroke) {
+ shapeContext.save();
+ shapeContext.strokeStyle = css3color(
+ s.options.strokeColor,
+ s.options.strokeOpacity
+ );
+ shapeContext.lineWidth = s.options.strokeWidth;
- // TODO: will not deselect areas that were previously selected, so this only works
- // for an initial bind.
+ shapeContext.beginPath();
- if (u.isBool(area_options.selected)) {
- ar.selected = area_options.selected;
- }
- }
- }
- }
- },
- // keys: a comma-separated list
- drawSelections: function (keys) {
- var i, key_arr = u.asArray(keys);
+ me.renderShape(shapeContext, s.mapArea, offset);
+ shapeContext.closePath();
+ shapeContext.stroke();
+ shapeContext.restore();
+ }
+ });
+
+ if (hasMasks) {
+ // render the new shapes against the mask
+
+ maskContext.globalCompositeOperation = 'source-out';
+ maskContext.drawImage(shapeCanvas, 0, 0);
+
+ // flatten into the main canvas
+ context.drawImage(maskCanvas, 0, 0);
+ } else {
+ context.drawImage(shapeCanvas, 0, 0);
+ }
+
+ me.active = false;
+ return me.canvas;
+ },
+
+ // create a canvas mimicing dimensions of an existing element
+ createCanvasFor: function (md) {
+ return $(
+ ' '
+ )[0];
+ },
+ clearHighlight: function () {
+ var c = this.map_data.overlay_canvas;
+ c.getContext('2d').clearRect(0, 0, c.width, c.height);
+ },
+ // Draw all items from selected_list to a new canvas, then swap with the old one. This is used to delete items when using canvases.
+ refreshSelections: function () {
+ var canvas_temp,
+ map_data = this.map_data;
+ // draw new base canvas, then swap with the old one to avoid flickering
+ canvas_temp = map_data.base_canvas;
+
+ map_data.base_canvas = this.createVisibleCanvas(map_data);
+ $(map_data.base_canvas).hide();
+ $(canvas_temp).before(map_data.base_canvas);
+
+ map_data.redrawSelections();
+
+ $(map_data.base_canvas).show();
+ $(canvas_temp).remove();
+ }
+ };
+
+ vmlMethods = {
+ renderShape: function (mapArea, options, cssclass) {
+ var me = this,
+ fill,
+ stroke,
+ e,
+ t_fill,
+ el_name,
+ el_class,
+ template,
+ c = mapArea.coords();
+ el_name = me.elementName ? 'name="' + me.elementName + '" ' : '';
+ el_class = cssclass ? 'class="' + cssclass + '" ' : '';
+
+ t_fill =
+ ' ';
+
+ stroke = options.stroke
+ ? ' strokeweight=' +
+ options.strokeWidth +
+ ' stroked="t" strokecolor="#' +
+ options.strokeColor +
+ '"'
+ : ' stroked="f"';
+
+ fill = options.fill ? ' filled="t"' : ' filled="f"';
+
+ switch (mapArea.shape) {
+ case 'rect':
+ template =
+ '' +
+ t_fill +
+ ' ';
+ break;
+ case 'poly':
+ template =
+ '' +
+ t_fill +
+ ' ';
+ break;
+ case 'circ':
+ case 'circle':
+ template =
+ '' +
+ t_fill +
+ ' ';
+ break;
+ }
+ e = $(template);
+ $(me.canvas).append(e);
+
+ return e;
+ },
+ render: function () {
+ var opts,
+ me = this;
+
+ $.each(this.shapes, function (_, e) {
+ me.renderShape(e.mapArea, e.options);
+ });
+
+ if (this.masks.length) {
+ $.each(this.masks, function (_, e) {
+ opts = u.updateProps({}, e.options, {
+ fillOpacity: 1,
+ fillColor: e.options.fillColorMask
+ });
+ me.renderShape(e.mapArea, opts, 'mapster_mask');
+ });
+ }
+
+ this.active = false;
+ return this.canvas;
+ },
+
+ createCanvasFor: function (md) {
+ var w = md.scaleInfo.width,
+ h = md.scaleInfo.height;
+ return $(
+ ' '
+ )[0];
+ },
+
+ clearHighlight: function () {
+ $(this.map_data.overlay_canvas).children().remove();
+ },
+ // remove single or all selections
+ removeSelections: function (area_id) {
+ if (area_id >= 0) {
+ $(this.map_data.base_canvas)
+ .find('[name="static_' + area_id.toString() + '"]')
+ .remove();
+ } else {
+ $(this.map_data.base_canvas).children().remove();
+ }
+ }
+ };
+
+ // for all methods with two implemenatations, add a function that will automatically replace itself with the correct
+ // method on first invocation
+
+ $.each(
+ [
+ 'renderShape',
+ 'addAltImage',
+ 'render',
+ 'createCanvasFor',
+ 'clearHighlight',
+ 'removeSelections',
+ 'refreshSelections'
+ ],
+ function (_, e) {
+ p[e] = (function (method) {
+ return function () {
+ p[method] =
+ (m.hasCanvas() ? canvasMethods[method] : vmlMethods[method]) ||
+ noop;
+
+ return p[method].apply(this, arguments);
+ };
+ })(e);
+ }
+ );
+})(jQuery);
- for (i = key_arr.length - 1; i >= 0; i--) {
- this.data[key_arr[i]].drawSelection();
- }
- },
- redrawSelections: function () {
- $.each(this.data, function (i, e) {
- if (e.isSelectedOrStatic()) {
- e.drawSelection();
- }
- });
+/*
+ mapimage.js
+ The MapImage object, repesents an instance of a single bound imagemap
+*/
- },
- ///called when images are done loading
- initialize: function () {
- var imgCopy, base_canvas, overlay_canvas, wrap, parentId, css, i,size,
- img,sort_func, sorted_list, scale,
- me = this,
- opts = me.options;
-
- if (me.complete) {
- return;
- }
+(function ($) {
+ 'use strict';
+
+ var m = $.mapster,
+ u = m.utils,
+ ap = [];
+ /**
+ * An object encapsulating all the images used by a MapData.
+ */
+
+ m.MapImages = function (owner) {
+ this.owner = owner;
+ this.clear();
+ };
+
+ m.MapImages.prototype = {
+ constructor: m.MapImages,
+
+ /* interface to make this array-like */
+
+ slice: function () {
+ return ap.slice.apply(this, arguments);
+ },
+ splice: function () {
+ ap.slice.apply(this.status, arguments);
+ var result = ap.slice.apply(this, arguments);
+ return result;
+ },
- img = $(me.image);
+ /**
+ * a boolean value indicates whether all images are done loading
+ * @return {bool} true when all are done
+ */
+ complete: function () {
+ return $.inArray(false, this.status) < 0;
+ },
- parentId = img.parent().attr('id');
+ /**
+ * Save an image in the images array and return its index
+ * @param {Image} image An Image object
+ * @return {int} the index of the image
+ */
- // create a div wrapper only if there's not already a wrapper, otherwise, own it
+ _add: function (image) {
+ var index = ap.push.call(this, image) - 1;
+ this.status[index] = false;
+ return index;
+ },
- if (parentId && parentId.length >= 12 && parentId.substring(0, 12) === "mapster_wrap") {
- wrap = img.parent();
- wrap.attr('id', me.wrapId());
- } else {
- wrap = $('
');
+ /**
+ * Return the index of an Image within the images array
+ * @param {Image} img An Image
+ * @return {int} the index within the array, or -1 if it was not found
+ */
- if (opts.wrapClass) {
- if (opts.wrapClass === true) {
- wrap.addClass(img[0].className);
- }
- else {
- wrap.addClass(opts.wrapClass);
- }
- }
- }
- me.wrapper = wrap;
+ indexOf: function (image) {
+ return u.indexOf(this, image);
+ },
- // me.images[1] is the copy of the original image. It should be loaded & at its native size now so we can obtain the true
- // width & height. This is needed to scale the imagemap if not being shown at its native size. It is also needed purely
- // to finish binding in case the original image was not visible. It can be impossible in some browsers to obtain the
- // native size of a hidden image.
+ /**
+ * Clear this object and reset it to its initial state after binding.
+ */
- me.scaleInfo = scale = u.scaleMap(me.images[0],me.images[1], opts.scaleMap);
+ clear: function () {
+ var me = this;
- me.base_canvas = base_canvas = me.graphics.createVisibleCanvas(me);
- me.overlay_canvas = overlay_canvas = me.graphics.createVisibleCanvas(me);
+ if (me.ids && me.ids.length > 0) {
+ $.each(me.ids, function (_, e) {
+ delete me[e];
+ });
+ }
- // Now we got what we needed from the copy -clone from the original image again to make sure any other attributes are copied
- imgCopy = $(me.images[1])
- .addClass('mapster_el '+ me.images[0].className)
- .attr({id:null, usemap: null});
+ /**
+ * A list of the cross-reference IDs bound to this object
+ * @type {string[]}
+ */
- size=u.size(me.images[0]);
+ me.ids = [];
- if (size.complete) {
- imgCopy.css({
- width: size.width,
- height: size.height
- });
- }
+ /**
+ * Length property for array-like behavior, set to zero when initializing. Array prototype
+ * methods will update it after that.
+ *
+ * @type {int}
+ */
- me.buildDataset();
+ me.length = 0;
- // now that we have processed all the areas, set css for wrapper, scale map if needed
+ /**
+ * the loaded status of the corresponding image
+ * @type {boolean[]}
+ */
- css = {
- display: 'block',
- position: 'relative',
- padding: 0,
- width: scale.width,
- height: scale.height
- };
+ me.status = [];
- if (opts.wrapCss) {
- $.extend(css, opts.wrapCss);
- }
- // if we were rebinding with an existing wrapper, the image will aready be in it
- if (img.parent()[0] !== me.wrapper[0]) {
+ // actually erase the images
- img.before(me.wrapper);
- }
+ me.splice(0);
+ },
- wrap.css(css);
+ /**
+ * Bind an image to the map and add it to the queue to be loaded; return an ID that
+ * can be used to reference the
+ *
+ * @param {Image|string} image An Image object or a URL to an image
+ * @param {string} [id] An id to refer to this image
+ * @returns {int} an ID referencing the index of the image object in
+ * map_data.images
+ */
- // move all generated images into the wrapper for easy removal later
+ add: function (image, id) {
+ var index,
+ src,
+ me = this;
- $(me.images.slice(2)).hide();
- for (i = 1; i < me.images.length; i++) {
- wrap.append(me.images[i]);
- }
+ if (!image) {
+ return;
+ }
- //me.images[1].style.cssText = me.image.style.cssText;
+ if (typeof image === 'string') {
+ src = image;
+ image = me[src];
+ if (typeof image === 'object') {
+ return me.indexOf(image);
+ }
- wrap.append(base_canvas)
- .append(overlay_canvas)
- .append(img.css(m.canvas_style));
+ image = $(' ').addClass('mapster_el').hide();
+
+ index = me._add(image[0]);
+
+ image
+ .on('load', function (e) {
+ me.imageLoaded.call(me, e);
+ })
+ .on('error', function (e) {
+ me.imageLoadError.call(me, e);
+ });
+
+ image.attr('src', src);
+ } else {
+ // use attr because we want the actual source, not the resolved path the browser will return directly calling image.src
+
+ index = me._add($(image)[0]);
+ }
+ if (id) {
+ if (this[id]) {
+ throw (
+ id + ' is already used or is not available as an altImage alias.'
+ );
+ }
+ me.ids.push(id);
+ me[id] = me[index];
+ }
+ return index;
+ },
- // images[0] is the original image with map, images[1] is the copy/background that is visible
+ /**
+ * Bind the images in this object,
+ * @return {Promise} a promise that resolves when the images have finished loading
+ */
- u.setOpacity(me.images[0], 0);
- $(me.images[1]).show();
+ bind: function () {
+ var me = this,
+ promise,
+ triesLeft = me.owner.options.configTimeout / 200,
+ /* A recursive function to continue checking that the images have been
+ loaded until a timeout has elapsed */
- u.setOpacity(me.images[1],1);
+ check = function () {
+ var i;
- if (opts.isSelectable && opts.onGetList) {
- sorted_list = me.data.slice(0);
- if (opts.sortList) {
- if (opts.sortList === "desc") {
- sort_func = function (a, b) {
- return a === b ? 0 : (a > b ? -1 : 1);
- };
- }
- else {
- sort_func = function (a, b) {
- return a === b ? 0 : (a < b ? -1 : 1);
- };
- }
+ // refresh status of images
- sorted_list.sort(function (a, b) {
- a = a.value;
- b = b.value;
- return sort_func(a, b);
- });
- }
+ i = me.length;
- me.options.boundList = opts.onGetList.call(me.image, sorted_list);
+ while (i-- > 0) {
+ if (!me.isLoaded(i)) {
+ break;
}
+ }
+
+ // check to see if every image has already been loaded
+
+ if (me.complete()) {
+ me.resolve();
+ } else {
+ // to account for failure of onLoad to fire in rare situations
+ if (triesLeft-- > 0) {
+ me.imgTimeout = window.setTimeout(function () {
+ check.call(me, true);
+ }, 50);
+ } else {
+ me.imageLoadError.call(me);
+ }
+ }
+ };
- me.complete=true;
- me.processCommandQueue();
+ promise = me.deferred = u.defer();
- if (opts.onConfigured && typeof opts.onConfigured === 'function') {
- opts.onConfigured.call(img, true);
- }
- },
+ check();
+ return promise;
+ },
- // when rebind is true, the MapArea data will not be rebuilt.
- buildDataset: function(rebind) {
- var sel,areas,j,area_id,$area,area,curKey,mapArea,key,keys,mapAreaId,group_value,dataItem,href,
- me=this,
- opts=me.options,
- default_group;
-
- function addAreaData(key, value) {
- var dataItem = new m.AreaData(me, key, value);
- dataItem.areaId = me._xref[key] = me.data.push(dataItem) - 1;
- return dataItem.areaId;
- }
+ resolve: function () {
+ var me = this,
+ resolver = me.deferred;
- me._xref = {};
- me.data = [];
- if (!rebind) {
- me.mapAreas=[];
- }
+ if (resolver) {
+ // Make a copy of the resolver before calling & removing it to ensure
+ // it is not called twice
+ me.deferred = null;
+ resolver.resolve();
+ }
+ },
- default_group = !opts.mapKey;
- if (default_group) {
- opts.mapKey = 'data-mapster-key';
- }
+ /**
+ * Event handler for image onload
+ * @param {object} e jQuery event data
+ */
- // the [attribute] selector is broken on old IE with jQuery. hasVml() is a quick and dirty
- // way to test for that
+ imageLoaded: function (e) {
+ var me = this,
+ index = me.indexOf(e.target);
- sel = m.hasVml() ? 'area' :
- (default_group ?
- 'area[coords]' :
- 'area[' + opts.mapKey + ']');
+ if (index >= 0) {
+ me.status[index] = true;
+ if ($.inArray(false, me.status) < 0) {
+ me.resolve();
+ }
+ }
+ },
- areas = $(me.map).find(sel).off('.mapster');
+ /**
+ * Event handler for onload error
+ * @param {object} e jQuery event data
+ */
- for (mapAreaId = 0;mapAreaId= 0) {
+ deferred.resolve();
+ }
+ }
+ if (me.activeAreaEvent) {
+ window.clearTimeout(me.activeAreaEvent);
+ me.activeAreaEvent = 0;
+ }
+ if (delay < 0) {
+ deferred.reject();
+ } else {
+ if (area.owner.currentAction || delay) {
+ me.activeAreaEvent = window.setTimeout(
+ (function () {
+ return function () {
+ queueMouseEvent(me, 0, area, deferred);
+ };
+ })(area),
+ delay || 100
+ );
+ } else {
+ cbFinal(area.areaId);
+ }
+ }
+ return deferred;
+ }
+
+ /**
+ * Mousedown event. This is captured only to prevent browser from drawing an outline around an
+ * area when it's clicked.
+ *
+ * @param {EventData} e jQuery event data
+ */
+
+ function mousedown(e) {
+ if (!m.hasCanvas()) {
+ this.blur();
+ }
+ e.preventDefault();
+ }
+
+ /**
+ * Mouseover event. Handle highlight rendering and client callback on mouseover
+ *
+ * @param {MapData} me The MapData context
+ * @param {EventData} e jQuery event data
+ * @return {[type]} [description]
+ */
+
+ function mouseover(me, e) {
+ var arData = me.getAllDataForArea(this),
+ ar = arData.length ? arData[0] : null;
+
+ // mouseover events are ignored entirely while resizing, though we do care about mouseout events
+ // and must queue the action to keep things clean.
+
+ if (!ar || ar.isNotRendered() || ar.owner.currentAction) {
+ return;
+ }
- if (rebind) {
- mapArea = me.mapAreas[$area.data('mapster')-1];
- mapArea.configure(curKey);
- } else {
- mapArea = new m.MapArea(me, area,curKey);
- me.mapAreas.push(mapArea);
- }
+ if (me.currentAreaId === ar.areaId) {
+ return;
+ }
+ if (me.highlightId !== ar.areaId) {
+ me.clearEffects();
- keys = mapArea.keys; // converted to an array by mapArea
+ ar.highlight();
+ if (me.options.showToolTip) {
+ $.each(arData, function (_, e) {
+ if (e.effectiveOptions().toolTip) {
+ e.showToolTip();
+ }
+ });
+ }
+ }
- // Iterate through each mapKey assigned to this area
- for (j = keys.length - 1; j >= 0; j--) {
- key = keys[j];
+ me.currentAreaId = ar.areaId;
- if (opts.mapValue) {
- group_value = $area.attr(opts.mapValue);
- }
- if (default_group) {
- // set an attribute so we can refer to the area by index from the DOM object if no key
- area_id = addAreaData(me.data.length, group_value);
- dataItem = me.data[area_id];
- dataItem.key = key = area_id.toString();
- }
- else {
- area_id = me._xref[key];
- if (area_id >= 0) {
- dataItem = me.data[area_id];
- if (group_value && !me.data[area_id].value) {
- dataItem.value = group_value;
- }
- }
- else {
- area_id = addAreaData(key, group_value);
- dataItem = me.data[area_id];
- dataItem.isPrimary=j===0;
- }
- }
- mapArea.areaDataXref.push(area_id);
- dataItem.areasXref.push(mapAreaId);
- }
+ if (u.isFunction(me.options.onMouseover)) {
+ me.options.onMouseover.call(this, {
+ e: e,
+ options: ar.effectiveOptions(),
+ key: ar.key,
+ selected: ar.isSelected()
+ });
+ }
+ }
+
+ /**
+ * Mouseout event.
+ *
+ * @param {MapData} me The MapData context
+ * @param {EventData} e jQuery event data
+ * @return {[type]} [description]
+ */
+
+ function mouseout(me, e) {
+ var newArea,
+ ar = me.getDataForArea(this),
+ opts = me.options;
+
+ if (me.currentAreaId < 0 || !ar) {
+ return;
+ }
- href=$area.attr('href');
- if (href && href!=='#' && !dataItem.href)
- {
- dataItem.href=href;
- }
+ newArea = me.getDataForArea(e.relatedTarget);
- if (!mapArea.nohref) {
- $area.on('click.mapster', me.click)
- .on('mouseover.mapster touchstart.mapster.noPreventDefault', me.mouseover)
- .on('mouseout.mapster touchend.mapster.noPreventDefault', me.mouseout)
- .on('mousedown.mapster', me.mousedown);
+ if (newArea === ar) {
+ return;
+ }
+ me.currentAreaId = -1;
+ ar.area = null;
+ queueMouseEvent(me, opts.mouseoutDelay, ar).then(me.clearEffects);
- }
+ if (u.isFunction(opts.onMouseout)) {
+ opts.onMouseout.call(this, {
+ e: e,
+ options: opts,
+ key: ar.key,
+ selected: ar.isSelected()
+ });
+ }
+ }
+
+ /**
+ * Clear any active tooltip or highlight
+ *
+ * @param {MapData} me The MapData context
+ * @param {EventData} e jQuery event data
+ * @return {[type]} [description]
+ */
+
+ function clearEffects(me) {
+ var opts = me.options;
+
+ me.ensureNoHighlight();
+
+ if (
+ opts.toolTipClose &&
+ $.inArray('area-mouseout', opts.toolTipClose) >= 0 &&
+ me.activeToolTip
+ ) {
+ me.clearToolTip();
+ }
+ }
+
+ /**
+ * Mouse click event handler
+ *
+ * @param {MapData} me The MapData context
+ * @param {EventData} e jQuery event data
+ * @return {[type]} [description]
+ */
+
+ function click(me, e) {
+ var list,
+ list_target,
+ newSelectionState,
+ canChangeState,
+ cbResult,
+ that = this,
+ ar = me.getDataForArea(this),
+ opts = me.options;
+
+ function clickArea(ar) {
+ var areaOpts, target;
+ canChangeState =
+ ar.isSelectable() && (ar.isDeselectable() || !ar.isSelected());
+
+ if (canChangeState) {
+ newSelectionState = !ar.isSelected();
+ } else {
+ newSelectionState = ar.isSelected();
+ }
+
+ list_target = m.getBoundList(opts, ar.key);
+
+ if (u.isFunction(opts.onClick)) {
+ cbResult = opts.onClick.call(that, {
+ e: e,
+ listTarget: list_target,
+ key: ar.key,
+ selected: newSelectionState
+ });
- // store an ID with each area.
- $area.data("mapster", mapAreaId+1);
- }
+ if (u.isBool(cbResult)) {
+ if (!cbResult) {
+ return false;
+ }
+ target = $(ar.area).attr('href');
+ if (target !== '#') {
+ window.location.href = target;
+ return false;
+ }
+ }
+ }
+
+ if (canChangeState) {
+ ar.toggle();
+ }
+
+ if (opts.boundList && opts.boundList.length > 0) {
+ m.setBoundListProperties(opts, list_target, ar.isSelected());
+ }
+
+ areaOpts = ar.effectiveOptions();
+ if (areaOpts.includeKeys) {
+ list = u.split(areaOpts.includeKeys);
+ $.each(list, function (_, e) {
+ var ar = me.getDataForKey(e.toString());
+ if (!ar.options.isMask) {
+ clickArea(ar);
+ }
+ });
+ }
+ }
- // TODO listenToList
- // if (opts.listenToList && opts.nitG) {
- // opts.nitG.bind('click.mapster', event_hooks[map_data.hooks_index].listclick_hook);
- // }
+ mousedown.call(this, e);
- // populate areas from config options
- me.setAreaOptions(opts.areas);
- me.redrawSelections();
+ if (opts.clickNavigate && ar.href) {
+ window.location.href = ar.href;
+ return;
+ }
- },
- processCommandQueue: function() {
+ if (ar && !ar.owner.currentAction) {
+ opts = me.options;
+ clickArea(ar);
+ }
+ }
- var cur,me=this;
- while (!me.currentAction && me.commands.length) {
- cur = me.commands[0];
- me.commands.splice(0,1);
- m.impl[cur.command].apply(cur.that, cur.args);
- }
- },
- clearEvents: function () {
- $(this.map).find('area')
- .off('.mapster');
- $(this.images)
- .off('.mapster');
- },
- _clearCanvases: function (preserveState) {
- // remove the canvas elements created
- if (!preserveState) {
- $(this.base_canvas).remove();
- }
- $(this.overlay_canvas).remove();
- },
- clearMapData: function (preserveState) {
- var me = this;
- this._clearCanvases(preserveState);
+ /**
+ * Prototype for a MapData object, representing an ImageMapster bound object
+ * @param {Element} image an IMG element
+ * @param {object} options ImageMapster binding options
+ */
+ m.MapData = function (image, options) {
+ var me = this;
- // release refs to DOM elements
- $.each(this.data, function (i, e) {
- e.reset();
- });
- this.data = null;
- if (!preserveState) {
- // get rid of everything except the original image
- this.image.style.cssText = this.imgCssText;
- $(this.wrapper).before(this.image).remove();
- }
+ // (Image) main map image
- me.images.clear();
+ me.image = image;
- this.image = null;
- u.ifFunction(this.clearTooltip, this);
- },
+ me.images = new m.MapImages(me);
+ me.graphics = new m.Graphics(me);
- // Compelete cleanup process for deslecting items. Called after a batch operation, or by AreaData for single
- // operations not flagged as "partial"
+ // save the initial style of the image for unbinding. This is problematic, chrome
+ // duplicates styles when assigning, and cssText is apparently not universally supported.
+ // Need to do something more robust to make unbinding work universally.
- removeSelectionFinish: function () {
- var g = this.graphics;
+ me.imgCssText = image.style.cssText || null;
- g.refreshSelections();
- // do not call ensure_no_highlight- we don't really want to unhilight it, just remove the effect
- g.clearHighlight();
- }
+ initializeDefaults(me);
+
+ me.configureOptions(options);
+
+ // create context-bound event handlers from our private functions
+
+ me.mouseover = function (e) {
+ mouseover.call(this, me, e);
};
-} (jQuery));
+ me.mouseout = function (e) {
+ mouseout.call(this, me, e);
+ };
+ me.click = function (e) {
+ click.call(this, me, e);
+ };
+ me.clearEffects = function (e) {
+ clearEffects.call(this, me, e);
+ };
+ };
-/* areadata.js
- AreaData and MapArea protoypes
-*/
+ m.MapData.prototype = {
+ constructor: m.MapData,
-(function ($) {
- var m = $.mapster, u = m.utils;
+ /**
+ * Set target.options from defaults + options
+ * @param {[type]} target The target
+ * @param {[type]} options The options to merge
+ */
+
+ configureOptions: function (options) {
+ this.options = u.updateProps({}, m.defaults, options);
+ },
/**
- * Select this area
- *
- * @param {AreaData} me AreaData context
- * @param {object} options Options for rendering the selection
+ * Ensure all images are loaded
+ * @return {Promise} A promise that resolves when the images have finished loading (or fail)
*/
- function select(options) {
- // need to add the new one first so that the double-opacity effect leaves the current one highlighted for singleSelect
- var me=this, o = me.owner;
- if (o.options.singleSelect) {
- o.clearSelections();
- }
+ bindImages: function () {
+ var me = this,
+ mi = me.images;
- // because areas can overlap - we can't depend on the selection state to tell us anything about the inner areas.
- // don't check if it's already selected
- if (!me.isSelected()) {
- if (options) {
+ // reset the images if this is a rebind
- // cache the current options, and map the altImageId if an altimage
- // was passed
+ if (mi.length > 2) {
+ mi.splice(2);
+ } else if (mi.length === 0) {
+ // add the actual main image
+ mi.add(me.image);
+ // will create a duplicate of the main image, we need this to get raw size info
+ mi.add(me.image.src);
+ }
- me.optsCache = $.extend(me.effectiveRenderOptions('select'),
- options,
- {
- altImageId: o.images.add(options.altImage)
- });
- }
+ configureAltImages(me);
- me.drawSelection();
+ return me.images.bind();
+ },
- me.selected = true;
- me.changeState('select', true);
- }
+ /**
+ * Test whether an async action is currently in progress
+ * @return {Boolean} true or false indicating state
+ */
- if (o.options.singleSelect) {
- o.graphics.refreshSelections();
- }
- }
+ isActive: function () {
+ return !this.complete || this.currentAction;
+ },
/**
- * Deselect this area, optionally deferring finalization so additional areas can be deselected
- * in a single operation
+ * Return an object indicating the various states. This isn't really used by
+ * production code.
*
- * @param {boolean} partial when true, the caller must invoke "finishRemoveSelection" to render
+ * @return {object} An object with properties for various states
*/
- function deselect(partial) {
- var me=this;
- me.selected = false;
- me.changeState('select', false);
+ state: function () {
+ return {
+ complete: this.complete,
+ resizing: this.currentAction === 'resizing',
+ zoomed: this.zoomed,
+ zoomedArea: this.zoomedArea,
+ scaleInfo: this.scaleInfo
+ };
+ },
- // release information about last area options when deselecting.
+ /**
+ * Get a unique ID for the wrapper of this imagemapster
+ * @return {string} A string that is unique to this image
+ */
- me.optsCache=null;
- me.owner.graphics.removeSelections(me.areaId);
+ wrapId: function () {
+ return 'mapster_wrap_' + this.index;
+ },
+ _idFromKey: function (key) {
+ return typeof key === 'string' &&
+ Object.prototype.hasOwnProperty.call(this._xref, key)
+ ? this._xref[key]
+ : -1;
+ },
- // Complete selection removal process. This is separated because it's very inefficient to perform the whole
- // process for multiple removals, as the canvas must be totally redrawn at the end of the process.ar.remove
+ /**
+ * Return a comma-separated string of all selected keys
+ * @return {string} CSV of all keys that are currently selected
+ */
- if (!partial) {
- me.owner.removeSelectionFinish();
+ getSelected: function () {
+ var result = '';
+ $.each(this.data, function (_, e) {
+ if (e.isSelected()) {
+ result += (result ? ',' : '') + this.key;
}
- }
+ });
+ return result;
+ },
/**
- * Toggle the selection state of this area
- * @param {object} options Rendering options, if toggling on
- * @return {bool} The new selection state
+ * Get an array of MapAreas associated with a specific AREA based on the keys for that area
+ * @param {Element} area An HTML AREA
+ * @param {number} atMost A number limiting the number of areas to be returned (typically 1 or 0 for no limit)
+ * @return {MapArea[]} Array of MapArea objects
*/
- function toggle(options) {
- var me=this;
- if (!me.isSelected()) {
- me.select(options);
- }
- else {
- me.deselect();
+
+ getAllDataForArea: function (area, atMost) {
+ var i,
+ ar,
+ result,
+ me = this,
+ key = $(area).filter('area').attr(me.options.mapKey);
+
+ if (key) {
+ result = [];
+ key = u.split(key);
+
+ for (i = 0; i < (atMost || key.length); i++) {
+ ar = me.data[me._idFromKey(key[i])];
+ if (ar) {
+ ar.area = area.length ? area[0] : area;
+ // set the actual area moused over/selected
+ // TODO: this is a brittle model for capturing which specific area - if this method was not used,
+ // ar.area could have old data. fix this.
+ result.push(ar);
+ }
}
- return me.isSelected();
- }
+ }
+
+ return result;
+ },
+ getDataForArea: function (area) {
+ var ar = this.getAllDataForArea(area, 1);
+ return ar ? ar[0] || null : null;
+ },
+ getDataForKey: function (key) {
+ return this.data[this._idFromKey(key)];
+ },
/**
- * An AreaData object; represents a conceptual area that can be composed of
- * one or more MapArea objects
+ * Get the primary keys associated with an area group.
+ * If this is a primary key, it will be returned.
*
- * @param {MapData} owner The MapData object to which this belongs
- * @param {string} key The key for this area
- * @param {string} value The mapValue string for this area
+ * @param {string key An area key
+ * @return {string} A CSV of area keys
*/
- m.AreaData = function (owner, key, value) {
- $.extend(this,{
- owner: owner,
- key: key || '',
- // means this represents the first key in a list of keys (it's the area group that gets highlighted on mouseover)
- isPrimary: true,
- areaId: -1,
- href: '',
- value: value || '',
- options:{},
- // "null" means unchanged. Use "isSelected" method to just test true/false
- selected: null,
- // xref to MapArea objects
- areasXref: [],
- // (temporary storage) - the actual area moused over
- area: null,
- // the last options used to render this. Cache so when re-drawing after a remove, changes in options won't
- // break already selected things.
- optsCache: null
- });
- };
+ getKeysForGroup: function (key) {
+ var ar = this.getDataForKey(key);
+
+ return !ar
+ ? ''
+ : ar.isPrimary
+ ? ar.key
+ : this.getPrimaryKeysForMapAreas(ar.areas()).join(',');
+ },
/**
- * The public API for AreaData object
+ * given an array of MapArea object, return an array of its unique primary keys
+ * @param {MapArea[]} areas The areas to analyze
+ * @return {string[]} An array of unique primary keys
*/
- m.AreaData.prototype = {
- constuctor: m.AreaData,
- select: select,
- deselect: deselect,
- toggle: toggle,
- areas: function() {
- var i,result=[];
- for (i=0;i= 0) {
+ this.graphics.clearHighlight();
+ ar = this.data[this.highlightId];
+ ar.changeState('highlight', false);
+ this.setHighlightId(-1);
+ }
+ },
+ setHighlightId: function (id) {
+ this.highlightId = id;
+ },
- },
+ /**
+ * Clear all active selections on this map
+ */
+ clearSelections: function () {
+ $.each(this.data, function (_, e) {
+ if (e.selected) {
+ e.deselect(true);
+ }
+ });
+ this.removeSelectionFinish();
+ },
- /**
- * Return the overall options effective for this area.
- * This should get the default options, and merge in area-specific options, finally
- * overlaying options passed by parameter
- *
- * @param {[type]} options options which will supercede all other options for this area
- * @return {[type]} the combined options
- */
+ /**
+ * Set area options from an array of option data.
+ *
+ * @param {object[]} areas An array of objects containing area-specific options
+ */
- effectiveOptions: function (options) {
+ setAreaOptions: function (areas) {
+ var i, area_options, ar;
+ areas = areas || [];
- var opts = u.updateProps({},
- this.owner.area_options,
- this.options,
- options || {},
- {
- id: this.areaId
- }
- );
+ // refer by: map_data.options[map_data.data[x].area_option_id]
- opts.selected = this.isSelected();
+ for (i = areas.length - 1; i >= 0; i--) {
+ area_options = areas[i];
+ if (area_options) {
+ ar = this.getDataForKey(area_options.key);
+ if (ar) {
+ u.updateProps(ar.options, area_options);
- return opts;
- },
+ // TODO: will not deselect areas that were previously selected, so this only works
+ // for an initial bind.
- /**
- * Return the options effective for this area for a "render" or "highlight" mode.
- * This should get the default options, merge in the areas-specific options,
- * and then the mode-specific options.
- * @param {string} mode 'render' or 'highlight'
- * @param {[type]} options options which will supercede all other options for this area
- * @return {[type]} the combined options
- */
-
- effectiveRenderOptions: function (mode, options) {
- var allOpts,opts=this.optsCache;
-
- if (!opts || mode==='highlight') {
- allOpts = this.effectiveOptions(options);
- opts = u.updateProps({},
- allOpts,
- allOpts["render_" + mode]
- );
-
- if (mode!=='highlight') {
- this.optsCache=opts;
- }
+ if (u.isBool(area_options.selected)) {
+ ar.selected = area_options.selected;
}
- return $.extend({},opts);
- },
+ }
+ }
+ }
+ },
+ // keys: a comma-separated list
+ drawSelections: function (keys) {
+ var i,
+ key_arr = u.asArray(keys);
+
+ for (i = key_arr.length - 1; i >= 0; i--) {
+ this.data[key_arr[i]].drawSelection();
+ }
+ },
+ redrawSelections: function () {
+ $.each(this.data, function (_, e) {
+ if (e.isSelectedOrStatic()) {
+ e.drawSelection();
+ }
+ });
+ },
+ ///called when images are done loading
+ initialize: function () {
+ var imgCopy,
+ base_canvas,
+ overlay_canvas,
+ wrap,
+ parentId,
+ css,
+ i,
+ size,
+ img,
+ sort_func,
+ sorted_list,
+ scale,
+ me = this,
+ opts = me.options;
+
+ if (me.complete) {
+ return;
+ }
+
+ img = $(me.image);
+
+ parentId = img.parent().attr('id');
+
+ // create a div wrapper only if there's not already a wrapper, otherwise, own it
+
+ if (
+ parentId &&
+ parentId.length >= 12 &&
+ parentId.substring(0, 12) === 'mapster_wrap'
+ ) {
+ wrap = img.parent();
+ wrap.attr('id', me.wrapId());
+ } else {
+ wrap = $('
');
+
+ if (opts.wrapClass) {
+ if (opts.wrapClass === true) {
+ wrap.addClass(img[0].className);
+ } else {
+ wrap.addClass(opts.wrapClass);
+ }
+ }
+ }
+ me.wrapper = wrap;
+
+ // me.images[1] is the copy of the original image. It should be loaded & at its native size now so we can obtain the true
+ // width & height. This is needed to scale the imagemap if not being shown at its native size. It is also needed purely
+ // to finish binding in case the original image was not visible. It can be impossible in some browsers to obtain the
+ // native size of a hidden image.
+
+ me.scaleInfo = scale = u.scaleMap(
+ me.images[0],
+ me.images[1],
+ opts.scaleMap
+ );
+
+ me.base_canvas = base_canvas = me.graphics.createVisibleCanvas(me);
+ me.overlay_canvas = overlay_canvas = me.graphics.createVisibleCanvas(me);
+
+ // Now we got what we needed from the copy -clone from the original image again to make sure any other attributes are copied
+ imgCopy = $(me.images[1])
+ .addClass('mapster_el ' + me.images[0].className)
+ .attr({ id: null, usemap: null });
+
+ size = u.size(me.images[0]);
+
+ if (size.complete) {
+ imgCopy.css({
+ width: size.width,
+ height: size.height
+ });
+ }
- // Fire callback on area state change
- changeState: function (state_type, state) {
- if (u.isFunction(this.owner.options.onStateChange)) {
- this.owner.options.onStateChange.call(this.owner.image,
- {
- key: this.key,
- state: state_type,
- selected: state
- }
- );
- }
- },
+ me.buildDataset();
- // highlight this area
+ // now that we have processed all the areas, set css for wrapper, scale map if needed
- highlight: function (options) {
- var o = this.owner;
- o.ensureNoHighlight();
- if (this.effectiveOptions().highlight) {
- o.graphics.addShapeGroup(this, "highlight",options);
- }
- o.setHighlightId(this.areaId);
- this.changeState('highlight', true);
- },
+ css = {
+ display: 'block',
+ position: 'relative',
+ padding: 0,
+ width: scale.width,
+ height: scale.height
+ };
- // select this area. if "callEvent" is true then the state change event will be called. (This method can be used
- // during config operations, in which case no event is indicated)
+ if (opts.wrapCss) {
+ $.extend(css, opts.wrapCss);
+ }
+ // if we were rebinding with an existing wrapper, the image will aready be in it
+ if (img.parent()[0] !== me.wrapper[0]) {
+ img.before(me.wrapper);
+ }
- drawSelection: function () {
+ wrap.css(css);
+ // move all generated images into the wrapper for easy removal later
- this.owner.graphics.addShapeGroup(this, "select");
+ $(me.images.slice(2)).hide();
+ for (i = 1; i < me.images.length; i++) {
+ wrap.append(me.images[i]);
+ }
- }
+ //me.images[1].style.cssText = me.image.style.cssText;
+ wrap
+ .append(base_canvas)
+ .append(overlay_canvas)
+ .append(img.css(m.canvas_style));
- };
- // represents an HTML area
- m.MapArea = function (owner,areaEl,keys) {
- if (!owner) {
- return;
- }
- var me = this;
- me.owner = owner; // a MapData object
- me.area = areaEl;
- me.areaDataXref=[]; // a list of map_data.data[] id's for each areaData object containing this
- me.originalCoords = [];
- $.each(u.split(areaEl.coords), function (i, el) {
- me.originalCoords.push(parseFloat(el));
- });
- me.length = me.originalCoords.length;
- me.shape = areaEl.shape.toLowerCase();
- me.nohref = areaEl.nohref || !areaEl.href;
- me.configure(keys);
- };
- m.MapArea.prototype= {
- constructor: m.MapArea,
- configure: function(keys) {
- this.keys = u.split(keys);
- },
- reset: function() {
- this.area=null;
- },
- coords: function (offset) {
- return $.map(this.originalCoords,function(e) {
- return offset ? e : e+offset;
- });
- }
- };
-} (jQuery));
+ // images[0] is the original image with map, images[1] is the copy/background that is visible
-/* areacorners.js
- determine the best place to put a box of dimensions (width,height) given a circle, rect or poly
-*/
+ u.setOpacity(me.images[0], 0);
+ $(me.images[1]).show();
-(function ($) {
- var u=$.mapster.utils;
+ u.setOpacity(me.images[1], 1);
+ if (opts.isSelectable && opts.onGetList) {
+ sorted_list = me.data.slice(0);
+ if (opts.sortList) {
+ if (opts.sortList === 'desc') {
+ sort_func = function (a, b) {
+ return a === b ? 0 : a > b ? -1 : 1;
+ };
+ } else {
+ sort_func = function (a, b) {
+ return a === b ? 0 : a < b ? -1 : 1;
+ };
+ }
- /**
- * Compute positions that will place a target with dimensions [width,height] outside
- * but near the boundaries of the elements "elements". When an imagemap is passed, the
- *
- * @param {Element|Element[]} elements An element or an array of elements (such as a jQuery object)
- * @param {Element} image The image to which area elements are bound, if this is an image map.
- * @param {Element} container The contianer in which the target must be constrained (or document, if missing)
- * @param {int} width The width of the target object
- * @return {object} a structure with the x and y positions
- */
- u.areaCorners = function (elements, image, container, width, height) {
- var pos,found, minX, minY, maxX, maxY, bestMinX, bestMaxX, bestMinY, bestMaxY, curX, curY, nest, j,
- offsetx=0,
- offsety=0,
- rootx,
- rooty,
- iCoords,radius,angle,el,
- coords=[];
-
- // if a single element was passed, map it to an array
-
- elements = elements.length ?
- elements:
- [elements];
-
- container = container ?
- $(container):
- $(document.body);
-
- // get the relative root of calculation
-
- pos = container.offset();
- rootx = pos.left;
- rooty = pos.top;
-
- // with areas, all we know about is relative to the top-left corner of the image. We need to add an offset compared to
- // the actual container. After this calculation, offsetx/offsety can be added to either the area coords, or the target's
- // absolute position to get the correct top/left boundaries of the container.
-
- if (image) {
- pos = $(image).offset();
- offsetx = pos.left;
- offsety = pos.top;
+ sorted_list.sort(function (a, b) {
+ a = a.value;
+ b = b.value;
+ return sort_func(a, b);
+ });
}
- // map the coordinates of any type of shape to a poly and use the logic. simpler than using three different
- // calculation methods. Circles use a 20 degree increment for this estimation.
+ me.options.boundList = opts.onGetList.call(me.image, sorted_list);
+ }
+
+ me.complete = true;
+ me.processCommandQueue();
+
+ if (opts.onConfigured && typeof opts.onConfigured === 'function') {
+ opts.onConfigured.call(img, true);
+ }
+ },
+
+ // when rebind is true, the MapArea data will not be rebuilt.
+ buildDataset: function (rebind) {
+ var sel,
+ areas,
+ j,
+ area_id,
+ $area,
+ area,
+ curKey,
+ mapArea,
+ key,
+ keys,
+ mapAreaId,
+ group_value,
+ dataItem,
+ href,
+ me = this,
+ opts = me.options,
+ default_group;
+
+ function addAreaData(key, value) {
+ var dataItem = new m.AreaData(me, key, value);
+ dataItem.areaId = me._xref[key] = me.data.push(dataItem) - 1;
+ return dataItem.areaId;
+ }
+
+ me._xref = {};
+ me.data = [];
+ if (!rebind) {
+ me.mapAreas = [];
+ }
+
+ default_group = !opts.mapKey;
+ if (default_group) {
+ opts.mapKey = 'data-mapster-key';
+ }
+
+ // the [attribute] selector is broken on old IE with jQuery. hasVml() is a quick and dirty
+ // way to test for that
+
+ sel = m.hasVml()
+ ? 'area'
+ : default_group
+ ? 'area[coords]'
+ : 'area[' + opts.mapKey + ']';
+
+ areas = $(me.map).find(sel).off('.mapster');
+
+ for (mapAreaId = 0; mapAreaId < areas.length; mapAreaId++) {
+ area_id = 0;
+ area = areas[mapAreaId];
+ $area = $(area);
+
+ // skip areas with no coords - selector broken for older ie
+ if (!area.coords) {
+ continue;
+ }
+ // Create a key if none was assigned by the user
- for (j=0;j= 0; j--) {
+ key = keys[j];
+
+ if (opts.mapValue) {
+ group_value = $area.attr(opts.mapValue);
+ }
+ if (default_group) {
+ // set an attribute so we can refer to the area by index from the DOM object if no key
+ area_id = addAreaData(me.data.length, group_value);
+ dataItem = me.data[area_id];
+ dataItem.key = key = area_id.toString();
+ } else {
+ area_id = me._xref[key];
+ if (area_id >= 0) {
+ dataItem = me.data[area_id];
+ if (group_value && !me.data[area_id].value) {
+ dataItem.value = group_value;
+ }
} else {
- el=$(el);
- pos = el.position();
- coords.push(pos.left,pos.top,
- pos.left+el.width(),pos.top,
- pos.left+el.width(),pos.top+el.height(),
- pos.left,pos.top+el.height());
+ area_id = addAreaData(key, group_value);
+ dataItem = me.data[area_id];
+ dataItem.isPrimary = j === 0;
+ }
+ }
+ mapArea.areaDataXref.push(area_id);
+ dataItem.areasXref.push(mapAreaId);
+ }
+
+ href = $area.attr('href');
+ if (href && href !== '#' && !dataItem.href) {
+ dataItem.href = href;
+ }
- }
+ if (!mapArea.nohref) {
+ $area
+ .on('click.mapster', me.click)
+ .on(
+ 'mouseover.mapster touchstart.mapster.noPreventDefault',
+ me.mouseover
+ )
+ .on(
+ 'mouseout.mapster touchend.mapster.noPreventDefault',
+ me.mouseout
+ )
+ .on('mousedown.mapster', me.mousedown);
}
- minX = minY = bestMinX = bestMinY = 999999;
- maxX = maxY = bestMaxX = bestMaxY = -1;
+ // store an ID with each area.
+ $area.data('mapster', mapAreaId + 1);
+ }
+
+ // TODO listenToList
+ // if (opts.listenToList && opts.nitG) {
+ // opts.nitG.bind('click.mapster', event_hooks[map_data.hooks_index].listclick_hook);
+ // }
+
+ // populate areas from config options
+ me.setAreaOptions(opts.areas);
+ me.redrawSelections();
+ },
+ processCommandQueue: function () {
+ var cur,
+ me = this;
+ while (!me.currentAction && me.commands.length) {
+ cur = me.commands[0];
+ me.commands.splice(0, 1);
+ m.impl[cur.command].apply(cur.that, cur.args);
+ }
+ },
+ clearEvents: function () {
+ $(this.map).find('area').off('.mapster');
+ $(this.images).off('.mapster');
+ },
+ _clearCanvases: function (preserveState) {
+ // remove the canvas elements created
+ if (!preserveState) {
+ $(this.base_canvas).remove();
+ }
+ $(this.overlay_canvas).remove();
+ },
+ clearMapData: function (preserveState) {
+ var me = this;
+ this._clearCanvases(preserveState);
+
+ // release refs to DOM elements
+ $.each(this.data, function (_, e) {
+ e.reset();
+ });
+ this.data = null;
+ if (!preserveState) {
+ // get rid of everything except the original image
+ this.image.style.cssText = this.imgCssText;
+ $(this.wrapper).before(this.image).remove();
+ }
+
+ me.images.clear();
+
+ this.image = null;
+ u.ifFunction(this.clearTooltip, this);
+ },
+
+ // Compelete cleanup process for deslecting items. Called after a batch operation, or by AreaData for single
+ // operations not flagged as "partial"
+
+ removeSelectionFinish: function () {
+ var g = this.graphics;
+
+ g.refreshSelections();
+ // do not call ensure_no_highlight- we don't really want to unhilight it, just remove the effect
+ g.clearHighlight();
+ }
+ };
+})(jQuery);
- for (j = coords.length - 2; j >= 0; j -= 2) {
- curX = coords[j];
- curY = coords[j + 1];
+/* areadata.js
+ AreaData and MapArea protoypes
+*/
- if (curX < minX) {
- minX = curX;
- bestMaxY = curY;
- }
- if (curX > maxX) {
- maxX = curX;
- bestMinY = curY;
- }
- if (curY < minY) {
- minY = curY;
- bestMaxX = curX;
- }
- if (curY > maxY) {
- maxY = curY;
- bestMinX = curX;
- }
+(function ($) {
+ 'use strict';
+
+ var m = $.mapster,
+ u = m.utils;
+
+ /**
+ * Select this area
+ *
+ * @param {AreaData} me AreaData context
+ * @param {object} options Options for rendering the selection
+ */
+ function select(options) {
+ // need to add the new one first so that the double-opacity effect leaves the current one highlighted for singleSelect
+
+ var me = this,
+ o = me.owner;
+ if (o.options.singleSelect) {
+ o.clearSelections();
+ }
- }
+ // because areas can overlap - we can't depend on the selection state to tell us anything about the inner areas.
+ // don't check if it's already selected
+ if (!me.isSelected()) {
+ if (options) {
+ // cache the current options, and map the altImageId if an altimage
+ // was passed
- // try to figure out the best place for the tooltip
-
- if (width && height) {
- found=false;
- $.each([[bestMaxX - width, minY - height], [bestMinX, minY - height],
- [minX - width, bestMaxY - height], [minX - width, bestMinY],
- [maxX,bestMaxY - height], [ maxX,bestMinY],
- [bestMaxX - width, maxY], [bestMinX, maxY]
- ],function (i, e) {
- if (!found && (e[0] > rootx && e[1] > rooty)) {
- nest = e;
- found=true;
- return false;
- }
- });
-
- // default to lower-right corner if nothing fit inside the boundaries of the image
-
- if (!found) {
- nest=[maxX,maxY];
- }
- }
- return nest;
- };
-} (jQuery));
+ me.optsCache = $.extend(me.effectiveRenderOptions('select'), options, {
+ altImageId: o.images.add(options.altImage)
+ });
+ }
-/* scale.js: resize and zoom functionality
- requires areacorners.js
-*/
+ me.drawSelection();
+ me.selected = true;
+ me.changeState('select', true);
+ }
-(function ($) {
- var m = $.mapster, u = m.utils, p = m.MapArea.prototype;
+ if (o.options.singleSelect) {
+ o.graphics.refreshSelections();
+ }
+ }
- m.utils.getScaleInfo = function (eff, actual) {
- var pct;
- if (!actual) {
- pct = 1;
- actual=eff;
- } else {
- pct = eff.width / actual.width || eff.height / actual.height;
- // make sure a float error doesn't muck us up
- if (pct > 0.98 && pct < 1.02) { pct = 1; }
- }
- return {
- scale: (pct !== 1),
- scalePct: pct,
- realWidth: actual.width,
- realHeight: actual.height,
- width: eff.width,
- height: eff.height,
- ratio: eff.width / eff.height
- };
- };
- // Scale a set of AREAs, return old data as an array of objects
- m.utils.scaleMap = function (image, imageRaw, scale) {
+ /**
+ * Deselect this area, optionally deferring finalization so additional areas can be deselected
+ * in a single operation
+ *
+ * @param {boolean} partial when true, the caller must invoke "finishRemoveSelection" to render
+ */
- // stunningly, jQuery width can return zero even as width does not, seems to happen only
- // with adBlock or maybe other plugins. These must interfere with onload events somehow.
+ function deselect(partial) {
+ var me = this;
+ me.selected = false;
+ me.changeState('select', false);
+ // release information about last area options when deselecting.
- var vis=u.size(image),
- raw=u.size(imageRaw,true);
+ me.optsCache = null;
+ me.owner.graphics.removeSelections(me.areaId);
- if (!raw.complete()) {
- throw("Another script, such as an extension, appears to be interfering with image loading. Please let us know about this.");
- }
- if (!vis.complete()) {
- vis=raw;
- }
- return this.getScaleInfo(vis, scale ? raw : null);
- };
+ // Complete selection removal process. This is separated because it's very inefficient to perform the whole
+ // process for multiple removals, as the canvas must be totally redrawn at the end of the process.ar.remove
+
+ if (!partial) {
+ me.owner.removeSelectionFinish();
+ }
+ }
+
+ /**
+ * Toggle the selection state of this area
+ * @param {object} options Rendering options, if toggling on
+ * @return {bool} The new selection state
+ */
+ function toggle(options) {
+ var me = this;
+ if (!me.isSelected()) {
+ me.select(options);
+ } else {
+ me.deselect();
+ }
+ return me.isSelected();
+ }
+
+ /**
+ * An AreaData object; represents a conceptual area that can be composed of
+ * one or more MapArea objects
+ *
+ * @param {MapData} owner The MapData object to which this belongs
+ * @param {string} key The key for this area
+ * @param {string} value The mapValue string for this area
+ */
+
+ m.AreaData = function (owner, key, value) {
+ $.extend(this, {
+ owner: owner,
+ key: key || '',
+ // means this represents the first key in a list of keys (it's the area group that gets highlighted on mouseover)
+ isPrimary: true,
+ areaId: -1,
+ href: '',
+ value: value || '',
+ options: {},
+ // "null" means unchanged. Use "isSelected" method to just test true/false
+ selected: null,
+ // xref to MapArea objects
+ areasXref: [],
+ // (temporary storage) - the actual area moused over
+ area: null,
+ // the last options used to render this. Cache so when re-drawing after a remove, changes in options won't
+ // break already selected things.
+ optsCache: null
+ });
+ };
+
+ /**
+ * The public API for AreaData object
+ */
+
+ m.AreaData.prototype = {
+ constuctor: m.AreaData,
+ select: select,
+ deselect: deselect,
+ toggle: toggle,
+ areas: function () {
+ var i,
+ result = [];
+ for (i = 0; i < this.areasXref.length; i++) {
+ result.push(this.owner.mapAreas[this.areasXref[i]]);
+ }
+ return result;
+ },
+ // return all coordinates for all areas
+ coords: function (offset) {
+ var coords = [];
+ $.each(this.areas(), function (_, el) {
+ coords = coords.concat(el.coords(offset));
+ });
+ return coords;
+ },
+ reset: function () {
+ $.each(this.areas(), function (_, e) {
+ e.reset();
+ });
+ this.areasXref = [];
+ this.options = null;
+ },
+ // Return the effective selected state of an area, incorporating staticState
+ isSelectedOrStatic: function () {
+ var o = this.effectiveOptions();
+ return u.isBool(o.staticState) ? o.staticState : this.isSelected();
+ },
+ isSelected: function () {
+ return u.isBool(this.selected)
+ ? this.selected
+ : u.isBool(this.owner.area_options.selected)
+ ? this.owner.area_options.selected
+ : false;
+ },
+ isSelectable: function () {
+ return u.isBool(this.effectiveOptions().staticState)
+ ? false
+ : u.isBool(this.owner.options.staticState)
+ ? false
+ : u.boolOrDefault(this.effectiveOptions().isSelectable, true);
+ },
+ isDeselectable: function () {
+ return u.isBool(this.effectiveOptions().staticState)
+ ? false
+ : u.isBool(this.owner.options.staticState)
+ ? false
+ : u.boolOrDefault(this.effectiveOptions().isDeselectable, true);
+ },
+ isNotRendered: function () {
+ var area = $(this.area);
+ return (
+ area.attr('nohref') ||
+ !area.attr('href') ||
+ this.effectiveOptions().isMask
+ );
+ },
/**
- * Resize the image map. Only one of newWidth and newHeight should be passed to preserve scale
+ * Return the overall options effective for this area.
+ * This should get the default options, and merge in area-specific options, finally
+ * overlaying options passed by parameter
*
- * @param {int} width The new width OR an object containing named parameters matching this function sig
- * @param {int} height The new height
- * @param {int} effectDuration Time in ms for the resize animation, or zero for no animation
- * @param {function} callback A function to invoke when the operation finishes
- * @return {promise} NOT YET IMPLEMENTED
+ * @param {[type]} options options which will supercede all other options for this area
+ * @return {[type]} the combined options
*/
- m.MapData.prototype.resize = function (width, height, duration, callback) {
- var p,promises,newsize,els, highlightId, ratio,
- me = this;
-
- // allow omitting duration
- callback = callback || duration;
-
- function sizeCanvas(canvas, w, h) {
- if (m.hasCanvas()) {
- canvas.width = w;
- canvas.height = h;
- } else {
- $(canvas).width(w);
- $(canvas).height(h);
- }
+ effectiveOptions: function (options) {
+ var opts = u.updateProps(
+ {},
+ this.owner.area_options,
+ this.options,
+ options || {},
+ {
+ id: this.areaId
}
+ );
- // Finalize resize action, do callback, pass control to command queue
+ opts.selected = this.isSelected();
- function cleanupAndNotify() {
+ return opts;
+ },
+
+ /**
+ * Return the options effective for this area for a "render" or "highlight" mode.
+ * This should get the default options, merge in the areas-specific options,
+ * and then the mode-specific options.
+ * @param {string} mode 'render' or 'highlight'
+ * @param {[type]} options options which will supercede all other options for this area
+ * @return {[type]} the combined options
+ */
- me.currentAction = '';
+ effectiveRenderOptions: function (mode, options) {
+ var allOpts,
+ opts = this.optsCache;
- if (u.isFunction(callback)) {
- callback();
- }
+ if (!opts || mode === 'highlight') {
+ allOpts = this.effectiveOptions(options);
+ opts = u.updateProps({}, allOpts, allOpts['render_' + mode]);
- me.processCommandQueue();
+ if (mode !== 'highlight') {
+ this.optsCache = opts;
}
+ }
+ return $.extend({}, opts);
+ },
+
+ // Fire callback on area state change
+ changeState: function (state_type, state) {
+ if (u.isFunction(this.owner.options.onStateChange)) {
+ this.owner.options.onStateChange.call(this.owner.image, {
+ key: this.key,
+ state: state_type,
+ selected: state
+ });
+ }
+ },
+
+ // highlight this area
+
+ highlight: function (options) {
+ var o = this.owner;
+ o.ensureNoHighlight();
+ if (this.effectiveOptions().highlight) {
+ o.graphics.addShapeGroup(this, 'highlight', options);
+ }
+ o.setHighlightId(this.areaId);
+ this.changeState('highlight', true);
+ },
+
+ // select this area. if "callEvent" is true then the state change event will be called. (This method can be used
+ // during config operations, in which case no event is indicated)
+
+ drawSelection: function () {
+ this.owner.graphics.addShapeGroup(this, 'select');
+ }
+ };
+ // represents an HTML area
+ m.MapArea = function (owner, areaEl, keys) {
+ if (!owner) {
+ return;
+ }
+ var me = this;
+ me.owner = owner; // a MapData object
+ me.area = areaEl;
+ me.areaDataXref = []; // a list of map_data.data[] id's for each areaData object containing this
+ me.originalCoords = [];
+ $.each(u.split(areaEl.coords), function (_, el) {
+ me.originalCoords.push(parseFloat(el));
+ });
+ me.length = me.originalCoords.length;
+ me.shape = areaEl.shape.toLowerCase();
+ me.nohref = areaEl.nohref || !areaEl.href;
+ me.configure(keys);
+ };
+ m.MapArea.prototype = {
+ constructor: m.MapArea,
+ configure: function (keys) {
+ this.keys = u.split(keys);
+ },
+ reset: function () {
+ this.area = null;
+ },
+ coords: function (offset) {
+ return $.map(this.originalCoords, function (e) {
+ return offset ? e : e + offset;
+ });
+ }
+ };
+})(jQuery);
- // handle cleanup after the inner elements are resized
+/* areacorners.js
+ determine the best place to put a box of dimensions (width,height) given a circle, rect or poly
+*/
- function finishResize() {
- sizeCanvas(me.overlay_canvas, width, height);
+(function ($) {
+ 'use strict';
+
+ var u = $.mapster.utils;
+
+ /**
+ * Compute positions that will place a target with dimensions [width,height] outside
+ * but near the boundaries of the elements "elements". When an imagemap is passed, the
+ *
+ * @param {Element|Element[]} elements An element or an array of elements (such as a jQuery object)
+ * @param {Element} image The image to which area elements are bound, if this is an image map.
+ * @param {Element} container The contianer in which the target must be constrained (or document, if missing)
+ * @param {int} width The width of the target object
+ * @return {object} a structure with the x and y positions
+ */
+ u.areaCorners = function (elements, image, container, width, height) {
+ var pos,
+ found,
+ minX,
+ minY,
+ maxX,
+ maxY,
+ bestMinX,
+ bestMaxX,
+ bestMinY,
+ bestMaxY,
+ curX,
+ curY,
+ nest,
+ j,
+ offsetx = 0,
+ offsety = 0,
+ rootx,
+ rooty,
+ iCoords,
+ radius,
+ angle,
+ el,
+ coords = [];
+
+ // if a single element was passed, map it to an array
+
+ elements = elements.length ? elements : [elements];
+
+ container = container ? $(container) : $(document.body);
+
+ // get the relative root of calculation
+
+ pos = container.offset();
+ rootx = pos.left;
+ rooty = pos.top;
+
+ // with areas, all we know about is relative to the top-left corner of the image. We need to add an offset compared to
+ // the actual container. After this calculation, offsetx/offsety can be added to either the area coords, or the target's
+ // absolute position to get the correct top/left boundaries of the container.
+
+ if (image) {
+ pos = $(image).offset();
+ offsetx = pos.left;
+ offsety = pos.top;
+ }
- // restore highlight state if it was highlighted before
- if (highlightId >= 0) {
- var areaData = me.data[highlightId];
- areaData.tempOptions = { fade: false };
- me.getDataForKey(areaData.key).highlight();
- areaData.tempOptions = null;
+ // map the coordinates of any type of shape to a poly and use the logic. simpler than using three different
+ // calculation methods. Circles use a 20 degree increment for this estimation.
+
+ for (j = 0; j < elements.length; j++) {
+ el = elements[j];
+ if (el.nodeName === 'AREA') {
+ iCoords = u.split(el.coords, parseInt);
+
+ switch (el.shape) {
+ case 'circle':
+ curX = iCoords[0];
+ curY = iCoords[1];
+ radius = iCoords[2];
+ coords = [];
+ for (j = 0; j < 360; j += 20) {
+ angle = (j * Math.PI) / 180;
+ coords.push(
+ curX + radius * Math.cos(angle),
+ curY + radius * Math.sin(angle)
+ );
}
- sizeCanvas(me.base_canvas, width, height);
- me.redrawSelections();
- cleanupAndNotify();
+ break;
+ case 'rect':
+ coords.push(
+ iCoords[0],
+ iCoords[1],
+ iCoords[2],
+ iCoords[1],
+ iCoords[2],
+ iCoords[3],
+ iCoords[0],
+ iCoords[3]
+ );
+ break;
+ default:
+ coords = coords.concat(iCoords);
+ break;
}
- function resizeMapData() {
- $(me.image).css(newsize);
- // start calculation at the same time as effect
- me.scaleInfo = u.getScaleInfo({
- width: width,
- height: height
- },
- {
- width: me.scaleInfo.realWidth,
- height: me.scaleInfo.realHeight
- });
- $.each(me.data, function (i, e) {
- $.each(e.areas(), function (i, e) {
- e.resize();
- });
- });
+ // map area positions to it's real position in the container
+
+ for (j = 0; j < coords.length; j += 2) {
+ coords[j] = parseInt(coords[j], 10) + offsetx;
+ coords[j + 1] = parseInt(coords[j + 1], 10) + offsety;
}
+ } else {
+ el = $(el);
+ pos = el.position();
+ coords.push(
+ pos.left,
+ pos.top,
+ pos.left + el.width(),
+ pos.top,
+ pos.left + el.width(),
+ pos.top + el.height(),
+ pos.left,
+ pos.top + el.height()
+ );
+ }
+ }
- if (me.scaleInfo.width === width && me.scaleInfo.height === height) {
- return;
+ minX = minY = bestMinX = bestMinY = 999999;
+ maxX = maxY = bestMaxX = bestMaxY = -1;
+
+ for (j = coords.length - 2; j >= 0; j -= 2) {
+ curX = coords[j];
+ curY = coords[j + 1];
+
+ if (curX < minX) {
+ minX = curX;
+ bestMaxY = curY;
+ }
+ if (curX > maxX) {
+ maxX = curX;
+ bestMinY = curY;
+ }
+ if (curY < minY) {
+ minY = curY;
+ bestMaxX = curX;
+ }
+ if (curY > maxY) {
+ maxY = curY;
+ bestMinX = curX;
+ }
+ }
+
+ // try to figure out the best place for the tooltip
+
+ if (width && height) {
+ found = false;
+ $.each(
+ [
+ [bestMaxX - width, minY - height],
+ [bestMinX, minY - height],
+ [minX - width, bestMaxY - height],
+ [minX - width, bestMinY],
+ [maxX, bestMaxY - height],
+ [maxX, bestMinY],
+ [bestMaxX - width, maxY],
+ [bestMinX, maxY]
+ ],
+ function (_, e) {
+ if (!found && e[0] > rootx && e[1] > rooty) {
+ nest = e;
+ found = true;
+ return false;
+ }
}
+ );
+
+ // default to lower-right corner if nothing fit inside the boundaries of the image
- highlightId = me.highlightId;
+ if (!found) {
+ nest = [maxX, maxY];
+ }
+ }
+ return nest;
+ };
+})(jQuery);
+
+/*
+ scale.js
+ Resize and zoom functionality
+ Requires areacorners.js
+*/
+(function ($) {
+ 'use strict';
- if (!width) {
- ratio = height / me.scaleInfo.realHeight;
- width = Math.round(me.scaleInfo.realWidth * ratio);
- }
- if (!height) {
- ratio = width / me.scaleInfo.realWidth;
- height = Math.round(me.scaleInfo.realHeight * ratio);
- }
+ var m = $.mapster,
+ u = m.utils,
+ p = m.MapArea.prototype;
- newsize = { 'width': String(width) + 'px', 'height': String(height) + 'px' };
- if (!m.hasCanvas()) {
- $(me.base_canvas).children().remove();
- }
+ m.utils.getScaleInfo = function (eff, actual) {
+ var pct;
+ if (!actual) {
+ pct = 1;
+ actual = eff;
+ } else {
+ pct = eff.width / actual.width || eff.height / actual.height;
+ // make sure a float error doesn't muck us up
+ if (pct > 0.98 && pct < 1.02) {
+ pct = 1;
+ }
+ }
+ return {
+ scale: pct !== 1,
+ scalePct: pct,
+ realWidth: actual.width,
+ realHeight: actual.height,
+ width: eff.width,
+ height: eff.height,
+ ratio: eff.width / eff.height
+ };
+ };
+ // Scale a set of AREAs, return old data as an array of objects
+ m.utils.scaleMap = function (image, imageRaw, scale) {
+ // stunningly, jQuery width can return zero even as width does not, seems to happen only
+ // with adBlock or maybe other plugins. These must interfere with onload events somehow.
- // resize all the elements that are part of the map except the image itself (which is not visible)
- // but including the div wrapper
- els = $(me.wrapper).find('.mapster_el').add(me.wrapper);
-
- if (duration) {
- promises = [];
- me.currentAction = 'resizing';
- els.each(function (i, e) {
- p = u.defer();
- promises.push(p);
-
- $(e).animate(newsize, {
- duration: duration,
- complete: p.resolve,
- easing: "linear"
- });
- });
+ var vis = u.size(image),
+ raw = u.size(imageRaw, true);
- p = u.defer();
- promises.push(p);
+ if (!raw.complete()) {
+ throw 'Another script, such as an extension, appears to be interfering with image loading. Please let us know about this.';
+ }
+ if (!vis.complete()) {
+ vis = raw;
+ }
+ return this.getScaleInfo(vis, scale ? raw : null);
+ };
+
+ /**
+ * Resize the image map. Only one of newWidth and newHeight should be passed to preserve scale
+ *
+ * @param {int} width The new width OR an object containing named parameters matching this function sig
+ * @param {int} height The new height
+ * @param {int} effectDuration Time in ms for the resize animation, or zero for no animation
+ * @param {function} callback A function to invoke when the operation finishes
+ * @return {promise} NOT YET IMPLEMENTED
+ */
+
+ m.MapData.prototype.resize = function (width, height, duration, callback) {
+ var p,
+ promises,
+ newsize,
+ els,
+ highlightId,
+ ratio,
+ me = this;
+
+ // allow omitting duration
+ callback = callback || duration;
+
+ function sizeCanvas(canvas, w, h) {
+ if (m.hasCanvas()) {
+ canvas.width = w;
+ canvas.height = h;
+ } else {
+ $(canvas).width(w);
+ $(canvas).height(h);
+ }
+ }
- // though resizeMapData is not async, it needs to be finished just the same as the animations,
- // so add it to the "to do" list.
+ // Finalize resize action, do callback, pass control to command queue
- u.when.all(promises).then(finishResize);
- resizeMapData();
- p.resolve();
- } else {
- els.css(newsize);
- resizeMapData();
- finishResize();
+ function cleanupAndNotify() {
+ me.currentAction = '';
- }
- };
+ if (u.isFunction(callback)) {
+ callback();
+ }
+
+ me.processCommandQueue();
+ }
+ // handle cleanup after the inner elements are resized
+
+ function finishResize() {
+ sizeCanvas(me.overlay_canvas, width, height);
+
+ // restore highlight state if it was highlighted before
+ if (highlightId >= 0) {
+ var areaData = me.data[highlightId];
+ areaData.tempOptions = { fade: false };
+ me.getDataForKey(areaData.key).highlight();
+ areaData.tempOptions = null;
+ }
+ sizeCanvas(me.base_canvas, width, height);
+ me.redrawSelections();
+ cleanupAndNotify();
+ }
- m.MapArea = u.subclass(m.MapArea, function () {
- //change the area tag data if needed
- this.base.init();
- if (this.owner.scaleInfo.scale) {
- this.resize();
+ function resizeMapData() {
+ $(me.image).css(newsize);
+ // start calculation at the same time as effect
+ me.scaleInfo = u.getScaleInfo(
+ {
+ width: width,
+ height: height
+ },
+ {
+ width: me.scaleInfo.realWidth,
+ height: me.scaleInfo.realHeight
}
- });
+ );
+ $.each(me.data, function (_, e) {
+ $.each(e.areas(), function (_, e) {
+ e.resize();
+ });
+ });
+ }
- p.coords = function (percent, coordOffset) {
- var j, newCoords = [],
- pct = percent || this.owner.scaleInfo.scalePct,
- offset = coordOffset || 0;
+ if (me.scaleInfo.width === width && me.scaleInfo.height === height) {
+ return;
+ }
- if (pct === 1 && coordOffset === 0) {
- return this.originalCoords;
- }
+ highlightId = me.highlightId;
- for (j = 0; j < this.length; j++) {
- //amount = j % 2 === 0 ? xPct : yPct;
- newCoords.push(Math.round(this.originalCoords[j] * pct) + offset);
- }
- return newCoords;
- };
- p.resize = function () {
- this.area.coords = this.coords().join(',');
- };
+ if (!width) {
+ ratio = height / me.scaleInfo.realHeight;
+ width = Math.round(me.scaleInfo.realWidth * ratio);
+ }
+ if (!height) {
+ ratio = width / me.scaleInfo.realWidth;
+ height = Math.round(me.scaleInfo.realHeight * ratio);
+ }
- p.reset = function () {
- this.area.coords = this.coords(1).join(',');
- };
+ newsize = { width: String(width) + 'px', height: String(height) + 'px' };
+ if (!m.hasCanvas()) {
+ $(me.base_canvas).children().remove();
+ }
- m.impl.resize = function (width, height, duration, callback) {
- if (!width && !height) {
- return false;
- }
- var x= (new m.Method(this,
- function () {
- this.resize(width, height, duration, callback);
- },
- null,
- {
- name: 'resize',
- args: arguments
- }
- )).go();
- return x;
- };
+ // resize all the elements that are part of the map except the image itself (which is not visible)
+ // but including the div wrapper
+ els = $(me.wrapper).find('.mapster_el').add(me.wrapper);
+
+ if (duration) {
+ promises = [];
+ me.currentAction = 'resizing';
+ els.each(function (_, e) {
+ p = u.defer();
+ promises.push(p);
+
+ $(e).animate(newsize, {
+ duration: duration,
+ complete: p.resolve,
+ easing: 'linear'
+ });
+ });
+
+ p = u.defer();
+ promises.push(p);
+
+ // though resizeMapData is not async, it needs to be finished just the same as the animations,
+ // so add it to the "to do" list.
+
+ u.when.all(promises).then(finishResize);
+ resizeMapData();
+ p.resolve();
+ } else {
+ els.css(newsize);
+ resizeMapData();
+ finishResize();
+ }
+ };
-/*
+ m.MapArea = u.subclass(m.MapArea, function () {
+ //change the area tag data if needed
+ this.base.init();
+ if (this.owner.scaleInfo.scale) {
+ this.resize();
+ }
+ });
+
+ p.coords = function (percent, coordOffset) {
+ var j,
+ newCoords = [],
+ pct = percent || this.owner.scaleInfo.scalePct,
+ offset = coordOffset || 0;
+
+ if (pct === 1 && coordOffset === 0) {
+ return this.originalCoords;
+ }
+
+ for (j = 0; j < this.length; j++) {
+ //amount = j % 2 === 0 ? xPct : yPct;
+ newCoords.push(Math.round(this.originalCoords[j] * pct) + offset);
+ }
+ return newCoords;
+ };
+ p.resize = function () {
+ this.area.coords = this.coords().join(',');
+ };
+
+ p.reset = function () {
+ this.area.coords = this.coords(1).join(',');
+ };
+
+ m.impl.resize = function (width, height, duration, callback) {
+ if (!width && !height) {
+ return false;
+ }
+ var x = new m.Method(
+ this,
+ function () {
+ this.resize(width, height, duration, callback);
+ },
+ null,
+ {
+ name: 'resize',
+ args: arguments
+ }
+ ).go();
+ return x;
+ };
+
+ /*
m.impl.zoom = function (key, opts) {
var options = opts || {};
@@ -3576,232 +3805,237 @@
key: key
}
)).go();
-
-
};
*/
-} (jQuery));
+})(jQuery);
-/* tooltip.js - tooltip functionality
- requires areacorners.js
+/*
+ tooltip.js
+ Tooltip functionality
+ Requires areacorners.js
*/
(function ($) {
-
- var m = $.mapster, u = m.utils;
-
- $.extend(m.defaults, {
- toolTipContainer: '
',
- showToolTip: false,
- toolTipFade: true,
- toolTipClose: ['area-mouseout','image-mouseout'],
- onShowToolTip: null,
- onHideToolTip: null
- });
-
- $.extend(m.area_defaults, {
- toolTip: null,
- toolTipClose: null
- });
-
-
- /**
- * Show a tooltip positioned near this area.
- *
- * @param {string|jquery} html A string of html or a jQuery object containing the tooltip content.
- * @param {string|jquery} [template] The html template in which to wrap the content
- * @param {string|object} [css] CSS to apply to the outermost element of the tooltip
- * @return {jquery} The tooltip that was created
- */
-
- function createToolTip(html, template, css) {
- var tooltip;
-
- // wrap the template in a jQuery object, or clone the template if it's already one.
- // This assumes that anything other than a string is a jQuery object; if it's not jQuery will
- // probably throw an error.
-
- if (template) {
- tooltip = typeof template === 'string' ?
- $(template) :
- $(template).clone();
-
- tooltip.append(html);
- } else {
- tooltip=$(html);
- }
-
- // always set display to block, or the positioning css won't work if the end user happened to
- // use a non-block type element.
-
- tooltip.css($.extend((css || {}),{
- display:"block",
- position:"absolute"
- })).hide();
-
- $('body').append(tooltip);
-
- // we must actually add the tooltip to the DOM and "show" it in order to figure out how much space it
- // consumes, and then reposition it with that knowledge.
- // We also cache the actual opacity setting to restore finally.
-
- tooltip.attr("data-opacity",tooltip.css("opacity"))
- .css("opacity",0);
-
- // doesn't really show it because opacity=0
-
- return tooltip.show();
+ 'use strict';
+
+ var m = $.mapster,
+ u = m.utils;
+
+ $.extend(m.defaults, {
+ toolTipContainer:
+ '
',
+ showToolTip: false,
+ toolTipFade: true,
+ toolTipClose: ['area-mouseout', 'image-mouseout'],
+ onShowToolTip: null,
+ onHideToolTip: null
+ });
+
+ $.extend(m.area_defaults, {
+ toolTip: null,
+ toolTipClose: null
+ });
+
+ /**
+ * Show a tooltip positioned near this area.
+ *
+ * @param {string|jquery} html A string of html or a jQuery object containing the tooltip content.
+ * @param {string|jquery} [template] The html template in which to wrap the content
+ * @param {string|object} [css] CSS to apply to the outermost element of the tooltip
+ * @return {jquery} The tooltip that was created
+ */
+
+ function createToolTip(html, template, css) {
+ var tooltip;
+
+ // wrap the template in a jQuery object, or clone the template if it's already one.
+ // This assumes that anything other than a string is a jQuery object; if it's not jQuery will
+ // probably throw an error.
+
+ if (template) {
+ tooltip =
+ typeof template === 'string' ? $(template) : $(template).clone();
+
+ tooltip.append(html);
+ } else {
+ tooltip = $(html);
}
-
- /**
- * Show a tooltip positioned near this area.
- *
- * @param {jquery} tooltip The tooltip
- * @param {object} [options] options for displaying the tooltip.
- * @config {int} [left] The 0-based absolute x position for the tooltip
- * @config {int} [top] The 0-based absolute y position for the tooltip
- * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
- * @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
- */
-
- function showToolTipImpl(tooltip,options)
- {
- var tooltipCss = {
- "left": options.left + "px",
- "top": options.top + "px"
- },
- actalOpacity=tooltip.attr("data-opacity") || 0,
- zindex = tooltip.css("z-index");
-
- if (parseInt(zindex,10)===0
- || zindex === "auto") {
- tooltipCss["z-index"] = 9999;
- }
-
- tooltip.css(tooltipCss)
- .addClass('mapster_tooltip');
-
-
- if (options.fadeDuration && options.fadeDuration>0) {
- u.fader(tooltip[0], 0, actalOpacity, options.fadeDuration);
- } else {
- u.setOpacity(tooltip[0], actalOpacity);
- }
+ // always set display to block, or the positioning css won't work if the end user happened to
+ // use a non-block type element.
+
+ tooltip
+ .css(
+ $.extend(css || {}, {
+ display: 'block',
+ position: 'absolute'
+ })
+ )
+ .hide();
+
+ $('body').append(tooltip);
+
+ // we must actually add the tooltip to the DOM and "show" it in order to figure out how much space it
+ // consumes, and then reposition it with that knowledge.
+ // We also cache the actual opacity setting to restore finally.
+
+ tooltip.attr('data-opacity', tooltip.css('opacity')).css('opacity', 0);
+
+ // doesn't really show it because opacity=0
+
+ return tooltip.show();
+ }
+
+ /**
+ * Show a tooltip positioned near this area.
+ *
+ * @param {jquery} tooltip The tooltip
+ * @param {object} [options] options for displaying the tooltip.
+ * @config {int} [left] The 0-based absolute x position for the tooltip
+ * @config {int} [top] The 0-based absolute y position for the tooltip
+ * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
+ * @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
+ */
+
+ function showToolTipImpl(tooltip, options) {
+ var tooltipCss = {
+ left: options.left + 'px',
+ top: options.top + 'px'
+ },
+ actalOpacity = tooltip.attr('data-opacity') || 0,
+ zindex = tooltip.css('z-index');
+
+ if (parseInt(zindex, 10) === 0 || zindex === 'auto') {
+ tooltipCss['z-index'] = 9999;
}
- /**
- * Hide and remove active tooltips
- *
- * @param {MapData} this The mapdata object to which the tooltips belong
- */
+ tooltip.css(tooltipCss).addClass('mapster_tooltip');
- m.MapData.prototype.clearToolTip = function() {
- if (this.activeToolTip) {
- this.activeToolTip.stop().remove();
- this.activeToolTip = null;
- this.activeToolTipID = null;
- u.ifFunction(this.options.onHideToolTip, this);
+ if (options.fadeDuration && options.fadeDuration > 0) {
+ u.fader(tooltip[0], 0, actalOpacity, options.fadeDuration);
+ } else {
+ u.setOpacity(tooltip[0], actalOpacity);
+ }
+ }
+
+ /**
+ * Hide and remove active tooltips
+ *
+ * @param {MapData} this The mapdata object to which the tooltips belong
+ */
+
+ m.MapData.prototype.clearToolTip = function () {
+ if (this.activeToolTip) {
+ this.activeToolTip.stop().remove();
+ this.activeToolTip = null;
+ this.activeToolTipID = null;
+ u.ifFunction(this.options.onHideToolTip, this);
+ }
+ };
+
+ /**
+ * Configure the binding between a named tooltip closing option, and a mouse event.
+ *
+ * If a callback is passed, it will be called when the activating event occurs, and the tooltip will
+ * only closed if it returns true.
+ *
+ * @param {MapData} [this] The MapData object to which this tooltip belongs.
+ * @param {String} option The name of the tooltip closing option
+ * @param {String} event UI event to bind to this option
+ * @param {Element} target The DOM element that is the target of the event
+ * @param {Function} [beforeClose] Callback when the tooltip is closed
+ * @param {Function} [onClose] Callback when the tooltip is closed
+ */
+ function bindToolTipClose(
+ options,
+ bindOption,
+ event,
+ target,
+ beforeClose,
+ onClose
+ ) {
+ var event_name = event + '.mapster-tooltip';
+
+ if ($.inArray(bindOption, options) >= 0) {
+ target.off(event_name).on(event_name, function (e) {
+ if (!beforeClose || beforeClose.call(this, e)) {
+ target.off('.mapster-tooltip');
+ if (onClose) {
+ onClose.call(this);
+ }
}
- };
-
- /**
- * Configure the binding between a named tooltip closing option, and a mouse event.
- *
- * If a callback is passed, it will be called when the activating event occurs, and the tooltip will
- * only closed if it returns true.
- *
- * @param {MapData} [this] The MapData object to which this tooltip belongs.
- * @param {String} option The name of the tooltip closing option
- * @param {String} event UI event to bind to this option
- * @param {Element} target The DOM element that is the target of the event
- * @param {Function} [beforeClose] Callback when the tooltip is closed
- * @param {Function} [onClose] Callback when the tooltip is closed
- */
- function bindToolTipClose(options, bindOption, event, target, beforeClose, onClose) {
- var event_name = event + '.mapster-tooltip';
-
- if ($.inArray(bindOption, options) >= 0) {
- target.off(event_name)
- .on(event_name, function (e) {
- if (!beforeClose || beforeClose.call(this,e)) {
- target.off('.mapster-tooltip');
- if (onClose) {
- onClose.call(this);
- }
- }
- });
+ });
- return {
- object: target,
- event: event_name
- };
- }
+ return {
+ object: target,
+ event: event_name
+ };
+ }
+ }
+
+ /**
+ * Show a tooltip.
+ *
+ * @param {string|jquery} [tooltip] A string of html or a jQuery object containing the tooltip content.
+ *
+ * @param {string|jquery} [target] The target of the tooltip, to be used to determine positioning. If null,
+ * absolute position values must be passed with left and top.
+ *
+ * @param {string|jquery} [image] If target is an [area] the image that owns it
+ *
+ * @param {string|jquery} [container] An element within which the tooltip must be bounded
+ *
+ *
+ *
+ * @param {object|string|jQuery} [options] options to apply when creating this tooltip - OR -
+ * The markup, or a jquery object, containing the data for the tooltip
+ *
+ * @config {string} [closeEvents] A string with one or more comma-separated values that determine when the tooltip
+ * closes: 'area-click','tooltip-click','image-mouseout' are valid values
+ * then no template will be used.
+ * @config {int} [offsetx] the horizontal amount to offset the tooltip
+ * @config {int} [offsety] the vertical amount to offset the tooltip
+ * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
+ */
+
+ function showToolTip(tooltip, target, image, container, options) {
+ var corners,
+ ttopts = {};
+
+ options = options || {};
+
+ if (target) {
+ corners = u.areaCorners(
+ target,
+ image,
+ container,
+ tooltip.outerWidth(true),
+ tooltip.outerHeight(true)
+ );
+
+ // Try to upper-left align it first, if that doesn't work, change the parameters
+
+ ttopts.left = corners[0];
+ ttopts.top = corners[1];
+ } else {
+ ttopts.left = options.left;
+ ttopts.top = options.top;
}
- /**
- * Show a tooltip.
- *
- * @param {string|jquery} [tooltip] A string of html or a jQuery object containing the tooltip content.
- *
- * @param {string|jquery} [target] The target of the tooltip, to be used to determine positioning. If null,
- * absolute position values must be passed with left and top.
- *
- * @param {string|jquery} [image] If target is an [area] the image that owns it
- *
- * @param {string|jquery} [container] An element within which the tooltip must be bounded
- *
- *
- *
- * @param {object|string|jQuery} [options] options to apply when creating this tooltip - OR -
- * The markup, or a jquery object, containing the data for the tooltip
- *
- * @config {string} [closeEvents] A string with one or more comma-separated values that determine when the tooltip
- * closes: 'area-click','tooltip-click','image-mouseout' are valid values
- * then no template will be used.
- * @config {int} [offsetx] the horizontal amount to offset the tooltip
- * @config {int} [offsety] the vertical amount to offset the tooltip
- * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
- */
-
- function showToolTip(tooltip,target,image,container,options) {
- var corners,
- ttopts = {};
-
- options = options || {};
-
-
- if (target) {
-
- corners = u.areaCorners(target,image,container,
- tooltip.outerWidth(true),
- tooltip.outerHeight(true));
-
- // Try to upper-left align it first, if that doesn't work, change the parameters
-
- ttopts.left = corners[0];
- ttopts.top = corners[1];
-
- } else {
-
- ttopts.left = options.left;
- ttopts.top = options.top;
- }
-
- ttopts.left += (options.offsetx || 0);
- ttopts.top +=(options.offsety || 0);
+ ttopts.left += options.offsetx || 0;
+ ttopts.top += options.offsety || 0;
- ttopts.css= options.css;
- ttopts.fadeDuration = options.fadeDuration;
+ ttopts.css = options.css;
+ ttopts.fadeDuration = options.fadeDuration;
- showToolTipImpl(tooltip,ttopts);
+ showToolTipImpl(tooltip, ttopts);
- return tooltip;
- }
+ return tooltip;
+ }
- /**
+ /**
* Show a tooltip positioned near this area.
*
* @param {string|jquery} [content] A string of html or a jQuery object containing the tooltip content.
@@ -3818,171 +4052,217 @@
* @config {int} [offsety] the vertical amount to offset the tooltip
* @config {string|object} [css] CSS to apply to the outermost element of the tooltip
*/
- m.AreaData.prototype.showToolTip= function(content,options) {
- var tooltip, closeOpts, target, tipClosed, template,
- ttopts = {},
- ad=this,
- md=ad.owner,
- areaOpts = ad.effectiveOptions();
-
- // copy the options object so we can update it
- options = options ? $.extend({},options) : {};
-
- content = content || areaOpts.toolTip;
- closeOpts = options.closeEvents || areaOpts.toolTipClose || md.options.toolTipClose || 'tooltip-click';
-
- template = typeof options.template !== 'undefined' ?
- options.template :
- md.options.toolTipContainer;
-
- options.closeEvents = typeof closeOpts === 'string' ?
- closeOpts = u.split(closeOpts) :
- closeOpts;
-
- options.fadeDuration = options.fadeDuration ||
- (md.options.toolTipFade ?
- (md.options.fadeDuration || areaOpts.fadeDuration) : 0);
-
- target = ad.area ?
- ad.area :
- $.map(ad.areas(),
- function(e) {
- return e.area;
- });
-
- if (md.activeToolTipID===ad.areaId) {
- return;
- }
-
- md.clearToolTip();
-
- md.activeToolTip = tooltip = createToolTip(content,
- template,
- options.css);
-
- md.activeToolTipID = ad.areaId;
-
- tipClosed = function() {
- md.clearToolTip();
- };
-
- bindToolTipClose(closeOpts,'area-click', 'click', $(md.map), null, tipClosed);
- bindToolTipClose(closeOpts,'tooltip-click', 'click', tooltip,null, tipClosed);
- bindToolTipClose(closeOpts,'image-mouseout', 'mouseout', $(md.image), function(e) {
- return (e.relatedTarget && e.relatedTarget.nodeName!=='AREA' && e.relatedTarget!==ad.area);
- }, tipClosed);
-
-
- showToolTip(tooltip,
- target,
- md.image,
- options.container,
- template,
- options);
-
- u.ifFunction(md.options.onShowToolTip, ad.area,
- {
- toolTip: tooltip,
- options: ttopts,
- areaOptions: areaOpts,
- key: ad.key,
- selected: ad.isSelected()
+ m.AreaData.prototype.showToolTip = function (content, options) {
+ var tooltip,
+ closeOpts,
+ target,
+ tipClosed,
+ template,
+ ttopts = {},
+ ad = this,
+ md = ad.owner,
+ areaOpts = ad.effectiveOptions();
+
+ // copy the options object so we can update it
+ options = options ? $.extend({}, options) : {};
+
+ content = content || areaOpts.toolTip;
+ closeOpts =
+ options.closeEvents ||
+ areaOpts.toolTipClose ||
+ md.options.toolTipClose ||
+ 'tooltip-click';
+
+ template =
+ typeof options.template !== 'undefined'
+ ? options.template
+ : md.options.toolTipContainer;
+
+ options.closeEvents =
+ typeof closeOpts === 'string'
+ ? (closeOpts = u.split(closeOpts))
+ : closeOpts;
+
+ options.fadeDuration =
+ options.fadeDuration ||
+ (md.options.toolTipFade
+ ? md.options.fadeDuration || areaOpts.fadeDuration
+ : 0);
+
+ target = ad.area
+ ? ad.area
+ : $.map(ad.areas(), function (e) {
+ return e.area;
});
- return tooltip;
- };
-
-
- /**
- * Parse an object that could be a string, a jquery object, or an object with a "contents" property
- * containing html or a jQuery object.
- *
- * @param {object|string|jQuery} options The parameter to parse
- * @return {string|jquery} A string or jquery object
- */
- function getHtmlFromOptions(options) {
-
- // see if any html was passed as either the options object itself, or the content property
-
- return (options ?
- ((typeof options === 'string' || options.jquery) ?
- options :
- options.content) :
- null);
+ if (md.activeToolTipID === ad.areaId) {
+ return;
}
- /**
- * Activate or remove a tooltip for an area. When this method is called on an area, the
- * key parameter doesn't apply and "options" is the first parameter.
- *
- * When called with no parameters, or "key" is a falsy value, any active tooltip is cleared.
- *
- * When only a key is provided, the default tooltip for the area is used.
- *
- * When html is provided, this is used instead of the default tooltip.
- *
- * When "noTemplate" is true, the default tooltip template will not be used either, meaning only
- * the actual html passed will be used.
- *
- * @param {string|AreaElement} key The area for which to activate a tooltip, or a DOM element.
- *
- * @param {object|string|jquery} [options] options to apply when creating this tooltip - OR -
- * The markup, or a jquery object, containing the data for the tooltip
- * @config {string|jQuery} [content] the inner content of the tooltip; the tooltip text or HTML
- * @config {Element|jQuery} [container] the inner content of the tooltip; the tooltip text or HTML
- * @config {bool} [template] a template to use instead of the default. If this property exists and is null,
- * then no template will be used.
- * @config {int} [offsetx] the horizontal amount to offset the tooltip.
- * @config {int} [offsety] the vertical amount to offset the tooltip.
- * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
- * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
- * @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
- * @return {jQuery} The jQuery object
- */
+ md.clearToolTip();
- m.impl.tooltip = function (key,options) {
- return (new m.Method(this,
- function mapData() {
- var tooltip, target, md=this;
- if (!key) {
- md.clearToolTip();
- } else {
- target=$(key);
- if (md.activeToolTipID ===target[0]) {
- return;
- }
- md.clearToolTip();
+ md.activeToolTip = tooltip = createToolTip(content, template, options.css);
- md.activeToolTip = tooltip = createToolTip(getHtmlFromOptions(options),
- options.template || md.options.toolTipContainer,
- options.css);
- md.activeToolTipID = target[0];
+ md.activeToolTipID = ad.areaId;
- bindToolTipClose(['tooltip-click'],'tooltip-click', 'click', tooltip, null, function() {
- md.clearToolTip();
- });
+ tipClosed = function () {
+ md.clearToolTip();
+ };
- md.activeToolTip = tooltip = showToolTip(tooltip,
- target,
- md.image,
- options.container,
- options);
- }
- },
- function areaData() {
- if ($.isPlainObject(key) && !options) {
- options = key;
- }
+ bindToolTipClose(
+ closeOpts,
+ 'area-click',
+ 'click',
+ $(md.map),
+ null,
+ tipClosed
+ );
+ bindToolTipClose(
+ closeOpts,
+ 'tooltip-click',
+ 'click',
+ tooltip,
+ null,
+ tipClosed
+ );
+ bindToolTipClose(
+ closeOpts,
+ 'image-mouseout',
+ 'mouseout',
+ $(md.image),
+ function (e) {
+ return (
+ e.relatedTarget &&
+ e.relatedTarget.nodeName !== 'AREA' &&
+ e.relatedTarget !== ad.area
+ );
+ },
+ tipClosed
+ );
+
+ showToolTip(
+ tooltip,
+ target,
+ md.image,
+ options.container,
+ template,
+ options
+ );
+
+ u.ifFunction(md.options.onShowToolTip, ad.area, {
+ toolTip: tooltip,
+ options: ttopts,
+ areaOptions: areaOpts,
+ key: ad.key,
+ selected: ad.isSelected()
+ });
- this.showToolTip(getHtmlFromOptions(options),options);
- },
- {
- name: 'tooltip',
- args: arguments,
- key: key
+ return tooltip;
+ };
+
+ /**
+ * Parse an object that could be a string, a jquery object, or an object with a "contents" property
+ * containing html or a jQuery object.
+ *
+ * @param {object|string|jQuery} options The parameter to parse
+ * @return {string|jquery} A string or jquery object
+ */
+ function getHtmlFromOptions(options) {
+ // see if any html was passed as either the options object itself, or the content property
+
+ return options
+ ? typeof options === 'string' || options.jquery
+ ? options
+ : options.content
+ : null;
+ }
+
+ /**
+ * Activate or remove a tooltip for an area. When this method is called on an area, the
+ * key parameter doesn't apply and "options" is the first parameter.
+ *
+ * When called with no parameters, or "key" is a falsy value, any active tooltip is cleared.
+ *
+ * When only a key is provided, the default tooltip for the area is used.
+ *
+ * When html is provided, this is used instead of the default tooltip.
+ *
+ * When "noTemplate" is true, the default tooltip template will not be used either, meaning only
+ * the actual html passed will be used.
+ *
+ * @param {string|AreaElement} key The area for which to activate a tooltip, or a DOM element.
+ *
+ * @param {object|string|jquery} [options] options to apply when creating this tooltip - OR -
+ * The markup, or a jquery object, containing the data for the tooltip
+ * @config {string|jQuery} [content] the inner content of the tooltip; the tooltip text or HTML
+ * @config {Element|jQuery} [container] the inner content of the tooltip; the tooltip text or HTML
+ * @config {bool} [template] a template to use instead of the default. If this property exists and is null,
+ * then no template will be used.
+ * @config {int} [offsetx] the horizontal amount to offset the tooltip.
+ * @config {int} [offsety] the vertical amount to offset the tooltip.
+ * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
+ * @config {string|object} [css] CSS to apply to the outermost element of the tooltip
+ * @config {bool} [fadeDuration] When non-zero, the duration in milliseconds of a fade-in effect for the tooltip.
+ * @return {jQuery} The jQuery object
+ */
+
+ m.impl.tooltip = function (key, options) {
+ return new m.Method(
+ this,
+ function mapData() {
+ var tooltip,
+ target,
+ md = this;
+ if (!key) {
+ md.clearToolTip();
+ } else {
+ target = $(key);
+ if (md.activeToolTipID === target[0]) {
+ return;
+ }
+ md.clearToolTip();
+
+ md.activeToolTip = tooltip = createToolTip(
+ getHtmlFromOptions(options),
+ options.template || md.options.toolTipContainer,
+ options.css
+ );
+ md.activeToolTipID = target[0];
+
+ bindToolTipClose(
+ ['tooltip-click'],
+ 'tooltip-click',
+ 'click',
+ tooltip,
+ null,
+ function () {
+ md.clearToolTip();
+ }
+ );
+
+ md.activeToolTip = tooltip = showToolTip(
+ tooltip,
+ target,
+ md.image,
+ options.container,
+ options
+ );
}
- )).go();
- };
-} (jQuery));
+ },
+ function areaData() {
+ if ($.isPlainObject(key) && !options) {
+ options = key;
+ }
+
+ this.showToolTip(getHtmlFromOptions(options), options);
+ },
+ {
+ name: 'tooltip',
+ args: arguments,
+ key: key
+ }
+ ).go();
+ };
+})(jQuery);
}));
\ No newline at end of file
diff --git a/dist/jquery.imagemapster.min.js b/dist/jquery.imagemapster.min.js
index 17e13f7..85e5d8d 100644
--- a/dist/jquery.imagemapster.min.js
+++ b/dist/jquery.imagemapster.min.js
@@ -5,5 +5,5 @@
* License: MIT
*/
-!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),a(t),t}:a(jQuery)}(function(jQuery){function id(e,t,a){var i=e,n=i.map_data,s=a.isMask;cd.each(t.areas(),function(e,t){a.isMask=s||t.nohref&&n.options.noHrefIsMask,i.addShape(t,a)}),a.isMask=s}function jd(e){return Math.max(0,Math.min(parseInt(e,16),255))}function kd(e,t){return"rgba("+jd(e.substr(0,2))+","+jd(e.substr(2,2))+","+jd(e.substr(4,2))+","+t+")"}function ld(){}var cd,dd,gd,hd,ed,fd,Se,Te,Ue,Ve,Bf,Cf,Df,ui,vi,wi,lj,mj,Rj,Sj,Tj,Uj,Lk,Mk,Nk;function Gf(e){var t=e.options,a=e.images;Cf.hasCanvas()&&(Bf.each(t.altImages||{},function(e,t){a.add(t,e)}),Bf.each([t].concat(t.areas),function(e,t){Bf.each([t=t,t.render_highlight,t.render_select],function(e,t){t&&t.altImage&&(t.altImageId=a.add(t.altImage))})})),e.area_options=Df.updateProps({},Cf.area_defaults,t)}function Kf(e,t){var a=e.getDataForArea(this),i=e.options;e.currentAreaId<0||!a||e.getDataForArea(t.relatedTarget)!==a&&(e.currentAreaId=-1,a.area=null,function e(t,a,i,n){return n=n||Df.when.defer(),t.activeAreaEvent&&(window.clearTimeout(t.activeAreaEvent),t.activeAreaEvent=0),a<0?n.reject():i.owner.currentAction||a?t.activeAreaEvent=window.setTimeout(function(){e(t,0,i,n)},a||100):(a=i.areaId,t.currentAreaId!==a&&0<=t.highlightId&&n.resolve()),n}(e,i.mouseoutDelay,a).then(e.clearEffects),Df.isFunction(i.onMouseout)&&i.onMouseout.call(this,{e:t,options:i,key:a.key,selected:a.isSelected()}))}function Mf(i,n){var s,o,r,c,l,u=this,e=i.getDataForArea(this),h=i.options;(function(e){Cf.hasCanvas()||this.blur(),e.preventDefault()}).call(this,n),h.clickNavigate&&e.href?window.location.href=e.href:e&&!e.owner.currentAction&&(h=i.options,function a(e){var t;if(c=e.isSelectable()&&(e.isDeselectable()||!e.isSelected()),r=c?!e.isSelected():e.isSelected(),o=Cf.getBoundList(h,e.key),Df.isFunction(h.onClick)&&(l=h.onClick.call(u,{e:n,listTarget:o,key:e.key,selected:r}),Df.isBool(l))){if(!l)return;if("#"!==(t=Bf(e.area).attr("href")))return void(window.location.href=t)}c&&e.toggle(),h.boundList&&0=e.index;t--)m.map_cache[t].index--};function hasVml(){var e=$("
").appendTo("body");e.html(' ');var t=e[0].firstChild;t.style.behavior="url(#default#VML)";t=!t||"object"==typeof t.adj;return e.remove(),t}function namespaces(){return"object"==typeof document.namespaces?document.namespaces:null}function hasCanvas(){var e=namespaces();return(!e||!e.g_vml_)&&!!$(" ")[0].getContext}function merge_areas(a,e){var i,n=a.options.areas;e&&$.each(e,function(e,t){t&&t.key&&(0<=(i=u.indexOfProp(n,"key",t.key))?$.extend(n[i],t):n.push(t),(i=a.getDataForKey(t.key))&&$.extend(i.options,t))})}function merge_options(e,t){var a=u.updateProps({},t);delete a.areas,u.updateProps(e.options,a),merge_areas(e,t.areas),u.updateProps(e.area_options,e.options)}return me.get=function(e){var t=m.getMapData(this);if(!t||!t.complete)throw"Can't access data until binding complete.";return new m.Method(this,function(){return this.getSelected()},function(){return this.isSelected()},{name:"get",args:arguments,key:e,first:!0,allowAsync:!0,defaultReturn:""}).go()},me.data=function(e){return new m.Method(this,null,function(){return this},{name:"data",args:arguments,key:e}).go()},me.highlight=function(t){return new m.Method(this,function(){if(!1!==t){var e=this.highlightId;return 0<=e?this.data[e].key:null}this.ensureNoHighlight()},function(){this.highlight()},{name:"highlight",args:arguments,key:t,first:!0}).go()},me.keys=function(e,i){var n=[],a=m.getMapData(this);if(!a||!a.complete)throw"Can't access data until binding complete.";function s(e){var t,a=[];i?(t=e.areas(),$.each(t,function(e,t){a=a.concat(t.keys)})):a.push(e.key),$.each(a,function(e,t){$.inArray(t,n)<0&&n.push(t)})}return a&&a.complete?("string"==typeof e?i?s(a.getDataForKey(e)):n=[a.getKeysForGroup(e)]:(i=e,this.each(function(e,t){"AREA"===t.nodeName&&s(a.getDataForArea(t))})),n.join(",")):""},me.select=function(){me.set.call(this,!0)},me.deselect=function(){me.set.call(this,!1)},me.set=function(i,n,e){var s,o,r,c,l=e;function h(e){e&&$.inArray(e,c)<0&&(c.push(e),r+=(""===r?"":",")+e.key)}function d(a){$.each(c,function(e,t){t=function(e){var t=i;if(e){switch(i){case!0:e.select(l);break;case!1:e.deselect(!0);break;default:t=e.toggle(l)}return t}}(t);a.options.boundList&&m.setBoundListProperties(a.options,m.getBoundList(a.options,r),t)}),i||a.removeSelectionFinish()}return this.filter("img,area").each(function(e,t){var a;(o=m.getMapData(t))!==s&&(s&&d(s),c=[],r=""),o&&(a="","IMG"===t.nodeName.toUpperCase()?m.queueCommand(o,$(t),"set",[i,n,l])||(n instanceof Array?n.length&&(a=n.join(",")):a=n,a&&$.each(u.split(a),function(e,t){h(o.getDataForKey(t.toString())),s=o})):(l=n,m.queueCommand(o,$(t),"set",[i,l])||(h(o.getDataForArea(t)),s=o)))}),o&&d(o),this},me.unbind=function(e){return new m.Method(this,function(){this.clearEvents(),this.clearMapData(e),removeMap(this)},null,{name:"unbind",args:arguments}).go()},me.rebind=function(t){return new m.Method(this,function(){var e=this;e.complete=!1,e.configureOptions(t),e.bindImages().then(function(){e.buildDataset(!0),e.complete=!0})},null,{name:"rebind",args:arguments}).go()},me.get_options=function(e,t){var a=u.isBool(e)?e:t;return new m.Method(this,function(){var e=$.extend({},this.options);return a&&(e.render_select=u.updateProps({},m.render_defaults,e,e.render_select),e.render_highlight=u.updateProps({},m.render_defaults,e,e.render_highlight)),e},function(){return a?this.effectiveOptions():this.options},{name:"get_options",args:arguments,first:!0,allowAsync:!0,key:e}).go()},me.set_options=function(e){return new m.Method(this,function(){merge_options(this,e)},null,{name:"set_options",args:arguments}).go()},me.unload=function(){for(var e=m.map_cache.length-1;0<=e;e--)m.map_cache[e]&&me.unbind.call($(m.map_cache[e].image));me.graphics=null},me.snapshot=function(){return new m.Method(this,function(){$.each(this.data,function(e,t){t.selected=!1}),this.base_canvas=this.graphics.createVisibleCanvas(this),$(this.image).before(this.base_canvas)},null,{name:"snapshot"}).go()},me.state=function(){var a,i=null;return $(this).each(function(e,t){if("IMG"===t.nodeName)return(a=m.getMapData(t))&&(i=a.state()),!1}),i},me.bind=function(s){return this.each(function(e,t){var a,i=$(t),n=m.getMapData(t);if(n){if(me.unbind.apply(i),!n.complete)return i.on(),!0;n=null}if(t=(a=this.getAttribute("usemap"))&&$('map[name="'+a.substr(1)+'"]'),!(i.is("img")&&a&&0')[0]},clearHighlight:function(){var e=this.map_data.overlay_canvas;e.getContext("2d").clearRect(0,0,e.width,e.height)},refreshSelections:function(){var e=this.map_data,t=e.base_canvas;e.base_canvas=this.createVisibleCanvas(e),cd(e.base_canvas).hide(),cd(t).before(e.base_canvas),e.redrawSelections(),cd(e.base_canvas).show(),cd(t).remove()}},hd={renderShape:function(e,t,a){var i,n=this,s=e.coords(),o=n.elementName?'name="'+n.elementName+'" ':"",r=a?'class="'+a+'" ':"",c=' ',l=t.stroke?" strokeweight="+t.strokeWidth+' stroked="t" strokecolor="#'+t.strokeColor+'"':' stroked="f"',u=t.fill?' filled="t"':' filled="f"';switch(e.shape){case"rect":i="'+c+" ";break;case"poly":i="'+c+" ";break;case"circ":case"circle":i="'+c+" "}return e=cd(i),cd(n.canvas).append(e),e},render:function(){var a,i=this;return cd.each(this.shapes,function(e,t){i.renderShape(t.mapArea,t.options)}),this.masks.length&&cd.each(this.masks,function(e,t){a=fd.updateProps({},t.options,{fillOpacity:1,fillColor:t.options.fillColorMask}),i.renderShape(t.mapArea,a,"mapster_mask")}),this.active=!1,this.canvas},createCanvasFor:function(e){var t=e.scaleInfo.width,e=e.scaleInfo.height;return cd(' ')[0]},clearHighlight:function(){cd(this.map_data.overlay_canvas).children().remove()},removeSelections:function(e){(0<=e?cd(this.map_data.base_canvas).find('[name="static_'+e.toString()+'"]'):cd(this.map_data.base_canvas).children()).remove()}},cd.each(["renderShape","addAltImage","render","createCanvasFor","clearHighlight","removeSelections","refreshSelections"],function(e,t){var a;dd[t]=(a=t,function(){return dd[a]=(ed.hasCanvas()?gd:hd)[a]||ld,dd[a].apply(this,arguments)})}),Se=jQuery,Te=Se.mapster,Ue=Te.utils,Ve=[],Te.MapImages=function(e){this.owner=e,this.clear()},Te.MapImages.prototype={constructor:Te.MapImages,slice:function(){return Ve.slice.apply(this,arguments)},splice:function(){return Ve.slice.apply(this.status,arguments),Ve.slice.apply(this,arguments)},complete:function(){return Se.inArray(!1,this.status)<0},_add:function(e){e=Ve.push.call(this,e)-1;return this.status[e]=!1,e},indexOf:function(e){return Ue.indexOf(this,e)},clear:function(){var a=this;a.ids&&0 ").addClass("mapster_el").hide(),a=n._add(e[0]),e.on("load",function(e){n.imageLoaded.call(n,e)}).on("error",function(e){n.imageLoadError.call(n,e)}),e.attr("src",i)}else a=n._add(Se(e)[0]);if(t){if(this[t])throw t+" is already used or is not available as an altImage alias.";n.ids.push(t),n[t]=n[a]}return a}},bind:function(e){var t=this,a=t.owner.options.configTimeout/200,i=function(){for(var e=t.length;0'),u.wrapClass&&(!0===u.wrapClass?a.addClass(s[0].className):a.addClass(u.wrapClass))),l.wrapper=a,l.scaleInfo=c=Df.scaleMap(l.images[0],l.images[1],u.scaleMap),l.base_canvas=t=l.graphics.createVisibleCanvas(l),l.overlay_canvas=r=l.graphics.createVisibleCanvas(l),e=Bf(l.images[1]).addClass("mapster_el "+l.images[0].className).attr({id:null,usemap:null}),(n=Df.size(l.images[0])).complete&&e.css({width:n.width,height:n.height}),l.buildDataset(),c={display:"block",position:"relative",padding:0,width:c.width,height:c.height},u.wrapCss&&Bf.extend(c,u.wrapCss),s.parent()[0]!==l.wrapper[0]&&s.before(l.wrapper),a.css(c),Bf(l.images.slice(2)).hide(),i=1;iw&&t[1]>k)return v=t,!(o=!0)}),o||(v=[l,u])),v},Rj=jQuery,Sj=Rj.mapster,Tj=Sj.utils,Uj=Sj.MapArea.prototype,Sj.utils.getScaleInfo=function(e,t){var a;return t?.98<(a=e.width/t.width||e.height/t.height)&&a<1.02&&(a=1):(a=1,t=e),{scale:1!==a,scalePct:a,realWidth:t.width,realHeight:t.height,width:e.width,height:e.height,ratio:e.width/e.height}},Sj.utils.scaleMap=function(e,t,a){e=Tj.size(e),t=Tj.size(t,!0);if(!t.complete())throw"Another script, such as an extension, appears to be interfering with image loading. Please let us know about this.";return e.complete()||(e=t),this.getScaleInfo(e,a?t:null)},Sj.MapData.prototype.resize=function(t,a,i,n){var s,o,r,c,e,l=this;function u(e,t,a){Sj.hasCanvas()?(e.width=t,e.height=a):(Rj(e).width(t),Rj(e).height(a))}function h(){var e;u(l.overlay_canvas,t,a),0<=c&&((e=l.data[c]).tempOptions={fade:!1},l.getDataForKey(e.key).highlight(),e.tempOptions=null),u(l.base_canvas,t,a),l.redrawSelections(),l.currentAction="",Tj.isFunction(n)&&n(),l.processCommandQueue()}function d(){Rj(l.image).css(r),l.scaleInfo=Tj.getScaleInfo({width:t,height:a},{width:l.scaleInfo.realWidth,height:l.scaleInfo.realHeight}),Rj.each(l.data,function(e,t){Rj.each(t.areas(),function(e,t){t.resize()})})}n=n||i,l.scaleInfo.width===t&&l.scaleInfo.height===a||(c=l.highlightId,t||(e=a/l.scaleInfo.realHeight,t=Math.round(l.scaleInfo.realWidth*e)),a||(e=t/l.scaleInfo.realWidth,a=Math.round(l.scaleInfo.realHeight*e)),r={width:String(t)+"px",height:String(a)+"px"},Sj.hasCanvas()||Rj(l.base_canvas).children().remove(),e=Rj(l.wrapper).find(".mapster_el").add(l.wrapper),i?(o=[],l.currentAction="resizing",e.each(function(e,t){s=Tj.defer(),o.push(s),Rj(t).animate(r,{duration:i,complete:s.resolve,easing:"linear"})}),s=Tj.defer(),o.push(s),Tj.when.all(o).then(h),d(),s.resolve()):(e.css(r),d(),h()))},Sj.MapArea=Tj.subclass(Sj.MapArea,function(){this.base.init(),this.owner.scaleInfo.scale&&this.resize()}),Uj.coords=function(e,t){var a,i=[],n=e||this.owner.scaleInfo.scalePct,s=t||0;if(1===n&&0===t)return this.originalCoords;for(a=0;a',showToolTip:!1,toolTipFade:!0,toolTipClose:["area-mouseout","image-mouseout"],onShowToolTip:null,onHideToolTip:null}),Lk.extend(Mk.area_defaults,{toolTip:null,toolTipClose:null}),Mk.MapData.prototype.clearToolTip=function(){this.activeToolTip&&(this.activeToolTip.stop().remove(),this.activeToolTip=null,this.activeToolTipID=null,Nk.ifFunction(this.options.onHideToolTip,this))},Mk.AreaData.prototype.showToolTip=function(e,t){var a,i,n,s,o=this,r=o.owner,c=o.effectiveOptions();if(t=t?Lk.extend({},t):{},e=e||c.toolTip,i=t.closeEvents||c.toolTipClose||r.options.toolTipClose||"tooltip-click",s=void 0!==t.template?t.template:r.options.toolTipContainer,t.closeEvents="string"==typeof i?i=Nk.split(i):i,t.fadeDuration=t.fadeDuration||(r.options.toolTipFade?r.options.fadeDuration||c.fadeDuration:0),n=o.area||Lk.map(o.areas(),function(e){return e.area}),r.activeToolTipID!==o.areaId)return r.clearToolTip(),r.activeToolTip=a=Ok(e,s,t.css),r.activeToolTipID=o.areaId,e=function(){r.clearToolTip()},Qk(i,"area-click","click",Lk(r.map),null,e),Qk(i,"tooltip-click","click",a,null,e),Qk(i,"image-mouseout","mouseout",Lk(r.image),function(e){return e.relatedTarget&&"AREA"!==e.relatedTarget.nodeName&&e.relatedTarget!==o.area},e),Rk(a,n,r.image,t.container,s),Nk.ifFunction(r.options.onShowToolTip,o.area,{toolTip:a,options:{},areaOptions:c,key:o.key,selected:o.isSelected()}),a},Mk.impl.tooltip=function(i,n){return new Mk.Method(this,function(){var e,t,a=this;i?(t=Lk(i),a.activeToolTipID!==t[0]&&(a.clearToolTip(),a.activeToolTip=e=Ok(Sk(n),n.template||a.options.toolTipContainer,n.css),a.activeToolTipID=t[0],Qk(["tooltip-click"],"tooltip-click","click",e,null,function(){a.clearToolTip()}),a.activeToolTip=Rk(e,t,a.image,n.container,n))):a.clearToolTip()},function(){Lk.isPlainObject(i)&&!n&&(n=i),this.showToolTip(Sk(n),n)},{name:"tooltip",args:arguments,key:i}).go()}});
+!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof module&&module.exports?module.exports=function(e,t){return void 0===t&&(t="undefined"!=typeof window?require("jquery"):require("jquery")(e)),a(t),t}:a(jQuery)}(function(jQuery){!function(e){"use strict";var i,t=!1;try{var a=Object.defineProperty({},"passive",{get:function(){return t=!0}});window.addEventListener("testPassive.mapster",function(){},a),window.removeEventListener("testPassive.mapster",function(){},a)}catch(e){}t&&(i=function(e,t,a){if(!e.includes("noPreventDefault"))return console.warn("non-passive events - listener not added"),!1;window.addEventListener(t,a,{passive:!0})},e.event.special.touchstart={setup:function(e,t,a){return i(t,"touchstart",a)}},e.event.special.touchend={setup:function(e,t,a){return i(t,"touchend",a)}})}(jQuery),function($){"use strict";var mapster_version="1.3.2-beta.0",ya,za,Aa;$.fn.mapster=function(e){var t=$.mapster.impl;return $.mapster.utils.isFunction(t[e])?t[e].apply(this,Array.prototype.slice.call(arguments,1)):"object"!=typeof e&&e?void $.error("Method "+e+" does not exist on jQuery.mapster"):t.bind.apply(this,arguments)},$.mapster={version:mapster_version,render_defaults:{isSelectable:!0,isDeselectable:!0,fade:!1,fadeDuration:150,fill:!0,fillColor:"000000",fillColorMask:"FFFFFF",fillOpacity:.7,highlight:!0,stroke:!1,strokeColor:"ff0000",strokeOpacity:1,strokeWidth:1,includeKeys:"",altImage:null,altImageId:null,altImages:{}},defaults:{clickNavigate:!1,wrapClass:null,wrapCss:null,onGetList:null,sortList:!1,listenToList:!1,mapKey:"",mapValue:"",singleSelect:!1,listKey:"value",listSelectedAttribute:"selected",listSelectedClass:null,onClick:null,onMouseover:null,onMouseout:null,mouseoutDelay:0,onStateChange:null,boundList:null,onConfigured:null,configTimeout:3e4,noHrefIsMask:!0,scaleMap:!0,safeLoad:!1,areas:[]},shared_defaults:{render_highlight:{fade:!0},render_select:{fade:!1},staticState:null,selected:null},area_defaults:{includeKeys:"",isMask:!1},canvas_style:{position:"absolute",left:0,top:0,padding:0,border:0},hasCanvas:null,map_cache:[],hooks:{},addHook:function(e,t){this.hooks[e]=(this.hooks[e]||[]).push(t)},callHooks:function(e,a){$.each(this.hooks[e]||[],function(e,t){t.apply(a)})},utils:{when:{all:function(e){return Promise.all(e)},defer:function(){return new function(){this.promise=new Promise(function(e,t){this.resolve=e,this.reject=t}.bind(this)),this.then=this.promise.then.bind(this.promise),this.catch=this.promise.catch.bind(this.promise)}}},defer:function(){return this.when.defer()},subclass:function(a,i){function e(){var e=this,t=Array.prototype.slice.call(arguments,0);e.base=a.prototype,e.base.init=function(){a.prototype.constructor.apply(e,t)},i.apply(e,t)}return(e.prototype=new a).constructor=e},asArray:function(e){return e.constructor===Array?e:this.split(e)},split:function(e,t){for(var a,i=e.split(","),n=0;n=e.index;t--)m.map_cache[t].index--};function hasVml(){var e=$("
").appendTo("body");e.html(' ');var t=e[0].firstChild;t.style.behavior="url(#default#VML)";t=!t||"object"==typeof t.adj;return e.remove(),t}function namespaces(){return"object"==typeof document.namespaces?document.namespaces:null}function hasCanvas(){var e=namespaces();return(!e||!e.g_vml_)&&!!$(" ")[0].getContext}function merge_areas(a,e){var i,n=a.options.areas;e&&$.each(e,function(e,t){t&&t.key&&(0<=(i=u.indexOfProp(n,"key",t.key))?$.extend(n[i],t):n.push(t),(i=a.getDataForKey(t.key))&&$.extend(i.options,t))})}function merge_options(e,t){var a=u.updateProps({},t);delete a.areas,u.updateProps(e.options,a),merge_areas(e,t.areas),u.updateProps(e.area_options,e.options)}return me.get=function(e){var t=m.getMapData(this);if(!t||!t.complete)throw"Can't access data until binding complete.";return new m.Method(this,function(){return this.getSelected()},function(){return this.isSelected()},{name:"get",args:arguments,key:e,first:!0,allowAsync:!0,defaultReturn:""}).go()},me.data=function(e){return new m.Method(this,null,function(){return this},{name:"data",args:arguments,key:e}).go()},me.highlight=function(t){return new m.Method(this,function(){if(!1!==t){var e=this.highlightId;return 0<=e?this.data[e].key:null}this.ensureNoHighlight()},function(){this.highlight()},{name:"highlight",args:arguments,key:t,first:!0}).go()},me.keys=function(e,i){var n=[],a=m.getMapData(this);if(!a||!a.complete)throw"Can't access data until binding complete.";function s(e){var t,a=[];i?(t=e.areas(),$.each(t,function(e,t){a=a.concat(t.keys)})):a.push(e.key),$.each(a,function(e,t){$.inArray(t,n)<0&&n.push(t)})}return a&&a.complete?("string"==typeof e?i?s(a.getDataForKey(e)):n=[a.getKeysForGroup(e)]:(i=e,this.each(function(e,t){"AREA"===t.nodeName&&s(a.getDataForArea(t))})),n.join(",")):""},me.select=function(){me.set.call(this,!0)},me.deselect=function(){me.set.call(this,!1)},me.set=function(i,n,e){var s,o,r,c,l=e;function h(e){e&&$.inArray(e,c)<0&&(c.push(e),r+=(""===r?"":",")+e.key)}function p(a){$.each(c,function(e,t){t=function(e){var t=i;if(e){switch(i){case!0:e.select(l);break;case!1:e.deselect(!0);break;default:t=e.toggle(l)}return t}}(t);a.options.boundList&&m.setBoundListProperties(a.options,m.getBoundList(a.options,r),t)}),i||a.removeSelectionFinish()}return this.filter("img,area").each(function(e,t){var a;(o=m.getMapData(t))!==s&&(s&&p(s),c=[],r=""),o&&(a="","IMG"===t.nodeName.toUpperCase()?m.queueCommand(o,$(t),"set",[i,n,l])||(n instanceof Array?n.length&&(a=n.join(",")):a=n,a&&$.each(u.split(a),function(e,t){h(o.getDataForKey(t.toString())),s=o})):(l=n,m.queueCommand(o,$(t),"set",[i,l])||(h(o.getDataForArea(t)),s=o)))}),o&&p(o),this},me.unbind=function(e){return new m.Method(this,function(){this.clearEvents(),this.clearMapData(e),removeMap(this)},null,{name:"unbind",args:arguments}).go()},me.rebind=function(t){return new m.Method(this,function(){var e=this;e.complete=!1,e.configureOptions(t),e.bindImages().then(function(){e.buildDataset(!0),e.complete=!0})},null,{name:"rebind",args:arguments}).go()},me.get_options=function(e,t){var a=u.isBool(e)?e:t;return new m.Method(this,function(){var e=$.extend({},this.options);return a&&(e.render_select=u.updateProps({},m.render_defaults,e,e.render_select),e.render_highlight=u.updateProps({},m.render_defaults,e,e.render_highlight)),e},function(){return a?this.effectiveOptions():this.options},{name:"get_options",args:arguments,first:!0,allowAsync:!0,key:e}).go()},me.set_options=function(e){return new m.Method(this,function(){merge_options(this,e)},null,{name:"set_options",args:arguments}).go()},me.unload=function(){for(var e=m.map_cache.length-1;0<=e;e--)m.map_cache[e]&&me.unbind.call($(m.map_cache[e].image));me.graphics=null},me.snapshot=function(){return new m.Method(this,function(){$.each(this.data,function(e,t){t.selected=!1}),this.base_canvas=this.graphics.createVisibleCanvas(this),$(this.image).before(this.base_canvas)},null,{name:"snapshot"}).go()},me.state=function(){var a,i=null;return $(this).each(function(e,t){if("IMG"===t.nodeName)return(a=m.getMapData(t))&&(i=a.state()),!1}),i},me.bind=function(s){return this.each(function(e,t){var a,i=$(t),n=m.getMapData(t);if(n){if(me.unbind.apply(i),!n.complete)return i.on(),!0;n=null}if(t=(a=this.getAttribute("usemap"))&&$('map[name="'+a.substr(1)+'"]'),!(i.is("img")&&a&&0')[0]},clearHighlight:function(){var e=this.map_data.overlay_canvas;e.getContext("2d").clearRect(0,0,e.width,e.height)},refreshSelections:function(){var e=this.map_data,t=e.base_canvas;e.base_canvas=this.createVisibleCanvas(e),h(e.base_canvas).hide(),h(t).before(e.base_canvas),e.redrawSelections(),h(e.base_canvas).show(),h(t).remove()}},s={renderShape:function(e,t,a){var i,n=this,s=e.coords(),o=n.elementName?'name="'+n.elementName+'" ':"",r=a?'class="'+a+'" ':"",c=' ',l=t.stroke?" strokeweight="+t.strokeWidth+' stroked="t" strokecolor="#'+t.strokeColor+'"':' stroked="f"',u=t.fill?' filled="t"':' filled="f"';switch(e.shape){case"rect":i="'+c+" ";break;case"poly":i="'+c+" ";break;case"circ":case"circle":i="'+c+" "}return e=h(i),h(n.canvas).append(e),e},render:function(){var a,i=this;return h.each(this.shapes,function(e,t){i.renderShape(t.mapArea,t.options)}),this.masks.length&&h.each(this.masks,function(e,t){a=c.updateProps({},t.options,{fillOpacity:1,fillColor:t.options.fillColorMask}),i.renderShape(t.mapArea,a,"mapster_mask")}),this.active=!1,this.canvas},createCanvasFor:function(e){var t=e.scaleInfo.width,e=e.scaleInfo.height;return h(' ')[0]},clearHighlight:function(){h(this.map_data.overlay_canvas).children().remove()},removeSelections:function(e){(0<=e?h(this.map_data.base_canvas).find('[name="static_'+e.toString()+'"]'):h(this.map_data.base_canvas).children()).remove()}},h.each(["renderShape","addAltImage","render","createCanvasFor","clearHighlight","removeSelections","refreshSelections"],function(e,t){var a;i[t]=(a=t,function(){return i[a]=(r.hasCanvas()?n:s)[a]||o,i[a].apply(this,arguments)})})}(jQuery),function(s){"use strict";var e=s.mapster,n=e.utils,t=[];e.MapImages=function(e){this.owner=e,this.clear()},e.MapImages.prototype={constructor:e.MapImages,slice:function(){return t.slice.apply(this,arguments)},splice:function(){return t.slice.apply(this.status,arguments),t.slice.apply(this,arguments)},complete:function(){return s.inArray(!1,this.status)<0},_add:function(e){e=t.push.call(this,e)-1;return this.status[e]=!1,e},indexOf:function(e){return n.indexOf(this,e)},clear:function(){var a=this;a.ids&&0 ").addClass("mapster_el").hide(),a=n._add(e[0]),e.on("load",function(e){n.imageLoaded.call(n,e)}).on("error",function(e){n.imageLoadError.call(n,e)}),e.attr("src",i)}else a=n._add(s(e)[0]);if(t){if(this[t])throw t+" is already used or is not available as an altImage alias.";n.ids.push(t),n[t]=n[a]}return a}},bind:function(){var t=this,a=t.owner.options.configTimeout/200,i=function(){for(var e=t.length;0'),u.wrapClass&&(!0===u.wrapClass?a.addClass(s[0].className):a.addClass(u.wrapClass))),l.wrapper=a,l.scaleInfo=c=p.scaleMap(l.images[0],l.images[1],u.scaleMap),l.base_canvas=t=l.graphics.createVisibleCanvas(l),l.overlay_canvas=r=l.graphics.createVisibleCanvas(l),e=y(l.images[1]).addClass("mapster_el "+l.images[0].className).attr({id:null,usemap:null}),(n=p.size(l.images[0])).complete&&e.css({width:n.width,height:n.height}),l.buildDataset(),c={display:"block",position:"relative",padding:0,width:c.width,height:c.height},u.wrapCss&&y.extend(c,u.wrapCss),s.parent()[0]!==l.wrapper[0]&&s.before(l.wrapper),a.css(c),y(l.images.slice(2)).hide(),i=1;iw&&t[1]>b)return v=t,!(o=!0)}),o||(v=[l,u])),v}}(jQuery),function(d){"use strict";var f=d.mapster,m=f.utils,e=f.MapArea.prototype;f.utils.getScaleInfo=function(e,t){var a;return t?.98<(a=e.width/t.width||e.height/t.height)&&a<1.02&&(a=1):(a=1,t=e),{scale:1!==a,scalePct:a,realWidth:t.width,realHeight:t.height,width:e.width,height:e.height,ratio:e.width/e.height}},f.utils.scaleMap=function(e,t,a){e=m.size(e),t=m.size(t,!0);if(!t.complete())throw"Another script, such as an extension, appears to be interfering with image loading. Please let us know about this.";return e.complete()||(e=t),this.getScaleInfo(e,a?t:null)},f.MapData.prototype.resize=function(t,a,i,n){var s,o,r,c,e,l=this;function u(e,t,a){f.hasCanvas()?(e.width=t,e.height=a):(d(e).width(t),d(e).height(a))}function h(){var e;u(l.overlay_canvas,t,a),0<=c&&((e=l.data[c]).tempOptions={fade:!1},l.getDataForKey(e.key).highlight(),e.tempOptions=null),u(l.base_canvas,t,a),l.redrawSelections(),l.currentAction="",m.isFunction(n)&&n(),l.processCommandQueue()}function p(){d(l.image).css(r),l.scaleInfo=m.getScaleInfo({width:t,height:a},{width:l.scaleInfo.realWidth,height:l.scaleInfo.realHeight}),d.each(l.data,function(e,t){d.each(t.areas(),function(e,t){t.resize()})})}n=n||i,l.scaleInfo.width===t&&l.scaleInfo.height===a||(c=l.highlightId,t||(e=a/l.scaleInfo.realHeight,t=Math.round(l.scaleInfo.realWidth*e)),a||(e=t/l.scaleInfo.realWidth,a=Math.round(l.scaleInfo.realHeight*e)),r={width:String(t)+"px",height:String(a)+"px"},f.hasCanvas()||d(l.base_canvas).children().remove(),e=d(l.wrapper).find(".mapster_el").add(l.wrapper),i?(o=[],l.currentAction="resizing",e.each(function(e,t){s=m.defer(),o.push(s),d(t).animate(r,{duration:i,complete:s.resolve,easing:"linear"})}),s=m.defer(),o.push(s),m.when.all(o).then(h),p(),s.resolve()):(e.css(r),p(),h()))},f.MapArea=m.subclass(f.MapArea,function(){this.base.init(),this.owner.scaleInfo.scale&&this.resize()}),e.coords=function(e,t){var a,i=[],n=e||this.owner.scaleInfo.scalePct,s=t||0;if(1===n&&0===t)return this.originalCoords;for(a=0;a',showToolTip:!1,toolTipFade:!0,toolTipClose:["area-mouseout","image-mouseout"],onShowToolTip:null,onHideToolTip:null}),l.extend(e.area_defaults,{toolTip:null,toolTipClose:null}),e.MapData.prototype.clearToolTip=function(){this.activeToolTip&&(this.activeToolTip.stop().remove(),this.activeToolTip=null,this.activeToolTipID=null,u.ifFunction(this.options.onHideToolTip,this))},e.AreaData.prototype.showToolTip=function(e,t){var a,i,n,s,o=this,r=o.owner,c=o.effectiveOptions();if(t=t?l.extend({},t):{},e=e||c.toolTip,i=t.closeEvents||c.toolTipClose||r.options.toolTipClose||"tooltip-click",s=void 0!==t.template?t.template:r.options.toolTipContainer,t.closeEvents="string"==typeof i?i=u.split(i):i,t.fadeDuration=t.fadeDuration||(r.options.toolTipFade?r.options.fadeDuration||c.fadeDuration:0),n=o.area||l.map(o.areas(),function(e){return e.area}),r.activeToolTipID!==o.areaId)return r.clearToolTip(),r.activeToolTip=a=h(e,s,t.css),r.activeToolTipID=o.areaId,e=function(){r.clearToolTip()},p(i,"area-click","click",l(r.map),null,e),p(i,"tooltip-click","click",a,null,e),p(i,"image-mouseout","mouseout",l(r.image),function(e){return e.relatedTarget&&"AREA"!==e.relatedTarget.nodeName&&e.relatedTarget!==o.area},e),d(a,n,r.image,t.container,s),u.ifFunction(r.options.onShowToolTip,o.area,{toolTip:a,options:{},areaOptions:c,key:o.key,selected:o.isSelected()}),a},e.impl.tooltip=function(i,n){return new e.Method(this,function(){var e,t,a=this;i?(t=l(i),a.activeToolTipID!==t[0]&&(a.clearToolTip(),a.activeToolTip=e=h(s(n),n.template||a.options.toolTipContainer,n.css),a.activeToolTipID=t[0],p(["tooltip-click"],"tooltip-click","click",e,null,function(){a.clearToolTip()}),a.activeToolTip=d(e,t,a.image,n.container,n))):a.clearToolTip()},function(){l.isPlainObject(i)&&!n&&(n=i),this.showToolTip(s(n),n)},{name:"tooltip",args:arguments,key:i}).go()}}(jQuery)});
//# sourceMappingURL=jquery.imagemapster.min.js.map
\ No newline at end of file
diff --git a/dist/jquery.imagemapster.min.js.map b/dist/jquery.imagemapster.min.js.map
index 5aac7f8..997c2aa 100644
--- a/dist/jquery.imagemapster.min.js.map
+++ b/dist/jquery.imagemapster.min.js.map
@@ -1 +1 @@
-{"version":3,"file":"jquery.imagemapster.min.js","sources":["jquery.imagemapster.js"],"names":["factory","define","amd","module","exports","root","jQuery","undefined","window","require","addShapeGroupImpl","graphics","areaData","options","me","md","map_data","isMask","$","each","areas","i","e","nohref","noHrefIsMask","addShape","hex_to_decimal","hex","Math","max","min","parseInt","css3color","color","opacity","substr","noop","p","canvasMethods","vmlMethods","m","u","ap","configureAltImages","opts","mi","images","hasCanvas","altImages","add","concat","obj","render_highlight","render_select","i2","e2","altImage","altImageId","area_options","updateProps","area_defaults","mouseout","ar","getDataForArea","this","currentAreaId","relatedTarget","area","queueMouseEvent","delay","deferred","when","defer","activeAreaEvent","clearTimeout","reject","owner","currentAction","setTimeout","areaId","highlightId","resolve","mouseoutDelay","then","clearEffects","isFunction","onMouseout","call","key","selected","isSelected","click","list","list_target","newSelectionState","canChangeState","cbResult","that","blur","preventDefault","clickNavigate","href","location","clickArea","target","isSelectable","isDeselectable","getBoundList","onClick","listTarget","isBool","attr","toggle","boundList","length","setBoundListProperties","areaOpts","effectiveOptions","includeKeys","split","getDataForKey","toString","createToolTip","html","template","css","tooltip","clone","append","extend","display","position","hide","show","bindToolTipClose","bindOption","event","beforeClose","onClose","event_name","inArray","off","on","showToolTip","image","container","tooltipCss","ttopts","corners","areaCorners","outerWidth","outerHeight","left","top","offsetx","offsety","fadeDuration","actalOpacity","zindex","addClass","fader","setOpacity","getHtmlFromOptions","jquery","content","setupListener","supportsPassive","Object","defineProperty","get","addEventListener","removeEventListener","ns","type","listener","includes","console","warn","passive","special","touchstart","setup","_","touchend","mapster_version","elements","lastKey","fade_func","fn","mapster","method","impl","utils","apply","Array","prototype","slice","arguments","error","bind","version","render_defaults","fade","fill","fillColor","fillColorMask","fillOpacity","highlight","stroke","strokeColor","strokeOpacity","strokeWidth","defaults","wrapClass","wrapCss","onGetList","sortList","listenToList","mapKey","mapValue","singleSelect","listKey","listSelectedAttribute","listSelectedClass","onMouseover","onStateChange","onConfigured","configTimeout","scaleMap","safeLoad","shared_defaults","staticState","canvas_style","padding","border","map_cache","hooks","addHook","name","callback","push","callHooks","context","all","deferredArray","Promise","promise","catch","subclass","BaseClass","constr","Subclass","args","base","init","constructor","asArray","text","cb","el","arr","trim","splice","_target","_template","isEmptyObject","onlyProps","prop","src","isPlainObject","isElement","o","HTMLElement","nodeType","nodeName","indexOf","indexOfProp","val","result","boolOrDefault","def","isUndef","ifFunction","size","raw","width","naturalWidth","imgWidth","height","naturalHeight","imgHeight","complete","style","op","endOp","duration","index","cbIntervals","key_list","is","removeClass","getMapDataIndex","img","id","tagName","toLowerCase","parent","getMapData","queueCommand","command","commands","unload","capProp","toUpperCase","jqwidth","Method","func_map","func_area","output","input","first","allowAsync","go","data","area_list","len","getData","addMap","removeMap","hasVml","a","appendTo","b","firstChild","behavior","has","adj","remove","namespaces","document","d","g_vml_","getContext","merge_areas","map_areas","merge_options","temp_opts","getSelected","defaultReturn","ensureNoHighlight","keys","keyList","addUniqueKeys","ad","getKeysForGroup","join","select","set","deselect","lastMap","addArea","finishSetForMap","newState","setSelection","removeSelectionFinish","filter","unbind","preserveState","clearEvents","clearMapData","rebind","configureOptions","bindImages","buildDataset","get_options","effective","eff","set_options","snapshot","base_canvas","createVisibleCanvas","before","state","usemap","map","getAttribute","MapData","initialize","useCanvas","shapes","value","v","createStyleSheet","addRule","test","eval","Graphics","active","canvas","masks","begin","elementName","c","mapArea","mapData","createCanvasFor","addShapeGroup","mode","effectiveRenderOptions","overlay_canvas","render","find","not","renderShape","offset","coords","shape","rect","moveTo","lineTo","arc","PI","addAltImage","beginPath","closePath","clip","globalAlpha","altImageOpacity","drawImage","scaleInfo","maskCanvas","maskContext","hasMasks","shapeCanvas","shapeContext","clearRect","save","lineWidth","fillStyle","restore","s","strokeStyle","globalCompositeOperation","clearHighlight","refreshSelections","canvas_temp","redrawSelections","cssclass","el_name","el_class","t_fill","w","h","children","removeSelections","area_id","MapImages","clear","status","_add","ids","imageLoaded","imageLoadError","retry","triesLeft","check","isLoaded","imgTimeout","resolver","imgCssText","cssText","mapAreas","_xref","_tooltip_events","mouseover","arData","getAllDataForArea","isNotRendered","toolTip","toolTipClose","activeToolTip","clearToolTip","isActive","resizing","zoomed","zoomedArea","wrapId","_idFromKey","hasOwnProperty","atMost","isPrimary","getPrimaryKeysForMapAreas","changeState","setHighlightId","clearSelections","setAreaOptions","drawSelections","key_arr","drawSelection","isSelectedOrStatic","imgCopy","wrap","sort_func","sorted_list","scale","parentId","substring","className","wrapper","sort","processCommandQueue","sel","j","$area","curKey","mapAreaId","group_value","dataItem","default_group","addAreaData","AreaData","String","configure","MapArea","areaDataXref","areasXref","mousedown","cur","_clearCanvases","reset","clearTooltip","g","optsCache","constuctor","partial","allOpts","state_type","areaEl","originalCoords","parseFloat","pos","found","minX","minY","maxX","maxY","bestMinX","bestMaxX","bestMinY","bestMaxY","curX","curY","nest","rootx","rooty","iCoords","radius","angle","body","cos","sin","getScaleInfo","actual","pct","scalePct","realWidth","realHeight","ratio","imageRaw","vis","resize","promises","newsize","sizeCanvas","finishResize","tempOptions","resizeMapData","round","els","animate","easing","percent","coordOffset","newCoords","toolTipContainer","toolTipFade","onShowToolTip","onHideToolTip","stop","activeToolTipID","closeOpts","closeEvents","tipClosed","areaOptions"],"mappings":"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"}
\ No newline at end of file
+{"version":3,"file":"jquery.imagemapster.min.js","sources":["jquery.imagemapster.js"],"names":["factory","define","amd","module","exports","root","jQuery","undefined","window","require","$","setupListener","supportsPassive","opts","Object","defineProperty","get","addEventListener","removeEventListener","e","ns","type","listener","includes","console","warn","passive","event","special","touchstart","setup","_","touchend","mapster_version","elements","lastKey","fade_func","fn","mapster","method","m","impl","utils","isFunction","apply","this","Array","prototype","slice","call","arguments","error","bind","version","render_defaults","isSelectable","isDeselectable","fade","fadeDuration","fill","fillColor","fillColorMask","fillOpacity","highlight","stroke","strokeColor","strokeOpacity","strokeWidth","includeKeys","altImage","altImageId","altImages","defaults","clickNavigate","wrapClass","wrapCss","onGetList","sortList","listenToList","mapKey","mapValue","singleSelect","listKey","listSelectedAttribute","listSelectedClass","onClick","onMouseover","onMouseout","mouseoutDelay","onStateChange","boundList","onConfigured","configTimeout","noHrefIsMask","scaleMap","safeLoad","areas","shared_defaults","render_highlight","render_select","staticState","selected","area_defaults","isMask","canvas_style","position","left","top","padding","border","hasCanvas","map_cache","hooks","addHook","name","callback","push","callHooks","context","each","when","all","deferredArray","Promise","defer","promise","resolve","reject","then","catch","subclass","BaseClass","constr","Subclass","me","args","base","init","constructor","asArray","obj","split","text","cb","el","arr","i","length","trim","splice","updateProps","_target","_template","target","template","isEmptyObject","onlyProps","prop","src","p","inArray","isPlainObject","extend","isElement","o","HTMLElement","nodeType","nodeName","indexOf","indexOfProp","val","result","boolOrDefault","def","isBool","isUndef","ifFunction","that","size","image","raw","u","width","naturalWidth","imgWidth","height","naturalHeight","imgHeight","complete","setOpacity","opacity","style","css","fader","op","endOp","duration","index","cbIntervals","setTimeout","getBoundList","key_list","key","list","is","add","setBoundListProperties","addClass","removeClass","getMapDataIndex","img","id","tagName","toLowerCase","parent","attr","getMapData","queueCommand","map_data","command","currentAction","commands","unload","off","ap","capProp","substr","toUpperCase","jqwidth","Method","func_map","func_area","output","input","first","allowAsync","go","data","ar","area_list","len","getData","addMap","removeMap","hasVml","a","appendTo","html","b","firstChild","behavior","has","adj","remove","namespaces","document","d","g_vml_","getContext","merge_areas","map_areas","options","getDataForKey","merge_options","temp_opts","area_options","md","getSelected","isSelected","defaultReturn","highlightId","ensureNoHighlight","keys","keyList","addUniqueKeys","ad","concat","getKeysForGroup","getDataForArea","join","select","set","deselect","lastMap","addArea","finishSetForMap","newState","toggle","setSelection","removeSelectionFinish","filter","toString","unbind","preserveState","clearEvents","clearMapData","rebind","configureOptions","bindImages","buildDataset","get_options","effective","eff","effectiveOptions","set_options","graphics","snapshot","base_canvas","createVisibleCanvas","before","state","usemap","on","map","getAttribute","MapData","initialize","useCanvas","shapes","value","v","createStyleSheet","addRule","test","eval","canvasMethods","vmlMethods","addShapeGroupImpl","areaData","nohref","addShape","hex_to_decimal","hex","Math","max","min","parseInt","css3color","color","noop","Graphics","active","canvas","masks","begin","elementName","c","mapArea","mapData","createCanvasFor","addShapeGroup","mode","effectiveRenderOptions","areaId","overlay_canvas","render","find","not","renderShape","offset","coords","shape","rect","moveTo","lineTo","arc","PI","addAltImage","beginPath","closePath","clip","globalAlpha","altImageOpacity","drawImage","owner","scaleInfo","maskCanvas","maskContext","hasMasks","shapeCanvas","shapeContext","clearRect","save","lineWidth","fillStyle","restore","s","images","strokeStyle","globalCompositeOperation","clearHighlight","refreshSelections","canvas_temp","hide","redrawSelections","show","cssclass","el_name","el_class","t_fill","append","w","h","children","removeSelections","area_id","MapImages","clear","status","_add","ids","imageLoaded","imageLoadError","triesLeft","check","isLoaded","imgTimeout","deferred","resolver","clearTimeout","configureAltImages","mi","e2","mouseout","currentAreaId","relatedTarget","area","queueMouseEvent","delay","activeAreaEvent","clearEffects","click","list_target","newSelectionState","canChangeState","cbResult","blur","preventDefault","href","location","clickArea","listTarget","areaOpts","imgCssText","cssText","mapAreas","_xref","_tooltip_events","mouseover","arData","getAllDataForArea","isNotRendered","showToolTip","toolTip","toolTipClose","activeToolTip","clearToolTip","isActive","resizing","zoomed","zoomedArea","wrapId","_idFromKey","hasOwnProperty","atMost","isPrimary","getPrimaryKeysForMapAreas","changeState","setHighlightId","clearSelections","setAreaOptions","drawSelections","key_arr","drawSelection","isSelectedOrStatic","imgCopy","wrap","sort_func","sorted_list","scale","parentId","substring","className","wrapper","display","sort","processCommandQueue","sel","j","$area","curKey","mapAreaId","group_value","dataItem","default_group","addAreaData","AreaData","String","configure","MapArea","areaDataXref","areasXref","mousedown","cur","_clearCanvases","reset","clearTooltip","g","optsCache","constuctor","partial","allOpts","state_type","areaEl","originalCoords","parseFloat","areaCorners","container","pos","found","minX","minY","maxX","maxY","bestMinX","bestMaxX","bestMinY","bestMaxY","curX","curY","nest","rootx","rooty","iCoords","radius","angle","offsetx","offsety","body","cos","sin","getScaleInfo","actual","pct","scalePct","realWidth","realHeight","ratio","imageRaw","vis","resize","promises","newsize","sizeCanvas","finishResize","tempOptions","resizeMapData","round","els","animate","easing","percent","coordOffset","newCoords","createToolTip","tooltip","clone","bindToolTipClose","bindOption","beforeClose","onClose","event_name","tooltipCss","ttopts","corners","outerWidth","outerHeight","actalOpacity","zindex","getHtmlFromOptions","jquery","content","toolTipContainer","toolTipFade","onShowToolTip","onHideToolTip","stop","activeToolTipID","closeOpts","closeEvents","tipClosed","areaOptions"],"mappings":"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"}
\ No newline at end of file
diff --git a/examples/altimages.html b/examples/altimages.html
index 807d5a2..4cedc4d 100644
--- a/examples/altimages.html
+++ b/examples/altimages.html
@@ -1,164 +1,686 @@
-
-
-
- AltImages Demo
-
-
-
-
-
-
-
- AltImages Demo
-
- click to bind az with altimage
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+ AltImages Demo
+
+
+
+
+
+
+
+ AltImages Demo
+
+ click to bind az with altimage
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/multiple-maps.html b/examples/multiple-maps.html
index 1bc36a9..a0e77b6 100644
--- a/examples/multiple-maps.html
+++ b/examples/multiple-maps.html
@@ -4,10 +4,7 @@
Multiple Maps Demo
-
+
-
-
-
-
-
-
-
-
-Shapes Demo (For Full IE Compatibility)
-While masks sort of work for Internet Explorer 6-8, if you really want to create areas within areas, you can use polygons to split
-a shape into two connecting parts and combine them as a group. This example is created by rendering the outer circle in two
-"c-shaped" halves and rendering the inner circle separately. The other "shapes" demo uses masks and much less markup to do the same thing,
-but more complex situations where the inner area is not a solid color might not work as well in IE.
-
The outer circle is selected independently from the inner circle.
-The rightmost rectangle is selected with the center circle (and has independent rendering options), but does not itself respond to mouse events.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-