| 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 /** |
| 11 * Creates a new exceptions list item. | 11 * Creates a new exceptions list item. |
| 12 * @param {Array} exception A pair of the form [filter, setting]. | 12 * @param {Array} exception A pair of the form [filter, setting]. |
| 13 * @constructor | 13 * @constructor |
| 14 * @extends {cr.ui.ListItem} | 14 * @extends {cr.ui.ListItem} |
| 15 */ | 15 */ |
| 16 function ExceptionsListItem(exception) { | 16 function ExceptionsListItem(exception) { |
| 17 var el = cr.doc.createElement('li'); | 17 var el = cr.doc.createElement('li'); |
| 18 el.exceptionsPattern = exception[0]; | 18 el.dataItem = exception; |
| 19 el.__proto__ = ExceptionsListItem.prototype; | 19 el.__proto__ = ExceptionsListItem.prototype; |
| 20 el.decorate(); | 20 el.decorate(); |
| 21 | 21 |
| 22 if (exception[1] == 'allow') | |
| 23 el.option_allow.selected = 'selected'; | |
| 24 else if (exception[1] == 'block') | |
| 25 el.option_block.selected = 'selected'; | |
| 26 | |
| 27 return el; | 22 return el; |
| 28 } | 23 } |
| 29 | 24 |
| 30 ExceptionsListItem.prototype = { | 25 ExceptionsListItem.prototype = { |
| 31 __proto__: ListItem.prototype, | 26 __proto__: ListItem.prototype, |
| 32 | 27 |
| 33 /** | 28 /** |
| 34 * Called when an element is decorated as a list item. | 29 * Called when an element is decorated as a list item. |
| 35 */ | 30 */ |
| 36 decorate: function() { | 31 decorate: function() { |
| 37 ListItem.prototype.decorate.call(this); | 32 ListItem.prototype.decorate.call(this); |
| 38 | 33 |
| 39 // TODO(estade): these should be plain text when the items are not | 34 // Labels for display mode. |
| 40 // actively being edited. | 35 var patternLabel = cr.doc.createElement('span'); |
| 36 patternLabel.textContent = this.pattern; |
| 37 this.appendChild(patternLabel); |
| 38 |
| 39 var settingLabel = cr.doc.createElement('span'); |
| 40 settingLabel.textContent = this.settingForDisplay(); |
| 41 settingLabel.className = 'exceptionSetting'; |
| 42 this.appendChild(settingLabel); |
| 43 |
| 44 // Elements for edit mode. |
| 41 var input = cr.doc.createElement('input'); | 45 var input = cr.doc.createElement('input'); |
| 42 input.type = 'text'; | 46 input.type = 'text'; |
| 43 input.value = this.exceptionsPattern; | |
| 44 this.appendChild(input); | 47 this.appendChild(input); |
| 45 input.className = 'exceptionInput'; | 48 input.className = 'exceptionInput hidden'; |
| 46 | 49 |
| 47 var select = cr.doc.createElement('select'); | 50 var select = cr.doc.createElement('select'); |
| 48 var option_allow = cr.doc.createElement('option'); | 51 var optionAllow = cr.doc.createElement('option'); |
| 49 option_allow.textContent = templateData.allowException; | 52 optionAllow.textContent = templateData.allowException; |
| 50 var option_block = cr.doc.createElement('option'); | 53 var optionBlock = cr.doc.createElement('option'); |
| 51 option_block.textContent = templateData.blockException; | 54 optionBlock.textContent = templateData.blockException; |
| 52 select.appendChild(option_allow); | 55 select.appendChild(optionAllow); |
| 53 select.appendChild(option_block); | 56 select.appendChild(optionBlock); |
| 54 this.appendChild(select); | 57 this.appendChild(select); |
| 55 select.className = 'exceptionSelect'; | 58 select.className = 'exceptionSetting hidden'; |
| 56 | 59 |
| 60 this.patternLabel = patternLabel; |
| 61 this.settingLabel = settingLabel; |
| 57 this.input = input; | 62 this.input = input; |
| 58 this.select = select; | 63 this.select = select; |
| 59 this.option_allow = option_allow; | 64 this.optionAllow = optionAllow; |
| 60 this.option_block = option_block; | 65 this.optionBlock = optionBlock; |
| 66 |
| 67 this.updateEditables(); |
| 68 |
| 69 // Handle events on the editable nodes. |
| 70 var eventsToStop = |
| 71 ['mousedown', 'mouseup', 'contextmenu', 'dblclick', 'paste']; |
| 72 eventsToStop.forEach(function(type) { |
| 73 input.addEventListener(type, function(e) { |
| 74 e.stopPropagation(); |
| 75 }); |
| 76 } |
| 77 ); |
| 78 |
| 79 var listItem = this; |
| 80 // Handles enter and escape which trigger reset and commit respectively. |
| 81 function handleKeydown(e) { |
| 82 // Make sure that the tree does not handle the key. |
| 83 e.stopPropagation(); |
| 84 |
| 85 // Calling list.focus blurs the input which will stop editing the list |
| 86 // item. |
| 87 switch (e.keyIdentifier) { |
| 88 case 'U+001B': // Esc |
| 89 // Reset the inputs. |
| 90 listItem.updateEditables(); |
| 91 case 'Enter': |
| 92 if (listItem.parentNode) |
| 93 listItem.parentNode.focus(); |
| 94 } |
| 95 } |
| 96 |
| 97 function handleBlur(e) { |
| 98 // When the blur event happens we do not know who is getting focus so we |
| 99 // delay this a bit since we want to know if the other input got focus |
| 100 // before deciding if we should exit edit mode. |
| 101 var doc = e.target.ownerDocument; |
| 102 window.setTimeout(function() { |
| 103 var activeElement = doc.activeElement; |
| 104 if (!listItem.contains(activeElement)) { |
| 105 listItem.editing = false; |
| 106 } |
| 107 }, 50); |
| 108 } |
| 109 |
| 110 input.addEventListener('keydown', handleKeydown); |
| 111 input.addEventListener('blur', handleBlur); |
| 112 |
| 113 select.addEventListener('keydown', handleKeydown); |
| 114 select.addEventListener('blur', handleBlur); |
| 115 }, |
| 116 |
| 117 /** |
| 118 * The pattern (e.g., a URL) for the exception. |
| 119 * @type {string} |
| 120 */ |
| 121 get pattern() { |
| 122 return this.dataItem[0]; |
| 123 }, |
| 124 set pattern(pattern) { |
| 125 this.dataItem[0] = pattern; |
| 126 }, |
| 127 |
| 128 /** |
| 129 * The setting (allow/block) for the exception. |
| 130 * @type {string} |
| 131 */ |
| 132 get setting() { |
| 133 return this.dataItem[1]; |
| 134 }, |
| 135 set setting(setting) { |
| 136 this.dataItem[1] = setting; |
| 137 }, |
| 138 |
| 139 /** |
| 140 * Gets a human-readable setting string. |
| 141 * @type {string} |
| 142 */ |
| 143 settingForDisplay: function() { |
| 144 var setting = this.setting; |
| 145 if (setting == 'allow') |
| 146 return templateData.allowException; |
| 147 else if (setting == 'block') |
| 148 return templateData.blockException; |
| 149 }, |
| 150 |
| 151 /** |
| 152 * Copy the data model values to the editable nodes. |
| 153 */ |
| 154 updateEditables: function() { |
| 155 if (!(this.pattern && this.setting)) |
| 156 return; |
| 157 |
| 158 this.input.value = this.pattern; |
| 159 |
| 160 if (this.setting == 'allow') |
| 161 this.optionAllow.selected = true; |
| 162 else if (this.setting == 'block') |
| 163 this.optionBlock.selected = true; |
| 164 }, |
| 165 |
| 166 /** |
| 167 * Whether the user is currently able to edit the list item. |
| 168 * @type {boolean} |
| 169 */ |
| 170 get editing() { |
| 171 return this.hasAttribute('editing'); |
| 172 }, |
| 173 set editing(editing) { |
| 174 var oldEditing = this.editing; |
| 175 if (oldEditing == editing) |
| 176 return; |
| 177 |
| 178 var listItem = this; |
| 179 var pattern = this.pattern; |
| 180 var setting = this.setting; |
| 181 var patternLabel = this.patternLabel; |
| 182 var settingLabel = this.settingLabel; |
| 183 var input = this.input; |
| 184 var select = this.select; |
| 185 var optionAllow = this.optionAllow; |
| 186 var optionBlock = this.optionBlock; |
| 187 |
| 188 patternLabel.classList.toggle('hidden'); |
| 189 settingLabel.classList.toggle('hidden'); |
| 190 input.classList.toggle('hidden'); |
| 191 select.classList.toggle('hidden'); |
| 192 |
| 193 var doc = this.ownerDocument; |
| 194 if (editing) { |
| 195 this.setAttribute('editing', ''); |
| 196 cr.ui.limitInputWidth(input, this, 20); |
| 197 input.focus(); |
| 198 input.select(); |
| 199 } else { |
| 200 // Check that we have a valid pattern and if not we do not change then |
| 201 // editing mode. |
| 202 var newPattern = input.value; |
| 203 |
| 204 // TODO(estade): check for pattern validity. |
| 205 if (false) { |
| 206 // In case the item was removed before getting here we should |
| 207 // not alert. |
| 208 if (listItem.parentNode) { |
| 209 // TODO(estade): i18n |
| 210 alert('invalid pattern'); |
| 211 } |
| 212 input.focus(); |
| 213 input.select(); |
| 214 return; |
| 215 } |
| 216 |
| 217 this.pattern = patternLabel.textContent = newPattern; |
| 218 if (optionAllow.selected) |
| 219 this.setting = 'allow'; |
| 220 else if (optionBlock.selected) |
| 221 this.setting = 'block'; |
| 222 settingLabel.textContent = this.settingForDisplay(); |
| 223 |
| 224 this.removeAttribute('editing'); |
| 225 |
| 226 if (pattern != this.pattern) |
| 227 chrome.send('removeImageExceptions', [pattern]); |
| 228 |
| 229 chrome.send('setImageException', [this.pattern, this.setting]); |
| 230 } |
| 61 } | 231 } |
| 62 }; | 232 }; |
| 63 | 233 |
| 64 /** | 234 /** |
| 65 * Creates a new exceptions list. | 235 * Creates a new exceptions list. |
| 66 * @constructor | 236 * @constructor |
| 67 * @extends {cr.ui.List} | 237 * @extends {cr.ui.List} |
| 68 */ | 238 */ |
| 69 var ExceptionsList = cr.ui.define('list'); | 239 var ExceptionsList = cr.ui.define('list'); |
| 70 | 240 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 100 * Removes all exceptions from the js model. | 270 * Removes all exceptions from the js model. |
| 101 */ | 271 */ |
| 102 clear: function() { | 272 clear: function() { |
| 103 this.dataModel = new ArrayDataModel([]); | 273 this.dataModel = new ArrayDataModel([]); |
| 104 }, | 274 }, |
| 105 | 275 |
| 106 /** | 276 /** |
| 107 * Removes all selected rows from browser's model. | 277 * Removes all selected rows from browser's model. |
| 108 */ | 278 */ |
| 109 removeSelectedRows: function() { | 279 removeSelectedRows: function() { |
| 110 var selection = this.selectionModel; | |
| 111 var removePatterns = []; | 280 var removePatterns = []; |
| 112 var selectedItems = this.selectedItems; | 281 var selectedItems = this.selectedItems; |
| 113 for (var i = 0; i < selectedItems.length; ++i) { | 282 for (var i = 0; i < selectedItems.length; ++i) { |
| 114 removePatterns.push(selectedItems[i][0]); | 283 removePatterns.push(selectedItems[i][0]); |
| 115 } | 284 } |
| 116 | 285 |
| 117 chrome.send('removeImageExceptions', removePatterns); | 286 chrome.send('removeImageExceptions', removePatterns); |
| 287 }, |
| 288 |
| 289 /** |
| 290 * Puts the selected row in editing mode. |
| 291 */ |
| 292 editSelectedRow: function() { |
| 293 var li = this.getListItem(this.selectedItem); |
| 294 if (li) |
| 295 li.editing = true; |
| 118 } | 296 } |
| 119 }; | 297 }; |
| 120 | 298 |
| 121 var ExceptionsArea = cr.ui.define('div'); | 299 var ExceptionsArea = cr.ui.define('div'); |
| 122 | 300 |
| 123 ExceptionsArea.prototype = { | 301 ExceptionsArea.prototype = { |
| 124 __proto__: HTMLDivElement.prototype, | 302 __proto__: HTMLDivElement.prototype, |
| 125 | 303 |
| 126 decorate: function() { | 304 decorate: function() { |
| 127 ExceptionsList.decorate($('imagesExceptionsList')); | 305 ExceptionsList.decorate($('imagesExceptionsList')); |
| 128 | 306 |
| 129 var addRow = cr.doc.createElement('button'); | 307 var addRow = cr.doc.createElement('button'); |
| 130 addRow.textContent = templateData.addExceptionRow; | 308 addRow.textContent = templateData.addExceptionRow; |
| 131 this.appendChild(addRow); | 309 this.appendChild(addRow); |
| 132 | 310 |
| 311 // TODO(estade): disable "Edit" when other than exactly 1 row is |
| 312 // highlighted. |
| 313 var editRow = cr.doc.createElement('button'); |
| 314 editRow.textContent = templateData.editExceptionRow; |
| 315 this.appendChild(editRow); |
| 316 |
| 133 // TODO(estade): disable "Remove" when no row is highlighted. | 317 // TODO(estade): disable "Remove" when no row is highlighted. |
| 134 var removeRow = cr.doc.createElement('button'); | 318 var removeRow = cr.doc.createElement('button'); |
| 135 removeRow.textContent = templateData.removeExceptionRow; | 319 removeRow.textContent = templateData.removeExceptionRow; |
| 136 this.appendChild(removeRow); | 320 this.appendChild(removeRow); |
| 137 | 321 |
| 322 addRow.onclick = function(event) { |
| 323 // TODO(estade): implement this. |
| 324 }; |
| 325 |
| 326 editRow.onclick = function(event) { |
| 327 imagesExceptionsList.editSelectedRow(); |
| 328 }; |
| 329 |
| 138 removeRow.onclick = function(event) { | 330 removeRow.onclick = function(event) { |
| 139 imagesExceptionsList.removeSelectedRows(); | 331 imagesExceptionsList.removeSelectedRows(); |
| 140 }; | 332 }; |
| 141 | |
| 142 addRow.onclick = function(event) { | |
| 143 // TODO(estade): implement this. | |
| 144 }; | |
| 145 } | 333 } |
| 146 }; | 334 }; |
| 147 | 335 |
| 148 return { | 336 return { |
| 149 ExceptionsListItem: ExceptionsListItem, | 337 ExceptionsListItem: ExceptionsListItem, |
| 150 ExceptionsList: ExceptionsList, | 338 ExceptionsList: ExceptionsList, |
| 151 ExceptionsArea: ExceptionsArea | 339 ExceptionsArea: ExceptionsArea |
| 152 }; | 340 }; |
| 153 }); | 341 }); |
| OLD | NEW |