Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
seleniumhq
GitHub Repository: seleniumhq/selenium
Path: blob/trunk/third_party/closure/goog/datasource/fastdatanode.js
2868 views
1
// Copyright 2007 The Closure Library Authors. All Rights Reserved.
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
// http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS-IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
15
/**
16
* @fileoverview
17
* Efficient implementation of DataNode API.
18
*
19
* The implementation consists of three concrete classes for modelling
20
* DataNodes with different characteristics: FastDataNode,
21
* FastPrimitiveDataNode and FastListNode.
22
*
23
* FastDataNode is for bean-like or map-like objects that consists of
24
* key/value mappings and where the primary access pattern is by key.
25
*
26
* FastPrimitiveDataNode wraps primitives like strings, boolean, and numbers.
27
*
28
* FastListNode is for array-like data nodes. It also supports key-based
29
* lookups if the data nodes have an "id" property or if child nodes are
30
* explicitly added by name. It is most efficient if these features are not
31
* used.
32
*
33
* FastDataNodes can be constructed from JSON-like objects via the function
34
* goog.ds.FastDataNode.fromJs.
35
36
*/
37
38
goog.provide('goog.ds.AbstractFastDataNode');
39
goog.provide('goog.ds.FastDataNode');
40
goog.provide('goog.ds.FastListNode');
41
goog.provide('goog.ds.PrimitiveFastDataNode');
42
43
goog.require('goog.ds.DataManager');
44
goog.require('goog.ds.DataNodeList');
45
goog.require('goog.ds.EmptyNodeList');
46
goog.require('goog.string');
47
48
/*
49
* Implementation note: In order to reduce the number of objects,
50
* FastDataNode stores its key/value mappings directly in the FastDataNode
51
* object iself (instead of a separate map). To make this work we have to
52
* sure that there are no name clashes with other attribute names used by
53
* FastDataNode (like dataName and parent). This is especially difficult in
54
* the light of automatic renaming by the JavaScript compiler. For this reason,
55
* all internal attributes start with "__" so that they are not renamed
56
* by the compiler.
57
*/
58
59
/**
60
* Creates a new abstract data node.
61
* @param {string} dataName Name of the datanode.
62
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
63
* @constructor
64
* @extends {goog.ds.DataNodeList}
65
*/
66
// TODO(arv): Use interfaces when available.
67
goog.ds.AbstractFastDataNode = function(dataName, opt_parent) {
68
if (!dataName) {
69
throw Error('Cannot create a fast data node without a data name');
70
}
71
this['__dataName'] = dataName;
72
this['__parent'] = opt_parent;
73
};
74
75
76
/**
77
* Return the name of this data node.
78
* @return {string} Name of this data noden.
79
* @override
80
*/
81
goog.ds.AbstractFastDataNode.prototype.getDataName = function() {
82
return this['__dataName'];
83
};
84
85
86
/**
87
* Set the name of this data node.
88
* @param {string} value Name.
89
* @override
90
*/
91
goog.ds.AbstractFastDataNode.prototype.setDataName = function(value) {
92
this['__dataName'] = value;
93
};
94
95
96
/**
97
* Get the path leading to this data node.
98
* @return {string} Data path.
99
* @override
100
*/
101
goog.ds.AbstractFastDataNode.prototype.getDataPath = function() {
102
var parentPath;
103
if (this['__parent']) {
104
parentPath = this['__parent'].getDataPath() + goog.ds.STR_PATH_SEPARATOR;
105
} else {
106
parentPath = '';
107
}
108
return parentPath + this.getDataName();
109
};
110
111
112
113
/**
114
* Creates a new fast data node, using the properties of root.
115
* @param {Object} root JSON-like object to initialize data node from.
116
* @param {string} dataName Name of this data node.
117
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
118
* @extends {goog.ds.AbstractFastDataNode}
119
* @constructor
120
*/
121
goog.ds.FastDataNode = function(root, dataName, opt_parent) {
122
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
123
this.extendWith(root);
124
};
125
goog.inherits(goog.ds.FastDataNode, goog.ds.AbstractFastDataNode);
126
127
128
/**
129
* Add all attributes of object to this data node.
130
* @param {Object} object Object to add attributes from.
131
* @protected
132
*/
133
goog.ds.FastDataNode.prototype.extendWith = function(object) {
134
for (var key in object) {
135
this[key] = object[key];
136
}
137
};
138
139
140
/**
141
* Creates a new FastDataNode structure initialized from object. This will
142
* return an instance of the most suitable sub-class of FastDataNode.
143
*
144
* You should not modify object after creating a fast data node from it
145
* or assume that changing object changes the data node. Doing so results
146
* in undefined behaviour.
147
*
148
* @param {Object|number|boolean|string} object Object to initialize data
149
* node from.
150
* @param {string} dataName Name of data node.
151
* @param {goog.ds.DataNode=} opt_parent Parent of data node.
152
* @return {!goog.ds.AbstractFastDataNode} Data node representing object.
153
*/
154
goog.ds.FastDataNode.fromJs = function(object, dataName, opt_parent) {
155
if (goog.isArray(object)) {
156
return new goog.ds.FastListNode(object, dataName, opt_parent);
157
} else if (goog.isObject(object)) {
158
return new goog.ds.FastDataNode(object, dataName, opt_parent);
159
} else {
160
return new goog.ds.PrimitiveFastDataNode(
161
object || !!object, dataName, opt_parent);
162
}
163
};
164
165
166
/**
167
* Static instance of an empty list.
168
* @type {!goog.ds.EmptyNodeList}
169
* @private
170
*/
171
goog.ds.FastDataNode.emptyList_ = new goog.ds.EmptyNodeList();
172
173
174
/**
175
* Not supported for normal FastDataNodes.
176
* @param {*} value Value to set data node to.
177
* @override
178
*/
179
goog.ds.FastDataNode.prototype.set = function(value) {
180
throw new Error('Not implemented yet');
181
};
182
183
184
/** @override */
185
goog.ds.FastDataNode.prototype.getChildNodes = function(opt_selector) {
186
if (!opt_selector || opt_selector == goog.ds.STR_ALL_CHILDREN_SELECTOR) {
187
return this;
188
} else if (opt_selector.indexOf(goog.ds.STR_WILDCARD) == -1) {
189
var child = this.getChildNode(opt_selector);
190
return child ? new goog.ds.FastListNode([child], '') :
191
new goog.ds.EmptyNodeList();
192
} else {
193
throw Error('Unsupported selector: ' + opt_selector);
194
}
195
};
196
197
198
/**
199
* Makes sure that a named child is wrapped in a data node structure.
200
* @param {string} name Name of child to wrap.
201
* @private
202
*/
203
goog.ds.FastDataNode.prototype.wrapChild_ = function(name) {
204
var child = this[name];
205
if (child != null && !child.getDataName) {
206
this[name] = goog.ds.FastDataNode.fromJs(this[name], name, this);
207
}
208
};
209
210
211
/**
212
* Get a child node by name.
213
* @param {string} name Name of child node.
214
* @param {boolean=} opt_create Whether to create the child if it does not
215
* exist.
216
* @return {goog.ds.DataNode} Child node.
217
* @override
218
*/
219
goog.ds.FastDataNode.prototype.getChildNode = function(name, opt_create) {
220
this.wrapChild_(name);
221
// this[name] always is a data node object, so using "||" is fine.
222
var child = this[name] || null;
223
if (child == null && opt_create) {
224
child = new goog.ds.FastDataNode({}, name, this);
225
this[name] = child;
226
}
227
return child;
228
};
229
230
231
/**
232
* Sets a child node. Creates the child if it does not exist.
233
*
234
* Calling this function makes any child nodes previously obtained for name
235
* invalid. You should not use these child nodes but instead obtain a new
236
* instance by calling getChildNode.
237
*
238
* @override
239
*/
240
goog.ds.FastDataNode.prototype.setChildNode = function(name, value) {
241
if (value != null) {
242
this[name] = value;
243
} else {
244
delete this[name];
245
}
246
goog.ds.DataManager.getInstance().fireDataChange(
247
this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + name);
248
return null;
249
};
250
251
252
/**
253
* Returns the value of a child node. By using this method you can avoid
254
* the need to create PrimitiveFastData nodes.
255
* @param {string} name Name of child node.
256
* @return {Object} Value of child node.
257
* @override
258
*/
259
goog.ds.FastDataNode.prototype.getChildNodeValue = function(name) {
260
var child = this[name];
261
if (child != null) {
262
return (child.getDataName ? child.get() : child);
263
} else {
264
return null;
265
}
266
};
267
268
269
/**
270
* Returns whether this data node is a list. Always returns false for
271
* instances of FastDataNode but may return true for subclasses.
272
* @return {boolean} Whether this data node is array-like.
273
* @override
274
*/
275
goog.ds.FastDataNode.prototype.isList = function() {
276
return false;
277
};
278
279
280
/**
281
* Returns a javascript object representation of this data node. You should
282
* not modify the object returned by this function.
283
* @return {!Object} Javascript object representation of this data node.
284
*/
285
goog.ds.FastDataNode.prototype.getJsObject = function() {
286
var result = {};
287
for (var key in this) {
288
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
289
result[key] =
290
(this[key]['__dataName'] ? this[key].getJsObject() : this[key]);
291
}
292
}
293
return result;
294
};
295
296
297
/**
298
* Creates a deep copy of this data node.
299
* @return {goog.ds.FastDataNode} Clone of this data node.
300
*/
301
goog.ds.FastDataNode.prototype.clone = function() {
302
return /** @type {!goog.ds.FastDataNode} */ (
303
goog.ds.FastDataNode.fromJs(this.getJsObject(), this.getDataName()));
304
};
305
306
307
/*
308
* Implementation of goog.ds.DataNodeList for FastDataNode.
309
*/
310
311
312
/**
313
* Adds a child to this data node.
314
* @param {goog.ds.DataNode} value Child node to add.
315
* @override
316
*/
317
goog.ds.FastDataNode.prototype.add = function(value) {
318
this.setChildNode(value.getDataName(), value);
319
};
320
321
322
/**
323
* Gets the value of this data node (if called without opt_key) or
324
* gets a child node (if called with opt_key).
325
* @param {string=} opt_key Name of child node.
326
* @return {*} This data node or a child node.
327
* @override
328
*/
329
goog.ds.FastDataNode.prototype.get = function(opt_key) {
330
if (!goog.isDef(opt_key)) {
331
// if there is no key, DataNode#get was called
332
return this;
333
} else {
334
return this.getChildNode(opt_key);
335
}
336
};
337
338
339
/**
340
* Gets a child node by index. This method has a complexity of O(n) where
341
* n is the number of children. If you need a faster implementation of this
342
* method, you should use goog.ds.FastListNode.
343
* @param {number} index Index of child node (starting from 0).
344
* @return {goog.ds.DataNode} Child node at specified index.
345
* @override
346
*/
347
goog.ds.FastDataNode.prototype.getByIndex = function(index) {
348
var i = 0;
349
for (var key in this) {
350
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
351
if (i == index) {
352
this.wrapChild_(key);
353
return this[key];
354
}
355
++i;
356
}
357
}
358
return null;
359
};
360
361
362
/**
363
* Gets the number of child nodes. This method has a complexity of O(n) where
364
* n is the number of children. If you need a faster implementation of this
365
* method, you should use goog.ds.FastListNode.
366
* @return {number} Number of child nodes.
367
* @override
368
*/
369
goog.ds.FastDataNode.prototype.getCount = function() {
370
var count = 0;
371
for (var key in this) {
372
if (!goog.string.startsWith(key, '__') && !goog.isFunction(this[key])) {
373
++count;
374
}
375
}
376
// maybe cache this?
377
return count;
378
};
379
380
381
/**
382
* Sets a child node.
383
* @param {string} name Name of child node.
384
* @param {Object} value Value of child node.
385
* @override
386
*/
387
goog.ds.FastDataNode.prototype.setNode = function(name, value) {
388
this.setChildNode(name, value);
389
};
390
391
392
/**
393
* Removes a child node.
394
* @override
395
*/
396
goog.ds.FastDataNode.prototype.removeNode = function(name) {
397
delete this[name];
398
return false;
399
};
400
401
402
403
/**
404
* Creates a new data node wrapping a primitive value.
405
* @param {number|boolean|string} value Value the value to wrap.
406
* @param {string} dataName name Name of this data node.
407
* @param {goog.ds.DataNode=} opt_parent Parent of this data node.
408
* @extends {goog.ds.AbstractFastDataNode}
409
* @constructor
410
* @final
411
*/
412
goog.ds.PrimitiveFastDataNode = function(value, dataName, opt_parent) {
413
this.value_ = value;
414
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
415
};
416
goog.inherits(goog.ds.PrimitiveFastDataNode, goog.ds.AbstractFastDataNode);
417
418
419
/**
420
* Returns the value of this data node.
421
* @return {(boolean|number|string)} Value of this data node.
422
* @override
423
*/
424
goog.ds.PrimitiveFastDataNode.prototype.get = function() {
425
return this.value_;
426
};
427
428
429
/**
430
* Sets this data node to a new value.
431
* @param {*} value Value to set data node to.
432
* @override
433
*/
434
goog.ds.PrimitiveFastDataNode.prototype.set = function(value) {
435
if (goog.isArray(value) || goog.isObject(value)) {
436
throw Error('can only set PrimitiveFastDataNode to primitive values');
437
}
438
this.value_ = value;
439
goog.ds.DataManager.getInstance().fireDataChange(this.getDataPath());
440
};
441
442
443
/**
444
* Returns child nodes of this data node. Always returns an unmodifiable,
445
* empty list.
446
* @return {!goog.ds.DataNodeList} (Empty) list of child nodes.
447
* @override
448
*/
449
goog.ds.PrimitiveFastDataNode.prototype.getChildNodes = function() {
450
return goog.ds.FastDataNode.emptyList_;
451
};
452
453
454
/**
455
* Get a child node by name. Always returns null.
456
* @param {string} name Name of child node.
457
* @return {goog.ds.DataNode} Child node.
458
* @override
459
*/
460
goog.ds.PrimitiveFastDataNode.prototype.getChildNode = function(name) {
461
return null;
462
};
463
464
465
/**
466
* Returns the value of a child node. Always returns null.
467
* @param {string} name Name of child node.
468
* @return {Object} Value of child node.
469
* @override
470
*/
471
goog.ds.PrimitiveFastDataNode.prototype.getChildNodeValue = function(name) {
472
return null;
473
};
474
475
476
/**
477
* Not supported by primitive data nodes.
478
* @param {string} name Name of child node.
479
* @param {Object} value Value of child node.
480
* @override
481
*/
482
goog.ds.PrimitiveFastDataNode.prototype.setChildNode = function(name, value) {
483
throw Error('Cannot set a child node for a PrimitiveFastDataNode');
484
};
485
486
487
/**
488
* Returns whether this data node is a list. Always returns false for
489
* instances of PrimitiveFastDataNode.
490
* @return {boolean} Whether this data node is array-like.
491
* @override
492
*/
493
goog.ds.PrimitiveFastDataNode.prototype.isList = function() {
494
return false;
495
};
496
497
498
/**
499
* Returns a javascript object representation of this data node. You should
500
* not modify the object returned by this function.
501
* @return {*} Javascript object representation of this data node.
502
*/
503
goog.ds.PrimitiveFastDataNode.prototype.getJsObject = function() {
504
return this.value_;
505
};
506
507
508
/**
509
* Creates a new list node from an array.
510
* @param {Array<?>} values values hold by this list node.
511
* @param {string} dataName name of this node.
512
* @param {goog.ds.DataNode=} opt_parent parent of this node.
513
* @extends {goog.ds.AbstractFastDataNode}
514
* @constructor
515
* @final
516
*/
517
// TODO(arv): Use interfaces when available. This implements DataNodeList
518
// as well.
519
goog.ds.FastListNode = function(values, dataName, opt_parent) {
520
this.values_ = [];
521
for (var i = 0; i < values.length; ++i) {
522
var name = values[i].id || ('[' + i + ']');
523
this.values_.push(goog.ds.FastDataNode.fromJs(values[i], name, this));
524
if (values[i].id) {
525
if (!this.map_) {
526
this.map_ = {};
527
}
528
this.map_[values[i].id] = i;
529
}
530
}
531
goog.ds.AbstractFastDataNode.call(this, dataName, opt_parent);
532
};
533
goog.inherits(goog.ds.FastListNode, goog.ds.AbstractFastDataNode);
534
535
536
/**
537
* Not supported for FastListNodes.
538
* @param {*} value Value to set data node to.
539
* @override
540
*/
541
goog.ds.FastListNode.prototype.set = function(value) {
542
throw Error('Cannot set a FastListNode to a new value');
543
};
544
545
546
/**
547
* Returns child nodes of this data node. Currently, only supports
548
* returning all children.
549
* @return {!goog.ds.DataNodeList} List of child nodes.
550
* @override
551
*/
552
goog.ds.FastListNode.prototype.getChildNodes = function() {
553
return this;
554
};
555
556
557
/**
558
* Get a child node by name.
559
* @param {string} key Name of child node.
560
* @param {boolean=} opt_create Whether to create the child if it does not
561
* exist.
562
* @return {goog.ds.DataNode} Child node.
563
* @override
564
*/
565
goog.ds.FastListNode.prototype.getChildNode = function(key, opt_create) {
566
var index = this.getKeyAsNumber_(key);
567
if (index == null && this.map_) {
568
index = this.map_[key];
569
}
570
if (index != null && this.values_[index]) {
571
return this.values_[index];
572
} else if (opt_create) {
573
this.setChildNode(key, {});
574
return this.getChildNode(key);
575
} else {
576
return null;
577
}
578
};
579
580
581
/**
582
* Returns the value of a child node.
583
* @param {string} key Name of child node.
584
* @return {*} Value of child node.
585
* @override
586
*/
587
goog.ds.FastListNode.prototype.getChildNodeValue = function(key) {
588
var child = this.getChildNode(key);
589
return (child ? child.get() : null);
590
};
591
592
593
/**
594
* Tries to interpret key as a numeric index enclosed by square brakcets.
595
* @param {string} key Key that should be interpreted as a number.
596
* @return {?number} Numeric index or null if key is not of the form
597
* described above.
598
* @private
599
*/
600
goog.ds.FastListNode.prototype.getKeyAsNumber_ = function(key) {
601
if (key.charAt(0) == '[' && key.charAt(key.length - 1) == ']') {
602
return Number(key.substring(1, key.length - 1));
603
} else {
604
return null;
605
}
606
};
607
608
609
/**
610
* Sets a child node. Creates the child if it does not exist. To set
611
* children at a certain index, use a key of the form '[index]'. Note, that
612
* you can only set values at existing numeric indices. To add a new node
613
* to this list, you have to use the add method.
614
*
615
* Calling this function makes any child nodes previously obtained for name
616
* invalid. You should not use these child nodes but instead obtain a new
617
* instance by calling getChildNode.
618
*
619
* @override
620
*/
621
goog.ds.FastListNode.prototype.setChildNode = function(key, value) {
622
var count = this.values_.length;
623
if (value != null) {
624
if (!value.getDataName) {
625
value = goog.ds.FastDataNode.fromJs(value, key, this);
626
}
627
var index = this.getKeyAsNumber_(key);
628
if (index != null) {
629
if (index < 0 || index >= this.values_.length) {
630
throw Error('List index out of bounds: ' + index);
631
}
632
// NOTE: This code here appears to want to use "index" rather than
633
// "key" here (which would be better for an array. However, changing
634
// that would require knowing that there wasn't a mix of non-number
635
// keys, as using index that would risk overwriting those values if
636
// they were set first. Instead we loosen the type so we can use
637
// strings as indexes.
638
639
/** @type {!Object} */
640
var values = this.values_;
641
642
values[key] = value;
643
} else {
644
if (!this.map_) {
645
this.map_ = {};
646
}
647
this.values_.push(value);
648
this.map_[key] = this.values_.length - 1;
649
}
650
} else {
651
this.removeNode(key);
652
}
653
var dm = goog.ds.DataManager.getInstance();
654
dm.fireDataChange(this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + key);
655
if (this.values_.length != count) {
656
this.listSizeChanged_();
657
}
658
return null;
659
};
660
661
662
/**
663
* Fire data changes that are appropriate when the size of this list changes.
664
* Should be called whenever the list size has changed.
665
* @private
666
*/
667
goog.ds.FastListNode.prototype.listSizeChanged_ = function() {
668
var dm = goog.ds.DataManager.getInstance();
669
dm.fireDataChange(this.getDataPath());
670
dm.fireDataChange(
671
this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + 'count()');
672
};
673
674
675
/**
676
* Returns whether this data node is a list. Always returns true.
677
* @return {boolean} Whether this data node is array-like.
678
* @override
679
*/
680
goog.ds.FastListNode.prototype.isList = function() {
681
return true;
682
};
683
684
685
/**
686
* Returns a javascript object representation of this data node. You should
687
* not modify the object returned by this function.
688
* @return {!Object} Javascript object representation of this data node.
689
*/
690
goog.ds.FastListNode.prototype.getJsObject = function() {
691
var result = [];
692
for (var i = 0; i < this.values_.length; ++i) {
693
result.push(this.values_[i].getJsObject());
694
}
695
return result;
696
};
697
698
699
/*
700
* Implementation of goog.ds.DataNodeList for FastListNode.
701
*/
702
703
704
/**
705
* Adds a child to this data node
706
* @param {goog.ds.DataNode} value Child node to add.
707
* @override
708
*/
709
goog.ds.FastListNode.prototype.add = function(value) {
710
if (!value.getDataName) {
711
value = goog.ds.FastDataNode.fromJs(
712
value, String('[' + (this.values_.length) + ']'), this);
713
}
714
this.values_.push(value);
715
var dm = goog.ds.DataManager.getInstance();
716
dm.fireDataChange(
717
this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + '[' +
718
(this.values_.length - 1) + ']');
719
this.listSizeChanged_();
720
};
721
722
723
/**
724
* Gets the value of this data node (if called without opt_key) or
725
* gets a child node (if called with opt_key).
726
* @param {string=} opt_key Name of child node.
727
* @return {Array|goog.ds.DataNode} Array of child nodes (if called without
728
* opt_key), or a named child node otherwise.
729
* @override
730
*/
731
goog.ds.FastListNode.prototype.get = function(opt_key) {
732
// if there are no arguments, DataNode.get was called
733
if (!goog.isDef(opt_key)) {
734
return this.values_;
735
} else {
736
return this.getChildNode(opt_key);
737
}
738
};
739
740
741
/**
742
* Gets a child node by (numeric) index.
743
* @param {number} index Index of child node (starting from 0).
744
* @return {goog.ds.DataNode} Child node at specified index.
745
* @override
746
*/
747
goog.ds.FastListNode.prototype.getByIndex = function(index) {
748
var child = this.values_[index];
749
return (child != null ? child : null); // never return undefined
750
};
751
752
753
/**
754
* Gets the number of child nodes.
755
* @return {number} Number of child nodes.
756
* @override
757
*/
758
goog.ds.FastListNode.prototype.getCount = function() {
759
return this.values_.length;
760
};
761
762
763
/**
764
* Sets a child node.
765
* @param {string} name Name of child node.
766
* @param {Object} value Value of child node.
767
* @override
768
*/
769
goog.ds.FastListNode.prototype.setNode = function(name, value) {
770
throw Error('Setting child nodes of a FastListNode is not implemented, yet');
771
};
772
773
774
/**
775
* Removes a child node.
776
* @override
777
*/
778
goog.ds.FastListNode.prototype.removeNode = function(name) {
779
var index = this.getKeyAsNumber_(name);
780
if (index == null && this.map_) {
781
index = this.map_[name];
782
}
783
if (index != null) {
784
this.values_.splice(index, 1);
785
if (this.map_) {
786
var keyToDelete = null;
787
for (var key in this.map_) {
788
if (this.map_[key] == index) {
789
keyToDelete = key;
790
} else if (this.map_[key] > index) {
791
--this.map_[key];
792
}
793
}
794
if (keyToDelete) {
795
delete this.map_[keyToDelete];
796
}
797
}
798
var dm = goog.ds.DataManager.getInstance();
799
dm.fireDataChange(
800
this.getDataPath() + goog.ds.STR_PATH_SEPARATOR + '[' + index + ']');
801
this.listSizeChanged_();
802
}
803
return false;
804
};
805
806
807
/**
808
* Returns the index of a named child nodes. This method only works if
809
* this list uses mixed name/indexed lookup, i.e. if its child node have
810
* an 'id' attribute.
811
* @param {string} name Name of child node to determine index of.
812
* @return {number} Index of child node named name.
813
*/
814
goog.ds.FastListNode.prototype.indexOf = function(name) {
815
var index = this.getKeyAsNumber_(name);
816
if (index == null && this.map_) {
817
index = this.map_[name];
818
}
819
if (index == null) {
820
throw Error('Cannot determine index for: ' + name);
821
}
822
return /** @type {number} */ (index);
823
};
824
825