├── .babelrc
├── .eslintignore
├── .eslintrc.js
├── .gitignore
├── .npmignore
├── .remarkrc
├── CHANGES.md
├── LICENSE-MIT.txt
├── README.md
├── demo
├── images
│ ├── bt_right_arrow_22072.png
│ ├── mapmarker_drawingpin_right_pink_23026.png
│ ├── mapmarker_marker_outside_azure_23007.png
│ └── mapmarker_pushpin_right_azure_22998.png
├── index.html
├── index.js
└── stylesheets
│ ├── github-light.css
│ ├── index.css
│ ├── normalize.css
│ └── stylesheet.css
├── dist
├── index.esm.js
├── index.esm.min.js
├── index.esm.min.js.map
├── index.umd.js
├── index.umd.min.js
└── index.umd.min.js.map
├── docs
└── jsdoc-config.js
├── lgtm.yml
├── package.json
├── params.json
├── rollup.config.js
├── src
├── jquery.imageMaps.js
└── typedefs.js
└── test
├── accessibility.js
└── ui.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["@babel/preset-env"]
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | jquery.imageMaps.min.js
3 | docs/jsdoc
4 | dist
5 |
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | module.exports = {
3 | env: {
4 | browser: true,
5 | es6: true
6 | },
7 | settings: {
8 | polyfills: [
9 | "Array.isArray",
10 | "console",
11 | "Error"
12 | ]
13 | },
14 | overrides: {
15 | files: ['docs/jsdoc-config.js'],
16 | rules: {
17 | strict: 0,
18 | 'import/unambiguous': 0,
19 | 'import/no-commonjs': 0
20 | }
21 | },
22 | extends: ['ash-nazg/sauron', 'plugin:testcafe/recommended'],
23 | globals: {
24 | Atomics: 'readonly',
25 | SharedArrayBuffer: 'readonly'
26 | },
27 | parserOptions: {
28 | ecmaVersion: 2018,
29 | sourceType: 'module'
30 | },
31 | rules: {
32 | indent: ['error', 4],
33 | 'valid-jsdoc': 0
34 | }
35 | };
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | docs/jsdoc
3 | package-lock.json
4 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | docs
3 | test
4 |
--------------------------------------------------------------------------------
/.remarkrc:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/CHANGES.md:
--------------------------------------------------------------------------------
1 | # ImageMaps
2 |
3 | ## ?
4 |
5 | - Compatibility fix: Add `core-js-bundle` to demo (since
6 | Babelification may still require some polyfills
7 | be added for the sake of some older browsers)
8 | - Fix: Avoid error if `getNaturalImageSize` is supplied a string
9 | - Fix: For non-IE8, set a `targetAreaEl` for `onClick` call
10 | - Update: Remove deprecated `@babel/polyfill` in favor of its
11 | recommended replacement, `core-js-bundle`
12 | - Enhancement: Add a `copyImageMaps` static method (on `$.imageMaps`);
13 | allows for preserving width/height/shapes at earlier state (e.g.,
14 | if rebuilding the same map element with different qualities); also
15 | use internally
16 | - npm: Further devDeps updates (non-major version changes)
17 | - npm: Update jquery, devDeps
18 | - npm: Add jquery to `peerDependencies` (since expected to be
19 | present, but as we are a plugin, it is not a direct dependency)
20 |
21 | ## 1.0.0
22 |
23 | - Fix: Reference to undefined `shapetype` -> `shapeType`
24 | - Fix: Avoid error in `onMouseMove` if `coords` is false
25 | - Fix: Grammar nit in thrown error
26 | - Breaking enhancement: ES6 Modules (changes script path)
27 | - Enhancement: Avoid zoom if less than 0 or NaN
28 | - Update: Save copies of no-longer-cross-origin-accessible images locally;
29 | use npm jquery
30 | - Accessibility: Add more color contrast to Github ribbon; image alt text;
31 | use labels, visible colors, main role, fieldset/legend group, visible
32 | link text
33 | - Refactoring: Use ES6
34 | - Refactoring: Change `getCoordsByRatio` to class method since does
35 | not require `this`
36 | - Linting (ESLint): Add eslint-config-ash-nazg/sauron; line breaks, avoid
37 | now redundant radix to `parseInt`, prefer `const`/`let`; indicate polyfills
38 | for sake of eslint-plugin-compat (though `Array.isArray()` is made
39 | available by @babel/polyfill).
40 | - Docs: Add JSDoc, CHANGES; integrate demo, adding external files and
41 | making local
42 | - License: Rename file to add ".txt" extension and to reflect license type
43 | - npm: Add `package.json`/`package-lock.json`; add `eslint`, `start`,
44 | `open`/`open-docs`, `docs`, `rollup`, `prepublishOnly` scripts
45 |
--------------------------------------------------------------------------------
/LICENSE-MIT.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 NAVER Corp.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # image-maps
2 |
3 | image maps jQuery plugin
4 |
5 | ## supported devices and browser
6 |
7 | * PC - IE9+, Chrome, Firefox
8 | * Mobile - iOS, Android (editing is not supported)
9 |
10 | ## example
11 |
12 |
13 |
14 | ## LICENSE
15 |
16 | ```
17 | The MIT License (MIT)
18 |
19 | Copyright (c) 2016 NAVER Corp.
20 |
21 | Permission is hereby granted, free of charge, to any person obtaining a copy
22 | of this software and associated documentation files (the "Software"), to deal
23 | in the Software without restriction, including without limitation the rights
24 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
25 | copies of the Software, and to permit persons to whom the Software is
26 | furnished to do so, subject to the following conditions:
27 |
28 | The above copyright notice and this permission notice shall be included in all
29 | copies or substantial portions of the Software.
30 |
31 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
32 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
33 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
34 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
35 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
36 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 | SOFTWARE.
38 | ```
39 |
--------------------------------------------------------------------------------
/demo/images/bt_right_arrow_22072.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naver/image-maps/c1a3d6a2998737273035f545e48456fde97c60f9/demo/images/bt_right_arrow_22072.png
--------------------------------------------------------------------------------
/demo/images/mapmarker_drawingpin_right_pink_23026.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naver/image-maps/c1a3d6a2998737273035f545e48456fde97c60f9/demo/images/mapmarker_drawingpin_right_pink_23026.png
--------------------------------------------------------------------------------
/demo/images/mapmarker_marker_outside_azure_23007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naver/image-maps/c1a3d6a2998737273035f545e48456fde97c60f9/demo/images/mapmarker_marker_outside_azure_23007.png
--------------------------------------------------------------------------------
/demo/images/mapmarker_pushpin_right_azure_22998.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/naver/image-maps/c1a3d6a2998737273035f545e48456fde97c60f9/demo/images/mapmarker_pushpin_right_azure_22998.png
--------------------------------------------------------------------------------
/demo/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ImageMaps by naver
7 |
8 |
9 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 | Fork me on GitHub
29 |
30 |
ImageMaps
31 |
32 |
0. Shape Url
33 |
35 |
36 |
37 |
38 |
51 |
57 |
58 |
59 |
3. Text Shape Type
60 |
Size:
61 |
62 |
63 |
64 |
Text:
65 |
66 |
67 |
add text
68 |
69 |
70 |
97 |
98 |
102 |
103 |
Edit Image Maps
104 |
106 |
107 |
108 |
109 |
115 |
117 |
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/demo/index.js:
--------------------------------------------------------------------------------
1 | /* globals jQuery, jqueryImageMaps */
2 | /* eslint-disable import/unambiguous */
3 | // import jqueryImageMaps from '../dist/index.esm.js';
4 |
5 | const $ = jqueryImageMaps(jQuery);
6 |
7 | /* const imageMaps = */ $('._image_maps').imageMaps({
8 | isEditMode: true,
9 | shape: 'rect',
10 | shapeStyle: {
11 | fill: '#ffffff',
12 | stroke: 'red',
13 | 'stroke-width': 2
14 | },
15 | onSelect (e, data) {
16 | console.log(data); // eslint-disable-line no-console
17 | }
18 | });
19 |
20 | $('#rect').on('click', function (e) {
21 | e.preventDefault();
22 | $('._image_maps').setShapeStyle({
23 | fill: $('a.color.selected').data('color'),
24 | stroke: $('a.color.selected').data('color'),
25 | 'stroke-width': 2
26 | }).addShape(null, $('#link').val(), 'rect');
27 | });
28 |
29 | $('#circle').on('click', function (e) {
30 | e.preventDefault();
31 | $('._image_maps').setShapeStyle({
32 | fill: $('a.color.selected').data('color'),
33 | stroke: $('a.color.selected').data('color'),
34 | 'stroke-width': 2
35 | }).addShape(null, $('#link').val(), 'circle');
36 | });
37 |
38 | $('#ellipse').on('click', function (e) {
39 | e.preventDefault();
40 | $('._image_maps').setShapeStyle({
41 | fill: $('a.color.selected').data('color'),
42 | stroke: $('a.color.selected').data('color'),
43 | 'stroke-width': 2
44 | }).addShape(null, $('#link').val(), 'ellipse');
45 | });
46 |
47 | $('a.color').on('click', function (e) {
48 | e.preventDefault();
49 | $('a.color').removeClass('selected');
50 | $(this).addClass('selected');
51 | });
52 |
53 | $('#text').on('click', function (e) {
54 | e.preventDefault();
55 | $('._image_maps').setTextShape($('#text_input').val(), {
56 | fill: $('a.color.selected').data('color'),
57 | stroke: '',
58 | 'stroke-width': ''
59 | }).addShape([null, null, $('#size').val()], $('#link').val(), 'text');
60 | });
61 |
62 | $('#image').on('click', function (e) {
63 | e.preventDefault();
64 | $('._image_maps').setImageShape(
65 | $('input.image_input:checked').data('image')
66 | ).addShape(null, $('#link').val(), 'image');
67 | });
68 |
69 | $('#remove').on('click', function (e) {
70 | e.preventDefault();
71 | $('._image_maps').removeShape();
72 | });
73 |
74 | $('#remove_all').on('click', function (e) {
75 | e.preventDefault();
76 | $('._image_maps').removeAllShapes();
77 | });
78 |
79 | const viewEl = $('._image_maps_view');
80 | viewEl.imageMaps();
81 |
82 | $('#maps_zoom').on('click', function (e) {
83 | e.preventDefault();
84 |
85 | const zoomInput = $('#zoom');
86 | const val = Number(zoomInput.val() || 100);
87 |
88 | if (typeof val !== 'number' || isNaN(val) || val <= 0) {
89 | alert( // eslint-disable-line no-alert
90 | 'You must enter a number and one greater than 0.'
91 | );
92 | return;
93 | }
94 |
95 | viewEl.zoom([val]);
96 |
97 | // for image resize
98 | $('._imageMaps_area_view').css({
99 | width: val * 0.01 * viewEl.width(),
100 | height: val * 0.01 * viewEl.height()
101 | });
102 | });
103 |
104 | $('#view').on('click', function (e) {
105 | e.preventDefault();
106 |
107 | $('._image_maps').copyImageMapsTo($('._image_maps_view'));
108 | });
109 |
--------------------------------------------------------------------------------
/demo/stylesheets/github-light.css:
--------------------------------------------------------------------------------
1 | /*
2 | The MIT License (MIT)
3 |
4 | Copyright (c) 2015 GitHub, Inc.
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
24 | */
25 |
26 | .pl-c /* comment */ {
27 | color: #969896;
28 | }
29 |
30 | .pl-c1 /* constant, markup.raw, meta.diff.header, meta.module-reference, meta.property-name, support, support.constant, support.variable, variable.other.constant */,
31 | .pl-s .pl-v /* string variable */ {
32 | color: #0086b3;
33 | }
34 |
35 | .pl-e /* entity */,
36 | .pl-en /* entity.name */ {
37 | color: #795da3;
38 | }
39 |
40 | .pl-s .pl-s1 /* string source */,
41 | .pl-smi /* storage.modifier.import, storage.modifier.package, storage.type.java, variable.other, variable.parameter.function */ {
42 | color: #333;
43 | }
44 |
45 | .pl-ent /* entity.name.tag */ {
46 | color: #63a35c;
47 | }
48 |
49 | .pl-k /* keyword, storage, storage.type */ {
50 | color: #a71d5d;
51 | }
52 |
53 | .pl-pds /* punctuation.definition.string, string.regexp.character-class */,
54 | .pl-s /* string */,
55 | .pl-s .pl-pse .pl-s1 /* string punctuation.section.embedded source */,
56 | .pl-sr /* string.regexp */,
57 | .pl-sr .pl-cce /* string.regexp constant.character.escape */,
58 | .pl-sr .pl-sra /* string.regexp string.regexp.arbitrary-repitition */,
59 | .pl-sr .pl-sre /* string.regexp source.ruby.embedded */ {
60 | color: #183691;
61 | }
62 |
63 | .pl-v /* variable */ {
64 | color: #ed6a43;
65 | }
66 |
67 | .pl-id /* invalid.deprecated */ {
68 | color: #b52a1d;
69 | }
70 |
71 | .pl-ii /* invalid.illegal */ {
72 | background-color: #b52a1d;
73 | color: #f8f8f8;
74 | }
75 |
76 | .pl-sr .pl-cce /* string.regexp constant.character.escape */ {
77 | color: #63a35c;
78 | font-weight: bold;
79 | }
80 |
81 | .pl-ml /* markup.list */ {
82 | color: #693a17;
83 | }
84 |
85 | .pl-mh /* markup.heading */,
86 | .pl-mh .pl-en /* markup.heading entity.name */,
87 | .pl-ms /* meta.separator */ {
88 | color: #1d3e81;
89 | font-weight: bold;
90 | }
91 |
92 | .pl-mq /* markup.quote */ {
93 | color: #008080;
94 | }
95 |
96 | .pl-mi /* markup.italic */ {
97 | color: #333;
98 | font-style: italic;
99 | }
100 |
101 | .pl-mb /* markup.bold */ {
102 | color: #333;
103 | font-weight: bold;
104 | }
105 |
106 | .pl-md /* markup.deleted, meta.diff.header.from-file */ {
107 | background-color: #ffecec;
108 | color: #bd2c00;
109 | }
110 |
111 | .pl-mi1 /* markup.inserted, meta.diff.header.to-file */ {
112 | background-color: #eaffea;
113 | color: #55a532;
114 | }
115 |
116 | .pl-mdr /* meta.diff.range */ {
117 | color: #795da3;
118 | font-weight: bold;
119 | }
120 |
121 | .pl-mo /* meta.output */ {
122 | color: #1d3e81;
123 | }
124 |
125 |
--------------------------------------------------------------------------------
/demo/stylesheets/index.css:
--------------------------------------------------------------------------------
1 | #forkongithub a{background:#1B6600;color:#fff;text-decoration:none;font-family:arial,sans-serif;text-align:center;font-weight:bold;padding:5px 40px;font-size:1rem;line-height:2rem;position:relative;transition:0.5s;}#forkongithub a:hover{background:#fff;color:#1B6600;}#forkongithub a::before,#forkongithub a::after{content:"";width:100%;display:block;position:absolute;top:1px;left:0;height:1px;background:#fff;}#forkongithub a::after{bottom:1px;top:auto;}@media screen and (min-width:800px){#forkongithub{position:fixed;display:block;top:0;right:0;width:200px;overflow:hidden;height:200px;z-index:9999;}#forkongithub a{width:200px;position:absolute;top:60px;right:-60px;transform:rotate(45deg);-webkit-transform:rotate(45deg);-ms-transform:rotate(45deg);-moz-transform:rotate(45deg);-o-transform:rotate(45deg);box-shadow:4px 4px 10px rgba(0,0,0,0.8);}}
2 |
3 | .big_title {
4 | font-weight: bold;
5 | font-size: 40px;
6 | margin: 80px 0;
7 | text-align: center;
8 | }
9 |
10 | ._imageMaps_area {
11 | padding-bottom: 50px;
12 | }
13 |
14 | ._imageMaps_area,
15 | ._imageMaps_area_view {
16 | margin: 0 auto;
17 | width: 700px;
18 | position: relative;
19 | max-width: 100%;
20 | max-height: 100%;
21 | }
22 |
23 | ._imageMaps_area_view {
24 | width: 500px;
25 | }
26 |
27 | img {
28 | position: relative;
29 | width: 100%;
30 | height: 100%;
31 | }
32 |
33 | a:not(.forkongithub) {
34 | width: 18px;
35 | height: 18px;
36 | text-decoration: none;
37 | }
38 |
39 | .shape {
40 | margin: 18px 0;
41 | }
42 |
43 | .btn {
44 | padding: 5px 2px;
45 | border: 2px solid black;
46 | background-color: #ffffff;
47 | color: #000000;
48 | }
49 |
50 | a.color {
51 | display: inline-block;
52 | vertical-align: middle;
53 | }
54 |
55 | a.color.selected {
56 | border: 3px solid black;
57 | }
58 |
59 | input[type=text],
60 | input[type=number] {
61 | height: 24px;
62 | }
63 |
64 | label > img {
65 | width: 7%;
66 | height: 7%;
67 | }
68 |
69 | label[for=image_4] > img {
70 | width: 45px;
71 | }
72 |
73 | div.box {
74 | margin: 0 auto;
75 | width: 650px;
76 | border-bottom: 1px solid grey;
77 | padding: 15px 0 15px 0;
78 | }
79 |
80 | div.desc {
81 | margin: 0 auto;
82 | width: 650px;
83 | }
84 |
85 | .view_header {
86 | float: left;
87 | position: relative;
88 | }
89 |
90 | .maps_view {
91 | margin-left: 20px;
92 | top: 16px;
93 | position: relative;
94 | }
95 |
96 | #zoom,.maps_zoom {
97 | top: 16px;
98 | position: relative;
99 | }
100 |
101 | .result_view_header {
102 | width: 500px;
103 | height: 70px;
104 | }
105 |
--------------------------------------------------------------------------------
/demo/stylesheets/normalize.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */
2 |
3 | /**
4 | * 1. Set default font family to sans-serif.
5 | * 2. Prevent iOS text size adjust after orientation change, without disabling
6 | * user zoom.
7 | */
8 |
9 | html {
10 | font-family: sans-serif; /* 1 */
11 | -ms-text-size-adjust: 100%; /* 2 */
12 | -webkit-text-size-adjust: 100%; /* 2 */
13 | }
14 |
15 | /**
16 | * Remove default margin.
17 | */
18 |
19 | body {
20 | margin: 0;
21 | }
22 |
23 | /* HTML5 display definitions
24 | ========================================================================== */
25 |
26 | /**
27 | * Correct `block` display not defined for any HTML5 element in IE 8/9.
28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11
29 | * and Firefox.
30 | * Correct `block` display not defined for `main` in IE 11.
31 | */
32 |
33 | article,
34 | aside,
35 | details,
36 | figcaption,
37 | figure,
38 | footer,
39 | header,
40 | hgroup,
41 | main,
42 | menu,
43 | nav,
44 | section,
45 | summary {
46 | display: block;
47 | }
48 |
49 | /**
50 | * 1. Correct `inline-block` display not defined in IE 8/9.
51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera.
52 | */
53 |
54 | audio,
55 | canvas,
56 | progress,
57 | video {
58 | display: inline-block; /* 1 */
59 | vertical-align: baseline; /* 2 */
60 | }
61 |
62 | /**
63 | * Prevent modern browsers from displaying `audio` without controls.
64 | * Remove excess height in iOS 5 devices.
65 | */
66 |
67 | audio:not([controls]) {
68 | display: none;
69 | height: 0;
70 | }
71 |
72 | /**
73 | * Address `[hidden]` styling not present in IE 8/9/10.
74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22.
75 | */
76 |
77 | [hidden],
78 | template {
79 | display: none;
80 | }
81 |
82 | /* Links
83 | ========================================================================== */
84 |
85 | /**
86 | * Remove the gray background color from active links in IE 10.
87 | */
88 |
89 | a {
90 | background-color: transparent;
91 | }
92 |
93 | /**
94 | * Improve readability when focused and also mouse hovered in all browsers.
95 | */
96 |
97 | a:active,
98 | a:hover {
99 | outline: 0;
100 | }
101 |
102 | /* Text-level semantics
103 | ========================================================================== */
104 |
105 | /**
106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome.
107 | */
108 |
109 | abbr[title] {
110 | border-bottom: 1px dotted;
111 | }
112 |
113 | /**
114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome.
115 | */
116 |
117 | b,
118 | strong {
119 | font-weight: bold;
120 | }
121 |
122 | /**
123 | * Address styling not present in Safari and Chrome.
124 | */
125 |
126 | dfn {
127 | font-style: italic;
128 | }
129 |
130 | /**
131 | * Address variable `h1` font-size and margin within `section` and `article`
132 | * contexts in Firefox 4+, Safari, and Chrome.
133 | */
134 |
135 | h1 {
136 | font-size: 2em;
137 | margin: 0.67em 0;
138 | }
139 |
140 | /**
141 | * Address styling not present in IE 8/9.
142 | */
143 |
144 | mark {
145 | background: #ff0;
146 | color: #000;
147 | }
148 |
149 | /**
150 | * Address inconsistent and variable font size in all browsers.
151 | */
152 |
153 | small {
154 | font-size: 80%;
155 | }
156 |
157 | /**
158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers.
159 | */
160 |
161 | sub,
162 | sup {
163 | font-size: 75%;
164 | line-height: 0;
165 | position: relative;
166 | vertical-align: baseline;
167 | }
168 |
169 | sup {
170 | top: -0.5em;
171 | }
172 |
173 | sub {
174 | bottom: -0.25em;
175 | }
176 |
177 | /* Embedded content
178 | ========================================================================== */
179 |
180 | /**
181 | * Remove border when inside `a` element in IE 8/9/10.
182 | */
183 |
184 | img {
185 | border: 0;
186 | }
187 |
188 | /**
189 | * Correct overflow not hidden in IE 9/10/11.
190 | */
191 |
192 | svg:not(:root) {
193 | overflow: hidden;
194 | }
195 |
196 | /* Grouping content
197 | ========================================================================== */
198 |
199 | /**
200 | * Address margin not present in IE 8/9 and Safari.
201 | */
202 |
203 | figure {
204 | margin: 1em 40px;
205 | }
206 |
207 | /**
208 | * Address differences between Firefox and other browsers.
209 | */
210 |
211 | hr {
212 | box-sizing: content-box;
213 | height: 0;
214 | }
215 |
216 | /**
217 | * Contain overflow in all browsers.
218 | */
219 |
220 | pre {
221 | overflow: auto;
222 | }
223 |
224 | /**
225 | * Address odd `em`-unit font size rendering in all browsers.
226 | */
227 |
228 | code,
229 | kbd,
230 | pre,
231 | samp {
232 | font-family: monospace, monospace;
233 | font-size: 1em;
234 | }
235 |
236 | /* Forms
237 | ========================================================================== */
238 |
239 | /**
240 | * Known limitation: by default, Chrome and Safari on OS X allow very limited
241 | * styling of `select`, unless a `border` property is set.
242 | */
243 |
244 | /**
245 | * 1. Correct color not being inherited.
246 | * Known issue: affects color of disabled elements.
247 | * 2. Correct font properties not being inherited.
248 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome.
249 | */
250 |
251 | button,
252 | input,
253 | optgroup,
254 | select,
255 | textarea {
256 | color: inherit; /* 1 */
257 | font: inherit; /* 2 */
258 | margin: 0; /* 3 */
259 | }
260 |
261 | /**
262 | * Address `overflow` set to `hidden` in IE 8/9/10/11.
263 | */
264 |
265 | button {
266 | overflow: visible;
267 | }
268 |
269 | /**
270 | * Address inconsistent `text-transform` inheritance for `button` and `select`.
271 | * All other form control elements do not inherit `text-transform` values.
272 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera.
273 | * Correct `select` style inheritance in Firefox.
274 | */
275 |
276 | button,
277 | select {
278 | text-transform: none;
279 | }
280 |
281 | /**
282 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio`
283 | * and `video` controls.
284 | * 2. Correct inability to style clickable `input` types in iOS.
285 | * 3. Improve usability and consistency of cursor style between image-type
286 | * `input` and others.
287 | */
288 |
289 | button,
290 | html input[type="button"], /* 1 */
291 | input[type="reset"],
292 | input[type="submit"] {
293 | -webkit-appearance: button; /* 2 */
294 | cursor: pointer; /* 3 */
295 | }
296 |
297 | /**
298 | * Re-set default cursor for disabled elements.
299 | */
300 |
301 | button[disabled],
302 | html input[disabled] {
303 | cursor: default;
304 | }
305 |
306 | /**
307 | * Remove inner padding and border in Firefox 4+.
308 | */
309 |
310 | button::-moz-focus-inner,
311 | input::-moz-focus-inner {
312 | border: 0;
313 | padding: 0;
314 | }
315 |
316 | /**
317 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in
318 | * the UA stylesheet.
319 | */
320 |
321 | input {
322 | line-height: normal;
323 | }
324 |
325 | /**
326 | * It's recommended that you don't attempt to style these elements.
327 | * Firefox's implementation doesn't respect box-sizing, padding, or width.
328 | *
329 | * 1. Address box sizing set to `content-box` in IE 8/9/10.
330 | * 2. Remove excess padding in IE 8/9/10.
331 | */
332 |
333 | input[type="checkbox"],
334 | input[type="radio"] {
335 | box-sizing: border-box; /* 1 */
336 | padding: 0; /* 2 */
337 | }
338 |
339 | /**
340 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain
341 | * `font-size` values of the `input`, it causes the cursor style of the
342 | * decrement button to change from `default` to `text`.
343 | */
344 |
345 | input[type="number"]::-webkit-inner-spin-button,
346 | input[type="number"]::-webkit-outer-spin-button {
347 | height: auto;
348 | }
349 |
350 | /**
351 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome.
352 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome
353 | * (include `-moz` to future-proof).
354 | */
355 |
356 | input[type="search"] {
357 | -webkit-appearance: textfield; /* 1 */ /* 2 */
358 | box-sizing: content-box;
359 | }
360 |
361 | /**
362 | * Remove inner padding and search cancel button in Safari and Chrome on OS X.
363 | * Safari (but not Chrome) clips the cancel button when the search input has
364 | * padding (and `textfield` appearance).
365 | */
366 |
367 | input[type="search"]::-webkit-search-cancel-button,
368 | input[type="search"]::-webkit-search-decoration {
369 | -webkit-appearance: none;
370 | }
371 |
372 | /**
373 | * Define consistent border, margin, and padding.
374 | */
375 |
376 | fieldset {
377 | border: 1px solid #c0c0c0;
378 | margin: 0 2px;
379 | padding: 0.35em 0.625em 0.75em;
380 | }
381 |
382 | /**
383 | * 1. Correct `color` not being inherited in IE 8/9/10/11.
384 | * 2. Remove padding so people aren't caught out if they zero out fieldsets.
385 | */
386 |
387 | legend {
388 | border: 0; /* 1 */
389 | padding: 0; /* 2 */
390 | }
391 |
392 | /**
393 | * Remove default vertical scrollbar in IE 8/9/10/11.
394 | */
395 |
396 | textarea {
397 | overflow: auto;
398 | }
399 |
400 | /**
401 | * Don't inherit the `font-weight` (applied by a rule above).
402 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X.
403 | */
404 |
405 | optgroup {
406 | font-weight: bold;
407 | }
408 |
409 | /* Tables
410 | ========================================================================== */
411 |
412 | /**
413 | * Remove most spacing between table cells.
414 | */
415 |
416 | table {
417 | border-collapse: collapse;
418 | border-spacing: 0;
419 | }
420 |
421 | td,
422 | th {
423 | padding: 0;
424 | }
425 |
--------------------------------------------------------------------------------
/demo/stylesheets/stylesheet.css:
--------------------------------------------------------------------------------
1 | * {
2 | box-sizing: border-box; }
3 |
4 | body {
5 | padding: 0;
6 | margin: 0;
7 | font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
8 | font-size: 16px;
9 | line-height: 1.5;
10 | color: #606c71; }
11 |
12 | a {
13 | color: #1e6bb8;
14 | text-decoration: none; }
15 | a:hover {
16 | text-decoration: underline; }
17 |
18 | .btn {
19 | display: inline-block;
20 | margin-bottom: 1rem;
21 | color: rgba(255, 255, 255, 0.7);
22 | background-color: rgba(255, 255, 255, 0.08);
23 | border-color: rgba(255, 255, 255, 0.2);
24 | border-style: solid;
25 | border-width: 1px;
26 | border-radius: 0.3rem;
27 | transition: color 0.2s, background-color 0.2s, border-color 0.2s; }
28 | .btn + .btn {
29 | margin-left: 1rem; }
30 |
31 | .btn:hover {
32 | color: rgba(255, 255, 255, 0.8);
33 | text-decoration: none;
34 | background-color: rgba(255, 255, 255, 0.2);
35 | border-color: rgba(255, 255, 255, 0.3); }
36 |
37 | @media screen and (min-width: 64em) {
38 | .btn {
39 | padding: 0.75rem 1rem; } }
40 |
41 | @media screen and (min-width: 42em) and (max-width: 64em) {
42 | .btn {
43 | padding: 0.6rem 0.9rem;
44 | font-size: 0.9rem; } }
45 |
46 | @media screen and (max-width: 42em) {
47 | .btn {
48 | display: block;
49 | width: 100%;
50 | padding: 0.75rem;
51 | font-size: 0.9rem; }
52 | .btn + .btn {
53 | margin-top: 1rem;
54 | margin-left: 0; } }
55 |
56 | .page-header {
57 | color: #fff;
58 | text-align: center;
59 | background-color: #159957;
60 | background-image: linear-gradient(120deg, #155799, #159957); }
61 |
62 | @media screen and (min-width: 64em) {
63 | .page-header {
64 | padding: 5rem 6rem; } }
65 |
66 | @media screen and (min-width: 42em) and (max-width: 64em) {
67 | .page-header {
68 | padding: 3rem 4rem; } }
69 |
70 | @media screen and (max-width: 42em) {
71 | .page-header {
72 | padding: 2rem 1rem; } }
73 |
74 | .project-name {
75 | margin-top: 0;
76 | margin-bottom: 0.1rem; }
77 |
78 | @media screen and (min-width: 64em) {
79 | .project-name {
80 | font-size: 3.25rem; } }
81 |
82 | @media screen and (min-width: 42em) and (max-width: 64em) {
83 | .project-name {
84 | font-size: 2.25rem; } }
85 |
86 | @media screen and (max-width: 42em) {
87 | .project-name {
88 | font-size: 1.75rem; } }
89 |
90 | .project-tagline {
91 | margin-bottom: 2rem;
92 | font-weight: normal;
93 | opacity: 0.7; }
94 |
95 | @media screen and (min-width: 64em) {
96 | .project-tagline {
97 | font-size: 1.25rem; } }
98 |
99 | @media screen and (min-width: 42em) and (max-width: 64em) {
100 | .project-tagline {
101 | font-size: 1.15rem; } }
102 |
103 | @media screen and (max-width: 42em) {
104 | .project-tagline {
105 | font-size: 1rem; } }
106 |
107 | .main-content :first-child {
108 | margin-top: 0; }
109 | .main-content img {
110 | max-width: 100%; }
111 | .main-content h1, .main-content h2, .main-content h3, .main-content h4, .main-content h5, .main-content h6 {
112 | margin-top: 2rem;
113 | margin-bottom: 1rem;
114 | font-weight: normal;
115 | color: #159957; }
116 | .main-content p {
117 | margin-bottom: 1em; }
118 | .main-content code {
119 | padding: 2px 4px;
120 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
121 | font-size: 0.9rem;
122 | color: #383e41;
123 | background-color: #f3f6fa;
124 | border-radius: 0.3rem; }
125 | .main-content pre {
126 | padding: 0.8rem;
127 | margin-top: 0;
128 | margin-bottom: 1rem;
129 | font: 1rem Consolas, "Liberation Mono", Menlo, Courier, monospace;
130 | color: #567482;
131 | word-wrap: normal;
132 | background-color: #f3f6fa;
133 | border: solid 1px #dce6f0;
134 | border-radius: 0.3rem; }
135 | .main-content pre > code {
136 | padding: 0;
137 | margin: 0;
138 | font-size: 0.9rem;
139 | color: #567482;
140 | word-break: normal;
141 | white-space: pre;
142 | background: transparent;
143 | border: 0; }
144 | .main-content .highlight {
145 | margin-bottom: 1rem; }
146 | .main-content .highlight pre {
147 | margin-bottom: 0;
148 | word-break: normal; }
149 | .main-content .highlight pre, .main-content pre {
150 | padding: 0.8rem;
151 | overflow: auto;
152 | font-size: 0.9rem;
153 | line-height: 1.45;
154 | border-radius: 0.3rem; }
155 | .main-content pre code, .main-content pre tt {
156 | display: inline;
157 | max-width: initial;
158 | padding: 0;
159 | margin: 0;
160 | overflow: initial;
161 | line-height: inherit;
162 | word-wrap: normal;
163 | background-color: transparent;
164 | border: 0; }
165 | .main-content pre code:before, .main-content pre code:after, .main-content pre tt:before, .main-content pre tt:after {
166 | content: normal; }
167 | .main-content ul, .main-content ol {
168 | margin-top: 0; }
169 | .main-content blockquote {
170 | padding: 0 1rem;
171 | margin-left: 0;
172 | color: #819198;
173 | border-left: 0.3rem solid #dce6f0; }
174 | .main-content blockquote > :first-child {
175 | margin-top: 0; }
176 | .main-content blockquote > :last-child {
177 | margin-bottom: 0; }
178 | .main-content table {
179 | display: block;
180 | width: 100%;
181 | overflow: auto;
182 | word-break: normal;
183 | word-break: keep-all; }
184 | .main-content table th {
185 | font-weight: bold; }
186 | .main-content table th, .main-content table td {
187 | padding: 0.5rem 1rem;
188 | border: 1px solid #e9ebec; }
189 | .main-content dl {
190 | padding: 0; }
191 | .main-content dl dt {
192 | padding: 0;
193 | margin-top: 1rem;
194 | font-size: 1rem;
195 | font-weight: bold; }
196 | .main-content dl dd {
197 | padding: 0;
198 | margin-bottom: 1rem; }
199 | .main-content hr {
200 | height: 2px;
201 | padding: 0;
202 | margin: 1rem 0;
203 | background-color: #eff0f1;
204 | border: 0; }
205 |
206 | @media screen and (min-width: 64em) {
207 | .main-content {
208 | max-width: 64rem;
209 | padding: 2rem 6rem;
210 | margin: 0 auto;
211 | font-size: 1.1rem; } }
212 |
213 | @media screen and (min-width: 42em) and (max-width: 64em) {
214 | .main-content {
215 | padding: 2rem 4rem;
216 | font-size: 1.1rem; } }
217 |
218 | @media screen and (max-width: 42em) {
219 | .main-content {
220 | padding: 2rem 1rem;
221 | font-size: 1rem; } }
222 |
223 | .site-footer {
224 | padding-top: 2rem;
225 | margin-top: 2rem;
226 | border-top: solid 1px #eff0f1; }
227 |
228 | .site-footer-owner {
229 | display: block;
230 | font-weight: bold; }
231 |
232 | .site-footer-credits {
233 | color: #819198; }
234 |
235 | @media screen and (min-width: 64em) {
236 | .site-footer {
237 | font-size: 1rem; } }
238 |
239 | @media screen and (min-width: 42em) and (max-width: 64em) {
240 | .site-footer {
241 | font-size: 1rem; } }
242 |
243 | @media screen and (max-width: 42em) {
244 | .site-footer {
245 | font-size: 0.9rem; } }
246 |
--------------------------------------------------------------------------------
/dist/index.esm.js:
--------------------------------------------------------------------------------
1 | function _classCallCheck(instance, Constructor) {
2 | if (!(instance instanceof Constructor)) {
3 | throw new TypeError("Cannot call a class as a function");
4 | }
5 | }
6 |
7 | function _defineProperties(target, props) {
8 | for (var i = 0; i < props.length; i++) {
9 | var descriptor = props[i];
10 | descriptor.enumerable = descriptor.enumerable || false;
11 | descriptor.configurable = true;
12 | if ("value" in descriptor) descriptor.writable = true;
13 | Object.defineProperty(target, descriptor.key, descriptor);
14 | }
15 | }
16 |
17 | function _createClass(Constructor, protoProps, staticProps) {
18 | if (protoProps) _defineProperties(Constructor.prototype, protoProps);
19 | if (staticProps) _defineProperties(Constructor, staticProps);
20 | return Constructor;
21 | }
22 |
23 | function _slicedToArray(arr, i) {
24 | return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest();
25 | }
26 |
27 | function _toConsumableArray(arr) {
28 | return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread();
29 | }
30 |
31 | function _arrayWithoutHoles(arr) {
32 | if (Array.isArray(arr)) {
33 | for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
34 |
35 | return arr2;
36 | }
37 | }
38 |
39 | function _arrayWithHoles(arr) {
40 | if (Array.isArray(arr)) return arr;
41 | }
42 |
43 | function _iterableToArray(iter) {
44 | if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter);
45 | }
46 |
47 | function _iterableToArrayLimit(arr, i) {
48 | var _arr = [];
49 | var _n = true;
50 | var _d = false;
51 | var _e = undefined;
52 |
53 | try {
54 | for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
55 | _arr.push(_s.value);
56 |
57 | if (i && _arr.length === i) break;
58 | }
59 | } catch (err) {
60 | _d = true;
61 | _e = err;
62 | } finally {
63 | try {
64 | if (!_n && _i["return"] != null) _i["return"]();
65 | } finally {
66 | if (_d) throw _e;
67 | }
68 | }
69 |
70 | return _arr;
71 | }
72 |
73 | function _nonIterableSpread() {
74 | throw new TypeError("Invalid attempt to spread non-iterable instance");
75 | }
76 |
77 | function _nonIterableRest() {
78 | throw new TypeError("Invalid attempt to destructure non-iterable instance");
79 | }
80 |
81 | // The MIT License (MIT)
82 | // Copyright (c) 2016 NAVER Corp.
83 | // Permission is hereby granted, free of charge, to any person obtaining a copy
84 | // of this software and associated documentation files (the "Software"), to deal
85 | // in the Software without restriction, including without limitation the rights
86 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
87 | // copies of the Software, and to permit persons to whom the Software is
88 | // furnished to do so, subject to the following conditions:
89 | // The above copyright notice and this permission notice shall be included
90 | // in all copies or substantial portions of the Software.
91 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
92 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
93 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
94 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
95 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
96 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
97 | // SOFTWARE.
98 |
99 | /**
100 | * imageMaps 1.1.0
101 | * jquery plugin which can be partially linked to the image
102 | *
103 | * https://github.com/naver/image-maps
104 | * demo - https://naver.github.io/image-maps/
105 | *
106 | * Released on: July 6, 2016
107 | * @module imageMaps
108 | */
109 | var shapeFaceClass = '_shape_face';
110 | var shapeVertexClass = '_shape_vertex';
111 | var areaClass = 'area';
112 | /**
113 | * @typedef
114 | * {"rect"|"circle"|"ellipse"|"text"|"image"|"poly"|"polyline"|"polygon"}
115 | * module:imageMaps.ShapeType
116 | */
117 |
118 | var SHAPE = {
119 | RECT: 'rect',
120 | CIRCLE: 'circle',
121 | ELLIPSE: 'ellipse',
122 | TEXT: 'text',
123 | IMAGE: 'image',
124 | POLY: 'poly',
125 | POLYLINE: 'polyline',
126 | POLYGON: 'polygon'
127 | };
128 | /**
129 | * @see https://api.jquery.com/css/
130 | * @typedef {PlainObject} module:imageMaps.ShapeStyles
131 | */
132 |
133 | /**
134 | * @typedef {PlainObject} module:imageMaps.ImageMapOptions
135 | * @property {boolean} [isEditMode=false]
136 | * @property {module:imageMaps.ShapeType} [shape="rect"]
137 | * @property {string} [shapeText="press on link"]
138 | * @property {module:imageMaps.ShapeStyles} [shapeStyle] Defaults to
139 | * `{fill: '#ffffff', 'fill-opacity': 0.2,
140 | * stroke: '#ffffff', 'stroke-width': 3}`
141 | * @property {function} [onClick=function () {}]
142 | * @property {function} [onMouseDown=function () {}]
143 | * @property {function} [onMouseMove=function () {}]
144 | * @property {function} [onMouseUp=function () {}]
145 | * @property {function} [onSelect=function () {}]
146 | */
147 |
148 | /**
149 | * @type {module:imageMaps.ImageMapOptions}
150 | */
151 |
152 | var defaults = {
153 | isEditMode: false,
154 | // select map area shape type - rect, circle, text, image, poly
155 | shape: SHAPE.RECT,
156 | shapeText: 'press on link',
157 | // shape 옵션이 text일 때 적용된다.
158 | shapeStyle: {
159 | fill: '#ffffff',
160 | 'fill-opacity': 0.2,
161 | stroke: '#ffffff',
162 | 'stroke-width': 3
163 | },
164 |
165 | /* eslint-disable no-empty-function */
166 | onClick: function onClick(e, targetAreaHref) {},
167 | onMouseDown: function onMouseDown(e, shapeType, coords) {},
168 | onMouseMove: function onMouseMove(e, shapeType, movedCoords) {},
169 | onMouseUp: function onMouseUp(e, shapeType, updatedCoords) {},
170 | onSelect: function onSelect(e, shapeInfo) {}
171 | /* eslint-enable no-empty-function */
172 |
173 | };
174 | var defaultShapeOptions = {
175 | // top-left-x, top-left-y, bottom-right-x, botton-right-y
176 | rect: [0, 0, 20, 20],
177 | circle: [0, 0, 10],
178 | // center-x, center-y, radius
179 | ellipse: [0, 0, 5, 5],
180 | // center-x, center-y, radius-x, radius-y
181 | text: [0, 0, 12] // bottom-right-x, bottom-right-y, font-size
182 |
183 | };
184 | var FONT_SIZE_RATIO = 0.5;
185 | var NS_SVG = 'http://www.w3.org/2000/svg';
186 | var NS_XLINK = 'http://www.w3.org/1999/xlink';
187 | /**
188 | * Adds {@link external:"jQuery.fn"} methods.
189 | * @function module:imageMaps.jqueryImageMaps
190 | * @param {external:jQuery} $
191 | * @returns {external:jQuery}
192 | */
193 |
194 | function jqueryImageMaps($) {
195 | // The actual plugin constructor
196 |
197 | /**
198 | * @memberof module:imageMaps.jqueryImageMaps~
199 | */
200 | var ImageMaps =
201 | /*#__PURE__*/
202 | function () {
203 | /**
204 | *
205 | * @param {external:jQuery} container
206 | * @param {module:imageMaps.ImageMapOptions} [options]
207 | */
208 | function ImageMaps(container, options) {
209 | _classCallCheck(this, ImageMaps);
210 |
211 | this.container = $(container);
212 | this.mapEl = null;
213 | this.svgEl = null; // merge the default options with user-provided options
214 |
215 | this.options = $.extend(true, {}, defaults, options);
216 | this.shapeType = this.options.shape;
217 | this.isEditMode = this.options.isEditMode;
218 | this.shapeStyle = this.options.shapeStyle;
219 | this.shapeText = '';
220 | this.shapeImageUrl = '';
221 | this.shapeCoords = null;
222 | this.vertexCoords = null;
223 | this.grabType = null;
224 | this.containerWidth = 0;
225 | this.containerHeight = 0;
226 | this.touchStartCoords = {
227 | x: null,
228 | y: null
229 | };
230 | this.dragInfo = {
231 | face: {
232 | x: null,
233 | y: null
234 | },
235 | vertex: {
236 | x: null,
237 | y: null
238 | }
239 | };
240 | this.shapeLimitCoords = {
241 | x: 30,
242 | y: 30,
243 | radius: 15
244 | };
245 | this.allShapeInfo = {};
246 | }
247 | /**
248 | * ImageMaps: 이미지 엘리먼트 하단에 map, area 엘리먼트 생성 및 속성 부여.
249 | * @param {?(module:imageMaps.Coords)} coords
250 | * @param {Url} linkUrl
251 | * @returns {void}
252 | */
253 |
254 |
255 | _createClass(ImageMaps, [{
256 | key: "createMaps",
257 | value: function createMaps(coords, linkUrl) {
258 | var imageWidth = this.container.width();
259 |
260 | if (isNaN(imageWidth) || !imageWidth) {
261 | this.container.one('load', $.proxy(_createMaps, this, coords, linkUrl));
262 | } else {
263 | _createMaps.call(this, coords, linkUrl);
264 | }
265 | }
266 | /**
267 | * @param {module:imageMaps.ShapeType} shapeType
268 | * @returns {void}
269 | */
270 |
271 | }, {
272 | key: "setShapeType",
273 | value: function setShapeType(shapeType) {
274 | this.shapeType = shapeType;
275 | }
276 | /**
277 | *
278 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
279 | * @returns {void}
280 | */
281 |
282 | }, {
283 | key: "setShapeStyle",
284 | value: function setShapeStyle(styleOptions) {
285 | styleOptions = styleOptions || {};
286 | this.shapeStyle = $.extend({}, true, this.shapeStyle, styleOptions);
287 | }
288 | /**
289 | * @todo Implement
290 | * @param {Url} linkUrl
291 | * @param {Integer} index
292 | * @returns {void}
293 | */
294 |
295 | }, {
296 | key: "setUrl",
297 | value: function setUrl(linkUrl, index) {} // eslint-disable-line class-methods-use-this
298 | // Todo
299 |
300 | /**
301 | *
302 | * @param {string} text
303 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
304 | * @returns {void}
305 | */
306 |
307 | }, {
308 | key: "setTextShape",
309 | value: function setTextShape(text, styleOptions) {
310 | this.setShapeStyle(styleOptions);
311 | this.shapeText = text;
312 | }
313 | /**
314 | *
315 | * @param {string} imageUrl
316 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
317 | * @returns {void}
318 | */
319 |
320 | }, {
321 | key: "setImageShape",
322 | value: function setImageShape(imageUrl, styleOptions) {
323 | this.setShapeStyle(styleOptions);
324 | this.shapeImageUrl = imageUrl;
325 | }
326 | /**
327 | *
328 | * @param {?(module:imageMaps.Coords)} coords
329 | * @param {Url} linkUrl
330 | * @param {module:imageMaps.ShapeType} [shapeType]
331 | * @returns {void}
332 | */
333 |
334 | }, {
335 | key: "addShape",
336 | value: function addShape(coords, linkUrl, shapeType) {
337 | if (shapeType) {
338 | this.setShapeType(shapeType);
339 | }
340 |
341 | this.createMaps(coords, linkUrl);
342 | }
343 | /**
344 | * @param {Integer} [index]
345 | * @returns {void}
346 | */
347 |
348 | }, {
349 | key: "removeShape",
350 | value: function removeShape(index) {
351 | if (!this.shapeEl) {
352 | return;
353 | }
354 |
355 | if (typeof index === 'undefined') {
356 | index = this.shapeEl.data('index');
357 | }
358 |
359 | var areaEl = this.mapEl.find('area[data-index="' + index + '"]');
360 | var shapeEl = this.svgEl.find('.' + shapeFaceClass + '[data-index="' + index + '"]');
361 | this.detachEvents(shapeEl, [{
362 | type: 'click touchend'
363 | }]);
364 | shapeEl.parent().remove();
365 | areaEl.remove();
366 | this.removeShapeInfo(index);
367 | }
368 | /**
369 | *
370 | * @returns {void}
371 | */
372 |
373 | }, {
374 | key: "removeAllShapes",
375 | value: function removeAllShapes() {
376 | var _this = this;
377 |
378 | if (!this.shapeEl) {
379 | return;
380 | }
381 |
382 | var allShapeEls = this.svgEl.find('.' + shapeFaceClass);
383 | allShapeEls.each(function (i, shapeEl) {
384 | _this.removeShape($(shapeEl).data('index'));
385 | });
386 | this.allShapeInfo = {};
387 | }
388 | /**
389 | *
390 | * @returns {void}
391 | */
392 |
393 | }, {
394 | key: "removeImageMaps",
395 | value: function removeImageMaps() {
396 | this.removeAllShapes();
397 | this.svgEl && this.svgEl.remove();
398 | }
399 | /**
400 | * @typedef {PlainObject} module:imageMaps.ShapeInfoOptions
401 | * @property {Integer} index
402 | * @property {module:imageMaps.ShapeCoords} coords
403 | * @property {module:imageMaps.ShapeType} type
404 | * @property {Url} url
405 | * @property {module:imageMaps.ShapeStyles} style
406 | */
407 |
408 | /**
409 | * @typedef {PlainObject} module:imageMaps.ShapeSecondaryOptions
410 | * @property {string} text
411 | * @property {HTMLImageElement|string} href
412 | */
413 |
414 | /**
415 | *
416 | * @param {Integer} index
417 | * @param {module:imageMaps.ShapeInfoOptions} shapeOptions
418 | * @param {
419 | * module:imageMaps.ShapeSecondaryOptions
420 | * } [shapeSecondaryOptions]
421 | * @returns {void}
422 | */
423 |
424 | }, {
425 | key: "updateShapeInfo",
426 | value: function updateShapeInfo(index, shapeOptions, shapeSecondaryOptions) {
427 | var shapeInfo = this.allShapeInfo;
428 | shapeOptions.index = index;
429 |
430 | if (!shapeInfo['shape' + index]) {
431 | shapeInfo['shape' + index] = $.extend(true, shapeOptions, shapeSecondaryOptions);
432 | } else {
433 | shapeInfo['shape' + index] = $.extend(true, {}, shapeInfo['shape' + index], shapeOptions, shapeSecondaryOptions);
434 | }
435 | }
436 | /**
437 | * @param {Integer} index
438 | * @returns {void}
439 | */
440 |
441 | }, {
442 | key: "removeShapeInfo",
443 | value: function removeShapeInfo(index) {
444 | delete this.allShapeInfo['shape' + index];
445 | }
446 | /**
447 | *
448 | * @param {Integer} index
449 | * @returns {module:imageMaps.ShapeInfoOptions|
450 | * module:imageMaps.ShapeSecondaryOptions}
451 | */
452 |
453 | }, {
454 | key: "getShapeInfo",
455 | value: function getShapeInfo(index) {
456 | return this.allShapeInfo['shape' + index];
457 | }
458 | /**
459 | * @typedef {PlainObject} module:imageMaps.AllShapeInfo
460 | * @property {module:imageMaps.ShapeType} type
461 | * @property {module:imageMaps.Coords} coords
462 | * @property {Integer} index
463 | * @property {module:imageMaps.ShapeInfoOptions|
464 | * module:imageMaps.ShapeSecondaryOptions} shape
465 | */
466 |
467 | /**
468 | *
469 | * @returns {module:imageMaps.AllShapeInfo}
470 | */
471 |
472 | }, {
473 | key: "getAllShapesInfo",
474 | value: function getAllShapesInfo() {
475 | return $.extend(true, {}, this.allShapeInfo);
476 | }
477 | /**
478 | *
479 | * @param {Float[]} percentages
480 | * @returns {void}
481 | */
482 |
483 | }, {
484 | key: "zoom",
485 | value: function zoom(percentages) {
486 | _zoom.call(this, percentages);
487 | }
488 | /**
489 | *
490 | * @returns {void}
491 | */
492 |
493 | }, {
494 | key: "enableClick",
495 | value: function enableClick() {
496 | this.attachEvents(this.svgEl.find('.' + shapeFaceClass), [{
497 | type: 'touchstart',
498 | handler: onTouchStart
499 | }, {
500 | type: 'click touchend',
501 | handler: onClickShapeFace
502 | }]);
503 | }
504 | /**
505 | *
506 | * @returns {void}
507 | */
508 |
509 | }, {
510 | key: "disableClick",
511 | value: function disableClick() {
512 | this.detachEvents(this.svgEl.find('.' + shapeFaceClass), [{
513 | type: 'touchstart',
514 | handler: onTouchStart
515 | }, {
516 | type: 'click touchend',
517 | handler: onClickShapeFace
518 | }]);
519 | }
520 | /**
521 | *
522 | * @param {module:imageMaps.ShapeCoords} coords
523 | * @returns {void}
524 | */
525 |
526 | }, {
527 | key: "setShapeCoords",
528 | value: function setShapeCoords(coords) {
529 | this.shapeCoords = coords;
530 | }
531 | /**
532 | *
533 | * @param {module:imageMaps.VertexCoords} coords
534 | * @returns {void}
535 | */
536 |
537 | }, {
538 | key: "setVertexCoords",
539 | value: function setVertexCoords(coords) {
540 | this.vertexCoords = coords;
541 | }
542 | /**
543 | *
544 | * @param {module:imageMaps.ShapeElement} element
545 | * @returns {void}
546 | */
547 |
548 | }, {
549 | key: "setShapeElement",
550 | value: function setShapeElement(element) {
551 | this.shapeEl = element;
552 | }
553 | /**
554 | * @typedef {Element} module:imageMaps.VertexElement
555 | */
556 |
557 | /**
558 | *
559 | * @param {module:imageMaps.VertexElement} element
560 | * @returns {void}
561 | */
562 |
563 | }, {
564 | key: "setVertexElement",
565 | value: function setVertexElement(element) {
566 | this.vertexEl = element;
567 | }
568 | /**
569 | *
570 | * @param {module:imageMaps.VertexElements} elements
571 | * @returns {void}
572 | */
573 |
574 | }, {
575 | key: "setVertexElements",
576 | value: function setVertexElements(elements) {
577 | this.vertexEls = elements;
578 | }
579 | /**
580 | * @typedef {PlainObject} module:imageMaps.TypeHandler
581 | * @property {string} type
582 | * @property {function} handler
583 | */
584 |
585 | /**
586 | * ImageMaps: 이미지맵 이벤트 할당.
587 | * @param {Node|external:jQuery} element
588 | * @param {module:imageMaps.TypeHandler[]} eventOptions
589 | * @returns {void}
590 | */
591 |
592 | }, {
593 | key: "attachEvents",
594 | value: function attachEvents(element, eventOptions) {
595 | var _this2 = this;
596 |
597 | element = $(element);
598 | eventOptions.forEach(function (_ref) {
599 | var type = _ref.type,
600 | handler = _ref.handler;
601 | element.on(type + '.' + areaClass, $.proxy(handler, _this2));
602 | });
603 | }
604 | /**
605 | * ImageMaps: 이미지맵 이벤트 해제.
606 | * @param {external:jQuery} element
607 | * @param {module:imageMaps.TypeHandler[]} eventOptions
608 | * @returns {void}
609 | */
610 |
611 | }, {
612 | key: "detachEvents",
613 | value: function detachEvents(element, eventOptions) {
614 | var _this3 = this;
615 |
616 | element = $(element);
617 | eventOptions.forEach(function (_ref2) {
618 | var type = _ref2.type,
619 | handler = _ref2.handler;
620 | var eventType = type || '';
621 | var eventHandler = handler ? $.proxy(handler, _this3) : '';
622 |
623 | if (eventHandler) {
624 | element.off(eventType + '.' + areaClass, eventHandler);
625 | } else {
626 | element.off(eventType + '.' + areaClass);
627 | }
628 | });
629 | }
630 | }]);
631 |
632 | return ImageMaps;
633 | }();
634 |
635 | ImageMaps.getCoordsByRatio = getCoordsByRatio;
636 | /**
637 | * @memberof module:imageMaps.jqueryImageMaps~
638 | * @this module:imageMaps~ImageMaps
639 | * @param {?(module:imageMaps.Coords)} coords
640 | * @param {Url} linkUrl
641 | * @returns {void}
642 | */
643 |
644 | function _createMaps(coords, linkUrl) {
645 | // 최초 맵영역을 만드는 순간에 map 엘리먼트를 만들고 하위에 area 엘리먼트 생성.
646 | var uid = guid();
647 |
648 | if (!this.container.attr('usemap')) {
649 | this.mapEl = $(' ').insertAfter(this.container);
650 | this.container.attr('usemap', '#' + uid);
651 | } else {
652 | var usemapName = this.container.attr('usemap').replace('#', '');
653 | this.mapEl = $('body').find('map[name=' + usemapName + ']');
654 | }
655 |
656 | this.containerWidth = this.container.width();
657 | this.containerHeight = this.container.height();
658 | var imageWidth = this.containerWidth;
659 | var imageHeight = this.containerHeight;
660 | var centerX = imageWidth / 2;
661 | var centerY = imageHeight / 2; // 파라미터로 좌표값을 받으면 좌표에 해당하는 영역을 함께 그려준다.
662 |
663 | var shapeType = this.shapeType;
664 | var shapeCoords = [];
665 | var isDefaultTextCoords = false;
666 | coords = convertStringToNumber(coords);
667 |
668 | if (!Array.isArray(coords)) {
669 | // default 편집영역의 사이즈는 이미지의 0.1배로 계산. (내 맘대로..)
670 | var defaultShapeX = imageWidth * 0.1,
671 | defaultShapeY = imageHeight * 0.1;
672 | var defaultRadius = defaultShapeX >= defaultShapeY ? defaultShapeY : defaultShapeX; // invalid 좌표값이거나 배열이 아닌 타입일 경우는 디폴트 좌표로 그린다.
673 |
674 | if (shapeType === SHAPE.RECT) {
675 | shapeCoords = $.extend([], defaultShapeOptions.rect, [centerX - defaultShapeX, centerY - defaultShapeY, centerX + defaultShapeX, centerY + defaultShapeY]);
676 | } else if (shapeType === SHAPE.CIRCLE) {
677 | shapeCoords = $.extend([], defaultShapeOptions.circle, [centerX, centerY, defaultRadius]);
678 | } else if (shapeType === SHAPE.ELLIPSE) {
679 | shapeCoords = $.extend([], defaultShapeOptions.ellipse, [centerX, centerY, defaultRadius, defaultRadius]);
680 | } else if (shapeType === SHAPE.IMAGE) {
681 | var imageSize = getNaturalImageSize(this.shapeImageUrl);
682 | defaultShapeX = imageSize.width / 2;
683 | defaultShapeY = imageSize.height / 2;
684 | shapeCoords = [centerX - defaultShapeX, centerY - defaultShapeY, centerX + defaultShapeX, centerY + defaultShapeY];
685 | }
686 | } else {
687 | // 타입별로 정상적으로 좌표값을 받았다면 해당 좌표로 그린다.
688 | // eslint-disable-next-line no-lonely-if
689 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
690 | shapeCoords = $.extend([], defaultShapeOptions.rect, coords);
691 | } else if (shapeType === SHAPE.CIRCLE) {
692 | shapeCoords = $.extend([], defaultShapeOptions.circle, coords);
693 | } else if (shapeType === SHAPE.ELLIPSE) {
694 | shapeCoords = $.extend([], defaultShapeOptions.ellipse, coords);
695 | } else if (shapeType === SHAPE.TEXT) {
696 | if (!coords[0]) {
697 | coords[0] = centerX;
698 | isDefaultTextCoords = true;
699 | }
700 |
701 | if (!coords[1]) {
702 | coords[1] = centerY;
703 | isDefaultTextCoords = true;
704 | }
705 |
706 | if (!coords[2]) {
707 | coords[2] = 20;
708 | }
709 |
710 | shapeCoords = $.extend([], defaultShapeOptions.text, coords);
711 | }
712 | }
713 |
714 | var index = this.mapEl.find('.' + shapeFaceClass).length;
715 | var areaType = shapeType;
716 | var shapeSecondaryOptions = {};
717 |
718 | if (shapeType === SHAPE.TEXT || shapeType === SHAPE.IMAGE) {
719 | areaType = SHAPE.RECT;
720 |
721 | if (shapeType === SHAPE.TEXT) {
722 | shapeSecondaryOptions = {
723 | text: this.shapeText
724 | };
725 | } else {
726 | shapeSecondaryOptions = {
727 | href: this.shapeImageUrl
728 | };
729 | }
730 | }
731 |
732 | createOverlay.call(this, shapeCoords, uid, linkUrl, index);
733 | this.setShapeCoords(shapeCoords);
734 | this.updateShapeInfo(index, {
735 | coords: shapeCoords,
736 | type: shapeType,
737 | url: linkUrl,
738 | style: this.shapeStyle
739 | }, shapeSecondaryOptions);
740 |
741 | if (isDefaultTextCoords && this.isEditMode && shapeType === SHAPE.TEXT) {
742 | adjustTextShape.call(this);
743 | }
744 |
745 | if (shapeType === SHAPE.ELLIPSE) {
746 | areaType = SHAPE.CIRCLE;
747 | shapeCoords = [shapeCoords[0], shapeCoords[1], defaultShapeOptions.ellipse[2], defaultShapeOptions.ellipse[2]];
748 | }
749 |
750 | createArea.call(this, areaType, shapeCoords, linkUrl, index);
751 | }
752 | /**
753 | * @memberof module:imageMaps.jqueryImageMaps~
754 | * @this module:imageMaps~ImageMaps
755 | * @param {module:imageMaps.ShapeCoords} shapeCoords
756 | * @param {string} uid
757 | * @param {Url} linkUrl
758 | * @param {Integer} index
759 | * @returns {void}
760 | */
761 |
762 |
763 | function createOverlay(shapeCoords, uid, linkUrl, index) {
764 | var containerWidth = this.container.width(),
765 | containerHeight = this.container.height();
766 |
767 | if (typeof document.createElementNS !== 'undefined') {
768 | var svgNativeEl = this.mapEl.find('svg').get(0);
769 | var svgEl = $(svgNativeEl);
770 | var shapeType = this.shapeType;
771 |
772 | if (!svgNativeEl) {
773 | svgNativeEl = document.createElementNS(NS_SVG, 'svg');
774 | svgEl = $(svgNativeEl);
775 | this.svgEl = svgEl;
776 |
777 | if (this.isEditMode) {
778 | this.attachEvents(svgEl, [{
779 | type: 'mousedown',
780 | handler: onMouseDown
781 | }]);
782 | } else {
783 | this.attachEvents(this.mapEl, [{
784 | type: 'touchstart',
785 | handler: onTouchStart
786 | }, {
787 | type: 'click touchend',
788 | handler: onClickShapeFace
789 | }]);
790 | }
791 |
792 | this.attachEvents(window, [{
793 | type: 'resize',
794 | handler: onResize
795 | }]);
796 | } // svgEl.get(0).setAttributeNS("http://www.w3.org/2000/xmlns/", "xmlns:xlink", "http://www.w3.org/1999/xlink");
797 | // svg의 width, height는 DOM API로 처리해야 사이즈가 제대로 나옴.
798 |
799 |
800 | svgNativeEl.setAttribute('width', containerWidth);
801 | svgNativeEl.setAttribute('height', containerHeight); // container의 부모에 대한 상대좌표에 따라 svg의 좌표값이 결정된다.
802 |
803 | var containerPos = this.container.position();
804 | svgEl.attr({
805 | xmlns: NS_SVG,
806 | 'xmlns:xlink': NS_XLINK,
807 | version: '1.1',
808 | 'data-Id': uid
809 | }).css({
810 | position: 'absolute',
811 | zIndex: 1000,
812 | overflow: 'hidden',
813 | top: containerPos.top,
814 | left: containerPos.left
815 | });
816 | var shapeGroupEl = createShape.call(this, shapeType, shapeCoords, linkUrl, index);
817 | svgEl.append(shapeGroupEl);
818 | this.mapEl.append(svgEl);
819 | }
820 | }
821 | /**
822 | * @memberof module:imageMaps.jqueryImageMaps~
823 | * @this module:imageMaps~ImageMaps
824 | * @param {string} areaType
825 | * @param {module:imageMaps.ShapeCoords} shapeCoords
826 | * @param {Url} linkUrl
827 | * @param {string|Integer} index
828 | * @returns {void}
829 | */
830 |
831 |
832 | function createArea(areaType, shapeCoords, linkUrl, index) {
833 | $(' ').appendTo(this.mapEl);
834 | }
835 | /**
836 | * @memberof module:imageMaps.jqueryImageMaps~
837 | * @this module:imageMaps~ImageMaps
838 | * @param {module:imageMaps.ShapeType} shapeType
839 | * @param {module:imageMaps.ShapeCoords} shapeCoords
840 | * @param {Url} linkUrl
841 | * @param {string|Integer} index
842 | * @returns {void}
843 | */
844 |
845 |
846 | function createShape(shapeType, shapeCoords, linkUrl, index) {
847 | if (shapeType === SHAPE.POLY) {
848 | shapeType = SHAPE.POLYLINE;
849 | }
850 |
851 | var shapeEl = $(document.createElementNS(NS_SVG, shapeType));
852 | var gEl = $(document.createElementNS(NS_SVG, 'g'));
853 | drawShape.call(this, shapeCoords, shapeEl);
854 | var cursor = 'default';
855 |
856 | if (this.isEditMode) {
857 | cursor = 'move';
858 | } else if (linkUrl !== '') {
859 | cursor = 'pointer';
860 | }
861 |
862 | this.setShapeStyle({
863 | cursor: cursor
864 | });
865 | shapeEl.css(this.shapeStyle);
866 |
867 | if (shapeType === SHAPE.TEXT) {
868 | shapeEl.css({
869 | 'fill-opacity': '',
870 | 'stroke-opacity': ''
871 | });
872 | }
873 |
874 | shapeEl.attr('data-index', index);
875 | gEl.append(shapeEl);
876 | this.setShapeElement(shapeEl);
877 |
878 | if (this.isEditMode && shapeType !== 'text') {
879 | var vertexEls = createVertex(shapeType, shapeCoords, index);
880 | gEl.append.apply(gEl, _toConsumableArray(vertexEls));
881 | this.setVertexElements(vertexEls);
882 | }
883 |
884 | return gEl;
885 | }
886 | /**
887 | * @typedef {PlainObject} module:imageMaps.ShapeOptions
888 | * @property {string} text
889 | * @property {string} href
890 | * @property {module:imageMaps.ShapeType} type
891 | */
892 |
893 | /**
894 | * @memberof module:imageMaps.jqueryImageMaps~
895 | * @this module:imageMaps~ImageMaps
896 | * @param {module:imageMaps.ShapeCoords} shapeCoords
897 | * @param {module:imageMaps.ShapeElement} [shapeEl]
898 | * @param {module:imageMaps.ShapeOptions} [shapeOptions]
899 | * @returns {void}
900 | */
901 |
902 |
903 | function drawShape(shapeCoords, shapeEl, shapeOptions) {
904 | shapeEl = shapeEl || this.shapeEl;
905 | var shapeType = shapeOptions ? shapeOptions.type : this.shapeType;
906 |
907 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
908 | shapeEl.attr({
909 | x: shapeCoords[0],
910 | y: shapeCoords[1],
911 | "class": shapeFaceClass
912 | });
913 |
914 | if (shapeCoords[2]) {
915 | shapeEl.attr('width', shapeCoords[2] - shapeCoords[0]);
916 | }
917 |
918 | if (shapeCoords[3]) {
919 | shapeEl.attr('height', shapeCoords[3] - shapeCoords[1]);
920 | }
921 |
922 | if (shapeType === SHAPE.IMAGE) {
923 | // xlink 속성 설정 시에는 DOM api의 setAttributeNS를 사용해야 함.
924 | // svg 전용 속성은 무조건 DOM api를 사용해야 함.
925 | shapeEl.get(0).setAttributeNS(NS_XLINK, 'href', shapeOptions ? shapeOptions.href : this.shapeImageUrl); // image 엘리먼트의 width, height를 고정 비율로 변경되는 걸 해제해주기 위한 속성 셋팅.
926 |
927 | shapeEl.get(0).setAttribute('preserveAspectRatio', 'none');
928 | }
929 | } else if (shapeType === SHAPE.CIRCLE) {
930 | shapeEl.attr({
931 | cx: shapeCoords[0],
932 | cy: shapeCoords[1],
933 | "class": shapeFaceClass
934 | });
935 |
936 | if (shapeCoords[2]) {
937 | shapeEl.attr('r', shapeCoords[2]);
938 | }
939 | } else if (shapeType === SHAPE.ELLIPSE) {
940 | shapeEl.attr({
941 | cx: shapeCoords[0],
942 | cy: shapeCoords[1],
943 | "class": shapeFaceClass
944 | });
945 |
946 | if (shapeCoords[2]) {
947 | shapeEl.attr('rx', shapeCoords[2]);
948 | }
949 |
950 | if (shapeCoords[3]) {
951 | shapeEl.attr('ry', shapeCoords[3]);
952 | }
953 | } else if (shapeType === SHAPE.TEXT) {
954 | shapeEl.attr({
955 | x: shapeCoords[0],
956 | y: shapeCoords[1],
957 | 'font-size': shapeCoords[2],
958 | "class": shapeFaceClass
959 | });
960 | shapeEl.text(shapeOptions && shapeOptions.text || this.shapeText);
961 | }
962 | }
963 | /**
964 | * @memberof module:imageMaps.jqueryImageMaps~
965 | * @this module:imageMaps~ImageMaps
966 | * @returns {void}
967 | */
968 |
969 |
970 | function adjustTextShape() {
971 | var shapeEl = this.shapeEl;
972 | var shapeSize = shapeEl.get(0).getBBox();
973 | var centerX = shapeSize.width / 2;
974 | var centerY = parseFloat(shapeEl.attr('font-size')) * FONT_SIZE_RATIO / 2;
975 | var bottomRightX = parseInt(shapeEl.attr('x'));
976 | var bottomRightY = parseInt(shapeEl.attr('y'));
977 | var resultX = bottomRightX - centerX;
978 | var resultY = bottomRightY + centerY;
979 | this.updateShapeInfo(shapeEl.data('index'), {
980 | coords: [resultX, resultY, shapeEl.attr('font-size')]
981 | });
982 | shapeEl.attr({
983 | x: resultX,
984 | y: resultY
985 | });
986 | }
987 | /**
988 | * `SVGRect` element for each vertex coordinate
989 | * @typedef {SVGRect[]} module:imageMaps.VertexElements One
990 | */
991 |
992 | /**
993 | * @memberof module:imageMaps.jqueryImageMaps~
994 | * @static
995 | * @param {module:imageMaps.ShapeType} shapeType
996 | * @param {module:imageMaps.ShapeCoords} shapeCoords
997 | * @param {Integer} index
998 | * @returns {module:imageMaps.VertexElements}
999 | */
1000 |
1001 |
1002 | function createVertex(shapeType, shapeCoords, index) {
1003 | var vertexCoords = calculateVertexCoords(shapeType, shapeCoords);
1004 | var vertexTemp = vertexCoords.map(function () {
1005 | var vertexEl = $(document.createElementNS(NS_SVG, 'rect'));
1006 | vertexEl.attr('data-index', index).css({
1007 | fill: '#ffffff',
1008 | stroke: '#000000',
1009 | 'stroke-width': 2
1010 | });
1011 | return vertexEl;
1012 | });
1013 | drawVertex(vertexCoords, vertexTemp, shapeType);
1014 | return vertexTemp;
1015 | }
1016 | /**
1017 | * @typedef {PlainObject} module:imageMaps.VertexCoords
1018 | * @property {Float} x
1019 | * @property {Float} y
1020 | * @property {module:imageMaps.CursorType} type
1021 | */
1022 |
1023 | /**
1024 | * @memberof module:imageMaps.jqueryImageMaps~
1025 | * @static
1026 | * @param {module:imageMaps.VertexCoords} vertexCoords
1027 | * @param {module:imageMaps.VertexElements} vertexEls
1028 | * @param {module:imageMaps.ShapeType} shapeType Not currently in use
1029 | * @returns {void}
1030 | */
1031 |
1032 |
1033 | function drawVertex(vertexCoords, vertexEls, shapeType) {
1034 | vertexCoords.forEach(function (eachCoords, i) {
1035 | $(vertexEls[i]).attr({
1036 | x: eachCoords.x - 3,
1037 | y: eachCoords.y - 3,
1038 | width: 7,
1039 | height: 7,
1040 | 'data-direction': eachCoords.type,
1041 | "class": shapeVertexClass
1042 | }).css('cursor', getCursor(eachCoords.type));
1043 | });
1044 | }
1045 | /**
1046 | * @typedef {module:imageMaps.Coords} module:imageMaps.ShapeCoords
1047 | */
1048 |
1049 | /**
1050 | * @memberof module:imageMaps.jqueryImageMaps~
1051 | * @static
1052 | * @param {module:imageMaps.ShapeType} shapeType
1053 | * @param {module:imageMaps.ShapeCoords} shapeCoords
1054 | * @returns {module:imageMaps.VertexCoords}
1055 | */
1056 |
1057 |
1058 | function calculateVertexCoords(shapeType, shapeCoords) {
1059 | var vertexArr = [];
1060 |
1061 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
1062 | // 좌상, 좌하, 우상, 우하, 상, 하, 좌, 우 순
1063 | // 개별 vertex의 좌표값이므로 좌표의 순서는 크게 상관 없지만 참고로...
1064 | vertexArr = [{
1065 | x: shapeCoords[0],
1066 | y: shapeCoords[1],
1067 | type: 'nw'
1068 | }, {
1069 | x: shapeCoords[0],
1070 | y: shapeCoords[3],
1071 | type: 'sw'
1072 | }, {
1073 | x: shapeCoords[2],
1074 | y: shapeCoords[1],
1075 | type: 'ne'
1076 | }, {
1077 | x: shapeCoords[2],
1078 | y: shapeCoords[3],
1079 | type: 'se'
1080 | }, {
1081 | x: (shapeCoords[2] - shapeCoords[0]) / 2 + shapeCoords[0],
1082 | y: shapeCoords[1],
1083 | type: 'n'
1084 | }, {
1085 | x: (shapeCoords[2] - shapeCoords[0]) / 2 + shapeCoords[0],
1086 | y: shapeCoords[3],
1087 | type: 's'
1088 | }, {
1089 | x: shapeCoords[0],
1090 | y: (shapeCoords[3] - shapeCoords[1]) / 2 + shapeCoords[1],
1091 | type: 'w'
1092 | }, {
1093 | x: shapeCoords[2],
1094 | y: (shapeCoords[3] - shapeCoords[1]) / 2 + shapeCoords[1],
1095 | type: 'e'
1096 | }];
1097 | } else if (shapeType === SHAPE.CIRCLE) {
1098 | // 상, 하, 좌, 우
1099 | vertexArr = [{
1100 | x: shapeCoords[0],
1101 | y: shapeCoords[1] - shapeCoords[2],
1102 | type: 'n'
1103 | }, {
1104 | x: shapeCoords[0],
1105 | y: shapeCoords[1] + shapeCoords[2],
1106 | type: 's'
1107 | }, {
1108 | x: shapeCoords[0] - shapeCoords[2],
1109 | y: shapeCoords[1],
1110 | type: 'w'
1111 | }, {
1112 | x: shapeCoords[0] + shapeCoords[2],
1113 | y: shapeCoords[1],
1114 | type: 'e'
1115 | }];
1116 | } else if (shapeType === SHAPE.ELLIPSE) {
1117 | // 상, 하, 좌, 우
1118 | vertexArr = [{
1119 | x: shapeCoords[0],
1120 | y: shapeCoords[1] - shapeCoords[3],
1121 | type: 'n'
1122 | }, {
1123 | x: shapeCoords[0],
1124 | y: shapeCoords[1] + shapeCoords[3],
1125 | type: 's'
1126 | }, {
1127 | x: shapeCoords[0] - shapeCoords[2],
1128 | y: shapeCoords[1],
1129 | type: 'w'
1130 | }, {
1131 | x: shapeCoords[0] + shapeCoords[2],
1132 | y: shapeCoords[1],
1133 | type: 'e'
1134 | }];
1135 | }
1136 |
1137 | return vertexArr;
1138 | }
1139 | /**
1140 | * @memberof module:imageMaps.jqueryImageMaps~
1141 | * @this module:imageMaps~ImageMaps
1142 | * @param {module:imageMaps.ShapeCoords} shapeCoords
1143 | * @param {Element} areaEl
1144 | * @param {module:imageMaps.ShapeType} [shapeType]
1145 | * @returns {void}
1146 | */
1147 |
1148 |
1149 | function drawArea(shapeCoords, areaEl, shapeType) {
1150 | var shapeEl = this.svgEl.find('.' + shapeFaceClass + '[data-index="' + areaEl.data('index') + '"]');
1151 | shapeType = shapeType || this.shapeType;
1152 |
1153 | if (shapeType === SHAPE.TEXT) {
1154 | shapeCoords = convertTextToRectCoords(shapeEl);
1155 | } else if (shapeType === SHAPE.ELLIPSE) {
1156 | shapeCoords = [shapeCoords[0], shapeCoords[1], defaultShapeOptions.ellipse[2]];
1157 | }
1158 |
1159 | areaEl.attr('coords', shapeCoords.join(','));
1160 | }
1161 | /**
1162 | * @typedef {"col"|"row"|Direction|"ew"|"ns"|"nesw"|"nwse"}
1163 | * module:imageMaps.CursorType
1164 | */
1165 |
1166 | /**
1167 | * @memberof module:imageMaps.jqueryImageMaps~
1168 | * @static
1169 | * @param {module:imageMaps.CursorType} type
1170 | * CSS cursor resize type
1171 | * @returns {string}
1172 | */
1173 |
1174 |
1175 | function getCursor(type) {
1176 | return type + '-resize';
1177 | }
1178 | /**
1179 | * @memberof module:imageMaps.jqueryImageMaps~
1180 | * @this module:imageMaps~ImageMaps
1181 | * @param {Event} e The `touchstart` event
1182 | * @returns {void}
1183 | */
1184 |
1185 |
1186 | function onTouchStart(e) {
1187 | var touchCoords = e.originalEvent.touches[0];
1188 | this.touchStartCoords.x = touchCoords.pageX;
1189 | this.touchStartCoords.y = touchCoords.pageY;
1190 | }
1191 | /**
1192 | * @memberof module:imageMaps.jqueryImageMaps~
1193 | * @this module:imageMaps~ImageMaps
1194 | * @param {Event} e The `click touchend` event
1195 | * @returns {void}
1196 | */
1197 |
1198 |
1199 | function onClickShapeFace(e) {
1200 | // IE8이 이외의 브라우저는 아래 계산 로직을 타지 않아도 된다.
1201 | // IE8은 area 엘리먼트 클릭 시 href 속성의 url로 이동.
1202 | var targetAreaEl = $(e.currentTarget);
1203 |
1204 | if (e.currentTarget.tagName.toLowerCase() !== 'area') {
1205 | e.preventDefault();
1206 |
1207 | if (this.dragInfo.face.x && this.dragInfo.face.x !== e.pageX || this.dragInfo.face.y && this.dragInfo.face.y !== e.pageY || e.target.tagName.toLowerCase() === 'svg' || e.type === 'touchend' && e.originalEvent.changedTouches[0].pageX !== this.touchStartCoords.x && e.originalEvent.changedTouches[0].pageY !== this.touchStartCoords.y) {
1208 | return;
1209 | } // 클릭하거나 마우스엔터, 마우스다운 된 shape를 현재 타겟으로 저장.
1210 | // 타겟이 되는 shape의 좌표 정보를 가지고 모든 로직이 수행되도록 한다.
1211 |
1212 |
1213 | var targetEl = $(e.target);
1214 | var index = targetEl.attr('data-index');
1215 | targetAreaEl = this.mapEl.find('area[data-index="' + index + '"]');
1216 | var url = targetAreaEl.attr('href');
1217 | url !== '#' && window.open(targetAreaEl.attr('href'));
1218 | }
1219 |
1220 | this.options.onClick.call(this, e, targetAreaEl.attr('href'));
1221 | } // drag & drop
1222 |
1223 | /**
1224 | * @memberof module:imageMaps.jqueryImageMaps~
1225 | * @this module:imageMaps~ImageMaps
1226 | * @param {Event} e The `mousedown` event
1227 | * @returns {void}
1228 | */
1229 |
1230 |
1231 | function onMouseDown(e) {
1232 | e.preventDefault();
1233 |
1234 | if (e.target.tagName.toLowerCase() === 'svg') {
1235 | return;
1236 | }
1237 |
1238 | var targetEl = $(e.target);
1239 | var index = targetEl.attr('data-index');
1240 | var shapeInfo = this.getShapeInfo(index);
1241 | var groupEl = targetEl.parent();
1242 | var shapeEl = groupEl.find(':first-child');
1243 | var coords = [];
1244 | var shapeType = shapeEl.get(0).tagName.toLowerCase();
1245 |
1246 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
1247 | var targetX = parseInt(shapeEl.attr('x'));
1248 | var targetY = parseInt(shapeEl.attr('y'));
1249 | coords = [targetX, targetY, targetX + parseInt(shapeEl.attr('width')), targetY + parseInt(shapeEl.attr('height'))];
1250 |
1251 | if (shapeType === SHAPE.IMAGE) {
1252 | this.setImageShape(shapeEl.attr('href'));
1253 | }
1254 | } else if (shapeType === SHAPE.CIRCLE) {
1255 | var _targetX = parseInt(shapeEl.attr('cx'));
1256 |
1257 | var _targetY = parseInt(shapeEl.attr('cy'));
1258 |
1259 | coords = [_targetX, _targetY, parseInt(shapeEl.attr('r'))];
1260 | } else if (shapeType === SHAPE.ELLIPSE) {
1261 | var _targetX2 = parseInt(shapeEl.attr('cx'));
1262 |
1263 | var _targetY2 = parseInt(shapeEl.attr('cy'));
1264 |
1265 | coords = [_targetX2, _targetY2, parseInt(shapeEl.attr('rx')), parseInt(shapeEl.attr('ry'))];
1266 | } else if (shapeType === SHAPE.TEXT) {
1267 | var _targetX3 = parseFloat(shapeEl.attr('x'));
1268 |
1269 | var _targetY3 = parseFloat(shapeEl.attr('y'));
1270 |
1271 | var fontSize = parseFloat(shapeEl.attr('font-size'));
1272 | coords = [_targetX3, _targetY3, fontSize];
1273 | this.shapeText = shapeEl.text();
1274 | } else if (shapeType === SHAPE.POLYGON) {
1275 | shapeType = SHAPE.POLY;
1276 | }
1277 |
1278 | this.setShapeType(shapeType);
1279 | this.setShapeElement(shapeEl);
1280 | this.setShapeCoords(coords);
1281 |
1282 | if (shapeType !== SHAPE.TEXT) {
1283 | shapeEl.attr('data-fill', shapeEl.css('fill'));
1284 | shapeEl.css('fill', '#ffffff');
1285 | this.setVertexCoords(calculateVertexCoords(shapeType, coords));
1286 | var vertexTemp = [];
1287 | var vertexEls = this.mapEl.find('.' + shapeVertexClass + '[data-index="' + index + '"]');
1288 | vertexEls.each(function () {
1289 | vertexTemp.push($(this));
1290 | });
1291 | this.setVertexElements(vertexTemp);
1292 | }
1293 |
1294 | if (targetEl.is('.' + shapeFaceClass)) {
1295 | this.grabType = 'face';
1296 | declareShape.call(this, targetEl, e.pageX, e.pageY);
1297 | } else if (targetEl.is('.' + shapeVertexClass)) {
1298 | this.grabType = 'vertex';
1299 | declareVertex.call(this, targetEl, index);
1300 | }
1301 |
1302 | this.attachEvents(this.mapEl.parent(), [{
1303 | type: 'mouseup',
1304 | handler: onMouseUp
1305 | }, {
1306 | type: 'mousemove',
1307 | handler: onMouseMove
1308 | }]);
1309 | this.options.onSelect.call(this, e, shapeInfo);
1310 | this.options.onMouseDown.call(this, e, shapeType, coords);
1311 | }
1312 | /**
1313 | * @memberof module:imageMaps.jqueryImageMaps~
1314 | * @this module:imageMaps~ImageMaps
1315 | * @param {Event} e The `mouseup` event
1316 | * @returns {void}
1317 | */
1318 |
1319 |
1320 | function onMouseUp(e) {
1321 | var targetEl = $(e.target);
1322 | var shapeEl = this.shapeEl;
1323 | shapeEl.css('fill', shapeEl.attr('data-fill'));
1324 | targetEl.attr('data-movable', false);
1325 | var updatedCoords = determineShape.call(this);
1326 | this.setShapeCoords(updatedCoords);
1327 | this.updateShapeInfo(shapeEl.data('index'), {
1328 | coords: updatedCoords
1329 | });
1330 | this.detachEvents(this.mapEl.parent(), [{
1331 | type: 'mouseup',
1332 | handler: onMouseUp
1333 | }, {
1334 | type: 'mousemove',
1335 | handler: onMouseMove
1336 | }]);
1337 | this.options.onMouseUp.call(this, e, this.shapeType, updatedCoords);
1338 | }
1339 | /**
1340 | * @memberof module:imageMaps.jqueryImageMaps~
1341 | * @this module:imageMaps~ImageMaps
1342 | * @param {Event} e The `mousemove` event
1343 | * @returns {void}
1344 | */
1345 |
1346 |
1347 | function onMouseMove(e) {
1348 | var targetEl = $(e.target);
1349 |
1350 | var _this$shapeCoords = _slicedToArray(this.shapeCoords, 2),
1351 | x = _this$shapeCoords[0],
1352 | y = _this$shapeCoords[1];
1353 |
1354 | var grabType = this.grabType,
1355 | shapeType = this.shapeType;
1356 | var coords = {}; // 좌표 계산 시 e.offsetX, offsetY값은 이벤트 발생 대상(e.currentTarget)
1357 | // 기준 좌표 값이므로
1358 | // 이벤트 발생 도중(특히 mousemove) 겹치는 이벤트 타겟이 생기면 해당 타겟 기준
1359 | // 좌표로 변경되어 좌표가 튀는 현상 발생.
1360 | // 그러므로 브라우저에서 drag & drop 구현 시 웬만하면 브라우저의 절대 좌표값인
1361 | // e.pageX, pageY를 사용하도록 한다.
1362 |
1363 | if (grabType === 'face' || grabType === 'vertex') {
1364 | if (grabType === 'face') {
1365 | var movedX = x + e.pageX;
1366 | var movedY = y + e.pageY;
1367 | coords = getMovedShapeCoords.call(this, movedX - this.dragInfo.face.x, movedY - this.dragInfo.face.y);
1368 | } else if (grabType === 'vertex') {
1369 | coords = getMovedVertexCoords.call(this, e.pageX - this.svgEl.offset().left, e.pageY - this.svgEl.offset().top);
1370 | }
1371 |
1372 | if (!coords) {
1373 | return;
1374 | }
1375 |
1376 | if (shapeType !== SHAPE.TEXT) {
1377 | this.setVertexCoords(coords.vertexCoords);
1378 | drawVertex(coords.vertexCoords, this.vertexEls, this.shapeType);
1379 | }
1380 |
1381 | var index = parseInt(coords.grabEl.attr('data-index'));
1382 | drawShape.call(this, coords.movedCoords, this.svgEl.find('.' + shapeFaceClass + '[data-index="' + index + '"]'));
1383 | drawArea.call(this, coords.movedCoords, this.mapEl.find('area[data-index="' + index + '"]')); // svg 내 엘리먼트들은 z-index 영향을 받지 않고 document 순서에 영향을 받는다.
1384 | // 그래서 drag 시 다른 요소들보다 최상위에 두려면 엘리먼트 순서를 부모의 가장 하위에 두어야 한다.
1385 | // mousedown에서 이 로직을 넣을 경우,
1386 | // 외부에서 click 이벤트를 할당했을 때 mousedown 핸들러에서 dom 우선순위 조정하는 과정에서
1387 | // click 이벤트가 해제되는 이슈로 mousemove 안에 둠.
1388 |
1389 | if ((targetEl.is('.' + shapeFaceClass) || targetEl.is('.' + shapeVertexClass)) && (Math.abs(this.dragInfo.face.x - e.pageX) <= 1 || Math.abs(this.dragInfo.face.y - e.pageY) <= 1)) {
1390 | this.svgEl.append(targetEl.parent());
1391 | }
1392 |
1393 | this.options.onMouseMove.call(this, e, shapeType, coords.movedCoords);
1394 | }
1395 | }
1396 | /**
1397 | * @memberof module:imageMaps.jqueryImageMaps~
1398 | * @this module:imageMaps~ImageMaps
1399 | * @param {Event} e The `resize` event
1400 | * @returns {void}
1401 | */
1402 |
1403 |
1404 | function onResize(e) {
1405 | var containerWidth = this.container.width();
1406 | var containerHeight = this.container.height();
1407 |
1408 | if (this.containerWidth !== containerWidth || this.containerHeight !== containerHeight) {
1409 | redraw.call(this, containerWidth, containerHeight);
1410 | }
1411 | }
1412 | /**
1413 | * @memberof module:imageMaps.jqueryImageMaps~
1414 | * @this module:imageMaps~ImageMaps
1415 | * @param {Float[]} percentages
1416 | * @returns {void}
1417 | */
1418 |
1419 |
1420 | function _zoom(percentages) {
1421 | var _this4 = this;
1422 |
1423 | var widthPercentage = percentages[0];
1424 | var heightPercentage = percentages.length < 2 ? widthPercentage : percentages[1];
1425 | var containerWidth = widthPercentage * 0.01 * this.container.width();
1426 | var containerHeight = heightPercentage * 0.01 * this.container.height();
1427 | this.container.css({
1428 | width: containerWidth + 'px',
1429 | height: containerHeight + 'px'
1430 | });
1431 | setTimeout(function () {
1432 | if (_this4.svgEl && _this4.svgEl.length > 0) {
1433 | redraw.call(_this4, containerWidth, containerHeight);
1434 | }
1435 | });
1436 | }
1437 | /**
1438 | * @memberof module:imageMaps.jqueryImageMaps~
1439 | * @this module:imageMaps~ImageMaps
1440 | * @param {Float} containerWidth
1441 | * @param {Float} containerHeight
1442 | * @returns {void}
1443 | */
1444 |
1445 |
1446 | function redraw(containerWidth, containerHeight) {
1447 | var _this5 = this;
1448 |
1449 | var allShapeInfo = this.allShapeInfo;
1450 | var widthRatio = containerWidth / this.containerWidth;
1451 | var heightRatio = containerHeight / this.containerHeight;
1452 | var containerPos = this.container.position();
1453 | this.svgEl.get(0).setAttribute('width', containerWidth);
1454 | this.svgEl.get(0).setAttribute('height', containerHeight);
1455 | this.svgEl.css({
1456 | top: containerPos.top,
1457 | left: containerPos.left
1458 | });
1459 | $.each(allShapeInfo, function (index, item) {
1460 | item.coords = getCoordsByRatio(item.coords, item.type, widthRatio, heightRatio);
1461 | drawVertex(calculateVertexCoords(item.type, item.coords), _this5.svgEl.find('.' + shapeVertexClass + '[data-index="' + item.index + '"]'), item.type);
1462 | drawShape.call(_this5, item.coords, _this5.svgEl.find('.' + shapeFaceClass + '[data-index="' + item.index + '"]'), item);
1463 | drawArea.call(_this5, item.coords, _this5.mapEl.find('area[data-index="' + item.index + '"]'), item.type);
1464 | });
1465 | this.containerWidth = containerWidth;
1466 | this.containerHeight = containerHeight;
1467 | }
1468 | /**
1469 | * @typedef {Element} module:imageMaps.ShapeElement
1470 | */
1471 |
1472 | /**
1473 | * @memberof module:imageMaps.jqueryImageMaps~
1474 | * @this module:imageMaps~ImageMaps
1475 | * @param {module:imageMaps.ShapeElement} shapeEl
1476 | * @param {Float} x
1477 | * @param {Float} y
1478 | * @returns {void}
1479 | */
1480 |
1481 |
1482 | function declareShape(shapeEl, x, y) {
1483 | this.dragInfo.face.x = x;
1484 | this.dragInfo.face.y = y;
1485 | shapeEl.attr('data-movable', true);
1486 | }
1487 | /**
1488 | * @typedef {PlainObject} module:imageMaps.MovedCoords
1489 | * @property {module:imageMaps.Coords} movedCoords,
1490 | * @property {module:imageMaps.VertexCoords} vertexCoords,
1491 | * @property {module:imageMaps.ShapeElement} grabEl
1492 | */
1493 |
1494 | /**
1495 | * @memberof module:imageMaps.jqueryImageMaps~
1496 | * @this module:imageMaps~ImageMaps
1497 | * @param {Float} x
1498 | * @param {Float} y
1499 | * @returns {module:imageMaps.MovedCoords|void}
1500 | */
1501 |
1502 |
1503 | function getMovedShapeCoords(x, y) {
1504 | var shapeEl = this.shapeEl;
1505 |
1506 | if (shapeEl.attr('data-movable') === 'false') {
1507 | return undefined;
1508 | }
1509 |
1510 | var movedCoords = [];
1511 | var vertexCoords = [];
1512 | var shapeType = this.shapeType;
1513 |
1514 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
1515 | var width = parseInt(shapeEl.attr('width'));
1516 | var height = parseInt(shapeEl.attr('height'));
1517 | var movedBottomRightX = x + width;
1518 | var movedBottomRightY = y + height;
1519 | movedCoords = [x, y, movedBottomRightX, movedBottomRightY];
1520 | vertexCoords = calculateVertexCoords(SHAPE.RECT, movedCoords);
1521 | } else if (shapeType === SHAPE.CIRCLE) {
1522 | movedCoords = [x, y, parseInt(shapeEl.attr('r'))];
1523 | vertexCoords = calculateVertexCoords(SHAPE.CIRCLE, movedCoords);
1524 | } else if (shapeType === SHAPE.ELLIPSE) {
1525 | movedCoords = [x, y, parseInt(shapeEl.attr('rx')), parseInt(shapeEl.attr('ry'))];
1526 | vertexCoords = calculateVertexCoords(SHAPE.ELLIPSE, movedCoords);
1527 | } else if (shapeType === SHAPE.TEXT) {
1528 | movedCoords = [x, y];
1529 | }
1530 |
1531 | return {
1532 | movedCoords: movedCoords,
1533 | vertexCoords: vertexCoords,
1534 | grabEl: shapeEl
1535 | };
1536 | }
1537 | /**
1538 | * @typedef {GenericArray} module:imageMaps.Coords
1539 | * @property {Float} 0
1540 | * @property {Float} 1
1541 | * @property {Float} 2
1542 | * @property {Float} 3
1543 | */
1544 |
1545 | /**
1546 | * @memberof module:imageMaps.jqueryImageMaps~
1547 | * @this module:imageMaps~ImageMaps
1548 | * @returns {module:imageMaps.Coords}
1549 | */
1550 |
1551 |
1552 | function determineShape() {
1553 | var shapeEl = this.shapeEl,
1554 | shapeType = this.shapeType;
1555 | var updatedCoords = [];
1556 |
1557 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
1558 | var x = parseInt(shapeEl.attr('x'));
1559 | var y = parseInt(shapeEl.attr('y'));
1560 | updatedCoords = [x, y, x + parseInt(shapeEl.attr('width')), y + parseInt(shapeEl.attr('height'))];
1561 | } else if (shapeType === SHAPE.CIRCLE) {
1562 | updatedCoords = [parseInt(shapeEl.attr('cx')), parseInt(shapeEl.attr('cy')), parseInt(shapeEl.attr('r'))];
1563 | } else if (shapeType === SHAPE.ELLIPSE) {
1564 | updatedCoords = [parseInt(shapeEl.attr('cx')), parseInt(shapeEl.attr('cy')), parseInt(shapeEl.attr('rx')), parseInt(shapeEl.attr('ry'))];
1565 | } else if (shapeType === SHAPE.TEXT) {
1566 | updatedCoords = [parseInt(shapeEl.attr('x')), parseInt(shapeEl.attr('y'))];
1567 | }
1568 |
1569 | return updatedCoords;
1570 | }
1571 | /**
1572 | * @memberof module:imageMaps.jqueryImageMaps~
1573 | * @this module:imageMaps~ImageMaps
1574 | * @param {external:jQuery} vertexEl
1575 | * @param {Integer} index Not currently in use
1576 | * @returns {void}
1577 | */
1578 |
1579 |
1580 | function declareVertex(vertexEl, index) {
1581 | this.setVertexElement(vertexEl);
1582 | var vertexIndex = 0;
1583 | this.vertexEls.forEach(function (item, idx) {
1584 | if (vertexEl.get(0) === item.get(0)) {
1585 | vertexIndex = idx;
1586 | }
1587 | });
1588 | var coords = this.vertexCoords[vertexIndex];
1589 | this.dragInfo.vertex.x = coords.x;
1590 | this.dragInfo.vertex.y = coords.y;
1591 | vertexEl.attr('data-movable', true);
1592 | }
1593 | /**
1594 | * @memberof module:imageMaps.jqueryImageMaps~
1595 | * @this module:imageMaps~ImageMaps
1596 | * @param {Float} x
1597 | * @param {Float} y
1598 | * @returns {module:imageMaps.MovedVertexCoords|void}
1599 | */
1600 |
1601 |
1602 | function getMovedVertexCoords(x, y) {
1603 | if (this.vertexEl.attr('data-movable') === 'false') {
1604 | return undefined;
1605 | }
1606 |
1607 | var movedCoords = [];
1608 | var vertexCoords = [];
1609 | var shapeType = this.shapeType;
1610 | var direction = this.vertexEl.attr('data-direction');
1611 |
1612 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE) {
1613 | switch (direction) {
1614 | default:
1615 | // eslint-disable-next-line no-console
1616 | console.warn('Unexpected direction', direction);
1617 | break;
1618 | // 좌상
1619 |
1620 | case 'nw':
1621 | movedCoords = getValidCoordsForRect.call(this, [x, y, this.shapeCoords[2], this.shapeCoords[3]], direction);
1622 | break;
1623 | // 좌하
1624 |
1625 | case 'sw':
1626 | movedCoords = getValidCoordsForRect.call(this, [x, this.shapeCoords[1], this.shapeCoords[2], y], direction);
1627 | break;
1628 | // 우상
1629 |
1630 | case 'ne':
1631 | movedCoords = getValidCoordsForRect.call(this, [this.shapeCoords[0], y, x, this.shapeCoords[3]], direction);
1632 | break;
1633 | // 우하
1634 |
1635 | case 'se':
1636 | movedCoords = getValidCoordsForRect.call(this, [this.shapeCoords[0], this.shapeCoords[1], x, y], direction);
1637 | break;
1638 | // 상
1639 |
1640 | case 'n':
1641 | movedCoords = getValidCoordsForRect.call(this, [this.shapeCoords[0], y, this.shapeCoords[2], this.shapeCoords[3]], direction);
1642 | break;
1643 | // 하
1644 |
1645 | case 's':
1646 | movedCoords = getValidCoordsForRect.call(this, [this.shapeCoords[0], this.shapeCoords[1], this.shapeCoords[2], y], direction);
1647 | break;
1648 | // 좌
1649 |
1650 | case 'w':
1651 | movedCoords = getValidCoordsForRect.call(this, [x, this.shapeCoords[1], this.shapeCoords[2], this.shapeCoords[3]], direction);
1652 | break;
1653 | // 우
1654 |
1655 | case 'e':
1656 | movedCoords = getValidCoordsForRect.call(this, [this.shapeCoords[0], this.shapeCoords[1], x, this.shapeCoords[3]], direction);
1657 | break;
1658 | }
1659 | } else if (shapeType === SHAPE.CIRCLE) {
1660 | switch (direction) {
1661 | default:
1662 | // eslint-disable-next-line no-console
1663 | console.warn('Unexpected direction', direction);
1664 | break;
1665 |
1666 | case 'n':
1667 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, this.shapeCoords[1] - y)];
1668 | break;
1669 |
1670 | case 's':
1671 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, y - this.shapeCoords[1])];
1672 | break;
1673 |
1674 | case 'w':
1675 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, this.shapeCoords[0] - x)];
1676 | break;
1677 |
1678 | case 'e':
1679 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, x - this.shapeCoords[0])];
1680 | break;
1681 | }
1682 | } else if (shapeType === SHAPE.ELLIPSE) {
1683 | switch (direction) {
1684 | default:
1685 | // eslint-disable-next-line no-console
1686 | console.warn('Unexpected direction', direction);
1687 | break;
1688 |
1689 | case 'n':
1690 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], this.shapeCoords[2], getValidCoordsForCircle.call(this, this.shapeCoords[1] - y)];
1691 | break;
1692 |
1693 | case 's':
1694 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], this.shapeCoords[2], getValidCoordsForCircle.call(this, y - this.shapeCoords[1])];
1695 | break;
1696 |
1697 | case 'w':
1698 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, this.shapeCoords[0] - x), this.shapeCoords[3]];
1699 | break;
1700 |
1701 | case 'e':
1702 | movedCoords = [this.shapeCoords[0], this.shapeCoords[1], getValidCoordsForCircle.call(this, x - this.shapeCoords[0]), this.shapeCoords[3]];
1703 | break;
1704 | }
1705 | }
1706 |
1707 | vertexCoords = calculateVertexCoords(shapeType, movedCoords);
1708 | return {
1709 | movedCoords: movedCoords,
1710 | vertexCoords: vertexCoords,
1711 | grabEl: this.vertexEl
1712 | };
1713 | }
1714 | /**
1715 | * @typedef {"se"|"sw"|"ne"|"nw"|"w"|"s"|"n"|"e"} module:imageMaps.Direction
1716 | */
1717 |
1718 | /**
1719 | * @memberof module:imageMaps.jqueryImageMaps~
1720 | * @this module:imageMaps~ImageMaps
1721 | * @param {module:imageMaps.RectCoords} coords
1722 | * @param {module:imageMaps.Direction} direction
1723 | * @returns {module:imageMaps.RectCoords}
1724 | */
1725 |
1726 |
1727 | function getValidCoordsForRect(coords, direction) {
1728 | var _coords = _slicedToArray(coords, 4),
1729 | topLeftX = _coords[0],
1730 | topLeftY = _coords[1],
1731 | bottomRightX = _coords[2],
1732 | bottomRightY = _coords[3];
1733 |
1734 | if (bottomRightX - topLeftX <= this.shapeLimitCoords.x) {
1735 | if (direction === 'se' || direction === 'ne' || direction === 'e') {
1736 | bottomRightX = topLeftX + this.shapeLimitCoords.x;
1737 | }
1738 |
1739 | if (direction === 'nw' || direction === 'sw' || direction === 'w') {
1740 | topLeftX = bottomRightX - this.shapeLimitCoords.x;
1741 | }
1742 | }
1743 |
1744 | if (bottomRightY - topLeftY <= this.shapeLimitCoords.y) {
1745 | if (direction === 'se' || direction === 'sw' || direction === 's') {
1746 | bottomRightY = topLeftY + this.shapeLimitCoords.y;
1747 | }
1748 |
1749 | if (direction === 'nw' || direction === 'ne' || direction === 'n') {
1750 | topLeftY = bottomRightY - this.shapeLimitCoords.y;
1751 | }
1752 | }
1753 |
1754 | return [topLeftX, topLeftY, bottomRightX, bottomRightY];
1755 | }
1756 | /**
1757 | * @memberof module:imageMaps.jqueryImageMaps~
1758 | * @this module:imageMaps~ImageMaps
1759 | * @param {Float} coordsDiff
1760 | * @returns {Float}
1761 | */
1762 |
1763 |
1764 | function getValidCoordsForCircle(coordsDiff) {
1765 | var radius;
1766 |
1767 | if (coordsDiff <= this.shapeLimitCoords.radius) {
1768 | radius = this.shapeLimitCoords.radius;
1769 | } else {
1770 | radius = coordsDiff;
1771 | }
1772 |
1773 | return radius;
1774 | }
1775 | /**
1776 | * @memberof module:imageMaps.jqueryImageMaps~
1777 | * @static
1778 | * @param {module:imageMaps.Coords} coords
1779 | * @param {module:imageMaps.ShapeType} shapeType
1780 | * @param {Float} widthRatio
1781 | * @param {Float} heightRatio
1782 | * @returns {module:imageMaps.Coords}
1783 | */
1784 |
1785 |
1786 | function getCoordsByRatio(coords, shapeType, widthRatio, heightRatio) {
1787 | var adjustCoords = [];
1788 |
1789 | if (shapeType === SHAPE.RECT || shapeType === SHAPE.IMAGE || shapeType === SHAPE.ELLIPSE) {
1790 | adjustCoords = [coords[0] * widthRatio, coords[1] * heightRatio, coords[2] * widthRatio, coords[3] * heightRatio];
1791 | } else if (shapeType === SHAPE.CIRCLE) {
1792 | var radiusRatio;
1793 |
1794 | if (widthRatio >= heightRatio) {
1795 | radiusRatio = heightRatio;
1796 | } else {
1797 | radiusRatio = widthRatio;
1798 | }
1799 |
1800 | if (widthRatio === 1) {
1801 | radiusRatio = heightRatio;
1802 | }
1803 |
1804 | if (heightRatio === 1) {
1805 | radiusRatio = widthRatio;
1806 | }
1807 |
1808 | adjustCoords = [coords[0] * widthRatio, coords[1] * heightRatio, coords[2] * radiusRatio];
1809 | } else if (shapeType === SHAPE.TEXT) {
1810 | adjustCoords = [coords[0] * widthRatio, coords[1] * heightRatio, coords[2] * widthRatio];
1811 | }
1812 |
1813 | return adjustCoords;
1814 | }
1815 | /**
1816 | * @typedef {GenericArray} module:imageMaps.RectCoords
1817 | * @property {Float} 0
1818 | * @property {Float} 1
1819 | * @property {Float} 2
1820 | * @property {Float} 3
1821 | */
1822 |
1823 | /**
1824 | * @memberof module:imageMaps.jqueryImageMaps~
1825 | * @static
1826 | * @param {module:imageMaps.ShapeElement} shapeEl
1827 | * @returns {module:imageMaps.RectCoords}
1828 | */
1829 |
1830 |
1831 | function convertTextToRectCoords(shapeEl) {
1832 | var bottomLeftX = parseFloat(shapeEl.attr('x'));
1833 | var bottomLeftY = parseFloat(shapeEl.attr('y'));
1834 | var shapeSize = shapeEl.get(0).getBBox();
1835 | var width = shapeSize.width;
1836 | var height = parseFloat(shapeEl.attr('font-size')) * FONT_SIZE_RATIO / 2;
1837 | return [bottomLeftX, bottomLeftY - height, bottomLeftX + width, bottomLeftY];
1838 | }
1839 | /**
1840 | * @memberof module:imageMaps.jqueryImageMaps~
1841 | * @static
1842 | * @param {string} [coords]
1843 | * @returns {?(Float[])}
1844 | */
1845 |
1846 |
1847 | function convertStringToNumber(coords) {
1848 | if (!coords) {
1849 | return null;
1850 | }
1851 |
1852 | return _toConsumableArray(coords).map(function (ch) {
1853 | return parseFloat(ch);
1854 | });
1855 | } // UTIL FUNCTIONS
1856 |
1857 | /**
1858 | * GUID: img의 usemap 속성, map의 name 속성을 unique id로 생성.
1859 | * @memberof module:imageMaps.jqueryImageMaps~
1860 | * @static
1861 | * @see https://stackoverflow.com/questions/105034/create-guid-uuid-in-javascript
1862 | * @returns {string}
1863 | */
1864 |
1865 |
1866 | function guid() {
1867 | /**
1868 | * @memberof module:imageMaps.jqueryImageMaps~guid.
1869 | * @static
1870 | * @returns {string}
1871 | */
1872 | function s4() {
1873 | return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);
1874 | }
1875 |
1876 | return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();
1877 | }
1878 | /**
1879 | * @typedef {PlainObject} module:imageMaps.Dimensions
1880 | * @property {Float} width
1881 | * @property {Float} height
1882 | */
1883 |
1884 | /**
1885 | * @memberof module:imageMaps.jqueryImageMaps~
1886 | * @static
1887 | * @param {HTMLImageElement|string} imageElOrUrl
1888 | * @todo If this is to handle an image element, other contexts which use
1889 | * the passed in URL should also
1890 | * @returns {module:imageMaps.Dimensions}
1891 | */
1892 |
1893 |
1894 | function getNaturalImageSize(imageElOrUrl) {
1895 | var imageObj = new Image();
1896 |
1897 | if ('naturalWidth' in imageObj && typeof imageElOrUrl !== 'string') {
1898 | return {
1899 | width: imageElOrUrl.naturalWidth,
1900 | height: imageElOrUrl.naturalHeight
1901 | };
1902 | }
1903 |
1904 | if (typeof imageElOrUrl === 'string') {
1905 | imageElOrUrl = {
1906 | src: imageElOrUrl
1907 | };
1908 | }
1909 |
1910 | imageObj.src = imageElOrUrl.src;
1911 | return {
1912 | width: imageObj.width,
1913 | height: imageObj.height
1914 | };
1915 | }
1916 |
1917 | $.fn.extend({
1918 | /**
1919 | * @function external:"jQuery.fn".createMaps
1920 | * @param {?(module:imageMaps.Coords)} coords
1921 | * @param {Url} linkUrl
1922 | * @returns {external:jQuery}
1923 | */
1924 | createMaps: function createMaps(coords, linkUrl) {
1925 | this.data('image_maps_inst').createMaps(coords, linkUrl);
1926 | return this;
1927 | },
1928 |
1929 | /**
1930 | *
1931 | * @param {external:jQuery} targetEl
1932 | * @returns {external:jQuery}
1933 | */
1934 | copyImageMapsTo: function copyImageMapsTo(targetEl) {
1935 | $.imageMaps.copyImageMaps({
1936 | shapes: this.getAllShapes(),
1937 | width: this.width(),
1938 | height: this.height()
1939 | }, targetEl);
1940 | return this;
1941 | },
1942 |
1943 | /**
1944 | * @function external:"jQuery.fn".addShape
1945 | * @param {?(module:imageMaps.Coords)} coords
1946 | * @param {Url} linkUrl
1947 | * @param {module:imageMaps.ShapeType} shapeType
1948 | * @returns {external:jQuery}
1949 | */
1950 | addShape: function addShape(coords, linkUrl, shapeType) {
1951 | this.data('image_maps_inst').addShape(coords, linkUrl, shapeType);
1952 | return this;
1953 | },
1954 |
1955 | /**
1956 | * @function external:"jQuery.fn".removeShape
1957 | * @param {Integer} [index]
1958 | * @returns {external:jQuery}
1959 | */
1960 | removeShape: function removeShape(index) {
1961 | this.data('image_maps_inst').removeShape(index);
1962 | return this;
1963 | },
1964 |
1965 | /**
1966 | * @function external:"jQuery.fn".removeAllShapes
1967 | * @returns {external:jQuery}
1968 | */
1969 | removeAllShapes: function removeAllShapes() {
1970 | this.data('image_maps_inst').removeAllShapes();
1971 | },
1972 |
1973 | /**
1974 | * @function external:"jQuery.fn".destroy
1975 | * @returns {external:jQuery}
1976 | */
1977 | destroy: function destroy() {
1978 | var imageMapsObj = this.data('image_maps_inst');
1979 |
1980 | if (!imageMapsObj) {
1981 | return;
1982 | }
1983 |
1984 | imageMapsObj.removeImageMaps();
1985 | this.data('image_maps_inst', null);
1986 | },
1987 |
1988 | /**
1989 | * @function external:"jQuery.fn".setShapeStyle
1990 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
1991 | * @returns {external:jQuery}
1992 | */
1993 | setShapeStyle: function setShapeStyle(styleOptions) {
1994 | this.data('image_maps_inst').setShapeStyle(styleOptions);
1995 | return this;
1996 | },
1997 |
1998 | /**
1999 | * @function external:"jQuery.fn".setUrl
2000 | * @param {Url} linkUrl
2001 | * @param {Integer} index
2002 | * @returns {external:jQuery}
2003 | */
2004 | setUrl: function setUrl(linkUrl, index) {
2005 | this.data('image_maps_inst').setUrl(linkUrl, index);
2006 | return this;
2007 | },
2008 |
2009 | /**
2010 | * @function external:"jQuery.fn".setTextShape
2011 | * @param {string} text
2012 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
2013 | * @returns {external:jQuery}
2014 | */
2015 | setTextShape: function setTextShape(text, styleOptions) {
2016 | this.data('image_maps_inst').setTextShape(text, styleOptions);
2017 | return this;
2018 | },
2019 |
2020 | /**
2021 | * @function external:"jQuery.fn".setImageShape
2022 | * @param {Url} imageUrl
2023 | * @param {module:imageMaps.ShapeStyles} [styleOptions]
2024 | * @returns {external:jQuery}
2025 | */
2026 | setImageShape: function setImageShape(imageUrl, styleOptions) {
2027 | this.data('image_maps_inst').setImageShape(imageUrl, styleOptions);
2028 | return this;
2029 | },
2030 |
2031 | /**
2032 | * @function external:"jQuery.fn".enableClick
2033 | * @returns {void}
2034 | */
2035 | enableClick: function enableClick() {
2036 | this.data('image_maps_inst').enableClick();
2037 | },
2038 |
2039 | /**
2040 | * @function external:"jQuery.fn".disableClick
2041 | * @returns {void}
2042 | */
2043 | disableClick: function disableClick() {
2044 | this.data('image_maps_inst').disableClick();
2045 | },
2046 |
2047 | /**
2048 | * @function external:"jQuery.fn".getAllShapes
2049 | * @returns {module:imageMaps.AllShapeInfo}
2050 | */
2051 | getAllShapes: function getAllShapes() {
2052 | return this.data('image_maps_inst').getAllShapesInfo();
2053 | },
2054 |
2055 | /**
2056 | * @function external:"jQuery.fn".getCoordsByRatio
2057 | * @param {module:imageMaps.Coords} coords
2058 | * @param {module:imageMaps.ShapeType} shapeType
2059 | * @param {Float} widthRatio
2060 | * @param {Float} heightRatio
2061 | * @returns {module:imageMaps.Coords}
2062 | */
2063 | getCoordsByRatio: function getCoordsByRatio(coords, shapeType, widthRatio, heightRatio) {
2064 | return ImageMaps.getCoordsByRatio(coords, shapeType, widthRatio, heightRatio);
2065 | },
2066 |
2067 | /**
2068 | * @function external:"jQuery.fn".zoom
2069 | * @param {Float[]} percentages
2070 | * @returns {void}
2071 | */
2072 | zoom: function zoom(percentages) {
2073 | this.data('image_maps_inst').zoom(percentages);
2074 | }
2075 | });
2076 | $.imageMaps = {
2077 | /**
2078 | * @typedef {PlainObject} module:imageMaps.SourceInfo
2079 | * @property {module:imageMaps.AllShapeInfo} shapes
2080 | * @property {Float} width
2081 | * @property {Float} height
2082 | */
2083 |
2084 | /**
2085 | * @param {module:imageMaps.SourceInfo} sourceInfo
2086 | * @param {external:jQuery} targetEl
2087 | * @returns {void}
2088 | */
2089 | copyImageMaps: function copyImageMaps(_ref3, targetEl) {
2090 | var shapes = _ref3.shapes,
2091 | width = _ref3.width,
2092 | height = _ref3.height;
2093 | targetEl.removeAllShapes();
2094 | $.each(shapes, function (index, item) {
2095 | targetEl.setShapeStyle(item.style);
2096 |
2097 | if (item.href) {
2098 | targetEl.setImageShape(item.href);
2099 | }
2100 |
2101 | if (item.text) {
2102 | targetEl.setTextShape(item.text);
2103 | }
2104 |
2105 | var widthRatio = width;
2106 | var heightRatio = height;
2107 | var newCoords = getCoordsByRatio(item.coords, item.type, targetEl.width() / widthRatio, targetEl.height() / heightRatio);
2108 | targetEl.addShape(newCoords, item.url, item.type);
2109 | });
2110 | }
2111 | };
2112 | /**
2113 | * @function external:"jQuery.fn".imageMaps
2114 | * @this external:jQuery
2115 | * @param {module:imageMaps.ImageMapOptions} [options]
2116 | * @throws {Error}
2117 | * @returns {module:imageMaps.ImageMaps|void}
2118 | */
2119 |
2120 | $.fn.imageMaps = function (options) {
2121 | if (this.length === 1) {
2122 | if (!this.data('image_maps_inst')) {
2123 | var imageMapsInst = new ImageMaps(this, options);
2124 | this.data('image_maps_inst', imageMapsInst);
2125 | return imageMapsInst;
2126 | }
2127 |
2128 | return this.data('image_maps_inst');
2129 | }
2130 |
2131 | if (this.length > 1) {
2132 | throw new Error('imageMaps instance has already been created.');
2133 | }
2134 |
2135 | return undefined;
2136 | };
2137 |
2138 | return $;
2139 | }
2140 |
2141 | export default jqueryImageMaps;
2142 |
--------------------------------------------------------------------------------
/dist/index.esm.min.js:
--------------------------------------------------------------------------------
1 | function t(t,e){for(var a=0;a0&&w.call(e,i,r)})}).call(this,t)}},{key:"enableClick",value:function(){this.attachEvents(this.svgEl.find("."+s),[{type:"touchstart",handler:m},{type:"click touchend",handler:x}])}},{key:"disableClick",value:function(){this.detachEvents(this.svgEl.find("."+s),[{type:"touchstart",handler:m},{type:"click touchend",handler:x}])}},{key:"setShapeCoords",value:function(t){this.shapeCoords=t}},{key:"setVertexCoords",value:function(t){this.vertexCoords=t}},{key:"setShapeElement",value:function(t){this.shapeEl=t}},{key:"setVertexElement",value:function(t){this.vertexEl=t}},{key:"setVertexElements",value:function(t){this.vertexEls=t}},{key:"attachEvents",value:function(t,e){var a=this;t=d(t),e.forEach(function(e){var s=e.type,i=e.handler;t.on(s+"."+r,d.proxy(i,a))})}},{key:"detachEvents",value:function(t,e){var a=this;t=d(t),e.forEach(function(e){var s=e.type,i=e.handler,n=s||"",h=i?d.proxy(i,a):"";h?t.off(n+"."+r,h):t.off(n+"."+r)})}}])&&t(a.prototype,i),n&&t(a,n),e}();function u(t,e){var i=function(){function t(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}();if(this.container.attr("usemap")){var r=this.container.attr("usemap").replace("#","");this.mapEl=d("body").find("map[name="+r+"]")}else this.mapEl=d(" ").insertAfter(this.container),this.container.attr("usemap","#"+i);this.containerWidth=this.container.width(),this.containerHeight=this.container.height();var h,f,u=this.containerWidth,E=this.containerHeight,I=u/2,S=E/2,w=this.shapeType,k=[],L=!1;if(t=function(t){return t?a(t).map(function(t){return parseFloat(t)}):null}(t),Array.isArray(t))w===n.RECT||w===n.IMAGE?k=d.extend([],o.rect,t):w===n.CIRCLE?k=d.extend([],o.circle,t):w===n.ELLIPSE?k=d.extend([],o.ellipse,t):w===n.TEXT&&(t[0]||(t[0]=I,L=!0),t[1]||(t[1]=S,L=!0),t[2]||(t[2]=20),k=d.extend([],o.text,t));else{var b=.1*u,M=.1*E,A=b>=M?M:b;if(w===n.RECT)k=d.extend([],o.rect,[I-b,S-M,I+b,S+M]);else if(w===n.CIRCLE)k=d.extend([],o.circle,[I,S,A]);else if(w===n.ELLIPSE)k=d.extend([],o.ellipse,[I,S,A,A]);else if(w===n.IMAGE){var _=(h=this.shapeImageUrl,"naturalWidth"in(f=new Image)&&"string"!=typeof h?{width:h.naturalWidth,height:h.naturalHeight}:("string"==typeof h&&(h={src:h}),f.src=h.src,{width:f.width,height:f.height}));k=[I-(b=_.width/2),S-(M=_.height/2),I+b,S+M]}}var R=this.mapEl.find("."+s).length,P=w,X={};w!==n.TEXT&&w!==n.IMAGE||(P=n.RECT,X=w===n.TEXT?{text:this.shapeText}:{href:this.shapeImageUrl}),function(t,e,s,i){var r=this.container.width(),h=this.container.height();if(void 0!==document.createElementNS){var o=this.mapEl.find("svg").get(0),p=d(o),f=this.shapeType;o||(o=document.createElementNS(l,"svg"),p=d(o),this.svgEl=p,this.isEditMode?this.attachEvents(p,[{type:"mousedown",handler:C}]):this.attachEvents(this.mapEl,[{type:"touchstart",handler:m},{type:"click touchend",handler:x}]),this.attachEvents(window,[{type:"resize",handler:T}])),o.setAttribute("width",r),o.setAttribute("height",h);var u=this.container.position();p.attr({xmlns:l,"xmlns:xlink":c,version:"1.1","data-Id":e}).css({position:"absolute",zIndex:1e3,overflow:"hidden",top:u.top,left:u.left});var E=function(t,e,s,i){t===n.POLY&&(t=n.POLYLINE);var r=d(document.createElementNS(l,t)),h=d(document.createElementNS(l,"g"));y.call(this,e,r);var o="default";if(this.isEditMode?o="move":""!==s&&(o="pointer"),this.setShapeStyle({cursor:o}),r.css(this.shapeStyle),t===n.TEXT&&r.css({"fill-opacity":"","stroke-opacity":""}),r.attr("data-index",i),h.append(r),this.setShapeElement(r),this.isEditMode&&"text"!==t){var p=function(t,e,a){var s=g(t,e),i=s.map(function(){var t=d(document.createElementNS(l,"rect"));return t.attr("data-index",a).css({fill:"#ffffff",stroke:"#000000","stroke-width":2}),t});return v(s,i),i}(t,e,i);h.append.apply(h,a(p)),this.setVertexElements(p)}return h}.call(this,f,t,s,i);p.append(E),this.mapEl.append(p)}}.call(this,k,i,e,R),this.setShapeCoords(k),this.updateShapeInfo(R,{coords:k,type:w,url:e,style:this.shapeStyle},X),L&&this.isEditMode&&w===n.TEXT&&function(){var t=this.shapeEl,e=t.get(0).getBBox().width/2,a=parseFloat(t.attr("font-size"))*p/2,s=parseInt(t.attr("x")),i=parseInt(t.attr("y")),r=s-e,n=i+a;this.updateShapeInfo(t.data("index"),{coords:[r,n,t.attr("font-size")]}),t.attr({x:r,y:n})}.call(this),w===n.ELLIPSE&&(P=n.CIRCLE,k=[k[0],k[1],o.ellipse[2],o.ellipse[2]]),function(t,e,a,s){d(" ").appendTo(this.mapEl)}.call(this,P,k,e,R)}function y(t,e,a){e=e||this.shapeEl;var i=a?a.type:this.shapeType;i===n.RECT||i===n.IMAGE?(e.attr({x:t[0],y:t[1],class:s}),t[2]&&e.attr("width",t[2]-t[0]),t[3]&&e.attr("height",t[3]-t[1]),i===n.IMAGE&&(e.get(0).setAttributeNS(c,"href",a?a.href:this.shapeImageUrl),e.get(0).setAttribute("preserveAspectRatio","none"))):i===n.CIRCLE?(e.attr({cx:t[0],cy:t[1],class:s}),t[2]&&e.attr("r",t[2])):i===n.ELLIPSE?(e.attr({cx:t[0],cy:t[1],class:s}),t[2]&&e.attr("rx",t[2]),t[3]&&e.attr("ry",t[3])):i===n.TEXT&&(e.attr({x:t[0],y:t[1],"font-size":t[2],class:s}),e.text(a&&a.text||this.shapeText))}function v(t,e,a){t.forEach(function(t,a){d(e[a]).attr({x:t.x-3,y:t.y-3,width:7,height:7,"data-direction":t.type,class:i}).css("cursor",t.type+"-resize")})}function g(t,e){var a=[];return t===n.RECT||t===n.IMAGE?a=[{x:e[0],y:e[1],type:"nw"},{x:e[0],y:e[3],type:"sw"},{x:e[2],y:e[1],type:"ne"},{x:e[2],y:e[3],type:"se"},{x:(e[2]-e[0])/2+e[0],y:e[1],type:"n"},{x:(e[2]-e[0])/2+e[0],y:e[3],type:"s"},{x:e[0],y:(e[3]-e[1])/2+e[1],type:"w"},{x:e[2],y:(e[3]-e[1])/2+e[1],type:"e"}]:t===n.CIRCLE?a=[{x:e[0],y:e[1]-e[2],type:"n"},{x:e[0],y:e[1]+e[2],type:"s"},{x:e[0]-e[2],y:e[1],type:"w"},{x:e[0]+e[2],y:e[1],type:"e"}]:t===n.ELLIPSE&&(a=[{x:e[0],y:e[1]-e[3],type:"n"},{x:e[0],y:e[1]+e[3],type:"s"},{x:e[0]-e[2],y:e[1],type:"w"},{x:e[0]+e[2],y:e[1],type:"e"}]),a}function E(t,e,a){var i=this.svgEl.find("."+s+'[data-index="'+e.data("index")+'"]');(a=a||this.shapeType)===n.TEXT?t=function(t){var e=parseFloat(t.attr("x")),a=parseFloat(t.attr("y")),s=t.get(0).getBBox().width,i=parseFloat(t.attr("font-size"))*p/2;return[e,a-i,e+s,a]}(i):a===n.ELLIPSE&&(t=[t[0],t[1],o.ellipse[2]]),e.attr("coords",t.join(","))}function m(t){var e=t.originalEvent.touches[0];this.touchStartCoords.x=e.pageX,this.touchStartCoords.y=e.pageY}function x(t){var e=d(t.currentTarget);if("area"!==t.currentTarget.tagName.toLowerCase()){if(t.preventDefault(),this.dragInfo.face.x&&this.dragInfo.face.x!==t.pageX||this.dragInfo.face.y&&this.dragInfo.face.y!==t.pageY||"svg"===t.target.tagName.toLowerCase()||"touchend"===t.type&&t.originalEvent.changedTouches[0].pageX!==this.touchStartCoords.x&&t.originalEvent.changedTouches[0].pageY!==this.touchStartCoords.y)return;var a=d(t.target).attr("data-index");"#"!==(e=this.mapEl.find('area[data-index="'+a+'"]')).attr("href")&&window.open(e.attr("href"))}this.options.onClick.call(this,t,e.attr("href"))}function C(t){if(t.preventDefault(),"svg"!==t.target.tagName.toLowerCase()){var e=d(t.target),a=e.attr("data-index"),r=this.getShapeInfo(a),h=e.parent().find(":first-child"),o=[],p=h.get(0).tagName.toLowerCase();if(p===n.RECT||p===n.IMAGE){var l=parseInt(h.attr("x")),c=parseInt(h.attr("y"));o=[l,c,l+parseInt(h.attr("width")),c+parseInt(h.attr("height"))],p===n.IMAGE&&this.setImageShape(h.attr("href"))}else p===n.CIRCLE?o=[parseInt(h.attr("cx")),parseInt(h.attr("cy")),parseInt(h.attr("r"))]:p===n.ELLIPSE?o=[parseInt(h.attr("cx")),parseInt(h.attr("cy")),parseInt(h.attr("rx")),parseInt(h.attr("ry"))]:p===n.TEXT?(o=[parseFloat(h.attr("x")),parseFloat(h.attr("y")),parseFloat(h.attr("font-size"))],this.shapeText=h.text()):p===n.POLYGON&&(p=n.POLY);if(this.setShapeType(p),this.setShapeElement(h),this.setShapeCoords(o),p!==n.TEXT){h.attr("data-fill",h.css("fill")),h.css("fill","#ffffff"),this.setVertexCoords(g(p,o));var f=[];this.mapEl.find("."+i+'[data-index="'+a+'"]').each(function(){f.push(d(this))}),this.setVertexElements(f)}e.is("."+s)?(this.grabType="face",function(t,e,a){this.dragInfo.face.x=e,this.dragInfo.face.y=a,t.attr("data-movable",!0)}.call(this,e,t.pageX,t.pageY)):e.is("."+i)&&(this.grabType="vertex",function(t,e){this.setVertexElement(t);var a=0;this.vertexEls.forEach(function(e,s){t.get(0)===e.get(0)&&(a=s)});var s=this.vertexCoords[a];this.dragInfo.vertex.x=s.x,this.dragInfo.vertex.y=s.y,t.attr("data-movable",!0)}.call(this,e,a)),this.attachEvents(this.mapEl.parent(),[{type:"mouseup",handler:I},{type:"mousemove",handler:S}]),this.options.onSelect.call(this,t,r),this.options.onMouseDown.call(this,t,p,o)}}function I(t){var e=d(t.target),a=this.shapeEl;a.css("fill",a.attr("data-fill")),e.attr("data-movable",!1);var s=function(){var t=this.shapeEl,e=this.shapeType,a=[];if(e===n.RECT||e===n.IMAGE){var s=parseInt(t.attr("x")),i=parseInt(t.attr("y"));a=[s,i,s+parseInt(t.attr("width")),i+parseInt(t.attr("height"))]}else e===n.CIRCLE?a=[parseInt(t.attr("cx")),parseInt(t.attr("cy")),parseInt(t.attr("r"))]:e===n.ELLIPSE?a=[parseInt(t.attr("cx")),parseInt(t.attr("cy")),parseInt(t.attr("rx")),parseInt(t.attr("ry"))]:e===n.TEXT&&(a=[parseInt(t.attr("x")),parseInt(t.attr("y"))]);return a}.call(this);this.setShapeCoords(s),this.updateShapeInfo(a.data("index"),{coords:s}),this.detachEvents(this.mapEl.parent(),[{type:"mouseup",handler:I},{type:"mousemove",handler:S}]),this.options.onMouseUp.call(this,t,this.shapeType,s)}function S(t){var a=d(t.target),r=e(this.shapeCoords,2),h=r[0],o=r[1],p=this.grabType,l=this.shapeType,c={};if("face"===p||"vertex"===p){if("face"===p){var f=h+t.pageX,u=o+t.pageY;c=function(t,e){var a=this.shapeEl;if("false"!==a.attr("data-movable")){var s=[],i=[],r=this.shapeType;if(r===n.RECT||r===n.IMAGE){var h=parseInt(a.attr("width")),o=parseInt(a.attr("height")),p=t+h,l=e+o;s=[t,e,p,l],i=g(n.RECT,s)}else r===n.CIRCLE?(s=[t,e,parseInt(a.attr("r"))],i=g(n.CIRCLE,s)):r===n.ELLIPSE?(s=[t,e,parseInt(a.attr("rx")),parseInt(a.attr("ry"))],i=g(n.ELLIPSE,s)):r===n.TEXT&&(s=[t,e]);return{movedCoords:s,vertexCoords:i,grabEl:a}}}.call(this,f-this.dragInfo.face.x,u-this.dragInfo.face.y)}else"vertex"===p&&(c=function(t,e){if("false"!==this.vertexEl.attr("data-movable")){var a=[],s=[],i=this.shapeType,r=this.vertexEl.attr("data-direction");if(i===n.RECT||i===n.IMAGE)switch(r){default:console.warn("Unexpected direction",r);break;case"nw":a=k.call(this,[t,e,this.shapeCoords[2],this.shapeCoords[3]],r);break;case"sw":a=k.call(this,[t,this.shapeCoords[1],this.shapeCoords[2],e],r);break;case"ne":a=k.call(this,[this.shapeCoords[0],e,t,this.shapeCoords[3]],r);break;case"se":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],t,e],r);break;case"n":a=k.call(this,[this.shapeCoords[0],e,this.shapeCoords[2],this.shapeCoords[3]],r);break;case"s":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],e],r);break;case"w":a=k.call(this,[t,this.shapeCoords[1],this.shapeCoords[2],this.shapeCoords[3]],r);break;case"e":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],t,this.shapeCoords[3]],r)}else if(i===n.CIRCLE)switch(r){default:console.warn("Unexpected direction",r);break;case"n":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,this.shapeCoords[1]-e)];break;case"s":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,e-this.shapeCoords[1])];break;case"w":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,this.shapeCoords[0]-t)];break;case"e":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,t-this.shapeCoords[0])]}else if(i===n.ELLIPSE)switch(r){default:console.warn("Unexpected direction",r);break;case"n":a=[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],L.call(this,this.shapeCoords[1]-e)];break;case"s":a=[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],L.call(this,e-this.shapeCoords[1])];break;case"w":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,this.shapeCoords[0]-t),this.shapeCoords[3]];break;case"e":a=[this.shapeCoords[0],this.shapeCoords[1],L.call(this,t-this.shapeCoords[0]),this.shapeCoords[3]]}return s=g(i,a),{movedCoords:a,vertexCoords:s,grabEl:this.vertexEl}}}.call(this,t.pageX-this.svgEl.offset().left,t.pageY-this.svgEl.offset().top));if(!c)return;l!==n.TEXT&&(this.setVertexCoords(c.vertexCoords),v(c.vertexCoords,this.vertexEls,this.shapeType));var m=parseInt(c.grabEl.attr("data-index"));y.call(this,c.movedCoords,this.svgEl.find("."+s+'[data-index="'+m+'"]')),E.call(this,c.movedCoords,this.mapEl.find('area[data-index="'+m+'"]')),(a.is("."+s)||a.is("."+i))&&(Math.abs(this.dragInfo.face.x-t.pageX)<=1||Math.abs(this.dragInfo.face.y-t.pageY)<=1)&&this.svgEl.append(a.parent()),this.options.onMouseMove.call(this,t,l,c.movedCoords)}}function T(t){var e=this.container.width(),a=this.container.height();this.containerWidth===e&&this.containerHeight===a||w.call(this,e,a)}function w(t,e){var a=this,r=this.allShapeInfo,n=t/this.containerWidth,h=e/this.containerHeight,o=this.container.position();this.svgEl.get(0).setAttribute("width",t),this.svgEl.get(0).setAttribute("height",e),this.svgEl.css({top:o.top,left:o.left}),d.each(r,function(t,e){e.coords=b(e.coords,e.type,n,h),v(g(e.type,e.coords),a.svgEl.find("."+i+'[data-index="'+e.index+'"]'),e.type),y.call(a,e.coords,a.svgEl.find("."+s+'[data-index="'+e.index+'"]'),e),E.call(a,e.coords,a.mapEl.find('area[data-index="'+e.index+'"]'),e.type)}),this.containerWidth=t,this.containerHeight=e}function k(t,a){var s=e(t,4),i=s[0],r=s[1],n=s[2],h=s[3];return n-i<=this.shapeLimitCoords.x&&("se"!==a&&"ne"!==a&&"e"!==a||(n=i+this.shapeLimitCoords.x),"nw"!==a&&"sw"!==a&&"w"!==a||(i=n-this.shapeLimitCoords.x)),h-r<=this.shapeLimitCoords.y&&("se"!==a&&"sw"!==a&&"s"!==a||(h=r+this.shapeLimitCoords.y),"nw"!==a&&"ne"!==a&&"n"!==a||(r=h-this.shapeLimitCoords.y)),[i,r,n,h]}function L(t){return t<=this.shapeLimitCoords.radius?this.shapeLimitCoords.radius:t}function b(t,e,a,s){var i=[];if(e===n.RECT||e===n.IMAGE||e===n.ELLIPSE)i=[t[0]*a,t[1]*s,t[2]*a,t[3]*s];else if(e===n.CIRCLE){var r;r=a>=s?s:a,1===a&&(r=s),1===s&&(r=a),i=[t[0]*a,t[1]*s,t[2]*r]}else e===n.TEXT&&(i=[t[0]*a,t[1]*s,t[2]*a]);return i}return f.getCoordsByRatio=b,d.fn.extend({createMaps:function(t,e){return this.data("image_maps_inst").createMaps(t,e),this},copyImageMapsTo:function(t){return d.imageMaps.copyImageMaps({shapes:this.getAllShapes(),width:this.width(),height:this.height()},t),this},addShape:function(t,e,a){return this.data("image_maps_inst").addShape(t,e,a),this},removeShape:function(t){return this.data("image_maps_inst").removeShape(t),this},removeAllShapes:function(){this.data("image_maps_inst").removeAllShapes()},destroy:function(){var t=this.data("image_maps_inst");t&&(t.removeImageMaps(),this.data("image_maps_inst",null))},setShapeStyle:function(t){return this.data("image_maps_inst").setShapeStyle(t),this},setUrl:function(t,e){return this.data("image_maps_inst").setUrl(t,e),this},setTextShape:function(t,e){return this.data("image_maps_inst").setTextShape(t,e),this},setImageShape:function(t,e){return this.data("image_maps_inst").setImageShape(t,e),this},enableClick:function(){this.data("image_maps_inst").enableClick()},disableClick:function(){this.data("image_maps_inst").disableClick()},getAllShapes:function(){return this.data("image_maps_inst").getAllShapesInfo()},getCoordsByRatio:function(t,e,a,s){return f.getCoordsByRatio(t,e,a,s)},zoom:function(t){this.data("image_maps_inst").zoom(t)}}),d.imageMaps={copyImageMaps:function(t,e){var a=t.shapes,s=t.width,i=t.height;e.removeAllShapes(),d.each(a,function(t,a){e.setShapeStyle(a.style),a.href&&e.setImageShape(a.href),a.text&&e.setTextShape(a.text);var r=s,n=i,h=b(a.coords,a.type,e.width()/r,e.height()/n);e.addShape(h,a.url,a.type)})}},d.fn.imageMaps=function(t){if(1===this.length){if(!this.data("image_maps_inst")){var e=new f(this,t);return this.data("image_maps_inst",e),e}return this.data("image_maps_inst")}if(this.length>1)throw new Error("imageMaps instance has already been created.")},d}
2 | //# sourceMappingURL=index.esm.min.js.map
3 |
--------------------------------------------------------------------------------
/dist/index.umd.min.js:
--------------------------------------------------------------------------------
1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).jqueryImageMaps=e()}(this,function(){"use strict";function t(t,e){for(var a=0;a0&&w.call(e,i,r)})}).call(this,t)}},{key:"enableClick",value:function(){this.attachEvents(this.svgEl.find("."+s),[{type:"touchstart",handler:m},{type:"click touchend",handler:x}])}},{key:"disableClick",value:function(){this.detachEvents(this.svgEl.find("."+s),[{type:"touchstart",handler:m},{type:"click touchend",handler:x}])}},{key:"setShapeCoords",value:function(t){this.shapeCoords=t}},{key:"setVertexCoords",value:function(t){this.vertexCoords=t}},{key:"setShapeElement",value:function(t){this.shapeEl=t}},{key:"setVertexElement",value:function(t){this.vertexEl=t}},{key:"setVertexElements",value:function(t){this.vertexEls=t}},{key:"attachEvents",value:function(t,e){var a=this;t=d(t),e.forEach(function(e){var s=e.type,i=e.handler;t.on(s+"."+r,d.proxy(i,a))})}},{key:"detachEvents",value:function(t,e){var a=this;t=d(t),e.forEach(function(e){var s=e.type,i=e.handler,n=s||"",h=i?d.proxy(i,a):"";h?t.off(n+"."+r,h):t.off(n+"."+r)})}}])&&t(a.prototype,i),n&&t(a,n),e}();function u(t,e){var i=function(){function t(){return Math.floor(65536*(1+Math.random())).toString(16).substring(1)}return t()+t()+"-"+t()+"-"+t()+"-"+t()+"-"+t()+t()+t()}();if(this.container.attr("usemap")){var r=this.container.attr("usemap").replace("#","");this.mapEl=d("body").find("map[name="+r+"]")}else this.mapEl=d(" ").insertAfter(this.container),this.container.attr("usemap","#"+i);this.containerWidth=this.container.width(),this.containerHeight=this.container.height();var h,f,u=this.containerWidth,E=this.containerHeight,I=u/2,S=E/2,w=this.shapeType,k=[],b=!1;if(t=function(t){return t?a(t).map(function(t){return parseFloat(t)}):null}(t),Array.isArray(t))w===n.RECT||w===n.IMAGE?k=d.extend([],o.rect,t):w===n.CIRCLE?k=d.extend([],o.circle,t):w===n.ELLIPSE?k=d.extend([],o.ellipse,t):w===n.TEXT&&(t[0]||(t[0]=I,b=!0),t[1]||(t[1]=S,b=!0),t[2]||(t[2]=20),k=d.extend([],o.text,t));else{var L=.1*u,M=.1*E,A=L>=M?M:L;if(w===n.RECT)k=d.extend([],o.rect,[I-L,S-M,I+L,S+M]);else if(w===n.CIRCLE)k=d.extend([],o.circle,[I,S,A]);else if(w===n.ELLIPSE)k=d.extend([],o.ellipse,[I,S,A,A]);else if(w===n.IMAGE){var _=(h=this.shapeImageUrl,"naturalWidth"in(f=new Image)&&"string"!=typeof h?{width:h.naturalWidth,height:h.naturalHeight}:("string"==typeof h&&(h={src:h}),f.src=h.src,{width:f.width,height:f.height}));k=[I-(L=_.width/2),S-(M=_.height/2),I+L,S+M]}}var R=this.mapEl.find("."+s).length,P=w,X={};w!==n.TEXT&&w!==n.IMAGE||(P=n.RECT,X=w===n.TEXT?{text:this.shapeText}:{href:this.shapeImageUrl}),function(t,e,s,i){var r=this.container.width(),h=this.container.height();if(void 0!==document.createElementNS){var o=this.mapEl.find("svg").get(0),p=d(o),f=this.shapeType;o||(o=document.createElementNS(l,"svg"),p=d(o),this.svgEl=p,this.isEditMode?this.attachEvents(p,[{type:"mousedown",handler:C}]):this.attachEvents(this.mapEl,[{type:"touchstart",handler:m},{type:"click touchend",handler:x}]),this.attachEvents(window,[{type:"resize",handler:T}])),o.setAttribute("width",r),o.setAttribute("height",h);var u=this.container.position();p.attr({xmlns:l,"xmlns:xlink":c,version:"1.1","data-Id":e}).css({position:"absolute",zIndex:1e3,overflow:"hidden",top:u.top,left:u.left});var E=function(t,e,s,i){t===n.POLY&&(t=n.POLYLINE);var r=d(document.createElementNS(l,t)),h=d(document.createElementNS(l,"g"));y.call(this,e,r);var o="default";if(this.isEditMode?o="move":""!==s&&(o="pointer"),this.setShapeStyle({cursor:o}),r.css(this.shapeStyle),t===n.TEXT&&r.css({"fill-opacity":"","stroke-opacity":""}),r.attr("data-index",i),h.append(r),this.setShapeElement(r),this.isEditMode&&"text"!==t){var p=function(t,e,a){var s=g(t,e),i=s.map(function(){var t=d(document.createElementNS(l,"rect"));return t.attr("data-index",a).css({fill:"#ffffff",stroke:"#000000","stroke-width":2}),t});return v(s,i),i}(t,e,i);h.append.apply(h,a(p)),this.setVertexElements(p)}return h}.call(this,f,t,s,i);p.append(E),this.mapEl.append(p)}}.call(this,k,i,e,R),this.setShapeCoords(k),this.updateShapeInfo(R,{coords:k,type:w,url:e,style:this.shapeStyle},X),b&&this.isEditMode&&w===n.TEXT&&function(){var t=this.shapeEl,e=t.get(0).getBBox().width/2,a=parseFloat(t.attr("font-size"))*p/2,s=parseInt(t.attr("x")),i=parseInt(t.attr("y")),r=s-e,n=i+a;this.updateShapeInfo(t.data("index"),{coords:[r,n,t.attr("font-size")]}),t.attr({x:r,y:n})}.call(this),w===n.ELLIPSE&&(P=n.CIRCLE,k=[k[0],k[1],o.ellipse[2],o.ellipse[2]]),function(t,e,a,s){d(" ").appendTo(this.mapEl)}.call(this,P,k,e,R)}function y(t,e,a){e=e||this.shapeEl;var i=a?a.type:this.shapeType;i===n.RECT||i===n.IMAGE?(e.attr({x:t[0],y:t[1],class:s}),t[2]&&e.attr("width",t[2]-t[0]),t[3]&&e.attr("height",t[3]-t[1]),i===n.IMAGE&&(e.get(0).setAttributeNS(c,"href",a?a.href:this.shapeImageUrl),e.get(0).setAttribute("preserveAspectRatio","none"))):i===n.CIRCLE?(e.attr({cx:t[0],cy:t[1],class:s}),t[2]&&e.attr("r",t[2])):i===n.ELLIPSE?(e.attr({cx:t[0],cy:t[1],class:s}),t[2]&&e.attr("rx",t[2]),t[3]&&e.attr("ry",t[3])):i===n.TEXT&&(e.attr({x:t[0],y:t[1],"font-size":t[2],class:s}),e.text(a&&a.text||this.shapeText))}function v(t,e,a){t.forEach(function(t,a){d(e[a]).attr({x:t.x-3,y:t.y-3,width:7,height:7,"data-direction":t.type,class:i}).css("cursor",t.type+"-resize")})}function g(t,e){var a=[];return t===n.RECT||t===n.IMAGE?a=[{x:e[0],y:e[1],type:"nw"},{x:e[0],y:e[3],type:"sw"},{x:e[2],y:e[1],type:"ne"},{x:e[2],y:e[3],type:"se"},{x:(e[2]-e[0])/2+e[0],y:e[1],type:"n"},{x:(e[2]-e[0])/2+e[0],y:e[3],type:"s"},{x:e[0],y:(e[3]-e[1])/2+e[1],type:"w"},{x:e[2],y:(e[3]-e[1])/2+e[1],type:"e"}]:t===n.CIRCLE?a=[{x:e[0],y:e[1]-e[2],type:"n"},{x:e[0],y:e[1]+e[2],type:"s"},{x:e[0]-e[2],y:e[1],type:"w"},{x:e[0]+e[2],y:e[1],type:"e"}]:t===n.ELLIPSE&&(a=[{x:e[0],y:e[1]-e[3],type:"n"},{x:e[0],y:e[1]+e[3],type:"s"},{x:e[0]-e[2],y:e[1],type:"w"},{x:e[0]+e[2],y:e[1],type:"e"}]),a}function E(t,e,a){var i=this.svgEl.find("."+s+'[data-index="'+e.data("index")+'"]');(a=a||this.shapeType)===n.TEXT?t=function(t){var e=parseFloat(t.attr("x")),a=parseFloat(t.attr("y")),s=t.get(0).getBBox().width,i=parseFloat(t.attr("font-size"))*p/2;return[e,a-i,e+s,a]}(i):a===n.ELLIPSE&&(t=[t[0],t[1],o.ellipse[2]]),e.attr("coords",t.join(","))}function m(t){var e=t.originalEvent.touches[0];this.touchStartCoords.x=e.pageX,this.touchStartCoords.y=e.pageY}function x(t){var e=d(t.currentTarget);if("area"!==t.currentTarget.tagName.toLowerCase()){if(t.preventDefault(),this.dragInfo.face.x&&this.dragInfo.face.x!==t.pageX||this.dragInfo.face.y&&this.dragInfo.face.y!==t.pageY||"svg"===t.target.tagName.toLowerCase()||"touchend"===t.type&&t.originalEvent.changedTouches[0].pageX!==this.touchStartCoords.x&&t.originalEvent.changedTouches[0].pageY!==this.touchStartCoords.y)return;var a=d(t.target).attr("data-index");"#"!==(e=this.mapEl.find('area[data-index="'+a+'"]')).attr("href")&&window.open(e.attr("href"))}this.options.onClick.call(this,t,e.attr("href"))}function C(t){if(t.preventDefault(),"svg"!==t.target.tagName.toLowerCase()){var e=d(t.target),a=e.attr("data-index"),r=this.getShapeInfo(a),h=e.parent().find(":first-child"),o=[],p=h.get(0).tagName.toLowerCase();if(p===n.RECT||p===n.IMAGE){var l=parseInt(h.attr("x")),c=parseInt(h.attr("y"));o=[l,c,l+parseInt(h.attr("width")),c+parseInt(h.attr("height"))],p===n.IMAGE&&this.setImageShape(h.attr("href"))}else p===n.CIRCLE?o=[parseInt(h.attr("cx")),parseInt(h.attr("cy")),parseInt(h.attr("r"))]:p===n.ELLIPSE?o=[parseInt(h.attr("cx")),parseInt(h.attr("cy")),parseInt(h.attr("rx")),parseInt(h.attr("ry"))]:p===n.TEXT?(o=[parseFloat(h.attr("x")),parseFloat(h.attr("y")),parseFloat(h.attr("font-size"))],this.shapeText=h.text()):p===n.POLYGON&&(p=n.POLY);if(this.setShapeType(p),this.setShapeElement(h),this.setShapeCoords(o),p!==n.TEXT){h.attr("data-fill",h.css("fill")),h.css("fill","#ffffff"),this.setVertexCoords(g(p,o));var f=[];this.mapEl.find("."+i+'[data-index="'+a+'"]').each(function(){f.push(d(this))}),this.setVertexElements(f)}e.is("."+s)?(this.grabType="face",function(t,e,a){this.dragInfo.face.x=e,this.dragInfo.face.y=a,t.attr("data-movable",!0)}.call(this,e,t.pageX,t.pageY)):e.is("."+i)&&(this.grabType="vertex",function(t,e){this.setVertexElement(t);var a=0;this.vertexEls.forEach(function(e,s){t.get(0)===e.get(0)&&(a=s)});var s=this.vertexCoords[a];this.dragInfo.vertex.x=s.x,this.dragInfo.vertex.y=s.y,t.attr("data-movable",!0)}.call(this,e,a)),this.attachEvents(this.mapEl.parent(),[{type:"mouseup",handler:I},{type:"mousemove",handler:S}]),this.options.onSelect.call(this,t,r),this.options.onMouseDown.call(this,t,p,o)}}function I(t){var e=d(t.target),a=this.shapeEl;a.css("fill",a.attr("data-fill")),e.attr("data-movable",!1);var s=function(){var t=this.shapeEl,e=this.shapeType,a=[];if(e===n.RECT||e===n.IMAGE){var s=parseInt(t.attr("x")),i=parseInt(t.attr("y"));a=[s,i,s+parseInt(t.attr("width")),i+parseInt(t.attr("height"))]}else e===n.CIRCLE?a=[parseInt(t.attr("cx")),parseInt(t.attr("cy")),parseInt(t.attr("r"))]:e===n.ELLIPSE?a=[parseInt(t.attr("cx")),parseInt(t.attr("cy")),parseInt(t.attr("rx")),parseInt(t.attr("ry"))]:e===n.TEXT&&(a=[parseInt(t.attr("x")),parseInt(t.attr("y"))]);return a}.call(this);this.setShapeCoords(s),this.updateShapeInfo(a.data("index"),{coords:s}),this.detachEvents(this.mapEl.parent(),[{type:"mouseup",handler:I},{type:"mousemove",handler:S}]),this.options.onMouseUp.call(this,t,this.shapeType,s)}function S(t){var a=d(t.target),r=e(this.shapeCoords,2),h=r[0],o=r[1],p=this.grabType,l=this.shapeType,c={};if("face"===p||"vertex"===p){if("face"===p){var f=h+t.pageX,u=o+t.pageY;c=function(t,e){var a=this.shapeEl;if("false"!==a.attr("data-movable")){var s=[],i=[],r=this.shapeType;if(r===n.RECT||r===n.IMAGE){var h=parseInt(a.attr("width")),o=parseInt(a.attr("height")),p=t+h,l=e+o;s=[t,e,p,l],i=g(n.RECT,s)}else r===n.CIRCLE?(s=[t,e,parseInt(a.attr("r"))],i=g(n.CIRCLE,s)):r===n.ELLIPSE?(s=[t,e,parseInt(a.attr("rx")),parseInt(a.attr("ry"))],i=g(n.ELLIPSE,s)):r===n.TEXT&&(s=[t,e]);return{movedCoords:s,vertexCoords:i,grabEl:a}}}.call(this,f-this.dragInfo.face.x,u-this.dragInfo.face.y)}else"vertex"===p&&(c=function(t,e){if("false"!==this.vertexEl.attr("data-movable")){var a=[],s=[],i=this.shapeType,r=this.vertexEl.attr("data-direction");if(i===n.RECT||i===n.IMAGE)switch(r){default:console.warn("Unexpected direction",r);break;case"nw":a=k.call(this,[t,e,this.shapeCoords[2],this.shapeCoords[3]],r);break;case"sw":a=k.call(this,[t,this.shapeCoords[1],this.shapeCoords[2],e],r);break;case"ne":a=k.call(this,[this.shapeCoords[0],e,t,this.shapeCoords[3]],r);break;case"se":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],t,e],r);break;case"n":a=k.call(this,[this.shapeCoords[0],e,this.shapeCoords[2],this.shapeCoords[3]],r);break;case"s":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],e],r);break;case"w":a=k.call(this,[t,this.shapeCoords[1],this.shapeCoords[2],this.shapeCoords[3]],r);break;case"e":a=k.call(this,[this.shapeCoords[0],this.shapeCoords[1],t,this.shapeCoords[3]],r)}else if(i===n.CIRCLE)switch(r){default:console.warn("Unexpected direction",r);break;case"n":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,this.shapeCoords[1]-e)];break;case"s":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,e-this.shapeCoords[1])];break;case"w":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,this.shapeCoords[0]-t)];break;case"e":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,t-this.shapeCoords[0])]}else if(i===n.ELLIPSE)switch(r){default:console.warn("Unexpected direction",r);break;case"n":a=[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],b.call(this,this.shapeCoords[1]-e)];break;case"s":a=[this.shapeCoords[0],this.shapeCoords[1],this.shapeCoords[2],b.call(this,e-this.shapeCoords[1])];break;case"w":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,this.shapeCoords[0]-t),this.shapeCoords[3]];break;case"e":a=[this.shapeCoords[0],this.shapeCoords[1],b.call(this,t-this.shapeCoords[0]),this.shapeCoords[3]]}return s=g(i,a),{movedCoords:a,vertexCoords:s,grabEl:this.vertexEl}}}.call(this,t.pageX-this.svgEl.offset().left,t.pageY-this.svgEl.offset().top));if(!c)return;l!==n.TEXT&&(this.setVertexCoords(c.vertexCoords),v(c.vertexCoords,this.vertexEls,this.shapeType));var m=parseInt(c.grabEl.attr("data-index"));y.call(this,c.movedCoords,this.svgEl.find("."+s+'[data-index="'+m+'"]')),E.call(this,c.movedCoords,this.mapEl.find('area[data-index="'+m+'"]')),(a.is("."+s)||a.is("."+i))&&(Math.abs(this.dragInfo.face.x-t.pageX)<=1||Math.abs(this.dragInfo.face.y-t.pageY)<=1)&&this.svgEl.append(a.parent()),this.options.onMouseMove.call(this,t,l,c.movedCoords)}}function T(t){var e=this.container.width(),a=this.container.height();this.containerWidth===e&&this.containerHeight===a||w.call(this,e,a)}function w(t,e){var a=this,r=this.allShapeInfo,n=t/this.containerWidth,h=e/this.containerHeight,o=this.container.position();this.svgEl.get(0).setAttribute("width",t),this.svgEl.get(0).setAttribute("height",e),this.svgEl.css({top:o.top,left:o.left}),d.each(r,function(t,e){e.coords=L(e.coords,e.type,n,h),v(g(e.type,e.coords),a.svgEl.find("."+i+'[data-index="'+e.index+'"]'),e.type),y.call(a,e.coords,a.svgEl.find("."+s+'[data-index="'+e.index+'"]'),e),E.call(a,e.coords,a.mapEl.find('area[data-index="'+e.index+'"]'),e.type)}),this.containerWidth=t,this.containerHeight=e}function k(t,a){var s=e(t,4),i=s[0],r=s[1],n=s[2],h=s[3];return n-i<=this.shapeLimitCoords.x&&("se"!==a&&"ne"!==a&&"e"!==a||(n=i+this.shapeLimitCoords.x),"nw"!==a&&"sw"!==a&&"w"!==a||(i=n-this.shapeLimitCoords.x)),h-r<=this.shapeLimitCoords.y&&("se"!==a&&"sw"!==a&&"s"!==a||(h=r+this.shapeLimitCoords.y),"nw"!==a&&"ne"!==a&&"n"!==a||(r=h-this.shapeLimitCoords.y)),[i,r,n,h]}function b(t){return t<=this.shapeLimitCoords.radius?this.shapeLimitCoords.radius:t}function L(t,e,a,s){var i=[];if(e===n.RECT||e===n.IMAGE||e===n.ELLIPSE)i=[t[0]*a,t[1]*s,t[2]*a,t[3]*s];else if(e===n.CIRCLE){var r;r=a>=s?s:a,1===a&&(r=s),1===s&&(r=a),i=[t[0]*a,t[1]*s,t[2]*r]}else e===n.TEXT&&(i=[t[0]*a,t[1]*s,t[2]*a]);return i}return f.getCoordsByRatio=L,d.fn.extend({createMaps:function(t,e){return this.data("image_maps_inst").createMaps(t,e),this},copyImageMapsTo:function(t){return d.imageMaps.copyImageMaps({shapes:this.getAllShapes(),width:this.width(),height:this.height()},t),this},addShape:function(t,e,a){return this.data("image_maps_inst").addShape(t,e,a),this},removeShape:function(t){return this.data("image_maps_inst").removeShape(t),this},removeAllShapes:function(){this.data("image_maps_inst").removeAllShapes()},destroy:function(){var t=this.data("image_maps_inst");t&&(t.removeImageMaps(),this.data("image_maps_inst",null))},setShapeStyle:function(t){return this.data("image_maps_inst").setShapeStyle(t),this},setUrl:function(t,e){return this.data("image_maps_inst").setUrl(t,e),this},setTextShape:function(t,e){return this.data("image_maps_inst").setTextShape(t,e),this},setImageShape:function(t,e){return this.data("image_maps_inst").setImageShape(t,e),this},enableClick:function(){this.data("image_maps_inst").enableClick()},disableClick:function(){this.data("image_maps_inst").disableClick()},getAllShapes:function(){return this.data("image_maps_inst").getAllShapesInfo()},getCoordsByRatio:function(t,e,a,s){return f.getCoordsByRatio(t,e,a,s)},zoom:function(t){this.data("image_maps_inst").zoom(t)}}),d.imageMaps={copyImageMaps:function(t,e){var a=t.shapes,s=t.width,i=t.height;e.removeAllShapes(),d.each(a,function(t,a){e.setShapeStyle(a.style),a.href&&e.setImageShape(a.href),a.text&&e.setTextShape(a.text);var r=s,n=i,h=L(a.coords,a.type,e.width()/r,e.height()/n);e.addShape(h,a.url,a.type)})}},d.fn.imageMaps=function(t){if(1===this.length){if(!this.data("image_maps_inst")){var e=new f(this,t);return this.data("image_maps_inst",e),e}return this.data("image_maps_inst")}if(this.length>1)throw new Error("imageMaps instance has already been created.")},d}});
2 | //# sourceMappingURL=index.umd.min.js.map
3 |
--------------------------------------------------------------------------------
/docs/jsdoc-config.js:
--------------------------------------------------------------------------------
1 | /* eslint-env node */
2 | 'use strict';
3 |
4 | module.exports = {
5 | plugins: ['plugins/markdown'],
6 | recurseDepth: 10,
7 | source: {
8 | exclude: [
9 | 'node_modules',
10 | 'dist',
11 | 'test'
12 | ],
13 | excludePattern: 'rollup*|.*?.min.js'
14 | },
15 | sourceType: 'module',
16 | tags: {
17 | allowUnknownTags: false
18 | },
19 | templates: {
20 | cleverLinks: true,
21 | monospaceLinks: false
22 | },
23 | opts: {
24 | recurse: true,
25 | verbose: true,
26 | destination: 'docs/jsdoc'
27 | }
28 | };
29 |
--------------------------------------------------------------------------------
/lgtm.yml:
--------------------------------------------------------------------------------
1 | extraction:
2 | javascript:
3 | index:
4 | filters:
5 | - exclude: "dist"
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "imagemaps",
3 | "version": "1.0.1",
4 | "description": "jQuery plugin which can graphically build area maps on an image",
5 | "main": "dist/index.umd.js",
6 | "module": "dist/index.esm.js",
7 | "scripts": {
8 | "prepublishOnly": "npm run docs",
9 | "eslint": "eslint --report-unused-disable-directives .",
10 | "rollup": "rollup -c",
11 | "open-docs": "opn http://localhost:8041/docs/jsdoc/",
12 | "open": "opn http://localhost:8041/demo/",
13 | "start": "static -p 8041",
14 | "docs": "rm -rf docs/jsdoc/*;jsdoc --pedantic -c docs/jsdoc-config.js .",
15 | "test": "npm run eslint && npm run rollup && testcafe chrome test/**/*.js"
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/naver/image-maps.git"
20 | },
21 | "keywords": [
22 | "jquery",
23 | "imagemaps"
24 | ],
25 | "author": {
26 | "name": "Naver Corp.",
27 | "email": "ahnbj2000@naver.com",
28 | "url": "https://github.com/ahnbj2000"
29 | },
30 | "contributors": [
31 | "ahnbj2000",
32 | "brettz9",
33 | "todtod80",
34 | "beanmilk"
35 | ],
36 | "license": "MIT",
37 | "bugs": {
38 | "url": "https://github.com/naver/image-maps/issues"
39 | },
40 | "homepage": "https://github.com/naver/image-maps#readme",
41 | "engines": {},
42 | "browserslist": [
43 | "cover 100%"
44 | ],
45 | "peerDependencies": {
46 | "jquery": "^3.4.1"
47 | },
48 | "dependencies": {},
49 | "devDependencies": {
50 | "@babel/core": "^7.4.4",
51 | "@babel/preset-env": "^7.4.4",
52 | "@mysticatea/eslint-plugin": "^10.0.3",
53 | "axe-testcafe": "^1.1.0",
54 | "core-js-bundle": "^3.0.1",
55 | "eslint": "^5.16.0",
56 | "eslint-config-ash-nazg": "^4.0.0",
57 | "eslint-config-standard": "^12.0.0",
58 | "eslint-plugin-compat": "^3.1.1",
59 | "eslint-plugin-eslint-comments": "^3.1.1",
60 | "eslint-plugin-import": "^2.17.2",
61 | "eslint-plugin-jsdoc": "^4.8.3",
62 | "eslint-plugin-markdown": "^1.0.0",
63 | "eslint-plugin-no-use-extend-native": "^0.4.0",
64 | "eslint-plugin-node": "^9.0.1",
65 | "eslint-plugin-promise": "^4.1.1",
66 | "eslint-plugin-standard": "^4.0.0",
67 | "eslint-plugin-testcafe": "^0.2.1",
68 | "eslint-plugin-unicorn": "^8.0.2",
69 | "jquery": "^3.4.1",
70 | "jsdoc": "^3.6.1",
71 | "node-static": "^0.7.11",
72 | "opn-cli": "^4.1.0",
73 | "rollup": "1.11.3",
74 | "rollup-plugin-babel": "^4.3.2",
75 | "rollup-plugin-node-builtins": "^2.1.2",
76 | "rollup-plugin-node-resolve": "^4.2.3",
77 | "rollup-plugin-re": "^1.0.7",
78 | "rollup-plugin-terser": "^4.0.4",
79 | "testcafe": "^1.1.4",
80 | "typescript": "^3.4.5"
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/params.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ImageMaps",
3 | "tagline": "jquery plugin which can be partially linked to the image",
4 | "body": "# imageMaps\r\nimage maps jquery plugin\r\n\r\n## supported devices and browser\r\n * PC - IE9+, Chrome, Firefox\r\n * Mobile - iOS, Android (editing is not supported)\r\n \r\n## example\r\n\r\nhttp://s.codepen.io/potatofactory/debug/RRbXRe\r\n\r\n## LICENSE\r\n\r\n```\r\nThe MIT License (MIT)\r\n\r\nCopyright (c) 2016 NAVER Corp.\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\r\n```\r\n",
5 | "note": "Don't delete this file! It's used internally to help with page regeneration."
6 | }
7 |
--------------------------------------------------------------------------------
/rollup.config.js:
--------------------------------------------------------------------------------
1 | import babel from 'rollup-plugin-babel';
2 | import {terser} from 'rollup-plugin-terser';
3 |
4 | /**
5 | * @external RollupConfig
6 | * @type {PlainObject}
7 | * @see {@link https://rollupjs.org/guide/en#big-list-of-options}
8 | */
9 |
10 | /**
11 | * @param {PlainObject} config
12 | * @param {boolean} config.minifying
13 | * @param {string} [config.format='umd'} = {}]
14 | * @returns {external:RollupConfig}
15 | */
16 | function getRollupObject ({minifying, format = 'umd'} = {}) {
17 | const nonMinified = {
18 | input: 'src/jquery.imageMaps.js',
19 | output: {
20 | format,
21 | sourcemap: minifying,
22 | file: `dist/index.${format}${minifying ? '.min' : ''}.js`,
23 | name: 'jqueryImageMaps'
24 | },
25 | plugins: [
26 | babel()
27 | ]
28 | };
29 | if (minifying) {
30 | nonMinified.plugins.push(terser());
31 | }
32 | return nonMinified;
33 | }
34 |
35 | // eslint-disable-next-line import/no-anonymous-default-export
36 | export default [
37 | getRollupObject({minifying: true, format: 'umd'}),
38 | getRollupObject({minifying: false, format: 'umd'}),
39 | getRollupObject({minifying: true, format: 'esm'}),
40 | getRollupObject({minifying: false, format: 'esm'})
41 | ];
42 |
--------------------------------------------------------------------------------
/src/typedefs.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable import/unambiguous */
2 | /**
3 | * @external jQuery
4 | */
5 | /**
6 | * The jQuery plugin namespace.
7 | * @external "jQuery.fn"
8 | * @see {@link https://learn.jquery.com/plugins/|jQuery Plugins}
9 | */
10 | /**
11 | * @typedef {number} Integer
12 | */
13 | /**
14 | * @typedef {number} Float
15 | */
16 | /**
17 | * @typedef {String} Url
18 | */
19 | /**
20 | * @typedef {object} PlainObject
21 | */
22 | /**
23 | * @typedef {Array} GenericArray
24 | */
25 |
--------------------------------------------------------------------------------
/test/accessibility.js:
--------------------------------------------------------------------------------
1 | // https://github.com/DevExpress/testcafe
2 | // https://devexpress.github.io/testcafe/documentation/test-api/
3 | // https://github.com/helen-dikareva/axe-testcafe
4 | import axeCheck from 'axe-testcafe';
5 |
6 | fixture`TestCafe Axe accessibility tests (Demo)`
7 | .page`http://localhost:8041/demo/`;
8 |
9 | test('Demo: General accessibility', async (t) => {
10 | await axeCheck(t); // , axeContent, axeOptions: https://github.com/dequelabs/axe-core/blob/develop/doc/API.md#api-name-axerun
11 | });
12 |
--------------------------------------------------------------------------------
/test/ui.js:
--------------------------------------------------------------------------------
1 | // https://github.com/DevExpress/testcafe
2 | // https://devexpress.github.io/testcafe/documentation/test-api/
3 | // https://github.com/helen-dikareva/axe-testcafe
4 | import {Selector} from 'testcafe';
5 |
6 | fixture`TestCafe UI tests`
7 | .page`http://localhost:8041/demo/`;
8 |
9 | test('Demo: Add red rectangle', async (t) => {
10 | await t
11 | .click('a[data-color="red"]')
12 | .click('#rect')
13 | .expect(
14 | Selector('div._imageMaps_area > map > svg > g > rect._shape_face')
15 | .getAttribute('style')
16 | ).match(/stroke:\s*red/u, 'Red stroke');
17 | });
18 |
--------------------------------------------------------------------------------