cropper_rails 1.0.0 → 1.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d84332dcb790ed21af1e086b857f1f17acec02a880b41197b9afdbf5cc7f8be6
4
- data.tar.gz: 001b94ba91002854a76980e5833df5fa5e0a6c03422aa08881ded2361a7aa05a
3
+ metadata.gz: 0e6a467c1958fd3ddd131cf60a3b058e6e69af6a07f72e188c1c1d19033512e3
4
+ data.tar.gz: 698eab8c4eee8efc59236bd1bf7f20962f3a8b2cd963dccd3482f6f16557540f
5
5
  SHA512:
6
- metadata.gz: dfaa9b5e2a04e478623bf8ce238fb8ed61b3bb3ce79eb95930cf8ac26bbf928c5d257fae2b6170983a1e2b9815d0d9b0c787df4dce54a1cd42ac32ba04ccc8b0
7
- data.tar.gz: 5e086e1ca15b399738c71274abd108d8cfb4787ca5baeb5772eca5d9d0727a3035be011fdddf5d6db71d0ba7f5c2a48ba441d8d28e72e1eddb01755e6848dea0
6
+ metadata.gz: 003d20c6b59514d33a74bf7211d45d6013992966c1ff33ff6afca3914396e5b2f2d27c81d13562bdf79076c06f8124778a84d401c3fd40dce4df68a1fea619a0
7
+ data.tar.gz: fd6a0a53ff412fd49c1c7fe4bcf606bb70ddde24c648b57149d70ec94cad94cafc43e89680dbc5ac4483af5833e5fc65ab95a8ce0ef6075d02f8e67f3e7fb51a
@@ -0,0 +1,24 @@
1
+ ---
2
+ name: Bug report
3
+ about: Create a report to help us improve
4
+
5
+ ---
6
+
7
+ **Describe the bug**
8
+ A clear and concise description of what the bug is.
9
+
10
+ **To Reproduce**
11
+ Steps to reproduce the behavior:
12
+ 1. Go to '...'
13
+ 2. Click on '....'
14
+ 3. Scroll down to '....'
15
+ 4. See error
16
+
17
+ **Expected behavior**
18
+ A clear and concise description of what you expected to happen.
19
+
20
+ **Screenshots**
21
+ If applicable, add screenshots to help explain your problem.
22
+
23
+ **Additional context**
24
+ Add any other context about the problem here.
@@ -0,0 +1,17 @@
1
+ ---
2
+ name: Feature request
3
+ about: Suggest an idea for this project
4
+
5
+ ---
6
+
7
+ **Is your feature request related to a problem? Please describe.**
8
+ A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
9
+
10
+ **Describe the solution you'd like**
11
+ A clear and concise description of what you want to happen.
12
+
13
+ **Describe alternatives you've considered**
14
+ A clear and concise description of any alternative solutions or features you've considered.
15
+
16
+ **Additional context**
17
+ Add any other context or screenshots about the feature request here.
data/CODE_OF_CONDUCT.md CHANGED
@@ -1,74 +1,52 @@
1
- # Contributor Covenant Code of Conduct
1
+ # Code of Merit
2
2
 
3
- ## Our Pledge
3
+ 1. The project creators, lead developers, core team, constitute
4
+ the managing members of the project and have final say in every decision
5
+ of the project, technical or otherwise, including overruling previous decisions.
6
+ There are no limitations to this decisional power.
4
7
 
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
8
+ 2. Contributions are an expected result of your membership on the project.
9
+ Don't expect others to do your work or help you with your work forever.
11
10
 
12
- ## Our Standards
11
+ 3. All members have the same opportunities to seek any challenge they want
12
+ within the project.
13
13
 
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
14
+ 4. Authority or position in the project will be proportional
15
+ to the accrued contribution. Seniority must be earned.
16
16
 
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
17
+ 5. Software is evolutive: the better implementations must supersede lesser
18
+ implementations. Technical advantage is the primary evaluation metric.
22
19
 
23
- Examples of unacceptable behavior by participants include:
20
+ 6. This is a space for technical prowess; topics outside of the project
21
+ will not be tolerated.
24
22
 
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
23
+ 7. Non technical conflicts will be discussed in a separate space. Disruption
24
+ of the project will not be allowed.
33
25
 
34
- ## Our Responsibilities
26
+ 8. Individual characteristics, including but not limited to,
27
+ body, sex, sexual preference, race, language, religion, nationality,
28
+ or political preferences are irrelevant in the scope of the project and
29
+ will not be taken into account concerning your value or that of your contribution
30
+ to the project.
35
31
 
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
32
+ 9. Discuss or debate the idea, not the person.
39
33
 
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
34
+ 10. There is no room for ambiguity: Ambiguity will be met with questioning;
35
+ further ambiguity will be met with silence. It is the responsibility
36
+ of the originator to provide requested context.
45
37
 
46
- ## Scope
38
+ 11. If something is illegal outside the scope of the project, it is illegal
39
+ in the scope of the project. This Code of Merit does not take precedence over
40
+ governing law.
47
41
 
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
42
+ 12. This Code of Merit governs the technical procedures of the project not the
43
+ activities outside of it.
54
44
 
55
- ## Enforcement
45
+ 13. Participation on the project equates to agreement of this Code of Merit.
56
46
 
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at contact@d1ceward.com. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
47
+ 14. No objectives beyond the stated objectives of this project are relevant
48
+ to the project. Any intent to deviate the project from its original purpose
49
+ of existence will constitute grounds for remedial action which may include
50
+ expulsion from the project.
63
51
 
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/
52
+ This document is the Code of Merit (http://code-of-merit.org), version 1.0.
data/CONTRIBUTING.md ADDED
@@ -0,0 +1,11 @@
1
+ ## Contributing
2
+
3
+ Bug reports and pull requests are welcome on GitHub at https://github.com/D1ceWard/cropper_rails. By contributing you agree to abide by the Code of Merit.
4
+
5
+ Example :
6
+
7
+ 1. Fork it
8
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
9
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
10
+ 4. Push to the branch (`git push origin my-new-feature`)
11
+ 5. Create new Pull Request
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright 2015-present Chen Fengyuan
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
13
+ all 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
21
+ THE SOFTWARE.
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
1
  # Cropper for Rails
2
- [![Gem Version](https://badge.fury.io/rb/jquery-cropper-rails.svg)](https://badge.fury.io/rb/jquery-cropper-rails)
2
+ [![Gem Version](https://badge.fury.io/rb/cropper_rails.svg)](https://badge.fury.io/rb/cropper_rails)
3
3
  [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/D1ceWard/jquery-cropper-rails/graphs/commit-activity)
4
4
 
5
5
 
@@ -35,7 +35,7 @@ Add to your `app/assets/stylesheets/application.css`:
35
35
 
36
36
  ## Contributing
37
37
 
38
- Bug reports and pull requests are welcome on GitHub at https://github.com/D1ceWard/cropper_rails. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
38
+ Bug reports and pull requests are welcome on GitHub at https://github.com/D1ceWard/cropper_rails. By contributing you agree to abide by the Code of Merit.
39
39
 
40
40
  ## Code of Conduct
41
41
 
data/VERSIONS.md CHANGED
@@ -2,4 +2,9 @@
2
2
 
3
3
  | Gem | Cropper.js | jQuery Cropper |
4
4
  |--------|------------|----------------|
5
+ | 1.1.2 | 1.5.10 | 1.0.1 |
6
+ | 1.1.1 | 1.5.9 | 1.0.1 |
7
+ | 1.1.0 | 1.5.6 | 1.0.1 |
8
+ | 1.0.2 | 1.4.3 | 1.0.0 |
9
+ | 1.0.1 | 1.4.2 | 1.0.0 |
5
10
  | 1.0.0 | 1.4.1 | 1.0.0 |
@@ -22,5 +22,5 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_runtime_dependency 'jquery-rails', '~> 4.0'
24
24
 
25
- spec.add_development_dependency 'bundler', '~> 1.16'
25
+ spec.add_development_dependency 'bundler', '~> 2.0'
26
26
  end
@@ -1,7 +1,7 @@
1
1
  module Cropper
2
2
  module Rails
3
- VERSION = '1.0.0'.freeze
4
- CROPPERJS_VERSION = '1.4.1'.freeze
5
- JQUERY_CROPPER_VERSION = '4.0.0'.freeze
3
+ VERSION = '1.1.2'.freeze
4
+ CROPPER_VERSION = '1.5.10'.freeze
5
+ JQUERY_CROPPER_VERSION = '1.0.1'.freeze
6
6
  end
7
7
  end
@@ -1,24 +1,145 @@
1
1
  /*!
2
- * Cropper.js v1.4.1
2
+ * Cropper.js v1.5.10
3
3
  * https://fengyuanchen.github.io/cropperjs
4
4
  *
5
5
  * Copyright 2015-present Chen Fengyuan
6
6
  * Released under the MIT license
7
7
  *
8
- * Date: 2018-07-15T09:55:31.170Z
8
+ * Date: 2021-02-12T06:37:49.781Z
9
9
  */
10
10
 
11
11
  (function (global, factory) {
12
12
  typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
13
13
  typeof define === 'function' && define.amd ? define(factory) :
14
- (global.Cropper = factory());
14
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.Cropper = factory());
15
15
  }(this, (function () { 'use strict';
16
16
 
17
- var IN_BROWSER = typeof window !== 'undefined';
18
- var WINDOW = IN_BROWSER ? window : {};
19
- var NAMESPACE = 'cropper';
17
+ function _typeof(obj) {
18
+ "@babel/helpers - typeof";
19
+
20
+ if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
21
+ _typeof = function (obj) {
22
+ return typeof obj;
23
+ };
24
+ } else {
25
+ _typeof = function (obj) {
26
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
27
+ };
28
+ }
29
+
30
+ return _typeof(obj);
31
+ }
32
+
33
+ function _classCallCheck(instance, Constructor) {
34
+ if (!(instance instanceof Constructor)) {
35
+ throw new TypeError("Cannot call a class as a function");
36
+ }
37
+ }
38
+
39
+ function _defineProperties(target, props) {
40
+ for (var i = 0; i < props.length; i++) {
41
+ var descriptor = props[i];
42
+ descriptor.enumerable = descriptor.enumerable || false;
43
+ descriptor.configurable = true;
44
+ if ("value" in descriptor) descriptor.writable = true;
45
+ Object.defineProperty(target, descriptor.key, descriptor);
46
+ }
47
+ }
48
+
49
+ function _createClass(Constructor, protoProps, staticProps) {
50
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
51
+ if (staticProps) _defineProperties(Constructor, staticProps);
52
+ return Constructor;
53
+ }
54
+
55
+ function _defineProperty(obj, key, value) {
56
+ if (key in obj) {
57
+ Object.defineProperty(obj, key, {
58
+ value: value,
59
+ enumerable: true,
60
+ configurable: true,
61
+ writable: true
62
+ });
63
+ } else {
64
+ obj[key] = value;
65
+ }
66
+
67
+ return obj;
68
+ }
69
+
70
+ function ownKeys(object, enumerableOnly) {
71
+ var keys = Object.keys(object);
72
+
73
+ if (Object.getOwnPropertySymbols) {
74
+ var symbols = Object.getOwnPropertySymbols(object);
75
+ if (enumerableOnly) symbols = symbols.filter(function (sym) {
76
+ return Object.getOwnPropertyDescriptor(object, sym).enumerable;
77
+ });
78
+ keys.push.apply(keys, symbols);
79
+ }
80
+
81
+ return keys;
82
+ }
83
+
84
+ function _objectSpread2(target) {
85
+ for (var i = 1; i < arguments.length; i++) {
86
+ var source = arguments[i] != null ? arguments[i] : {};
87
+
88
+ if (i % 2) {
89
+ ownKeys(Object(source), true).forEach(function (key) {
90
+ _defineProperty(target, key, source[key]);
91
+ });
92
+ } else if (Object.getOwnPropertyDescriptors) {
93
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
94
+ } else {
95
+ ownKeys(Object(source)).forEach(function (key) {
96
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
97
+ });
98
+ }
99
+ }
100
+
101
+ return target;
102
+ }
103
+
104
+ function _toConsumableArray(arr) {
105
+ return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread();
106
+ }
107
+
108
+ function _arrayWithoutHoles(arr) {
109
+ if (Array.isArray(arr)) return _arrayLikeToArray(arr);
110
+ }
111
+
112
+ function _iterableToArray(iter) {
113
+ if (typeof Symbol !== "undefined" && Symbol.iterator in Object(iter)) return Array.from(iter);
114
+ }
115
+
116
+ function _unsupportedIterableToArray(o, minLen) {
117
+ if (!o) return;
118
+ if (typeof o === "string") return _arrayLikeToArray(o, minLen);
119
+ var n = Object.prototype.toString.call(o).slice(8, -1);
120
+ if (n === "Object" && o.constructor) n = o.constructor.name;
121
+ if (n === "Map" || n === "Set") return Array.from(o);
122
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
123
+ }
124
+
125
+ function _arrayLikeToArray(arr, len) {
126
+ if (len == null || len > arr.length) len = arr.length;
127
+
128
+ for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
129
+
130
+ return arr2;
131
+ }
132
+
133
+ function _nonIterableSpread() {
134
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
135
+ }
136
+
137
+ var IS_BROWSER = typeof window !== 'undefined' && typeof window.document !== 'undefined';
138
+ var WINDOW = IS_BROWSER ? window : {};
139
+ var IS_TOUCH_DEVICE = IS_BROWSER && WINDOW.document.documentElement ? 'ontouchstart' in WINDOW.document.documentElement : false;
140
+ var HAS_POINTER_EVENT = IS_BROWSER ? 'PointerEvent' in WINDOW : false;
141
+ var NAMESPACE = 'cropper'; // Actions
20
142
 
21
- // Actions
22
143
  var ACTION_ALL = 'all';
23
144
  var ACTION_CROP = 'crop';
24
145
  var ACTION_MOVE = 'move';
@@ -30,136 +151,114 @@
30
151
  var ACTION_NORTH_EAST = 'ne';
31
152
  var ACTION_NORTH_WEST = 'nw';
32
153
  var ACTION_SOUTH_EAST = 'se';
33
- var ACTION_SOUTH_WEST = 'sw';
34
-
35
- // Classes
36
- var CLASS_CROP = NAMESPACE + '-crop';
37
- var CLASS_DISABLED = NAMESPACE + '-disabled';
38
- var CLASS_HIDDEN = NAMESPACE + '-hidden';
39
- var CLASS_HIDE = NAMESPACE + '-hide';
40
- var CLASS_INVISIBLE = NAMESPACE + '-invisible';
41
- var CLASS_MODAL = NAMESPACE + '-modal';
42
- var CLASS_MOVE = NAMESPACE + '-move';
43
-
44
- // Data keys
45
- var DATA_ACTION = NAMESPACE + 'Action';
46
- var DATA_PREVIEW = NAMESPACE + 'Preview';
47
-
48
- // Drag modes
154
+ var ACTION_SOUTH_WEST = 'sw'; // Classes
155
+
156
+ var CLASS_CROP = "".concat(NAMESPACE, "-crop");
157
+ var CLASS_DISABLED = "".concat(NAMESPACE, "-disabled");
158
+ var CLASS_HIDDEN = "".concat(NAMESPACE, "-hidden");
159
+ var CLASS_HIDE = "".concat(NAMESPACE, "-hide");
160
+ var CLASS_INVISIBLE = "".concat(NAMESPACE, "-invisible");
161
+ var CLASS_MODAL = "".concat(NAMESPACE, "-modal");
162
+ var CLASS_MOVE = "".concat(NAMESPACE, "-move"); // Data keys
163
+
164
+ var DATA_ACTION = "".concat(NAMESPACE, "Action");
165
+ var DATA_PREVIEW = "".concat(NAMESPACE, "Preview"); // Drag modes
166
+
49
167
  var DRAG_MODE_CROP = 'crop';
50
168
  var DRAG_MODE_MOVE = 'move';
51
- var DRAG_MODE_NONE = 'none';
169
+ var DRAG_MODE_NONE = 'none'; // Events
52
170
 
53
- // Events
54
171
  var EVENT_CROP = 'crop';
55
172
  var EVENT_CROP_END = 'cropend';
56
173
  var EVENT_CROP_MOVE = 'cropmove';
57
174
  var EVENT_CROP_START = 'cropstart';
58
175
  var EVENT_DBLCLICK = 'dblclick';
59
- var EVENT_POINTER_DOWN = WINDOW.PointerEvent ? 'pointerdown' : 'touchstart mousedown';
60
- var EVENT_POINTER_MOVE = WINDOW.PointerEvent ? 'pointermove' : 'touchmove mousemove';
61
- var EVENT_POINTER_UP = WINDOW.PointerEvent ? 'pointerup pointercancel' : 'touchend touchcancel mouseup';
176
+ var EVENT_TOUCH_START = IS_TOUCH_DEVICE ? 'touchstart' : 'mousedown';
177
+ var EVENT_TOUCH_MOVE = IS_TOUCH_DEVICE ? 'touchmove' : 'mousemove';
178
+ var EVENT_TOUCH_END = IS_TOUCH_DEVICE ? 'touchend touchcancel' : 'mouseup';
179
+ var EVENT_POINTER_DOWN = HAS_POINTER_EVENT ? 'pointerdown' : EVENT_TOUCH_START;
180
+ var EVENT_POINTER_MOVE = HAS_POINTER_EVENT ? 'pointermove' : EVENT_TOUCH_MOVE;
181
+ var EVENT_POINTER_UP = HAS_POINTER_EVENT ? 'pointerup pointercancel' : EVENT_TOUCH_END;
62
182
  var EVENT_READY = 'ready';
63
183
  var EVENT_RESIZE = 'resize';
64
- var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll';
65
- var EVENT_ZOOM = 'zoom';
184
+ var EVENT_WHEEL = 'wheel';
185
+ var EVENT_ZOOM = 'zoom'; // Mime types
186
+
187
+ var MIME_TYPE_JPEG = 'image/jpeg'; // RegExps
66
188
 
67
- // RegExps
68
- var REGEXP_ACTIONS = /^(?:e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/;
189
+ var REGEXP_ACTIONS = /^e|w|s|n|se|sw|ne|nw|all|crop|move|zoom$/;
69
190
  var REGEXP_DATA_URL = /^data:/;
70
191
  var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/;
71
- var REGEXP_TAG_NAME = /^(?:img|canvas)$/i;
192
+ var REGEXP_TAG_NAME = /^img|canvas$/i; // Misc
193
+ // Inspired by the default width and height of a canvas element.
194
+
195
+ var MIN_CONTAINER_WIDTH = 200;
196
+ var MIN_CONTAINER_HEIGHT = 100;
72
197
 
73
198
  var DEFAULTS = {
74
199
  // Define the view mode of the cropper
75
- viewMode: 0, // 0, 1, 2, 3
76
-
200
+ viewMode: 0,
201
+ // 0, 1, 2, 3
77
202
  // Define the dragging mode of the cropper
78
- dragMode: DRAG_MODE_CROP, // 'crop', 'move' or 'none'
79
-
203
+ dragMode: DRAG_MODE_CROP,
204
+ // 'crop', 'move' or 'none'
80
205
  // Define the initial aspect ratio of the crop box
81
206
  initialAspectRatio: NaN,
82
-
83
207
  // Define the aspect ratio of the crop box
84
208
  aspectRatio: NaN,
85
-
86
209
  // An object with the previous cropping result data
87
210
  data: null,
88
-
89
211
  // A selector for adding extra containers to preview
90
212
  preview: '',
91
-
92
213
  // Re-render the cropper when resize the window
93
214
  responsive: true,
94
-
95
215
  // Restore the cropped area after resize the window
96
216
  restore: true,
97
-
98
217
  // Check if the current image is a cross-origin image
99
218
  checkCrossOrigin: true,
100
-
101
219
  // Check the current image's Exif Orientation information
102
220
  checkOrientation: true,
103
-
104
221
  // Show the black modal
105
222
  modal: true,
106
-
107
223
  // Show the dashed lines for guiding
108
224
  guides: true,
109
-
110
225
  // Show the center indicator for guiding
111
226
  center: true,
112
-
113
227
  // Show the white modal to highlight the crop box
114
228
  highlight: true,
115
-
116
229
  // Show the grid background
117
230
  background: true,
118
-
119
231
  // Enable to crop the image automatically when initialize
120
232
  autoCrop: true,
121
-
122
233
  // Define the percentage of automatic cropping area when initializes
123
234
  autoCropArea: 0.8,
124
-
125
235
  // Enable to move the image
126
236
  movable: true,
127
-
128
237
  // Enable to rotate the image
129
238
  rotatable: true,
130
-
131
239
  // Enable to scale the image
132
240
  scalable: true,
133
-
134
241
  // Enable to zoom the image
135
242
  zoomable: true,
136
-
137
243
  // Enable to zoom the image by dragging touch
138
244
  zoomOnTouch: true,
139
-
140
245
  // Enable to zoom the image by wheeling mouse
141
246
  zoomOnWheel: true,
142
-
143
247
  // Define zoom ratio when zoom the image by wheeling mouse
144
248
  wheelZoomRatio: 0.1,
145
-
146
249
  // Enable to move the crop box
147
250
  cropBoxMovable: true,
148
-
149
251
  // Enable to resize the crop box
150
252
  cropBoxResizable: true,
151
-
152
253
  // Toggle drag mode between "crop" and "move" when click twice on the cropper
153
254
  toggleDragModeOnDblclick: true,
154
-
155
255
  // Size limitation
156
256
  minCanvasWidth: 0,
157
257
  minCanvasHeight: 0,
158
258
  minCropBoxWidth: 0,
159
259
  minCropBoxHeight: 0,
160
- minContainerWidth: 200,
161
- minContainerHeight: 100,
162
-
260
+ minContainerWidth: MIN_CONTAINER_WIDTH,
261
+ minContainerHeight: MIN_CONTAINER_HEIGHT,
163
262
  // Shortcuts of events
164
263
  ready: null,
165
264
  cropstart: null,
@@ -171,80 +270,48 @@
171
270
 
172
271
  var TEMPLATE = '<div class="cropper-container" touch-action="none">' + '<div class="cropper-wrap-box">' + '<div class="cropper-canvas"></div>' + '</div>' + '<div class="cropper-drag-box"></div>' + '<div class="cropper-crop-box">' + '<span class="cropper-view-box"></span>' + '<span class="cropper-dashed dashed-h"></span>' + '<span class="cropper-dashed dashed-v"></span>' + '<span class="cropper-center"></span>' + '<span class="cropper-face"></span>' + '<span class="cropper-line line-e" data-cropper-action="e"></span>' + '<span class="cropper-line line-n" data-cropper-action="n"></span>' + '<span class="cropper-line line-w" data-cropper-action="w"></span>' + '<span class="cropper-line line-s" data-cropper-action="s"></span>' + '<span class="cropper-point point-e" data-cropper-action="e"></span>' + '<span class="cropper-point point-n" data-cropper-action="n"></span>' + '<span class="cropper-point point-w" data-cropper-action="w"></span>' + '<span class="cropper-point point-s" data-cropper-action="s"></span>' + '<span class="cropper-point point-ne" data-cropper-action="ne"></span>' + '<span class="cropper-point point-nw" data-cropper-action="nw"></span>' + '<span class="cropper-point point-sw" data-cropper-action="sw"></span>' + '<span class="cropper-point point-se" data-cropper-action="se"></span>' + '</div>' + '</div>';
173
272
 
174
- var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
175
- return typeof obj;
176
- } : function (obj) {
177
- return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
178
- };
179
-
180
- var classCallCheck = function (instance, Constructor) {
181
- if (!(instance instanceof Constructor)) {
182
- throw new TypeError("Cannot call a class as a function");
183
- }
184
- };
185
-
186
- var createClass = function () {
187
- function defineProperties(target, props) {
188
- for (var i = 0; i < props.length; i++) {
189
- var descriptor = props[i];
190
- descriptor.enumerable = descriptor.enumerable || false;
191
- descriptor.configurable = true;
192
- if ("value" in descriptor) descriptor.writable = true;
193
- Object.defineProperty(target, descriptor.key, descriptor);
194
- }
195
- }
196
-
197
- return function (Constructor, protoProps, staticProps) {
198
- if (protoProps) defineProperties(Constructor.prototype, protoProps);
199
- if (staticProps) defineProperties(Constructor, staticProps);
200
- return Constructor;
201
- };
202
- }();
203
-
204
- var toConsumableArray = function (arr) {
205
- if (Array.isArray(arr)) {
206
- for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
207
-
208
- return arr2;
209
- } else {
210
- return Array.from(arr);
211
- }
212
- };
213
-
214
273
  /**
215
274
  * Check if the given value is not a number.
216
275
  */
217
- var isNaN = Number.isNaN || WINDOW.isNaN;
218
276
 
277
+ var isNaN = Number.isNaN || WINDOW.isNaN;
219
278
  /**
220
279
  * Check if the given value is a number.
221
280
  * @param {*} value - The value to check.
222
281
  * @returns {boolean} Returns `true` if the given value is a number, else `false`.
223
282
  */
283
+
224
284
  function isNumber(value) {
225
285
  return typeof value === 'number' && !isNaN(value);
226
286
  }
287
+ /**
288
+ * Check if the given value is a positive number.
289
+ * @param {*} value - The value to check.
290
+ * @returns {boolean} Returns `true` if the given value is a positive number, else `false`.
291
+ */
227
292
 
293
+ var isPositiveNumber = function isPositiveNumber(value) {
294
+ return value > 0 && value < Infinity;
295
+ };
228
296
  /**
229
297
  * Check if the given value is undefined.
230
298
  * @param {*} value - The value to check.
231
299
  * @returns {boolean} Returns `true` if the given value is undefined, else `false`.
232
300
  */
301
+
233
302
  function isUndefined(value) {
234
303
  return typeof value === 'undefined';
235
304
  }
236
-
237
305
  /**
238
306
  * Check if the given value is an object.
239
307
  * @param {*} value - The value to check.
240
308
  * @returns {boolean} Returns `true` if the given value is an object, else `false`.
241
309
  */
310
+
242
311
  function isObject(value) {
243
- return (typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' && value !== null;
312
+ return _typeof(value) === 'object' && value !== null;
244
313
  }
245
-
246
314
  var hasOwnProperty = Object.prototype.hasOwnProperty;
247
-
248
315
  /**
249
316
  * Check if the given value is a plain object.
250
317
  * @param {*} value - The value to check.
@@ -259,41 +326,45 @@
259
326
  try {
260
327
  var _constructor = value.constructor;
261
328
  var prototype = _constructor.prototype;
262
-
263
-
264
329
  return _constructor && prototype && hasOwnProperty.call(prototype, 'isPrototypeOf');
265
- } catch (e) {
330
+ } catch (error) {
266
331
  return false;
267
332
  }
268
333
  }
269
-
270
334
  /**
271
335
  * Check if the given value is a function.
272
336
  * @param {*} value - The value to check.
273
337
  * @returns {boolean} Returns `true` if the given value is a function, else `false`.
274
338
  */
339
+
275
340
  function isFunction(value) {
276
341
  return typeof value === 'function';
277
342
  }
343
+ var slice = Array.prototype.slice;
344
+ /**
345
+ * Convert array-like or iterable object to an array.
346
+ * @param {*} value - The value to convert.
347
+ * @returns {Array} Returns a new array.
348
+ */
278
349
 
350
+ function toArray(value) {
351
+ return Array.from ? Array.from(value) : slice.call(value);
352
+ }
279
353
  /**
280
354
  * Iterate the given data.
281
355
  * @param {*} data - The data to iterate.
282
356
  * @param {Function} callback - The process function for each element.
283
357
  * @returns {*} The original data.
284
358
  */
359
+
285
360
  function forEach(data, callback) {
286
361
  if (data && isFunction(callback)) {
287
- if (Array.isArray(data) || isNumber(data.length) /* array-like */) {
288
- var length = data.length;
289
-
290
- var i = void 0;
291
-
292
- for (i = 0; i < length; i += 1) {
293
- if (callback.call(data, data[i], i, data) === false) {
294
- break;
295
- }
296
- }
362
+ if (Array.isArray(data) || isNumber(data.length)
363
+ /* array-like */
364
+ ) {
365
+ toArray(data).forEach(function (value, key) {
366
+ callback.call(data, value, key, data);
367
+ });
297
368
  } else if (isObject(data)) {
298
369
  Object.keys(data).forEach(function (key) {
299
370
  callback.call(data, data[key], key, data);
@@ -303,81 +374,76 @@
303
374
 
304
375
  return data;
305
376
  }
306
-
307
377
  /**
308
378
  * Extend the given object.
309
- * @param {*} obj - The object to be extended.
310
- * @param {*} args - The rest objects which will be merged to the first object.
379
+ * @param {*} target - The target object to extend.
380
+ * @param {*} args - The rest objects for merging to the target object.
311
381
  * @returns {Object} The extended object.
312
382
  */
313
- var assign = Object.assign || function assign(obj) {
314
- for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
383
+
384
+ var assign = Object.assign || function assign(target) {
385
+ for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
315
386
  args[_key - 1] = arguments[_key];
316
387
  }
317
388
 
318
- if (isObject(obj) && args.length > 0) {
389
+ if (isObject(target) && args.length > 0) {
319
390
  args.forEach(function (arg) {
320
391
  if (isObject(arg)) {
321
392
  Object.keys(arg).forEach(function (key) {
322
- obj[key] = arg[key];
393
+ target[key] = arg[key];
323
394
  });
324
395
  }
325
396
  });
326
397
  }
327
398
 
328
- return obj;
399
+ return target;
329
400
  };
330
-
331
- var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/i;
332
-
401
+ var REGEXP_DECIMALS = /\.\d*(?:0|9){12}\d*$/;
333
402
  /**
334
403
  * Normalize decimal number.
335
- * Check out {@link http://0.30000000000000004.com/}
404
+ * Check out {@link https://0.30000000000000004.com/}
336
405
  * @param {number} value - The value to normalize.
337
406
  * @param {number} [times=100000000000] - The times for normalizing.
338
407
  * @returns {number} Returns the normalized number.
339
408
  */
409
+
340
410
  function normalizeDecimalNumber(value) {
341
411
  var times = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 100000000000;
342
-
343
412
  return REGEXP_DECIMALS.test(value) ? Math.round(value * times) / times : value;
344
413
  }
345
-
346
- var REGEXP_SUFFIX = /^(?:width|height|left|top|marginLeft|marginTop)$/;
347
-
414
+ var REGEXP_SUFFIX = /^width|height|left|top|marginLeft|marginTop$/;
348
415
  /**
349
416
  * Apply styles to the given element.
350
417
  * @param {Element} element - The target element.
351
418
  * @param {Object} styles - The styles for applying.
352
419
  */
420
+
353
421
  function setStyle(element, styles) {
354
422
  var style = element.style;
355
-
356
-
357
423
  forEach(styles, function (value, property) {
358
424
  if (REGEXP_SUFFIX.test(property) && isNumber(value)) {
359
- value += 'px';
425
+ value = "".concat(value, "px");
360
426
  }
361
427
 
362
428
  style[property] = value;
363
429
  });
364
430
  }
365
-
366
431
  /**
367
432
  * Check if the given element has a special class.
368
433
  * @param {Element} element - The element to check.
369
434
  * @param {string} value - The class to search.
370
435
  * @returns {boolean} Returns `true` if the special class was found.
371
436
  */
437
+
372
438
  function hasClass(element, value) {
373
439
  return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1;
374
440
  }
375
-
376
441
  /**
377
442
  * Add classes to the given element.
378
443
  * @param {Element} element - The target element.
379
444
  * @param {string} value - The classes to be added.
380
445
  */
446
+
381
447
  function addClass(element, value) {
382
448
  if (!value) {
383
449
  return;
@@ -400,15 +466,15 @@
400
466
  if (!className) {
401
467
  element.className = value;
402
468
  } else if (className.indexOf(value) < 0) {
403
- element.className = className + ' ' + value;
469
+ element.className = "".concat(className, " ").concat(value);
404
470
  }
405
471
  }
406
-
407
472
  /**
408
473
  * Remove classes from the given element.
409
474
  * @param {Element} element - The target element.
410
475
  * @param {string} value - The classes to be removed.
411
476
  */
477
+
412
478
  function removeClass(element, value) {
413
479
  if (!value) {
414
480
  return;
@@ -430,13 +496,13 @@
430
496
  element.className = element.className.replace(value, '');
431
497
  }
432
498
  }
433
-
434
499
  /**
435
500
  * Add or remove classes from the given element.
436
501
  * @param {Element} element - The target element.
437
502
  * @param {string} value - The classes to be toggled.
438
503
  * @param {boolean} added - Add only.
439
504
  */
505
+
440
506
  function toggleClass(element, value, added) {
441
507
  if (!value) {
442
508
  return;
@@ -447,33 +513,32 @@
447
513
  toggleClass(elem, value, added);
448
514
  });
449
515
  return;
450
- }
516
+ } // IE10-11 doesn't support the second parameter of `classList.toggle`
517
+
451
518
 
452
- // IE10-11 doesn't support the second parameter of `classList.toggle`
453
519
  if (added) {
454
520
  addClass(element, value);
455
521
  } else {
456
522
  removeClass(element, value);
457
523
  }
458
524
  }
459
-
460
- var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g;
461
-
525
+ var REGEXP_CAMEL_CASE = /([a-z\d])([A-Z])/g;
462
526
  /**
463
527
  * Transform the given string from camelCase to kebab-case
464
528
  * @param {string} value - The value to transform.
465
529
  * @returns {string} The transformed value.
466
530
  */
467
- function hyphenate(value) {
468
- return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase();
469
- }
470
531
 
532
+ function toParamCase(value) {
533
+ return value.replace(REGEXP_CAMEL_CASE, '$1-$2').toLowerCase();
534
+ }
471
535
  /**
472
536
  * Get data from the given element.
473
537
  * @param {Element} element - The target element.
474
538
  * @param {string} name - The data key to get.
475
539
  * @returns {string} The data value.
476
540
  */
541
+
477
542
  function getData(element, name) {
478
543
  if (isObject(element[name])) {
479
544
  return element[name];
@@ -483,80 +548,79 @@
483
548
  return element.dataset[name];
484
549
  }
485
550
 
486
- return element.getAttribute('data-' + hyphenate(name));
551
+ return element.getAttribute("data-".concat(toParamCase(name)));
487
552
  }
488
-
489
553
  /**
490
554
  * Set data to the given element.
491
555
  * @param {Element} element - The target element.
492
556
  * @param {string} name - The data key to set.
493
557
  * @param {string} data - The data value.
494
558
  */
559
+
495
560
  function setData(element, name, data) {
496
561
  if (isObject(data)) {
497
562
  element[name] = data;
498
563
  } else if (element.dataset) {
499
564
  element.dataset[name] = data;
500
565
  } else {
501
- element.setAttribute('data-' + hyphenate(name), data);
566
+ element.setAttribute("data-".concat(toParamCase(name)), data);
502
567
  }
503
568
  }
504
-
505
569
  /**
506
570
  * Remove data from the given element.
507
571
  * @param {Element} element - The target element.
508
572
  * @param {string} name - The data key to remove.
509
573
  */
574
+
510
575
  function removeData(element, name) {
511
576
  if (isObject(element[name])) {
512
577
  try {
513
578
  delete element[name];
514
- } catch (e) {
579
+ } catch (error) {
515
580
  element[name] = undefined;
516
581
  }
517
582
  } else if (element.dataset) {
518
583
  // #128 Safari not allows to delete dataset property
519
584
  try {
520
585
  delete element.dataset[name];
521
- } catch (e) {
586
+ } catch (error) {
522
587
  element.dataset[name] = undefined;
523
588
  }
524
589
  } else {
525
- element.removeAttribute('data-' + hyphenate(name));
590
+ element.removeAttribute("data-".concat(toParamCase(name)));
526
591
  }
527
592
  }
528
-
529
593
  var REGEXP_SPACES = /\s\s*/;
594
+
530
595
  var onceSupported = function () {
531
596
  var supported = false;
532
597
 
533
- if (IN_BROWSER) {
598
+ if (IS_BROWSER) {
534
599
  var once = false;
600
+
535
601
  var listener = function listener() {};
602
+
536
603
  var options = Object.defineProperty({}, 'once', {
537
- get: function get$$1() {
604
+ get: function get() {
538
605
  supported = true;
539
606
  return once;
540
607
  },
541
608
 
542
-
543
609
  /**
544
610
  * This setter can fix a `TypeError` in strict mode
545
611
  * {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Getter_only}
546
612
  * @param {boolean} value - The value to set
547
613
  */
548
- set: function set$$1(value) {
614
+ set: function set(value) {
549
615
  once = value;
550
616
  }
551
617
  });
552
-
553
618
  WINDOW.addEventListener('test', listener, options);
554
619
  WINDOW.removeEventListener('test', listener, options);
555
620
  }
556
621
 
557
622
  return supported;
558
623
  }();
559
-
560
624
  /**
561
625
  * Remove event listener from the target element.
562
626
  * @param {Element} element - The event target.
@@ -564,16 +628,15 @@
564
628
  * @param {Function} listener - The event listener.
565
629
  * @param {Object} options - The event options.
566
630
  */
631
+
632
+
567
633
  function removeListener(element, type, listener) {
568
634
  var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
569
-
570
635
  var handler = listener;
571
-
572
636
  type.trim().split(REGEXP_SPACES).forEach(function (event) {
573
637
  if (!onceSupported) {
574
638
  var listeners = element.listeners;
575
639
 
576
-
577
640
  if (listeners && listeners[event] && listeners[event][listener]) {
578
641
  handler = listeners[event][listener];
579
642
  delete listeners[event][listener];
@@ -591,7 +654,6 @@
591
654
  element.removeEventListener(event, handler, options);
592
655
  });
593
656
  }
594
-
595
657
  /**
596
658
  * Add event listener to the target element.
597
659
  * @param {Element} element - The event target.
@@ -599,24 +661,23 @@
599
661
  * @param {Function} listener - The event listener.
600
662
  * @param {Object} options - The event options.
601
663
  */
664
+
602
665
  function addListener(element, type, listener) {
603
666
  var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
604
-
605
667
  var _handler = listener;
606
-
607
668
  type.trim().split(REGEXP_SPACES).forEach(function (event) {
608
669
  if (options.once && !onceSupported) {
609
670
  var _element$listeners = element.listeners,
610
- listeners = _element$listeners === undefined ? {} : _element$listeners;
611
-
671
+ listeners = _element$listeners === void 0 ? {} : _element$listeners;
612
672
 
613
673
  _handler = function handler() {
614
- for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
674
+ delete listeners[event][listener];
675
+ element.removeEventListener(event, _handler, options);
676
+
677
+ for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
615
678
  args[_key2] = arguments[_key2];
616
679
  }
617
680
 
618
- delete listeners[event][listener];
619
- element.removeEventListener(event, _handler, options);
620
681
  listener.apply(element, args);
621
682
  };
622
683
 
@@ -635,7 +696,6 @@
635
696
  element.addEventListener(event, _handler, options);
636
697
  });
637
698
  }
638
-
639
699
  /**
640
700
  * Dispatch event on the target element.
641
701
  * @param {Element} element - The event target.
@@ -643,10 +703,10 @@
643
703
  * @param {Object} data - The additional event data.
644
704
  * @returns {boolean} Indicate if the event is default prevented or not.
645
705
  */
706
+
646
707
  function dispatchEvent(element, type, data) {
647
- var event = void 0;
708
+ var event; // Event and CustomEvent on IE9-11 are global objects, not constructors
648
709
 
649
- // Event and CustomEvent on IE9-11 are global objects, not constructors
650
710
  if (isFunction(Event) && isFunction(CustomEvent)) {
651
711
  event = new CustomEvent(type, {
652
712
  detail: data,
@@ -660,103 +720,95 @@
660
720
 
661
721
  return element.dispatchEvent(event);
662
722
  }
663
-
664
723
  /**
665
724
  * Get the offset base on the document.
666
725
  * @param {Element} element - The target element.
667
726
  * @returns {Object} The offset data.
668
727
  */
728
+
669
729
  function getOffset(element) {
670
730
  var box = element.getBoundingClientRect();
671
-
672
731
  return {
673
732
  left: box.left + (window.pageXOffset - document.documentElement.clientLeft),
674
733
  top: box.top + (window.pageYOffset - document.documentElement.clientTop)
675
734
  };
676
735
  }
677
-
678
736
  var location = WINDOW.location;
679
-
680
- var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i;
681
-
737
+ var REGEXP_ORIGINS = /^(\w+:)\/\/([^:/?#]*):?(\d*)/i;
682
738
  /**
683
739
  * Check if the given URL is a cross origin URL.
684
740
  * @param {string} url - The target URL.
685
741
  * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`.
686
742
  */
743
+
687
744
  function isCrossOriginURL(url) {
688
745
  var parts = url.match(REGEXP_ORIGINS);
689
-
690
- return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port);
746
+ return parts !== null && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port);
691
747
  }
692
-
693
748
  /**
694
749
  * Add timestamp to the given URL.
695
750
  * @param {string} url - The target URL.
696
751
  * @returns {string} The result URL.
697
752
  */
698
- function addTimestamp(url) {
699
- var timestamp = 'timestamp=' + new Date().getTime();
700
753
 
754
+ function addTimestamp(url) {
755
+ var timestamp = "timestamp=".concat(new Date().getTime());
701
756
  return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp;
702
757
  }
703
-
704
758
  /**
705
759
  * Get transforms base on the given object.
706
760
  * @param {Object} obj - The target object.
707
761
  * @returns {string} A string contains transform values.
708
762
  */
763
+
709
764
  function getTransforms(_ref) {
710
765
  var rotate = _ref.rotate,
711
766
  scaleX = _ref.scaleX,
712
767
  scaleY = _ref.scaleY,
713
768
  translateX = _ref.translateX,
714
769
  translateY = _ref.translateY;
715
-
716
770
  var values = [];
717
771
 
718
772
  if (isNumber(translateX) && translateX !== 0) {
719
- values.push('translateX(' + translateX + 'px)');
773
+ values.push("translateX(".concat(translateX, "px)"));
720
774
  }
721
775
 
722
776
  if (isNumber(translateY) && translateY !== 0) {
723
- values.push('translateY(' + translateY + 'px)');
724
- }
777
+ values.push("translateY(".concat(translateY, "px)"));
778
+ } // Rotate should come first before scale to match orientation transform
779
+
725
780
 
726
- // Rotate should come first before scale to match orientation transform
727
781
  if (isNumber(rotate) && rotate !== 0) {
728
- values.push('rotate(' + rotate + 'deg)');
782
+ values.push("rotate(".concat(rotate, "deg)"));
729
783
  }
730
784
 
731
785
  if (isNumber(scaleX) && scaleX !== 1) {
732
- values.push('scaleX(' + scaleX + ')');
786
+ values.push("scaleX(".concat(scaleX, ")"));
733
787
  }
734
788
 
735
789
  if (isNumber(scaleY) && scaleY !== 1) {
736
- values.push('scaleY(' + scaleY + ')');
790
+ values.push("scaleY(".concat(scaleY, ")"));
737
791
  }
738
792
 
739
793
  var transform = values.length ? values.join(' ') : 'none';
740
-
741
794
  return {
742
795
  WebkitTransform: transform,
743
796
  msTransform: transform,
744
797
  transform: transform
745
798
  };
746
799
  }
747
-
748
800
  /**
749
801
  * Get the max ratio of a group of pointers.
750
802
  * @param {string} pointers - The target pointers.
751
803
  * @returns {number} The result ratio.
752
804
  */
805
+
753
806
  function getMaxZoomRatio(pointers) {
754
- var pointers2 = assign({}, pointers);
755
- var ratios = [];
807
+ var pointers2 = _objectSpread2({}, pointers);
756
808
 
809
+ var maxRatio = 0;
757
810
  forEach(pointers, function (pointer, pointerId) {
758
811
  delete pointers2[pointerId];
759
-
760
812
  forEach(pointers2, function (pointer2) {
761
813
  var x1 = Math.abs(pointer.startX - pointer2.startX);
762
814
  var y1 = Math.abs(pointer.startY - pointer2.startY);
@@ -766,89 +818,73 @@
766
818
  var z2 = Math.sqrt(x2 * x2 + y2 * y2);
767
819
  var ratio = (z2 - z1) / z1;
768
820
 
769
- ratios.push(ratio);
821
+ if (Math.abs(ratio) > Math.abs(maxRatio)) {
822
+ maxRatio = ratio;
823
+ }
770
824
  });
771
825
  });
772
-
773
- ratios.sort(function (a, b) {
774
- return Math.abs(a) < Math.abs(b);
775
- });
776
-
777
- return ratios[0];
826
+ return maxRatio;
778
827
  }
779
-
780
828
  /**
781
829
  * Get a pointer from an event object.
782
830
  * @param {Object} event - The target event object.
783
831
  * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not.
784
832
  * @returns {Object} The result pointer contains start and/or end point coordinates.
785
833
  */
834
+
786
835
  function getPointer(_ref2, endOnly) {
787
836
  var pageX = _ref2.pageX,
788
837
  pageY = _ref2.pageY;
789
-
790
838
  var end = {
791
839
  endX: pageX,
792
840
  endY: pageY
793
841
  };
794
-
795
- return endOnly ? end : assign({
842
+ return endOnly ? end : _objectSpread2({
796
843
  startX: pageX,
797
844
  startY: pageY
798
845
  }, end);
799
846
  }
800
-
801
847
  /**
802
848
  * Get the center point coordinate of a group of pointers.
803
849
  * @param {Object} pointers - The target pointers.
804
850
  * @returns {Object} The center point coordinate.
805
851
  */
852
+
806
853
  function getPointersCenter(pointers) {
807
854
  var pageX = 0;
808
855
  var pageY = 0;
809
856
  var count = 0;
810
-
811
857
  forEach(pointers, function (_ref3) {
812
858
  var startX = _ref3.startX,
813
859
  startY = _ref3.startY;
814
-
815
860
  pageX += startX;
816
861
  pageY += startY;
817
862
  count += 1;
818
863
  });
819
-
820
864
  pageX /= count;
821
865
  pageY /= count;
822
-
823
866
  return {
824
867
  pageX: pageX,
825
868
  pageY: pageY
826
869
  };
827
870
  }
828
-
829
- /**
830
- * Check if the given value is a finite number.
831
- */
832
- var isFinite = Number.isFinite || WINDOW.isFinite;
833
-
834
871
  /**
835
872
  * Get the max sizes in a rectangle under the given aspect ratio.
836
873
  * @param {Object} data - The original sizes.
837
874
  * @param {string} [type='contain'] - The adjust type.
838
875
  * @returns {Object} The result sizes.
839
876
  */
877
+
840
878
  function getAdjustedSizes(_ref4) // or 'cover'
841
879
  {
842
880
  var aspectRatio = _ref4.aspectRatio,
843
881
  height = _ref4.height,
844
882
  width = _ref4.width;
845
883
  var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'contain';
884
+ var isValidWidth = isPositiveNumber(width);
885
+ var isValidHeight = isPositiveNumber(height);
846
886
 
847
- var isValidNumber = function isValidNumber(value) {
848
- return isFinite(value) && value > 0;
849
- };
850
-
851
- if (isValidNumber(width) && isValidNumber(height)) {
887
+ if (isValidWidth && isValidHeight) {
852
888
  var adjustedWidth = height * aspectRatio;
853
889
 
854
890
  if (type === 'contain' && adjustedWidth > width || type === 'cover' && adjustedWidth < width) {
@@ -856,9 +892,9 @@
856
892
  } else {
857
893
  width = height * aspectRatio;
858
894
  }
859
- } else if (isValidNumber(width)) {
895
+ } else if (isValidWidth) {
860
896
  height = width / aspectRatio;
861
- } else if (isValidNumber(height)) {
897
+ } else if (isValidHeight) {
862
898
  width = height * aspectRatio;
863
899
  }
864
900
 
@@ -867,17 +903,16 @@
867
903
  height: height
868
904
  };
869
905
  }
870
-
871
906
  /**
872
907
  * Get the new sizes of a rectangle after rotated.
873
908
  * @param {Object} data - The original sizes.
874
909
  * @returns {Object} The result sizes.
875
910
  */
911
+
876
912
  function getRotatedSizes(_ref5) {
877
913
  var width = _ref5.width,
878
914
  height = _ref5.height,
879
915
  degree = _ref5.degree;
880
-
881
916
  degree = Math.abs(degree) % 180;
882
917
 
883
918
  if (degree === 90) {
@@ -892,7 +927,6 @@
892
927
  var cosArc = Math.cos(arc);
893
928
  var newWidth = width * cosArc + height * sinArc;
894
929
  var newHeight = width * sinArc + height * cosArc;
895
-
896
930
  return degree > 90 ? {
897
931
  width: newHeight,
898
932
  height: newWidth
@@ -901,7 +935,6 @@
901
935
  height: newHeight
902
936
  };
903
937
  }
904
-
905
938
  /**
906
939
  * Get a canvas which drew the given image.
907
940
  * @param {HTMLImageElement} image - The image for drawing.
@@ -910,34 +943,34 @@
910
943
  * @param {Object} options - The options.
911
944
  * @returns {HTMLCanvasElement} The result canvas.
912
945
  */
946
+
913
947
  function getSourceCanvas(image, _ref6, _ref7, _ref8) {
914
948
  var imageAspectRatio = _ref6.aspectRatio,
915
949
  imageNaturalWidth = _ref6.naturalWidth,
916
950
  imageNaturalHeight = _ref6.naturalHeight,
917
951
  _ref6$rotate = _ref6.rotate,
918
- rotate = _ref6$rotate === undefined ? 0 : _ref6$rotate,
952
+ rotate = _ref6$rotate === void 0 ? 0 : _ref6$rotate,
919
953
  _ref6$scaleX = _ref6.scaleX,
920
- scaleX = _ref6$scaleX === undefined ? 1 : _ref6$scaleX,
954
+ scaleX = _ref6$scaleX === void 0 ? 1 : _ref6$scaleX,
921
955
  _ref6$scaleY = _ref6.scaleY,
922
- scaleY = _ref6$scaleY === undefined ? 1 : _ref6$scaleY;
956
+ scaleY = _ref6$scaleY === void 0 ? 1 : _ref6$scaleY;
923
957
  var aspectRatio = _ref7.aspectRatio,
924
958
  naturalWidth = _ref7.naturalWidth,
925
959
  naturalHeight = _ref7.naturalHeight;
926
960
  var _ref8$fillColor = _ref8.fillColor,
927
- fillColor = _ref8$fillColor === undefined ? 'transparent' : _ref8$fillColor,
961
+ fillColor = _ref8$fillColor === void 0 ? 'transparent' : _ref8$fillColor,
928
962
  _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled,
929
- imageSmoothingEnabled = _ref8$imageSmoothingE === undefined ? true : _ref8$imageSmoothingE,
963
+ imageSmoothingEnabled = _ref8$imageSmoothingE === void 0 ? true : _ref8$imageSmoothingE,
930
964
  _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality,
931
- imageSmoothingQuality = _ref8$imageSmoothingQ === undefined ? 'low' : _ref8$imageSmoothingQ,
965
+ imageSmoothingQuality = _ref8$imageSmoothingQ === void 0 ? 'low' : _ref8$imageSmoothingQ,
932
966
  _ref8$maxWidth = _ref8.maxWidth,
933
- maxWidth = _ref8$maxWidth === undefined ? Infinity : _ref8$maxWidth,
967
+ maxWidth = _ref8$maxWidth === void 0 ? Infinity : _ref8$maxWidth,
934
968
  _ref8$maxHeight = _ref8.maxHeight,
935
- maxHeight = _ref8$maxHeight === undefined ? Infinity : _ref8$maxHeight,
969
+ maxHeight = _ref8$maxHeight === void 0 ? Infinity : _ref8$maxHeight,
936
970
  _ref8$minWidth = _ref8.minWidth,
937
- minWidth = _ref8$minWidth === undefined ? 0 : _ref8$minWidth,
971
+ minWidth = _ref8$minWidth === void 0 ? 0 : _ref8$minWidth,
938
972
  _ref8$minHeight = _ref8.minHeight,
939
- minHeight = _ref8$minHeight === undefined ? 0 : _ref8$minHeight;
940
-
973
+ minHeight = _ref8$minHeight === void 0 ? 0 : _ref8$minHeight;
941
974
  var canvas = document.createElement('canvas');
942
975
  var context = canvas.getContext('2d');
943
976
  var maxSizes = getAdjustedSizes({
@@ -951,10 +984,9 @@
951
984
  height: minHeight
952
985
  }, 'cover');
953
986
  var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth));
954
- var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight));
955
-
956
- // Note: should always use image's natural sizes for drawing as
987
+ var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); // Note: should always use image's natural sizes for drawing as
957
988
  // imageData.naturalWidth === canvasData.naturalHeight when rotate % 180 === 90
989
+
958
990
  var destMaxSizes = getAdjustedSizes({
959
991
  aspectRatio: imageAspectRatio,
960
992
  width: maxWidth,
@@ -968,7 +1000,6 @@
968
1000
  var destWidth = Math.min(destMaxSizes.width, Math.max(destMinSizes.width, imageNaturalWidth));
969
1001
  var destHeight = Math.min(destMaxSizes.height, Math.max(destMinSizes.height, imageNaturalHeight));
970
1002
  var params = [-destWidth / 2, -destHeight / 2, destWidth, destHeight];
971
-
972
1003
  canvas.width = normalizeDecimalNumber(width);
973
1004
  canvas.height = normalizeDecimalNumber(height);
974
1005
  context.fillStyle = fillColor;
@@ -979,15 +1010,13 @@
979
1010
  context.scale(scaleX, scaleY);
980
1011
  context.imageSmoothingEnabled = imageSmoothingEnabled;
981
1012
  context.imageSmoothingQuality = imageSmoothingQuality;
982
- context.drawImage.apply(context, [image].concat(toConsumableArray(params.map(function (param) {
1013
+ context.drawImage.apply(context, [image].concat(_toConsumableArray(params.map(function (param) {
983
1014
  return Math.floor(normalizeDecimalNumber(param));
984
1015
  }))));
985
1016
  context.restore();
986
1017
  return canvas;
987
1018
  }
988
-
989
1019
  var fromCharCode = String.fromCharCode;
990
-
991
1020
  /**
992
1021
  * Get string from char code in data view.
993
1022
  * @param {DataView} dataView - The data view for read.
@@ -998,140 +1027,139 @@
998
1027
 
999
1028
  function getStringFromCharCode(dataView, start, length) {
1000
1029
  var str = '';
1001
- var i = void 0;
1002
-
1003
1030
  length += start;
1004
1031
 
1005
- for (i = start; i < length; i += 1) {
1032
+ for (var i = start; i < length; i += 1) {
1006
1033
  str += fromCharCode(dataView.getUint8(i));
1007
1034
  }
1008
1035
 
1009
1036
  return str;
1010
1037
  }
1011
-
1012
1038
  var REGEXP_DATA_URL_HEAD = /^data:.*,/;
1013
-
1014
1039
  /**
1015
1040
  * Transform Data URL to array buffer.
1016
1041
  * @param {string} dataURL - The Data URL to transform.
1017
1042
  * @returns {ArrayBuffer} The result array buffer.
1018
1043
  */
1044
+
1019
1045
  function dataURLToArrayBuffer(dataURL) {
1020
1046
  var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, '');
1021
1047
  var binary = atob(base64);
1022
1048
  var arrayBuffer = new ArrayBuffer(binary.length);
1023
1049
  var uint8 = new Uint8Array(arrayBuffer);
1024
-
1025
1050
  forEach(uint8, function (value, i) {
1026
1051
  uint8[i] = binary.charCodeAt(i);
1027
1052
  });
1028
-
1029
1053
  return arrayBuffer;
1030
1054
  }
1031
-
1032
1055
  /**
1033
1056
  * Transform array buffer to Data URL.
1034
1057
  * @param {ArrayBuffer} arrayBuffer - The array buffer to transform.
1035
1058
  * @param {string} mimeType - The mime type of the Data URL.
1036
1059
  * @returns {string} The result Data URL.
1037
1060
  */
1061
+
1038
1062
  function arrayBufferToDataURL(arrayBuffer, mimeType) {
1063
+ var chunks = []; // Chunk Typed Array for better performance (#435)
1064
+
1065
+ var chunkSize = 8192;
1039
1066
  var uint8 = new Uint8Array(arrayBuffer);
1040
- var data = '';
1041
1067
 
1042
- // TypedArray.prototype.forEach is not supported in some browsers as IE.
1043
- if (isFunction(uint8.forEach)) {
1044
- // Use native `forEach` method first for better performance
1045
- uint8.forEach(function (value) {
1046
- data += fromCharCode(value);
1047
- });
1048
- } else {
1049
- forEach(uint8, function (value) {
1050
- data += fromCharCode(value);
1051
- });
1068
+ while (uint8.length > 0) {
1069
+ // XXX: Babel's `toConsumableArray` helper will throw error in IE or Safari 9
1070
+ // eslint-disable-next-line prefer-spread
1071
+ chunks.push(fromCharCode.apply(null, toArray(uint8.subarray(0, chunkSize))));
1072
+ uint8 = uint8.subarray(chunkSize);
1052
1073
  }
1053
1074
 
1054
- return 'data:' + mimeType + ';base64,' + btoa(data);
1075
+ return "data:".concat(mimeType, ";base64,").concat(btoa(chunks.join('')));
1055
1076
  }
1056
-
1057
1077
  /**
1058
1078
  * Get orientation value from given array buffer.
1059
1079
  * @param {ArrayBuffer} arrayBuffer - The array buffer to read.
1060
1080
  * @returns {number} The read orientation value.
1061
1081
  */
1062
- function getOrientation(arrayBuffer) {
1082
+
1083
+ function resetAndGetOrientation(arrayBuffer) {
1063
1084
  var dataView = new DataView(arrayBuffer);
1064
- var orientation = void 0;
1065
- var littleEndian = void 0;
1066
- var app1Start = void 0;
1067
- var ifdStart = void 0;
1068
-
1069
- // Only handle JPEG image (start by 0xFFD8)
1070
- if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
1071
- var length = dataView.byteLength;
1072
- var offset = 2;
1073
-
1074
- while (offset < length) {
1075
- if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
1076
- app1Start = offset;
1077
- break;
1078
- }
1085
+ var orientation; // Ignores range error when the image does not have correct Exif information
1079
1086
 
1080
- offset += 1;
1081
- }
1082
- }
1087
+ try {
1088
+ var littleEndian;
1089
+ var app1Start;
1090
+ var ifdStart; // Only handle JPEG image (start by 0xFFD8)
1091
+
1092
+ if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) {
1093
+ var length = dataView.byteLength;
1094
+ var offset = 2;
1095
+
1096
+ while (offset + 1 < length) {
1097
+ if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) {
1098
+ app1Start = offset;
1099
+ break;
1100
+ }
1083
1101
 
1084
- if (app1Start) {
1085
- var exifIDCode = app1Start + 4;
1086
- var tiffOffset = app1Start + 10;
1102
+ offset += 1;
1103
+ }
1104
+ }
1087
1105
 
1088
- if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
1089
- var endianness = dataView.getUint16(tiffOffset);
1106
+ if (app1Start) {
1107
+ var exifIDCode = app1Start + 4;
1108
+ var tiffOffset = app1Start + 10;
1090
1109
 
1091
- littleEndian = endianness === 0x4949;
1110
+ if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') {
1111
+ var endianness = dataView.getUint16(tiffOffset);
1112
+ littleEndian = endianness === 0x4949;
1092
1113
 
1093
- if (littleEndian || endianness === 0x4D4D /* bigEndian */) {
1094
- if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
1095
- var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
1114
+ if (littleEndian || endianness === 0x4D4D
1115
+ /* bigEndian */
1116
+ ) {
1117
+ if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) {
1118
+ var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian);
1096
1119
 
1097
- if (firstIFDOffset >= 0x00000008) {
1098
- ifdStart = tiffOffset + firstIFDOffset;
1120
+ if (firstIFDOffset >= 0x00000008) {
1121
+ ifdStart = tiffOffset + firstIFDOffset;
1122
+ }
1099
1123
  }
1100
1124
  }
1101
- }
1125
+ }
1102
1126
  }
1103
- }
1104
1127
 
1105
- if (ifdStart) {
1106
- var _length = dataView.getUint16(ifdStart, littleEndian);
1107
- var _offset = void 0;
1108
- var i = void 0;
1128
+ if (ifdStart) {
1129
+ var _length = dataView.getUint16(ifdStart, littleEndian);
1109
1130
 
1110
- for (i = 0; i < _length; i += 1) {
1111
- _offset = ifdStart + i * 12 + 2;
1131
+ var _offset;
1112
1132
 
1113
- if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) {
1114
- // 8 is the offset of the current tag's value
1115
- _offset += 8;
1133
+ var i;
1116
1134
 
1117
- // Get the original orientation value
1118
- orientation = dataView.getUint16(_offset, littleEndian);
1135
+ for (i = 0; i < _length; i += 1) {
1136
+ _offset = ifdStart + i * 12 + 2;
1119
1137
 
1120
- // Override the orientation with its default value
1121
- dataView.setUint16(_offset, 1, littleEndian);
1122
- break;
1123
- }
1138
+ if (dataView.getUint16(_offset, littleEndian) === 0x0112
1139
+ /* Orientation */
1140
+ ) {
1141
+ // 8 is the offset of the current tag's value
1142
+ _offset += 8; // Get the original orientation value
1143
+
1144
+ orientation = dataView.getUint16(_offset, littleEndian); // Override the orientation with its default value
1145
+
1146
+ dataView.setUint16(_offset, 1, littleEndian);
1147
+ break;
1148
+ }
1149
+ }
1124
1150
  }
1151
+ } catch (error) {
1152
+ orientation = 1;
1125
1153
  }
1126
1154
 
1127
1155
  return orientation;
1128
1156
  }
1129
-
1130
1157
  /**
1131
1158
  * Parse Exif Orientation value.
1132
1159
  * @param {number} orientation - The orientation to parse.
1133
1160
  * @returns {Object} The parsed result.
1134
1161
  */
1162
+
1135
1163
  function parseOrientation(orientation) {
1136
1164
  var rotate = 0;
1137
1165
  var scaleX = 1;
@@ -1142,40 +1170,38 @@
1142
1170
  case 2:
1143
1171
  scaleX = -1;
1144
1172
  break;
1145
-
1146
1173
  // Rotate left 180°
1174
+
1147
1175
  case 3:
1148
1176
  rotate = -180;
1149
1177
  break;
1150
-
1151
1178
  // Flip vertical
1179
+
1152
1180
  case 4:
1153
1181
  scaleY = -1;
1154
1182
  break;
1155
-
1156
1183
  // Flip vertical and rotate right 90°
1184
+
1157
1185
  case 5:
1158
1186
  rotate = 90;
1159
1187
  scaleY = -1;
1160
1188
  break;
1161
-
1162
1189
  // Rotate right 90°
1190
+
1163
1191
  case 6:
1164
1192
  rotate = 90;
1165
1193
  break;
1166
-
1167
1194
  // Flip horizontal and rotate right 90°
1195
+
1168
1196
  case 7:
1169
1197
  rotate = 90;
1170
1198
  scaleX = -1;
1171
1199
  break;
1172
-
1173
1200
  // Rotate left 90°
1201
+
1174
1202
  case 8:
1175
1203
  rotate = -90;
1176
1204
  break;
1177
-
1178
- default:
1179
1205
  }
1180
1206
 
1181
1207
  return {
@@ -1201,34 +1227,27 @@
1201
1227
  options = this.options,
1202
1228
  container = this.container,
1203
1229
  cropper = this.cropper;
1204
-
1205
-
1230
+ var minWidth = Number(options.minContainerWidth);
1231
+ var minHeight = Number(options.minContainerHeight);
1206
1232
  addClass(cropper, CLASS_HIDDEN);
1207
1233
  removeClass(element, CLASS_HIDDEN);
1208
-
1209
1234
  var containerData = {
1210
- width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200),
1211
- height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100)
1235
+ width: Math.max(container.offsetWidth, minWidth >= 0 ? minWidth : MIN_CONTAINER_WIDTH),
1236
+ height: Math.max(container.offsetHeight, minHeight >= 0 ? minHeight : MIN_CONTAINER_HEIGHT)
1212
1237
  };
1213
-
1214
1238
  this.containerData = containerData;
1215
-
1216
1239
  setStyle(cropper, {
1217
1240
  width: containerData.width,
1218
1241
  height: containerData.height
1219
1242
  });
1220
-
1221
1243
  addClass(element, CLASS_HIDDEN);
1222
1244
  removeClass(cropper, CLASS_HIDDEN);
1223
1245
  },
1224
-
1225
-
1226
1246
  // Canvas (image wrapper)
1227
1247
  initCanvas: function initCanvas() {
1228
1248
  var containerData = this.containerData,
1229
1249
  imageData = this.imageData;
1230
1250
  var viewMode = this.options.viewMode;
1231
-
1232
1251
  var rotated = Math.abs(imageData.rotate) % 180 === 90;
1233
1252
  var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth;
1234
1253
  var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight;
@@ -1255,16 +1274,15 @@
1255
1274
  width: canvasWidth,
1256
1275
  height: canvasHeight
1257
1276
  };
1258
-
1259
- canvasData.left = (containerData.width - canvasWidth) / 2;
1260
- canvasData.top = (containerData.height - canvasHeight) / 2;
1261
- canvasData.oldLeft = canvasData.left;
1262
- canvasData.oldTop = canvasData.top;
1263
-
1264
1277
  this.canvasData = canvasData;
1265
1278
  this.limited = viewMode === 1 || viewMode === 2;
1266
1279
  this.limitCanvas(true, true);
1267
- this.initialImageData = assign({}, imageData);
1280
+ canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth);
1281
+ canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight);
1282
+ canvasData.left = (containerData.width - canvasData.width) / 2;
1283
+ canvasData.top = (containerData.height - canvasData.height) / 2;
1284
+ canvasData.oldLeft = canvasData.left;
1285
+ canvasData.oldTop = canvasData.top;
1268
1286
  this.initialCanvasData = assign({}, canvasData);
1269
1287
  },
1270
1288
  limitCanvas: function limitCanvas(sizeLimited, positionLimited) {
@@ -1274,7 +1292,6 @@
1274
1292
  cropBoxData = this.cropBoxData;
1275
1293
  var viewMode = options.viewMode;
1276
1294
  var aspectRatio = canvasData.aspectRatio;
1277
-
1278
1295
  var cropped = this.cropped && cropBoxData;
1279
1296
 
1280
1297
  if (sizeLimited) {
@@ -1317,8 +1334,6 @@
1317
1334
 
1318
1335
  minCanvasWidth = _getAdjustedSizes.width;
1319
1336
  minCanvasHeight = _getAdjustedSizes.height;
1320
-
1321
-
1322
1337
  canvasData.minWidth = minCanvasWidth;
1323
1338
  canvasData.minHeight = minCanvasHeight;
1324
1339
  canvasData.maxWidth = Infinity;
@@ -1329,7 +1344,6 @@
1329
1344
  if (viewMode > (cropped ? 0 : 1)) {
1330
1345
  var newCanvasLeft = containerData.width - canvasData.width;
1331
1346
  var newCanvasTop = containerData.height - canvasData.height;
1332
-
1333
1347
  canvasData.minLeft = Math.min(0, newCanvasLeft);
1334
1348
  canvasData.minTop = Math.min(0, newCanvasTop);
1335
1349
  canvasData.maxLeft = Math.max(0, newCanvasLeft);
@@ -1365,7 +1379,6 @@
1365
1379
  var canvasData = this.canvasData,
1366
1380
  imageData = this.imageData;
1367
1381
 
1368
-
1369
1382
  if (transformed) {
1370
1383
  var _getRotatedSizes = getRotatedSizes({
1371
1384
  width: imageData.naturalWidth * Math.abs(imageData.scaleX || 1),
@@ -1377,7 +1390,6 @@
1377
1390
 
1378
1391
  var width = canvasData.width * (naturalWidth / canvasData.naturalWidth);
1379
1392
  var height = canvasData.height * (naturalHeight / canvasData.naturalHeight);
1380
-
1381
1393
  canvasData.left -= (width - canvasData.width) / 2;
1382
1394
  canvasData.top -= (height - canvasData.height) / 2;
1383
1395
  canvasData.width = width;
@@ -1398,14 +1410,11 @@
1398
1410
 
1399
1411
  canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth);
1400
1412
  canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight);
1401
-
1402
1413
  this.limitCanvas(false, true);
1403
-
1404
1414
  canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft);
1405
1415
  canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop);
1406
1416
  canvasData.oldLeft = canvasData.left;
1407
1417
  canvasData.oldTop = canvasData.top;
1408
-
1409
1418
  setStyle(this.canvas, assign({
1410
1419
  width: canvasData.width,
1411
1420
  height: canvasData.height
@@ -1413,7 +1422,6 @@
1413
1422
  translateX: canvasData.left,
1414
1423
  translateY: canvasData.top
1415
1424
  })));
1416
-
1417
1425
  this.renderImage(changed);
1418
1426
 
1419
1427
  if (this.cropped && this.limited) {
@@ -1423,10 +1431,8 @@
1423
1431
  renderImage: function renderImage(changed) {
1424
1432
  var canvasData = this.canvasData,
1425
1433
  imageData = this.imageData;
1426
-
1427
1434
  var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth);
1428
1435
  var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight);
1429
-
1430
1436
  assign(imageData, {
1431
1437
  width: width,
1432
1438
  height: height,
@@ -1448,7 +1454,6 @@
1448
1454
  initCropBox: function initCropBox() {
1449
1455
  var options = this.options,
1450
1456
  canvasData = this.canvasData;
1451
-
1452
1457
  var aspectRatio = options.aspectRatio || options.initialAspectRatio;
1453
1458
  var autoCropArea = Number(options.autoCropArea) || 0.8;
1454
1459
  var cropBoxData = {
@@ -1465,20 +1470,17 @@
1465
1470
  }
1466
1471
 
1467
1472
  this.cropBoxData = cropBoxData;
1468
- this.limitCropBox(true, true);
1473
+ this.limitCropBox(true, true); // Initialize auto crop area
1469
1474
 
1470
- // Initialize auto crop area
1471
1475
  cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);
1472
- cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight);
1476
+ cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); // The width/height of auto crop area must large than "minWidth/Height"
1473
1477
 
1474
- // The width/height of auto crop area must large than "minWidth/Height"
1475
1478
  cropBoxData.width = Math.max(cropBoxData.minWidth, cropBoxData.width * autoCropArea);
1476
1479
  cropBoxData.height = Math.max(cropBoxData.minHeight, cropBoxData.height * autoCropArea);
1477
1480
  cropBoxData.left = canvasData.left + (canvasData.width - cropBoxData.width) / 2;
1478
1481
  cropBoxData.top = canvasData.top + (canvasData.height - cropBoxData.height) / 2;
1479
1482
  cropBoxData.oldLeft = cropBoxData.left;
1480
1483
  cropBoxData.oldTop = cropBoxData.top;
1481
-
1482
1484
  this.initialCropBoxData = assign({}, cropBoxData);
1483
1485
  },
1484
1486
  limitCropBox: function limitCropBox(sizeLimited, positionLimited) {
@@ -1489,14 +1491,12 @@
1489
1491
  limited = this.limited;
1490
1492
  var aspectRatio = options.aspectRatio;
1491
1493
 
1492
-
1493
1494
  if (sizeLimited) {
1494
1495
  var minCropBoxWidth = Number(options.minCropBoxWidth) || 0;
1495
1496
  var minCropBoxHeight = Number(options.minCropBoxHeight) || 0;
1496
1497
  var maxCropBoxWidth = limited ? Math.min(containerData.width, canvasData.width, canvasData.width + canvasData.left, containerData.width - canvasData.left) : containerData.width;
1497
- var maxCropBoxHeight = limited ? Math.min(containerData.height, canvasData.height, canvasData.height + canvasData.top, containerData.height - canvasData.top) : containerData.height;
1498
+ var maxCropBoxHeight = limited ? Math.min(containerData.height, canvasData.height, canvasData.height + canvasData.top, containerData.height - canvasData.top) : containerData.height; // The min/maxCropBoxWidth/Height must be less than container's width/height
1498
1499
 
1499
- // The min/maxCropBoxWidth/Height must be less than container's width/height
1500
1500
  minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width);
1501
1501
  minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height);
1502
1502
 
@@ -1518,9 +1518,9 @@
1518
1518
  } else {
1519
1519
  maxCropBoxWidth = maxCropBoxHeight * aspectRatio;
1520
1520
  }
1521
- }
1521
+ } // The minWidth/Height must be less than maxWidth/Height
1522
+
1522
1523
 
1523
- // The minWidth/Height must be less than maxWidth/Height
1524
1524
  cropBoxData.minWidth = Math.min(minCropBoxWidth, maxCropBoxWidth);
1525
1525
  cropBoxData.minHeight = Math.min(minCropBoxHeight, maxCropBoxHeight);
1526
1526
  cropBoxData.maxWidth = maxCropBoxWidth;
@@ -1546,7 +1546,6 @@
1546
1546
  containerData = this.containerData,
1547
1547
  cropBoxData = this.cropBoxData;
1548
1548
 
1549
-
1550
1549
  if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) {
1551
1550
  cropBoxData.left = cropBoxData.oldLeft;
1552
1551
  }
@@ -1557,9 +1556,7 @@
1557
1556
 
1558
1557
  cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth);
1559
1558
  cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight);
1560
-
1561
1559
  this.limitCropBox(false, true);
1562
-
1563
1560
  cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft);
1564
1561
  cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop);
1565
1562
  cropBoxData.oldLeft = cropBoxData.left;
@@ -1594,10 +1591,11 @@
1594
1591
 
1595
1592
  var preview = {
1596
1593
  initPreview: function initPreview() {
1597
- var crossOrigin = this.crossOrigin;
1594
+ var element = this.element,
1595
+ crossOrigin = this.crossOrigin;
1598
1596
  var preview = this.options.preview;
1599
-
1600
1597
  var url = crossOrigin ? this.crossOriginUrl : this.url;
1598
+ var alt = element.alt || 'The image to preview';
1601
1599
  var image = document.createElement('img');
1602
1600
 
1603
1601
  if (crossOrigin) {
@@ -1605,6 +1603,7 @@
1605
1603
  }
1606
1604
 
1607
1605
  image.src = url;
1606
+ image.alt = alt;
1608
1607
  this.viewBox.appendChild(image);
1609
1608
  this.viewBoxImage = image;
1610
1609
 
@@ -1615,17 +1614,15 @@
1615
1614
  var previews = preview;
1616
1615
 
1617
1616
  if (typeof preview === 'string') {
1618
- previews = this.element.ownerDocument.querySelectorAll(preview);
1617
+ previews = element.ownerDocument.querySelectorAll(preview);
1619
1618
  } else if (preview.querySelector) {
1620
1619
  previews = [preview];
1621
1620
  }
1622
1621
 
1623
1622
  this.previews = previews;
1624
-
1625
1623
  forEach(previews, function (el) {
1626
- var img = document.createElement('img');
1624
+ var img = document.createElement('img'); // Save the original size for recover
1627
1625
 
1628
- // Save the original size for recover
1629
1626
  setData(el, DATA_PREVIEW, {
1630
1627
  width: el.offsetWidth,
1631
1628
  height: el.offsetHeight,
@@ -1637,15 +1634,15 @@
1637
1634
  }
1638
1635
 
1639
1636
  img.src = url;
1640
-
1637
+ img.alt = alt;
1641
1638
  /**
1642
1639
  * Override img element styles
1643
1640
  * Add `display:block` to avoid margin top issue
1644
1641
  * Add `height:auto` to override `height` attribute on IE8
1645
1642
  * (Occur only when margin-top <= -height)
1646
1643
  */
1647
- img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;"';
1648
1644
 
1645
+ img.style.cssText = 'display:block;' + 'width:100%;' + 'height:auto;' + 'min-width:0!important;' + 'min-height:0!important;' + 'max-width:none!important;' + 'max-height:none!important;' + 'image-orientation:0deg!important;"';
1649
1646
  el.innerHTML = '';
1650
1647
  el.appendChild(img);
1651
1648
  });
@@ -1653,12 +1650,10 @@
1653
1650
  resetPreview: function resetPreview() {
1654
1651
  forEach(this.previews, function (element) {
1655
1652
  var data = getData(element, DATA_PREVIEW);
1656
-
1657
1653
  setStyle(element, {
1658
1654
  width: data.width,
1659
1655
  height: data.height
1660
1656
  });
1661
-
1662
1657
  element.innerHTML = data.html;
1663
1658
  removeData(element, DATA_PREVIEW);
1664
1659
  });
@@ -1671,7 +1666,6 @@
1671
1666
  cropBoxHeight = cropBoxData.height;
1672
1667
  var width = imageData.width,
1673
1668
  height = imageData.height;
1674
-
1675
1669
  var left = cropBoxData.left - canvasData.left - imageData.left;
1676
1670
  var top = cropBoxData.top - canvasData.top - imageData.top;
1677
1671
 
@@ -1686,7 +1680,6 @@
1686
1680
  translateX: -left,
1687
1681
  translateY: -top
1688
1682
  }, imageData))));
1689
-
1690
1683
  forEach(this.previews, function (element) {
1691
1684
  var data = getData(element, DATA_PREVIEW);
1692
1685
  var originalWidth = data.width;
@@ -1710,7 +1703,6 @@
1710
1703
  width: newWidth,
1711
1704
  height: newHeight
1712
1705
  });
1713
-
1714
1706
  setStyle(element.getElementsByTagName('img')[0], assign({
1715
1707
  width: width * ratio,
1716
1708
  height: height * ratio
@@ -1728,7 +1720,6 @@
1728
1720
  options = this.options,
1729
1721
  cropper = this.cropper;
1730
1722
 
1731
-
1732
1723
  if (isFunction(options.cropstart)) {
1733
1724
  addListener(element, EVENT_CROP_START, options.cropstart);
1734
1725
  }
@@ -1752,7 +1743,10 @@
1752
1743
  addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = this.cropStart.bind(this));
1753
1744
 
1754
1745
  if (options.zoomable && options.zoomOnWheel) {
1755
- addListener(cropper, EVENT_WHEEL, this.onWheel = this.wheel.bind(this));
1746
+ addListener(cropper, EVENT_WHEEL, this.onWheel = this.wheel.bind(this), {
1747
+ passive: false,
1748
+ capture: true
1749
+ });
1756
1750
  }
1757
1751
 
1758
1752
  if (options.toggleDragModeOnDblclick) {
@@ -1771,7 +1765,6 @@
1771
1765
  options = this.options,
1772
1766
  cropper = this.cropper;
1773
1767
 
1774
-
1775
1768
  if (isFunction(options.cropstart)) {
1776
1769
  removeListener(element, EVENT_CROP_START, options.cropstart);
1777
1770
  }
@@ -1795,7 +1788,10 @@
1795
1788
  removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart);
1796
1789
 
1797
1790
  if (options.zoomable && options.zoomOnWheel) {
1798
- removeListener(cropper, EVENT_WHEEL, this.onWheel);
1791
+ removeListener(cropper, EVENT_WHEEL, this.onWheel, {
1792
+ passive: false,
1793
+ capture: true
1794
+ });
1799
1795
  }
1800
1796
 
1801
1797
  if (options.toggleDragModeOnDblclick) {
@@ -1813,23 +1809,18 @@
1813
1809
 
1814
1810
  var handlers = {
1815
1811
  resize: function resize() {
1816
- var options = this.options,
1817
- container = this.container,
1818
- containerData = this.containerData;
1819
-
1820
- var minContainerWidth = Number(options.minContainerWidth) || 200;
1821
- var minContainerHeight = Number(options.minContainerHeight) || 100;
1822
-
1823
- if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) {
1812
+ if (this.disabled) {
1824
1813
  return;
1825
1814
  }
1826
1815
 
1827
- var ratio = container.offsetWidth / containerData.width;
1816
+ var options = this.options,
1817
+ container = this.container,
1818
+ containerData = this.containerData;
1819
+ var ratio = container.offsetWidth / containerData.width; // Resize when width changed or height changed
1828
1820
 
1829
- // Resize when width changed or height changed
1830
1821
  if (ratio !== 1 || container.offsetHeight !== containerData.height) {
1831
- var canvasData = void 0;
1832
- var cropBoxData = void 0;
1822
+ var canvasData;
1823
+ var cropBoxData;
1833
1824
 
1834
1825
  if (options.restore) {
1835
1826
  canvasData = this.getCanvasData();
@@ -1855,7 +1846,7 @@
1855
1846
 
1856
1847
  this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP);
1857
1848
  },
1858
- wheel: function wheel(e) {
1849
+ wheel: function wheel(event) {
1859
1850
  var _this = this;
1860
1851
 
1861
1852
  var ratio = Number(this.options.wheelZoomRatio) || 0.1;
@@ -1865,53 +1856,56 @@
1865
1856
  return;
1866
1857
  }
1867
1858
 
1868
- e.preventDefault();
1859
+ event.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21)
1869
1860
 
1870
- // Limit wheel speed to prevent zoom too fast (#21)
1871
1861
  if (this.wheeling) {
1872
1862
  return;
1873
1863
  }
1874
1864
 
1875
1865
  this.wheeling = true;
1876
-
1877
1866
  setTimeout(function () {
1878
1867
  _this.wheeling = false;
1879
1868
  }, 50);
1880
1869
 
1881
- if (e.deltaY) {
1882
- delta = e.deltaY > 0 ? 1 : -1;
1883
- } else if (e.wheelDelta) {
1884
- delta = -e.wheelDelta / 120;
1885
- } else if (e.detail) {
1886
- delta = e.detail > 0 ? 1 : -1;
1870
+ if (event.deltaY) {
1871
+ delta = event.deltaY > 0 ? 1 : -1;
1872
+ } else if (event.wheelDelta) {
1873
+ delta = -event.wheelDelta / 120;
1874
+ } else if (event.detail) {
1875
+ delta = event.detail > 0 ? 1 : -1;
1887
1876
  }
1888
1877
 
1889
- this.zoom(-delta * ratio, e);
1878
+ this.zoom(-delta * ratio, event);
1890
1879
  },
1891
- cropStart: function cropStart(e) {
1892
- if (this.disabled) {
1880
+ cropStart: function cropStart(event) {
1881
+ var buttons = event.buttons,
1882
+ button = event.button;
1883
+
1884
+ if (this.disabled // Handle mouse event and pointer event and ignore touch event
1885
+ || (event.type === 'mousedown' || event.type === 'pointerdown' && event.pointerType === 'mouse') && ( // No primary button (Usually the left button)
1886
+ isNumber(buttons) && buttons !== 1 || isNumber(button) && button !== 0 // Open context menu
1887
+ || event.ctrlKey)) {
1893
1888
  return;
1894
1889
  }
1895
1890
 
1896
1891
  var options = this.options,
1897
1892
  pointers = this.pointers;
1893
+ var action;
1898
1894
 
1899
- var action = void 0;
1900
-
1901
- if (e.changedTouches) {
1895
+ if (event.changedTouches) {
1902
1896
  // Handle touch event
1903
- forEach(e.changedTouches, function (touch) {
1897
+ forEach(event.changedTouches, function (touch) {
1904
1898
  pointers[touch.identifier] = getPointer(touch);
1905
1899
  });
1906
1900
  } else {
1907
1901
  // Handle mouse event and pointer event
1908
- pointers[e.pointerId || 0] = getPointer(e);
1902
+ pointers[event.pointerId || 0] = getPointer(event);
1909
1903
  }
1910
1904
 
1911
1905
  if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) {
1912
1906
  action = ACTION_ZOOM;
1913
1907
  } else {
1914
- action = getData(e.target, DATA_ACTION);
1908
+ action = getData(event.target, DATA_ACTION);
1915
1909
  }
1916
1910
 
1917
1911
  if (!REGEXP_ACTIONS.test(action)) {
@@ -1919,15 +1913,14 @@
1919
1913
  }
1920
1914
 
1921
1915
  if (dispatchEvent(this.element, EVENT_CROP_START, {
1922
- originalEvent: e,
1916
+ originalEvent: event,
1923
1917
  action: action
1924
1918
  }) === false) {
1925
1919
  return;
1926
- }
1920
+ } // This line is required for preventing page zooming in iOS browsers
1927
1921
 
1928
- // This line is required for preventing page zooming in iOS browsers
1929
- e.preventDefault();
1930
1922
 
1923
+ event.preventDefault();
1931
1924
  this.action = action;
1932
1925
  this.cropping = false;
1933
1926
 
@@ -1936,37 +1929,35 @@
1936
1929
  addClass(this.dragBox, CLASS_MODAL);
1937
1930
  }
1938
1931
  },
1939
- cropMove: function cropMove(e) {
1932
+ cropMove: function cropMove(event) {
1940
1933
  var action = this.action;
1941
1934
 
1942
-
1943
1935
  if (this.disabled || !action) {
1944
1936
  return;
1945
1937
  }
1946
1938
 
1947
1939
  var pointers = this.pointers;
1948
-
1949
-
1950
- e.preventDefault();
1940
+ event.preventDefault();
1951
1941
 
1952
1942
  if (dispatchEvent(this.element, EVENT_CROP_MOVE, {
1953
- originalEvent: e,
1943
+ originalEvent: event,
1954
1944
  action: action
1955
1945
  }) === false) {
1956
1946
  return;
1957
1947
  }
1958
1948
 
1959
- if (e.changedTouches) {
1960
- forEach(e.changedTouches, function (touch) {
1961
- assign(pointers[touch.identifier], getPointer(touch, true));
1949
+ if (event.changedTouches) {
1950
+ forEach(event.changedTouches, function (touch) {
1951
+ // The first parameter should not be undefined (#432)
1952
+ assign(pointers[touch.identifier] || {}, getPointer(touch, true));
1962
1953
  });
1963
1954
  } else {
1964
- assign(pointers[e.pointerId || 0], getPointer(e, true));
1955
+ assign(pointers[event.pointerId || 0] || {}, getPointer(event, true));
1965
1956
  }
1966
1957
 
1967
- this.change(e);
1958
+ this.change(event);
1968
1959
  },
1969
- cropEnd: function cropEnd(e) {
1960
+ cropEnd: function cropEnd(event) {
1970
1961
  if (this.disabled) {
1971
1962
  return;
1972
1963
  }
@@ -1974,20 +1965,19 @@
1974
1965
  var action = this.action,
1975
1966
  pointers = this.pointers;
1976
1967
 
1977
-
1978
- if (e.changedTouches) {
1979
- forEach(e.changedTouches, function (touch) {
1968
+ if (event.changedTouches) {
1969
+ forEach(event.changedTouches, function (touch) {
1980
1970
  delete pointers[touch.identifier];
1981
1971
  });
1982
1972
  } else {
1983
- delete pointers[e.pointerId || 0];
1973
+ delete pointers[event.pointerId || 0];
1984
1974
  }
1985
1975
 
1986
1976
  if (!action) {
1987
1977
  return;
1988
1978
  }
1989
1979
 
1990
- e.preventDefault();
1980
+ event.preventDefault();
1991
1981
 
1992
1982
  if (!Object.keys(pointers).length) {
1993
1983
  this.action = '';
@@ -1999,14 +1989,14 @@
1999
1989
  }
2000
1990
 
2001
1991
  dispatchEvent(this.element, EVENT_CROP_END, {
2002
- originalEvent: e,
1992
+ originalEvent: event,
2003
1993
  action: action
2004
1994
  });
2005
1995
  }
2006
1996
  };
2007
1997
 
2008
1998
  var change = {
2009
- change: function change(e) {
1999
+ change: function change(event) {
2010
2000
  var options = this.options,
2011
2001
  canvasData = this.canvasData,
2012
2002
  containerData = this.containerData,
@@ -2018,7 +2008,6 @@
2018
2008
  top = cropBoxData.top,
2019
2009
  width = cropBoxData.width,
2020
2010
  height = cropBoxData.height;
2021
-
2022
2011
  var right = left + width;
2023
2012
  var bottom = top + height;
2024
2013
  var minLeft = 0;
@@ -2026,17 +2015,15 @@
2026
2015
  var maxWidth = containerData.width;
2027
2016
  var maxHeight = containerData.height;
2028
2017
  var renderable = true;
2029
- var offset = void 0;
2018
+ var offset; // Locking aspect ratio in "free mode" by holding shift key
2030
2019
 
2031
- // Locking aspect ratio in "free mode" by holding shift key
2032
- if (!aspectRatio && e.shiftKey) {
2020
+ if (!aspectRatio && event.shiftKey) {
2033
2021
  aspectRatio = width && height ? width / height : 1;
2034
2022
  }
2035
2023
 
2036
2024
  if (this.limited) {
2037
2025
  minLeft = cropBoxData.minLeft;
2038
2026
  minTop = cropBoxData.minTop;
2039
-
2040
2027
  maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width);
2041
2028
  maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height);
2042
2029
  }
@@ -2046,6 +2033,7 @@
2046
2033
  x: pointer.endX - pointer.startX,
2047
2034
  y: pointer.endY - pointer.startY
2048
2035
  };
2036
+
2049
2037
  var check = function check(side) {
2050
2038
  switch (side) {
2051
2039
  case ACTION_EAST:
@@ -2075,8 +2063,6 @@
2075
2063
  }
2076
2064
 
2077
2065
  break;
2078
-
2079
- default:
2080
2066
  }
2081
2067
  };
2082
2068
 
@@ -2086,8 +2072,8 @@
2086
2072
  left += range.x;
2087
2073
  top += range.y;
2088
2074
  break;
2089
-
2090
2075
  // Resize crop box
2076
+
2091
2077
  case ACTION_EAST:
2092
2078
  if (range.x >= 0 && (right >= maxWidth || aspectRatio && (top <= minTop || bottom >= maxHeight))) {
2093
2079
  renderable = false;
@@ -2393,20 +2379,20 @@
2393
2379
  }
2394
2380
 
2395
2381
  break;
2396
-
2397
2382
  // Move canvas
2383
+
2398
2384
  case ACTION_MOVE:
2399
2385
  this.move(range.x, range.y);
2400
2386
  renderable = false;
2401
2387
  break;
2402
-
2403
2388
  // Zoom canvas
2389
+
2404
2390
  case ACTION_ZOOM:
2405
- this.zoom(getMaxZoomRatio(pointers), e);
2391
+ this.zoom(getMaxZoomRatio(pointers), event);
2406
2392
  renderable = false;
2407
2393
  break;
2408
-
2409
2394
  // Create crop box
2395
+
2410
2396
  case ACTION_CROP:
2411
2397
  if (!range.x || !range.y) {
2412
2398
  renderable = false;
@@ -2428,9 +2414,9 @@
2428
2414
 
2429
2415
  if (range.y < 0) {
2430
2416
  top -= height;
2431
- }
2417
+ } // Show the crop box if is hidden
2418
+
2432
2419
 
2433
- // Show the crop box if is hidden
2434
2420
  if (!this.cropped) {
2435
2421
  removeClass(this.cropBox, CLASS_HIDDEN);
2436
2422
  this.cropped = true;
@@ -2441,8 +2427,6 @@
2441
2427
  }
2442
2428
 
2443
2429
  break;
2444
-
2445
- default:
2446
2430
  }
2447
2431
 
2448
2432
  if (renderable) {
@@ -2452,9 +2436,9 @@
2452
2436
  cropBoxData.top = top;
2453
2437
  this.action = action;
2454
2438
  this.renderCropBox();
2455
- }
2439
+ } // Override
2440
+
2456
2441
 
2457
- // Override
2458
2442
  forEach(pointers, function (p) {
2459
2443
  p.startX = p.endX;
2460
2444
  p.startY = p.endY;
@@ -2479,8 +2463,6 @@
2479
2463
 
2480
2464
  return this;
2481
2465
  },
2482
-
2483
-
2484
2466
  // Reset the image and crop box to their initial states
2485
2467
  reset: function reset() {
2486
2468
  if (this.ready && !this.disabled) {
@@ -2496,8 +2478,6 @@
2496
2478
 
2497
2479
  return this;
2498
2480
  },
2499
-
2500
-
2501
2481
  // Clear the crop box
2502
2482
  clear: function clear() {
2503
2483
  if (this.cropped && !this.disabled) {
@@ -2507,12 +2487,10 @@
2507
2487
  width: 0,
2508
2488
  height: 0
2509
2489
  });
2510
-
2511
2490
  this.cropped = false;
2512
2491
  this.renderCropBox();
2513
- this.limitCanvas(true, true);
2492
+ this.limitCanvas(true, true); // Render canvas after crop box rendered
2514
2493
 
2515
- // Render canvas after crop box rendered
2516
2494
  this.renderCanvas();
2517
2495
  removeClass(this.dragBox, CLASS_MODAL);
2518
2496
  addClass(this.cropBox, CLASS_HIDDEN);
@@ -2521,7 +2499,6 @@
2521
2499
  return this;
2522
2500
  },
2523
2501
 
2524
-
2525
2502
  /**
2526
2503
  * Replace the image's src and rebuild the cropper
2527
2504
  * @param {string} url - The new URL.
@@ -2542,7 +2519,6 @@
2542
2519
 
2543
2520
  if (this.ready) {
2544
2521
  this.viewBoxImage.src = url;
2545
-
2546
2522
  forEach(this.previews, function (element) {
2547
2523
  element.getElementsByTagName('img')[0].src = url;
2548
2524
  });
@@ -2560,8 +2536,6 @@
2560
2536
 
2561
2537
  return this;
2562
2538
  },
2563
-
2564
-
2565
2539
  // Enable (unfreeze) the cropper
2566
2540
  enable: function enable() {
2567
2541
  if (this.ready && this.disabled) {
@@ -2571,8 +2545,6 @@
2571
2545
 
2572
2546
  return this;
2573
2547
  },
2574
-
2575
-
2576
2548
  // Disable (freeze) the cropper
2577
2549
  disable: function disable() {
2578
2550
  if (this.ready && !this.disabled) {
@@ -2583,7 +2555,6 @@
2583
2555
  return this;
2584
2556
  },
2585
2557
 
2586
-
2587
2558
  /**
2588
2559
  * Destroy the cropper and remove the instance from the image
2589
2560
  * @returns {Cropper} this
@@ -2591,22 +2562,20 @@
2591
2562
  destroy: function destroy() {
2592
2563
  var element = this.element;
2593
2564
 
2594
-
2595
- if (!getData(element, NAMESPACE)) {
2565
+ if (!element[NAMESPACE]) {
2596
2566
  return this;
2597
2567
  }
2598
2568
 
2569
+ element[NAMESPACE] = undefined;
2570
+
2599
2571
  if (this.isImg && this.replaced) {
2600
2572
  element.src = this.originalUrl;
2601
2573
  }
2602
2574
 
2603
2575
  this.uncreate();
2604
- removeData(element, NAMESPACE);
2605
-
2606
2576
  return this;
2607
2577
  },
2608
2578
 
2609
-
2610
2579
  /**
2611
2580
  * Move the canvas with relative offsets
2612
2581
  * @param {number} offsetX - The relative offset distance on the x-axis.
@@ -2615,15 +2584,12 @@
2615
2584
  */
2616
2585
  move: function move(offsetX) {
2617
2586
  var offsetY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : offsetX;
2618
- var _canvasData = this.canvasData,
2619
- left = _canvasData.left,
2620
- top = _canvasData.top;
2621
-
2622
-
2587
+ var _this$canvasData = this.canvasData,
2588
+ left = _this$canvasData.left,
2589
+ top = _this$canvasData.top;
2623
2590
  return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY));
2624
2591
  },
2625
2592
 
2626
-
2627
2593
  /**
2628
2594
  * Move the canvas to an absolute point
2629
2595
  * @param {number} x - The x-axis coordinate.
@@ -2633,9 +2599,7 @@
2633
2599
  moveTo: function moveTo(x) {
2634
2600
  var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x;
2635
2601
  var canvasData = this.canvasData;
2636
-
2637
2602
  var changed = false;
2638
-
2639
2603
  x = Number(x);
2640
2604
  y = Number(y);
2641
2605
 
@@ -2658,7 +2622,6 @@
2658
2622
  return this;
2659
2623
  },
2660
2624
 
2661
-
2662
2625
  /**
2663
2626
  * Zoom the canvas with a relative ratio
2664
2627
  * @param {number} ratio - The target ratio.
@@ -2667,8 +2630,6 @@
2667
2630
  */
2668
2631
  zoom: function zoom(ratio, _originalEvent) {
2669
2632
  var canvasData = this.canvasData;
2670
-
2671
-
2672
2633
  ratio = Number(ratio);
2673
2634
 
2674
2635
  if (ratio < 0) {
@@ -2680,7 +2641,6 @@
2680
2641
  return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, null, _originalEvent);
2681
2642
  },
2682
2643
 
2683
-
2684
2644
  /**
2685
2645
  * Zoom the canvas to an absolute ratio
2686
2646
  * @param {number} ratio - The target ratio.
@@ -2695,8 +2655,6 @@
2695
2655
  height = canvasData.height,
2696
2656
  naturalWidth = canvasData.naturalWidth,
2697
2657
  naturalHeight = canvasData.naturalHeight;
2698
-
2699
-
2700
2658
  ratio = Number(ratio);
2701
2659
 
2702
2660
  if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) {
@@ -2713,14 +2671,12 @@
2713
2671
 
2714
2672
  if (_originalEvent) {
2715
2673
  var pointers = this.pointers;
2716
-
2717
2674
  var offset = getOffset(this.cropper);
2718
2675
  var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : {
2719
2676
  pageX: _originalEvent.pageX,
2720
2677
  pageY: _originalEvent.pageY
2721
- };
2678
+ }; // Zoom from the triggering point of the event
2722
2679
 
2723
- // Zoom from the triggering point of the event
2724
2680
  canvasData.left -= (newWidth - width) * ((center.pageX - offset.left - canvasData.left) / width);
2725
2681
  canvasData.top -= (newHeight - height) * ((center.pageY - offset.top - canvasData.top) / height);
2726
2682
  } else if (isPlainObject(pivot) && isNumber(pivot.x) && isNumber(pivot.y)) {
@@ -2740,7 +2696,6 @@
2740
2696
  return this;
2741
2697
  },
2742
2698
 
2743
-
2744
2699
  /**
2745
2700
  * Rotate the canvas with a relative degree
2746
2701
  * @param {number} degree - The rotate degree.
@@ -2750,7 +2705,6 @@
2750
2705
  return this.rotateTo((this.imageData.rotate || 0) + Number(degree));
2751
2706
  },
2752
2707
 
2753
-
2754
2708
  /**
2755
2709
  * Rotate the canvas to an absolute degree
2756
2710
  * @param {number} degree - The rotate degree.
@@ -2767,7 +2721,6 @@
2767
2721
  return this;
2768
2722
  },
2769
2723
 
2770
-
2771
2724
  /**
2772
2725
  * Scale the image on the x-axis.
2773
2726
  * @param {number} scaleX - The scale ratio on the x-axis.
@@ -2775,12 +2728,9 @@
2775
2728
  */
2776
2729
  scaleX: function scaleX(_scaleX) {
2777
2730
  var scaleY = this.imageData.scaleY;
2778
-
2779
-
2780
2731
  return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1);
2781
2732
  },
2782
2733
 
2783
-
2784
2734
  /**
2785
2735
  * Scale the image on the y-axis.
2786
2736
  * @param {number} scaleY - The scale ratio on the y-axis.
@@ -2788,12 +2738,9 @@
2788
2738
  */
2789
2739
  scaleY: function scaleY(_scaleY) {
2790
2740
  var scaleX = this.imageData.scaleX;
2791
-
2792
-
2793
2741
  return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY);
2794
2742
  },
2795
2743
 
2796
-
2797
2744
  /**
2798
2745
  * Scale the image
2799
2746
  * @param {number} scaleX - The scale ratio on the x-axis.
@@ -2803,9 +2750,7 @@
2803
2750
  scale: function scale(scaleX) {
2804
2751
  var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX;
2805
2752
  var imageData = this.imageData;
2806
-
2807
2753
  var transformed = false;
2808
-
2809
2754
  scaleX = Number(scaleX);
2810
2755
  scaleY = Number(scaleY);
2811
2756
 
@@ -2828,20 +2773,18 @@
2828
2773
  return this;
2829
2774
  },
2830
2775
 
2831
-
2832
2776
  /**
2833
2777
  * Get the cropped area position and size data (base on the original image)
2834
2778
  * @param {boolean} [rounded=false] - Indicate if round the data values or not.
2835
2779
  * @returns {Object} The result cropped data.
2836
2780
  */
2837
- getData: function getData$$1() {
2781
+ getData: function getData() {
2838
2782
  var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
2839
2783
  var options = this.options,
2840
2784
  imageData = this.imageData,
2841
2785
  canvasData = this.canvasData,
2842
2786
  cropBoxData = this.cropBoxData;
2843
-
2844
- var data = void 0;
2787
+ var data;
2845
2788
 
2846
2789
  if (this.ready && this.cropped) {
2847
2790
  data = {
@@ -2850,9 +2793,7 @@
2850
2793
  width: cropBoxData.width,
2851
2794
  height: cropBoxData.height
2852
2795
  };
2853
-
2854
2796
  var ratio = imageData.width / imageData.naturalWidth;
2855
-
2856
2797
  forEach(data, function (n, i) {
2857
2798
  data[i] = n / ratio;
2858
2799
  });
@@ -2862,7 +2803,6 @@
2862
2803
  // we should round the top-left corner and the dimension (#343).
2863
2804
  var bottom = Math.round(data.y + data.height);
2864
2805
  var right = Math.round(data.x + data.width);
2865
-
2866
2806
  data.x = Math.round(data.x);
2867
2807
  data.y = Math.round(data.y);
2868
2808
  data.width = right - data.x;
@@ -2889,17 +2829,15 @@
2889
2829
  return data;
2890
2830
  },
2891
2831
 
2892
-
2893
2832
  /**
2894
2833
  * Set the cropped area position and size with new data
2895
2834
  * @param {Object} data - The new data.
2896
2835
  * @returns {Cropper} this
2897
2836
  */
2898
- setData: function setData$$1(data) {
2837
+ setData: function setData(data) {
2899
2838
  var options = this.options,
2900
2839
  imageData = this.imageData,
2901
2840
  canvasData = this.canvasData;
2902
-
2903
2841
  var cropBoxData = {};
2904
2842
 
2905
2843
  if (this.ready && !this.disabled && isPlainObject(data)) {
@@ -2952,7 +2890,6 @@
2952
2890
  return this;
2953
2891
  },
2954
2892
 
2955
-
2956
2893
  /**
2957
2894
  * Get the container size data.
2958
2895
  * @returns {Object} The result container data.
@@ -2961,7 +2898,6 @@
2961
2898
  return this.ready ? assign({}, this.containerData) : {};
2962
2899
  },
2963
2900
 
2964
-
2965
2901
  /**
2966
2902
  * Get the image position and size data.
2967
2903
  * @returns {Object} The result image data.
@@ -2970,14 +2906,12 @@
2970
2906
  return this.sized ? assign({}, this.imageData) : {};
2971
2907
  },
2972
2908
 
2973
-
2974
2909
  /**
2975
2910
  * Get the canvas position and size data.
2976
2911
  * @returns {Object} The result canvas data.
2977
2912
  */
2978
2913
  getCanvasData: function getCanvasData() {
2979
2914
  var canvasData = this.canvasData;
2980
-
2981
2915
  var data = {};
2982
2916
 
2983
2917
  if (this.ready) {
@@ -2989,7 +2923,6 @@
2989
2923
  return data;
2990
2924
  },
2991
2925
 
2992
-
2993
2926
  /**
2994
2927
  * Set the canvas position and size with new data.
2995
2928
  * @param {Object} data - The new canvas data.
@@ -2999,7 +2932,6 @@
2999
2932
  var canvasData = this.canvasData;
3000
2933
  var aspectRatio = canvasData.aspectRatio;
3001
2934
 
3002
-
3003
2935
  if (this.ready && !this.disabled && isPlainObject(data)) {
3004
2936
  if (isNumber(data.left)) {
3005
2937
  canvasData.left = data.left;
@@ -3023,15 +2955,13 @@
3023
2955
  return this;
3024
2956
  },
3025
2957
 
3026
-
3027
2958
  /**
3028
2959
  * Get the crop box position and size data.
3029
2960
  * @returns {Object} The result crop box data.
3030
2961
  */
3031
2962
  getCropBoxData: function getCropBoxData() {
3032
2963
  var cropBoxData = this.cropBoxData;
3033
-
3034
- var data = void 0;
2964
+ var data;
3035
2965
 
3036
2966
  if (this.ready && this.cropped) {
3037
2967
  data = {
@@ -3045,7 +2975,6 @@
3045
2975
  return data || {};
3046
2976
  },
3047
2977
 
3048
-
3049
2978
  /**
3050
2979
  * Set the crop box position and size with new data.
3051
2980
  * @param {Object} data - The new crop box data.
@@ -3054,9 +2983,8 @@
3054
2983
  setCropBoxData: function setCropBoxData(data) {
3055
2984
  var cropBoxData = this.cropBoxData;
3056
2985
  var aspectRatio = this.options.aspectRatio;
3057
-
3058
- var widthChanged = void 0;
3059
- var heightChanged = void 0;
2986
+ var widthChanged;
2987
+ var heightChanged;
3060
2988
 
3061
2989
  if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) {
3062
2990
  if (isNumber(data.left)) {
@@ -3091,7 +3019,6 @@
3091
3019
  return this;
3092
3020
  },
3093
3021
 
3094
-
3095
3022
  /**
3096
3023
  * Get a canvas drawn the cropped image.
3097
3024
  * @param {Object} [options={}] - The config options.
@@ -3105,19 +3032,17 @@
3105
3032
  }
3106
3033
 
3107
3034
  var canvasData = this.canvasData;
3035
+ var source = getSourceCanvas(this.image, this.imageData, canvasData, options); // Returns the source canvas if it is not cropped.
3108
3036
 
3109
- var source = getSourceCanvas(this.image, this.imageData, canvasData, options);
3110
-
3111
- // Returns the source canvas if it is not cropped.
3112
3037
  if (!this.cropped) {
3113
3038
  return source;
3114
3039
  }
3115
3040
 
3116
- var _getData = this.getData(),
3117
- initialX = _getData.x,
3118
- initialY = _getData.y,
3119
- initialWidth = _getData.width,
3120
- initialHeight = _getData.height;
3041
+ var _this$getData = this.getData(),
3042
+ initialX = _this$getData.x,
3043
+ initialY = _this$getData.y,
3044
+ initialWidth = _this$getData.width,
3045
+ initialHeight = _this$getData.height;
3121
3046
 
3122
3047
  var ratio = source.width / Math.floor(canvasData.naturalWidth);
3123
3048
 
@@ -3150,42 +3075,34 @@
3150
3075
 
3151
3076
  width = Math.min(maxSizes.width, Math.max(minSizes.width, width));
3152
3077
  height = Math.min(maxSizes.height, Math.max(minSizes.height, height));
3153
-
3154
3078
  var canvas = document.createElement('canvas');
3155
3079
  var context = canvas.getContext('2d');
3156
-
3157
3080
  canvas.width = normalizeDecimalNumber(width);
3158
3081
  canvas.height = normalizeDecimalNumber(height);
3159
-
3160
3082
  context.fillStyle = options.fillColor || 'transparent';
3161
3083
  context.fillRect(0, 0, width, height);
3162
-
3163
3084
  var _options$imageSmoothi = options.imageSmoothingEnabled,
3164
- imageSmoothingEnabled = _options$imageSmoothi === undefined ? true : _options$imageSmoothi,
3085
+ imageSmoothingEnabled = _options$imageSmoothi === void 0 ? true : _options$imageSmoothi,
3165
3086
  imageSmoothingQuality = options.imageSmoothingQuality;
3166
-
3167
-
3168
3087
  context.imageSmoothingEnabled = imageSmoothingEnabled;
3169
3088
 
3170
3089
  if (imageSmoothingQuality) {
3171
3090
  context.imageSmoothingQuality = imageSmoothingQuality;
3172
- }
3091
+ } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage
3092
+
3173
3093
 
3174
- // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage
3175
3094
  var sourceWidth = source.width;
3176
- var sourceHeight = source.height;
3095
+ var sourceHeight = source.height; // Source canvas parameters
3177
3096
 
3178
- // Source canvas parameters
3179
3097
  var srcX = initialX;
3180
3098
  var srcY = initialY;
3181
- var srcWidth = void 0;
3182
- var srcHeight = void 0;
3099
+ var srcWidth;
3100
+ var srcHeight; // Destination canvas parameters
3183
3101
 
3184
- // Destination canvas parameters
3185
- var dstX = void 0;
3186
- var dstY = void 0;
3187
- var dstWidth = void 0;
3188
- var dstHeight = void 0;
3102
+ var dstX;
3103
+ var dstY;
3104
+ var dstWidth;
3105
+ var dstHeight;
3189
3106
 
3190
3107
  if (srcX <= -initialWidth || srcX > sourceWidth) {
3191
3108
  srcX = 0;
@@ -3219,25 +3136,21 @@
3219
3136
  dstHeight = srcHeight;
3220
3137
  }
3221
3138
 
3222
- var params = [srcX, srcY, srcWidth, srcHeight];
3139
+ var params = [srcX, srcY, srcWidth, srcHeight]; // Avoid "IndexSizeError"
3223
3140
 
3224
- // Avoid "IndexSizeError"
3225
3141
  if (dstWidth > 0 && dstHeight > 0) {
3226
3142
  var scale = width / initialWidth;
3227
-
3228
3143
  params.push(dstX * scale, dstY * scale, dstWidth * scale, dstHeight * scale);
3229
- }
3230
-
3231
- // All the numerical parameters should be integer for `drawImage`
3144
+ } // All the numerical parameters should be integer for `drawImage`
3232
3145
  // https://github.com/fengyuanchen/cropper/issues/476
3233
- context.drawImage.apply(context, [source].concat(toConsumableArray(params.map(function (param) {
3146
+
3147
+
3148
+ context.drawImage.apply(context, [source].concat(_toConsumableArray(params.map(function (param) {
3234
3149
  return Math.floor(normalizeDecimalNumber(param));
3235
3150
  }))));
3236
-
3237
3151
  return canvas;
3238
3152
  },
3239
3153
 
3240
-
3241
3154
  /**
3242
3155
  * Change the aspect ratio of the crop box.
3243
3156
  * @param {number} aspectRatio - The new aspect ratio.
@@ -3246,7 +3159,6 @@
3246
3159
  setAspectRatio: function setAspectRatio(aspectRatio) {
3247
3160
  var options = this.options;
3248
3161
 
3249
-
3250
3162
  if (!this.disabled && !isUndefined(aspectRatio)) {
3251
3163
  // 0 -> NaN
3252
3164
  options.aspectRatio = Math.max(0, aspectRatio) || NaN;
@@ -3263,7 +3175,6 @@
3263
3175
  return this;
3264
3176
  },
3265
3177
 
3266
-
3267
3178
  /**
3268
3179
  * Change the drag mode.
3269
3180
  * @param {string} mode - The new drag mode.
@@ -3274,13 +3185,10 @@
3274
3185
  dragBox = this.dragBox,
3275
3186
  face = this.face;
3276
3187
 
3277
-
3278
3188
  if (this.ready && !this.disabled) {
3279
3189
  var croppable = mode === DRAG_MODE_CROP;
3280
3190
  var movable = options.movable && mode === DRAG_MODE_MOVE;
3281
-
3282
3191
  mode = croppable || movable ? mode : DRAG_MODE_NONE;
3283
-
3284
3192
  options.dragMode = mode;
3285
3193
  setData(dragBox, DATA_ACTION, mode);
3286
3194
  toggleClass(dragBox, CLASS_CROP, croppable);
@@ -3300,7 +3208,7 @@
3300
3208
 
3301
3209
  var AnotherCropper = WINDOW.Cropper;
3302
3210
 
3303
- var Cropper = function () {
3211
+ var Cropper = /*#__PURE__*/function () {
3304
3212
  /**
3305
3213
  * Create a new Cropper.
3306
3214
  * @param {Element} element - The target element for cropping.
@@ -3308,7 +3216,8 @@
3308
3216
  */
3309
3217
  function Cropper(element) {
3310
3218
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
3311
- classCallCheck(this, Cropper);
3219
+
3220
+ _classCallCheck(this, Cropper);
3312
3221
 
3313
3222
  if (!element || !REGEXP_TAG_NAME.test(element.tagName)) {
3314
3223
  throw new Error('The first argument is required and must be an <img> or <canvas> element.');
@@ -3327,33 +3236,30 @@
3327
3236
  this.init();
3328
3237
  }
3329
3238
 
3330
- createClass(Cropper, [{
3331
- key: 'init',
3239
+ _createClass(Cropper, [{
3240
+ key: "init",
3332
3241
  value: function init() {
3333
3242
  var element = this.element;
3334
-
3335
3243
  var tagName = element.tagName.toLowerCase();
3336
- var url = void 0;
3244
+ var url;
3337
3245
 
3338
- if (getData(element, NAMESPACE)) {
3246
+ if (element[NAMESPACE]) {
3339
3247
  return;
3340
3248
  }
3341
3249
 
3342
- setData(element, NAMESPACE, this);
3250
+ element[NAMESPACE] = this;
3343
3251
 
3344
3252
  if (tagName === 'img') {
3345
- this.isImg = true;
3253
+ this.isImg = true; // e.g.: "img/picture.jpg"
3346
3254
 
3347
- // e.g.: "img/picture.jpg"
3348
3255
  url = element.getAttribute('src') || '';
3349
- this.originalUrl = url;
3256
+ this.originalUrl = url; // Stop when it's a blank image
3350
3257
 
3351
- // Stop when it's a blank image
3352
3258
  if (!url) {
3353
3259
  return;
3354
- }
3260
+ } // e.g.: "https://example.com/img/picture.jpg"
3261
+
3355
3262
 
3356
- // e.g.: "http://example.com/img/picture.jpg"
3357
3263
  url = element.src;
3358
3264
  } else if (tagName === 'canvas' && window.HTMLCanvasElement) {
3359
3265
  url = element.toDataURL();
@@ -3362,7 +3268,7 @@
3362
3268
  this.load(url);
3363
3269
  }
3364
3270
  }, {
3365
- key: 'load',
3271
+ key: "load",
3366
3272
  value: function load(url) {
3367
3273
  var _this = this;
3368
3274
 
@@ -3372,76 +3278,89 @@
3372
3278
 
3373
3279
  this.url = url;
3374
3280
  this.imageData = {};
3375
-
3376
3281
  var element = this.element,
3377
3282
  options = this.options;
3378
3283
 
3379
-
3380
3284
  if (!options.rotatable && !options.scalable) {
3381
3285
  options.checkOrientation = false;
3382
- }
3286
+ } // Only IE10+ supports Typed Arrays
3287
+
3383
3288
 
3384
3289
  if (!options.checkOrientation || !window.ArrayBuffer) {
3385
3290
  this.clone();
3386
3291
  return;
3387
- }
3292
+ } // Detect the mime type of the image directly if it is a Data URL
3293
+
3388
3294
 
3389
- // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari
3390
3295
  if (REGEXP_DATA_URL.test(url)) {
3296
+ // Read ArrayBuffer from Data URL of JPEG images directly for better performance
3391
3297
  if (REGEXP_DATA_URL_JPEG.test(url)) {
3392
3298
  this.read(dataURLToArrayBuffer(url));
3393
3299
  } else {
3300
+ // Only a JPEG image may contains Exif Orientation information,
3301
+ // the rest types of Data URLs are not necessary to check orientation at all.
3394
3302
  this.clone();
3395
3303
  }
3396
3304
 
3397
3305
  return;
3398
- }
3306
+ } // 1. Detect the mime type of the image by a XMLHttpRequest.
3307
+ // 2. Load the image as ArrayBuffer for reading orientation if its a JPEG image.
3399
3308
 
3400
- var xhr = new XMLHttpRequest();
3401
3309
 
3310
+ var xhr = new XMLHttpRequest();
3311
+ var clone = this.clone.bind(this);
3402
3312
  this.reloading = true;
3403
- this.xhr = xhr;
3404
-
3405
- var done = function done() {
3406
- _this.reloading = false;
3407
- _this.xhr = null;
3408
- };
3409
-
3410
- xhr.ontimeout = done;
3411
- xhr.onabort = done;
3412
- xhr.onerror = function () {
3413
- done();
3414
- _this.clone();
3313
+ this.xhr = xhr; // 1. Cross origin requests are only supported for protocol schemes:
3314
+ // http, https, data, chrome, chrome-extension.
3315
+ // 2. Access to XMLHttpRequest from a Data URL will be blocked by CORS policy
3316
+ // in some browsers as IE11 and Safari.
3317
+
3318
+ xhr.onabort = clone;
3319
+ xhr.onerror = clone;
3320
+ xhr.ontimeout = clone;
3321
+
3322
+ xhr.onprogress = function () {
3323
+ // Abort the request directly if it not a JPEG image for better performance
3324
+ if (xhr.getResponseHeader('content-type') !== MIME_TYPE_JPEG) {
3325
+ xhr.abort();
3326
+ }
3415
3327
  };
3416
3328
 
3417
3329
  xhr.onload = function () {
3418
- done();
3419
3330
  _this.read(xhr.response);
3420
3331
  };
3421
3332
 
3422
- // Bust cache when there is a "crossOrigin" property
3333
+ xhr.onloadend = function () {
3334
+ _this.reloading = false;
3335
+ _this.xhr = null;
3336
+ }; // Bust cache when there is a "crossOrigin" property to avoid browser cache error
3337
+
3338
+
3423
3339
  if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) {
3424
3340
  url = addTimestamp(url);
3425
- }
3341
+ } // The third parameter is required for avoiding side-effect (#682)
3426
3342
 
3427
- xhr.open('get', url);
3343
+
3344
+ xhr.open('GET', url, true);
3428
3345
  xhr.responseType = 'arraybuffer';
3429
3346
  xhr.withCredentials = element.crossOrigin === 'use-credentials';
3430
3347
  xhr.send();
3431
3348
  }
3432
3349
  }, {
3433
- key: 'read',
3350
+ key: "read",
3434
3351
  value: function read(arrayBuffer) {
3435
3352
  var options = this.options,
3436
- imageData = this.imageData;
3353
+ imageData = this.imageData; // Reset the orientation value to its default value 1
3354
+ // as some iOS browsers will render image with its orientation
3437
3355
 
3438
- var orientation = getOrientation(arrayBuffer);
3356
+ var orientation = resetAndGetOrientation(arrayBuffer);
3439
3357
  var rotate = 0;
3440
3358
  var scaleX = 1;
3441
3359
  var scaleY = 1;
3442
3360
 
3443
3361
  if (orientation > 1) {
3444
- this.url = arrayBufferToDataURL(arrayBuffer, 'image/jpeg');
3362
+ // Generate a new URL which has the default orientation value
3363
+ this.url = arrayBufferToDataURL(arrayBuffer, MIME_TYPE_JPEG);
3445
3364
 
3446
3365
  var _parseOrientation = parseOrientation(orientation);
3447
3366
 
@@ -3462,31 +3381,24 @@
3462
3381
  this.clone();
3463
3382
  }
3464
3383
  }, {
3465
- key: 'clone',
3384
+ key: "clone",
3466
3385
  value: function clone() {
3467
3386
  var element = this.element,
3468
3387
  url = this.url;
3469
-
3470
- var crossOrigin = void 0;
3471
- var crossOriginUrl = void 0;
3388
+ var crossOrigin = element.crossOrigin;
3389
+ var crossOriginUrl = url;
3472
3390
 
3473
3391
  if (this.options.checkCrossOrigin && isCrossOriginURL(url)) {
3474
- crossOrigin = element.crossOrigin;
3475
-
3476
-
3477
- if (crossOrigin) {
3478
- crossOriginUrl = url;
3479
- } else {
3392
+ if (!crossOrigin) {
3480
3393
  crossOrigin = 'anonymous';
3394
+ } // Bust cache when there is not a "crossOrigin" property (#519)
3481
3395
 
3482
- // Bust cache when there is not a "crossOrigin" property
3483
- crossOriginUrl = addTimestamp(url);
3484
- }
3396
+
3397
+ crossOriginUrl = addTimestamp(url);
3485
3398
  }
3486
3399
 
3487
3400
  this.crossOrigin = crossOrigin;
3488
3401
  this.crossOriginUrl = crossOriginUrl;
3489
-
3490
3402
  var image = document.createElement('img');
3491
3403
 
3492
3404
  if (crossOrigin) {
@@ -3494,6 +3406,7 @@
3494
3406
  }
3495
3407
 
3496
3408
  image.src = crossOriginUrl || url;
3409
+ image.alt = element.alt || 'The image to crop';
3497
3410
  this.image = image;
3498
3411
  image.onload = this.start.bind(this);
3499
3412
  image.onerror = this.stop.bind(this);
@@ -3501,69 +3414,68 @@
3501
3414
  element.parentNode.insertBefore(image, element.nextSibling);
3502
3415
  }
3503
3416
  }, {
3504
- key: 'start',
3417
+ key: "start",
3505
3418
  value: function start() {
3506
3419
  var _this2 = this;
3507
3420
 
3508
- var image = this.isImg ? this.element : this.image;
3509
-
3421
+ var image = this.image;
3510
3422
  image.onload = null;
3511
3423
  image.onerror = null;
3512
- this.sizing = true;
3424
+ this.sizing = true; // Match all browsers that use WebKit as the layout engine in iOS devices,
3425
+ // such as Safari for iOS, Chrome for iOS, and in-app browsers.
3426
+
3427
+ var isIOSWebKit = WINDOW.navigator && /(?:iPad|iPhone|iPod).*?AppleWebKit/i.test(WINDOW.navigator.userAgent);
3513
3428
 
3514
- var IS_SAFARI = WINDOW.navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(WINDOW.navigator.userAgent);
3515
3429
  var done = function done(naturalWidth, naturalHeight) {
3516
3430
  assign(_this2.imageData, {
3517
3431
  naturalWidth: naturalWidth,
3518
3432
  naturalHeight: naturalHeight,
3519
3433
  aspectRatio: naturalWidth / naturalHeight
3520
3434
  });
3435
+ _this2.initialImageData = assign({}, _this2.imageData);
3521
3436
  _this2.sizing = false;
3522
3437
  _this2.sized = true;
3438
+
3523
3439
  _this2.build();
3524
- };
3440
+ }; // Most modern browsers (excepts iOS WebKit)
3441
+
3525
3442
 
3526
- // Modern browsers (except Safari)
3527
- if (image.naturalWidth && !IS_SAFARI) {
3443
+ if (image.naturalWidth && !isIOSWebKit) {
3528
3444
  done(image.naturalWidth, image.naturalHeight);
3529
3445
  return;
3530
3446
  }
3531
3447
 
3532
3448
  var sizingImage = document.createElement('img');
3533
3449
  var body = document.body || document.documentElement;
3534
-
3535
3450
  this.sizingImage = sizingImage;
3536
3451
 
3537
3452
  sizingImage.onload = function () {
3538
3453
  done(sizingImage.width, sizingImage.height);
3539
3454
 
3540
- if (!IS_SAFARI) {
3455
+ if (!isIOSWebKit) {
3541
3456
  body.removeChild(sizingImage);
3542
3457
  }
3543
3458
  };
3544
3459
 
3545
- sizingImage.src = image.src;
3546
-
3547
- // iOS Safari will convert the image automatically
3460
+ sizingImage.src = image.src; // iOS WebKit will convert the image automatically
3548
3461
  // with its orientation once append it into DOM (#279)
3549
- if (!IS_SAFARI) {
3462
+
3463
+ if (!isIOSWebKit) {
3550
3464
  sizingImage.style.cssText = 'left:0;' + 'max-height:none!important;' + 'max-width:none!important;' + 'min-height:0!important;' + 'min-width:0!important;' + 'opacity:0;' + 'position:absolute;' + 'top:0;' + 'z-index:-1;';
3551
3465
  body.appendChild(sizingImage);
3552
3466
  }
3553
3467
  }
3554
3468
  }, {
3555
- key: 'stop',
3469
+ key: "stop",
3556
3470
  value: function stop() {
3557
3471
  var image = this.image;
3558
-
3559
-
3560
3472
  image.onload = null;
3561
3473
  image.onerror = null;
3562
3474
  image.parentNode.removeChild(image);
3563
3475
  this.image = null;
3564
3476
  }
3565
3477
  }, {
3566
- key: 'build',
3478
+ key: "build",
3567
3479
  value: function build() {
3568
3480
  if (!this.sized || this.ready) {
3569
3481
  return;
@@ -3571,61 +3483,50 @@
3571
3483
 
3572
3484
  var element = this.element,
3573
3485
  options = this.options,
3574
- image = this.image;
3575
-
3576
- // Create cropper elements
3486
+ image = this.image; // Create cropper elements
3577
3487
 
3578
3488
  var container = element.parentNode;
3579
3489
  var template = document.createElement('div');
3580
-
3581
3490
  template.innerHTML = TEMPLATE;
3582
-
3583
- var cropper = template.querySelector('.' + NAMESPACE + '-container');
3584
- var canvas = cropper.querySelector('.' + NAMESPACE + '-canvas');
3585
- var dragBox = cropper.querySelector('.' + NAMESPACE + '-drag-box');
3586
- var cropBox = cropper.querySelector('.' + NAMESPACE + '-crop-box');
3587
- var face = cropBox.querySelector('.' + NAMESPACE + '-face');
3588
-
3491
+ var cropper = template.querySelector(".".concat(NAMESPACE, "-container"));
3492
+ var canvas = cropper.querySelector(".".concat(NAMESPACE, "-canvas"));
3493
+ var dragBox = cropper.querySelector(".".concat(NAMESPACE, "-drag-box"));
3494
+ var cropBox = cropper.querySelector(".".concat(NAMESPACE, "-crop-box"));
3495
+ var face = cropBox.querySelector(".".concat(NAMESPACE, "-face"));
3589
3496
  this.container = container;
3590
3497
  this.cropper = cropper;
3591
3498
  this.canvas = canvas;
3592
3499
  this.dragBox = dragBox;
3593
3500
  this.cropBox = cropBox;
3594
- this.viewBox = cropper.querySelector('.' + NAMESPACE + '-view-box');
3501
+ this.viewBox = cropper.querySelector(".".concat(NAMESPACE, "-view-box"));
3595
3502
  this.face = face;
3503
+ canvas.appendChild(image); // Hide the original image
3596
3504
 
3597
- canvas.appendChild(image);
3598
-
3599
- // Hide the original image
3600
- addClass(element, CLASS_HIDDEN);
3505
+ addClass(element, CLASS_HIDDEN); // Inserts the cropper after to the current image
3601
3506
 
3602
- // Inserts the cropper after to the current image
3603
- container.insertBefore(cropper, element.nextSibling);
3507
+ container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden
3604
3508
 
3605
- // Show the image if is hidden
3606
3509
  if (!this.isImg) {
3607
3510
  removeClass(image, CLASS_HIDE);
3608
3511
  }
3609
3512
 
3610
3513
  this.initPreview();
3611
3514
  this.bind();
3612
-
3613
3515
  options.initialAspectRatio = Math.max(0, options.initialAspectRatio) || NaN;
3614
3516
  options.aspectRatio = Math.max(0, options.aspectRatio) || NaN;
3615
3517
  options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0;
3616
-
3617
3518
  addClass(cropBox, CLASS_HIDDEN);
3618
3519
 
3619
3520
  if (!options.guides) {
3620
- addClass(cropBox.getElementsByClassName(NAMESPACE + '-dashed'), CLASS_HIDDEN);
3521
+ addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-dashed")), CLASS_HIDDEN);
3621
3522
  }
3622
3523
 
3623
3524
  if (!options.center) {
3624
- addClass(cropBox.getElementsByClassName(NAMESPACE + '-center'), CLASS_HIDDEN);
3525
+ addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-center")), CLASS_HIDDEN);
3625
3526
  }
3626
3527
 
3627
3528
  if (options.background) {
3628
- addClass(cropper, NAMESPACE + '-bg');
3529
+ addClass(cropper, "".concat(NAMESPACE, "-bg"));
3629
3530
  }
3630
3531
 
3631
3532
  if (!options.highlight) {
@@ -3638,8 +3539,8 @@
3638
3539
  }
3639
3540
 
3640
3541
  if (!options.cropBoxResizable) {
3641
- addClass(cropBox.getElementsByClassName(NAMESPACE + '-line'), CLASS_HIDDEN);
3642
- addClass(cropBox.getElementsByClassName(NAMESPACE + '-point'), CLASS_HIDDEN);
3542
+ addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-line")), CLASS_HIDDEN);
3543
+ addClass(cropBox.getElementsByClassName("".concat(NAMESPACE, "-point")), CLASS_HIDDEN);
3643
3544
  }
3644
3545
 
3645
3546
  this.render();
@@ -3661,7 +3562,7 @@
3661
3562
  dispatchEvent(element, EVENT_READY);
3662
3563
  }
3663
3564
  }, {
3664
- key: 'unbuild',
3565
+ key: "unbuild",
3665
3566
  value: function unbuild() {
3666
3567
  if (!this.ready) {
3667
3568
  return;
@@ -3674,7 +3575,7 @@
3674
3575
  removeClass(this.element, CLASS_HIDDEN);
3675
3576
  }
3676
3577
  }, {
3677
- key: 'uncreate',
3578
+ key: "uncreate",
3678
3579
  value: function uncreate() {
3679
3580
  if (this.ready) {
3680
3581
  this.unbuild();
@@ -3685,35 +3586,35 @@
3685
3586
  this.sizing = false;
3686
3587
  this.sized = false;
3687
3588
  } else if (this.reloading) {
3589
+ this.xhr.onabort = null;
3688
3590
  this.xhr.abort();
3689
3591
  } else if (this.image) {
3690
3592
  this.stop();
3691
3593
  }
3692
3594
  }
3693
-
3694
3595
  /**
3695
3596
  * Get the no conflict cropper class.
3696
3597
  * @returns {Cropper} The cropper class.
3697
3598
  */
3698
3599
 
3699
3600
  }], [{
3700
- key: 'noConflict',
3601
+ key: "noConflict",
3701
3602
  value: function noConflict() {
3702
3603
  window.Cropper = AnotherCropper;
3703
3604
  return Cropper;
3704
3605
  }
3705
-
3706
3606
  /**
3707
3607
  * Change the default options.
3708
3608
  * @param {Object} options - The new default options.
3709
3609
  */
3710
3610
 
3711
3611
  }, {
3712
- key: 'setDefaults',
3612
+ key: "setDefaults",
3713
3613
  value: function setDefaults(options) {
3714
3614
  assign(DEFAULTS, isPlainObject(options) && options);
3715
3615
  }
3716
3616
  }]);
3617
+
3717
3618
  return Cropper;
3718
3619
  }();
3719
3620