Start to cleant setSelections (#3119)

This commit is contained in:
Andrea Bogazzi 2016-07-31 12:21:52 -04:00 committed by GitHub
parent 948019f622
commit d93f91febc
11 changed files with 693 additions and 316 deletions

269
dist/fabric.js vendored
View file

@ -12110,6 +12110,7 @@ fabric.util.object.extend(fabric.StaticCanvas.prototype, /** @lends fabric.Stati
/**
* Return the object scale factor counting also the group scaling
* @return {Object} object with scaleX and scaleY properties
*/
getObjectScaling: function() {
var scaleX = this.scaleX, scaleY = this.scaleY;
@ -21757,12 +21758,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
*/
setSelectionStart: function(index) {
index = Math.max(index, 0);
if (this.selectionStart !== index) {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
this.selectionStart = index;
}
this._updateTextarea();
this._updateAndFire('selectionStart', index);
},
/**
@ -21771,14 +21767,31 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
*/
setSelectionEnd: function(index) {
index = Math.min(index, this.text.length);
if (this.selectionEnd !== index) {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
this.selectionEnd = index;
this._updateAndFire('selectionEnd', index);
},
/**
* @private
* @param {String} property 'selectionStart' or 'selectionEnd'
* @param {Number} index new position of property
*/
_updateAndFire: function(property, index) {
if (this[property] !== index) {
this._fireSelectionChanged();
this[property] = index;
}
this._updateTextarea();
},
/**
* Fires the even of selection changed
* @private
*/
_fireSelectionChanged: function() {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
},
/**
* Gets style of a current selection/cursor (at the start position)
* @param {Number} [startIndex] Start index to get styles at
@ -21857,7 +21870,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
if (!this.active || !this.isEditing) {
return;
}
var chars = this.text.split(''),
boundaries, ctx;
@ -22817,6 +22829,7 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* Aborts cursor animation and clears all timeouts
*/
abortCursorAnimation: function() {
var shouldClear = this._currentTickState || this._currentTickCompleteState;
this._currentTickState && this._currentTickState.abort();
this._currentTickCompleteState && this._currentTickCompleteState.abort();
@ -22826,15 +22839,20 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
this._currentCursorOpacity = 0;
// to clear just itext area we need to transform the context
// it may not be worth it
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
if (shouldClear) {
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
}
},
/**
* Selects entire text
*/
selectAll: function() {
this.setSelectionStart(0);
this.setSelectionEnd(this.text.length);
this.selectionStart = 0;
this.selectionEnd = this.text.length;
this._fireSelectionChanged();
this._updateTextarea();
},
/**
@ -22965,12 +22983,15 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* @param {Number} selectionStart Index of a character
*/
selectWord: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */
newSelectionEnd = this.searchWordBoundary(selectionStart, 1);
/* search forward */
newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
/**
@ -22978,11 +22999,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
* @param {Number} selectionStart Index of a character
*/
selectLine: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.findLineBoundaryLeft(selectionStart),
newSelectionEnd = this.findLineBoundaryRight(selectionStart);
newSelectionEnd = this.findLineBoundaryRight(selectionStart);
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
},
/**
@ -23014,9 +23038,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
if (!this.canvas) {
return this;
}
this.canvas.renderAll();
this.canvas.fire('text:editing:entered', { target: this });
this.canvas.renderAll();
this.initMouseMoveHandler();
return this;
},
@ -23052,13 +23075,15 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
return;
}
if (newSelectionStart > this.__selectionStartOnMouseDown) {
this.setSelectionStart(this.__selectionStartOnMouseDown);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = this.__selectionStartOnMouseDown;
this.selectionEnd = newSelectionStart;
}
else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(this.__selectionStartOnMouseDown);
this.selectionStart = newSelectionStart;
this.selectionEnd = this.__selectionStartOnMouseDown;
}
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
@ -23225,7 +23250,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
this._removeSingleCharAndStyle(start + 1);
end--;
}
this.setSelectionStart(start);
this.selectionStart = start;
this.selectionEnd = start;
},
_removeSingleCharAndStyle: function(index) {
@ -23248,7 +23274,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
if (this.selectionEnd - this.selectionStart > 1) {
this._removeCharsFromTo(this.selectionStart, this.selectionEnd);
this.setSelectionEnd(this.selectionStart);
}
//short circuit for block paste
if (!useCopiedStyle && this.isEmptyStyles()) {
@ -23281,10 +23306,11 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass(/** @lends fabric.Imag
return;
}
this._updateTextarea();
this.canvas && this.canvas.renderAll();
this.setCoords();
this._fireSelectionChanged();
this.fire('changed');
this.canvas && this.canvas.fire('text:changed', { target: this });
this.canvas && this.canvas.renderAll();
},
/**
@ -23575,7 +23601,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.isEditing) {
this.__selectionStartOnMouseDown = this.selectionStart;
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.abortCursorAnimation()
}
this.renderCursorOrSelection()
}
});
},
@ -23602,7 +23631,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.__lastSelected && !this.__corner) {
this.enterEditing(options.e);
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.initDelayedCursor(true);
}
else {
this.renderCursorOrSelection();
}
}
this.selected = true;
});
@ -23617,17 +23651,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (e.shiftKey) {
if (newSelectionStart < this.selectionStart) {
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(newSelectionStart);
this.selectionEnd = this.selectionStart;
this.selectionStart = newSelectionStart;
}
else {
this.setSelectionEnd(newSelectionStart);
this.selectionEnd = newSelectionStart;
}
}
else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionStart;
}
this._fireSelectionChanged();
this._updateTextarea();
},
/**
@ -24051,19 +24087,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorDown: function(e) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right');
if (e.shiftKey) {
this.moveCursorDownWithShift(offset);
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
else {
this.moveCursorDownWithoutShift(offset);
}
this.initDelayedCursor();
this._moveCursorUpOrDown('Down', e);
},
/**
@ -24072,8 +24099,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorDownWithoutShift: function(offset) {
this._selectionDirection = 'right';
this.setSelectionStart(this.selectionStart + offset);
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionEnd + offset;
this.selectionStart = this.selectionEnd;
return offset !== 0;
},
/**
@ -24081,8 +24109,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
swapSelectionPoints: function() {
var swapSel = this.selectionEnd;
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(swapSel);
this.selectionEnd = this.selectionStart;
this.selectionStart = swapSel;
},
/**
@ -24094,18 +24122,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
this._selectionDirection = 'right';
}
if (this._selectionDirection === 'right') {
this.setSelectionEnd(this.selectionEnd + offset);
this.selectionEnd += offset;
}
else {
this.setSelectionStart(this.selectionStart + offset);
this.selectionStart += offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'left') {
this.swapSelectionPoints();
this._selectionDirection = 'right';
}
if (this.selectionEnd > this.text.length) {
this.setSelectionEnd(this.text.length);
this.selectionEnd = this.text.length;
}
return offset !== 0;
},
/**
@ -24187,19 +24216,34 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorUp: function(e) {
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this._moveCursorUpOrDown('Up', e);
},
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right');
/**
* Moves cursor up or down, fires the events
* @param {String} direction 'Up' or 'Down'
* @param {Event} e Event object
*/
_moveCursorUpOrDown: function(direction, e) {
var action = 'get' + direction + 'CursorOffset',
moveAction = 'moveCursor' + direction,
offset = this[action](e, this._selectionDirection === 'right');
if (e.shiftKey) {
this.moveCursorUpWithShift(offset);
moveAction += 'WithShift';
}
else {
this.moveCursorUpWithoutShift(offset);
moveAction += 'WithoutShift';
}
if (this[moveAction](offset)) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
}
this.initDelayedCursor();
},
/**
@ -24211,15 +24255,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
this._selectionDirection = 'left';
}
if (this._selectionDirection === 'right') {
this.setSelectionEnd(this.selectionEnd - offset);
this.selectionEnd -= offset;
}
else {
this.setSelectionStart(this.selectionStart - offset);
this.selectionStart -= offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'right') {
this.swapSelectionPoints();
this._selectionDirection = 'left';
}
return offset !== 0;
},
/**
@ -24227,12 +24272,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Number} offset
*/
moveCursorUpWithoutShift: function(offset) {
if (this.selectionStart === this.selectionEnd) {
this.setSelectionStart(this.selectionStart - offset);
}
this.setSelectionEnd(this.selectionStart);
this._selectionDirection = 'left';
this.selectionStart -= offset;
this.selectionEnd = this.selectionStart;
return offset !== 0;
},
/**
@ -24243,33 +24286,28 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorLeftWithShift(e);
}
else {
this.moveCursorLeftWithoutShift(e);
}
this.initDelayedCursor();
this._moveCursorLeftOrRight('Left', e);
},
/**
* @private
* @return {Boolean} true if a change happened
*/
_move: function(e, prop, direction) {
var propMethod = (prop === 'selectionStart' ? 'setSelectionStart' : 'setSelectionEnd');
var newValue;
if (e.altKey) {
this[propMethod](this['findWordBoundary' + direction](this[prop]));
newValue = this['findWordBoundary' + direction](this[prop]);
}
else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) {
this[propMethod](this['findLineBoundary' + direction](this[prop]));
newValue = this['findLineBoundary' + direction](this[prop]);
}
else {
this[propMethod](this[prop] + (direction === 'Left' ? -1 : 1));
this[prop] += direction === 'Left' ? -1 : 1;
return true;
}
if (typeof newValue !== undefined && this[prop] !== newValue) {
this[prop] = newValue;
return true;
}
},
@ -24277,14 +24315,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @private
*/
_moveLeft: function(e, prop) {
this._move(e, prop, 'Left');
return this._move(e, prop, 'Left');
},
/**
* @private
*/
_moveRight: function(e, prop) {
this._move(e, prop, 'Right');
return this._move(e, prop, 'Right');
},
/**
@ -24292,14 +24330,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e
*/
moveCursorLeftWithoutShift: function(e) {
var change = false;
this._selectionDirection = 'left';
// only move cursor when there is no selection,
// otherwise we discard it, and leave cursor on same place
if (this.selectionEnd === this.selectionStart) {
this._moveLeft(e, 'selectionStart');
if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {
change = this._moveLeft(e, 'selectionStart');
}
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionStart;
return change;
},
/**
@ -24308,11 +24348,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorLeftWithShift: function(e) {
if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {
this._moveLeft(e, 'selectionEnd');
return this._moveLeft(e, 'selectionEnd');
}
else {
else if (this.selectionStart !== 0){
this._selectionDirection = 'left';
this._moveLeft(e, 'selectionStart');
return this._moveLeft(e, 'selectionStart');
}
},
@ -24324,18 +24364,31 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
this._moveCursorLeftOrRight('Right', e);
},
this.abortCursorAnimation();
/**
* Moves cursor right or Left, fires event
* @param {String} direction 'Left', 'Right'
* @param {Event} e Event object
*/
_moveCursorLeftOrRight: function(direction, e) {
var actionName = 'moveCursor' + direction + 'With';
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorRightWithShift(e);
actionName += 'Shift';
}
else {
this.moveCursorRightWithoutShift(e);
actionName += 'outShift';
}
this.initDelayedCursor();
if (this[actionName](e)) {
console.log('will fire');
this.abortCursorAnimation();
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
};
},
/**
@ -24344,11 +24397,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorRightWithShift: function(e) {
if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {
this._moveRight(e, 'selectionStart');
return this._moveRight(e, 'selectionStart');
}
else {
else if (this.selectionEnd !== this.text.length) {
this._selectionDirection = 'right';
this._moveRight(e, 'selectionEnd');
return this._moveRight(e, 'selectionEnd');
}
},
@ -24357,15 +24410,17 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorRightWithoutShift: function(e) {
var changed = false;
this._selectionDirection = 'right';
if (this.selectionStart === this.selectionEnd) {
this._moveRight(e, 'selectionStart');
this.setSelectionEnd(this.selectionStart);
changed = this._moveRight(e, 'selectionStart');
this.selectionEnd = this.selectionStart;
return changed;
}
else {
this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText());
this.setSelectionStart(this.selectionEnd);
this.selectionStart = this.selectionEnd;
return true
}
},

8
dist/fabric.min.js vendored

File diff suppressed because one or more lines are too long

BIN
dist/fabric.min.js.gz vendored

Binary file not shown.

233
dist/fabric.require.js vendored
View file

@ -10181,26 +10181,25 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
},
setSelectionStart: function(index) {
index = Math.max(index, 0);
if (this.selectionStart !== index) {
this.fire("selection:changed");
this.canvas && this.canvas.fire("text:selection:changed", {
target: this
});
this.selectionStart = index;
}
this._updateTextarea();
this._updateAndFire("selectionStart", index);
},
setSelectionEnd: function(index) {
index = Math.min(index, this.text.length);
if (this.selectionEnd !== index) {
this.fire("selection:changed");
this.canvas && this.canvas.fire("text:selection:changed", {
target: this
});
this.selectionEnd = index;
this._updateAndFire("selectionEnd", index);
},
_updateAndFire: function(property, index) {
if (this[property] !== index) {
this._fireSelectionChanged();
this[property] = index;
}
this._updateTextarea();
},
_fireSelectionChanged: function() {
this.fire("selection:changed");
this.canvas && this.canvas.fire("text:selection:changed", {
target: this
});
},
getSelectionStyles: function(startIndex, endIndex) {
if (arguments.length === 2) {
var styles = [];
@ -10761,16 +10760,21 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
}, delay);
},
abortCursorAnimation: function() {
var shouldClear = this._currentTickState || this._currentTickCompleteState;
this._currentTickState && this._currentTickState.abort();
this._currentTickCompleteState && this._currentTickCompleteState.abort();
clearTimeout(this._cursorTimeout1);
clearTimeout(this._cursorTimeout2);
this._currentCursorOpacity = 0;
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
if (shouldClear) {
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
}
},
selectAll: function() {
this.setSelectionStart(0);
this.setSelectionEnd(this.text.length);
this.selectionStart = 0;
this.selectionEnd = this.text.length;
this._fireSelectionChanged();
this._updateTextarea();
},
getSelectedText: function() {
return this.text.slice(this.selectionStart, this.selectionEnd);
@ -10840,14 +10844,21 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
return index;
},
selectWord: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.searchWordBoundary(selectionStart, -1), newSelectionEnd = this.searchWordBoundary(selectionStart, 1);
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
selectLine: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.findLineBoundaryLeft(selectionStart), newSelectionEnd = this.findLineBoundaryRight(selectionStart);
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
},
enterEditing: function(e) {
if (this.isEditing || !this.editable) {
@ -10868,10 +10879,10 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
if (!this.canvas) {
return this;
}
this.canvas.renderAll();
this.canvas.fire("text:editing:entered", {
target: this
});
this.canvas.renderAll();
this.initMouseMoveHandler();
return this;
},
@ -10897,12 +10908,14 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
return;
}
if (newSelectionStart > this.__selectionStartOnMouseDown) {
this.setSelectionStart(this.__selectionStartOnMouseDown);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = this.__selectionStartOnMouseDown;
this.selectionEnd = newSelectionStart;
} else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(this.__selectionStartOnMouseDown);
this.selectionStart = newSelectionStart;
this.selectionEnd = this.__selectionStartOnMouseDown;
}
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
_setEditingProps: function() {
@ -11020,7 +11033,8 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
this._removeSingleCharAndStyle(start + 1);
end--;
}
this.setSelectionStart(start);
this.selectionStart = start;
this.selectionEnd = start;
},
_removeSingleCharAndStyle: function(index) {
var isBeginningOfLine = this.text[index - 1] === "\n", indexStyle = isBeginningOfLine ? index : index - 1;
@ -11032,7 +11046,6 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
var style;
if (this.selectionEnd - this.selectionStart > 1) {
this._removeCharsFromTo(this.selectionStart, this.selectionEnd);
this.setSelectionEnd(this.selectionStart);
}
if (!useCopiedStyle && this.isEmptyStyles()) {
this.insertChar(_chars, false);
@ -11056,12 +11069,13 @@ fabric.Image.filters.BaseFilter = fabric.util.createClass({
return;
}
this._updateTextarea();
this.canvas && this.canvas.renderAll();
this.setCoords();
this._fireSelectionChanged();
this.fire("changed");
this.canvas && this.canvas.fire("text:changed", {
target: this
});
this.canvas && this.canvas.renderAll();
},
insertNewlineStyleObject: function(lineIndex, charIndex, isEndOfLine) {
this.shiftLineStyles(lineIndex, +1);
@ -11228,7 +11242,10 @@ fabric.util.object.extend(fabric.IText.prototype, {
}
if (this.isEditing) {
this.__selectionStartOnMouseDown = this.selectionStart;
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.abortCursorAnimation();
}
this.renderCursorOrSelection();
}
});
},
@ -11244,7 +11261,11 @@ fabric.util.object.extend(fabric.IText.prototype, {
}
if (this.__lastSelected && !this.__corner) {
this.enterEditing(options.e);
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.initDelayedCursor(true);
} else {
this.renderCursorOrSelection();
}
}
this.selected = true;
});
@ -11253,15 +11274,17 @@ fabric.util.object.extend(fabric.IText.prototype, {
var newSelectionStart = this.getSelectionStartFromPointer(e);
if (e.shiftKey) {
if (newSelectionStart < this.selectionStart) {
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(newSelectionStart);
this.selectionEnd = this.selectionStart;
this.selectionStart = newSelectionStart;
} else {
this.setSelectionEnd(newSelectionStart);
this.selectionEnd = newSelectionStart;
}
} else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionStart;
}
this._fireSelectionChanged();
this._updateTextarea();
},
getSelectionStartFromPointer: function(e) {
var mouseOffset = this.getLocalPointer(e), prevWidth = 0, width = 0, height = 0, charIndex = 0, newSelectionStart, line;
@ -11491,42 +11514,39 @@ fabric.util.object.extend(fabric.IText.prototype, {
return indexOnNextLine;
},
moveCursorDown: function(e) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getDownCursorOffset(e, this._selectionDirection === "right");
if (e.shiftKey) {
this.moveCursorDownWithShift(offset);
} else {
this.moveCursorDownWithoutShift(offset);
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
this.initDelayedCursor();
this._moveCursorUpOrDown("Down", e);
},
moveCursorDownWithoutShift: function(offset) {
this._selectionDirection = "right";
this.setSelectionStart(this.selectionStart + offset);
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionEnd + offset;
this.selectionStart = this.selectionEnd;
return offset !== 0;
},
swapSelectionPoints: function() {
var swapSel = this.selectionEnd;
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(swapSel);
this.selectionEnd = this.selectionStart;
this.selectionStart = swapSel;
},
moveCursorDownWithShift: function(offset) {
if (this.selectionEnd === this.selectionStart) {
this._selectionDirection = "right";
}
if (this._selectionDirection === "right") {
this.setSelectionEnd(this.selectionEnd + offset);
this.selectionEnd += offset;
} else {
this.setSelectionStart(this.selectionStart + offset);
this.selectionStart += offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === "left") {
this.swapSelectionPoints();
this._selectionDirection = "right";
}
if (this.selectionEnd > this.text.length) {
this.setSelectionEnd(this.text.length);
this.selectionEnd = this.text.length;
}
return offset !== 0;
},
getUpCursorOffset: function(e, isRight) {
var selectionProp = isRight ? this.selectionEnd : this.selectionStart, cursorLocation = this.get2DCursorLocation(selectionProp), lineIndex = cursorLocation.lineIndex;
@ -11559,110 +11579,131 @@ fabric.util.object.extend(fabric.IText.prototype, {
return indexOnPrevLine;
},
moveCursorUp: function(e) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getUpCursorOffset(e, this._selectionDirection === "right");
if (e.shiftKey) {
this.moveCursorUpWithShift(offset);
} else {
this.moveCursorUpWithoutShift(offset);
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this._moveCursorUpOrDown("Up", e);
},
_moveCursorUpOrDown: function(direction, e) {
var action = "get" + direction + "CursorOffset", moveAction = "moveCursor" + direction, offset = this[action](e, this._selectionDirection === "right");
if (e.shiftKey) {
moveAction += "WithShift";
} else {
moveAction += "WithoutShift";
}
if (this[moveAction](offset)) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
}
this.initDelayedCursor();
},
moveCursorUpWithShift: function(offset) {
if (this.selectionEnd === this.selectionStart) {
this._selectionDirection = "left";
}
if (this._selectionDirection === "right") {
this.setSelectionEnd(this.selectionEnd - offset);
this.selectionEnd -= offset;
} else {
this.setSelectionStart(this.selectionStart - offset);
this.selectionStart -= offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === "right") {
this.swapSelectionPoints();
this._selectionDirection = "left";
}
return offset !== 0;
},
moveCursorUpWithoutShift: function(offset) {
if (this.selectionStart === this.selectionEnd) {
this.setSelectionStart(this.selectionStart - offset);
}
this.setSelectionEnd(this.selectionStart);
this._selectionDirection = "left";
this.selectionStart -= offset;
this.selectionEnd = this.selectionStart;
return offset !== 0;
},
moveCursorLeft: function(e) {
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorLeftWithShift(e);
} else {
this.moveCursorLeftWithoutShift(e);
}
this.initDelayedCursor();
this._moveCursorLeftOrRight("Left", e);
},
_move: function(e, prop, direction) {
var propMethod = prop === "selectionStart" ? "setSelectionStart" : "setSelectionEnd";
var newValue;
if (e.altKey) {
this[propMethod](this["findWordBoundary" + direction](this[prop]));
newValue = this["findWordBoundary" + direction](this[prop]);
} else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36) {
this[propMethod](this["findLineBoundary" + direction](this[prop]));
newValue = this["findLineBoundary" + direction](this[prop]);
} else {
this[propMethod](this[prop] + (direction === "Left" ? -1 : 1));
this[prop] += direction === "Left" ? -1 : 1;
return true;
}
if (typeof newValue !== undefined && this[prop] !== newValue) {
this[prop] = newValue;
return true;
}
},
_moveLeft: function(e, prop) {
this._move(e, prop, "Left");
return this._move(e, prop, "Left");
},
_moveRight: function(e, prop) {
this._move(e, prop, "Right");
return this._move(e, prop, "Right");
},
moveCursorLeftWithoutShift: function(e) {
var change = false;
this._selectionDirection = "left";
if (this.selectionEnd === this.selectionStart) {
this._moveLeft(e, "selectionStart");
if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {
change = this._moveLeft(e, "selectionStart");
}
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionStart;
return change;
},
moveCursorLeftWithShift: function(e) {
if (this._selectionDirection === "right" && this.selectionStart !== this.selectionEnd) {
this._moveLeft(e, "selectionEnd");
} else {
return this._moveLeft(e, "selectionEnd");
} else if (this.selectionStart !== 0) {
this._selectionDirection = "left";
this._moveLeft(e, "selectionStart");
return this._moveLeft(e, "selectionStart");
}
},
moveCursorRight: function(e) {
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
this.abortCursorAnimation();
this._moveCursorLeftOrRight("Right", e);
},
_moveCursorLeftOrRight: function(direction, e) {
var actionName = "moveCursor" + direction + "With";
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorRightWithShift(e);
actionName += "Shift";
} else {
this.moveCursorRightWithoutShift(e);
actionName += "outShift";
}
if (this[actionName](e)) {
console.log("will fire");
this.abortCursorAnimation();
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
}
this.initDelayedCursor();
},
moveCursorRightWithShift: function(e) {
if (this._selectionDirection === "left" && this.selectionStart !== this.selectionEnd) {
this._moveRight(e, "selectionStart");
} else {
return this._moveRight(e, "selectionStart");
} else if (this.selectionEnd !== this.text.length) {
this._selectionDirection = "right";
this._moveRight(e, "selectionEnd");
return this._moveRight(e, "selectionEnd");
}
},
moveCursorRightWithoutShift: function(e) {
var changed = false;
this._selectionDirection = "right";
if (this.selectionStart === this.selectionEnd) {
this._moveRight(e, "selectionStart");
this.setSelectionEnd(this.selectionStart);
changed = this._moveRight(e, "selectionStart");
this.selectionEnd = this.selectionStart;
return changed;
} else {
this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText());
this.setSelectionStart(this.selectionEnd);
this.selectionStart = this.selectionEnd;
return true;
}
},
removeChars: function(e) {

View file

@ -157,6 +157,7 @@
* Aborts cursor animation and clears all timeouts
*/
abortCursorAnimation: function() {
var shouldClear = this._currentTickState || this._currentTickCompleteState;
this._currentTickState && this._currentTickState.abort();
this._currentTickCompleteState && this._currentTickCompleteState.abort();
@ -166,15 +167,20 @@
this._currentCursorOpacity = 0;
// to clear just itext area we need to transform the context
// it may not be worth it
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
if (shouldClear) {
this.canvas && this.canvas.clearContext(this.canvas.contextTop || this.ctx);
}
},
/**
* Selects entire text
*/
selectAll: function() {
this.setSelectionStart(0);
this.setSelectionEnd(this.text.length);
this.selectionStart = 0;
this.selectionEnd = this.text.length;
this._fireSelectionChanged();
this._updateTextarea();
},
/**
@ -305,12 +311,15 @@
* @param {Number} selectionStart Index of a character
*/
selectWord: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.searchWordBoundary(selectionStart, -1), /* search backwards */
newSelectionEnd = this.searchWordBoundary(selectionStart, 1);
/* search forward */
newSelectionEnd = this.searchWordBoundary(selectionStart, 1); /* search forward */
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
/**
@ -318,11 +327,14 @@
* @param {Number} selectionStart Index of a character
*/
selectLine: function(selectionStart) {
selectionStart = selectionStart || this.selectionStart;
var newSelectionStart = this.findLineBoundaryLeft(selectionStart),
newSelectionEnd = this.findLineBoundaryRight(selectionStart);
newSelectionEnd = this.findLineBoundaryRight(selectionStart);
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionEnd);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionEnd;
this._fireSelectionChanged();
this._updateTextarea();
},
/**
@ -354,9 +366,8 @@
if (!this.canvas) {
return this;
}
this.canvas.renderAll();
this.canvas.fire('text:editing:entered', { target: this });
this.canvas.renderAll();
this.initMouseMoveHandler();
return this;
},
@ -392,13 +403,15 @@
return;
}
if (newSelectionStart > this.__selectionStartOnMouseDown) {
this.setSelectionStart(this.__selectionStartOnMouseDown);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = this.__selectionStartOnMouseDown;
this.selectionEnd = newSelectionStart;
}
else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(this.__selectionStartOnMouseDown);
this.selectionStart = newSelectionStart;
this.selectionEnd = this.__selectionStartOnMouseDown;
}
this._fireSelectionChanged();
this._updateTextarea();
this.renderCursorOrSelection();
},
@ -565,7 +578,8 @@
this._removeSingleCharAndStyle(start + 1);
end--;
}
this.setSelectionStart(start);
this.selectionStart = start;
this.selectionEnd = start;
},
_removeSingleCharAndStyle: function(index) {
@ -588,7 +602,6 @@
if (this.selectionEnd - this.selectionStart > 1) {
this._removeCharsFromTo(this.selectionStart, this.selectionEnd);
this.setSelectionEnd(this.selectionStart);
}
//short circuit for block paste
if (!useCopiedStyle && this.isEmptyStyles()) {
@ -621,10 +634,11 @@
return;
}
this._updateTextarea();
this.canvas && this.canvas.renderAll();
this.setCoords();
this._fireSelectionChanged();
this.fire('changed');
this.canvas && this.canvas.fire('text:changed', { target: this });
this.canvas && this.canvas.renderAll();
},
/**

View file

@ -103,7 +103,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.isEditing) {
this.__selectionStartOnMouseDown = this.selectionStart;
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.abortCursorAnimation();
}
this.renderCursorOrSelection();
}
});
},
@ -130,7 +133,12 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.__lastSelected && !this.__corner) {
this.enterEditing(options.e);
this.initDelayedCursor(true);
if (this.selectionStart === this.selectionEnd) {
this.initDelayedCursor(true);
}
else {
this.renderCursorOrSelection();
}
}
this.selected = true;
});
@ -145,17 +153,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (e.shiftKey) {
if (newSelectionStart < this.selectionStart) {
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(newSelectionStart);
this.selectionEnd = this.selectionStart;
this.selectionStart = newSelectionStart;
}
else {
this.setSelectionEnd(newSelectionStart);
this.selectionEnd = newSelectionStart;
}
}
else {
this.setSelectionStart(newSelectionStart);
this.setSelectionEnd(newSelectionStart);
this.selectionStart = newSelectionStart;
this.selectionEnd = newSelectionStart;
}
this._fireSelectionChanged();
this._updateTextarea();
},
/**

View file

@ -343,19 +343,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorDown: function(e) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getDownCursorOffset(e, this._selectionDirection === 'right');
if (e.shiftKey) {
this.moveCursorDownWithShift(offset);
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
else {
this.moveCursorDownWithoutShift(offset);
}
this.initDelayedCursor();
this._moveCursorUpOrDown('Down', e);
},
/**
@ -364,8 +355,9 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorDownWithoutShift: function(offset) {
this._selectionDirection = 'right';
this.setSelectionStart(this.selectionStart + offset);
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionEnd + offset;
this.selectionStart = this.selectionEnd;
return offset !== 0;
},
/**
@ -373,8 +365,8 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
swapSelectionPoints: function() {
var swapSel = this.selectionEnd;
this.setSelectionEnd(this.selectionStart);
this.setSelectionStart(swapSel);
this.selectionEnd = this.selectionStart;
this.selectionStart = swapSel;
},
/**
@ -386,18 +378,19 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
this._selectionDirection = 'right';
}
if (this._selectionDirection === 'right') {
this.setSelectionEnd(this.selectionEnd + offset);
this.selectionEnd += offset;
}
else {
this.setSelectionStart(this.selectionStart + offset);
this.selectionStart += offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'left') {
this.swapSelectionPoints();
this._selectionDirection = 'right';
}
if (this.selectionEnd > this.text.length) {
this.setSelectionEnd(this.text.length);
this.selectionEnd = this.text.length;
}
return offset !== 0;
},
/**
@ -479,19 +472,34 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorUp: function(e) {
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this._moveCursorUpOrDown('Up', e);
},
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
var offset = this.getUpCursorOffset(e, this._selectionDirection === 'right');
/**
* Moves cursor up or down, fires the events
* @param {String} direction 'Up' or 'Down'
* @param {Event} e Event object
*/
_moveCursorUpOrDown: function(direction, e) {
var action = 'get' + direction + 'CursorOffset',
moveAction = 'moveCursor' + direction,
offset = this[action](e, this._selectionDirection === 'right');
if (e.shiftKey) {
this.moveCursorUpWithShift(offset);
moveAction += 'WithShift';
}
else {
this.moveCursorUpWithoutShift(offset);
moveAction += 'WithoutShift';
}
if (this[moveAction](offset)) {
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
}
this.initDelayedCursor();
},
/**
@ -503,15 +511,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
this._selectionDirection = 'left';
}
if (this._selectionDirection === 'right') {
this.setSelectionEnd(this.selectionEnd - offset);
this.selectionEnd -= offset;
}
else {
this.setSelectionStart(this.selectionStart - offset);
this.selectionStart -= offset;
}
if (this.selectionEnd < this.selectionStart && this._selectionDirection === 'right') {
this.swapSelectionPoints();
this._selectionDirection = 'left';
}
return offset !== 0;
},
/**
@ -519,12 +528,10 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Number} offset
*/
moveCursorUpWithoutShift: function(offset) {
if (this.selectionStart === this.selectionEnd) {
this.setSelectionStart(this.selectionStart - offset);
}
this.setSelectionEnd(this.selectionStart);
this._selectionDirection = 'left';
this.selectionStart -= offset;
this.selectionEnd = this.selectionStart;
return offset !== 0;
},
/**
@ -535,33 +542,28 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.selectionStart === 0 && this.selectionEnd === 0) {
return;
}
this.abortCursorAnimation();
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorLeftWithShift(e);
}
else {
this.moveCursorLeftWithoutShift(e);
}
this.initDelayedCursor();
this._moveCursorLeftOrRight('Left', e);
},
/**
* @private
* @return {Boolean} true if a change happened
*/
_move: function(e, prop, direction) {
var propMethod = (prop === 'selectionStart' ? 'setSelectionStart' : 'setSelectionEnd');
var newValue;
if (e.altKey) {
this[propMethod](this['findWordBoundary' + direction](this[prop]));
newValue = this['findWordBoundary' + direction](this[prop]);
}
else if (e.metaKey || e.keyCode === 35 || e.keyCode === 36 ) {
this[propMethod](this['findLineBoundary' + direction](this[prop]));
newValue = this['findLineBoundary' + direction](this[prop]);
}
else {
this[propMethod](this[prop] + (direction === 'Left' ? -1 : 1));
this[prop] += direction === 'Left' ? -1 : 1;
return true;
}
if (typeof newValue !== undefined && this[prop] !== newValue) {
this[prop] = newValue;
return true;
}
},
@ -569,14 +571,14 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @private
*/
_moveLeft: function(e, prop) {
this._move(e, prop, 'Left');
return this._move(e, prop, 'Left');
},
/**
* @private
*/
_moveRight: function(e, prop) {
this._move(e, prop, 'Right');
return this._move(e, prop, 'Right');
},
/**
@ -584,14 +586,16 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e
*/
moveCursorLeftWithoutShift: function(e) {
var change = false;
this._selectionDirection = 'left';
// only move cursor when there is no selection,
// otherwise we discard it, and leave cursor on same place
if (this.selectionEnd === this.selectionStart) {
this._moveLeft(e, 'selectionStart');
if (this.selectionEnd === this.selectionStart && this.selectionStart !== 0) {
change = this._moveLeft(e, 'selectionStart');
}
this.setSelectionEnd(this.selectionStart);
this.selectionEnd = this.selectionStart;
return change;
},
/**
@ -600,11 +604,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorLeftWithShift: function(e) {
if (this._selectionDirection === 'right' && this.selectionStart !== this.selectionEnd) {
this._moveLeft(e, 'selectionEnd');
return this._moveLeft(e, 'selectionEnd');
}
else {
else if (this.selectionStart !== 0){
this._selectionDirection = 'left';
this._moveLeft(e, 'selectionStart');
return this._moveLeft(e, 'selectionStart');
}
},
@ -616,18 +620,30 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
if (this.selectionStart >= this.text.length && this.selectionEnd >= this.text.length) {
return;
}
this._moveCursorLeftOrRight('Right', e);
},
this.abortCursorAnimation();
/**
* Moves cursor right or Left, fires event
* @param {String} direction 'Left', 'Right'
* @param {Event} e Event object
*/
_moveCursorLeftOrRight: function(direction, e) {
var actionName = 'moveCursor' + direction + 'With';
this._currentCursorOpacity = 1;
if (e.shiftKey) {
this.moveCursorRightWithShift(e);
actionName += 'Shift';
}
else {
this.moveCursorRightWithoutShift(e);
actionName += 'outShift';
}
if (this[actionName](e)) {
this.abortCursorAnimation();
this.initDelayedCursor();
this._fireSelectionChanged();
this._updateTextarea();
}
this.initDelayedCursor();
},
/**
@ -636,11 +652,11 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
*/
moveCursorRightWithShift: function(e) {
if (this._selectionDirection === 'left' && this.selectionStart !== this.selectionEnd) {
this._moveRight(e, 'selectionStart');
return this._moveRight(e, 'selectionStart');
}
else {
else if (this.selectionEnd !== this.text.length) {
this._selectionDirection = 'right';
this._moveRight(e, 'selectionEnd');
return this._moveRight(e, 'selectionEnd');
}
},
@ -649,15 +665,17 @@ fabric.util.object.extend(fabric.IText.prototype, /** @lends fabric.IText.protot
* @param {Event} e Event object
*/
moveCursorRightWithoutShift: function(e) {
var changed = false;
this._selectionDirection = 'right';
if (this.selectionStart === this.selectionEnd) {
this._moveRight(e, 'selectionStart');
this.setSelectionEnd(this.selectionStart);
changed = this._moveRight(e, 'selectionStart');
this.selectionEnd = this.selectionStart;
return changed;
}
else {
this.setSelectionEnd(this.selectionEnd + this.getNumNewLinesInSelectedText());
this.setSelectionStart(this.selectionEnd);
this.selectionStart = this.selectionEnd;
return true;
}
},

View file

@ -213,12 +213,7 @@
*/
setSelectionStart: function(index) {
index = Math.max(index, 0);
if (this.selectionStart !== index) {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
this.selectionStart = index;
}
this._updateTextarea();
this._updateAndFire('selectionStart', index);
},
/**
@ -227,14 +222,31 @@
*/
setSelectionEnd: function(index) {
index = Math.min(index, this.text.length);
if (this.selectionEnd !== index) {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
this.selectionEnd = index;
this._updateAndFire('selectionEnd', index);
},
/**
* @private
* @param {String} property 'selectionStart' or 'selectionEnd'
* @param {Number} index new position of property
*/
_updateAndFire: function(property, index) {
if (this[property] !== index) {
this._fireSelectionChanged();
this[property] = index;
}
this._updateTextarea();
},
/**
* Fires the even of selection changed
* @private
*/
_fireSelectionChanged: function() {
this.fire('selection:changed');
this.canvas && this.canvas.fire('text:selection:changed', { target: this });
},
/**
* Gets style of a current selection/cursor (at the start position)
* @param {Number} [startIndex] Start index to get styles at
@ -313,7 +325,6 @@
if (!this.active || !this.isEditing) {
return;
}
var chars = this.text.split(''),
boundaries, ctx;

View file

@ -36,7 +36,8 @@ testrunner.run({
'./test/unit/object_interactivity.js',
'./test/unit/object_geometry.js',
'./test/unit/object_origin.js',
'./test/unit/itext.js'
'./test/unit/itext.js',
'./test/unit/itext_key_behaviour.js'
]
}, function(err, report) {
if (err) {

View file

@ -0,0 +1,228 @@
(function(){
test('event selection:changed firing', function() {
var iText = new fabric.IText('test need some word\nsecond line'),
selection = 0;
function countSelectionChange() {
selection++;
}
iText.on('selection:changed', countSelectionChange);
iText.enterEditing();
equal(selection, 0, 'should not fire on enter edit');
iText.selectAll();
equal(selection, 1, 'should fire once on selectAll');
equal(iText.selectionStart, 0, 'should start from 0');
equal(iText.selectionEnd, 31, 'should end at end of text');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.selectWord();
equal(selection, 1, 'should fire once on selectWord');
equal(iText.selectionStart, 0, 'should start at word start');
equal(iText.selectionEnd, 4, 'should end at word end');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.selectLine();
equal(selection, 1, 'should fire once on selectLine');
equal(iText.selectionStart, 0, 'should start at line start');
equal(iText.selectionEnd, 19, 'should end at line end');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorLeft({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorLeft');
equal(iText.selectionStart, 1, 'should be 1 less than 2');
equal(iText.selectionEnd, 1, 'should be 1 less than 2');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorRight({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorRight');
equal(iText.selectionStart, 3, 'should be 1 more than 2');
equal(iText.selectionEnd, 3, 'should be 1 more than 2');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorDown({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorDown');
equal(iText.selectionStart, 22, 'should be on second line');
equal(iText.selectionEnd, 22, 'should be on second line');
iText.moveCursorDown({ shiftKey: false});
equal(selection, 2, 'should fire once on moveCursorDown');
equal(iText.selectionStart, 31, 'should be at end of text');
equal(iText.selectionEnd, 31, 'should be at end of text');
selection = 0;
iText.selectionStart = 22;
iText.selectionEnd = 22;
iText.moveCursorUp({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorUp');
equal(iText.selectionStart, 2, 'should be back to first line');
equal(iText.selectionEnd, 2, 'should be back on first line');
iText.moveCursorUp({ shiftKey: false});
equal(selection, 2, 'should fire once on moveCursorUp');
equal(iText.selectionStart, 0, 'should be back to first line');
equal(iText.selectionEnd, 0, 'should be back on first line');
selection = 0;
iText.selectionStart = 0;
iText.selectionEnd = 0;
iText.moveCursorLeft({ shiftKey: false});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 0, 'should not move');
equal(iText.selectionEnd, 0, 'should not move');
iText.moveCursorUp({ shiftKey: false});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 0, 'should not move');
equal(iText.selectionEnd, 0, 'should not move');
selection = 0;
iText.selectionStart = 31;
iText.selectionEnd = 31;
iText.moveCursorRight({ shiftKey: false});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 31, 'should not move');
equal(iText.selectionEnd, 31, 'should not move');
iText.moveCursorDown({ shiftKey: false});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 31, 'should not move');
equal(iText.selectionEnd, 31, 'should not move');
selection = 0;
iText.selectionStart = 28;
iText.selectionEnd = 31;
iText.moveCursorUp({ shiftKey: false});
equal(selection, 1, 'should fire');
equal(iText.selectionStart, 9, 'should move to upper line');
equal(iText.selectionEnd, 9, 'should move to upper line');
selection = 0;
iText.selectionStart = 1;
iText.selectionEnd = 4;
iText.moveCursorDown({ shiftKey: false});
equal(selection, 1, 'should fire');
equal(iText.selectionStart, 24, 'should move to down line');
equal(iText.selectionEnd, 24, 'should move to down line');
selection = 0;
iText.selectionStart = 0;
iText.selectionEnd = 0;
iText.insertChars('hello');
equal(selection, 1, 'should fire once on insert multiple chars');
equal(iText.selectionStart, 5, 'should be at end of text inserted');
equal(iText.selectionEnd, 5, 'should be at end of text inserted');
});
test('moving cursor with shift', function() {
var iText = new fabric.IText('test need some word\nsecond line'),
selection = 0;
function countSelectionChange() {
selection++;
}
iText.on('selection:changed', countSelectionChange);
iText.enterEditing();
equal(selection, 0, 'should not fire on enter edit');
iText.selectAll();
equal(selection, 1, 'should fire once on selectAll');
equal(iText.selectionStart, 0, 'should start from 0');
equal(iText.selectionEnd, 31, 'should end at end of text');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.selectWord();
equal(selection, 1, 'should fire once on selectWord');
equal(iText.selectionStart, 0, 'should start at word start');
equal(iText.selectionEnd, 4, 'should end at word end');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.selectLine();
equal(selection, 1, 'should fire once on selectLine');
equal(iText.selectionStart, 0, 'should start at line start');
equal(iText.selectionEnd, 19, 'should end at line end');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorLeft({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorLeft');
equal(iText.selectionStart, 1, 'should be 1 less than 2');
equal(iText.selectionEnd, 1, 'should be 1 less than 2');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorRight({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorRight');
equal(iText.selectionStart, 3, 'should be 1 more than 2');
equal(iText.selectionEnd, 3, 'should be 1 more than 2');
selection = 0;
iText.selectionStart = 2;
iText.selectionEnd = 2;
iText.moveCursorDown({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorDown');
equal(iText.selectionStart, 22, 'should be on second line');
equal(iText.selectionEnd, 22, 'should be on second line');
iText.moveCursorDown({ shiftKey: false});
equal(selection, 2, 'should fire once on moveCursorDown');
equal(iText.selectionStart, 31, 'should be at end of text');
equal(iText.selectionEnd, 31, 'should be at end of text');
selection = 0;
iText.selectionStart = 22;
iText.selectionEnd = 22;
iText.moveCursorUp({ shiftKey: false});
equal(selection, 1, 'should fire once on moveCursorUp');
equal(iText.selectionStart, 2, 'should be back to first line');
equal(iText.selectionEnd, 2, 'should be back on first line');
iText.moveCursorUp({ shiftKey: false});
equal(selection, 2, 'should fire once on moveCursorUp');
equal(iText.selectionStart, 0, 'should be back to first line');
equal(iText.selectionEnd, 0, 'should be back on first line');
selection = 0;
iText.selectionStart = 0;
iText.selectionEnd = 1;
iText._selectionDirection = 'left';
iText.moveCursorLeft({ shiftKey: true});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 0, 'should not move');
equal(iText.selectionEnd, 1, 'should not move');
iText.moveCursorUp({ shiftKey: true});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 0, 'should not move');
equal(iText.selectionEnd, 1, 'should not move');
selection = 0;
iText.selectionStart = 30;
iText.selectionEnd = 31;
iText._selectionDirection = 'right';
iText.moveCursorRight({ shiftKey: true});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 30, 'should not move');
equal(iText.selectionEnd, 31, 'should not move');
iText.moveCursorDown({ shiftKey: true});
equal(selection, 0, 'should not fire with no change');
equal(iText.selectionStart, 30, 'should not move');
equal(iText.selectionEnd, 31, 'should not move');
selection = 0;
});
})();

View file

@ -1440,7 +1440,6 @@ test('toDataURL & reference to canvas', function() {
group.scaleY = 2;
object.group = group;
var objectScale = object.getObjectScaling();
console.log(objectScale);
deepEqual(objectScale, {
scaleX: object.scaleX * group.scaleX,
scaleY: object.scaleY * group.scaleY