cropper_rails 1.0.0 → 1.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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