Esanders has uploaded a new change for review. https://gerrit.wikimedia.org/r/295349
Change subject: Add a node-type index ...................................................................... Add a node-type index Bug: T135950 Change-Id: I51ae4491c26851f9a590825bff962c917bc77ee1 --- M src/dm/ve.dm.Document.js 1 file changed, 85 insertions(+), 6 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/VisualEditor/VisualEditor refs/changes/49/295349/1 diff --git a/src/dm/ve.dm.Document.js b/src/dm/ve.dm.Document.js index 28f0ccb..971a1f9 100644 --- a/src/dm/ve.dm.Document.js +++ b/src/dm/ve.dm.Document.js @@ -50,6 +50,7 @@ // Properties this.parentDocument = parentDocument; this.completeHistory = []; + this.nodesByType = {}; if ( data instanceof ve.dm.ElementLinearData ) { // Pre-split ElementLinearData @@ -306,6 +307,7 @@ // The end state is stack = [ [this.documentNode] [ array, of, its, children ] ] // so attach all nodes in stack[1] to the root node ve.batchSplice( this.documentNode, 0, 0, currentStack ); + this.updateNodesByType( [ this.documentNode ], [] ); doc.buildingNodeTree = false; }; @@ -954,16 +956,19 @@ * @return {ve.dm.Node[]} Array containing the rebuilt/inserted nodes */ ve.dm.Document.prototype.rebuildNodes = function ( parent, index, numNodes, offset, newLength ) { - var // Get a slice of the document where it's been changed - data = this.data.sliceObject( offset, offset + newLength ), + // Get a slice of the document where it's been changed + var data = this.data.sliceObject( offset, offset + newLength ), // Build document fragment from data fragment = new this.constructor( data, this.htmlDocument, this ), // Get generated child nodes from the document fragment - nodes = fragment.getDocumentNode().getChildren(); - // Replace nodes in the model tree - ve.batchSplice( parent, index, numNodes, nodes ); + addedNodes = fragment.getDocumentNode().getChildren(), + // Replace nodes in the model tree + removedNodes = ve.batchSplice( parent, index, numNodes, addedNodes ); + + this.updateNodesByType( addedNodes, removedNodes ); + // Return inserted nodes - return nodes; + return addedNodes; }; /** @@ -981,6 +986,80 @@ }; /** + * Update the nodes-by-type index + * + * @param {ve.dm.Node[]} addedNodes Added nodes + * @param {ve.dm.Node[]} removedNodes Removed nodes + */ +ve.dm.Document.prototype.updateNodesByType = function ( addedNodes, removedNodes ) { + var doc = this; + + function remove( node ) { + var type = node.getType(), + nodes = doc.nodesByType[ type ] || [], + index = nodes.indexOf( node ); + + if ( index !== -1 ) { + nodes.splice( index, 1 ); + if ( !nodes.length ) { + delete doc.nodesByType[ type ]; + } + } + } + + function add( node ) { + var type = node.getType(), + nodes = doc.nodesByType[ type ] = doc.nodesByType[ type ] || []; + + nodes.push( node ); + } + + function traverse( nodes, action ) { + nodes.forEach( function ( node ) { + if ( node.hasChildren() ) { + node.traverse( action ); + } + action( node ); + } ); + } + + traverse( removedNodes, remove ); + traverse( addedNodes, add ); +}; + +/** + * Get all nodes in the tree for a specific type + * + * If a string type is passed only nodes of that exact type will be returned, + * if a node class is passed, all sub types will be matched. + * + * @param {string|Function} type Node type name or node constructor + * @param {boolean} sort Sort nodes by document order + * @return {ve.dm.Node[]} Nodes of a specific type + */ +ve.dm.Document.prototype.getNodesByType = function ( type, sort ) { + var t, nodeType, + nodes = []; + if ( type instanceof Function ) { + for ( t in this.nodesByType ) { + nodeType = ve.dm.nodeFactory.lookup( t ); + if ( nodeType.prototype === type.prototype || nodeType.prototype instanceof type ) { + nodes = nodes.concat( this.getNodesByType( t ) ); + } + } + } else { + nodes = this.nodesByType[ type ]; + } + + if ( sort ) { + nodes.sort( function ( a, b ) { + return a.getOffset() - b.getOffset(); + } ); + } + return nodes; +}; + +/** * Fix up data so it can safely be inserted into the document data at an offset. * * TODO: this function needs more work but it seems to work, mostly -- To view, visit https://gerrit.wikimedia.org/r/295349 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I51ae4491c26851f9a590825bff962c917bc77ee1 Gerrit-PatchSet: 1 Gerrit-Project: VisualEditor/VisualEditor Gerrit-Branch: master Gerrit-Owner: Esanders <esand...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits