jenkins-bot has submitted this change and it was merged.
Change subject: Kill rangy (almost)
......................................................................
Kill rangy (almost)
Replace simple range getting and setting with native Selection/Range
api that is supported by Chrome/FF & IE10+.
Bonus: Fix documentation in ve.ce.DomRange, and variable names
in various places.
Rename getSelection to getRangeSelection to avoid confusion with
native method.
Fixme: Some tests in ve.ce.TestRunner were pretending to pass because
of a typo (startNode instead of startContainer). Have been logically
commented out with an if(false) but should be fixed in later.
Change-Id: If6f5f59f96b0787b0a4545d430dae3ef0b8deb4d
---
M src/ce/ve.ce.Document.js
M src/ce/ve.ce.DomRange.js
M src/ce/ve.ce.Surface.js
M src/ce/ve.ce.SurfaceObserver.js
M src/ui/ve.ui.Surface.js
M tests/ce/ve.ce.Surface.test.js
M tests/ce/ve.ce.TestRunner.js
7 files changed, 139 insertions(+), 137 deletions(-)
Approvals:
Catrope: Looks good to me, approved
jenkins-bot: Verified
diff --git a/src/ce/ve.ce.Document.js b/src/ce/ve.ce.Document.js
index c50cafd..8ea5658 100644
--- a/src/ce/ve.ce.Document.js
+++ b/src/ce/ve.ce.Document.js
@@ -150,8 +150,6 @@
/**
* Get a DOM node and DOM element offset for a document offset.
*
- * The results of this function are meant to be used with rangy.
- *
* @method
* @param {number} offset Linear model offset
* @returns {Object} Object containing a node and offset property where node
is an HTML element and
diff --git a/src/ce/ve.ce.DomRange.js b/src/ce/ve.ce.DomRange.js
index 4f1d6d2..2647e4e 100644
--- a/src/ce/ve.ce.DomRange.js
+++ b/src/ce/ve.ce.DomRange.js
@@ -6,7 +6,7 @@
*/
/**
- * DomRange.
+ * DOM range
*
* @class
* @constructor
@@ -24,7 +24,14 @@
/* Static Methods */
-ve.ce.DomRange.newFromDomSelection = function ( selection ) {
+/**
+ * Create a new DOM range from a document's native selection
+ *
+ * @param {HTMLDocument} doc Document to get selection from
+ * @return {ve.ce.DomRange} DOM range
+ */
+ve.ce.DomRange.newFromDocument = function ( doc ) {
+ var selection = doc.getSelection();
return new ve.ce.DomRange(
selection.focusNode, selection.focusOffset,
selection.anchorNode, selection.anchorOffset
);
@@ -32,7 +39,11 @@
/* Methods */
-/** */
+/**
+ * Check if a DOM range is equal to another DOM range
+ * @param {ve.ce.DomRange} other DOM range to compare to
+ * @return {boolean} The other DOM range is equal to this one
+ */
ve.ce.DomRange.prototype.equals = function ( other ) {
return other &&
this.focusNode === other.focusNode &&
@@ -42,6 +53,8 @@
};
/**
+ * Get a linear model ve.Range for the DOM range
+ *
* @returns {ve.Range}
*/
ve.ce.DomRange.prototype.getRange = function () {
diff --git a/src/ce/ve.ce.Surface.js b/src/ce/ve.ce.Surface.js
index c8f1618..cc933e4 100644
--- a/src/ce/ve.ce.Surface.js
+++ b/src/ce/ve.ce.Surface.js
@@ -35,6 +35,8 @@
this.selectionTimeout = null;
this.$window = this.$( this.getElementWindow() );
this.$document = this.$( this.getElementDocument() );
+ // Window.getSelection returns a live singleton representing the
document's selection
+ this.nativeSelection = this.getElementWindow().getSelection();
this.eventSequencer = new ve.EventSequencer( [
'keydown', 'keypress', 'keyup',
'compositionstart', 'compositionend'
@@ -277,7 +279,7 @@
* @returns {Object|null} Start and end selection rectangles
*/
ve.ce.Surface.prototype.getSelectionInlineClientRects = function () {
- var inlineRects, surfaceRect, sel, boundingRect, rtl, x, collapsedRect;
+ var inlineRects, surfaceRect, boundingRect, rtl, x, collapsedRect;
if ( this.focusedNode ) {
inlineRects = this.focusedNode.getInlineRects();
surfaceRect = this.getSurface().getBoundingClientRect();
@@ -291,10 +293,8 @@
};
}
- sel = this.getElementDocument().getSelection();
-
// We can't do anything if there's no selection
- if ( sel.rangeCount === 0 ) {
+ if ( this.nativeSelection.rangeCount === 0 ) {
return null;
}
@@ -302,14 +302,14 @@
// * in Firefox on page load when the address bar is still focused
// * in empty paragraphs
try {
- return ve.getStartAndEndRects( sel.getRangeAt( 0
).getClientRects() );
+ return ve.getStartAndEndRects( this.nativeSelection.getRangeAt(
0 ).getClientRects() );
} catch ( e ) {
// When possible, pretend the cursor is the left/right border
of the node
// (depending on directionality) as a fallback.
- if ( sel.focusNode && sel.focusNode.nodeType ===
Node.ELEMENT_NODE ) {
+ if ( this.nativeSelection.focusNode &&
this.nativeSelection.focusNode.nodeType === Node.ELEMENT_NODE ) {
// We would use getBoundingClientRect(), but in iOS7
that's relative to the
// document rather than to the viewport
- boundingRect = sel.focusNode.getClientRects()[0];
+ boundingRect =
this.nativeSelection.focusNode.getClientRects()[0];
if ( !boundingRect ) {
// FF can return null when focusNode is
invisible
return null;
@@ -344,7 +344,7 @@
* @returns {Object|null} Selection rectangle, with keys top, bottom, left,
right, width, height
*/
ve.ce.Surface.prototype.getSelectionBoundingClientRect = function () {
- var inlineRects, boundingRect, surfaceRect, sel;
+ var inlineRects, boundingRect, surfaceRect;
if ( this.focusedNode ) {
boundingRect = this.focusedNode.getBoundingRect();
@@ -356,15 +356,13 @@
return ve.translateRect( boundingRect, surfaceRect.left,
surfaceRect.top );
}
- sel = this.getElementDocument().getSelection();
-
// We can't do anything if there's no selection
- if ( sel.rangeCount === 0 ) {
+ if ( this.nativeSelection.rangeCount === 0 ) {
return null;
}
try {
- inlineRects = sel.getRangeAt( 0 ).getClientRects();
+ inlineRects = this.nativeSelection.getRangeAt( 0
).getClientRects();
// Try the zeroth inline rect first as Chrome sometimes returns
a rectangle
// full of zeros for getBoundingClientRect when the cursor is
collapsed.
// We could test for this failure and fall back to inline[0],
except for the
@@ -374,7 +372,7 @@
if ( inlineRects.length === 1 ) {
return inlineRects[0];
}
- return sel.getRangeAt( 0 ).getBoundingClientRect();
+ return this.nativeSelection.getRangeAt( 0
).getBoundingClientRect();
} catch ( e ) {
return null;
}
@@ -522,17 +520,14 @@
ve.ce.Surface.prototype.onFocusChange = function () {
var hasFocus = false;
- // rangy.getSelection can throw an exception in FF
- try {
- hasFocus = ve.contains(
- [
- this.documentView.getDocumentNode().$element[0],
- this.$pasteTarget[0]
- ],
- rangy.getSelection( this.getElementDocument()
).anchorNode,
- true
- );
- } catch ( ex ) {}
+ hasFocus = ve.contains(
+ [
+ this.documentView.getDocumentNode().$element[0],
+ this.$pasteTarget[0]
+ ],
+ this.nativeSelection.anchorNode,
+ true
+ );
if ( hasFocus && !this.isFocused() ) {
this.onDocumentFocus();
@@ -950,7 +945,7 @@
* @param {jQuery.Event} e Copy event
*/
ve.ce.Surface.prototype.onCopy = function ( e ) {
- var rangyRange, sel, originalRange,
+ var nativeRange, originalRange,
clipboardIndex, clipboardItem, pasteData,
scrollTop, unsafeSelector,
view = this,
@@ -1022,27 +1017,25 @@
);
// If direct clipboard editing is not allowed, we must use the
pasteTarget to
// select the data we want to go in the clipboard
- rangyRange = rangy.createRange( this.getElementDocument() );
- rangyRange.setStart( this.$pasteTarget[0], 0 );
- rangyRange.setEnd( this.$pasteTarget[0],
this.$pasteTarget[0].childNodes.length );
+ nativeRange = this.getElementDocument().createRange();
+ nativeRange.setStart( this.$pasteTarget[0], 0 );
+ nativeRange.setEnd( this.$pasteTarget[0],
this.$pasteTarget[0].childNodes.length );
// Save scroll position before changing focus to "offscreen"
paste target
scrollTop = this.$window.scrollTop();
- sel = rangy.getSelection( this.getElementDocument() );
- originalRange = sel.getRangeAt( 0 ).cloneRange();
- sel.removeAllRanges();
+ originalRange = this.nativeSelection.getRangeAt( 0
).cloneRange();
+ this.nativeSelection.removeAllRanges();
this.$pasteTarget[0].focus();
- sel.addRange( rangyRange, false );
+ this.nativeSelection.addRange( nativeRange );
// Restore scroll position after changing focus
this.$window.scrollTop( scrollTop );
setTimeout( function () {
// Change focus back
- sel = rangy.getSelection( view.getElementDocument() );
- sel.removeAllRanges();
+ view.nativeSelection.removeAllRanges();
view.documentView.getDocumentNode().$element[0].focus();
- sel.addRange( originalRange );
+ view.nativeSelection.addRange( originalRange );
// Restore scroll position
view.$window.scrollTop( scrollTop );
} );
@@ -1077,7 +1070,7 @@
* @param {jQuery.Event} e Paste event
*/
ve.ce.Surface.prototype.beforePaste = function ( e ) {
- var tx, node, range, contextElement, rangyRange, sel,
+ var tx, node, range, contextElement, nativeRange,
context, leftText, rightText, textNode, textStart, textEnd,
selection = this.model.getSelection(),
clipboardData = e.originalEvent.clipboardData,
@@ -1093,7 +1086,7 @@
this.surfaceObserver.stopTimerLoop();
// Pasting into a range? Remove first.
- if ( !rangy.getSelection( this.$document[0] ).isCollapsed ) {
+ if ( !this.nativeSelection.isCollapsed ) {
tx = ve.dm.Transaction.newFromRemoval( doc, selection );
selection = tx.translateRange( selection );
this.model.change( tx, selection );
@@ -1150,15 +1143,14 @@
// so do it up here.
this.$pasteTarget[0].focus();
- rangyRange = rangy.createRange( this.getElementDocument() );
+ nativeRange = this.getElementDocument().createRange();
// Assume that the DM node only generated one child
textNode = this.$pasteTarget.children().contents()[0];
// Place the cursor between the placeholder characters
- rangyRange.setStart( textNode, textStart );
- rangyRange.setEnd( textNode, textEnd );
- sel = rangy.getSelection( this.getElementDocument() );
- sel.removeAllRanges();
- sel.addRange( rangyRange, false );
+ nativeRange.setStart( textNode, textStart );
+ nativeRange.setEnd( textNode, textEnd );
+ this.nativeSelection.removeAllRanges();
+ this.nativeSelection.addRange( nativeRange );
this.beforePasteData.context = context;
this.beforePasteData.leftText = leftText;
@@ -1189,7 +1181,7 @@
selection = this.model.getSelection();
// If the selection doesn't collapse after paste then nothing was
inserted
- if ( !rangy.getSelection( this.getElementDocument() ).isCollapsed ) {
+ if ( !this.nativeSelection.isCollapsed ) {
return;
}
@@ -1440,7 +1432,7 @@
* @param {ve.Range|null} selection
*/
ve.ce.Surface.prototype.onModelSelect = function ( selection ) {
- var start, end, rangySel, rangyRange,
+ var start, end, nativeRange,
next = null,
previous = this.focusedNode;
@@ -1476,17 +1468,16 @@
next.setFocused( true );
this.focusedNode = next;
- rangySel = rangy.getSelection(
this.getElementDocument() );
// As FF won't fire a copy event with nothing selected,
make
// a dummy selection of one space in the pasteTarget.
// onCopy will ignore this native selection and use the
DM selection
this.$pasteTarget.text( ' ' );
- rangyRange = rangy.createRange(
this.getElementDocument() );
- rangyRange.setStart( this.$pasteTarget[0], 0 );
- rangyRange.setEnd( this.$pasteTarget[0], 1 );
- rangySel.removeAllRanges();
+ nativeRange = this.getElementDocument().createRange();
+ nativeRange.setStart( this.$pasteTarget[0], 0 );
+ nativeRange.setEnd( this.$pasteTarget[0], 1 );
+ this.nativeSelection.removeAllRanges();
this.$pasteTarget[0].focus();
- rangySel.addRange( rangyRange, false );
+ this.nativeSelection.addRange( nativeRange );
// Since the selection is no longer in the
documentNode, clear the SurfaceObserver's
// selection state. Otherwise, if the user places the
selection back into the documentNode
// in exactly the same place where it was before, the
observer won't consider that a change.
@@ -1820,7 +1811,8 @@
* @param {jQuery.Event} e Up or down key down event
*/
ve.ce.Surface.prototype.handleUpOrDownArrowKey = function ( e ) {
- var selection, rangySelection, rangyRange, slug, $cursorHolder,
+ var selection, nativeRange, slug, $cursorHolder,
+ rangySelection = rangy.getSelection( this.getElementDocument()
),
direction = e.keyCode === OO.ui.Keys.DOWN ? 1 : -1;
// TODO: onDocumentKeyDown did this already
@@ -1829,7 +1821,6 @@
this.surfaceObserver.pollOnce();
selection = this.model.getSelection();
- rangySelection = rangy.getSelection( this.$document[0] );
if ( this.focusedNode ) {
$cursorHolder = this.$( '<span
class="ve-ce-surface-cursorHolder"> </span>' ).hide();
@@ -1839,34 +1830,35 @@
$cursorHolder.insertAfter(
this.focusedNode.$element.last() );
}
} else if ( !selection.isCollapsed() && selection.isBackwards() &&
!rangySelection.isBackwards() ) {
- // Perform programatic handling for a selection that is
expanded and backwards accordig to
+ // TODO: Implement our own isBackwards for native selections so
we can kill rangy here
+ // Perform programatic handling for a selection that is
expanded and backwards according to
// model data but not according to browser data.
slug = this.documentView.getSlugAtOffset( selection.to );
if ( !slug ) {
$cursorHolder = this.$( '<span
class="ve-ce-surface-cursorHolder"> </span>' ).hide();
- rangySelection.anchorNode.splitText(
rangySelection.anchorOffset );
- rangySelection.anchorNode.parentNode.insertBefore(
+ this.nativeSelection.anchorNode.splitText(
this.nativeSelection.anchorOffset );
+ this.nativeSelection.anchorNode.parentNode.insertBefore(
$cursorHolder[0],
- rangySelection.anchorNode.nextSibling
+ this.nativeSelection.anchorNode.nextSibling
);
}
}
if ( $cursorHolder || slug ) {
- rangyRange = rangy.createRange( this.$document[0] );
- rangyRange.selectNode( $cursorHolder ? $cursorHolder[0] : slug
);
- rangySelection.setSingleRange( rangyRange );
+ nativeRange = this.getElementDocument().createRange();
+ nativeRange.selectNode( $cursorHolder ? $cursorHolder[0] : slug
);
+ this.nativeSelection.removeAllRanges();
+ this.nativeSelection.addRange( nativeRange );
}
setTimeout( ve.bind( function () {
- var view, range;
+ var node, range;
if ( $cursorHolder ) {
$cursorHolder.remove();
this.surfaceObserver.clear();
}
- rangySelection = rangy.getSelection( this.$document[0] );
// Chrome bug lets you cursor into a multi-line
contentEditable=false with up/down...
- view = $( rangySelection.anchorNode ).closest(
'.ve-ce-leafNode,.ve-ce-branchNode' ).data( 'view' );
- if ( view.isFocusable() ) {
- range = direction === 1 ? view.getOuterRange() :
view.getOuterRange().flip();
+ node = $( this.nativeSelection.anchorNode ).closest(
'.ve-ce-leafNode,.ve-ce-branchNode' ).data( 'view' );
+ if ( node.isFocusable() ) {
+ range = direction === 1 ? node.getOuterRange() :
node.getOuterRange().flip();
} else {
this.surfaceObserver.pollOnce();
range = new ve.Range( this.model.getSelection().to );
@@ -2270,19 +2262,26 @@
* @param {ve.Range} range Range to show selection on
*/
ve.ce.Surface.prototype.showSelection = function ( range ) {
- var documentElement = this.documentView.getDocumentNode().$element[0],
- selection = this.getSelection( range ),
- rangySel = rangy.getSelection( this.$document[0] ),
- rangyRange = rangy.createRange( this.$document[0] );
+ var endRange,
+ documentElement =
this.documentView.getDocumentNode().$element[0],
+ rangeSelection = this.getRangeSelection( range ),
+ nativeRange = this.getElementDocument().createRange();
- if ( selection.end ) {
- rangyRange.setStart( selection.start.node,
selection.start.offset );
- rangyRange.setEnd( selection.end.node, selection.end.offset );
- rangySel.removeAllRanges();
- rangySel.addRange( rangyRange, selection.isBackwards );
+ this.nativeSelection.removeAllRanges();
+ if ( rangeSelection.end ) {
+ nativeRange.setStart( rangeSelection.start.node,
rangeSelection.start.offset );
+ nativeRange.setEnd( rangeSelection.end.node,
rangeSelection.end.offset );
+ if ( rangeSelection.isBackwards && this.nativeSelection.extend
) {
+ endRange = nativeRange.cloneRange();
+ endRange.collapse( false );
+ this.nativeSelection.addRange( endRange );
+ this.nativeSelection.extend(
nativeRange.startContainer, nativeRange.startOffset );
+ } else {
+ this.nativeSelection.addRange( nativeRange );
+ }
} else {
- rangyRange.setStart( selection.start.node,
selection.start.offset );
- rangySel.setSingleRange( rangyRange );
+ nativeRange.setStart( rangeSelection.start.node,
rangeSelection.start.offset );
+ this.nativeSelection.addRange( nativeRange );
}
// Setting a range doesn't give focus in all browsers so make sure this
happens
// Also set focus after range to prevent scrolling to top
@@ -2298,7 +2297,7 @@
* @param {ve.Range} range Range to get selection for
* @returns {Object} Object containing start and end node/offset selections,
and an isBackwards flag.
*/
-ve.ce.Surface.prototype.getSelection = function ( range ) {
+ve.ce.Surface.prototype.getRangeSelection = function ( range ) {
range = new ve.Range(
this.getNearestCorrectOffset( range.from, -1 ),
this.getNearestCorrectOffset( range.to, 1 )
@@ -2430,7 +2429,7 @@
}
// At the beginning of a node, take from the right
if (
- rangy.getSelection( this.$document[0] ).anchorOffset === 0 &&
+ this.nativeSelection.anchorOffset === 0 &&
rightAnnotations &&
!rightAnnotations.compareTo( insertionAnnotations )
) {
diff --git a/src/ce/ve.ce.SurfaceObserver.js b/src/ce/ve.ce.SurfaceObserver.js
index 8e5bb7a..fc8df6b 100644
--- a/src/ce/ve.ce.SurfaceObserver.js
+++ b/src/ce/ve.ce.SurfaceObserver.js
@@ -1,5 +1,3 @@
-/*global rangy */
-
/*!
* VisualEditor ContentEditable Surface class.
*
@@ -72,7 +70,7 @@
* @param {ve.Range} range Initial range to use
*/
ve.ce.SurfaceObserver.prototype.clear = function ( range ) {
- this.rangyRange = null;
+ this.domRange = null;
this.range = range || null;
this.node = null;
this.text = null;
@@ -176,7 +174,7 @@
* @fires selectionChange
*/
ve.ce.SurfaceObserver.prototype.pollOnceInternal = function ( emitChanges ) {
- var $nodeOrSlug, node, text, hash, range, rangyRange, $slugWrapper,
observer = this;
+ var $nodeOrSlug, node, text, hash, range, domRange, $slugWrapper,
observer = this;
if ( !this.domDocument ) {
return;
@@ -184,14 +182,14 @@
range = this.range;
node = this.node;
- rangyRange = ve.ce.DomRange.newFromDomSelection( rangy.getSelection(
this.domDocument ) );
+ domRange = ve.ce.DomRange.newFromDocument( this.domDocument );
- if ( !rangyRange.equals( this.rangyRange ) ) {
- this.rangyRange = rangyRange;
+ if ( !domRange.equals( this.domRange ) ) {
+ this.domRange = domRange;
node = null;
- $nodeOrSlug = $( rangyRange.anchorNode ).closest(
'.ve-ce-branchNode, .ve-ce-branchNode-slug' );
+ $nodeOrSlug = $( domRange.anchorNode ).closest(
'.ve-ce-branchNode, .ve-ce-branchNode-slug' );
if ( $nodeOrSlug.length ) {
- range = rangyRange.getRange();
+ range = domRange.getRange();
if ( $nodeOrSlug.hasClass( 've-ce-branchNode-slug' ) ) {
$slugWrapper = $nodeOrSlug.closest(
'.ve-ce-branchNode-blockSlugWrapper' );
} else {
diff --git a/src/ui/ve.ui.Surface.js b/src/ui/ve.ui.Surface.js
index 8a01a29..d0d05d8 100644
--- a/src/ui/ve.ui.Surface.js
+++ b/src/ui/ve.ui.Surface.js
@@ -4,7 +4,6 @@
* @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
-/*global rangy */
/**
* A surface is a top-level object which contains both a surface model and a
surface view.
@@ -408,7 +407,7 @@
};
ve.ui.Surface.prototype.initFilibuster = function () {
- var uiSurface = this;
+ var surface = this;
this.filibuster = new ve.Filibuster()
.wrapClass( ve.EventSequencer )
.wrapNamespace( ve.dm, 've.dm' )
@@ -419,30 +418,30 @@
ve.ui.Surface.prototype.stopFilibuster
] )
.setObserver( 'dm doc', function () {
- return JSON.stringify(
uiSurface.model.documentModel.data.data );
+ return JSON.stringify(
surface.model.documentModel.data.data );
} )
.setObserver( 'dm range', function () {
- var selection = uiSurface.model.selection;
+ var selection = surface.model.selection;
if ( !selection ) {
return null;
}
return [ selection.from, selection.to ].join( ',' );
} )
.setObserver( 'DOM doc', function () {
- return uiSurface.view.$element.html();
+ return surface.view.$element.html();
} )
.setObserver( 'DOM selection', function () {
- var range, sel;
- sel = rangy.getSelection(
uiSurface.view.getElementDocument() );
- if ( sel.rangeCount === 0 ) {
+ var nativeRange,
+ nativeSelection = surface.view.nativeSelection;
+ if ( nativeSelection.rangeCount === 0 ) {
return null;
}
- range = sel.getRangeAt( 0 );
+ nativeRange = nativeSelection.getRangeAt( 0 );
return JSON.stringify( {
- startContainer: range.startContainer.outerHTML,
- startOffset: range.startOffset,
- endContainer: range.endContainer.outerHTML,
- endOffset: range.endOffset
+ startContainer:
nativeRange.startContainer.outerHTML,
+ startOffset: nativeRange.startOffset,
+ endContainer:
nativeRange.endContainer.outerHTML,
+ endOffset: nativeRange.endOffset
} );
} );
};
diff --git a/tests/ce/ve.ce.Surface.test.js b/tests/ce/ve.ce.Surface.test.js
index dd9a6a7..5748cb3 100644
--- a/tests/ce/ve.ce.Surface.test.js
+++ b/tests/ce/ve.ce.Surface.test.js
@@ -934,7 +934,7 @@
}
} );
-QUnit.test( 'getSelection', function ( assert ) {
+QUnit.test( 'getRangeSelection', function ( assert ) {
var i, j, l, surface, selection, expectedNode, internlListNode, node,
msg,
expect = 0,
cases = [
@@ -1061,7 +1061,7 @@
if ( node.isFocusable() ) {
assert.equal( null, cases[i].expected[j],
'Focusable node at ' + j );
} else {
- selection = surface.getView().getSelection( new
ve.Range( j ) );
+ selection =
surface.getView().getRangeSelection( new ve.Range( j ) );
if ( selection.end ) {
expectedNode = $( '<div>' ).html(
cases[i].expected[j].startNode )[0].childNodes[0];
assert.equalDomElement(
selection.start.node, expectedNode, 'Start node ' + msg );
diff --git a/tests/ce/ve.ce.TestRunner.js b/tests/ce/ve.ce.TestRunner.js
index 95ecd42..bb988ca 100644
--- a/tests/ce/ve.ce.TestRunner.js
+++ b/tests/ce/ve.ce.TestRunner.js
@@ -4,7 +4,6 @@
* @copyright 2011-2014 VisualEditor Team and others; see AUTHORS.txt
* @license The MIT License (MIT); see LICENSE.txt
*/
-/*global rangy */
/**
* Text offset from start or end of string
@@ -112,19 +111,20 @@
*
* @class
* @constructor
- * @param {ve.ui.Surface} uiSurface The UI Surface
+ * @param {ve.ui.Surface} surface The UI Surface
*/
-ve.ce.TestRunner = function VeCeTestRunner( uiSurface ) {
+ve.ce.TestRunner = function VeCeTestRunner( surface ) {
var testRunner,
callId = 0;
- this.uiSurface = uiSurface;
- this.view = uiSurface.view;
- this.model = uiSurface.model;
- this.doc = uiSurface.getElementDocument();
+ this.surface = surface;
+ this.view = surface.view;
+ this.model = surface.model;
+ this.doc = surface.getElementDocument();
+ this.nativeSelection = surface.getElementWindow().getSelection();
this.postponedCalls = {};
// Turn off SurfaceObserver setTimeouts
- uiSurface.view.surfaceObserver.frequency = null;
+ surface.view.surfaceObserver.frequency = null;
// Take control of eventSequencer 'setTimeouts'
testRunner = this;
@@ -146,7 +146,7 @@
* @returns {Node} The paragraph node
*/
-ve.ce.TestRunner.prototype.getP = function () {
+ve.ce.TestRunner.prototype.getParagraph = function () {
var p = this.view.$element.find( '.ve-ce-documentNode > p' )[0];
if ( p === undefined ) {
if ( this.view.$element.find( '.ve-ce-documentNode' )[0] ===
undefined ) {
@@ -196,22 +196,18 @@
*/
ve.ce.TestRunner.prototype.changeText = function ( text ) {
var extra,
- range = null,
- sel = rangy.getSelection( this.doc ),
- ranges = sel.getAllRanges();
+ nativeRange = this.nativeSelection.getRangeAt( 0 );
- if ( ranges.length > 0 ) {
- range = ranges[0];
- }
// TODO: Enable multi-paragraph testing. For now, assuming one
paragraph.
- if ( range && range.startNode && text.startsWith(
this.startNode.textContent ) ) {
+ // FIXME: renaming startNode to startContainer revealed failing tests
+ if ( false && nativeRange && nativeRange.startContainer &&
text.indexOf( nativeRange.startContainer.textContent ) === 0 ) {
// We're just appending
- extra = range.startNode.textContent.substring(
range.startNode.textContent.length );
- // This is fine IF startNode is a TextNode
- range.startNode.textContent += extra;
+ extra = nativeRange.startContainer.textContent.substring(
nativeRange.startContainer.textContent.length );
+ // This is fine IF startContainer is a TextNode
+ nativeRange.startContainer.textContent += extra;
} else {
// Wipe out the node
- this.getP().textContent = text;
+ this.getParagraph().textContent = text;
}
this.lastText = text;
};
@@ -228,7 +224,7 @@
* @returns {number} return.endOffset The endoffset within the node
*/
ve.ce.TestRunner.prototype.changeSel = function ( start, end ) {
- var foundStart, foundEnd, rangyRange, sel;
+ var foundStart, foundEnd, nativeRange;
if ( typeof start === 'number' ) {
start = new ve.ce.TestOffset( 'forward', start );
}
@@ -236,8 +232,8 @@
end = new ve.ce.TestOffset( 'forward', end );
}
- foundStart = start.resolve( this.getP() );
- foundEnd = start.resolve( this.getP() );
+ foundStart = start.resolve( this.getParagraph() );
+ foundEnd = start.resolve( this.getParagraph() );
if ( !foundStart.node ) {
throw new Error( 'Bad start offset: ' + start.offset );
}
@@ -245,13 +241,12 @@
throw new Error( 'Bad end offset: ', end.offset );
}
- rangyRange = rangy.createRange( this.doc );
- rangyRange.setStart( foundStart.node, foundStart.offset );
- rangyRange.setEnd( foundEnd.node, foundEnd.offset );
- sel = rangy.getSelection( this.doc );
- sel.removeAllRanges();
- this.getP().focus();
- sel.addRange( rangyRange, false );
+ nativeRange = this.doc.createRange();
+ nativeRange.setStart( foundStart.node, foundStart.offset );
+ nativeRange.setEnd( foundEnd.node, foundEnd.offset );
+ this.nativeSelection.removeAllRanges();
+ this.getParagraph().focus();
+ this.nativeSelection.addRange( nativeRange, false );
this.lastSel = [start, end];
return {
--
To view, visit https://gerrit.wikimedia.org/r/158893
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: If6f5f59f96b0787b0a4545d430dae3ef0b8deb4d
Gerrit-PatchSet: 5
Gerrit-Project: VisualEditor/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits