Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / settings / advanced_settings / advanced_settings_item.js
blob7e189922a228ab04151cda1be26bac09ed8d417b
1 // Copyright 2014 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.
5 cr.define('print_preview', function() {
6 'use strict';
8 /**
9 * Component that renders a destination item in a destination list.
10 * @param {!cr.EventTarget} eventTarget Event target to dispatch selection
11 * events to.
12 * @param {!print_preview.PrintTicketStore} printTicketStore Contains the
13 * print ticket to print.
14 * @param {!Object} capability Capability to render.
15 * @constructor
16 * @extends {print_preview.Component}
18 function AdvancedSettingsItem(eventTarget, printTicketStore, capability) {
19 print_preview.Component.call(this);
21 /**
22 * Event target to dispatch selection events to.
23 * @private {!cr.EventTarget}
25 this.eventTarget_ = eventTarget;
27 /**
28 * Contains the print ticket to print.
29 * @private {!print_preview.PrintTicketStore}
31 this.printTicketStore_ = printTicketStore;
33 /**
34 * Capability this component renders.
35 * @private {!Object}
37 this.capability_ = capability;
39 /**
40 * Value selected by user. {@code null}, if user has not changed the default
41 * value yet (still, the value can be the default one, if it is what user
42 * selected).
43 * @private {?string}
45 this.selectedValue_ = null;
47 /**
48 * Active filter query.
49 * @private {RegExp}
51 this.query_ = null;
53 /**
54 * Search hint for the control.
55 * @private {print_preview.SearchBubble}
57 this.searchBubble_ = null;
59 /** @private {!EventTracker} */
60 this.tracker_ = new EventTracker();
63 AdvancedSettingsItem.prototype = {
64 __proto__: print_preview.Component.prototype,
66 /** @override */
67 createDom: function() {
68 this.setElementInternal(this.cloneTemplateInternal(
69 'advanced-settings-item-template'));
71 this.tracker_.add(
72 this.select_, 'change', this.onSelectChange_.bind(this));
73 this.tracker_.add(this.text_, 'input', this.onTextInput_.bind(this));
75 this.initializeValue_();
77 this.renderCapability_();
80 /**
81 * ID of the corresponding vendor capability.
82 * @return {string}
84 get id() {
85 return this.capability_.id;
88 /**
89 * Currently selected value.
90 * @return {string}
92 get selectedValue() {
93 return this.selectedValue_ || '';
96 /**
97 * Whether the corresponding ticket item was changed or not.
98 * @return {boolean}
100 isModified: function() {
101 return !!this.selectedValue_;
104 /** @param {RegExp} query Query to update the filter with. */
105 updateSearchQuery: function(query) {
106 this.query_ = query;
107 this.renderCapability_();
110 get searchBubbleShown() {
111 return getIsVisible(this.getElement()) && !!this.searchBubble_;
115 * @return {HTMLSelectElement} Select element.
116 * @private
118 get select_() {
119 return this.getChildElement(
120 '.advanced-settings-item-value-select-control');
124 * @return {HTMLSelectElement} Text element.
125 * @private
127 get text_() {
128 return this.getChildElement('.advanced-settings-item-value-text-control');
132 * Called when the select element value is changed.
133 * @private
135 onSelectChange_: function() {
136 this.selectedValue_ = this.select_.value;
140 * Called when the text element value is changed.
141 * @private
143 onTextInput_: function() {
144 this.selectedValue_ = this.text_.value || null;
146 if (this.query_) {
147 var optionMatches = (this.selectedValue_ || '').match(this.query_);
148 // Even if there's no match anymore, keep the item visible to do not
149 // surprise user. Even if there's a match, do not show the bubble, user
150 // is already aware that this option is visible and matches the search.
151 // Showing the bubble will only create a distraction by moving UI
152 // elements around.
153 if (!optionMatches)
154 this.hideSearchBubble_();
159 * @param {!Object} entity Entity to get the display name for. Entity in
160 * is either a vendor capability or vendor capability option.
161 * @return {string} The entity display name.
162 * @private
164 getEntityDisplayName_: function(entity) {
165 var displayName = entity.display_name;
166 if (!displayName && entity.display_name_localized)
167 displayName = getStringForCurrentLocale(entity.display_name_localized);
168 return displayName || '';
172 * Renders capability properties according to the current state.
173 * @private
175 renderCapability_: function() {
176 var textContent = this.getEntityDisplayName_(this.capability_);
177 // Whether capability name matches the query.
178 var nameMatches = this.query_ ? !!textContent.match(this.query_) : true;
179 // An array of text segments of the capability value matching the query.
180 var optionMatches = null;
181 if (this.query_) {
182 if (this.capability_.type == 'SELECT') {
183 // Look for the first option that matches the query.
184 for (var i = 0; i < this.select_.length && !optionMatches; i++)
185 optionMatches = this.select_.options[i].text.match(this.query_);
186 } else {
187 optionMatches = (this.text_.value || this.text_.placeholder || '')
188 .match(this.query_);
191 var matches = nameMatches || !!optionMatches;
193 if (!optionMatches)
194 this.hideSearchBubble_();
196 setIsVisible(this.getElement(), matches);
197 if (!matches)
198 return;
200 var nameEl = this.getChildElement('.advanced-settings-item-label');
201 if (this.query_) {
202 nameEl.textContent = '';
203 this.addTextWithHighlight_(nameEl, textContent);
204 } else {
205 nameEl.textContent = textContent;
207 nameEl.title = textContent;
209 if (optionMatches)
210 this.showSearchBubble_(optionMatches[0]);
214 * Shows search bubble for this element.
215 * @param {string} text Text to show in the search bubble.
216 * @private
218 showSearchBubble_: function(text) {
219 var element =
220 this.capability_.type == 'SELECT' ? this.select_ : this.text_;
221 if (!this.searchBubble_) {
222 this.searchBubble_ = new print_preview.SearchBubble(text);
223 this.searchBubble_.attachTo(element);
224 } else {
225 this.searchBubble_.content = text;
230 * Hides search bubble associated with this element.
231 * @private
233 hideSearchBubble_: function() {
234 if (this.searchBubble_) {
235 this.searchBubble_.dispose();
236 this.searchBubble_ = null;
241 * Initializes the element's value control.
242 * @private
244 initializeValue_: function() {
245 this.selectedValue_ =
246 this.printTicketStore_.vendorItems.ticketItems[this.id] || null;
248 if (this.capability_.type == 'SELECT')
249 this.initializeSelectValue_();
250 else
251 this.initializeTextValue_();
255 * Initializes the select element.
256 * @private
258 initializeSelectValue_: function() {
259 setIsVisible(
260 this.getChildElement('.advanced-settings-item-value-select'), true);
261 var selectEl = this.select_;
262 var indexToSelect = 0;
263 this.capability_.select_cap.option.forEach(function(option, index) {
264 var item = document.createElement('option');
265 item.text = this.getEntityDisplayName_(option);
266 item.value = option.value;
267 if (option.is_default)
268 indexToSelect = index;
269 selectEl.appendChild(item);
270 }, this);
271 for (var i = 0, option; option = selectEl.options[i]; i++) {
272 if (option.value == this.selectedValue_) {
273 indexToSelect = i;
274 break;
277 selectEl.selectedIndex = indexToSelect;
281 * Initializes the text element.
282 * @private
284 initializeTextValue_: function() {
285 setIsVisible(
286 this.getChildElement('.advanced-settings-item-value-text'), true);
288 var defaultValue = null;
289 if (this.capability_.type == 'TYPED_VALUE' &&
290 this.capability_.typed_value_cap) {
291 defaultValue = this.capability_.typed_value_cap.default || null;
292 } else if (this.capability_.type == 'RANGE' &&
293 this.capability_.range_cap) {
294 defaultValue = this.capability_.range_cap.default || null;
297 this.text_.placeholder = defaultValue || '';
299 this.text_.value = this.selectedValue;
303 * Adds text to parent element wrapping search query matches in highlighted
304 * spans.
305 * @param {!Element} parent Element to build the text in.
306 * @param {string} text The text string to highlight segments in.
307 * @private
309 addTextWithHighlight_: function(parent, text) {
310 text.split(this.query_).forEach(function(section, i) {
311 if (i % 2 == 0) {
312 parent.appendChild(document.createTextNode(section));
313 } else {
314 var span = document.createElement('span');
315 span.className = 'advanced-settings-item-query-highlight';
316 span.textContent = section;
317 parent.appendChild(span);
323 // Export
324 return {
325 AdvancedSettingsItem: AdvancedSettingsItem