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 selectionCol
.style
.borderLeft
= '0';
46 checkbox
.type
= 'checkbox';
48 var idCell
= addNode(tr
, 'td');
49 idCell
.style
.textAlign
= 'right';
51 var typeCell
= addNode(tr
, 'td');
52 var descriptionCell
= addNode(tr
, 'td');
53 this.descriptionCell_
= descriptionCell
;
56 checkbox
.onchange
= this.onCheckboxToggled_
.bind(this);
58 var onclick
= this.onClicked_
.bind(this);
59 idCell
.onclick
= onclick
;
60 typeCell
.onclick
= onclick
;
61 descriptionCell
.onclick
= onclick
;
63 tr
.onmouseover
= this.onMouseover_
.bind(this);
64 tr
.onmouseout
= this.onMouseout_
.bind(this);
66 // Set the cell values to match this source's data.
67 if (this.getSourceId() >= 0) {
68 addTextNode(idCell
, this.getSourceId());
70 addTextNode(idCell
, '-');
72 var sourceTypeString
= this.sourceEntry_
.getSourceTypeString();
73 addTextNode(typeCell
, sourceTypeString
);
74 this.updateDescription_();
76 // Add a CSS classname specific to this source type (so CSS can specify
77 // different stylings for different types).
78 var sourceTypeClass
= sourceTypeString
.toLowerCase().replace(/_
/g
, '-');
79 this.row_
.classList
.add('source-' + sourceTypeClass
);
84 onSourceUpdated: function() {
85 if (this.sourceEntry_
.isInactive() != this.isInactive_
||
86 this.sourceEntry_
.isError() != this.isError_
) {
90 if (this.description_
!= this.sourceEntry_
.getDescription())
91 this.updateDescription_();
94 var matchesFilter
= this.matchesFilter(this.parentView_
.currentFilter_
);
95 this.setIsMatchedByFilter(matchesFilter
);
99 * Changes |row_|'s class based on currently set flags. Clears any previous
100 * class set by this method. This method is needed so that some styles
103 updateClass_: function() {
104 this.isInactive_
= this.sourceEntry_
.isInactive();
105 this.isError_
= this.sourceEntry_
.isError();
107 // Each element of this list contains a property of |this| and the
108 // corresponding class name to set if that property is true. Entries
109 // earlier in the list take precedence.
110 var propertyNames
= [
111 ['isSelected_', 'selected'],
112 ['isMouseOver_', 'mouseover'],
113 ['isError_', 'error'],
114 ['isInactive_', 'inactive'],
117 // Loop through |propertyNames| in order, checking if each property
118 // is true. For the first such property found, if any, add the
119 // corresponding class to the SourceEntry's row. Remove classes
120 // that correspond to any other property.
121 var noStyleSet
= true;
122 for (var i
= 0; i
< propertyNames
.length
; ++i
) {
123 var setStyle
= noStyleSet
&& this[propertyNames
[i
][0]];
125 this.row_
.classList
.add(propertyNames
[i
][1]);
128 this.row_
.classList
.remove(propertyNames
[i
][1]);
133 getSourceEntry: function() {
134 return this.sourceEntry_
;
137 setIsMatchedByFilter: function(isMatchedByFilter
) {
138 if (this.isMatchedByFilter() == isMatchedByFilter
)
139 return; // No change.
141 this.isMatchedByFilter_
= isMatchedByFilter
;
143 this.setFilterStyles(isMatchedByFilter
);
145 if (isMatchedByFilter
) {
146 this.parentView_
.incrementPostfilterCount(1);
148 this.parentView_
.incrementPostfilterCount(-1);
149 // If we are filtering an entry away, make sure it is no longer
150 // part of the selection.
151 this.setSelected(false);
155 isMatchedByFilter: function() {
156 return this.isMatchedByFilter_
;
159 setFilterStyles: function(isMatchedByFilter
) {
160 // Hide rows which have been filtered away.
161 if (isMatchedByFilter
) {
162 this.row_
.style
.display
= '';
164 this.row_
.style
.display
= 'none';
168 matchesFilter: function(filter
) {
169 if (filter
.isActive
&& this.isInactive_
)
171 if (filter
.isInactive
&& !this.isInactive_
)
173 if (filter
.isError
&& !this.isError_
)
175 if (filter
.isNotError
&& this.isError_
)
178 // Check source type, if needed.
181 var sourceType
= this.sourceEntry_
.getSourceTypeString().toLowerCase();
182 for (i
= 0; i
< filter
.type
.length
; ++i
) {
183 if (sourceType
.search(filter
.type
[i
]) != -1)
186 if (i
== filter
.type
.length
)
190 // Check source ID, if needed.
192 if (filter
.id
.indexOf(this.getSourceId() + '') == -1)
196 if (filter
.text
== '')
199 // The description is not always contained in one of the log entries.
200 if (this.description_
.toLowerCase().indexOf(filter
.text
) != -1)
203 // Allow specifying source types by name.
204 var sourceType
= this.sourceEntry_
.getSourceTypeString();
205 if (sourceType
.toLowerCase().indexOf(filter
.text
) != -1)
208 return searchLogEntriesForText(
210 this.sourceEntry_
.getLogEntries(),
211 SourceTracker
.getInstance().getPrivacyStripping());
214 isSelected: function() {
215 return this.isSelected_
;
218 setSelected: function(isSelected
) {
219 if (isSelected
== this.isSelected())
222 this.isSelected_
= isSelected
;
224 this.setSelectedStyles(isSelected
);
225 this.parentView_
.modifySelectionArray(this.getSourceId(), isSelected
);
226 this.parentView_
.onSelectionChanged();
229 setSelectedStyles: function(isSelected
) {
230 this.isSelected_
= isSelected
;
231 this.getSelectionCheckbox().checked
= isSelected
;
235 setMouseoverStyle: function(isMouseOver
) {
236 this.isMouseOver_
= isMouseOver
;
240 onClicked_: function() {
241 this.parentView_
.clearSelection();
242 this.setSelected(true);
243 if (this.isSelected())
244 this.parentView_
.scrollToSourceId(this.getSourceId());
247 onMouseover_: function() {
248 this.setMouseoverStyle(true);
251 onMouseout_: function() {
252 this.setMouseoverStyle(false);
255 updateDescription_: function() {
256 this.description_
= this.sourceEntry_
.getDescription();
257 this.descriptionCell_
.innerHTML
= '';
258 addTextNode(this.descriptionCell_
, this.description_
);
261 onCheckboxToggled_: function() {
262 this.setSelected(this.getSelectionCheckbox().checked
);
263 if (this.isSelected())
264 this.parentView_
.scrollToSourceId(this.getSourceId());
267 getSelectionCheckbox: function() {
268 return this.row_
.childNodes
[0].firstChild
;
271 getSourceId: function() {
272 return this.sourceEntry_
.getSourceId();
276 * Returns source ID of the entry whose row is currently above this one's.
277 * Returns null if no such node exists.
279 getPreviousNodeSourceId: function() {
280 var prevNode
= this.row_
.previousSibling
;
281 if (prevNode
== null)
287 * Returns source ID of the entry whose row is currently below this one's.
288 * Returns null if no such node exists.
290 getNextNodeSourceId: function() {
291 var nextNode
= this.row_
.nextSibling
;
292 if (nextNode
== null)
298 * Moves current object's row before |entry|'s row.
300 moveBefore: function(entry
) {
301 this.row_
.parentNode
.insertBefore(this.row_
, entry
.row_
);
305 * Moves current object's row after |entry|'s row.
307 moveAfter: function(entry
) {
308 this.row_
.parentNode
.insertBefore(this.row_
, entry
.row_
.nextSibling
);