r102675 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r102674‎ | r102675 | r102676 >
Date:19:26, 10 November 2011
Author:tparscal
Status:deferred
Tags:
Comment:
Added es.DocumentLeafNode, which like es.DocumentBranchNode is a mixin-like class (we may want to switch to using a more natural composition mechanism than es.extendClass in the future) - now es.DocumentNode also has an abstract method called hasChildren which returns a boolean and can indicate if a node is a leaf or a branch.
Modified paths:
  • /trunk/extensions/VisualEditor/demo/index.html (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentBranchNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentLeafNode.js (added) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentModelBranchNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentModelLeafNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentViewBranchNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/modules/es/bases/es.DocumentViewLeafNode.js (modified) (history)
  • /trunk/extensions/VisualEditor/tests/es/index.html (modified) (history)

Diff [purge]

Index: trunk/extensions/VisualEditor/tests/es/index.html
@@ -23,8 +23,9 @@
2424 <!-- Bases -->
2525 <script src="../../modules/es/bases/es.EventEmitter.js"></script>
2626 <script src="../../modules/es/bases/es.DocumentNode.js"></script>
 27+ <script src="../../modules/es/bases/es.DocumentModelNode.js"></script>
2728 <script src="../../modules/es/bases/es.DocumentBranchNode.js"></script>
28 - <script src="../../modules/es/bases/es.DocumentModelNode.js"></script>
 29+ <script src="../../modules/es/bases/es.DocumentLeafNode.js"></script>
2930 <script src="../../modules/es/bases/es.DocumentModelBranchNode.js"></script>
3031 <script src="../../modules/es/bases/es.DocumentModelLeafNode.js"></script>
3132
Index: trunk/extensions/VisualEditor/demo/index.html
@@ -69,8 +69,9 @@
7070 <!-- Bases -->
7171 <script src="../modules/es/bases/es.EventEmitter.js"></script>
7272 <script src="../modules/es/bases/es.DocumentNode.js"></script>
 73+ <script src="../modules/es/bases/es.DocumentModelNode.js"></script>
7374 <script src="../modules/es/bases/es.DocumentBranchNode.js"></script>
74 - <script src="../modules/es/bases/es.DocumentModelNode.js"></script>
 75+ <script src="../modules/es/bases/es.DocumentLeafNode.js"></script>
7576 <script src="../modules/es/bases/es.DocumentModelBranchNode.js"></script>
7677 <script src="../modules/es/bases/es.DocumentModelLeafNode.js"></script>
7778 <script src="../modules/es/bases/es.DocumentViewNode.js"></script>
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentViewLeafNode.js
@@ -4,12 +4,14 @@
55 * @class
66 * @abstract
77 * @constructor
 8+ * @extends {es.DocumentLeafNode}
89 * @extends {es.DocumentViewNode}
910 * @param model {es.ModelNode} Model to observe
1011 * @param {jQuery} [$element] Element to use as a container
1112 */
1213 es.DocumentViewLeafNode = function( model, $element ) {
1314 // Inheritance
 15+ es.DocumentLeafNode.call( this );
1416 es.DocumentViewNode.call( this, model, $element );
1517
1618 // Properties
@@ -80,4 +82,5 @@
8183
8284 /* Inheritance */
8385
 86+es.extendClass( es.DocumentViewLeafNode, es.DocumentLeafNode );
8487 es.extendClass( es.DocumentViewLeafNode, es.DocumentViewNode );
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentLeafNode.js
@@ -0,0 +1,23 @@
 2+/**
 3+ * Creates an es.DocumentLeafNode object.
 4+ *
 5+ * @class
 6+ * @abstract
 7+ * @constructor
 8+ */
 9+es.DocumentLeafNode = function() {
 10+ //
 11+};
 12+
 13+/* Methods */
 14+
 15+/**
 16+ * Checks if this node has child nodes.
 17+ *
 18+ * @method
 19+ * @see {es.DocumentNode.prototype.hasChildren}
 20+ * @returns {Boolean} Whether this node has children
 21+ */
 22+es.DocumentLeafNode.prototype.hasChildren = function() {
 23+ return false;
 24+};
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentModelLeafNode.js
@@ -4,14 +4,15 @@
55 * @class
66 * @abstract
77 * @constructor
 8+ * @extends {es.DocumentLeafNode}
89 * @extends {es.DocumentModelNode}
9 - * @extends {es.DocumentNode}
1010 * @param {String} type Symbolic name of node type
1111 * @param {Object} element Element object in document data
1212 * @param {Integer} [length] Length of content data in document
1313 */
1414 es.DocumentModelLeafNode = function( type, element, length ) {
1515 // Inheritance
 16+ es.DocumentLeafNode.call( this );
1617 es.DocumentModelNode.call( this, type, element, length );
1718
1819 // Properties
@@ -80,4 +81,5 @@
8182
8283 /* Inheritance */
8384
 85+es.extendClass( es.DocumentModelLeafNode, es.DocumentLeafNode );
8486 es.extendClass( es.DocumentModelLeafNode, es.DocumentModelNode );
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentViewBranchNode.js
@@ -4,15 +4,15 @@
55 * @class
66 * @abstract
77 * @constructor
 8+ * @extends {es.DocumentBranchNode}
89 * @extends {es.DocumentViewNode}
9 - * @extends {es.DocumentBranchNode}
1010 * @param model {es.ModelNode} Model to observe
1111 * @param {jQuery} [$element] Element to use as a container
1212 */
1313 es.DocumentViewBranchNode = function( model, $element, horizontal ) {
1414 // Inheritance
 15+ es.DocumentBranchNode.call( this );
1516 es.DocumentViewNode.call( this, model, $element );
16 - es.DocumentBranchNode.call( this );
1717
1818 // Properties
1919 this.horizontal = horizontal || false;
@@ -243,5 +243,5 @@
244244
245245 /* Inheritance */
246246
 247+es.extendClass( es.DocumentViewBranchNode, es.DocumentBranchNode );
247248 es.extendClass( es.DocumentViewBranchNode, es.DocumentViewNode );
248 -es.extendClass( es.DocumentViewBranchNode, es.DocumentBranchNode );
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentBranchNode.js
@@ -13,6 +13,17 @@
1414 /* Methods */
1515
1616 /**
 17+ * Checks if this node has child nodes.
 18+ *
 19+ * @method
 20+ * @see {es.DocumentNode.prototype.hasChildren}
 21+ * @returns {Boolean} Whether this node has children
 22+ */
 23+es.DocumentBranchNode.prototype.hasChildren = function() {
 24+ return true;
 25+};
 26+
 27+/**
1728 * Gets a list of child nodes.
1829 *
1930 * @abstract
@@ -33,21 +44,21 @@
3445 */
3546 es.DocumentBranchNode.prototype.getRangeFromNode = function( node, shallow ) {
3647 if ( this.children.length ) {
37 - var isBranch;
 48+ var childNode;
3849 for ( var i = 0, length = this.children.length, left = 0; i < length; i++ ) {
39 - if ( this.children[i] === node ) {
40 - return new es.Range( left, left + this.children[i].getElementLength() );
 50+ childNode = this.children[i];
 51+ if ( childNode === node ) {
 52+ return new es.Range( left, left + childNode.getElementLength() );
4153 }
42 - isBranch = typeof this.children[i].getChildren === 'function';
43 - if ( !shallow && isBranch && this.children[i].getChildren().length ) {
44 - var range = this.children[i].getRangeFromNode( node );
 54+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
 55+ var range = childNode.getRangeFromNode( node );
4556 if ( range !== null ) {
4657 // Include opening of parent
4758 left++;
4859 return es.Range.newFromTranslatedRange( range, left );
4960 }
5061 }
51 - left += this.children[i].getElementLength();
 62+ left += childNode.getElementLength();
5263 }
5364 }
5465 return null;
@@ -69,19 +80,19 @@
7081 es.DocumentBranchNode.prototype.getOffsetFromNode = function( node, shallow ) {
7182 if ( this.children.length ) {
7283 var offset = 0,
73 - isBranch;
 84+ childNode;
7485 for ( var i = 0, length = this.children.length; i < length; i++ ) {
75 - if ( this.children[i] === node ) {
 86+ childNode = this.children[i];
 87+ if ( childNode === node ) {
7688 return offset;
7789 }
78 - isBranch = typeof this.children[i].getChildren === 'function';
79 - if ( !shallow && isBranch && this.children[i].getChildren().length ) {
80 - var childOffset = this.getOffsetFromNode.call( this.children[i], node );
 90+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
 91+ var childOffset = this.getOffsetFromNode.call( childNode, node );
8192 if ( childOffset !== -1 ) {
8293 return offset + 1 + childOffset;
8394 }
8495 }
85 - offset += this.children[i].getElementLength();
 96+ offset += childNode.getElementLength();
8697 }
8798 }
8899 return -1;
@@ -105,20 +116,20 @@
106117 if ( this.children.length ) {
107118 var nodeOffset = 0,
108119 nodeLength,
109 - isBranch;
 120+ childNode;
110121 for ( var i = 0, length = this.children.length; i < length; i++ ) {
 122+ childNode = this.children[i];
111123 if ( offset == nodeOffset ) {
112 - // The requested offset is right before this.children[i],
 124+ // The requested offset is right before childNode,
113125 // so it's not inside any of this's children, but inside this
114126 return this;
115127 }
116 - nodeLength = this.children[i].getElementLength();
 128+ nodeLength = childNode.getElementLength();
117129 if ( offset >= nodeOffset && offset < nodeOffset + nodeLength ) {
118 - isBranch = typeof this.children[i].getChildren === 'function';
119 - if ( !shallow && isBranch && this.children[i].getChildren().length ) {
120 - return this.getNodeFromOffset.call( this.children[i], offset - nodeOffset - 1 );
 130+ if ( !shallow && childNode.hasChildren() && childNode.getChildren().length ) {
 131+ return this.getNodeFromOffset.call( childNode, offset - nodeOffset - 1 );
121132 } else {
122 - return this.children[i];
 133+ return childNode;
123134 }
124135 }
125136 nodeOffset += nodeLength;
@@ -155,7 +166,8 @@
156167 start = range.start,
157168 end = range.end,
158169 startInside,
159 - endInside;
 170+ endInside,
 171+ childNode;
160172
161173 if ( start < 0 ) {
162174 throw 'The start offset of the range is negative';
@@ -173,20 +185,21 @@
174186 // This node has children, loop over them
175187 left = 1; // First offset inside the first child. Offset 0 is before the first child
176188 for ( i = 0; i < this.children.length; i++ ) {
177 - // left <= any offset inside this.children[i] <= right
178 - right = left + this.children[i].getContentLength();
 189+ childNode = this.children[i];
 190+ // left <= any offset inside childNode <= right
 191+ right = left + childNode.getContentLength();
179192
180193 if ( start == end && ( start == left - 1 || start == right + 1 ) ) {
181194 // Empty range outside of any node
182195 return [];
183196 }
184197
185 - startInside = start >= left && start <= right; // is the start inside this.children[i]?
186 - endInside = end >= left && end <= right; // is the end inside this.children[i]?
 198+ startInside = start >= left && start <= right; // is the start inside childNode?
 199+ endInside = end >= left && end <= right; // is the end inside childNode?
187200
188201 if ( startInside && endInside ) {
189 - // The range is entirely inside this.children[i]
190 - if ( shallow || !this.children[i].children ) {
 202+ // The range is entirely inside childNode
 203+ if ( shallow || !childNode.children ) {
191204 // For leaf nodes, use the same behavior as for shallow calls.
192205 // A proper recursive function would let the recursion handle this,
193206 // but the leaves don't have .selectNodes() because they're not DocumentBranchNodes
@@ -194,14 +207,14 @@
195208 // TODO should probably rewrite this recursive function as an iterative function anyway, probably faster
196209 nodes = [
197210 {
198 - 'node': this.children[i],
 211+ 'node': childNode,
199212 'range': new es.Range( start - left, end - left ),
200213 'globalRange': new es.Range( start, end )
201214 }
202215 ];
203216 } else {
204 - // Recurse into this.children[i]
205 - nodes = this.children[i].selectNodes( new es.Range( start - left, end - left ) );
 217+ // Recurse into childNode
 218+ nodes = childNode.selectNodes( new es.Range( start - left, end - left ) );
206219 // Adjust globalRange
207220 for ( j = 0; j < nodes.length; j++ ) {
208221 if ( nodes[j].globalRange !== undefined ) {
@@ -209,48 +222,48 @@
210223 }
211224 }
212225 }
213 - // Since the start and end are both inside this.children[i], we know for sure that we're
 226+ // Since the start and end are both inside childNode, we know for sure that we're
214227 // done, so return
215228 return nodes;
216229 } else if ( startInside ) {
217 - // The start is inside this.children[i] but the end isn't
218 - // Add a range from the start of the range to the end of this.children[i]
 230+ // The start is inside childNode but the end isn't
 231+ // Add a range from the start of the range to the end of childNode
219232 nodes.push( {
220 - 'node': this.children[i],
 233+ 'node': childNode,
221234 'range': new es.Range( start - left, right - left ),
222235 'globalRange': new es.Range( start, right )
223236 } );
224237 } else if ( endInside ) {
225 - // The end is inside this.children[i] but the start isn't
226 - // Add a range from the start of this.children[i] to the end of the range
 238+ // The end is inside childNode but the start isn't
 239+ // Add a range from the start of childNode to the end of the range
227240 nodes.push( {
228 - 'node': this.children[i],
 241+ 'node': childNode,
229242 'range': new es.Range( 0, end - left ),
230243 'globalRange': new es.Range( left, end )
231244 } );
232245 // We've found the end, so we're done
233246 return nodes;
234247 } else if ( end == right + 1 ) {
235 - // end is between this.children[i] and this.children[i+1]
236 - // start is not inside this.children[i], so the selection covers
237 - // all of this.children[i], then ends
238 - nodes.push( { 'node': this.children[i] } );
 248+ // end is between childNode and this.children[i+1]
 249+ // start is not inside childNode, so the selection covers
 250+ // all of childNode, then ends
 251+ nodes.push( { 'node': childNode } );
239252 // We've reached the end so we're done
240253 return nodes;
241254 } else if ( start == left - 1 ) {
242 - // start is between this.children[i-1] and this.children[i]
243 - // end is not inside this.children[i], so the selection covers
244 - // all of this.children[i] and more
245 - nodes.push( { 'node': this.children[i] } );
 255+ // start is between this.children[i-1] and childNode
 256+ // end is not inside childNode, so the selection covers
 257+ // all of childNode and more
 258+ nodes.push( { 'node': childNode } );
246259 } else if ( nodes.length > 0 ) {
247 - // Neither the start nor the end is inside this.children[i], but nodes is non-empty,
248 - // so this.children[i] must be between the start and the end
 260+ // Neither the start nor the end is inside childNode, but nodes is non-empty,
 261+ // so childNode must be between the start and the end
249262 // Add the entire node, so no range property
250 - nodes.push( { 'node': this.children[i] } );
 263+ nodes.push( { 'node': childNode } );
251264 }
252265
253266 // Move left to the start of this.children[i+1] for the next iteration
254 - // We use +2 because we need to jump over the offset between this.children[i] and
 267+ // We use +2 because we need to jump over the offset between childNode and
255268 // this.children[i+1]
256269 left = right + 2;
257270 if ( end < left ) {
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentModelBranchNode.js
@@ -4,16 +4,16 @@
55 * @class
66 * @abstract
77 * @constructor
 8+ * @extends {es.DocumentBranchNode}
89 * @extends {es.DocumentModelNode}
9 - * @extends {es.DocumentBranchNode}
1010 * @param {String} type Symbolic name of node type
1111 * @param {Object} element Element object in document data
1212 * @param {es.DocumentModelBranchNode[]} [contents] List of child nodes to append
1313 */
1414 es.DocumentModelBranchNode = function( type, element, contents ) {
1515 // Inheritance
 16+ es.DocumentBranchNode.call( this );
1617 es.DocumentModelNode.call( this, type, element, 0 );
17 - es.DocumentBranchNode.call( this );
1818
1919 // Child nodes
2020 if ( es.isArray( contents ) ) {
@@ -240,5 +240,5 @@
241241
242242 /* Inheritance */
243243
 244+es.extendClass( es.DocumentModelBranchNode, es.DocumentBranchNode );
244245 es.extendClass( es.DocumentModelBranchNode, es.DocumentModelNode );
245 -es.extendClass( es.DocumentModelBranchNode, es.DocumentBranchNode );
Index: trunk/extensions/VisualEditor/modules/es/bases/es.DocumentNode.js
@@ -23,6 +23,7 @@
2424 * Gets the content length.
2525 *
2626 * @method
 27+ * @abstract
2728 * @returns {Integer} Length of content
2829 */
2930 es.DocumentNode.prototype.getContentLength = function() {
@@ -33,12 +34,24 @@
3435 * Gets the element length.
3536 *
3637 * @method
 38+ * @abstract
3739 * @returns {Integer} Length of content
3840 */
3941 es.DocumentNode.prototype.getElementLength = function() {
4042 throw 'DocumentNode.getElementLength not implemented in this subclass:' + this.constructor;
4143 };
4244
 45+/**
 46+ * Checks if this node has child nodes.
 47+ *
 48+ * @method
 49+ * @abstract
 50+ * @returns {Boolean} Whether this node has children
 51+ */
 52+es.DocumentNode.prototype.hasChildren = function() {
 53+ throw 'DocumentNode.hasChildren not implemented in this subclass:' + this.constructor;
 54+};
 55+
4356 /* Inheritance */
4457
4558 es.extendClass( es.DocumentNode, es.EventEmitter );

Status & tagging log