OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 // require: array_data_model.js | 5 // require: array_data_model.js |
6 // require: list_selection_model.js | 6 // require: list_selection_model.js |
7 // require: list_selection_controller.js | 7 // require: list_selection_controller.js |
8 // require: list_item.js | 8 // require: list_item.js |
9 | 9 |
10 /** | 10 /** |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
312 var length = this.dataModel ? this.dataModel.length : 0; | 312 var length = this.dataModel ? this.dataModel.length : 0; |
313 this.selectionModel = new ListSelectionModel(length); | 313 this.selectionModel = new ListSelectionModel(length); |
314 | 314 |
315 this.addEventListener('dblclick', this.handleDoubleClickOrTap_); | 315 this.addEventListener('dblclick', this.handleDoubleClickOrTap_); |
316 this.addEventListener('mousedown', this.handlePointerDownUp_); | 316 this.addEventListener('mousedown', this.handlePointerDownUp_); |
317 this.addEventListener('mouseup', this.handlePointerDownUp_); | 317 this.addEventListener('mouseup', this.handlePointerDownUp_); |
318 this.addEventListener('keydown', this.handleKeyDown); | 318 this.addEventListener('keydown', this.handleKeyDown); |
319 this.addEventListener('focus', this.handleElementFocus_, true); | 319 this.addEventListener('focus', this.handleElementFocus_, true); |
320 this.addEventListener('blur', this.handleElementBlur_, true); | 320 this.addEventListener('blur', this.handleElementBlur_, true); |
321 this.addEventListener('scroll', this.handleScroll.bind(this)); | 321 this.addEventListener('scroll', this.handleScroll.bind(this)); |
322 this.setAttribute('role', 'listbox'); | 322 this.setAttribute('role', 'list'); |
323 | 323 |
324 this.touchHandler_ = new cr.ui.TouchHandler(this); | 324 this.touchHandler_ = new cr.ui.TouchHandler(this); |
325 this.addEventListener(cr.ui.TouchHandler.EventType.TOUCH_START, | 325 this.addEventListener(cr.ui.TouchHandler.EventType.TOUCH_START, |
326 this.handlePointerDownUp_); | 326 this.handlePointerDownUp_); |
327 this.addEventListener(cr.ui.TouchHandler.EventType.TOUCH_END, | 327 this.addEventListener(cr.ui.TouchHandler.EventType.TOUCH_END, |
328 this.handlePointerDownUp_); | 328 this.handlePointerDownUp_); |
329 this.addEventListener(cr.ui.TouchHandler.EventType.TAP, | 329 this.addEventListener(cr.ui.TouchHandler.EventType.TAP, |
330 this.handleDoubleClickOrTap_); | 330 this.handleDoubleClickOrTap_); |
331 this.touchHandler_.enable(false, false); | 331 this.touchHandler_.enable(false, false); |
332 // Make list focusable | 332 // Make list focusable |
333 if (!this.hasAttribute('tabindex')) | 333 if (!this.hasAttribute('tabindex')) |
334 this.tabIndex = 0; | 334 this.tabIndex = 0; |
| 335 |
| 336 // Try to get an unique id prefix from the id of this element or the |
| 337 // nearest ancestor with an id. |
| 338 var element = this; |
| 339 while (element && !element.id) |
| 340 element = element.parentElement; |
| 341 if (element && element.id) |
| 342 this.uniqueIdPrefix_ = element.id; |
| 343 else |
| 344 this.uniqueIdPrefix_ = 'list'; |
| 345 |
| 346 // The next id suffix to use when giving each item an unique id. |
| 347 this.nextUniqueIdSuffix_ = 0; |
335 }, | 348 }, |
336 | 349 |
337 /** | 350 /** |
338 * @param {ListItem=} item The list item to measure. | 351 * @param {ListItem=} item The list item to measure. |
339 * @return {number} The height of the given item. If the fixed height on CSS | 352 * @return {number} The height of the given item. If the fixed height on CSS |
340 * is set by 'px', uses that value as height. Otherwise, measures the size. | 353 * is set by 'px', uses that value as height. Otherwise, measures the size. |
341 * @private | 354 * @private |
342 */ | 355 */ |
343 measureItemHeight_: function(item) { | 356 measureItemHeight_: function(item) { |
344 var height = item.style.height; | 357 var height = item.style.height; |
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
575 | 588 |
576 /** | 589 /** |
577 * Callback from the selection model. We dispatch {@code change} events | 590 * Callback from the selection model. We dispatch {@code change} events |
578 * when the selection changes. | 591 * when the selection changes. |
579 * @param {!cr.Event} e Event with change info. | 592 * @param {!cr.Event} e Event with change info. |
580 * @private | 593 * @private |
581 */ | 594 */ |
582 handleOnChange_: function(ce) { | 595 handleOnChange_: function(ce) { |
583 ce.changes.forEach(function(change) { | 596 ce.changes.forEach(function(change) { |
584 var listItem = this.getListItemByIndex(change.index); | 597 var listItem = this.getListItemByIndex(change.index); |
585 if (listItem) | 598 if (listItem) { |
586 listItem.selected = change.selected; | 599 listItem.selected = change.selected; |
| 600 if (change.selected) |
| 601 this.setAttribute('aria-activedescendant', listItem.id); |
| 602 } |
587 }, this); | 603 }, this); |
588 | 604 |
589 cr.dispatchSimpleEvent(this, 'change'); | 605 cr.dispatchSimpleEvent(this, 'change'); |
590 }, | 606 }, |
591 | 607 |
592 /** | 608 /** |
593 * Handles a change of the lead item from the selection model. | 609 * Handles a change of the lead item from the selection model. |
594 * @param {Event} pe The property change event. | 610 * @param {Event} pe The property change event. |
595 * @private | 611 * @private |
596 */ | 612 */ |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
809 }, | 825 }, |
810 | 826 |
811 /** | 827 /** |
812 * Creates a new list item. | 828 * Creates a new list item. |
813 * @param {*} value The value to use for the item. | 829 * @param {*} value The value to use for the item. |
814 * @return {!ListItem} The newly created list item. | 830 * @return {!ListItem} The newly created list item. |
815 */ | 831 */ |
816 createItem: function(value) { | 832 createItem: function(value) { |
817 var item = new this.itemConstructor_(value); | 833 var item = new this.itemConstructor_(value); |
818 item.label = value; | 834 item.label = value; |
| 835 item.id = this.uniqueIdPrefix_ + '-' + this.nextUniqueIdSuffix_++; |
819 if (typeof item.decorate == 'function') | 836 if (typeof item.decorate == 'function') |
820 item.decorate(); | 837 item.decorate(); |
821 return item; | 838 return item; |
822 }, | 839 }, |
823 | 840 |
824 /** | 841 /** |
825 * Creates the selection controller to use internally. | 842 * Creates the selection controller to use internally. |
826 * @param {cr.ui.ListSelectionModel} sm The underlying selection model. | 843 * @param {cr.ui.ListSelectionModel} sm The underlying selection model. |
827 * @return {!cr.ui.ListSelectionController} The newly created selection | 844 * @return {!cr.ui.ListSelectionController} The newly created selection |
828 * controller. | 845 * controller. |
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1265 * because list items can contain controls that can be focused, and for some | 1282 * because list items can contain controls that can be focused, and for some |
1266 * purposes (e.g., styling), the list can still be conceptually focused at | 1283 * purposes (e.g., styling), the list can still be conceptually focused at |
1267 * that point even though it doesn't actually have the page focus. | 1284 * that point even though it doesn't actually have the page focus. |
1268 */ | 1285 */ |
1269 cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); | 1286 cr.defineProperty(List, 'hasElementFocus', cr.PropertyKind.BOOL_ATTR); |
1270 | 1287 |
1271 return { | 1288 return { |
1272 List: List | 1289 List: List |
1273 }; | 1290 }; |
1274 }); | 1291 }); |
OLD | NEW |