Elim cr-checkbox
[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}
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     },
139     /**
140      * Called when the text element value is changed.
141      * @private
142      */
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_();
155       }
156     },
158     /**
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
163      */
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 || '';
169     },
171     /**
172      * Renders capability properties according to the current state.
173      * @private
174      */
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_);
189         }
190       }
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;
206       }
207       nameEl.title = textContent;
209       if (optionMatches)
210         this.showSearchBubble_(optionMatches[0]);
211     },
213     /**
214      * Shows search bubble for this element.
215      * @param {string} text Text to show in the search bubble.
216      * @private
217      */
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;
226       }
227     },
229     /**
230      * Hides search bubble associated with this element.
231      * @private
232      */
233     hideSearchBubble_: function() {
234       if (this.searchBubble_) {
235         this.searchBubble_.dispose();
236         this.searchBubble_ = null;
237       }
238     },
240     /**
241      * Initializes the element's value control.
242      * @private
243      */
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_();
252     },
254     /**
255      * Initializes the select element.
256      * @private
257      */
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;
275         }
276       }
277       selectEl.selectedIndex = indexToSelect;
278     },
280     /**
281      * Initializes the text element.
282      * @private
283      */
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;
295       }
297       this.text_.placeholder = defaultValue || '';
299       this.text_.value = this.selectedValue;
300     },
302     /**
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
308      */
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);
318         }
319       });
320     }
321   };
323   // Export
324   return {
325     AdvancedSettingsItem: AdvancedSettingsItem
326   };