diff --git a/CHANGELOG.md b/CHANGELOG.md index 64ef1ebbf..b9046ed70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,74 +1,63 @@ # Changelog - -## next +## 1.1.0 (Oct 8, 2017) - Added 4 new options to `getCroppedCanvas` method: `minWidth`, `minHeight`, `maxWidth` and `maxHeight`. -- Improved crop box resizing (#222). - +- Enhanced image scaling: the `scaleX` and `scaleY` values should only be `1` or `-1` before, but now they can be any numbers. +- Improved crop box resizing behaviour in the northeast, northwest, southeast and southwest directions. (#222). ## 1.0.0 (Sep 3, 2017) - Fixed a bug of zoom out after cleared the crop box in view mode 1, 2 and 3 (#209). -- Fixed a bug of crop box resizing (#222). - +- Improve crop box resizing behaviour in the east, west, south and north directions (#222). ## 1.0.0-rc.3 (Jul 7, 2017) - Added two new options (`imageSmoothingEnabled` and `imageSmoothingQuality`) to `getCroppedCanvas` method. - Fixed a bug of RegExp using (#195 by @arusakov). - ## 1.0.0-rc.2 (May 30, 2017) - Fixed the issue of canvas box initialization (#179). - ## 1.0.0-rc.1 (Apr 30, 2017) - Change the `main` field value from `dist/cropper.js` (UMD) to `dist/cropper.common.js` (CommonJS). - Added `module` and `browser` fields to `package.json`. - ## 1.0.0-rc (Mar 25, 2017) - Fixed the bug of touch zoom (#161). - Fixed the bug of window resize (#162). - Improve the `toggleDragModeOnDblclick` option (only available when the `dragMode` option is set to `crop` or `move`) - ## 1.0.0-beta.2 (Feb 25, 2017) - Fixed the bug of rotate square image lead image shrink (#155). - Improved RegExps for DataURL processing (#156). - ## 1.0.0-beta.1 (Jan 21, 2017) - Use CSS3 2D Transforms instead of `left` and `top` for better performance (#138). - Set `withCredentials` attribute when read the image data by XMLHttpRequest (#141). - ## 1.0.0-beta (Jan 1, 2017) - Supports to set an element for preview (#113). - Improved event handler for Pointer Events (#127). - ## 1.0.0-alpha (Dec 4, 2016) - Built JavaScript with Rollup. - Build CSS with PostCSS. - Fixed a bug of auto crop when replace the image (#83). - ## 0.8.1 (Sep 3, 2016) - Fixed the bug of cropping (#80). - Fixed the bug of calling `ready` event twice when call `replace` method (#81). - Fixed the bug of `getCroppedCanvas` when set `scalable` or `rotatable` to `false` (#82). - ## 0.8.0 (Aug 18, 2016) - Removed `build` event. @@ -76,27 +65,23 @@ - Fixed the error of orientation transform. - Ported code to ECMAScript 6. - ## 0.7.2 (Jun 8, 2016) - Fixed a bug of `data-*` attributes setting and getting. - Fixed the calling order of `scale` and `rotate`. - ## 0.7.1 (May 28, 2016) - Improved the rotate and scale transform behaviour. - Improved the `getCroppedCanvas` method (returns the whole canvas if it is not cropped). - Check cross origin setting when load image by XMLHTTPRequest. - ## 0.7.0 (Mar 20, 2016) - Supports 7 custom events: `build`, `built`, `cropstart`, `cropmove`, `cropend`, `crop` and `zoom`. - The original callback options become shortcuts of these events now. - IE8 is no longer supported after added these custom events. - ## 0.6.0 (Feb 22, 2016) - Added a new parameter to the `replace` method for applying filters. @@ -104,36 +89,30 @@ - Fixed incorrect size limitation of the crop box (#30). - Fixed incorrect cropped canvas when scaleX or scaleY great than 1. - ## 0.5.6 (Jan 18, 2016) - Fixed crossOriginUrl undefined error when exists the `crossOrigin` property. - Fixed the issue in the "destroy" method (#24). - Optimized tests. - ## 0.5.5 (Jan 1, 2016) - Fixed a dimension bug in the "getCroppedCanvas" method. - Added an example for cropping round image. - ## 0.5.4 (Dec 28, 2015) - Supports to zoom from event triggering point. - ## 0.5.3 (Dec 24, 2015) - Limit wheel speed to prevent zoom too fast (#21) - Improve the `setCropBoxData` method (#22) - ## 0.5.2 (Dec 15, 2015) - Fix event handlers - ## 0.5.1 (Dec 12, 2015) - Handle Data URL (avoid to use XMLHttpRequest to open a Data URL) @@ -141,34 +120,28 @@ - Not to transform the image to base64 when Orientation equals to `1` - Fix some typos - ## 0.5.0 (Dec 5, 2015) - Added a new option: `checkOrientation` - Added a timestamp to the url of preview image - ## 0.4.0 (Dec 2, 2015) - Added a new option: `restore` - Fixed #12: Added vendor prefixes to CSS `transform` - ## 0.3.3 (Nov 30, 2015) - Floor the numerical parameters for `CanvasRenderingContext2D.drawImage` - ## 0.3.2 (Nov 18, 2015) - Fixed #10: improve new crop box creating - ## 0.3.1 (Nov 11, 2015) - Fixed #7: reset the `crossOrigin` when call the `replace` method - ## 0.3.0 (Oct 28, 2015) - Supports four view modes @@ -177,7 +150,6 @@ - Added some examples - Fixed some issues - ### Options - Added `viewMode` @@ -189,27 +161,23 @@ - Removed `strict` (supported by `viewMode: 1`) - Removed `dragCrop` (supported by `dragMode: 'crop'`) - ## 0.2.1 (Oct 28, 2015) - Fix the error jQuery reference on the `setCanvasData` method - Fix typo on the `destroy` method - ## 0.2.0 (Oct 25, 2015) - Added 5 new methods: `moveTo`, `zoomTo`, `rotateTo`, `scaleX` and `scaleY` - Improved 4 methods: `move`, `zoom`, `rotate` and `getCanvasData` - Improved cropping - ## 0.1.1 (Oct 10, 2015) - Improved canvas limitation - Improved crop box limitation - Improved preview for cross origin image - ## 0.1.0 (Sep 25, 2015) - Supports touch (mobile) diff --git a/README.md b/README.md index f3977a93b..08fa10a05 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,10 @@ -# Cropper.js +# Cropper.js [![Build Status](https://travis-ci.org/fengyuanchen/cropperjs.svg)](https://travis-ci.org/fengyuanchen/cropperjs) > JavaScript image cropper. - [Website](https://fengyuanchen.github.io/cropperjs) - [Photo Editor](https://fengyuanchen.github.io/photo-editor) - An advanced example of Cropper.js. -[![Build Status Images](https://travis-ci.org/fengyuanchen/cropperjs.svg)](https://travis-ci.org/fengyuanchen/cropperjs) - - - ## Table of contents - [Features](#features) @@ -23,8 +19,6 @@ - [Versioning](#versioning) - [License](#license) - - ## Features - Supports 38 [options](#options) @@ -40,35 +34,26 @@ - Supports to translate Exif Orientation information - Cross-browser support - - ## Main -``` +```text dist/ -├── cropper.css ( 5 KB) -├── cropper.min.css ( 4 KB) -├── cropper.js (90 KB, UMD) -├── cropper.min.js (33 KB, UMD, compressed) -├── cropper.common.js (90 KB, CommonJS) -└── cropper.esm.js (90 KB, ES Module) +├── cropper.css +├── cropper.min.css (compressed) +├── cropper.js (UMD) +├── cropper.min.js (UMD, compressed) +├── cropper.common.js (CommonJS, default) +└── cropper.esm.js (ES Module) ``` - ## Getting started -### Quick start - -Four quick start options are available: - -- [Download the latest release](https://github.com/fengyuanchen/cropperjs/archive/master.zip). -- Clone the repository: `git clone https://github.com/fengyuanchen/cropperjs.git`. -- Install with [NPM](https://npmjs.com): `npm install cropperjs`. -- Install with [Bower](https://bower.io): `bower install cropperjs`. - - ### Installation +```shell +npm install cropperjs +``` + Include files: ```html @@ -78,7 +63,6 @@ Include files: The [cdnjs](https://github.com/cdnjs/cdnjs) provides CDN support for Cropper.js's CSS and JavaScript. You can find the links [here](https://cdnjs.com/libraries/cropperjs). - ### Usage Initialize with `Cropper` constructor: @@ -117,30 +101,24 @@ var cropper = new Cropper(image, { }); ``` - #### FAQ -##### How to crop a new area after zoom in or zoom out? +How to crop a new area after zoom in or zoom out? > Just double click your mouse to enter crop mode. - -##### How to move the image after crop an area? +How to move the image after crop an area? > Just double click your mouse to enter move mode. - -##### How to fix aspect ratio in free ratio mode? +How to fix aspect ratio in free ratio mode? > Just hold the `shift` key when you resize the crop box. - -##### How to crop a square area in free ratio mode? +How to crop a square area in free ratio mode? > Just hold the `shift` key when you crop on the image. - - #### Notes - The size of the cropper inherits from the size of the image's parent element (wrapper), so be sure to wrap the image with a **visible block element**. @@ -150,24 +128,19 @@ var cropper = new Cropper(image, { - If you try to start cropper on a cross-origin image, please make sure that your browser supports HTML5 [CORS settings attributes](https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_settings_attributes), and your image server supports the `Access-Control-Allow-Origin` option (see the [HTTP access control (CORS)](https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS)). - #### Known issues - [Known iOS resource limits](https://developer.apple.com/library/mac/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html): As iOS devices limit memory, the browser may crash when you are cropping a large image (iPhone camera resolution). To avoid this, you may resize the image first (preferably below 1024 pixels) before start a cropper. - Known image size increase: When export the cropped image on browser-side with the `HTMLCanvasElement.toDataURL` method, the size of the exported image may be greater than the original image's. This is because the type of the exported image is not the same as the original image's. So just pass the type the original image's as the first parameter to `toDataURL` to fix this. For example, if the original type is JPEG, then use `cropper.getCroppedCanvas().toDataURL('image/jpeg')` to export image. - [⬆ back to top](#table-of-contents) - - ## Options You may set cropper options with `new Cropper(image, options)`. If you want to change the global default options, You may use `Cropper.setDefaults(options)`. - ### viewMode - Type: `Number` @@ -180,7 +153,6 @@ If you want to change the global default options, You may use `Cropper.setDefaul Define the view mode of the cropper. If you set `viewMode` to `0`, the crop box can extend outside the canvas, while a value of `1`, `2` or `3` will restrict the crop box to the size of the canvas. A `viewMode` of `2` or `3` will additionally restrict the canvas to the container. Note that if the proportions of the canvas and the container are the same, there is no difference between `2` and `3`. - ### dragMode - Type: `String` @@ -192,7 +164,6 @@ Define the view mode of the cropper. If you set `viewMode` to `0`, the crop box Define the dragging mode of the cropper. - ### aspectRatio - Type: `Number` @@ -200,7 +171,6 @@ Define the dragging mode of the cropper. Set the aspect ratio of the crop box. By default, the crop box is free ratio. - ### data - Type: `Object` @@ -208,7 +178,6 @@ Set the aspect ratio of the crop box. By default, the crop box is free ratio. The previous cropped data if you had stored, will be passed to `setData` method automatically when built. - ### preview - Type: `Element` or `String` @@ -224,7 +193,6 @@ Add extra elements (containers) for previewing. - If you set an `aspectRatio` option, be sure to set the same aspect ratio to the preview container. - If preview is not getting properly displayed, set `overflow: hidden` style to the preview container. - ### responsive - Type: `Boolean` @@ -232,7 +200,6 @@ Add extra elements (containers) for previewing. Re-render the cropper when resize the window. - ### restore - Type: `Boolean` @@ -240,7 +207,6 @@ Re-render the cropper when resize the window. Restore the cropped area after resize the window. - ### checkCrossOrigin - Type: `Boolean` @@ -254,7 +220,6 @@ By adding `crossOrigin` attribute to image will stop adding timestamp to image u If the value of the image's `crossOrigin` attribute is `"use-credentials"`, then the `withCredentials` attribute will set to `true` when read the image data by XMLHttpRequest. - ### checkOrientation - Type: `Boolean` @@ -270,7 +235,6 @@ Requires to set both the `rotatable` and `scalable` options to `true` at the sam > Requires [Typed Arrays](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) support ([IE 10+](http://caniuse.com/typedarrays)). - ### modal - Type: `Boolean` @@ -278,7 +242,6 @@ Requires to set both the `rotatable` and `scalable` options to `true` at the sam Show the black modal above the image and under the crop box. - ### guides - Type: `Boolean` @@ -286,7 +249,6 @@ Show the black modal above the image and under the crop box. Show the dashed lines above the crop box. - ### center - Type: `Boolean` @@ -294,7 +256,6 @@ Show the dashed lines above the crop box. Show the center indicator above the crop box. - ### highlight - Type: `Boolean` @@ -302,7 +263,6 @@ Show the center indicator above the crop box. Show the white modal above the crop box (highlight the crop box). - ### background - Type: `Boolean` @@ -310,7 +270,6 @@ Show the white modal above the crop box (highlight the crop box). Show the grid background of the container. - ### autoCrop - Type: `Boolean` @@ -318,7 +277,6 @@ Show the grid background of the container. Enable to crop the image automatically when initialize. - ### autoCropArea - Type: `Number` @@ -326,7 +284,6 @@ Enable to crop the image automatically when initialize. A number between 0 and 1. Define the automatic cropping area size (percentage). - ### movable - Type: `Boolean` @@ -334,7 +291,6 @@ A number between 0 and 1. Define the automatic cropping area size (percentage). Enable to move the image. - ### rotatable - Type: `Boolean` @@ -342,7 +298,6 @@ Enable to move the image. Enable to rotate the image. - ### scalable - Type: `Boolean` @@ -350,7 +305,6 @@ Enable to rotate the image. Enable to scale the image. - ### zoomable - Type: `Boolean` @@ -358,7 +312,6 @@ Enable to scale the image. Enable to zoom the image. - ### zoomOnTouch - Type: `Boolean` @@ -366,7 +319,6 @@ Enable to zoom the image. Enable to zoom the image by dragging touch. - ### zoomOnWheel - Type: `Boolean` @@ -374,7 +326,6 @@ Enable to zoom the image by dragging touch. Enable to zoom the image by wheeling mouse. - ### wheelZoomRatio - Type: `Number` @@ -382,7 +333,6 @@ Enable to zoom the image by wheeling mouse. Define zoom ratio when zoom the image by wheeling mouse. - ### cropBoxMovable - Type: `Boolean` @@ -390,7 +340,6 @@ Define zoom ratio when zoom the image by wheeling mouse. Enable to move the crop box by dragging. - ### cropBoxResizable - Type: `Boolean` @@ -398,7 +347,6 @@ Enable to move the crop box by dragging. Enable to resize the crop box by dragging. - ### toggleDragModeOnDblclick - Type: `Boolean` @@ -406,7 +354,6 @@ Enable to resize the crop box by dragging. Enable to toggle drag mode between "crop" and "move" when click twice on the cropper. - ### minContainerWidth - Type: `Number` @@ -414,7 +361,6 @@ Enable to toggle drag mode between "crop" and "move" when click twice on the cro The minimum width of the container. - ### minContainerHeight - Type: `Number` @@ -422,7 +368,6 @@ The minimum width of the container. The minimum height of the container. - ### minCanvasWidth - Type: `Number` @@ -430,7 +375,6 @@ The minimum height of the container. The minimum width of the canvas (image wrapper). - ### minCanvasHeight - Type: `Number` @@ -438,7 +382,6 @@ The minimum width of the canvas (image wrapper). The minimum height of the canvas (image wrapper). - ### minCropBoxWidth - Type: `Number` @@ -448,7 +391,6 @@ The minimum width of the crop box. **Note:** This size is relative to the page, not the image. - ### minCropBoxHeight - Type: `Number` @@ -458,7 +400,6 @@ The minimum height of the crop box. **Note:** This size is relative to the page, not the image. - ### ready - Type: `Function` @@ -466,7 +407,6 @@ The minimum height of the crop box. A shortcut of the "ready" event. - ### cropstart - Type: `Function` @@ -474,7 +414,6 @@ A shortcut of the "ready" event. A shortcut of the "cropstart" event. - ### cropmove - Type: `Function` @@ -482,7 +421,6 @@ A shortcut of the "cropstart" event. A shortcut of the "cropmove" event. - ### cropend - Type: `Function` @@ -490,7 +428,6 @@ A shortcut of the "cropmove" event. A shortcut of the "cropend" event. - ### crop - Type: `Function` @@ -498,7 +435,6 @@ A shortcut of the "cropend" event. A shortcut of the "crop" event. - ### zoom - Type: `Function` @@ -506,11 +442,8 @@ A shortcut of the "crop" event. A shortcut of the "zoom" event. - [⬆ back to top](#table-of-contents) - - ## Methods As there is an **asynchronous** process when load the image, you **should call most of the methods after ready**, except "setAspectRatio", "replace" and "destroy". @@ -529,7 +462,6 @@ new Cropper(image, { }); ``` - ### crop() Show the crop box manually. @@ -547,17 +479,14 @@ new Cropper(image, { }); ``` - ### reset() Reset the image and crop box to their initial states. - ### clear() Clear the crop box. - ### replace(url[, onlyColorChanged]) - **url**: @@ -569,25 +498,20 @@ Clear the crop box. - If only change the color, not the size, then the cropper only need to change the srcs of all related images, not need to rebuild the cropper. This can be used for applying filters. - If not present, its default value is `false`. - Replace the image's src and rebuild the cropper. - ### enable() Enable (unfreeze) the cropper. - ### disable() Disable (freeze) the cropper. - ### destroy() Destroy the cropper and remove the instance from the image. - ### move(offsetX[, offsetY]) - **offsetX**: @@ -607,7 +531,6 @@ cropper.move(1, 0); cropper.move(0, -1); ``` - ### moveTo(x[, y]) - **x**: @@ -621,7 +544,6 @@ cropper.move(0, -1); Move the canvas (image wrapper) to an absolute point. - ### zoom(ratio) - **ratio**: @@ -636,7 +558,6 @@ cropper.zoom(0.1); cropper.zoom(-0.1); ``` - ### zoomTo(ratio) - **ratio**: @@ -648,7 +569,6 @@ Zoom the canvas (image wrapper) to an absolute ratio. cropper.zoomTo(1); // 1:1 (canvasData.width === canvasData.naturalWidth) ``` - ### rotate(degree) - **degree**: @@ -665,7 +585,6 @@ cropper.rotate(90); cropper.rotate(-90); ``` - ### rotateTo(degree) - **degree**: @@ -673,7 +592,6 @@ cropper.rotate(-90); Rotate the image to an absolute degree. - ### scale(scaleX[, scaleY]) - **scaleX**: @@ -697,7 +615,6 @@ cropper.scale(-1, 1); // Flip horizontal cropper.scale(1, -1); // Flip vertical ``` - ### scaleX(scaleX) - **scaleX**: @@ -708,7 +625,6 @@ cropper.scale(1, -1); // Flip vertical Scale the abscissa of the image. - ### scaleY(scaleY) - **scaleY**: @@ -719,7 +635,6 @@ Scale the abscissa of the image. Scale the ordinate of the image. - ### getData([rounded]) - **rounded** (optional): @@ -742,12 +657,11 @@ Output the final cropped area position and size data (base on the natural size o > You can send the data to server-side to crop the image directly: > 1. Rotate the image with the `rotate` property. -> 2. Scale the image with the `scaleX` and `scaleY` properties. -> 3. Crop the image with the `x`, `y`, `width` and `height` properties. +> 1. Scale the image with the `scaleX` and `scaleY` properties. +> 1. Crop the image with the `x`, `y`, `width` and `height` properties. ![A schematic diagram for data's properties](docs/images/data.jpg) - ### setData(data) - **data**: @@ -759,7 +673,6 @@ Change the cropped area position and size with new data (base on the original im > **Note:** This method only available when the `viewMode` option great than or equal to `1`. - ### getContainerData() - (return value): @@ -772,7 +685,6 @@ Output the container size data. ![A schematic diagram for cropper's layers](docs/images/layers.jpg) - ### getImageData() - (return value): @@ -791,7 +703,6 @@ Output the container size data. Output the image position, size and other related data. - ### getCanvasData() - (return value): @@ -815,7 +726,6 @@ if (imageData.rotate % 180 === 0) { } ``` - ### setCanvasData(data) - **data**: @@ -828,7 +738,6 @@ if (imageData.rotate % 180 === 0) { Change the canvas (image wrapper) position and size with new data. - ### getCropBoxData() - (return value): @@ -841,7 +750,6 @@ Change the canvas (image wrapper) position and size with new data. Output the crop box position and size data. - ### setCropBoxData(data) - **data**: @@ -854,7 +762,6 @@ Output the crop box position and size data. Change the crop box position and size with new data. - ### getCroppedCanvas([options]) - **options** (optional): @@ -868,7 +775,7 @@ Change the crop box position and size with new data. - `maxHeight`: the maximum destination height of the output canvas, the default value is `Infinity`. - `fillColor`: a color to fill any alpha values in the output canvas, the default value is `transparent`. - [`imageSmoothingEnabled`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingEnabled): set to change if images are smoothed (`true`, default) or not (`false`). - - [`imageSmoothingQuality`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality): set the quality of image smoothing, one of "low", "medium", or "high". + - [`imageSmoothingQuality`](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/imageSmoothingQuality): set the quality of image smoothing, one of "low" (default), "medium", or "high". - (return value): - Type: `HTMLCanvasElement` @@ -934,7 +841,6 @@ cropper.getCroppedCanvas().toBlob(function (blob) { Change the aspect ratio of the crop box. - ### setDragMode([mode]) - **mode** (optional): @@ -946,14 +852,10 @@ Change the drag mode. **Tips:** You can toggle the "crop" and "move" mode by double click on the cropper. - [⬆ back to top](#table-of-contents) - - ## Events - ### ready This event fires when the target image has been loaded and the cropper instance is ready for cropping. @@ -969,7 +871,6 @@ image.addEventListener('ready', function () { cropper = new Cropper(image); ``` - ### cropstart - **event.detail.originalEvent**: @@ -1001,7 +902,6 @@ image.addEventListener('cropstart', function (e) { }); ``` - ### cropmove - **event.detail.originalEvent**: @@ -1012,7 +912,6 @@ image.addEventListener('cropstart', function (e) { This event fires when the canvas (image wrapper) or the crop box is changing. - ### cropend - **event.detail.originalEvent**: @@ -1023,7 +922,6 @@ This event fires when the canvas (image wrapper) or the crop box is changing. This event fires when the canvas (image wrapper) or the crop box stops to change. - ### crop - **event.detail.x** @@ -1038,7 +936,6 @@ This event fires when the canvas (image wrapper) or the crop box stops to change This event fires when the canvas (image wrapper) or the crop box changed. - ### zoom - **event.detail.originalEvent**: @@ -1068,11 +965,8 @@ image.addEventListener('zoom', function (e) { }); ``` - [⬆ back to top](#table-of-contents) - - ## No conflict If you have to use other cropper with the same namespace, just call the `Cropper.noConflict` static method to revert to it. @@ -1086,8 +980,6 @@ If you have to use other cropper with the same namespace, just call the `Cropper ``` - - ## Browser support - Chrome (latest) @@ -1097,26 +989,18 @@ If you have to use other cropper with the same namespace, just call the `Cropper - Edge (latest) - Internet Explorer 9+ - - ## Contributing Please read through our [contributing guidelines](CONTRIBUTING.md). - - ## Versioning Maintained under the [Semantic Versioning guidelines](http://semver.org/). - - ## License [MIT](http://opensource.org/licenses/MIT) © [Fengyuan Chen](http://chenfengyuan.com) - - ## Related projects - [iron-cropper](https://www.webcomponents.org/element/safetychanger/iron-cropper) (web component) by @safetychanger diff --git a/dist/cropper.common.js b/dist/cropper.common.js index c15f2b849..c3cdca2c0 100644 --- a/dist/cropper.common.js +++ b/dist/cropper.common.js @@ -1,21 +1,81 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:11:03.372Z */ 'use strict'; +var _window = window; +var PointerEvent = _window.PointerEvent; + + +var NAMESPACE = 'cropper'; + +// Actions +var ACTION_ALL = 'all'; +var ACTION_CROP = 'crop'; +var ACTION_MOVE = 'move'; +var ACTION_ZOOM = 'zoom'; +var ACTION_EAST = 'e'; +var ACTION_WEST = 'w'; +var ACTION_SOUTH = 's'; +var ACTION_NORTH = 'n'; +var ACTION_NORTH_EAST = 'ne'; +var ACTION_NORTH_WEST = 'nw'; +var ACTION_SOUTH_EAST = 'se'; +var ACTION_SOUTH_WEST = 'sw'; + +// Classes +var CLASS_CROP = NAMESPACE + '-crop'; +var CLASS_DISABLED = NAMESPACE + '-disabled'; +var CLASS_HIDDEN = NAMESPACE + '-hidden'; +var CLASS_HIDE = NAMESPACE + '-hide'; +var CLASS_INVISIBLE = NAMESPACE + '-invisible'; +var CLASS_MODAL = NAMESPACE + '-modal'; +var CLASS_MOVE = NAMESPACE + '-move'; + +// Data keys +var DATA_ACTION = 'action'; +var DATA_PREVIEW = 'preview'; + +// Drag modes +var DRAG_MODE_CROP = 'crop'; +var DRAG_MODE_MOVE = 'move'; +var DRAG_MODE_NONE = 'none'; + +// Events +var EVENT_CROP = 'crop'; +var EVENT_CROP_END = 'cropend'; +var EVENT_CROP_MOVE = 'cropmove'; +var EVENT_CROP_START = 'cropstart'; +var EVENT_DBLCLICK = 'dblclick'; +var EVENT_ERROR = 'error'; +var EVENT_LOAD = 'load'; +var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; +var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; +var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; +var EVENT_READY = 'ready'; +var EVENT_RESIZE = 'resize'; +var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; +var EVENT_ZOOM = 'zoom'; + +// RegExps +var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; +var REGEXP_DATA_URL = /^data:/; +var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; +var REGEXP_TAG_NAME = /^(img|canvas)$/i; + var DEFAULTS = { // Define the view mode of the cropper viewMode: 0, // 0, 1, 2, 3 // Define the dragging mode of the cropper - dragMode: 'crop', // 'crop', 'move' or 'none' + dragMode: DRAG_MODE_CROP, // 'crop', 'move' or 'none' // Define the aspect ratio of the crop box aspectRatio: NaN, @@ -110,94 +170,105 @@ var TEMPLATE = '
' + '
1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; @@ -220,6 +291,12 @@ function extend(obj) { return obj; } +/** + * Takes a function and returns a new one that will always have a particular context. + * @param {Function} fn - The target function. + * @param {Object} context - The new context for the function. + * @returns {boolean} The new function. + */ function proxy(fn, context) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; @@ -234,9 +311,17 @@ function proxy(fn, context) { }; } +var REGEXP_SUFFIX = /^(width|height|left|top|marginLeft|marginTop)$/; + +/** + * Apply styles to the given element. + * @param {Element} element - The target element. + * @param {Object} styles - The styles for applying. + */ function setStyle(element, styles) { var style = element.style; + each(styles, function (value, property) { if (REGEXP_SUFFIX.test(property) && isNumber(value)) { value += 'px'; @@ -246,10 +331,21 @@ function setStyle(element, styles) { }); } +/** + * Check if the given element has a special class. + * @param {Element} element - The element to check. + * @param {string} value - The class to search. + * @returns {boolean} Returns `true` if the special class was found. + */ function hasClass(element, value) { return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1; } +/** + * Add classes to the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be added. + */ function addClass(element, value) { if (!value) { return; @@ -267,7 +363,7 @@ function addClass(element, value) { return; } - var className = trim(element.className); + var className = element.className.trim(); if (!className) { element.className = value; @@ -276,6 +372,11 @@ function addClass(element, value) { } } +/** + * Remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be removed. + */ function removeClass(element, value) { if (!value) { return; @@ -298,6 +399,12 @@ function removeClass(element, value) { } } +/** + * Add or remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be toggled. + * @param {boolean} added - Add only. + */ function toggleClass(element, value, added) { if (!value) { return; @@ -318,10 +425,23 @@ function toggleClass(element, value, added) { } } -function hyphenate(str) { - return str.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); +var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g; + +/** + * Hyphenate the given value. + * @param {string} value - The value to hyphenate. + * @returns {string} The hyphenated value. + */ +function hyphenate(value) { + return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); } +/** + * Get data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to get. + * @returns {string} The data value. + */ function getData(element, name) { if (isObject(element[name])) { return element[name]; @@ -332,6 +452,12 @@ function getData(element, name) { return element.getAttribute('data-' + hyphenate(name)); } +/** + * Set data to the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to set. + * @param {string} data - The data value. + */ function setData(element, name, data) { if (isObject(data)) { element[name] = data; @@ -342,6 +468,11 @@ function setData(element, name, data) { } } +/** + * Remove data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to remove. + */ function removeData(element, name) { if (isObject(element[name])) { delete element[name]; @@ -357,53 +488,86 @@ function removeData(element, name) { } } -function removeListener(element, type, handler) { - var types = trim(type).split(REGEXP_SPACES); +var REGEXP_SPACES = /\s+/; + +/** + * Remove event listener from the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to remove, + * @param {Function} listener - The event listener to remove. + * @param {Object} options - The event options. + */ +function removeListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - removeListener(element, t, handler); + removeListener(element, t, listener); }); return; } + if (isFunction(listener.onceListener)) { + listener = listener.onceListener; + delete listener.onceListener; + } + if (element.removeEventListener) { - element.removeEventListener(type, handler, false); + element.removeEventListener(type, listener, options); } else if (element.detachEvent) { - element.detachEvent('on' + type, handler); + element.detachEvent('on' + type, listener); } } -function addListener(element, type, _handler, once) { - var types = trim(type).split(REGEXP_SPACES); - var originalHandler = _handler; +/** + * Add event listener to the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to add, + * @param {Function} listener - The event listener to add. + * @param {Object} options - The event options. + */ +function addListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - addListener(element, t, _handler); + addListener(element, t, listener); }); return; } - if (once) { - _handler = function handler() { + if (options.once) { + var originalListener = listener; + var onceListener = function onceListener() { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } - removeListener(element, type, _handler); - - return originalHandler.apply(element, args); + removeListener(element, type, onceListener); + return originalListener.apply(element, args); }; + originalListener.onceListener = onceListener; + listener = onceListener; } if (element.addEventListener) { - element.addEventListener(type, _handler, false); + element.addEventListener(type, listener, options); } else if (element.attachEvent) { - element.attachEvent('on' + type, _handler); + element.attachEvent('on' + type, listener); } } +/** + * Dispatch event on the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to dispatch, + * @param {Object} data - The additional event data. + * @returns {boolean} Indicate if the event is default prevented or not. + */ function dispatchEvent(element, type, data) { if (element.dispatchEvent) { var event = void 0; @@ -440,26 +604,11 @@ function dispatchEvent(element, type, data) { return true; } -function getEvent(event) { - var e = event || window.event; - - // Fix target property (IE8) - if (!e.target) { - e.target = e.srcElement || document; - } - - if (!isNumber(e.pageX) && isNumber(e.clientX)) { - var eventDoc = event.target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - e.pageX = e.clientX + ((doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0)); - e.pageY = e.clientY + ((doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0)); - } - - return e; -} - +/** + * Get the offset base on the document. + * @param {Element} element - The target element. + * @returns {Object} The offset data. + */ function getOffset(element) { var doc = document.documentElement; var box = element.getBoundingClientRect(); @@ -470,93 +619,79 @@ function getOffset(element) { }; } -function getByTag(element, tagName) { - return element.getElementsByTagName(tagName); -} - -function getByClass(element, className) { - return element.getElementsByClassName ? element.getElementsByClassName(className) : element.querySelectorAll('.' + className); -} - -function createElement(tagName) { - return document.createElement(tagName); -} - -function appendChild(element, elem) { - element.appendChild(elem); -} - -function removeChild(element) { - if (element.parentNode) { - element.parentNode.removeChild(element); - } -} - +/** + * Empty an element. + * @param {Element} element - The element to empty. + */ function empty(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } +var _window$1 = window; +var location = _window$1.location; + +var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i; + +/** + * Check if the given URL is a cross origin URL. + * @param {string} url - The target URL. + * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`. + */ function isCrossOriginURL(url) { var parts = url.match(REGEXP_ORIGINS); return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); } +/** + * Add timestamp to the given URL. + * @param {string} url - The target URL. + * @returns {string} The result URL. + */ function addTimestamp(url) { var timestamp = 'timestamp=' + new Date().getTime(); return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; } -function getImageSize(image, callback) { - // Modern browsers (ignore Safari) - if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { - callback(image.naturalWidth, image.naturalHeight); - return; - } - - // IE8: Don't use `new Image()` here - var newImage = createElement('img'); - - newImage.onload = function load() { - callback(this.width, this.height); - }; - - newImage.src = image.src; -} +/** + * Get transforms base on the given object. + * @param {Object} obj - The target object. + * @returns {string} A string contains transform values. + */ +function getTransforms(_ref) { + var rotate = _ref.rotate, + scaleX = _ref.scaleX, + scaleY = _ref.scaleY, + translateX = _ref.translateX, + translateY = _ref.translateY; -function getTransforms(data) { - var transforms = []; - var translateX = data.translateX; - var translateY = data.translateY; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; + var values = []; if (isNumber(translateX) && translateX !== 0) { - transforms.push('translateX(' + translateX + 'px)'); + values.push('translateX(' + translateX + 'px)'); } if (isNumber(translateY) && translateY !== 0) { - transforms.push('translateY(' + translateY + 'px)'); + values.push('translateY(' + translateY + 'px)'); } // Rotate should come first before scale to match orientation transform if (isNumber(rotate) && rotate !== 0) { - transforms.push('rotate(' + rotate + 'deg)'); + values.push('rotate(' + rotate + 'deg)'); } if (isNumber(scaleX) && scaleX !== 1) { - transforms.push('scaleX(' + scaleX + ')'); + values.push('scaleX(' + scaleX + ')'); } if (isNumber(scaleY) && scaleY !== 1) { - transforms.push('scaleY(' + scaleY + ')'); + values.push('scaleY(' + scaleY + ')'); } - var transform = transforms.length ? transforms.join(' ') : 'none'; + var transform = values.length ? values.join(' ') : 'none'; return { WebkitTransform: transform, @@ -565,136 +700,326 @@ function getTransforms(data) { }; } -function getRotatedSizes(data, reversed) { - var deg = Math.abs(data.degree) % 180; - var arc = (deg > 90 ? 180 - deg : deg) * Math.PI / 180; - var sinArc = Math.sin(arc); - var cosArc = Math.cos(arc); - var width = data.width; - var height = data.height; - var aspectRatio = data.aspectRatio; - var newWidth = void 0; - var newHeight = void 0; - - if (!reversed) { - newWidth = width * cosArc + height * sinArc; - newHeight = width * sinArc + height * cosArc; - } else { - newWidth = width / (cosArc + sinArc / aspectRatio); - newHeight = newWidth / aspectRatio; +var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent); + +/** + * Get an image's natural sizes. + * @param {string} image - The target image. + * @param {Function} callback - The callback function. + */ +function getImageNaturalSizes(image, callback) { + // Modern browsers (except Safari) + if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { + callback(image.naturalWidth, image.naturalHeight); + return; } - return { - width: newWidth, - height: newHeight + var newImage = document.createElement('img'); + + newImage.onload = function () { + callback(newImage.width, newImage.height); }; + + newImage.src = image.src; } -function getSourceCanvas(image, data, options) { - var canvas = createElement('canvas'); - var context = canvas.getContext('2d'); - var dstX = 0; - var dstY = 0; - var dstWidth = data.naturalWidth; - var dstHeight = data.naturalHeight; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; - var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1); - var rotatable = isNumber(rotate) && rotate !== 0; - var advanced = rotatable || scalable; - var canvasWidth = dstWidth * Math.abs(scaleX || 1); - var canvasHeight = dstHeight * Math.abs(scaleY || 1); - var translateX = void 0; - var translateY = void 0; - var rotated = void 0; - - if (scalable) { - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } +/** + * Get the max ratio of a group of pointers. + * @param {string} pointers - The target pointers. + * @returns {number} The result ratio. + */ +function getMaxZoomRatio(pointers) { + var pointers2 = extend({}, pointers); + var ratios = []; - if (rotatable) { - rotated = getRotatedSizes({ - width: canvasWidth, - height: canvasHeight, - degree: rotate + each(pointers, function (pointer, pointerId) { + delete pointers2[pointerId]; + + each(pointers2, function (pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + + ratios.push(ratio); }); + }); - canvasWidth = rotated.width; - canvasHeight = rotated.height; - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } + ratios.sort(function (a, b) { + return Math.abs(a) < Math.abs(b); + }); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + return ratios[0]; +} - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); - } +/** + * Get a pointer from an event object. + * @param {Object} event - The target event object. + * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. + * @returns {Object} The result pointer contains start and/or end point coordinates. + */ +function getPointer(_ref2, endOnly) { + var pageX = _ref2.pageX, + pageY = _ref2.pageY; - if (advanced) { - dstX = -dstWidth / 2; - dstY = -dstHeight / 2; + var end = { + endX: pageX, + endY: pageY + }; - context.save(); - context.translate(translateX, translateY); + if (endOnly) { + return end; } - // Rotate should come first before scale as in the "getTransform" function - if (rotatable) { - context.rotate(rotate * Math.PI / 180); - } + return extend({ + startX: pageX, + startY: pageY + }, end); +} - if (scalable) { - context.scale(scaleX, scaleY); - } +/** + * Get the center point coordinate of a group of pointers. + * @param {Object} pointers - The target pointers. + * @returns {Object} The center point coordinate. + */ +function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + each(pointers, function (_ref3) { + var startX = _ref3.startX, + startY = _ref3.startY; + + pageX += startX; + pageY += startY; + count += 1; + }); + + pageX /= count; + pageY /= count; + + return { + pageX: pageX, + pageY: pageY + }; +} + +/** + * Check if the given value is a finite number. + */ +var isFinite = Number.isFinite || window.isFinite; + +/** + * Get the max sizes in a rectangle under the given aspect ratio. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getContainSizes(_ref4) { + var aspectRatio = _ref4.aspectRatio, + height = _ref4.height, + width = _ref4.width; - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; + var isValidNumber = function isValidNumber(value) { + return isFinite(value) && value > 0; + }; + + if (isValidNumber(width) && isValidNumber(height)) { + if (height * aspectRatio > width) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } + } else if (isValidNumber(width)) { + height = width / aspectRatio; + } else if (isValidNumber(height)) { + width = height * aspectRatio; } - context.drawImage(image, Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + return { + width: width, + height: height + }; +} + +/** + * Get the new sizes of a rectangle after rotated. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getRotatedSizes(_ref5) { + var width = _ref5.width, + height = _ref5.height, + degree = _ref5.degree; - if (advanced) { - context.restore(); + degree = Math.abs(degree); + + if (degree % 180 === 90) { + return { + width: height, + height: width + }; } + var arc = degree % 90 * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + + return { + width: width * cosArc + height * sinArc, + height: width * sinArc + height * cosArc + }; +} + +/** + * Get a canvas which drew the given image. + * @param {HTMLImageElement} image - The image for drawing. + * @param {Object} imageData - The image data. + * @param {Object} canvasData - The canvas data. + * @param {Object} options - The options. + * @returns {HTMLCanvasElement} The result canvas. + */ +function getSourceCanvas(image, _ref6, _ref7, _ref8) { + var imageNaturalWidth = _ref6.naturalWidth, + imageNaturalHeight = _ref6.naturalHeight, + rotate = _ref6.rotate, + scaleX = _ref6.scaleX, + scaleY = _ref6.scaleY; + var aspectRatio = _ref7.aspectRatio, + naturalWidth = _ref7.naturalWidth, + naturalHeight = _ref7.naturalHeight; + var _ref8$fillColor = _ref8.fillColor, + fillColor = _ref8$fillColor === undefined ? 'transparent' : _ref8$fillColor, + _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled, + imageSmoothingEnabled = _ref8$imageSmoothingE === undefined ? true : _ref8$imageSmoothingE, + _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality, + imageSmoothingQuality = _ref8$imageSmoothingQ === undefined ? 'low' : _ref8$imageSmoothingQ, + _ref8$maxWidth = _ref8.maxWidth, + maxWidth = _ref8$maxWidth === undefined ? Infinity : _ref8$maxWidth, + _ref8$maxHeight = _ref8.maxHeight, + maxHeight = _ref8$maxHeight === undefined ? Infinity : _ref8$maxHeight, + _ref8$minWidth = _ref8.minWidth, + minWidth = _ref8$minWidth === undefined ? 0 : _ref8$minWidth, + _ref8$minHeight = _ref8.minHeight, + minHeight = _ref8$minHeight === undefined ? 0 : _ref8$minHeight; + + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: maxWidth, + height: maxHeight + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minWidth, + height: minHeight + }); + var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth)); + var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); + + canvas.width = width; + canvas.height = height; + context.fillStyle = fillColor; + context.fillRect(0, 0, width, height); + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.imageSmoothingEnabled = imageSmoothingEnabled; + context.imageSmoothingQuality = imageSmoothingQuality; + context.drawImage(image, Math.floor(-imageNaturalWidth / 2), Math.floor(-imageNaturalHeight / 2), Math.floor(imageNaturalWidth), Math.floor(imageNaturalHeight)); + context.restore(); return canvas; } +var fromCharCode = String.fromCharCode; + +/** + * Get string from char code in data view. + * @param {DataView} dataView - The data view for read. + * @param {number} start - The start index. + * @param {number} length - The read length. + * @returns {string} The read result. + */ + function getStringFromCharCode(dataView, start, length) { var str = ''; - var i = start; + var i = void 0; + + length += start; - for (length += start; i < length; i += 1) { + for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } return str; } +var _window2 = window; +var atob = _window2.atob; + +var REGEXP_DATA_URL_HEAD = /^data:.*,/; + +/** + * Transform Data URL to array buffer. + * @param {string} dataURL - The Data URL to transform. + * @returns {ArrayBuffer} The result array buffer. + */ +function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var arrayBuffer = new ArrayBuffer(binary.length); + var uint8 = new Uint8Array(arrayBuffer); + + each(uint8, function (value, i) { + uint8[i] = binary.charCodeAt(i); + }); + + return arrayBuffer; +} + +var _window3 = window; +var btoa = _window3.btoa; + +/** + * Transform array buffer to Data URL. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {string} mimeType - The mime type of the Data URL. + * @returns {string} The result Data URL. + */ + +function arrayBufferToDataURL(arrayBuffer, mimeType) { + var uint8 = new Uint8Array(arrayBuffer); + var data = ''; + + // TypedArray.prototype.forEach is not supported in some browsers. + each(uint8, function (value) { + data += fromCharCode(value); + }); + + return 'data:' + mimeType + ';base64,' + btoa(data); +} + +/** + * Get orientation value from given array buffer. + * @param {ArrayBuffer} arrayBuffer - The array buffer to read. + * @returns {number} The read orientation value. + */ function getOrientation(arrayBuffer) { var dataView = new DataView(arrayBuffer); - var length = dataView.byteLength; var orientation = void 0; - var exifIDCode = void 0; - var tiffOffset = void 0; - var firstIFDOffset = void 0; var littleEndian = void 0; - var endianness = void 0; var app1Start = void 0; var ifdStart = void 0; - var offset = void 0; - var i = void 0; // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - offset = 2; + var length = dataView.byteLength; + var offset = 2; while (offset < length) { if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { @@ -707,16 +1032,17 @@ function getOrientation(arrayBuffer) { } if (app1Start) { - exifIDCode = app1Start + 4; - tiffOffset = app1Start + 10; + var exifIDCode = app1Start + 4; + var tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - endianness = dataView.getUint16(tiffOffset); + var endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; @@ -727,23 +1053,22 @@ function getOrientation(arrayBuffer) { } if (ifdStart) { - length = dataView.getUint16(ifdStart, littleEndian); + var _length = dataView.getUint16(ifdStart, littleEndian); + var _offset = void 0; + var i = void 0; - for (i = 0; i < length; i += 1) { - offset = ifdStart + i * 12 + 2; + for (i = 0; i < _length; i += 1) { + _offset = ifdStart + i * 12 + 2; - if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) { + if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) { // 8 is the offset of the current tag's value - offset += 8; + _offset += 8; // Get the original orientation value - orientation = dataView.getUint16(offset, littleEndian); - - // Override the orientation with its default value for Safari - if (IS_SAFARI_OR_UIWEBVIEW) { - dataView.setUint16(offset, 1, littleEndian); - } + orientation = dataView.getUint16(_offset, littleEndian); + // Override the orientation with its default value + dataView.setUint16(_offset, 1, littleEndian); break; } } @@ -752,83 +1077,108 @@ function getOrientation(arrayBuffer) { return orientation; } -function dataURLToArrayBuffer(dataURL) { - var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); - var binary = atob(base64); - var length = binary.length; - var arrayBuffer = new ArrayBuffer(length); - var dataView = new Uint8Array(arrayBuffer); - var i = void 0; - - for (i = 0; i < length; i += 1) { - dataView[i] = binary.charCodeAt(i); - } - - return arrayBuffer; -} - -// Only available for JPEG image -function arrayBufferToDataURL(arrayBuffer) { - var dataView = new Uint8Array(arrayBuffer); - var length = dataView.length; - var base64 = ''; - var i = void 0; - - for (i = 0; i < length; i += 1) { - base64 += fromCharCode(dataView[i]); +/** + * Parse Exif Orientation value. + * @param {number} orientation - The orientation to parse. + * @returns {Object} The parsed result. + */ +function parseOrientation(orientation) { + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + + switch (orientation) { + // Flip horizontal + case 2: + scaleX = -1; + break; + + // Rotate left 180° + case 3: + rotate = -180; + break; + + // Flip vertical + case 4: + scaleY = -1; + break; + + // Flip vertical and rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // Rotate right 90° + case 6: + rotate = 90; + break; + + // Flip horizontal and rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // Rotate left 90° + case 8: + rotate = -90; + break; + + default: } - return 'data:image/jpeg;base64,' + btoa(base64); + return { + rotate: rotate, + scaleX: scaleX, + scaleY: scaleY + }; } var render = { render: function render() { - var self = this; - - self.initContainer(); - self.initCanvas(); - self.initCropBox(); + this.initContainer(); + this.initCanvas(); + this.initCropBox(); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } }, initContainer: function initContainer() { - var self = this; - var options = self.options; - var element = self.element; - var container = self.container; - var cropper = self.cropper; - var hidden = 'cropper-hidden'; + var element = this.element, + options = this.options, + container = this.container, + cropper = this.cropper; + - addClass(cropper, hidden); - removeClass(element, hidden); + addClass(cropper, CLASS_HIDDEN); + removeClass(element, CLASS_HIDDEN); var containerData = { width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200), height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100) }; - self.containerData = containerData; + this.containerData = containerData; setStyle(cropper, { width: containerData.width, height: containerData.height }); - addClass(element, hidden); - removeClass(cropper, hidden); + addClass(element, CLASS_HIDDEN); + removeClass(cropper, CLASS_HIDDEN); }, // Canvas (image wrapper) initCanvas: function initCanvas() { - var self = this; - var viewMode = self.options.viewMode; - var containerData = self.containerData; - var imageData = self.imageData; + var containerData = this.containerData, + imageData = this.imageData; + var viewMode = this.options.viewMode; + var rotated = Math.abs(imageData.rotate) % 180 === 90; var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth; var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight; @@ -849,9 +1199,9 @@ var render = { } var canvasData = { + aspectRatio: aspectRatio, naturalWidth: naturalWidth, naturalHeight: naturalHeight, - aspectRatio: aspectRatio, width: canvasWidth, height: canvasHeight }; @@ -861,21 +1211,21 @@ var render = { canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - self.canvasData = canvasData; - self.limited = viewMode === 1 || viewMode === 2; - self.limitCanvas(true, true); - self.initialImageData = extend({}, imageData); - self.initialCanvasData = extend({}, canvasData); + this.canvasData = canvasData; + this.limited = viewMode === 1 || viewMode === 2; + this.limitCanvas(true, true); + this.initialImageData = extend({}, imageData); + this.initialCanvasData = extend({}, canvasData); }, limitCanvas: function limitCanvas(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; var viewMode = options.viewMode; - var containerData = self.containerData; - var canvasData = self.canvasData; var aspectRatio = canvasData.aspectRatio; - var cropBoxData = self.cropBoxData; - var cropped = self.cropped && cropBoxData; + + var cropped = this.cropped && cropBoxData; if (sizeLimited) { var minCanvasWidth = Number(options.minCanvasWidth) || 0; @@ -909,17 +1259,15 @@ var render = { } } - if (minCanvasWidth && minCanvasHeight) { - if (minCanvasHeight * aspectRatio > minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else { - minCanvasWidth = minCanvasHeight * aspectRatio; - } - } else if (minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else if (minCanvasHeight) { - minCanvasWidth = minCanvasHeight * aspectRatio; - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minCanvasWidth, + height: minCanvasHeight + }); + + minCanvasWidth = _getContainSizes.width; + minCanvasHeight = _getContainSizes.height; + canvasData.minWidth = minCanvasWidth; canvasData.minHeight = minCanvasHeight; @@ -937,7 +1285,7 @@ var render = { canvasData.maxLeft = Math.max(0, newCanvasLeft); canvasData.maxTop = Math.max(0, newCanvasTop); - if (cropped && self.limited) { + if (cropped && this.limited) { canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width)); canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height)); canvasData.maxLeft = cropBoxData.left; @@ -963,47 +1311,31 @@ var render = { } } }, - renderCanvas: function renderCanvas(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var rotate = imageData.rotate; - - if (self.rotated) { - self.rotated = false; - - // Computes rotated sizes with image sizes - var rotatedData = getRotatedSizes({ - width: imageData.width, - height: imageData.height, - degree: rotate - }); - var aspectRatio = rotatedData.width / rotatedData.height; - var isSquareImage = imageData.aspectRatio === 1; - - if (isSquareImage || aspectRatio !== canvasData.aspectRatio) { - canvasData.left -= (rotatedData.width - canvasData.width) / 2; - canvasData.top -= (rotatedData.height - canvasData.height) / 2; - canvasData.width = rotatedData.width; - canvasData.height = rotatedData.height; - canvasData.aspectRatio = aspectRatio; - canvasData.naturalWidth = imageData.naturalWidth; - canvasData.naturalHeight = imageData.naturalHeight; - - // Computes rotated sizes with natural image sizes - if (isSquareImage && rotate % 90 || rotate % 180) { - var rotatedData2 = getRotatedSizes({ - width: imageData.naturalWidth, - height: imageData.naturalHeight, - degree: rotate - }); + renderCanvas: function renderCanvas(changed, transformed) { + var canvasData = this.canvasData, + imageData = this.imageData; - canvasData.naturalWidth = rotatedData2.width; - canvasData.naturalHeight = rotatedData2.height; - } - self.limitCanvas(true, false); - } + if (transformed) { + var _getRotatedSizes = getRotatedSizes({ + width: imageData.naturalWidth * Math.abs(imageData.scaleX), + height: imageData.naturalHeight * Math.abs(imageData.scaleY), + degree: imageData.rotate + }), + naturalWidth = _getRotatedSizes.width, + naturalHeight = _getRotatedSizes.height; + + var width = canvasData.width * (naturalWidth / canvasData.naturalWidth); + var height = canvasData.height * (naturalHeight / canvasData.naturalHeight); + + canvasData.left -= (width - canvasData.width) / 2; + canvasData.top -= (height - canvasData.height) / 2; + canvasData.width = width; + canvasData.height = height; + canvasData.aspectRatio = naturalWidth / naturalHeight; + canvasData.naturalWidth = naturalWidth; + canvasData.naturalHeight = naturalHeight; + this.limitCanvas(true, false); } if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) { @@ -1017,14 +1349,14 @@ var render = { canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); - self.limitCanvas(false, true); + this.limitCanvas(false, true); canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft); canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop); canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - setStyle(self.canvas, extend({ + setStyle(this.canvas, extend({ width: canvasData.width, height: canvasData.height }, getTransforms({ @@ -1032,52 +1364,26 @@ var render = { translateY: canvasData.top }))); - self.renderImage(); + this.renderImage(changed); - if (self.cropped && self.limited) { - self.limitCropBox(true, true); - } - - if (changed) { - self.output(); + if (this.cropped && this.limited) { + this.limitCropBox(true, true); } }, renderImage: function renderImage(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var newImageData = void 0; - var reversedData = void 0; - var reversedWidth = void 0; - var reversedHeight = void 0; - - if (imageData.rotate) { - reversedData = getRotatedSizes({ - width: canvasData.width, - height: canvasData.height, - degree: imageData.rotate, - aspectRatio: imageData.aspectRatio - }, true); - - reversedWidth = reversedData.width; - reversedHeight = reversedData.height; - - newImageData = { - width: reversedWidth, - height: reversedHeight, - left: (canvasData.width - reversedWidth) / 2, - top: (canvasData.height - reversedHeight) / 2 - }; - } + var canvasData = this.canvasData, + imageData = this.imageData; - extend(imageData, newImageData || { - width: canvasData.width, - height: canvasData.height, - left: 0, - top: 0 - }); + var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth); + var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight); - setStyle(self.image, extend({ + extend(imageData, { + width: width, + height: height, + left: (canvasData.width - width) / 2, + top: (canvasData.height - height) / 2 + }); + setStyle(this.image, extend({ width: imageData.width, height: imageData.height }, getTransforms(extend({ @@ -1086,15 +1392,15 @@ var render = { }, imageData)))); if (changed) { - self.output(); + this.output(); } }, initCropBox: function initCropBox() { - var self = this; - var options = self.options; + var options = this.options, + canvasData = this.canvasData; var aspectRatio = options.aspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; - var canvasData = self.canvasData; var cropBoxData = { width: canvasData.width, height: canvasData.height @@ -1108,8 +1414,8 @@ var render = { } } - self.cropBoxData = cropBoxData; - self.limitCropBox(true, true); + this.cropBoxData = cropBoxData; + this.limitCropBox(true, true); // Initialize auto crop area cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); @@ -1123,16 +1429,16 @@ var render = { cropBoxData.oldLeft = cropBoxData.left; cropBoxData.oldTop = cropBoxData.top; - self.initialCropBoxData = extend({}, cropBoxData); + this.initialCropBoxData = extend({}, cropBoxData); }, limitCropBox: function limitCropBox(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData, + limited = this.limited; var aspectRatio = options.aspectRatio; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var limited = self.limited; + if (sizeLimited) { var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; @@ -1140,7 +1446,7 @@ var render = { var maxCropBoxWidth = Math.min(containerData.width, limited ? canvasData.width : containerData.width); var maxCropBoxHeight = Math.min(containerData.height, limited ? canvasData.height : containerData.height); - // The min/maxCropBoxWidth/Height must be less than containerWidth/Height + // The min/maxCropBoxWidth/Height must be less than container's width/height minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width); minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height); @@ -1186,10 +1492,10 @@ var render = { } }, renderCropBox: function renderCropBox() { - var self = this; - var options = self.options; - var containerData = self.containerData; - var cropBoxData = self.cropBoxData; + var options = this.options, + containerData = this.containerData, + cropBoxData = this.cropBoxData; + if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) { cropBoxData.left = cropBoxData.oldLeft; @@ -1202,7 +1508,7 @@ var render = { cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); - self.limitCropBox(false, true); + this.limitCropBox(false, true); cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft); cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop); @@ -1211,10 +1517,10 @@ var render = { if (options.movable && options.cropBoxMovable) { // Turn to move the canvas when the crop box is equal to the container - setData(self.face, 'action', cropBoxData.width === containerData.width && cropBoxData.height === containerData.height ? 'move' : 'all'); + setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL); } - setStyle(self.cropBox, extend({ + setStyle(this.cropBox, extend({ width: cropBoxData.width, height: cropBoxData.height }, getTransforms({ @@ -1222,42 +1528,38 @@ var render = { translateY: cropBoxData.top }))); - if (self.cropped && self.limited) { - self.limitCanvas(true, true); + if (this.cropped && this.limited) { + this.limitCanvas(true, true); } - if (!self.disabled) { - self.output(); + if (!this.disabled) { + this.output(); } }, output: function output() { - var self = this; - - self.preview(); + this.preview(); - if (self.complete) { - dispatchEvent(self.element, 'crop', self.getData()); + if (this.complete) { + dispatchEvent(this.element, EVENT_CROP, this.getData()); } } }; -var DATA_PREVIEW = 'preview'; - var preview = { initPreview: function initPreview() { - var self = this; - var preview = self.options.preview; - var image = createElement('img'); - var crossOrigin = self.crossOrigin; - var url = crossOrigin ? self.crossOriginUrl : self.url; + var crossOrigin = this.crossOrigin; + var preview = this.options.preview; + + var url = crossOrigin ? this.crossOriginUrl : this.url; + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; } image.src = url; - appendChild(self.viewBox, image); - self.image2 = image; + this.viewBox.appendChild(image); + this.image2 = image; if (!preview) { return; @@ -1265,10 +1567,10 @@ var preview = { var previews = preview.querySelector ? [preview] : document.querySelectorAll(preview); - self.previews = previews; + this.previews = previews; each(previews, function (element) { - var img = createElement('img'); + var img = document.createElement('img'); // Save the original size for recover setData(element, DATA_PREVIEW, { @@ -1293,7 +1595,7 @@ var preview = { 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;"'; empty(element); - appendChild(element, img); + element.appendChild(img); }); }, resetPreview: function resetPreview() { @@ -1310,22 +1612,22 @@ var preview = { }); }, preview: function preview() { - var self = this; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var cropBoxWidth = cropBoxData.width; - var cropBoxHeight = cropBoxData.height; - var width = imageData.width; - var height = imageData.height; + var imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var cropBoxWidth = cropBoxData.width, + cropBoxHeight = cropBoxData.height; + var width = imageData.width, + height = imageData.height; + var left = cropBoxData.left - canvasData.left - imageData.left; var top = cropBoxData.top - canvasData.top - imageData.top; - if (!self.cropped || self.disabled) { + if (!this.cropped || this.disabled) { return; } - setStyle(self.image2, extend({ + setStyle(this.image2, extend({ width: width, height: height }, getTransforms(extend({ @@ -1333,7 +1635,7 @@ var preview = { translateY: -top }, imageData)))); - each(self.previews, function (element) { + each(this.previews, function (element) { var data = getData(element, DATA_PREVIEW); var originalWidth = data.width; var originalHeight = data.height; @@ -1357,39 +1659,23 @@ var preview = { height: newHeight }); - setStyle(getByTag(element, 'img')[0], extend({ + setStyle(element.getElementsByTagName('img')[0], extend({ width: width * ratio, height: height * ratio }, getTransforms(extend({ translateX: -left * ratio, translateY: -top * ratio - }, imageData)))); - }); - } -}; - -// Globals -var PointerEvent = typeof window !== 'undefined' ? window.PointerEvent : null; - -// Events -var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; -var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; -var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; -var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; -var EVENT_DBLCLICK = 'dblclick'; -var EVENT_RESIZE = 'resize'; -var EVENT_CROP_START = 'cropstart'; -var EVENT_CROP_MOVE = 'cropmove'; -var EVENT_CROP_END = 'cropend'; -var EVENT_CROP$1 = 'crop'; -var EVENT_ZOOM = 'zoom'; + }, imageData)))); + }); + } +}; var events = { bind: function bind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { addListener(element, EVENT_CROP_START, options.cropstart); @@ -1404,35 +1690,35 @@ var events = { } if (isFunction(options.crop)) { - addListener(element, EVENT_CROP$1, options.crop); + addListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { addListener(element, EVENT_ZOOM, options.zoom); } - addListener(cropper, EVENT_POINTER_DOWN, self.onCropStart = proxy(self.cropStart, self)); + addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = proxy(this.cropStart, this)); if (options.zoomable && options.zoomOnWheel) { - addListener(cropper, EVENT_WHEEL, self.onWheel = proxy(self.wheel, self)); + addListener(cropper, EVENT_WHEEL, this.onWheel = proxy(this.wheel, this)); } if (options.toggleDragModeOnDblclick) { - addListener(cropper, EVENT_DBLCLICK, self.onDblclick = proxy(self.dblclick, self)); + addListener(cropper, EVENT_DBLCLICK, this.onDblclick = proxy(this.dblclick, this)); } - addListener(document, EVENT_POINTER_MOVE, self.onCropMove = proxy(self.cropMove, self)); - addListener(document, EVENT_POINTER_UP, self.onCropEnd = proxy(self.cropEnd, self)); + addListener(document, EVENT_POINTER_MOVE, this.onCropMove = proxy(this.cropMove, this)); + addListener(document, EVENT_POINTER_UP, this.onCropEnd = proxy(this.cropEnd, this)); if (options.responsive) { - addListener(window, EVENT_RESIZE, self.onResize = proxy(self.resize, self)); + addListener(window, EVENT_RESIZE, this.onResize = proxy(this.resize, this)); } }, unbind: function unbind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { removeListener(element, EVENT_CROP_START, options.cropstart); @@ -1447,63 +1733,42 @@ var events = { } if (isFunction(options.crop)) { - removeListener(element, EVENT_CROP$1, options.crop); + removeListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { removeListener(element, EVENT_ZOOM, options.zoom); } - removeListener(cropper, EVENT_POINTER_DOWN, self.onCropStart); + removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart); if (options.zoomable && options.zoomOnWheel) { - removeListener(cropper, EVENT_WHEEL, self.onWheel); + removeListener(cropper, EVENT_WHEEL, this.onWheel); } if (options.toggleDragModeOnDblclick) { - removeListener(cropper, EVENT_DBLCLICK, self.onDblclick); + removeListener(cropper, EVENT_DBLCLICK, this.onDblclick); } - removeListener(document, EVENT_POINTER_MOVE, self.onCropMove); - removeListener(document, EVENT_POINTER_UP, self.onCropEnd); + removeListener(document, EVENT_POINTER_MOVE, this.onCropMove); + removeListener(document, EVENT_POINTER_UP, this.onCropEnd); if (options.responsive) { - removeListener(window, EVENT_RESIZE, self.onResize); + removeListener(window, EVENT_RESIZE, this.onResize); } } }; -var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; - -function getPointer(_ref, endOnly) { - var pageX = _ref.pageX, - pageY = _ref.pageY; - - var end = { - endX: pageX, - endY: pageY - }; - - if (endOnly) { - return end; - } - - return extend({ - startX: pageX, - startY: pageY - }, end); -} - var handlers = { resize: function resize() { - var self = this; - var options = self.options; - var container = self.container; - var containerData = self.containerData; + var options = this.options, + container = this.container, + containerData = this.containerData; + var minContainerWidth = Number(options.minContainerWidth) || 200; var minContainerHeight = Number(options.minContainerHeight) || 100; - if (self.disabled || containerData.width === minContainerWidth || containerData.height === minContainerHeight) { + if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) { return; } @@ -1515,52 +1780,50 @@ var handlers = { var cropBoxData = void 0; if (options.restore) { - canvasData = self.getCanvasData(); - cropBoxData = self.getCropBoxData(); + canvasData = this.getCanvasData(); + cropBoxData = this.getCropBoxData(); } - self.render(); + this.render(); if (options.restore) { - self.setCanvasData(each(canvasData, function (n, i) { + this.setCanvasData(each(canvasData, function (n, i) { canvasData[i] = n * ratio; })); - self.setCropBoxData(each(cropBoxData, function (n, i) { + this.setCropBoxData(each(cropBoxData, function (n, i) { cropBoxData[i] = n * ratio; })); } } }, dblclick: function dblclick() { - var self = this; - - if (self.disabled || self.options.dragMode === 'none') { + if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) { return; } - self.setDragMode(hasClass(self.dragBox, 'cropper-crop') ? 'move' : 'crop'); + this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP); }, - wheel: function wheel(event) { - var self = this; - var e = getEvent(event); - var ratio = Number(self.options.wheelZoomRatio) || 0.1; + wheel: function wheel(e) { + var _this = this; + + var ratio = Number(this.options.wheelZoomRatio) || 0.1; var delta = 1; - if (self.disabled) { + if (this.disabled) { return; } e.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21) - if (self.wheeling) { + if (this.wheeling) { return; } - self.wheeling = true; + this.wheeling = true; setTimeout(function () { - self.wheeling = false; + _this.wheeling = false; }, 50); if (e.deltaY) { @@ -1571,18 +1834,16 @@ var handlers = { delta = e.detail > 0 ? 1 : -1; } - self.zoom(-delta * ratio, e); + this.zoom(-delta * ratio, e); }, - cropStart: function cropStart(event) { - var self = this; - - if (self.disabled) { + cropStart: function cropStart(e) { + if (this.disabled) { return; } - var options = self.options; - var pointers = self.pointers; - var e = getEvent(event); + var options = this.options, + pointers = this.pointers; + var action = void 0; if (e.changedTouches) { @@ -1596,16 +1857,16 @@ var handlers = { } if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { - action = 'zoom'; + action = ACTION_ZOOM; } else { - action = getData(e.target, 'action'); + action = getData(e.target, DATA_ACTION); } if (!REGEXP_ACTIONS.test(action)) { return; } - if (dispatchEvent(self.element, 'cropstart', { + if (dispatchEvent(this.element, EVENT_CROP_START, { originalEvent: e, action: action }) === false) { @@ -1614,28 +1875,28 @@ var handlers = { e.preventDefault(); - self.action = action; - self.cropping = false; + this.action = action; + this.cropping = false; - if (action === 'crop') { - self.cropping = true; - addClass(self.dragBox, 'cropper-modal'); + if (action === ACTION_CROP) { + this.cropping = true; + addClass(this.dragBox, CLASS_MODAL); } }, - cropMove: function cropMove(event) { - var self = this; - var action = self.action; + cropMove: function cropMove(e) { + var action = this.action; + - if (self.disabled || !action) { + if (this.disabled || !action) { return; } - var pointers = self.pointers; - var e = getEvent(event); + var pointers = this.pointers; + e.preventDefault(); - if (dispatchEvent(self.element, 'cropmove', { + if (dispatchEvent(this.element, EVENT_CROP_MOVE, { originalEvent: e, action: action }) === false) { @@ -1650,18 +1911,16 @@ var handlers = { extend(pointers[e.pointerId || 0], getPointer(e, true)); } - self.change(e); + this.change(e); }, - cropEnd: function cropEnd(event) { - var self = this; - - if (self.disabled) { + cropEnd: function cropEnd(e) { + if (this.disabled) { return; } - var action = self.action; - var pointers = self.pointers; - var e = getEvent(event); + var action = this.action, + pointers = this.pointers; + if (e.changedTouches) { each(e.changedTouches, function (touch) { @@ -1678,71 +1937,35 @@ var handlers = { e.preventDefault(); if (!Object.keys(pointers).length) { - self.action = ''; + this.action = ''; } - if (self.cropping) { - self.cropping = false; - toggleClass(self.dragBox, 'cropper-modal', self.cropped && this.options.modal); + if (this.cropping) { + this.cropping = false; + toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal); } - dispatchEvent(self.element, 'cropend', { + dispatchEvent(this.element, EVENT_CROP_END, { originalEvent: e, action: action }); } }; -// Actions -var ACTION_EAST = 'e'; -var ACTION_WEST = 'w'; -var ACTION_SOUTH = 's'; -var ACTION_NORTH = 'n'; -var ACTION_SOUTH_EAST = 'se'; -var ACTION_SOUTH_WEST = 'sw'; -var ACTION_NORTH_EAST = 'ne'; -var ACTION_NORTH_WEST = 'nw'; - -function getMaxZoomRatio(pointers) { - var pointers2 = extend({}, pointers); - var ratios = []; - - each(pointers, function (pointer, pointerId) { - delete pointers2[pointerId]; - - each(pointers2, function (pointer2) { - var x1 = Math.abs(pointer.startX - pointer2.startX); - var y1 = Math.abs(pointer.startY - pointer2.startY); - var x2 = Math.abs(pointer.endX - pointer2.endX); - var y2 = Math.abs(pointer.endY - pointer2.endY); - var z1 = Math.sqrt(x1 * x1 + y1 * y1); - var z2 = Math.sqrt(x2 * x2 + y2 * y2); - var ratio = (z2 - z1) / z1; - - ratios.push(ratio); - }); - }); - - ratios.sort(function (a, b) { - return Math.abs(a) < Math.abs(b); - }); - - return ratios[0]; -} - var change = { change: function change(e) { - var self = this; - var options = self.options; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; + var options = this.options, + canvasData = this.canvasData, + containerData = this.containerData, + cropBoxData = this.cropBoxData, + pointers = this.pointers; + var action = this.action; var aspectRatio = options.aspectRatio; - var action = self.action; - var width = cropBoxData.width; - var height = cropBoxData.height; - var left = cropBoxData.left; - var top = cropBoxData.top; + var left = cropBoxData.left, + top = cropBoxData.top, + width = cropBoxData.width, + height = cropBoxData.height; + var right = left + width; var bottom = top + height; var minLeft = 0; @@ -1757,23 +1980,56 @@ var change = { aspectRatio = width && height ? width / height : 1; } - if (self.limited) { + if (this.limited) { minLeft = cropBoxData.minLeft; minTop = cropBoxData.minTop; + maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width); maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height); } - var pointers = self.pointers; var pointer = pointers[Object.keys(pointers)[0]]; var range = { x: pointer.endX - pointer.startX, y: pointer.endY - pointer.startY }; + var check = function check(side) { + switch (side) { + case ACTION_EAST: + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + + break; + + case ACTION_WEST: + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + + break; + + case ACTION_NORTH: + if (top + range.y < minTop) { + range.y = minTop - top; + } + + break; + + case ACTION_SOUTH: + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + + break; + + default: + } + }; switch (action) { // Move crop box - case 'all': + case ACTION_ALL: left += range.x; top += range.y; break; @@ -1785,10 +2041,7 @@ var change = { break; } - if (right + range.x > maxWidth) { - range.x = maxWidth - right; - } - + check(ACTION_EAST); width += range.x; if (aspectRatio) { @@ -1809,10 +2062,7 @@ var change = { break; } - if (top + range.y < minTop) { - range.y = minTop - top; - } - + check(ACTION_NORTH); height -= range.y; top += range.y; @@ -1834,10 +2084,7 @@ var change = { break; } - if (left + range.x < minLeft) { - range.x = minLeft - left; - } - + check(ACTION_WEST); width -= range.x; left += range.x; @@ -1859,10 +2106,7 @@ var change = { break; } - if (bottom + range.y > maxHeight) { - range.y = maxHeight - bottom; - } - + check(ACTION_SOUTH); height += range.y; if (aspectRatio) { @@ -1884,10 +2128,14 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -1930,11 +2178,15 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; left += range.y * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -1979,10 +2231,14 @@ var change = { break; } + check(ACTION_WEST); width -= range.x; left += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -2025,9 +2281,13 @@ var change = { break; } + check(ACTION_EAST); width += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -2062,25 +2322,25 @@ var change = { break; // Move canvas - case 'move': - self.move(range.x, range.y); + case ACTION_MOVE: + this.move(range.x, range.y); renderable = false; break; // Zoom canvas - case 'zoom': - self.zoom(getMaxZoomRatio(pointers), e); + case ACTION_ZOOM: + this.zoom(getMaxZoomRatio(pointers), e); renderable = false; break; // Create crop box - case 'crop': + case ACTION_CROP: if (!range.x || !range.y) { renderable = false; break; } - offset = getOffset(self.cropper); + offset = getOffset(this.cropper); left = pointer.startX - offset.left; top = pointer.startY - offset.top; width = cropBoxData.minWidth; @@ -2098,12 +2358,12 @@ var change = { } // Show the crop box if is hidden - if (!self.cropped) { - removeClass(self.cropBox, 'cropper-hidden'); - self.cropped = true; + if (!this.cropped) { + removeClass(this.cropBox, CLASS_HIDDEN); + this.cropped = true; - if (self.limited) { - self.limitCropBox(true, true); + if (this.limited) { + this.limitCropBox(true, true); } } @@ -2117,9 +2377,8 @@ var change = { cropBoxData.height = height; cropBoxData.left = left; cropBoxData.top = top; - self.action = action; - - self.renderCropBox(); + this.action = action; + this.renderCropBox(); } // Override @@ -2130,228 +2389,188 @@ var change = { } }; -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function getPointersCenter(pointers) { - var pageX = 0; - var pageY = 0; - var count = 0; - - each(pointers, function (_ref) { - var startX = _ref.startX, - startY = _ref.startY; - - pageX += startX; - pageY += startY; - count += 1; - }); - - pageX /= count; - pageY /= count; - - return { - pageX: pageX, - pageY: pageY - }; -} - var methods = { // Show the crop box manually crop: function crop() { - var self = this; + if (this.ready && !this.disabled) { + if (!this.cropped) { + this.cropped = true; + this.limitCropBox(true, true); - if (self.ready && !self.disabled) { - if (!self.cropped) { - self.cropped = true; - self.limitCropBox(true, true); - - if (self.options.modal) { - addClass(self.dragBox, 'cropper-modal'); + if (this.options.modal) { + addClass(this.dragBox, CLASS_MODAL); } - removeClass(self.cropBox, 'cropper-hidden'); + removeClass(this.cropBox, CLASS_HIDDEN); } - self.setCropBoxData(self.initialCropBoxData); + this.setCropBoxData(this.initialCropBoxData); } - return self; + return this; }, // Reset the image and crop box to their initial states reset: function reset() { - var self = this; - - if (self.ready && !self.disabled) { - self.imageData = extend({}, self.initialImageData); - self.canvasData = extend({}, self.initialCanvasData); - self.cropBoxData = extend({}, self.initialCropBoxData); + if (this.ready && !this.disabled) { + this.imageData = extend({}, this.initialImageData); + this.canvasData = extend({}, this.initialCanvasData); + this.cropBoxData = extend({}, this.initialCropBoxData); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } - return self; + return this; }, // Clear the crop box clear: function clear() { - var self = this; - - if (self.cropped && !self.disabled) { - extend(self.cropBoxData, { + if (this.cropped && !this.disabled) { + extend(this.cropBoxData, { left: 0, top: 0, width: 0, height: 0 }); - self.cropped = false; - self.renderCropBox(); - - self.limitCanvas(true, true); + this.cropped = false; + this.renderCropBox(); + this.limitCanvas(true, true); // Render canvas after crop box rendered - self.renderCanvas(); - - removeClass(self.dragBox, 'cropper-modal'); - addClass(self.cropBox, 'cropper-hidden'); + this.renderCanvas(); + removeClass(this.dragBox, CLASS_MODAL); + addClass(this.cropBox, CLASS_HIDDEN); } - return self; + return this; }, /** * Replace the image's src and rebuild the cropper - * - * @param {String} url - * @param {Boolean} onlyColorChanged (optional) + * @param {string} url - The new URL. + * @param {boolean} [onlyColorChanged] - Indicate if the new image only changed color. + * @returns {Object} this */ - replace: function replace(url, onlyColorChanged) { - var self = this; + replace: function replace(url) { + var onlyColorChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - if (!self.disabled && url) { - if (self.isImg) { - self.element.src = url; + if (!this.disabled && url) { + if (this.isImg) { + this.element.src = url; } if (onlyColorChanged) { - self.url = url; - self.image.src = url; + this.url = url; + this.image.src = url; - if (self.ready) { - self.image2.src = url; + if (this.ready) { + this.image2.src = url; - each(self.previews, function (element) { - getByTag(element, 'img')[0].src = url; + each(this.previews, function (element) { + element.getElementsByTagName('img')[0].src = url; }); } } else { - if (self.isImg) { - self.replaced = true; + if (this.isImg) { + this.replaced = true; } // Clear previous data - self.options.data = null; - self.load(url); + this.options.data = null; + this.load(url); } } - return self; + return this; }, // Enable (unfreeze) the cropper enable: function enable() { - var self = this; - - if (self.ready) { - self.disabled = false; - removeClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = false; + removeClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Disable (freeze) the cropper disable: function disable() { - var self = this; - - if (self.ready) { - self.disabled = true; - addClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = true; + addClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Destroy the cropper and remove the instance from the image destroy: function destroy() { - var self = this; - var element = self.element; - var image = self.image; + var element = this.element, + image = this.image; - if (self.loaded) { - if (self.isImg && self.replaced) { - element.src = self.originalUrl; + + if (this.loaded) { + if (this.isImg && this.replaced) { + element.src = this.originalUrl; } - self.unbuild(); - removeClass(element, 'cropper-hidden'); - } else if (self.isImg) { - removeListener(element, 'load', self.onStart); + this.unbuild(); + removeClass(element, CLASS_HIDDEN); + } else if (this.isImg) { + removeListener(element, EVENT_LOAD, this.onStart); } else if (image) { - removeChild(image); + image.parentNode.removeChild(image); } - removeData(element, 'cropper'); + removeData(element, NAMESPACE); - return self; + return this; }, /** * Move the canvas with relative offsets - * - * @param {Number} offsetX - * @param {Number} offsetY (optional) + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} offsetY - The relative offset distance on the y-axis. + * @returns {Object} this */ move: function move(offsetX, offsetY) { - var self = this; - var canvasData = self.canvasData; + var _canvasData = this.canvasData, + left = _canvasData.left, + top = _canvasData.top; + - return self.moveTo(isUndefined(offsetX) ? offsetX : canvasData.left + Number(offsetX), isUndefined(offsetY) ? offsetY : canvasData.top + Number(offsetY)); + return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY)); }, /** * Move the canvas to an absolute point - * - * @param {Number} x - * @param {Number} y (optional) + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Object} this */ - moveTo: function moveTo(x, y) { - var self = this; - var canvasData = self.canvasData; - var changed = false; + moveTo: function moveTo(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var canvasData = this.canvasData; - // If "y" is not present, its default value is "x" - if (isUndefined(y)) { - y = x; - } + var changed = false; x = Number(x); y = Number(y); - if (self.ready && !self.disabled && self.options.movable) { + if (this.ready && !this.disabled && this.options.movable) { if (isNumber(x)) { canvasData.left = x; changed = true; @@ -2363,23 +2582,23 @@ var methods = { } if (changed) { - self.renderCanvas(true); + this.renderCanvas(true); } } - return self; + return this; }, /** * Zoom the canvas with a relative ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoom: function zoom(ratio, _originalEvent) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + ratio = Number(ratio); @@ -2389,42 +2608,43 @@ var methods = { ratio = 1 + ratio; } - return self.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); + return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); }, /** * Zoom the canvas to an absolute ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoomTo: function zoomTo(ratio, _originalEvent) { - var self = this; - var options = self.options; - var canvasData = self.canvasData; - var width = canvasData.width; - var height = canvasData.height; - var naturalWidth = canvasData.naturalWidth; - var naturalHeight = canvasData.naturalHeight; + var options = this.options, + canvasData = this.canvasData; + var width = canvasData.width, + height = canvasData.height, + naturalWidth = canvasData.naturalWidth, + naturalHeight = canvasData.naturalHeight; + ratio = Number(ratio); - if (ratio >= 0 && self.ready && !self.disabled && options.zoomable) { + if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) { var newWidth = naturalWidth * ratio; var newHeight = naturalHeight * ratio; - if (dispatchEvent(self.element, 'zoom', { + if (dispatchEvent(this.element, EVENT_ZOOM, { originalEvent: _originalEvent, oldRatio: width / naturalWidth, ratio: newWidth / naturalWidth }) === false) { - return self; + return this; } if (_originalEvent) { - var pointers = self.pointers; - var offset = getOffset(self.cropper); + var pointers = this.pointers; + + var offset = getOffset(this.cropper); var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : { pageX: _originalEvent.pageX, pageY: _originalEvent.pageY @@ -2441,128 +2661,116 @@ var methods = { canvasData.width = newWidth; canvasData.height = newHeight; - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** * Rotate the canvas with a relative degree - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotate: function rotate(degree) { - var self = this; - - return self.rotateTo((self.imageData.rotate || 0) + Number(degree)); + return this.rotateTo((this.imageData.rotate || 0) + Number(degree)); }, /** * Rotate the canvas to an absolute degree - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate() - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotateTo: function rotateTo(degree) { - var self = this; - degree = Number(degree); - if (isNumber(degree) && self.ready && !self.disabled && self.options.rotatable) { - self.imageData.rotate = degree % 360; - self.rotated = true; - self.renderCanvas(true); + if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) { + this.imageData.rotate = degree % 360; + this.renderCanvas(true, true); } - return self; + return this; + }, + + + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Object} this + */ + scaleX: function scaleX(_scaleX) { + var scaleY = this.imageData.scaleY; + + + return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + + + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Object} this + */ + scaleY: function scaleY(_scaleY) { + var scaleX = this.imageData.scaleX; + + + return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); }, /** * Scale the image - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale() - * - * @param {Number} scaleX - * @param {Number} scaleY (optional) + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Object} this */ - scale: function scale(scaleX, scaleY) { - var self = this; - var imageData = self.imageData; - var changed = false; + scale: function scale(scaleX) { + var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX; + var imageData = this.imageData; - // If "scaleY" is not present, its default value is "scaleX" - if (isUndefined(scaleY)) { - scaleY = scaleX; - } + var transformed = false; scaleX = Number(scaleX); scaleY = Number(scaleY); - if (self.ready && !self.disabled && self.options.scalable) { + if (this.ready && !this.disabled && this.options.scalable) { if (isNumber(scaleX)) { imageData.scaleX = scaleX; - changed = true; + transformed = true; } if (isNumber(scaleY)) { imageData.scaleY = scaleY; - changed = true; + transformed = true; } - if (changed) { - self.renderImage(true); + if (transformed) { + this.renderCanvas(true, true); } } - return self; - }, - - - /** - * Scale the abscissa of the image - * - * @param {Number} scaleX - */ - scaleX: function scaleX(_scaleX) { - var self = this; - var scaleY = self.imageData.scaleY; - - return self.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); - }, - - - /** - * Scale the ordinate of the image - * - * @param {Number} scaleY - */ - scaleY: function scaleY(_scaleY) { - var self = this; - var scaleX = self.imageData.scaleX; - - return self.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + return this; }, /** * Get the cropped area position and size data (base on the original image) - * - * @param {Boolean} rounded (optional) - * @return {Object} data + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. */ - getData: function getData$$1(rounded) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var ratio = void 0; + getData: function getData$$1() { + var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { x: cropBoxData.left - canvasData.left, y: cropBoxData.top - canvasData.top, @@ -2570,7 +2778,7 @@ var methods = { height: cropBoxData.height }; - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; each(data, function (n, i) { n /= ratio; @@ -2600,51 +2808,47 @@ var methods = { /** * Set the cropped area position and size with new data - * - * @param {Object} data + * @param {Object} data - The new data. + * @returns {Object} this */ setData: function setData$$1(data) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData; + var cropBoxData = {}; - var rotated = void 0; - var scaled = void 0; - var ratio = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { + var transformed = false; + if (options.rotatable) { if (isNumber(data.rotate) && data.rotate !== imageData.rotate) { imageData.rotate = data.rotate; - rotated = true; - self.rotated = rotated; + transformed = true; } } if (options.scalable) { if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) { imageData.scaleX = data.scaleX; - scaled = true; + transformed = true; } if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) { imageData.scaleY = data.scaleY; - scaled = true; + transformed = true; } } - if (rotated) { - self.renderCanvas(); - } else if (scaled) { - self.renderImage(); + if (transformed) { + this.renderCanvas(true, true); } - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; if (isNumber(data.x)) { cropBoxData.left = data.x * ratio + canvasData.left; @@ -2662,48 +2866,41 @@ var methods = { cropBoxData.height = data.height * ratio; } - self.setCropBoxData(cropBoxData); + this.setCropBoxData(cropBoxData); } - return self; + return this; }, /** - * Get the container size data - * - * @return {Object} data + * Get the container size data. + * @returns {Object} The result container data. */ getContainerData: function getContainerData() { - var self = this; - - return self.ready ? self.containerData : {}; + return this.ready ? extend({}, this.containerData) : {}; }, /** - * Get the image position and size data - * - * @return {Object} data + * Get the image position and size data. + * @returns {Object} The result image data. */ getImageData: function getImageData() { - var self = this; - - return self.loaded ? self.imageData : {}; + return this.loaded ? extend({}, this.imageData) : {}; }, /** - * Get the canvas position and size data - * - * @return {Object} data + * Get the canvas position and size data. + * @returns {Object} The result canvas data. */ getCanvasData: function getCanvasData() { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + var data = {}; - if (self.ready) { + if (this.ready) { each(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) { data[n] = canvasData[n]; }); @@ -2714,20 +2911,20 @@ var methods = { /** - * Set the canvas position and size with new data - * - * @param {Object} data + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Object} this */ setCanvasData: function setCanvasData(data) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; var aspectRatio = canvasData.aspectRatio; + if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { canvasData.left = data.left; } @@ -2744,24 +2941,23 @@ var methods = { canvasData.width = data.height * aspectRatio; } - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** - * Get the crop box position and size data - * - * @return {Object} data + * Get the crop box position and size data. + * @returns {Object} The result crop box data. */ getCropBoxData: function getCropBoxData() { - var self = this; - var cropBoxData = self.cropBoxData; + var cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { left: cropBoxData.left, top: cropBoxData.top, @@ -2775,22 +2971,22 @@ var methods = { /** - * Set the crop box position and size with new data - * - * @param {Object} data + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Object} this */ setCropBoxData: function setCropBoxData(data) { - var self = this; - var cropBoxData = self.cropBoxData; - var aspectRatio = self.options.aspectRatio; + var cropBoxData = this.cropBoxData; + var aspectRatio = this.options.aspectRatio; + var widthChanged = void 0; var heightChanged = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && self.cropped && !self.disabled && isPlainObject(data)) { + if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { cropBoxData.left = data.left; } @@ -2817,210 +3013,204 @@ var methods = { } } - self.renderCropBox(); + this.renderCropBox(); } - return self; + return this; }, /** - * Get a canvas drawn the cropped image - * - * @param {Object} options (optional) - * @return {HTMLCanvasElement} canvas + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. */ - getCroppedCanvas: function getCroppedCanvas(options) { - var self = this; + getCroppedCanvas: function getCroppedCanvas() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - if (!self.ready || !window.HTMLCanvasElement) { + if (!this.ready || !window.HTMLCanvasElement) { return null; } - if (!isPlainObject(options)) { - options = {}; - } + var canvasData = this.canvasData; + + var source = getSourceCanvas(this.image, this.imageData, canvasData, options); - // Return the whole canvas if not cropped - if (!self.cropped) { - return getSourceCanvas(self.image, self.imageData, options); + // Returns the source canvas if it is not cropped. + if (!this.cropped) { + return source; } - var data = self.getData(); - var originalWidth = data.width; - var originalHeight = data.height; - var aspectRatio = originalWidth / originalHeight; - var scaledWidth = void 0; - var scaledHeight = void 0; - var scaledRatio = void 0; + var _getData = this.getData(), + x = _getData.x, + y = _getData.y, + initialWidth = _getData.width, + initialHeight = _getData.height; - if (isPlainObject(options)) { - scaledWidth = options.width; - scaledHeight = options.height; + var aspectRatio = initialWidth / initialHeight; + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.maxWidth || Infinity, + height: options.maxHeight || Infinity + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.minWidth || 0, + height: options.minHeight || 0 + }); - if (scaledWidth) { - scaledHeight = scaledWidth / aspectRatio; - scaledRatio = scaledWidth / originalWidth; - } else if (scaledHeight) { - scaledWidth = scaledHeight * aspectRatio; - scaledRatio = scaledHeight / originalHeight; - } - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.width || initialWidth, + height: options.height || initialHeight + }), + width = _getContainSizes.width, + height = _getContainSizes.height; - // The canvas element will use `Math.floor` on a float number, so floor first - var canvasWidth = Math.floor(scaledWidth || originalWidth); - var canvasHeight = Math.floor(scaledHeight || originalHeight); + width = Math.min(maxSizes.width, Math.max(minSizes.width, width)); + height = Math.min(maxSizes.height, Math.max(minSizes.height, height)); - var canvas = createElement('canvas'); + var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + canvas.width = width; + canvas.height = height; + + context.fillStyle = options.fillColor || 'transparent'; + context.fillRect(0, 0, width, height); - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); + var _options$imageSmoothi = options.imageSmoothingEnabled, + imageSmoothingEnabled = _options$imageSmoothi === undefined ? true : _options$imageSmoothi, + imageSmoothingQuality = options.imageSmoothingQuality; + + + context.imageSmoothingEnabled = imageSmoothingEnabled; + + if (imageSmoothingQuality) { + context.imageSmoothingQuality = imageSmoothingQuality; } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage - var parameters = function () { - var source = getSourceCanvas(self.image, self.imageData, options); - var sourceWidth = source.width; - var sourceHeight = source.height; - var canvasData = self.canvasData; - var params = [source]; - - // Source canvas - var srcX = data.x + canvasData.naturalWidth * (Math.abs(data.scaleX || 1) - 1) / 2; - var srcY = data.y + canvasData.naturalHeight * (Math.abs(data.scaleY || 1) - 1) / 2; - var srcWidth = void 0; - var srcHeight = void 0; - - // Destination canvas - var dstX = void 0; - var dstY = void 0; - var dstWidth = void 0; - var dstHeight = void 0; - - if (srcX <= -originalWidth || srcX > sourceWidth) { - srcX = 0; - srcWidth = 0; - dstX = 0; - dstWidth = 0; - } else if (srcX <= 0) { - dstX = -srcX; - srcX = 0; - srcWidth = Math.min(sourceWidth, originalWidth + srcX); - dstWidth = srcWidth; - } else if (srcX <= sourceWidth) { - dstX = 0; - srcWidth = Math.min(originalWidth, sourceWidth - srcX); - dstWidth = srcWidth; - } - - if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) { - srcY = 0; - srcHeight = 0; - dstY = 0; - dstHeight = 0; - } else if (srcY <= 0) { - dstY = -srcY; - srcY = 0; - srcHeight = Math.min(sourceHeight, originalHeight + srcY); - dstHeight = srcHeight; - } else if (srcY <= sourceHeight) { - dstY = 0; - srcHeight = Math.min(originalHeight, sourceHeight - srcY); - dstHeight = srcHeight; - } - - params.push(Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)); - - // Scale destination sizes - if (scaledRatio) { - dstX *= scaledRatio; - dstY *= scaledRatio; - dstWidth *= scaledRatio; - dstHeight *= scaledRatio; - } - - // Avoid "IndexSizeError" in IE and Firefox - if (dstWidth > 0 && dstHeight > 0) { - params.push(Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); - } - - return params; - }(); - - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; - - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; - } - - context.drawImage.apply(context, _toConsumableArray(parameters)); + var sourceWidth = source.width; + var sourceHeight = source.height; + + // Source canvas parameters + var srcX = x; + var srcY = y; + var srcWidth = void 0; + var srcHeight = void 0; + + // Destination canvas parameters + var dstX = void 0; + var dstY = void 0; + var dstWidth = void 0; + var dstHeight = void 0; + + if (srcX <= -initialWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + srcWidth = Math.min(sourceWidth, initialWidth + srcX); + dstWidth = srcWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + srcWidth = Math.min(initialWidth, sourceWidth - srcX); + dstWidth = srcWidth; + } + + if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + srcHeight = Math.min(sourceHeight, initialHeight + srcY); + dstHeight = srcHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + srcHeight = Math.min(initialHeight, sourceHeight - srcY); + dstHeight = srcHeight; + } + + // All the numerical parameters should be integer for `drawImage` + // https://github.com/fengyuanchen/cropper/issues/476 + var params = [Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)]; + + // Avoid "IndexSizeError" + if (dstWidth > 0 && dstHeight > 0) { + var scale = width / initialWidth; + + params.push(Math.floor(dstX * scale), Math.floor(dstY * scale), Math.floor(dstWidth * scale), Math.floor(dstHeight * scale)); + } + + context.drawImage.apply(context, [source].concat(params)); return canvas; }, /** - * Change the aspect ratio of the crop box - * - * @param {Number} aspectRatio + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Object} this */ setAspectRatio: function setAspectRatio(aspectRatio) { - var self = this; - var options = self.options; + var options = this.options; + - if (!self.disabled && !isUndefined(aspectRatio)) { + if (!this.disabled && !isUndefined(aspectRatio)) { // 0 -> NaN options.aspectRatio = Math.max(0, aspectRatio) || NaN; - if (self.ready) { - self.initCropBox(); + if (this.ready) { + this.initCropBox(); - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } } - return self; + return this; }, /** - * Change the drag mode - * - * @param {String} mode (optional) + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Object} this */ setDragMode: function setDragMode(mode) { - var self = this; - var options = self.options; - var dragBox = self.dragBox; - var face = self.face; - var croppable = void 0; - var movable = void 0; - - if (self.loaded && !self.disabled) { - croppable = mode === 'crop'; - movable = options.movable && mode === 'move'; - mode = croppable || movable ? mode : 'none'; - - setData(dragBox, 'action', mode); - toggleClass(dragBox, 'cropper-crop', croppable); - toggleClass(dragBox, 'cropper-move', movable); + var options = this.options, + dragBox = this.dragBox, + face = this.face; + + + if (this.loaded && !this.disabled) { + var croppable = mode === DRAG_MODE_CROP; + var movable = options.movable && mode === DRAG_MODE_MOVE; + + mode = croppable || movable ? mode : DRAG_MODE_NONE; + + setData(dragBox, DATA_ACTION, mode); + toggleClass(dragBox, CLASS_CROP, croppable); + toggleClass(dragBox, CLASS_MOVE, movable); if (!options.cropBoxMovable) { // Sync drag mode to crop box when it is not movable - setData(face, 'action', mode); - toggleClass(face, 'cropper-crop', croppable); - toggleClass(face, 'cropper-move', movable); + setData(face, DATA_ACTION, mode); + toggleClass(face, CLASS_CROP, croppable); + toggleClass(face, CLASS_MOVE, movable); } } - return self; + return this; } }; @@ -3028,55 +3218,47 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -// Constants -var NAMESPACE = 'cropper'; - -// Classes -var CLASS_HIDDEN = NAMESPACE + '-hidden'; - -// Events -var EVENT_ERROR = 'error'; -var EVENT_LOAD = 'load'; -var EVENT_READY = 'ready'; -var EVENT_CROP = 'crop'; - -// RegExps -var REGEXP_DATA_URL = /^data:/; -var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; - -var AnotherCropper = void 0; +var AnotherCropper = window.Cropper; var Cropper = function () { - function Cropper(element, options) { + /** + * Create a new Cropper. + * @param {Element} element - The target element for cropping. + * @param {Object} [options={}] - The configuration options. + */ + function Cropper(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Cropper); - var self = this; - - self.element = element; - self.options = extend({}, DEFAULTS, isPlainObject(options) && options); - self.loaded = false; - self.ready = false; - self.complete = false; - self.rotated = false; - self.cropped = false; - self.disabled = false; - self.replaced = false; - self.limited = false; - self.wheeling = false; - self.isImg = false; - self.originalUrl = ''; - self.canvasData = null; - self.cropBoxData = null; - self.previews = null; - self.pointers = {}; - self.init(); + if (!element || !REGEXP_TAG_NAME.test(element.tagName)) { + throw new Error('The first argument is required and must be an or element.'); + } + + this.element = element; + this.options = extend({}, DEFAULTS, isPlainObject(options) && options); + this.complete = false; + this.cropped = false; + this.disabled = false; + this.isImg = false; + this.limited = false; + this.loaded = false; + this.ready = false; + this.replaced = false; + this.wheeling = false; + this.originalUrl = ''; + this.canvasData = null; + this.cropBoxData = null; + this.previews = null; + this.pointers = {}; + this.init(); } _createClass(Cropper, [{ key: 'init', value: function init() { - var self = this; - var element = self.element; + var element = this.element; + var tagName = element.tagName.toLowerCase(); var url = void 0; @@ -3084,14 +3266,14 @@ var Cropper = function () { return; } - setData(element, NAMESPACE, self); + setData(element, NAMESPACE, this); if (tagName === 'img') { - self.isImg = true; + this.isImg = true; // e.g.: "img/picture.jpg" url = element.getAttribute('src'); - self.originalUrl = url; + this.originalUrl = url; // Stop when it's a blank image if (!url) { @@ -3104,45 +3286,48 @@ var Cropper = function () { url = element.toDataURL(); } - self.load(url); + this.load(url); } }, { key: 'load', value: function load(url) { - var self = this; - var options = self.options; - var element = self.element; + var _this = this; if (!url) { return; } - self.url = url; - self.imageData = {}; + this.url = url; + this.imageData = {}; + + var element = this.element, + options = this.options; + if (!options.checkOrientation || !window.ArrayBuffer) { - self.clone(); + this.clone(); return; } // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari if (REGEXP_DATA_URL.test(url)) { if (REGEXP_DATA_URL_JPEG.test(url)) { - self.read(dataURLToArrayBuffer(url)); + this.read(dataURLToArrayBuffer(url)); } else { - self.clone(); + this.clone(); } + return; } var xhr = new XMLHttpRequest(); xhr.onerror = function () { - self.clone(); + _this.clone(); }; xhr.onload = function () { - self.read(xhr.response); + _this.read(xhr.response); }; if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) { @@ -3157,57 +3342,22 @@ var Cropper = function () { }, { key: 'read', value: function read(arrayBuffer) { - var self = this; - var options = self.options; + var options = this.options, + imageData = this.imageData; + var orientation = getOrientation(arrayBuffer); - var imageData = self.imageData; var rotate = 0; var scaleX = 1; var scaleY = 1; if (orientation > 1) { - self.url = arrayBufferToDataURL(arrayBuffer); - - switch (orientation) { - // flip horizontal - case 2: - scaleX = -1; - break; - - // rotate left 180° - case 3: - rotate = -180; - break; - - // flip vertical - case 4: - scaleY = -1; - break; - - // flip vertical + rotate right 90° - case 5: - rotate = 90; - scaleY = -1; - break; - - // rotate right 90° - case 6: - rotate = 90; - break; - - // flip horizontal + rotate right 90° - case 7: - rotate = 90; - scaleX = -1; - break; + this.url = arrayBufferToDataURL(arrayBuffer, 'image/jpeg'); - // rotate left 90° - case 8: - rotate = -90; - break; + var _parseOrientation = parseOrientation(orientation); - default: - } + rotate = _parseOrientation.rotate; + scaleX = _parseOrientation.scaleX; + scaleY = _parseOrientation.scaleY; } if (options.rotatable) { @@ -3219,20 +3369,21 @@ var Cropper = function () { imageData.scaleY = scaleY; } - self.clone(); + this.clone(); } }, { key: 'clone', value: function clone() { - var self = this; - var element = self.element; - var url = self.url; + var element = this.element, + url = this.url; + var crossOrigin = void 0; var crossOriginUrl = void 0; - if (self.options.checkCrossOrigin && isCrossOriginURL(url)) { + if (this.options.checkCrossOrigin && isCrossOriginURL(url)) { crossOrigin = element.crossOrigin; + if (crossOrigin) { crossOriginUrl = url; } else { @@ -3243,10 +3394,10 @@ var Cropper = function () { } } - self.crossOrigin = crossOrigin; - self.crossOriginUrl = crossOriginUrl; + this.crossOrigin = crossOrigin; + this.crossOriginUrl = crossOriginUrl; - var image = createElement('img'); + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; @@ -3254,98 +3405,99 @@ var Cropper = function () { image.src = crossOriginUrl || url; - var start = proxy(self.start, self); - var stop = proxy(self.stop, self); + var start = proxy(this.start, this); + var stop = proxy(this.stop, this); - self.image = image; - self.onStart = start; - self.onStop = stop; + this.image = image; + this.onStart = start; + this.onStop = stop; - if (self.isImg) { + if (this.isImg) { if (element.complete) { - self.start(); + this.start(); } else { addListener(element, EVENT_LOAD, start); } } else { addListener(image, EVENT_LOAD, start); addListener(image, EVENT_ERROR, stop); - addClass(image, 'cropper-hide'); + addClass(image, CLASS_HIDE); element.parentNode.insertBefore(image, element.nextSibling); } } }, { key: 'start', value: function start(event) { - var self = this; - var image = self.isImg ? self.element : self.image; + var _this2 = this; + + var image = this.isImg ? this.element : this.image; if (event) { - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); } - getImageSize(image, function (naturalWidth, naturalHeight) { - extend(self.imageData, { + getImageNaturalSizes(image, function (naturalWidth, naturalHeight) { + extend(_this2.imageData, { naturalWidth: naturalWidth, naturalHeight: naturalHeight, aspectRatio: naturalWidth / naturalHeight }); - - self.loaded = true; - self.build(); + _this2.loaded = true; + _this2.build(); }); } }, { key: 'stop', value: function stop() { - var self = this; - var image = self.image; + var image = this.image; - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); - removeChild(image); - self.image = null; + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); + image.parentNode.removeChild(image); + this.image = null; } }, { key: 'build', value: function build() { - var self = this; - var options = self.options; - var element = self.element; - var image = self.image; + var _this3 = this; - if (!self.loaded) { + if (!this.loaded) { return; } // Unbuild first when replace - if (self.ready) { - self.unbuild(); + if (this.ready) { + this.unbuild(); } + var element = this.element, + options = this.options, + image = this.image; + // Create cropper elements + var container = element.parentNode; - var template = createElement('div'); + var template = document.createElement('div'); template.innerHTML = TEMPLATE; - var cropper = getByClass(template, 'cropper-container')[0]; - var canvas = getByClass(cropper, 'cropper-canvas')[0]; - var dragBox = getByClass(cropper, 'cropper-drag-box')[0]; - var cropBox = getByClass(cropper, 'cropper-crop-box')[0]; - var face = getByClass(cropBox, 'cropper-face')[0]; + var cropper = template.querySelector('.' + NAMESPACE + '-container'); + var canvas = cropper.querySelector('.' + NAMESPACE + '-canvas'); + var dragBox = cropper.querySelector('.' + NAMESPACE + '-drag-box'); + var cropBox = cropper.querySelector('.' + NAMESPACE + '-crop-box'); + var face = cropBox.querySelector('.' + NAMESPACE + '-face'); - self.container = container; - self.cropper = cropper; - self.canvas = canvas; - self.dragBox = dragBox; - self.cropBox = cropBox; - self.viewBox = getByClass(cropper, 'cropper-view-box')[0]; - self.face = face; + this.container = container; + this.cropper = cropper; + this.canvas = canvas; + this.dragBox = dragBox; + this.cropBox = cropBox; + this.viewBox = cropper.querySelector('.' + NAMESPACE + '-view-box'); + this.face = face; - appendChild(canvas, image); + canvas.appendChild(image); // Hide the original image addClass(element, CLASS_HIDDEN); @@ -3354,114 +3506,123 @@ var Cropper = function () { container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden - if (!self.isImg) { - removeClass(image, 'cropper-hide'); + if (!this.isImg) { + removeClass(image, CLASS_HIDE); } - self.initPreview(); - self.bind(); + this.initPreview(); + this.bind(); options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; - self.cropped = options.autoCrop; + this.cropped = options.autoCrop; if (options.autoCrop) { if (options.modal) { - addClass(dragBox, 'cropper-modal'); + addClass(dragBox, CLASS_MODAL); } } else { addClass(cropBox, CLASS_HIDDEN); } if (!options.guides) { - addClass(getByClass(cropBox, 'cropper-dashed'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-dashed'), CLASS_HIDDEN); } if (!options.center) { - addClass(getByClass(cropBox, 'cropper-center'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-center'), CLASS_HIDDEN); } if (options.background) { - addClass(cropper, 'cropper-bg'); + addClass(cropper, NAMESPACE + '-bg'); } if (!options.highlight) { - addClass(face, 'cropper-invisible'); + addClass(face, CLASS_INVISIBLE); } if (options.cropBoxMovable) { - addClass(face, 'cropper-move'); - setData(face, 'action', 'all'); + addClass(face, CLASS_MOVE); + setData(face, DATA_ACTION, ACTION_ALL); } if (!options.cropBoxResizable) { - addClass(getByClass(cropBox, 'cropper-line'), CLASS_HIDDEN); - addClass(getByClass(cropBox, 'cropper-point'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-line'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-point'), CLASS_HIDDEN); } - self.setDragMode(options.dragMode); - self.render(); - self.ready = true; - self.setData(options.data); + this.setDragMode(options.dragMode); + this.render(); + this.ready = true; + this.setData(options.data); // Call the "ready" option asynchronously to keep "image.cropper" is defined - self.completing = setTimeout(function () { + this.completing = setTimeout(function () { if (isFunction(options.ready)) { - addListener(element, EVENT_READY, options.ready, true); + addListener(element, EVENT_READY, options.ready, { + once: true + }); } dispatchEvent(element, EVENT_READY); - dispatchEvent(element, EVENT_CROP, self.getData()); + dispatchEvent(element, EVENT_CROP, _this3.getData()); - self.complete = true; + _this3.complete = true; }, 0); } }, { key: 'unbuild', value: function unbuild() { - var self = this; - - if (!self.ready) { + if (!this.ready) { return; } - if (!self.complete) { - clearTimeout(self.completing); + if (!this.complete) { + clearTimeout(this.completing); } - self.ready = false; - self.complete = false; - self.initialImageData = null; + this.ready = false; + this.complete = false; + this.initialImageData = null; // Clear `initialCanvasData` is necessary when replace - self.initialCanvasData = null; - self.initialCropBoxData = null; - self.containerData = null; - self.canvasData = null; + this.initialCanvasData = null; + this.initialCropBoxData = null; + this.containerData = null; + this.canvasData = null; // Clear `cropBoxData` is necessary when replace - self.cropBoxData = null; - self.unbind(); - - self.resetPreview(); - self.previews = null; + this.cropBoxData = null; + this.unbind(); + this.resetPreview(); + this.previews = null; + this.viewBox = null; + this.cropBox = null; + this.dragBox = null; + this.canvas = null; + this.container = null; + this.cropper.parentNode.removeChild(this.cropper); + this.cropper = null; + } + + /** + * Get the no conflict cropper class. + * @returns {Cropper} The cropper class. + */ - self.viewBox = null; - self.cropBox = null; - self.dragBox = null; - self.canvas = null; - self.container = null; - - removeChild(self.cropper); - self.cropper = null; - } }], [{ key: 'noConflict', value: function noConflict() { window.Cropper = AnotherCropper; return Cropper; } + + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + }, { key: 'setDefaults', value: function setDefaults(options) { @@ -3472,16 +3633,6 @@ var Cropper = function () { return Cropper; }(); -extend(Cropper.prototype, render); -extend(Cropper.prototype, preview); -extend(Cropper.prototype, events); -extend(Cropper.prototype, handlers); -extend(Cropper.prototype, change); -extend(Cropper.prototype, methods); - -if (typeof window !== 'undefined') { - AnotherCropper = window.Cropper; - window.Cropper = Cropper; -} +extend(Cropper.prototype, render, preview, events, handlers, change, methods); module.exports = Cropper; diff --git a/dist/cropper.css b/dist/cropper.css index 9237cdf51..4468e7f36 100644 --- a/dist/cropper.css +++ b/dist/cropper.css @@ -1,11 +1,11 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:10:57.634Z */ .cropper-container { @@ -14,15 +14,15 @@ line-height: 0; position: relative; -ms-touch-action: none; - touch-action: none; + touch-action: none; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -.cropper-container img { - /* Avoid margin top issue (Occur only when margin-top <= -height) */ +.cropper-container img {/*Avoid margin top issue (Occur only when margin-top <= -height) + */ display: block; height: 100%; image-orientation: 0deg; @@ -45,7 +45,8 @@ top: 0; } -.cropper-wrap-box { +.cropper-wrap-box, +.cropper-canvas { overflow: hidden; } @@ -72,7 +73,7 @@ border: 0 dashed #eee; display: block; opacity: .5; - position: absolute + position: absolute; } .cropper-dashed.dashed-h { @@ -100,11 +101,11 @@ opacity: .75; position: absolute; top: 50%; - width: 0 + width: 0; } .cropper-center:before, - .cropper-center:after { +.cropper-center:after { background-color: #eee; content: ' '; display: block; @@ -142,7 +143,7 @@ } .cropper-line { - background-color: #39f + background-color: #39f; } .cropper-line.line-e { @@ -177,7 +178,7 @@ background-color: #39f; height: 5px; opacity: .75; - width: 5px + width: 5px; } .cropper-point.point-e { @@ -236,27 +237,24 @@ } @media (min-width: 768px) { - .cropper-point.point-se { height: 15px; - width: 15px + width: 15px; } } @media (min-width: 992px) { - .cropper-point.point-se { height: 10px; - width: 10px + width: 10px; } } @media (min-width: 1200px) { - .cropper-point.point-se { height: 5px; opacity: .75; - width: 5px + width: 5px; } } diff --git a/dist/cropper.esm.js b/dist/cropper.esm.js index f6b09782b..e269fcdf4 100644 --- a/dist/cropper.esm.js +++ b/dist/cropper.esm.js @@ -1,19 +1,79 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:11:03.372Z */ +var _window = window; +var PointerEvent = _window.PointerEvent; + + +var NAMESPACE = 'cropper'; + +// Actions +var ACTION_ALL = 'all'; +var ACTION_CROP = 'crop'; +var ACTION_MOVE = 'move'; +var ACTION_ZOOM = 'zoom'; +var ACTION_EAST = 'e'; +var ACTION_WEST = 'w'; +var ACTION_SOUTH = 's'; +var ACTION_NORTH = 'n'; +var ACTION_NORTH_EAST = 'ne'; +var ACTION_NORTH_WEST = 'nw'; +var ACTION_SOUTH_EAST = 'se'; +var ACTION_SOUTH_WEST = 'sw'; + +// Classes +var CLASS_CROP = NAMESPACE + '-crop'; +var CLASS_DISABLED = NAMESPACE + '-disabled'; +var CLASS_HIDDEN = NAMESPACE + '-hidden'; +var CLASS_HIDE = NAMESPACE + '-hide'; +var CLASS_INVISIBLE = NAMESPACE + '-invisible'; +var CLASS_MODAL = NAMESPACE + '-modal'; +var CLASS_MOVE = NAMESPACE + '-move'; + +// Data keys +var DATA_ACTION = 'action'; +var DATA_PREVIEW = 'preview'; + +// Drag modes +var DRAG_MODE_CROP = 'crop'; +var DRAG_MODE_MOVE = 'move'; +var DRAG_MODE_NONE = 'none'; + +// Events +var EVENT_CROP = 'crop'; +var EVENT_CROP_END = 'cropend'; +var EVENT_CROP_MOVE = 'cropmove'; +var EVENT_CROP_START = 'cropstart'; +var EVENT_DBLCLICK = 'dblclick'; +var EVENT_ERROR = 'error'; +var EVENT_LOAD = 'load'; +var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; +var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; +var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; +var EVENT_READY = 'ready'; +var EVENT_RESIZE = 'resize'; +var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; +var EVENT_ZOOM = 'zoom'; + +// RegExps +var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; +var REGEXP_DATA_URL = /^data:/; +var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; +var REGEXP_TAG_NAME = /^(img|canvas)$/i; + var DEFAULTS = { // Define the view mode of the cropper viewMode: 0, // 0, 1, 2, 3 // Define the dragging mode of the cropper - dragMode: 'crop', // 'crop', 'move' or 'none' + dragMode: DRAG_MODE_CROP, // 'crop', 'move' or 'none' // Define the aspect ratio of the crop box aspectRatio: NaN, @@ -108,94 +168,105 @@ var TEMPLATE = '
' + '
1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; @@ -218,6 +289,12 @@ function extend(obj) { return obj; } +/** + * Takes a function and returns a new one that will always have a particular context. + * @param {Function} fn - The target function. + * @param {Object} context - The new context for the function. + * @returns {boolean} The new function. + */ function proxy(fn, context) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; @@ -232,9 +309,17 @@ function proxy(fn, context) { }; } +var REGEXP_SUFFIX = /^(width|height|left|top|marginLeft|marginTop)$/; + +/** + * Apply styles to the given element. + * @param {Element} element - The target element. + * @param {Object} styles - The styles for applying. + */ function setStyle(element, styles) { var style = element.style; + each(styles, function (value, property) { if (REGEXP_SUFFIX.test(property) && isNumber(value)) { value += 'px'; @@ -244,10 +329,21 @@ function setStyle(element, styles) { }); } +/** + * Check if the given element has a special class. + * @param {Element} element - The element to check. + * @param {string} value - The class to search. + * @returns {boolean} Returns `true` if the special class was found. + */ function hasClass(element, value) { return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1; } +/** + * Add classes to the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be added. + */ function addClass(element, value) { if (!value) { return; @@ -265,7 +361,7 @@ function addClass(element, value) { return; } - var className = trim(element.className); + var className = element.className.trim(); if (!className) { element.className = value; @@ -274,6 +370,11 @@ function addClass(element, value) { } } +/** + * Remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be removed. + */ function removeClass(element, value) { if (!value) { return; @@ -296,6 +397,12 @@ function removeClass(element, value) { } } +/** + * Add or remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be toggled. + * @param {boolean} added - Add only. + */ function toggleClass(element, value, added) { if (!value) { return; @@ -316,10 +423,23 @@ function toggleClass(element, value, added) { } } -function hyphenate(str) { - return str.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); +var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g; + +/** + * Hyphenate the given value. + * @param {string} value - The value to hyphenate. + * @returns {string} The hyphenated value. + */ +function hyphenate(value) { + return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); } +/** + * Get data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to get. + * @returns {string} The data value. + */ function getData(element, name) { if (isObject(element[name])) { return element[name]; @@ -330,6 +450,12 @@ function getData(element, name) { return element.getAttribute('data-' + hyphenate(name)); } +/** + * Set data to the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to set. + * @param {string} data - The data value. + */ function setData(element, name, data) { if (isObject(data)) { element[name] = data; @@ -340,6 +466,11 @@ function setData(element, name, data) { } } +/** + * Remove data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to remove. + */ function removeData(element, name) { if (isObject(element[name])) { delete element[name]; @@ -355,53 +486,86 @@ function removeData(element, name) { } } -function removeListener(element, type, handler) { - var types = trim(type).split(REGEXP_SPACES); +var REGEXP_SPACES = /\s+/; + +/** + * Remove event listener from the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to remove, + * @param {Function} listener - The event listener to remove. + * @param {Object} options - The event options. + */ +function removeListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - removeListener(element, t, handler); + removeListener(element, t, listener); }); return; } + if (isFunction(listener.onceListener)) { + listener = listener.onceListener; + delete listener.onceListener; + } + if (element.removeEventListener) { - element.removeEventListener(type, handler, false); + element.removeEventListener(type, listener, options); } else if (element.detachEvent) { - element.detachEvent('on' + type, handler); + element.detachEvent('on' + type, listener); } } -function addListener(element, type, _handler, once) { - var types = trim(type).split(REGEXP_SPACES); - var originalHandler = _handler; +/** + * Add event listener to the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to add, + * @param {Function} listener - The event listener to add. + * @param {Object} options - The event options. + */ +function addListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - addListener(element, t, _handler); + addListener(element, t, listener); }); return; } - if (once) { - _handler = function handler() { + if (options.once) { + var originalListener = listener; + var onceListener = function onceListener() { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } - removeListener(element, type, _handler); - - return originalHandler.apply(element, args); + removeListener(element, type, onceListener); + return originalListener.apply(element, args); }; + originalListener.onceListener = onceListener; + listener = onceListener; } if (element.addEventListener) { - element.addEventListener(type, _handler, false); + element.addEventListener(type, listener, options); } else if (element.attachEvent) { - element.attachEvent('on' + type, _handler); + element.attachEvent('on' + type, listener); } } +/** + * Dispatch event on the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to dispatch, + * @param {Object} data - The additional event data. + * @returns {boolean} Indicate if the event is default prevented or not. + */ function dispatchEvent(element, type, data) { if (element.dispatchEvent) { var event = void 0; @@ -438,26 +602,11 @@ function dispatchEvent(element, type, data) { return true; } -function getEvent(event) { - var e = event || window.event; - - // Fix target property (IE8) - if (!e.target) { - e.target = e.srcElement || document; - } - - if (!isNumber(e.pageX) && isNumber(e.clientX)) { - var eventDoc = event.target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - e.pageX = e.clientX + ((doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0)); - e.pageY = e.clientY + ((doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0)); - } - - return e; -} - +/** + * Get the offset base on the document. + * @param {Element} element - The target element. + * @returns {Object} The offset data. + */ function getOffset(element) { var doc = document.documentElement; var box = element.getBoundingClientRect(); @@ -468,93 +617,79 @@ function getOffset(element) { }; } -function getByTag(element, tagName) { - return element.getElementsByTagName(tagName); -} - -function getByClass(element, className) { - return element.getElementsByClassName ? element.getElementsByClassName(className) : element.querySelectorAll('.' + className); -} - -function createElement(tagName) { - return document.createElement(tagName); -} - -function appendChild(element, elem) { - element.appendChild(elem); -} - -function removeChild(element) { - if (element.parentNode) { - element.parentNode.removeChild(element); - } -} - +/** + * Empty an element. + * @param {Element} element - The element to empty. + */ function empty(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } +var _window$1 = window; +var location = _window$1.location; + +var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i; + +/** + * Check if the given URL is a cross origin URL. + * @param {string} url - The target URL. + * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`. + */ function isCrossOriginURL(url) { var parts = url.match(REGEXP_ORIGINS); return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); } +/** + * Add timestamp to the given URL. + * @param {string} url - The target URL. + * @returns {string} The result URL. + */ function addTimestamp(url) { var timestamp = 'timestamp=' + new Date().getTime(); return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; } -function getImageSize(image, callback) { - // Modern browsers (ignore Safari) - if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { - callback(image.naturalWidth, image.naturalHeight); - return; - } - - // IE8: Don't use `new Image()` here - var newImage = createElement('img'); - - newImage.onload = function load() { - callback(this.width, this.height); - }; - - newImage.src = image.src; -} +/** + * Get transforms base on the given object. + * @param {Object} obj - The target object. + * @returns {string} A string contains transform values. + */ +function getTransforms(_ref) { + var rotate = _ref.rotate, + scaleX = _ref.scaleX, + scaleY = _ref.scaleY, + translateX = _ref.translateX, + translateY = _ref.translateY; -function getTransforms(data) { - var transforms = []; - var translateX = data.translateX; - var translateY = data.translateY; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; + var values = []; if (isNumber(translateX) && translateX !== 0) { - transforms.push('translateX(' + translateX + 'px)'); + values.push('translateX(' + translateX + 'px)'); } if (isNumber(translateY) && translateY !== 0) { - transforms.push('translateY(' + translateY + 'px)'); + values.push('translateY(' + translateY + 'px)'); } // Rotate should come first before scale to match orientation transform if (isNumber(rotate) && rotate !== 0) { - transforms.push('rotate(' + rotate + 'deg)'); + values.push('rotate(' + rotate + 'deg)'); } if (isNumber(scaleX) && scaleX !== 1) { - transforms.push('scaleX(' + scaleX + ')'); + values.push('scaleX(' + scaleX + ')'); } if (isNumber(scaleY) && scaleY !== 1) { - transforms.push('scaleY(' + scaleY + ')'); + values.push('scaleY(' + scaleY + ')'); } - var transform = transforms.length ? transforms.join(' ') : 'none'; + var transform = values.length ? values.join(' ') : 'none'; return { WebkitTransform: transform, @@ -563,136 +698,326 @@ function getTransforms(data) { }; } -function getRotatedSizes(data, reversed) { - var deg = Math.abs(data.degree) % 180; - var arc = (deg > 90 ? 180 - deg : deg) * Math.PI / 180; - var sinArc = Math.sin(arc); - var cosArc = Math.cos(arc); - var width = data.width; - var height = data.height; - var aspectRatio = data.aspectRatio; - var newWidth = void 0; - var newHeight = void 0; - - if (!reversed) { - newWidth = width * cosArc + height * sinArc; - newHeight = width * sinArc + height * cosArc; - } else { - newWidth = width / (cosArc + sinArc / aspectRatio); - newHeight = newWidth / aspectRatio; +var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent); + +/** + * Get an image's natural sizes. + * @param {string} image - The target image. + * @param {Function} callback - The callback function. + */ +function getImageNaturalSizes(image, callback) { + // Modern browsers (except Safari) + if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { + callback(image.naturalWidth, image.naturalHeight); + return; } - return { - width: newWidth, - height: newHeight + var newImage = document.createElement('img'); + + newImage.onload = function () { + callback(newImage.width, newImage.height); }; + + newImage.src = image.src; } -function getSourceCanvas(image, data, options) { - var canvas = createElement('canvas'); - var context = canvas.getContext('2d'); - var dstX = 0; - var dstY = 0; - var dstWidth = data.naturalWidth; - var dstHeight = data.naturalHeight; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; - var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1); - var rotatable = isNumber(rotate) && rotate !== 0; - var advanced = rotatable || scalable; - var canvasWidth = dstWidth * Math.abs(scaleX || 1); - var canvasHeight = dstHeight * Math.abs(scaleY || 1); - var translateX = void 0; - var translateY = void 0; - var rotated = void 0; - - if (scalable) { - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } +/** + * Get the max ratio of a group of pointers. + * @param {string} pointers - The target pointers. + * @returns {number} The result ratio. + */ +function getMaxZoomRatio(pointers) { + var pointers2 = extend({}, pointers); + var ratios = []; - if (rotatable) { - rotated = getRotatedSizes({ - width: canvasWidth, - height: canvasHeight, - degree: rotate + each(pointers, function (pointer, pointerId) { + delete pointers2[pointerId]; + + each(pointers2, function (pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + + ratios.push(ratio); }); + }); - canvasWidth = rotated.width; - canvasHeight = rotated.height; - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } + ratios.sort(function (a, b) { + return Math.abs(a) < Math.abs(b); + }); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + return ratios[0]; +} - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); - } +/** + * Get a pointer from an event object. + * @param {Object} event - The target event object. + * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. + * @returns {Object} The result pointer contains start and/or end point coordinates. + */ +function getPointer(_ref2, endOnly) { + var pageX = _ref2.pageX, + pageY = _ref2.pageY; - if (advanced) { - dstX = -dstWidth / 2; - dstY = -dstHeight / 2; + var end = { + endX: pageX, + endY: pageY + }; - context.save(); - context.translate(translateX, translateY); + if (endOnly) { + return end; } - // Rotate should come first before scale as in the "getTransform" function - if (rotatable) { - context.rotate(rotate * Math.PI / 180); - } + return extend({ + startX: pageX, + startY: pageY + }, end); +} - if (scalable) { - context.scale(scaleX, scaleY); - } +/** + * Get the center point coordinate of a group of pointers. + * @param {Object} pointers - The target pointers. + * @returns {Object} The center point coordinate. + */ +function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + each(pointers, function (_ref3) { + var startX = _ref3.startX, + startY = _ref3.startY; + + pageX += startX; + pageY += startY; + count += 1; + }); + + pageX /= count; + pageY /= count; + + return { + pageX: pageX, + pageY: pageY + }; +} + +/** + * Check if the given value is a finite number. + */ +var isFinite = Number.isFinite || window.isFinite; + +/** + * Get the max sizes in a rectangle under the given aspect ratio. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getContainSizes(_ref4) { + var aspectRatio = _ref4.aspectRatio, + height = _ref4.height, + width = _ref4.width; - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; + var isValidNumber = function isValidNumber(value) { + return isFinite(value) && value > 0; + }; + + if (isValidNumber(width) && isValidNumber(height)) { + if (height * aspectRatio > width) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } + } else if (isValidNumber(width)) { + height = width / aspectRatio; + } else if (isValidNumber(height)) { + width = height * aspectRatio; } - context.drawImage(image, Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + return { + width: width, + height: height + }; +} + +/** + * Get the new sizes of a rectangle after rotated. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getRotatedSizes(_ref5) { + var width = _ref5.width, + height = _ref5.height, + degree = _ref5.degree; - if (advanced) { - context.restore(); + degree = Math.abs(degree); + + if (degree % 180 === 90) { + return { + width: height, + height: width + }; } + var arc = degree % 90 * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + + return { + width: width * cosArc + height * sinArc, + height: width * sinArc + height * cosArc + }; +} + +/** + * Get a canvas which drew the given image. + * @param {HTMLImageElement} image - The image for drawing. + * @param {Object} imageData - The image data. + * @param {Object} canvasData - The canvas data. + * @param {Object} options - The options. + * @returns {HTMLCanvasElement} The result canvas. + */ +function getSourceCanvas(image, _ref6, _ref7, _ref8) { + var imageNaturalWidth = _ref6.naturalWidth, + imageNaturalHeight = _ref6.naturalHeight, + rotate = _ref6.rotate, + scaleX = _ref6.scaleX, + scaleY = _ref6.scaleY; + var aspectRatio = _ref7.aspectRatio, + naturalWidth = _ref7.naturalWidth, + naturalHeight = _ref7.naturalHeight; + var _ref8$fillColor = _ref8.fillColor, + fillColor = _ref8$fillColor === undefined ? 'transparent' : _ref8$fillColor, + _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled, + imageSmoothingEnabled = _ref8$imageSmoothingE === undefined ? true : _ref8$imageSmoothingE, + _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality, + imageSmoothingQuality = _ref8$imageSmoothingQ === undefined ? 'low' : _ref8$imageSmoothingQ, + _ref8$maxWidth = _ref8.maxWidth, + maxWidth = _ref8$maxWidth === undefined ? Infinity : _ref8$maxWidth, + _ref8$maxHeight = _ref8.maxHeight, + maxHeight = _ref8$maxHeight === undefined ? Infinity : _ref8$maxHeight, + _ref8$minWidth = _ref8.minWidth, + minWidth = _ref8$minWidth === undefined ? 0 : _ref8$minWidth, + _ref8$minHeight = _ref8.minHeight, + minHeight = _ref8$minHeight === undefined ? 0 : _ref8$minHeight; + + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: maxWidth, + height: maxHeight + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minWidth, + height: minHeight + }); + var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth)); + var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); + + canvas.width = width; + canvas.height = height; + context.fillStyle = fillColor; + context.fillRect(0, 0, width, height); + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.imageSmoothingEnabled = imageSmoothingEnabled; + context.imageSmoothingQuality = imageSmoothingQuality; + context.drawImage(image, Math.floor(-imageNaturalWidth / 2), Math.floor(-imageNaturalHeight / 2), Math.floor(imageNaturalWidth), Math.floor(imageNaturalHeight)); + context.restore(); return canvas; } +var fromCharCode = String.fromCharCode; + +/** + * Get string from char code in data view. + * @param {DataView} dataView - The data view for read. + * @param {number} start - The start index. + * @param {number} length - The read length. + * @returns {string} The read result. + */ + function getStringFromCharCode(dataView, start, length) { var str = ''; - var i = start; + var i = void 0; + + length += start; - for (length += start; i < length; i += 1) { + for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } return str; } +var _window2 = window; +var atob = _window2.atob; + +var REGEXP_DATA_URL_HEAD = /^data:.*,/; + +/** + * Transform Data URL to array buffer. + * @param {string} dataURL - The Data URL to transform. + * @returns {ArrayBuffer} The result array buffer. + */ +function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var arrayBuffer = new ArrayBuffer(binary.length); + var uint8 = new Uint8Array(arrayBuffer); + + each(uint8, function (value, i) { + uint8[i] = binary.charCodeAt(i); + }); + + return arrayBuffer; +} + +var _window3 = window; +var btoa = _window3.btoa; + +/** + * Transform array buffer to Data URL. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {string} mimeType - The mime type of the Data URL. + * @returns {string} The result Data URL. + */ + +function arrayBufferToDataURL(arrayBuffer, mimeType) { + var uint8 = new Uint8Array(arrayBuffer); + var data = ''; + + // TypedArray.prototype.forEach is not supported in some browsers. + each(uint8, function (value) { + data += fromCharCode(value); + }); + + return 'data:' + mimeType + ';base64,' + btoa(data); +} + +/** + * Get orientation value from given array buffer. + * @param {ArrayBuffer} arrayBuffer - The array buffer to read. + * @returns {number} The read orientation value. + */ function getOrientation(arrayBuffer) { var dataView = new DataView(arrayBuffer); - var length = dataView.byteLength; var orientation = void 0; - var exifIDCode = void 0; - var tiffOffset = void 0; - var firstIFDOffset = void 0; var littleEndian = void 0; - var endianness = void 0; var app1Start = void 0; var ifdStart = void 0; - var offset = void 0; - var i = void 0; // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - offset = 2; + var length = dataView.byteLength; + var offset = 2; while (offset < length) { if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { @@ -705,16 +1030,17 @@ function getOrientation(arrayBuffer) { } if (app1Start) { - exifIDCode = app1Start + 4; - tiffOffset = app1Start + 10; + var exifIDCode = app1Start + 4; + var tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - endianness = dataView.getUint16(tiffOffset); + var endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; @@ -725,23 +1051,22 @@ function getOrientation(arrayBuffer) { } if (ifdStart) { - length = dataView.getUint16(ifdStart, littleEndian); + var _length = dataView.getUint16(ifdStart, littleEndian); + var _offset = void 0; + var i = void 0; - for (i = 0; i < length; i += 1) { - offset = ifdStart + i * 12 + 2; + for (i = 0; i < _length; i += 1) { + _offset = ifdStart + i * 12 + 2; - if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) { + if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) { // 8 is the offset of the current tag's value - offset += 8; + _offset += 8; // Get the original orientation value - orientation = dataView.getUint16(offset, littleEndian); - - // Override the orientation with its default value for Safari - if (IS_SAFARI_OR_UIWEBVIEW) { - dataView.setUint16(offset, 1, littleEndian); - } + orientation = dataView.getUint16(_offset, littleEndian); + // Override the orientation with its default value + dataView.setUint16(_offset, 1, littleEndian); break; } } @@ -750,83 +1075,108 @@ function getOrientation(arrayBuffer) { return orientation; } -function dataURLToArrayBuffer(dataURL) { - var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); - var binary = atob(base64); - var length = binary.length; - var arrayBuffer = new ArrayBuffer(length); - var dataView = new Uint8Array(arrayBuffer); - var i = void 0; - - for (i = 0; i < length; i += 1) { - dataView[i] = binary.charCodeAt(i); - } - - return arrayBuffer; -} - -// Only available for JPEG image -function arrayBufferToDataURL(arrayBuffer) { - var dataView = new Uint8Array(arrayBuffer); - var length = dataView.length; - var base64 = ''; - var i = void 0; - - for (i = 0; i < length; i += 1) { - base64 += fromCharCode(dataView[i]); +/** + * Parse Exif Orientation value. + * @param {number} orientation - The orientation to parse. + * @returns {Object} The parsed result. + */ +function parseOrientation(orientation) { + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + + switch (orientation) { + // Flip horizontal + case 2: + scaleX = -1; + break; + + // Rotate left 180° + case 3: + rotate = -180; + break; + + // Flip vertical + case 4: + scaleY = -1; + break; + + // Flip vertical and rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // Rotate right 90° + case 6: + rotate = 90; + break; + + // Flip horizontal and rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // Rotate left 90° + case 8: + rotate = -90; + break; + + default: } - return 'data:image/jpeg;base64,' + btoa(base64); + return { + rotate: rotate, + scaleX: scaleX, + scaleY: scaleY + }; } var render = { render: function render() { - var self = this; - - self.initContainer(); - self.initCanvas(); - self.initCropBox(); + this.initContainer(); + this.initCanvas(); + this.initCropBox(); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } }, initContainer: function initContainer() { - var self = this; - var options = self.options; - var element = self.element; - var container = self.container; - var cropper = self.cropper; - var hidden = 'cropper-hidden'; + var element = this.element, + options = this.options, + container = this.container, + cropper = this.cropper; + - addClass(cropper, hidden); - removeClass(element, hidden); + addClass(cropper, CLASS_HIDDEN); + removeClass(element, CLASS_HIDDEN); var containerData = { width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200), height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100) }; - self.containerData = containerData; + this.containerData = containerData; setStyle(cropper, { width: containerData.width, height: containerData.height }); - addClass(element, hidden); - removeClass(cropper, hidden); + addClass(element, CLASS_HIDDEN); + removeClass(cropper, CLASS_HIDDEN); }, // Canvas (image wrapper) initCanvas: function initCanvas() { - var self = this; - var viewMode = self.options.viewMode; - var containerData = self.containerData; - var imageData = self.imageData; + var containerData = this.containerData, + imageData = this.imageData; + var viewMode = this.options.viewMode; + var rotated = Math.abs(imageData.rotate) % 180 === 90; var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth; var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight; @@ -847,9 +1197,9 @@ var render = { } var canvasData = { + aspectRatio: aspectRatio, naturalWidth: naturalWidth, naturalHeight: naturalHeight, - aspectRatio: aspectRatio, width: canvasWidth, height: canvasHeight }; @@ -859,21 +1209,21 @@ var render = { canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - self.canvasData = canvasData; - self.limited = viewMode === 1 || viewMode === 2; - self.limitCanvas(true, true); - self.initialImageData = extend({}, imageData); - self.initialCanvasData = extend({}, canvasData); + this.canvasData = canvasData; + this.limited = viewMode === 1 || viewMode === 2; + this.limitCanvas(true, true); + this.initialImageData = extend({}, imageData); + this.initialCanvasData = extend({}, canvasData); }, limitCanvas: function limitCanvas(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; var viewMode = options.viewMode; - var containerData = self.containerData; - var canvasData = self.canvasData; var aspectRatio = canvasData.aspectRatio; - var cropBoxData = self.cropBoxData; - var cropped = self.cropped && cropBoxData; + + var cropped = this.cropped && cropBoxData; if (sizeLimited) { var minCanvasWidth = Number(options.minCanvasWidth) || 0; @@ -907,17 +1257,15 @@ var render = { } } - if (minCanvasWidth && minCanvasHeight) { - if (minCanvasHeight * aspectRatio > minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else { - minCanvasWidth = minCanvasHeight * aspectRatio; - } - } else if (minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else if (minCanvasHeight) { - minCanvasWidth = minCanvasHeight * aspectRatio; - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minCanvasWidth, + height: minCanvasHeight + }); + + minCanvasWidth = _getContainSizes.width; + minCanvasHeight = _getContainSizes.height; + canvasData.minWidth = minCanvasWidth; canvasData.minHeight = minCanvasHeight; @@ -935,7 +1283,7 @@ var render = { canvasData.maxLeft = Math.max(0, newCanvasLeft); canvasData.maxTop = Math.max(0, newCanvasTop); - if (cropped && self.limited) { + if (cropped && this.limited) { canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width)); canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height)); canvasData.maxLeft = cropBoxData.left; @@ -961,47 +1309,31 @@ var render = { } } }, - renderCanvas: function renderCanvas(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var rotate = imageData.rotate; - - if (self.rotated) { - self.rotated = false; - - // Computes rotated sizes with image sizes - var rotatedData = getRotatedSizes({ - width: imageData.width, - height: imageData.height, - degree: rotate - }); - var aspectRatio = rotatedData.width / rotatedData.height; - var isSquareImage = imageData.aspectRatio === 1; - - if (isSquareImage || aspectRatio !== canvasData.aspectRatio) { - canvasData.left -= (rotatedData.width - canvasData.width) / 2; - canvasData.top -= (rotatedData.height - canvasData.height) / 2; - canvasData.width = rotatedData.width; - canvasData.height = rotatedData.height; - canvasData.aspectRatio = aspectRatio; - canvasData.naturalWidth = imageData.naturalWidth; - canvasData.naturalHeight = imageData.naturalHeight; - - // Computes rotated sizes with natural image sizes - if (isSquareImage && rotate % 90 || rotate % 180) { - var rotatedData2 = getRotatedSizes({ - width: imageData.naturalWidth, - height: imageData.naturalHeight, - degree: rotate - }); + renderCanvas: function renderCanvas(changed, transformed) { + var canvasData = this.canvasData, + imageData = this.imageData; - canvasData.naturalWidth = rotatedData2.width; - canvasData.naturalHeight = rotatedData2.height; - } - self.limitCanvas(true, false); - } + if (transformed) { + var _getRotatedSizes = getRotatedSizes({ + width: imageData.naturalWidth * Math.abs(imageData.scaleX), + height: imageData.naturalHeight * Math.abs(imageData.scaleY), + degree: imageData.rotate + }), + naturalWidth = _getRotatedSizes.width, + naturalHeight = _getRotatedSizes.height; + + var width = canvasData.width * (naturalWidth / canvasData.naturalWidth); + var height = canvasData.height * (naturalHeight / canvasData.naturalHeight); + + canvasData.left -= (width - canvasData.width) / 2; + canvasData.top -= (height - canvasData.height) / 2; + canvasData.width = width; + canvasData.height = height; + canvasData.aspectRatio = naturalWidth / naturalHeight; + canvasData.naturalWidth = naturalWidth; + canvasData.naturalHeight = naturalHeight; + this.limitCanvas(true, false); } if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) { @@ -1015,14 +1347,14 @@ var render = { canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); - self.limitCanvas(false, true); + this.limitCanvas(false, true); canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft); canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop); canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - setStyle(self.canvas, extend({ + setStyle(this.canvas, extend({ width: canvasData.width, height: canvasData.height }, getTransforms({ @@ -1030,52 +1362,26 @@ var render = { translateY: canvasData.top }))); - self.renderImage(); + this.renderImage(changed); - if (self.cropped && self.limited) { - self.limitCropBox(true, true); - } - - if (changed) { - self.output(); + if (this.cropped && this.limited) { + this.limitCropBox(true, true); } }, renderImage: function renderImage(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var newImageData = void 0; - var reversedData = void 0; - var reversedWidth = void 0; - var reversedHeight = void 0; - - if (imageData.rotate) { - reversedData = getRotatedSizes({ - width: canvasData.width, - height: canvasData.height, - degree: imageData.rotate, - aspectRatio: imageData.aspectRatio - }, true); - - reversedWidth = reversedData.width; - reversedHeight = reversedData.height; - - newImageData = { - width: reversedWidth, - height: reversedHeight, - left: (canvasData.width - reversedWidth) / 2, - top: (canvasData.height - reversedHeight) / 2 - }; - } + var canvasData = this.canvasData, + imageData = this.imageData; - extend(imageData, newImageData || { - width: canvasData.width, - height: canvasData.height, - left: 0, - top: 0 - }); + var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth); + var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight); - setStyle(self.image, extend({ + extend(imageData, { + width: width, + height: height, + left: (canvasData.width - width) / 2, + top: (canvasData.height - height) / 2 + }); + setStyle(this.image, extend({ width: imageData.width, height: imageData.height }, getTransforms(extend({ @@ -1084,15 +1390,15 @@ var render = { }, imageData)))); if (changed) { - self.output(); + this.output(); } }, initCropBox: function initCropBox() { - var self = this; - var options = self.options; + var options = this.options, + canvasData = this.canvasData; var aspectRatio = options.aspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; - var canvasData = self.canvasData; var cropBoxData = { width: canvasData.width, height: canvasData.height @@ -1106,8 +1412,8 @@ var render = { } } - self.cropBoxData = cropBoxData; - self.limitCropBox(true, true); + this.cropBoxData = cropBoxData; + this.limitCropBox(true, true); // Initialize auto crop area cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); @@ -1121,16 +1427,16 @@ var render = { cropBoxData.oldLeft = cropBoxData.left; cropBoxData.oldTop = cropBoxData.top; - self.initialCropBoxData = extend({}, cropBoxData); + this.initialCropBoxData = extend({}, cropBoxData); }, limitCropBox: function limitCropBox(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData, + limited = this.limited; var aspectRatio = options.aspectRatio; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var limited = self.limited; + if (sizeLimited) { var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; @@ -1138,7 +1444,7 @@ var render = { var maxCropBoxWidth = Math.min(containerData.width, limited ? canvasData.width : containerData.width); var maxCropBoxHeight = Math.min(containerData.height, limited ? canvasData.height : containerData.height); - // The min/maxCropBoxWidth/Height must be less than containerWidth/Height + // The min/maxCropBoxWidth/Height must be less than container's width/height minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width); minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height); @@ -1184,10 +1490,10 @@ var render = { } }, renderCropBox: function renderCropBox() { - var self = this; - var options = self.options; - var containerData = self.containerData; - var cropBoxData = self.cropBoxData; + var options = this.options, + containerData = this.containerData, + cropBoxData = this.cropBoxData; + if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) { cropBoxData.left = cropBoxData.oldLeft; @@ -1200,7 +1506,7 @@ var render = { cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); - self.limitCropBox(false, true); + this.limitCropBox(false, true); cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft); cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop); @@ -1209,10 +1515,10 @@ var render = { if (options.movable && options.cropBoxMovable) { // Turn to move the canvas when the crop box is equal to the container - setData(self.face, 'action', cropBoxData.width === containerData.width && cropBoxData.height === containerData.height ? 'move' : 'all'); + setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL); } - setStyle(self.cropBox, extend({ + setStyle(this.cropBox, extend({ width: cropBoxData.width, height: cropBoxData.height }, getTransforms({ @@ -1220,42 +1526,38 @@ var render = { translateY: cropBoxData.top }))); - if (self.cropped && self.limited) { - self.limitCanvas(true, true); + if (this.cropped && this.limited) { + this.limitCanvas(true, true); } - if (!self.disabled) { - self.output(); + if (!this.disabled) { + this.output(); } }, output: function output() { - var self = this; - - self.preview(); + this.preview(); - if (self.complete) { - dispatchEvent(self.element, 'crop', self.getData()); + if (this.complete) { + dispatchEvent(this.element, EVENT_CROP, this.getData()); } } }; -var DATA_PREVIEW = 'preview'; - var preview = { initPreview: function initPreview() { - var self = this; - var preview = self.options.preview; - var image = createElement('img'); - var crossOrigin = self.crossOrigin; - var url = crossOrigin ? self.crossOriginUrl : self.url; + var crossOrigin = this.crossOrigin; + var preview = this.options.preview; + + var url = crossOrigin ? this.crossOriginUrl : this.url; + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; } image.src = url; - appendChild(self.viewBox, image); - self.image2 = image; + this.viewBox.appendChild(image); + this.image2 = image; if (!preview) { return; @@ -1263,10 +1565,10 @@ var preview = { var previews = preview.querySelector ? [preview] : document.querySelectorAll(preview); - self.previews = previews; + this.previews = previews; each(previews, function (element) { - var img = createElement('img'); + var img = document.createElement('img'); // Save the original size for recover setData(element, DATA_PREVIEW, { @@ -1291,7 +1593,7 @@ var preview = { 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;"'; empty(element); - appendChild(element, img); + element.appendChild(img); }); }, resetPreview: function resetPreview() { @@ -1308,22 +1610,22 @@ var preview = { }); }, preview: function preview() { - var self = this; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var cropBoxWidth = cropBoxData.width; - var cropBoxHeight = cropBoxData.height; - var width = imageData.width; - var height = imageData.height; + var imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var cropBoxWidth = cropBoxData.width, + cropBoxHeight = cropBoxData.height; + var width = imageData.width, + height = imageData.height; + var left = cropBoxData.left - canvasData.left - imageData.left; var top = cropBoxData.top - canvasData.top - imageData.top; - if (!self.cropped || self.disabled) { + if (!this.cropped || this.disabled) { return; } - setStyle(self.image2, extend({ + setStyle(this.image2, extend({ width: width, height: height }, getTransforms(extend({ @@ -1331,7 +1633,7 @@ var preview = { translateY: -top }, imageData)))); - each(self.previews, function (element) { + each(this.previews, function (element) { var data = getData(element, DATA_PREVIEW); var originalWidth = data.width; var originalHeight = data.height; @@ -1355,39 +1657,23 @@ var preview = { height: newHeight }); - setStyle(getByTag(element, 'img')[0], extend({ + setStyle(element.getElementsByTagName('img')[0], extend({ width: width * ratio, height: height * ratio }, getTransforms(extend({ translateX: -left * ratio, translateY: -top * ratio - }, imageData)))); - }); - } -}; - -// Globals -var PointerEvent = typeof window !== 'undefined' ? window.PointerEvent : null; - -// Events -var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; -var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; -var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; -var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; -var EVENT_DBLCLICK = 'dblclick'; -var EVENT_RESIZE = 'resize'; -var EVENT_CROP_START = 'cropstart'; -var EVENT_CROP_MOVE = 'cropmove'; -var EVENT_CROP_END = 'cropend'; -var EVENT_CROP$1 = 'crop'; -var EVENT_ZOOM = 'zoom'; + }, imageData)))); + }); + } +}; var events = { bind: function bind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { addListener(element, EVENT_CROP_START, options.cropstart); @@ -1402,35 +1688,35 @@ var events = { } if (isFunction(options.crop)) { - addListener(element, EVENT_CROP$1, options.crop); + addListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { addListener(element, EVENT_ZOOM, options.zoom); } - addListener(cropper, EVENT_POINTER_DOWN, self.onCropStart = proxy(self.cropStart, self)); + addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = proxy(this.cropStart, this)); if (options.zoomable && options.zoomOnWheel) { - addListener(cropper, EVENT_WHEEL, self.onWheel = proxy(self.wheel, self)); + addListener(cropper, EVENT_WHEEL, this.onWheel = proxy(this.wheel, this)); } if (options.toggleDragModeOnDblclick) { - addListener(cropper, EVENT_DBLCLICK, self.onDblclick = proxy(self.dblclick, self)); + addListener(cropper, EVENT_DBLCLICK, this.onDblclick = proxy(this.dblclick, this)); } - addListener(document, EVENT_POINTER_MOVE, self.onCropMove = proxy(self.cropMove, self)); - addListener(document, EVENT_POINTER_UP, self.onCropEnd = proxy(self.cropEnd, self)); + addListener(document, EVENT_POINTER_MOVE, this.onCropMove = proxy(this.cropMove, this)); + addListener(document, EVENT_POINTER_UP, this.onCropEnd = proxy(this.cropEnd, this)); if (options.responsive) { - addListener(window, EVENT_RESIZE, self.onResize = proxy(self.resize, self)); + addListener(window, EVENT_RESIZE, this.onResize = proxy(this.resize, this)); } }, unbind: function unbind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { removeListener(element, EVENT_CROP_START, options.cropstart); @@ -1445,63 +1731,42 @@ var events = { } if (isFunction(options.crop)) { - removeListener(element, EVENT_CROP$1, options.crop); + removeListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { removeListener(element, EVENT_ZOOM, options.zoom); } - removeListener(cropper, EVENT_POINTER_DOWN, self.onCropStart); + removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart); if (options.zoomable && options.zoomOnWheel) { - removeListener(cropper, EVENT_WHEEL, self.onWheel); + removeListener(cropper, EVENT_WHEEL, this.onWheel); } if (options.toggleDragModeOnDblclick) { - removeListener(cropper, EVENT_DBLCLICK, self.onDblclick); + removeListener(cropper, EVENT_DBLCLICK, this.onDblclick); } - removeListener(document, EVENT_POINTER_MOVE, self.onCropMove); - removeListener(document, EVENT_POINTER_UP, self.onCropEnd); + removeListener(document, EVENT_POINTER_MOVE, this.onCropMove); + removeListener(document, EVENT_POINTER_UP, this.onCropEnd); if (options.responsive) { - removeListener(window, EVENT_RESIZE, self.onResize); + removeListener(window, EVENT_RESIZE, this.onResize); } } }; -var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; - -function getPointer(_ref, endOnly) { - var pageX = _ref.pageX, - pageY = _ref.pageY; - - var end = { - endX: pageX, - endY: pageY - }; - - if (endOnly) { - return end; - } - - return extend({ - startX: pageX, - startY: pageY - }, end); -} - var handlers = { resize: function resize() { - var self = this; - var options = self.options; - var container = self.container; - var containerData = self.containerData; + var options = this.options, + container = this.container, + containerData = this.containerData; + var minContainerWidth = Number(options.minContainerWidth) || 200; var minContainerHeight = Number(options.minContainerHeight) || 100; - if (self.disabled || containerData.width === minContainerWidth || containerData.height === minContainerHeight) { + if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) { return; } @@ -1513,52 +1778,50 @@ var handlers = { var cropBoxData = void 0; if (options.restore) { - canvasData = self.getCanvasData(); - cropBoxData = self.getCropBoxData(); + canvasData = this.getCanvasData(); + cropBoxData = this.getCropBoxData(); } - self.render(); + this.render(); if (options.restore) { - self.setCanvasData(each(canvasData, function (n, i) { + this.setCanvasData(each(canvasData, function (n, i) { canvasData[i] = n * ratio; })); - self.setCropBoxData(each(cropBoxData, function (n, i) { + this.setCropBoxData(each(cropBoxData, function (n, i) { cropBoxData[i] = n * ratio; })); } } }, dblclick: function dblclick() { - var self = this; - - if (self.disabled || self.options.dragMode === 'none') { + if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) { return; } - self.setDragMode(hasClass(self.dragBox, 'cropper-crop') ? 'move' : 'crop'); + this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP); }, - wheel: function wheel(event) { - var self = this; - var e = getEvent(event); - var ratio = Number(self.options.wheelZoomRatio) || 0.1; + wheel: function wheel(e) { + var _this = this; + + var ratio = Number(this.options.wheelZoomRatio) || 0.1; var delta = 1; - if (self.disabled) { + if (this.disabled) { return; } e.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21) - if (self.wheeling) { + if (this.wheeling) { return; } - self.wheeling = true; + this.wheeling = true; setTimeout(function () { - self.wheeling = false; + _this.wheeling = false; }, 50); if (e.deltaY) { @@ -1569,18 +1832,16 @@ var handlers = { delta = e.detail > 0 ? 1 : -1; } - self.zoom(-delta * ratio, e); + this.zoom(-delta * ratio, e); }, - cropStart: function cropStart(event) { - var self = this; - - if (self.disabled) { + cropStart: function cropStart(e) { + if (this.disabled) { return; } - var options = self.options; - var pointers = self.pointers; - var e = getEvent(event); + var options = this.options, + pointers = this.pointers; + var action = void 0; if (e.changedTouches) { @@ -1594,16 +1855,16 @@ var handlers = { } if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { - action = 'zoom'; + action = ACTION_ZOOM; } else { - action = getData(e.target, 'action'); + action = getData(e.target, DATA_ACTION); } if (!REGEXP_ACTIONS.test(action)) { return; } - if (dispatchEvent(self.element, 'cropstart', { + if (dispatchEvent(this.element, EVENT_CROP_START, { originalEvent: e, action: action }) === false) { @@ -1612,28 +1873,28 @@ var handlers = { e.preventDefault(); - self.action = action; - self.cropping = false; + this.action = action; + this.cropping = false; - if (action === 'crop') { - self.cropping = true; - addClass(self.dragBox, 'cropper-modal'); + if (action === ACTION_CROP) { + this.cropping = true; + addClass(this.dragBox, CLASS_MODAL); } }, - cropMove: function cropMove(event) { - var self = this; - var action = self.action; + cropMove: function cropMove(e) { + var action = this.action; + - if (self.disabled || !action) { + if (this.disabled || !action) { return; } - var pointers = self.pointers; - var e = getEvent(event); + var pointers = this.pointers; + e.preventDefault(); - if (dispatchEvent(self.element, 'cropmove', { + if (dispatchEvent(this.element, EVENT_CROP_MOVE, { originalEvent: e, action: action }) === false) { @@ -1648,18 +1909,16 @@ var handlers = { extend(pointers[e.pointerId || 0], getPointer(e, true)); } - self.change(e); + this.change(e); }, - cropEnd: function cropEnd(event) { - var self = this; - - if (self.disabled) { + cropEnd: function cropEnd(e) { + if (this.disabled) { return; } - var action = self.action; - var pointers = self.pointers; - var e = getEvent(event); + var action = this.action, + pointers = this.pointers; + if (e.changedTouches) { each(e.changedTouches, function (touch) { @@ -1676,71 +1935,35 @@ var handlers = { e.preventDefault(); if (!Object.keys(pointers).length) { - self.action = ''; + this.action = ''; } - if (self.cropping) { - self.cropping = false; - toggleClass(self.dragBox, 'cropper-modal', self.cropped && this.options.modal); + if (this.cropping) { + this.cropping = false; + toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal); } - dispatchEvent(self.element, 'cropend', { + dispatchEvent(this.element, EVENT_CROP_END, { originalEvent: e, action: action }); } }; -// Actions -var ACTION_EAST = 'e'; -var ACTION_WEST = 'w'; -var ACTION_SOUTH = 's'; -var ACTION_NORTH = 'n'; -var ACTION_SOUTH_EAST = 'se'; -var ACTION_SOUTH_WEST = 'sw'; -var ACTION_NORTH_EAST = 'ne'; -var ACTION_NORTH_WEST = 'nw'; - -function getMaxZoomRatio(pointers) { - var pointers2 = extend({}, pointers); - var ratios = []; - - each(pointers, function (pointer, pointerId) { - delete pointers2[pointerId]; - - each(pointers2, function (pointer2) { - var x1 = Math.abs(pointer.startX - pointer2.startX); - var y1 = Math.abs(pointer.startY - pointer2.startY); - var x2 = Math.abs(pointer.endX - pointer2.endX); - var y2 = Math.abs(pointer.endY - pointer2.endY); - var z1 = Math.sqrt(x1 * x1 + y1 * y1); - var z2 = Math.sqrt(x2 * x2 + y2 * y2); - var ratio = (z2 - z1) / z1; - - ratios.push(ratio); - }); - }); - - ratios.sort(function (a, b) { - return Math.abs(a) < Math.abs(b); - }); - - return ratios[0]; -} - var change = { change: function change(e) { - var self = this; - var options = self.options; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; + var options = this.options, + canvasData = this.canvasData, + containerData = this.containerData, + cropBoxData = this.cropBoxData, + pointers = this.pointers; + var action = this.action; var aspectRatio = options.aspectRatio; - var action = self.action; - var width = cropBoxData.width; - var height = cropBoxData.height; - var left = cropBoxData.left; - var top = cropBoxData.top; + var left = cropBoxData.left, + top = cropBoxData.top, + width = cropBoxData.width, + height = cropBoxData.height; + var right = left + width; var bottom = top + height; var minLeft = 0; @@ -1755,23 +1978,56 @@ var change = { aspectRatio = width && height ? width / height : 1; } - if (self.limited) { + if (this.limited) { minLeft = cropBoxData.minLeft; minTop = cropBoxData.minTop; + maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width); maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height); } - var pointers = self.pointers; var pointer = pointers[Object.keys(pointers)[0]]; var range = { x: pointer.endX - pointer.startX, y: pointer.endY - pointer.startY }; + var check = function check(side) { + switch (side) { + case ACTION_EAST: + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + + break; + + case ACTION_WEST: + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + + break; + + case ACTION_NORTH: + if (top + range.y < minTop) { + range.y = minTop - top; + } + + break; + + case ACTION_SOUTH: + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + + break; + + default: + } + }; switch (action) { // Move crop box - case 'all': + case ACTION_ALL: left += range.x; top += range.y; break; @@ -1783,10 +2039,7 @@ var change = { break; } - if (right + range.x > maxWidth) { - range.x = maxWidth - right; - } - + check(ACTION_EAST); width += range.x; if (aspectRatio) { @@ -1807,10 +2060,7 @@ var change = { break; } - if (top + range.y < minTop) { - range.y = minTop - top; - } - + check(ACTION_NORTH); height -= range.y; top += range.y; @@ -1832,10 +2082,7 @@ var change = { break; } - if (left + range.x < minLeft) { - range.x = minLeft - left; - } - + check(ACTION_WEST); width -= range.x; left += range.x; @@ -1857,10 +2104,7 @@ var change = { break; } - if (bottom + range.y > maxHeight) { - range.y = maxHeight - bottom; - } - + check(ACTION_SOUTH); height += range.y; if (aspectRatio) { @@ -1882,10 +2126,14 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -1928,11 +2176,15 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; left += range.y * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -1977,10 +2229,14 @@ var change = { break; } + check(ACTION_WEST); width -= range.x; left += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -2023,9 +2279,13 @@ var change = { break; } + check(ACTION_EAST); width += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -2060,25 +2320,25 @@ var change = { break; // Move canvas - case 'move': - self.move(range.x, range.y); + case ACTION_MOVE: + this.move(range.x, range.y); renderable = false; break; // Zoom canvas - case 'zoom': - self.zoom(getMaxZoomRatio(pointers), e); + case ACTION_ZOOM: + this.zoom(getMaxZoomRatio(pointers), e); renderable = false; break; // Create crop box - case 'crop': + case ACTION_CROP: if (!range.x || !range.y) { renderable = false; break; } - offset = getOffset(self.cropper); + offset = getOffset(this.cropper); left = pointer.startX - offset.left; top = pointer.startY - offset.top; width = cropBoxData.minWidth; @@ -2096,12 +2356,12 @@ var change = { } // Show the crop box if is hidden - if (!self.cropped) { - removeClass(self.cropBox, 'cropper-hidden'); - self.cropped = true; + if (!this.cropped) { + removeClass(this.cropBox, CLASS_HIDDEN); + this.cropped = true; - if (self.limited) { - self.limitCropBox(true, true); + if (this.limited) { + this.limitCropBox(true, true); } } @@ -2115,9 +2375,8 @@ var change = { cropBoxData.height = height; cropBoxData.left = left; cropBoxData.top = top; - self.action = action; - - self.renderCropBox(); + this.action = action; + this.renderCropBox(); } // Override @@ -2128,228 +2387,188 @@ var change = { } }; -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function getPointersCenter(pointers) { - var pageX = 0; - var pageY = 0; - var count = 0; - - each(pointers, function (_ref) { - var startX = _ref.startX, - startY = _ref.startY; - - pageX += startX; - pageY += startY; - count += 1; - }); - - pageX /= count; - pageY /= count; - - return { - pageX: pageX, - pageY: pageY - }; -} - var methods = { // Show the crop box manually crop: function crop() { - var self = this; + if (this.ready && !this.disabled) { + if (!this.cropped) { + this.cropped = true; + this.limitCropBox(true, true); - if (self.ready && !self.disabled) { - if (!self.cropped) { - self.cropped = true; - self.limitCropBox(true, true); - - if (self.options.modal) { - addClass(self.dragBox, 'cropper-modal'); + if (this.options.modal) { + addClass(this.dragBox, CLASS_MODAL); } - removeClass(self.cropBox, 'cropper-hidden'); + removeClass(this.cropBox, CLASS_HIDDEN); } - self.setCropBoxData(self.initialCropBoxData); + this.setCropBoxData(this.initialCropBoxData); } - return self; + return this; }, // Reset the image and crop box to their initial states reset: function reset() { - var self = this; - - if (self.ready && !self.disabled) { - self.imageData = extend({}, self.initialImageData); - self.canvasData = extend({}, self.initialCanvasData); - self.cropBoxData = extend({}, self.initialCropBoxData); + if (this.ready && !this.disabled) { + this.imageData = extend({}, this.initialImageData); + this.canvasData = extend({}, this.initialCanvasData); + this.cropBoxData = extend({}, this.initialCropBoxData); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } - return self; + return this; }, // Clear the crop box clear: function clear() { - var self = this; - - if (self.cropped && !self.disabled) { - extend(self.cropBoxData, { + if (this.cropped && !this.disabled) { + extend(this.cropBoxData, { left: 0, top: 0, width: 0, height: 0 }); - self.cropped = false; - self.renderCropBox(); - - self.limitCanvas(true, true); + this.cropped = false; + this.renderCropBox(); + this.limitCanvas(true, true); // Render canvas after crop box rendered - self.renderCanvas(); - - removeClass(self.dragBox, 'cropper-modal'); - addClass(self.cropBox, 'cropper-hidden'); + this.renderCanvas(); + removeClass(this.dragBox, CLASS_MODAL); + addClass(this.cropBox, CLASS_HIDDEN); } - return self; + return this; }, /** * Replace the image's src and rebuild the cropper - * - * @param {String} url - * @param {Boolean} onlyColorChanged (optional) + * @param {string} url - The new URL. + * @param {boolean} [onlyColorChanged] - Indicate if the new image only changed color. + * @returns {Object} this */ - replace: function replace(url, onlyColorChanged) { - var self = this; + replace: function replace(url) { + var onlyColorChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - if (!self.disabled && url) { - if (self.isImg) { - self.element.src = url; + if (!this.disabled && url) { + if (this.isImg) { + this.element.src = url; } if (onlyColorChanged) { - self.url = url; - self.image.src = url; + this.url = url; + this.image.src = url; - if (self.ready) { - self.image2.src = url; + if (this.ready) { + this.image2.src = url; - each(self.previews, function (element) { - getByTag(element, 'img')[0].src = url; + each(this.previews, function (element) { + element.getElementsByTagName('img')[0].src = url; }); } } else { - if (self.isImg) { - self.replaced = true; + if (this.isImg) { + this.replaced = true; } // Clear previous data - self.options.data = null; - self.load(url); + this.options.data = null; + this.load(url); } } - return self; + return this; }, // Enable (unfreeze) the cropper enable: function enable() { - var self = this; - - if (self.ready) { - self.disabled = false; - removeClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = false; + removeClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Disable (freeze) the cropper disable: function disable() { - var self = this; - - if (self.ready) { - self.disabled = true; - addClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = true; + addClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Destroy the cropper and remove the instance from the image destroy: function destroy() { - var self = this; - var element = self.element; - var image = self.image; + var element = this.element, + image = this.image; - if (self.loaded) { - if (self.isImg && self.replaced) { - element.src = self.originalUrl; + + if (this.loaded) { + if (this.isImg && this.replaced) { + element.src = this.originalUrl; } - self.unbuild(); - removeClass(element, 'cropper-hidden'); - } else if (self.isImg) { - removeListener(element, 'load', self.onStart); + this.unbuild(); + removeClass(element, CLASS_HIDDEN); + } else if (this.isImg) { + removeListener(element, EVENT_LOAD, this.onStart); } else if (image) { - removeChild(image); + image.parentNode.removeChild(image); } - removeData(element, 'cropper'); + removeData(element, NAMESPACE); - return self; + return this; }, /** * Move the canvas with relative offsets - * - * @param {Number} offsetX - * @param {Number} offsetY (optional) + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} offsetY - The relative offset distance on the y-axis. + * @returns {Object} this */ move: function move(offsetX, offsetY) { - var self = this; - var canvasData = self.canvasData; + var _canvasData = this.canvasData, + left = _canvasData.left, + top = _canvasData.top; + - return self.moveTo(isUndefined(offsetX) ? offsetX : canvasData.left + Number(offsetX), isUndefined(offsetY) ? offsetY : canvasData.top + Number(offsetY)); + return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY)); }, /** * Move the canvas to an absolute point - * - * @param {Number} x - * @param {Number} y (optional) + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Object} this */ - moveTo: function moveTo(x, y) { - var self = this; - var canvasData = self.canvasData; - var changed = false; + moveTo: function moveTo(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var canvasData = this.canvasData; - // If "y" is not present, its default value is "x" - if (isUndefined(y)) { - y = x; - } + var changed = false; x = Number(x); y = Number(y); - if (self.ready && !self.disabled && self.options.movable) { + if (this.ready && !this.disabled && this.options.movable) { if (isNumber(x)) { canvasData.left = x; changed = true; @@ -2361,23 +2580,23 @@ var methods = { } if (changed) { - self.renderCanvas(true); + this.renderCanvas(true); } } - return self; + return this; }, /** * Zoom the canvas with a relative ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoom: function zoom(ratio, _originalEvent) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + ratio = Number(ratio); @@ -2387,42 +2606,43 @@ var methods = { ratio = 1 + ratio; } - return self.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); + return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); }, /** * Zoom the canvas to an absolute ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoomTo: function zoomTo(ratio, _originalEvent) { - var self = this; - var options = self.options; - var canvasData = self.canvasData; - var width = canvasData.width; - var height = canvasData.height; - var naturalWidth = canvasData.naturalWidth; - var naturalHeight = canvasData.naturalHeight; + var options = this.options, + canvasData = this.canvasData; + var width = canvasData.width, + height = canvasData.height, + naturalWidth = canvasData.naturalWidth, + naturalHeight = canvasData.naturalHeight; + ratio = Number(ratio); - if (ratio >= 0 && self.ready && !self.disabled && options.zoomable) { + if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) { var newWidth = naturalWidth * ratio; var newHeight = naturalHeight * ratio; - if (dispatchEvent(self.element, 'zoom', { + if (dispatchEvent(this.element, EVENT_ZOOM, { originalEvent: _originalEvent, oldRatio: width / naturalWidth, ratio: newWidth / naturalWidth }) === false) { - return self; + return this; } if (_originalEvent) { - var pointers = self.pointers; - var offset = getOffset(self.cropper); + var pointers = this.pointers; + + var offset = getOffset(this.cropper); var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : { pageX: _originalEvent.pageX, pageY: _originalEvent.pageY @@ -2439,128 +2659,116 @@ var methods = { canvasData.width = newWidth; canvasData.height = newHeight; - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** * Rotate the canvas with a relative degree - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotate: function rotate(degree) { - var self = this; - - return self.rotateTo((self.imageData.rotate || 0) + Number(degree)); + return this.rotateTo((this.imageData.rotate || 0) + Number(degree)); }, /** * Rotate the canvas to an absolute degree - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate() - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotateTo: function rotateTo(degree) { - var self = this; - degree = Number(degree); - if (isNumber(degree) && self.ready && !self.disabled && self.options.rotatable) { - self.imageData.rotate = degree % 360; - self.rotated = true; - self.renderCanvas(true); + if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) { + this.imageData.rotate = degree % 360; + this.renderCanvas(true, true); } - return self; + return this; + }, + + + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Object} this + */ + scaleX: function scaleX(_scaleX) { + var scaleY = this.imageData.scaleY; + + + return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + + + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Object} this + */ + scaleY: function scaleY(_scaleY) { + var scaleX = this.imageData.scaleX; + + + return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); }, /** * Scale the image - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale() - * - * @param {Number} scaleX - * @param {Number} scaleY (optional) + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Object} this */ - scale: function scale(scaleX, scaleY) { - var self = this; - var imageData = self.imageData; - var changed = false; + scale: function scale(scaleX) { + var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX; + var imageData = this.imageData; - // If "scaleY" is not present, its default value is "scaleX" - if (isUndefined(scaleY)) { - scaleY = scaleX; - } + var transformed = false; scaleX = Number(scaleX); scaleY = Number(scaleY); - if (self.ready && !self.disabled && self.options.scalable) { + if (this.ready && !this.disabled && this.options.scalable) { if (isNumber(scaleX)) { imageData.scaleX = scaleX; - changed = true; + transformed = true; } if (isNumber(scaleY)) { imageData.scaleY = scaleY; - changed = true; + transformed = true; } - if (changed) { - self.renderImage(true); + if (transformed) { + this.renderCanvas(true, true); } } - return self; - }, - - - /** - * Scale the abscissa of the image - * - * @param {Number} scaleX - */ - scaleX: function scaleX(_scaleX) { - var self = this; - var scaleY = self.imageData.scaleY; - - return self.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); - }, - - - /** - * Scale the ordinate of the image - * - * @param {Number} scaleY - */ - scaleY: function scaleY(_scaleY) { - var self = this; - var scaleX = self.imageData.scaleX; - - return self.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + return this; }, /** * Get the cropped area position and size data (base on the original image) - * - * @param {Boolean} rounded (optional) - * @return {Object} data + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. */ - getData: function getData$$1(rounded) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var ratio = void 0; + getData: function getData$$1() { + var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { x: cropBoxData.left - canvasData.left, y: cropBoxData.top - canvasData.top, @@ -2568,7 +2776,7 @@ var methods = { height: cropBoxData.height }; - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; each(data, function (n, i) { n /= ratio; @@ -2598,51 +2806,47 @@ var methods = { /** * Set the cropped area position and size with new data - * - * @param {Object} data + * @param {Object} data - The new data. + * @returns {Object} this */ setData: function setData$$1(data) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData; + var cropBoxData = {}; - var rotated = void 0; - var scaled = void 0; - var ratio = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { + var transformed = false; + if (options.rotatable) { if (isNumber(data.rotate) && data.rotate !== imageData.rotate) { imageData.rotate = data.rotate; - rotated = true; - self.rotated = rotated; + transformed = true; } } if (options.scalable) { if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) { imageData.scaleX = data.scaleX; - scaled = true; + transformed = true; } if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) { imageData.scaleY = data.scaleY; - scaled = true; + transformed = true; } } - if (rotated) { - self.renderCanvas(); - } else if (scaled) { - self.renderImage(); + if (transformed) { + this.renderCanvas(true, true); } - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; if (isNumber(data.x)) { cropBoxData.left = data.x * ratio + canvasData.left; @@ -2660,48 +2864,41 @@ var methods = { cropBoxData.height = data.height * ratio; } - self.setCropBoxData(cropBoxData); + this.setCropBoxData(cropBoxData); } - return self; + return this; }, /** - * Get the container size data - * - * @return {Object} data + * Get the container size data. + * @returns {Object} The result container data. */ getContainerData: function getContainerData() { - var self = this; - - return self.ready ? self.containerData : {}; + return this.ready ? extend({}, this.containerData) : {}; }, /** - * Get the image position and size data - * - * @return {Object} data + * Get the image position and size data. + * @returns {Object} The result image data. */ getImageData: function getImageData() { - var self = this; - - return self.loaded ? self.imageData : {}; + return this.loaded ? extend({}, this.imageData) : {}; }, /** - * Get the canvas position and size data - * - * @return {Object} data + * Get the canvas position and size data. + * @returns {Object} The result canvas data. */ getCanvasData: function getCanvasData() { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + var data = {}; - if (self.ready) { + if (this.ready) { each(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) { data[n] = canvasData[n]; }); @@ -2712,20 +2909,20 @@ var methods = { /** - * Set the canvas position and size with new data - * - * @param {Object} data + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Object} this */ setCanvasData: function setCanvasData(data) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; var aspectRatio = canvasData.aspectRatio; + if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { canvasData.left = data.left; } @@ -2742,24 +2939,23 @@ var methods = { canvasData.width = data.height * aspectRatio; } - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** - * Get the crop box position and size data - * - * @return {Object} data + * Get the crop box position and size data. + * @returns {Object} The result crop box data. */ getCropBoxData: function getCropBoxData() { - var self = this; - var cropBoxData = self.cropBoxData; + var cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { left: cropBoxData.left, top: cropBoxData.top, @@ -2773,22 +2969,22 @@ var methods = { /** - * Set the crop box position and size with new data - * - * @param {Object} data + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Object} this */ setCropBoxData: function setCropBoxData(data) { - var self = this; - var cropBoxData = self.cropBoxData; - var aspectRatio = self.options.aspectRatio; + var cropBoxData = this.cropBoxData; + var aspectRatio = this.options.aspectRatio; + var widthChanged = void 0; var heightChanged = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && self.cropped && !self.disabled && isPlainObject(data)) { + if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { cropBoxData.left = data.left; } @@ -2815,210 +3011,204 @@ var methods = { } } - self.renderCropBox(); + this.renderCropBox(); } - return self; + return this; }, /** - * Get a canvas drawn the cropped image - * - * @param {Object} options (optional) - * @return {HTMLCanvasElement} canvas + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. */ - getCroppedCanvas: function getCroppedCanvas(options) { - var self = this; + getCroppedCanvas: function getCroppedCanvas() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - if (!self.ready || !window.HTMLCanvasElement) { + if (!this.ready || !window.HTMLCanvasElement) { return null; } - if (!isPlainObject(options)) { - options = {}; - } + var canvasData = this.canvasData; + + var source = getSourceCanvas(this.image, this.imageData, canvasData, options); - // Return the whole canvas if not cropped - if (!self.cropped) { - return getSourceCanvas(self.image, self.imageData, options); + // Returns the source canvas if it is not cropped. + if (!this.cropped) { + return source; } - var data = self.getData(); - var originalWidth = data.width; - var originalHeight = data.height; - var aspectRatio = originalWidth / originalHeight; - var scaledWidth = void 0; - var scaledHeight = void 0; - var scaledRatio = void 0; + var _getData = this.getData(), + x = _getData.x, + y = _getData.y, + initialWidth = _getData.width, + initialHeight = _getData.height; - if (isPlainObject(options)) { - scaledWidth = options.width; - scaledHeight = options.height; + var aspectRatio = initialWidth / initialHeight; + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.maxWidth || Infinity, + height: options.maxHeight || Infinity + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.minWidth || 0, + height: options.minHeight || 0 + }); - if (scaledWidth) { - scaledHeight = scaledWidth / aspectRatio; - scaledRatio = scaledWidth / originalWidth; - } else if (scaledHeight) { - scaledWidth = scaledHeight * aspectRatio; - scaledRatio = scaledHeight / originalHeight; - } - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.width || initialWidth, + height: options.height || initialHeight + }), + width = _getContainSizes.width, + height = _getContainSizes.height; - // The canvas element will use `Math.floor` on a float number, so floor first - var canvasWidth = Math.floor(scaledWidth || originalWidth); - var canvasHeight = Math.floor(scaledHeight || originalHeight); + width = Math.min(maxSizes.width, Math.max(minSizes.width, width)); + height = Math.min(maxSizes.height, Math.max(minSizes.height, height)); - var canvas = createElement('canvas'); + var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + canvas.width = width; + canvas.height = height; + + context.fillStyle = options.fillColor || 'transparent'; + context.fillRect(0, 0, width, height); - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); + var _options$imageSmoothi = options.imageSmoothingEnabled, + imageSmoothingEnabled = _options$imageSmoothi === undefined ? true : _options$imageSmoothi, + imageSmoothingQuality = options.imageSmoothingQuality; + + + context.imageSmoothingEnabled = imageSmoothingEnabled; + + if (imageSmoothingQuality) { + context.imageSmoothingQuality = imageSmoothingQuality; } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage - var parameters = function () { - var source = getSourceCanvas(self.image, self.imageData, options); - var sourceWidth = source.width; - var sourceHeight = source.height; - var canvasData = self.canvasData; - var params = [source]; - - // Source canvas - var srcX = data.x + canvasData.naturalWidth * (Math.abs(data.scaleX || 1) - 1) / 2; - var srcY = data.y + canvasData.naturalHeight * (Math.abs(data.scaleY || 1) - 1) / 2; - var srcWidth = void 0; - var srcHeight = void 0; - - // Destination canvas - var dstX = void 0; - var dstY = void 0; - var dstWidth = void 0; - var dstHeight = void 0; - - if (srcX <= -originalWidth || srcX > sourceWidth) { - srcX = 0; - srcWidth = 0; - dstX = 0; - dstWidth = 0; - } else if (srcX <= 0) { - dstX = -srcX; - srcX = 0; - srcWidth = Math.min(sourceWidth, originalWidth + srcX); - dstWidth = srcWidth; - } else if (srcX <= sourceWidth) { - dstX = 0; - srcWidth = Math.min(originalWidth, sourceWidth - srcX); - dstWidth = srcWidth; - } - - if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) { - srcY = 0; - srcHeight = 0; - dstY = 0; - dstHeight = 0; - } else if (srcY <= 0) { - dstY = -srcY; - srcY = 0; - srcHeight = Math.min(sourceHeight, originalHeight + srcY); - dstHeight = srcHeight; - } else if (srcY <= sourceHeight) { - dstY = 0; - srcHeight = Math.min(originalHeight, sourceHeight - srcY); - dstHeight = srcHeight; - } - - params.push(Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)); - - // Scale destination sizes - if (scaledRatio) { - dstX *= scaledRatio; - dstY *= scaledRatio; - dstWidth *= scaledRatio; - dstHeight *= scaledRatio; - } - - // Avoid "IndexSizeError" in IE and Firefox - if (dstWidth > 0 && dstHeight > 0) { - params.push(Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); - } - - return params; - }(); - - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; - - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; - } - - context.drawImage.apply(context, _toConsumableArray(parameters)); + var sourceWidth = source.width; + var sourceHeight = source.height; + + // Source canvas parameters + var srcX = x; + var srcY = y; + var srcWidth = void 0; + var srcHeight = void 0; + + // Destination canvas parameters + var dstX = void 0; + var dstY = void 0; + var dstWidth = void 0; + var dstHeight = void 0; + + if (srcX <= -initialWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + srcWidth = Math.min(sourceWidth, initialWidth + srcX); + dstWidth = srcWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + srcWidth = Math.min(initialWidth, sourceWidth - srcX); + dstWidth = srcWidth; + } + + if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + srcHeight = Math.min(sourceHeight, initialHeight + srcY); + dstHeight = srcHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + srcHeight = Math.min(initialHeight, sourceHeight - srcY); + dstHeight = srcHeight; + } + + // All the numerical parameters should be integer for `drawImage` + // https://github.com/fengyuanchen/cropper/issues/476 + var params = [Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)]; + + // Avoid "IndexSizeError" + if (dstWidth > 0 && dstHeight > 0) { + var scale = width / initialWidth; + + params.push(Math.floor(dstX * scale), Math.floor(dstY * scale), Math.floor(dstWidth * scale), Math.floor(dstHeight * scale)); + } + + context.drawImage.apply(context, [source].concat(params)); return canvas; }, /** - * Change the aspect ratio of the crop box - * - * @param {Number} aspectRatio + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Object} this */ setAspectRatio: function setAspectRatio(aspectRatio) { - var self = this; - var options = self.options; + var options = this.options; + - if (!self.disabled && !isUndefined(aspectRatio)) { + if (!this.disabled && !isUndefined(aspectRatio)) { // 0 -> NaN options.aspectRatio = Math.max(0, aspectRatio) || NaN; - if (self.ready) { - self.initCropBox(); + if (this.ready) { + this.initCropBox(); - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } } - return self; + return this; }, /** - * Change the drag mode - * - * @param {String} mode (optional) + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Object} this */ setDragMode: function setDragMode(mode) { - var self = this; - var options = self.options; - var dragBox = self.dragBox; - var face = self.face; - var croppable = void 0; - var movable = void 0; - - if (self.loaded && !self.disabled) { - croppable = mode === 'crop'; - movable = options.movable && mode === 'move'; - mode = croppable || movable ? mode : 'none'; - - setData(dragBox, 'action', mode); - toggleClass(dragBox, 'cropper-crop', croppable); - toggleClass(dragBox, 'cropper-move', movable); + var options = this.options, + dragBox = this.dragBox, + face = this.face; + + + if (this.loaded && !this.disabled) { + var croppable = mode === DRAG_MODE_CROP; + var movable = options.movable && mode === DRAG_MODE_MOVE; + + mode = croppable || movable ? mode : DRAG_MODE_NONE; + + setData(dragBox, DATA_ACTION, mode); + toggleClass(dragBox, CLASS_CROP, croppable); + toggleClass(dragBox, CLASS_MOVE, movable); if (!options.cropBoxMovable) { // Sync drag mode to crop box when it is not movable - setData(face, 'action', mode); - toggleClass(face, 'cropper-crop', croppable); - toggleClass(face, 'cropper-move', movable); + setData(face, DATA_ACTION, mode); + toggleClass(face, CLASS_CROP, croppable); + toggleClass(face, CLASS_MOVE, movable); } } - return self; + return this; } }; @@ -3026,55 +3216,47 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -// Constants -var NAMESPACE = 'cropper'; - -// Classes -var CLASS_HIDDEN = NAMESPACE + '-hidden'; - -// Events -var EVENT_ERROR = 'error'; -var EVENT_LOAD = 'load'; -var EVENT_READY = 'ready'; -var EVENT_CROP = 'crop'; - -// RegExps -var REGEXP_DATA_URL = /^data:/; -var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; - -var AnotherCropper = void 0; +var AnotherCropper = window.Cropper; var Cropper = function () { - function Cropper(element, options) { + /** + * Create a new Cropper. + * @param {Element} element - The target element for cropping. + * @param {Object} [options={}] - The configuration options. + */ + function Cropper(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Cropper); - var self = this; - - self.element = element; - self.options = extend({}, DEFAULTS, isPlainObject(options) && options); - self.loaded = false; - self.ready = false; - self.complete = false; - self.rotated = false; - self.cropped = false; - self.disabled = false; - self.replaced = false; - self.limited = false; - self.wheeling = false; - self.isImg = false; - self.originalUrl = ''; - self.canvasData = null; - self.cropBoxData = null; - self.previews = null; - self.pointers = {}; - self.init(); + if (!element || !REGEXP_TAG_NAME.test(element.tagName)) { + throw new Error('The first argument is required and must be an or element.'); + } + + this.element = element; + this.options = extend({}, DEFAULTS, isPlainObject(options) && options); + this.complete = false; + this.cropped = false; + this.disabled = false; + this.isImg = false; + this.limited = false; + this.loaded = false; + this.ready = false; + this.replaced = false; + this.wheeling = false; + this.originalUrl = ''; + this.canvasData = null; + this.cropBoxData = null; + this.previews = null; + this.pointers = {}; + this.init(); } _createClass(Cropper, [{ key: 'init', value: function init() { - var self = this; - var element = self.element; + var element = this.element; + var tagName = element.tagName.toLowerCase(); var url = void 0; @@ -3082,14 +3264,14 @@ var Cropper = function () { return; } - setData(element, NAMESPACE, self); + setData(element, NAMESPACE, this); if (tagName === 'img') { - self.isImg = true; + this.isImg = true; // e.g.: "img/picture.jpg" url = element.getAttribute('src'); - self.originalUrl = url; + this.originalUrl = url; // Stop when it's a blank image if (!url) { @@ -3102,45 +3284,48 @@ var Cropper = function () { url = element.toDataURL(); } - self.load(url); + this.load(url); } }, { key: 'load', value: function load(url) { - var self = this; - var options = self.options; - var element = self.element; + var _this = this; if (!url) { return; } - self.url = url; - self.imageData = {}; + this.url = url; + this.imageData = {}; + + var element = this.element, + options = this.options; + if (!options.checkOrientation || !window.ArrayBuffer) { - self.clone(); + this.clone(); return; } // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari if (REGEXP_DATA_URL.test(url)) { if (REGEXP_DATA_URL_JPEG.test(url)) { - self.read(dataURLToArrayBuffer(url)); + this.read(dataURLToArrayBuffer(url)); } else { - self.clone(); + this.clone(); } + return; } var xhr = new XMLHttpRequest(); xhr.onerror = function () { - self.clone(); + _this.clone(); }; xhr.onload = function () { - self.read(xhr.response); + _this.read(xhr.response); }; if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) { @@ -3155,57 +3340,22 @@ var Cropper = function () { }, { key: 'read', value: function read(arrayBuffer) { - var self = this; - var options = self.options; + var options = this.options, + imageData = this.imageData; + var orientation = getOrientation(arrayBuffer); - var imageData = self.imageData; var rotate = 0; var scaleX = 1; var scaleY = 1; if (orientation > 1) { - self.url = arrayBufferToDataURL(arrayBuffer); - - switch (orientation) { - // flip horizontal - case 2: - scaleX = -1; - break; - - // rotate left 180° - case 3: - rotate = -180; - break; - - // flip vertical - case 4: - scaleY = -1; - break; - - // flip vertical + rotate right 90° - case 5: - rotate = 90; - scaleY = -1; - break; - - // rotate right 90° - case 6: - rotate = 90; - break; - - // flip horizontal + rotate right 90° - case 7: - rotate = 90; - scaleX = -1; - break; + this.url = arrayBufferToDataURL(arrayBuffer, 'image/jpeg'); - // rotate left 90° - case 8: - rotate = -90; - break; + var _parseOrientation = parseOrientation(orientation); - default: - } + rotate = _parseOrientation.rotate; + scaleX = _parseOrientation.scaleX; + scaleY = _parseOrientation.scaleY; } if (options.rotatable) { @@ -3217,20 +3367,21 @@ var Cropper = function () { imageData.scaleY = scaleY; } - self.clone(); + this.clone(); } }, { key: 'clone', value: function clone() { - var self = this; - var element = self.element; - var url = self.url; + var element = this.element, + url = this.url; + var crossOrigin = void 0; var crossOriginUrl = void 0; - if (self.options.checkCrossOrigin && isCrossOriginURL(url)) { + if (this.options.checkCrossOrigin && isCrossOriginURL(url)) { crossOrigin = element.crossOrigin; + if (crossOrigin) { crossOriginUrl = url; } else { @@ -3241,10 +3392,10 @@ var Cropper = function () { } } - self.crossOrigin = crossOrigin; - self.crossOriginUrl = crossOriginUrl; + this.crossOrigin = crossOrigin; + this.crossOriginUrl = crossOriginUrl; - var image = createElement('img'); + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; @@ -3252,98 +3403,99 @@ var Cropper = function () { image.src = crossOriginUrl || url; - var start = proxy(self.start, self); - var stop = proxy(self.stop, self); + var start = proxy(this.start, this); + var stop = proxy(this.stop, this); - self.image = image; - self.onStart = start; - self.onStop = stop; + this.image = image; + this.onStart = start; + this.onStop = stop; - if (self.isImg) { + if (this.isImg) { if (element.complete) { - self.start(); + this.start(); } else { addListener(element, EVENT_LOAD, start); } } else { addListener(image, EVENT_LOAD, start); addListener(image, EVENT_ERROR, stop); - addClass(image, 'cropper-hide'); + addClass(image, CLASS_HIDE); element.parentNode.insertBefore(image, element.nextSibling); } } }, { key: 'start', value: function start(event) { - var self = this; - var image = self.isImg ? self.element : self.image; + var _this2 = this; + + var image = this.isImg ? this.element : this.image; if (event) { - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); } - getImageSize(image, function (naturalWidth, naturalHeight) { - extend(self.imageData, { + getImageNaturalSizes(image, function (naturalWidth, naturalHeight) { + extend(_this2.imageData, { naturalWidth: naturalWidth, naturalHeight: naturalHeight, aspectRatio: naturalWidth / naturalHeight }); - - self.loaded = true; - self.build(); + _this2.loaded = true; + _this2.build(); }); } }, { key: 'stop', value: function stop() { - var self = this; - var image = self.image; + var image = this.image; - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); - removeChild(image); - self.image = null; + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); + image.parentNode.removeChild(image); + this.image = null; } }, { key: 'build', value: function build() { - var self = this; - var options = self.options; - var element = self.element; - var image = self.image; + var _this3 = this; - if (!self.loaded) { + if (!this.loaded) { return; } // Unbuild first when replace - if (self.ready) { - self.unbuild(); + if (this.ready) { + this.unbuild(); } + var element = this.element, + options = this.options, + image = this.image; + // Create cropper elements + var container = element.parentNode; - var template = createElement('div'); + var template = document.createElement('div'); template.innerHTML = TEMPLATE; - var cropper = getByClass(template, 'cropper-container')[0]; - var canvas = getByClass(cropper, 'cropper-canvas')[0]; - var dragBox = getByClass(cropper, 'cropper-drag-box')[0]; - var cropBox = getByClass(cropper, 'cropper-crop-box')[0]; - var face = getByClass(cropBox, 'cropper-face')[0]; + var cropper = template.querySelector('.' + NAMESPACE + '-container'); + var canvas = cropper.querySelector('.' + NAMESPACE + '-canvas'); + var dragBox = cropper.querySelector('.' + NAMESPACE + '-drag-box'); + var cropBox = cropper.querySelector('.' + NAMESPACE + '-crop-box'); + var face = cropBox.querySelector('.' + NAMESPACE + '-face'); - self.container = container; - self.cropper = cropper; - self.canvas = canvas; - self.dragBox = dragBox; - self.cropBox = cropBox; - self.viewBox = getByClass(cropper, 'cropper-view-box')[0]; - self.face = face; + this.container = container; + this.cropper = cropper; + this.canvas = canvas; + this.dragBox = dragBox; + this.cropBox = cropBox; + this.viewBox = cropper.querySelector('.' + NAMESPACE + '-view-box'); + this.face = face; - appendChild(canvas, image); + canvas.appendChild(image); // Hide the original image addClass(element, CLASS_HIDDEN); @@ -3352,114 +3504,123 @@ var Cropper = function () { container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden - if (!self.isImg) { - removeClass(image, 'cropper-hide'); + if (!this.isImg) { + removeClass(image, CLASS_HIDE); } - self.initPreview(); - self.bind(); + this.initPreview(); + this.bind(); options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; - self.cropped = options.autoCrop; + this.cropped = options.autoCrop; if (options.autoCrop) { if (options.modal) { - addClass(dragBox, 'cropper-modal'); + addClass(dragBox, CLASS_MODAL); } } else { addClass(cropBox, CLASS_HIDDEN); } if (!options.guides) { - addClass(getByClass(cropBox, 'cropper-dashed'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-dashed'), CLASS_HIDDEN); } if (!options.center) { - addClass(getByClass(cropBox, 'cropper-center'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-center'), CLASS_HIDDEN); } if (options.background) { - addClass(cropper, 'cropper-bg'); + addClass(cropper, NAMESPACE + '-bg'); } if (!options.highlight) { - addClass(face, 'cropper-invisible'); + addClass(face, CLASS_INVISIBLE); } if (options.cropBoxMovable) { - addClass(face, 'cropper-move'); - setData(face, 'action', 'all'); + addClass(face, CLASS_MOVE); + setData(face, DATA_ACTION, ACTION_ALL); } if (!options.cropBoxResizable) { - addClass(getByClass(cropBox, 'cropper-line'), CLASS_HIDDEN); - addClass(getByClass(cropBox, 'cropper-point'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-line'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-point'), CLASS_HIDDEN); } - self.setDragMode(options.dragMode); - self.render(); - self.ready = true; - self.setData(options.data); + this.setDragMode(options.dragMode); + this.render(); + this.ready = true; + this.setData(options.data); // Call the "ready" option asynchronously to keep "image.cropper" is defined - self.completing = setTimeout(function () { + this.completing = setTimeout(function () { if (isFunction(options.ready)) { - addListener(element, EVENT_READY, options.ready, true); + addListener(element, EVENT_READY, options.ready, { + once: true + }); } dispatchEvent(element, EVENT_READY); - dispatchEvent(element, EVENT_CROP, self.getData()); + dispatchEvent(element, EVENT_CROP, _this3.getData()); - self.complete = true; + _this3.complete = true; }, 0); } }, { key: 'unbuild', value: function unbuild() { - var self = this; - - if (!self.ready) { + if (!this.ready) { return; } - if (!self.complete) { - clearTimeout(self.completing); + if (!this.complete) { + clearTimeout(this.completing); } - self.ready = false; - self.complete = false; - self.initialImageData = null; + this.ready = false; + this.complete = false; + this.initialImageData = null; // Clear `initialCanvasData` is necessary when replace - self.initialCanvasData = null; - self.initialCropBoxData = null; - self.containerData = null; - self.canvasData = null; + this.initialCanvasData = null; + this.initialCropBoxData = null; + this.containerData = null; + this.canvasData = null; // Clear `cropBoxData` is necessary when replace - self.cropBoxData = null; - self.unbind(); - - self.resetPreview(); - self.previews = null; + this.cropBoxData = null; + this.unbind(); + this.resetPreview(); + this.previews = null; + this.viewBox = null; + this.cropBox = null; + this.dragBox = null; + this.canvas = null; + this.container = null; + this.cropper.parentNode.removeChild(this.cropper); + this.cropper = null; + } + + /** + * Get the no conflict cropper class. + * @returns {Cropper} The cropper class. + */ - self.viewBox = null; - self.cropBox = null; - self.dragBox = null; - self.canvas = null; - self.container = null; - - removeChild(self.cropper); - self.cropper = null; - } }], [{ key: 'noConflict', value: function noConflict() { window.Cropper = AnotherCropper; return Cropper; } + + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + }, { key: 'setDefaults', value: function setDefaults(options) { @@ -3470,16 +3631,6 @@ var Cropper = function () { return Cropper; }(); -extend(Cropper.prototype, render); -extend(Cropper.prototype, preview); -extend(Cropper.prototype, events); -extend(Cropper.prototype, handlers); -extend(Cropper.prototype, change); -extend(Cropper.prototype, methods); - -if (typeof window !== 'undefined') { - AnotherCropper = window.Cropper; - window.Cropper = Cropper; -} +extend(Cropper.prototype, render, preview, events, handlers, change, methods); export default Cropper; diff --git a/dist/cropper.js b/dist/cropper.js index 1a79cc597..1052f8f35 100644 --- a/dist/cropper.js +++ b/dist/cropper.js @@ -1,11 +1,11 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:11:03.372Z */ (function (global, factory) { @@ -14,12 +14,72 @@ (global.Cropper = factory()); }(this, (function () { 'use strict'; +var _window = window; +var PointerEvent = _window.PointerEvent; + + +var NAMESPACE = 'cropper'; + +// Actions +var ACTION_ALL = 'all'; +var ACTION_CROP = 'crop'; +var ACTION_MOVE = 'move'; +var ACTION_ZOOM = 'zoom'; +var ACTION_EAST = 'e'; +var ACTION_WEST = 'w'; +var ACTION_SOUTH = 's'; +var ACTION_NORTH = 'n'; +var ACTION_NORTH_EAST = 'ne'; +var ACTION_NORTH_WEST = 'nw'; +var ACTION_SOUTH_EAST = 'se'; +var ACTION_SOUTH_WEST = 'sw'; + +// Classes +var CLASS_CROP = NAMESPACE + '-crop'; +var CLASS_DISABLED = NAMESPACE + '-disabled'; +var CLASS_HIDDEN = NAMESPACE + '-hidden'; +var CLASS_HIDE = NAMESPACE + '-hide'; +var CLASS_INVISIBLE = NAMESPACE + '-invisible'; +var CLASS_MODAL = NAMESPACE + '-modal'; +var CLASS_MOVE = NAMESPACE + '-move'; + +// Data keys +var DATA_ACTION = 'action'; +var DATA_PREVIEW = 'preview'; + +// Drag modes +var DRAG_MODE_CROP = 'crop'; +var DRAG_MODE_MOVE = 'move'; +var DRAG_MODE_NONE = 'none'; + +// Events +var EVENT_CROP = 'crop'; +var EVENT_CROP_END = 'cropend'; +var EVENT_CROP_MOVE = 'cropmove'; +var EVENT_CROP_START = 'cropstart'; +var EVENT_DBLCLICK = 'dblclick'; +var EVENT_ERROR = 'error'; +var EVENT_LOAD = 'load'; +var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; +var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; +var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; +var EVENT_READY = 'ready'; +var EVENT_RESIZE = 'resize'; +var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; +var EVENT_ZOOM = 'zoom'; + +// RegExps +var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; +var REGEXP_DATA_URL = /^data:/; +var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; +var REGEXP_TAG_NAME = /^(img|canvas)$/i; + var DEFAULTS = { // Define the view mode of the cropper viewMode: 0, // 0, 1, 2, 3 // Define the dragging mode of the cropper - dragMode: 'crop', // 'crop', 'move' or 'none' + dragMode: DRAG_MODE_CROP, // 'crop', 'move' or 'none' // Define the aspect ratio of the crop box aspectRatio: NaN, @@ -114,94 +174,105 @@ var TEMPLATE = '
' + '
1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; @@ -224,6 +295,12 @@ function extend(obj) { return obj; } +/** + * Takes a function and returns a new one that will always have a particular context. + * @param {Function} fn - The target function. + * @param {Object} context - The new context for the function. + * @returns {boolean} The new function. + */ function proxy(fn, context) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; @@ -238,9 +315,17 @@ function proxy(fn, context) { }; } +var REGEXP_SUFFIX = /^(width|height|left|top|marginLeft|marginTop)$/; + +/** + * Apply styles to the given element. + * @param {Element} element - The target element. + * @param {Object} styles - The styles for applying. + */ function setStyle(element, styles) { var style = element.style; + each(styles, function (value, property) { if (REGEXP_SUFFIX.test(property) && isNumber(value)) { value += 'px'; @@ -250,10 +335,21 @@ function setStyle(element, styles) { }); } +/** + * Check if the given element has a special class. + * @param {Element} element - The element to check. + * @param {string} value - The class to search. + * @returns {boolean} Returns `true` if the special class was found. + */ function hasClass(element, value) { return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1; } +/** + * Add classes to the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be added. + */ function addClass(element, value) { if (!value) { return; @@ -271,7 +367,7 @@ function addClass(element, value) { return; } - var className = trim(element.className); + var className = element.className.trim(); if (!className) { element.className = value; @@ -280,6 +376,11 @@ function addClass(element, value) { } } +/** + * Remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be removed. + */ function removeClass(element, value) { if (!value) { return; @@ -302,6 +403,12 @@ function removeClass(element, value) { } } +/** + * Add or remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be toggled. + * @param {boolean} added - Add only. + */ function toggleClass(element, value, added) { if (!value) { return; @@ -322,10 +429,23 @@ function toggleClass(element, value, added) { } } -function hyphenate(str) { - return str.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); +var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g; + +/** + * Hyphenate the given value. + * @param {string} value - The value to hyphenate. + * @returns {string} The hyphenated value. + */ +function hyphenate(value) { + return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); } +/** + * Get data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to get. + * @returns {string} The data value. + */ function getData(element, name) { if (isObject(element[name])) { return element[name]; @@ -336,6 +456,12 @@ function getData(element, name) { return element.getAttribute('data-' + hyphenate(name)); } +/** + * Set data to the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to set. + * @param {string} data - The data value. + */ function setData(element, name, data) { if (isObject(data)) { element[name] = data; @@ -346,6 +472,11 @@ function setData(element, name, data) { } } +/** + * Remove data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to remove. + */ function removeData(element, name) { if (isObject(element[name])) { delete element[name]; @@ -361,53 +492,86 @@ function removeData(element, name) { } } -function removeListener(element, type, handler) { - var types = trim(type).split(REGEXP_SPACES); +var REGEXP_SPACES = /\s+/; + +/** + * Remove event listener from the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to remove, + * @param {Function} listener - The event listener to remove. + * @param {Object} options - The event options. + */ +function removeListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - removeListener(element, t, handler); + removeListener(element, t, listener); }); return; } + if (isFunction(listener.onceListener)) { + listener = listener.onceListener; + delete listener.onceListener; + } + if (element.removeEventListener) { - element.removeEventListener(type, handler, false); + element.removeEventListener(type, listener, options); } else if (element.detachEvent) { - element.detachEvent('on' + type, handler); + element.detachEvent('on' + type, listener); } } -function addListener(element, type, _handler, once) { - var types = trim(type).split(REGEXP_SPACES); - var originalHandler = _handler; +/** + * Add event listener to the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to add, + * @param {Function} listener - The event listener to add. + * @param {Object} options - The event options. + */ +function addListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - addListener(element, t, _handler); + addListener(element, t, listener); }); return; } - if (once) { - _handler = function handler() { + if (options.once) { + var originalListener = listener; + var onceListener = function onceListener() { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } - removeListener(element, type, _handler); - - return originalHandler.apply(element, args); + removeListener(element, type, onceListener); + return originalListener.apply(element, args); }; + originalListener.onceListener = onceListener; + listener = onceListener; } if (element.addEventListener) { - element.addEventListener(type, _handler, false); + element.addEventListener(type, listener, options); } else if (element.attachEvent) { - element.attachEvent('on' + type, _handler); + element.attachEvent('on' + type, listener); } } +/** + * Dispatch event on the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to dispatch, + * @param {Object} data - The additional event data. + * @returns {boolean} Indicate if the event is default prevented or not. + */ function dispatchEvent(element, type, data) { if (element.dispatchEvent) { var event = void 0; @@ -444,26 +608,11 @@ function dispatchEvent(element, type, data) { return true; } -function getEvent(event) { - var e = event || window.event; - - // Fix target property (IE8) - if (!e.target) { - e.target = e.srcElement || document; - } - - if (!isNumber(e.pageX) && isNumber(e.clientX)) { - var eventDoc = event.target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - e.pageX = e.clientX + ((doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0)); - e.pageY = e.clientY + ((doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0)); - } - - return e; -} - +/** + * Get the offset base on the document. + * @param {Element} element - The target element. + * @returns {Object} The offset data. + */ function getOffset(element) { var doc = document.documentElement; var box = element.getBoundingClientRect(); @@ -474,93 +623,79 @@ function getOffset(element) { }; } -function getByTag(element, tagName) { - return element.getElementsByTagName(tagName); -} - -function getByClass(element, className) { - return element.getElementsByClassName ? element.getElementsByClassName(className) : element.querySelectorAll('.' + className); -} - -function createElement(tagName) { - return document.createElement(tagName); -} - -function appendChild(element, elem) { - element.appendChild(elem); -} - -function removeChild(element) { - if (element.parentNode) { - element.parentNode.removeChild(element); - } -} - +/** + * Empty an element. + * @param {Element} element - The element to empty. + */ function empty(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } +var _window$1 = window; +var location = _window$1.location; + +var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i; + +/** + * Check if the given URL is a cross origin URL. + * @param {string} url - The target URL. + * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`. + */ function isCrossOriginURL(url) { var parts = url.match(REGEXP_ORIGINS); return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); } +/** + * Add timestamp to the given URL. + * @param {string} url - The target URL. + * @returns {string} The result URL. + */ function addTimestamp(url) { var timestamp = 'timestamp=' + new Date().getTime(); return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; } -function getImageSize(image, callback) { - // Modern browsers (ignore Safari) - if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { - callback(image.naturalWidth, image.naturalHeight); - return; - } - - // IE8: Don't use `new Image()` here - var newImage = createElement('img'); - - newImage.onload = function load() { - callback(this.width, this.height); - }; - - newImage.src = image.src; -} +/** + * Get transforms base on the given object. + * @param {Object} obj - The target object. + * @returns {string} A string contains transform values. + */ +function getTransforms(_ref) { + var rotate = _ref.rotate, + scaleX = _ref.scaleX, + scaleY = _ref.scaleY, + translateX = _ref.translateX, + translateY = _ref.translateY; -function getTransforms(data) { - var transforms = []; - var translateX = data.translateX; - var translateY = data.translateY; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; + var values = []; if (isNumber(translateX) && translateX !== 0) { - transforms.push('translateX(' + translateX + 'px)'); + values.push('translateX(' + translateX + 'px)'); } if (isNumber(translateY) && translateY !== 0) { - transforms.push('translateY(' + translateY + 'px)'); + values.push('translateY(' + translateY + 'px)'); } // Rotate should come first before scale to match orientation transform if (isNumber(rotate) && rotate !== 0) { - transforms.push('rotate(' + rotate + 'deg)'); + values.push('rotate(' + rotate + 'deg)'); } if (isNumber(scaleX) && scaleX !== 1) { - transforms.push('scaleX(' + scaleX + ')'); + values.push('scaleX(' + scaleX + ')'); } if (isNumber(scaleY) && scaleY !== 1) { - transforms.push('scaleY(' + scaleY + ')'); + values.push('scaleY(' + scaleY + ')'); } - var transform = transforms.length ? transforms.join(' ') : 'none'; + var transform = values.length ? values.join(' ') : 'none'; return { WebkitTransform: transform, @@ -569,136 +704,326 @@ function getTransforms(data) { }; } -function getRotatedSizes(data, reversed) { - var deg = Math.abs(data.degree) % 180; - var arc = (deg > 90 ? 180 - deg : deg) * Math.PI / 180; - var sinArc = Math.sin(arc); - var cosArc = Math.cos(arc); - var width = data.width; - var height = data.height; - var aspectRatio = data.aspectRatio; - var newWidth = void 0; - var newHeight = void 0; - - if (!reversed) { - newWidth = width * cosArc + height * sinArc; - newHeight = width * sinArc + height * cosArc; - } else { - newWidth = width / (cosArc + sinArc / aspectRatio); - newHeight = newWidth / aspectRatio; +var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent); + +/** + * Get an image's natural sizes. + * @param {string} image - The target image. + * @param {Function} callback - The callback function. + */ +function getImageNaturalSizes(image, callback) { + // Modern browsers (except Safari) + if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { + callback(image.naturalWidth, image.naturalHeight); + return; } - return { - width: newWidth, - height: newHeight + var newImage = document.createElement('img'); + + newImage.onload = function () { + callback(newImage.width, newImage.height); }; + + newImage.src = image.src; } -function getSourceCanvas(image, data, options) { - var canvas = createElement('canvas'); - var context = canvas.getContext('2d'); - var dstX = 0; - var dstY = 0; - var dstWidth = data.naturalWidth; - var dstHeight = data.naturalHeight; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; - var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1); - var rotatable = isNumber(rotate) && rotate !== 0; - var advanced = rotatable || scalable; - var canvasWidth = dstWidth * Math.abs(scaleX || 1); - var canvasHeight = dstHeight * Math.abs(scaleY || 1); - var translateX = void 0; - var translateY = void 0; - var rotated = void 0; - - if (scalable) { - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } +/** + * Get the max ratio of a group of pointers. + * @param {string} pointers - The target pointers. + * @returns {number} The result ratio. + */ +function getMaxZoomRatio(pointers) { + var pointers2 = extend({}, pointers); + var ratios = []; - if (rotatable) { - rotated = getRotatedSizes({ - width: canvasWidth, - height: canvasHeight, - degree: rotate + each(pointers, function (pointer, pointerId) { + delete pointers2[pointerId]; + + each(pointers2, function (pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + + ratios.push(ratio); }); + }); - canvasWidth = rotated.width; - canvasHeight = rotated.height; - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } + ratios.sort(function (a, b) { + return Math.abs(a) < Math.abs(b); + }); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + return ratios[0]; +} - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); - } +/** + * Get a pointer from an event object. + * @param {Object} event - The target event object. + * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. + * @returns {Object} The result pointer contains start and/or end point coordinates. + */ +function getPointer(_ref2, endOnly) { + var pageX = _ref2.pageX, + pageY = _ref2.pageY; - if (advanced) { - dstX = -dstWidth / 2; - dstY = -dstHeight / 2; + var end = { + endX: pageX, + endY: pageY + }; - context.save(); - context.translate(translateX, translateY); + if (endOnly) { + return end; } - // Rotate should come first before scale as in the "getTransform" function - if (rotatable) { - context.rotate(rotate * Math.PI / 180); - } + return extend({ + startX: pageX, + startY: pageY + }, end); +} - if (scalable) { - context.scale(scaleX, scaleY); - } +/** + * Get the center point coordinate of a group of pointers. + * @param {Object} pointers - The target pointers. + * @returns {Object} The center point coordinate. + */ +function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + each(pointers, function (_ref3) { + var startX = _ref3.startX, + startY = _ref3.startY; + + pageX += startX; + pageY += startY; + count += 1; + }); + + pageX /= count; + pageY /= count; + + return { + pageX: pageX, + pageY: pageY + }; +} + +/** + * Check if the given value is a finite number. + */ +var isFinite = Number.isFinite || window.isFinite; + +/** + * Get the max sizes in a rectangle under the given aspect ratio. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getContainSizes(_ref4) { + var aspectRatio = _ref4.aspectRatio, + height = _ref4.height, + width = _ref4.width; - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; + var isValidNumber = function isValidNumber(value) { + return isFinite(value) && value > 0; + }; + + if (isValidNumber(width) && isValidNumber(height)) { + if (height * aspectRatio > width) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } + } else if (isValidNumber(width)) { + height = width / aspectRatio; + } else if (isValidNumber(height)) { + width = height * aspectRatio; } - context.drawImage(image, Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + return { + width: width, + height: height + }; +} + +/** + * Get the new sizes of a rectangle after rotated. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getRotatedSizes(_ref5) { + var width = _ref5.width, + height = _ref5.height, + degree = _ref5.degree; - if (advanced) { - context.restore(); + degree = Math.abs(degree); + + if (degree % 180 === 90) { + return { + width: height, + height: width + }; } + var arc = degree % 90 * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + + return { + width: width * cosArc + height * sinArc, + height: width * sinArc + height * cosArc + }; +} + +/** + * Get a canvas which drew the given image. + * @param {HTMLImageElement} image - The image for drawing. + * @param {Object} imageData - The image data. + * @param {Object} canvasData - The canvas data. + * @param {Object} options - The options. + * @returns {HTMLCanvasElement} The result canvas. + */ +function getSourceCanvas(image, _ref6, _ref7, _ref8) { + var imageNaturalWidth = _ref6.naturalWidth, + imageNaturalHeight = _ref6.naturalHeight, + rotate = _ref6.rotate, + scaleX = _ref6.scaleX, + scaleY = _ref6.scaleY; + var aspectRatio = _ref7.aspectRatio, + naturalWidth = _ref7.naturalWidth, + naturalHeight = _ref7.naturalHeight; + var _ref8$fillColor = _ref8.fillColor, + fillColor = _ref8$fillColor === undefined ? 'transparent' : _ref8$fillColor, + _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled, + imageSmoothingEnabled = _ref8$imageSmoothingE === undefined ? true : _ref8$imageSmoothingE, + _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality, + imageSmoothingQuality = _ref8$imageSmoothingQ === undefined ? 'low' : _ref8$imageSmoothingQ, + _ref8$maxWidth = _ref8.maxWidth, + maxWidth = _ref8$maxWidth === undefined ? Infinity : _ref8$maxWidth, + _ref8$maxHeight = _ref8.maxHeight, + maxHeight = _ref8$maxHeight === undefined ? Infinity : _ref8$maxHeight, + _ref8$minWidth = _ref8.minWidth, + minWidth = _ref8$minWidth === undefined ? 0 : _ref8$minWidth, + _ref8$minHeight = _ref8.minHeight, + minHeight = _ref8$minHeight === undefined ? 0 : _ref8$minHeight; + + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: maxWidth, + height: maxHeight + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minWidth, + height: minHeight + }); + var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth)); + var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); + + canvas.width = width; + canvas.height = height; + context.fillStyle = fillColor; + context.fillRect(0, 0, width, height); + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.imageSmoothingEnabled = imageSmoothingEnabled; + context.imageSmoothingQuality = imageSmoothingQuality; + context.drawImage(image, Math.floor(-imageNaturalWidth / 2), Math.floor(-imageNaturalHeight / 2), Math.floor(imageNaturalWidth), Math.floor(imageNaturalHeight)); + context.restore(); return canvas; } +var fromCharCode = String.fromCharCode; + +/** + * Get string from char code in data view. + * @param {DataView} dataView - The data view for read. + * @param {number} start - The start index. + * @param {number} length - The read length. + * @returns {string} The read result. + */ + function getStringFromCharCode(dataView, start, length) { var str = ''; - var i = start; + var i = void 0; + + length += start; - for (length += start; i < length; i += 1) { + for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } return str; } +var _window2 = window; +var atob = _window2.atob; + +var REGEXP_DATA_URL_HEAD = /^data:.*,/; + +/** + * Transform Data URL to array buffer. + * @param {string} dataURL - The Data URL to transform. + * @returns {ArrayBuffer} The result array buffer. + */ +function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var arrayBuffer = new ArrayBuffer(binary.length); + var uint8 = new Uint8Array(arrayBuffer); + + each(uint8, function (value, i) { + uint8[i] = binary.charCodeAt(i); + }); + + return arrayBuffer; +} + +var _window3 = window; +var btoa = _window3.btoa; + +/** + * Transform array buffer to Data URL. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {string} mimeType - The mime type of the Data URL. + * @returns {string} The result Data URL. + */ + +function arrayBufferToDataURL(arrayBuffer, mimeType) { + var uint8 = new Uint8Array(arrayBuffer); + var data = ''; + + // TypedArray.prototype.forEach is not supported in some browsers. + each(uint8, function (value) { + data += fromCharCode(value); + }); + + return 'data:' + mimeType + ';base64,' + btoa(data); +} + +/** + * Get orientation value from given array buffer. + * @param {ArrayBuffer} arrayBuffer - The array buffer to read. + * @returns {number} The read orientation value. + */ function getOrientation(arrayBuffer) { var dataView = new DataView(arrayBuffer); - var length = dataView.byteLength; var orientation = void 0; - var exifIDCode = void 0; - var tiffOffset = void 0; - var firstIFDOffset = void 0; var littleEndian = void 0; - var endianness = void 0; var app1Start = void 0; var ifdStart = void 0; - var offset = void 0; - var i = void 0; // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - offset = 2; + var length = dataView.byteLength; + var offset = 2; while (offset < length) { if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { @@ -711,16 +1036,17 @@ function getOrientation(arrayBuffer) { } if (app1Start) { - exifIDCode = app1Start + 4; - tiffOffset = app1Start + 10; + var exifIDCode = app1Start + 4; + var tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - endianness = dataView.getUint16(tiffOffset); + var endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; @@ -731,23 +1057,22 @@ function getOrientation(arrayBuffer) { } if (ifdStart) { - length = dataView.getUint16(ifdStart, littleEndian); + var _length = dataView.getUint16(ifdStart, littleEndian); + var _offset = void 0; + var i = void 0; - for (i = 0; i < length; i += 1) { - offset = ifdStart + i * 12 + 2; + for (i = 0; i < _length; i += 1) { + _offset = ifdStart + i * 12 + 2; - if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) { + if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) { // 8 is the offset of the current tag's value - offset += 8; + _offset += 8; // Get the original orientation value - orientation = dataView.getUint16(offset, littleEndian); - - // Override the orientation with its default value for Safari - if (IS_SAFARI_OR_UIWEBVIEW) { - dataView.setUint16(offset, 1, littleEndian); - } + orientation = dataView.getUint16(_offset, littleEndian); + // Override the orientation with its default value + dataView.setUint16(_offset, 1, littleEndian); break; } } @@ -756,83 +1081,108 @@ function getOrientation(arrayBuffer) { return orientation; } -function dataURLToArrayBuffer(dataURL) { - var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); - var binary = atob(base64); - var length = binary.length; - var arrayBuffer = new ArrayBuffer(length); - var dataView = new Uint8Array(arrayBuffer); - var i = void 0; - - for (i = 0; i < length; i += 1) { - dataView[i] = binary.charCodeAt(i); - } - - return arrayBuffer; -} - -// Only available for JPEG image -function arrayBufferToDataURL(arrayBuffer) { - var dataView = new Uint8Array(arrayBuffer); - var length = dataView.length; - var base64 = ''; - var i = void 0; - - for (i = 0; i < length; i += 1) { - base64 += fromCharCode(dataView[i]); +/** + * Parse Exif Orientation value. + * @param {number} orientation - The orientation to parse. + * @returns {Object} The parsed result. + */ +function parseOrientation(orientation) { + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + + switch (orientation) { + // Flip horizontal + case 2: + scaleX = -1; + break; + + // Rotate left 180° + case 3: + rotate = -180; + break; + + // Flip vertical + case 4: + scaleY = -1; + break; + + // Flip vertical and rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // Rotate right 90° + case 6: + rotate = 90; + break; + + // Flip horizontal and rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // Rotate left 90° + case 8: + rotate = -90; + break; + + default: } - return 'data:image/jpeg;base64,' + btoa(base64); + return { + rotate: rotate, + scaleX: scaleX, + scaleY: scaleY + }; } var render = { render: function render() { - var self = this; - - self.initContainer(); - self.initCanvas(); - self.initCropBox(); + this.initContainer(); + this.initCanvas(); + this.initCropBox(); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } }, initContainer: function initContainer() { - var self = this; - var options = self.options; - var element = self.element; - var container = self.container; - var cropper = self.cropper; - var hidden = 'cropper-hidden'; + var element = this.element, + options = this.options, + container = this.container, + cropper = this.cropper; + - addClass(cropper, hidden); - removeClass(element, hidden); + addClass(cropper, CLASS_HIDDEN); + removeClass(element, CLASS_HIDDEN); var containerData = { width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200), height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100) }; - self.containerData = containerData; + this.containerData = containerData; setStyle(cropper, { width: containerData.width, height: containerData.height }); - addClass(element, hidden); - removeClass(cropper, hidden); + addClass(element, CLASS_HIDDEN); + removeClass(cropper, CLASS_HIDDEN); }, // Canvas (image wrapper) initCanvas: function initCanvas() { - var self = this; - var viewMode = self.options.viewMode; - var containerData = self.containerData; - var imageData = self.imageData; + var containerData = this.containerData, + imageData = this.imageData; + var viewMode = this.options.viewMode; + var rotated = Math.abs(imageData.rotate) % 180 === 90; var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth; var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight; @@ -853,9 +1203,9 @@ var render = { } var canvasData = { + aspectRatio: aspectRatio, naturalWidth: naturalWidth, naturalHeight: naturalHeight, - aspectRatio: aspectRatio, width: canvasWidth, height: canvasHeight }; @@ -865,21 +1215,21 @@ var render = { canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - self.canvasData = canvasData; - self.limited = viewMode === 1 || viewMode === 2; - self.limitCanvas(true, true); - self.initialImageData = extend({}, imageData); - self.initialCanvasData = extend({}, canvasData); + this.canvasData = canvasData; + this.limited = viewMode === 1 || viewMode === 2; + this.limitCanvas(true, true); + this.initialImageData = extend({}, imageData); + this.initialCanvasData = extend({}, canvasData); }, limitCanvas: function limitCanvas(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; var viewMode = options.viewMode; - var containerData = self.containerData; - var canvasData = self.canvasData; var aspectRatio = canvasData.aspectRatio; - var cropBoxData = self.cropBoxData; - var cropped = self.cropped && cropBoxData; + + var cropped = this.cropped && cropBoxData; if (sizeLimited) { var minCanvasWidth = Number(options.minCanvasWidth) || 0; @@ -913,17 +1263,15 @@ var render = { } } - if (minCanvasWidth && minCanvasHeight) { - if (minCanvasHeight * aspectRatio > minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else { - minCanvasWidth = minCanvasHeight * aspectRatio; - } - } else if (minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else if (minCanvasHeight) { - minCanvasWidth = minCanvasHeight * aspectRatio; - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minCanvasWidth, + height: minCanvasHeight + }); + + minCanvasWidth = _getContainSizes.width; + minCanvasHeight = _getContainSizes.height; + canvasData.minWidth = minCanvasWidth; canvasData.minHeight = minCanvasHeight; @@ -941,7 +1289,7 @@ var render = { canvasData.maxLeft = Math.max(0, newCanvasLeft); canvasData.maxTop = Math.max(0, newCanvasTop); - if (cropped && self.limited) { + if (cropped && this.limited) { canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width)); canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height)); canvasData.maxLeft = cropBoxData.left; @@ -967,47 +1315,31 @@ var render = { } } }, - renderCanvas: function renderCanvas(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var rotate = imageData.rotate; - - if (self.rotated) { - self.rotated = false; - - // Computes rotated sizes with image sizes - var rotatedData = getRotatedSizes({ - width: imageData.width, - height: imageData.height, - degree: rotate - }); - var aspectRatio = rotatedData.width / rotatedData.height; - var isSquareImage = imageData.aspectRatio === 1; - - if (isSquareImage || aspectRatio !== canvasData.aspectRatio) { - canvasData.left -= (rotatedData.width - canvasData.width) / 2; - canvasData.top -= (rotatedData.height - canvasData.height) / 2; - canvasData.width = rotatedData.width; - canvasData.height = rotatedData.height; - canvasData.aspectRatio = aspectRatio; - canvasData.naturalWidth = imageData.naturalWidth; - canvasData.naturalHeight = imageData.naturalHeight; - - // Computes rotated sizes with natural image sizes - if (isSquareImage && rotate % 90 || rotate % 180) { - var rotatedData2 = getRotatedSizes({ - width: imageData.naturalWidth, - height: imageData.naturalHeight, - degree: rotate - }); + renderCanvas: function renderCanvas(changed, transformed) { + var canvasData = this.canvasData, + imageData = this.imageData; - canvasData.naturalWidth = rotatedData2.width; - canvasData.naturalHeight = rotatedData2.height; - } - self.limitCanvas(true, false); - } + if (transformed) { + var _getRotatedSizes = getRotatedSizes({ + width: imageData.naturalWidth * Math.abs(imageData.scaleX), + height: imageData.naturalHeight * Math.abs(imageData.scaleY), + degree: imageData.rotate + }), + naturalWidth = _getRotatedSizes.width, + naturalHeight = _getRotatedSizes.height; + + var width = canvasData.width * (naturalWidth / canvasData.naturalWidth); + var height = canvasData.height * (naturalHeight / canvasData.naturalHeight); + + canvasData.left -= (width - canvasData.width) / 2; + canvasData.top -= (height - canvasData.height) / 2; + canvasData.width = width; + canvasData.height = height; + canvasData.aspectRatio = naturalWidth / naturalHeight; + canvasData.naturalWidth = naturalWidth; + canvasData.naturalHeight = naturalHeight; + this.limitCanvas(true, false); } if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) { @@ -1021,14 +1353,14 @@ var render = { canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); - self.limitCanvas(false, true); + this.limitCanvas(false, true); canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft); canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop); canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - setStyle(self.canvas, extend({ + setStyle(this.canvas, extend({ width: canvasData.width, height: canvasData.height }, getTransforms({ @@ -1036,52 +1368,26 @@ var render = { translateY: canvasData.top }))); - self.renderImage(); + this.renderImage(changed); - if (self.cropped && self.limited) { - self.limitCropBox(true, true); - } - - if (changed) { - self.output(); + if (this.cropped && this.limited) { + this.limitCropBox(true, true); } }, renderImage: function renderImage(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var newImageData = void 0; - var reversedData = void 0; - var reversedWidth = void 0; - var reversedHeight = void 0; - - if (imageData.rotate) { - reversedData = getRotatedSizes({ - width: canvasData.width, - height: canvasData.height, - degree: imageData.rotate, - aspectRatio: imageData.aspectRatio - }, true); - - reversedWidth = reversedData.width; - reversedHeight = reversedData.height; - - newImageData = { - width: reversedWidth, - height: reversedHeight, - left: (canvasData.width - reversedWidth) / 2, - top: (canvasData.height - reversedHeight) / 2 - }; - } + var canvasData = this.canvasData, + imageData = this.imageData; - extend(imageData, newImageData || { - width: canvasData.width, - height: canvasData.height, - left: 0, - top: 0 - }); + var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth); + var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight); - setStyle(self.image, extend({ + extend(imageData, { + width: width, + height: height, + left: (canvasData.width - width) / 2, + top: (canvasData.height - height) / 2 + }); + setStyle(this.image, extend({ width: imageData.width, height: imageData.height }, getTransforms(extend({ @@ -1090,15 +1396,15 @@ var render = { }, imageData)))); if (changed) { - self.output(); + this.output(); } }, initCropBox: function initCropBox() { - var self = this; - var options = self.options; + var options = this.options, + canvasData = this.canvasData; var aspectRatio = options.aspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; - var canvasData = self.canvasData; var cropBoxData = { width: canvasData.width, height: canvasData.height @@ -1112,8 +1418,8 @@ var render = { } } - self.cropBoxData = cropBoxData; - self.limitCropBox(true, true); + this.cropBoxData = cropBoxData; + this.limitCropBox(true, true); // Initialize auto crop area cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); @@ -1127,16 +1433,16 @@ var render = { cropBoxData.oldLeft = cropBoxData.left; cropBoxData.oldTop = cropBoxData.top; - self.initialCropBoxData = extend({}, cropBoxData); + this.initialCropBoxData = extend({}, cropBoxData); }, limitCropBox: function limitCropBox(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData, + limited = this.limited; var aspectRatio = options.aspectRatio; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var limited = self.limited; + if (sizeLimited) { var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; @@ -1144,7 +1450,7 @@ var render = { var maxCropBoxWidth = Math.min(containerData.width, limited ? canvasData.width : containerData.width); var maxCropBoxHeight = Math.min(containerData.height, limited ? canvasData.height : containerData.height); - // The min/maxCropBoxWidth/Height must be less than containerWidth/Height + // The min/maxCropBoxWidth/Height must be less than container's width/height minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width); minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height); @@ -1190,10 +1496,10 @@ var render = { } }, renderCropBox: function renderCropBox() { - var self = this; - var options = self.options; - var containerData = self.containerData; - var cropBoxData = self.cropBoxData; + var options = this.options, + containerData = this.containerData, + cropBoxData = this.cropBoxData; + if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) { cropBoxData.left = cropBoxData.oldLeft; @@ -1206,7 +1512,7 @@ var render = { cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); - self.limitCropBox(false, true); + this.limitCropBox(false, true); cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft); cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop); @@ -1215,10 +1521,10 @@ var render = { if (options.movable && options.cropBoxMovable) { // Turn to move the canvas when the crop box is equal to the container - setData(self.face, 'action', cropBoxData.width === containerData.width && cropBoxData.height === containerData.height ? 'move' : 'all'); + setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL); } - setStyle(self.cropBox, extend({ + setStyle(this.cropBox, extend({ width: cropBoxData.width, height: cropBoxData.height }, getTransforms({ @@ -1226,42 +1532,38 @@ var render = { translateY: cropBoxData.top }))); - if (self.cropped && self.limited) { - self.limitCanvas(true, true); + if (this.cropped && this.limited) { + this.limitCanvas(true, true); } - if (!self.disabled) { - self.output(); + if (!this.disabled) { + this.output(); } }, output: function output() { - var self = this; - - self.preview(); + this.preview(); - if (self.complete) { - dispatchEvent(self.element, 'crop', self.getData()); + if (this.complete) { + dispatchEvent(this.element, EVENT_CROP, this.getData()); } } }; -var DATA_PREVIEW = 'preview'; - var preview = { initPreview: function initPreview() { - var self = this; - var preview = self.options.preview; - var image = createElement('img'); - var crossOrigin = self.crossOrigin; - var url = crossOrigin ? self.crossOriginUrl : self.url; + var crossOrigin = this.crossOrigin; + var preview = this.options.preview; + + var url = crossOrigin ? this.crossOriginUrl : this.url; + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; } image.src = url; - appendChild(self.viewBox, image); - self.image2 = image; + this.viewBox.appendChild(image); + this.image2 = image; if (!preview) { return; @@ -1269,10 +1571,10 @@ var preview = { var previews = preview.querySelector ? [preview] : document.querySelectorAll(preview); - self.previews = previews; + this.previews = previews; each(previews, function (element) { - var img = createElement('img'); + var img = document.createElement('img'); // Save the original size for recover setData(element, DATA_PREVIEW, { @@ -1297,7 +1599,7 @@ var preview = { 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;"'; empty(element); - appendChild(element, img); + element.appendChild(img); }); }, resetPreview: function resetPreview() { @@ -1314,22 +1616,22 @@ var preview = { }); }, preview: function preview() { - var self = this; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var cropBoxWidth = cropBoxData.width; - var cropBoxHeight = cropBoxData.height; - var width = imageData.width; - var height = imageData.height; + var imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var cropBoxWidth = cropBoxData.width, + cropBoxHeight = cropBoxData.height; + var width = imageData.width, + height = imageData.height; + var left = cropBoxData.left - canvasData.left - imageData.left; var top = cropBoxData.top - canvasData.top - imageData.top; - if (!self.cropped || self.disabled) { + if (!this.cropped || this.disabled) { return; } - setStyle(self.image2, extend({ + setStyle(this.image2, extend({ width: width, height: height }, getTransforms(extend({ @@ -1337,7 +1639,7 @@ var preview = { translateY: -top }, imageData)))); - each(self.previews, function (element) { + each(this.previews, function (element) { var data = getData(element, DATA_PREVIEW); var originalWidth = data.width; var originalHeight = data.height; @@ -1361,39 +1663,23 @@ var preview = { height: newHeight }); - setStyle(getByTag(element, 'img')[0], extend({ + setStyle(element.getElementsByTagName('img')[0], extend({ width: width * ratio, height: height * ratio }, getTransforms(extend({ translateX: -left * ratio, translateY: -top * ratio - }, imageData)))); - }); - } -}; - -// Globals -var PointerEvent = typeof window !== 'undefined' ? window.PointerEvent : null; - -// Events -var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; -var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; -var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; -var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; -var EVENT_DBLCLICK = 'dblclick'; -var EVENT_RESIZE = 'resize'; -var EVENT_CROP_START = 'cropstart'; -var EVENT_CROP_MOVE = 'cropmove'; -var EVENT_CROP_END = 'cropend'; -var EVENT_CROP$1 = 'crop'; -var EVENT_ZOOM = 'zoom'; + }, imageData)))); + }); + } +}; var events = { bind: function bind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { addListener(element, EVENT_CROP_START, options.cropstart); @@ -1408,35 +1694,35 @@ var events = { } if (isFunction(options.crop)) { - addListener(element, EVENT_CROP$1, options.crop); + addListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { addListener(element, EVENT_ZOOM, options.zoom); } - addListener(cropper, EVENT_POINTER_DOWN, self.onCropStart = proxy(self.cropStart, self)); + addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = proxy(this.cropStart, this)); if (options.zoomable && options.zoomOnWheel) { - addListener(cropper, EVENT_WHEEL, self.onWheel = proxy(self.wheel, self)); + addListener(cropper, EVENT_WHEEL, this.onWheel = proxy(this.wheel, this)); } if (options.toggleDragModeOnDblclick) { - addListener(cropper, EVENT_DBLCLICK, self.onDblclick = proxy(self.dblclick, self)); + addListener(cropper, EVENT_DBLCLICK, this.onDblclick = proxy(this.dblclick, this)); } - addListener(document, EVENT_POINTER_MOVE, self.onCropMove = proxy(self.cropMove, self)); - addListener(document, EVENT_POINTER_UP, self.onCropEnd = proxy(self.cropEnd, self)); + addListener(document, EVENT_POINTER_MOVE, this.onCropMove = proxy(this.cropMove, this)); + addListener(document, EVENT_POINTER_UP, this.onCropEnd = proxy(this.cropEnd, this)); if (options.responsive) { - addListener(window, EVENT_RESIZE, self.onResize = proxy(self.resize, self)); + addListener(window, EVENT_RESIZE, this.onResize = proxy(this.resize, this)); } }, unbind: function unbind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { removeListener(element, EVENT_CROP_START, options.cropstart); @@ -1451,63 +1737,42 @@ var events = { } if (isFunction(options.crop)) { - removeListener(element, EVENT_CROP$1, options.crop); + removeListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { removeListener(element, EVENT_ZOOM, options.zoom); } - removeListener(cropper, EVENT_POINTER_DOWN, self.onCropStart); + removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart); if (options.zoomable && options.zoomOnWheel) { - removeListener(cropper, EVENT_WHEEL, self.onWheel); + removeListener(cropper, EVENT_WHEEL, this.onWheel); } if (options.toggleDragModeOnDblclick) { - removeListener(cropper, EVENT_DBLCLICK, self.onDblclick); + removeListener(cropper, EVENT_DBLCLICK, this.onDblclick); } - removeListener(document, EVENT_POINTER_MOVE, self.onCropMove); - removeListener(document, EVENT_POINTER_UP, self.onCropEnd); + removeListener(document, EVENT_POINTER_MOVE, this.onCropMove); + removeListener(document, EVENT_POINTER_UP, this.onCropEnd); if (options.responsive) { - removeListener(window, EVENT_RESIZE, self.onResize); + removeListener(window, EVENT_RESIZE, this.onResize); } } }; -var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; - -function getPointer(_ref, endOnly) { - var pageX = _ref.pageX, - pageY = _ref.pageY; - - var end = { - endX: pageX, - endY: pageY - }; - - if (endOnly) { - return end; - } - - return extend({ - startX: pageX, - startY: pageY - }, end); -} - var handlers = { resize: function resize() { - var self = this; - var options = self.options; - var container = self.container; - var containerData = self.containerData; + var options = this.options, + container = this.container, + containerData = this.containerData; + var minContainerWidth = Number(options.minContainerWidth) || 200; var minContainerHeight = Number(options.minContainerHeight) || 100; - if (self.disabled || containerData.width === minContainerWidth || containerData.height === minContainerHeight) { + if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) { return; } @@ -1519,52 +1784,50 @@ var handlers = { var cropBoxData = void 0; if (options.restore) { - canvasData = self.getCanvasData(); - cropBoxData = self.getCropBoxData(); + canvasData = this.getCanvasData(); + cropBoxData = this.getCropBoxData(); } - self.render(); + this.render(); if (options.restore) { - self.setCanvasData(each(canvasData, function (n, i) { + this.setCanvasData(each(canvasData, function (n, i) { canvasData[i] = n * ratio; })); - self.setCropBoxData(each(cropBoxData, function (n, i) { + this.setCropBoxData(each(cropBoxData, function (n, i) { cropBoxData[i] = n * ratio; })); } } }, dblclick: function dblclick() { - var self = this; - - if (self.disabled || self.options.dragMode === 'none') { + if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) { return; } - self.setDragMode(hasClass(self.dragBox, 'cropper-crop') ? 'move' : 'crop'); + this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP); }, - wheel: function wheel(event) { - var self = this; - var e = getEvent(event); - var ratio = Number(self.options.wheelZoomRatio) || 0.1; + wheel: function wheel(e) { + var _this = this; + + var ratio = Number(this.options.wheelZoomRatio) || 0.1; var delta = 1; - if (self.disabled) { + if (this.disabled) { return; } e.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21) - if (self.wheeling) { + if (this.wheeling) { return; } - self.wheeling = true; + this.wheeling = true; setTimeout(function () { - self.wheeling = false; + _this.wheeling = false; }, 50); if (e.deltaY) { @@ -1575,18 +1838,16 @@ var handlers = { delta = e.detail > 0 ? 1 : -1; } - self.zoom(-delta * ratio, e); + this.zoom(-delta * ratio, e); }, - cropStart: function cropStart(event) { - var self = this; - - if (self.disabled) { + cropStart: function cropStart(e) { + if (this.disabled) { return; } - var options = self.options; - var pointers = self.pointers; - var e = getEvent(event); + var options = this.options, + pointers = this.pointers; + var action = void 0; if (e.changedTouches) { @@ -1600,16 +1861,16 @@ var handlers = { } if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { - action = 'zoom'; + action = ACTION_ZOOM; } else { - action = getData(e.target, 'action'); + action = getData(e.target, DATA_ACTION); } if (!REGEXP_ACTIONS.test(action)) { return; } - if (dispatchEvent(self.element, 'cropstart', { + if (dispatchEvent(this.element, EVENT_CROP_START, { originalEvent: e, action: action }) === false) { @@ -1618,28 +1879,28 @@ var handlers = { e.preventDefault(); - self.action = action; - self.cropping = false; + this.action = action; + this.cropping = false; - if (action === 'crop') { - self.cropping = true; - addClass(self.dragBox, 'cropper-modal'); + if (action === ACTION_CROP) { + this.cropping = true; + addClass(this.dragBox, CLASS_MODAL); } }, - cropMove: function cropMove(event) { - var self = this; - var action = self.action; + cropMove: function cropMove(e) { + var action = this.action; + - if (self.disabled || !action) { + if (this.disabled || !action) { return; } - var pointers = self.pointers; - var e = getEvent(event); + var pointers = this.pointers; + e.preventDefault(); - if (dispatchEvent(self.element, 'cropmove', { + if (dispatchEvent(this.element, EVENT_CROP_MOVE, { originalEvent: e, action: action }) === false) { @@ -1654,18 +1915,16 @@ var handlers = { extend(pointers[e.pointerId || 0], getPointer(e, true)); } - self.change(e); + this.change(e); }, - cropEnd: function cropEnd(event) { - var self = this; - - if (self.disabled) { + cropEnd: function cropEnd(e) { + if (this.disabled) { return; } - var action = self.action; - var pointers = self.pointers; - var e = getEvent(event); + var action = this.action, + pointers = this.pointers; + if (e.changedTouches) { each(e.changedTouches, function (touch) { @@ -1682,71 +1941,35 @@ var handlers = { e.preventDefault(); if (!Object.keys(pointers).length) { - self.action = ''; + this.action = ''; } - if (self.cropping) { - self.cropping = false; - toggleClass(self.dragBox, 'cropper-modal', self.cropped && this.options.modal); + if (this.cropping) { + this.cropping = false; + toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal); } - dispatchEvent(self.element, 'cropend', { + dispatchEvent(this.element, EVENT_CROP_END, { originalEvent: e, action: action }); } }; -// Actions -var ACTION_EAST = 'e'; -var ACTION_WEST = 'w'; -var ACTION_SOUTH = 's'; -var ACTION_NORTH = 'n'; -var ACTION_SOUTH_EAST = 'se'; -var ACTION_SOUTH_WEST = 'sw'; -var ACTION_NORTH_EAST = 'ne'; -var ACTION_NORTH_WEST = 'nw'; - -function getMaxZoomRatio(pointers) { - var pointers2 = extend({}, pointers); - var ratios = []; - - each(pointers, function (pointer, pointerId) { - delete pointers2[pointerId]; - - each(pointers2, function (pointer2) { - var x1 = Math.abs(pointer.startX - pointer2.startX); - var y1 = Math.abs(pointer.startY - pointer2.startY); - var x2 = Math.abs(pointer.endX - pointer2.endX); - var y2 = Math.abs(pointer.endY - pointer2.endY); - var z1 = Math.sqrt(x1 * x1 + y1 * y1); - var z2 = Math.sqrt(x2 * x2 + y2 * y2); - var ratio = (z2 - z1) / z1; - - ratios.push(ratio); - }); - }); - - ratios.sort(function (a, b) { - return Math.abs(a) < Math.abs(b); - }); - - return ratios[0]; -} - var change = { change: function change(e) { - var self = this; - var options = self.options; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; + var options = this.options, + canvasData = this.canvasData, + containerData = this.containerData, + cropBoxData = this.cropBoxData, + pointers = this.pointers; + var action = this.action; var aspectRatio = options.aspectRatio; - var action = self.action; - var width = cropBoxData.width; - var height = cropBoxData.height; - var left = cropBoxData.left; - var top = cropBoxData.top; + var left = cropBoxData.left, + top = cropBoxData.top, + width = cropBoxData.width, + height = cropBoxData.height; + var right = left + width; var bottom = top + height; var minLeft = 0; @@ -1761,23 +1984,56 @@ var change = { aspectRatio = width && height ? width / height : 1; } - if (self.limited) { + if (this.limited) { minLeft = cropBoxData.minLeft; minTop = cropBoxData.minTop; + maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width); maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height); } - var pointers = self.pointers; var pointer = pointers[Object.keys(pointers)[0]]; var range = { x: pointer.endX - pointer.startX, y: pointer.endY - pointer.startY }; + var check = function check(side) { + switch (side) { + case ACTION_EAST: + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + + break; + + case ACTION_WEST: + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + + break; + + case ACTION_NORTH: + if (top + range.y < minTop) { + range.y = minTop - top; + } + + break; + + case ACTION_SOUTH: + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + + break; + + default: + } + }; switch (action) { // Move crop box - case 'all': + case ACTION_ALL: left += range.x; top += range.y; break; @@ -1789,10 +2045,7 @@ var change = { break; } - if (right + range.x > maxWidth) { - range.x = maxWidth - right; - } - + check(ACTION_EAST); width += range.x; if (aspectRatio) { @@ -1813,10 +2066,7 @@ var change = { break; } - if (top + range.y < minTop) { - range.y = minTop - top; - } - + check(ACTION_NORTH); height -= range.y; top += range.y; @@ -1838,10 +2088,7 @@ var change = { break; } - if (left + range.x < minLeft) { - range.x = minLeft - left; - } - + check(ACTION_WEST); width -= range.x; left += range.x; @@ -1863,10 +2110,7 @@ var change = { break; } - if (bottom + range.y > maxHeight) { - range.y = maxHeight - bottom; - } - + check(ACTION_SOUTH); height += range.y; if (aspectRatio) { @@ -1888,10 +2132,14 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -1934,11 +2182,15 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; left += range.y * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -1983,10 +2235,14 @@ var change = { break; } + check(ACTION_WEST); width -= range.x; left += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -2029,9 +2285,13 @@ var change = { break; } + check(ACTION_EAST); width += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -2066,25 +2326,25 @@ var change = { break; // Move canvas - case 'move': - self.move(range.x, range.y); + case ACTION_MOVE: + this.move(range.x, range.y); renderable = false; break; // Zoom canvas - case 'zoom': - self.zoom(getMaxZoomRatio(pointers), e); + case ACTION_ZOOM: + this.zoom(getMaxZoomRatio(pointers), e); renderable = false; break; // Create crop box - case 'crop': + case ACTION_CROP: if (!range.x || !range.y) { renderable = false; break; } - offset = getOffset(self.cropper); + offset = getOffset(this.cropper); left = pointer.startX - offset.left; top = pointer.startY - offset.top; width = cropBoxData.minWidth; @@ -2102,12 +2362,12 @@ var change = { } // Show the crop box if is hidden - if (!self.cropped) { - removeClass(self.cropBox, 'cropper-hidden'); - self.cropped = true; + if (!this.cropped) { + removeClass(this.cropBox, CLASS_HIDDEN); + this.cropped = true; - if (self.limited) { - self.limitCropBox(true, true); + if (this.limited) { + this.limitCropBox(true, true); } } @@ -2121,9 +2381,8 @@ var change = { cropBoxData.height = height; cropBoxData.left = left; cropBoxData.top = top; - self.action = action; - - self.renderCropBox(); + this.action = action; + this.renderCropBox(); } // Override @@ -2134,228 +2393,188 @@ var change = { } }; -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function getPointersCenter(pointers) { - var pageX = 0; - var pageY = 0; - var count = 0; - - each(pointers, function (_ref) { - var startX = _ref.startX, - startY = _ref.startY; - - pageX += startX; - pageY += startY; - count += 1; - }); - - pageX /= count; - pageY /= count; - - return { - pageX: pageX, - pageY: pageY - }; -} - var methods = { // Show the crop box manually crop: function crop() { - var self = this; + if (this.ready && !this.disabled) { + if (!this.cropped) { + this.cropped = true; + this.limitCropBox(true, true); - if (self.ready && !self.disabled) { - if (!self.cropped) { - self.cropped = true; - self.limitCropBox(true, true); - - if (self.options.modal) { - addClass(self.dragBox, 'cropper-modal'); + if (this.options.modal) { + addClass(this.dragBox, CLASS_MODAL); } - removeClass(self.cropBox, 'cropper-hidden'); + removeClass(this.cropBox, CLASS_HIDDEN); } - self.setCropBoxData(self.initialCropBoxData); + this.setCropBoxData(this.initialCropBoxData); } - return self; + return this; }, // Reset the image and crop box to their initial states reset: function reset() { - var self = this; - - if (self.ready && !self.disabled) { - self.imageData = extend({}, self.initialImageData); - self.canvasData = extend({}, self.initialCanvasData); - self.cropBoxData = extend({}, self.initialCropBoxData); + if (this.ready && !this.disabled) { + this.imageData = extend({}, this.initialImageData); + this.canvasData = extend({}, this.initialCanvasData); + this.cropBoxData = extend({}, this.initialCropBoxData); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } - return self; + return this; }, // Clear the crop box clear: function clear() { - var self = this; - - if (self.cropped && !self.disabled) { - extend(self.cropBoxData, { + if (this.cropped && !this.disabled) { + extend(this.cropBoxData, { left: 0, top: 0, width: 0, height: 0 }); - self.cropped = false; - self.renderCropBox(); - - self.limitCanvas(true, true); + this.cropped = false; + this.renderCropBox(); + this.limitCanvas(true, true); // Render canvas after crop box rendered - self.renderCanvas(); - - removeClass(self.dragBox, 'cropper-modal'); - addClass(self.cropBox, 'cropper-hidden'); + this.renderCanvas(); + removeClass(this.dragBox, CLASS_MODAL); + addClass(this.cropBox, CLASS_HIDDEN); } - return self; + return this; }, /** * Replace the image's src and rebuild the cropper - * - * @param {String} url - * @param {Boolean} onlyColorChanged (optional) + * @param {string} url - The new URL. + * @param {boolean} [onlyColorChanged] - Indicate if the new image only changed color. + * @returns {Object} this */ - replace: function replace(url, onlyColorChanged) { - var self = this; + replace: function replace(url) { + var onlyColorChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - if (!self.disabled && url) { - if (self.isImg) { - self.element.src = url; + if (!this.disabled && url) { + if (this.isImg) { + this.element.src = url; } if (onlyColorChanged) { - self.url = url; - self.image.src = url; + this.url = url; + this.image.src = url; - if (self.ready) { - self.image2.src = url; + if (this.ready) { + this.image2.src = url; - each(self.previews, function (element) { - getByTag(element, 'img')[0].src = url; + each(this.previews, function (element) { + element.getElementsByTagName('img')[0].src = url; }); } } else { - if (self.isImg) { - self.replaced = true; + if (this.isImg) { + this.replaced = true; } // Clear previous data - self.options.data = null; - self.load(url); + this.options.data = null; + this.load(url); } } - return self; + return this; }, // Enable (unfreeze) the cropper enable: function enable() { - var self = this; - - if (self.ready) { - self.disabled = false; - removeClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = false; + removeClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Disable (freeze) the cropper disable: function disable() { - var self = this; - - if (self.ready) { - self.disabled = true; - addClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = true; + addClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Destroy the cropper and remove the instance from the image destroy: function destroy() { - var self = this; - var element = self.element; - var image = self.image; + var element = this.element, + image = this.image; - if (self.loaded) { - if (self.isImg && self.replaced) { - element.src = self.originalUrl; + + if (this.loaded) { + if (this.isImg && this.replaced) { + element.src = this.originalUrl; } - self.unbuild(); - removeClass(element, 'cropper-hidden'); - } else if (self.isImg) { - removeListener(element, 'load', self.onStart); + this.unbuild(); + removeClass(element, CLASS_HIDDEN); + } else if (this.isImg) { + removeListener(element, EVENT_LOAD, this.onStart); } else if (image) { - removeChild(image); + image.parentNode.removeChild(image); } - removeData(element, 'cropper'); + removeData(element, NAMESPACE); - return self; + return this; }, /** * Move the canvas with relative offsets - * - * @param {Number} offsetX - * @param {Number} offsetY (optional) + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} offsetY - The relative offset distance on the y-axis. + * @returns {Object} this */ move: function move(offsetX, offsetY) { - var self = this; - var canvasData = self.canvasData; + var _canvasData = this.canvasData, + left = _canvasData.left, + top = _canvasData.top; + - return self.moveTo(isUndefined(offsetX) ? offsetX : canvasData.left + Number(offsetX), isUndefined(offsetY) ? offsetY : canvasData.top + Number(offsetY)); + return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY)); }, /** * Move the canvas to an absolute point - * - * @param {Number} x - * @param {Number} y (optional) + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Object} this */ - moveTo: function moveTo(x, y) { - var self = this; - var canvasData = self.canvasData; - var changed = false; + moveTo: function moveTo(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var canvasData = this.canvasData; - // If "y" is not present, its default value is "x" - if (isUndefined(y)) { - y = x; - } + var changed = false; x = Number(x); y = Number(y); - if (self.ready && !self.disabled && self.options.movable) { + if (this.ready && !this.disabled && this.options.movable) { if (isNumber(x)) { canvasData.left = x; changed = true; @@ -2367,23 +2586,23 @@ var methods = { } if (changed) { - self.renderCanvas(true); + this.renderCanvas(true); } } - return self; + return this; }, /** * Zoom the canvas with a relative ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoom: function zoom(ratio, _originalEvent) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + ratio = Number(ratio); @@ -2393,42 +2612,43 @@ var methods = { ratio = 1 + ratio; } - return self.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); + return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); }, /** * Zoom the canvas to an absolute ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoomTo: function zoomTo(ratio, _originalEvent) { - var self = this; - var options = self.options; - var canvasData = self.canvasData; - var width = canvasData.width; - var height = canvasData.height; - var naturalWidth = canvasData.naturalWidth; - var naturalHeight = canvasData.naturalHeight; + var options = this.options, + canvasData = this.canvasData; + var width = canvasData.width, + height = canvasData.height, + naturalWidth = canvasData.naturalWidth, + naturalHeight = canvasData.naturalHeight; + ratio = Number(ratio); - if (ratio >= 0 && self.ready && !self.disabled && options.zoomable) { + if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) { var newWidth = naturalWidth * ratio; var newHeight = naturalHeight * ratio; - if (dispatchEvent(self.element, 'zoom', { + if (dispatchEvent(this.element, EVENT_ZOOM, { originalEvent: _originalEvent, oldRatio: width / naturalWidth, ratio: newWidth / naturalWidth }) === false) { - return self; + return this; } if (_originalEvent) { - var pointers = self.pointers; - var offset = getOffset(self.cropper); + var pointers = this.pointers; + + var offset = getOffset(this.cropper); var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : { pageX: _originalEvent.pageX, pageY: _originalEvent.pageY @@ -2445,128 +2665,116 @@ var methods = { canvasData.width = newWidth; canvasData.height = newHeight; - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** * Rotate the canvas with a relative degree - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotate: function rotate(degree) { - var self = this; - - return self.rotateTo((self.imageData.rotate || 0) + Number(degree)); + return this.rotateTo((this.imageData.rotate || 0) + Number(degree)); }, /** * Rotate the canvas to an absolute degree - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate() - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotateTo: function rotateTo(degree) { - var self = this; - degree = Number(degree); - if (isNumber(degree) && self.ready && !self.disabled && self.options.rotatable) { - self.imageData.rotate = degree % 360; - self.rotated = true; - self.renderCanvas(true); + if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) { + this.imageData.rotate = degree % 360; + this.renderCanvas(true, true); } - return self; + return this; + }, + + + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Object} this + */ + scaleX: function scaleX(_scaleX) { + var scaleY = this.imageData.scaleY; + + + return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + + + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Object} this + */ + scaleY: function scaleY(_scaleY) { + var scaleX = this.imageData.scaleX; + + + return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); }, /** * Scale the image - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale() - * - * @param {Number} scaleX - * @param {Number} scaleY (optional) + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Object} this */ - scale: function scale(scaleX, scaleY) { - var self = this; - var imageData = self.imageData; - var changed = false; + scale: function scale(scaleX) { + var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX; + var imageData = this.imageData; - // If "scaleY" is not present, its default value is "scaleX" - if (isUndefined(scaleY)) { - scaleY = scaleX; - } + var transformed = false; scaleX = Number(scaleX); scaleY = Number(scaleY); - if (self.ready && !self.disabled && self.options.scalable) { + if (this.ready && !this.disabled && this.options.scalable) { if (isNumber(scaleX)) { imageData.scaleX = scaleX; - changed = true; + transformed = true; } if (isNumber(scaleY)) { imageData.scaleY = scaleY; - changed = true; + transformed = true; } - if (changed) { - self.renderImage(true); + if (transformed) { + this.renderCanvas(true, true); } } - return self; - }, - - - /** - * Scale the abscissa of the image - * - * @param {Number} scaleX - */ - scaleX: function scaleX(_scaleX) { - var self = this; - var scaleY = self.imageData.scaleY; - - return self.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); - }, - - - /** - * Scale the ordinate of the image - * - * @param {Number} scaleY - */ - scaleY: function scaleY(_scaleY) { - var self = this; - var scaleX = self.imageData.scaleX; - - return self.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + return this; }, /** * Get the cropped area position and size data (base on the original image) - * - * @param {Boolean} rounded (optional) - * @return {Object} data + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. */ - getData: function getData$$1(rounded) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var ratio = void 0; + getData: function getData$$1() { + var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { x: cropBoxData.left - canvasData.left, y: cropBoxData.top - canvasData.top, @@ -2574,7 +2782,7 @@ var methods = { height: cropBoxData.height }; - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; each(data, function (n, i) { n /= ratio; @@ -2604,51 +2812,47 @@ var methods = { /** * Set the cropped area position and size with new data - * - * @param {Object} data + * @param {Object} data - The new data. + * @returns {Object} this */ setData: function setData$$1(data) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData; + var cropBoxData = {}; - var rotated = void 0; - var scaled = void 0; - var ratio = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { + var transformed = false; + if (options.rotatable) { if (isNumber(data.rotate) && data.rotate !== imageData.rotate) { imageData.rotate = data.rotate; - rotated = true; - self.rotated = rotated; + transformed = true; } } if (options.scalable) { if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) { imageData.scaleX = data.scaleX; - scaled = true; + transformed = true; } if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) { imageData.scaleY = data.scaleY; - scaled = true; + transformed = true; } } - if (rotated) { - self.renderCanvas(); - } else if (scaled) { - self.renderImage(); + if (transformed) { + this.renderCanvas(true, true); } - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; if (isNumber(data.x)) { cropBoxData.left = data.x * ratio + canvasData.left; @@ -2666,48 +2870,41 @@ var methods = { cropBoxData.height = data.height * ratio; } - self.setCropBoxData(cropBoxData); + this.setCropBoxData(cropBoxData); } - return self; + return this; }, /** - * Get the container size data - * - * @return {Object} data + * Get the container size data. + * @returns {Object} The result container data. */ getContainerData: function getContainerData() { - var self = this; - - return self.ready ? self.containerData : {}; + return this.ready ? extend({}, this.containerData) : {}; }, /** - * Get the image position and size data - * - * @return {Object} data + * Get the image position and size data. + * @returns {Object} The result image data. */ getImageData: function getImageData() { - var self = this; - - return self.loaded ? self.imageData : {}; + return this.loaded ? extend({}, this.imageData) : {}; }, /** - * Get the canvas position and size data - * - * @return {Object} data + * Get the canvas position and size data. + * @returns {Object} The result canvas data. */ getCanvasData: function getCanvasData() { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + var data = {}; - if (self.ready) { + if (this.ready) { each(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) { data[n] = canvasData[n]; }); @@ -2718,20 +2915,20 @@ var methods = { /** - * Set the canvas position and size with new data - * - * @param {Object} data + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Object} this */ setCanvasData: function setCanvasData(data) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; var aspectRatio = canvasData.aspectRatio; + if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { canvasData.left = data.left; } @@ -2748,24 +2945,23 @@ var methods = { canvasData.width = data.height * aspectRatio; } - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** - * Get the crop box position and size data - * - * @return {Object} data + * Get the crop box position and size data. + * @returns {Object} The result crop box data. */ getCropBoxData: function getCropBoxData() { - var self = this; - var cropBoxData = self.cropBoxData; + var cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { left: cropBoxData.left, top: cropBoxData.top, @@ -2779,22 +2975,22 @@ var methods = { /** - * Set the crop box position and size with new data - * - * @param {Object} data + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Object} this */ setCropBoxData: function setCropBoxData(data) { - var self = this; - var cropBoxData = self.cropBoxData; - var aspectRatio = self.options.aspectRatio; + var cropBoxData = this.cropBoxData; + var aspectRatio = this.options.aspectRatio; + var widthChanged = void 0; var heightChanged = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && self.cropped && !self.disabled && isPlainObject(data)) { + if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { cropBoxData.left = data.left; } @@ -2821,210 +3017,204 @@ var methods = { } } - self.renderCropBox(); + this.renderCropBox(); } - return self; + return this; }, /** - * Get a canvas drawn the cropped image - * - * @param {Object} options (optional) - * @return {HTMLCanvasElement} canvas + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. */ - getCroppedCanvas: function getCroppedCanvas(options) { - var self = this; + getCroppedCanvas: function getCroppedCanvas() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - if (!self.ready || !window.HTMLCanvasElement) { + if (!this.ready || !window.HTMLCanvasElement) { return null; } - if (!isPlainObject(options)) { - options = {}; - } + var canvasData = this.canvasData; + + var source = getSourceCanvas(this.image, this.imageData, canvasData, options); - // Return the whole canvas if not cropped - if (!self.cropped) { - return getSourceCanvas(self.image, self.imageData, options); + // Returns the source canvas if it is not cropped. + if (!this.cropped) { + return source; } - var data = self.getData(); - var originalWidth = data.width; - var originalHeight = data.height; - var aspectRatio = originalWidth / originalHeight; - var scaledWidth = void 0; - var scaledHeight = void 0; - var scaledRatio = void 0; + var _getData = this.getData(), + x = _getData.x, + y = _getData.y, + initialWidth = _getData.width, + initialHeight = _getData.height; - if (isPlainObject(options)) { - scaledWidth = options.width; - scaledHeight = options.height; + var aspectRatio = initialWidth / initialHeight; + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.maxWidth || Infinity, + height: options.maxHeight || Infinity + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.minWidth || 0, + height: options.minHeight || 0 + }); - if (scaledWidth) { - scaledHeight = scaledWidth / aspectRatio; - scaledRatio = scaledWidth / originalWidth; - } else if (scaledHeight) { - scaledWidth = scaledHeight * aspectRatio; - scaledRatio = scaledHeight / originalHeight; - } - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.width || initialWidth, + height: options.height || initialHeight + }), + width = _getContainSizes.width, + height = _getContainSizes.height; - // The canvas element will use `Math.floor` on a float number, so floor first - var canvasWidth = Math.floor(scaledWidth || originalWidth); - var canvasHeight = Math.floor(scaledHeight || originalHeight); + width = Math.min(maxSizes.width, Math.max(minSizes.width, width)); + height = Math.min(maxSizes.height, Math.max(minSizes.height, height)); - var canvas = createElement('canvas'); + var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + canvas.width = width; + canvas.height = height; + + context.fillStyle = options.fillColor || 'transparent'; + context.fillRect(0, 0, width, height); - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); + var _options$imageSmoothi = options.imageSmoothingEnabled, + imageSmoothingEnabled = _options$imageSmoothi === undefined ? true : _options$imageSmoothi, + imageSmoothingQuality = options.imageSmoothingQuality; + + + context.imageSmoothingEnabled = imageSmoothingEnabled; + + if (imageSmoothingQuality) { + context.imageSmoothingQuality = imageSmoothingQuality; } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage - var parameters = function () { - var source = getSourceCanvas(self.image, self.imageData, options); - var sourceWidth = source.width; - var sourceHeight = source.height; - var canvasData = self.canvasData; - var params = [source]; - - // Source canvas - var srcX = data.x + canvasData.naturalWidth * (Math.abs(data.scaleX || 1) - 1) / 2; - var srcY = data.y + canvasData.naturalHeight * (Math.abs(data.scaleY || 1) - 1) / 2; - var srcWidth = void 0; - var srcHeight = void 0; - - // Destination canvas - var dstX = void 0; - var dstY = void 0; - var dstWidth = void 0; - var dstHeight = void 0; - - if (srcX <= -originalWidth || srcX > sourceWidth) { - srcX = 0; - srcWidth = 0; - dstX = 0; - dstWidth = 0; - } else if (srcX <= 0) { - dstX = -srcX; - srcX = 0; - srcWidth = Math.min(sourceWidth, originalWidth + srcX); - dstWidth = srcWidth; - } else if (srcX <= sourceWidth) { - dstX = 0; - srcWidth = Math.min(originalWidth, sourceWidth - srcX); - dstWidth = srcWidth; - } - - if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) { - srcY = 0; - srcHeight = 0; - dstY = 0; - dstHeight = 0; - } else if (srcY <= 0) { - dstY = -srcY; - srcY = 0; - srcHeight = Math.min(sourceHeight, originalHeight + srcY); - dstHeight = srcHeight; - } else if (srcY <= sourceHeight) { - dstY = 0; - srcHeight = Math.min(originalHeight, sourceHeight - srcY); - dstHeight = srcHeight; - } - - params.push(Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)); - - // Scale destination sizes - if (scaledRatio) { - dstX *= scaledRatio; - dstY *= scaledRatio; - dstWidth *= scaledRatio; - dstHeight *= scaledRatio; - } - - // Avoid "IndexSizeError" in IE and Firefox - if (dstWidth > 0 && dstHeight > 0) { - params.push(Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); - } - - return params; - }(); - - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; - - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; - } - - context.drawImage.apply(context, _toConsumableArray(parameters)); + var sourceWidth = source.width; + var sourceHeight = source.height; + + // Source canvas parameters + var srcX = x; + var srcY = y; + var srcWidth = void 0; + var srcHeight = void 0; + + // Destination canvas parameters + var dstX = void 0; + var dstY = void 0; + var dstWidth = void 0; + var dstHeight = void 0; + + if (srcX <= -initialWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + srcWidth = Math.min(sourceWidth, initialWidth + srcX); + dstWidth = srcWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + srcWidth = Math.min(initialWidth, sourceWidth - srcX); + dstWidth = srcWidth; + } + + if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + srcHeight = Math.min(sourceHeight, initialHeight + srcY); + dstHeight = srcHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + srcHeight = Math.min(initialHeight, sourceHeight - srcY); + dstHeight = srcHeight; + } + + // All the numerical parameters should be integer for `drawImage` + // https://github.com/fengyuanchen/cropper/issues/476 + var params = [Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)]; + + // Avoid "IndexSizeError" + if (dstWidth > 0 && dstHeight > 0) { + var scale = width / initialWidth; + + params.push(Math.floor(dstX * scale), Math.floor(dstY * scale), Math.floor(dstWidth * scale), Math.floor(dstHeight * scale)); + } + + context.drawImage.apply(context, [source].concat(params)); return canvas; }, /** - * Change the aspect ratio of the crop box - * - * @param {Number} aspectRatio + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Object} this */ setAspectRatio: function setAspectRatio(aspectRatio) { - var self = this; - var options = self.options; + var options = this.options; + - if (!self.disabled && !isUndefined(aspectRatio)) { + if (!this.disabled && !isUndefined(aspectRatio)) { // 0 -> NaN options.aspectRatio = Math.max(0, aspectRatio) || NaN; - if (self.ready) { - self.initCropBox(); + if (this.ready) { + this.initCropBox(); - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } } - return self; + return this; }, /** - * Change the drag mode - * - * @param {String} mode (optional) + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Object} this */ setDragMode: function setDragMode(mode) { - var self = this; - var options = self.options; - var dragBox = self.dragBox; - var face = self.face; - var croppable = void 0; - var movable = void 0; - - if (self.loaded && !self.disabled) { - croppable = mode === 'crop'; - movable = options.movable && mode === 'move'; - mode = croppable || movable ? mode : 'none'; - - setData(dragBox, 'action', mode); - toggleClass(dragBox, 'cropper-crop', croppable); - toggleClass(dragBox, 'cropper-move', movable); + var options = this.options, + dragBox = this.dragBox, + face = this.face; + + + if (this.loaded && !this.disabled) { + var croppable = mode === DRAG_MODE_CROP; + var movable = options.movable && mode === DRAG_MODE_MOVE; + + mode = croppable || movable ? mode : DRAG_MODE_NONE; + + setData(dragBox, DATA_ACTION, mode); + toggleClass(dragBox, CLASS_CROP, croppable); + toggleClass(dragBox, CLASS_MOVE, movable); if (!options.cropBoxMovable) { // Sync drag mode to crop box when it is not movable - setData(face, 'action', mode); - toggleClass(face, 'cropper-crop', croppable); - toggleClass(face, 'cropper-move', movable); + setData(face, DATA_ACTION, mode); + toggleClass(face, CLASS_CROP, croppable); + toggleClass(face, CLASS_MOVE, movable); } } - return self; + return this; } }; @@ -3032,55 +3222,47 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -// Constants -var NAMESPACE = 'cropper'; - -// Classes -var CLASS_HIDDEN = NAMESPACE + '-hidden'; - -// Events -var EVENT_ERROR = 'error'; -var EVENT_LOAD = 'load'; -var EVENT_READY = 'ready'; -var EVENT_CROP = 'crop'; - -// RegExps -var REGEXP_DATA_URL = /^data:/; -var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; - -var AnotherCropper = void 0; +var AnotherCropper = window.Cropper; var Cropper = function () { - function Cropper(element, options) { + /** + * Create a new Cropper. + * @param {Element} element - The target element for cropping. + * @param {Object} [options={}] - The configuration options. + */ + function Cropper(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Cropper); - var self = this; - - self.element = element; - self.options = extend({}, DEFAULTS, isPlainObject(options) && options); - self.loaded = false; - self.ready = false; - self.complete = false; - self.rotated = false; - self.cropped = false; - self.disabled = false; - self.replaced = false; - self.limited = false; - self.wheeling = false; - self.isImg = false; - self.originalUrl = ''; - self.canvasData = null; - self.cropBoxData = null; - self.previews = null; - self.pointers = {}; - self.init(); + if (!element || !REGEXP_TAG_NAME.test(element.tagName)) { + throw new Error('The first argument is required and must be an or element.'); + } + + this.element = element; + this.options = extend({}, DEFAULTS, isPlainObject(options) && options); + this.complete = false; + this.cropped = false; + this.disabled = false; + this.isImg = false; + this.limited = false; + this.loaded = false; + this.ready = false; + this.replaced = false; + this.wheeling = false; + this.originalUrl = ''; + this.canvasData = null; + this.cropBoxData = null; + this.previews = null; + this.pointers = {}; + this.init(); } _createClass(Cropper, [{ key: 'init', value: function init() { - var self = this; - var element = self.element; + var element = this.element; + var tagName = element.tagName.toLowerCase(); var url = void 0; @@ -3088,14 +3270,14 @@ var Cropper = function () { return; } - setData(element, NAMESPACE, self); + setData(element, NAMESPACE, this); if (tagName === 'img') { - self.isImg = true; + this.isImg = true; // e.g.: "img/picture.jpg" url = element.getAttribute('src'); - self.originalUrl = url; + this.originalUrl = url; // Stop when it's a blank image if (!url) { @@ -3108,45 +3290,48 @@ var Cropper = function () { url = element.toDataURL(); } - self.load(url); + this.load(url); } }, { key: 'load', value: function load(url) { - var self = this; - var options = self.options; - var element = self.element; + var _this = this; if (!url) { return; } - self.url = url; - self.imageData = {}; + this.url = url; + this.imageData = {}; + + var element = this.element, + options = this.options; + if (!options.checkOrientation || !window.ArrayBuffer) { - self.clone(); + this.clone(); return; } // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari if (REGEXP_DATA_URL.test(url)) { if (REGEXP_DATA_URL_JPEG.test(url)) { - self.read(dataURLToArrayBuffer(url)); + this.read(dataURLToArrayBuffer(url)); } else { - self.clone(); + this.clone(); } + return; } var xhr = new XMLHttpRequest(); xhr.onerror = function () { - self.clone(); + _this.clone(); }; xhr.onload = function () { - self.read(xhr.response); + _this.read(xhr.response); }; if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) { @@ -3161,57 +3346,22 @@ var Cropper = function () { }, { key: 'read', value: function read(arrayBuffer) { - var self = this; - var options = self.options; + var options = this.options, + imageData = this.imageData; + var orientation = getOrientation(arrayBuffer); - var imageData = self.imageData; var rotate = 0; var scaleX = 1; var scaleY = 1; if (orientation > 1) { - self.url = arrayBufferToDataURL(arrayBuffer); - - switch (orientation) { - // flip horizontal - case 2: - scaleX = -1; - break; - - // rotate left 180° - case 3: - rotate = -180; - break; - - // flip vertical - case 4: - scaleY = -1; - break; - - // flip vertical + rotate right 90° - case 5: - rotate = 90; - scaleY = -1; - break; - - // rotate right 90° - case 6: - rotate = 90; - break; - - // flip horizontal + rotate right 90° - case 7: - rotate = 90; - scaleX = -1; - break; + this.url = arrayBufferToDataURL(arrayBuffer, 'image/jpeg'); - // rotate left 90° - case 8: - rotate = -90; - break; + var _parseOrientation = parseOrientation(orientation); - default: - } + rotate = _parseOrientation.rotate; + scaleX = _parseOrientation.scaleX; + scaleY = _parseOrientation.scaleY; } if (options.rotatable) { @@ -3223,20 +3373,21 @@ var Cropper = function () { imageData.scaleY = scaleY; } - self.clone(); + this.clone(); } }, { key: 'clone', value: function clone() { - var self = this; - var element = self.element; - var url = self.url; + var element = this.element, + url = this.url; + var crossOrigin = void 0; var crossOriginUrl = void 0; - if (self.options.checkCrossOrigin && isCrossOriginURL(url)) { + if (this.options.checkCrossOrigin && isCrossOriginURL(url)) { crossOrigin = element.crossOrigin; + if (crossOrigin) { crossOriginUrl = url; } else { @@ -3247,10 +3398,10 @@ var Cropper = function () { } } - self.crossOrigin = crossOrigin; - self.crossOriginUrl = crossOriginUrl; + this.crossOrigin = crossOrigin; + this.crossOriginUrl = crossOriginUrl; - var image = createElement('img'); + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; @@ -3258,98 +3409,99 @@ var Cropper = function () { image.src = crossOriginUrl || url; - var start = proxy(self.start, self); - var stop = proxy(self.stop, self); + var start = proxy(this.start, this); + var stop = proxy(this.stop, this); - self.image = image; - self.onStart = start; - self.onStop = stop; + this.image = image; + this.onStart = start; + this.onStop = stop; - if (self.isImg) { + if (this.isImg) { if (element.complete) { - self.start(); + this.start(); } else { addListener(element, EVENT_LOAD, start); } } else { addListener(image, EVENT_LOAD, start); addListener(image, EVENT_ERROR, stop); - addClass(image, 'cropper-hide'); + addClass(image, CLASS_HIDE); element.parentNode.insertBefore(image, element.nextSibling); } } }, { key: 'start', value: function start(event) { - var self = this; - var image = self.isImg ? self.element : self.image; + var _this2 = this; + + var image = this.isImg ? this.element : this.image; if (event) { - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); } - getImageSize(image, function (naturalWidth, naturalHeight) { - extend(self.imageData, { + getImageNaturalSizes(image, function (naturalWidth, naturalHeight) { + extend(_this2.imageData, { naturalWidth: naturalWidth, naturalHeight: naturalHeight, aspectRatio: naturalWidth / naturalHeight }); - - self.loaded = true; - self.build(); + _this2.loaded = true; + _this2.build(); }); } }, { key: 'stop', value: function stop() { - var self = this; - var image = self.image; + var image = this.image; - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); - removeChild(image); - self.image = null; + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); + image.parentNode.removeChild(image); + this.image = null; } }, { key: 'build', value: function build() { - var self = this; - var options = self.options; - var element = self.element; - var image = self.image; + var _this3 = this; - if (!self.loaded) { + if (!this.loaded) { return; } // Unbuild first when replace - if (self.ready) { - self.unbuild(); + if (this.ready) { + this.unbuild(); } + var element = this.element, + options = this.options, + image = this.image; + // Create cropper elements + var container = element.parentNode; - var template = createElement('div'); + var template = document.createElement('div'); template.innerHTML = TEMPLATE; - var cropper = getByClass(template, 'cropper-container')[0]; - var canvas = getByClass(cropper, 'cropper-canvas')[0]; - var dragBox = getByClass(cropper, 'cropper-drag-box')[0]; - var cropBox = getByClass(cropper, 'cropper-crop-box')[0]; - var face = getByClass(cropBox, 'cropper-face')[0]; + var cropper = template.querySelector('.' + NAMESPACE + '-container'); + var canvas = cropper.querySelector('.' + NAMESPACE + '-canvas'); + var dragBox = cropper.querySelector('.' + NAMESPACE + '-drag-box'); + var cropBox = cropper.querySelector('.' + NAMESPACE + '-crop-box'); + var face = cropBox.querySelector('.' + NAMESPACE + '-face'); - self.container = container; - self.cropper = cropper; - self.canvas = canvas; - self.dragBox = dragBox; - self.cropBox = cropBox; - self.viewBox = getByClass(cropper, 'cropper-view-box')[0]; - self.face = face; + this.container = container; + this.cropper = cropper; + this.canvas = canvas; + this.dragBox = dragBox; + this.cropBox = cropBox; + this.viewBox = cropper.querySelector('.' + NAMESPACE + '-view-box'); + this.face = face; - appendChild(canvas, image); + canvas.appendChild(image); // Hide the original image addClass(element, CLASS_HIDDEN); @@ -3358,114 +3510,123 @@ var Cropper = function () { container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden - if (!self.isImg) { - removeClass(image, 'cropper-hide'); + if (!this.isImg) { + removeClass(image, CLASS_HIDE); } - self.initPreview(); - self.bind(); + this.initPreview(); + this.bind(); options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; - self.cropped = options.autoCrop; + this.cropped = options.autoCrop; if (options.autoCrop) { if (options.modal) { - addClass(dragBox, 'cropper-modal'); + addClass(dragBox, CLASS_MODAL); } } else { addClass(cropBox, CLASS_HIDDEN); } if (!options.guides) { - addClass(getByClass(cropBox, 'cropper-dashed'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-dashed'), CLASS_HIDDEN); } if (!options.center) { - addClass(getByClass(cropBox, 'cropper-center'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-center'), CLASS_HIDDEN); } if (options.background) { - addClass(cropper, 'cropper-bg'); + addClass(cropper, NAMESPACE + '-bg'); } if (!options.highlight) { - addClass(face, 'cropper-invisible'); + addClass(face, CLASS_INVISIBLE); } if (options.cropBoxMovable) { - addClass(face, 'cropper-move'); - setData(face, 'action', 'all'); + addClass(face, CLASS_MOVE); + setData(face, DATA_ACTION, ACTION_ALL); } if (!options.cropBoxResizable) { - addClass(getByClass(cropBox, 'cropper-line'), CLASS_HIDDEN); - addClass(getByClass(cropBox, 'cropper-point'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-line'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-point'), CLASS_HIDDEN); } - self.setDragMode(options.dragMode); - self.render(); - self.ready = true; - self.setData(options.data); + this.setDragMode(options.dragMode); + this.render(); + this.ready = true; + this.setData(options.data); // Call the "ready" option asynchronously to keep "image.cropper" is defined - self.completing = setTimeout(function () { + this.completing = setTimeout(function () { if (isFunction(options.ready)) { - addListener(element, EVENT_READY, options.ready, true); + addListener(element, EVENT_READY, options.ready, { + once: true + }); } dispatchEvent(element, EVENT_READY); - dispatchEvent(element, EVENT_CROP, self.getData()); + dispatchEvent(element, EVENT_CROP, _this3.getData()); - self.complete = true; + _this3.complete = true; }, 0); } }, { key: 'unbuild', value: function unbuild() { - var self = this; - - if (!self.ready) { + if (!this.ready) { return; } - if (!self.complete) { - clearTimeout(self.completing); + if (!this.complete) { + clearTimeout(this.completing); } - self.ready = false; - self.complete = false; - self.initialImageData = null; + this.ready = false; + this.complete = false; + this.initialImageData = null; // Clear `initialCanvasData` is necessary when replace - self.initialCanvasData = null; - self.initialCropBoxData = null; - self.containerData = null; - self.canvasData = null; + this.initialCanvasData = null; + this.initialCropBoxData = null; + this.containerData = null; + this.canvasData = null; // Clear `cropBoxData` is necessary when replace - self.cropBoxData = null; - self.unbind(); - - self.resetPreview(); - self.previews = null; + this.cropBoxData = null; + this.unbind(); + this.resetPreview(); + this.previews = null; + this.viewBox = null; + this.cropBox = null; + this.dragBox = null; + this.canvas = null; + this.container = null; + this.cropper.parentNode.removeChild(this.cropper); + this.cropper = null; + } + + /** + * Get the no conflict cropper class. + * @returns {Cropper} The cropper class. + */ - self.viewBox = null; - self.cropBox = null; - self.dragBox = null; - self.canvas = null; - self.container = null; - - removeChild(self.cropper); - self.cropper = null; - } }], [{ key: 'noConflict', value: function noConflict() { window.Cropper = AnotherCropper; return Cropper; } + + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + }, { key: 'setDefaults', value: function setDefaults(options) { @@ -3476,17 +3637,7 @@ var Cropper = function () { return Cropper; }(); -extend(Cropper.prototype, render); -extend(Cropper.prototype, preview); -extend(Cropper.prototype, events); -extend(Cropper.prototype, handlers); -extend(Cropper.prototype, change); -extend(Cropper.prototype, methods); - -if (typeof window !== 'undefined') { - AnotherCropper = window.Cropper; - window.Cropper = Cropper; -} +extend(Cropper.prototype, render, preview, events, handlers, change, methods); return Cropper; diff --git a/dist/cropper.min.css b/dist/cropper.min.css index 38f7dfb75..4819bac5c 100644 --- a/dist/cropper.min.css +++ b/dist/cropper.min.css @@ -1,11 +1,10 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z - */ - -.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline-color:rgba(51,153,255,.75);outline:1px solid #39f;overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:e-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:n-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:w-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:s-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:e-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:n-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:w-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:ne-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nw-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:sw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:se-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed} \ No newline at end of file + * Date: 2017-10-08T09:10:57.634Z + */.cropper-container{direction:ltr;font-size:0;line-height:0;position:relative;-ms-touch-action:none;touch-action:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.cropper-container img{display:block;height:100%;image-orientation:0deg;max-height:none!important;max-width:none!important;min-height:0!important;min-width:0!important;width:100%}.cropper-canvas,.cropper-crop-box,.cropper-drag-box,.cropper-modal,.cropper-wrap-box{bottom:0;left:0;position:absolute;right:0;top:0}.cropper-canvas,.cropper-wrap-box{overflow:hidden}.cropper-drag-box{background-color:#fff;opacity:0}.cropper-modal{background-color:#000;opacity:.5}.cropper-view-box{display:block;height:100%;outline-color:rgba(51,153,255,.75);outline:1px solid #39f;overflow:hidden;width:100%}.cropper-dashed{border:0 dashed #eee;display:block;opacity:.5;position:absolute}.cropper-dashed.dashed-h{border-bottom-width:1px;border-top-width:1px;height:33.33333%;left:0;top:33.33333%;width:100%}.cropper-dashed.dashed-v{border-left-width:1px;border-right-width:1px;height:100%;left:33.33333%;top:0;width:33.33333%}.cropper-center{display:block;height:0;left:50%;opacity:.75;position:absolute;top:50%;width:0}.cropper-center:after,.cropper-center:before{background-color:#eee;content:" ";display:block;position:absolute}.cropper-center:before{height:1px;left:-3px;top:0;width:7px}.cropper-center:after{height:7px;left:0;top:-3px;width:1px}.cropper-face,.cropper-line,.cropper-point{display:block;height:100%;opacity:.1;position:absolute;width:100%}.cropper-face{background-color:#fff;left:0;top:0}.cropper-line{background-color:#39f}.cropper-line.line-e{cursor:e-resize;right:-3px;top:0;width:5px}.cropper-line.line-n{cursor:n-resize;height:5px;left:0;top:-3px}.cropper-line.line-w{cursor:w-resize;left:-3px;top:0;width:5px}.cropper-line.line-s{bottom:-3px;cursor:s-resize;height:5px;left:0}.cropper-point{background-color:#39f;height:5px;opacity:.75;width:5px}.cropper-point.point-e{cursor:e-resize;margin-top:-3px;right:-3px;top:50%}.cropper-point.point-n{cursor:n-resize;left:50%;margin-left:-3px;top:-3px}.cropper-point.point-w{cursor:w-resize;left:-3px;margin-top:-3px;top:50%}.cropper-point.point-s{bottom:-3px;cursor:s-resize;left:50%;margin-left:-3px}.cropper-point.point-ne{cursor:ne-resize;right:-3px;top:-3px}.cropper-point.point-nw{cursor:nw-resize;left:-3px;top:-3px}.cropper-point.point-sw{bottom:-3px;cursor:sw-resize;left:-3px}.cropper-point.point-se{bottom:-3px;cursor:se-resize;height:20px;opacity:1;right:-3px;width:20px}@media (min-width:768px){.cropper-point.point-se{height:15px;width:15px}}@media (min-width:992px){.cropper-point.point-se{height:10px;width:10px}}@media (min-width:1200px){.cropper-point.point-se{height:5px;opacity:.75;width:5px}}.cropper-point.point-se:before{background-color:#39f;bottom:-50%;content:" ";display:block;height:200%;opacity:0;position:absolute;right:-50%;width:200%}.cropper-invisible{opacity:0}.cropper-bg{background-image:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAAA3NCSVQICAjb4U/gAAAABlBMVEXMzMz////TjRV2AAAACXBIWXMAAArrAAAK6wGCiw1aAAAAHHRFWHRTb2Z0d2FyZQBBZG9iZSBGaXJld29ya3MgQ1M26LyyjAAAABFJREFUCJlj+M/AgBVhF/0PAH6/D/HkDxOGAAAAAElFTkSuQmCC")}.cropper-hide{display:block;height:0;position:absolute;width:0}.cropper-hidden{display:none!important}.cropper-move{cursor:move}.cropper-crop{cursor:crosshair}.cropper-disabled .cropper-drag-box,.cropper-disabled .cropper-face,.cropper-disabled .cropper-line,.cropper-disabled .cropper-point{cursor:not-allowed} +/*# sourceMappingURL=cropper.min.css.map */ \ No newline at end of file diff --git a/dist/cropper.min.js b/dist/cropper.min.js index d924db827..9e4443c72 100644 --- a/dist/cropper.min.js +++ b/dist/cropper.min.js @@ -1,11 +1,10 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:11:03.372Z */ - -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.Cropper=e()}(this,function(){"use strict";function t(t){return ot.call(t).slice(8,-1).toLowerCase()}function e(t){return"number"==typeof t&&!isNaN(t)}function a(t){return void 0===t}function i(t){return"object"===(void 0===t?"undefined":Z(t))&&null!==t}function o(t){if(!i(t))return!1;try{var e=t.constructor,a=e.prototype;return e&&a&&nt.call(a,"isPrototypeOf")}catch(t){return!1}}function n(e){return"function"===t(e)}function r(e){return Array.isArray?Array.isArray(e):"array"===t(e)}function h(t){return"string"==typeof t&&(t=t.trim?t.trim():t.replace(_,"$1")),t}function c(t,a){if(t&&n(a)){var o=void 0;if(r(t)||e(t.length)){var h=t.length;for(o=0;o1?e-1:0),o=1;o0){if(Object.assign)return Object.assign.apply(Object,[t].concat(a));a.forEach(function(e){i(e)&&Object.keys(e).forEach(function(a){t[a]=e[a]})})}return t}function l(t,e){for(var a=arguments.length,i=Array(a>2?a-2:0),o=2;o-1}function u(t,a){if(a)if(e(t.length))c(t,function(t){u(t,a)});else if(t.classList)t.classList.add(a);else{var i=h(t.className);i?i.indexOf(a)<0&&(t.className=i+" "+a):t.className=a}}function m(t,a){a&&(e(t.length)?c(t,function(t){m(t,a)}):t.classList?t.classList.remove(a):t.className.indexOf(a)>=0&&(t.className=t.className.replace(a,"")))}function g(t,a,i){a&&(e(t.length)?c(t,function(t){g(t,a,i)}):i?u(t,a):m(t,a))}function f(t){return t.replace(V,"$1-$2").toLowerCase()}function v(t,e){return i(t[e])?t[e]:t.dataset?t.dataset[e]:t.getAttribute("data-"+f(e))}function w(t,e,a){i(a)?t[e]=a:t.dataset?t.dataset[e]=a:t.setAttribute("data-"+f(e),a)}function b(t,e){if(i(t[e]))delete t[e];else if(t.dataset)try{delete t.dataset[e]}catch(a){t.dataset[e]=null}else t.removeAttribute("data-"+f(e))}function x(t,e,a){var i=h(e).split(G);i.length>1?c(i,function(e){x(t,e,a)}):t.removeEventListener?t.removeEventListener(e,a,!1):t.detachEvent&&t.detachEvent("on"+e,a)}function y(t,e,a,i){var o=h(e).split(G),n=a;o.length>1?c(o,function(e){y(t,e,a)}):(i&&(a=function(){for(var i=arguments.length,o=Array(i),r=0;r90?180-a:a)*Math.PI/180,o=Math.sin(i),n=Math.cos(i),r=t.width,h=t.height,c=t.aspectRatio,s=void 0,l=void 0;return e?l=(s=r/(n+o/c))/c:(s=r*n+h*o,l=r*o+h*n),{width:s,height:l}}function S(t,a,i){var o=T("canvas"),n=o.getContext("2d"),r=0,h=0,c=a.naturalWidth,s=a.naturalHeight,l=a.rotate,d=a.scaleX,p=a.scaleY,u=e(d)&&e(p)&&(1!==d||1!==p),m=e(l)&&0!==l,g=m||u,f=c*Math.abs(d||1),v=s*Math.abs(p||1),w=void 0,b=void 0,x=void 0;return u&&(w=f/2,b=v/2),m&&(w=(f=(x=O({width:f,height:v,degree:l})).width)/2,b=(v=x.height)/2),o.width=f,o.height=v,i.fillColor&&(n.fillStyle=i.fillColor,n.fillRect(0,0,f,v)),g&&(r=-c/2,h=-s/2,n.save(),n.translate(w,b)),m&&n.rotate(l*Math.PI/180),u&&n.scale(d,p),n.imageSmoothingEnabled=!!i.imageSmoothingEnabled,i.imageSmoothingQuality&&(n.imageSmoothingQuality=i.imageSmoothingQuality),n.drawImage(t,Math.floor(r),Math.floor(h),Math.floor(c),Math.floor(s)),g&&n.restore(),o}function z(t,e,a){var i="",o=e;for(a+=e;o=8&&(s=o+n)),s)for(a=e.getUint16(s,r),d=0;da.width?3===e?c=a.height*h:l=a.width/h:3===e?l=a.width/h:c=a.height*h;var d={naturalWidth:n,naturalHeight:r,aspectRatio:h,width:c,height:l};d.left=(a.width-c)/2,d.top=(a.height-l)/2,d.oldLeft=d.left,d.oldTop=d.top,t.canvasData=d,t.limited=1===e||2===e,t.limitCanvas(!0,!0),t.initialImageData=s({},i),t.initialCanvasData=s({},d)},limitCanvas:function(t,e){var a=this,i=a.options,o=i.viewMode,n=a.containerData,r=a.canvasData,h=r.aspectRatio,c=a.cropBoxData,s=a.cropped&&c;if(t){var l=Number(i.minCanvasWidth)||0,d=Number(i.minCanvasHeight)||0;o>1?(l=Math.max(l,n.width),d=Math.max(d,n.height),3===o&&(d*h>l?l=d*h:d=l/h)):o>0&&(l?l=Math.max(l,s?c.width:0):d?d=Math.max(d,s?c.height:0):s&&(l=c.width,(d=c.height)*h>l?l=d*h:d=l/h)),l&&d?d*h>l?d=l/h:l=d*h:l?d=l/h:d&&(l=d*h),r.minWidth=l,r.minHeight=d,r.maxWidth=1/0,r.maxHeight=1/0}if(e)if(o){var p=n.width-r.width,u=n.height-r.height;r.minLeft=Math.min(0,p),r.minTop=Math.min(0,u),r.maxLeft=Math.max(0,p),r.maxTop=Math.max(0,u),s&&a.limited&&(r.minLeft=Math.min(c.left,c.left+(c.width-r.width)),r.minTop=Math.min(c.top,c.top+(c.height-r.height)),r.maxLeft=c.left,r.maxTop=c.top,2===o&&(r.width>=n.width&&(r.minLeft=Math.min(0,p),r.maxLeft=Math.max(0,p)),r.height>=n.height&&(r.minTop=Math.min(0,u),r.maxTop=Math.max(0,u))))}else r.minLeft=-r.width,r.minTop=-r.height,r.maxLeft=n.width,r.maxTop=n.height},renderCanvas:function(t){var e=this,a=e.canvasData,i=e.imageData,o=i.rotate;if(e.rotated){e.rotated=!1;var n=O({width:i.width,height:i.height,degree:o}),r=n.width/n.height,h=1===i.aspectRatio;if(h||r!==a.aspectRatio){if(a.left-=(n.width-a.width)/2,a.top-=(n.height-a.height)/2,a.width=n.width,a.height=n.height,a.aspectRatio=r,a.naturalWidth=i.naturalWidth,a.naturalHeight=i.naturalHeight,h&&o%90||o%180){var c=O({width:i.naturalWidth,height:i.naturalHeight,degree:o});a.naturalWidth=c.width,a.naturalHeight=c.height}e.limitCanvas(!0,!1)}}(a.width>a.maxWidth||a.widtha.maxHeight||a.heighto.width?n.height=n.width/a:n.width=n.height*a),t.cropBoxData=n,t.limitCropBox(!0,!0),n.width=Math.min(Math.max(n.width,n.minWidth),n.maxWidth),n.height=Math.min(Math.max(n.height,n.minHeight),n.maxHeight),n.width=Math.max(n.minWidth,n.width*i),n.height=Math.max(n.minHeight,n.height*i),n.left=o.left+(o.width-n.width)/2,n.top=o.top+(o.height-n.height)/2,n.oldLeft=n.left,n.oldTop=n.top,t.initialCropBoxData=s({},n)},limitCropBox:function(t,e){var a=this,i=a.options,o=i.aspectRatio,n=a.containerData,r=a.canvasData,h=a.cropBoxData,c=a.limited;if(t){var s=Number(i.minCropBoxWidth)||0,l=Number(i.minCropBoxHeight)||0,d=Math.min(n.width,c?r.width:n.width),p=Math.min(n.height,c?r.height:n.height);s=Math.min(s,n.width),l=Math.min(l,n.height),o&&(s&&l?l*o>s?l=s/o:s=l*o:s?l=s/o:l&&(s=l*o),p*o>d?p=d/o:d=p*o),h.minWidth=Math.min(s,d),h.minHeight=Math.min(l,p),h.maxWidth=d,h.maxHeight=p}e&&(c?(h.minLeft=Math.max(0,r.left),h.minTop=Math.max(0,r.top),h.maxLeft=Math.min(n.width,r.left+r.width)-h.width,h.maxTop=Math.min(n.height,r.top+r.height)-h.height):(h.minLeft=0,h.minTop=0,h.maxLeft=n.width-h.width,h.maxTop=n.height-h.height))},renderCropBox:function(){var t=this,e=t.options,a=t.containerData,i=t.cropBoxData;(i.width>i.maxWidth||i.widthi.maxHeight||i.heightc&&(u=o*(g=c/n),m=c),d(t,{width:u,height:m}),d(B(t,"img")[0],s({width:r*g,height:h*g},N(s({translateX:-l*g,translateY:-p*g},e))))}))}},st="undefined"!=typeof window?window.PointerEvent:null,lt=st?"pointerdown":"touchstart mousedown",dt=st?"pointermove":"touchmove mousemove",pt=st?" pointerup pointercancel":"touchend touchcancel mouseup",ut={bind:function(){var t=this,e=t.options,a=t.element,i=t.cropper;n(e.cropstart)&&y(a,"cropstart",e.cropstart),n(e.cropmove)&&y(a,"cropmove",e.cropmove),n(e.cropend)&&y(a,"cropend",e.cropend),n(e.crop)&&y(a,"crop",e.crop),n(e.zoom)&&y(a,"zoom",e.zoom),y(i,lt,t.onCropStart=l(t.cropStart,t)),e.zoomable&&e.zoomOnWheel&&y(i,"wheel mousewheel DOMMouseScroll",t.onWheel=l(t.wheel,t)),e.toggleDragModeOnDblclick&&y(i,"dblclick",t.onDblclick=l(t.dblclick,t)),y(document,dt,t.onCropMove=l(t.cropMove,t)),y(document,pt,t.onCropEnd=l(t.cropEnd,t)),e.responsive&&y(window,"resize",t.onResize=l(t.resize,t))},unbind:function(){var t=this,e=t.options,a=t.element,i=t.cropper;n(e.cropstart)&&x(a,"cropstart",e.cropstart),n(e.cropmove)&&x(a,"cropmove",e.cropmove),n(e.cropend)&&x(a,"cropend",e.cropend),n(e.crop)&&x(a,"crop",e.crop),n(e.zoom)&&x(a,"zoom",e.zoom),x(i,lt,t.onCropStart),e.zoomable&&e.zoomOnWheel&&x(i,"wheel mousewheel DOMMouseScroll",t.onWheel),e.toggleDragModeOnDblclick&&x(i,"dblclick",t.onDblclick),x(document,dt,t.onCropMove),x(document,pt,t.onCropEnd),e.responsive&&x(window,"resize",t.onResize)}},mt=/^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/,gt={resize:function(){var t=this,e=t.options,a=t.container,i=t.containerData,o=Number(e.minContainerWidth)||200,n=Number(e.minContainerHeight)||100;if(!t.disabled&&i.width!==o&&i.height!==n){var r=a.offsetWidth/i.width;if(1!==r||a.offsetHeight!==i.height){var h=void 0,s=void 0;e.restore&&(h=t.getCanvasData(),s=t.getCropBoxData()),t.render(),e.restore&&(t.setCanvasData(c(h,function(t,e){h[e]=t*r})),t.setCropBoxData(c(s,function(t,e){s[e]=t*r})))}}},dblclick:function(){var t=this;t.disabled||"none"===t.options.dragMode||t.setDragMode(p(t.dragBox,"cropper-crop")?"move":"crop")},wheel:function(t){var e=this,a=C(t),i=Number(e.options.wheelZoomRatio)||.1,o=1;e.disabled||(a.preventDefault(),e.wheeling||(e.wheeling=!0,setTimeout(function(){e.wheeling=!1},50),a.deltaY?o=a.deltaY>0?1:-1:a.wheelDelta?o=-a.wheelDelta/120:a.detail&&(o=a.detail>0?1:-1),e.zoom(-o*i,a)))},cropStart:function(t){var e=this;if(!e.disabled){var a=e.options,i=e.pointers,o=C(t),n=void 0;o.changedTouches?c(o.changedTouches,function(t){i[t.identifier]=U(t)}):i[o.pointerId||0]=U(o),n=Object.keys(i).length>1&&a.zoomable&&a.zoomOnTouch?"zoom":v(o.target,"action"),mt.test(n)&&!1!==M(e.element,"cropstart",{originalEvent:o,action:n})&&(o.preventDefault(),e.action=n,e.cropping=!1,"crop"===n&&(e.cropping=!0,u(e.dragBox,"cropper-modal")))}},cropMove:function(t){var e=this,a=e.action;if(!e.disabled&&a){var i=e.pointers,o=C(t);o.preventDefault(),!1!==M(e.element,"cropmove",{originalEvent:o,action:a})&&(o.changedTouches?c(o.changedTouches,function(t){s(i[t.identifier],U(t,!0))}):s(i[o.pointerId||0],U(o,!0)),e.change(o))}},cropEnd:function(t){var e=this;if(!e.disabled){var a=e.action,i=e.pointers,o=C(t);o.changedTouches?c(o.changedTouches,function(t){delete i[t.identifier]}):delete i[o.pointerId||0],a&&(o.preventDefault(),Object.keys(i).length||(e.action=""),e.cropping&&(e.cropping=!1,g(e.dragBox,"cropper-modal",e.cropped&&this.options.modal)),M(e.element,"cropend",{originalEvent:o,action:a}))}}},ft={change:function(t){var e=this,a=e.options,i=e.containerData,o=e.canvasData,n=e.cropBoxData,r=a.aspectRatio,h=e.action,s=n.width,l=n.height,d=n.left,p=n.top,u=d+s,g=p+l,f=0,v=0,w=i.width,b=i.height,x=!0,y=void 0;!r&&t.shiftKey&&(r=s&&l?s/l:1),e.limited&&(f=n.minLeft,v=n.minTop,w=f+Math.min(i.width,o.width,o.left+o.width),b=v+Math.min(i.height,o.height,o.top+o.height));var M=e.pointers,C=M[Object.keys(M)[0]],B={x:C.endX-C.startX,y:C.endY-C.startY};switch(h){case"all":d+=B.x,p+=B.y;break;case"e":if(B.x>=0&&(u>=w||r&&(p<=v||g>=b))){x=!1;break}u+B.x>w&&(B.x=w-u),s+=B.x,r&&(l=s/r,p-=B.x/r/2),s<0&&(h="w",s=0);break;case"n":if(B.y<=0&&(p<=v||r&&(d<=f||u>=w))){x=!1;break}p+B.y=b))){x=!1;break}d+B.x=0&&(g>=b||r&&(d<=f||u>=w))){x=!1;break}g+B.y>b&&(B.y=b-g),l+=B.y,r&&(s=l*r,d-=B.y*r/2),l<0&&(h="n",l=0);break;case"ne":if(r){if(B.y<=0&&(p<=v||u>=w)){x=!1;break}l-=B.y,p+=B.y,s=l*r}else B.x>=0?uv&&(l-=B.y,p+=B.y):(l-=B.y,p+=B.y);s<0&&l<0?(h="sw",l=0,s=0):s<0?(h="nw",s=0):l<0&&(h="se",l=0);break;case"nw":if(r){if(B.y<=0&&(p<=v||d<=f)){x=!1;break}l-=B.y,p+=B.y,s=l*r,d+=B.y*r}else B.x<=0?d>f?(s-=B.x,d+=B.x):B.y<=0&&p<=v&&(x=!1):(s-=B.x,d+=B.x),B.y<=0?p>v&&(l-=B.y,p+=B.y):(l-=B.y,p+=B.y);s<0&&l<0?(h="se",l=0,s=0):s<0?(h="ne",s=0):l<0&&(h="sw",l=0);break;case"sw":if(r){if(B.x<=0&&(d<=f||g>=b)){x=!1;break}s-=B.x,d+=B.x,l=s/r}else B.x<=0?d>f?(s-=B.x,d+=B.x):B.y>=0&&g>=b&&(x=!1):(s-=B.x,d+=B.x),B.y>=0?g=0&&(u>=w||g>=b)){x=!1;break}l=(s+=B.x)/r}else B.x>=0?u=0&&g>=b&&(x=!1):s+=B.x,B.y>=0?g0?h=B.y>0?"se":"ne":B.x<0&&(d-=s,h=B.y>0?"sw":"nw"),B.y<0&&(p-=l),e.cropped||(m(e.cropBox,"cropper-hidden"),e.cropped=!0,e.limited&&e.limitCropBox(!0,!0))}x&&(n.width=s,n.height=l,n.left=d,n.top=p,e.action=h,e.renderCropBox()),c(M,function(t){t.startX=t.endX,t.startY=t.endY})}},vt={crop:function(){var t=this;return t.ready&&!t.disabled&&(t.cropped||(t.cropped=!0,t.limitCropBox(!0,!0),t.options.modal&&u(t.dragBox,"cropper-modal"),m(t.cropBox,"cropper-hidden")),t.setCropBoxData(t.initialCropBoxData)),t},reset:function(){var t=this;return t.ready&&!t.disabled&&(t.imageData=s({},t.initialImageData),t.canvasData=s({},t.initialCanvasData),t.cropBoxData=s({},t.initialCropBoxData),t.renderCanvas(),t.cropped&&t.renderCropBox()),t},clear:function(){var t=this;return t.cropped&&!t.disabled&&(s(t.cropBoxData,{left:0,top:0,width:0,height:0}),t.cropped=!1,t.renderCropBox(),t.limitCanvas(!0,!0),t.renderCanvas(),m(t.dragBox,"cropper-modal"),u(t.cropBox,"cropper-hidden")),t},replace:function(t,e){var a=this;return!a.disabled&&t&&(a.isImg&&(a.element.src=t),e?(a.url=t,a.image.src=t,a.ready&&(a.image2.src=t,c(a.previews,function(e){B(e,"img")[0].src=t}))):(a.isImg&&(a.replaced=!0),a.options.data=null,a.load(t))),a},enable:function(){var t=this;return t.ready&&(t.disabled=!1,m(t.cropper,"cropper-disabled")),t},disable:function(){var t=this;return t.ready&&(t.disabled=!0,u(t.cropper,"cropper-disabled")),t},destroy:function(){var t=this,e=t.element,a=t.image;return t.loaded?(t.isImg&&t.replaced&&(e.src=t.originalUrl),t.unbuild(),m(e,"cropper-hidden")):t.isImg?x(e,"load",t.onStart):a&&W(a),b(e,"cropper"),t},move:function(t,e){var i=this,o=i.canvasData;return i.moveTo(a(t)?t:o.left+Number(t),a(e)?e:o.top+Number(e))},moveTo:function(t,i){var o=this,n=o.canvasData,r=!1;return a(i)&&(i=t),t=Number(t),i=Number(i),o.ready&&!o.disabled&&o.options.movable&&(e(t)&&(n.left=t,r=!0),e(i)&&(n.top=i,r=!0),r&&o.renderCanvas(!0)),o},zoom:function(t,e){var a=this,i=a.canvasData;return t=Number(t),t=t<0?1/(1-t):1+t,a.zoomTo(i.width*t/i.naturalWidth,e)},zoomTo:function(t,e){var a=this,i=a.options,o=a.canvasData,n=o.width,r=o.height,h=o.naturalWidth,c=o.naturalHeight;if((t=Number(t))>=0&&a.ready&&!a.disabled&&i.zoomable){var s=h*t,l=c*t;if(!1===M(a.element,"zoom",{originalEvent:e,oldRatio:n/h,ratio:s/h}))return a;if(e){var d=a.pointers,p=D(a.cropper),u=d&&Object.keys(d).length?q(d):{pageX:e.pageX,pageY:e.pageY};o.left-=(s-n)*((u.pageX-p.left-o.left)/n),o.top-=(l-r)*((u.pageY-p.top-o.top)/r)}else o.left-=(s-n)/2,o.top-=(l-r)/2;o.width=s,o.height=l,a.renderCanvas(!0)}return a},rotate:function(t){var e=this;return e.rotateTo((e.imageData.rotate||0)+Number(t))},rotateTo:function(t){var a=this;return t=Number(t),e(t)&&a.ready&&!a.disabled&&a.options.rotatable&&(a.imageData.rotate=t%360,a.rotated=!0,a.renderCanvas(!0)),a},scale:function(t,i){var o=this,n=o.imageData,r=!1;return a(i)&&(i=t),t=Number(t),i=Number(i),o.ready&&!o.disabled&&o.options.scalable&&(e(t)&&(n.scaleX=t,r=!0),e(i)&&(n.scaleY=i,r=!0),r&&o.renderImage(!0)),o},scaleX:function(t){var a=this,i=a.imageData.scaleY;return a.scale(t,e(i)?i:1)},scaleY:function(t){var a=this,i=a.imageData.scaleX;return a.scale(e(i)?i:1,t)},getData:function(t){var e=this,a=e.options,i=e.imageData,o=e.canvasData,n=e.cropBoxData,r=void 0,h=void 0;return e.ready&&e.cropped?(h={x:n.left-o.left,y:n.top-o.top,width:n.width,height:n.height},r=i.width/i.naturalWidth,c(h,function(e,a){e/=r,h[a]=t?Math.round(e):e})):h={x:0,y:0,width:0,height:0},a.rotatable&&(h.rotate=i.rotate||0),a.scalable&&(h.scaleX=i.scaleX||1,h.scaleY=i.scaleY||1),h},setData:function(t){var a=this,i=a.options,r=a.imageData,h=a.canvasData,c={},s=void 0,l=void 0,d=void 0;return n(t)&&(t=t.call(a.element)),a.ready&&!a.disabled&&o(t)&&(i.rotatable&&e(t.rotate)&&t.rotate!==r.rotate&&(r.rotate=t.rotate,s=!0,a.rotated=s),i.scalable&&(e(t.scaleX)&&t.scaleX!==r.scaleX&&(r.scaleX=t.scaleX,l=!0),e(t.scaleY)&&t.scaleY!==r.scaleY&&(r.scaleY=t.scaleY,l=!0)),s?a.renderCanvas():l&&a.renderImage(),d=r.width/r.naturalWidth,e(t.x)&&(c.left=t.x*d+h.left),e(t.y)&&(c.top=t.y*d+h.top),e(t.width)&&(c.width=t.width*d),e(t.height)&&(c.height=t.height*d),a.setCropBoxData(c)),a},getContainerData:function(){var t=this;return t.ready?t.containerData:{}},getImageData:function(){var t=this;return t.loaded?t.imageData:{}},getCanvasData:function(){var t=this,e=t.canvasData,a={};return t.ready&&c(["left","top","width","height","naturalWidth","naturalHeight"],function(t){a[t]=e[t]}),a},setCanvasData:function(t){var a=this,i=a.canvasData,r=i.aspectRatio;return n(t)&&(t=t.call(a.element)),a.ready&&!a.disabled&&o(t)&&(e(t.left)&&(i.left=t.left),e(t.top)&&(i.top=t.top),e(t.width)?(i.width=t.width,i.height=t.width/r):e(t.height)&&(i.height=t.height,i.width=t.height*r),a.renderCanvas(!0)),a},getCropBoxData:function(){var t=this,e=t.cropBoxData,a=void 0;return t.ready&&t.cropped&&(a={left:e.left,top:e.top,width:e.width,height:e.height}),a||{}},setCropBoxData:function(t){var a=this,i=a.cropBoxData,r=a.options.aspectRatio,h=void 0,c=void 0;return n(t)&&(t=t.call(a.element)),a.ready&&a.cropped&&!a.disabled&&o(t)&&(e(t.left)&&(i.left=t.left),e(t.top)&&(i.top=t.top),e(t.width)&&t.width!==i.width&&(h=!0,i.width=t.width),e(t.height)&&t.height!==i.height&&(c=!0,i.height=t.height),r&&(h?i.height=i.width/r:c&&(i.width=i.height*r)),a.renderCropBox()),a},getCroppedCanvas:function(t){var e=this;if(!e.ready||!window.HTMLCanvasElement)return null;if(o(t)||(t={}),!e.cropped)return S(e.image,e.imageData,t);var a=e.getData(),i=a.width,n=a.height,r=i/n,h=void 0,c=void 0,s=void 0;o(t)&&(h=t.width,c=t.height,h?(c=h/r,s=h/i):c&&(h=c*r,s=c/n));var l=Math.floor(h||i),d=Math.floor(c||n),p=T("canvas"),u=p.getContext("2d");p.width=l,p.height=d,t.fillColor&&(u.fillStyle=t.fillColor,u.fillRect(0,0,l,d));var m=function(){var o=S(e.image,e.imageData,t),r=o.width,h=o.height,c=e.canvasData,l=[o],d=a.x+c.naturalWidth*(Math.abs(a.scaleX||1)-1)/2,p=a.y+c.naturalHeight*(Math.abs(a.scaleY||1)-1)/2,u=void 0,m=void 0,g=void 0,f=void 0,v=void 0,w=void 0;return d<=-i||d>r?(d=0,u=0,g=0,v=0):d<=0?(g=-d,d=0,v=u=Math.min(r,i+d)):d<=r&&(g=0,v=u=Math.min(i,r-d)),u<=0||p<=-n||p>h?(p=0,m=0,f=0,w=0):p<=0?(f=-p,p=0,w=m=Math.min(h,n+p)):p<=h&&(f=0,w=m=Math.min(n,h-p)),l.push(Math.floor(d),Math.floor(p),Math.floor(u),Math.floor(m)),s&&(g*=s,f*=s,v*=s,w*=s),v>0&&w>0&&l.push(Math.floor(g),Math.floor(f),Math.floor(v),Math.floor(w)),l}();return u.imageSmoothingEnabled=!!t.imageSmoothingEnabled,t.imageSmoothingQuality&&(u.imageSmoothingQuality=t.imageSmoothingQuality),u.drawImage.apply(u,P(m)),p},setAspectRatio:function(t){var e=this,i=e.options;return e.disabled||a(t)||(i.aspectRatio=Math.max(0,t)||NaN,e.ready&&(e.initCropBox(),e.cropped&&e.renderCropBox())),e},setDragMode:function(t){var e=this,a=e.options,i=e.dragBox,o=e.face,n=void 0,r=void 0;return e.loaded&&!e.disabled&&(n="crop"===t,r=a.movable&&"move"===t,w(i,"action",t=n||r?t:"none"),g(i,"cropper-crop",n),g(i,"cropper-move",r),a.cropBoxMovable||(w(o,"action",t),g(o,"cropper-crop",n),g(o,"cropper-move",r))),e}},wt=function(){function t(t,e){for(var a=0;a1)switch(e.url=I(t),i){case 2:r=-1;break;case 3:n=-180;break;case 4:h=-1;break;case 5:n=90,h=-1;break;case 6:n=90;break;case 7:n=90,r=-1;break;case 8:n=-90}a.rotatable&&(o.rotate=n),a.scalable&&(o.scaleX=r,o.scaleY=h),e.clone()}},{key:"clone",value:function(){var t=this,e=t.element,a=t.url,i=void 0,o=void 0;t.options.checkCrossOrigin&&H(a)&&((i=e.crossOrigin)?o=a:(i="anonymous",o=X(a))),t.crossOrigin=i,t.crossOriginUrl=o;var n=T("img");i&&(n.crossOrigin=i),n.src=o||a;var r=l(t.start,t),h=l(t.stop,t);t.image=n,t.onStart=r,t.onStop=h,t.isImg?e.complete?t.start():y(e,"load",r):(y(n,"load",r),y(n,"error",h),u(n,"cropper-hide"),e.parentNode.insertBefore(n,e.nextSibling))}},{key:"start",value:function(t){var e=this,a=e.isImg?e.element:e.image;t&&(x(a,"load",e.onStart),x(a,"error",e.onStop)),Y(a,function(t,a){s(e.imageData,{naturalWidth:t,naturalHeight:a,aspectRatio:t/a}),e.loaded=!0,e.build()})}},{key:"stop",value:function(){var t=this,e=t.image;x(e,"load",t.onStart),x(e,"error",t.onStop),W(e),t.image=null}},{key:"build",value:function(){var t=this,e=t.options,a=t.element,i=t.image;if(t.loaded){t.ready&&t.unbuild();var o=a.parentNode,r=T("div");r.innerHTML='
';var h=k(r,"cropper-container")[0],c=k(h,"cropper-canvas")[0],s=k(h,"cropper-drag-box")[0],l=k(h,"cropper-crop-box")[0],d=k(l,"cropper-face")[0];t.container=o,t.cropper=h,t.canvas=c,t.dragBox=s,t.cropBox=l,t.viewBox=k(h,"cropper-view-box")[0],t.face=d,L(c,i),u(a,"cropper-hidden"),o.insertBefore(h,a.nextSibling),t.isImg||m(i,"cropper-hide"),t.initPreview(),t.bind(),e.aspectRatio=Math.max(0,e.aspectRatio)||NaN,e.viewMode=Math.max(0,Math.min(3,Math.round(e.viewMode)))||0,t.cropped=e.autoCrop,e.autoCrop?e.modal&&u(s,"cropper-modal"):u(l,"cropper-hidden"),e.guides||u(k(l,"cropper-dashed"),"cropper-hidden"),e.center||u(k(l,"cropper-center"),"cropper-hidden"),e.background&&u(h,"cropper-bg"),e.highlight||u(d,"cropper-invisible"),e.cropBoxMovable&&(u(d,"cropper-move"),w(d,"action","all")),e.cropBoxResizable||(u(k(l,"cropper-line"),"cropper-hidden"),u(k(l,"cropper-point"),"cropper-hidden")),t.setDragMode(e.dragMode),t.render(),t.ready=!0,t.setData(e.data),t.completing=setTimeout(function(){n(e.ready)&&y(a,"ready",e.ready,!0),M(a,"ready"),M(a,"crop",t.getData()),t.complete=!0},0)}}},{key:"unbuild",value:function(){var t=this;t.ready&&(t.complete||clearTimeout(t.completing),t.ready=!1,t.complete=!1,t.initialImageData=null,t.initialCanvasData=null,t.initialCropBoxData=null,t.containerData=null,t.canvasData=null,t.cropBoxData=null,t.unbind(),t.resetPreview(),t.previews=null,t.viewBox=null,t.cropBox=null,t.dragBox=null,t.canvas=null,t.container=null,W(t.cropper),t.cropper=null)}}],[{key:"noConflict",value:function(){return window.Cropper=yt,t}},{key:"setDefaults",value:function(t){s($,o(t)&&t)}}]),t}();return s(Mt.prototype,ht),s(Mt.prototype,ct),s(Mt.prototype,ut),s(Mt.prototype,gt),s(Mt.prototype,ft),s(Mt.prototype,vt),"undefined"!=typeof window&&(yt=window.Cropper,window.Cropper=Mt),Mt}); \ No newline at end of file +!function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):t.Cropper=i()}(this,function(){"use strict";function t(t){return"number"==typeof t&&!K(t)}function i(t){return void 0===t}function e(t){return"object"===(void 0===t?"undefined":F(t))&&null!==t}function a(t){if(!e(t))return!1;try{var i=t.constructor,a=i.prototype;return i&&a&&V.call(a,"isPrototypeOf")}catch(t){return!1}}function n(t){return"function"==typeof t}function o(i,a){if(i&&n(a))if(Array.isArray(i)||t(i.length)){var o=i.length,r=void 0;for(r=0;r1?i-1:0),n=1;n0){if(Object.assign)return Object.assign.apply(Object,[t].concat(a));a.forEach(function(i){e(i)&&Object.keys(i).forEach(function(e){t[e]=i[e]})})}return t}function h(t,i){for(var e=arguments.length,a=Array(e>2?e-2:0),n=2;n-1}function l(i,e){if(e)if(t(i.length))o(i,function(t){l(t,e)});else if(i.classList)i.classList.add(e);else{var a=i.className.trim();a?a.indexOf(e)<0&&(i.className=a+" "+e):i.className=e}}function d(i,e){e&&(t(i.length)?o(i,function(t){d(t,e)}):i.classList?i.classList.remove(e):i.className.indexOf(e)>=0&&(i.className=i.className.replace(e,"")))}function p(i,e,a){e&&(t(i.length)?o(i,function(t){p(t,e,a)}):a?l(i,e):d(i,e))}function m(t){return t.replace(J,"$1-$2").toLowerCase()}function u(t,i){return e(t[i])?t[i]:t.dataset?t.dataset[i]:t.getAttribute("data-"+m(i))}function g(t,i,a){e(a)?t[i]=a:t.dataset?t.dataset[i]=a:t.setAttribute("data-"+m(i),a)}function f(t,i){if(e(t[i]))delete t[i];else if(t.dataset)try{delete t.dataset[i]}catch(e){t.dataset[i]=null}else t.removeAttribute("data-"+m(i))}function v(t,i,e){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},r=i.trim().split(_);r.length>1?o(r,function(i){v(t,i,e)}):(n(e.onceListener)&&delete(e=e.onceListener).onceListener,t.removeEventListener?t.removeEventListener(i,e,a):t.detachEvent&&t.detachEvent("on"+i,e))}function w(t,i,e){var a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{},n=i.trim().split(_);if(n.length>1)o(n,function(i){w(t,i,e)});else{if(a.once){var r=e,h=function e(){for(var a=arguments.length,n=Array(a),o=0;o0};return n(a)&&n(e)?e*i>a?e=a/i:a=e*i:n(a)?e=a/i:n(e)&&(a=e*i),{width:a,height:e}}function N(t){var i=t.width,e=t.height,a=t.degree;if((a=Math.abs(a))%180==90)return{width:e,height:i};var n=a%90*Math.PI/180,o=Math.sin(n),r=Math.cos(n);return{width:i*r+e*o,height:i*o+e*r}}function H(t,i,e,a){var n=i.naturalWidth,o=i.naturalHeight,r=i.rotate,h=i.scaleX,s=i.scaleY,c=e.aspectRatio,l=e.naturalWidth,d=e.naturalHeight,p=a.fillColor,m=void 0===p?"transparent":p,u=a.imageSmoothingEnabled,g=void 0===u||u,f=a.imageSmoothingQuality,v=void 0===f?"low":f,w=a.maxWidth,b=void 0===w?1/0:w,x=a.maxHeight,y=void 0===x?1/0:x,M=a.minWidth,C=void 0===M?0:M,D=a.minHeight,B=void 0===D?0:D,k=document.createElement("canvas"),E=k.getContext("2d"),T=W({aspectRatio:c,width:b,height:y}),N=W({aspectRatio:c,width:C,height:B}),H=Math.min(T.width,Math.max(N.width,l)),L=Math.min(T.height,Math.max(N.height,d));return k.width=H,k.height=L,E.fillStyle=m,E.fillRect(0,0,H,L),E.save(),E.translate(H/2,L/2),E.rotate(r*Math.PI/180),E.scale(h,s),E.imageSmoothingEnabled=g,E.imageSmoothingQuality=v,E.drawImage(t,Math.floor(-n/2),Math.floor(-o/2),Math.floor(n),Math.floor(o)),E.restore(),k}function L(t,i,e){var a="",n=void 0;for(e+=i,n=i;n=8&&(o=s+l)}}}if(o){var d=i.getUint16(o,a),p=void 0,m=void 0;for(m=0;mt.width?3===e?s=t.height*h:c=t.width/h:3===e?c=t.width/h:s=t.height*h;var l={aspectRatio:h,naturalWidth:n,naturalHeight:o,width:s,height:c};l.left=(t.width-s)/2,l.top=(t.height-c)/2,l.oldLeft=l.left,l.oldTop=l.top,this.canvasData=l,this.limited=1===e||2===e,this.limitCanvas(!0,!0),this.initialImageData=r({},i),this.initialCanvasData=r({},l)},limitCanvas:function(t,i){var e=this.options,a=this.containerData,n=this.canvasData,o=this.cropBoxData,r=e.viewMode,h=n.aspectRatio,s=this.cropped&&o;if(t){var c=Number(e.minCanvasWidth)||0,l=Number(e.minCanvasHeight)||0;r>1?(c=Math.max(c,a.width),l=Math.max(l,a.height),3===r&&(l*h>c?c=l*h:l=c/h)):r>0&&(c?c=Math.max(c,s?o.width:0):l?l=Math.max(l,s?o.height:0):s&&(c=o.width,(l=o.height)*h>c?c=l*h:l=c/h));var d=W({aspectRatio:h,width:c,height:l});c=d.width,l=d.height,n.minWidth=c,n.minHeight=l,n.maxWidth=1/0,n.maxHeight=1/0}if(i)if(r){var p=a.width-n.width,m=a.height-n.height;n.minLeft=Math.min(0,p),n.minTop=Math.min(0,m),n.maxLeft=Math.max(0,p),n.maxTop=Math.max(0,m),s&&this.limited&&(n.minLeft=Math.min(o.left,o.left+(o.width-n.width)),n.minTop=Math.min(o.top,o.top+(o.height-n.height)),n.maxLeft=o.left,n.maxTop=o.top,2===r&&(n.width>=a.width&&(n.minLeft=Math.min(0,p),n.maxLeft=Math.max(0,p)),n.height>=a.height&&(n.minTop=Math.min(0,m),n.maxTop=Math.max(0,m))))}else n.minLeft=-n.width,n.minTop=-n.height,n.maxLeft=a.width,n.maxTop=a.height},renderCanvas:function(t,i){var e=this.canvasData,a=this.imageData;if(i){var n=N({width:a.naturalWidth*Math.abs(a.scaleX),height:a.naturalHeight*Math.abs(a.scaleY),degree:a.rotate}),o=n.width,h=n.height,c=e.width*(o/e.naturalWidth),l=e.height*(h/e.naturalHeight);e.left-=(c-e.width)/2,e.top-=(l-e.height)/2,e.width=c,e.height=l,e.aspectRatio=o/h,e.naturalWidth=o,e.naturalHeight=h,this.limitCanvas(!0,!1)}(e.width>e.maxWidth||e.widthe.maxHeight||e.heighti.width?n.height=n.width/e:n.width=n.height*e),this.cropBoxData=n,this.limitCropBox(!0,!0),n.width=Math.min(Math.max(n.width,n.minWidth),n.maxWidth),n.height=Math.min(Math.max(n.height,n.minHeight),n.maxHeight),n.width=Math.max(n.minWidth,n.width*a),n.height=Math.max(n.minHeight,n.height*a),n.left=i.left+(i.width-n.width)/2,n.top=i.top+(i.height-n.height)/2,n.oldLeft=n.left,n.oldTop=n.top,this.initialCropBoxData=r({},n)},limitCropBox:function(t,i){var e=this.options,a=this.containerData,n=this.canvasData,o=this.cropBoxData,r=this.limited,h=e.aspectRatio;if(t){var s=Number(e.minCropBoxWidth)||0,c=Number(e.minCropBoxHeight)||0,l=Math.min(a.width,r?n.width:a.width),d=Math.min(a.height,r?n.height:a.height);s=Math.min(s,a.width),c=Math.min(c,a.height),h&&(s&&c?c*h>s?c=s/h:s=c*h:s?c=s/h:c&&(s=c*h),d*h>l?d=l/h:l=d*h),o.minWidth=Math.min(s,l),o.minHeight=Math.min(c,d),o.maxWidth=l,o.maxHeight=d}i&&(r?(o.minLeft=Math.max(0,n.left),o.minTop=Math.max(0,n.top),o.maxLeft=Math.min(a.width,n.left+n.width)-o.width,o.maxTop=Math.min(a.height,n.top+n.height)-o.height):(o.minLeft=0,o.minTop=0,o.maxLeft=a.width-o.width,o.maxTop=a.height-o.height))},renderCropBox:function(){var t=this.options,i=this.containerData,e=this.cropBoxData;(e.width>e.maxWidth||e.widthe.maxHeight||e.height=i.width&&e.height>=i.height?"move":"all"),s(this.cropBox,r({width:e.width,height:e.height},D({translateX:e.left,translateY:e.top}))),this.cropped&&this.limited&&this.limitCanvas(!0,!0),this.disabled||this.output()},output:function(){this.preview(),this.complete&&b(this.element,"crop",this.getData())}},ct={initPreview:function(){var t=this.crossOrigin,i=this.options.preview,e=t?this.crossOriginUrl:this.url,a=document.createElement("img");if(t&&(a.crossOrigin=t),a.src=e,this.viewBox.appendChild(a),this.image2=a,i){var n=i.querySelector?[i]:document.querySelectorAll(i);this.previews=n,o(n,function(i){var a=document.createElement("img");g(i,"preview",{width:i.offsetWidth,height:i.offsetHeight,html:i.innerHTML}),t&&(a.crossOrigin=t),a.src=e,a.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;"',y(i),i.appendChild(a)})}},resetPreview:function(){o(this.previews,function(t){var i=u(t,"preview");s(t,{width:i.width,height:i.height}),t.innerHTML=i.html,f(t,"preview")})},preview:function(){var t=this.imageData,i=this.canvasData,e=this.cropBoxData,a=e.width,n=e.height,h=t.width,c=t.height,l=e.left-i.left-t.left,d=e.top-i.top-t.top;this.cropped&&!this.disabled&&(s(this.image2,r({width:h,height:c},D(r({translateX:-l,translateY:-d},t)))),o(this.previews,function(i){var e=u(i,"preview"),o=e.width,p=e.height,m=o,g=p,f=1;a&&(g=n*(f=o/a)),n&&g>p&&(m=a*(f=p/n),g=p),s(i,{width:m,height:g}),s(i.getElementsByTagName("img")[0],r({width:h*f,height:c*f},D(r({translateX:-l*f,translateY:-d*f},t))))}))}},lt={bind:function(){var t=this.element,i=this.options,e=this.cropper;n(i.cropstart)&&w(t,"cropstart",i.cropstart),n(i.cropmove)&&w(t,"cropmove",i.cropmove),n(i.cropend)&&w(t,"cropend",i.cropend),n(i.crop)&&w(t,"crop",i.crop),n(i.zoom)&&w(t,"zoom",i.zoom),w(e,I,this.onCropStart=h(this.cropStart,this)),i.zoomable&&i.zoomOnWheel&&w(e,"wheel mousewheel DOMMouseScroll",this.onWheel=h(this.wheel,this)),i.toggleDragModeOnDblclick&&w(e,"dblclick",this.onDblclick=h(this.dblclick,this)),w(document,U,this.onCropMove=h(this.cropMove,this)),w(document,j,this.onCropEnd=h(this.cropEnd,this)),i.responsive&&w(window,"resize",this.onResize=h(this.resize,this))},unbind:function(){var t=this.element,i=this.options,e=this.cropper;n(i.cropstart)&&v(t,"cropstart",i.cropstart),n(i.cropmove)&&v(t,"cropmove",i.cropmove),n(i.cropend)&&v(t,"cropend",i.cropend),n(i.crop)&&v(t,"crop",i.crop),n(i.zoom)&&v(t,"zoom",i.zoom),v(e,I,this.onCropStart),i.zoomable&&i.zoomOnWheel&&v(e,"wheel mousewheel DOMMouseScroll",this.onWheel),i.toggleDragModeOnDblclick&&v(e,"dblclick",this.onDblclick),v(document,U,this.onCropMove),v(document,j,this.onCropEnd),i.responsive&&v(window,"resize",this.onResize)}},dt={resize:function(){var t=this.options,i=this.container,e=this.containerData,a=Number(t.minContainerWidth)||200,n=Number(t.minContainerHeight)||100;if(!(this.disabled||e.width<=a||e.height<=n)){var r=i.offsetWidth/e.width;if(1!==r||i.offsetHeight!==e.height){var h=void 0,s=void 0;t.restore&&(h=this.getCanvasData(),s=this.getCropBoxData()),this.render(),t.restore&&(this.setCanvasData(o(h,function(t,i){h[i]=t*r})),this.setCropBoxData(o(s,function(t,i){s[i]=t*r})))}}},dblclick:function(){this.disabled||"none"===this.options.dragMode||this.setDragMode(c(this.dragBox,"cropper-crop")?"move":"crop")},wheel:function(t){var i=this,e=Number(this.options.wheelZoomRatio)||.1,a=1;this.disabled||(t.preventDefault(),this.wheeling||(this.wheeling=!0,setTimeout(function(){i.wheeling=!1},50),t.deltaY?a=t.deltaY>0?1:-1:t.wheelDelta?a=-t.wheelDelta/120:t.detail&&(a=t.detail>0?1:-1),this.zoom(-a*e,t)))},cropStart:function(t){if(!this.disabled){var i=this.options,e=this.pointers,a=void 0;t.changedTouches?o(t.changedTouches,function(t){e[t.identifier]=E(t)}):e[t.pointerId||0]=E(t),a=Object.keys(e).length>1&&i.zoomable&&i.zoomOnTouch?"zoom":u(t.target,"action"),P.test(a)&&!1!==b(this.element,"cropstart",{originalEvent:t,action:a})&&(t.preventDefault(),this.action=a,this.cropping=!1,"crop"===a&&(this.cropping=!0,l(this.dragBox,"cropper-modal")))}},cropMove:function(t){var i=this.action;if(!this.disabled&&i){var e=this.pointers;t.preventDefault(),!1!==b(this.element,"cropmove",{originalEvent:t,action:i})&&(t.changedTouches?o(t.changedTouches,function(t){r(e[t.identifier],E(t,!0))}):r(e[t.pointerId||0],E(t,!0)),this.change(t))}},cropEnd:function(t){if(!this.disabled){var i=this.action,e=this.pointers;t.changedTouches?o(t.changedTouches,function(t){delete e[t.identifier]}):delete e[t.pointerId||0],i&&(t.preventDefault(),Object.keys(e).length||(this.action=""),this.cropping&&(this.cropping=!1,p(this.dragBox,"cropper-modal",this.cropped&&this.options.modal)),b(this.element,"cropend",{originalEvent:t,action:i}))}}},pt={change:function(t){var i=this.options,e=this.canvasData,a=this.containerData,n=this.cropBoxData,r=this.pointers,h=this.action,s=i.aspectRatio,c=n.left,l=n.top,p=n.width,m=n.height,u=c+p,g=l+m,f=0,v=0,w=a.width,b=a.height,y=!0,M=void 0;!s&&t.shiftKey&&(s=p&&m?p/m:1),this.limited&&(f=n.minLeft,v=n.minTop,w=f+Math.min(a.width,e.width,e.left+e.width),b=v+Math.min(a.height,e.height,e.top+e.height));var C=r[Object.keys(r)[0]],D={x:C.endX-C.startX,y:C.endY-C.startY},B=function(t){switch(t){case"e":u+D.x>w&&(D.x=w-u);break;case"w":c+D.xb&&(D.y=b-g)}};switch(h){case"all":c+=D.x,l+=D.y;break;case"e":if(D.x>=0&&(u>=w||s&&(l<=v||g>=b))){y=!1;break}B("e"),p+=D.x,s&&(m=p/s,l-=D.x/s/2),p<0&&(h="w",p=0);break;case"n":if(D.y<=0&&(l<=v||s&&(c<=f||u>=w))){y=!1;break}B("n"),m-=D.y,l+=D.y,s&&(p=m*s,c+=D.y*s/2),m<0&&(h="s",m=0);break;case"w":if(D.x<=0&&(c<=f||s&&(l<=v||g>=b))){y=!1;break}B("w"),p-=D.x,c+=D.x,s&&(m=p/s,l+=D.x/s/2),p<0&&(h="e",p=0);break;case"s":if(D.y>=0&&(g>=b||s&&(c<=f||u>=w))){y=!1;break}B("s"),m+=D.y,s&&(p=m*s,c-=D.y*s/2),m<0&&(h="n",m=0);break;case"ne":if(s){if(D.y<=0&&(l<=v||u>=w)){y=!1;break}B("n"),m-=D.y,l+=D.y,p=m*s}else B("n"),B("e"),D.x>=0?uv&&(m-=D.y,l+=D.y):(m-=D.y,l+=D.y);p<0&&m<0?(h="sw",m=0,p=0):p<0?(h="nw",p=0):m<0&&(h="se",m=0);break;case"nw":if(s){if(D.y<=0&&(l<=v||c<=f)){y=!1;break}B("n"),m-=D.y,l+=D.y,p=m*s,c+=D.y*s}else B("n"),B("w"),D.x<=0?c>f?(p-=D.x,c+=D.x):D.y<=0&&l<=v&&(y=!1):(p-=D.x,c+=D.x),D.y<=0?l>v&&(m-=D.y,l+=D.y):(m-=D.y,l+=D.y);p<0&&m<0?(h="se",m=0,p=0):p<0?(h="ne",p=0):m<0&&(h="sw",m=0);break;case"sw":if(s){if(D.x<=0&&(c<=f||g>=b)){y=!1;break}B("w"),p-=D.x,c+=D.x,m=p/s}else B("s"),B("w"),D.x<=0?c>f?(p-=D.x,c+=D.x):D.y>=0&&g>=b&&(y=!1):(p-=D.x,c+=D.x),D.y>=0?g=0&&(u>=w||g>=b)){y=!1;break}B("e"),m=(p+=D.x)/s}else B("s"),B("e"),D.x>=0?u=0&&g>=b&&(y=!1):p+=D.x,D.y>=0?g0?h=D.y>0?"se":"ne":D.x<0&&(c-=p,h=D.y>0?"sw":"nw"),D.y<0&&(l-=m),this.cropped||(d(this.cropBox,A),this.cropped=!0,this.limited&&this.limitCropBox(!0,!0))}y&&(n.width=p,n.height=m,n.left=c,n.top=l,this.action=h,this.renderCropBox()),o(r,function(t){t.startX=t.endX,t.startY=t.endY})}},mt={crop:function(){return this.ready&&!this.disabled&&(this.cropped||(this.cropped=!0,this.limitCropBox(!0,!0),this.options.modal&&l(this.dragBox,"cropper-modal"),d(this.cropBox,A)),this.setCropBoxData(this.initialCropBoxData)),this},reset:function(){return this.ready&&!this.disabled&&(this.imageData=r({},this.initialImageData),this.canvasData=r({},this.initialCanvasData),this.cropBoxData=r({},this.initialCropBoxData),this.renderCanvas(),this.cropped&&this.renderCropBox()),this},clear:function(){return this.cropped&&!this.disabled&&(r(this.cropBoxData,{left:0,top:0,width:0,height:0}),this.cropped=!1,this.renderCropBox(),this.limitCanvas(!0,!0),this.renderCanvas(),d(this.dragBox,"cropper-modal"),l(this.cropBox,A)),this},replace:function(t){var i=arguments.length>1&&void 0!==arguments[1]&&arguments[1];return!this.disabled&&t&&(this.isImg&&(this.element.src=t),i?(this.url=t,this.image.src=t,this.ready&&(this.image2.src=t,o(this.previews,function(i){i.getElementsByTagName("img")[0].src=t}))):(this.isImg&&(this.replaced=!0),this.options.data=null,this.load(t))),this},enable:function(){return this.ready&&(this.disabled=!1,d(this.cropper,"cropper-disabled")),this},disable:function(){return this.ready&&(this.disabled=!0,l(this.cropper,"cropper-disabled")),this},destroy:function(){var t=this.element,i=this.image;return this.loaded?(this.isImg&&this.replaced&&(t.src=this.originalUrl),this.unbuild(),d(t,A)):this.isImg?v(t,"load",this.onStart):i&&i.parentNode.removeChild(i),f(t,"cropper"),this},move:function(t,e){var a=this.canvasData,n=a.left,o=a.top;return this.moveTo(i(t)?t:n+Number(t),i(e)?e:o+Number(e))},moveTo:function(i){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i,a=this.canvasData,n=!1;return i=Number(i),e=Number(e),this.ready&&!this.disabled&&this.options.movable&&(t(i)&&(a.left=i,n=!0),t(e)&&(a.top=e,n=!0),n&&this.renderCanvas(!0)),this},zoom:function(t,i){var e=this.canvasData;return t=Number(t),t=t<0?1/(1-t):1+t,this.zoomTo(e.width*t/e.naturalWidth,i)},zoomTo:function(t,i){var e=this.options,a=this.canvasData,n=a.width,o=a.height,r=a.naturalWidth,h=a.naturalHeight;if((t=Number(t))>=0&&this.ready&&!this.disabled&&e.zoomable){var s=r*t,c=h*t;if(!1===b(this.element,"zoom",{originalEvent:i,oldRatio:n/r,ratio:s/r}))return this;if(i){var l=this.pointers,d=x(this.cropper),p=l&&Object.keys(l).length?T(l):{pageX:i.pageX,pageY:i.pageY};a.left-=(s-n)*((p.pageX-d.left-a.left)/n),a.top-=(c-o)*((p.pageY-d.top-a.top)/o)}else a.left-=(s-n)/2,a.top-=(c-o)/2;a.width=s,a.height=c,this.renderCanvas(!0)}return this},rotate:function(t){return this.rotateTo((this.imageData.rotate||0)+Number(t))},rotateTo:function(i){return i=Number(i),t(i)&&this.ready&&!this.disabled&&this.options.rotatable&&(this.imageData.rotate=i%360,this.renderCanvas(!0,!0)),this},scaleX:function(i){var e=this.imageData.scaleY;return this.scale(i,t(e)?e:1)},scaleY:function(i){var e=this.imageData.scaleX;return this.scale(t(e)?e:1,i)},scale:function(i){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i,a=this.imageData,n=!1;return i=Number(i),e=Number(e),this.ready&&!this.disabled&&this.options.scalable&&(t(i)&&(a.scaleX=i,n=!0),t(e)&&(a.scaleY=e,n=!0),n&&this.renderCanvas(!0,!0)),this},getData:function(){var t=arguments.length>0&&void 0!==arguments[0]&&arguments[0],i=this.options,e=this.imageData,a=this.canvasData,n=this.cropBoxData,r=void 0;if(this.ready&&this.cropped){r={x:n.left-a.left,y:n.top-a.top,width:n.width,height:n.height};var h=e.width/e.naturalWidth;o(r,function(i,e){i/=h,r[e]=t?Math.round(i):i})}else r={x:0,y:0,width:0,height:0};return i.rotatable&&(r.rotate=e.rotate||0),i.scalable&&(r.scaleX=e.scaleX||1,r.scaleY=e.scaleY||1),r},setData:function(i){var e=this.options,o=this.imageData,r=this.canvasData,h={};if(n(i)&&(i=i.call(this.element)),this.ready&&!this.disabled&&a(i)){var s=!1;e.rotatable&&t(i.rotate)&&i.rotate!==o.rotate&&(o.rotate=i.rotate,s=!0),e.scalable&&(t(i.scaleX)&&i.scaleX!==o.scaleX&&(o.scaleX=i.scaleX,s=!0),t(i.scaleY)&&i.scaleY!==o.scaleY&&(o.scaleY=i.scaleY,s=!0)),s&&this.renderCanvas(!0,!0);var c=o.width/o.naturalWidth;t(i.x)&&(h.left=i.x*c+r.left),t(i.y)&&(h.top=i.y*c+r.top),t(i.width)&&(h.width=i.width*c),t(i.height)&&(h.height=i.height*c),this.setCropBoxData(h)}return this},getContainerData:function(){return this.ready?r({},this.containerData):{}},getImageData:function(){return this.loaded?r({},this.imageData):{}},getCanvasData:function(){var t=this.canvasData,i={};return this.ready&&o(["left","top","width","height","naturalWidth","naturalHeight"],function(e){i[e]=t[e]}),i},setCanvasData:function(i){var e=this.canvasData,o=e.aspectRatio;return n(i)&&(i=i.call(this.element)),this.ready&&!this.disabled&&a(i)&&(t(i.left)&&(e.left=i.left),t(i.top)&&(e.top=i.top),t(i.width)?(e.width=i.width,e.height=i.width/o):t(i.height)&&(e.height=i.height,e.width=i.height*o),this.renderCanvas(!0)),this},getCropBoxData:function(){var t=this.cropBoxData,i=void 0;return this.ready&&this.cropped&&(i={left:t.left,top:t.top,width:t.width,height:t.height}),i||{}},setCropBoxData:function(i){var e=this.cropBoxData,o=this.options.aspectRatio,r=void 0,h=void 0;return n(i)&&(i=i.call(this.element)),this.ready&&this.cropped&&!this.disabled&&a(i)&&(t(i.left)&&(e.left=i.left),t(i.top)&&(e.top=i.top),t(i.width)&&i.width!==e.width&&(r=!0,e.width=i.width),t(i.height)&&i.height!==e.height&&(h=!0,e.height=i.height),o&&(r?e.height=e.width/o:h&&(e.width=e.height*o)),this.renderCropBox()),this},getCroppedCanvas:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{};if(!this.ready||!window.HTMLCanvasElement)return null;var i=this.canvasData,e=H(this.image,this.imageData,i,t);if(!this.cropped)return e;var a=this.getData(),n=a.x,o=a.y,r=a.width,h=a.height,s=r/h,c=W({aspectRatio:s,width:t.maxWidth||1/0,height:t.maxHeight||1/0}),l=W({aspectRatio:s,width:t.minWidth||0,height:t.minHeight||0}),d=W({aspectRatio:s,width:t.width||r,height:t.height||h}),p=d.width,m=d.height;p=Math.min(c.width,Math.max(l.width,p)),m=Math.min(c.height,Math.max(l.height,m));var u=document.createElement("canvas"),g=u.getContext("2d");u.width=p,u.height=m,g.fillStyle=t.fillColor||"transparent",g.fillRect(0,0,p,m);var f=t.imageSmoothingEnabled,v=void 0===f||f,w=t.imageSmoothingQuality;g.imageSmoothingEnabled=v,w&&(g.imageSmoothingQuality=w);var b=e.width,x=e.height,y=n,M=o,C=void 0,D=void 0,B=void 0,k=void 0,E=void 0,T=void 0;y<=-r||y>b?(y=0,C=0,B=0,E=0):y<=0?(B=-y,y=0,E=C=Math.min(b,r+y)):y<=b&&(B=0,E=C=Math.min(r,b-y)),C<=0||M<=-h||M>x?(M=0,D=0,k=0,T=0):M<=0?(k=-M,M=0,T=D=Math.min(x,h+M)):M<=x&&(k=0,T=D=Math.min(h,x-M));var N=[Math.floor(y),Math.floor(M),Math.floor(C),Math.floor(D)];if(E>0&&T>0){var L=p/r;N.push(Math.floor(B*L),Math.floor(k*L),Math.floor(E*L),Math.floor(T*L))}return g.drawImage.apply(g,[e].concat(N)),u},setAspectRatio:function(t){var e=this.options;return this.disabled||i(t)||(e.aspectRatio=Math.max(0,t)||NaN,this.ready&&(this.initCropBox(),this.cropped&&this.renderCropBox())),this},setDragMode:function(t){var i=this.options,e=this.dragBox,a=this.face;if(this.loaded&&!this.disabled){var n="crop"===t,o=i.movable&&"move"===t;g(e,"action",t=n||o?t:"none"),p(e,"cropper-crop",n),p(e,"cropper-move",o),i.cropBoxMovable||(g(a,"action",t),p(a,"cropper-crop",n),p(a,"cropper-move",o))}return this}},ut=function(){function t(t,i){for(var e=0;e1&&void 0!==arguments[1]?arguments[1]:{};if(z(this,t),!i||!Q.test(i.tagName))throw new Error("The first argument is required and must be an or element.");this.element=i,this.options=r({},Z,a(e)&&e),this.complete=!1,this.cropped=!1,this.disabled=!1,this.isImg=!1,this.limited=!1,this.loaded=!1,this.ready=!1,this.replaced=!1,this.wheeling=!1,this.originalUrl="",this.canvasData=null,this.cropBoxData=null,this.previews=null,this.pointers={},this.init()}return ut(t,[{key:"init",value:function(){var t=this.element,i=t.tagName.toLowerCase(),e=void 0;if(!u(t,"cropper")){if(g(t,"cropper",this),"img"===i){if(this.isImg=!0,e=t.getAttribute("src"),this.originalUrl=e,!e)return;e=t.src}else"canvas"===i&&window.HTMLCanvasElement&&(e=t.toDataURL());this.load(e)}}},{key:"load",value:function(t){var i=this;if(t){this.url=t,this.imageData={};var e=this.element,a=this.options;if(a.checkOrientation&&window.ArrayBuffer)if(q.test(t))$.test(t)?this.read(Y(t)):this.clone();else{var n=new XMLHttpRequest;n.onerror=function(){i.clone()},n.onload=function(){i.read(n.response)},a.checkCrossOrigin&&M(t)&&e.crossOrigin&&(t=C(t)),n.open("get",t),n.responseType="arraybuffer",n.withCredentials="use-credentials"===e.crossOrigin,n.send()}else this.clone()}}},{key:"read",value:function(t){var i=this.options,e=this.imageData,a=O(t),n=0,o=1,r=1;if(a>1){this.url=X(t,"image/jpeg");var h=S(a);n=h.rotate,o=h.scaleX,r=h.scaleY}i.rotatable&&(e.rotate=n),i.scalable&&(e.scaleX=o,e.scaleY=r),this.clone()}},{key:"clone",value:function(){var t=this.element,i=this.url,e=void 0,a=void 0;this.options.checkCrossOrigin&&M(i)&&((e=t.crossOrigin)?a=i:(e="anonymous",a=C(i))),this.crossOrigin=e,this.crossOriginUrl=a;var n=document.createElement("img");e&&(n.crossOrigin=e),n.src=a||i;var o=h(this.start,this),r=h(this.stop,this);this.image=n,this.onStart=o,this.onStop=r,this.isImg?t.complete?this.start():w(t,"load",o):(w(n,"load",o),w(n,"error",r),l(n,"cropper-hide"),t.parentNode.insertBefore(n,t.nextSibling))}},{key:"start",value:function(t){var i=this,e=this.isImg?this.element:this.image;t&&(v(e,"load",this.onStart),v(e,"error",this.onStop)),B(e,function(t,e){r(i.imageData,{naturalWidth:t,naturalHeight:e,aspectRatio:t/e}),i.loaded=!0,i.build()})}},{key:"stop",value:function(){var t=this.image;v(t,"load",this.onStart),v(t,"error",this.onStop),t.parentNode.removeChild(t),this.image=null}},{key:"build",value:function(){var t=this;if(this.loaded){this.ready&&this.unbuild();var i=this.element,e=this.options,a=this.image,o=i.parentNode,r=document.createElement("div");r.innerHTML='
';var h=r.querySelector(".cropper-container"),s=h.querySelector(".cropper-canvas"),c=h.querySelector(".cropper-drag-box"),p=h.querySelector(".cropper-crop-box"),m=p.querySelector(".cropper-face");this.container=o,this.cropper=h,this.canvas=s,this.dragBox=c,this.cropBox=p,this.viewBox=h.querySelector(".cropper-view-box"),this.face=m,s.appendChild(a),l(i,A),o.insertBefore(h,i.nextSibling),this.isImg||d(a,"cropper-hide"),this.initPreview(),this.bind(),e.aspectRatio=Math.max(0,e.aspectRatio)||NaN,e.viewMode=Math.max(0,Math.min(3,Math.round(e.viewMode)))||0,this.cropped=e.autoCrop,e.autoCrop?e.modal&&l(c,"cropper-modal"):l(p,A),e.guides||l(p.getElementsByClassName("cropper-dashed"),A),e.center||l(p.getElementsByClassName("cropper-center"),A),e.background&&l(h,"cropper-bg"),e.highlight||l(m,"cropper-invisible"),e.cropBoxMovable&&(l(m,"cropper-move"),g(m,"action","all")),e.cropBoxResizable||(l(p.getElementsByClassName("cropper-line"),A),l(p.getElementsByClassName("cropper-point"),A)),this.setDragMode(e.dragMode),this.render(),this.ready=!0,this.setData(e.data),this.completing=setTimeout(function(){n(e.ready)&&w(i,"ready",e.ready,{once:!0}),b(i,"ready"),b(i,"crop",t.getData()),t.complete=!0},0)}}},{key:"unbuild",value:function(){this.ready&&(this.complete||clearTimeout(this.completing),this.ready=!1,this.complete=!1,this.initialImageData=null,this.initialCanvasData=null,this.initialCropBoxData=null,this.containerData=null,this.canvasData=null,this.cropBoxData=null,this.unbind(),this.resetPreview(),this.previews=null,this.viewBox=null,this.cropBox=null,this.dragBox=null,this.canvas=null,this.container=null,this.cropper.parentNode.removeChild(this.cropper),this.cropper=null)}}],[{key:"noConflict",value:function(){return window.Cropper=gt,t}},{key:"setDefaults",value:function(t){r(Z,a(t)&&t)}}]),t}();return r(ft.prototype,st,ct,lt,dt,pt,mt),ft}); \ No newline at end of file diff --git a/docs/css/cropper.css b/docs/css/cropper.css index 9237cdf51..4468e7f36 100644 --- a/docs/css/cropper.css +++ b/docs/css/cropper.css @@ -1,11 +1,11 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:10:57.634Z */ .cropper-container { @@ -14,15 +14,15 @@ line-height: 0; position: relative; -ms-touch-action: none; - touch-action: none; + touch-action: none; -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } -.cropper-container img { - /* Avoid margin top issue (Occur only when margin-top <= -height) */ +.cropper-container img {/*Avoid margin top issue (Occur only when margin-top <= -height) + */ display: block; height: 100%; image-orientation: 0deg; @@ -45,7 +45,8 @@ top: 0; } -.cropper-wrap-box { +.cropper-wrap-box, +.cropper-canvas { overflow: hidden; } @@ -72,7 +73,7 @@ border: 0 dashed #eee; display: block; opacity: .5; - position: absolute + position: absolute; } .cropper-dashed.dashed-h { @@ -100,11 +101,11 @@ opacity: .75; position: absolute; top: 50%; - width: 0 + width: 0; } .cropper-center:before, - .cropper-center:after { +.cropper-center:after { background-color: #eee; content: ' '; display: block; @@ -142,7 +143,7 @@ } .cropper-line { - background-color: #39f + background-color: #39f; } .cropper-line.line-e { @@ -177,7 +178,7 @@ background-color: #39f; height: 5px; opacity: .75; - width: 5px + width: 5px; } .cropper-point.point-e { @@ -236,27 +237,24 @@ } @media (min-width: 768px) { - .cropper-point.point-se { height: 15px; - width: 15px + width: 15px; } } @media (min-width: 992px) { - .cropper-point.point-se { height: 10px; - width: 10px + width: 10px; } } @media (min-width: 1200px) { - .cropper-point.point-se { height: 5px; opacity: .75; - width: 5px + width: 5px; } } diff --git a/docs/index.html b/docs/index.html index 95c973ea2..5f7f17e14 100644 --- a/docs/index.html +++ b/docs/index.html @@ -47,7 +47,7 @@
-

Cropper.js v1.0.0

+

Cropper.js v1.1.0

JavaScript image cropper.

@@ -524,7 +524,7 @@
- Photo Editor + Photo Editor
diff --git a/docs/js/cropper.js b/docs/js/cropper.js index 1a79cc597..1052f8f35 100644 --- a/docs/js/cropper.js +++ b/docs/js/cropper.js @@ -1,11 +1,11 @@ /*! - * Cropper.js v1.0.0 + * Cropper.js v1.1.0 * https://github.com/fengyuanchen/cropperjs * - * Copyright (c) 2017 Fengyuan Chen + * Copyright (c) 2015-2017 Fengyuan Chen * Released under the MIT license * - * Date: 2017-09-03T12:52:44.102Z + * Date: 2017-10-08T09:11:03.372Z */ (function (global, factory) { @@ -14,12 +14,72 @@ (global.Cropper = factory()); }(this, (function () { 'use strict'; +var _window = window; +var PointerEvent = _window.PointerEvent; + + +var NAMESPACE = 'cropper'; + +// Actions +var ACTION_ALL = 'all'; +var ACTION_CROP = 'crop'; +var ACTION_MOVE = 'move'; +var ACTION_ZOOM = 'zoom'; +var ACTION_EAST = 'e'; +var ACTION_WEST = 'w'; +var ACTION_SOUTH = 's'; +var ACTION_NORTH = 'n'; +var ACTION_NORTH_EAST = 'ne'; +var ACTION_NORTH_WEST = 'nw'; +var ACTION_SOUTH_EAST = 'se'; +var ACTION_SOUTH_WEST = 'sw'; + +// Classes +var CLASS_CROP = NAMESPACE + '-crop'; +var CLASS_DISABLED = NAMESPACE + '-disabled'; +var CLASS_HIDDEN = NAMESPACE + '-hidden'; +var CLASS_HIDE = NAMESPACE + '-hide'; +var CLASS_INVISIBLE = NAMESPACE + '-invisible'; +var CLASS_MODAL = NAMESPACE + '-modal'; +var CLASS_MOVE = NAMESPACE + '-move'; + +// Data keys +var DATA_ACTION = 'action'; +var DATA_PREVIEW = 'preview'; + +// Drag modes +var DRAG_MODE_CROP = 'crop'; +var DRAG_MODE_MOVE = 'move'; +var DRAG_MODE_NONE = 'none'; + +// Events +var EVENT_CROP = 'crop'; +var EVENT_CROP_END = 'cropend'; +var EVENT_CROP_MOVE = 'cropmove'; +var EVENT_CROP_START = 'cropstart'; +var EVENT_DBLCLICK = 'dblclick'; +var EVENT_ERROR = 'error'; +var EVENT_LOAD = 'load'; +var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; +var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; +var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; +var EVENT_READY = 'ready'; +var EVENT_RESIZE = 'resize'; +var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; +var EVENT_ZOOM = 'zoom'; + +// RegExps +var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; +var REGEXP_DATA_URL = /^data:/; +var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; +var REGEXP_TAG_NAME = /^(img|canvas)$/i; + var DEFAULTS = { // Define the view mode of the cropper viewMode: 0, // 0, 1, 2, 3 // Define the dragging mode of the cropper - dragMode: 'crop', // 'crop', 'move' or 'none' + dragMode: DRAG_MODE_CROP, // 'crop', 'move' or 'none' // Define the aspect ratio of the crop box aspectRatio: NaN, @@ -114,94 +174,105 @@ var TEMPLATE = '
' + '
1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) { args[_key - 1] = arguments[_key]; @@ -224,6 +295,12 @@ function extend(obj) { return obj; } +/** + * Takes a function and returns a new one that will always have a particular context. + * @param {Function} fn - The target function. + * @param {Object} context - The new context for the function. + * @returns {boolean} The new function. + */ function proxy(fn, context) { for (var _len2 = arguments.length, args = Array(_len2 > 2 ? _len2 - 2 : 0), _key2 = 2; _key2 < _len2; _key2++) { args[_key2 - 2] = arguments[_key2]; @@ -238,9 +315,17 @@ function proxy(fn, context) { }; } +var REGEXP_SUFFIX = /^(width|height|left|top|marginLeft|marginTop)$/; + +/** + * Apply styles to the given element. + * @param {Element} element - The target element. + * @param {Object} styles - The styles for applying. + */ function setStyle(element, styles) { var style = element.style; + each(styles, function (value, property) { if (REGEXP_SUFFIX.test(property) && isNumber(value)) { value += 'px'; @@ -250,10 +335,21 @@ function setStyle(element, styles) { }); } +/** + * Check if the given element has a special class. + * @param {Element} element - The element to check. + * @param {string} value - The class to search. + * @returns {boolean} Returns `true` if the special class was found. + */ function hasClass(element, value) { return element.classList ? element.classList.contains(value) : element.className.indexOf(value) > -1; } +/** + * Add classes to the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be added. + */ function addClass(element, value) { if (!value) { return; @@ -271,7 +367,7 @@ function addClass(element, value) { return; } - var className = trim(element.className); + var className = element.className.trim(); if (!className) { element.className = value; @@ -280,6 +376,11 @@ function addClass(element, value) { } } +/** + * Remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be removed. + */ function removeClass(element, value) { if (!value) { return; @@ -302,6 +403,12 @@ function removeClass(element, value) { } } +/** + * Add or remove classes from the given element. + * @param {Element} element - The target element. + * @param {string} value - The classes to be toggled. + * @param {boolean} added - Add only. + */ function toggleClass(element, value, added) { if (!value) { return; @@ -322,10 +429,23 @@ function toggleClass(element, value, added) { } } -function hyphenate(str) { - return str.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); +var REGEXP_HYPHENATE = /([a-z\d])([A-Z])/g; + +/** + * Hyphenate the given value. + * @param {string} value - The value to hyphenate. + * @returns {string} The hyphenated value. + */ +function hyphenate(value) { + return value.replace(REGEXP_HYPHENATE, '$1-$2').toLowerCase(); } +/** + * Get data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to get. + * @returns {string} The data value. + */ function getData(element, name) { if (isObject(element[name])) { return element[name]; @@ -336,6 +456,12 @@ function getData(element, name) { return element.getAttribute('data-' + hyphenate(name)); } +/** + * Set data to the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to set. + * @param {string} data - The data value. + */ function setData(element, name, data) { if (isObject(data)) { element[name] = data; @@ -346,6 +472,11 @@ function setData(element, name, data) { } } +/** + * Remove data from the given element. + * @param {Element} element - The target element. + * @param {string} name - The data key to remove. + */ function removeData(element, name) { if (isObject(element[name])) { delete element[name]; @@ -361,53 +492,86 @@ function removeData(element, name) { } } -function removeListener(element, type, handler) { - var types = trim(type).split(REGEXP_SPACES); +var REGEXP_SPACES = /\s+/; + +/** + * Remove event listener from the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to remove, + * @param {Function} listener - The event listener to remove. + * @param {Object} options - The event options. + */ +function removeListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - removeListener(element, t, handler); + removeListener(element, t, listener); }); return; } + if (isFunction(listener.onceListener)) { + listener = listener.onceListener; + delete listener.onceListener; + } + if (element.removeEventListener) { - element.removeEventListener(type, handler, false); + element.removeEventListener(type, listener, options); } else if (element.detachEvent) { - element.detachEvent('on' + type, handler); + element.detachEvent('on' + type, listener); } } -function addListener(element, type, _handler, once) { - var types = trim(type).split(REGEXP_SPACES); - var originalHandler = _handler; +/** + * Add event listener to the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to add, + * @param {Function} listener - The event listener to add. + * @param {Object} options - The event options. + */ +function addListener(element, type, listener) { + var options = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; + + var types = type.trim().split(REGEXP_SPACES); if (types.length > 1) { each(types, function (t) { - addListener(element, t, _handler); + addListener(element, t, listener); }); return; } - if (once) { - _handler = function handler() { + if (options.once) { + var originalListener = listener; + var onceListener = function onceListener() { for (var _len4 = arguments.length, args = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) { args[_key4] = arguments[_key4]; } - removeListener(element, type, _handler); - - return originalHandler.apply(element, args); + removeListener(element, type, onceListener); + return originalListener.apply(element, args); }; + originalListener.onceListener = onceListener; + listener = onceListener; } if (element.addEventListener) { - element.addEventListener(type, _handler, false); + element.addEventListener(type, listener, options); } else if (element.attachEvent) { - element.attachEvent('on' + type, _handler); + element.attachEvent('on' + type, listener); } } +/** + * Dispatch event on the given element. + * @param {Element} element - The target element. + * @param {string} type - The event type(s) to dispatch, + * @param {Object} data - The additional event data. + * @returns {boolean} Indicate if the event is default prevented or not. + */ function dispatchEvent(element, type, data) { if (element.dispatchEvent) { var event = void 0; @@ -444,26 +608,11 @@ function dispatchEvent(element, type, data) { return true; } -function getEvent(event) { - var e = event || window.event; - - // Fix target property (IE8) - if (!e.target) { - e.target = e.srcElement || document; - } - - if (!isNumber(e.pageX) && isNumber(e.clientX)) { - var eventDoc = event.target.ownerDocument || document; - var doc = eventDoc.documentElement; - var body = eventDoc.body; - - e.pageX = e.clientX + ((doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0)); - e.pageY = e.clientY + ((doc && doc.scrollTop || body && body.scrollTop || 0) - (doc && doc.clientTop || body && body.clientTop || 0)); - } - - return e; -} - +/** + * Get the offset base on the document. + * @param {Element} element - The target element. + * @returns {Object} The offset data. + */ function getOffset(element) { var doc = document.documentElement; var box = element.getBoundingClientRect(); @@ -474,93 +623,79 @@ function getOffset(element) { }; } -function getByTag(element, tagName) { - return element.getElementsByTagName(tagName); -} - -function getByClass(element, className) { - return element.getElementsByClassName ? element.getElementsByClassName(className) : element.querySelectorAll('.' + className); -} - -function createElement(tagName) { - return document.createElement(tagName); -} - -function appendChild(element, elem) { - element.appendChild(elem); -} - -function removeChild(element) { - if (element.parentNode) { - element.parentNode.removeChild(element); - } -} - +/** + * Empty an element. + * @param {Element} element - The element to empty. + */ function empty(element) { while (element.firstChild) { element.removeChild(element.firstChild); } } +var _window$1 = window; +var location = _window$1.location; + +var REGEXP_ORIGINS = /^(https?:)\/\/([^:/?#]+):?(\d*)/i; + +/** + * Check if the given URL is a cross origin URL. + * @param {string} url - The target URL. + * @returns {boolean} Returns `true` if the given URL is a cross origin URL, else `false`. + */ function isCrossOriginURL(url) { var parts = url.match(REGEXP_ORIGINS); return parts && (parts[1] !== location.protocol || parts[2] !== location.hostname || parts[3] !== location.port); } +/** + * Add timestamp to the given URL. + * @param {string} url - The target URL. + * @returns {string} The result URL. + */ function addTimestamp(url) { var timestamp = 'timestamp=' + new Date().getTime(); return url + (url.indexOf('?') === -1 ? '?' : '&') + timestamp; } -function getImageSize(image, callback) { - // Modern browsers (ignore Safari) - if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { - callback(image.naturalWidth, image.naturalHeight); - return; - } - - // IE8: Don't use `new Image()` here - var newImage = createElement('img'); - - newImage.onload = function load() { - callback(this.width, this.height); - }; - - newImage.src = image.src; -} +/** + * Get transforms base on the given object. + * @param {Object} obj - The target object. + * @returns {string} A string contains transform values. + */ +function getTransforms(_ref) { + var rotate = _ref.rotate, + scaleX = _ref.scaleX, + scaleY = _ref.scaleY, + translateX = _ref.translateX, + translateY = _ref.translateY; -function getTransforms(data) { - var transforms = []; - var translateX = data.translateX; - var translateY = data.translateY; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; + var values = []; if (isNumber(translateX) && translateX !== 0) { - transforms.push('translateX(' + translateX + 'px)'); + values.push('translateX(' + translateX + 'px)'); } if (isNumber(translateY) && translateY !== 0) { - transforms.push('translateY(' + translateY + 'px)'); + values.push('translateY(' + translateY + 'px)'); } // Rotate should come first before scale to match orientation transform if (isNumber(rotate) && rotate !== 0) { - transforms.push('rotate(' + rotate + 'deg)'); + values.push('rotate(' + rotate + 'deg)'); } if (isNumber(scaleX) && scaleX !== 1) { - transforms.push('scaleX(' + scaleX + ')'); + values.push('scaleX(' + scaleX + ')'); } if (isNumber(scaleY) && scaleY !== 1) { - transforms.push('scaleY(' + scaleY + ')'); + values.push('scaleY(' + scaleY + ')'); } - var transform = transforms.length ? transforms.join(' ') : 'none'; + var transform = values.length ? values.join(' ') : 'none'; return { WebkitTransform: transform, @@ -569,136 +704,326 @@ function getTransforms(data) { }; } -function getRotatedSizes(data, reversed) { - var deg = Math.abs(data.degree) % 180; - var arc = (deg > 90 ? 180 - deg : deg) * Math.PI / 180; - var sinArc = Math.sin(arc); - var cosArc = Math.cos(arc); - var width = data.width; - var height = data.height; - var aspectRatio = data.aspectRatio; - var newWidth = void 0; - var newHeight = void 0; - - if (!reversed) { - newWidth = width * cosArc + height * sinArc; - newHeight = width * sinArc + height * cosArc; - } else { - newWidth = width / (cosArc + sinArc / aspectRatio); - newHeight = newWidth / aspectRatio; +var IS_SAFARI_OR_UIWEBVIEW = navigator && /(Macintosh|iPhone|iPod|iPad).*AppleWebKit/i.test(navigator.userAgent); + +/** + * Get an image's natural sizes. + * @param {string} image - The target image. + * @param {Function} callback - The callback function. + */ +function getImageNaturalSizes(image, callback) { + // Modern browsers (except Safari) + if (image.naturalWidth && !IS_SAFARI_OR_UIWEBVIEW) { + callback(image.naturalWidth, image.naturalHeight); + return; } - return { - width: newWidth, - height: newHeight + var newImage = document.createElement('img'); + + newImage.onload = function () { + callback(newImage.width, newImage.height); }; + + newImage.src = image.src; } -function getSourceCanvas(image, data, options) { - var canvas = createElement('canvas'); - var context = canvas.getContext('2d'); - var dstX = 0; - var dstY = 0; - var dstWidth = data.naturalWidth; - var dstHeight = data.naturalHeight; - var rotate = data.rotate; - var scaleX = data.scaleX; - var scaleY = data.scaleY; - var scalable = isNumber(scaleX) && isNumber(scaleY) && (scaleX !== 1 || scaleY !== 1); - var rotatable = isNumber(rotate) && rotate !== 0; - var advanced = rotatable || scalable; - var canvasWidth = dstWidth * Math.abs(scaleX || 1); - var canvasHeight = dstHeight * Math.abs(scaleY || 1); - var translateX = void 0; - var translateY = void 0; - var rotated = void 0; - - if (scalable) { - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } +/** + * Get the max ratio of a group of pointers. + * @param {string} pointers - The target pointers. + * @returns {number} The result ratio. + */ +function getMaxZoomRatio(pointers) { + var pointers2 = extend({}, pointers); + var ratios = []; - if (rotatable) { - rotated = getRotatedSizes({ - width: canvasWidth, - height: canvasHeight, - degree: rotate + each(pointers, function (pointer, pointerId) { + delete pointers2[pointerId]; + + each(pointers2, function (pointer2) { + var x1 = Math.abs(pointer.startX - pointer2.startX); + var y1 = Math.abs(pointer.startY - pointer2.startY); + var x2 = Math.abs(pointer.endX - pointer2.endX); + var y2 = Math.abs(pointer.endY - pointer2.endY); + var z1 = Math.sqrt(x1 * x1 + y1 * y1); + var z2 = Math.sqrt(x2 * x2 + y2 * y2); + var ratio = (z2 - z1) / z1; + + ratios.push(ratio); }); + }); - canvasWidth = rotated.width; - canvasHeight = rotated.height; - translateX = canvasWidth / 2; - translateY = canvasHeight / 2; - } + ratios.sort(function (a, b) { + return Math.abs(a) < Math.abs(b); + }); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + return ratios[0]; +} - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); - } +/** + * Get a pointer from an event object. + * @param {Object} event - The target event object. + * @param {boolean} endOnly - Indicates if only returns the end point coordinate or not. + * @returns {Object} The result pointer contains start and/or end point coordinates. + */ +function getPointer(_ref2, endOnly) { + var pageX = _ref2.pageX, + pageY = _ref2.pageY; - if (advanced) { - dstX = -dstWidth / 2; - dstY = -dstHeight / 2; + var end = { + endX: pageX, + endY: pageY + }; - context.save(); - context.translate(translateX, translateY); + if (endOnly) { + return end; } - // Rotate should come first before scale as in the "getTransform" function - if (rotatable) { - context.rotate(rotate * Math.PI / 180); - } + return extend({ + startX: pageX, + startY: pageY + }, end); +} - if (scalable) { - context.scale(scaleX, scaleY); - } +/** + * Get the center point coordinate of a group of pointers. + * @param {Object} pointers - The target pointers. + * @returns {Object} The center point coordinate. + */ +function getPointersCenter(pointers) { + var pageX = 0; + var pageY = 0; + var count = 0; - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; + each(pointers, function (_ref3) { + var startX = _ref3.startX, + startY = _ref3.startY; + + pageX += startX; + pageY += startY; + count += 1; + }); + + pageX /= count; + pageY /= count; + + return { + pageX: pageX, + pageY: pageY + }; +} + +/** + * Check if the given value is a finite number. + */ +var isFinite = Number.isFinite || window.isFinite; + +/** + * Get the max sizes in a rectangle under the given aspect ratio. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getContainSizes(_ref4) { + var aspectRatio = _ref4.aspectRatio, + height = _ref4.height, + width = _ref4.width; - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; + var isValidNumber = function isValidNumber(value) { + return isFinite(value) && value > 0; + }; + + if (isValidNumber(width) && isValidNumber(height)) { + if (height * aspectRatio > width) { + height = width / aspectRatio; + } else { + width = height * aspectRatio; + } + } else if (isValidNumber(width)) { + height = width / aspectRatio; + } else if (isValidNumber(height)) { + width = height * aspectRatio; } - context.drawImage(image, Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); + return { + width: width, + height: height + }; +} + +/** + * Get the new sizes of a rectangle after rotated. + * @param {Object} data - The original sizes. + * @returns {Object} The result sizes. + */ +function getRotatedSizes(_ref5) { + var width = _ref5.width, + height = _ref5.height, + degree = _ref5.degree; - if (advanced) { - context.restore(); + degree = Math.abs(degree); + + if (degree % 180 === 90) { + return { + width: height, + height: width + }; } + var arc = degree % 90 * Math.PI / 180; + var sinArc = Math.sin(arc); + var cosArc = Math.cos(arc); + + return { + width: width * cosArc + height * sinArc, + height: width * sinArc + height * cosArc + }; +} + +/** + * Get a canvas which drew the given image. + * @param {HTMLImageElement} image - The image for drawing. + * @param {Object} imageData - The image data. + * @param {Object} canvasData - The canvas data. + * @param {Object} options - The options. + * @returns {HTMLCanvasElement} The result canvas. + */ +function getSourceCanvas(image, _ref6, _ref7, _ref8) { + var imageNaturalWidth = _ref6.naturalWidth, + imageNaturalHeight = _ref6.naturalHeight, + rotate = _ref6.rotate, + scaleX = _ref6.scaleX, + scaleY = _ref6.scaleY; + var aspectRatio = _ref7.aspectRatio, + naturalWidth = _ref7.naturalWidth, + naturalHeight = _ref7.naturalHeight; + var _ref8$fillColor = _ref8.fillColor, + fillColor = _ref8$fillColor === undefined ? 'transparent' : _ref8$fillColor, + _ref8$imageSmoothingE = _ref8.imageSmoothingEnabled, + imageSmoothingEnabled = _ref8$imageSmoothingE === undefined ? true : _ref8$imageSmoothingE, + _ref8$imageSmoothingQ = _ref8.imageSmoothingQuality, + imageSmoothingQuality = _ref8$imageSmoothingQ === undefined ? 'low' : _ref8$imageSmoothingQ, + _ref8$maxWidth = _ref8.maxWidth, + maxWidth = _ref8$maxWidth === undefined ? Infinity : _ref8$maxWidth, + _ref8$maxHeight = _ref8.maxHeight, + maxHeight = _ref8$maxHeight === undefined ? Infinity : _ref8$maxHeight, + _ref8$minWidth = _ref8.minWidth, + minWidth = _ref8$minWidth === undefined ? 0 : _ref8$minWidth, + _ref8$minHeight = _ref8.minHeight, + minHeight = _ref8$minHeight === undefined ? 0 : _ref8$minHeight; + + var canvas = document.createElement('canvas'); + var context = canvas.getContext('2d'); + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: maxWidth, + height: maxHeight + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minWidth, + height: minHeight + }); + var width = Math.min(maxSizes.width, Math.max(minSizes.width, naturalWidth)); + var height = Math.min(maxSizes.height, Math.max(minSizes.height, naturalHeight)); + + canvas.width = width; + canvas.height = height; + context.fillStyle = fillColor; + context.fillRect(0, 0, width, height); + context.save(); + context.translate(width / 2, height / 2); + context.rotate(rotate * Math.PI / 180); + context.scale(scaleX, scaleY); + context.imageSmoothingEnabled = imageSmoothingEnabled; + context.imageSmoothingQuality = imageSmoothingQuality; + context.drawImage(image, Math.floor(-imageNaturalWidth / 2), Math.floor(-imageNaturalHeight / 2), Math.floor(imageNaturalWidth), Math.floor(imageNaturalHeight)); + context.restore(); return canvas; } +var fromCharCode = String.fromCharCode; + +/** + * Get string from char code in data view. + * @param {DataView} dataView - The data view for read. + * @param {number} start - The start index. + * @param {number} length - The read length. + * @returns {string} The read result. + */ + function getStringFromCharCode(dataView, start, length) { var str = ''; - var i = start; + var i = void 0; + + length += start; - for (length += start; i < length; i += 1) { + for (i = start; i < length; i += 1) { str += fromCharCode(dataView.getUint8(i)); } return str; } +var _window2 = window; +var atob = _window2.atob; + +var REGEXP_DATA_URL_HEAD = /^data:.*,/; + +/** + * Transform Data URL to array buffer. + * @param {string} dataURL - The Data URL to transform. + * @returns {ArrayBuffer} The result array buffer. + */ +function dataURLToArrayBuffer(dataURL) { + var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); + var binary = atob(base64); + var arrayBuffer = new ArrayBuffer(binary.length); + var uint8 = new Uint8Array(arrayBuffer); + + each(uint8, function (value, i) { + uint8[i] = binary.charCodeAt(i); + }); + + return arrayBuffer; +} + +var _window3 = window; +var btoa = _window3.btoa; + +/** + * Transform array buffer to Data URL. + * @param {ArrayBuffer} arrayBuffer - The array buffer to transform. + * @param {string} mimeType - The mime type of the Data URL. + * @returns {string} The result Data URL. + */ + +function arrayBufferToDataURL(arrayBuffer, mimeType) { + var uint8 = new Uint8Array(arrayBuffer); + var data = ''; + + // TypedArray.prototype.forEach is not supported in some browsers. + each(uint8, function (value) { + data += fromCharCode(value); + }); + + return 'data:' + mimeType + ';base64,' + btoa(data); +} + +/** + * Get orientation value from given array buffer. + * @param {ArrayBuffer} arrayBuffer - The array buffer to read. + * @returns {number} The read orientation value. + */ function getOrientation(arrayBuffer) { var dataView = new DataView(arrayBuffer); - var length = dataView.byteLength; var orientation = void 0; - var exifIDCode = void 0; - var tiffOffset = void 0; - var firstIFDOffset = void 0; var littleEndian = void 0; - var endianness = void 0; var app1Start = void 0; var ifdStart = void 0; - var offset = void 0; - var i = void 0; // Only handle JPEG image (start by 0xFFD8) if (dataView.getUint8(0) === 0xFF && dataView.getUint8(1) === 0xD8) { - offset = 2; + var length = dataView.byteLength; + var offset = 2; while (offset < length) { if (dataView.getUint8(offset) === 0xFF && dataView.getUint8(offset + 1) === 0xE1) { @@ -711,16 +1036,17 @@ function getOrientation(arrayBuffer) { } if (app1Start) { - exifIDCode = app1Start + 4; - tiffOffset = app1Start + 10; + var exifIDCode = app1Start + 4; + var tiffOffset = app1Start + 10; if (getStringFromCharCode(dataView, exifIDCode, 4) === 'Exif') { - endianness = dataView.getUint16(tiffOffset); + var endianness = dataView.getUint16(tiffOffset); + littleEndian = endianness === 0x4949; if (littleEndian || endianness === 0x4D4D /* bigEndian */) { if (dataView.getUint16(tiffOffset + 2, littleEndian) === 0x002A) { - firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); + var firstIFDOffset = dataView.getUint32(tiffOffset + 4, littleEndian); if (firstIFDOffset >= 0x00000008) { ifdStart = tiffOffset + firstIFDOffset; @@ -731,23 +1057,22 @@ function getOrientation(arrayBuffer) { } if (ifdStart) { - length = dataView.getUint16(ifdStart, littleEndian); + var _length = dataView.getUint16(ifdStart, littleEndian); + var _offset = void 0; + var i = void 0; - for (i = 0; i < length; i += 1) { - offset = ifdStart + i * 12 + 2; + for (i = 0; i < _length; i += 1) { + _offset = ifdStart + i * 12 + 2; - if (dataView.getUint16(offset, littleEndian) === 0x0112 /* Orientation */) { + if (dataView.getUint16(_offset, littleEndian) === 0x0112 /* Orientation */) { // 8 is the offset of the current tag's value - offset += 8; + _offset += 8; // Get the original orientation value - orientation = dataView.getUint16(offset, littleEndian); - - // Override the orientation with its default value for Safari - if (IS_SAFARI_OR_UIWEBVIEW) { - dataView.setUint16(offset, 1, littleEndian); - } + orientation = dataView.getUint16(_offset, littleEndian); + // Override the orientation with its default value + dataView.setUint16(_offset, 1, littleEndian); break; } } @@ -756,83 +1081,108 @@ function getOrientation(arrayBuffer) { return orientation; } -function dataURLToArrayBuffer(dataURL) { - var base64 = dataURL.replace(REGEXP_DATA_URL_HEAD, ''); - var binary = atob(base64); - var length = binary.length; - var arrayBuffer = new ArrayBuffer(length); - var dataView = new Uint8Array(arrayBuffer); - var i = void 0; - - for (i = 0; i < length; i += 1) { - dataView[i] = binary.charCodeAt(i); - } - - return arrayBuffer; -} - -// Only available for JPEG image -function arrayBufferToDataURL(arrayBuffer) { - var dataView = new Uint8Array(arrayBuffer); - var length = dataView.length; - var base64 = ''; - var i = void 0; - - for (i = 0; i < length; i += 1) { - base64 += fromCharCode(dataView[i]); +/** + * Parse Exif Orientation value. + * @param {number} orientation - The orientation to parse. + * @returns {Object} The parsed result. + */ +function parseOrientation(orientation) { + var rotate = 0; + var scaleX = 1; + var scaleY = 1; + + switch (orientation) { + // Flip horizontal + case 2: + scaleX = -1; + break; + + // Rotate left 180° + case 3: + rotate = -180; + break; + + // Flip vertical + case 4: + scaleY = -1; + break; + + // Flip vertical and rotate right 90° + case 5: + rotate = 90; + scaleY = -1; + break; + + // Rotate right 90° + case 6: + rotate = 90; + break; + + // Flip horizontal and rotate right 90° + case 7: + rotate = 90; + scaleX = -1; + break; + + // Rotate left 90° + case 8: + rotate = -90; + break; + + default: } - return 'data:image/jpeg;base64,' + btoa(base64); + return { + rotate: rotate, + scaleX: scaleX, + scaleY: scaleY + }; } var render = { render: function render() { - var self = this; - - self.initContainer(); - self.initCanvas(); - self.initCropBox(); + this.initContainer(); + this.initCanvas(); + this.initCropBox(); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } }, initContainer: function initContainer() { - var self = this; - var options = self.options; - var element = self.element; - var container = self.container; - var cropper = self.cropper; - var hidden = 'cropper-hidden'; + var element = this.element, + options = this.options, + container = this.container, + cropper = this.cropper; + - addClass(cropper, hidden); - removeClass(element, hidden); + addClass(cropper, CLASS_HIDDEN); + removeClass(element, CLASS_HIDDEN); var containerData = { width: Math.max(container.offsetWidth, Number(options.minContainerWidth) || 200), height: Math.max(container.offsetHeight, Number(options.minContainerHeight) || 100) }; - self.containerData = containerData; + this.containerData = containerData; setStyle(cropper, { width: containerData.width, height: containerData.height }); - addClass(element, hidden); - removeClass(cropper, hidden); + addClass(element, CLASS_HIDDEN); + removeClass(cropper, CLASS_HIDDEN); }, // Canvas (image wrapper) initCanvas: function initCanvas() { - var self = this; - var viewMode = self.options.viewMode; - var containerData = self.containerData; - var imageData = self.imageData; + var containerData = this.containerData, + imageData = this.imageData; + var viewMode = this.options.viewMode; + var rotated = Math.abs(imageData.rotate) % 180 === 90; var naturalWidth = rotated ? imageData.naturalHeight : imageData.naturalWidth; var naturalHeight = rotated ? imageData.naturalWidth : imageData.naturalHeight; @@ -853,9 +1203,9 @@ var render = { } var canvasData = { + aspectRatio: aspectRatio, naturalWidth: naturalWidth, naturalHeight: naturalHeight, - aspectRatio: aspectRatio, width: canvasWidth, height: canvasHeight }; @@ -865,21 +1215,21 @@ var render = { canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - self.canvasData = canvasData; - self.limited = viewMode === 1 || viewMode === 2; - self.limitCanvas(true, true); - self.initialImageData = extend({}, imageData); - self.initialCanvasData = extend({}, canvasData); + this.canvasData = canvasData; + this.limited = viewMode === 1 || viewMode === 2; + this.limitCanvas(true, true); + this.initialImageData = extend({}, imageData); + this.initialCanvasData = extend({}, canvasData); }, limitCanvas: function limitCanvas(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; var viewMode = options.viewMode; - var containerData = self.containerData; - var canvasData = self.canvasData; var aspectRatio = canvasData.aspectRatio; - var cropBoxData = self.cropBoxData; - var cropped = self.cropped && cropBoxData; + + var cropped = this.cropped && cropBoxData; if (sizeLimited) { var minCanvasWidth = Number(options.minCanvasWidth) || 0; @@ -913,17 +1263,15 @@ var render = { } } - if (minCanvasWidth && minCanvasHeight) { - if (minCanvasHeight * aspectRatio > minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else { - minCanvasWidth = minCanvasHeight * aspectRatio; - } - } else if (minCanvasWidth) { - minCanvasHeight = minCanvasWidth / aspectRatio; - } else if (minCanvasHeight) { - minCanvasWidth = minCanvasHeight * aspectRatio; - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: minCanvasWidth, + height: minCanvasHeight + }); + + minCanvasWidth = _getContainSizes.width; + minCanvasHeight = _getContainSizes.height; + canvasData.minWidth = minCanvasWidth; canvasData.minHeight = minCanvasHeight; @@ -941,7 +1289,7 @@ var render = { canvasData.maxLeft = Math.max(0, newCanvasLeft); canvasData.maxTop = Math.max(0, newCanvasTop); - if (cropped && self.limited) { + if (cropped && this.limited) { canvasData.minLeft = Math.min(cropBoxData.left, cropBoxData.left + (cropBoxData.width - canvasData.width)); canvasData.minTop = Math.min(cropBoxData.top, cropBoxData.top + (cropBoxData.height - canvasData.height)); canvasData.maxLeft = cropBoxData.left; @@ -967,47 +1315,31 @@ var render = { } } }, - renderCanvas: function renderCanvas(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var rotate = imageData.rotate; - - if (self.rotated) { - self.rotated = false; - - // Computes rotated sizes with image sizes - var rotatedData = getRotatedSizes({ - width: imageData.width, - height: imageData.height, - degree: rotate - }); - var aspectRatio = rotatedData.width / rotatedData.height; - var isSquareImage = imageData.aspectRatio === 1; - - if (isSquareImage || aspectRatio !== canvasData.aspectRatio) { - canvasData.left -= (rotatedData.width - canvasData.width) / 2; - canvasData.top -= (rotatedData.height - canvasData.height) / 2; - canvasData.width = rotatedData.width; - canvasData.height = rotatedData.height; - canvasData.aspectRatio = aspectRatio; - canvasData.naturalWidth = imageData.naturalWidth; - canvasData.naturalHeight = imageData.naturalHeight; - - // Computes rotated sizes with natural image sizes - if (isSquareImage && rotate % 90 || rotate % 180) { - var rotatedData2 = getRotatedSizes({ - width: imageData.naturalWidth, - height: imageData.naturalHeight, - degree: rotate - }); + renderCanvas: function renderCanvas(changed, transformed) { + var canvasData = this.canvasData, + imageData = this.imageData; - canvasData.naturalWidth = rotatedData2.width; - canvasData.naturalHeight = rotatedData2.height; - } - self.limitCanvas(true, false); - } + if (transformed) { + var _getRotatedSizes = getRotatedSizes({ + width: imageData.naturalWidth * Math.abs(imageData.scaleX), + height: imageData.naturalHeight * Math.abs(imageData.scaleY), + degree: imageData.rotate + }), + naturalWidth = _getRotatedSizes.width, + naturalHeight = _getRotatedSizes.height; + + var width = canvasData.width * (naturalWidth / canvasData.naturalWidth); + var height = canvasData.height * (naturalHeight / canvasData.naturalHeight); + + canvasData.left -= (width - canvasData.width) / 2; + canvasData.top -= (height - canvasData.height) / 2; + canvasData.width = width; + canvasData.height = height; + canvasData.aspectRatio = naturalWidth / naturalHeight; + canvasData.naturalWidth = naturalWidth; + canvasData.naturalHeight = naturalHeight; + this.limitCanvas(true, false); } if (canvasData.width > canvasData.maxWidth || canvasData.width < canvasData.minWidth) { @@ -1021,14 +1353,14 @@ var render = { canvasData.width = Math.min(Math.max(canvasData.width, canvasData.minWidth), canvasData.maxWidth); canvasData.height = Math.min(Math.max(canvasData.height, canvasData.minHeight), canvasData.maxHeight); - self.limitCanvas(false, true); + this.limitCanvas(false, true); canvasData.left = Math.min(Math.max(canvasData.left, canvasData.minLeft), canvasData.maxLeft); canvasData.top = Math.min(Math.max(canvasData.top, canvasData.minTop), canvasData.maxTop); canvasData.oldLeft = canvasData.left; canvasData.oldTop = canvasData.top; - setStyle(self.canvas, extend({ + setStyle(this.canvas, extend({ width: canvasData.width, height: canvasData.height }, getTransforms({ @@ -1036,52 +1368,26 @@ var render = { translateY: canvasData.top }))); - self.renderImage(); + this.renderImage(changed); - if (self.cropped && self.limited) { - self.limitCropBox(true, true); - } - - if (changed) { - self.output(); + if (this.cropped && this.limited) { + this.limitCropBox(true, true); } }, renderImage: function renderImage(changed) { - var self = this; - var canvasData = self.canvasData; - var imageData = self.imageData; - var newImageData = void 0; - var reversedData = void 0; - var reversedWidth = void 0; - var reversedHeight = void 0; - - if (imageData.rotate) { - reversedData = getRotatedSizes({ - width: canvasData.width, - height: canvasData.height, - degree: imageData.rotate, - aspectRatio: imageData.aspectRatio - }, true); - - reversedWidth = reversedData.width; - reversedHeight = reversedData.height; - - newImageData = { - width: reversedWidth, - height: reversedHeight, - left: (canvasData.width - reversedWidth) / 2, - top: (canvasData.height - reversedHeight) / 2 - }; - } + var canvasData = this.canvasData, + imageData = this.imageData; - extend(imageData, newImageData || { - width: canvasData.width, - height: canvasData.height, - left: 0, - top: 0 - }); + var width = imageData.naturalWidth * (canvasData.width / canvasData.naturalWidth); + var height = imageData.naturalHeight * (canvasData.height / canvasData.naturalHeight); - setStyle(self.image, extend({ + extend(imageData, { + width: width, + height: height, + left: (canvasData.width - width) / 2, + top: (canvasData.height - height) / 2 + }); + setStyle(this.image, extend({ width: imageData.width, height: imageData.height }, getTransforms(extend({ @@ -1090,15 +1396,15 @@ var render = { }, imageData)))); if (changed) { - self.output(); + this.output(); } }, initCropBox: function initCropBox() { - var self = this; - var options = self.options; + var options = this.options, + canvasData = this.canvasData; var aspectRatio = options.aspectRatio; + var autoCropArea = Number(options.autoCropArea) || 0.8; - var canvasData = self.canvasData; var cropBoxData = { width: canvasData.width, height: canvasData.height @@ -1112,8 +1418,8 @@ var render = { } } - self.cropBoxData = cropBoxData; - self.limitCropBox(true, true); + this.cropBoxData = cropBoxData; + this.limitCropBox(true, true); // Initialize auto crop area cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); @@ -1127,16 +1433,16 @@ var render = { cropBoxData.oldLeft = cropBoxData.left; cropBoxData.oldTop = cropBoxData.top; - self.initialCropBoxData = extend({}, cropBoxData); + this.initialCropBoxData = extend({}, cropBoxData); }, limitCropBox: function limitCropBox(sizeLimited, positionLimited) { - var self = this; - var options = self.options; + var options = this.options, + containerData = this.containerData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData, + limited = this.limited; var aspectRatio = options.aspectRatio; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var limited = self.limited; + if (sizeLimited) { var minCropBoxWidth = Number(options.minCropBoxWidth) || 0; @@ -1144,7 +1450,7 @@ var render = { var maxCropBoxWidth = Math.min(containerData.width, limited ? canvasData.width : containerData.width); var maxCropBoxHeight = Math.min(containerData.height, limited ? canvasData.height : containerData.height); - // The min/maxCropBoxWidth/Height must be less than containerWidth/Height + // The min/maxCropBoxWidth/Height must be less than container's width/height minCropBoxWidth = Math.min(minCropBoxWidth, containerData.width); minCropBoxHeight = Math.min(minCropBoxHeight, containerData.height); @@ -1190,10 +1496,10 @@ var render = { } }, renderCropBox: function renderCropBox() { - var self = this; - var options = self.options; - var containerData = self.containerData; - var cropBoxData = self.cropBoxData; + var options = this.options, + containerData = this.containerData, + cropBoxData = this.cropBoxData; + if (cropBoxData.width > cropBoxData.maxWidth || cropBoxData.width < cropBoxData.minWidth) { cropBoxData.left = cropBoxData.oldLeft; @@ -1206,7 +1512,7 @@ var render = { cropBoxData.width = Math.min(Math.max(cropBoxData.width, cropBoxData.minWidth), cropBoxData.maxWidth); cropBoxData.height = Math.min(Math.max(cropBoxData.height, cropBoxData.minHeight), cropBoxData.maxHeight); - self.limitCropBox(false, true); + this.limitCropBox(false, true); cropBoxData.left = Math.min(Math.max(cropBoxData.left, cropBoxData.minLeft), cropBoxData.maxLeft); cropBoxData.top = Math.min(Math.max(cropBoxData.top, cropBoxData.minTop), cropBoxData.maxTop); @@ -1215,10 +1521,10 @@ var render = { if (options.movable && options.cropBoxMovable) { // Turn to move the canvas when the crop box is equal to the container - setData(self.face, 'action', cropBoxData.width === containerData.width && cropBoxData.height === containerData.height ? 'move' : 'all'); + setData(this.face, DATA_ACTION, cropBoxData.width >= containerData.width && cropBoxData.height >= containerData.height ? ACTION_MOVE : ACTION_ALL); } - setStyle(self.cropBox, extend({ + setStyle(this.cropBox, extend({ width: cropBoxData.width, height: cropBoxData.height }, getTransforms({ @@ -1226,42 +1532,38 @@ var render = { translateY: cropBoxData.top }))); - if (self.cropped && self.limited) { - self.limitCanvas(true, true); + if (this.cropped && this.limited) { + this.limitCanvas(true, true); } - if (!self.disabled) { - self.output(); + if (!this.disabled) { + this.output(); } }, output: function output() { - var self = this; - - self.preview(); + this.preview(); - if (self.complete) { - dispatchEvent(self.element, 'crop', self.getData()); + if (this.complete) { + dispatchEvent(this.element, EVENT_CROP, this.getData()); } } }; -var DATA_PREVIEW = 'preview'; - var preview = { initPreview: function initPreview() { - var self = this; - var preview = self.options.preview; - var image = createElement('img'); - var crossOrigin = self.crossOrigin; - var url = crossOrigin ? self.crossOriginUrl : self.url; + var crossOrigin = this.crossOrigin; + var preview = this.options.preview; + + var url = crossOrigin ? this.crossOriginUrl : this.url; + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; } image.src = url; - appendChild(self.viewBox, image); - self.image2 = image; + this.viewBox.appendChild(image); + this.image2 = image; if (!preview) { return; @@ -1269,10 +1571,10 @@ var preview = { var previews = preview.querySelector ? [preview] : document.querySelectorAll(preview); - self.previews = previews; + this.previews = previews; each(previews, function (element) { - var img = createElement('img'); + var img = document.createElement('img'); // Save the original size for recover setData(element, DATA_PREVIEW, { @@ -1297,7 +1599,7 @@ var preview = { 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;"'; empty(element); - appendChild(element, img); + element.appendChild(img); }); }, resetPreview: function resetPreview() { @@ -1314,22 +1616,22 @@ var preview = { }); }, preview: function preview() { - var self = this; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var cropBoxWidth = cropBoxData.width; - var cropBoxHeight = cropBoxData.height; - var width = imageData.width; - var height = imageData.height; + var imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var cropBoxWidth = cropBoxData.width, + cropBoxHeight = cropBoxData.height; + var width = imageData.width, + height = imageData.height; + var left = cropBoxData.left - canvasData.left - imageData.left; var top = cropBoxData.top - canvasData.top - imageData.top; - if (!self.cropped || self.disabled) { + if (!this.cropped || this.disabled) { return; } - setStyle(self.image2, extend({ + setStyle(this.image2, extend({ width: width, height: height }, getTransforms(extend({ @@ -1337,7 +1639,7 @@ var preview = { translateY: -top }, imageData)))); - each(self.previews, function (element) { + each(this.previews, function (element) { var data = getData(element, DATA_PREVIEW); var originalWidth = data.width; var originalHeight = data.height; @@ -1361,39 +1663,23 @@ var preview = { height: newHeight }); - setStyle(getByTag(element, 'img')[0], extend({ + setStyle(element.getElementsByTagName('img')[0], extend({ width: width * ratio, height: height * ratio }, getTransforms(extend({ translateX: -left * ratio, translateY: -top * ratio - }, imageData)))); - }); - } -}; - -// Globals -var PointerEvent = typeof window !== 'undefined' ? window.PointerEvent : null; - -// Events -var EVENT_POINTER_DOWN = PointerEvent ? 'pointerdown' : 'touchstart mousedown'; -var EVENT_POINTER_MOVE = PointerEvent ? 'pointermove' : 'touchmove mousemove'; -var EVENT_POINTER_UP = PointerEvent ? ' pointerup pointercancel' : 'touchend touchcancel mouseup'; -var EVENT_WHEEL = 'wheel mousewheel DOMMouseScroll'; -var EVENT_DBLCLICK = 'dblclick'; -var EVENT_RESIZE = 'resize'; -var EVENT_CROP_START = 'cropstart'; -var EVENT_CROP_MOVE = 'cropmove'; -var EVENT_CROP_END = 'cropend'; -var EVENT_CROP$1 = 'crop'; -var EVENT_ZOOM = 'zoom'; + }, imageData)))); + }); + } +}; var events = { bind: function bind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { addListener(element, EVENT_CROP_START, options.cropstart); @@ -1408,35 +1694,35 @@ var events = { } if (isFunction(options.crop)) { - addListener(element, EVENT_CROP$1, options.crop); + addListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { addListener(element, EVENT_ZOOM, options.zoom); } - addListener(cropper, EVENT_POINTER_DOWN, self.onCropStart = proxy(self.cropStart, self)); + addListener(cropper, EVENT_POINTER_DOWN, this.onCropStart = proxy(this.cropStart, this)); if (options.zoomable && options.zoomOnWheel) { - addListener(cropper, EVENT_WHEEL, self.onWheel = proxy(self.wheel, self)); + addListener(cropper, EVENT_WHEEL, this.onWheel = proxy(this.wheel, this)); } if (options.toggleDragModeOnDblclick) { - addListener(cropper, EVENT_DBLCLICK, self.onDblclick = proxy(self.dblclick, self)); + addListener(cropper, EVENT_DBLCLICK, this.onDblclick = proxy(this.dblclick, this)); } - addListener(document, EVENT_POINTER_MOVE, self.onCropMove = proxy(self.cropMove, self)); - addListener(document, EVENT_POINTER_UP, self.onCropEnd = proxy(self.cropEnd, self)); + addListener(document, EVENT_POINTER_MOVE, this.onCropMove = proxy(this.cropMove, this)); + addListener(document, EVENT_POINTER_UP, this.onCropEnd = proxy(this.cropEnd, this)); if (options.responsive) { - addListener(window, EVENT_RESIZE, self.onResize = proxy(self.resize, self)); + addListener(window, EVENT_RESIZE, this.onResize = proxy(this.resize, this)); } }, unbind: function unbind() { - var self = this; - var options = self.options; - var element = self.element; - var cropper = self.cropper; + var element = this.element, + options = this.options, + cropper = this.cropper; + if (isFunction(options.cropstart)) { removeListener(element, EVENT_CROP_START, options.cropstart); @@ -1451,63 +1737,42 @@ var events = { } if (isFunction(options.crop)) { - removeListener(element, EVENT_CROP$1, options.crop); + removeListener(element, EVENT_CROP, options.crop); } if (isFunction(options.zoom)) { removeListener(element, EVENT_ZOOM, options.zoom); } - removeListener(cropper, EVENT_POINTER_DOWN, self.onCropStart); + removeListener(cropper, EVENT_POINTER_DOWN, this.onCropStart); if (options.zoomable && options.zoomOnWheel) { - removeListener(cropper, EVENT_WHEEL, self.onWheel); + removeListener(cropper, EVENT_WHEEL, this.onWheel); } if (options.toggleDragModeOnDblclick) { - removeListener(cropper, EVENT_DBLCLICK, self.onDblclick); + removeListener(cropper, EVENT_DBLCLICK, this.onDblclick); } - removeListener(document, EVENT_POINTER_MOVE, self.onCropMove); - removeListener(document, EVENT_POINTER_UP, self.onCropEnd); + removeListener(document, EVENT_POINTER_MOVE, this.onCropMove); + removeListener(document, EVENT_POINTER_UP, this.onCropEnd); if (options.responsive) { - removeListener(window, EVENT_RESIZE, self.onResize); + removeListener(window, EVENT_RESIZE, this.onResize); } } }; -var REGEXP_ACTIONS = /^(e|w|s|n|se|sw|ne|nw|all|crop|move|zoom)$/; - -function getPointer(_ref, endOnly) { - var pageX = _ref.pageX, - pageY = _ref.pageY; - - var end = { - endX: pageX, - endY: pageY - }; - - if (endOnly) { - return end; - } - - return extend({ - startX: pageX, - startY: pageY - }, end); -} - var handlers = { resize: function resize() { - var self = this; - var options = self.options; - var container = self.container; - var containerData = self.containerData; + var options = this.options, + container = this.container, + containerData = this.containerData; + var minContainerWidth = Number(options.minContainerWidth) || 200; var minContainerHeight = Number(options.minContainerHeight) || 100; - if (self.disabled || containerData.width === minContainerWidth || containerData.height === minContainerHeight) { + if (this.disabled || containerData.width <= minContainerWidth || containerData.height <= minContainerHeight) { return; } @@ -1519,52 +1784,50 @@ var handlers = { var cropBoxData = void 0; if (options.restore) { - canvasData = self.getCanvasData(); - cropBoxData = self.getCropBoxData(); + canvasData = this.getCanvasData(); + cropBoxData = this.getCropBoxData(); } - self.render(); + this.render(); if (options.restore) { - self.setCanvasData(each(canvasData, function (n, i) { + this.setCanvasData(each(canvasData, function (n, i) { canvasData[i] = n * ratio; })); - self.setCropBoxData(each(cropBoxData, function (n, i) { + this.setCropBoxData(each(cropBoxData, function (n, i) { cropBoxData[i] = n * ratio; })); } } }, dblclick: function dblclick() { - var self = this; - - if (self.disabled || self.options.dragMode === 'none') { + if (this.disabled || this.options.dragMode === DRAG_MODE_NONE) { return; } - self.setDragMode(hasClass(self.dragBox, 'cropper-crop') ? 'move' : 'crop'); + this.setDragMode(hasClass(this.dragBox, CLASS_CROP) ? DRAG_MODE_MOVE : DRAG_MODE_CROP); }, - wheel: function wheel(event) { - var self = this; - var e = getEvent(event); - var ratio = Number(self.options.wheelZoomRatio) || 0.1; + wheel: function wheel(e) { + var _this = this; + + var ratio = Number(this.options.wheelZoomRatio) || 0.1; var delta = 1; - if (self.disabled) { + if (this.disabled) { return; } e.preventDefault(); // Limit wheel speed to prevent zoom too fast (#21) - if (self.wheeling) { + if (this.wheeling) { return; } - self.wheeling = true; + this.wheeling = true; setTimeout(function () { - self.wheeling = false; + _this.wheeling = false; }, 50); if (e.deltaY) { @@ -1575,18 +1838,16 @@ var handlers = { delta = e.detail > 0 ? 1 : -1; } - self.zoom(-delta * ratio, e); + this.zoom(-delta * ratio, e); }, - cropStart: function cropStart(event) { - var self = this; - - if (self.disabled) { + cropStart: function cropStart(e) { + if (this.disabled) { return; } - var options = self.options; - var pointers = self.pointers; - var e = getEvent(event); + var options = this.options, + pointers = this.pointers; + var action = void 0; if (e.changedTouches) { @@ -1600,16 +1861,16 @@ var handlers = { } if (Object.keys(pointers).length > 1 && options.zoomable && options.zoomOnTouch) { - action = 'zoom'; + action = ACTION_ZOOM; } else { - action = getData(e.target, 'action'); + action = getData(e.target, DATA_ACTION); } if (!REGEXP_ACTIONS.test(action)) { return; } - if (dispatchEvent(self.element, 'cropstart', { + if (dispatchEvent(this.element, EVENT_CROP_START, { originalEvent: e, action: action }) === false) { @@ -1618,28 +1879,28 @@ var handlers = { e.preventDefault(); - self.action = action; - self.cropping = false; + this.action = action; + this.cropping = false; - if (action === 'crop') { - self.cropping = true; - addClass(self.dragBox, 'cropper-modal'); + if (action === ACTION_CROP) { + this.cropping = true; + addClass(this.dragBox, CLASS_MODAL); } }, - cropMove: function cropMove(event) { - var self = this; - var action = self.action; + cropMove: function cropMove(e) { + var action = this.action; + - if (self.disabled || !action) { + if (this.disabled || !action) { return; } - var pointers = self.pointers; - var e = getEvent(event); + var pointers = this.pointers; + e.preventDefault(); - if (dispatchEvent(self.element, 'cropmove', { + if (dispatchEvent(this.element, EVENT_CROP_MOVE, { originalEvent: e, action: action }) === false) { @@ -1654,18 +1915,16 @@ var handlers = { extend(pointers[e.pointerId || 0], getPointer(e, true)); } - self.change(e); + this.change(e); }, - cropEnd: function cropEnd(event) { - var self = this; - - if (self.disabled) { + cropEnd: function cropEnd(e) { + if (this.disabled) { return; } - var action = self.action; - var pointers = self.pointers; - var e = getEvent(event); + var action = this.action, + pointers = this.pointers; + if (e.changedTouches) { each(e.changedTouches, function (touch) { @@ -1682,71 +1941,35 @@ var handlers = { e.preventDefault(); if (!Object.keys(pointers).length) { - self.action = ''; + this.action = ''; } - if (self.cropping) { - self.cropping = false; - toggleClass(self.dragBox, 'cropper-modal', self.cropped && this.options.modal); + if (this.cropping) { + this.cropping = false; + toggleClass(this.dragBox, CLASS_MODAL, this.cropped && this.options.modal); } - dispatchEvent(self.element, 'cropend', { + dispatchEvent(this.element, EVENT_CROP_END, { originalEvent: e, action: action }); } }; -// Actions -var ACTION_EAST = 'e'; -var ACTION_WEST = 'w'; -var ACTION_SOUTH = 's'; -var ACTION_NORTH = 'n'; -var ACTION_SOUTH_EAST = 'se'; -var ACTION_SOUTH_WEST = 'sw'; -var ACTION_NORTH_EAST = 'ne'; -var ACTION_NORTH_WEST = 'nw'; - -function getMaxZoomRatio(pointers) { - var pointers2 = extend({}, pointers); - var ratios = []; - - each(pointers, function (pointer, pointerId) { - delete pointers2[pointerId]; - - each(pointers2, function (pointer2) { - var x1 = Math.abs(pointer.startX - pointer2.startX); - var y1 = Math.abs(pointer.startY - pointer2.startY); - var x2 = Math.abs(pointer.endX - pointer2.endX); - var y2 = Math.abs(pointer.endY - pointer2.endY); - var z1 = Math.sqrt(x1 * x1 + y1 * y1); - var z2 = Math.sqrt(x2 * x2 + y2 * y2); - var ratio = (z2 - z1) / z1; - - ratios.push(ratio); - }); - }); - - ratios.sort(function (a, b) { - return Math.abs(a) < Math.abs(b); - }); - - return ratios[0]; -} - var change = { change: function change(e) { - var self = this; - var options = self.options; - var containerData = self.containerData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; + var options = this.options, + canvasData = this.canvasData, + containerData = this.containerData, + cropBoxData = this.cropBoxData, + pointers = this.pointers; + var action = this.action; var aspectRatio = options.aspectRatio; - var action = self.action; - var width = cropBoxData.width; - var height = cropBoxData.height; - var left = cropBoxData.left; - var top = cropBoxData.top; + var left = cropBoxData.left, + top = cropBoxData.top, + width = cropBoxData.width, + height = cropBoxData.height; + var right = left + width; var bottom = top + height; var minLeft = 0; @@ -1761,23 +1984,56 @@ var change = { aspectRatio = width && height ? width / height : 1; } - if (self.limited) { + if (this.limited) { minLeft = cropBoxData.minLeft; minTop = cropBoxData.minTop; + maxWidth = minLeft + Math.min(containerData.width, canvasData.width, canvasData.left + canvasData.width); maxHeight = minTop + Math.min(containerData.height, canvasData.height, canvasData.top + canvasData.height); } - var pointers = self.pointers; var pointer = pointers[Object.keys(pointers)[0]]; var range = { x: pointer.endX - pointer.startX, y: pointer.endY - pointer.startY }; + var check = function check(side) { + switch (side) { + case ACTION_EAST: + if (right + range.x > maxWidth) { + range.x = maxWidth - right; + } + + break; + + case ACTION_WEST: + if (left + range.x < minLeft) { + range.x = minLeft - left; + } + + break; + + case ACTION_NORTH: + if (top + range.y < minTop) { + range.y = minTop - top; + } + + break; + + case ACTION_SOUTH: + if (bottom + range.y > maxHeight) { + range.y = maxHeight - bottom; + } + + break; + + default: + } + }; switch (action) { // Move crop box - case 'all': + case ACTION_ALL: left += range.x; top += range.y; break; @@ -1789,10 +2045,7 @@ var change = { break; } - if (right + range.x > maxWidth) { - range.x = maxWidth - right; - } - + check(ACTION_EAST); width += range.x; if (aspectRatio) { @@ -1813,10 +2066,7 @@ var change = { break; } - if (top + range.y < minTop) { - range.y = minTop - top; - } - + check(ACTION_NORTH); height -= range.y; top += range.y; @@ -1838,10 +2088,7 @@ var change = { break; } - if (left + range.x < minLeft) { - range.x = minLeft - left; - } - + check(ACTION_WEST); width -= range.x; left += range.x; @@ -1863,10 +2110,7 @@ var change = { break; } - if (bottom + range.y > maxHeight) { - range.y = maxHeight - bottom; - } - + check(ACTION_SOUTH); height += range.y; if (aspectRatio) { @@ -1888,10 +2132,14 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -1934,11 +2182,15 @@ var change = { break; } + check(ACTION_NORTH); height -= range.y; top += range.y; width = height * aspectRatio; left += range.y * aspectRatio; } else { + check(ACTION_NORTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -1983,10 +2235,14 @@ var change = { break; } + check(ACTION_WEST); width -= range.x; left += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_WEST); + if (range.x <= 0) { if (left > minLeft) { width -= range.x; @@ -2029,9 +2285,13 @@ var change = { break; } + check(ACTION_EAST); width += range.x; height = width / aspectRatio; } else { + check(ACTION_SOUTH); + check(ACTION_EAST); + if (range.x >= 0) { if (right < maxWidth) { width += range.x; @@ -2066,25 +2326,25 @@ var change = { break; // Move canvas - case 'move': - self.move(range.x, range.y); + case ACTION_MOVE: + this.move(range.x, range.y); renderable = false; break; // Zoom canvas - case 'zoom': - self.zoom(getMaxZoomRatio(pointers), e); + case ACTION_ZOOM: + this.zoom(getMaxZoomRatio(pointers), e); renderable = false; break; // Create crop box - case 'crop': + case ACTION_CROP: if (!range.x || !range.y) { renderable = false; break; } - offset = getOffset(self.cropper); + offset = getOffset(this.cropper); left = pointer.startX - offset.left; top = pointer.startY - offset.top; width = cropBoxData.minWidth; @@ -2102,12 +2362,12 @@ var change = { } // Show the crop box if is hidden - if (!self.cropped) { - removeClass(self.cropBox, 'cropper-hidden'); - self.cropped = true; + if (!this.cropped) { + removeClass(this.cropBox, CLASS_HIDDEN); + this.cropped = true; - if (self.limited) { - self.limitCropBox(true, true); + if (this.limited) { + this.limitCropBox(true, true); } } @@ -2121,9 +2381,8 @@ var change = { cropBoxData.height = height; cropBoxData.left = left; cropBoxData.top = top; - self.action = action; - - self.renderCropBox(); + this.action = action; + this.renderCropBox(); } // Override @@ -2134,228 +2393,188 @@ var change = { } }; -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -function getPointersCenter(pointers) { - var pageX = 0; - var pageY = 0; - var count = 0; - - each(pointers, function (_ref) { - var startX = _ref.startX, - startY = _ref.startY; - - pageX += startX; - pageY += startY; - count += 1; - }); - - pageX /= count; - pageY /= count; - - return { - pageX: pageX, - pageY: pageY - }; -} - var methods = { // Show the crop box manually crop: function crop() { - var self = this; + if (this.ready && !this.disabled) { + if (!this.cropped) { + this.cropped = true; + this.limitCropBox(true, true); - if (self.ready && !self.disabled) { - if (!self.cropped) { - self.cropped = true; - self.limitCropBox(true, true); - - if (self.options.modal) { - addClass(self.dragBox, 'cropper-modal'); + if (this.options.modal) { + addClass(this.dragBox, CLASS_MODAL); } - removeClass(self.cropBox, 'cropper-hidden'); + removeClass(this.cropBox, CLASS_HIDDEN); } - self.setCropBoxData(self.initialCropBoxData); + this.setCropBoxData(this.initialCropBoxData); } - return self; + return this; }, // Reset the image and crop box to their initial states reset: function reset() { - var self = this; - - if (self.ready && !self.disabled) { - self.imageData = extend({}, self.initialImageData); - self.canvasData = extend({}, self.initialCanvasData); - self.cropBoxData = extend({}, self.initialCropBoxData); + if (this.ready && !this.disabled) { + this.imageData = extend({}, this.initialImageData); + this.canvasData = extend({}, this.initialCanvasData); + this.cropBoxData = extend({}, this.initialCropBoxData); + this.renderCanvas(); - self.renderCanvas(); - - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } - return self; + return this; }, // Clear the crop box clear: function clear() { - var self = this; - - if (self.cropped && !self.disabled) { - extend(self.cropBoxData, { + if (this.cropped && !this.disabled) { + extend(this.cropBoxData, { left: 0, top: 0, width: 0, height: 0 }); - self.cropped = false; - self.renderCropBox(); - - self.limitCanvas(true, true); + this.cropped = false; + this.renderCropBox(); + this.limitCanvas(true, true); // Render canvas after crop box rendered - self.renderCanvas(); - - removeClass(self.dragBox, 'cropper-modal'); - addClass(self.cropBox, 'cropper-hidden'); + this.renderCanvas(); + removeClass(this.dragBox, CLASS_MODAL); + addClass(this.cropBox, CLASS_HIDDEN); } - return self; + return this; }, /** * Replace the image's src and rebuild the cropper - * - * @param {String} url - * @param {Boolean} onlyColorChanged (optional) + * @param {string} url - The new URL. + * @param {boolean} [onlyColorChanged] - Indicate if the new image only changed color. + * @returns {Object} this */ - replace: function replace(url, onlyColorChanged) { - var self = this; + replace: function replace(url) { + var onlyColorChanged = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false; - if (!self.disabled && url) { - if (self.isImg) { - self.element.src = url; + if (!this.disabled && url) { + if (this.isImg) { + this.element.src = url; } if (onlyColorChanged) { - self.url = url; - self.image.src = url; + this.url = url; + this.image.src = url; - if (self.ready) { - self.image2.src = url; + if (this.ready) { + this.image2.src = url; - each(self.previews, function (element) { - getByTag(element, 'img')[0].src = url; + each(this.previews, function (element) { + element.getElementsByTagName('img')[0].src = url; }); } } else { - if (self.isImg) { - self.replaced = true; + if (this.isImg) { + this.replaced = true; } // Clear previous data - self.options.data = null; - self.load(url); + this.options.data = null; + this.load(url); } } - return self; + return this; }, // Enable (unfreeze) the cropper enable: function enable() { - var self = this; - - if (self.ready) { - self.disabled = false; - removeClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = false; + removeClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Disable (freeze) the cropper disable: function disable() { - var self = this; - - if (self.ready) { - self.disabled = true; - addClass(self.cropper, 'cropper-disabled'); + if (this.ready) { + this.disabled = true; + addClass(this.cropper, CLASS_DISABLED); } - return self; + return this; }, // Destroy the cropper and remove the instance from the image destroy: function destroy() { - var self = this; - var element = self.element; - var image = self.image; + var element = this.element, + image = this.image; - if (self.loaded) { - if (self.isImg && self.replaced) { - element.src = self.originalUrl; + + if (this.loaded) { + if (this.isImg && this.replaced) { + element.src = this.originalUrl; } - self.unbuild(); - removeClass(element, 'cropper-hidden'); - } else if (self.isImg) { - removeListener(element, 'load', self.onStart); + this.unbuild(); + removeClass(element, CLASS_HIDDEN); + } else if (this.isImg) { + removeListener(element, EVENT_LOAD, this.onStart); } else if (image) { - removeChild(image); + image.parentNode.removeChild(image); } - removeData(element, 'cropper'); + removeData(element, NAMESPACE); - return self; + return this; }, /** * Move the canvas with relative offsets - * - * @param {Number} offsetX - * @param {Number} offsetY (optional) + * @param {number} offsetX - The relative offset distance on the x-axis. + * @param {number} offsetY - The relative offset distance on the y-axis. + * @returns {Object} this */ move: function move(offsetX, offsetY) { - var self = this; - var canvasData = self.canvasData; + var _canvasData = this.canvasData, + left = _canvasData.left, + top = _canvasData.top; + - return self.moveTo(isUndefined(offsetX) ? offsetX : canvasData.left + Number(offsetX), isUndefined(offsetY) ? offsetY : canvasData.top + Number(offsetY)); + return this.moveTo(isUndefined(offsetX) ? offsetX : left + Number(offsetX), isUndefined(offsetY) ? offsetY : top + Number(offsetY)); }, /** * Move the canvas to an absolute point - * - * @param {Number} x - * @param {Number} y (optional) + * @param {number} x - The x-axis coordinate. + * @param {number} [y=x] - The y-axis coordinate. + * @returns {Object} this */ - moveTo: function moveTo(x, y) { - var self = this; - var canvasData = self.canvasData; - var changed = false; + moveTo: function moveTo(x) { + var y = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : x; + var canvasData = this.canvasData; - // If "y" is not present, its default value is "x" - if (isUndefined(y)) { - y = x; - } + var changed = false; x = Number(x); y = Number(y); - if (self.ready && !self.disabled && self.options.movable) { + if (this.ready && !this.disabled && this.options.movable) { if (isNumber(x)) { canvasData.left = x; changed = true; @@ -2367,23 +2586,23 @@ var methods = { } if (changed) { - self.renderCanvas(true); + this.renderCanvas(true); } } - return self; + return this; }, /** * Zoom the canvas with a relative ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoom: function zoom(ratio, _originalEvent) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + ratio = Number(ratio); @@ -2393,42 +2612,43 @@ var methods = { ratio = 1 + ratio; } - return self.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); + return this.zoomTo(canvasData.width * ratio / canvasData.naturalWidth, _originalEvent); }, /** * Zoom the canvas to an absolute ratio - * - * @param {Number} ratio - * @param {Event} _originalEvent (private) + * @param {number} ratio - The target ratio. + * @param {Event} _originalEvent - The original event if any. + * @returns {Object} this */ zoomTo: function zoomTo(ratio, _originalEvent) { - var self = this; - var options = self.options; - var canvasData = self.canvasData; - var width = canvasData.width; - var height = canvasData.height; - var naturalWidth = canvasData.naturalWidth; - var naturalHeight = canvasData.naturalHeight; + var options = this.options, + canvasData = this.canvasData; + var width = canvasData.width, + height = canvasData.height, + naturalWidth = canvasData.naturalWidth, + naturalHeight = canvasData.naturalHeight; + ratio = Number(ratio); - if (ratio >= 0 && self.ready && !self.disabled && options.zoomable) { + if (ratio >= 0 && this.ready && !this.disabled && options.zoomable) { var newWidth = naturalWidth * ratio; var newHeight = naturalHeight * ratio; - if (dispatchEvent(self.element, 'zoom', { + if (dispatchEvent(this.element, EVENT_ZOOM, { originalEvent: _originalEvent, oldRatio: width / naturalWidth, ratio: newWidth / naturalWidth }) === false) { - return self; + return this; } if (_originalEvent) { - var pointers = self.pointers; - var offset = getOffset(self.cropper); + var pointers = this.pointers; + + var offset = getOffset(this.cropper); var center = pointers && Object.keys(pointers).length ? getPointersCenter(pointers) : { pageX: _originalEvent.pageX, pageY: _originalEvent.pageY @@ -2445,128 +2665,116 @@ var methods = { canvasData.width = newWidth; canvasData.height = newHeight; - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** * Rotate the canvas with a relative degree - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotate: function rotate(degree) { - var self = this; - - return self.rotateTo((self.imageData.rotate || 0) + Number(degree)); + return this.rotateTo((this.imageData.rotate || 0) + Number(degree)); }, /** * Rotate the canvas to an absolute degree - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#rotate() - * - * @param {Number} degree + * @param {number} degree - The rotate degree. + * @returns {Object} this */ rotateTo: function rotateTo(degree) { - var self = this; - degree = Number(degree); - if (isNumber(degree) && self.ready && !self.disabled && self.options.rotatable) { - self.imageData.rotate = degree % 360; - self.rotated = true; - self.renderCanvas(true); + if (isNumber(degree) && this.ready && !this.disabled && this.options.rotatable) { + this.imageData.rotate = degree % 360; + this.renderCanvas(true, true); } - return self; + return this; + }, + + + /** + * Scale the image on the x-axis. + * @param {number} scaleX - The scale ratio on the x-axis. + * @returns {Object} this + */ + scaleX: function scaleX(_scaleX) { + var scaleY = this.imageData.scaleY; + + + return this.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); + }, + + + /** + * Scale the image on the y-axis. + * @param {number} scaleY - The scale ratio on the y-axis. + * @returns {Object} this + */ + scaleY: function scaleY(_scaleY) { + var scaleX = this.imageData.scaleX; + + + return this.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); }, /** * Scale the image - * https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function#scale() - * - * @param {Number} scaleX - * @param {Number} scaleY (optional) + * @param {number} scaleX - The scale ratio on the x-axis. + * @param {number} [scaleY=scaleX] - The scale ratio on the y-axis. + * @returns {Object} this */ - scale: function scale(scaleX, scaleY) { - var self = this; - var imageData = self.imageData; - var changed = false; + scale: function scale(scaleX) { + var scaleY = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : scaleX; + var imageData = this.imageData; - // If "scaleY" is not present, its default value is "scaleX" - if (isUndefined(scaleY)) { - scaleY = scaleX; - } + var transformed = false; scaleX = Number(scaleX); scaleY = Number(scaleY); - if (self.ready && !self.disabled && self.options.scalable) { + if (this.ready && !this.disabled && this.options.scalable) { if (isNumber(scaleX)) { imageData.scaleX = scaleX; - changed = true; + transformed = true; } if (isNumber(scaleY)) { imageData.scaleY = scaleY; - changed = true; + transformed = true; } - if (changed) { - self.renderImage(true); + if (transformed) { + this.renderCanvas(true, true); } } - return self; - }, - - - /** - * Scale the abscissa of the image - * - * @param {Number} scaleX - */ - scaleX: function scaleX(_scaleX) { - var self = this; - var scaleY = self.imageData.scaleY; - - return self.scale(_scaleX, isNumber(scaleY) ? scaleY : 1); - }, - - - /** - * Scale the ordinate of the image - * - * @param {Number} scaleY - */ - scaleY: function scaleY(_scaleY) { - var self = this; - var scaleX = self.imageData.scaleX; - - return self.scale(isNumber(scaleX) ? scaleX : 1, _scaleY); + return this; }, /** * Get the cropped area position and size data (base on the original image) - * - * @param {Boolean} rounded (optional) - * @return {Object} data + * @param {boolean} [rounded=false] - Indicate if round the data values or not. + * @returns {Object} The result cropped data. */ - getData: function getData$$1(rounded) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; - var cropBoxData = self.cropBoxData; - var ratio = void 0; + getData: function getData$$1() { + var rounded = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData, + cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { x: cropBoxData.left - canvasData.left, y: cropBoxData.top - canvasData.top, @@ -2574,7 +2782,7 @@ var methods = { height: cropBoxData.height }; - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; each(data, function (n, i) { n /= ratio; @@ -2604,51 +2812,47 @@ var methods = { /** * Set the cropped area position and size with new data - * - * @param {Object} data + * @param {Object} data - The new data. + * @returns {Object} this */ setData: function setData$$1(data) { - var self = this; - var options = self.options; - var imageData = self.imageData; - var canvasData = self.canvasData; + var options = this.options, + imageData = this.imageData, + canvasData = this.canvasData; + var cropBoxData = {}; - var rotated = void 0; - var scaled = void 0; - var ratio = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { + var transformed = false; + if (options.rotatable) { if (isNumber(data.rotate) && data.rotate !== imageData.rotate) { imageData.rotate = data.rotate; - rotated = true; - self.rotated = rotated; + transformed = true; } } if (options.scalable) { if (isNumber(data.scaleX) && data.scaleX !== imageData.scaleX) { imageData.scaleX = data.scaleX; - scaled = true; + transformed = true; } if (isNumber(data.scaleY) && data.scaleY !== imageData.scaleY) { imageData.scaleY = data.scaleY; - scaled = true; + transformed = true; } } - if (rotated) { - self.renderCanvas(); - } else if (scaled) { - self.renderImage(); + if (transformed) { + this.renderCanvas(true, true); } - ratio = imageData.width / imageData.naturalWidth; + var ratio = imageData.width / imageData.naturalWidth; if (isNumber(data.x)) { cropBoxData.left = data.x * ratio + canvasData.left; @@ -2666,48 +2870,41 @@ var methods = { cropBoxData.height = data.height * ratio; } - self.setCropBoxData(cropBoxData); + this.setCropBoxData(cropBoxData); } - return self; + return this; }, /** - * Get the container size data - * - * @return {Object} data + * Get the container size data. + * @returns {Object} The result container data. */ getContainerData: function getContainerData() { - var self = this; - - return self.ready ? self.containerData : {}; + return this.ready ? extend({}, this.containerData) : {}; }, /** - * Get the image position and size data - * - * @return {Object} data + * Get the image position and size data. + * @returns {Object} The result image data. */ getImageData: function getImageData() { - var self = this; - - return self.loaded ? self.imageData : {}; + return this.loaded ? extend({}, this.imageData) : {}; }, /** - * Get the canvas position and size data - * - * @return {Object} data + * Get the canvas position and size data. + * @returns {Object} The result canvas data. */ getCanvasData: function getCanvasData() { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; + var data = {}; - if (self.ready) { + if (this.ready) { each(['left', 'top', 'width', 'height', 'naturalWidth', 'naturalHeight'], function (n) { data[n] = canvasData[n]; }); @@ -2718,20 +2915,20 @@ var methods = { /** - * Set the canvas position and size with new data - * - * @param {Object} data + * Set the canvas position and size with new data. + * @param {Object} data - The new canvas data. + * @returns {Object} this */ setCanvasData: function setCanvasData(data) { - var self = this; - var canvasData = self.canvasData; + var canvasData = this.canvasData; var aspectRatio = canvasData.aspectRatio; + if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && !self.disabled && isPlainObject(data)) { + if (this.ready && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { canvasData.left = data.left; } @@ -2748,24 +2945,23 @@ var methods = { canvasData.width = data.height * aspectRatio; } - self.renderCanvas(true); + this.renderCanvas(true); } - return self; + return this; }, /** - * Get the crop box position and size data - * - * @return {Object} data + * Get the crop box position and size data. + * @returns {Object} The result crop box data. */ getCropBoxData: function getCropBoxData() { - var self = this; - var cropBoxData = self.cropBoxData; + var cropBoxData = this.cropBoxData; + var data = void 0; - if (self.ready && self.cropped) { + if (this.ready && this.cropped) { data = { left: cropBoxData.left, top: cropBoxData.top, @@ -2779,22 +2975,22 @@ var methods = { /** - * Set the crop box position and size with new data - * - * @param {Object} data + * Set the crop box position and size with new data. + * @param {Object} data - The new crop box data. + * @returns {Object} this */ setCropBoxData: function setCropBoxData(data) { - var self = this; - var cropBoxData = self.cropBoxData; - var aspectRatio = self.options.aspectRatio; + var cropBoxData = this.cropBoxData; + var aspectRatio = this.options.aspectRatio; + var widthChanged = void 0; var heightChanged = void 0; if (isFunction(data)) { - data = data.call(self.element); + data = data.call(this.element); } - if (self.ready && self.cropped && !self.disabled && isPlainObject(data)) { + if (this.ready && this.cropped && !this.disabled && isPlainObject(data)) { if (isNumber(data.left)) { cropBoxData.left = data.left; } @@ -2821,210 +3017,204 @@ var methods = { } } - self.renderCropBox(); + this.renderCropBox(); } - return self; + return this; }, /** - * Get a canvas drawn the cropped image - * - * @param {Object} options (optional) - * @return {HTMLCanvasElement} canvas + * Get a canvas drawn the cropped image. + * @param {Object} [options={}] - The config options. + * @returns {HTMLCanvasElement} - The result canvas. */ - getCroppedCanvas: function getCroppedCanvas(options) { - var self = this; + getCroppedCanvas: function getCroppedCanvas() { + var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - if (!self.ready || !window.HTMLCanvasElement) { + if (!this.ready || !window.HTMLCanvasElement) { return null; } - if (!isPlainObject(options)) { - options = {}; - } + var canvasData = this.canvasData; + + var source = getSourceCanvas(this.image, this.imageData, canvasData, options); - // Return the whole canvas if not cropped - if (!self.cropped) { - return getSourceCanvas(self.image, self.imageData, options); + // Returns the source canvas if it is not cropped. + if (!this.cropped) { + return source; } - var data = self.getData(); - var originalWidth = data.width; - var originalHeight = data.height; - var aspectRatio = originalWidth / originalHeight; - var scaledWidth = void 0; - var scaledHeight = void 0; - var scaledRatio = void 0; + var _getData = this.getData(), + x = _getData.x, + y = _getData.y, + initialWidth = _getData.width, + initialHeight = _getData.height; - if (isPlainObject(options)) { - scaledWidth = options.width; - scaledHeight = options.height; + var aspectRatio = initialWidth / initialHeight; + var maxSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.maxWidth || Infinity, + height: options.maxHeight || Infinity + }); + var minSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.minWidth || 0, + height: options.minHeight || 0 + }); - if (scaledWidth) { - scaledHeight = scaledWidth / aspectRatio; - scaledRatio = scaledWidth / originalWidth; - } else if (scaledHeight) { - scaledWidth = scaledHeight * aspectRatio; - scaledRatio = scaledHeight / originalHeight; - } - } + var _getContainSizes = getContainSizes({ + aspectRatio: aspectRatio, + width: options.width || initialWidth, + height: options.height || initialHeight + }), + width = _getContainSizes.width, + height = _getContainSizes.height; - // The canvas element will use `Math.floor` on a float number, so floor first - var canvasWidth = Math.floor(scaledWidth || originalWidth); - var canvasHeight = Math.floor(scaledHeight || originalHeight); + width = Math.min(maxSizes.width, Math.max(minSizes.width, width)); + height = Math.min(maxSizes.height, Math.max(minSizes.height, height)); - var canvas = createElement('canvas'); + var canvas = document.createElement('canvas'); var context = canvas.getContext('2d'); - canvas.width = canvasWidth; - canvas.height = canvasHeight; + canvas.width = width; + canvas.height = height; + + context.fillStyle = options.fillColor || 'transparent'; + context.fillRect(0, 0, width, height); - if (options.fillColor) { - context.fillStyle = options.fillColor; - context.fillRect(0, 0, canvasWidth, canvasHeight); + var _options$imageSmoothi = options.imageSmoothingEnabled, + imageSmoothingEnabled = _options$imageSmoothi === undefined ? true : _options$imageSmoothi, + imageSmoothingQuality = options.imageSmoothingQuality; + + + context.imageSmoothingEnabled = imageSmoothingEnabled; + + if (imageSmoothingQuality) { + context.imageSmoothingQuality = imageSmoothingQuality; } // https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D.drawImage - var parameters = function () { - var source = getSourceCanvas(self.image, self.imageData, options); - var sourceWidth = source.width; - var sourceHeight = source.height; - var canvasData = self.canvasData; - var params = [source]; - - // Source canvas - var srcX = data.x + canvasData.naturalWidth * (Math.abs(data.scaleX || 1) - 1) / 2; - var srcY = data.y + canvasData.naturalHeight * (Math.abs(data.scaleY || 1) - 1) / 2; - var srcWidth = void 0; - var srcHeight = void 0; - - // Destination canvas - var dstX = void 0; - var dstY = void 0; - var dstWidth = void 0; - var dstHeight = void 0; - - if (srcX <= -originalWidth || srcX > sourceWidth) { - srcX = 0; - srcWidth = 0; - dstX = 0; - dstWidth = 0; - } else if (srcX <= 0) { - dstX = -srcX; - srcX = 0; - srcWidth = Math.min(sourceWidth, originalWidth + srcX); - dstWidth = srcWidth; - } else if (srcX <= sourceWidth) { - dstX = 0; - srcWidth = Math.min(originalWidth, sourceWidth - srcX); - dstWidth = srcWidth; - } - - if (srcWidth <= 0 || srcY <= -originalHeight || srcY > sourceHeight) { - srcY = 0; - srcHeight = 0; - dstY = 0; - dstHeight = 0; - } else if (srcY <= 0) { - dstY = -srcY; - srcY = 0; - srcHeight = Math.min(sourceHeight, originalHeight + srcY); - dstHeight = srcHeight; - } else if (srcY <= sourceHeight) { - dstY = 0; - srcHeight = Math.min(originalHeight, sourceHeight - srcY); - dstHeight = srcHeight; - } - - params.push(Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)); - - // Scale destination sizes - if (scaledRatio) { - dstX *= scaledRatio; - dstY *= scaledRatio; - dstWidth *= scaledRatio; - dstHeight *= scaledRatio; - } - - // Avoid "IndexSizeError" in IE and Firefox - if (dstWidth > 0 && dstHeight > 0) { - params.push(Math.floor(dstX), Math.floor(dstY), Math.floor(dstWidth), Math.floor(dstHeight)); - } - - return params; - }(); - - context.imageSmoothingEnabled = !!options.imageSmoothingEnabled; - - if (options.imageSmoothingQuality) { - context.imageSmoothingQuality = options.imageSmoothingQuality; - } - - context.drawImage.apply(context, _toConsumableArray(parameters)); + var sourceWidth = source.width; + var sourceHeight = source.height; + + // Source canvas parameters + var srcX = x; + var srcY = y; + var srcWidth = void 0; + var srcHeight = void 0; + + // Destination canvas parameters + var dstX = void 0; + var dstY = void 0; + var dstWidth = void 0; + var dstHeight = void 0; + + if (srcX <= -initialWidth || srcX > sourceWidth) { + srcX = 0; + srcWidth = 0; + dstX = 0; + dstWidth = 0; + } else if (srcX <= 0) { + dstX = -srcX; + srcX = 0; + srcWidth = Math.min(sourceWidth, initialWidth + srcX); + dstWidth = srcWidth; + } else if (srcX <= sourceWidth) { + dstX = 0; + srcWidth = Math.min(initialWidth, sourceWidth - srcX); + dstWidth = srcWidth; + } + + if (srcWidth <= 0 || srcY <= -initialHeight || srcY > sourceHeight) { + srcY = 0; + srcHeight = 0; + dstY = 0; + dstHeight = 0; + } else if (srcY <= 0) { + dstY = -srcY; + srcY = 0; + srcHeight = Math.min(sourceHeight, initialHeight + srcY); + dstHeight = srcHeight; + } else if (srcY <= sourceHeight) { + dstY = 0; + srcHeight = Math.min(initialHeight, sourceHeight - srcY); + dstHeight = srcHeight; + } + + // All the numerical parameters should be integer for `drawImage` + // https://github.com/fengyuanchen/cropper/issues/476 + var params = [Math.floor(srcX), Math.floor(srcY), Math.floor(srcWidth), Math.floor(srcHeight)]; + + // Avoid "IndexSizeError" + if (dstWidth > 0 && dstHeight > 0) { + var scale = width / initialWidth; + + params.push(Math.floor(dstX * scale), Math.floor(dstY * scale), Math.floor(dstWidth * scale), Math.floor(dstHeight * scale)); + } + + context.drawImage.apply(context, [source].concat(params)); return canvas; }, /** - * Change the aspect ratio of the crop box - * - * @param {Number} aspectRatio + * Change the aspect ratio of the crop box. + * @param {number} aspectRatio - The new aspect ratio. + * @returns {Object} this */ setAspectRatio: function setAspectRatio(aspectRatio) { - var self = this; - var options = self.options; + var options = this.options; + - if (!self.disabled && !isUndefined(aspectRatio)) { + if (!this.disabled && !isUndefined(aspectRatio)) { // 0 -> NaN options.aspectRatio = Math.max(0, aspectRatio) || NaN; - if (self.ready) { - self.initCropBox(); + if (this.ready) { + this.initCropBox(); - if (self.cropped) { - self.renderCropBox(); + if (this.cropped) { + this.renderCropBox(); } } } - return self; + return this; }, /** - * Change the drag mode - * - * @param {String} mode (optional) + * Change the drag mode. + * @param {string} mode - The new drag mode. + * @returns {Object} this */ setDragMode: function setDragMode(mode) { - var self = this; - var options = self.options; - var dragBox = self.dragBox; - var face = self.face; - var croppable = void 0; - var movable = void 0; - - if (self.loaded && !self.disabled) { - croppable = mode === 'crop'; - movable = options.movable && mode === 'move'; - mode = croppable || movable ? mode : 'none'; - - setData(dragBox, 'action', mode); - toggleClass(dragBox, 'cropper-crop', croppable); - toggleClass(dragBox, 'cropper-move', movable); + var options = this.options, + dragBox = this.dragBox, + face = this.face; + + + if (this.loaded && !this.disabled) { + var croppable = mode === DRAG_MODE_CROP; + var movable = options.movable && mode === DRAG_MODE_MOVE; + + mode = croppable || movable ? mode : DRAG_MODE_NONE; + + setData(dragBox, DATA_ACTION, mode); + toggleClass(dragBox, CLASS_CROP, croppable); + toggleClass(dragBox, CLASS_MOVE, movable); if (!options.cropBoxMovable) { // Sync drag mode to crop box when it is not movable - setData(face, 'action', mode); - toggleClass(face, 'cropper-crop', croppable); - toggleClass(face, 'cropper-move', movable); + setData(face, DATA_ACTION, mode); + toggleClass(face, CLASS_CROP, croppable); + toggleClass(face, CLASS_MOVE, movable); } } - return self; + return this; } }; @@ -3032,55 +3222,47 @@ var _createClass = function () { function defineProperties(target, props) { for function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } -// Constants -var NAMESPACE = 'cropper'; - -// Classes -var CLASS_HIDDEN = NAMESPACE + '-hidden'; - -// Events -var EVENT_ERROR = 'error'; -var EVENT_LOAD = 'load'; -var EVENT_READY = 'ready'; -var EVENT_CROP = 'crop'; - -// RegExps -var REGEXP_DATA_URL = /^data:/; -var REGEXP_DATA_URL_JPEG = /^data:image\/jpeg;base64,/; - -var AnotherCropper = void 0; +var AnotherCropper = window.Cropper; var Cropper = function () { - function Cropper(element, options) { + /** + * Create a new Cropper. + * @param {Element} element - The target element for cropping. + * @param {Object} [options={}] - The configuration options. + */ + function Cropper(element) { + var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _classCallCheck(this, Cropper); - var self = this; - - self.element = element; - self.options = extend({}, DEFAULTS, isPlainObject(options) && options); - self.loaded = false; - self.ready = false; - self.complete = false; - self.rotated = false; - self.cropped = false; - self.disabled = false; - self.replaced = false; - self.limited = false; - self.wheeling = false; - self.isImg = false; - self.originalUrl = ''; - self.canvasData = null; - self.cropBoxData = null; - self.previews = null; - self.pointers = {}; - self.init(); + if (!element || !REGEXP_TAG_NAME.test(element.tagName)) { + throw new Error('The first argument is required and must be an or element.'); + } + + this.element = element; + this.options = extend({}, DEFAULTS, isPlainObject(options) && options); + this.complete = false; + this.cropped = false; + this.disabled = false; + this.isImg = false; + this.limited = false; + this.loaded = false; + this.ready = false; + this.replaced = false; + this.wheeling = false; + this.originalUrl = ''; + this.canvasData = null; + this.cropBoxData = null; + this.previews = null; + this.pointers = {}; + this.init(); } _createClass(Cropper, [{ key: 'init', value: function init() { - var self = this; - var element = self.element; + var element = this.element; + var tagName = element.tagName.toLowerCase(); var url = void 0; @@ -3088,14 +3270,14 @@ var Cropper = function () { return; } - setData(element, NAMESPACE, self); + setData(element, NAMESPACE, this); if (tagName === 'img') { - self.isImg = true; + this.isImg = true; // e.g.: "img/picture.jpg" url = element.getAttribute('src'); - self.originalUrl = url; + this.originalUrl = url; // Stop when it's a blank image if (!url) { @@ -3108,45 +3290,48 @@ var Cropper = function () { url = element.toDataURL(); } - self.load(url); + this.load(url); } }, { key: 'load', value: function load(url) { - var self = this; - var options = self.options; - var element = self.element; + var _this = this; if (!url) { return; } - self.url = url; - self.imageData = {}; + this.url = url; + this.imageData = {}; + + var element = this.element, + options = this.options; + if (!options.checkOrientation || !window.ArrayBuffer) { - self.clone(); + this.clone(); return; } // XMLHttpRequest disallows to open a Data URL in some browsers like IE11 and Safari if (REGEXP_DATA_URL.test(url)) { if (REGEXP_DATA_URL_JPEG.test(url)) { - self.read(dataURLToArrayBuffer(url)); + this.read(dataURLToArrayBuffer(url)); } else { - self.clone(); + this.clone(); } + return; } var xhr = new XMLHttpRequest(); xhr.onerror = function () { - self.clone(); + _this.clone(); }; xhr.onload = function () { - self.read(xhr.response); + _this.read(xhr.response); }; if (options.checkCrossOrigin && isCrossOriginURL(url) && element.crossOrigin) { @@ -3161,57 +3346,22 @@ var Cropper = function () { }, { key: 'read', value: function read(arrayBuffer) { - var self = this; - var options = self.options; + var options = this.options, + imageData = this.imageData; + var orientation = getOrientation(arrayBuffer); - var imageData = self.imageData; var rotate = 0; var scaleX = 1; var scaleY = 1; if (orientation > 1) { - self.url = arrayBufferToDataURL(arrayBuffer); - - switch (orientation) { - // flip horizontal - case 2: - scaleX = -1; - break; - - // rotate left 180° - case 3: - rotate = -180; - break; - - // flip vertical - case 4: - scaleY = -1; - break; - - // flip vertical + rotate right 90° - case 5: - rotate = 90; - scaleY = -1; - break; - - // rotate right 90° - case 6: - rotate = 90; - break; - - // flip horizontal + rotate right 90° - case 7: - rotate = 90; - scaleX = -1; - break; + this.url = arrayBufferToDataURL(arrayBuffer, 'image/jpeg'); - // rotate left 90° - case 8: - rotate = -90; - break; + var _parseOrientation = parseOrientation(orientation); - default: - } + rotate = _parseOrientation.rotate; + scaleX = _parseOrientation.scaleX; + scaleY = _parseOrientation.scaleY; } if (options.rotatable) { @@ -3223,20 +3373,21 @@ var Cropper = function () { imageData.scaleY = scaleY; } - self.clone(); + this.clone(); } }, { key: 'clone', value: function clone() { - var self = this; - var element = self.element; - var url = self.url; + var element = this.element, + url = this.url; + var crossOrigin = void 0; var crossOriginUrl = void 0; - if (self.options.checkCrossOrigin && isCrossOriginURL(url)) { + if (this.options.checkCrossOrigin && isCrossOriginURL(url)) { crossOrigin = element.crossOrigin; + if (crossOrigin) { crossOriginUrl = url; } else { @@ -3247,10 +3398,10 @@ var Cropper = function () { } } - self.crossOrigin = crossOrigin; - self.crossOriginUrl = crossOriginUrl; + this.crossOrigin = crossOrigin; + this.crossOriginUrl = crossOriginUrl; - var image = createElement('img'); + var image = document.createElement('img'); if (crossOrigin) { image.crossOrigin = crossOrigin; @@ -3258,98 +3409,99 @@ var Cropper = function () { image.src = crossOriginUrl || url; - var start = proxy(self.start, self); - var stop = proxy(self.stop, self); + var start = proxy(this.start, this); + var stop = proxy(this.stop, this); - self.image = image; - self.onStart = start; - self.onStop = stop; + this.image = image; + this.onStart = start; + this.onStop = stop; - if (self.isImg) { + if (this.isImg) { if (element.complete) { - self.start(); + this.start(); } else { addListener(element, EVENT_LOAD, start); } } else { addListener(image, EVENT_LOAD, start); addListener(image, EVENT_ERROR, stop); - addClass(image, 'cropper-hide'); + addClass(image, CLASS_HIDE); element.parentNode.insertBefore(image, element.nextSibling); } } }, { key: 'start', value: function start(event) { - var self = this; - var image = self.isImg ? self.element : self.image; + var _this2 = this; + + var image = this.isImg ? this.element : this.image; if (event) { - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); } - getImageSize(image, function (naturalWidth, naturalHeight) { - extend(self.imageData, { + getImageNaturalSizes(image, function (naturalWidth, naturalHeight) { + extend(_this2.imageData, { naturalWidth: naturalWidth, naturalHeight: naturalHeight, aspectRatio: naturalWidth / naturalHeight }); - - self.loaded = true; - self.build(); + _this2.loaded = true; + _this2.build(); }); } }, { key: 'stop', value: function stop() { - var self = this; - var image = self.image; + var image = this.image; - removeListener(image, EVENT_LOAD, self.onStart); - removeListener(image, EVENT_ERROR, self.onStop); - removeChild(image); - self.image = null; + removeListener(image, EVENT_LOAD, this.onStart); + removeListener(image, EVENT_ERROR, this.onStop); + image.parentNode.removeChild(image); + this.image = null; } }, { key: 'build', value: function build() { - var self = this; - var options = self.options; - var element = self.element; - var image = self.image; + var _this3 = this; - if (!self.loaded) { + if (!this.loaded) { return; } // Unbuild first when replace - if (self.ready) { - self.unbuild(); + if (this.ready) { + this.unbuild(); } + var element = this.element, + options = this.options, + image = this.image; + // Create cropper elements + var container = element.parentNode; - var template = createElement('div'); + var template = document.createElement('div'); template.innerHTML = TEMPLATE; - var cropper = getByClass(template, 'cropper-container')[0]; - var canvas = getByClass(cropper, 'cropper-canvas')[0]; - var dragBox = getByClass(cropper, 'cropper-drag-box')[0]; - var cropBox = getByClass(cropper, 'cropper-crop-box')[0]; - var face = getByClass(cropBox, 'cropper-face')[0]; + var cropper = template.querySelector('.' + NAMESPACE + '-container'); + var canvas = cropper.querySelector('.' + NAMESPACE + '-canvas'); + var dragBox = cropper.querySelector('.' + NAMESPACE + '-drag-box'); + var cropBox = cropper.querySelector('.' + NAMESPACE + '-crop-box'); + var face = cropBox.querySelector('.' + NAMESPACE + '-face'); - self.container = container; - self.cropper = cropper; - self.canvas = canvas; - self.dragBox = dragBox; - self.cropBox = cropBox; - self.viewBox = getByClass(cropper, 'cropper-view-box')[0]; - self.face = face; + this.container = container; + this.cropper = cropper; + this.canvas = canvas; + this.dragBox = dragBox; + this.cropBox = cropBox; + this.viewBox = cropper.querySelector('.' + NAMESPACE + '-view-box'); + this.face = face; - appendChild(canvas, image); + canvas.appendChild(image); // Hide the original image addClass(element, CLASS_HIDDEN); @@ -3358,114 +3510,123 @@ var Cropper = function () { container.insertBefore(cropper, element.nextSibling); // Show the image if is hidden - if (!self.isImg) { - removeClass(image, 'cropper-hide'); + if (!this.isImg) { + removeClass(image, CLASS_HIDE); } - self.initPreview(); - self.bind(); + this.initPreview(); + this.bind(); options.aspectRatio = Math.max(0, options.aspectRatio) || NaN; options.viewMode = Math.max(0, Math.min(3, Math.round(options.viewMode))) || 0; - self.cropped = options.autoCrop; + this.cropped = options.autoCrop; if (options.autoCrop) { if (options.modal) { - addClass(dragBox, 'cropper-modal'); + addClass(dragBox, CLASS_MODAL); } } else { addClass(cropBox, CLASS_HIDDEN); } if (!options.guides) { - addClass(getByClass(cropBox, 'cropper-dashed'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-dashed'), CLASS_HIDDEN); } if (!options.center) { - addClass(getByClass(cropBox, 'cropper-center'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-center'), CLASS_HIDDEN); } if (options.background) { - addClass(cropper, 'cropper-bg'); + addClass(cropper, NAMESPACE + '-bg'); } if (!options.highlight) { - addClass(face, 'cropper-invisible'); + addClass(face, CLASS_INVISIBLE); } if (options.cropBoxMovable) { - addClass(face, 'cropper-move'); - setData(face, 'action', 'all'); + addClass(face, CLASS_MOVE); + setData(face, DATA_ACTION, ACTION_ALL); } if (!options.cropBoxResizable) { - addClass(getByClass(cropBox, 'cropper-line'), CLASS_HIDDEN); - addClass(getByClass(cropBox, 'cropper-point'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-line'), CLASS_HIDDEN); + addClass(cropBox.getElementsByClassName(NAMESPACE + '-point'), CLASS_HIDDEN); } - self.setDragMode(options.dragMode); - self.render(); - self.ready = true; - self.setData(options.data); + this.setDragMode(options.dragMode); + this.render(); + this.ready = true; + this.setData(options.data); // Call the "ready" option asynchronously to keep "image.cropper" is defined - self.completing = setTimeout(function () { + this.completing = setTimeout(function () { if (isFunction(options.ready)) { - addListener(element, EVENT_READY, options.ready, true); + addListener(element, EVENT_READY, options.ready, { + once: true + }); } dispatchEvent(element, EVENT_READY); - dispatchEvent(element, EVENT_CROP, self.getData()); + dispatchEvent(element, EVENT_CROP, _this3.getData()); - self.complete = true; + _this3.complete = true; }, 0); } }, { key: 'unbuild', value: function unbuild() { - var self = this; - - if (!self.ready) { + if (!this.ready) { return; } - if (!self.complete) { - clearTimeout(self.completing); + if (!this.complete) { + clearTimeout(this.completing); } - self.ready = false; - self.complete = false; - self.initialImageData = null; + this.ready = false; + this.complete = false; + this.initialImageData = null; // Clear `initialCanvasData` is necessary when replace - self.initialCanvasData = null; - self.initialCropBoxData = null; - self.containerData = null; - self.canvasData = null; + this.initialCanvasData = null; + this.initialCropBoxData = null; + this.containerData = null; + this.canvasData = null; // Clear `cropBoxData` is necessary when replace - self.cropBoxData = null; - self.unbind(); - - self.resetPreview(); - self.previews = null; + this.cropBoxData = null; + this.unbind(); + this.resetPreview(); + this.previews = null; + this.viewBox = null; + this.cropBox = null; + this.dragBox = null; + this.canvas = null; + this.container = null; + this.cropper.parentNode.removeChild(this.cropper); + this.cropper = null; + } + + /** + * Get the no conflict cropper class. + * @returns {Cropper} The cropper class. + */ - self.viewBox = null; - self.cropBox = null; - self.dragBox = null; - self.canvas = null; - self.container = null; - - removeChild(self.cropper); - self.cropper = null; - } }], [{ key: 'noConflict', value: function noConflict() { window.Cropper = AnotherCropper; return Cropper; } + + /** + * Change the default options. + * @param {Object} options - The new default options. + */ + }, { key: 'setDefaults', value: function setDefaults(options) { @@ -3476,17 +3637,7 @@ var Cropper = function () { return Cropper; }(); -extend(Cropper.prototype, render); -extend(Cropper.prototype, preview); -extend(Cropper.prototype, events); -extend(Cropper.prototype, handlers); -extend(Cropper.prototype, change); -extend(Cropper.prototype, methods); - -if (typeof window !== 'undefined') { - AnotherCropper = window.Cropper; - window.Cropper = Cropper; -} +extend(Cropper.prototype, render, preview, events, handlers, change, methods); return Cropper; diff --git a/package-lock.json b/package-lock.json index 3bac06ede..2af24144f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,13 @@ { "name": "cropperjs", - "version": "1.0.0", + "version": "1.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { "acorn": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.1.tgz", - "integrity": "sha512-vOk6uEMctu0vQrvuSqFdJyqj1Q0S5VTDL79qtjo+DhRr+1mmaD+tluFSCZqhvi/JUhXSzoZN2BhtstaPEeE8cw==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.1.2.tgz", + "integrity": "sha512-o96FZLJBPY1lvTuJylGA9Bk3t/GKPPJG8H0ydQQl01crzwJgspa4AEIq/pVTXigmK0PHVQhiAtn8WMBLL9D2WA==", "dev": true }, "acorn-jsx": { @@ -28,9 +28,9 @@ } }, "ajv": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.2.tgz", - "integrity": "sha1-R8aNaehvXZUxA7AHSpQw3GPaXjk=", + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.2.3.tgz", + "integrity": "sha1-wG9Zh3jETGsWGrr+NGa4GtGBTtI=", "dev": true, "requires": { "co": "4.6.0", @@ -40,9 +40,9 @@ } }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-2.1.0.tgz", + "integrity": "sha1-opbhf3v658HOT34N5T0pyzIWLfA=", "dev": true }, "alphanum-sort": { @@ -51,10 +51,16 @@ "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM=", "dev": true }, + "amdefine": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", + "integrity": "sha1-SlKCrBZHKek2Gbz9OtFR+BfOkfU=", + "dev": true + }, "ansi-escapes": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-2.0.0.tgz", - "integrity": "sha1-W65SvkJIeN2Xg+iRDj/Cki6DyBs=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", "dev": true }, "ansi-regex": { @@ -103,12 +109,24 @@ "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", "dev": true }, + "array-differ": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", + "integrity": "sha1-7/UuN1gknTO+QCuLuOVkuytdQDE=", + "dev": true + }, "array-filter": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/array-filter/-/array-filter-0.0.1.tgz", "integrity": "sha1-fajPLiZijtcygDWB/SH2fKzS7uw=", "dev": true }, + "array-find-index": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz", + "integrity": "sha1-3wEKoSh+Fku9pvlyOwqWoexBh6E=", + "dev": true + }, "array-map": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/array-map/-/array-map-0.0.0.tgz", @@ -150,13 +168,13 @@ }, "asn1": { "version": "0.2.3", - "resolved": "http://registry.npm.taobao.org/asn1/download/asn1-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz", "integrity": "sha1-2sh4dxPJlmhJ/IGAd36+nB3fO4Y=", "dev": true }, "assert-plus": { "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-0.2.0.tgz", "integrity": "sha1-104bh+ev/A24qttwIfP+SBAasjQ=", "dev": true }, @@ -168,7 +186,7 @@ }, "asynckit": { "version": "0.4.0", - "resolved": "http://registry.npm.taobao.org/asynckit/download/asynckit-0.4.0.tgz", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=", "dev": true }, @@ -179,10 +197,10 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000721", + "caniuse-db": "1.0.30000744", "normalize-range": "0.1.2", "num2fraction": "1.2.2", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" }, "dependencies": { @@ -192,21 +210,21 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000721", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000744", + "electron-to-chromium": "1.3.24" } } } }, "aws-sign2": { "version": "0.6.0", - "resolved": "http://registry.npm.taobao.org/aws-sign2/download/aws-sign2-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.6.0.tgz", "integrity": "sha1-FDQt0428yU0OW4fXY81jYSwOeU8=", "dev": true }, "aws4": { "version": "1.6.0", - "resolved": "http://registry.npm.taobao.org/aws4/download/aws4-1.6.0.tgz", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.6.0.tgz", "integrity": "sha1-g+9cqGCysy5KDe7e6MdxudtXRx4=", "dev": true }, @@ -238,7 +256,7 @@ "babel-types": "6.26.0", "babylon": "6.18.0", "convert-source-map": "1.5.0", - "debug": "2.6.8", + "debug": "2.6.9", "json5": "0.5.1", "lodash": "4.17.4", "minimatch": "3.0.4", @@ -745,7 +763,7 @@ "babel-plugin-transform-es2015-unicode-regex": "6.24.1", "babel-plugin-transform-exponentiation-operator": "6.24.1", "babel-plugin-transform-regenerator": "6.26.0", - "browserslist": "2.4.0", + "browserslist": "2.5.0", "invariant": "2.2.2", "semver": "5.4.1" } @@ -762,7 +780,7 @@ "home-or-tmp": "2.0.0", "lodash": "4.17.4", "mkdirp": "0.5.1", - "source-map-support": "0.4.16" + "source-map-support": "0.4.18" } }, "babel-runtime": { @@ -799,7 +817,7 @@ "babel-runtime": "6.26.0", "babel-types": "6.26.0", "babylon": "6.18.0", - "debug": "2.6.8", + "debug": "2.6.9", "globals": "9.18.0", "invariant": "2.2.2", "lodash": "4.17.4" @@ -831,7 +849,7 @@ }, "bcrypt-pbkdf": { "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/bcrypt-pbkdf/download/bcrypt-pbkdf-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", "dev": true, "optional": true, @@ -845,9 +863,15 @@ "integrity": "sha1-muuabF6IY4qtFx4Wf1kAq+JINdA=", "dev": true }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==", + "dev": true + }, "boom": { "version": "2.10.1", - "resolved": "http://registry.npm.taobao.org/boom/download/boom-2.10.1.tgz", + "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { @@ -876,13 +900,13 @@ } }, "browserslist": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.4.0.tgz", - "integrity": "sha512-aM2Gt4x9bVlCUteADBS6JP0F+2tMWKM1jQzUulVROtdFWFIcIVvY76AJbr7GDqy0eDhn+PcnpzzivGxY4qiaKQ==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-2.5.0.tgz", + "integrity": "sha512-6Vw1LIigGw8zCK0gxczksUMZlO+oPUwBazAztMmFL/F8D5wB0qCuxRJGYgYM3JzaO0v2ZMRIg+nnnOgNsPGHeA==", "dev": true, "requires": { - "caniuse-lite": "1.0.30000721", - "electron-to-chromium": "1.3.20" + "caniuse-lite": "1.0.30000744", + "electron-to-chromium": "1.3.24" } }, "builtin-modules": { @@ -907,11 +931,21 @@ "dev": true }, "camelcase": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", - "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=", "dev": true }, + "camelcase-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", + "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "map-obj": "1.0.1" + } + }, "caniuse-api": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-1.6.1.tgz", @@ -919,7 +953,7 @@ "dev": true, "requires": { "browserslist": "1.7.7", - "caniuse-db": "1.0.30000721", + "caniuse-db": "1.0.30000744", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" }, @@ -930,27 +964,27 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000721", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000744", + "electron-to-chromium": "1.3.24" } } } }, "caniuse-db": { - "version": "1.0.30000721", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000721.tgz", - "integrity": "sha1-zcUu/o+C3RORZhW3job3BOzmGAI=", + "version": "1.0.30000744", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30000744.tgz", + "integrity": "sha1-AHWP991fcTjTShVgjcz3Glllb/4=", "dev": true }, "caniuse-lite": { - "version": "1.0.30000721", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000721.tgz", - "integrity": "sha1-kxohp72FAWMAMo0h8SbYS3NDfTU=", + "version": "1.0.30000744", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000744.tgz", + "integrity": "sha1-hg+lyDujT+YZOX1gfzC7R0ghZxs=", "dev": true }, "caseless": { "version": "0.12.0", - "resolved": "http://registry.npm.taobao.org/caseless/download/caseless-0.12.0.tgz", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, @@ -990,9 +1024,9 @@ "dev": true }, "clap": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.0.tgz", - "integrity": "sha1-WckP4+E3EEdG/xlGmiemNP9oyFc=", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/clap/-/clap-1.2.3.tgz", + "integrity": "sha512-4CoL/A3hf90V3VIEjeuhSvlGFEHKzOz+Wfc2IVZc+FaUgU0ZQafJTP49fvnULipOPcAfqhyI2duwQyns6xqjYA==", "dev": true, "requires": { "chalk": "1.1.3" @@ -1008,9 +1042,9 @@ } }, "cli-spinners": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.0.0.tgz", - "integrity": "sha1-75h+09SDkaw9q5GAtAanQhgNbmo=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-1.1.0.tgz", + "integrity": "sha1-8YR7FohE2RemceudFH499JfJDQY=", "dev": true }, "cli-width": { @@ -1058,6 +1092,16 @@ "integrity": "sha1-Jgt6meux7f4kdTgXX3gyQ8sZ0Uk=", "dev": true }, + "clone-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-1.0.0.tgz", + "integrity": "sha1-6uCiQT9VwJQvgYwin+/OhF1/Oxw=", + "dev": true, + "requires": { + "is-regexp": "1.0.0", + "is-supported-regexp-flag": "1.0.0" + } + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -1099,6 +1143,12 @@ "color-name": "1.1.3" } }, + "color-diff": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/color-diff/-/color-diff-0.1.7.tgz", + "integrity": "sha1-bbeM2UgqjkWdQIIer0tQMoPcuOI=", + "dev": true + }, "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", @@ -1114,6 +1164,44 @@ "color-name": "1.1.3" } }, + "colorguard": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/colorguard/-/colorguard-1.2.0.tgz", + "integrity": "sha1-8/rK9cquuk71RlPZ+yW7cxd8DYQ=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "color-diff": "0.1.7", + "log-symbols": "1.0.2", + "object-assign": "4.1.1", + "pipetteur": "2.0.3", + "plur": "2.1.2", + "postcss": "5.2.18", + "postcss-reporter": "1.4.1", + "text-table": "0.2.0", + "yargs": "1.3.3" + }, + "dependencies": { + "postcss-reporter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", + "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.17.4", + "log-symbols": "1.0.2", + "postcss": "5.2.18" + } + }, + "yargs": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-1.3.3.tgz", + "integrity": "sha1-BU3oth8i7v23IHBZ6u+da4P7kxo=", + "dev": true + } + } + }, "colormin": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/colormin/-/colormin-1.1.2.tgz", @@ -1133,7 +1221,7 @@ }, "combined-stream": { "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/combined-stream/download/combined-stream-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.5.tgz", "integrity": "sha1-k4NwpXtKUd6ix3wV1cX9+JUWQAk=", "dev": true, "requires": { @@ -1210,6 +1298,45 @@ } } }, + "cp-file": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cp-file/-/cp-file-3.2.0.tgz", + "integrity": "sha1-b4NhYlRiTwrViqSqjQdvAmvn4Yg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "mkdirp": "0.5.1", + "nested-error-stacks": "1.0.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "readable-stream": "2.3.3" + } + }, + "cpy": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/cpy/-/cpy-4.0.1.tgz", + "integrity": "sha1-tnJn66LzlgugalphrJQDNCKDNCQ=", + "dev": true, + "requires": { + "cp-file": "3.2.0", + "globby": "4.1.0", + "meow": "3.7.0", + "nested-error-stacks": "1.0.2", + "object-assign": "4.1.1", + "pinkie-promise": "2.0.1" + } + }, + "cpy-cli": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/cpy-cli/-/cpy-cli-1.0.1.tgz", + "integrity": "sha1-Z/taSi3sKMqKv/N13kuecfanVhw=", + "dev": true, + "requires": { + "cpy": "4.0.1", + "meow": "3.7.0" + } + }, "cross-spawn": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", @@ -1223,7 +1350,7 @@ }, "cryptiles": { "version": "2.0.5", - "resolved": "http://registry.npm.taobao.org/cryptiles/download/cryptiles-2.0.5.tgz", + "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { @@ -1231,14 +1358,14 @@ } }, "css-color-function": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.0.tgz", - "integrity": "sha1-csdnuvl48BuKipT0Lxe6XSKndvw=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/css-color-function/-/css-color-function-1.3.3.tgz", + "integrity": "sha1-jtJMLAIFBzM5+voAS8jBQfzLKC4=", "dev": true, "requires": { "balanced-match": "0.1.0", "color": "0.11.4", - "debug": "0.7.4", + "debug": "3.1.0", "rgb": "0.1.0" }, "dependencies": { @@ -1249,9 +1376,29 @@ "dev": true }, "debug": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-0.7.4.tgz", - "integrity": "sha1-BuHqgILCyxTjmAbiLi9vdX+Srzk=", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + } + } + }, + "css-color-list": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-color-list/-/css-color-list-0.0.1.tgz", + "integrity": "sha1-hxjoaVrnosyHh76HFfHACKfyixU=", + "dev": true, + "requires": { + "css-color-names": "0.0.1" + }, + "dependencies": { + "css-color-names": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.1.tgz", + "integrity": "sha1-XQVI+iVkVu3kqaDCrHqxnT6xrYE=", "dev": true } } @@ -1262,6 +1409,54 @@ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", "dev": true }, + "css-rule-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-rule-stream/-/css-rule-stream-1.1.0.tgz", + "integrity": "sha1-N4bnGYmD2WWibjGVfgkHjLt3BaI=", + "dev": true, + "requires": { + "css-tokenize": "1.0.1", + "duplexer2": "0.0.2", + "ldjson-stream": "1.2.1", + "through2": "0.6.5" + } + }, + "css-tokenize": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-tokenize/-/css-tokenize-1.0.1.tgz", + "integrity": "sha1-RiXLHtohwUOFi3+B1oA8HSb8FL4=", + "dev": true, + "requires": { + "inherits": "2.0.3", + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "css-unit-converter": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.1.tgz", @@ -1279,7 +1474,7 @@ "defined": "1.0.0", "has": "1.0.1", "object-assign": "4.1.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-calc": "5.3.1", "postcss-colormin": "2.2.2", "postcss-convert-values": "2.6.1", @@ -1314,7 +1509,7 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "1.2.0", + "clap": "1.2.3", "source-map": "0.5.7" } }, @@ -1324,9 +1519,18 @@ "integrity": "sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs=", "dev": true }, + "currently-unhandled": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", + "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", + "dev": true, + "requires": { + "array-find-index": "1.0.2" + } + }, "dashdash": { "version": "1.14.1", - "resolved": "http://registry.npm.taobao.org/dashdash/download/dashdash-1.14.1.tgz", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { @@ -1335,16 +1539,16 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "debug": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.8.tgz", - "integrity": "sha1-5zFTHKLt4n0YgiJCfaF4IdaP9Pw=", + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "dev": true, "requires": { "ms": "2.0.0" @@ -1390,19 +1594,49 @@ "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1", - "rimraf": "2.6.1" + "rimraf": "2.6.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "arrify": "1.0.1", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + } } }, "delayed-stream": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/delayed-stream/download/delayed-stream-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", "dev": true }, "dependency-graph": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.5.0.tgz", - "integrity": "sha1-ce33lF27qGwbGayYK2r7ZHa1bdU=", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.5.1.tgz", + "integrity": "sha512-nk3OjiI68T3876/tsm4Hm57ye7zc4Kl87hkcALBMCuSrN1q1NvuY5HCnSSkoJjGdrMo5gmu0WTN2cV/D76q/mw==", "dev": true }, "detect-indent": { @@ -1414,6 +1648,12 @@ "repeating": "2.0.1" } }, + "diff": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.4.0.tgz", + "integrity": "sha512-QpVuMTEoJMF7cKzi6bvWhRulU1fZqZnvyVQgNhPaxxuTYwyjn/j1v9falseQ/uXWwPnO56RBfwtg4h/EQXmucA==", + "dev": true + }, "doctrine": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.0.tgz", @@ -1424,15 +1664,135 @@ "isarray": "1.0.0" } }, + "doiuse": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/doiuse/-/doiuse-2.6.0.tgz", + "integrity": "sha1-GJLRC2Gpo1at2/K2FJM+gfi7ODQ=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000744", + "css-rule-stream": "1.1.0", + "duplexer2": "0.0.2", + "jsonfilter": "1.1.2", + "ldjson-stream": "1.2.1", + "lodash": "4.17.4", + "multimatch": "2.1.0", + "postcss": "5.2.18", + "source-map": "0.4.4", + "through2": "0.6.5", + "yargs": "3.32.0" + }, + "dependencies": { + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000744", + "electron-to-chromium": "1.3.24" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "dev": true, + "requires": { + "number-is-nan": "1.0.1" + } + }, + "os-locale": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "dev": true, + "requires": { + "lcid": "1.0.0" + } + }, + "source-map": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.4.4.tgz", + "integrity": "sha1-66T12pwNyZneaAMti092FzZSA2s=", + "dev": true, + "requires": { + "amdefine": "1.0.1" + } + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "dev": true, + "requires": { + "code-point-at": "1.1.0", + "is-fullwidth-code-point": "1.0.0", + "strip-ansi": "3.0.1" + } + }, + "yargs": { + "version": "3.32.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "dev": true, + "requires": { + "camelcase": "2.1.1", + "cliui": "3.2.0", + "decamelize": "1.2.0", + "os-locale": "1.4.0", + "string-width": "1.0.2", + "window-size": "0.1.4", + "y18n": "3.2.1" + } + } + } + }, "duplexer": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.1.tgz", "integrity": "sha1-rOb/gIwc5mtX0ev5eXessCM0z8E=", "dev": true }, + "duplexer2": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", + "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", + "dev": true, + "requires": { + "readable-stream": "1.1.14" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "ecc-jsbn": { "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/ecc-jsbn/download/ecc-jsbn-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz", "integrity": "sha1-D8c6ntXw1Tw4GTOYUj735UN3dQU=", "dev": true, "optional": true, @@ -1440,10 +1800,34 @@ "jsbn": "0.1.1" } }, + "editorconfig": { + "version": "0.13.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", + "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", + "dev": true, + "requires": { + "bluebird": "3.5.1", + "commander": "2.11.0", + "lru-cache": "3.2.0", + "semver": "5.4.1", + "sigmund": "1.0.1" + }, + "dependencies": { + "lru-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", + "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "dev": true, + "requires": { + "pseudomap": "1.0.2" + } + } + } + }, "electron-to-chromium": { - "version": "1.3.20", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.20.tgz", - "integrity": "sha1-Lu3VzLrn3cVX9orR/OnBcukV5OU=", + "version": "1.3.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.24.tgz", + "integrity": "sha1-m3uIuwXOufoBahd4M8wt3jiPIbY=", "dev": true }, "error-ex": { @@ -1456,9 +1840,9 @@ } }, "es-abstract": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.8.1.tgz", - "integrity": "sha512-G6pkMLdmxF3dh4hbuYuQiku29rRqo9p5+iRf7mZTEELT/xZ/D9Vzg04ddlvzJuJuCmZp1WBbfbVLZEeygYNkpw==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.9.0.tgz", + "integrity": "sha512-kk3IJoKo7A3pWJc0OV8yZ/VEX2oSUytfekrJiqoxBlKJMFAJVJVpGdHClCCTdv+Fn2zHfpDHHIelMFhZVfef3Q==", "dev": true, "requires": { "es-to-primitive": "1.1.1", @@ -1481,7 +1865,7 @@ }, "es6-promise": { "version": "4.0.5", - "resolved": "http://registry.npm.taobao.org/es6-promise/download/es6-promise-4.0.5.tgz", + "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.0.5.tgz", "integrity": "sha1-eILzCt3lskDM+n99eMVIMwlRrkI=", "dev": true }, @@ -1492,20 +1876,20 @@ "dev": true }, "eslint": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.6.0.tgz", - "integrity": "sha1-mM7UpwaoervmMgeJXQAjo44lC74=", + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-4.8.0.tgz", + "integrity": "sha1-Ip7w41Tg5h2DfHqA/fuoJeGZgV4=", "dev": true, "requires": { - "ajv": "5.2.2", + "ajv": "5.2.3", "babel-code-frame": "6.26.0", "chalk": "2.1.0", "concat-stream": "1.6.0", "cross-spawn": "5.1.0", - "debug": "2.6.8", + "debug": "3.1.0", "doctrine": "2.0.0", "eslint-scope": "3.7.1", - "espree": "3.5.0", + "espree": "3.5.1", "esquery": "1.0.0", "estraverse": "4.2.0", "esutils": "2.0.2", @@ -1515,9 +1899,9 @@ "globals": "9.18.0", "ignore": "3.3.5", "imurmurhash": "0.1.4", - "inquirer": "3.2.3", + "inquirer": "3.3.0", "is-resolvable": "1.0.0", - "js-yaml": "3.9.1", + "js-yaml": "3.10.0", "json-stable-stringify": "1.0.1", "levn": "0.3.0", "lodash": "4.17.4", @@ -1526,13 +1910,13 @@ "natural-compare": "1.4.0", "optionator": "0.8.2", "path-is-inside": "1.0.2", - "pluralize": "4.0.0", + "pluralize": "7.0.0", "progress": "2.0.0", "require-uncached": "1.0.3", "semver": "5.4.1", "strip-ansi": "4.0.0", "strip-json-comments": "2.0.1", - "table": "4.0.1", + "table": "4.0.2", "text-table": "0.2.0" }, "dependencies": { @@ -1562,12 +1946,35 @@ "supports-color": "4.4.0" } }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "dev": true, + "requires": { + "ms": "2.0.0" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, "has-flag": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", @@ -1575,9 +1982,9 @@ "dev": true }, "js-yaml": { - "version": "3.9.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.9.1.tgz", - "integrity": "sha512-CbcG379L1e+mWBnLvHWWeLs8GyV/EMw862uLI3c+GxVyDHWZcjZinwuBd3iW2pgxgIlksW/1vNJa4to+RvDOww==", + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", "dev": true, "requires": { "argparse": "1.0.9", @@ -1605,9 +2012,9 @@ } }, "eslint-config-airbnb-base": { - "version": "11.3.2", - "resolved": "http://registry.npm.taobao.org/eslint-config-airbnb-base/download/eslint-config-airbnb-base-11.3.2.tgz", - "integrity": "sha1-hwOxGr48iKx+wrdFt/31LgCuaAo=", + "version": "12.0.2", + "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-12.0.2.tgz", + "integrity": "sha512-rQqOvAzrMC3BBCH6Dd/1RenDi+RW4vdgnh8xcPf6sgd324ad6aX7hSZ52L1SfDGe2VsZR2yB5uPvDfXYvxHZmA==", "dev": true, "requires": { "eslint-restricted-globals": "0.1.1" @@ -1619,7 +2026,7 @@ "integrity": "sha512-yUtXS15gIcij68NmXmP9Ni77AQuCN0itXbCc/jWd8C6/yKZaSNXicpC8cgvjnxVdmfsosIXrjpzFq7GcDryb6A==", "dev": true, "requires": { - "debug": "2.6.8", + "debug": "2.6.9", "resolve": "1.4.0" } }, @@ -1629,7 +2036,7 @@ "integrity": "sha512-jDI/X5l/6D1rRD/3T43q8Qgbls2nq5km5KSqiwlyUbGo5+04fXhMKdCPhjwbqAa6HXWaMxj8Q4hQDIh7IadJQw==", "dev": true, "requires": { - "debug": "2.6.8", + "debug": "2.6.9", "pkg-dir": "1.0.0" } }, @@ -1641,7 +2048,7 @@ "requires": { "builtin-modules": "1.1.1", "contains-path": "0.1.0", - "debug": "2.6.8", + "debug": "2.6.9", "doctrine": "1.5.0", "eslint-import-resolver-node": "0.3.1", "eslint-module-utils": "2.1.1", @@ -1660,19 +2067,76 @@ "esutils": "2.0.2", "isarray": "1.0.0" } - } - } - }, - "eslint-restricted-globals": { - "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/eslint-restricted-globals/download/eslint-restricted-globals-0.1.1.tgz", - "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", - "dev": true - }, - "eslint-scope": { - "version": "3.7.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", - "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "eslint-restricted-globals": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/eslint-restricted-globals/-/eslint-restricted-globals-0.1.1.tgz", + "integrity": "sha1-NfDVy8ZMLj7WLpO0saevBbp+1Nc=", + "dev": true + }, + "eslint-scope": { + "version": "3.7.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-3.7.1.tgz", + "integrity": "sha1-PWPD7f2gLgbgGkUq2IyqzHzctug=", "dev": true, "requires": { "esrecurse": "4.2.0", @@ -1680,12 +2144,12 @@ } }, "espree": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.0.tgz", - "integrity": "sha1-mDWGJb3QVYYeon4oZ+pyn69GPY0=", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.1.tgz", + "integrity": "sha1-DJiLirRttTEAoZVK5LqZXd0n2H4=", "dev": true, "requires": { - "acorn": "5.1.1", + "acorn": "5.1.2", "acorn-jsx": "3.0.1" } }, @@ -1762,6 +2226,15 @@ "strip-eof": "1.0.0" } }, + "execall": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-1.0.0.tgz", + "integrity": "sha1-c9CQTjlbPKsGWLCNCewlMH8pu3M=", + "dev": true, + "requires": { + "clone-regexp": "1.0.0" + } + }, "expand-brackets": { "version": "0.1.5", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", @@ -1782,19 +2255,19 @@ }, "extend": { "version": "3.0.1", - "resolved": "http://registry.npm.taobao.org/extend/download/extend-3.0.1.tgz", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.1.tgz", "integrity": "sha1-p1Xqe8Gt/MWjHOfnYtuq3F5jZEQ=", "dev": true }, "external-editor": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.4.tgz", - "integrity": "sha1-HtkZnanL/i7y96MbL96LDRI2iXI=", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.0.5.tgz", + "integrity": "sha512-Msjo64WT5W+NhOpQXh0nOHm+n0RfU1QUwDnKYvJ8dEJ8zlwLrqXNTv5mSUTJpepf41PDJGyhueTw2vNZW+Fr/w==", "dev": true, "requires": { - "iconv-lite": "0.4.18", + "iconv-lite": "0.4.19", "jschardet": "1.5.1", - "tmp": "0.0.31" + "tmp": "0.0.33" } }, "extglob": { @@ -1808,7 +2281,7 @@ }, "extract-zip": { "version": "1.6.5", - "resolved": "http://registry.npm.taobao.org/extract-zip/download/extract-zip-1.6.5.tgz", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.5.tgz", "integrity": "sha1-maBnNbbqIOqbcF13ms/8yHz/BEA=", "dev": true, "requires": { @@ -1820,7 +2293,7 @@ "dependencies": { "debug": { "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/debug/download/debug-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.2.0.tgz", "integrity": "sha1-+HBX6ZWxofauaklgZkE3vFbwOdo=", "dev": true, "requires": { @@ -1829,7 +2302,7 @@ }, "mkdirp": { "version": "0.5.0", - "resolved": "http://registry.npm.taobao.org/mkdirp/download/mkdirp-0.5.0.tgz", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.0.tgz", "integrity": "sha1-HXMHam35hs2TROFecfzAWkyavxI=", "dev": true, "requires": { @@ -1838,7 +2311,7 @@ }, "ms": { "version": "0.7.1", - "resolved": "http://registry.npm.taobao.org/ms/download/ms-0.7.1.tgz", + "resolved": "https://registry.npmjs.org/ms/-/ms-0.7.1.tgz", "integrity": "sha1-nNE8A62/8ltl7/3nzoZO6VIBcJg=", "dev": true } @@ -1846,7 +2319,7 @@ }, "extsprintf": { "version": "1.3.0", - "resolved": "http://registry.npm.taobao.org/extsprintf/download/extsprintf-1.3.0.tgz", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=", "dev": true }, @@ -1864,7 +2337,7 @@ }, "fd-slicer": { "version": "1.0.1", - "resolved": "http://registry.npm.taobao.org/fd-slicer/download/fd-slicer-1.0.1.tgz", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz", "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { @@ -1886,7 +2359,7 @@ "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", "dev": true, "requires": { - "flat-cache": "1.2.2", + "flat-cache": "1.3.0", "object-assign": "4.1.1" } }, @@ -1920,9 +2393,9 @@ } }, "flat-cache": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.2.2.tgz", - "integrity": "sha1-+oZxTnLCHbiGAXYezy9VXRq8a5Y=", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", "dev": true, "requires": { "circular-json": "0.3.3", @@ -1960,13 +2433,13 @@ }, "forever-agent": { "version": "0.6.1", - "resolved": "http://registry.npm.taobao.org/forever-agent/download/forever-agent-0.6.1.tgz", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=", "dev": true }, "form-data": { "version": "2.1.4", - "resolved": "http://registry.npm.taobao.org/form-data/download/form-data-2.1.4.tgz", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.1.4.tgz", "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { @@ -1983,7 +2456,7 @@ }, "fs-extra": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/fs-extra/download/fs-extra-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { @@ -2010,6 +2483,12 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, + "gather-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gather-stream/-/gather-stream-1.0.0.tgz", + "integrity": "sha1-szmUr0V6gRVwDUEPMXczy+egkEs=", + "dev": true + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -2017,9 +2496,9 @@ "dev": true }, "get-stdin": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", - "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz", + "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, "get-stream": { @@ -2030,7 +2509,7 @@ }, "getpass": { "version": "0.1.7", - "resolved": "http://registry.npm.taobao.org/getpass/download/getpass-0.1.7.tgz", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { @@ -2039,19 +2518,18 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, "glob": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha1-DwiGD2oVUSey+t1PnOJLGqtuTSI=", "dev": true, "requires": { - "fs.realpath": "1.0.0", "inflight": "1.0.6", "inherits": "2.0.3", "minimatch": "3.0.4", @@ -2085,19 +2563,25 @@ "dev": true }, "globby": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", - "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-4.1.0.tgz", + "integrity": "sha1-CA9UVJ7BuCpsYOYx/ILhIR2+lfg=", "dev": true, "requires": { "array-union": "1.0.2", "arrify": "1.0.1", - "glob": "7.1.2", + "glob": "6.0.4", "object-assign": "4.1.1", "pify": "2.3.0", "pinkie-promise": "2.0.1" } }, + "globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha1-L0SUrIkZ43Z8XLtpHp9GMyQoXUM=", + "dev": true + }, "graceful-fs": { "version": "4.1.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", @@ -2106,13 +2590,13 @@ }, "har-schema": { "version": "1.0.5", - "resolved": "http://registry.npm.taobao.org/har-schema/download/har-schema-1.0.5.tgz", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-1.0.5.tgz", "integrity": "sha1-0mMTX0MwfALGAq/I/pWXDAFRNp4=", "dev": true }, "har-validator": { "version": "4.2.1", - "resolved": "http://registry.npm.taobao.org/har-validator/download/har-validator-4.2.1.tgz", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-4.2.1.tgz", "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { @@ -2122,7 +2606,7 @@ "dependencies": { "ajv": { "version": "4.11.8", - "resolved": "http://registry.npm.taobao.org/ajv/download/ajv-4.11.8.tgz", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { @@ -2158,7 +2642,7 @@ }, "hasha": { "version": "2.2.0", - "resolved": "http://registry.npm.taobao.org/hasha/download/hasha-2.2.0.tgz", + "resolved": "https://registry.npmjs.org/hasha/-/hasha-2.2.0.tgz", "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { @@ -2168,7 +2652,7 @@ }, "hawk": { "version": "3.1.3", - "resolved": "http://registry.npm.taobao.org/hawk/download/hawk-3.1.3.tgz", + "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { @@ -2180,7 +2664,7 @@ }, "hoek": { "version": "2.16.3", - "resolved": "http://registry.npm.taobao.org/hoek/download/hoek-2.16.3.tgz", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", "dev": true }, @@ -2206,9 +2690,15 @@ "integrity": "sha1-ZouTd26q5V696POtRkswekljYl4=", "dev": true }, + "html-tags": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz", + "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos=", + "dev": true + }, "http-signature": { "version": "1.1.1", - "resolved": "http://registry.npm.taobao.org/http-signature/download/http-signature-1.1.1.tgz", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz", "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { @@ -2218,9 +2708,9 @@ } }, "iconv-lite": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==", "dev": true }, "ignore": { @@ -2235,6 +2725,15 @@ "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", "dev": true }, + "indent-string": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", + "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", + "dev": true, + "requires": { + "repeating": "2.0.1" + } + }, "indexes-of": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", @@ -2258,16 +2757,16 @@ "dev": true }, "inquirer": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.2.3.tgz", - "integrity": "sha512-Bc3KbimpDTOeQdDj18Ir/rlsGuhBSSNqdOnxaAuKhpkdnMMuKsEGbZD2v5KFF9oso2OU+BPh7+/u5obmFDRmWw==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { - "ansi-escapes": "2.0.0", + "ansi-escapes": "3.0.0", "chalk": "2.1.0", "cli-cursor": "2.1.0", "cli-width": "2.2.0", - "external-editor": "2.0.4", + "external-editor": "2.0.5", "figures": "2.0.0", "lodash": "4.17.4", "mute-stream": "0.0.7", @@ -2346,6 +2845,12 @@ "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=", "dev": true }, + "irregular-plurals": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.3.0.tgz", + "integrity": "sha512-njf5A+Mxb3kojuHd1DzISjjIl+XhyzovXEOyPPSzdQozq/Lf2tN27mOrAAsxEPZxpn6I4MGzs1oo9TxXxPFpaA==", + "dev": true + }, "is-absolute-url": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz", @@ -2517,6 +3022,12 @@ "has": "1.0.1" } }, + "is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", + "dev": true + }, "is-resolvable": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.0.0.tgz", @@ -2532,6 +3043,12 @@ "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", "dev": true }, + "is-supported-regexp-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-supported-regexp-flag/-/is-supported-regexp-flag-1.0.0.tgz", + "integrity": "sha1-i1IMhfrnolM4LUsCZS4EVXbhO7g=", + "dev": true + }, "is-svg": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz", @@ -2549,10 +3066,16 @@ }, "is-typedarray": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/is-typedarray/download/is-typedarray-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", "dev": true }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", @@ -2582,14 +3105,14 @@ }, "isstream": { "version": "0.1.2", - "resolved": "http://registry.npm.taobao.org/isstream/download/isstream-0.1.2.tgz", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=", "dev": true }, "js-base64": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.1.9.tgz", - "integrity": "sha1-8OgK4DmkvWVLXygfyT8EqRSn/M4=", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.3.2.tgz", + "integrity": "sha512-Y2/+DnfJJXT1/FCwUebUhLWb3QihxiSC42+ctHLGogmW2jPY6LCapMdFZXRvVP2z6qyKW7s6qncE/9gSqZiArw==", "dev": true }, "js-tokens": { @@ -2610,7 +3133,7 @@ }, "jsbn": { "version": "0.1.1", - "resolved": "http://registry.npm.taobao.org/jsbn/download/jsbn-0.1.1.tgz", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true, "optional": true @@ -2629,7 +3152,7 @@ }, "json-schema": { "version": "0.2.3", - "resolved": "http://registry.npm.taobao.org/json-schema/download/json-schema-0.2.3.tgz", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=", "dev": true }, @@ -2650,7 +3173,7 @@ }, "json-stringify-safe": { "version": "5.0.1", - "resolved": "http://registry.npm.taobao.org/json-stringify-safe/download/json-stringify-safe-5.0.1.tgz", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", "dev": true }, @@ -2662,22 +3185,68 @@ }, "jsonfile": { "version": "2.4.0", - "resolved": "http://registry.npm.taobao.org/jsonfile/download/jsonfile-2.4.0.tgz", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz", "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { "graceful-fs": "4.1.11" } }, + "jsonfilter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/jsonfilter/-/jsonfilter-1.1.2.tgz", + "integrity": "sha1-Ie987cdRk4E8dZMulqmL4gW6WhE=", + "dev": true, + "requires": { + "JSONStream": "0.8.4", + "minimist": "1.2.0", + "stream-combiner": "0.2.2", + "through2": "0.6.5" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "stream-combiner": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", + "integrity": "sha1-rsjLrBd7Vrb0+kec7YwZEs7lKFg=", + "dev": true, + "requires": { + "duplexer": "0.1.1", + "through": "2.3.8" + } + } + } + }, "jsonify": { "version": "0.0.0", "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.0.tgz", "integrity": "sha1-LHS27kHZPKUbe1qu6PUDYx0lKnM=", "dev": true }, + "jsonparse": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-0.0.5.tgz", + "integrity": "sha1-MwVCrT8KZUZlt3jz6y2an6UHrGQ=", + "dev": true + }, + "JSONStream": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-0.8.4.tgz", + "integrity": "sha1-kWV9/m/4V0gwZhMrRhi2Lo9Ih70=", + "dev": true, + "requires": { + "jsonparse": "0.0.5", + "through": "2.3.8" + } + }, "jsprim": { "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/jsprim/download/jsprim-1.4.1.tgz", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", "dev": true, "requires": { @@ -2689,7 +3258,7 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } @@ -2697,7 +3266,7 @@ }, "kew": { "version": "0.7.0", - "resolved": "http://registry.npm.taobao.org/kew/download/kew-0.7.0.tgz", + "resolved": "https://registry.npmjs.org/kew/-/kew-0.7.0.tgz", "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", "dev": true }, @@ -2712,13 +3281,19 @@ }, "klaw": { "version": "1.3.1", - "resolved": "http://registry.npm.taobao.org/klaw/download/klaw-1.3.1.tgz", + "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { "graceful-fs": "4.1.11" } }, + "known-css-properties": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.2.0.tgz", + "integrity": "sha512-UTCzU28rRI9wkb8qSGoZa9pgWvxr4LjP2MEhi9XHb/1XMOJy0uTnIxaxzj8My/PORG+kQG6VzAcGvRw66eIOfA==", + "dev": true + }, "lcid": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", @@ -2728,6 +3303,16 @@ "invert-kv": "1.0.0" } }, + "ldjson-stream": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ldjson-stream/-/ldjson-stream-1.2.1.tgz", + "integrity": "sha1-kb7O2lrE7SsX5kn7d356v6AYnCs=", + "dev": true, + "requires": { + "split2": "0.2.1", + "through2": "0.6.5" + } + }, "levn": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", @@ -2739,15 +3324,16 @@ } }, "load-json-file": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", - "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", + "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { "graceful-fs": "4.1.11", "parse-json": "2.2.0", "pify": "2.3.0", - "strip-bom": "3.0.0" + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" } }, "locate-path": { @@ -2835,6 +3421,16 @@ "js-tokens": "3.0.2" } }, + "loud-rejection": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/loud-rejection/-/loud-rejection-1.6.0.tgz", + "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", + "dev": true, + "requires": { + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" + } + }, "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", @@ -2851,6 +3447,12 @@ "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", "dev": true }, + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + }, "map-stream": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", @@ -2863,6 +3465,12 @@ "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", "dev": true }, + "mathml-tag-names": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.0.1.tgz", + "integrity": "sha1-jUEmgWi/htEQK5gQnijlMeejRXg=", + "dev": true + }, "mem": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", @@ -2907,6 +3515,32 @@ } } }, + "meow": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-3.7.0.tgz", + "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", + "dev": true, + "requires": { + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, "micromatch": { "version": "2.3.11", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", @@ -2929,20 +3563,20 @@ } }, "mime": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.0.tgz", - "integrity": "sha512-n9ChLv77+QQEapYz8lV+rIZAW3HhAPW2CXnzb1GN5uMkuczshwvkW7XPsbzU0ZQN3sP47Er2KVkp2p3KyqZKSQ==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==", "dev": true }, "mime-db": { "version": "1.30.0", - "resolved": "http://registry.npm.taobao.org/mime-db/download/mime-db-1.30.0.tgz", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.30.0.tgz", "integrity": "sha1-dMZD2i3Z1qRTmZY0ZbJtXKfXHwE=", "dev": true }, "mime-types": { "version": "2.1.17", - "resolved": "http://registry.npm.taobao.org/mime-types/download/mime-types-2.1.17.tgz", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.17.tgz", "integrity": "sha1-Cdejk/A+mVp5+K+Fe3Cp4KsWVXo=", "dev": true, "requires": { @@ -2985,6 +3619,18 @@ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", "dev": true }, + "multimatch": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/multimatch/-/multimatch-2.1.0.tgz", + "integrity": "sha1-nHkGoi+0wCkZ4vX3UWG0zb1LKis=", + "dev": true, + "requires": { + "array-differ": "1.0.0", + "array-union": "1.0.2", + "arrify": "1.0.1", + "minimatch": "3.0.4" + } + }, "mute-stream": { "version": "0.0.7", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", @@ -2997,9 +3643,18 @@ "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", "dev": true }, + "nested-error-stacks": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz", + "integrity": "sha1-GfYZWRUZ8JZ2mlupqG5u7sgjw88=", + "dev": true, + "requires": { + "inherits": "2.0.3" + } + }, "node-qunit-phantomjs": { "version": "1.5.0", - "resolved": "http://registry.npm.taobao.org/node-qunit-phantomjs/download/node-qunit-phantomjs-1.5.0.tgz", + "resolved": "https://registry.npmjs.org/node-qunit-phantomjs/-/node-qunit-phantomjs-1.5.0.tgz", "integrity": "sha1-1q8tGR2JLJXoxAoTOtMIPwbVyyA=", "dev": true, "requires": { @@ -3011,7 +3666,7 @@ "dependencies": { "minimist": { "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/minimist/download/minimist-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", "dev": true } @@ -3044,6 +3699,12 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, + "normalize-selector": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/normalize-selector/-/normalize-selector-0.2.0.tgz", + "integrity": "sha1-0LFF62kRicY6eNIB3E/bEpPvDAM=", + "dev": true + }, "normalize-url": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz", @@ -3099,6 +3760,44 @@ "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", "dev": true }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3133,7 +3832,7 @@ }, "oauth-sign": { "version": "0.8.2", - "resolved": "http://registry.npm.taobao.org/oauth-sign/download/oauth-sign-0.8.2.tgz", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz", "integrity": "sha1-Rqarfwrq2N6unsBWV4C31O/rnUM=", "dev": true }, @@ -3205,7 +3904,7 @@ "requires": { "chalk": "1.1.3", "cli-cursor": "2.1.0", - "cli-spinners": "1.0.0", + "cli-spinners": "1.1.0", "log-symbols": "1.0.2" } }, @@ -3308,12 +4007,14 @@ "dev": true }, "path-type": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", - "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz", + "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "pify": "2.3.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" } }, "pause-stream": { @@ -3327,19 +4028,19 @@ }, "pend": { "version": "1.2.0", - "resolved": "http://registry.npm.taobao.org/pend/download/pend-1.2.0.tgz", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=", "dev": true }, "performance-now": { "version": "0.2.0", - "resolved": "http://registry.npm.taobao.org/performance-now/download/performance-now-0.2.0.tgz", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz", "integrity": "sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU=", "dev": true }, "phantomjs-prebuilt": { "version": "2.1.15", - "resolved": "http://registry.npm.taobao.org/phantomjs-prebuilt/download/phantomjs-prebuilt-2.1.15.tgz", + "resolved": "https://registry.npmjs.org/phantomjs-prebuilt/-/phantomjs-prebuilt-2.1.15.tgz", "integrity": "sha1-IPhugtM0nFBZF1J3RbekEeCLOQM=", "dev": true, "requires": { @@ -3356,13 +4057,13 @@ "dependencies": { "progress": { "version": "1.1.8", - "resolved": "http://registry.npm.taobao.org/progress/download/progress-1.1.8.tgz", + "resolved": "https://registry.npmjs.org/progress/-/progress-1.1.8.tgz", "integrity": "sha1-4mDHj2Fhzdmw5WzD4Khd4Xx6V74=", "dev": true }, "which": { "version": "1.2.14", - "resolved": "http://registry.npm.taobao.org/which/download/which-1.2.14.tgz", + "resolved": "https://registry.npmjs.org/which/-/which-1.2.14.tgz", "integrity": "sha1-mofEN48D6CfOyvGs31bHNsAcFOU=", "dev": true, "requires": { @@ -3392,14 +4093,24 @@ "pinkie": "2.0.4" } }, + "pipetteur": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pipetteur/-/pipetteur-2.0.3.tgz", + "integrity": "sha1-GVV2CVno0aEcsqUOyD7sRwYz5J8=", + "dev": true, + "requires": { + "onecolor": "3.0.4", + "synesthesia": "1.0.1" + } + }, "pixrem": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/pixrem/-/pixrem-4.0.1.tgz", "integrity": "sha1-LaSh3m7EQjxfw3lOkwuB1EkOxoY=", "dev": true, "requires": { - "browserslist": "2.4.0", - "postcss": "6.0.10", + "browserslist": "2.5.0", + "postcss": "6.0.13", "reduce-css-calc": "1.3.0" }, "dependencies": { @@ -3430,16 +4141,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3467,7 +4184,7 @@ "dev": true, "requires": { "onecolor": "3.0.4", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -3497,16 +4214,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3518,20 +4241,29 @@ } } }, + "plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", + "dev": true, + "requires": { + "irregular-plurals": "1.3.0" + } + }, "pluralize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-4.0.0.tgz", - "integrity": "sha1-WbcIwcAZCi9pLxx2GMRGsFL9F2I=", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "postcss": { - "version": "5.2.17", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.17.tgz", - "integrity": "sha1-z09Ze4ZNZcikkrLqvp1wbIecOIs=", + "version": "5.2.18", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", + "integrity": "sha512-zrUjRRe1bpXKsX1qAJNJjqZViErVuyEkMTRrwu4ud4sbTtIBRmtaYDrHmcGgmrbsW3MHfmtIf+vJumgQn+PrXg==", "dev": true, "requires": { "chalk": "1.1.3", - "js-base64": "2.1.9", + "js-base64": "2.3.2", "source-map": "0.5.7", "supports-color": "3.2.3" }, @@ -3555,7 +4287,7 @@ "requires": { "babel-runtime": "6.26.0", "balanced-match": "0.4.2", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -3591,16 +4323,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3618,7 +4356,7 @@ "integrity": "sha1-lNxCLI+QmX8WvTOjZUu77AhJY7Q=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-selector-parser": "2.2.3" }, "dependencies": { @@ -3649,16 +4387,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3676,27 +4420,28 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-message-helpers": "2.0.0", "reduce-css-calc": "1.3.0" } }, "postcss-cli": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-4.1.0.tgz", - "integrity": "sha1-j2gDZ4rNek8hSD8aQDkTb24cIU8=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/postcss-cli/-/postcss-cli-4.1.1.tgz", + "integrity": "sha1-uUvY//u3rB9i8mB+ePyTl/f2Ol0=", "dev": true, "requires": { - "chalk": "1.1.3", + "chalk": "2.1.0", "chokidar": "1.7.0", - "dependency-graph": "0.5.0", - "fs-extra": "3.0.1", + "dependency-graph": "0.5.1", + "fs-extra": "4.0.2", "get-stdin": "5.0.1", "globby": "6.1.0", "ora": "1.3.0", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-load-config": "1.2.0", - "postcss-reporter": "4.0.0", + "postcss-reporter": "5.0.0", + "pretty-hrtime": "1.0.3", "read-cache": "1.0.0", "yargs": "8.0.2" }, @@ -3710,17 +4455,48 @@ "color-convert": "1.9.0" } }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, "fs-extra": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-3.0.1.tgz", - "integrity": "sha1-N5TzeMWLNC6n27sjCVEJxLO2IpE=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-4.0.2.tgz", + "integrity": "sha1-+RcExT0bRh+JNFKwwwfZmXZHq2s=", "dev": true, "requires": { "graceful-fs": "4.1.11", - "jsonfile": "3.0.1", + "jsonfile": "4.0.0", "universalify": "0.1.1" } }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -3741,38 +4517,31 @@ "dev": true }, "jsonfile": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-3.0.1.tgz", - "integrity": "sha1-pezG9l9T9mLEQVx2daAzHQmS7GY=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", "dev": true, "requires": { "graceful-fs": "4.1.11" } }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" - }, - "dependencies": { - "chalk": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", - "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", - "dev": true, - "requires": { - "ansi-styles": "3.2.0", - "escape-string-regexp": "1.0.5", - "supports-color": "4.4.0" - } - } } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3790,8 +4559,8 @@ "integrity": "sha1-fgEG9Pah7LGtWzqFU6zl6Ciq4Yc=", "dev": true, "requires": { - "css-color-function": "1.3.0", - "postcss": "6.0.10", + "css-color-function": "1.3.3", + "postcss": "6.0.13", "postcss-message-helpers": "2.0.0", "postcss-value-parser": "3.3.0" }, @@ -3823,16 +4592,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3851,7 +4626,7 @@ "dev": true, "requires": { "color": "1.0.3", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-message-helpers": "2.0.0", "reduce-function-call": "1.0.2" }, @@ -3903,16 +4678,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -3931,7 +4712,7 @@ "dev": true, "requires": { "color": "1.0.3", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-message-helpers": "2.0.0" }, "dependencies": { @@ -3982,16 +4763,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4009,7 +4796,7 @@ "integrity": "sha1-EnA2ZvoxBDDj8wpFTawThjF9WEQ=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0", "units-css": "0.4.0" }, @@ -4041,16 +4828,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4069,7 +4862,7 @@ "dev": true, "requires": { "color": "1.0.3", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-message-helpers": "2.0.0", "reduce-function-call": "1.0.2" }, @@ -4121,16 +4914,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4148,7 +4947,7 @@ "integrity": "sha1-7rrwPTY7QwC5Z5K9MIHBntZlE9M=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0" }, "dependencies": { @@ -4179,16 +4978,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4206,7 +5011,7 @@ "integrity": "sha1-FFOcinExSUtILg3RzCZf9lFLUmM=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0" }, "dependencies": { @@ -4237,16 +5042,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4264,7 +5075,7 @@ "integrity": "sha1-N9XJNToHoJJwkSqCYGu0Kg1wLAQ=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0", "rgb-hex": "2.1.0" }, @@ -4296,16 +5107,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4324,7 +5141,7 @@ "dev": true, "requires": { "colormin": "1.1.2", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -4334,7 +5151,7 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -4344,12 +5161,12 @@ "integrity": "sha512-jA6kGdcUMZqLUgw6MdpyNWGFhk0LIITVhC/jTnLRZLoXSTR88qT2cFOn3LbY06udt1PVdTCHDG3plBjxVKf8BQ==", "dev": true, "requires": { - "autoprefixer": "7.1.3", + "autoprefixer": "7.1.5", "caniuse-api": "2.0.0", "chalk": "2.1.0", "pixrem": "4.0.1", "pleeease-filters": "4.0.0", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-apply": "0.8.0", "postcss-attribute-case-insensitive": "2.0.0", "postcss-calc": "6.0.0", @@ -4362,14 +5179,14 @@ "postcss-color-rgb": "2.0.0", "postcss-color-rgba-fallback": "3.0.0", "postcss-custom-media": "6.0.0", - "postcss-custom-properties": "6.1.0", + "postcss-custom-properties": "6.2.0", "postcss-custom-selectors": "4.0.1", "postcss-font-family-system-ui": "2.0.1", "postcss-font-variant": "3.0.0", "postcss-image-set-polyfill": "0.3.5", "postcss-initial": "2.0.0", "postcss-media-minmax": "3.0.0", - "postcss-nesting": "4.1.0", + "postcss-nesting": "4.2.1", "postcss-pseudo-class-any-link": "4.0.0", "postcss-pseudoelements": "5.0.0", "postcss-replace-overflow-wrap": "2.0.0", @@ -4387,16 +5204,16 @@ } }, "autoprefixer": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.3.tgz", - "integrity": "sha512-zGy6aRrZjWhR+25n89jYkpLXutg6xdDGKKnVNzkfamnnhK3mYchkKj5GJR14aJiU0x4UqZ1+N728tkFNUL5N2g==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-7.1.5.tgz", + "integrity": "sha512-sMN453qIm8Z+tunzYWW+Y490wWkICHhCYm/VohLjjl+N7ARSFuF5au7E6tr7oEbeeXj8mNjpSw2kxjJaO6YCOw==", "dev": true, "requires": { - "browserslist": "2.4.0", - "caniuse-lite": "1.0.30000721", + "browserslist": "2.5.0", + "caniuse-lite": "1.0.30000744", "normalize-range": "0.1.2", "num2fraction": "1.2.2", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0" } }, @@ -4406,8 +5223,8 @@ "integrity": "sha1-sd21pZZrFvSNxJmERNS7xsfZ2DQ=", "dev": true, "requires": { - "browserslist": "2.4.0", - "caniuse-lite": "1.0.30000721", + "browserslist": "2.5.0", + "caniuse-lite": "1.0.30000744", "lodash.memoize": "4.1.2", "lodash.uniq": "4.5.0" } @@ -4430,13 +5247,13 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, @@ -4447,7 +5264,7 @@ "dev": true, "requires": { "css-unit-converter": "1.1.1", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-selector-parser": "2.2.3", "reduce-css-calc": "2.0.5" } @@ -4462,6 +5279,12 @@ "postcss-value-parser": "3.3.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4479,7 +5302,7 @@ "integrity": "sha1-vlMnhBEOyylQRPtTlaGABushpzc=", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -4509,16 +5332,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4531,13 +5360,13 @@ } }, "postcss-custom-properties": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.1.0.tgz", - "integrity": "sha1-nK8RUaxBsenmTTov+ezplsoYl30=", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-6.2.0.tgz", + "integrity": "sha512-eNR2h9T9ciKMoQEORrPjH33XeN/nuvVuxArOKmHtsFbGbNss631tgTrKou3/pmjAZbA4QQkhLIkPQkIk3WW+8w==", "dev": true, "requires": { "balanced-match": "1.0.0", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -4567,16 +5396,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4594,7 +5429,7 @@ "integrity": "sha1-eBOC+UxS5yfvXKR3bqKt9JphE4I=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-selector-matches": "3.0.1" }, "dependencies": { @@ -4625,16 +5460,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4652,7 +5493,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-discard-duplicates": { @@ -4661,7 +5502,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-discard-empty": { @@ -4670,7 +5511,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-discard-overridden": { @@ -4679,7 +5520,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-discard-unused": { @@ -4688,7 +5529,7 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "uniqs": "2.0.0" } }, @@ -4698,7 +5539,7 @@ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "uniqid": "4.1.1" } }, @@ -4709,7 +5550,7 @@ "dev": true, "requires": { "lodash": "4.17.4", - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-value-parser": "3.3.0" }, "dependencies": { @@ -4740,16 +5581,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4767,7 +5614,71 @@ "integrity": "sha1-CMzIj2BQuoLtjvLMdsDGprQfGD4=", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "source-map": "0.6.1", + "supports-color": "4.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-header": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-header/-/postcss-header-1.0.0.tgz", + "integrity": "sha512-YUcU2oHQNsNVUDPdQg6/TXBWvI7dBGf2bsLQdVlLiLM5kiGLGCcszYDlVTaicmXpKANdS1T7bxpJtCacrMButw==", + "dev": true, + "requires": { + "babel-register": "6.26.0", + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -4797,16 +5708,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4824,7 +5741,7 @@ "integrity": "sha1-Dxk0E3AM8fgr05Bm7wFtZaShgYE=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-media-query-parser": "0.2.3" }, "dependencies": { @@ -4855,16 +5772,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4883,7 +5806,7 @@ "dev": true, "requires": { "lodash.template": "4.4.0", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -4913,16 +5836,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -4934,6 +5863,15 @@ } } }, + "postcss-less": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/postcss-less/-/postcss-less-0.14.0.tgz", + "integrity": "sha1-xjGwicbM5CK5oQ86lY0r7dOBkyQ=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, "postcss-load-config": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-1.2.0.tgz", @@ -4972,7 +5910,7 @@ "integrity": "sha1-Z1JWA3pD70C8Twdgv9BtTcadSNI=", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5002,16 +5940,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5036,7 +5980,7 @@ "dev": true, "requires": { "has": "1.0.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5046,7 +5990,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-merge-rules": { @@ -5057,7 +6001,7 @@ "requires": { "browserslist": "1.7.7", "caniuse-api": "1.6.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-selector-parser": "2.2.3", "vendors": "1.0.1" }, @@ -5068,8 +6012,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000721", - "electron-to-chromium": "1.3.20" + "caniuse-db": "1.0.30000744", + "electron-to-chromium": "1.3.24" } } } @@ -5087,7 +6031,7 @@ "dev": true, "requires": { "object-assign": "4.1.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5097,7 +6041,7 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5108,7 +6052,7 @@ "dev": true, "requires": { "alphanum-sort": "1.0.2", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0", "uniqs": "2.0.0" } @@ -5121,17 +6065,17 @@ "requires": { "alphanum-sort": "1.0.2", "has": "1.0.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-selector-parser": "2.2.3" } }, "postcss-nesting": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.1.0.tgz", - "integrity": "sha512-jn5bGJMSAawifyj2cXcqDw7mWt36HKY3TBCPlzkYpgOAwZcHpM5C5K5xPdj97pmdj5Q5SCpaFobt9ONitYo5lg==", + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-4.2.1.tgz", + "integrity": "sha512-IkyWXICwagCnlaviRexi7qOdwPw3+xVVjgFfGsxmztvRVaNxAlrypOIKqDE5mxY+BVxnId1rnUKBRQoNE2VDaA==", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5161,16 +6105,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5188,7 +6138,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-normalize-url": { @@ -5199,7 +6149,7 @@ "requires": { "is-absolute-url": "2.1.0", "normalize-url": "1.9.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5209,7 +6159,7 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5219,7 +6169,7 @@ "integrity": "sha1-kVKgYT00UHIFE+iJKFS65C0O5o4=", "dev": true, "requires": { - "postcss": "6.0.10", + "postcss": "6.0.13", "postcss-selector-parser": "2.2.3" }, "dependencies": { @@ -5250,16 +6200,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5277,7 +6233,7 @@ "integrity": "sha1-7vGU6NUkZFylIKlJ6V5RjoEkAss=", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5307,16 +6263,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5334,7 +6296,7 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5344,7 +6306,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "5.2.17" + "postcss": "5.2.18" } }, "postcss-reduce-transforms": { @@ -5354,7 +6316,7 @@ "dev": true, "requires": { "has": "1.0.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0" } }, @@ -5364,7 +6326,7 @@ "integrity": "sha1-eU22+qVPjbEAhUOSqTr0V2i04ls=", "dev": true, "requires": { - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5394,16 +6356,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5416,14 +6384,147 @@ } }, "postcss-reporter": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-4.0.0.tgz", - "integrity": "sha512-IEVx20y277AIs3bZ6sUdzdq0YOE2RRbwnjUvTMfYYZmws0mE7YgqxZd0J8j60Byaf/QbjxyLfFJEQHH2bb+ecA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-5.0.0.tgz", + "integrity": "sha512-rBkDbaHAu5uywbCR2XE8a25tats3xSOsGNx6mppK6Q9kSFGKc/FyAzfci+fWM2l+K402p1D0pNcfDGxeje5IKg==", "dev": true, "requires": { - "chalk": "1.1.3", + "chalk": "2.1.0", "lodash": "4.17.4", - "log-symbols": "1.0.2" + "log-symbols": "2.1.0", + "postcss": "6.0.13" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "log-symbols": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.1.0.tgz", + "integrity": "sha512-zLeLrzMA1A2vRF1e/0Mo+LNINzi6jzBylHj5WqvQ/WK/5WCZt8si9SyN4p9llr/HRYvVR1AoXHRHl4WTHyQAzQ==", + "dev": true, + "requires": { + "chalk": "2.1.0" + } + }, + "postcss": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "source-map": "0.6.1", + "supports-color": "4.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "postcss-resolve-nested-selector": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.1.tgz", + "integrity": "sha1-Kcy8fDfe36wwTp//C/FZaz9qDk4=", + "dev": true + }, + "postcss-scss": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-1.0.2.tgz", + "integrity": "sha1-/0XPM1S4ee6JpOtoaA9GrJuxT5Q=", + "dev": true, + "requires": { + "postcss": "6.0.13" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "source-map": "0.6.1", + "supports-color": "4.4.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } } }, "postcss-selector-matches": { @@ -5433,7 +6534,7 @@ "dev": true, "requires": { "balanced-match": "0.4.2", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5469,16 +6570,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5497,7 +6604,7 @@ "dev": true, "requires": { "balanced-match": "0.4.2", - "postcss": "6.0.10" + "postcss": "6.0.13" }, "dependencies": { "ansi-styles": { @@ -5533,16 +6640,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5565,6 +6678,16 @@ "uniq": "1.0.1" } }, + "postcss-sorting": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-2.1.0.tgz", + "integrity": "sha1-MrHpr6kTuyJaatB21QPY+YO7SoI=", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "5.2.18" + } + }, "postcss-svgo": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-2.1.6.tgz", @@ -5572,7 +6695,7 @@ "dev": true, "requires": { "is-svg": "2.1.0", - "postcss": "5.2.17", + "postcss": "5.2.18", "postcss-value-parser": "3.3.0", "svgo": "0.7.2" } @@ -5584,7 +6707,7 @@ "dev": true, "requires": { "alphanum-sort": "1.0.2", - "postcss": "5.2.17", + "postcss": "5.2.18", "uniqs": "2.0.0" } }, @@ -5594,10 +6717,10 @@ "integrity": "sha1-4Erjhq9+pu9d9RxbRJ1rlQLNmbI=", "dev": true, "requires": { - "mime": "1.4.0", + "mime": "1.4.1", "minimatch": "3.0.4", "mkdirp": "0.5.1", - "postcss": "6.0.10", + "postcss": "6.0.13", "xxhashjs": "0.2.1" }, "dependencies": { @@ -5628,16 +6751,22 @@ "dev": true }, "postcss": { - "version": "6.0.10", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.10.tgz", - "integrity": "sha512-7WOpqea/cQHH1XUXdN1mqoFFmhigW3KAXJ+ssMOk/f6mKmwqFgqqdwsnjLGH+wuY+kwaJvT4whHcfKt5kWga0A==", + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", "dev": true, "requires": { "chalk": "2.1.0", - "source-map": "0.5.7", + "source-map": "0.6.1", "supports-color": "4.4.0" } }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, "supports-color": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", @@ -5662,7 +6791,7 @@ "dev": true, "requires": { "has": "1.0.1", - "postcss": "5.2.17", + "postcss": "5.2.18", "uniqs": "2.0.0" } }, @@ -5684,6 +6813,12 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "pretty-hrtime": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", + "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=", + "dev": true + }, "private": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/private/-/private-0.1.7.tgz", @@ -5719,7 +6854,7 @@ }, "punycode": { "version": "1.4.1", - "resolved": "http://registry.npm.taobao.org/punycode/download/punycode-1.4.1.tgz", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", "dev": true }, @@ -5731,7 +6866,7 @@ }, "qs": { "version": "6.4.0", - "resolved": "http://registry.npm.taobao.org/qs/download/qs-6.4.0.tgz", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.4.0.tgz", "integrity": "sha1-E+JtKK1rD/qpExLNO/cI7TUecjM=", "dev": true }, @@ -5810,36 +6945,34 @@ "pify": "2.3.0" } }, + "read-file-stdin": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/read-file-stdin/-/read-file-stdin-0.2.1.tgz", + "integrity": "sha1-JezP86FTtoCa+ssj7hU4fbng7mE=", + "dev": true, + "requires": { + "gather-stream": "1.0.0" + } + }, "read-pkg": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", - "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", + "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "2.0.0", + "load-json-file": "1.1.0", "normalize-package-data": "2.4.0", - "path-type": "2.0.0" + "path-type": "1.1.0" } }, "read-pkg-up": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", - "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", + "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "2.1.0", - "read-pkg": "2.0.0" - }, - "dependencies": { - "find-up": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", - "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", - "dev": true, - "requires": { - "locate-path": "2.0.0" - } - } + "find-up": "1.1.2", + "read-pkg": "1.1.0" } }, "readable-stream": { @@ -5869,6 +7002,16 @@ "set-immediate-shim": "1.0.1" } }, + "redent": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", + "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", + "dev": true, + "requires": { + "indent-string": "2.1.0", + "strip-indent": "1.0.1" + } + }, "reduce-css-calc": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-1.3.0.tgz", @@ -5906,9 +7049,9 @@ } }, "regenerate": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.2.tgz", - "integrity": "sha1-0ZQcZ7rUN+G+dkM63Vs4X5WxkmA=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", + "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==", "dev": true }, "regenerator-runtime": { @@ -5943,7 +7086,7 @@ "integrity": "sha1-SdA4g3uNz4v6W5pCE5k45uoq4kA=", "dev": true, "requires": { - "regenerate": "1.3.2", + "regenerate": "1.3.3", "regjsgen": "0.2.0", "regjsparser": "0.1.5" } @@ -6000,7 +7143,7 @@ }, "request": { "version": "2.81.0", - "resolved": "http://registry.npm.taobao.org/request/download/request-2.81.0.tgz", + "resolved": "https://registry.npmjs.org/request/-/request-2.81.0.tgz", "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { @@ -6023,14 +7166,14 @@ "qs": "6.4.0", "safe-buffer": "5.1.1", "stringstream": "0.0.5", - "tough-cookie": "2.3.2", + "tough-cookie": "2.3.3", "tunnel-agent": "0.6.0", "uuid": "3.1.0" } }, "request-progress": { "version": "2.0.1", - "resolved": "http://registry.npm.taobao.org/request-progress/download/request-progress-2.0.1.tgz", + "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-2.0.1.tgz", "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { @@ -6109,18 +7252,34 @@ "dev": true }, "rimraf": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.1.tgz", - "integrity": "sha1-wjOOxkPfeht/5cVPqG9XQopV8z0=", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", "dev": true, "requires": { "glob": "7.1.2" + }, + "dependencies": { + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + } } }, "rollup": { - "version": "0.49.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.49.2.tgz", - "integrity": "sha512-9mySqItSwq5/dXYQyFGrrzqV282EZfz4kSCU2m4e6OjgqLmIsp9zK6qNQ6wbBWR4EhASEqQMBQ/IF45jaNPAtw==", + "version": "0.50.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-0.50.0.tgz", + "integrity": "sha512-7RqCBQ9iwsOBPkjYgoIaeUij606mSkDMExP0NT7QDI3bqkHYQHrQ83uoNIXwPcQm/vP2VbsUz3kiyZZ1qPlLTQ==", "dev": true }, "rollup-plugin-babel": { @@ -6252,6 +7411,12 @@ "jsonify": "0.0.0" } }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=", + "dev": true + }, "signal-exit": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", @@ -6282,14 +7447,17 @@ "dev": true }, "slice-ansi": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-0.0.4.tgz", - "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", - "dev": true + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "2.0.0" + } }, "sntp": { "version": "1.0.9", - "resolved": "http://registry.npm.taobao.org/sntp/download/sntp-1.0.9.tgz", + "resolved": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz", "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { @@ -6312,9 +7480,9 @@ "dev": true }, "source-map-support": { - "version": "0.4.16", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.16.tgz", - "integrity": "sha512-A6vlydY7H/ljr4L2UOhDSajQdZQ6dMD7cLH0pzwcmwLyc9u8PNI4WGtnfDDzX7uzGL6c/T+ORL97Zlh+S4iOrg==", + "version": "0.4.18", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.4.18.tgz", + "integrity": "sha512-try0/JqxPLF9nOjvSta7tVondkP5dwgyLDjVoyMDlmjugT2lRZ1OfsrYTkCd2hkDnJTKRbO/Rl3orm8vlsUzbA==", "dev": true, "requires": { "source-map": "0.5.7" @@ -6341,6 +7509,12 @@ "integrity": "sha1-yd96NCRZSt5r0RkA1ZZpbcBrrFc=", "dev": true }, + "specificity": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.3.2.tgz", + "integrity": "sha512-Nc/QN/A425Qog7j9aHmwOrlwX2e7pNI47ciwxwy4jOlvbbMHkNNJchit+FX+UjF3IAdiaaV5BKeWuDUnws6G1A==", + "dev": true + }, "split": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", @@ -6350,6 +7524,15 @@ "through": "2.3.8" } }, + "split2": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/split2/-/split2-0.2.1.tgz", + "integrity": "sha1-At2smtwD7Au3jBKC7Aecpuha6QA=", + "dev": true, + "requires": { + "through2": "0.6.5" + } + }, "sprintf-js": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", @@ -6358,7 +7541,7 @@ }, "sshpk": { "version": "1.13.1", - "resolved": "http://registry.npm.taobao.org/sshpk/download/sshpk-1.13.1.tgz", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.13.1.tgz", "integrity": "sha1-US322mKHFEMW3EwY/hzx2UBzm+M=", "dev": true, "requires": { @@ -6374,12 +7557,18 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } } }, + "stdin": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/stdin/-/stdin-0.0.1.tgz", + "integrity": "sha1-0wQZgarsPf28d6GzjWNy449ftx4=", + "dev": true + }, "stream-combiner": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", @@ -6438,13 +7627,13 @@ "dev": true, "requires": { "define-properties": "1.1.2", - "es-abstract": "1.8.1", + "es-abstract": "1.9.0", "function-bind": "1.1.1" } }, "stringstream": { "version": "0.0.5", - "resolved": "http://registry.npm.taobao.org/stringstream/download/stringstream-0.0.5.tgz", + "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", "dev": true }, @@ -6458,10 +7647,13 @@ } }, "strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", - "dev": true + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "0.2.1" + } }, "strip-eof": { "version": "1.0.0", @@ -6469,18 +7661,395 @@ "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", "dev": true }, + "strip-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", + "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", + "dev": true, + "requires": { + "get-stdin": "4.0.1" + } + }, "strip-json-comments": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", "dev": true }, + "style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha1-eVjHk+R+MuB9K1yv5cC/jhLneQI=", + "dev": true + }, + "stylefmt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/stylefmt/-/stylefmt-6.0.0.tgz", + "integrity": "sha1-yFHpwteLiplQL3S6PYY7MBY+7JM=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "css-color-list": "0.0.1", + "diff": "3.4.0", + "editorconfig": "0.13.3", + "globby": "6.1.0", + "minimist": "1.2.0", + "postcss": "6.0.13", + "postcss-scss": "1.0.2", + "postcss-sorting": "2.1.0", + "postcss-value-parser": "3.3.0", + "stdin": "0.0.1", + "stylelint": "7.13.0", + "stylelint-order": "0.4.4" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "postcss": { + "version": "6.0.13", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.13.tgz", + "integrity": "sha512-nHsrD1PPTMSJDfU+osVsLtPkSP9YGeoOz4FDLN4r1DW4N5vqL1J+gACzTQHsfwIiWG/0/nV4yCzjTMo1zD8U1g==", + "dev": true, + "requires": { + "chalk": "2.1.0", + "source-map": "0.6.1", + "supports-color": "4.4.0" + }, + "dependencies": { + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + } + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "stylehacks": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-2.3.2.tgz", + "integrity": "sha1-ZMg+BDimjJ7fRJ6MVSp9mrYAmws=", + "dev": true, + "requires": { + "browserslist": "1.7.7", + "chalk": "1.1.3", + "log-symbols": "1.0.2", + "minimist": "1.2.0", + "plur": "2.1.2", + "postcss": "5.2.18", + "postcss-reporter": "1.4.1", + "postcss-selector-parser": "2.2.3", + "read-file-stdin": "0.2.1", + "text-table": "0.2.0", + "write-file-stdout": "0.0.2" + }, + "dependencies": { + "browserslist": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-1.7.7.tgz", + "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", + "dev": true, + "requires": { + "caniuse-db": "1.0.30000744", + "electron-to-chromium": "1.3.24" + } + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + }, + "postcss-reporter": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-1.4.1.tgz", + "integrity": "sha1-wTbwpbFhkV83ndN2XGEHX357mvI=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.17.4", + "log-symbols": "1.0.2", + "postcss": "5.2.18" + } + } + } + }, + "stylelint": { + "version": "7.13.0", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-7.13.0.tgz", + "integrity": "sha1-ER+Xttpy53XICADWu29fhpmXeF0=", + "dev": true, + "requires": { + "autoprefixer": "6.7.7", + "balanced-match": "0.4.2", + "chalk": "2.1.0", + "colorguard": "1.2.0", + "cosmiconfig": "2.2.2", + "debug": "2.6.9", + "doiuse": "2.6.0", + "execall": "1.0.0", + "file-entry-cache": "2.0.0", + "get-stdin": "5.0.1", + "globby": "6.1.0", + "globjoin": "0.1.4", + "html-tags": "2.0.0", + "ignore": "3.3.5", + "imurmurhash": "0.1.4", + "known-css-properties": "0.2.0", + "lodash": "4.17.4", + "log-symbols": "1.0.2", + "mathml-tag-names": "2.0.1", + "meow": "3.7.0", + "micromatch": "2.3.11", + "normalize-selector": "0.2.0", + "pify": "2.3.0", + "postcss": "5.2.18", + "postcss-less": "0.14.0", + "postcss-media-query-parser": "0.2.3", + "postcss-reporter": "3.0.0", + "postcss-resolve-nested-selector": "0.1.1", + "postcss-scss": "0.4.1", + "postcss-selector-parser": "2.2.3", + "postcss-value-parser": "3.3.0", + "resolve-from": "3.0.0", + "specificity": "0.3.2", + "string-width": "2.1.1", + "style-search": "0.1.0", + "stylehacks": "2.3.2", + "sugarss": "0.2.0", + "svg-tags": "1.0.0", + "table": "4.0.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", + "dev": true, + "requires": { + "color-convert": "1.9.0" + } + }, + "balanced-match": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-0.4.2.tgz", + "integrity": "sha1-yz8+PHMtwPAe5wtAPzAuYddwmDg=", + "dev": true + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "get-stdin": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-5.0.1.tgz", + "integrity": "sha1-Ei4WFZHiH/TFJTAwVpPyDmOTo5g=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true, + "requires": { + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "1.0.2", + "glob": "7.1.2", + "object-assign": "4.1.1", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "postcss-reporter": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-reporter/-/postcss-reporter-3.0.0.tgz", + "integrity": "sha1-CeoPN6RExWk4eGBuCbAY6+/3z48=", + "dev": true, + "requires": { + "chalk": "1.1.3", + "lodash": "4.17.4", + "log-symbols": "1.0.2", + "postcss": "5.2.18" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, + "postcss-scss": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/postcss-scss/-/postcss-scss-0.4.1.tgz", + "integrity": "sha1-rXcbgfD3L19IRdCKpg+TVXZT1Uw=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, + "resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" + } + } + } + }, + "stylelint-order": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-0.4.4.tgz", + "integrity": "sha1-2338oFQbUGIBDH4uIedFeR/AiKw=", + "dev": true, + "requires": { + "lodash": "4.17.4", + "postcss": "5.2.18", + "stylelint": "7.13.0" + } + }, + "sugarss": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-0.2.0.tgz", + "integrity": "sha1-rDQjdWMyfG/4l7ZHQr9q7BkK054=", + "dev": true, + "requires": { + "postcss": "5.2.18" + } + }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", "dev": true }, + "svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", + "dev": true + }, "svgo": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/svgo/-/svgo-0.7.2.tgz", @@ -6496,28 +8065,70 @@ "whet.extend": "0.9.9" } }, + "synesthesia": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/synesthesia/-/synesthesia-1.0.1.tgz", + "integrity": "sha1-XvlepUjA1cbm+btLDQcx3/hkp3c=", + "dev": true, + "requires": { + "css-color-names": "0.0.3" + }, + "dependencies": { + "css-color-names": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.3.tgz", + "integrity": "sha1-3gzvFvTYqoIioyDVttfpu62nufY=", + "dev": true + } + } + }, "table": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/table/-/table-4.0.1.tgz", - "integrity": "sha1-qBFsEz+sLGH0pCCrbN9cTWHw5DU=", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/table/-/table-4.0.2.tgz", + "integrity": "sha512-UUkEAPdSGxtRpiV9ozJ5cMTtYiqz7Ni1OGqLXRCynrvzdtR1p+cfOWe2RJLwvUG8hNanaSRjecIqwOjqeatDsA==", "dev": true, "requires": { - "ajv": "4.11.8", - "ajv-keywords": "1.5.1", - "chalk": "1.1.3", + "ajv": "5.2.3", + "ajv-keywords": "2.1.0", + "chalk": "2.1.0", "lodash": "4.17.4", - "slice-ansi": "0.0.4", + "slice-ansi": "1.0.0", "string-width": "2.1.1" }, "dependencies": { - "ajv": { - "version": "4.11.8", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-4.11.8.tgz", - "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", + "ansi-styles": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.0.tgz", + "integrity": "sha512-NnSOmMEYtVR2JVMIGTzynRkkaxtiq1xnFBcdQD/DnNCYPoEPsVJhM98BDyaoNOQIi7p4okdi3E27eN7GQbsUug==", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "color-convert": "1.9.0" + } + }, + "chalk": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.1.0.tgz", + "integrity": "sha512-LUHGS/dge4ujbXMJrnihYMcL4AoOweGnw9Tp3kQuqy1Kx5c1qKjqvMJZ6nVJPMWJtKCTN72ZogH3oeSO9g9rXQ==", + "dev": true, + "requires": { + "ansi-styles": "3.2.0", + "escape-string-regexp": "1.0.5", + "supports-color": "4.4.0" + } + }, + "has-flag": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-2.0.0.tgz", + "integrity": "sha1-6CB68cx7MNRGzHC3NLXovhj4jVE=", + "dev": true + }, + "supports-color": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.4.0.tgz", + "integrity": "sha512-rKC3+DyXWgK0ZLKwmRsrkyHVZAjNkfzeehuFWdGGcqGDTZFH73+RH6S/RDAAxl9GusSjZSUWYLmT9N5pzXFOXQ==", + "dev": true, + "requires": { + "has-flag": "2.0.0" } } } @@ -6530,7 +8141,7 @@ }, "throttleit": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/throttleit/download/throttleit-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", "integrity": "sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw=", "dev": true }, @@ -6540,10 +8151,46 @@ "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", "dev": true }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": "1.0.34", + "xtend": "4.0.1" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "0.0.1", + "string_decoder": "0.10.31" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + } + } + }, "tmp": { - "version": "0.0.31", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.31.tgz", - "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -6556,14 +8203,20 @@ "dev": true }, "tough-cookie": { - "version": "2.3.2", - "resolved": "http://registry.npm.taobao.org/tough-cookie/download/tough-cookie-2.3.2.tgz", - "integrity": "sha1-8IH3bkyFcg5sN6X6ztc3FQ2EByo=", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.3.3.tgz", + "integrity": "sha1-C2GKVWW23qkL80JdBNVe3EdadWE=", "dev": true, "requires": { "punycode": "1.4.1" } }, + "trim-newlines": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-1.0.0.tgz", + "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", + "dev": true + }, "trim-right": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/trim-right/-/trim-right-1.0.1.tgz", @@ -6578,7 +8231,7 @@ }, "tunnel-agent": { "version": "0.6.0", - "resolved": "http://registry.npm.taobao.org/tunnel-agent/download/tunnel-agent-0.6.0.tgz", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { @@ -6587,7 +8240,7 @@ }, "tweetnacl": { "version": "0.14.5", - "resolved": "http://registry.npm.taobao.org/tweetnacl/download/tweetnacl-0.14.5.tgz", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=", "dev": true, "optional": true @@ -6608,9 +8261,9 @@ "dev": true }, "uglify-js": { - "version": "3.0.28", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.0.28.tgz", - "integrity": "sha512-0h/qGay016GG2lVav3Kz174F3T2Vjlz2v6HCt+WDQpoXfco0hWwF5gHK9yh88mUYvIC+N7Z8NT8WpjSp1yoqGA==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.1.3.tgz", + "integrity": "sha512-5ZUOgufCHjN2mBBLfz63UtWTP6va2sSzBpNCM+/iqI6RnPzEhANmB0EKiKBYdQbc3v7KeomXJ2DJx0Xq9gvUvA==", "dev": true, "requires": { "commander": "2.11.0", @@ -6662,8 +8315,8 @@ }, "uuid": { "version": "3.1.0", - "resolved": "http://registry.npm.taobao.org/uuid/download/uuid-3.1.0.tgz", - "integrity": "sha1-PdPT55Crwk17DToDT/q6vijrvAQ=", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.1.0.tgz", + "integrity": "sha512-DIWtzUkw04M4k3bf1IcpS2tngXEL26YUD2M0tMDUpnUrz2hgzUBlD55a4FjdLGPvfHxS6uluGWvaVEqgBcVa+g==", "dev": true }, "validate-npm-package-license": { @@ -6684,7 +8337,7 @@ }, "verror": { "version": "1.10.0", - "resolved": "http://registry.npm.taobao.org/verror/download/verror-1.10.0.tgz", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { @@ -6695,7 +8348,7 @@ "dependencies": { "assert-plus": { "version": "1.0.0", - "resolved": "http://registry.npm.taobao.org/assert-plus/download/assert-plus-1.0.0.tgz", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true } @@ -6728,6 +8381,12 @@ "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", "dev": true }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=", + "dev": true + }, "wordwrap": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", @@ -6781,6 +8440,18 @@ "mkdirp": "0.5.1" } }, + "write-file-stdout": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/write-file-stdout/-/write-file-stdout-0.0.2.tgz", + "integrity": "sha1-wlLXx8WxtAKJdjDjRTx7/mkNnKE=", + "dev": true + }, + "xtend": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true + }, "xxhashjs": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.1.tgz", @@ -6821,6 +8492,71 @@ "which-module": "2.0.0", "y18n": "3.2.1", "yargs-parser": "7.0.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "2.0.0" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "dev": true, + "requires": { + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "strip-bom": "3.0.0" + } + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "dev": true, + "requires": { + "pify": "2.3.0" + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "dev": true, + "requires": { + "load-json-file": "2.0.0", + "normalize-package-data": "2.4.0", + "path-type": "2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "dev": true, + "requires": { + "find-up": "2.1.0", + "read-pkg": "2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } } }, "yargs-parser": { @@ -6830,11 +8566,19 @@ "dev": true, "requires": { "camelcase": "4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", + "dev": true + } } }, "yauzl": { "version": "2.4.1", - "resolved": "http://registry.npm.taobao.org/yauzl/download/yauzl-2.4.1.tgz", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz", "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { diff --git a/package.json b/package.json index f94a1ce78..4d57dc61c 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "cropperjs", "description": "JavaScript image cropper.", - "version": "1.0.0", + "version": "1.1.0", "main": "dist/cropper.common.js", "module": "dist/cropper.esm.js", "browser": "dist/cropper.js", @@ -31,36 +31,39 @@ "development" ], "scripts": { - "build:css": "postcss src/css/cropper.css --no-map -o dist/cropper.css", - "build:js": "rollup -c", "build": "npm run build:css && npm run build:js", - "compress:css": "postcss dist/cropper.css -u cssnano --no-map -o dist/cropper.min.css", - "compress:js": "uglifyjs dist/cropper.js -o dist/cropper.min.js -c -m --comments /^!/", + "build:css": "postcss src/css/cropper.css -o dist/cropper.css -m", + "build:js": "rollup -c", "compress": "npm run compress:css && npm run compress:js", - "watch:css": "postcss src/css/cropper.css -o docs/css/cropper.css -w", - "watch:js": "rollup -c -w -m", + "compress:css": "postcss dist/cropper.css -u cssnano -o dist/cropper.min.css -m", + "compress:js": "uglifyjs dist/cropper.js -o dist/cropper.min.js -c -m --comments /^!/", + "copy": "cpy dist/cropper.css docs/css", "lint": "eslint src/js --fix", - "postbuild": "npm test && npm run compress && node build", + "postbuild": "npm test && npm run compress && npm run copy", "prebuild": "npm run lint", "start": "npm-run-all --parallel watch:*", - "test": "node-qunit-phantomjs test/index.html --timeout 10" + "test": "node-qunit-phantomjs test/index.html --timeout 10", + "watch:css": "postcss src/css/cropper.css -o docs/css/cropper.css -m -w", + "watch:js": "rollup -c -m -w" }, "devDependencies": { "babel-core": "^6.26.0", "babel-preset-env": "^1.6.0", + "cpy-cli": "^1.0.1", "cssnano": "^3.10.0", - "eslint": "^4.6.0", - "eslint-config-airbnb-base": "^11.3.2", + "eslint": "^4.8.0", + "eslint-config-airbnb-base": "^12.0.2", "eslint-plugin-import": "^2.7.0", "node-qunit-phantomjs": "^1.5.0", "npm-run-all": "^4.1.1", - "postcss-cli": "^4.1.0", + "postcss-cli": "^4.1.1", "postcss-cssnext": "^3.0.2", + "postcss-header": "^1.0.0", "postcss-url": "^7.1.2", - "rollup": "^0.49.2", + "rollup": "^0.50.0", "rollup-plugin-babel": "^3.0.2", "rollup-watch": "^4.3.1", "stylefmt": "^6.0.0", - "uglify-js": "^3.0.28" + "uglify-js": "^3.1.3" } }