Textbox implementaion from Jaffer Haider, with one minor change in textbox_key_behavior

This commit is contained in:
inssein 2015-05-27 11:44:53 -07:00
parent 697d17bd70
commit a1e578b137
8 changed files with 110 additions and 5 deletions

View file

@ -244,6 +244,11 @@ var filesToInclude = [
ifSpecifiedInclude('itext', 'src/mixins/itext_key_behavior.mixin.js'),
ifSpecifiedInclude('itext', 'src/mixins/itext.svg_export.js'),
ifSpecifiedInclude('textbox', 'src/shapes/textbox.class.js'),
ifSpecifiedInclude('textbox', 'src/mixins/textbox_behavior.mixin.js'),
ifSpecifiedInclude('textbox', 'src/mixins/textbox_click_behavior.mixin.js'),
ifSpecifiedInclude('textbox', 'src/mixins/textbox_key_behavior.mixin.js'),
ifSpecifiedInclude('node', 'src/node.js'),
ifSpecifiedAMDInclude(amdLib)

0
build.sh Executable file → Normal file
View file

0
build_all Executable file → Normal file
View file

View file

@ -0,0 +1,22 @@
fabric.util.object.extend(fabric.Textbox.prototype, /** @lends fabric.Textbox.prototype */ {
/**
* Overrides superclass function and adjusts cursor offset value because
* lines do not necessarily end with a newline in Textbox.
* @param {Event} e
* @param {Boolean} isRight
* @returns {Number}
*/
getDownCursorOffset: function(e, isRight) {
return fabric.IText.prototype.getDownCursorOffset.apply(this, [e, isRight]) - 1;
},
/**
* Overrides superclass function and adjusts cursor offset value because
* lines do not necessarily end with a newline in Textbox.
* @param {Event} e
* @param {Boolean} isRight
* @returns {Number}
*/
getUpCursorOffset: function(e, isRight) {
return fabric.IText.prototype.getUpCursorOffset.apply(this, [e, isRight]) - 1;
}
});

View file

@ -0,0 +1,41 @@
(function() {
/**
* Override _setObjectScale and add Textbox specific resizing behavior. Resizing
* a Textbox doesn't scale text, it only changes width and makes text wrap automatically.
*/
var setObjectScaleOverridden = fabric.Canvas.prototype._setObjectScale;
fabric.Canvas.prototype._setObjectScale = function(localMouse, transform,
lockScalingX, lockScalingY, by, lockScalingFlip) {
var t = transform.target;
if (t instanceof fabric.Textbox) {
var w = t.width * ((localMouse.x / transform.scaleX) / (t.width + t.strokeWidth));
if (w >= t.minWidth) {
t.set('width', w);
}
}
else {
setObjectScaleOverridden.call(fabric.Canvas.prototype, localMouse, transform,
lockScalingX, lockScalingY, by, lockScalingFlip);
}
};
/**
* Sets controls of this group to the Textbox's special configuration if
* one is present in the group. Deletes _controlsVisibility otherwise, so that
* it gets initialized to default value at runtime.
*/
fabric.Group.prototype._refreshControlsVisibility = function() {
if (typeof fabric.Textbox === 'undefined') {
return;
}
for (var i = this._objects.length; i--; ) {
if (this._objects[i] instanceof fabric.Textbox) {
this.setControlsVisibility(fabric.Textbox.getTextboxControlVisibility());
return;
}
}
};
})();

View file

@ -0,0 +1,22 @@
(function() {
var getNewSelectionStartFromOffsetOverriden = fabric.IText.prototype._getNewSelectionStartFromOffset;
/**
* Overrides the IText implementation and always sends lineIndex as 0 for Textboxes.
* @param {Number} mouseOffset
* @param {Number} prevWidth
* @param {Number} width
* @param {Number} index
* @param {Number} lineIndex
* @param {Number} jlen
* @returns {Number}
*/
fabric.IText.prototype._getNewSelectionStartFromOffset = function(mouseOffset,
prevWidth, width, index, lineIndex, jlen) {
if (this instanceof fabric.Textbox) {
lineIndex = 0;
}
return getNewSelectionStartFromOffsetOverriden
.call(this, mouseOffset,
prevWidth, width, index, lineIndex, jlen);
};
})();

View file

@ -59,14 +59,14 @@
/**
* Index where text selection starts (or where cursor is when there is no selection)
* @type Nubmer
* @type Number
* @default
*/
selectionStart: 0,
/**
* Index where text selection ends
* @type Nubmer
* @type Number
* @default
*/
selectionEnd: 0,
@ -932,7 +932,7 @@
* @param {CanvasRenderingContext2D} ctx Context to render on
*/
_getWidthOfChar: function(ctx, _char, lineIndex, charIndex) {
if (this.textAlign === 'justify' && /\s/.test(_char)) {
if (this.textAlign === 'justify' && this._reSpacesAndTabs.test(_char)) {
return this._getWidthOfSpace(ctx, lineIndex);
}
@ -1008,7 +1008,7 @@
var line = this._textLines[lineIndex],
wordsWidth = this._getWidthOfWords(ctx, line, lineIndex),
widthDiff = this.width - wordsWidth,
numSpaces = line.length - line.replace(/\s+/g, '').length,
numSpaces = line.length - line.replace(this._reSpacesAndTabs, '').length,
width = widthDiff / numSpaces;
this.__widthOfSpace[lineIndex] = width;
return width;

View file

@ -59,6 +59,13 @@
*/
_reNewline: /\r?\n/,
/**
* Use this regular expression to filter for whitespace that is not a new line.
* Mostly used when text is 'justify' aligned.
* @private
*/
_reSpacesAndTabs: /[ \t\r]+/g,
/**
* Retrieves object's fontSize
* @method getFontSize
@ -329,7 +336,7 @@
ctx = fabric.util.createCanvasElement().getContext('2d');
this._setTextStyles(ctx);
}
this._textLines = this.text.split(this._reNewline);
this._textLines = this._splitTextIntoLines();
this._clearCache();
var currentTextAlign = this.textAlign;
this.textAlign = 'left';
@ -798,6 +805,14 @@
ctx.restore();
},
/**
* Returns the text as an array of lines.
* @returns {Array} Lines in the text
*/
_splitTextIntoLines: function() {
return this.text.split(this._reNewline);
},
/**
* Returns object representation of an instance
* @param {Array} [propertiesToInclude] Any properties that you might want to additionally include in the output