Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(121)

Side by Side Diff: chrome/test/data/webui/md_bookmarks/store_test.js

Issue 2639453002: [MD Bookmarks] Add Select for Bookmarks. (Closed)
Patch Set: some more clean up Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 suite('<bookmarks-store>', function() { 5 suite('<bookmarks-store>', function() {
6 var store; 6 var store;
7 var TEST_TREE; 7 var TEST_TREE;
8 8
9 setup(function() { 9 setup(function() {
10 TEST_TREE = createFolder('0', [ 10 TEST_TREE = createFolder('0', [
11 createFolder( 11 createFolder(
12 '1', 12 '1',
13 [ 13 [
14 createItem('2', {url: 'link2'}), 14 createItem('2', {url: 'link2'}),
15 createFolder('3', []), 15 createFolder('3', []),
16 createItem('6', {url: 'link4'}),
17 createItem('7', {url: 'link5'}),
16 ]), 18 ]),
17 createItem('4', {url: 'link4'}), 19 createItem('4', {url: 'link4'}),
18 createItem('5', {url: 'link5'}), 20 createItem('5', {url: 'link5'}),
19 ]); 21 ]);
20 22
21 store = document.createElement('bookmarks-store'); 23 store = document.createElement('bookmarks-store');
22 replaceBody(store); 24 replaceBody(store);
23 store.setupStore_(TEST_TREE); 25 store.setupStore_(TEST_TREE);
24 }); 26 });
25 27
(...skipping 24 matching lines...) Expand all
50 }); 52 });
51 53
52 test('correct paths generated for nodes', function() { 54 test('correct paths generated for nodes', function() {
53 var TEST_PATHS = { 55 var TEST_PATHS = {
54 '0': 'rootNode', 56 '0': 'rootNode',
55 '1': 'rootNode.children.#0', 57 '1': 'rootNode.children.#0',
56 '2': 'rootNode.children.#0.children.#0', 58 '2': 'rootNode.children.#0.children.#0',
57 '3': 'rootNode.children.#0.children.#1', 59 '3': 'rootNode.children.#0.children.#1',
58 '4': 'rootNode.children.#1', 60 '4': 'rootNode.children.#1',
59 '5': 'rootNode.children.#2', 61 '5': 'rootNode.children.#2',
62 '6': 'rootNode.children.#0.children.#2',
63 '7': 'rootNode.children.#0.children.#3',
60 }; 64 };
61 65
62 for (var id in store.idToNodeMap_) 66 for (var id in store.idToNodeMap_)
63 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path); 67 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path);
64 }); 68 });
65 69
66 test('store updates on selected event', function() { 70 test('store updates on selected event', function() {
67 // First child of root is selected by default. 71 // First child of root is selected by default.
68 assertEquals('1', store.selectedId); 72 assertEquals('1', store.selectedId);
69 assertTrue(store.idToNodeMap_['1'].isSelected); 73 assertTrue(store.idToNodeMap_['1'].isSelectedFolder);
70 74
71 // Selecting a selected folder doesn't deselect it. 75 // Selecting a selected folder doesn't deselect it.
72 store.fire('selected-folder-changed', '1'); 76 store.fire('selected-folder-changed', '1');
73 assertEquals('1', store.selectedId); 77 assertEquals('1', store.selectedId);
74 assertTrue(store.idToNodeMap_['1'].isSelected); 78 assertTrue(store.idToNodeMap_['1'].isSelectedFolder);
75 79
76 // Select a deeply nested descendant. 80 // Select a deeply nested descendant.
77 store.fire('selected-folder-changed', '3'); 81 store.fire('selected-folder-changed', '3');
78 assertEquals('3', store.selectedId); 82 assertEquals('3', store.selectedId);
79 assertTrue(store.idToNodeMap_['3'].isSelected); 83 assertTrue(store.idToNodeMap_['3'].isSelectedFolder);
80 assertFalse(store.idToNodeMap_['1'].isSelected); 84 assertFalse(store.idToNodeMap_['1'].isSelectedFolder);
81 85
82 // Select a folder in separate subtree. 86 // Select a folder in separate subtree.
83 store.fire('selected-folder-changed', '5'); 87 store.fire('selected-folder-changed', '5');
84 assertEquals('5', store.selectedId); 88 assertEquals('5', store.selectedId);
85 assertTrue(store.idToNodeMap_['5'].isSelected); 89 assertTrue(store.idToNodeMap_['5'].isSelectedFolder);
86 assertFalse(store.idToNodeMap_['3'].isSelected); 90 assertFalse(store.idToNodeMap_['3'].isSelectedFolder);
87 }); 91 });
88 92
89 test('store updates on open and close', function() { 93 test('store updates on open and close', function() {
90 // All folders are open by default. 94 // All folders are open by default.
91 for (var id in store.idToNodeMap_) { 95 for (var id in store.idToNodeMap_) {
92 if (store.idToNodeMap_[id].url) 96 if (store.idToNodeMap_[id].url)
93 continue; 97 continue;
94 98
95 assertTrue(store.idToNodeMap_[id].isOpen); 99 assertTrue(store.idToNodeMap_[id].isOpen);
96 } 100 }
97 101
98 // Closing a folder doesn't close any descendants. 102 // Closing a folder doesn't close any descendants.
99 store.fire('folder-open-changed', {id: '1', open: false}); 103 store.fire('folder-open-changed', {id: '1', open: false});
100 assertFalse(store.idToNodeMap_['1'].isOpen); 104 assertFalse(store.idToNodeMap_['1'].isOpen);
101 assertTrue(store.idToNodeMap_['3'].isOpen); 105 assertTrue(store.idToNodeMap_['3'].isOpen);
102 store.fire('folder-open-changed', {id: '1', open: true}); 106 store.fire('folder-open-changed', {id: '1', open: true});
103 107
104 // Closing an ancestor folder of a selected folder selects the ancestor. 108 // Closing an ancestor folder of a selected folder selects the ancestor.
105 store.fire('selected-folder-changed', '3'); 109 store.fire('selected-folder-changed', '3');
106 store.fire('folder-open-changed', {id: '1', open: false}); 110 store.fire('folder-open-changed', {id: '1', open: false});
107 assertFalse(store.idToNodeMap_['1'].isOpen); 111 assertFalse(store.idToNodeMap_['1'].isOpen);
108 assertEquals('1', store.selectedId); 112 assertEquals('1', store.selectedId);
109 assertTrue(store.idToNodeMap_['1'].isSelected); 113 assertTrue(store.idToNodeMap_['1'].isSelectedFolder);
110 assertFalse(store.idToNodeMap_['3'].isSelected); 114 assertFalse(store.idToNodeMap_['3'].isSelectedFolder);
111 }); 115 });
112 116
113 test('deleting a node updates the tree', function() { 117 test('deleting a node updates the tree', function() {
118 var DELETE_RESULTS = [createFolder('0', [
119 createFolder(
120 '1',
121 [
122 createItem('2', {url: 'link2'}),
123 createFolder('3', []),
124 createItem('6', {url: 'link4'}),
125 createItem('7', {url: 'link5'}),
126 ]),
127 createItem('5', {url: 'link5'}),
128 ])];
129 chrome.bookmarks.getSubTree = function(parentId, callback) {
130 callback(DELETE_RESULTS);
131 }
114 // Remove an empty folder/bookmark. 132 // Remove an empty folder/bookmark.
115 store.onBookmarkRemoved_('4', {parentId: '0', index: '1'}); 133 store.onBookmarkRemoved_('4', {parentId: '0', index: 1});
116 134
117 // Check the tree is correct. 135 // Check the tree is correct.
118 assertEquals('5', store.rootNode.children[1].id); 136 assertEquals('5', store.rootNode.children[1].id);
119 137
120 // idToNodeMap_ has been updated. 138 // idToNodeMap_ has been updated.
121 assertEquals(undefined, store.idToNodeMap_['4']); 139 assertEquals(undefined, store.idToNodeMap_['4']);
122 assertEquals(store.rootNode.children[1], store.idToNodeMap_['5']); 140 assertEquals(store.rootNode.children[1], store.idToNodeMap_['5']);
123 141
124 // Paths have been updated. 142 // Paths have been updated.
125 var TEST_PATHS = { 143 var TEST_PATHS = {
126 '0': 'rootNode', 144 '0': 'rootNode',
127 '1': 'rootNode.children.#0', 145 '1': 'rootNode.children.#0',
128 '2': 'rootNode.children.#0.children.#0', 146 '2': 'rootNode.children.#0.children.#0',
129 '3': 'rootNode.children.#0.children.#1', 147 '3': 'rootNode.children.#0.children.#1',
130 '5': 'rootNode.children.#1', 148 '5': 'rootNode.children.#1',
149 '6': 'rootNode.children.#0.children.#2',
150 '7': 'rootNode.children.#0.children.#3',
131 }; 151 };
132 152
133 for (var id in store.idToNodeMap_) 153 for (var id in store.idToNodeMap_)
134 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path); 154 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path);
135 155
136 // Remove a folder with children. 156 // Remove a folder with children.
157 DELETE_RESULTS = [createFolder('0', [
tsergeant 2017/01/25 06:02:13 Overwriting this is a bit strange -- the ALLCAPS_N
jiaxi 2017/01/30 03:28:59 Done.
158 createItem('5', {url: 'link5'}),
159 ])];
160
137 store.onBookmarkRemoved_('1', {parentId: '0', index: '0'}); 161 store.onBookmarkRemoved_('1', {parentId: '0', index: '0'});
138 162
139 // Check the tree is correct. 163 // Check the tree is correct.
140 assertEquals('5', store.rootNode.children[0].id); 164 assertEquals('5', store.rootNode.children[0].id);
141 165
142 // idToNodeMap_ has been updated. 166 // idToNodeMap_ has been updated.
143 assertEquals(undefined, store.idToNodeMap_['1']); 167 assertEquals(undefined, store.idToNodeMap_['1']);
144 assertEquals(undefined, store.idToNodeMap_['2']); 168 assertEquals(undefined, store.idToNodeMap_['2']);
145 assertEquals(undefined, store.idToNodeMap_['3']); 169 assertEquals(undefined, store.idToNodeMap_['3']);
146 assertEquals(undefined, store.idToNodeMap_['4']); 170 assertEquals(undefined, store.idToNodeMap_['4']);
147 assertEquals(store.rootNode.children[0], store.idToNodeMap_['5']); 171 assertEquals(store.rootNode.children[0], store.idToNodeMap_['5']);
148 172
149 // Paths have been updated. 173 // Paths have been updated.
150 TEST_PATHS = { 174 TEST_PATHS = {
151 '0': 'rootNode', 175 '0': 'rootNode',
152 '5': 'rootNode.children.#0', 176 '5': 'rootNode.children.#0',
153 }; 177 };
154 178
155 for (var id in store.idToNodeMap_) 179 for (var id in store.idToNodeMap_)
156 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path); 180 assertEquals(TEST_PATHS[id], store.idToNodeMap_[id].path);
157 }); 181 });
158 182
159 test('selectedId updates after removing a selected folder', function() { 183 test('selectedId updates after removing a selected folder', function() {
160 // Selected folder gets removed. 184 // Selected folder gets removed.
161 store.selectedId = '2'; 185 store.selectedId = '2';
186 var DELETE_RESULTS = [createFolder('1', [
187 createFolder('3', []),
188 createItem('6', {url: 'link4'}),
189 createItem('7', {url: 'link5'}),
190 ])];
191 chrome.bookmarks.getSubTree = function(parentId, callback) {
192 callback(DELETE_RESULTS);
193 }
194
162 store.onBookmarkRemoved_('2', {parentId:'1', index:'0'}); 195 store.onBookmarkRemoved_('2', {parentId:'1', index:'0'});
163 assertTrue(store.idToNodeMap_['1'].isSelected); 196 assertTrue(store.idToNodeMap_['1'].isSelectedFolder);
164 assertEquals('1', store.selectedId); 197 assertEquals('1', store.selectedId);
165 198
166 // A folder with selected folder in it gets removed. 199 // A folder with selected folder in it gets removed.
200 DELETE_RESULTS = [createFolder('0', [
201 createItem('4', {url: 'link4'}),
202 createItem('5', {url: 'link5'}),
203 ])];
204
167 store.selectedId = '3'; 205 store.selectedId = '3';
168 store.onBookmarkRemoved_('1', {parentId:'0', index:'0'}); 206 store.onBookmarkRemoved_('1', {parentId:'0', index:'0'});
169 assertTrue(store.idToNodeMap_['0'].isSelected); 207 assertTrue(store.idToNodeMap_['0'].isSelectedFolder);
170 assertEquals('0', store.selectedId); 208 assertEquals('0', store.selectedId);
171 }); 209 });
172 210
173 test('displayedList updates after searchTerm changes', function() { 211 test('displayedList updates after searchTerm changes', function() {
174 var SEARCH_RESULTS = [ 212 var SEARCH_RESULTS = [
175 'cat', 213 createItem('1', {title: 'cat'}),
176 'apple', 214 createItem('2', {title: 'apple'}),
177 'Paris', 215 createItem('3', {title: 'paris'}),
178 ]; 216 ];
217 chrome.bookmarks.search = function(searchTerm, callback) {
tsergeant 2017/01/25 06:02:13 You're gonna need to rebase to pick up Angela's ch
jiaxi 2017/01/30 03:28:59 I've merged Angela's patch and it took a while to
218 callback(SEARCH_RESULTS);
219 };
179 220
180 chrome.bookmarks.search = function(searchTerm, callback) { 221 // Search for a non-empty string.
181 callback(SEARCH_RESULTS); 222 store.searchTerm = 'a';
182 }; 223 assertFalse(store.rootNode.children[0].isSelectedFolder);
224 assertEquals(null, store.selectedId);
225 assertEquals(SEARCH_RESULTS, store.displayedList);
183 226
184 // Search for a non-empty string. 227 // Clear the searchTerm.
185 store.searchTerm = 'a'; 228 store.searchTerm = '';
186 assertFalse(store.rootNode.children[0].isSelected); 229 var defaultFolder = store.rootNode.children[0];
187 assertEquals(null, store.selectedId); 230 assertTrue(defaultFolder.isSelectedFolder);
188 assertEquals(SEARCH_RESULTS, store.displayedList); 231 assertEquals(defaultFolder.id, store.selectedId);
232 assertEquals(defaultFolder.children, store.displayedList);
189 233
190 // Clear the searchTerm. 234 // Search with no bookmarks returned.
191 store.searchTerm = ''; 235 chrome.bookmarks.search = function(searchTerm, callback) {
192 var defaultFolder = store.rootNode.children[0]; 236 callback([]);
193 assertTrue(defaultFolder.isSelected); 237 };
194 assertEquals(defaultFolder.id, store.selectedId); 238 store.searchTerm = 'asdf';
195 assertEquals(defaultFolder.children, store.displayedList); 239 assertEquals(0, store.displayedList.length);
196
197 // Search with no bookmarks returned.
198 var EMPTY_RESULT = [];
199 chrome.bookmarks.search = function(searchTerm, callback) {
200 callback(EMPTY_RESULT);
201 };
202 store.searchTerm = 'asdf';
203 assertEquals(EMPTY_RESULT, store.displayedList);
204 }); 240 });
205 241
206 test('bookmark gets updated after editing', function() { 242 test('bookmark gets updated after editing', function() {
207 // Edit title updates idToNodeMap_ properly. 243 // Edit title updates idToNodeMap_ properly.
208 store.onBookmarkChanged_('4', {'title': 'test'}); 244 store.onBookmarkChanged_('4', {'title': 'test'});
209 assertEquals('test', store.idToNodeMap_['4'].title); 245 assertEquals('test', store.idToNodeMap_['4'].title);
210 assertEquals('link4', store.idToNodeMap_['4'].url); 246 assertEquals('link4', store.idToNodeMap_['4'].url);
211 247
212 // Edit url updates idToNodeMap_ properly. 248 // Edit url updates idToNodeMap_ properly.
213 store.onBookmarkChanged_('5', {'url': 'http://www.google.com'}); 249 store.onBookmarkChanged_('5', {'url': 'http://www.google.com'});
214 assertEquals('', store.idToNodeMap_['5'].title); 250 assertEquals('', store.idToNodeMap_['5'].title);
215 assertEquals('http://www.google.com', store.idToNodeMap_['5'].url); 251 assertEquals('http://www.google.com', store.idToNodeMap_['5'].url);
216 252
217 // Edit url and title updates idToNodeMap_ properly. 253 // Edit url and title updates idToNodeMap_ properly.
218 store.onBookmarkChanged_('2', { 254 store.onBookmarkChanged_('2', {
219 'title': 'test', 255 'title': 'test',
220 'url': 'http://www.google.com', 256 'url': 'http://www.google.com',
221 }); 257 });
222 assertEquals('test', store.idToNodeMap_['2'].title); 258 assertEquals('test', store.idToNodeMap_['2'].title);
223 assertEquals('http://www.google.com', store.idToNodeMap_['2'].url); 259 assertEquals('http://www.google.com', store.idToNodeMap_['2'].url);
224 }); 260 });
261
262 test('single select selects the correct bookmark', function() {
263 for (var id in store.idToNodeMap_) {
264 assertFalse(store.idToNodeMap_[id].isSelectedItem);
265 }
266
267 store.fire('select-item', {item: store.idToNodeMap_['2']});
268 assertDeepEquals(
269 [true, false, false, false],
270 store.displayedList.map(i => i.isSelectedItem));
271 assertEquals(0, store.anchorIndex_);
272
273 // Select other item will remove the previous selection.
274 store.fire('select-item', {item: store.idToNodeMap_['3']});
275 assertDeepEquals(
276 [false, true, false, false],
277 store.displayedList.map(i => i.isSelectedItem));
278 assertEquals(1, store.anchorIndex_);
279
280 // Delete the selected item will select the next item.
281 store.fire('select-item', {item: store.idToNodeMap_['2']});
282 var DELETE_RESULTS = [createFolder('1', [
283 createFolder('3', []),
284 createItem('6', {url: 'link4'}),
285 createItem('7', {url: 'link5'}),
286 ])];
287 chrome.bookmarks.getSubTree = function(parentId, callback) {
288 callback(DELETE_RESULTS);
289 }
290 store.onBookmarkRemoved_('2', {parentId: '1', index: 0});
291 assertDeepEquals(
292 [true, false, false],
293 store.displayedList.map(i => i.isSelectedItem));
294 assertEquals(0, store.anchorIndex_);
295
296 // Delete the selected item at the end of the list will select the previous
297 // item.
298 store.fire('select-item', {item: store.idToNodeMap_['7']});
299 DELETE_RESULTS = [createFolder('1', [
300 createFolder('3', []),
301 createItem('6', {url: 'link4'}),
302 ])];
303 store.onBookmarkRemoved_('7', {parentId: '1', index: 2});
304 assertDeepEquals(
305 [false, true],
306 store.displayedList.map(i => i.isSelectedItem));
307 assertEquals(1, store.anchorIndex_);
308
309 // Changing the selected folder will remove the select status of the
310 // bookmark.
311 store.selectedId = '3';
312 assertDeepEquals(
313 [false, false],
314 store.idToNodeMap_['1'].children.map(i => i.isSelectedItem));
315 assertEquals(undefined, store.anchorIndex_);
316 });
317
318 test('shift select selects the correct bookmarks', function() {
319 // When nothing has been selected, it selects a single item.
320 assertEquals(undefined, store.anchorIndex_);
321 store.fire('select-item', {item: store.idToNodeMap_['6'], shiftKey: true});
322 assertDeepEquals(
323 [false, false, true, false],
324 store.displayedList.map(i => i.isSelectedItem));
325 assertEquals(2, store.anchorIndex_);
326
327 // Select an item below the previous selected item.
328 store.fire('select-item', {item: store.idToNodeMap_['7'], shiftKey: true});
329 assertEquals(2, store.anchorIndex_);
330 assertDeepEquals(
331 [false, false, true, true],
332 store.displayedList.map(i => i.isSelectedItem));
333
334 // Select an item above the previous selected item.
335 store.fire('select-item', {item: store.idToNodeMap_['2'], shiftKey: true});
336 assertEquals(2, store.anchorIndex_);
337 assertDeepEquals(
338 [true, true, true, false],
339 store.displayedList.map(i => i.isSelectedItem));
340 });
341
342 test('ctrl select selects the correct bookmarks', function() {
343 // When nothing has been selected, it selects a single item.
344 assertEquals(undefined, store.anchorIndex_);
345 store.fire('select-item', {item: store.idToNodeMap_['6'], ctrlKey: true});
346 assertDeepEquals(
347 [false, false, true, false],
348 store.displayedList.map(i => i.isSelectedItem));
349 assertEquals(2, store.anchorIndex_);
350
351 // Select a new item will not deselect the previous item, but will update
352 // anchorIndex_.
353 store.fire('select-item', {item: store.idToNodeMap_['2'], ctrlKey: true});
354 assertDeepEquals(
355 [true, false, true, false],
356 store.displayedList.map(i => i.isSelectedItem));
357 assertEquals(0, store.anchorIndex_);
358 });
359
360 test('selection in search mode', function() {
361 // Item gets unselected in search.
362 var SEARCH_RESULTS = [
363 createItem('4', {url: 'link4'}),
364 createItem('2', {url: 'link2'}),
365 createItem('5', {url: 'link5'}),
366 ];
367 chrome.bookmarks.search = function(searchTerm, callback) {
368 callback(SEARCH_RESULTS);
369 };
370
371 store.selectedId = '1';
372 store.fire('select-item', {item: store.idToNodeMap_['3']});
373 store.searchTerm = 'a';
374 assertFalse(store.idToNodeMap_['3'].isSelectedItem);
375 assertEquals(undefined, store.anchorIndex_);
376
377 // anchorIndex_ gets updated properly in single select.
378 store.fire('select-item', {item: store.displayedList[1]});
379 assertDeepEquals(
380 [undefined, true, undefined],
381 store.displayedList.map(i => i.isSelectedItem));
382 assertEquals(1, store.anchorIndex_);
383
384 // anchorIndex_ gets updated properly in ctrl select.
385 store.fire('select-item', {item: store.displayedList[0], ctrlKey: true});
386 assertDeepEquals(
387 [true, true, undefined],
388 store.displayedList.map(i => i.isSelectedItem));
389 assertEquals(0, store.anchorIndex_);
390
391 // Delete the selected item will select the next item.
392 store.fire('select-item', {item: store.displayedList[1]});
393 SEARCH_RESULTS = [
394 createItem('4', {url: 'link4'}),
395 createItem('5', {url: 'link5'}),
396 ];
397 var DELETE_RESULTS = [createFolder('1', [
398 createFolder('3', []),
399 createItem('6', {url: 'link4'}),
400 createItem('7', {url: 'link5'}),
401 ])];
402 chrome.bookmarks.getSubTree = function(parentId, callback) {
403 callback(DELETE_RESULTS);
404 }
405
406 store.onBookmarkRemoved_('2', {parentId: '1', index: 0});
407 assertDeepEquals(
408 [undefined, true],
409 store.displayedList.map(i => i.isSelectedItem));
410 assertEquals(1, store.anchorIndex_);
411
412 // Delete the selected item at the end of the list will select the previous
413 // item.
414 store.fire('select-item', {item: store.displayedList[1]});
415 SEARCH_RESULTS = [
416 createItem('4', {url: 'link4'}),
417 createItem('2', {url: 'link2'}),
418 ];
419 DELETE_RESULTS = [createFolder('0', [
420 createFolder(
421 '1',
422 [
423 createItem('2', {url: 'link2'}),
424 createFolder('3', []),
425 createItem('6', {url: 'link4'}),
426 createItem('7', {url: 'link5'}),
427 ]),
428 createItem('4', {url: 'link4'}),
429 ])];
430
431 assertDeepEquals(
432 [undefined, true],
433 store.displayedList.map(i => i.isSelectedItem));
434 assertEquals(1, store.anchorIndex_);
435 });
225 }); 436 });
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698