Divec has uploaded a new change for review. ( https://gerrit.wikimedia.org/r/383404 )
Change subject: WIP: Get a ve.ce.BranchNode position's corresponding DOM position ...................................................................... WIP: Get a ve.ce.BranchNode position's corresponding DOM position TODO: unit testing Change-Id: I8c9a24dc877a530c9fa421e63caf73f78d79d04c --- M src/ce/ve.ce.BranchNode.js 1 file changed, 48 insertions(+), 39 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/04/383404/1 diff --git a/src/ce/ve.ce.BranchNode.js b/src/ce/ve.ce.BranchNode.js index b1a3131..5b5b04e 100644 --- a/src/ce/ve.ce.BranchNode.js +++ b/src/ce/ve.ce.BranchNode.js @@ -174,16 +174,8 @@ * @param {...ve.dm.BranchNode} [nodes] Variadic list of nodes to insert */ ve.ce.BranchNode.prototype.onSplice = function ( index ) { - var i, j, - length, - args = [], - anchorCeNode, - prevCeNode, - anchorDomNode, - afterAnchor, - node, - parentNode, - removals; + var i, length, removals, position, j, + args = []; for ( i = 0, length = arguments.length; i < length; i++ ) { args.push( arguments[ i ] ); @@ -205,37 +197,14 @@ removals[ i ].$element.detach(); } if ( args.length >= 3 ) { - if ( index > 0 ) { - // Get the element before the insertion - anchorCeNode = this.children[ index - 1 ]; - // If the CE node is a text node, its $element will be empty - // Look at its previous sibling, which cannot be a text node - if ( anchorCeNode.getType() === 'text' ) { - prevCeNode = this.children[ index - 2 ]; - if ( prevCeNode ) { - anchorDomNode = prevCeNode.$element.last()[ 0 ].nextSibling; - } else { - anchorDomNode = this.$element[ 0 ].firstChild; - } - } else { - anchorDomNode = anchorCeNode.$element.last()[ 0 ]; - } - } + position = this.getDomPosition( index ); for ( i = args.length - 1; i >= 2; i-- ) { args[ i ].attach( this ); - if ( anchorDomNode ) { - // DOM equivalent of $( anchorDomNode ).after( args[i].$element ); - afterAnchor = anchorDomNode.nextSibling; - parentNode = anchorDomNode.parentNode; - for ( j = 0, length = args[ i ].$element.length; j < length; j++ ) { - parentNode.insertBefore( args[ i ].$element[ j ], afterAnchor ); - } - } else { - // DOM equivalent of this.$element.prepend( args[j].$element ); - node = this.$element[ 0 ]; - for ( j = args[ i ].$element.length - 1; j >= 0; j-- ) { - node.insertBefore( args[ i ].$element[ j ], node.firstChild ); - } + for ( j = 0, length = args[ i ].$element.length; j < length; j++ ) { + position.node.insertBefore( + args[ i ].$element[ j ], + position.node.children[ position.offset ] + ); } if ( this.live !== args[ i ].isLive() ) { args[ i ].setLive( this.live ); @@ -386,3 +355,43 @@ // Parent method ve.ce.BranchNode.super.prototype.destroy.call( this ); }; + +/** + * Get the DOM position (node and offset) corresponding to a position in this node + * + * @param {number} offset The offset inside this node of the required position + * @return {Object|null} position The DOM position, or null if unattached + * @return {Node} return.node DOM node; guaranteed to be this node's final DOM node + * @return {number} return.offset Offset + */ +ve.ce.BranchNode.prototype.getDomPosition = function ( offset ) { + var ceNode, domOffset, + domNode = this.$element.last()[ 0 ], + textNodeCount = 0; + while ( true ) { + offset--; + ceNode = this.children[ offset ]; + if ( !ceNode ) { + // No children with DOM nodes; return the first offset inside this + // node's DOM node. + domOffset = 0; + break; + } + if ( ceNode.getType() === 'text' ) { + // Text nodes do not have a reference to their DOM nodes, so must + // adjust for this later + textNodeCount++; + continue; + } + if ( ceNode.$element.length > 0 ) { + domOffset = Array.prototype.indexOf.call( domNode.childNodes, ceNode.$element.last()[ 0 ] ) + 1; + break; + } + // Else no DOM representation (e.g. a MetaItem); move to previous element + } + if ( textNodeCount > 1 ) { + // The browser may normalize adjacent text nodes + ve.log( 'Multiple adjacent text nodes; expect trouble' ); + } + return { node: domNode, offset: domOffset + textNodeCount }; +}; -- To view, visit https://gerrit.wikimedia.org/r/383404 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I8c9a24dc877a530c9fa421e63caf73f78d79d04c Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Divec <da...@troi.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits