Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

tui-image-editor

Package Overview
Dependencies
Maintainers
1
Versions
34
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tui-image-editor - npm Package Compare versions

Comparing version 3.1.0 to 3.2.0

.eslintignore

6

.eslintrc.js

@@ -18,3 +18,9 @@ module.exports = {

"sourceType": "module"
},
'rules': {
'prefer-destructuring': ['error', {
VariableDeclarator: {array: true, object: true},
AssignmentExpression: {array: false, object: false}
}]
}
};

6

bower.json

@@ -32,3 +32,4 @@ {

"fabric": "~1.6.4",
"tui-code-snippet": "^1.3.0"
"tui-code-snippet": "^1.3.0",
"tui-color-picker": "^2.2.0"
},

@@ -40,4 +41,5 @@ "devDependencies": {

"resolutions": {
"tui-code-snippet": "^1.3.0"
"tui-code-snippet": "^1.3.0",
"tui-color-picker": "^2.2.0"
}
}
{
"example01-basic": {
"title": "1. Basic"
"example01-includeUi": {
"title": "1. Include ui"
},
"example02-mobile": {
"title": "2. Mobile"
"example02-useApiDirect": {
"title": "2. Use api direct (basic)"
},
"example03-mobile": {
"title": "3. Mobile"
}
}

@@ -674,3 +674,3 @@ /**

}).then(objectProps => {
console.log(objectProps);
// console.log(objectProps);
});

@@ -677,0 +677,0 @@ });

@@ -17,3 +17,3 @@ {

"logo": {
"url": "https://cloud.githubusercontent.com/assets/12269563/20029815/01133928-a39a-11e6-80f3-12500a91c755.png",
"url": "https://user-images.githubusercontent.com/35218826/40895380-0b9f4cd6-67ea-11e8-982f-18121daa3a04.png",
"width": "150px",

@@ -20,0 +20,0 @@ "height": "13px",

@@ -146,2 +146,6 @@ /* eslint-disable consts-on-top, no-process-env, require-jsdoc */

loader: 'babel'
},
{
test: /\.styl$/,
loader: 'css-loader!stylus-loader?paths=src/css/'
}

@@ -148,0 +152,0 @@ ]

{
"name": "tui-image-editor",
"author": "NHNEnt FE Development Lab <dl_javascript@nhnent.com>",
"version": "3.1.0",
"version": "3.2.0",
"license": "MIT",
"repository": "https://github.com/nhnent/tui.image-editor",
"repository": {
"type": "git",
"url": "https://github.com/nhnent/tui.image-editor.git"
},
"main": "dist/tui-image-editor.js",

@@ -23,2 +26,3 @@ "description": "TOAST UI Component: ImageEditor",

"babel-preset-es2015": "^6.18.0",
"css-loader": "^0.28.11",
"es5-shim": "^4.5.9",

@@ -28,2 +32,3 @@ "eslint": "^4.5.0",

"eslint-loader": "^1.6.1",
"extract-text-webpack-plugin": "^1.0.1",
"file-saver": "^1.3.3",

@@ -39,2 +44,3 @@ "istanbul-instrumenter-loader": "^1.0.0",

"karma-es5-shim": "0.0.4",
"karma-firefox-launcher": "^1.1.0",
"karma-jasmine": "^1.0.2",

@@ -48,2 +54,5 @@ "karma-jquery": "^0.2.2",

"simulant": "^0.2.2",
"stylus": "^0.54.5",
"stylus-loader": "^3.0.2",
"svgstore": "^2.0.3",
"tui-jsdoc-template": "^1.0.4",

@@ -56,3 +65,4 @@ "webpack": "^1.13.3",

"test:ne": "KARMA_SERVER=ne karma start",
"bundle": "webpack && webpack -p",
"bundle": "webpack && webpack -p && npm run bundle:svg",
"bundle:svg": "mkdir -p dist/svg && node makesvg.js",
"serve": "webpack-dev-server --inline --hot -d",

@@ -65,4 +75,5 @@ "cpy-dist2doc": "mkdir -p doc/dist && cp -f -r dist doc",

"core-js": "2.4.1",
"tui-code-snippet": "^1.3.0"
"tui-code-snippet": "^1.3.0",
"tui-color-picker": "^2.2.0"
}
}

@@ -1,7 +0,137 @@

# Image Editor
Canvas image editor
# ![Toast UI ImageEditor](https://user-images.githubusercontent.com/35218826/40895380-0b9f4cd6-67ea-11e8-982f-18121daa3a04.png)
> Full-featured photo image editor with use canvas, easy to apply, and great filter function
Full-featured photo image editor using canvas. It is really easy, and it comes with great filters.
![image](https://cloud.githubusercontent.com/assets/26706716/26335518/84f041e2-3fa7-11e7-8892-155a95c6d5c3.png)
## Feature
[![github version](https://img.shields.io/github/release/nhnent/tui.image-editor.svg)](https://github.com/nhnent/tui.image-editor/releases/latest) [![npm version](https://img.shields.io/npm/v/tui-image-editor.svg)](https://www.npmjs.com/package/tui-image-editor) [![bower version](https://img.shields.io/bower/v/tui.image-editor.svg)](https://github.com/nhnent/tui.image-editor/releases/latest) [![license](https://img.shields.io/github/license/nhnent/tui.image-editor.svg)](https://github.com/nhnent/tui.image-editor/blob/master/LICENSE) [![PRs welcome](https://img.shields.io/badge/PRs-welcome-ff69b4.svg)](https://github.com/nhnent/tui.image-editor/issues?q=is%3Aissue+is%3Aopen+label%3A%22help+wanted%22)[![code with hearth by NHN Entertainment](https://img.shields.io/badge/%3C%2F%3E%20with%20%E2%99%A5%20by-NHN%20Entertainment-ff1414.svg)](https://github.com/nhnent)
![6 -20-2018 17-45-54](https://user-images.githubusercontent.com/35218826/41647896-7b218ae0-74b2-11e8-90db-d7805cc23e8c.gif)
## 🚩 Table of Contents
* [Browser Support](#-browser-support)
* [Has full features that stick to the basic.](#-has-full-features-that-stick-to-the-basic)
* [Photo manipulation](#photo-manipulation)
* [Integration function](#integration-function)
* [Powerful filter function](#powerful-filter-function)
* [Select only the desired function](#select-only-the-desired-function)
* [Easy to apply the size and design you want](#-easy-to-apply-the-size-and-design-you-want)
* [Can be used everywhere](#can-be-used-everywhere)
* [Nice default & Fully customizable Themes](#nice-default--fully-customizable-themes)
* [Features](#-features)
* [Install](#-install)
* [Via Package Manager](#via-package-manager)
* [Via Contents Delivery Network (CDN)](#via-contents-delivery-network-cdn)
* [Download Source Files](#download-source-files)
* [Usage](#-usage)
* [HTML](#html)
* [JavaScript](#javascript)
* [Development](#develop)
* [Setup](#setup)
* [Run webpack-dev-server](#run-webpack-dev-server)
* [Documents](#-documents)
* [Contributing](#-contributing)
* [Dependency](#-dependency)
* [TOAST UI Family](#-toast-ui-family)
* [License](#-license)
## 🌏 Browser Support
| <img src="https://user-images.githubusercontent.com/1215767/34348387-a2e64588-ea4d-11e7-8267-a43365103afe.png" alt="Chrome" width="16px" height="16px" /> Chrome | <img src="https://user-images.githubusercontent.com/1215767/34348590-250b3ca2-ea4f-11e7-9efb-da953359321f.png" alt="IE" width="16px" height="16px" /> Internet Explorer | <img src="https://user-images.githubusercontent.com/1215767/34348380-93e77ae8-ea4d-11e7-8696-9a989ddbbbf5.png" alt="Edge" width="16px" height="16px" /> Edge | <img src="https://user-images.githubusercontent.com/1215767/34348394-a981f892-ea4d-11e7-9156-d128d58386b9.png" alt="Safari" width="16px" height="16px" /> Safari | <img src="https://user-images.githubusercontent.com/1215767/34348383-9e7ed492-ea4d-11e7-910c-03b39d52f496.png" alt="Firefox" width="16px" height="16px" /> Firefox |
| :---------: | :---------: | :---------: | :---------: | :---------: |
| Yes | 9+ | Yes | Yes | Yes |
## 💪 Has full features that stick to the basic.
### Photo manipulation
- Crop, Flip, Rotation, Drawing, Shape, Icon, Text, Mask Filter, Image Filter
### Integration function
- Download, Image Load, Undo, Redo, Reset, Delete Object(Shape, Line, Mask Image...)
<table>
<tr>
<th width="20%">Crop</th>
<th width="20%">Flip</th>
<th width="20%">Rotation</th>
<th width="20%">Drawing</th>
<th width="20%">Shape</th>
</tr>
<tr>
<td><img src="https://user-images.githubusercontent.com/35218826/40904241-0c28ec68-6815-11e8-8296-89a1716b22d8.png" alt="2018-06-04 4 33 16" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40904521-f7c6e184-6815-11e8-8ba3-c94664da69a2.png" alt="2018-06-04 4 40 06" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40904664-656aa748-6816-11e8-9943-6607c209deac.png" alt="2018-06-04 4 43 02" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40904850-0f26ebde-6817-11e8-97d0-d3a7e4bc02da.png" alt="2018-06-04 4 47 40" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40905037-a026296a-6817-11e8-9d28-9e1ca7bc58c4.png" alt="2018-06-04 4 51 45" style="max-width:100%;"></td>
</tr>
<tr>
<th>Icon</th>
<th>Text</th>
<th>Mask</th>
<th>Filter</th>
<th></th>
</tr>
<tr>
<td><img src="https://user-images.githubusercontent.com/35218826/40931205-2d255db6-6865-11e8-98af-ad34c5a01da1.png" alt="2018-06-05 2 06 29" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40931484-46253948-6866-11e8-8a04-fa042920e457.png" alt="2018-06-05 2 14 36" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40931743-21eeb346-6867-11e8-8e31-a59f7a43482b.png" alt="2018-06-05 2 20 46" style="max-width:100%;"></td>
<td><img src="https://user-images.githubusercontent.com/35218826/40932016-093ed1f4-6868-11e8-8224-a048c3ee8a09.png" alt="2018-06-05 2 27 10" style="max-width:100%;"></td>
<td></td>
</tr>
</tbody>
</table>
### Powerful filter function
- Grayscale, Invert, Sepia, Blur Sharpen, Emboss, RemoveWhite, GradientTransparency, Brightness, Noise, Pixelate, ColorFilter, Tint, Multiply, Blend
| Grayscale | Noise | Gradient | Emboss | Pixelate |
| --- | --- | --- | --- | --- |
| ![grayscale](https://user-images.githubusercontent.com/35218826/41753470-930fb7b0-7608-11e8-9966-1c890e73d131.png) | ![noise](https://user-images.githubusercontent.com/35218826/41753458-9013bc82-7608-11e8-91d9-74dcc3ffce31.png) | ![gradient-transparency](https://user-images.githubusercontent.com/35218826/41753459-903fe640-7608-11e8-87f4-cc0bff43b4ee.png) | ![emboss](https://user-images.githubusercontent.com/35218826/41753460-906c018a-7608-11e8-8861-c135c0117cea.png) | ![pixelate](https://user-images.githubusercontent.com/35218826/41753461-90a614a6-7608-11e8-97a7-0d3b7bb4aec4.png) |
| Sepia | Sepia2 | Blend-righten | Blend-diff | Invert |
| --- | --- | --- | --- | --- |
| ![sepia](https://user-images.githubusercontent.com/35218826/41753464-91acc41c-7608-11e8-8652-572f935ea704.png) | ![sepia2](https://user-images.githubusercontent.com/35218826/41753640-91e57248-7609-11e8-8960-145e0de57e39.png) | ![blend-righten](https://user-images.githubusercontent.com/35218826/41753462-9114bc3a-7608-11e8-9ab4-16ce20a34321.png) | ![blend-diff](https://user-images.githubusercontent.com/35218826/41753465-91e4baf2-7608-11e8-9b8f-79e1b956d387.png) | ![invert](https://user-images.githubusercontent.com/35218826/41753466-9260b224-7608-11e8-848a-73231a02ae3a.png) |
| Multifly | Tint | Brightness | Remove-white | Sharpen |
| --- | --- | --- | --- | --- |
| ![multifly](https://user-images.githubusercontent.com/35218826/41753467-92baae28-7608-11e8-80d2-187a310213f5.png) | ![tint](https://user-images.githubusercontent.com/35218826/41753468-92e6391c-7608-11e8-8977-651366ebe693.png) | ![brightness](https://user-images.githubusercontent.com/35218826/41753457-8fb3d3c6-7608-11e8-9e1d-10c6e4aeba68.png) | ![remove-white](https://user-images.githubusercontent.com/35218826/41753463-917feeb0-7608-11e8-862d-eb3af84e120a.png) | ![sharpen](https://user-images.githubusercontent.com/35218826/41753639-91b8470a-7609-11e8-8d13-48ac3232365b.png) |
### Select only the desired function
```javascripot
var imageEditor = new tui.ImageEditor('#tui-image-editor-container', {
includeUI: {
menu: ['shape', 'crop']
...
},
...
```
## 🙆 Easy to apply the size and design you want
### Can be used everywhere.
- Widely supported in browsers including IE9, which is the minimum requirement to support canvas.
- Option to support various display sizes.
(allows you to use the editor features on your web pages at least over **550 * 450 sizes**)
![2018-06-04 5 35 25](https://user-images.githubusercontent.com/35218826/40907369-9221f482-681e-11e8-801c-78d6f2e246a8.png)
### Nice default & Fully customizable Themes
- Has a white and black theme, and you can modify the theme file to customize it.
- Has an API so that you can create your own instead of the built-in.
| black - top | black - bottom | white - left | white - right |
| --- | --- | --- | --- |
| ![2018-06-05 1 41 13](https://user-images.githubusercontent.com/35218826/40930753-8b72502e-6863-11e8-9cff-1719aee9aef0.png) | ![2018-06-05 1 40 24](https://user-images.githubusercontent.com/35218826/40930755-8bcee136-6863-11e8-8e28-0a6722d38c59.png) | ![2018-06-05 1 41 48](https://user-images.githubusercontent.com/35218826/40930756-8bfe0b50-6863-11e8-8682-bab11a0a2289.png) | ![2018-06-05 1 42 27](https://user-images.githubusercontent.com/35218826/40930754-8ba1dba0-6863-11e8-9439-cc059241b675.png) |
## 🎨 Features
* Load image to canvas

@@ -12,3 +142,3 @@ * Undo/Redo (With shortcut)

* Rotation
* Free Drawing
* Free drawing
* Line drawing

@@ -21,42 +151,89 @@ * Shape

## Documentation
* **API** : [http://nhnent.github.io/tui.image-editor/latest/](http://nhnent.github.io/tui.image-editor/latest/)
* **Tutorial** : [https://github.com/nhnent/tui.image-editor/wiki/Tutorial](https://github.com/nhnent/tui.image-editor/wiki/Tutorial)
* **Example** : [http://nhnent.github.io/tui.image-editor/latest/tutorial-example01-basic.html](http://nhnent.github.io/tui.image-editor/latest/tutorial-example01-basic.html)
## 💾 Install
## Dependency
* [fabric.js](https://github.com/kangax/fabric.js/releases/tag/v1.6.7) >=1.6.7
* [tui.code-snippet](https://github.com/nhnent/tui.code-snippet/releases/tag/v1.2.5) >=1.3.0
The TOAST UI products can be installed by using the package manager or downloading the source directly.
However, we highly recommend using the package manager.
## Test Environment
### PC
* IE9~11
* Edge
* Chrome
* Firefox
* Safari
### Mobile
* iOS 9.3.x
* Android 4.4.x
### Via Package Manager
## Usage
### Use `npm`
You can find TOAST UI producs via [npm](https://www.npmjs.com/) and [bower](https://bower.io/) package managers.
Install by using the commands provided by each package manager.
When using npm, be sure [Node.js](https://nodejs.org) is installed in the environment.
Install the latest version using `npm` command:
#### npm
```sh
$ npm install --save tui-image-editor # Latest version
$ npm install --save tui-image-editor@<version> # Specific version
```
$ npm install tui-image-editor --save
#### bower
```sh
$ bower install tui-image-editor # Latest version
$ bower install tui-image-editor#<tag> # Specific version
```
or want to install the each version:
### Via Contents Delivery Network (CDN)
TOAST UI products are available over the CDN powered by [TOAST Cloud](https://www.toast.com).
You can use the CDN as below.
```html
<link rel="stylesheet" href="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.css">
<script src="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.js"></script>
```
$ npm install tui-image-editor@<version> --save
If you want to use a specific version, use the tag name instead of `latest` in the URL.
The CDN directory has the following structure.
```
tui-image-editor/
├─ latest/
│ ├─ tui-image-editor.js
│ ├─ tui-image-editor.min.js
│ └─ tui-image-editor.css
├─ v3.1.0/
│ ├─ ...
```
To access as module format in your code:
### Download Source Files
* [Download bundle files from `dist` folder](https://github.com/nhnent/tui.image-editor/tree/production/dist)
* [Download all sources for each version](https://github.com/nhnent/tui.image-editor/releases)
## 🔨 Usage
### HTML
Add the container element where TOAST UI ImageEditor will be created.
``` html
<body>
...
<div id="tui-image-editor"></div>
...
</body>
```
### javascript
Add dependencies & initialize ImageEditor class with given element to make an image editor.
```javascript
var ImageEditor = require('tui-image-editor');
var instance = new ImageEditor('.tui-image-editor', {
var blackTheme = require('./js/theme/black-theme.js');
var instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
includeUI: {
loadImage: {
path: 'img/sampleImage.jpg',
name: 'SampleImage'
},
theme: blackTheme, // or whiteTheme
initMenu: 'filter',
menuBarPosition: 'bottom'
},
cssMaxWidth: 700,

@@ -71,19 +248,7 @@ cssMaxHeight: 500,

### Use `bower`
Install the latest version using `bower` command:
Or ~ UI
```
$ bower install tui-image-editor
```
or want to install the each version:
```
$ bower install tui-image-editor#<tag>
```
To access as namespace format in your code:
```javascript
var imageEditor = new tui.ImageEditor('.tui-image-editor', {
var ImageEditor = require('tui-image-editor');
var instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
cssMaxWidth: 700,

@@ -98,29 +263,55 @@ cssMaxHeight: 500,

### Via Contents Delivery Network (CDN)
TOAST UI products are available over the CDN powered by [TOAST Cloud](https://www.toast.com).
See [details](https://nhnent.github.io/tui.image-editor/latest) for additional informations.
You can use the CDN as below.
## 🔧 Development
```html
<script src="https://uicdn.toast.com/tui-image-editor/latest/tui-image-editor.js"></script>
```
The TOAST UI products are open-source.
After fixing issues, create a pull request(PR).
Run npm scripts and develop with the following process.
If you want to use a specific version, use the tag name instead of `latest` in the url's path.
### Setup
The CDN directory has the following structure.
Fork `master` branch into your personal repository.
Clone to local computer.
Install node modules.
Before starting development, check for any errors.
```sh
$ git clone https://github.com/{username}/tui.image-editor.git
$ cd tui.image-editor
$ npm install
$ npm run test
```
tui-image-editor/
├─ latest/
│ ├─ tui-image-editor.js
│ └─ tui-image-editor.min.js
├─ v3.1.0/
│ ├─ ...
### Run webpack-dev-server
```sh
$ npm run serve
```
### Download
* [Download bundle files from `dist` folder](https://github.com/nhnent/tui.image-editor/tree/production/dist)
* [Download all sources for each version](https://github.com/nhnent/tui.image-editor/releases)
## 📙 Documents
* **Tutorial** : [https://github.com/nhnent/tui.image-editor/tree/master/docs](https://github.com/nhnent/tui.image-editor/tree/master/docs)
* **Example** : [http://nhnent.github.io/tui.image-editor/latest/tutorial-example01-includeUi.html](http://nhnent.github.io/tui.image-editor/latest/tutorial-example01-includeUi.html)
* **API** : [http://nhnent.github.io/tui.image-editor/latest/](http://nhnent.github.io/tui.image-editor/latest/)
## License
## 💬 Contributing
* [Code of Conduct](CODE_OF_CONDUCT.md)
* [Contributing guideline](CONTRIBUTING.md)
* [Issue guideline](ISSUE_TEMPLATE.md)
* [Commit convention](https://github.com/nhnent/tui.image-editor/blob/production/docs/COMMIT_MESSAGE_CONVENTION.md)
## 🔩 Dependency
* [fabric.js](https://github.com/kangax/fabric.js/releases/tag/v1.6.7) >=1.6.7
* [tui.code-snippet](https://github.com/nhnent/tui.code-snippet/releases/tag/v1.2.5) >=1.3.0
* [tui.color-picker](https://github.com/nhnent/tui.color-picker/releases/tag/v2.2.0) >=2.2.0
## 🍞 TOAST UI Family
* [TOAST UI Editor](https://github.com/nhnent/tui.editor)
* [TOAST UI Grid](https://github.com/nhnent/tui.grid)
* [TOAST UI Chart](https://github.com/nhnent/tui.chart)
* [TOAST UI Calendar](https://github.com/nhnent/tui.calendar)
* [TOAST UI Components](https://github.com/nhnent)
## 📜 License
[MIT LICENSE](https://github.com/nhnent/tui.image-editor/blob/master/LICENSE)

@@ -0,2 +1,4 @@

import './js/polyfill';
import ImageEditor from './js/imageEditor';
import './css/index.styl';

@@ -3,0 +5,0 @@ // commands

@@ -74,5 +74,7 @@ /**

const canvas = this.getCanvas();
canvas.forEachObject(obj => { // {@link http://fabricjs.com/docs/fabric.Object.html#evented}
obj.evented = false;
});
this._cropzone = new Cropzone({

@@ -91,3 +93,4 @@ left: -10,

lockRotation: true
});
}, this.graphics.cropSelectionStyle);
canvas.deactivateAll();

@@ -94,0 +97,0 @@ canvas.add(this._cropzone);

@@ -11,2 +11,3 @@ /**

const events = consts.eventNames;
const {rejectMessages} = consts;

@@ -42,2 +43,8 @@

this._pathMap = pathMap;
/**
* Option to add icon to drag.
* @type {boolean}
*/
this.useDragAddIcon = graphics.useDragAddIcon;
}

@@ -69,5 +76,29 @@

fill: this._oColor
}, selectionStyle, options));
}, selectionStyle, options, this.graphics.controlStyle));
canvas.add(icon).setActiveObject(icon);
if (this.useDragAddIcon) {
canvas.add(icon).setActiveObject(icon);
canvas.on({
'mouse:move': fEvent => {
canvas.selection = false;
this.fire(events.ICON_CREATE_RESIZE, {
moveOriginPointer: canvas.getPointer(fEvent.e)
});
},
'mouse:up': fEvent => {
this.fire(events.ICON_CREATE_END, {
moveOriginPointer: canvas.getPointer(fEvent.e)
});
canvas.defaultCursor = 'default';
canvas.off('mouse:up');
canvas.off('mouse:move');
canvas.selection = true;
}
});
} else {
canvas.add(icon).setActiveObject(icon);
}
resolve(this.graphics.createObjectProperties(icon));

@@ -74,0 +105,0 @@ });

@@ -14,2 +14,3 @@ /**

const KEY_CODES = consts.keyCodes;
const DEFAULT_TYPE = 'rect';

@@ -130,2 +131,3 @@ const DEFAULT_OPTIONS = {

canvas.defaultCursor = 'default';
canvas.selection = true;

@@ -313,2 +315,7 @@ canvas.uniScaleTransform = false;

_onFabricMouseDown(fEvent) {
if (!fEvent.target) {
this._isSelected = false;
this._shapeObj = false;
}
if (!this._isSelected && !this._shapeObj) {

@@ -369,2 +376,4 @@ const canvas = this.getCanvas();

this.fire(eventNames.ADD_OBJECT_AFTER, this.graphics.createObjectProperties(shape));
canvas.off({

@@ -371,0 +380,0 @@ 'mouse:move': this._handlers.mousemove,

@@ -121,2 +121,8 @@ /**

this.isPrevEditing = false;
/**
* use itext
* @type {boolean}
*/
this.useItext = graphics.useItext;
}

@@ -136,6 +142,20 @@

'before:selection:cleared': this._listeners.selectClear,
'object:scaling': this._listeners.scaling
'object:scaling': this._listeners.scaling,
'text:editing': this._listeners.modify
});
this._createTextarea();
if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
obj.set({
left: obj.left - (obj.width / 2),
top: obj.top - (obj.height / 2),
originX: 'left',
originY: 'top'
});
}
});
} else {
this._createTextarea();
}

@@ -153,3 +173,23 @@ this.setCanvasRatio();

canvas.defaultCursor = 'default';
canvas.deactivateAllWithDispatch(); // action for undo stack
if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
if (obj.text === '') {
obj.remove();
} else {
obj.set({
left: obj.left + (obj.width / 2),
top: obj.top + (obj.height / 2),
originX: 'center',
originY: 'center'
});
}
}
});
} else {
canvas.deactivateAllWithDispatch();
this._removeTextarea();
}
canvas.off({

@@ -159,6 +199,5 @@ 'mouse:down': this._listeners.mousedown,

'before:selection:cleared': this._listeners.selectClear,
'object:scaling': this._listeners.scaling
'object:scaling': this._listeners.scaling,
'text:editing': this._listeners.modify
});
this._removeTextarea();
}

@@ -184,2 +223,4 @@

const canvas = this.getCanvas();
let newText = null;
let selectionStyle = consts.fObjectOptions.SELECTION_STYLE;
let styles = this._defaultStyles;

@@ -190,7 +231,16 @@

if (options.styles) {
styles = snippet.extend(options.styles, styles);
styles = snippet.extend(styles, options.styles);
}
const newText = new fabric.Text(text, styles);
newText.set(consts.fObjectOptions.SELECTION_STYLE);
if (this.useItext) {
newText = new fabric.IText(text, styles);
selectionStyle = snippet.extend({}, selectionStyle, {
originX: 'left',
originY: 'top'
});
} else {
newText = new fabric.Text(text, styles);
}
newText.set(selectionStyle);
newText.on({

@@ -502,2 +552,3 @@ mouseup: this._onFabricMouseUp.bind(this)

const obj = fEvent.target;
if (obj && !obj.isType('text')) {

@@ -549,3 +600,5 @@ return;

if (this._isDoubleClick(newClickTime)) {
this._changeToEditingMode(fEvent.target);
if (!this.useItext) {
this._changeToEditingMode(fEvent.target);
}
this.fire(events.TEXT_EDITING); // fire editing text event

@@ -552,0 +605,0 @@ }

@@ -59,10 +59,18 @@ /**

OBJECT_SCALED: 'objectScaled',
OBJECT_CREATED: 'objectCreated',
TEXT_EDITING: 'textEditing',
TEXT_CHANGED: 'textChanged',
ICON_CREATE_RESIZE: 'iconCreateResize',
ICON_CREATE_END: 'iconCreateEnd',
ADD_TEXT: 'addText',
ADD_OBJECT: 'addObject',
ADD_OBJECT_AFTER: 'addObjectAfter',
MOUSE_DOWN: 'mousedown',
MOUSE_UP: 'mouseup',
MOUSE_MOVE: 'mousemove',
// UNDO/REDO Events
REDO_STACK_CHANGED: 'redoStackChanged',
UNDO_STACK_CHANGED: 'undoStackChanged'
UNDO_STACK_CHANGED: 'undoStackChanged',
SELECTION_CLEARED: 'selectionCleared',
SELECTION_CREATED: 'selectionCreated'
},

@@ -127,3 +135,89 @@

addedObject: 'The object is already added.'
},
/**
* Default icon menu svg path
* @type {Object.<string, string>}
*/
defaultIconPath: {
'icon-arrow': 'M40 12V0l24 24-24 24V36H0V12h40z',
'icon-arrow-2': 'M49,32 H3 V22 h46 l-18,-18 h12 l23,23 L43,50 h-12 l18,-18 z ',
'icon-arrow-3': 'M43.349998,27 L17.354,53 H1.949999 l25.996,-26 L1.949999,1 h15.404 L43.349998,27 z ',
'icon-star': 'M35,54.557999 l-19.912001,10.468 l3.804,-22.172001 l-16.108,-15.7 l22.26,-3.236 L35,3.746 l9.956,20.172001 l22.26,3.236 l-16.108,15.7 l3.804,22.172001 z ',
'icon-star-2': 'M17,31.212 l-7.194,4.08 l-4.728,-6.83 l-8.234,0.524 l-1.328,-8.226 l-7.644,-3.14 l2.338,-7.992 l-5.54,-6.18 l5.54,-6.176 l-2.338,-7.994 l7.644,-3.138 l1.328,-8.226 l8.234,0.522 l4.728,-6.83 L17,-24.312 l7.194,-4.08 l4.728,6.83 l8.234,-0.522 l1.328,8.226 l7.644,3.14 l-2.338,7.992 l5.54,6.178 l-5.54,6.178 l2.338,7.992 l-7.644,3.14 l-1.328,8.226 l-8.234,-0.524 l-4.728,6.83 z ',
'icon-polygon': 'M3,31 L19,3 h32 l16,28 l-16,28 H19 z ',
'icon-location': 'M24 62C8 45.503 0 32.837 0 24 0 10.745 10.745 0 24 0s24 10.745 24 24c0 8.837-8 21.503-24 38zm0-28c5.523 0 10-4.477 10-10s-4.477-10-10-10-10 4.477-10 10 4.477 10 10 10z',
'icon-heart': 'M49.994999,91.349998 l-6.96,-6.333 C18.324001,62.606995 2.01,47.829002 2.01,29.690998 C2.01,14.912998 13.619999,3.299999 28.401001,3.299999 c8.349,0 16.362,5.859 21.594,12 c5.229,-6.141 13.242001,-12 21.591,-12 c14.778,0 26.390999,11.61 26.390999,26.390999 c0,18.138 -16.314001,32.916 -41.025002,55.374001 l-6.96,6.285 z ',
'icon-bubble': 'M44 48L34 58V48H12C5.373 48 0 42.627 0 36V12C0 5.373 5.373 0 12 0h40c6.627 0 12 5.373 12 12v24c0 6.627-5.373 12-12 12h-8z'
},
defaultRotateRangeValus: {
realTimeEvent: true,
min: -360,
max: 360,
value: 0
},
defaultDrawRangeValus: {
min: 5,
max: 30,
value: 12
},
defaultShapeStrokeValus: {
realTimeEvent: false,
min: 2,
max: 300,
value: 3
},
defaultTextRangeValus: {
realTimeEvent: true,
min: 10,
max: 100,
value: 50
},
defaultFilterRangeValus: {
tintOpacityRange: {
min: 0,
max: 1,
value: 0.7
},
removewhiteThresholdRange: {
min: 0,
max: 255,
value: 60
},
removewhiteDistanceRange: {
min: 0,
max: 255,
value: 10
},
gradientTransparencyRange: {
min: 0,
max: 255,
value: 100
},
brightnessRange: {
min: -255,
max: 255,
value: 100
},
noiseRange: {
min: 0,
max: 1000,
value: 100
},
pixelateRange: {
min: 2,
max: 20,
value: 4
},
colorfilterThresholeRange: {
min: 0,
max: 255,
value: 45
}
}
};

@@ -43,3 +43,3 @@ /**

*/
applyTo(canvasEl) {
applyTo(canvasEl) { // eslint-disable-line
const context = canvasEl.getContext('2d');

@@ -46,0 +46,0 @@ const imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height);

@@ -32,5 +32,10 @@ /**

*/
initialize(options) {
initialize(options, extendsOptions) {
options = snippet.extend(options, extendsOptions);
options.type = 'cropzone';
this.callSuper('initialize', options);
this.options = options;
this.on({

@@ -65,7 +70,16 @@ 'moving': this._onMoving,

// Black dash line
this._strokeBorder(ctx, 'rgb(0, 0, 0)', cropzoneDashLineWidth);
if (this.options.lineWidth) {
this._fillInnerRect(ctx);
} else {
// Black dash line
this._strokeBorder(ctx, 'rgb(0, 0, 0)', {
lineDashWidth: cropzoneDashLineWidth
});
// White dash line
this._strokeBorder(ctx, 'rgb(255, 255, 255)', cropzoneDashLineWidth, cropzoneDashLineOffset);
// White dash line
this._strokeBorder(ctx, 'rgb(255, 255, 255)', {
lineDashWidth: cropzoneDashLineWidth,
lineDashOffset: cropzoneDashLineOffset
});
}

@@ -113,3 +127,3 @@ // Reset scale

ctx.lineTo(x[3] + 1, y[3] + 1);
ctx.lineTo(x[0] - 1, y[3] - 1);
ctx.lineTo(x[0] - 1, y[3] + 1);
ctx.lineTo(x[0] - 1, y[0] - 1);

@@ -131,2 +145,51 @@ ctx.closePath();

/**
* Draw Inner grid line
* @param {CanvasRenderingContext2D} ctx - Context
* @private
*/
_fillInnerRect(ctx) {
const {x: outerX, y: outerY} = this._getCoordinates(ctx);
const x = this._caculateInnerPosition(outerX, (outerX[2] - outerX[1]) / 3);
const y = this._caculateInnerPosition(outerY, (outerY[2] - outerY[1]) / 3);
ctx.save();
ctx.strokeStyle = 'rgba(255, 255, 255, 0.7)';
ctx.lineWidth = this.options.lineWidth;
ctx.beginPath();
ctx.moveTo(x[0], y[1]);
ctx.lineTo(x[3], y[1]);
ctx.moveTo(x[0], y[2]);
ctx.lineTo(x[3], y[2]);
ctx.moveTo(x[1], y[0]);
ctx.lineTo(x[1], y[3]);
ctx.moveTo(x[2], y[0]);
ctx.lineTo(x[2], y[3]);
ctx.stroke();
ctx.closePath();
ctx.restore();
},
/**
* Calculate Inner Position
* @param {Array} outer - outer position
* @param {number} size - interval for calcaulate
* @returns {Array} - inner position
* @private
*/
_caculateInnerPosition(outer, size) {
const position = [];
position[0] = outer[1];
position[1] = outer[1] + size;
position[2] = outer[1] + (size * 2);
position[3] = outer[2];
return position;
},
/**
* Get coordinates

@@ -170,3 +233,3 @@ * @param {CanvasRenderingContext2D} ctx - Context

*/
_strokeBorder(ctx, strokeStyle, lineDashWidth, lineDashOffset) {
_strokeBorder(ctx, strokeStyle, {lineDashWidth, lineDashOffset, lineWidth}) {
const halfWidth = this.getWidth() / 2,

@@ -177,2 +240,3 @@ halfHeight = this.getHeight() / 2;

ctx.strokeStyle = strokeStyle;
if (ctx.setLineDash) {

@@ -184,2 +248,5 @@ ctx.setLineDash([lineDashWidth, lineDashWidth]);

}
if (lineWidth) {
ctx.lineWidth = lineWidth;
}

@@ -186,0 +253,0 @@ ctx.beginPath();

@@ -28,2 +28,3 @@ /**

const events = consts.eventNames;
const {drawingModes, fObjectOptions} = consts;

@@ -49,6 +50,13 @@ const {extend, stamp, isArray, isString, forEachArray, forEachOwnProperties, CustomEvents} = snippet;

* @param {number} option.cssMaxHeight - Canvas css-max-height
* @param {boolean} option.useItext - Use IText in text mode
* @param {boolean} option.useDragAddIcon - Use dragable add in icon mode
* @ignore
*/
class Graphics {
constructor(element, cssMaxWidth, cssMaxHeight) {
constructor(element, {
cssMaxWidth,
cssMaxHeight,
useItext = false,
useDragAddIcon = false
} = {}) {
/**

@@ -73,2 +81,20 @@ * Fabric image instance

/**
* Use Itext mode for text component
* @type {boolean}
*/
this.useItext = useItext;
/**
* Use add drag icon mode for icon component
* @type {boolean}
*/
this.useDragAddIcon = useDragAddIcon;
/**
* cropper Selection Style
* @type {Object}
*/
this.cropSelectionStyle = {};
/**
* Image name

@@ -126,3 +152,5 @@ * @type {string}

onObjectSelected: this._onObjectSelected.bind(this),
onPathCreated: this._onPathCreated.bind(this)
onPathCreated: this._onPathCreated.bind(this),
onSelectionCleared: this._onSelectionCleared.bind(this),
onSelectionCreated: this._onSelectionCreated.bind(this)
};

@@ -181,2 +209,3 @@

}
/**

@@ -285,2 +314,10 @@ * Removes the object or group

/**
* Gets an active group object
* @returns {Object} active group object instance
*/
getActiveGroupObject() {
return this._canvas.getActiveGroup();
}
/**
* Activates an object or group

@@ -294,2 +331,10 @@ * @param {Object} target - target object or group

/**
* Set Crop selection style
* @param {Object} style - Selection styles
*/
setCropSelectionStyle(style) {
this.cropSelectionStyle = style;
}
/**
* Get component

@@ -336,2 +381,3 @@ * @param {string} name - Component name

}
/**

@@ -568,2 +614,12 @@ * Stop the current drawing mode and back to the 'NORMAL' mode

/**
* Change cursor style
* @param {string} cursorType - cursor type
*/
changeCursor(cursorType) {
const canvas = this.getCanvas();
canvas.defaultCursor = cursorType;
canvas.renderAll();
}
/**
* Whether it has the filter or not

@@ -843,3 +899,5 @@ * @param {string} type - Filter type

'object:selected': handler.onObjectSelected,
'path:created': handler.onPathCreated
'path:created': handler.onPathCreated,
'selection:cleared': handler.onSelectionCleared,
'selection:created': handler.onSelectionCreated
});

@@ -933,2 +991,39 @@ }

/**
* "selction:cleared" canvas event handler
* @private
*/
_onSelectionCleared() {
this.fire(events.SELECTION_CLEARED);
}
/**
* "selction:created" canvas event handler
* @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event
* @private
*/
_onSelectionCreated(fEvent) {
this.fire(events.SELECTION_CREATED, fEvent.target);
}
/**
* Canvas discard selection all
*/
discardSelection() {
this._canvas.discardActiveGroup();
this._canvas.discardActiveObject();
this._canvas.renderAll();
}
/**
* Canvas Selectable status change
* @param {boolean} selectable - expect status
*/
changeSelectableAll(selectable) {
this._canvas.forEachObject(obj => {
obj.selectable = selectable;
obj.hoverCursor = selectable ? 'move' : 'crosshair';
});
}
/**
* Return object's properties

@@ -956,3 +1051,3 @@ * @param {fabric.Object} obj - fabric object

if (obj.type === 'text') {
if (['i-text', 'text'].indexOf(obj.type) > -1) {
extend(props, this._createTextProperties(obj, props));

@@ -959,0 +1054,0 @@ }

@@ -6,3 +6,6 @@ /**

import snippet from 'tui-code-snippet';
import Promise from 'core-js/library/es6/promise';
import Invoker from './invoker';
import UI from './ui';
import action from './action';
import commandFactory from './factory/command';

@@ -22,14 +25,57 @@ import Graphics from './graphics';

* @param {string|jQuery|HTMLElement} wrapper - Wrapper's element or selector
* @param {Object} [option] - Canvas max width & height of css
* @param {number} option.cssMaxWidth - Canvas css-max-width
* @param {number} option.cssMaxHeight - Canvas css-max-height
* @param {Boolean} [option.usageStatistics=true] - Let us know the hostname. If you don't want to send the hostname, please set to false.
* @param {Object} [options] - Canvas max width & height of css
* @param {number} [options.includeUI] - Use the provided UI
* @param {Object} [options.includeUI.loadImage] - Basic editing image
* @param {string} options.includeUI.loadImage.path - image path
* @param {string} options.includeUI.loadImage.name - image name
* @param {Object} [options.includeUI.theme] - Theme object
* @param {Array} [options.includeUI.menu] - It can be selected when only specific menu is used. [default all]
* @param {string} [options.includeUI.initMenu] - The first menu to be selected and started.
* @param {string} [options.includeUI.menuBarPosition=bottom] - Menu bar position [top | bottom | left | right]
* @param {number} options.cssMaxWidth - Canvas css-max-width
* @param {number} options.cssMaxHeight - Canvas css-max-height
* @param {Boolean} [options.usageStatistics=true] - Let us know the hostname. If you don't want to send the hostname, please set to false.
* @example
* var ImageEditor = require('tui-image-editor');
* var blackTheme = require('./js/theme/black-theme.js');
* var instance = new ImageEditor(document.querySelector('#tui-image-editor'), {
* includeUI: {
* loadImage: {
* path: 'img/sampleImage.jpg',
* name: 'SampleImage'
* },
* theme: blackTheme, // or whiteTheme
* menu: ['shape', 'filter'],
* initMenu: 'filter',
* menuBarPosition: 'bottom'
* },
* cssMaxWidth: 700,
* cssMaxHeight: 500,
* selectionStyle: {
* cornerSize: 20,
* rotatingPointOffset: 70
* }
* });
*/
class ImageEditor {
constructor(wrapper, option) {
option = snippet.extend({
constructor(wrapper, options) {
options = snippet.extend({
includeUI: false,
usageStatistics: true
}, option);
}, options);
this.mode = null;
this.activeObjectId = null;
/**
* UI instance
* @type {Ui}
*/
if (options.includeUI) {
this.ui = new UI(wrapper, options.includeUI, this.getActions());
options = this.ui.setUiDefaultSelectionStyle(options);
}
/**
* Invoker

@@ -46,3 +92,10 @@ * @type {Invoker}

*/
this._graphics = new Graphics(wrapper, option.cssMaxWidth, option.cssMaxHeight);
this._graphics = new Graphics(
this.ui ? this.ui.getEditorArea() : wrapper, {
cssMaxWidth: options.cssMaxWidth,
cssMaxHeight: options.cssMaxHeight,
useItext: !!this.ui,
useDragAddIcon: !!this.ui
}
);

@@ -63,4 +116,9 @@ /**

addObject: this._onAddObject.bind(this),
addObjectAfter: this._onAddObjectAfter.bind(this),
textEditing: this._onTextEditing.bind(this),
textChanged: this._onTextChanged.bind(this)
textChanged: this._onTextChanged.bind(this),
iconCreateResize: this._onIconCreateResize.bind(this),
iconCreateEnd: this._onIconCreateEnd.bind(this),
selectionCleared: this._selectionCleared.bind(this),
selectionCreated: this._selectionCreated.bind(this)
};

@@ -71,9 +129,14 @@

this._attachDomEvents();
this._setSelectionStyle(options.selectionStyle, {
applyCropSelectionStyle: options.applyCropSelectionStyle,
applyGroupSelectionStyle: options.applyGroupSelectionStyle
});
if (option.selectionStyle) {
this._setSelectionStyle(option.selectionStyle);
if (options.usageStatistics) {
sendHostName();
}
if (option.usageStatistics) {
sendHostName();
if (this.ui) {
this.ui.initCanvas();
this.setReAction();
}

@@ -96,3 +159,2 @@ }

*/
/**

@@ -139,7 +201,24 @@ * Rotation status

* Set selection style by init option
* @param {Object} styles - Selection styles
* @param {Object} selectionStyle - Selection styles
* @param {Object} applyTargets - Selection apply targets
* @param {boolean} applyCropSelectionStyle - whether apply with crop selection style or not
* @param {boolean} applyGroupSelectionStyle - whether apply with group selection style or not
* @private
*/
_setSelectionStyle(styles) {
this._graphics.setSelectionStyle(styles);
_setSelectionStyle(selectionStyle, {applyCropSelectionStyle, applyGroupSelectionStyle}) {
if (selectionStyle) {
this._graphics.setSelectionStyle(selectionStyle);
}
if (applyCropSelectionStyle) {
this._graphics.setCropSelectionStyle(selectionStyle);
}
if (applyGroupSelectionStyle) {
this.on('selectionCreated', eventTarget => {
if (eventTarget.type === 'group') {
eventTarget.set(selectionStyle);
}
});
}
}

@@ -192,3 +271,8 @@

'textEditing': this._handlers.textEditing,
'textChanged': this._handlers.textChanged
'textChanged': this._handlers.textChanged,
'iconCreateResize': this._handlers.iconCreateResize,
'iconCreateEnd': this._handlers.iconCreateEnd,
'selectionCleared': this._handlers.selectionCleared,
'selectionCreated': this._handlers.selectionCreated,
'addObjectAfter': this._handlers.addObjectAfter
});

@@ -222,5 +306,2 @@ }

_onKeyDown(e) {
const activeObject = this._graphics.getActiveObject();
const activeObjectId = this._graphics.getObjectId(activeObject);
if ((e.ctrlKey || e.metaKey) && e.keyCode === keyCodes.Z) {

@@ -236,6 +317,5 @@ // There is no error message on shortcut when it's empty

if ((e.keyCode === keyCodes.BACKSPACE || e.keyCode === keyCodes.DEL) &&
activeObject) {
if ((e.keyCode === keyCodes.BACKSPACE || e.keyCode === keyCodes.DEL)) {
e.preventDefault();
this.removeObject(activeObjectId);
this.removeActiveObject();
}

@@ -246,2 +326,37 @@ }

/**
* Remove Active Object
*/
removeActiveObject() {
const activeObject = this._graphics.getActiveObject();
const activeObjectGroup = this._graphics.getActiveGroupObject();
if (activeObjectGroup) {
const objects = activeObjectGroup.getObjects();
this.discardSelection();
this._removeObjectStream(objects);
} else if (activeObject) {
const activeObjectId = this._graphics.getObjectId(activeObject);
this.removeObject(activeObjectId);
}
}
/**
* RemoveObject Sequential processing for prevent invoke lock
* @param {Array.<Object>} targetObjects - target Objects for remove
* @returns {object} targetObjects
* @private
*/
_removeObjectStream(targetObjects) {
if (!targetObjects.length) {
return true;
}
const targetObject = targetObjects.pop();
return this.removeObject(this._graphics.getObjectId(targetObject)).then(() => (
this._removeObjectStream(targetObjects)
));
}
/**
* mouse down event handler

@@ -386,2 +501,21 @@ * @param {Event} event mouse down event

/**
* discard selction
* @example
* imageEditor.discardSelection();
*/
discardSelection() {
this._graphics.discardSelection();
}
/**
* selectable status change
* @param {boolean} selectable - selctable status
* @example
* imageEditor.changeSelectableAll(false); // or true
*/
changeSelectableAll(selectable) {
this._graphics.changeSelectableAll(selectable);
}
/**
* Invoke command

@@ -864,2 +998,13 @@ * @param {String} commandName - Command name

/**
* change text mode
* @param {string} type - change type
* @private
*/
_changeActivateMode(type) {
if (type !== 'ICON' && this.getDrawingMode() !== type) {
this.startDrawingMode(type);
}
}
/**
* 'textChanged' event handler

@@ -874,2 +1019,24 @@ * @param {Object} objectProps changed object properties

/**
* 'iconCreateResize' event handler
* @param {Object} originPointer origin pointer
* @param {Number} originPointer.x x position
* @param {Number} originPointer.y y position
* @private
*/
_onIconCreateResize(originPointer) {
this.fire(events.ICON_CREATE_RESIZE, originPointer);
}
/**
* 'iconCreateEnd' event handler
* @param {Object} originPointer origin pointer
* @param {Number} originPointer.x x position
* @param {Number} originPointer.y y position
* @private
*/
_onIconCreateEnd(originPointer) {
this.fire(events.ICON_CREATE_END, originPointer);
}
/**
* 'textEditing' event handler

@@ -932,2 +1099,28 @@ * @private

/**
* 'addObjectAfter' event handler
* @param {Object} objectProps added object properties
* @private
*/
_onAddObjectAfter(objectProps) {
this.fire(events.ADD_OBJECT_AFTER, objectProps);
}
/**
* 'selectionCleared' event handler
* @private
*/
_selectionCleared() {
this.fire(events.SELECTION_CLEARED);
}
/**
* 'selectionCreated' event handler
* @param {Object} eventTarget - Fabric object
* @private
*/
_selectionCreated(eventTarget) {
this.fire(events.SELECTION_CREATED, eventTarget);
}
/**
* Register custom icons

@@ -946,2 +1139,12 @@ * @param {{iconType: string, pathValue: string}} infos - Infos to register icons

/**
* Change canvas cursor type
* @param {string} cursorType - cursor type
* @example
* imageEditor.changeCursor('crosshair');
*/
changeCursor(cursorType) {
this._graphics.changeCursor(cursorType);
}
/**
* Add icon on canvas

@@ -1164,2 +1367,19 @@ * @param {string} type - Icon type ('arrow', 'cancel', custom icon name)

/**
* Set properties of active object, Do not leave an invoke history.
* @param {number} id - object id
* @param {Object} keyValue - key & value
* @example
* imageEditor.setObjectPropertiesQuietly(id, {
* left:100,
* top:100,
* width: 200,
* height: 200,
* opacity: 0.5
* });
*/
setObjectPropertiesQuietly(id, keyValue) {
this._graphics.setObjectProperties(id, keyValue);
}
/**
* Get properties of active object corresponding key

@@ -1270,3 +1490,5 @@ * @param {number} id - object id

action.mixin(ImageEditor);
CustomEvents.mixin(ImageEditor);
module.exports = ImageEditor;

@@ -78,2 +78,48 @@ /**

/**
* ParseInt simpliment
* @param {number} value - Value
* @returns {number}
*/
toInteger(value) {
return parseInt(value, 10);
},
/**
* String to camelcase string
* @param {string} targetString - change target
* @returns {string}
* @private
*/
toCamelCase(targetString) {
return targetString.replace(/-([a-z])/g, ($0, $1) => $1.toUpperCase());
},
/**
* Check browser file api support
* @returns {boolean}
* @private
*/
isSupportFileApi() {
return !!(window.File && window.FileList && window.FileReader);
},
/**
* hex to rgb
* @param {string} color - hex color
* @param {string} alpha - color alpha value
* @returns {string} rgb expression
*/
getRgb(color, alpha) {
if (color.length === 4) {
color = `${color}${color.slice(1, 4)}`;
}
const r = parseInt(color.slice(1, 3), 16);
const g = parseInt(color.slice(3, 5), 16);
const b = parseInt(color.slice(5, 7), 16);
const a = alpha || 1;
return `rgba(${r}, ${g}, ${b}, ${a})`;
},
/**
* send hostname

@@ -96,3 +142,58 @@ */

});
},
/**
* Apply css resource
* @param {string} styleBuffer - serialized css text
* @param {string} tagId - style tag id
*/
styleLoad(styleBuffer, tagId) {
const [head] = document.getElementsByTagName('head');
const linkElement = document.createElement('link');
const styleData = encodeURIComponent(styleBuffer);
if (tagId) {
linkElement.id = tagId;
// linkElement.id = 'tui-image-editor-theme-style';
}
linkElement.setAttribute('rel', 'stylesheet');
linkElement.setAttribute('type', 'text/css');
linkElement.setAttribute('href', `data:text/css;charset=UTF-8,${styleData}`);
head.appendChild(linkElement);
},
/**
* Get selector
* @param {HTMLElement} targetElement - target element
* @returns {Function} selector
*/
getSelector(targetElement) {
return str => targetElement.querySelector(str);
},
/**
* Change base64 to blob
* @param {String} data - base64 string data
* @returns {Blob} Blob Data
*/
base64ToBlob(data) {
const rImageType = /data:(image\/.+);base64,/;
let mimeString = '';
let raw, uInt8Array, i;
raw = data.replace(rImageType, (header, imageType) => {
mimeString = imageType;
return '';
});
raw = atob(raw);
const rawLength = raw.length;
uInt8Array = new Uint8Array(rawLength); // eslint-disable-line
for (i = 0; i < rawLength; i += 1) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], {type: mimeString});
}
};

@@ -20,3 +20,6 @@ /**

beforeEach(() => {
graphics = new Graphics($('<canvas>'), cssMaxWidth, cssMaxHeight);
graphics = new Graphics($('<canvas>'), {
cssMaxWidth,
cssMaxHeight
});
canvas = graphics.getCanvas();

@@ -23,0 +26,0 @@ });

@@ -7,2 +7,3 @@ /**

import snippet from 'tui-code-snippet';
import Promise from 'core-js/library/es6/promise';
import ImageEditor from '../src/js/imageEditor';

@@ -19,2 +20,6 @@

spyOn(snippet, 'imagePing');
imageEditor = new ImageEditor(el, {
usageStatistics: false
});
});

@@ -39,3 +44,47 @@

});
it('removeObjectStream () must be executed as many times as the length of the Object array.', done => {
const promise = new Promise(resolve => {
resolve();
});
spyOn(imageEditor, '_removeObjectStream').and.callThrough();
spyOn(imageEditor, 'removeObject').and.returnValue(promise);
const removeJobsSequens = [1, 2, 3, 4];
const expected = removeJobsSequens.length + 1;
const removeObjectStremPromise = imageEditor._removeObjectStream(removeJobsSequens);
removeObjectStremPromise.then(() => {
expect(imageEditor._removeObjectStream.calls.count()).toBe(expected);
done();
});
});
describe('removeActiveObject()', () => {
it('_removeObjectStream should be executed when group exists.', () => {
spyOn(imageEditor._graphics, 'getActiveObject');
spyOn(imageEditor._graphics, 'getActiveGroupObject').and.returnValue({
getObjects: () => [1, 2, 3]
});
spyOn(imageEditor, '_removeObjectStream');
spyOn(imageEditor, 'discardSelection');
imageEditor.removeActiveObject();
expect(imageEditor.discardSelection).toHaveBeenCalled();
expect(imageEditor._removeObjectStream).toHaveBeenCalled();
});
it('removeObject must be executed when group does not exist.', () => {
spyOn(imageEditor._graphics, 'getActiveGroupObject').and.returnValue(null);
spyOn(imageEditor._graphics, 'getActiveObject').and.returnValue(jasmine.any(Object));
spyOn(imageEditor._graphics, 'getObjectId');
spyOn(imageEditor, 'removeObject');
imageEditor.removeActiveObject();
expect(imageEditor.removeObject).toHaveBeenCalled();
});
});
});
});

@@ -47,5 +47,6 @@ /**

it('"rotate()" should add angle value modular 360(===2*PI)', () => {
it('"rotate()" should add angle value modular 360(===2*PI)', done => {
rotationModule.setAngle(10).then(() => rotationModule.rotate(380)).then(() => {
expect(rotationModule.getCurrentAngle()).toBe(30);
done();
});

@@ -52,0 +53,0 @@ });

@@ -9,8 +9,9 @@ /**

const SafeUmdPlugin = require('safe-umd-webpack-plugin');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const isProduction = process.argv.indexOf('-p') > -1;
const FILENAME = pkg.name + (isProduction ? '.min.js' : '.js');
const FILENAME = pkg.name + (isProduction ? '.min' : '');
const BANNER = [
FILENAME,
`${FILENAME}.js`,
`@version ${pkg.version}`,

@@ -31,3 +32,3 @@ `@author ${pkg.author}`,

publicPath: 'dist',
filename: FILENAME
filename: `${FILENAME}.js`
},

@@ -61,3 +62,8 @@ externals: {

loader: 'babel'
},
{
test: /\.styl$/,
loader: ExtractTextPlugin.extract('css-loader?sourceMap!stylus-loader?paths=src/css/')
}
]

@@ -67,2 +73,3 @@ },

new webpack.BannerPlugin(BANNER),
new ExtractTextPlugin(`${FILENAME}.css`),
new SafeUmdPlugin()

@@ -69,0 +76,0 @@ ],

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc