Index: trunk/parsers/wikidom/lib/hype/models/es.DocumentModel.js |
— | — | @@ -34,6 +34,33 @@ |
35 | 35 | es.DocumentModel.nodeModels = {}; |
36 | 36 | |
37 | 37 | /** |
| 38 | + * Mapping of symbolic names and nesting rules. |
| 39 | + * |
| 40 | + * Each rule is an object with a parents and children property. Each of these properties may contain |
| 41 | + * one of three possible values: |
| 42 | + * Array - List of allowed element types |
| 43 | + * Null - Any element type is allowed (as long as the other element also allows it) |
| 44 | + * Boolean False - No elements are allowed (used for nodes that can not have children) |
| 45 | + * |
| 46 | + * @example Paragraph rules |
| 47 | + * { |
| 48 | + * 'parents': null, |
| 49 | + * 'children': false |
| 50 | + * } |
| 51 | + * @example List rules |
| 52 | + * { |
| 53 | + * 'parents': null, |
| 54 | + * 'children': ['listItem'] |
| 55 | + * } |
| 56 | + * @example ListItem rules |
| 57 | + * { |
| 58 | + * 'parents': ['list'], |
| 59 | + * 'children': false |
| 60 | + * } |
| 61 | + */ |
| 62 | +es.DocumentModel.nodeRules = {}; |
| 63 | + |
| 64 | +/** |
38 | 65 | * Mapping of operation types to pure functions. |
39 | 66 | * |
40 | 67 | * Each function is called in the context of a state, and takes an operation object as a parameter. |
Index: trunk/parsers/wikidom/lib/hype/models/es.TableRowModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.tableRow = es.TableRowModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.listItem = { |
| 30 | + 'parents': ['table'], |
| 31 | + 'children': ['tableCell'] |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/models/es.ParagraphModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.paragraph = es.ParagraphModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.paragraph = { |
| 30 | + 'parents': null, |
| 31 | + 'children': false |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/models/es.TableCellModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.tableCell = es.TableCellModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.listItem = { |
| 30 | + 'parents': ['tableRow'], |
| 31 | + 'children': null |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/models/es.TableModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.table = es.TableModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.table = { |
| 30 | + 'parents': null, |
| 31 | + 'children': ['tableRow'] |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/models/es.ListItemModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.listItem = es.ListItemModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.listItem = { |
| 30 | + 'parents': ['list'], |
| 31 | + 'children': false |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/models/es.ListModel.js |
— | — | @@ -24,3 +24,8 @@ |
25 | 25 | /* Registration */ |
26 | 26 | |
27 | 27 | es.DocumentModel.nodeModels.list = es.ListModel; |
| 28 | + |
| 29 | +es.DocumentModel.nodeRules.list = { |
| 30 | + 'parents': null, |
| 31 | + 'children': ['listItem'] |
| 32 | +}; |
Index: trunk/parsers/wikidom/lib/hype/bases/es.DocumentNode.js |
— | — | @@ -123,33 +123,30 @@ |
124 | 124 | * |
125 | 125 | * @method |
126 | 126 | * @param {es.Range} range Range to select nodes within |
127 | | - * @param {Boolean} [off] Whether to include a list of nodes that are not covered by the range |
128 | 127 | * @returns {Object} Object with 'on' and 'off' properties, 'on' being a list of objects with 'node' |
129 | 128 | * and 'range' properties describing nodes which are covered by the range and the range within the |
130 | 129 | * node that is covered, and 'off' being a list of nodes that are not covered by the range |
131 | 130 | */ |
132 | | -es.DocumentNode.prototype.selectNodes = function( range, off ) { |
| 131 | +es.DocumentNode.prototype.selectNodes = function( range ) { |
133 | 132 | range.normalize(); |
134 | | - var result = { 'on': [], 'off': [] }; |
| 133 | + var nodes = []; |
135 | 134 | for ( var i = 0, length = this.length, left = 0, right; i < length; i++ ) { |
136 | 135 | right = left + this[i].getElementLength() + 1; |
137 | 136 | if ( range.start >= left && range.start < right ) { |
138 | 137 | if ( range.end < right ) { |
139 | | - result.on.push( { |
| 138 | + nodes.push( { |
140 | 139 | 'node': this[i], |
141 | 140 | 'range': new es.Range( range.start - left, range.end - left ) |
142 | 141 | } ); |
143 | | - if ( !off ) { |
144 | | - break; |
145 | | - } |
| 142 | + break; |
146 | 143 | } else { |
147 | | - result.on.push( { |
| 144 | + nodes.push( { |
148 | 145 | 'node': this[i], |
149 | 146 | 'range': new es.Range( range.start - left, right - left - 1 ) |
150 | 147 | } ); |
151 | 148 | } |
152 | 149 | } else if ( range.end >= left && range.end < right ) { |
153 | | - result.on.push( { |
| 150 | + nodes.push( { |
154 | 151 | 'node': this[i], |
155 | 152 | 'range': new es.Range( 0, range.end - left ) |
156 | 153 | } ); |
— | — | @@ -157,14 +154,12 @@ |
158 | 155 | break; |
159 | 156 | } |
160 | 157 | } else if ( left >= range.start && right <= range.end ) { |
161 | | - result.on.push( { |
| 158 | + nodes.push( { |
162 | 159 | 'node': this[i], |
163 | 160 | 'range': new es.Range( 0, right - left - 1 ) |
164 | 161 | } ); |
165 | | - } else if( off ) { |
166 | | - result.off.push( this[i] ); |
167 | 162 | } |
168 | 163 | left = right; |
169 | 164 | } |
170 | | - return result; |
| 165 | + return nodes; |
171 | 166 | }; |
Index: trunk/parsers/wikidom/lib/hype/bases/es.DocumentViewBranchNode.js |
— | — | @@ -32,14 +32,17 @@ |
33 | 33 | * @param {es.Range} range Range of content to draw selection around |
34 | 34 | */ |
35 | 35 | es.DocumentViewBranchNode.prototype.drawSelection = function( range ) { |
36 | | - var nodes = this.selectNodes( range, true ), |
37 | | - i; |
38 | | - for ( i = 0; i < nodes.on.length; i++ ) { |
39 | | - nodes.on[i].node.drawSelection( nodes.on[i].range ); |
| 36 | + var nodes = this.selectNodes( range, true ); |
| 37 | + for ( var i = 0; i < this.length; i++ ) { |
| 38 | + if ( nodes.length && this[i] === nodes[0] ) { |
| 39 | + for ( var j = 0; j < nodes.on.length; j++ ) { |
| 40 | + nodes.on[j].node.drawSelection( nodes.on[j].range ); |
| 41 | + i++; |
| 42 | + } |
| 43 | + } else { |
| 44 | + this[i].clearSelection(); |
| 45 | + } |
40 | 46 | } |
41 | | - for ( i = 0; i < nodes.off.length; i++ ) { |
42 | | - nodes.off[i].clearSelection(); |
43 | | - } |
44 | 47 | }; |
45 | 48 | |
46 | 49 | /** |