Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / settings / advanced_settings / advanced_settings_item.js
blobb8ae300e5e64bb44beccecf0996e5d8bf3e23b52
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}
17    */
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}
24      */
25     this.eventTarget_ = eventTarget;
27     /**
28      * Contains the print ticket to print.
29      * @private {!print_preview.PrintTicketStore}
30      */
31     this.printTicketStore_ = printTicketStore;
33     /**
34      * Capability this component renders.
35      * @private {!Object}
36      */
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}
44      */
45     this.selectedValue_ = null;
47     /**
48      * Active filter query.
49      * @private {RegExp}
50      */
51     this.query_ = null;
53     /**
54      * Search hint for the control.
55      * @private {print_preview.SearchBubble}
56      */
57     this.searchBubble_ = null;
59     /** @private {!EventTracker} */
60     this.tracker_ = new EventTracker();
61   };
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_();
78     },
80     /**
81      * ID of the corresponding vendor capability.
82      * @return {string}
83      */
84     get id() {
85       return this.capability_.id;
86     },
88     /**
89      * Currently selected value.
90      * @return {string}
91      */
92     get selectedValue() {
93       return this.selectedValue_ || '';
94     },
96     /**
97      * Whether the corresponding ticket item was changed or not.
98      * @return {boolean}
99      */
100     isModified: function() {
101       return !!this.selectedValue_;
102     },
104     /** @param {RegExp} query Query to update the filter with. */
105     updateSearchQuery: function(query) {
106       this.query_ = query;
107       this.renderCapability_();
108     },
110     get searchBubbleShown() {
111       return getIsVisible(this.getElement()) && !!this.searchBubble_;
112     },
114     /**
115      * @return {HTMLSelectElement} Select element.
116      * @private
117      */
118     get select_() {
119       return this.getChildElement(
120           '.advanced-settings-item-value-select-control');
121     },
123     /**
124      * @return {HTMLSelectElement} Text element.
125      * @private
126      */
127     get text_() {
128       return this.getChildElement('.advanced-settings-item-value-text-control');
129     },
131     /**
132      * Called when the select element value is changed.
133      * @private
134      */
135     onSelectChange_: function() {
136       this.selectedValue_ = this.select_.value;
137       this.capability_.select_cap.option.some(function(option) {
138         if (this.select_.value == option.value && option.is_default)
139           this.selectedValue_ = null;
140         return this.select_.value == option.value || option.is_default;
141       }.bind(this));
142     },
144     /**
145      * Called when the text element value is changed.
146      * @private
147      */
148     onTextInput_: function() {
149       this.selectedValue_ = this.text_.value || null;
151       if (this.query_) {
152         var optionMatches = (this.selectedValue_ || '').match(this.query_);
153         // Even if there's no match anymore, keep the item visible to do not
154         // surprise user. Even if there's a match, do not show the bubble, user
155         // is already aware that this option is visible and matches the search.
156         // Showing the bubble will only create a distraction by moving UI
157         // elements around.
158         if (!optionMatches)
159           this.hideSearchBubble_();
160       }
161     },
163     /**
164      * @param {!Object} entity Entity to get the display name for. Entity in
165      *     is either a vendor capability or vendor capability option.
166      * @return {string} The entity display name.
167      * @private
168      */
169     getEntityDisplayName_: function(entity) {
170       var displayName = entity.display_name;
171       if (!displayName && entity.display_name_localized)
172         displayName = getStringForCurrentLocale(entity.display_name_localized);
173       return displayName || '';
174     },
176     /**
177      * Renders capability properties according to the current state.
178      * @private
179      */
180     renderCapability_: function() {
181       var textContent = this.getEntityDisplayName_(this.capability_);
182       // Whether capability name matches the query.
183       var nameMatches = this.query_ ? !!textContent.match(this.query_) : true;
184       // An array of text segments of the capability value matching the query.
185       var optionMatches = null;
186       if (this.query_) {
187         if (this.capability_.type == 'SELECT') {
188           // Look for the first option that matches the query.
189           for (var i = 0; i < this.select_.length && !optionMatches; i++)
190             optionMatches = this.select_.options[i].text.match(this.query_);
191         } else {
192           optionMatches = (this.text_.value || '').match(this.query_);
193         }
194       }
195       var matches = nameMatches || !!optionMatches;
197       if (!optionMatches)
198         this.hideSearchBubble_();
200       setIsVisible(this.getElement(), matches);
201       if (!matches)
202         return;
204       var nameEl = this.getChildElement('.advanced-settings-item-label');
205       if (this.query_) {
206         nameEl.textContent = '';
207         this.addTextWithHighlight_(nameEl, textContent);
208       } else {
209         nameEl.textContent = textContent;
210       }
211       nameEl.title = textContent;
213       if (optionMatches)
214         this.showSearchBubble_(optionMatches[0]);
215     },
217     /**
218      * Shows search bubble for this element.
219      * @param {string} text Text to show in the search bubble.
220      * @private
221      */
222     showSearchBubble_: function(text) {
223       var element =
224           this.capability_.type == 'SELECT' ? this.select_ : this.text_;
225       if (!this.searchBubble_) {
226         this.searchBubble_ = new print_preview.SearchBubble(text);
227         this.searchBubble_.attachTo(element);
228       } else {
229         this.searchBubble_.content = text;
230       }
231     },
233     /**
234      * Hides search bubble associated with this element.
235      * @private
236      */
237     hideSearchBubble_: function() {
238       if (this.searchBubble_) {
239         this.searchBubble_.dispose();
240         this.searchBubble_ = null;
241       }
242     },
244     /**
245      * Initializes the element's value control.
246      * @private
247      */
248     initializeValue_: function() {
249       this.selectedValue_ =
250           this.printTicketStore_.vendorItems.ticketItems[this.id] || null;
252       if (this.capability_.type == 'SELECT')
253         this.initializeSelectValue_();
254       else
255         this.initializeTextValue_();
256     },
258     /**
259      * Initializes the select element.
260      * @private
261      */
262     initializeSelectValue_: function() {
263       setIsVisible(
264           this.getChildElement('.advanced-settings-item-value-select'), true);
265       var selectEl = this.select_;
266       var indexToSelect = 0;
267       this.capability_.select_cap.option.forEach(function(option, index) {
268         var item = document.createElement('option');
269         item.text = this.getEntityDisplayName_(option);
270         item.value = option.value;
271         if (option.is_default)
272           indexToSelect = index;
273         selectEl.appendChild(item);
274       }, this);
275       for (var i = 0, option; option = selectEl.options[i]; i++) {
276         if (option.value == this.selectedValue_) {
277           indexToSelect = i;
278           break;
279         }
280       }
281       selectEl.selectedIndex = indexToSelect;
282     },
284     /**
285      * Initializes the text element.
286      * @private
287      */
288     initializeTextValue_: function() {
289       setIsVisible(
290           this.getChildElement('.advanced-settings-item-value-text'), true);
291       this.text_.value = this.selectedValue;
292     },
294     /**
295      * Adds text to parent element wrapping search query matches in highlighted
296      * spans.
297      * @param {!Element} parent Element to build the text in.
298      * @param {string} text The text string to highlight segments in.
299      * @private
300      */
301     addTextWithHighlight_: function(parent, text) {
302       text.split(this.query_).forEach(function(section, i) {
303         if (i % 2 == 0) {
304           parent.appendChild(document.createTextNode(section));
305         } else {
306           var span = document.createElement('span');
307           span.className = 'advanced-settings-item-query-highlight';
308           span.textContent = section;
309           parent.appendChild(span);
310         }
311       });
312     }
313   };
315   // Export
316   return {
317     AdvancedSettingsItem: AdvancedSettingsItem
318   };