Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 cr.define('options.contentSettings', function() { | 5 cr.define('options.contentSettings', function() { |
| 6 const List = cr.ui.List; | 6 const List = cr.ui.List; |
| 7 const ListItem = cr.ui.ListItem; | 7 const ListItem = cr.ui.ListItem; |
| 8 const ArrayDataModel = cr.ui.ArrayDataModel; | 8 const ArrayDataModel = cr.ui.ArrayDataModel; |
| 9 | 9 |
| 10 /** | 10 /** |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 32 | 32 |
| 33 ExceptionsListItem.prototype = { | 33 ExceptionsListItem.prototype = { |
| 34 __proto__: ListItem.prototype, | 34 __proto__: ListItem.prototype, |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * Called when an element is decorated as a list item. | 37 * Called when an element is decorated as a list item. |
| 38 */ | 38 */ |
| 39 decorate: function() { | 39 decorate: function() { |
| 40 ListItem.prototype.decorate.call(this); | 40 ListItem.prototype.decorate.call(this); |
| 41 | 41 |
| 42 // Labels for display mode. | 42 // Labels for display mode. |pattern| will be null for the 'add new |
| 43 var patternLabel = cr.doc.createElement('span'); | 43 // exception' row. |
| 44 patternLabel.textContent = this.pattern; | 44 if (this.pattern) { |
| 45 this.appendChild(patternLabel); | 45 this.isAddNewRow = false; |
| 46 | 46 |
| 47 var settingLabel = cr.doc.createElement('span'); | 47 var patternLabel = cr.doc.createElement('span'); |
| 48 settingLabel.textContent = this.settingForDisplay(); | 48 patternLabel.textContent = this.pattern; |
| 49 settingLabel.className = 'exceptionSetting'; | 49 patternLabel.className = 'exceptionPattern'; |
| 50 this.appendChild(settingLabel); | 50 this.appendChild(patternLabel); |
| 51 this.patternLabel = patternLabel; | |
| 52 | |
| 53 var settingLabel = cr.doc.createElement('span'); | |
| 54 settingLabel.textContent = this.settingForDisplay(); | |
| 55 settingLabel.className = 'exceptionSetting'; | |
| 56 this.appendChild(settingLabel); | |
| 57 this.settingLabel = settingLabel; | |
| 58 } else { | |
| 59 this.isAddNewRow = true; | |
| 60 } | |
| 51 | 61 |
| 52 // Elements for edit mode. | 62 // Elements for edit mode. |
| 53 var input = cr.doc.createElement('input'); | 63 var input = cr.doc.createElement('input'); |
| 54 input.type = 'text'; | 64 input.type = 'text'; |
| 55 this.appendChild(input); | 65 this.appendChild(input); |
| 56 input.className = 'exceptionInput hidden'; | 66 input.className = 'exceptionPattern'; |
| 67 if (this.isAddNewRow) | |
| 68 input.placeholder = templateData.addNewExceptionInstructions; | |
| 69 else | |
| 70 input.classList.add('hidden'); | |
| 57 | 71 |
| 58 var select = cr.doc.createElement('select'); | 72 var select = cr.doc.createElement('select'); |
| 59 var optionAllow = cr.doc.createElement('option'); | 73 var optionAllow = cr.doc.createElement('option'); |
| 60 optionAllow.textContent = templateData.allowException; | 74 optionAllow.textContent = templateData.allowException; |
| 61 select.appendChild(optionAllow); | 75 select.appendChild(optionAllow); |
| 62 | 76 |
| 63 if (this.enableAskOption) { | 77 if (this.enableAskOption) { |
| 64 var optionAsk = cr.doc.createElement('option'); | 78 var optionAsk = cr.doc.createElement('option'); |
| 65 optionAsk.textContent = templateData.askException; | 79 optionAsk.textContent = templateData.askException; |
| 66 select.appendChild(optionAsk); | 80 select.appendChild(optionAsk); |
| 67 this.optionAsk = optionAsk; | 81 this.optionAsk = optionAsk; |
| 68 } | 82 } |
| 69 | 83 |
| 70 if (this.contentType == 'cookies') { | 84 if (this.contentType == 'cookies') { |
| 71 var optionSession = cr.doc.createElement('option'); | 85 var optionSession = cr.doc.createElement('option'); |
| 72 optionSession.textContent = templateData.sessionException; | 86 optionSession.textContent = templateData.sessionException; |
| 73 select.appendChild(optionSession); | 87 select.appendChild(optionSession); |
| 74 this.optionSession = optionSession; | 88 this.optionSession = optionSession; |
| 75 } | 89 } |
| 76 | 90 |
| 77 var optionBlock = cr.doc.createElement('option'); | 91 var optionBlock = cr.doc.createElement('option'); |
| 78 optionBlock.textContent = templateData.blockException; | 92 optionBlock.textContent = templateData.blockException; |
| 79 select.appendChild(optionBlock); | 93 select.appendChild(optionBlock); |
| 80 | 94 |
| 81 this.appendChild(select); | 95 this.appendChild(select); |
| 82 select.className = 'exceptionSetting hidden'; | 96 select.className = 'exceptionSetting'; |
| 97 if (!this.isAddNewRow) | |
| 98 select.classList.add('hidden'); | |
| 83 | 99 |
| 84 // Used to track whether the URL pattern in the input is valid. | 100 // Used to track whether the URL pattern in the input is valid. |
| 85 // This will be true if the browser process has informed us that the | 101 // This will be true if the browser process has informed us that the |
| 86 // current text in the input is valid. Changing the text resets this to | 102 // current text in the input is valid. Changing the text resets this to |
| 87 // false, and getting a response from the browser sets it back to true. | 103 // false, and getting a response from the browser sets it back to true. |
| 88 // It starts off as false for empty string (new exceptions) or true for | 104 // It starts off as false for empty string (new exceptions) or true for |
| 89 // already-existing exceptions (which we assume are valid). | 105 // already-existing exceptions (which we assume are valid). |
| 90 this.inputValidityKnown = this.pattern; | 106 this.inputValidityKnown = this.pattern; |
| 91 // This one tracks the actual validity of the pattern in the input. This | 107 // This one tracks the actual validity of the pattern in the input. This |
| 92 // starts off as true so as not to annoy the user when he adds a new and | 108 // starts off as true so as not to annoy the user when he adds a new and |
| 93 // empty input. | 109 // empty input. |
| 94 this.inputIsValid = true; | 110 this.inputIsValid = true; |
| 95 | 111 |
| 96 this.patternLabel = patternLabel; | |
| 97 this.settingLabel = settingLabel; | |
| 98 this.input = input; | 112 this.input = input; |
| 99 this.select = select; | 113 this.select = select; |
| 100 this.optionAllow = optionAllow; | 114 this.optionAllow = optionAllow; |
| 101 this.optionBlock = optionBlock; | 115 this.optionBlock = optionBlock; |
| 102 | 116 |
| 103 this.updateEditables(); | 117 this.updateEditables(); |
| 104 if (!this.pattern) | |
| 105 input.value = templateData.examplePattern; | |
| 106 | 118 |
| 107 var listItem = this; | 119 var listItem = this; |
| 108 this.ondblclick = function(event) { | 120 |
| 121 this.addEventListener('selectedChange', function(event) { | |
| 109 // Editing notifications and geolocation is disabled for now. | 122 // Editing notifications and geolocation is disabled for now. |
| 110 if (listItem.contentType == 'notifications' || | 123 if (listItem.contentType == 'notifications' || |
| 111 listItem.contentType == 'location') | 124 listItem.contentType == 'location') |
| 112 return; | 125 return; |
| 113 | 126 |
| 114 listItem.editing = true; | 127 listItem.editing = listItem.selected; |
| 115 }; | 128 }); |
| 116 | 129 |
| 117 // Handle events on the editable nodes. | 130 // Handle events on the editable nodes. |
| 118 input.oninput = function(event) { | 131 input.oninput = function(event) { |
| 119 listItem.inputValidityKnown = false; | 132 listItem.inputValidityKnown = false; |
| 120 chrome.send('checkExceptionPatternValidity', | 133 chrome.send('checkExceptionPatternValidity', |
| 121 [listItem.contentType, listItem.mode, input.value]); | 134 [listItem.contentType, listItem.mode, input.value]); |
| 122 }; | 135 }; |
| 123 | 136 |
| 124 // Handles enter and escape which trigger reset and commit respectively. | 137 // Handles enter and escape which trigger reset and commit respectively. |
| 125 function handleKeydown(e) { | 138 function handleKeydown(e) { |
| 126 // Make sure that the tree does not handle the key. | 139 // Make sure that the tree does not handle the key. |
| 127 e.stopPropagation(); | 140 e.stopPropagation(); |
| 128 | 141 |
| 129 // Calling list.focus blurs the input which will stop editing the list | 142 // Calling list.focus blurs the input which will stop editing the list |
| 130 // item. | 143 // item. |
| 131 switch (e.keyIdentifier) { | 144 switch (e.keyIdentifier) { |
| 132 case 'U+001B': // Esc | 145 case 'U+001B': // Esc |
| 133 // Reset the inputs. | 146 // Reset the inputs. |
| 134 listItem.updateEditables(); | 147 listItem.updateEditables(); |
| 135 if (listItem.pattern) | 148 listItem.setPatternValid(true); |
| 136 listItem.maybeSetPatternValid(listItem.pattern, true); | |
| 137 case 'Enter': | 149 case 'Enter': |
| 138 if (listItem.parentNode) | 150 listItem.ownerDocument.activeElement.blur(); |
| 139 listItem.parentNode.focus(); | |
| 140 } | 151 } |
| 141 } | 152 } |
| 142 | 153 |
| 143 function handleBlur(e) { | |
| 144 // When the blur event happens we do not know who is getting focus so we | |
| 145 // delay this a bit since we want to know if the other input got focus | |
| 146 // before deciding if we should exit edit mode. | |
| 147 var doc = e.target.ownerDocument; | |
| 148 window.setTimeout(function() { | |
| 149 var activeElement = doc.activeElement; | |
| 150 if (!listItem.contains(activeElement)) { | |
| 151 listItem.editing = false; | |
| 152 } | |
| 153 }, 50); | |
| 154 } | |
| 155 | |
| 156 input.addEventListener('keydown', handleKeydown); | 154 input.addEventListener('keydown', handleKeydown); |
| 157 input.addEventListener('blur', handleBlur); | |
| 158 | |
| 159 select.addEventListener('keydown', handleKeydown); | 155 select.addEventListener('keydown', handleKeydown); |
| 160 select.addEventListener('blur', handleBlur); | |
| 161 }, | 156 }, |
| 162 | 157 |
| 163 /** | 158 /** |
| 164 * The pattern (e.g., a URL) for the exception. | 159 * The pattern (e.g., a URL) for the exception. |
| 165 * @type {string} | 160 * @type {string} |
| 166 */ | 161 */ |
| 167 get pattern() { | 162 get pattern() { |
| 168 return this.dataItem['displayPattern']; | 163 return this.dataItem['displayPattern']; |
| 169 }, | 164 }, |
| 170 set pattern(pattern) { | 165 set pattern(pattern) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 192 return templateData.allowException; | 187 return templateData.allowException; |
| 193 else if (setting == 'block') | 188 else if (setting == 'block') |
| 194 return templateData.blockException; | 189 return templateData.blockException; |
| 195 else if (setting == 'ask') | 190 else if (setting == 'ask') |
| 196 return templateData.askException; | 191 return templateData.askException; |
| 197 else if (setting == 'session') | 192 else if (setting == 'session') |
| 198 return templateData.sessionException; | 193 return templateData.sessionException; |
| 199 }, | 194 }, |
| 200 | 195 |
| 201 /** | 196 /** |
| 202 * Update this list item to reflect whether the input is a valid pattern | 197 * Update this list item to reflect whether the input is a valid pattern. |
| 203 * if |pattern| matches the text currently in the input. | |
| 204 * @param {string} pattern The pattern. | |
| 205 * @param {boolean} valid Whether said pattern is valid in the context of | 198 * @param {boolean} valid Whether said pattern is valid in the context of |
| 206 * a content exception setting. | 199 * a content exception setting. |
| 207 */ | 200 */ |
| 208 maybeSetPatternValid: function(pattern, valid) { | 201 setPatternValid: function(valid) { |
| 209 // Don't do anything for messages where we are not the intended recipient, | |
| 210 // or if the response is stale (i.e. the input value has changed since we | |
| 211 // sent the request to analyze it). | |
| 212 if (pattern != this.input.value) | |
| 213 return; | |
| 214 | |
| 215 if (valid) | 202 if (valid) |
| 216 this.input.setCustomValidity(''); | 203 this.input.setCustomValidity(''); |
| 217 else | 204 else |
| 218 this.input.setCustomValidity(' '); | 205 this.input.setCustomValidity(' '); |
| 219 this.inputIsValid = valid; | 206 this.inputIsValid = valid; |
| 220 this.inputValidityKnown = true; | 207 this.inputValidityKnown = true; |
| 221 }, | 208 }, |
| 222 | 209 |
| 223 /** | 210 /** |
| 224 * Copy the data model values to the editable nodes. | 211 * Copy the data model values to the editable nodes. |
| 225 */ | 212 */ |
| 226 updateEditables: function() { | 213 updateEditables: function() { |
| 227 this.input.value = this.pattern; | 214 if (this.isAddNewRow) |
|
stuartmorgan
2010/12/13 17:49:51
It seems like there's a bunch of this kind of logi
Evan Stade
2010/12/13 20:00:19
ok, i'll do this
| |
| 215 this.input.value = ''; | |
| 216 else | |
| 217 this.input.value = this.pattern; | |
| 228 | 218 |
| 229 if (this.setting == 'allow') | 219 if (this.setting == 'allow') |
| 230 this.optionAllow.selected = true; | 220 this.optionAllow.selected = true; |
| 231 else if (this.setting == 'block') | 221 else if (this.setting == 'block') |
| 232 this.optionBlock.selected = true; | 222 this.optionBlock.selected = true; |
| 233 else if (this.setting == 'session' && this.optionSession) | 223 else if (this.setting == 'session' && this.optionSession) |
| 234 this.optionSession.selected = true; | 224 this.optionSession.selected = true; |
| 235 else if (this.setting == 'ask' && this.optionAsk) | 225 else if (this.setting == 'ask' && this.optionAsk) |
| 236 this.optionAsk.selected = true; | 226 this.optionAsk.selected = true; |
| 237 }, | 227 }, |
| 238 | 228 |
| 239 /** | 229 /** |
| 240 * Whether the user is currently able to edit the list item. | 230 * Whether the user is currently able to edit the list item. |
| 241 * @type {boolean} | 231 * @type {boolean} |
| 242 */ | 232 */ |
| 243 get editing() { | 233 get editing() { |
| 244 return this.hasAttribute('editing'); | 234 return this.isAddNewRow || this.hasAttribute('editing'); |
| 245 }, | 235 }, |
| 246 set editing(editing) { | 236 set editing(editing) { |
| 247 var oldEditing = this.editing; | 237 var oldEditing = this.editing; |
| 248 if (oldEditing == editing) | 238 if (!this.isAddNewRow && (oldEditing == editing)) |
| 249 return; | 239 return; |
| 250 | 240 |
| 251 var listItem = this; | 241 var listItem = this; |
| 252 var pattern = this.pattern; | 242 var pattern = this.pattern; |
| 253 var setting = this.setting; | 243 var setting = this.setting; |
| 254 var patternLabel = this.patternLabel; | 244 var patternLabel = this.patternLabel; |
| 255 var settingLabel = this.settingLabel; | 245 var settingLabel = this.settingLabel; |
| 256 var input = this.input; | 246 var input = this.input; |
| 257 var select = this.select; | 247 var select = this.select; |
| 258 var optionAllow = this.optionAllow; | 248 var optionAllow = this.optionAllow; |
| 259 var optionBlock = this.optionBlock; | 249 var optionBlock = this.optionBlock; |
| 260 var optionSession = this.optionSession; | 250 var optionSession = this.optionSession; |
| 261 var optionAsk = this.optionAsk; | 251 var optionAsk = this.optionAsk; |
| 262 | 252 |
| 263 // Just delete this row if it was added via the Add button. | 253 if (!this.isAddNewRow) { |
| 264 if (!editing && !pattern && !input.value) { | 254 patternLabel.classList.toggle('hidden'); |
| 265 var model = listItem.parentNode.dataModel; | 255 settingLabel.classList.toggle('hidden'); |
| 266 model.splice(model.indexOf(listItem.dataItem), 1); | 256 input.classList.toggle('hidden'); |
| 267 return; | 257 select.classList.toggle('hidden'); |
| 268 } | 258 } |
| 269 | 259 |
| 270 // Check that we have a valid pattern and if not we do not change the | |
| 271 // editing mode. | |
| 272 if (!editing && (!this.inputValidityKnown || !this.inputIsValid)) { | |
| 273 input.focus(); | |
| 274 input.select(); | |
| 275 return; | |
| 276 } | |
| 277 | |
| 278 patternLabel.classList.toggle('hidden'); | |
| 279 settingLabel.classList.toggle('hidden'); | |
| 280 input.classList.toggle('hidden'); | |
| 281 select.classList.toggle('hidden'); | |
| 282 | |
| 283 var doc = this.ownerDocument; | |
| 284 var area = doc.querySelector('div[contentType=' + | |
| 285 listItem.contentType + '][mode=' + listItem.mode + ']'); | |
| 286 area.enableAddAndEditButtons(!editing); | |
| 287 | |
| 288 if (editing) { | 260 if (editing) { |
| 289 this.setAttribute('editing', ''); | 261 this.setAttribute('editing', ''); |
| 290 cr.ui.limitInputWidth(input, this, 20); | 262 cr.ui.limitInputWidth(input, this, 20); |
| 291 input.focus(); | 263 // When this is called in response to the selectedChange event, |
| 292 input.select(); | 264 // the list grabs focus immediately afterwards. Thus we must delay |
| 265 // our focus grab. | |
| 266 window.setTimeout(function() { | |
| 267 input.focus(); | |
| 268 input.select(); | |
| 269 }, 50); | |
| 270 | |
| 271 // TODO(estade): should we insert example text here for the AddNewRow | |
| 272 // input? | |
| 293 } else { | 273 } else { |
| 294 this.removeAttribute('editing'); | 274 this.removeAttribute('editing'); |
| 295 | 275 |
| 276 // Check that we have a valid pattern and if not we do not, abort | |
| 277 // changes to the exception. | |
| 278 if (!this.inputValidityKnown || !this.inputIsValid) { | |
| 279 this.updateEditables(); | |
| 280 this.setPatternValid(true); | |
| 281 return; | |
| 282 } | |
| 283 | |
| 296 var newPattern = input.value; | 284 var newPattern = input.value; |
| 297 | 285 |
| 298 var newSetting; | 286 var newSetting; |
| 299 if (optionAllow.selected) | 287 if (optionAllow.selected) |
| 300 newSetting = 'allow'; | 288 newSetting = 'allow'; |
| 301 else if (optionBlock.selected) | 289 else if (optionBlock.selected) |
| 302 newSetting = 'block'; | 290 newSetting = 'block'; |
| 303 else if (optionSession && optionSession.selected) | 291 else if (optionSession && optionSession.selected) |
| 304 newSetting = 'session'; | 292 newSetting = 'session'; |
| 305 else if (optionAsk && optionAsk.selected) | 293 else if (optionAsk && optionAsk.selected) |
| 306 newSetting = 'ask'; | 294 newSetting = 'ask'; |
| 307 | 295 |
| 308 // Empty edit - do nothing. | 296 // Empty edit - do nothing. |
| 309 if (pattern == newPattern && newSetting == this.setting) | 297 if ((pattern == newPattern && newSetting == this.setting) || |
| 298 (this.isAddNewRow && newPattern == '')) { | |
| 310 return; | 299 return; |
| 300 } | |
| 311 | 301 |
| 312 this.pattern = patternLabel.textContent = newPattern; | 302 if (!this.isAddNewRow) { |
| 313 this.setting = newSetting; | 303 patternLabel.textContent = newPattern; |
| 314 settingLabel.textContent = this.settingForDisplay(); | 304 settingLabel.textContent = this.settingForDisplay(); |
| 305 this.pattern = newPattern; | |
| 306 this.setting = newSetting; | |
| 307 } | |
| 315 | 308 |
| 316 if (pattern != this.pattern) { | 309 if (pattern != newPattern) { |
| 317 chrome.send('removeExceptions', | 310 chrome.send('removeExceptions', |
| 318 [this.contentType, this.mode, pattern]); | 311 [this.contentType, this.mode, pattern]); |
| 319 } | 312 } |
| 320 | 313 |
| 321 chrome.send('setException', | 314 chrome.send('setException', |
| 322 [this.contentType, this.mode, this.pattern, this.setting]); | 315 [this.contentType, this.mode, newPattern, newSetting]); |
| 323 } | 316 } |
| 324 } | 317 } |
| 325 }; | 318 }; |
| 326 | 319 |
| 327 /** | 320 /** |
| 328 * Creates a new exceptions list. | 321 * Creates a new exceptions list. |
| 329 * @constructor | 322 * @constructor |
| 330 * @extends {cr.ui.List} | 323 * @extends {cr.ui.List} |
| 331 */ | 324 */ |
| 332 var ExceptionsList = cr.ui.define('list'); | 325 var ExceptionsList = cr.ui.define('list'); |
| 333 | 326 |
| 334 ExceptionsList.prototype = { | 327 ExceptionsList.prototype = { |
| 335 __proto__: List.prototype, | 328 __proto__: List.prototype, |
| 336 | 329 |
| 337 /** | 330 /** |
| 338 * Called when an element is decorated as a list. | 331 * Called when an element is decorated as a list. |
| 339 */ | 332 */ |
| 340 decorate: function() { | 333 decorate: function() { |
| 341 List.prototype.decorate.call(this); | 334 List.prototype.decorate.call(this); |
| 342 | 335 |
| 343 this.dataModel = new ArrayDataModel([]); | 336 this.dataModel = new ArrayDataModel([]); |
| 344 | 337 |
| 338 this.contentType = this.parentNode.getAttribute('contentType'); | |
| 339 this.mode = this.getAttribute('mode'); | |
| 340 | |
| 341 var exceptionList = this; | |
| 342 function handleBlur(e) { | |
| 343 // When the blur event happens we do not know who is getting focus so we | |
| 344 // delay this a bit since we want to know if the other input got focus | |
| 345 // before deciding if we should clear the selection. | |
| 346 var doc = e.target.ownerDocument; | |
| 347 window.setTimeout(function() { | |
| 348 var activeElement = doc.activeElement; | |
| 349 if (!exceptionList.contains(activeElement)) | |
| 350 exceptionList.selectionModel.clear(); | |
| 351 }, 50); | |
| 352 } | |
| 353 | |
| 354 this.addEventListener('blur', handleBlur, true); | |
| 355 | |
| 345 // Whether the exceptions in this list allow an 'Ask every time' option. | 356 // Whether the exceptions in this list allow an 'Ask every time' option. |
| 346 this.enableAskOption = (this.contentType == 'plugins' && | 357 this.enableAskOption = (this.contentType == 'plugins' && |
| 347 templateData.enable_click_to_play); | 358 templateData.enable_click_to_play); |
| 359 | |
| 360 this.reset(); | |
| 348 }, | 361 }, |
| 349 | 362 |
| 350 /** | 363 /** |
| 351 * Creates an item to go in the list. | 364 * Creates an item to go in the list. |
| 352 * @param {Object} entry The element from the data model for this row. | 365 * @param {Object} entry The element from the data model for this row. |
| 353 */ | 366 */ |
| 354 createItem: function(entry) { | 367 createItem: function(entry) { |
| 355 return new ExceptionsListItem(this.contentType, | 368 return new ExceptionsListItem(this.contentType, |
| 356 this.mode, | 369 this.mode, |
| 357 this.enableAskOption, | 370 this.enableAskOption, |
| 358 entry); | 371 entry); |
| 359 }, | 372 }, |
| 360 | 373 |
| 361 /** | 374 /** |
| 362 * Adds an exception to the js model. | 375 * Adds an exception to the js model. |
| 363 * @param {Object} entry A dictionary of values for the exception. | 376 * @param {Object} entry A dictionary of values for the exception. |
| 364 */ | 377 */ |
| 365 addException: function(entry) { | 378 addException: function(entry) { |
| 366 this.dataModel.push(entry); | 379 this.dataModel.push(entry); |
| 367 | |
| 368 // When an empty row is added, put it into editing mode. | |
| 369 if (!entry['displayPattern'] && !entry['setting']) { | |
| 370 var index = this.dataModel.length - 1; | |
| 371 var sm = this.selectionModel; | |
| 372 sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index; | |
| 373 this.scrollIndexIntoView(index); | |
| 374 var li = this.getListItemByIndex(index); | |
| 375 li.editing = true; | |
| 376 } | |
| 377 }, | 380 }, |
| 378 | 381 |
| 379 /** | 382 /** |
| 380 * The browser has finished checking a pattern for validity. Update the | 383 * The browser has finished checking a pattern for validity. Update the |
| 381 * list item to reflect this. | 384 * list item to reflect this. |
| 382 * @param {string} pattern The pattern. | 385 * @param {string} pattern The pattern. |
| 383 * @param {bool} valid Whether said pattern is valid in the context of | 386 * @param {bool} valid Whether said pattern is valid in the context of |
| 384 * a content exception setting. | 387 * a content exception setting. |
| 385 */ | 388 */ |
| 386 patternValidityCheckComplete: function(pattern, valid) { | 389 patternValidityCheckComplete: function(pattern, valid) { |
| 387 for (var i = 0; i < this.dataModel.length; i++) { | 390 for (var i = this.firstIndex_; i < this.lastIndex_; i++) { |
| 388 var listItem = this.getListItemByIndex(i); | 391 var listItem = this.getListItemByIndex(i); |
| 389 if (listItem) | 392 // Don't do anything for messages for the item if it is not the intended |
| 390 listItem.maybeSetPatternValid(pattern, valid); | 393 // recipient, or if the response is stale (i.e. the input value has |
| 394 // changed since we sent the request to analyze it). | |
| 395 if (pattern == listItem.input.value) | |
| 396 listItem.setPatternValid(valid); | |
| 391 } | 397 } |
| 392 }, | 398 }, |
| 393 | 399 |
| 394 /** | 400 /** |
| 395 * Removes all exceptions from the js model. | 401 * Removes all exceptions from the js model. |
| 396 */ | 402 */ |
| 397 clear: function() { | 403 reset: function() { |
| 398 this.dataModel = new ArrayDataModel([]); | 404 this.dataModel = new ArrayDataModel([]); |
| 405 var addItemEntry = []; | |
| 406 this.dataModel.push(addItemEntry); | |
| 399 }, | 407 }, |
| 400 | 408 |
| 401 /** | 409 /** |
| 402 * Removes all selected rows from browser's model. | 410 * Removes all selected rows from browser's model. |
| 403 */ | 411 */ |
| 404 removeSelectedRows: function() { | 412 removeSelectedRows: function() { |
| 405 // The first member is the content type; the rest of the values describe | 413 // The first member is the content type; the rest of the values describe |
| 406 // the patterns we are removing. | 414 // the patterns we are removing. |
| 407 var args = [this.contentType]; | 415 var args = [this.contentType]; |
| 408 var selectedItems = this.selectedItems; | 416 var selectedItems = this.selectedItems; |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 430 if (li) | 438 if (li) |
| 431 li.editing = true; | 439 li.editing = true; |
| 432 } | 440 } |
| 433 }; | 441 }; |
| 434 | 442 |
| 435 return { | 443 return { |
| 436 ExceptionsListItem: ExceptionsListItem, | 444 ExceptionsListItem: ExceptionsListItem, |
| 437 ExceptionsList: ExceptionsList, | 445 ExceptionsList: ExceptionsList, |
| 438 }; | 446 }; |
| 439 }); | 447 }); |
| OLD | NEW |