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
3 // found in the LICENSE file.
7 * @fileoverview Simple list view.
10 base.requireStylesheet('ui.list_view');
11 base.exportTo('ui', function() {
16 var ListView = ui.define('x-list-view');
18 ListView.prototype = {
19 __proto__: HTMLUnknownElement.prototype,
21 decorate: function() {
22 this.onItemClicked_ = this.onItemClicked_.bind(this);
23 this.onKeyDown_ = this.onKeyDown_.bind(this);
24 this.observer_ = new WebKitMutationObserver(this.didMutate_.bind(this));
25 this.observer_.observe(this, { childList: true });
27 this.addEventListener('keydown', this.onKeyDown_);
30 appendChild: function(x) {
31 HTMLUnknownElement.prototype.appendChild.call(this, x);
32 this.didMutate_(this.observer_.takeRecords());
35 insertBefore: function(x, y) {
36 HTMLUnknownElement.prototype.insertBefore.call(this, x, y);
37 this.didMutate_(this.observer_.takeRecords());
40 removeChild: function(x) {
41 HTMLUnknownElement.prototype.removeChild.call(this, x);
42 this.didMutate_(this.observer_.takeRecords());
45 replaceChild: function(x, y) {
46 HTMLUnknownElement.prototype.replaceChild.call(this, x, y);
47 this.didMutate_(this.observer_.takeRecords());
50 didMutate_: function(records) {
51 var selectionChanged = false;
52 for (var i = 0; i < records.length; i++) {
53 var addedNodes = records[i].addedNodes;
55 for (var j = 0; j < addedNodes.length; j++)
56 this.decorateItem_(addedNodes[j]);
58 var removedNodes = records[i].removedNodes;
60 for (var j = 0; j < removedNodes.length; j++) {
61 selectionChanged |= removedNodes[j].selected;
62 this.undecorateItem_(removedNodes[j]);
67 base.dispatchSimpleEvent(this, 'selection-changed', false);
70 decorateItem_: function(item) {
71 item.classList.add('list-item');
72 item.addEventListener('click', this.onItemClicked_);
75 Object.defineProperty(
79 set: function(value) {
80 var oldSelection = listView.selectedElement;
81 if (oldSelection && oldSelection != this && value)
82 listView.selectedElement.removeAttribute('selected');
84 this.setAttribute('selected', 'selected');
86 this.removeAttribute('selected');
87 var newSelection = listView.selectedElement;
88 if (newSelection != oldSelection)
89 base.dispatchSimpleEvent(listView, 'selection-changed', false);
92 return this.hasAttribute('selected');
97 undecorateItem_: function(item) {
98 item.classList.remove('list-item');
99 item.removeEventListener('click', this.onItemClicked_);
100 delete item.selected;
103 get selectedElement() {
104 var el = this.querySelector('.list-item[selected]');
110 set selectedElement(el) {
112 if (this.selectedElement)
113 this.selectedElement.selected = false;
117 if (el.parentElement != this)
119 'Can only select elements that are children of this list view');
124 var changed = this.selectedElement !== undefined;
125 this.textContent = '';
127 base.dispatchSimpleEvent(this, 'selection-changed', false);
130 onItemClicked_: function(e) {
131 var currentSelectedElement = this.selectedElement;
132 if (currentSelectedElement)
133 currentSelectedElement.removeAttribute('selected');
134 e.target.setAttribute('selected', 'selected');
135 base.dispatchSimpleEvent(this, 'selection-changed', false);
138 onKeyDown_: function(e) {
139 if (e.keyCode == 38) { // Up arrow.
140 var prev = this.selectedElement.previousSibling;
142 prev.selected = true;
143 prev.scrollIntoView(false);
147 } else if(e.keyCode == 40) { // Down arrow.
148 var next = this.selectedElement.nextSibling;
150 next.selected = true;
151 next.scrollIntoView(false);
158 addItem: function(textContent) {
159 var item = document.createElement('div');
160 item.textContent = textContent;
161 this.appendChild(item);