diff --git a/README.md b/README.md index 33bab8b2..329265ae 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Using Fabric.js, you can create and populate objects on canvas; objects like sim ### Goals -- Unit tested (2200+ tests at the moment) +- Unit tested (2300+ tests at the moment) - Modular (~60 small ["classes", modules, mixins](http://fabricjs.com/docs/)) - Cross-browser - [Fast](https://github.com/kangax/fabric.js/wiki/Focus-on-speed) diff --git a/src/mixins/itext_behavior.mixin.js b/src/mixins/itext_behavior.mixin.js index b631913c..24d48d07 100644 --- a/src/mixins/itext_behavior.mixin.js +++ b/src/mixins/itext_behavior.mixin.js @@ -157,7 +157,8 @@ /** * Find new selection index representing start of current word according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Surrent selection index + * @return {Number} New selection index */ findWordBoundaryLeft: function(startFrom) { var offset = 0, index = startFrom - 1; @@ -179,7 +180,8 @@ /** * Find new selection index representing end of current word according to current selection index - * @param {Number} current selection index + * @param {Number} startFrom Current selection index + * @return {Number} New selection index */ findWordBoundaryRight: function(startFrom) { var offset = 0, index = startFrom; @@ -231,7 +233,7 @@ /** * Returns number of newlines in selected text - * @return {Number} + * @return {Number} Number of newlines in selected text */ getNumNewLinesInSelectedText: function() { var selectedText = this.getSelectedText(); @@ -305,7 +307,7 @@ this._setEditingProps(); this._tick(); - this.canvas.renderAll(); + this.canvas && this.canvas.renderAll(); this.fire('editing:entered'); @@ -323,9 +325,11 @@ * @private */ _setEditingProps: function() { - this.hoverCursor = - this.canvas.defaultCursor = - this.canvas.moveCursor = 'text'; + this.hoverCursor = 'text'; + + if (this.canvas) { + this.canvas.defaultCursor = this.canvas.moveCursor = 'text'; + } this.borderColor = this.editingBorderColor; @@ -354,8 +358,8 @@ lockMovementX: this.lockMovementX, lockMovementY: this.lockMovementY, hoverCursor: this.hoverCursor, - defaultCursor: this.canvas.defaultCursor, - moveCursor: this.canvas.moveCursor + defaultCursor: this.canvas && this.canvas.defaultCursor, + moveCursor: this.canvas && this.canvas.moveCursor }; }, @@ -366,12 +370,15 @@ if (!this._savedProps) return; this.hoverCursor = this._savedProps.overCursor; - this.canvas.defaultCursor = this._savedProps.defaultCursor; - this.canvas.moveCursor = this._savedProps.moveCursor; this.hasControls = this._savedProps.hasControls; this.borderColor = this._savedProps.borderColor; this.lockMovementX = this._savedProps.lockMovementX; this.lockMovementY = this._savedProps.lockMovementY; + + if (this.canvas) { + this.canvas.defaultCursor = this._savedProps.defaultCursor; + this.canvas.moveCursor = this._savedProps.moveCursor; + } }, /** diff --git a/src/shapes/itext.class.js b/src/shapes/itext.class.js index d1c7b13b..c493edd0 100644 --- a/src/shapes/itext.class.js +++ b/src/shapes/itext.class.js @@ -284,11 +284,11 @@ boundaries; if (this.selectionStart === this.selectionEnd) { - boundaries = this.getCursorBoundaries(chars, 'cursor'); + boundaries = this._getCursorBoundaries(chars, 'cursor'); this.renderCursor(boundaries); } else { - boundaries = this.getCursorBoundaries(chars, 'selection'); + boundaries = this._getCursorBoundaries(chars, 'selection'); this.renderSelection(chars, boundaries); } }, @@ -338,10 +338,11 @@ /** * Returns cursor boundaries (left, top, leftOffset, topOffset) + * @private * @param {Array} chars Array of characters * @param {String} typeOfBoundaries */ - getCursorBoundaries: function(chars, typeOfBoundaries) { + _getCursorBoundaries: function(chars, typeOfBoundaries) { var cursorLocation = this.get2DCursorLocation(), diff --git a/test/unit/itext.js b/test/unit/itext.js index e1790101..9d753006 100644 --- a/test/unit/itext.js +++ b/test/unit/itext.js @@ -2,9 +2,50 @@ QUnit.module('fabric.IText'); + var ITEXT_OBJECT = { + 'type': 'text', + 'originX': 'left', + 'originY': 'top', + 'left': 0, + 'top': 0, + 'width': 20, + 'height': 52, + 'fill': 'rgb(0,0,0)', + 'stroke': null, + 'strokeWidth': 1, + 'strokeDashArray': null, + 'strokeLineCap': 'butt', + 'strokeLineJoin': 'miter', + 'strokeMiterLimit': 10, + 'scaleX': 1, + 'scaleY': 1, + 'angle': 0, + 'flipX': false, + 'flipY': false, + 'opacity': 1, + 'shadow': null, + 'visible': true, + 'clipTo': null, + 'text': 'x', + 'fontSize': 40, + 'fontWeight': 'normal', + 'fontFamily': 'Times New Roman', + 'fontStyle': '', + 'lineHeight': 1.3, + 'textDecoration': '', + 'textAlign': 'left', + 'path': null, + 'backgroundColor': '', + 'textBackgroundColor': '', + 'useNative': true, + styles: { } + }; + test('constructor', function() { var iText = new fabric.IText('test'); + ok(iText instanceof fabric.IText); + ok(iText instanceof fabric.Text); }); test('initial properties', function() { @@ -16,6 +57,21 @@ deepEqual(iText.styles, { }); }); + test('instances', function() { + var iText = new fabric.IText('test'); + var lastInstance = fabric.IText.instances[fabric.IText.instances.length - 1]; + equal(lastInstance, iText); + }); + + test('fromObject', function() { + ok(typeof fabric.IText.fromObject == 'function'); + + var iText = fabric.IText.fromObject(ITEXT_OBJECT); + + ok(iText instanceof fabric.IText); + deepEqual(ITEXT_OBJECT, iText.toObject()); + }); + test('toObject', function() { var styles = { 0: { @@ -56,24 +112,201 @@ equal(iText.selectionStart, 0); }); - test('getSelectionStyles', function() { - // TODO: - ok(true); - }); - - test('setSelectionStyles', function() { - // TODO: - ok(true); - }); - test('get2DCursorLocation', function() { - // TODO: - ok(true); + var iText = new fabric.IText('test\nfoo\nbarbaz'); + var loc = iText.get2DCursorLocation(); + + equal(loc.lineIndex, 0); + equal(loc.charIndex, 0); + + // 'tes|t' + iText.selectionStart = iText.selectionEnd = 3; + var loc = iText.get2DCursorLocation(); + + equal(loc.lineIndex, 0); + equal(loc.charIndex, 3); + + // test + // fo|o + iText.selectionStart = iText.selectionEnd = 7; + var loc = iText.get2DCursorLocation(); + + equal(loc.lineIndex, 1); + equal(loc.charIndex, 2); + + // test + // foo + // barba|z + iText.selectionStart = iText.selectionEnd = 14; + var loc = iText.get2DCursorLocation(); + + equal(loc.lineIndex, 2); + equal(loc.charIndex, 5); }); test('isEmptyStyles', function() { - // TODO: - ok(true); + var iText = new fabric.IText('test'); + ok(iText.isEmptyStyles()); + + var iText = new fabric.IText('test', { + styles: { + 0: { + 0: { } + }, + 1: { + 0: { }, 1: { } + } + } + }); + ok(iText.isEmptyStyles()); + + var iText = new fabric.IText('test', { + styles: { + 0: { + 0: { } + }, + 1: { + 0: { fill: 'red' }, 1: { } + } + } + }); + ok(!iText.isEmptyStyles()); }); + test('selectAll', function() { + var iText = new fabric.IText('test'); + + iText.selectAll(); + equal(iText.selectionStart, 0); + equal(iText.selectionEnd, 4); + + iText.selectionStart = 1; + iText.selectionEnd = 2; + + iText.selectAll(); + equal(iText.selectionStart, 0); + equal(iText.selectionEnd, 4); + }); + + test('getSelectedText', function() { + var iText = new fabric.IText('test\nfoobarbaz'); + iText.selectionStart = 1; + iText.selectionEnd = 10; + equal(iText.getSelectedText(), 'est\nfooba'); + + iText.selectionStart = iText.selectionEnd = 3; + equal(iText.getSelectedText(), ''); + }); + + test('enterEditing, exitEditing', function() { + var iText = new fabric.IText('test'); + + equal(typeof iText.enterEditing, 'function'); + equal(typeof iText.exitEditing, 'function'); + + ok(!iText.isEditing); + + iText.enterEditing(); + ok(iText.isEditing); + + iText.exitEditing(); + ok(!iText.isEditing); + }); + + test('insertChars', function() { + var iText = new fabric.IText('test'); + + equal(typeof iText.insertChars, 'function'); + + iText.insertChars('foo_'); + equal(iText.text, 'foo_test'); + + iText.text = 'test'; + iText.selectionStart = iText.selectionEnd = 2; + iText.insertChars('_foo_'); + equal(iText.text, 'te_foo_st'); + + iText.text = 'test'; + iText.selectionStart = 1; + iText.selectionEnd = 3; + iText.insertChars('_foo_'); + equal(iText.text, 't_foo_t'); + }); + + test('insertNewline', function() { + var iText = new fabric.IText('test'); + + equal(typeof iText.insertNewline, 'function'); + + iText.selectionStart = iText.selectionEnd = 2; + iText.insertNewline(); + + equal(iText.text, 'te\nst'); + + iText.text = 'test'; + iText.selectionStart = 1; + iText.selectionEnd = 3; + iText.insertNewline(); + + equal(iText.text, 't\nt'); + }); + + test('selectWord', function() { + var iText = new fabric.IText('test foo bar-baz\nqux'); + + equal(typeof iText.selectWord, 'function'); + + iText.selectWord(1); + equal(iText.selectionStart, 0); // |test| + equal(iText.selectionEnd, 4); + + iText.selectWord(7); + equal(iText.selectionStart, 5); // |foo| + equal(iText.selectionEnd, 8); + }); + + // test('selectLine', function() { + // // TODO: + // }); + + // test('getSelectionStyles', function() { + // // TODO: + // }); + + // test('setSelectionStyles', function() { + // // TODO: + // }); + + // test('getCurrentCharFontSize', function() { + // // TODO: + // }); + + // test('getCurrentCharColor', function() { + // // TODO: + // }); + + // test('toSVG', function() { + // // TODO: + // }); + + // test('findWordBoundaryLeft', function() { + // // TODO: + // }); + + // test('findWordBoundaryRight', function() { + // // TODO: + // }); + + // test('findLineBoundaryLeft', function() { + // // TODO: + // }); + + // test('findLineBoundaryRight', function() { + // // TODO: + // }); + + // test('getNumNewLinesInSelectedText', function() { + // // TODO: + // }); + })();