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.
5 var SourceRow = (function() {
9 * A SourceRow represents the row corresponding to a single SourceEntry
10 * displayed by the EventsView.
14 function SourceRow(parentView, sourceEntry) {
15 this.parentView_ = parentView;
17 this.sourceEntry_ = sourceEntry;
18 this.isSelected_ = false;
19 this.isMatchedByFilter_ = false;
21 // Used to set CSS class for display. Must only be modified by calling
22 // corresponding set functions.
23 this.isSelected_ = false;
24 this.isMouseOver_ = false;
26 // Mirror sourceEntry's values, so we only update the DOM when necessary.
27 this.isError_ = sourceEntry.isError();
28 this.isInactive_ = sourceEntry.isInactive();
29 this.description_ = sourceEntry.getDescription();
32 this.onSourceUpdated();
35 SourceRow.prototype = {
36 createRow_: function() {
38 var tr = addNode(this.parentView_.tableBody_, 'tr');
39 tr._id = this.getSourceId();
40 tr.style.display = 'none';
43 var selectionCol = addNode(tr, 'td');
44 var checkbox = addNode(selectionCol, 'input');
45 checkbox.title = this.getSourceId();
46 selectionCol.style.borderLeft = '0';
47 checkbox.type = 'checkbox';
49 var idCell = addNode(tr, 'td');
50 idCell.style.textAlign = 'right';
52 var typeCell = addNode(tr, 'td');
53 var descriptionCell = addNode(tr, 'td');
54 this.descriptionCell_ = descriptionCell;
57 checkbox.onchange = this.onCheckboxToggled_.bind(this);
59 var onclick = this.onClicked_.bind(this);
60 idCell.onclick = onclick;
61 typeCell.onclick = onclick;
62 descriptionCell.onclick = onclick;
64 tr.onmouseover = this.onMouseover_.bind(this);
65 tr.onmouseout = this.onMouseout_.bind(this);
67 // Set the cell values to match this source's data.
68 if (this.getSourceId() >= 0) {
69 addTextNode(idCell, this.getSourceId());
71 addTextNode(idCell, '-');
73 var sourceTypeString = this.sourceEntry_.getSourceTypeString();
74 addTextNode(typeCell, sourceTypeString);
75 this.updateDescription_();
77 // Add a CSS classname specific to this source type (so CSS can specify
78 // different stylings for different types).
79 var sourceTypeClass = sourceTypeString.toLowerCase().replace(/_/g, '-');
80 this.row_.classList.add('source-' + sourceTypeClass);
85 onSourceUpdated: function() {
86 if (this.sourceEntry_.isInactive() != this.isInactive_ ||
87 this.sourceEntry_.isError() != this.isError_) {
91 if (this.description_ != this.sourceEntry_.getDescription())
92 this.updateDescription_();
95 var matchesFilter = this.parentView_.currentFilter_(this.sourceEntry_);
96 this.setIsMatchedByFilter(matchesFilter);
100 * Changes |row_|'s class based on currently set flags. Clears any previous
101 * class set by this method. This method is needed so that some styles
104 updateClass_: function() {
105 this.isInactive_ = this.sourceEntry_.isInactive();
106 this.isError_ = this.sourceEntry_.isError();
108 // Each element of this list contains a property of |this| and the
109 // corresponding class name to set if that property is true. Entries
110 // earlier in the list take precedence.
111 var propertyNames = [
112 ['isSelected_', 'selected'],
113 ['isMouseOver_', 'mouseover'],
114 ['isError_', 'error'],
115 ['isInactive_', 'inactive'],
118 // Loop through |propertyNames| in order, checking if each property
119 // is true. For the first such property found, if any, add the
120 // corresponding class to the SourceEntry's row. Remove classes
121 // that correspond to any other property.
122 var noStyleSet = true;
123 for (var i = 0; i < propertyNames.length; ++i) {
124 var setStyle = noStyleSet && this[propertyNames[i][0]];
126 this.row_.classList.add(propertyNames[i][1]);
129 this.row_.classList.remove(propertyNames[i][1]);
134 getSourceEntry: function() {
135 return this.sourceEntry_;
138 setIsMatchedByFilter: function(isMatchedByFilter) {
139 if (this.isMatchedByFilter() == isMatchedByFilter)
140 return; // No change.
142 this.isMatchedByFilter_ = isMatchedByFilter;
144 this.setFilterStyles(isMatchedByFilter);
146 if (isMatchedByFilter) {
147 this.parentView_.incrementPostfilterCount(1);
149 this.parentView_.incrementPostfilterCount(-1);
150 // If we are filtering an entry away, make sure it is no longer
151 // part of the selection.
152 this.setSelected(false);
156 isMatchedByFilter: function() {
157 return this.isMatchedByFilter_;
160 setFilterStyles: function(isMatchedByFilter) {
161 // Hide rows which have been filtered away.
162 if (isMatchedByFilter) {
163 this.row_.style.display = '';
165 this.row_.style.display = 'none';
169 isSelected: function() {
170 return this.isSelected_;
173 setSelected: function(isSelected) {
174 if (isSelected == this.isSelected())
177 this.isSelected_ = isSelected;
179 this.setSelectedStyles(isSelected);
180 this.parentView_.modifySelectionArray(this.getSourceId(), isSelected);
181 this.parentView_.onSelectionChanged();
184 setSelectedStyles: function(isSelected) {
185 this.isSelected_ = isSelected;
186 this.getSelectionCheckbox().checked = isSelected;
190 setMouseoverStyle: function(isMouseOver) {
191 this.isMouseOver_ = isMouseOver;
195 onClicked_: function() {
196 this.parentView_.clearSelection();
197 this.setSelected(true);
198 if (this.isSelected())
199 this.parentView_.scrollToSourceId(this.getSourceId());
202 onMouseover_: function() {
203 this.setMouseoverStyle(true);
206 onMouseout_: function() {
207 this.setMouseoverStyle(false);
210 updateDescription_: function() {
211 this.description_ = this.sourceEntry_.getDescription();
212 this.descriptionCell_.innerHTML = '';
213 addTextNode(this.descriptionCell_, this.description_);
216 onCheckboxToggled_: function() {
217 this.setSelected(this.getSelectionCheckbox().checked);
218 if (this.isSelected())
219 this.parentView_.scrollToSourceId(this.getSourceId());
222 getSelectionCheckbox: function() {
223 return this.row_.childNodes[0].firstChild;
226 getSourceId: function() {
227 return this.sourceEntry_.getSourceId();
231 * Returns source ID of the entry whose row is currently above this one's.
232 * Returns null if no such node exists.
234 getPreviousNodeSourceId: function() {
235 var prevNode = this.row_.previousSibling;
236 if (prevNode == null)
242 * Returns source ID of the entry whose row is currently below this one's.
243 * Returns null if no such node exists.
245 getNextNodeSourceId: function() {
246 var nextNode = this.row_.nextSibling;
247 if (nextNode == null)
253 * Moves current object's row before |entry|'s row.
255 moveBefore: function(entry) {
256 this.row_.parentNode.insertBefore(this.row_, entry.row_);
260 * Moves current object's row after |entry|'s row.
262 moveAfter: function(entry) {
263 this.row_.parentNode.insertBefore(this.row_, entry.row_.nextSibling);