OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 var SourceRow = (function() { |
| 6 'use strict'; |
| 7 |
| 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; |
| 16 |
| 17 this.sourceEntry_ = sourceEntry; |
| 18 this.isSelected_ = false; |
| 19 this.isMatchedByFilter_ = false; |
| 20 |
| 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; |
| 25 |
| 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(); |
| 30 |
| 31 this.createRow_(); |
| 32 this.onSourceUpdated(); |
| 33 } |
| 34 |
| 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; |
| 42 |
| 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'; |
| 48 |
| 49 var idCell = addNode(tr, 'td'); |
| 50 idCell.style.textAlign = 'right'; |
| 51 |
| 52 var typeCell = addNode(tr, 'td'); |
| 53 var descriptionCell = addNode(tr, 'td'); |
| 54 this.descriptionCell_ = descriptionCell; |
| 55 |
| 56 // Connect listeners. |
| 57 checkbox.onchange = this.onCheckboxToggled_.bind(this); |
| 58 |
| 59 var onclick = this.onClicked_.bind(this); |
| 60 idCell.onclick = onclick; |
| 61 typeCell.onclick = onclick; |
| 62 descriptionCell.onclick = onclick; |
| 63 |
| 64 tr.onmouseover = this.onMouseover_.bind(this); |
| 65 tr.onmouseout = this.onMouseout_.bind(this); |
| 66 |
| 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_(); |
| 76 |
| 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); |
| 81 |
| 82 this.updateClass_(); |
| 83 }, |
| 84 |
| 85 onSourceUpdated: function() { |
| 86 if (this.sourceEntry_.isInactive() != this.isInactive_ || |
| 87 this.sourceEntry_.isError() != this.isError_) { |
| 88 this.updateClass_(); |
| 89 } |
| 90 |
| 91 if (this.description_ != this.sourceEntry_.getDescription()) |
| 92 this.updateDescription_(); |
| 93 |
| 94 // Update filters. |
| 95 var matchesFilter = this.parentView_.currentFilter_(this.sourceEntry_); |
| 96 this.setIsMatchedByFilter(matchesFilter); |
| 97 }, |
| 98 |
| 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(); |
| 107 |
| 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 ]; |
| 117 |
| 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 }, |
| 133 |
| 134 getSourceEntry: function() { |
| 135 return this.sourceEntry_; |
| 136 }, |
| 137 |
| 138 setIsMatchedByFilter: function(isMatchedByFilter) { |
| 139 if (this.isMatchedByFilter() == isMatchedByFilter) |
| 140 return; // No change. |
| 141 |
| 142 this.isMatchedByFilter_ = isMatchedByFilter; |
| 143 |
| 144 this.setFilterStyles(isMatchedByFilter); |
| 145 |
| 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 }, |
| 155 |
| 156 isMatchedByFilter: function() { |
| 157 return this.isMatchedByFilter_; |
| 158 }, |
| 159 |
| 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 }, |
| 168 |
| 169 isSelected: function() { |
| 170 return this.isSelected_; |
| 171 }, |
| 172 |
| 173 setSelected: function(isSelected) { |
| 174 if (isSelected == this.isSelected()) |
| 175 return; |
| 176 |
| 177 this.isSelected_ = isSelected; |
| 178 |
| 179 this.setSelectedStyles(isSelected); |
| 180 this.parentView_.modifySelectionArray(this.getSourceId(), isSelected); |
| 181 this.parentView_.onSelectionChanged(); |
| 182 }, |
| 183 |
| 184 setSelectedStyles: function(isSelected) { |
| 185 this.isSelected_ = isSelected; |
| 186 this.getSelectionCheckbox().checked = isSelected; |
| 187 this.updateClass_(); |
| 188 }, |
| 189 |
| 190 setMouseoverStyle: function(isMouseOver) { |
| 191 this.isMouseOver_ = isMouseOver; |
| 192 this.updateClass_(); |
| 193 }, |
| 194 |
| 195 onClicked_: function() { |
| 196 this.parentView_.clearSelection(); |
| 197 this.setSelected(true); |
| 198 if (this.isSelected()) |
| 199 this.parentView_.scrollToSourceId(this.getSourceId()); |
| 200 }, |
| 201 |
| 202 onMouseover_: function() { |
| 203 this.setMouseoverStyle(true); |
| 204 }, |
| 205 |
| 206 onMouseout_: function() { |
| 207 this.setMouseoverStyle(false); |
| 208 }, |
| 209 |
| 210 updateDescription_: function() { |
| 211 this.description_ = this.sourceEntry_.getDescription(); |
| 212 this.descriptionCell_.innerHTML = ''; |
| 213 addTextNode(this.descriptionCell_, this.description_); |
| 214 }, |
| 215 |
| 216 onCheckboxToggled_: function() { |
| 217 this.setSelected(this.getSelectionCheckbox().checked); |
| 218 if (this.isSelected()) |
| 219 this.parentView_.scrollToSourceId(this.getSourceId()); |
| 220 }, |
| 221 |
| 222 getSelectionCheckbox: function() { |
| 223 return this.row_.childNodes[0].firstChild; |
| 224 }, |
| 225 |
| 226 getSourceId: function() { |
| 227 return this.sourceEntry_.getSourceId(); |
| 228 }, |
| 229 |
| 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 }, |
| 240 |
| 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 }, |
| 251 |
| 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 }, |
| 258 |
| 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 }; |
| 266 |
| 267 return SourceRow; |
| 268 })(); |
| 269 |
OLD | NEW |