d709fc27a759e7dda114849cb97c7aed.json 42 KB
{"ast":null,"code":"/**\r\n * @author NHN Ent. FE Development Team <dl_javascript@nhn.com>\r\n * @fileoverview Text module\r\n */\nimport fabric from 'fabric';\nimport snippet from 'tui-code-snippet';\nimport Component from '../interface/component';\nimport { eventNames as events, componentNames, fObjectOptions } from '../consts';\nimport { Promise } from '../util';\nconst defaultStyles = {\n  fill: '#000000',\n  left: 0,\n  top: 0\n};\nconst resetStyles = {\n  fill: '#000000',\n  fontStyle: 'normal',\n  fontWeight: 'normal',\n  textAlign: 'left',\n  underline: false\n};\nconst DBCLICK_TIME = 500;\n/**\r\n * Text\r\n * @class Text\r\n * @param {Graphics} graphics - Graphics instance\r\n * @extends {Component}\r\n * @ignore\r\n */\n\nclass Text extends Component {\n  constructor(graphics) {\n    super(componentNames.TEXT, graphics);\n    /**\r\n     * Default text style\r\n     * @type {Object}\r\n     */\n\n    this._defaultStyles = defaultStyles;\n    /**\r\n     * Selected state\r\n     * @type {boolean}\r\n     */\n\n    this._isSelected = false;\n    /**\r\n     * Selected text object\r\n     * @type {Object}\r\n     */\n\n    this._selectedObj = {};\n    /**\r\n     * Editing text object\r\n     * @type {Object}\r\n     */\n\n    this._editingObj = {};\n    /**\r\n     * Listeners for fabric event\r\n     * @type {Object}\r\n     */\n\n    this._listeners = {\n      mousedown: this._onFabricMouseDown.bind(this),\n      select: this._onFabricSelect.bind(this),\n      selectClear: this._onFabricSelectClear.bind(this),\n      scaling: this._onFabricScaling.bind(this)\n    };\n    /**\r\n     * Textarea element for editing\r\n     * @type {HTMLElement}\r\n     */\n\n    this._textarea = null;\n    /**\r\n     * Ratio of current canvas\r\n     * @type {number}\r\n     */\n\n    this._ratio = 1;\n    /**\r\n     * Last click time\r\n     * @type {Date}\r\n     */\n\n    this._lastClickTime = new Date().getTime();\n    /**\r\n     * Text object infos before editing\r\n     * @type {Object}\r\n     */\n\n    this._editingObjInfos = {};\n    /**\r\n     * Previous state of editing\r\n     * @type {boolean}\r\n     */\n\n    this.isPrevEditing = false;\n  }\n  /**\r\n   * Start input text mode\r\n   */\n\n\n  start() {\n    const canvas = this.getCanvas();\n    canvas.selection = false;\n    canvas.defaultCursor = 'text';\n    canvas.on({\n      'mouse:down': this._listeners.mousedown,\n      'selection:created': this._listeners.select,\n      'selection:updated': this._listeners.select,\n      'before:selection:cleared': this._listeners.selectClear,\n      'object:scaling': this._listeners.scaling,\n      'text:editing': this._listeners.modify\n    });\n    canvas.forEachObject(obj => {\n      if (obj.type === 'i-text') {\n        this.adjustOriginPosition(obj, 'start');\n      }\n    });\n    this.setCanvasRatio();\n  }\n  /**\r\n   * End input text mode\r\n   */\n\n\n  end() {\n    const canvas = this.getCanvas();\n    canvas.selection = true;\n    canvas.defaultCursor = 'default';\n    canvas.forEachObject(obj => {\n      if (obj.type === 'i-text') {\n        if (obj.text === '') {\n          canvas.remove(obj);\n        } else {\n          this.adjustOriginPosition(obj, 'end');\n        }\n      }\n    });\n    canvas.off({\n      'mouse:down': this._listeners.mousedown,\n      'object:selected': this._listeners.select,\n      'before:selection:cleared': this._listeners.selectClear,\n      'object:scaling': this._listeners.scaling,\n      'text:editing': this._listeners.modify\n    });\n  }\n  /**\r\n   * Adjust the origin position\r\n   * @param {fabric.Object} text - text object\r\n   * @param {string} editStatus - 'start' or 'end'\r\n   */\n\n\n  adjustOriginPosition(text, editStatus) {\n    let [originX, originY] = ['center', 'center'];\n\n    if (editStatus === 'start') {\n      [originX, originY] = ['left', 'top'];\n    }\n\n    const {\n      x: left,\n      y: top\n    } = text.getPointByOrigin(originX, originY);\n    text.set({\n      left,\n      top,\n      originX,\n      originY\n    });\n    text.setCoords();\n  }\n  /**\r\n   * Add new text on canvas image\r\n   * @param {string} text - Initial input text\r\n   * @param {Object} options - Options for generating text\r\n   *     @param {Object} [options.styles] Initial styles\r\n   *         @param {string} [options.styles.fill] Color\r\n   *         @param {string} [options.styles.fontFamily] Font type for text\r\n   *         @param {number} [options.styles.fontSize] Size\r\n   *         @param {string} [options.styles.fontStyle] Type of inclination (normal / italic)\r\n   *         @param {string} [options.styles.fontWeight] Type of thicker or thinner looking (normal / bold)\r\n   *         @param {string} [options.styles.textAlign] Type of text align (left / center / right)\r\n   *         @param {string} [options.styles.textDecoration] Type of line (underline / line-through / overline)\r\n   *     @param {{x: number, y: number}} [options.position] - Initial position\r\n   * @returns {Promise}\r\n   */\n\n\n  add(text, options) {\n    return new Promise(resolve => {\n      const canvas = this.getCanvas();\n      let newText = null;\n      let selectionStyle = fObjectOptions.SELECTION_STYLE;\n      let styles = this._defaultStyles;\n\n      this._setInitPos(options.position);\n\n      if (options.styles) {\n        styles = snippet.extend(styles, options.styles);\n      }\n\n      if (!snippet.isExisty(options.autofocus)) {\n        options.autofocus = true;\n      }\n\n      newText = new fabric.IText(text, styles);\n      selectionStyle = snippet.extend({}, selectionStyle, {\n        originX: 'left',\n        originY: 'top'\n      });\n      newText.set(selectionStyle);\n      newText.on({\n        mouseup: this._onFabricMouseUp.bind(this)\n      });\n      canvas.add(newText);\n\n      if (options.autofocus) {\n        newText.enterEditing();\n        newText.selectAll();\n      }\n\n      if (!canvas.getActiveObject()) {\n        canvas.setActiveObject(newText);\n      }\n\n      this.isPrevEditing = true;\n      resolve(this.graphics.createObjectProperties(newText));\n    });\n  }\n  /**\r\n   * Change text of activate object on canvas image\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @param {string} text - Changed text\r\n   * @returns {Promise}\r\n   */\n\n\n  change(activeObj, text) {\n    return new Promise(resolve => {\n      activeObj.set('text', text);\n      this.getCanvas().renderAll();\n      resolve();\n    });\n  }\n  /**\r\n   * Set style\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @param {Object} styleObj - Initial styles\r\n   *     @param {string} [styleObj.fill] Color\r\n   *     @param {string} [styleObj.fontFamily] Font type for text\r\n   *     @param {number} [styleObj.fontSize] Size\r\n   *     @param {string} [styleObj.fontStyle] Type of inclination (normal / italic)\r\n   *     @param {string} [styleObj.fontWeight] Type of thicker or thinner looking (normal / bold)\r\n   *     @param {string} [styleObj.textAlign] Type of text align (left / center / right)\r\n   *     @param {string} [styleObj.textDecoration] Type of line (underline / line-through / overline)\r\n   * @returns {Promise}\r\n   */\n\n\n  setStyle(activeObj, styleObj) {\n    return new Promise(resolve => {\n      snippet.forEach(styleObj, (val, key) => {\n        if (activeObj[key] === val && key !== 'fontSize') {\n          styleObj[key] = resetStyles[key] || '';\n        }\n      }, this);\n\n      if ('textDecoration' in styleObj) {\n        snippet.extend(styleObj, this._getTextDecorationAdaptObject(styleObj.textDecoration));\n      }\n\n      activeObj.set(styleObj);\n      this.getCanvas().renderAll();\n      resolve();\n    });\n  }\n  /**\r\n   * Get the text\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @returns {String} text\r\n   */\n\n\n  getText(activeObj) {\n    return activeObj.text;\n  }\n  /**\r\n   * Set infos of the current selected object\r\n   * @param {fabric.Text} obj - Current selected text object\r\n   * @param {boolean} state - State of selecting\r\n   */\n\n\n  setSelectedInfo(obj, state) {\n    this._selectedObj = obj;\n    this._isSelected = state;\n  }\n  /**\r\n   * Whether object is selected or not\r\n   * @returns {boolean} State of selecting\r\n   */\n\n\n  isSelected() {\n    return this._isSelected;\n  }\n  /**\r\n   * Get current selected text object\r\n   * @returns {fabric.Text} Current selected text object\r\n   */\n\n\n  getSelectedObj() {\n    return this._selectedObj;\n  }\n  /**\r\n   * Set ratio value of canvas\r\n   */\n\n\n  setCanvasRatio() {\n    const canvasElement = this.getCanvasElement();\n    const cssWidth = parseInt(canvasElement.style.maxWidth, 10);\n    const originWidth = canvasElement.width;\n    const ratio = originWidth / cssWidth;\n    this._ratio = ratio;\n  }\n  /**\r\n   * Get ratio value of canvas\r\n   * @returns {number} Ratio value\r\n   */\n\n\n  getCanvasRatio() {\n    return this._ratio;\n  }\n  /**\r\n   * Get text decoration adapt object\r\n   * @param {string} textDecoration - text decoration option string\r\n   * @returns {object} adapt object for override\r\n   */\n\n\n  _getTextDecorationAdaptObject(textDecoration) {\n    return {\n      underline: textDecoration === 'underline',\n      linethrough: textDecoration === 'line-through',\n      overline: textDecoration === 'overline'\n    };\n  }\n  /**\r\n   * Set initial position on canvas image\r\n   * @param {{x: number, y: number}} [position] - Selected position\r\n   * @private\r\n   */\n\n\n  _setInitPos(position) {\n    position = position || this.getCanvasImage().getCenterPoint();\n    this._defaultStyles.left = position.x;\n    this._defaultStyles.top = position.y;\n  }\n  /**\r\n   * Input event handler\r\n   * @private\r\n   */\n\n\n  _onInput() {\n    const ratio = this.getCanvasRatio();\n    const obj = this._editingObj;\n    const textareaStyle = this._textarea.style;\n    textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;\n    textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;\n  }\n  /**\r\n   * Keydown event handler\r\n   * @private\r\n   */\n\n\n  _onKeyDown() {\n    const ratio = this.getCanvasRatio();\n    const obj = this._editingObj;\n    const textareaStyle = this._textarea.style;\n    setTimeout(() => {\n      obj.text(this._textarea.value);\n      textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;\n      textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;\n    }, 0);\n  }\n  /**\r\n   * Blur event handler\r\n   * @private\r\n   */\n\n\n  _onBlur() {\n    const ratio = this.getCanvasRatio();\n    const editingObj = this._editingObj;\n    const editingObjInfos = this._editingObjInfos;\n    const textContent = this._textarea.value;\n    let transWidth = editingObj.width / ratio - editingObjInfos.width / ratio;\n    let transHeight = editingObj.height / ratio - editingObjInfos.height / ratio;\n\n    if (ratio === 1) {\n      transWidth /= 2;\n      transHeight /= 2;\n    }\n\n    this._textarea.style.display = 'none';\n    editingObj.set({\n      left: editingObjInfos.left + transWidth,\n      top: editingObjInfos.top + transHeight\n    });\n\n    if (textContent.length) {\n      this.getCanvas().add(editingObj);\n      const params = {\n        id: snippet.stamp(editingObj),\n        type: editingObj.type,\n        text: textContent\n      };\n      this.fire(events.TEXT_CHANGED, params);\n    }\n  }\n  /**\r\n   * Scroll event handler\r\n   * @private\r\n   */\n\n\n  _onScroll() {\n    this._textarea.scrollLeft = 0;\n    this._textarea.scrollTop = 0;\n  }\n  /**\r\n   * Fabric scaling event handler\r\n   * @param {fabric.Event} fEvent - Current scaling event on selected object\r\n   * @private\r\n   */\n\n\n  _onFabricScaling(fEvent) {\n    const obj = fEvent.target;\n    const scalingSize = obj.fontSize * obj.scaleY;\n    obj.fontSize = scalingSize;\n    obj.scaleX = 1;\n    obj.scaleY = 1;\n  }\n  /**\r\n   * onSelectClear handler in fabric canvas\r\n   * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event\r\n   * @private\r\n   */\n\n\n  _onFabricSelectClear(fEvent) {\n    const obj = this.getSelectedObj();\n    this.isPrevEditing = true;\n    this.setSelectedInfo(fEvent.target, false);\n\n    if (obj) {\n      // obj is empty object at initial time, will be set fabric object\n      if (obj.text === '') {\n        this.getCanvas().remove(obj);\n      }\n    }\n  }\n  /**\r\n   * onSelect handler in fabric canvas\r\n   * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event\r\n   * @private\r\n   */\n\n\n  _onFabricSelect(fEvent) {\n    this.isPrevEditing = true;\n    this.setSelectedInfo(fEvent.target, true);\n  }\n  /**\r\n   * Fabric 'mousedown' event handler\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\n\n\n  _onFabricMouseDown(fEvent) {\n    const obj = fEvent.target;\n\n    if (obj && !obj.isType('text')) {\n      return;\n    }\n\n    if (this.isPrevEditing) {\n      this.isPrevEditing = false;\n      return;\n    }\n\n    this._fireAddText(fEvent);\n  }\n  /**\r\n   * Fire 'addText' event if object is not selected.\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\n\n\n  _fireAddText(fEvent) {\n    const obj = fEvent.target;\n    const e = fEvent.e || {};\n    const originPointer = this.getCanvas().getPointer(e);\n\n    if (!obj) {\n      this.fire(events.ADD_TEXT, {\n        originPosition: {\n          x: originPointer.x,\n          y: originPointer.y\n        },\n        clientPosition: {\n          x: e.clientX || 0,\n          y: e.clientY || 0\n        }\n      });\n    }\n  }\n  /**\r\n   * Fabric mouseup event handler\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\n\n\n  _onFabricMouseUp(fEvent) {\n    const {\n      target\n    } = fEvent;\n    const newClickTime = new Date().getTime();\n\n    if (this._isDoubleClick(newClickTime) && !target.isEditing) {\n      target.enterEditing();\n    }\n\n    if (target.isEditing) {\n      this.fire(events.TEXT_EDITING); // fire editing text event\n    }\n\n    this._lastClickTime = newClickTime;\n  }\n  /**\r\n   * Get state of firing double click event\r\n   * @param {Date} newClickTime - Current clicked time\r\n   * @returns {boolean} Whether double clicked or not\r\n   * @private\r\n   */\n\n\n  _isDoubleClick(newClickTime) {\n    return newClickTime - this._lastClickTime < DBCLICK_TIME;\n  }\n\n}\n\nexport default Text;","map":{"version":3,"sources":["C:/Users/kkwan_000/Desktop/git/2017110269/minsung/src/js/component/text.js"],"names":["fabric","snippet","Component","eventNames","events","componentNames","fObjectOptions","Promise","defaultStyles","fill","left","top","resetStyles","fontStyle","fontWeight","textAlign","underline","DBCLICK_TIME","Text","constructor","graphics","TEXT","_defaultStyles","_isSelected","_selectedObj","_editingObj","_listeners","mousedown","_onFabricMouseDown","bind","select","_onFabricSelect","selectClear","_onFabricSelectClear","scaling","_onFabricScaling","_textarea","_ratio","_lastClickTime","Date","getTime","_editingObjInfos","isPrevEditing","start","canvas","getCanvas","selection","defaultCursor","on","modify","forEachObject","obj","type","adjustOriginPosition","setCanvasRatio","end","text","remove","off","editStatus","originX","originY","x","y","getPointByOrigin","set","setCoords","add","options","resolve","newText","selectionStyle","SELECTION_STYLE","styles","_setInitPos","position","extend","isExisty","autofocus","IText","mouseup","_onFabricMouseUp","enterEditing","selectAll","getActiveObject","setActiveObject","createObjectProperties","change","activeObj","renderAll","setStyle","styleObj","forEach","val","key","_getTextDecorationAdaptObject","textDecoration","getText","setSelectedInfo","state","isSelected","getSelectedObj","canvasElement","getCanvasElement","cssWidth","parseInt","style","maxWidth","originWidth","width","ratio","getCanvasRatio","linethrough","overline","getCanvasImage","getCenterPoint","_onInput","textareaStyle","Math","ceil","height","_onKeyDown","setTimeout","value","_onBlur","editingObj","editingObjInfos","textContent","transWidth","transHeight","display","length","params","id","stamp","fire","TEXT_CHANGED","_onScroll","scrollLeft","scrollTop","fEvent","target","scalingSize","fontSize","scaleY","scaleX","isType","_fireAddText","e","originPointer","getPointer","ADD_TEXT","originPosition","clientPosition","clientX","clientY","newClickTime","_isDoubleClick","isEditing","TEXT_EDITING"],"mappings":"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","sourcesContent":["/**\r\n * @author NHN Ent. FE Development Team <dl_javascript@nhn.com>\r\n * @fileoverview Text module\r\n */\r\nimport fabric from 'fabric';\r\nimport snippet from 'tui-code-snippet';\r\nimport Component from '../interface/component';\r\nimport { eventNames as events, componentNames, fObjectOptions } from '../consts';\r\nimport { Promise } from '../util';\r\n\r\nconst defaultStyles = {\r\n  fill: '#000000',\r\n  left: 0,\r\n  top: 0,\r\n};\r\nconst resetStyles = {\r\n  fill: '#000000',\r\n  fontStyle: 'normal',\r\n  fontWeight: 'normal',\r\n  textAlign: 'left',\r\n  underline: false,\r\n};\r\n\r\nconst DBCLICK_TIME = 500;\r\n\r\n/**\r\n * Text\r\n * @class Text\r\n * @param {Graphics} graphics - Graphics instance\r\n * @extends {Component}\r\n * @ignore\r\n */\r\nclass Text extends Component {\r\n  constructor(graphics) {\r\n    super(componentNames.TEXT, graphics);\r\n\r\n    /**\r\n     * Default text style\r\n     * @type {Object}\r\n     */\r\n    this._defaultStyles = defaultStyles;\r\n\r\n    /**\r\n     * Selected state\r\n     * @type {boolean}\r\n     */\r\n    this._isSelected = false;\r\n\r\n    /**\r\n     * Selected text object\r\n     * @type {Object}\r\n     */\r\n    this._selectedObj = {};\r\n\r\n    /**\r\n     * Editing text object\r\n     * @type {Object}\r\n     */\r\n    this._editingObj = {};\r\n\r\n    /**\r\n     * Listeners for fabric event\r\n     * @type {Object}\r\n     */\r\n    this._listeners = {\r\n      mousedown: this._onFabricMouseDown.bind(this),\r\n      select: this._onFabricSelect.bind(this),\r\n      selectClear: this._onFabricSelectClear.bind(this),\r\n      scaling: this._onFabricScaling.bind(this),\r\n    };\r\n\r\n    /**\r\n     * Textarea element for editing\r\n     * @type {HTMLElement}\r\n     */\r\n    this._textarea = null;\r\n\r\n    /**\r\n     * Ratio of current canvas\r\n     * @type {number}\r\n     */\r\n    this._ratio = 1;\r\n\r\n    /**\r\n     * Last click time\r\n     * @type {Date}\r\n     */\r\n    this._lastClickTime = new Date().getTime();\r\n\r\n    /**\r\n     * Text object infos before editing\r\n     * @type {Object}\r\n     */\r\n    this._editingObjInfos = {};\r\n\r\n    /**\r\n     * Previous state of editing\r\n     * @type {boolean}\r\n     */\r\n    this.isPrevEditing = false;\r\n  }\r\n\r\n  /**\r\n   * Start input text mode\r\n   */\r\n  start() {\r\n    const canvas = this.getCanvas();\r\n\r\n    canvas.selection = false;\r\n    canvas.defaultCursor = 'text';\r\n    canvas.on({\r\n      'mouse:down': this._listeners.mousedown,\r\n      'selection:created': this._listeners.select,\r\n      'selection:updated': this._listeners.select,\r\n      'before:selection:cleared': this._listeners.selectClear,\r\n      'object:scaling': this._listeners.scaling,\r\n      'text:editing': this._listeners.modify,\r\n    });\r\n\r\n    canvas.forEachObject((obj) => {\r\n      if (obj.type === 'i-text') {\r\n        this.adjustOriginPosition(obj, 'start');\r\n      }\r\n    });\r\n\r\n    this.setCanvasRatio();\r\n  }\r\n\r\n  /**\r\n   * End input text mode\r\n   */\r\n  end() {\r\n    const canvas = this.getCanvas();\r\n\r\n    canvas.selection = true;\r\n    canvas.defaultCursor = 'default';\r\n\r\n    canvas.forEachObject((obj) => {\r\n      if (obj.type === 'i-text') {\r\n        if (obj.text === '') {\r\n          canvas.remove(obj);\r\n        } else {\r\n          this.adjustOriginPosition(obj, 'end');\r\n        }\r\n      }\r\n    });\r\n\r\n    canvas.off({\r\n      'mouse:down': this._listeners.mousedown,\r\n      'object:selected': this._listeners.select,\r\n      'before:selection:cleared': this._listeners.selectClear,\r\n      'object:scaling': this._listeners.scaling,\r\n      'text:editing': this._listeners.modify,\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Adjust the origin position\r\n   * @param {fabric.Object} text - text object\r\n   * @param {string} editStatus - 'start' or 'end'\r\n   */\r\n  adjustOriginPosition(text, editStatus) {\r\n    let [originX, originY] = ['center', 'center'];\r\n    if (editStatus === 'start') {\r\n      [originX, originY] = ['left', 'top'];\r\n    }\r\n\r\n    const { x: left, y: top } = text.getPointByOrigin(originX, originY);\r\n    text.set({\r\n      left,\r\n      top,\r\n      originX,\r\n      originY,\r\n    });\r\n    text.setCoords();\r\n  }\r\n\r\n  /**\r\n   * Add new text on canvas image\r\n   * @param {string} text - Initial input text\r\n   * @param {Object} options - Options for generating text\r\n   *     @param {Object} [options.styles] Initial styles\r\n   *         @param {string} [options.styles.fill] Color\r\n   *         @param {string} [options.styles.fontFamily] Font type for text\r\n   *         @param {number} [options.styles.fontSize] Size\r\n   *         @param {string} [options.styles.fontStyle] Type of inclination (normal / italic)\r\n   *         @param {string} [options.styles.fontWeight] Type of thicker or thinner looking (normal / bold)\r\n   *         @param {string} [options.styles.textAlign] Type of text align (left / center / right)\r\n   *         @param {string} [options.styles.textDecoration] Type of line (underline / line-through / overline)\r\n   *     @param {{x: number, y: number}} [options.position] - Initial position\r\n   * @returns {Promise}\r\n   */\r\n  add(text, options) {\r\n    return new Promise((resolve) => {\r\n      const canvas = this.getCanvas();\r\n      let newText = null;\r\n      let selectionStyle = fObjectOptions.SELECTION_STYLE;\r\n      let styles = this._defaultStyles;\r\n\r\n      this._setInitPos(options.position);\r\n\r\n      if (options.styles) {\r\n        styles = snippet.extend(styles, options.styles);\r\n      }\r\n\r\n      if (!snippet.isExisty(options.autofocus)) {\r\n        options.autofocus = true;\r\n      }\r\n\r\n      newText = new fabric.IText(text, styles);\r\n      selectionStyle = snippet.extend({}, selectionStyle, {\r\n        originX: 'left',\r\n        originY: 'top',\r\n      });\r\n\r\n      newText.set(selectionStyle);\r\n      newText.on({\r\n        mouseup: this._onFabricMouseUp.bind(this),\r\n      });\r\n\r\n      canvas.add(newText);\r\n\r\n      if (options.autofocus) {\r\n        newText.enterEditing();\r\n        newText.selectAll();\r\n      }\r\n\r\n      if (!canvas.getActiveObject()) {\r\n        canvas.setActiveObject(newText);\r\n      }\r\n\r\n      this.isPrevEditing = true;\r\n      resolve(this.graphics.createObjectProperties(newText));\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Change text of activate object on canvas image\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @param {string} text - Changed text\r\n   * @returns {Promise}\r\n   */\r\n  change(activeObj, text) {\r\n    return new Promise((resolve) => {\r\n      activeObj.set('text', text);\r\n\r\n      this.getCanvas().renderAll();\r\n      resolve();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Set style\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @param {Object} styleObj - Initial styles\r\n   *     @param {string} [styleObj.fill] Color\r\n   *     @param {string} [styleObj.fontFamily] Font type for text\r\n   *     @param {number} [styleObj.fontSize] Size\r\n   *     @param {string} [styleObj.fontStyle] Type of inclination (normal / italic)\r\n   *     @param {string} [styleObj.fontWeight] Type of thicker or thinner looking (normal / bold)\r\n   *     @param {string} [styleObj.textAlign] Type of text align (left / center / right)\r\n   *     @param {string} [styleObj.textDecoration] Type of line (underline / line-through / overline)\r\n   * @returns {Promise}\r\n   */\r\n  setStyle(activeObj, styleObj) {\r\n    return new Promise((resolve) => {\r\n      snippet.forEach(\r\n        styleObj,\r\n        (val, key) => {\r\n          if (activeObj[key] === val && key !== 'fontSize') {\r\n            styleObj[key] = resetStyles[key] || '';\r\n          }\r\n        },\r\n        this\r\n      );\r\n\r\n      if ('textDecoration' in styleObj) {\r\n        snippet.extend(styleObj, this._getTextDecorationAdaptObject(styleObj.textDecoration));\r\n      }\r\n\r\n      activeObj.set(styleObj);\r\n\r\n      this.getCanvas().renderAll();\r\n      resolve();\r\n    });\r\n  }\r\n\r\n  /**\r\n   * Get the text\r\n   * @param {Object} activeObj - Current selected text object\r\n   * @returns {String} text\r\n   */\r\n  getText(activeObj) {\r\n    return activeObj.text;\r\n  }\r\n\r\n  /**\r\n   * Set infos of the current selected object\r\n   * @param {fabric.Text} obj - Current selected text object\r\n   * @param {boolean} state - State of selecting\r\n   */\r\n  setSelectedInfo(obj, state) {\r\n    this._selectedObj = obj;\r\n    this._isSelected = state;\r\n  }\r\n\r\n  /**\r\n   * Whether object is selected or not\r\n   * @returns {boolean} State of selecting\r\n   */\r\n  isSelected() {\r\n    return this._isSelected;\r\n  }\r\n\r\n  /**\r\n   * Get current selected text object\r\n   * @returns {fabric.Text} Current selected text object\r\n   */\r\n  getSelectedObj() {\r\n    return this._selectedObj;\r\n  }\r\n\r\n  /**\r\n   * Set ratio value of canvas\r\n   */\r\n  setCanvasRatio() {\r\n    const canvasElement = this.getCanvasElement();\r\n    const cssWidth = parseInt(canvasElement.style.maxWidth, 10);\r\n    const originWidth = canvasElement.width;\r\n    const ratio = originWidth / cssWidth;\r\n\r\n    this._ratio = ratio;\r\n  }\r\n\r\n  /**\r\n   * Get ratio value of canvas\r\n   * @returns {number} Ratio value\r\n   */\r\n  getCanvasRatio() {\r\n    return this._ratio;\r\n  }\r\n\r\n  /**\r\n   * Get text decoration adapt object\r\n   * @param {string} textDecoration - text decoration option string\r\n   * @returns {object} adapt object for override\r\n   */\r\n  _getTextDecorationAdaptObject(textDecoration) {\r\n    return {\r\n      underline: textDecoration === 'underline',\r\n      linethrough: textDecoration === 'line-through',\r\n      overline: textDecoration === 'overline',\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Set initial position on canvas image\r\n   * @param {{x: number, y: number}} [position] - Selected position\r\n   * @private\r\n   */\r\n  _setInitPos(position) {\r\n    position = position || this.getCanvasImage().getCenterPoint();\r\n\r\n    this._defaultStyles.left = position.x;\r\n    this._defaultStyles.top = position.y;\r\n  }\r\n\r\n  /**\r\n   * Input event handler\r\n   * @private\r\n   */\r\n  _onInput() {\r\n    const ratio = this.getCanvasRatio();\r\n    const obj = this._editingObj;\r\n    const textareaStyle = this._textarea.style;\r\n\r\n    textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;\r\n    textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;\r\n  }\r\n\r\n  /**\r\n   * Keydown event handler\r\n   * @private\r\n   */\r\n  _onKeyDown() {\r\n    const ratio = this.getCanvasRatio();\r\n    const obj = this._editingObj;\r\n    const textareaStyle = this._textarea.style;\r\n\r\n    setTimeout(() => {\r\n      obj.text(this._textarea.value);\r\n\r\n      textareaStyle.width = `${Math.ceil(obj.width / ratio)}px`;\r\n      textareaStyle.height = `${Math.ceil(obj.height / ratio)}px`;\r\n    }, 0);\r\n  }\r\n\r\n  /**\r\n   * Blur event handler\r\n   * @private\r\n   */\r\n  _onBlur() {\r\n    const ratio = this.getCanvasRatio();\r\n    const editingObj = this._editingObj;\r\n    const editingObjInfos = this._editingObjInfos;\r\n    const textContent = this._textarea.value;\r\n    let transWidth = editingObj.width / ratio - editingObjInfos.width / ratio;\r\n    let transHeight = editingObj.height / ratio - editingObjInfos.height / ratio;\r\n\r\n    if (ratio === 1) {\r\n      transWidth /= 2;\r\n      transHeight /= 2;\r\n    }\r\n\r\n    this._textarea.style.display = 'none';\r\n\r\n    editingObj.set({\r\n      left: editingObjInfos.left + transWidth,\r\n      top: editingObjInfos.top + transHeight,\r\n    });\r\n\r\n    if (textContent.length) {\r\n      this.getCanvas().add(editingObj);\r\n\r\n      const params = {\r\n        id: snippet.stamp(editingObj),\r\n        type: editingObj.type,\r\n        text: textContent,\r\n      };\r\n\r\n      this.fire(events.TEXT_CHANGED, params);\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Scroll event handler\r\n   * @private\r\n   */\r\n  _onScroll() {\r\n    this._textarea.scrollLeft = 0;\r\n    this._textarea.scrollTop = 0;\r\n  }\r\n\r\n  /**\r\n   * Fabric scaling event handler\r\n   * @param {fabric.Event} fEvent - Current scaling event on selected object\r\n   * @private\r\n   */\r\n  _onFabricScaling(fEvent) {\r\n    const obj = fEvent.target;\r\n    const scalingSize = obj.fontSize * obj.scaleY;\r\n\r\n    obj.fontSize = scalingSize;\r\n    obj.scaleX = 1;\r\n    obj.scaleY = 1;\r\n  }\r\n\r\n  /**\r\n   * onSelectClear handler in fabric canvas\r\n   * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event\r\n   * @private\r\n   */\r\n  _onFabricSelectClear(fEvent) {\r\n    const obj = this.getSelectedObj();\r\n\r\n    this.isPrevEditing = true;\r\n\r\n    this.setSelectedInfo(fEvent.target, false);\r\n\r\n    if (obj) {\r\n      // obj is empty object at initial time, will be set fabric object\r\n      if (obj.text === '') {\r\n        this.getCanvas().remove(obj);\r\n      }\r\n    }\r\n  }\r\n\r\n  /**\r\n   * onSelect handler in fabric canvas\r\n   * @param {{target: fabric.Object, e: MouseEvent}} fEvent - Fabric event\r\n   * @private\r\n   */\r\n  _onFabricSelect(fEvent) {\r\n    this.isPrevEditing = true;\r\n\r\n    this.setSelectedInfo(fEvent.target, true);\r\n  }\r\n\r\n  /**\r\n   * Fabric 'mousedown' event handler\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\r\n  _onFabricMouseDown(fEvent) {\r\n    const obj = fEvent.target;\r\n\r\n    if (obj && !obj.isType('text')) {\r\n      return;\r\n    }\r\n\r\n    if (this.isPrevEditing) {\r\n      this.isPrevEditing = false;\r\n\r\n      return;\r\n    }\r\n\r\n    this._fireAddText(fEvent);\r\n  }\r\n\r\n  /**\r\n   * Fire 'addText' event if object is not selected.\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\r\n  _fireAddText(fEvent) {\r\n    const obj = fEvent.target;\r\n    const e = fEvent.e || {};\r\n    const originPointer = this.getCanvas().getPointer(e);\r\n\r\n    if (!obj) {\r\n      this.fire(events.ADD_TEXT, {\r\n        originPosition: {\r\n          x: originPointer.x,\r\n          y: originPointer.y,\r\n        },\r\n        clientPosition: {\r\n          x: e.clientX || 0,\r\n          y: e.clientY || 0,\r\n        },\r\n      });\r\n    }\r\n  }\r\n\r\n  /**\r\n   * Fabric mouseup event handler\r\n   * @param {fabric.Event} fEvent - Current mousedown event on selected object\r\n   * @private\r\n   */\r\n  _onFabricMouseUp(fEvent) {\r\n    const { target } = fEvent;\r\n    const newClickTime = new Date().getTime();\r\n\r\n    if (this._isDoubleClick(newClickTime) && !target.isEditing) {\r\n      target.enterEditing();\r\n    }\r\n\r\n    if (target.isEditing) {\r\n      this.fire(events.TEXT_EDITING); // fire editing text event\r\n    }\r\n\r\n    this._lastClickTime = newClickTime;\r\n  }\r\n\r\n  /**\r\n   * Get state of firing double click event\r\n   * @param {Date} newClickTime - Current clicked time\r\n   * @returns {boolean} Whether double clicked or not\r\n   * @private\r\n   */\r\n  _isDoubleClick(newClickTime) {\r\n    return newClickTime - this._lastClickTime < DBCLICK_TIME;\r\n  }\r\n}\r\n\r\nexport default Text;\r\n"]},"metadata":{},"sourceType":"module"}