1<!DOCTYPE html> 2<!-- 3Copyright (c) 2014 The Chromium Authors. All rights reserved. 4Use of this source code is governed by a BSD-style license that can be 5found in the LICENSE file. 6--> 7 8<link rel="stylesheet" href="/tracing/ui/base/list_view.css"> 9 10<link rel="import" href="/tracing/base/event.html"> 11<link rel="import" href="/tracing/ui/base/container_that_decorates_its_children.html"> 12<link rel="import" href="/tracing/ui/base/ui.html"> 13<link rel="import" href="/tracing/ui/base/utils.html"> 14 15<script> 16'use strict'; 17 18/** 19 * @fileoverview Simple list view. 20 */ 21tr.exportTo('tr.ui.b', function() { 22 /** 23 * @constructor 24 */ 25 var ListView = tr.ui.b.define( 26 'x-list-view', tr.ui.b.ContainerThatDecoratesItsChildren); 27 28 ListView.prototype = { 29 __proto__: tr.ui.b.ContainerThatDecoratesItsChildren.prototype, 30 31 decorate: function() { 32 tr.ui.b.ContainerThatDecoratesItsChildren.prototype.decorate.call(this); 33 34 this.classList.add('x-list-view'); 35 this.onItemClicked_ = this.onItemClicked_.bind(this); 36 this.onKeyDown_ = this.onKeyDown_.bind(this); 37 this.tabIndex = 0; 38 this.addEventListener('keydown', this.onKeyDown_); 39 40 this.selectionChanged_ = false; 41 }, 42 43 decorateChild_: function(item) { 44 item.classList.add('list-item'); 45 item.addEventListener('click', this.onItemClicked_, true); 46 47 var listView = this; 48 Object.defineProperty( 49 item, 50 'selected', { 51 configurable: true, 52 set: function(value) { 53 var oldSelection = listView.selectedElement; 54 if (oldSelection && oldSelection != this && value) 55 listView.selectedElement.removeAttribute('selected'); 56 if (value) 57 this.setAttribute('selected', 'selected'); 58 else 59 this.removeAttribute('selected'); 60 var newSelection = listView.selectedElement; 61 if (newSelection != oldSelection) 62 tr.b.dispatchSimpleEvent(listView, 'selection-changed', false); 63 }, 64 get: function() { 65 return this.hasAttribute('selected'); 66 } 67 }); 68 }, 69 70 undecorateChild_: function(item) { 71 this.selectionChanged_ |= item.selected; 72 73 item.classList.remove('list-item'); 74 item.removeEventListener('click', this.onItemClicked_); 75 delete item.selected; 76 }, 77 78 beginDecorating_: function() { 79 this.selectionChanged_ = false; 80 }, 81 82 doneDecoratingForNow_: function() { 83 if (this.selectionChanged_) 84 tr.b.dispatchSimpleEvent(this, 'selection-changed', false); 85 }, 86 87 get selectedElement() { 88 var el = this.querySelector('.list-item[selected]'); 89 if (!el) 90 return undefined; 91 return el; 92 }, 93 94 set selectedElement(el) { 95 if (!el) { 96 if (this.selectedElement) 97 this.selectedElement.selected = false; 98 return; 99 } 100 101 if (el.parentElement != this) 102 throw new Error( 103 'Can only select elements that are children of this list view'); 104 el.selected = true; 105 }, 106 107 getElementByIndex: function(index) { 108 return this.querySelector('.list-item:nth-child(' + index + ')'); 109 }, 110 111 clear: function() { 112 var changed = this.selectedElement !== undefined; 113 tr.ui.b.ContainerThatDecoratesItsChildren.prototype.clear.call(this); 114 if (changed) 115 tr.b.dispatchSimpleEvent(this, 'selection-changed', false); 116 }, 117 118 onItemClicked_: function(e) { 119 var currentSelectedElement = this.selectedElement; 120 if (currentSelectedElement) 121 currentSelectedElement.removeAttribute('selected'); 122 var element = e.target; 123 while (element.parentElement != this) 124 element = element.parentElement; 125 if (element !== currentSelectedElement) 126 element.setAttribute('selected', 'selected'); 127 tr.b.dispatchSimpleEvent(this, 'selection-changed', false); 128 }, 129 130 onKeyDown_: function(e) { 131 if (this.selectedElement === undefined) 132 return; 133 134 if (e.keyCode == 38) { // Up arrow. 135 var prev = this.selectedElement.previousSibling; 136 if (prev) { 137 prev.selected = true; 138 tr.ui.b.scrollIntoViewIfNeeded(prev); 139 e.preventDefault(); 140 return true; 141 } 142 } else if (e.keyCode == 40) { // Down arrow. 143 var next = this.selectedElement.nextSibling; 144 if (next) { 145 next.selected = true; 146 tr.ui.b.scrollIntoViewIfNeeded(next); 147 e.preventDefault(); 148 return true; 149 } 150 } 151 }, 152 153 addItem: function(textContent) { 154 var item = document.createElement('div'); 155 item.textContent = textContent; 156 this.appendChild(item); 157 return item; 158 } 159 160 }; 161 162 return { 163 ListView: ListView 164 }; 165 166}); 167</script> 168