mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-24 22:35:41 +00:00
Merge changes I247d1b68,I5a8ca28a
* changes: Fix getOffsetFrom(Element|Text)Node for annotated aliens Add test for getOffsetFrom(Element|Text)Node
This commit is contained in:
commit
27dfe83e6f
|
@ -191,13 +191,12 @@ ve.ce.getOffsetFromTextNode = function ( domNode, domOffset ) {
|
||||||
* @method
|
* @method
|
||||||
* @param {HTMLElement} domNode DOM node
|
* @param {HTMLElement} domNode DOM node
|
||||||
* @param {number} domOffset DOM offset within the DOM Element
|
* @param {number} domOffset DOM offset within the DOM Element
|
||||||
* @param {boolean} [addOuterLength] Use outer length, which includes wrappers if any exist
|
* @param {number} [firstRecursionDirection] Which direction the first recursive call went in (+/-1)
|
||||||
* @returns {number} Linear model offset
|
* @returns {number} Linear model offset
|
||||||
*/
|
*/
|
||||||
ve.ce.getOffsetFromElementNode = function ( domNode, domOffset, addOuterLength ) {
|
ve.ce.getOffsetFromElementNode = function ( domNode, domOffset, firstRecursionDirection ) {
|
||||||
var $domNode = $( domNode ),
|
var direction, nodeModel, node,
|
||||||
nodeModel,
|
$domNode = $( domNode );
|
||||||
node;
|
|
||||||
|
|
||||||
if ( $domNode.hasClass( 've-ce-branchNode-slug' ) ) {
|
if ( $domNode.hasClass( 've-ce-branchNode-slug' ) ) {
|
||||||
if ( $domNode.prev().length ) {
|
if ( $domNode.prev().length ) {
|
||||||
|
@ -211,8 +210,8 @@ ve.ce.getOffsetFromElementNode = function ( domNode, domOffset, addOuterLength )
|
||||||
}
|
}
|
||||||
|
|
||||||
// IE sometimes puts the cursor in a text node inside ce="false". BAD!
|
// IE sometimes puts the cursor in a text node inside ce="false". BAD!
|
||||||
if ( domNode.contentEditable === 'false' ) {
|
if ( !firstRecursionDirection && !domNode.isContentEditable ) {
|
||||||
nodeModel = $domNode.data( 'view' ).getModel();
|
nodeModel = $domNode.closest( '.ve-ce-branchNode, .ve-ce-leafNode' ).data( 'view' ).getModel();
|
||||||
return nodeModel.getOffset() + nodeModel.getOuterLength();
|
return nodeModel.getOffset() + nodeModel.getOuterLength();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,22 +219,30 @@ ve.ce.getOffsetFromElementNode = function ( domNode, domOffset, addOuterLength )
|
||||||
node = $domNode.data( 'view' );
|
node = $domNode.data( 'view' );
|
||||||
if ( node && node instanceof ve.ce.Node ) {
|
if ( node && node instanceof ve.ce.Node ) {
|
||||||
nodeModel = $domNode.data( 'view' ).getModel();
|
nodeModel = $domNode.data( 'view' ).getModel();
|
||||||
if ( addOuterLength === true ) {
|
if ( firstRecursionDirection === -1 ) {
|
||||||
return nodeModel.getOffset() + nodeModel.getOuterLength();
|
return nodeModel.getOffset() + nodeModel.getOuterLength();
|
||||||
|
} else if ( firstRecursionDirection === 1 ) {
|
||||||
|
return nodeModel.getOffset();
|
||||||
} else {
|
} else {
|
||||||
return nodeModel.getOffset() + ( nodeModel.isWrapped() ? 1 : 0 );
|
return nodeModel.getOffset() + ( nodeModel.isWrapped() ? 1 : 0 );
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node = $domNode.contents().last()[0];
|
node = $domNode.contents().last()[0];
|
||||||
|
if ( !firstRecursionDirection ) {
|
||||||
|
direction = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
node = $domNode.contents()[ domOffset - 1 ];
|
node = $domNode.contents()[ domOffset - 1 ];
|
||||||
|
if ( !firstRecursionDirection ) {
|
||||||
|
direction = -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( node.nodeType === Node.TEXT_NODE ) {
|
if ( node.nodeType === Node.TEXT_NODE ) {
|
||||||
return ve.ce.getOffsetFromTextNode( node, node.length );
|
return ve.ce.getOffsetFromTextNode( node, node.length );
|
||||||
} else {
|
} else {
|
||||||
return ve.ce.getOffsetFromElementNode( node, 0, true );
|
return ve.ce.getOffsetFromElementNode( node, 0, direction );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,3 +29,75 @@ QUnit.test( 'getDomHash', 1, function ( assert ) {
|
||||||
'<SPAN>#<B><A>#</A></B><SPAN></SPAN><I>#</I>#</SPAN>'
|
'<SPAN>#<B><A>#</A></B><SPAN></SPAN><I>#</I>#</SPAN>'
|
||||||
);
|
);
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
QUnit.test( 'getOffsetFrom(Element|Text)Node', function ( assert ) {
|
||||||
|
var i, dom, target, surface, documentModel, documentView,
|
||||||
|
expected = 0,
|
||||||
|
testCases = [
|
||||||
|
{
|
||||||
|
'msg': 'Annotated alien',
|
||||||
|
'html': '<p>Foo<b><cite>Bar</cite></b>Baz</p>',
|
||||||
|
// CE html summary;
|
||||||
|
// <p>Foo<b><span [protectedNode]><cite>Bar</cite><img [shield]></span></b>Baz</p>
|
||||||
|
'expected': [
|
||||||
|
0,
|
||||||
|
1, 1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
4, 4, 4,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
7,
|
||||||
|
8,
|
||||||
|
9, 9,
|
||||||
|
10
|
||||||
|
]
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
for( i = 0; i < testCases.length; i++ ) {
|
||||||
|
expected += testCases[i].expected.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
QUnit.expect( expected );
|
||||||
|
|
||||||
|
function testOffsets( parent, testCase, expectedIndex ) {
|
||||||
|
var i;
|
||||||
|
switch ( parent.nodeType ) {
|
||||||
|
case Node.ELEMENT_NODE:
|
||||||
|
for ( i = 0; i <= parent.childNodes.length; i++ ) {
|
||||||
|
expectedIndex++;
|
||||||
|
assert.equal(
|
||||||
|
ve.ce.getOffsetFromElementNode( parent, i ),
|
||||||
|
testCase.expected[expectedIndex],
|
||||||
|
testCase.msg + ': offset ' + i + ' in <' + parent.nodeName.toLowerCase() + '>'
|
||||||
|
);
|
||||||
|
if ( parent.childNodes[i] ) {
|
||||||
|
expectedIndex = testOffsets( parent.childNodes[i], testCase, expectedIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Node.TEXT_NODE:
|
||||||
|
for ( i = 0; i <= parent.data.length; i++ ) {
|
||||||
|
expectedIndex++;
|
||||||
|
assert.equal(
|
||||||
|
ve.ce.getOffsetFromTextNode( parent, i ),
|
||||||
|
testCase.expected[expectedIndex],
|
||||||
|
testCase.msg + ': offset ' + i + ' in "' + parent.data + '"'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return expectedIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
for( i = 0; i < testCases.length; i++ ) {
|
||||||
|
dom = ve.createDocumentFromHtml( testCases[i].html );
|
||||||
|
target = new ve.init.sa.Target( $( '#qunit-fixture' ), dom );
|
||||||
|
surface = target.surface;
|
||||||
|
documentModel = surface.getModel().getDocument();
|
||||||
|
documentView = surface.getView().getDocument();
|
||||||
|
|
||||||
|
testOffsets( documentView.documentNode.$[0], testCases[i], -1 );
|
||||||
|
}
|
||||||
|
} );
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue