| 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 var patternLabel = cr.doc.createElement('span'); |
| 46 patternLabel.textContent = this.pattern; |
| 47 patternLabel.className = 'exceptionPattern'; |
| 48 this.appendChild(patternLabel); |
| 49 this.patternLabel = patternLabel; |
| 46 | 50 |
| 47 var settingLabel = cr.doc.createElement('span'); | 51 var settingLabel = cr.doc.createElement('span'); |
| 48 settingLabel.textContent = this.settingForDisplay(); | 52 settingLabel.textContent = this.settingForDisplay(); |
| 49 settingLabel.className = 'exceptionSetting'; | 53 settingLabel.className = 'exceptionSetting'; |
| 50 this.appendChild(settingLabel); | 54 this.appendChild(settingLabel); |
| 55 this.settingLabel = settingLabel; |
| 56 } |
| 51 | 57 |
| 52 // Elements for edit mode. | 58 // Elements for edit mode. |
| 53 var input = cr.doc.createElement('input'); | 59 var input = cr.doc.createElement('input'); |
| 54 input.type = 'text'; | 60 input.type = 'text'; |
| 55 this.appendChild(input); | 61 this.appendChild(input); |
| 56 input.className = 'exceptionInput hidden'; | 62 input.className = 'exceptionPattern hidden'; |
| 57 | 63 |
| 58 var select = cr.doc.createElement('select'); | 64 var select = cr.doc.createElement('select'); |
| 59 var optionAllow = cr.doc.createElement('option'); | 65 var optionAllow = cr.doc.createElement('option'); |
| 60 optionAllow.textContent = templateData.allowException; | 66 optionAllow.textContent = templateData.allowException; |
| 61 select.appendChild(optionAllow); | 67 select.appendChild(optionAllow); |
| 62 | 68 |
| 63 if (this.enableAskOption) { | 69 if (this.enableAskOption) { |
| 64 var optionAsk = cr.doc.createElement('option'); | 70 var optionAsk = cr.doc.createElement('option'); |
| 65 optionAsk.textContent = templateData.askException; | 71 optionAsk.textContent = templateData.askException; |
| 66 select.appendChild(optionAsk); | 72 select.appendChild(optionAsk); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 86 // current text in the input is valid. Changing the text resets this to | 92 // 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. | 93 // 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 | 94 // It starts off as false for empty string (new exceptions) or true for |
| 89 // already-existing exceptions (which we assume are valid). | 95 // already-existing exceptions (which we assume are valid). |
| 90 this.inputValidityKnown = this.pattern; | 96 this.inputValidityKnown = this.pattern; |
| 91 // This one tracks the actual validity of the pattern in the input. This | 97 // 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 | 98 // starts off as true so as not to annoy the user when he adds a new and |
| 93 // empty input. | 99 // empty input. |
| 94 this.inputIsValid = true; | 100 this.inputIsValid = true; |
| 95 | 101 |
| 96 this.patternLabel = patternLabel; | |
| 97 this.settingLabel = settingLabel; | |
| 98 this.input = input; | 102 this.input = input; |
| 99 this.select = select; | 103 this.select = select; |
| 100 this.optionAllow = optionAllow; | 104 this.optionAllow = optionAllow; |
| 101 this.optionBlock = optionBlock; | 105 this.optionBlock = optionBlock; |
| 102 | 106 |
| 103 this.updateEditables(); | 107 this.updateEditables(); |
| 104 if (!this.pattern) | |
| 105 input.value = templateData.examplePattern; | |
| 106 | 108 |
| 107 var listItem = this; | 109 var listItem = this; |
| 108 this.ondblclick = function(event) { | 110 |
| 111 this.addEventListener('selectedChange', function(event) { |
| 109 // Editing notifications and geolocation is disabled for now. | 112 // Editing notifications and geolocation is disabled for now. |
| 110 if (listItem.contentType == 'notifications' || | 113 if (listItem.contentType == 'notifications' || |
| 111 listItem.contentType == 'location') | 114 listItem.contentType == 'location') |
| 112 return; | 115 return; |
| 113 | 116 |
| 114 listItem.editing = true; | 117 listItem.editing = listItem.selected; |
| 115 }; | 118 }); |
| 116 | 119 |
| 117 // Handle events on the editable nodes. | 120 // Handle events on the editable nodes. |
| 118 input.oninput = function(event) { | 121 input.oninput = function(event) { |
| 119 listItem.inputValidityKnown = false; | 122 listItem.inputValidityKnown = false; |
| 120 chrome.send('checkExceptionPatternValidity', | 123 chrome.send('checkExceptionPatternValidity', |
| 121 [listItem.contentType, listItem.mode, input.value]); | 124 [listItem.contentType, listItem.mode, input.value]); |
| 122 }; | 125 }; |
| 123 | 126 |
| 124 // Handles enter and escape which trigger reset and commit respectively. | 127 // Handles enter and escape which trigger reset and commit respectively. |
| 125 function handleKeydown(e) { | 128 function handleKeydown(e) { |
| 126 // Make sure that the tree does not handle the key. | 129 // Make sure that the tree does not handle the key. |
| 127 e.stopPropagation(); | 130 e.stopPropagation(); |
| 128 | 131 |
| 129 // Calling list.focus blurs the input which will stop editing the list | 132 // Calling list.focus blurs the input which will stop editing the list |
| 130 // item. | 133 // item. |
| 131 switch (e.keyIdentifier) { | 134 switch (e.keyIdentifier) { |
| 132 case 'U+001B': // Esc | 135 case 'U+001B': // Esc |
| 133 // Reset the inputs. | 136 // Reset the inputs. |
| 134 listItem.updateEditables(); | 137 listItem.updateEditables(); |
| 135 if (listItem.pattern) | 138 listItem.setPatternValid(true); |
| 136 listItem.maybeSetPatternValid(listItem.pattern, true); | |
| 137 case 'Enter': | 139 case 'Enter': |
| 138 if (listItem.parentNode) | 140 listItem.ownerDocument.activeElement.blur(); |
| 139 listItem.parentNode.focus(); | |
| 140 } | 141 } |
| 141 } | 142 } |
| 142 | 143 |
| 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); | 144 input.addEventListener('keydown', handleKeydown); |
| 157 input.addEventListener('blur', handleBlur); | |
| 158 | |
| 159 select.addEventListener('keydown', handleKeydown); | 145 select.addEventListener('keydown', handleKeydown); |
| 160 select.addEventListener('blur', handleBlur); | |
| 161 }, | 146 }, |
| 162 | 147 |
| 163 /** | 148 /** |
| 164 * The pattern (e.g., a URL) for the exception. | 149 * The pattern (e.g., a URL) for the exception. |
| 165 * @type {string} | 150 * @type {string} |
| 166 */ | 151 */ |
| 167 get pattern() { | 152 get pattern() { |
| 168 return this.dataItem['displayPattern']; | 153 return this.dataItem['displayPattern']; |
| 169 }, | 154 }, |
| 170 set pattern(pattern) { | 155 set pattern(pattern) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 192 return templateData.allowException; | 177 return templateData.allowException; |
| 193 else if (setting == 'block') | 178 else if (setting == 'block') |
| 194 return templateData.blockException; | 179 return templateData.blockException; |
| 195 else if (setting == 'ask') | 180 else if (setting == 'ask') |
| 196 return templateData.askException; | 181 return templateData.askException; |
| 197 else if (setting == 'session') | 182 else if (setting == 'session') |
| 198 return templateData.sessionException; | 183 return templateData.sessionException; |
| 199 }, | 184 }, |
| 200 | 185 |
| 201 /** | 186 /** |
| 202 * Update this list item to reflect whether the input is a valid pattern | 187 * 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 | 188 * @param {boolean} valid Whether said pattern is valid in the context of |
| 206 * a content exception setting. | 189 * a content exception setting. |
| 207 */ | 190 */ |
| 208 maybeSetPatternValid: function(pattern, valid) { | 191 setPatternValid: function(valid) { |
| 209 // Don't do anything for messages where we are not the intended recipient, | 192 if (valid || !this.input.value) |
| 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) | |
| 216 this.input.setCustomValidity(''); | 193 this.input.setCustomValidity(''); |
| 217 else | 194 else |
| 218 this.input.setCustomValidity(' '); | 195 this.input.setCustomValidity(' '); |
| 219 this.inputIsValid = valid; | 196 this.inputIsValid = valid; |
| 220 this.inputValidityKnown = true; | 197 this.inputValidityKnown = true; |
| 221 }, | 198 }, |
| 222 | 199 |
| 223 /** | 200 /** |
| 201 * Set the <input> to its original contents. Used when the user quits |
| 202 * editing. |
| 203 */ |
| 204 resetInput: function() { |
| 205 this.input.value = this.pattern; |
| 206 }, |
| 207 |
| 208 /** |
| 224 * Copy the data model values to the editable nodes. | 209 * Copy the data model values to the editable nodes. |
| 225 */ | 210 */ |
| 226 updateEditables: function() { | 211 updateEditables: function() { |
| 227 this.input.value = this.pattern; | 212 this.resetInput(); |
| 228 | 213 |
| 229 if (this.setting == 'allow') | 214 if (this.setting == 'allow') |
| 230 this.optionAllow.selected = true; | 215 this.optionAllow.selected = true; |
| 231 else if (this.setting == 'block') | 216 else if (this.setting == 'block') |
| 232 this.optionBlock.selected = true; | 217 this.optionBlock.selected = true; |
| 233 else if (this.setting == 'session' && this.optionSession) | 218 else if (this.setting == 'session' && this.optionSession) |
| 234 this.optionSession.selected = true; | 219 this.optionSession.selected = true; |
| 235 else if (this.setting == 'ask' && this.optionAsk) | 220 else if (this.setting == 'ask' && this.optionAsk) |
| 236 this.optionAsk.selected = true; | 221 this.optionAsk.selected = true; |
| 237 }, | 222 }, |
| 238 | 223 |
| 239 /** | 224 /** |
| 225 * Fiddle with the display of elements of this list item when the editing |
| 226 * mode changes. |
| 227 */ |
| 228 toggleVisibilityForEditing: function() { |
| 229 this.patternLabel.classList.toggle('hidden'); |
| 230 this.settingLabel.classList.toggle('hidden'); |
| 231 this.input.classList.toggle('hidden'); |
| 232 this.select.classList.toggle('hidden'); |
| 233 }, |
| 234 |
| 235 /** |
| 240 * Whether the user is currently able to edit the list item. | 236 * Whether the user is currently able to edit the list item. |
| 241 * @type {boolean} | 237 * @type {boolean} |
| 242 */ | 238 */ |
| 243 get editing() { | 239 get editing() { |
| 244 return this.hasAttribute('editing'); | 240 return this.hasAttribute('editing'); |
| 245 }, | 241 }, |
| 246 set editing(editing) { | 242 set editing(editing) { |
| 247 var oldEditing = this.editing; | 243 var oldEditing = this.editing; |
| 248 if (oldEditing == editing) | 244 if (oldEditing == editing) |
| 249 return; | 245 return; |
| 250 | 246 |
| 251 var listItem = this; | |
| 252 var pattern = this.pattern; | |
| 253 var setting = this.setting; | |
| 254 var patternLabel = this.patternLabel; | |
| 255 var settingLabel = this.settingLabel; | |
| 256 var input = this.input; | 247 var input = this.input; |
| 257 var select = this.select; | |
| 258 var optionAllow = this.optionAllow; | |
| 259 var optionBlock = this.optionBlock; | |
| 260 var optionSession = this.optionSession; | |
| 261 var optionAsk = this.optionAsk; | |
| 262 | 248 |
| 263 // Just delete this row if it was added via the Add button. | 249 this.toggleVisibilityForEditing(); |
| 264 if (!editing && !pattern && !input.value) { | |
| 265 var model = listItem.parentNode.dataModel; | |
| 266 model.splice(model.indexOf(listItem.dataItem), 1); | |
| 267 return; | |
| 268 } | |
| 269 | |
| 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 | 250 |
| 288 if (editing) { | 251 if (editing) { |
| 289 this.setAttribute('editing', ''); | 252 this.setAttribute('editing', ''); |
| 290 cr.ui.limitInputWidth(input, this, 20); | 253 cr.ui.limitInputWidth(input, this, 20); |
| 291 input.focus(); | 254 // When this is called in response to the selectedChange event, |
| 292 input.select(); | 255 // the list grabs focus immediately afterwards. Thus we must delay |
| 256 // our focus grab. |
| 257 window.setTimeout(function() { |
| 258 input.focus(); |
| 259 input.select(); |
| 260 }, 50); |
| 261 |
| 262 // TODO(estade): should we insert example text here for the AddNewRow |
| 263 // input? |
| 293 } else { | 264 } else { |
| 294 this.removeAttribute('editing'); | 265 this.removeAttribute('editing'); |
| 295 | 266 |
| 267 // Check that we have a valid pattern and if not we do not, abort |
| 268 // changes to the exception. |
| 269 if (!this.inputValidityKnown || !this.inputIsValid) { |
| 270 this.updateEditables(); |
| 271 this.setPatternValid(true); |
| 272 return; |
| 273 } |
| 274 |
| 296 var newPattern = input.value; | 275 var newPattern = input.value; |
| 297 | 276 |
| 298 var newSetting; | 277 var newSetting; |
| 278 var optionAllow = this.optionAllow; |
| 279 var optionBlock = this.optionBlock; |
| 280 var optionSession = this.optionSession; |
| 281 var optionAsk = this.optionAsk; |
| 299 if (optionAllow.selected) | 282 if (optionAllow.selected) |
| 300 newSetting = 'allow'; | 283 newSetting = 'allow'; |
| 301 else if (optionBlock.selected) | 284 else if (optionBlock.selected) |
| 302 newSetting = 'block'; | 285 newSetting = 'block'; |
| 303 else if (optionSession && optionSession.selected) | 286 else if (optionSession && optionSession.selected) |
| 304 newSetting = 'session'; | 287 newSetting = 'session'; |
| 305 else if (optionAsk && optionAsk.selected) | 288 else if (optionAsk && optionAsk.selected) |
| 306 newSetting = 'ask'; | 289 newSetting = 'ask'; |
| 307 | 290 |
| 308 // Empty edit - do nothing. | 291 this.finishEdit(newPattern, newSetting); |
| 309 if (pattern == newPattern && newSetting == this.setting) | 292 } |
| 310 return; | 293 }, |
| 311 | 294 |
| 312 this.pattern = patternLabel.textContent = newPattern; | 295 /** |
| 313 this.setting = newSetting; | 296 * Editing is complete; update the model. |
| 314 settingLabel.textContent = this.settingForDisplay(); | 297 * @type {string} newPattern The pattern that the user entered. |
| 298 * @type {string} newSetting The setting the user chose. |
| 299 */ |
| 300 finishEdit: function(newPattern, newSetting) { |
| 301 // Empty edit - do nothing. |
| 302 if (newPattern == this.pattern && newSetting == this.setting) |
| 303 return; |
| 315 | 304 |
| 316 if (pattern != this.pattern) { | 305 this.patternLabel.textContent = newPattern; |
| 317 chrome.send('removeExceptions', | 306 this.settingLabel.textContent = this.settingForDisplay(); |
| 318 [this.contentType, this.mode, pattern]); | 307 var oldPattern = this.pattern; |
| 319 } | 308 this.pattern = newPattern; |
| 309 this.setting = newSetting; |
| 320 | 310 |
| 321 chrome.send('setException', | 311 if (oldPattern != newPattern) { |
| 322 [this.contentType, this.mode, this.pattern, this.setting]); | 312 chrome.send('removeExceptions', |
| 313 [this.contentType, this.mode, oldPattern]); |
| 323 } | 314 } |
| 315 |
| 316 chrome.send('setException', |
| 317 [this.contentType, this.mode, newPattern, newSetting]); |
| 324 } | 318 } |
| 325 }; | 319 }; |
| 326 | 320 |
| 327 /** | 321 /** |
| 322 * Creates a new list item for the Add New Item row, which doesn't represent |
| 323 * an actual entry in the exceptions list but allows the user to add new |
| 324 * exceptions. |
| 325 * @param {string} contentType The type of the list. |
| 326 * @param {string} mode The browser mode, 'otr' or 'normal'. |
| 327 * @param {boolean} enableAskOption Whether to show an 'ask every time' |
| 328 * option in the select. |
| 329 * @constructor |
| 330 * @extends {cr.ui.ExceptionsListItem} |
| 331 */ |
| 332 function ExceptionsAddRowListItem(contentType, mode, enableAskOption) { |
| 333 var el = cr.doc.createElement('li'); |
| 334 el.mode = mode; |
| 335 el.contentType = contentType; |
| 336 el.enableAskOption = enableAskOption; |
| 337 el.dataItem = []; |
| 338 el.__proto__ = ExceptionsAddRowListItem.prototype; |
| 339 el.decorate(); |
| 340 |
| 341 return el; |
| 342 } |
| 343 |
| 344 ExceptionsAddRowListItem.prototype = { |
| 345 __proto__: ExceptionsListItem.prototype, |
| 346 |
| 347 decorate: function() { |
| 348 ExceptionsListItem.prototype.decorate.call(this); |
| 349 |
| 350 this.input.placeholder = templateData.addNewExceptionInstructions; |
| 351 this.input.classList.remove('hidden'); |
| 352 this.select.classList.remove('hidden'); |
| 353 |
| 354 // Do we always want a default of allow? |
| 355 this.setting = 'allow'; |
| 356 }, |
| 357 |
| 358 /** |
| 359 * Clear the <input> and let the placeholder text show again. |
| 360 */ |
| 361 resetInput: function() { |
| 362 this.input.value = ''; |
| 363 }, |
| 364 |
| 365 /** |
| 366 * No elements show or hide when going into edit mode, so do nothing. |
| 367 */ |
| 368 toggleVisibilityForEditing: function() { |
| 369 // No-op. |
| 370 }, |
| 371 |
| 372 /** |
| 373 * Editing is complete; update the model. As long as the pattern isn't |
| 374 * empty, we'll just add it. |
| 375 * @type {string} newPattern The pattern that the user entered. |
| 376 * @type {string} newSetting The setting the user chose. |
| 377 */ |
| 378 finishEdit: function(newPattern, newSetting) { |
| 379 if (newPattern == '') |
| 380 return; |
| 381 |
| 382 chrome.send('setException', |
| 383 [this.contentType, this.mode, newPattern, newSetting]); |
| 384 }, |
| 385 }; |
| 386 |
| 387 /** |
| 328 * Creates a new exceptions list. | 388 * Creates a new exceptions list. |
| 329 * @constructor | 389 * @constructor |
| 330 * @extends {cr.ui.List} | 390 * @extends {cr.ui.List} |
| 331 */ | 391 */ |
| 332 var ExceptionsList = cr.ui.define('list'); | 392 var ExceptionsList = cr.ui.define('list'); |
| 333 | 393 |
| 334 ExceptionsList.prototype = { | 394 ExceptionsList.prototype = { |
| 335 __proto__: List.prototype, | 395 __proto__: List.prototype, |
| 336 | 396 |
| 337 /** | 397 /** |
| 338 * Called when an element is decorated as a list. | 398 * Called when an element is decorated as a list. |
| 339 */ | 399 */ |
| 340 decorate: function() { | 400 decorate: function() { |
| 341 List.prototype.decorate.call(this); | 401 List.prototype.decorate.call(this); |
| 342 | 402 |
| 343 this.dataModel = new ArrayDataModel([]); | 403 this.contentType = this.parentNode.getAttribute('contentType'); |
| 404 this.mode = this.getAttribute('mode'); |
| 405 |
| 406 var exceptionList = this; |
| 407 function handleBlur(e) { |
| 408 // When the blur event happens we do not know who is getting focus so we |
| 409 // delay this a bit until we know if the new focus node is outside the l
ist. |
| 410 var doc = e.target.ownerDocument; |
| 411 window.setTimeout(function() { |
| 412 var activeElement = doc.activeElement; |
| 413 if (!exceptionList.contains(activeElement)) |
| 414 exceptionList.selectionModel.clear(); |
| 415 }, 50); |
| 416 } |
| 417 |
| 418 this.addEventListener('blur', handleBlur, true); |
| 344 | 419 |
| 345 // Whether the exceptions in this list allow an 'Ask every time' option. | 420 // Whether the exceptions in this list allow an 'Ask every time' option. |
| 346 this.enableAskOption = (this.contentType == 'plugins' && | 421 this.enableAskOption = (this.contentType == 'plugins' && |
| 347 templateData.enable_click_to_play); | 422 templateData.enable_click_to_play); |
| 423 |
| 424 this.reset(); |
| 348 }, | 425 }, |
| 349 | 426 |
| 350 /** | 427 /** |
| 351 * Creates an item to go in the list. | 428 * Creates an item to go in the list. |
| 352 * @param {Object} entry The element from the data model for this row. | 429 * @param {Object} entry The element from the data model for this row. |
| 353 */ | 430 */ |
| 354 createItem: function(entry) { | 431 createItem: function(entry) { |
| 355 return new ExceptionsListItem(this.contentType, | 432 if (entry) { |
| 356 this.mode, | 433 return new ExceptionsListItem(this.contentType, |
| 357 this.enableAskOption, | 434 this.mode, |
| 358 entry); | 435 this.enableAskOption, |
| 436 entry); |
| 437 } else { |
| 438 return new ExceptionsAddRowListItem(this.contentType, |
| 439 this.mode, |
| 440 this.enableAskOption); |
| 441 } |
| 359 }, | 442 }, |
| 360 | 443 |
| 361 /** | 444 /** |
| 362 * Adds an exception to the js model. | 445 * Adds an exception to the js model. |
| 363 * @param {Object} entry A dictionary of values for the exception. | 446 * @param {Object} entry A dictionary of values for the exception. |
| 364 */ | 447 */ |
| 365 addException: function(entry) { | 448 addException: function(entry) { |
| 366 this.dataModel.push(entry); | 449 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 }, | 450 }, |
| 378 | 451 |
| 379 /** | 452 /** |
| 380 * The browser has finished checking a pattern for validity. Update the | 453 * The browser has finished checking a pattern for validity. Update the |
| 381 * list item to reflect this. | 454 * list item to reflect this. |
| 382 * @param {string} pattern The pattern. | 455 * @param {string} pattern The pattern. |
| 383 * @param {bool} valid Whether said pattern is valid in the context of | 456 * @param {bool} valid Whether said pattern is valid in the context of |
| 384 * a content exception setting. | 457 * a content exception setting. |
| 385 */ | 458 */ |
| 386 patternValidityCheckComplete: function(pattern, valid) { | 459 patternValidityCheckComplete: function(pattern, valid) { |
| 387 for (var i = 0; i < this.dataModel.length; i++) { | 460 var listItems = this.items; |
| 388 var listItem = this.getListItemByIndex(i); | 461 for (var i = 0; i < listItems.length; i++) { |
| 389 if (listItem) | 462 var listItem = listItems[i]; |
| 390 listItem.maybeSetPatternValid(pattern, valid); | 463 // Don't do anything for messages for the item if it is not the intended |
| 464 // recipient, or if the response is stale (i.e. the input value has |
| 465 // changed since we sent the request to analyze it). |
| 466 if (pattern == listItem.input.value) |
| 467 listItem.setPatternValid(valid); |
| 391 } | 468 } |
| 392 }, | 469 }, |
| 393 | 470 |
| 394 /** | 471 /** |
| 395 * Removes all exceptions from the js model. | 472 * Removes all exceptions from the js model. |
| 396 */ | 473 */ |
| 397 clear: function() { | 474 reset: function() { |
| 398 this.dataModel = new ArrayDataModel([]); | 475 // The null creates the Add New Exception row. |
| 476 this.dataModel = new ArrayDataModel([null]); |
| 399 }, | 477 }, |
| 400 | 478 |
| 401 /** | 479 /** |
| 402 * Removes all selected rows from browser's model. | 480 * Removes all selected rows from browser's model. |
| 403 */ | 481 */ |
| 404 removeSelectedRows: function() { | 482 removeSelectedRows: function() { |
| 405 // The first member is the content type; the rest of the values describe | 483 // The first member is the content type; the rest of the values describe |
| 406 // the patterns we are removing. | 484 // the patterns we are removing. |
| 407 var args = [this.contentType]; | 485 var args = [this.contentType]; |
| 408 var selectedItems = this.selectedItems; | 486 var selectedItems = this.selectedItems; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 427 */ | 505 */ |
| 428 editSelectedRow: function() { | 506 editSelectedRow: function() { |
| 429 var li = this.getListItem(this.selectedItem); | 507 var li = this.getListItem(this.selectedItem); |
| 430 if (li) | 508 if (li) |
| 431 li.editing = true; | 509 li.editing = true; |
| 432 } | 510 } |
| 433 }; | 511 }; |
| 434 | 512 |
| 435 return { | 513 return { |
| 436 ExceptionsListItem: ExceptionsListItem, | 514 ExceptionsListItem: ExceptionsListItem, |
| 515 ExceptionsAddRowListItem: ExceptionsAddRowListItem, |
| 437 ExceptionsList: ExceptionsList, | 516 ExceptionsList: ExceptionsList, |
| 438 }; | 517 }; |
| 439 }); | 518 }); |
| OLD | NEW |