Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / net_internals / source_row.js
blob137d70ae084680b2e574c7c52a13f2212b1fc963
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() {
6   'use strict';
8   /**
9    * A SourceRow represents the row corresponding to a single SourceEntry
10    * displayed by the EventsView.
11    *
12    * @constructor
13    */
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();
31     this.createRow_();
32     this.onSourceUpdated();
33   }
35   SourceRow.prototype = {
36     createRow_: function() {
37       // Create a row.
38       var tr = addNode(this.parentView_.tableBody_, 'tr');
39       tr._id = this.getSourceId();
40       tr.style.display = 'none';
41       this.row_ = tr;
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;
56       // Connect listeners.
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());
70       } else {
71         addTextNode(idCell, '-');
72       }
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);
82       this.updateClass_();
83     },
85     onSourceUpdated: function() {
86       if (this.sourceEntry_.isInactive() != this.isInactive_ ||
87           this.sourceEntry_.isError() != this.isError_) {
88         this.updateClass_();
89       }
91       if (this.description_ != this.sourceEntry_.getDescription())
92         this.updateDescription_();
94       // Update filters.
95       var matchesFilter = this.parentView_.currentFilter_(this.sourceEntry_);
96       this.setIsMatchedByFilter(matchesFilter);
97     },
99     /**
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
102      * override others.
103      */
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'],
116       ];
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]];
125         if (setStyle) {
126           this.row_.classList.add(propertyNames[i][1]);
127           noStyleSet = false;
128         } else {
129           this.row_.classList.remove(propertyNames[i][1]);
130         }
131       }
132     },
134     getSourceEntry: function() {
135       return this.sourceEntry_;
136     },
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);
148       } else {
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);
153       }
154     },
156     isMatchedByFilter: function() {
157       return this.isMatchedByFilter_;
158     },
160     setFilterStyles: function(isMatchedByFilter) {
161       // Hide rows which have been filtered away.
162       if (isMatchedByFilter) {
163         this.row_.style.display = '';
164       } else {
165         this.row_.style.display = 'none';
166       }
167     },
169     isSelected: function() {
170       return this.isSelected_;
171     },
173     setSelected: function(isSelected) {
174       if (isSelected == this.isSelected())
175         return;
177       this.isSelected_ = isSelected;
179       this.setSelectedStyles(isSelected);
180       this.parentView_.modifySelectionArray(this.getSourceId(), isSelected);
181       this.parentView_.onSelectionChanged();
182     },
184     setSelectedStyles: function(isSelected) {
185       this.isSelected_ = isSelected;
186       this.getSelectionCheckbox().checked = isSelected;
187       this.updateClass_();
188     },
190     setMouseoverStyle: function(isMouseOver) {
191       this.isMouseOver_ = isMouseOver;
192       this.updateClass_();
193     },
195     onClicked_: function() {
196       this.parentView_.clearSelection();
197       this.setSelected(true);
198       if (this.isSelected())
199         this.parentView_.scrollToSourceId(this.getSourceId());
200     },
202     onMouseover_: function() {
203       this.setMouseoverStyle(true);
204     },
206     onMouseout_: function() {
207       this.setMouseoverStyle(false);
208     },
210     updateDescription_: function() {
211       this.description_ = this.sourceEntry_.getDescription();
212       this.descriptionCell_.innerHTML = '';
213       addTextNode(this.descriptionCell_, this.description_);
214     },
216     onCheckboxToggled_: function() {
217       this.setSelected(this.getSelectionCheckbox().checked);
218       if (this.isSelected())
219         this.parentView_.scrollToSourceId(this.getSourceId());
220     },
222     getSelectionCheckbox: function() {
223       return this.row_.childNodes[0].firstChild;
224     },
226     getSourceId: function() {
227       return this.sourceEntry_.getSourceId();
228     },
230     /**
231      * Returns source ID of the entry whose row is currently above this one's.
232      * Returns null if no such node exists.
233      */
234     getPreviousNodeSourceId: function() {
235       var prevNode = this.row_.previousSibling;
236       if (prevNode == null)
237         return null;
238       return prevNode._id;
239     },
241     /**
242      * Returns source ID of the entry whose row is currently below this one's.
243      * Returns null if no such node exists.
244      */
245     getNextNodeSourceId: function() {
246       var nextNode = this.row_.nextSibling;
247       if (nextNode == null)
248         return null;
249       return nextNode._id;
250     },
252     /**
253      * Moves current object's row before |entry|'s row.
254      */
255     moveBefore: function(entry) {
256       this.row_.parentNode.insertBefore(this.row_, entry.row_);
257     },
259     /**
260      * Moves current object's row after |entry|'s row.
261      */
262     moveAfter: function(entry) {
263       this.row_.parentNode.insertBefore(this.row_, entry.row_.nextSibling);
264     }
265   };
267   return SourceRow;
268 })();