Skip to content

Commit

Permalink
fix: fixed Text object -> ITextObject (fix #262 #109) (#352)
Browse files Browse the repository at this point in the history
* fix: fixed Text object -> ITextObject

* apply codereview

Co-authored-by: jwc <[email protected]>
  • Loading branch information
jinwoo-kim-nhn and jwc committed Jun 16, 2020
1 parent 20601cf commit e20ae82
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 263 deletions.
182 changes: 25 additions & 157 deletions src/js/component/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import fabric from 'fabric';
import snippet from 'tui-code-snippet';
import Component from '../interface/component';
import {eventNames as events, componentNames, fObjectOptions} from '../consts';
import {makeStyleText, Promise} from '../util';
import {Promise} from '../util';

const defaultStyles = {
fill: '#000000',
Expand All @@ -20,24 +20,7 @@ const resetStyles = {
textAlign: 'left',
underline: false
};
const {browser} = snippet;

const TEXTAREA_CLASSNAME = 'tui-image-eidtor-textarea';
const TEXTAREA_STYLES = makeStyleText({
position: 'absolute',
padding: 0,
display: 'none',
border: '1px dotted red',
overflow: 'hidden',
resize: 'none',
outline: 'none',
'border-radius': 0,
'background-color': 'transparent',
'-webkit-appearance': 'none',
'z-index': 9999,
'white-space': 'pre'
});
const EXTRA_PIXEL_LINEHEIGHT = 0.1;

const DBCLICK_TIME = 500;

/**
Expand Down Expand Up @@ -115,12 +98,6 @@ class Text extends Component {
* @type {boolean}
*/
this.isPrevEditing = false;

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

/**
Expand All @@ -139,15 +116,11 @@ class Text extends Component {
'text:editing': this._listeners.modify
});

if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
this.adjustOriginPosition(obj, 'start');
}
});
} else {
this._createTextarea();
}
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
this.adjustOriginPosition(obj, 'start');
}
});

this.setCanvasRatio();
}
Expand All @@ -161,20 +134,15 @@ class Text extends Component {
canvas.selection = true;
canvas.defaultCursor = 'default';

if (this.useItext) {
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
if (obj.text === '') {
canvas.remove(obj);
} else {
this.adjustOriginPosition(obj, 'end');
}
canvas.forEachObject(obj => {
if (obj.type === 'i-text') {
if (obj.text === '') {
canvas.remove(obj);
} else {
this.adjustOriginPosition(obj, 'end');
}
});
} else {
canvas.discardActiveObject();
this._removeTextarea();
}
}
});

canvas.off({
'mouse:down': this._listeners.mousedown,
Expand Down Expand Up @@ -234,15 +202,11 @@ class Text extends Component {
styles = snippet.extend(styles, options.styles);
}

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 = new fabric.IText(text, styles);
selectionStyle = snippet.extend({}, selectionStyle, {
originX: 'left',
originY: 'top'
});

newText.set(selectionStyle);
newText.on({
Expand Down Expand Up @@ -387,59 +351,6 @@ class Text extends Component {
this._defaultStyles.top = position.y;
}

/**
* Create textarea element on canvas container
* @private
*/
_createTextarea() {
const container = this.getCanvasElement().parentNode;
const textarea = document.createElement('textarea');

textarea.className = TEXTAREA_CLASSNAME;
textarea.setAttribute('style', TEXTAREA_STYLES);
textarea.setAttribute('wrap', 'off');

container.appendChild(textarea);

this._textarea = textarea;

this._listeners = snippet.extend(this._listeners, {
input: this._onInput.bind(this),
keydown: this._onKeyDown.bind(this),
blur: this._onBlur.bind(this),
scroll: this._onScroll.bind(this)
});

if (browser.msie && browser.version === 9) {
fabric.util.addListener(textarea, 'keydown', this._listeners.keydown);
} else {
fabric.util.addListener(textarea, 'input', this._listeners.input);
}
fabric.util.addListener(textarea, 'blur', this._listeners.blur);
fabric.util.addListener(textarea, 'scroll', this._listeners.scroll);
}

/**
* Remove textarea element on canvas container
* @private
*/
_removeTextarea() {
const container = this.getCanvasElement().parentNode;
const textarea = container.querySelector('textarea');

container.removeChild(textarea);

this._textarea = null;

if (browser.msie && browser.version < 10) {
fabric.util.removeListener(textarea, 'keydown', this._listeners.keydown);
} else {
fabric.util.removeListener(textarea, 'input', this._listeners.input);
}
fabric.util.removeListener(textarea, 'blur', this._listeners.blur);
fabric.util.removeListener(textarea, 'scroll', this._listeners.scroll);
}

/**
* Input event handler
* @private
Expand Down Expand Up @@ -615,10 +526,11 @@ class Text extends Component {
const {target} = fEvent;
const newClickTime = (new Date()).getTime();

if (target.isEditing || this._isDoubleClick(newClickTime)) {
if (!this.useItext) {
this._changeToEditingMode(target);
}
if (this._isDoubleClick(newClickTime) && !target.isEditing) {
target.enterEditing();
}

if (target.isEditing) {
this.fire(events.TEXT_EDITING); // fire editing text event
}

Expand All @@ -634,50 +546,6 @@ class Text extends Component {
_isDoubleClick(newClickTime) {
return (newClickTime - this._lastClickTime < DBCLICK_TIME);
}

/**
* Change state of text object for editing
* @param {fabric.Text} obj - Text object fired event
* @private
*/
_changeToEditingMode(obj) {
const ratio = this.getCanvasRatio();
const textareaStyle = this._textarea.style;
const canvas = this.getCanvas();

this.isPrevEditing = true;

canvas.remove(obj);
canvas.discardActiveObject();

this._editingObj = obj;
this._textarea.value = obj.text;

this._editingObjInfos = {
left: obj.left,
top: obj.top,
width: obj.width,
height: obj.height
};

textareaStyle.display = 'block';
textareaStyle.left = `${obj.oCoords.tl.x / ratio}px`;
textareaStyle.top = `${obj.oCoords.tl.y / ratio}px`;
textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;
textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;
textareaStyle.transform = `rotate(${obj.angle}deg)`;
textareaStyle.color = obj.fill;

textareaStyle['font-size'] = `${obj.fontSize / ratio}px`;
textareaStyle['font-family'] = obj.fontFamily;
textareaStyle['font-style'] = obj.fontStyle;
textareaStyle['font-weight'] = obj.fontWeight;
textareaStyle['text-align'] = obj.textAlign;
textareaStyle['line-height'] = obj.lineHeight + EXTRA_PIXEL_LINEHEIGHT;
textareaStyle['transform-origin'] = 'left top';

this._textarea.focus();
}
}

export default Text;
8 changes: 0 additions & 8 deletions src/js/graphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,13 @@ const backstoreOnly = {
* @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.useItext - Use IText in text mode
* @param {boolean} option.useDragAddIcon - Use dragable add in icon mode
* @ignore
*/
class Graphics {
constructor(element, {
cssMaxWidth,
cssMaxHeight,
useItext = false,
useDragAddIcon = false
} = {}) {
/**
Expand All @@ -70,12 +68,6 @@ class Graphics {
*/
this.cssMaxHeight = cssMaxHeight || DEFAULT_CSS_MAX_HEIGHT;

/**
* Use Itext mode for text component
* @type {boolean}
*/
this.useItext = useItext;

/**
* Use add drag icon mode for icon component
* @type {boolean}
Expand Down
1 change: 0 additions & 1 deletion src/js/imageEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,6 @@ class ImageEditor {
this.ui ? this.ui.getEditorArea() : wrapper, {
cssMaxWidth: options.cssMaxWidth,
cssMaxHeight: options.cssMaxHeight,
useItext: !!this.ui,
useDragAddIcon: !!this.ui
}
);
Expand Down
97 changes: 0 additions & 97 deletions test/text.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -122,59 +122,6 @@ describe('Text', () => {
});
});

describe('_createTextarea()', () => {
let $textarea;

beforeEach(() => {
text._createTextarea();

$textarea = $(text.getCanvasElement().parentNode).find('textarea');
});

afterEach(() => {
text._removeTextarea();
});

it('should attach the created "textarea" element on canvas container.', () => {
expect($textarea.length).toEqual(1);
});

it('should have class name.', () => {
const expected = 'tui-image-eidtor-textarea';

expect($textarea.attr('class')).toEqual(expected);
});

it('should add inline style on "textarea" element.', () => {
expect($textarea.attr('style')).not.toEqual(null);
});
});

it('_removeTextarea() should remove "textarea" element on canvas container.', () => {
text._createTextarea();
text._removeTextarea();

const $textarea = $(text.getCanvasElement().parentNode).find('textarea');

expect($textarea.length).toEqual(0);
});

it('_onBlur() should hide the "textarea" element.', () => {
const obj = new fabric.Text('test');

text._createTextarea();

const $textarea = $(text.getCanvasElement().parentNode).find('textarea');

text._editingObj = obj;

canvas.add(obj);

text._onBlur();

expect($textarea.css('display')).toEqual('none');
});

it('_onFabricScaling() should change size of selected text object.', () => {
const obj = new fabric.Text('test');
const mock = {
Expand All @@ -192,48 +139,4 @@ describe('Text', () => {

expect(obj.fontSize).toEqual(originSize * scale);
});

describe('_changeToEditingMode()', () => {
let textarea;
const ratio = 10;
const expected = {
fontSize: 12,
fontFamily: 'Comic Sans',
fontStyle: 'italic',
fontWeight: '700',
textAlign: 'right',
lineHeight: '3'
};
const obj = new fabric.Text('test', expected);

beforeEach(() => {
text._createTextarea();

textarea = text._textarea;

canvas.add(obj);

spyOn(text, 'getCanvasRatio').and.returnValue(ratio);

text._changeToEditingMode(obj);
});

afterEach(() => {
text._removeTextarea();
});

it('should change selected text object into textarea.', () => {
expect(textarea.style.display).not.toEqual('none');
});

it('should set style of textarea by selected text object.', () => {
const textareaStyles = textarea.style;

expect(textareaStyles['font-size']).toEqual(`${expected.fontSize / ratio}px`);
expect(textareaStyles['font-family'].replace(/'|"|\\/g, '')).toEqual(expected.fontFamily);
expect(textareaStyles['font-weight']).toEqual(expected.fontWeight);
expect(textareaStyles['font-align']).toEqual(expected.fontAlign);
expect(textareaStyles['line-height']).toEqual(obj.lineHeight + 0.1);
});
});
});

0 comments on commit e20ae82

Please sign in to comment.