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.
6 * @fileoverview Defines a list of content setting rules.
9 cr.define('pluginSettings.ui', function() {
10 const InlineEditableItemList = options.InlineEditableItemList;
11 const InlineEditableItem = options.InlineEditableItem;
12 const ArrayDataModel = cr.ui.ArrayDataModel;
15 * CSS classes used by this class.
20 * A list of content setting rules.
22 RULE_LIST: 'rule-list',
25 * The element containing the content setting pattern for a rule.
27 RULE_PATTERN: 'rule-pattern',
30 * The element containing the behavior (allow or block) for a rule.
32 RULE_BEHAVIOR: 'rule-behavior',
35 * Static text (as opposed to an editable text field).
37 STATIC_TEXT: 'static-text',
40 * A single item in a list of rules.
41 * @param {!RuleList} list The rule list containing this item.
42 * @param {!Object} rule The content setting rule.
44 * @extends {options.InlineEditableItem}
46 function RuleListItem(list, rule) {
47 var el = cr.doc.createElement('li');
50 * The content setting rule.
57 * The rule list containing this item.
62 el.__proto__ = RuleListItem.prototype;
68 RuleListItem.prototype = {
69 __proto__: InlineEditableItem.prototype,
72 * The text input element for the pattern. This is only null in the
74 * @type {?HTMLInputElement}
80 * The popup button for the setting. This is only null in the prototype.
81 * @type {?HTMLSelectElement}
87 * The static text field containing the pattern.
88 * @type {?HTMLDivElement}
94 * The static text field containing the setting.
95 * @type {?HTMLDivElement}
101 * Decorates an elements as a list item.
103 decorate: function() {
104 InlineEditableItem.prototype.decorate.call(this);
106 this.isPlaceholder = !this.pattern;
107 var patternCell = this.createEditableTextCell(this.pattern);
108 patternCell.className = CSSClass.RULE_PATTERN;
109 this.contentElement.appendChild(patternCell);
110 var input = patternCell.querySelector('input');
113 patternCell.querySelector('.' + CSSClass.STATIC_TEXT);
115 input.placeholder = chrome.i18n.getMessage('addNewPattern');
118 // TODO(stuartmorgan): Create an createEditableSelectCell abstracting
120 // Setting label for display mode. |pattern| will be null for the 'add new
123 var settingLabel = cr.doc.createElement('span');
124 settingLabel.textContent = this.settingForDisplay();
125 settingLabel.className = CSSClass.RULE_BEHAVIOR;
126 settingLabel.setAttribute('displaymode', 'static');
127 this.contentElement.appendChild(settingLabel);
128 this.settingLabel_ = settingLabel;
131 // Setting select element for edit mode.
132 var select = cr.doc.createElement('select');
133 var optionAllow = cr.doc.createElement('option');
134 optionAllow.textContent = chrome.i18n.getMessage('allowRule');
135 optionAllow.value = 'allow';
136 select.appendChild(optionAllow);
138 var optionBlock = cr.doc.createElement('option');
139 optionBlock.textContent = chrome.i18n.getMessage('blockRule');
140 optionBlock.value = 'block';
141 select.appendChild(optionBlock);
143 this.contentElement.appendChild(select);
144 select.className = CSSClass.RULE_BEHAVIOR;
146 select.setAttribute('displaymode', 'edit');
150 this.select_ = select;
152 this.updateEditables();
154 // Listen for edit events.
155 this.addEventListener('canceledit', this.onEditCancelled_);
156 this.addEventListener('commitedit', this.onEditCommitted_);
160 * The pattern (e.g., a URL) for the rule.
164 return this.dataItem_['primaryPattern'];
166 set pattern(pattern) {
167 this.dataItem_['primaryPattern'] = pattern;
171 * The setting (allow/block) for the rule.
175 return this.dataItem_['setting'];
177 set setting(setting) {
178 this.dataItem_['setting'] = setting;
182 * Gets a human-readable setting string.
185 settingForDisplay: function() {
186 var setting = this.setting;
187 if (setting == 'allow') {
188 return chrome.i18n.getMessage('allowRule');
190 if (setting == 'block') {
191 return chrome.i18n.getMessage('blockRule');
196 * Set the <input> to its original contents. Used when the user quits
199 resetInput: function() {
200 this.input_.value = this.pattern;
204 * Copy the data model values to the editable nodes.
206 updateEditables: function() {
210 this.select_.querySelector('[value=\'' + this.setting + '\']');
212 settingOption.selected = true;
217 get hasBeenEdited() {
218 var livePattern = this.input_.value;
219 var liveSetting = this.select_.value;
220 return livePattern != this.pattern || liveSetting != this.setting;
224 * Called when committing an edit.
225 * @param {!Event} e The end event.
228 onEditCommitted_: function(e) {
229 var newPattern = this.input_.value;
230 var newSetting = this.select_.value;
232 this.finishEdit(newPattern, newSetting);
236 * Called when cancelling an edit; resets the control states.
237 * @param {!Event} e The cancel event.
240 onEditCancelled_: function() {
241 this.updateEditables();
245 * Editing is complete; update the model.
246 * @param {string} newPattern The pattern that the user entered.
247 * @param {string} newSetting The setting the user chose.
249 finishEdit: function(newPattern, newSetting) {
250 this.patternLabel_.textContent = newPattern;
251 this.settingLabel_.textContent = this.settingForDisplay();
252 var oldPattern = this.pattern;
253 this.pattern = newPattern;
254 this.setting = newSetting;
256 this.list_.settings.update(oldPattern, newPattern, newSetting,
257 this.list_.settingsChangedCallback());
262 * Create a new list item to add a rule.
263 * @param {!RuleList} list The rule list containing this item.
265 * @extends {AddRuleListItem}
267 function AddRuleListItem(list) {
268 var el = cr.doc.createElement('div');
271 el.__proto__ = AddRuleListItem.prototype;
277 AddRuleListItem.prototype = {
278 __proto__: RuleListItem.prototype,
281 * Initializes the element.
283 decorate: function() {
284 RuleListItem.prototype.decorate.call(this);
286 this.setting = 'allow';
290 * Clear the <input> and let the placeholder text show again.
292 resetInput: function() {
293 this.input_.value = '';
297 get hasBeenEdited() {
298 return this.input_.value != '';
302 * Editing is complete; update the model. As long as the pattern isn't
303 * empty, we'll just add it.
304 * @param {string} newPattern The pattern that the user entered.
305 * @param {string} newSetting The setting the user chose.
307 finishEdit: function(newPattern, newSetting) {
309 this.list_.settings.set(newPattern, newSetting,
310 this.list_.settingsChangedCallback());
315 * A list of content setting rules.
317 * @extends {cr.ui.List}
319 var RuleList = cr.ui.define('list');
321 RuleList.prototype = {
322 __proto__: InlineEditableItemList.prototype,
325 * The content settings model for this list.
331 * Called when an element is decorated as a list.
333 decorate: function() {
334 InlineEditableItemList.prototype.decorate.call(this);
336 this.classList.add(CSSClass.RULE_LIST);
338 this.autoExpands = true;
343 * Creates an item to go in the list.
344 * @param {?Object} entry The element from the data model for this row.
346 createItem: function(entry) {
348 return new RuleListItem(this, entry);
350 var addRuleItem = new AddRuleListItem(this);
351 addRuleItem.deletable = false;
357 * Sets the rules in the js model.
358 * @param {!Array} entries A list of dictionaries of values, each dictionary
361 setRules_: function(entries) {
362 var deleteCount = this.dataModel.length - 1;
364 var args = [0, deleteCount];
365 args.push.apply(args, entries);
366 this.dataModel.splice.apply(this.dataModel, args);
370 * Called when the list of content setting rules has been changed.
371 * @param {?string} error The error message, if an error occurred.
372 * Otherwise, this is null.
375 settingsChanged_: function(error) {
377 $('error').textContent = 'Error: ' + error;
379 $('error').textContent = '';
381 this.setRules_(this.settings.getAll());
385 * @return {function()} A bound callback to update the UI after the
386 * settings have been changed.
388 settingsChangedCallback: function() {
389 return this.settingsChanged_.bind(this);
393 * Binds this list to the content settings model.
394 * @param {!Settings} settings The content settings model.
396 setPluginSettings: function(settings) {
397 this.settings = settings;
398 this.settingsChanged_();
402 * Removes all rules from the js model.
405 // The null creates the Add New Rule row.
406 this.dataModel = new ArrayDataModel([null]);
410 deleteItemAtIndex: function(index) {
411 var listItem = this.getListItemByIndex(index);
412 if (listItem.undeletable) {
416 this.settings.clear(listItem.pattern, this.settingsChangedCallback());
421 RuleListItem: RuleListItem,
422 AddRuleListItem: AddRuleListItem,