jenkins-bot has submitted this change and it was merged.

Change subject: Reduce code duplication for annotation rendering
......................................................................


Reduce code duplication for annotation rendering

ve.dm.Converter and ve.ce.ContentBranchNode were duplicating a fair bit
of logic for annotation rendering. Moved the annotation opening and
closing logic into ve.dm.Converter.openAndCloseAnnotations, and
implemented both annotation rendering code paths in terms of that
function with callbacks for caller-specific behavior.

Change-Id: I7cba7d2fda7002287b07949a1b8120ba80bfe854
---
M modules/ve/ce/ve.ce.ContentBranchNode.js
M modules/ve/dm/ve.dm.Converter.js
2 files changed, 95 insertions(+), 90 deletions(-)

Approvals:
  Esanders: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/modules/ve/ce/ve.ce.ContentBranchNode.js 
b/modules/ve/ce/ve.ce.ContentBranchNode.js
index e7afb4e..8c589a7 100644
--- a/modules/ve/ce/ve.ce.ContentBranchNode.js
+++ b/modules/ve/ce/ve.ce.ContentBranchNode.js
@@ -55,12 +55,24 @@
  * @returns {jQuery}
  */
 ve.ce.ContentBranchNode.prototype.getRenderedContents = function () {
-       var i, j, itemHtml, itemAnnotations, startClosingAt, arr, annotation, 
$ann,
+       var i, itemHtml, itemAnnotations, $ann,
                store = this.model.doc.getStore(),
                annotationStack = new ve.dm.AnnotationSet( store ),
                annotatedHtml = [],
                $wrapper = $( '<div>' ),
                $current = $wrapper;
+
+       function openAnnotation( annotation ) {
+               // Create a new DOM node and descend into it
+               $ann = ve.ce.annotationFactory.create( annotation.getType(), 
annotation ).$;
+               $current.append( $ann );
+               $current = $ann;
+       }
+
+       function closeAnnotation() {
+               // Traverse up
+               $current = $current.parent();
+       }
 
        // Gather annotated HTML from the child nodes
        for ( i = 0; i < this.children.length; i++ ) {
@@ -77,43 +89,9 @@
                        itemAnnotations = new ve.dm.AnnotationSet( store );
                }
 
-               // FIXME code largely copied from ve.dm.Converter
-               // Close annotations as needed
-               // Go through annotationStack from bottom to top (low to high),
-               // and find the first annotation that's not in annotations.
-               startClosingAt = undefined;
-               arr = annotationStack.get();
-               for ( j = 0; j < arr.length; j++ ) {
-                       annotation = arr[j];
-                       if ( !itemAnnotations.contains( annotation ) ) {
-                               startClosingAt = j;
-                               break;
-                       }
-               }
-               if ( startClosingAt !== undefined ) {
-                       // Close all annotations from top to bottom (high to 
low)
-                       // until we reach startClosingAt
-                       for ( j = annotationStack.getLength() - 1; j >= 
startClosingAt; j-- ) {
-                               // Traverse up
-                               $current = $current.parent();
-                               // Remove from annotationStack
-                               annotationStack.removeAt( j );
-                       }
-               }
-
-               // Open annotations as needed
-               arr = itemAnnotations.get();
-               for ( j = 0; j < arr.length; j++ ) {
-                       annotation = arr[j];
-                       if ( !annotationStack.contains( annotation ) ) {
-                               // Create new node and descend into it
-                               $ann = ve.ce.annotationFactory.create( 
annotation.getType(), annotation ).$;
-                               $current.append( $ann );
-                               $current = $ann;
-                               // Add to annotationStack
-                               annotationStack.push( annotation );
-                       }
-               }
+               ve.dm.Converter.openAndCloseAnnotations( annotationStack, 
itemAnnotations,
+                       openAnnotation, closeAnnotation
+               );
 
                // Output the actual HTML
                $current.append( itemHtml );
diff --git a/modules/ve/dm/ve.dm.Converter.js b/modules/ve/dm/ve.dm.Converter.js
index 3c60157..8b23684 100644
--- a/modules/ve/dm/ve.dm.Converter.js
+++ b/modules/ve/dm/ve.dm.Converter.js
@@ -35,16 +35,63 @@
  * @returns {Array} Linear model data, one element per character
  */
 ve.dm.Converter.getDataContentFromText = function ( text, annotations ) {
-       var i, characters = text.split( '' );
+       var i, len, characters = text.split( '' );
        if ( !annotations || annotations.isEmpty() ) {
                return characters;
        }
        // Apply annotations to characters
-       for ( i = 0; i < characters.length; i++ ) {
+       for ( i = 0, len = characters.length; i < len; i++ ) {
                // Just store the annotations' indexes from the index-value 
store
                characters[i] = [characters[i], 
annotations.getIndexes().slice()];
        }
        return characters;
+};
+
+/**
+ * Utility function for annotation rendering. Transforms one set of 
annotations into another
+ * by opening and closing annotations. Each time an annotation is opened or 
closed, the associated
+ * callback is called with the annotation passed as a parameter.
+ *
+ * Note that currentSet will be modified, and will be equal to targetSet once 
this function returns.
+ *
+ * @param {ve.dm.AnnotationSet} currentSet The set of annotations currently 
opened. Will be modified.
+ * @param {ve.dm.AnnotationSet} targetSet The set of annotations we want to 
have.
+ * @param {Function} open Callback called when an annotation is opened. Passed 
a ve.dm.Annotation.
+ * @param {Function} close Callback called when an annotation is closed. 
Passed a ve.dm.Annotation.
+ */
+ve.dm.Converter.openAndCloseAnnotations = function ( currentSet, targetSet, 
open, close ) {
+       var i, len, arr, annotation, startClosingAt;
+       // Close annotations as needed
+       // Go through annotationStack from bottom to top (low to high),
+       // and find the first annotation that's not in annotations.
+       arr = currentSet.get();
+       for ( i = 0, len = arr.length; i < len; i++ ) {
+               annotation = arr[i];
+               if ( !targetSet.contains( annotation ) ) {
+                       startClosingAt = i;
+                       break;
+               }
+       }
+       if ( startClosingAt !== undefined ) {
+               // Close all annotations from top to bottom (high to low)
+               // until we reach startClosingAt
+               for ( i = currentSet.getLength() - 1; i >= startClosingAt; i-- 
) {
+                       close( arr[i] );
+                       // Remove from currentClone
+                       currentSet.removeAt( i );
+               }
+       }
+
+       // Open annotations as needed
+       arr = targetSet.get();
+       for ( i = 0, len = arr.length; i < len; i++ ) {
+               annotation = arr[i];
+               if ( !currentSet.contains( annotation ) ) {
+                       open( annotation );
+                       // Add to currentClone
+                       currentSet.push( annotation );
+               }
+       }
 };
 
 /* Methods */
@@ -549,13 +596,38 @@
  * @returns {HTMLDocument} Document containing the resulting HTML
  */
 ve.dm.Converter.prototype.getDomFromData = function ( store, data ) {
-       var text, i, j, k, annotations, annotation, annotationElement, 
dataElement, arr,
-               childDomElements, pre, ours, theirs, parentDomElement, 
lastChild, startClosingAt,
+       var text, i, j, k, annotations, annotationElement, dataElement,
+               childDomElements, pre, ours, theirs, parentDomElement, 
lastChild,
                isContentNode, changed, parentChanged, sibling, 
previousSiblings, doUnwrap, textNode,
+               conv = this,
                doc = ve.createDocumentFromHTML( '' ),
                container = doc.body,
                domElement = container,
                annotationStack = new ve.dm.AnnotationSet( store );
+
+       function openAnnotation( annotation ) {
+               // Add text if needed
+               if ( text.length > 0 ) {
+                       domElement.appendChild( doc.createTextNode( text ) );
+                       text = '';
+               }
+               // Create new node and descend into it
+               annotationElement = conv.getDomElementsFromDataElement(
+                       annotation.getElement(), doc
+               )[0];
+               domElement.appendChild( annotationElement );
+               domElement = annotationElement;
+       }
+
+       function closeAnnotation() {
+               // Add text if needed
+               if ( text.length > 0 ) {
+                       domElement.appendChild( doc.createTextNode( text ) );
+                       text = '';
+               }
+               // Traverse up
+               domElement = domElement.parentNode;
+       }
 
        for ( i = 0; i < data.length; i++ ) {
                if ( typeof data[i] === 'string' ) {
@@ -591,54 +663,9 @@
                                annotations = new ve.dm.AnnotationSet(
                                        store, store.values( 
data[i].annotations || data[i][1] )
                                );
-                               // Close annotations as needed
-                               // Go through annotationStack from bottom to 
top (low to high),
-                               // and find the first annotation that's not in 
annotations.
-                               startClosingAt = undefined;
-                               arr = annotationStack.get();
-                               for ( j = 0; j < arr.length; j++ ) {
-                                       annotation = arr[j];
-                                       if ( !annotations.contains( annotation 
) ) {
-                                               startClosingAt = j;
-                                               break;
-                                       }
-                               }
-                               if ( startClosingAt !== undefined ) {
-                                       // Close all annotations from top to 
bottom (high to low)
-                                       // until we reach startClosingAt
-                                       for ( j = annotationStack.getLength() - 
1; j >= startClosingAt; j-- ) {
-                                               // Add text if needed
-                                               if ( text.length > 0 ) {
-                                                       domElement.appendChild( 
doc.createTextNode( text ) );
-                                                       text = '';
-                                               }
-                                               // Traverse up
-                                               domElement = 
domElement.parentNode;
-                                               // Remove from annotationStack
-                                               annotationStack.removeAt( j );
-                                       }
-                               }
-
-                               // Open annotations as needed
-                               arr = annotations.get();
-                               for ( j = 0; j < arr.length; j++ ) {
-                                       annotation = arr[j];
-                                       if ( !annotationStack.contains( 
annotation ) ) {
-                                               // Add text if needed
-                                               if ( text.length > 0 ) {
-                                                       domElement.appendChild( 
doc.createTextNode( text ) );
-                                                       text = '';
-                                               }
-                                               // Create new node and descend 
into it
-                                               annotationElement = 
this.getDomElementsFromDataElement(
-                                                       
annotation.getElement(), doc
-                                               )[0];
-                                               domElement.appendChild( 
annotationElement );
-                                               domElement = annotationElement;
-                                               // Add to annotationStack
-                                               annotationStack.push( 
annotation );
-                                       }
-                               }
+                               ve.dm.Converter.openAndCloseAnnotations( 
annotationStack, annotations,
+                                       openAnnotation, closeAnnotation
+                               );
 
                                if ( data[i].annotations === undefined ) {
                                        // Annotated text

-- 
To view, visit https://gerrit.wikimedia.org/r/57245
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I7cba7d2fda7002287b07949a1b8120ba80bfe854
Gerrit-PatchSet: 12
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Catrope <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Trevor Parscal <[email protected]>
Gerrit-Reviewer: jenkins-bot

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to