From 1ec7b46d15bb49c70452df2e4fa30df75fb14157 Mon Sep 17 00:00:00 2001 From: Jason Chen Date: Thu, 20 Nov 2014 23:38:48 -0800 Subject: [PATCH] Initial getBounds implementation and tests --- src/core/editor.coffee | 30 ++++++++++++++ src/quill.coffee | 3 ++ test/unit/core/editor.coffee | 77 ++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) diff --git a/src/core/editor.coffee b/src/core/editor.coffee index cbc742c9c9..1054b9324c 100644 --- a/src/core/editor.coffee +++ b/src/core/editor.coffee @@ -75,6 +75,36 @@ class Editor else @root.focus() + getBounds: (index) -> + this.checkUpdate() + [leaf, offset] = @doc.findLeafAt(index, true) + throw new Error('Invalid position') unless leaf? + containerBounds = @root.parentNode.getBoundingClientRect() + if offset == 0 + bounds = leaf.node.parentNode.getBoundingClientRect() + return { + height: bounds.height + left: bounds.left - containerBounds.left, + top: bounds.top - containerBounds.top + } + else if offset == leaf.length + bounds = leaf.node.parentNode.getBoundingClientRect() + return { + height: bounds.height + left: bounds.right - containerBounds.left, + top: bounds.top - containerBounds.top + } + else + range = document.createRange() + range.setStart(leaf.node, offset) + range.setEnd(leaf.node, offset + 1) + bounds = range.getBoundingClientRect() + return { + height: bounds.height + left: bounds.left - containerBounds.left, + top: bounds.top - containerBounds.top + } + getDelta: -> return @delta diff --git a/src/quill.coffee b/src/quill.coffee index b9965487ca..8a5f728a01 100644 --- a/src/quill.coffee +++ b/src/quill.coffee @@ -133,6 +133,9 @@ class Quill extends EventEmitter2 delta = new Delta().retain(start).retain(end - start, formats) @editor.applyDelta(delta, source) + getBounds: (index) -> + return @editor.getBounds(index) + getContents: (start = 0, end = null) -> if _.isObject(start) end = start.end diff --git a/test/unit/core/editor.coffee b/test/unit/core/editor.coffee index 8e55e42f24..1b19dd72a3 100644 --- a/test/unit/core/editor.coffee +++ b/test/unit/core/editor.coffee @@ -270,4 +270,81 @@ describe('Editor', -> expect(@editor.checkUpdate).not.toHaveBeenCalled() ) ) + + describe('getBounds()', -> + reference = null + + beforeEach( -> + @editor.root.style.fontFamily = 'monospace' + unless reference? + @editor.root.innerHTML = '
0
' + reference = + normal: + height: @editor.root.firstChild.firstChild.offsetHeight + width: @editor.root.firstChild.firstChild.offsetWidth + @editor.root.innerHTML = '
0
' + reference.large = + height: @editor.root.firstChild.firstChild.offsetHeight + width: @editor.root.firstChild.firstChild.offsetWidth + @editor.root.innerHTML = '
012345
' + ) + + it('empty line', -> + @editor.root.innerHTML = "

" + bounds = @editor.getBounds(0) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(0, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('start of line', -> + bounds = @editor.getBounds(0) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(0, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('end of line', -> + bounds = @editor.getBounds(6) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(4*reference.normal.width + 2*reference.large.width, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('middle of plain text', -> + bounds = @editor.getBounds(1) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(reference.normal.width, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('middle of formatted text', -> + bounds = @editor.getBounds(3) + expect(bounds.height).toBeApproximately(reference.large.height, 1) + expect(bounds.left).toBeApproximately(2*reference.normal.width + reference.large.width, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('end of plain text start of formatted text', -> + bounds = @editor.getBounds(2) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(2*reference.normal.width, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('end of formatted text start of plain text', -> + bounds = @editor.getBounds(4) + expect(bounds.height).toBeApproximately(reference.large.height, 1) + expect(bounds.left).toBeApproximately(2*reference.normal.width + 2*reference.large.width, 1) + expect(bounds.top).toBeApproximately(0, 1) + ) + + it('second line', -> + @editor.root.innerHTML = "

0
" + bounds = @editor.getBounds(2) + expect(bounds.height).toBeApproximately(reference.normal.height, 1) + expect(bounds.left).toBeApproximately(0, 1) + expect(bounds.top).toBeApproximately(reference.normal.height, 1) + ) + ) )