2015-06-19 03:06:32 +00:00
|
|
|
(function(global) {
|
2015-06-16 20:54:03 +00:00
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
|
2016-12-30 21:41:16 +00:00
|
|
|
var fabric = global.fabric || (global.fabric = {});
|
2015-05-27 18:47:13 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Textbox class, based on IText, allows the user to resize the text rectangle
|
|
|
|
|
* and wraps lines automatically. Textboxes have their Y scaling locked, the
|
|
|
|
|
* user can only change width. Height is adjusted automatically based on the
|
|
|
|
|
* wrapping of lines.
|
|
|
|
|
* @class fabric.Textbox
|
|
|
|
|
* @extends fabric.IText
|
|
|
|
|
* @mixes fabric.Observable
|
|
|
|
|
* @return {fabric.Textbox} thisArg
|
|
|
|
|
* @see {@link fabric.Textbox#initialize} for constructor definition
|
|
|
|
|
*/
|
|
|
|
|
fabric.Textbox = fabric.util.createClass(fabric.IText, fabric.Observable, {
|
2016-05-08 19:22:51 +00:00
|
|
|
|
2015-05-27 18:47:13 +00:00
|
|
|
/**
|
2015-05-27 20:59:56 +00:00
|
|
|
* Type of an object
|
|
|
|
|
* @type String
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
type: 'textbox',
|
2016-05-08 19:22:51 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Minimum width of textbox, in pixels.
|
|
|
|
|
* @type Number
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
|
|
|
|
minWidth: 20,
|
2016-05-08 19:22:51 +00:00
|
|
|
|
2015-06-12 03:00:23 +00:00
|
|
|
/**
|
|
|
|
|
* Minimum calculated width of a textbox, in pixels.
|
2016-10-02 09:00:17 +00:00
|
|
|
* fixed to 2 so that an empty textbox cannot go to 0
|
|
|
|
|
* and is still selectable without text.
|
2015-06-12 03:00:23 +00:00
|
|
|
* @type Number
|
|
|
|
|
* @default
|
|
|
|
|
*/
|
2016-10-02 09:00:17 +00:00
|
|
|
dynamicMinWidth: 2,
|
2016-05-08 19:22:51 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Cached array of text wrapping.
|
|
|
|
|
* @type Array
|
|
|
|
|
*/
|
|
|
|
|
__cachedLines: null,
|
2016-05-08 19:22:51 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override standard Object class values
|
|
|
|
|
*/
|
|
|
|
|
lockScalingY: true,
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Override standard Object class values
|
|
|
|
|
*/
|
|
|
|
|
lockScalingFlip: true,
|
|
|
|
|
|
2016-11-21 20:25:46 +00:00
|
|
|
/**
|
|
|
|
|
* Override standard Object class values
|
|
|
|
|
* Textbox needs this on false
|
|
|
|
|
*/
|
|
|
|
|
noScaleCache: false,
|
|
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Constructor. Some scaling related property values are forced. Visibility
|
|
|
|
|
* of controls is also fixed; only the rotation and width controls are
|
|
|
|
|
* made available.
|
|
|
|
|
* @param {String} text Text string
|
|
|
|
|
* @param {Object} [options] Options object
|
2015-05-27 18:47:13 +00:00
|
|
|
* @return {fabric.Textbox} thisArg
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
initialize: function(text, options) {
|
2016-11-13 20:00:10 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
this.callSuper('initialize', text, options);
|
|
|
|
|
this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());
|
2016-11-13 20:00:10 +00:00
|
|
|
this.ctx = this.objectCaching ? this._cacheContext : fabric.util.createCanvasElement().getContext('2d');
|
2015-05-27 20:59:56 +00:00
|
|
|
// add width to this list of props that effect line wrapping.
|
2016-11-13 20:00:10 +00:00
|
|
|
this._dimensionAffectingProps.push('width');
|
2015-05-27 20:59:56 +00:00
|
|
|
},
|
2015-06-12 03:00:23 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Unlike superclass's version of this function, Textbox does not update
|
|
|
|
|
* its width.
|
|
|
|
|
* @private
|
|
|
|
|
* @override
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
initDimensions: function() {
|
2015-05-27 20:59:56 +00:00
|
|
|
if (this.__skipDimension) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
this.abortCursorAnimation();
|
|
|
|
|
this.clearContextTop();
|
|
|
|
|
this._clearCache();
|
2015-06-12 03:00:23 +00:00
|
|
|
// clear dynamicMinWidth as it will be different after we re-wrap line
|
|
|
|
|
this.dynamicMinWidth = 0;
|
|
|
|
|
// wrap lines
|
2017-04-22 07:15:38 +00:00
|
|
|
var newText = this._splitTextIntoLines(this.text);
|
|
|
|
|
this.textLines = newText.lines;
|
|
|
|
|
this._textLines = newText.graphemeLines;
|
|
|
|
|
this._unwrappedTextLines = newText._unwrappedLines;
|
|
|
|
|
this._text = newText.graphemeText;
|
|
|
|
|
this._styleMap = this._generateStyleMap(newText);
|
2015-06-12 03:00:23 +00:00
|
|
|
// if after wrapping, the width is smaller than dynamicMinWidth, change the width and re-wrap
|
2015-06-16 20:19:41 +00:00
|
|
|
if (this.dynamicMinWidth > this.width) {
|
2015-06-12 03:00:23 +00:00
|
|
|
this._set('width', this.dynamicMinWidth);
|
|
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
if (this.textAlign === 'justify') {
|
|
|
|
|
// once text is misured we need to make space fatter to make justified text.
|
|
|
|
|
this.enlargeSpaces();
|
|
|
|
|
}
|
2015-06-12 03:00:23 +00:00
|
|
|
// clear cache and re-calculate height
|
2017-04-22 07:15:38 +00:00
|
|
|
this.height = this.calcTextHeight();
|
2015-05-27 20:59:56 +00:00
|
|
|
},
|
2015-06-11 00:12:54 +00:00
|
|
|
|
2015-07-17 09:40:54 +00:00
|
|
|
/**
|
2015-07-20 17:56:26 +00:00
|
|
|
* Generate an object that translates the style object so that it is
|
|
|
|
|
* broken up by visual lines (new lines and automatic wrapping).
|
|
|
|
|
* The original text styles object is broken up by actual lines (new lines only),
|
|
|
|
|
* which is only sufficient for Text / IText
|
2015-07-17 09:40:54 +00:00
|
|
|
* @private
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
_generateStyleMap: function(textInfo) {
|
2015-06-12 03:00:23 +00:00
|
|
|
var realLineCount = 0,
|
2015-06-11 17:25:43 +00:00
|
|
|
realLineCharCount = 0,
|
2015-06-12 03:00:23 +00:00
|
|
|
charCount = 0,
|
|
|
|
|
map = {};
|
2015-06-11 00:12:54 +00:00
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
for (var i = 0; i < textInfo.graphemeLines.length; i++) {
|
|
|
|
|
if (textInfo.graphemeText[charCount] === '\n' && i > 0) {
|
2015-06-11 00:12:54 +00:00
|
|
|
realLineCharCount = 0;
|
|
|
|
|
charCount++;
|
|
|
|
|
realLineCount++;
|
|
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
else if (this._reSpaceAndTab.test(textInfo.graphemeText[charCount]) && i > 0) {
|
2015-06-16 20:19:41 +00:00
|
|
|
// this case deals with space's that are removed from end of lines when wrapping
|
|
|
|
|
realLineCharCount++;
|
|
|
|
|
charCount++;
|
2015-06-12 17:26:36 +00:00
|
|
|
}
|
2015-06-11 00:12:54 +00:00
|
|
|
|
2015-06-16 20:54:03 +00:00
|
|
|
map[i] = { line: realLineCount, offset: realLineCharCount };
|
2015-06-11 00:12:54 +00:00
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
charCount += textInfo.graphemeLines[i].length;
|
|
|
|
|
realLineCharCount += textInfo.graphemeLines[i].length;
|
2015-06-11 00:12:54 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return map;
|
|
|
|
|
},
|
|
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
/**
|
|
|
|
|
* Returns true if object has a style property or has it ina specified line
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @return {Boolean}
|
|
|
|
|
*/
|
|
|
|
|
styleHas: function(property, lineIndex) {
|
|
|
|
|
if (this._styleMap && !this.isWrapping) {
|
|
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
if (map) {
|
|
|
|
|
lineIndex = map.line;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return fabric.Text.prototype.styleHas.call(this, property, lineIndex);
|
|
|
|
|
},
|
|
|
|
|
|
2015-06-11 00:12:54 +00:00
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @param {Number} charIndex
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
_getStyleDeclaration: function(lineIndex, charIndex) {
|
|
|
|
|
if (this._styleMap && !this.isWrapping) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
2015-08-20 13:55:44 +00:00
|
|
|
if (!map) {
|
2017-04-22 07:15:38 +00:00
|
|
|
return null;
|
2015-08-20 13:55:44 +00:00
|
|
|
}
|
2015-06-11 00:12:54 +00:00
|
|
|
lineIndex = map.line;
|
|
|
|
|
charIndex = map.offset + charIndex;
|
|
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
return this.callSuper('_getStyleDeclaration', lineIndex, charIndex);
|
2015-06-11 00:12:54 +00:00
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @param {Number} charIndex
|
|
|
|
|
* @param {Object} style
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
_setStyleDeclaration: function(lineIndex, charIndex, style) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
lineIndex = map.line;
|
|
|
|
|
charIndex = map.offset + charIndex;
|
|
|
|
|
|
|
|
|
|
this.styles[lineIndex][charIndex] = style;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @param {Number} charIndex
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
_deleteStyleDeclaration: function(lineIndex, charIndex) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
lineIndex = map.line;
|
|
|
|
|
charIndex = map.offset + charIndex;
|
|
|
|
|
|
|
|
|
|
delete this.styles[lineIndex][charIndex];
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
_getLineStyle: function(lineIndex) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
return this.styles[map.line];
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @param {Object} style
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
_setLineStyle: function(lineIndex, style) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
this.styles[map.line] = style;
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @param {Number} lineIndex
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
_deleteLineStyle: function(lineIndex) {
|
2015-06-11 00:12:54 +00:00
|
|
|
var map = this._styleMap[lineIndex];
|
|
|
|
|
delete this.styles[map.line];
|
|
|
|
|
},
|
|
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Wraps text using the 'width' property of Textbox. First this function
|
|
|
|
|
* splits text on newlines, so we preserve newlines entered by the user.
|
|
|
|
|
* Then it wraps each line using the width of the Textbox by calling
|
|
|
|
|
* _wrapLine().
|
2017-04-22 07:15:38 +00:00
|
|
|
* @param {Array} lines The string array of text that is split into lines
|
|
|
|
|
* @param {Number} desiredWidth width you want to wrap to
|
2015-05-27 20:59:56 +00:00
|
|
|
* @returns {Array} Array of lines
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
_wrapText: function(lines, desiredWidth) {
|
|
|
|
|
var wrapped = [], i;
|
|
|
|
|
this.isWrapping = true;
|
2015-05-27 20:59:56 +00:00
|
|
|
for (i = 0; i < lines.length; i++) {
|
2017-04-22 07:15:38 +00:00
|
|
|
wrapped = wrapped.concat(this._wrapLine(lines[i], i, desiredWidth));
|
2015-05-27 20:59:56 +00:00
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
this.isWrapping = false;
|
2015-05-27 20:59:56 +00:00
|
|
|
return wrapped;
|
|
|
|
|
},
|
2015-06-03 23:39:10 +00:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Helper function to measure a string of text, given its lineIndex and charIndex offset
|
2017-04-22 07:15:38 +00:00
|
|
|
* it gets called when charBounds are not available yet.
|
2015-06-03 23:39:10 +00:00
|
|
|
* @param {CanvasRenderingContext2D} ctx
|
|
|
|
|
* @param {String} text
|
|
|
|
|
* @param {number} lineIndex
|
|
|
|
|
* @param {number} charOffset
|
|
|
|
|
* @returns {number}
|
|
|
|
|
* @private
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
_measureWord: function(word, lineIndex, charOffset) {
|
|
|
|
|
var width = 0, prevGrapheme, skipLeft = true;
|
2015-06-03 23:39:10 +00:00
|
|
|
charOffset = charOffset || 0;
|
2017-04-22 07:15:38 +00:00
|
|
|
for (var i = 0, len = word.length; i < len; i++) {
|
|
|
|
|
var box = this._getGraphemeBox(word[i], lineIndex, i + charOffset, prevGrapheme, skipLeft);
|
|
|
|
|
width += box.kernedWidth;
|
|
|
|
|
prevGrapheme = word[i];
|
2015-06-03 23:39:10 +00:00
|
|
|
}
|
|
|
|
|
return width;
|
|
|
|
|
},
|
|
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Wraps a line of text using the width of the Textbox and a context.
|
2017-04-22 07:15:38 +00:00
|
|
|
* @param {Array} line The grapheme array that represent the line
|
2015-06-11 00:12:54 +00:00
|
|
|
* @param {Number} lineIndex
|
2017-04-22 07:15:38 +00:00
|
|
|
* @param {Number} desiredWidth width you want to wrap the line to
|
2015-05-27 20:59:56 +00:00
|
|
|
* @returns {Array} Array of line(s) into which the given text is wrapped
|
|
|
|
|
* to.
|
|
|
|
|
*/
|
2017-04-22 07:15:38 +00:00
|
|
|
_wrapLine: function(_line, lineIndex, desiredWidth) {
|
2015-08-11 01:12:38 +00:00
|
|
|
var lineWidth = 0,
|
2017-04-22 07:15:38 +00:00
|
|
|
graphemeLines = [],
|
|
|
|
|
line = [],
|
|
|
|
|
// spaces in different languges?
|
|
|
|
|
words = _line.split(this._reSpaceAndTab),
|
2015-08-11 01:12:38 +00:00
|
|
|
word = '',
|
2015-06-16 20:19:41 +00:00
|
|
|
offset = 0,
|
2015-08-11 01:12:38 +00:00
|
|
|
infix = ' ',
|
2015-06-16 20:19:41 +00:00
|
|
|
wordWidth = 0,
|
2015-08-11 01:12:38 +00:00
|
|
|
infixWidth = 0,
|
2016-03-26 10:41:49 +00:00
|
|
|
largestWordWidth = 0,
|
2016-08-14 21:19:42 +00:00
|
|
|
lineJustStarted = true,
|
|
|
|
|
additionalSpace = this._getWidthOfCharSpacing();
|
2015-08-11 01:12:38 +00:00
|
|
|
for (var i = 0; i < words.length; i++) {
|
2017-04-22 07:15:38 +00:00
|
|
|
// i would avoid resplitting the graphemes
|
|
|
|
|
word = fabric.util.string.graphemeSplit(words[i]);
|
|
|
|
|
wordWidth = this._measureWord(word, lineIndex, offset);
|
2015-08-11 01:12:38 +00:00
|
|
|
offset += word.length;
|
2015-06-16 20:19:41 +00:00
|
|
|
|
2016-08-14 21:19:42 +00:00
|
|
|
lineWidth += infixWidth + wordWidth - additionalSpace;
|
2015-08-11 01:12:38 +00:00
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
if (lineWidth >= desiredWidth && !lineJustStarted) {
|
|
|
|
|
graphemeLines.push(line);
|
|
|
|
|
line = [];
|
2015-08-11 01:12:38 +00:00
|
|
|
lineWidth = wordWidth;
|
2016-03-26 10:41:49 +00:00
|
|
|
lineJustStarted = true;
|
2015-06-12 03:00:23 +00:00
|
|
|
}
|
|
|
|
|
|
2016-03-26 10:41:49 +00:00
|
|
|
if (!lineJustStarted) {
|
2017-04-22 07:15:38 +00:00
|
|
|
line.push(infix);
|
2015-05-27 20:59:56 +00:00
|
|
|
}
|
2017-04-22 07:15:38 +00:00
|
|
|
line = line.concat(word);
|
2015-08-11 01:12:38 +00:00
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
infixWidth = this._measureWord([infix], lineIndex, offset);
|
2015-08-11 01:12:38 +00:00
|
|
|
offset++;
|
2016-03-26 10:41:49 +00:00
|
|
|
lineJustStarted = false;
|
2015-06-16 20:19:41 +00:00
|
|
|
// keep track of largest word
|
|
|
|
|
if (wordWidth > largestWordWidth) {
|
|
|
|
|
largestWordWidth = wordWidth;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
i && graphemeLines.push(line);
|
2015-08-11 01:12:38 +00:00
|
|
|
|
2015-06-16 20:19:41 +00:00
|
|
|
if (largestWordWidth > this.dynamicMinWidth) {
|
2016-08-14 21:19:42 +00:00
|
|
|
this.dynamicMinWidth = largestWordWidth - additionalSpace;
|
2015-05-27 20:59:56 +00:00
|
|
|
}
|
2015-05-27 18:47:13 +00:00
|
|
|
|
2017-04-22 07:15:38 +00:00
|
|
|
return graphemeLines;
|
2015-05-27 20:59:56 +00:00
|
|
|
},
|
2017-04-22 07:15:38 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
2017-04-22 07:15:38 +00:00
|
|
|
* Gets lines of text to render in the Textbox. This function calculates
|
|
|
|
|
* text wrapping on the fly everytime it is called.
|
|
|
|
|
* @param {String} text text to split
|
|
|
|
|
* @returns {Array} Array of lines in the Textbox.
|
|
|
|
|
* @override
|
|
|
|
|
*/
|
|
|
|
|
_splitTextIntoLines: function(text) {
|
|
|
|
|
var newText = fabric.Text.prototype._splitTextIntoLines.call(this, text),
|
|
|
|
|
graphemeLines = this._wrapText(newText.lines, this.width),
|
|
|
|
|
lines = new Array(graphemeLines.length);
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < graphemeLines.length; i++) {
|
|
|
|
|
lines[i] = graphemeLines[i].join('');
|
|
|
|
|
}
|
|
|
|
|
newText.lines = lines;
|
|
|
|
|
newText.graphemeLines = graphemeLines;
|
|
|
|
|
return newText;
|
2015-05-27 20:59:56 +00:00
|
|
|
},
|
2015-05-27 18:47:13 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* When part of a group, we don't want the Textbox's scale to increase if
|
|
|
|
|
* the group's increases. That's why we reduce the scale of the Textbox by
|
|
|
|
|
* the amount that the group's increases. This is to maintain the effective
|
|
|
|
|
* scale of the Textbox at 1, so that font-size values make sense. Otherwise
|
|
|
|
|
* the same font-size value would result in different actual size depending
|
|
|
|
|
* on the value of the scale.
|
|
|
|
|
* @param {String} key
|
2016-08-20 10:05:19 +00:00
|
|
|
* @param {*} value
|
2015-05-27 20:59:56 +00:00
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
setOnGroup: function(key, value) {
|
2015-05-27 20:59:56 +00:00
|
|
|
if (key === 'scaleX') {
|
2015-05-31 22:44:44 +00:00
|
|
|
this.set('scaleX', Math.abs(1 / value));
|
2015-05-27 20:59:56 +00:00
|
|
|
this.set('width', (this.get('width') * value) /
|
|
|
|
|
(typeof this.__oldScaleX === 'undefined' ? 1 : this.__oldScaleX));
|
|
|
|
|
this.__oldScaleX = value;
|
|
|
|
|
}
|
|
|
|
|
},
|
2015-05-27 18:47:13 +00:00
|
|
|
|
2015-06-19 03:06:32 +00:00
|
|
|
getMinWidth: function() {
|
2015-06-12 03:00:23 +00:00
|
|
|
return Math.max(this.minWidth, this.dynamicMinWidth);
|
|
|
|
|
},
|
|
|
|
|
|
2015-05-27 18:47:13 +00:00
|
|
|
/**
|
2015-05-27 20:59:56 +00:00
|
|
|
* Returns object representation of an instance
|
|
|
|
|
* @method toObject
|
|
|
|
|
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output
|
|
|
|
|
* @return {Object} object representation of an instance
|
2015-05-27 18:47:13 +00:00
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
toObject: function(propertiesToInclude) {
|
2016-11-12 22:54:42 +00:00
|
|
|
return this.callSuper('toObject', ['minWidth'].concat(propertiesToInclude));
|
2015-05-27 20:59:56 +00:00
|
|
|
}
|
|
|
|
|
});
|
2016-12-30 21:41:16 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Returns fabric.Textbox instance from an object representation
|
|
|
|
|
* @static
|
|
|
|
|
* @memberOf fabric.Textbox
|
|
|
|
|
* @param {Object} object Object to create an instance from
|
2016-09-10 14:09:17 +00:00
|
|
|
* @param {Function} [callback] Callback to invoke when an fabric.Textbox instance is created
|
2016-12-30 21:41:16 +00:00
|
|
|
* @param {Boolean} [forceAsync] Force an async behaviour trying to create pattern first
|
2015-05-27 20:59:56 +00:00
|
|
|
* @return {fabric.Textbox} instance of fabric.Textbox
|
|
|
|
|
*/
|
2016-12-30 21:41:16 +00:00
|
|
|
fabric.Textbox.fromObject = function(object, callback, forceAsync) {
|
|
|
|
|
return fabric.Object._fromObject('Textbox', object, callback, forceAsync, 'text');
|
2015-05-27 20:59:56 +00:00
|
|
|
};
|
2016-12-30 21:41:16 +00:00
|
|
|
|
2015-05-27 20:59:56 +00:00
|
|
|
/**
|
|
|
|
|
* Returns the default controls visibility required for Textboxes.
|
|
|
|
|
* @returns {Object}
|
|
|
|
|
*/
|
2015-06-19 03:06:32 +00:00
|
|
|
fabric.Textbox.getTextboxControlVisibility = function() {
|
2015-05-27 20:59:56 +00:00
|
|
|
return {
|
|
|
|
|
tl: false,
|
|
|
|
|
tr: false,
|
|
|
|
|
br: false,
|
|
|
|
|
bl: false,
|
|
|
|
|
ml: true,
|
|
|
|
|
mt: false,
|
|
|
|
|
mr: true,
|
|
|
|
|
mb: false,
|
|
|
|
|
mtr: true
|
2015-05-27 18:47:13 +00:00
|
|
|
};
|
2015-05-27 20:59:56 +00:00
|
|
|
};
|
2016-05-25 13:00:38 +00:00
|
|
|
|
2015-06-16 20:54:03 +00:00
|
|
|
})(typeof exports !== 'undefined' ? exports : this);
|