Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(36)

Unified Diff: chrome/browser/resources/options/content_settings_exceptions_area.js

Issue 5699004: [tabbed options] more work on content settings exceptions lists (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use array.filter Created 10 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/resources/options/content_settings_exceptions_area.js
diff --git a/chrome/browser/resources/options/content_settings_exceptions_area.js b/chrome/browser/resources/options/content_settings_exceptions_area.js
index f727476bee28a9e8e6e33398bf672301979f3b5a..70775599055e4600905fc9228411f3b903eba1ed 100644
--- a/chrome/browser/resources/options/content_settings_exceptions_area.js
+++ b/chrome/browser/resources/options/content_settings_exceptions_area.js
@@ -39,21 +39,27 @@ cr.define('options.contentSettings', function() {
decorate: function() {
ListItem.prototype.decorate.call(this);
- // Labels for display mode.
- var patternLabel = cr.doc.createElement('span');
- patternLabel.textContent = this.pattern;
- this.appendChild(patternLabel);
-
- var settingLabel = cr.doc.createElement('span');
- settingLabel.textContent = this.settingForDisplay();
- settingLabel.className = 'exceptionSetting';
- this.appendChild(settingLabel);
+ // Labels for display mode. |pattern| will be null for the 'add new
+ // exception' row.
+ if (this.pattern) {
+ var patternLabel = cr.doc.createElement('span');
+ patternLabel.textContent = this.pattern;
+ patternLabel.className = 'exceptionPattern';
+ this.appendChild(patternLabel);
+ this.patternLabel = patternLabel;
+
+ var settingLabel = cr.doc.createElement('span');
+ settingLabel.textContent = this.settingForDisplay();
+ settingLabel.className = 'exceptionSetting';
+ this.appendChild(settingLabel);
+ this.settingLabel = settingLabel;
+ }
// Elements for edit mode.
var input = cr.doc.createElement('input');
input.type = 'text';
this.appendChild(input);
- input.className = 'exceptionInput hidden';
+ input.className = 'exceptionPattern hidden';
var select = cr.doc.createElement('select');
var optionAllow = cr.doc.createElement('option');
@@ -93,26 +99,23 @@ cr.define('options.contentSettings', function() {
// empty input.
this.inputIsValid = true;
- this.patternLabel = patternLabel;
- this.settingLabel = settingLabel;
this.input = input;
this.select = select;
this.optionAllow = optionAllow;
this.optionBlock = optionBlock;
this.updateEditables();
- if (!this.pattern)
- input.value = templateData.examplePattern;
var listItem = this;
- this.ondblclick = function(event) {
+
+ this.addEventListener('selectedChange', function(event) {
// Editing notifications and geolocation is disabled for now.
if (listItem.contentType == 'notifications' ||
listItem.contentType == 'location')
return;
- listItem.editing = true;
- };
+ listItem.editing = listItem.selected;
+ });
// Handle events on the editable nodes.
input.oninput = function(event) {
@@ -132,32 +135,14 @@ cr.define('options.contentSettings', function() {
case 'U+001B': // Esc
// Reset the inputs.
listItem.updateEditables();
- if (listItem.pattern)
- listItem.maybeSetPatternValid(listItem.pattern, true);
+ listItem.setPatternValid(true);
case 'Enter':
- if (listItem.parentNode)
- listItem.parentNode.focus();
+ listItem.ownerDocument.activeElement.blur();
}
}
- function handleBlur(e) {
- // When the blur event happens we do not know who is getting focus so we
- // delay this a bit since we want to know if the other input got focus
- // before deciding if we should exit edit mode.
- var doc = e.target.ownerDocument;
- window.setTimeout(function() {
- var activeElement = doc.activeElement;
- if (!listItem.contains(activeElement)) {
- listItem.editing = false;
- }
- }, 50);
- }
-
input.addEventListener('keydown', handleKeydown);
- input.addEventListener('blur', handleBlur);
-
select.addEventListener('keydown', handleKeydown);
- select.addEventListener('blur', handleBlur);
},
/**
@@ -199,20 +184,12 @@ cr.define('options.contentSettings', function() {
},
/**
- * Update this list item to reflect whether the input is a valid pattern
- * if |pattern| matches the text currently in the input.
- * @param {string} pattern The pattern.
+ * Update this list item to reflect whether the input is a valid pattern.
* @param {boolean} valid Whether said pattern is valid in the context of
* a content exception setting.
*/
- maybeSetPatternValid: function(pattern, valid) {
- // Don't do anything for messages where we are not the intended recipient,
- // or if the response is stale (i.e. the input value has changed since we
- // sent the request to analyze it).
- if (pattern != this.input.value)
- return;
-
- if (valid)
+ setPatternValid: function(valid) {
+ if (valid || !this.input.value)
this.input.setCustomValidity('');
else
this.input.setCustomValidity(' ');
@@ -221,10 +198,18 @@ cr.define('options.contentSettings', function() {
},
/**
+ * Set the <input> to its original contents. Used when the user quits
+ * editing.
+ */
+ resetInput: function() {
+ this.input.value = this.pattern;
+ },
+
+ /**
* Copy the data model values to the editable nodes.
*/
updateEditables: function() {
- this.input.value = this.pattern;
+ this.resetInput();
if (this.setting == 'allow')
this.optionAllow.selected = true;
@@ -237,6 +222,17 @@ cr.define('options.contentSettings', function() {
},
/**
+ * Fiddle with the display of elements of this list item when the editing
+ * mode changes.
+ */
+ toggleVisibilityForEditing: function() {
+ this.patternLabel.classList.toggle('hidden');
+ this.settingLabel.classList.toggle('hidden');
+ this.input.classList.toggle('hidden');
+ this.select.classList.toggle('hidden');
+ },
+
+ /**
* Whether the user is currently able to edit the list item.
* @type {boolean}
*/
@@ -248,54 +244,41 @@ cr.define('options.contentSettings', function() {
if (oldEditing == editing)
return;
- var listItem = this;
- var pattern = this.pattern;
- var setting = this.setting;
- var patternLabel = this.patternLabel;
- var settingLabel = this.settingLabel;
var input = this.input;
- var select = this.select;
- var optionAllow = this.optionAllow;
- var optionBlock = this.optionBlock;
- var optionSession = this.optionSession;
- var optionAsk = this.optionAsk;
-
- // Just delete this row if it was added via the Add button.
- if (!editing && !pattern && !input.value) {
- var model = listItem.parentNode.dataModel;
- model.splice(model.indexOf(listItem.dataItem), 1);
- return;
- }
- // Check that we have a valid pattern and if not we do not change the
- // editing mode.
- if (!editing && (!this.inputValidityKnown || !this.inputIsValid)) {
- input.focus();
- input.select();
- return;
- }
-
- patternLabel.classList.toggle('hidden');
- settingLabel.classList.toggle('hidden');
- input.classList.toggle('hidden');
- select.classList.toggle('hidden');
-
- var doc = this.ownerDocument;
- var area = doc.querySelector('div[contentType=' +
- listItem.contentType + '][mode=' + listItem.mode + ']');
- area.enableAddAndEditButtons(!editing);
+ this.toggleVisibilityForEditing();
if (editing) {
this.setAttribute('editing', '');
cr.ui.limitInputWidth(input, this, 20);
- input.focus();
- input.select();
+ // When this is called in response to the selectedChange event,
+ // the list grabs focus immediately afterwards. Thus we must delay
+ // our focus grab.
+ window.setTimeout(function() {
+ input.focus();
+ input.select();
+ }, 50);
+
+ // TODO(estade): should we insert example text here for the AddNewRow
+ // input?
} else {
this.removeAttribute('editing');
+ // Check that we have a valid pattern and if not we do not, abort
+ // changes to the exception.
+ if (!this.inputValidityKnown || !this.inputIsValid) {
+ this.updateEditables();
+ this.setPatternValid(true);
+ return;
+ }
+
var newPattern = input.value;
var newSetting;
+ var optionAllow = this.optionAllow;
+ var optionBlock = this.optionBlock;
+ var optionSession = this.optionSession;
+ var optionAsk = this.optionAsk;
if (optionAllow.selected)
newSetting = 'allow';
else if (optionBlock.selected)
@@ -305,26 +288,103 @@ cr.define('options.contentSettings', function() {
else if (optionAsk && optionAsk.selected)
newSetting = 'ask';
- // Empty edit - do nothing.
- if (pattern == newPattern && newSetting == this.setting)
- return;
+ this.finishEdit(newPattern, newSetting);
+ }
+ },
- this.pattern = patternLabel.textContent = newPattern;
- this.setting = newSetting;
- settingLabel.textContent = this.settingForDisplay();
+ /**
+ * Editing is complete; update the model.
+ * @type {string} newPattern The pattern that the user entered.
+ * @type {string} newSetting The setting the user chose.
+ */
+ finishEdit: function(newPattern, newSetting) {
+ // Empty edit - do nothing.
+ if (newPattern == this.pattern && newSetting == this.setting)
+ return;
- if (pattern != this.pattern) {
- chrome.send('removeExceptions',
- [this.contentType, this.mode, pattern]);
- }
+ this.patternLabel.textContent = newPattern;
+ this.settingLabel.textContent = this.settingForDisplay();
+ var oldPattern = this.pattern;
+ this.pattern = newPattern;
+ this.setting = newSetting;
- chrome.send('setException',
- [this.contentType, this.mode, this.pattern, this.setting]);
+ if (oldPattern != newPattern) {
+ chrome.send('removeExceptions',
+ [this.contentType, this.mode, oldPattern]);
}
+
+ chrome.send('setException',
+ [this.contentType, this.mode, newPattern, newSetting]);
}
};
/**
+ * Creates a new list item for the Add New Item row, which doesn't represent
+ * an actual entry in the exceptions list but allows the user to add new
+ * exceptions.
+ * @param {string} contentType The type of the list.
+ * @param {string} mode The browser mode, 'otr' or 'normal'.
+ * @param {boolean} enableAskOption Whether to show an 'ask every time'
+ * option in the select.
+ * @constructor
+ * @extends {cr.ui.ExceptionsListItem}
+ */
+ function ExceptionsAddRowListItem(contentType, mode, enableAskOption) {
+ var el = cr.doc.createElement('li');
+ el.mode = mode;
+ el.contentType = contentType;
+ el.enableAskOption = enableAskOption;
+ el.dataItem = [];
+ el.__proto__ = ExceptionsAddRowListItem.prototype;
+ el.decorate();
+
+ return el;
+ }
+
+ ExceptionsAddRowListItem.prototype = {
+ __proto__: ExceptionsListItem.prototype,
+
+ decorate: function() {
+ ExceptionsListItem.prototype.decorate.call(this);
+
+ this.input.placeholder = templateData.addNewExceptionInstructions;
+ this.input.classList.remove('hidden');
+ this.select.classList.remove('hidden');
+
+ // Do we always want a default of allow?
+ this.setting = 'allow';
+ },
+
+ /**
+ * Clear the <input> and let the placeholder text show again.
+ */
+ resetInput: function() {
+ this.input.value = '';
+ },
+
+ /**
+ * No elements show or hide when going into edit mode, so do nothing.
+ */
+ toggleVisibilityForEditing: function() {
+ // No-op.
+ },
+
+ /**
+ * Editing is complete; update the model. As long as the pattern isn't
+ * empty, we'll just add it.
+ * @type {string} newPattern The pattern that the user entered.
+ * @type {string} newSetting The setting the user chose.
+ */
+ finishEdit: function(newPattern, newSetting) {
+ if (newPattern == '')
+ return;
+
+ chrome.send('setException',
+ [this.contentType, this.mode, newPattern, newSetting]);
+ },
+ };
+
+ /**
* Creates a new exceptions list.
* @constructor
* @extends {cr.ui.List}
@@ -340,11 +400,29 @@ cr.define('options.contentSettings', function() {
decorate: function() {
List.prototype.decorate.call(this);
- this.dataModel = new ArrayDataModel([]);
+ this.contentType = this.parentNode.getAttribute('contentType');
+ this.mode = this.getAttribute('mode');
+
+ var exceptionList = this;
+ function handleBlur(e) {
+ // When the blur event happens we do not know who is getting focus so we
+ // delay this a bit until we know if the new focus node is outside the
+ // list.
+ var doc = e.target.ownerDocument;
+ window.setTimeout(function() {
+ var activeElement = doc.activeElement;
+ if (!exceptionList.contains(activeElement))
+ exceptionList.selectionModel.clear();
+ }, 50);
+ }
+
+ this.addEventListener('blur', handleBlur, true);
// Whether the exceptions in this list allow an 'Ask every time' option.
this.enableAskOption = (this.contentType == 'plugins' &&
templateData.enable_click_to_play);
+
+ this.reset();
},
/**
@@ -352,10 +430,16 @@ cr.define('options.contentSettings', function() {
* @param {Object} entry The element from the data model for this row.
*/
createItem: function(entry) {
- return new ExceptionsListItem(this.contentType,
- this.mode,
- this.enableAskOption,
- entry);
+ if (entry) {
+ return new ExceptionsListItem(this.contentType,
+ this.mode,
+ this.enableAskOption,
+ entry);
+ } else {
+ return new ExceptionsAddRowListItem(this.contentType,
+ this.mode,
+ this.enableAskOption);
+ }
},
/**
@@ -364,16 +448,6 @@ cr.define('options.contentSettings', function() {
*/
addException: function(entry) {
this.dataModel.push(entry);
-
- // When an empty row is added, put it into editing mode.
- if (!entry['displayPattern'] && !entry['setting']) {
- var index = this.dataModel.length - 1;
- var sm = this.selectionModel;
- sm.anchorIndex = sm.leadIndex = sm.selectedIndex = index;
- this.scrollIndexIntoView(index);
- var li = this.getListItemByIndex(index);
- li.editing = true;
- }
},
/**
@@ -384,18 +458,23 @@ cr.define('options.contentSettings', function() {
* a content exception setting.
*/
patternValidityCheckComplete: function(pattern, valid) {
- for (var i = 0; i < this.dataModel.length; i++) {
- var listItem = this.getListItemByIndex(i);
- if (listItem)
- listItem.maybeSetPatternValid(pattern, valid);
+ var listItems = this.items;
+ for (var i = 0; i < listItems.length; i++) {
+ var listItem = listItems[i];
+ // Don't do anything for messages for the item if it is not the intended
+ // recipient, or if the response is stale (i.e. the input value has
+ // changed since we sent the request to analyze it).
+ if (pattern == listItem.input.value)
+ listItem.setPatternValid(valid);
}
},
/**
* Removes all exceptions from the js model.
*/
- clear: function() {
- this.dataModel = new ArrayDataModel([]);
+ reset: function() {
+ // The null creates the Add New Exception row.
+ this.dataModel = new ArrayDataModel([null]);
},
/**
@@ -434,6 +513,7 @@ cr.define('options.contentSettings', function() {
return {
ExceptionsListItem: ExceptionsListItem,
+ ExceptionsAddRowListItem: ExceptionsAddRowListItem,
ExceptionsList: ExceptionsList,
};
});

Powered by Google App Engine
This is Rietveld 408576698