Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / resources / print_preview / search / destination_list_item.js
blob48b5b8174f78e0a73664a44c4eb5a44e321edc1c
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.
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.Destination} destination Destination data object to
13    *     render.
14    * @param {RegExp} query Active filter query.
15    * @constructor
16    * @extends {print_preview.Component}
17    */
18   function DestinationListItem(eventTarget, destination, query) {
19     print_preview.Component.call(this);
21     /**
22      * Event target to dispatch selection events to.
23      * @type {!cr.EventTarget}
24      * @private
25      */
26     this.eventTarget_ = eventTarget;
28     /**
29      * Destination that the list item renders.
30      * @type {!print_preview.Destination}
31      * @private
32      */
33     this.destination_ = destination;
35     /**
36      * Active filter query text.
37      * @type {RegExp}
38      * @private
39      */
40     this.query_ = query;
42     /**
43      * FedEx terms-of-service widget or {@code null} if this list item does not
44      * render the FedEx Office print destination.
45      * @type {print_preview.FedexTos}
46      * @private
47      */
48     this.fedexTos_ = null;
49   };
51   /**
52    * Event types dispatched by the destination list item.
53    * @enum {string}
54    */
55   DestinationListItem.EventType = {
56     // Dispatched when the list item is activated.
57     SELECT: 'print_preview.DestinationListItem.SELECT',
58     REGISTER_PROMO_CLICKED:
59         'print_preview.DestinationListItem.REGISTER_PROMO_CLICKED'
60   };
62   DestinationListItem.prototype = {
63     __proto__: print_preview.Component.prototype,
65     /** @override */
66     createDom: function() {
67       this.setElementInternal(this.cloneTemplateInternal(
68           'destination-list-item-template'));
69       this.updateUi_();
70     },
72     /** @override */
73     enterDocument: function() {
74       print_preview.Component.prototype.enterDocument.call(this);
75       this.tracker.add(this.getElement(), 'click', this.onActivate_.bind(this));
76       this.tracker.add(
77           this.getElement(), 'keydown', this.onKeyDown_.bind(this));
78       this.tracker.add(
79           this.getChildElement('.register-promo-button'),
80           'click',
81           this.onRegisterPromoClicked_.bind(this));
82     },
84     /** @return {!print_preiew.Destination} */
85     get destination() {
86       return this.destination_;
87     },
89     /**
90      * Updates the list item UI state.
91      * @param {!print_preview.Destination} destination Destination data object
92      *     to render.
93      * @param {RegExp} query Active filter query.
94      */
95     update: function(destination, query) {
96       this.destination_ = destination;
97       this.query_ = query;
98       this.updateUi_();
99     },
101     /**
102      * Initializes the element with destination's info.
103      * @private
104      */
105     updateUi_: function() {
106       var iconImg = this.getChildElement('.destination-list-item-icon');
107       iconImg.src = this.destination_.iconUrl;
109       var nameEl = this.getChildElement('.destination-list-item-name');
110       var textContent = this.destination_.displayName;
111       if (this.query_) {
112         nameEl.textContent = '';
113         // When search query is specified, make it obvious why this particular
114         // printer made it to the list. Display name is always visible, even if
115         // it does not match the search query.
116         this.addTextWithHighlight_(nameEl, textContent);
117         // Show the first matching property.
118         this.destination_.extraPropertiesToMatch.some(function(property) {
119           if (property.match(this.query_)) {
120             var hintSpan = document.createElement('span');
121             hintSpan.className = 'search-hint';
122             nameEl.appendChild(hintSpan);
123             this.addTextWithHighlight_(hintSpan, property);
124             // Add the same property to the element title.
125             textContent += ' (' + property + ')';
126             return true;
127           }
128         }, this);
129       } else {
130         // Show just the display name and nothing else to lessen visual clutter.
131         nameEl.textContent = textContent;
132       }
133       nameEl.title = textContent;
135       if (this.destination_.isExtension) {
136         var extensionNameEl = this.getChildElement('.extension-name');
137         var extensionName = this.destination_.extensionName;
138         extensionNameEl.title = this.destination_.extensionName;
139         if (this.query_) {
140           extensionNameEl.textContent = '';
141           this.addTextWithHighlight_(extensionNameEl, extensionName);
142         } else {
143           extensionNameEl.textContent = this.destination_.extensionName;
144         }
146         var extensionIconEl = this.getChildElement('.extension-icon');
147         extensionIconEl.style.backgroundImage = '-webkit-image-set(' +
148              'url(chrome://extension-icon/' +
149                   this.destination_.extensionId + '/24/1) 1x,' +
150              'url(chrome://extension-icon/' +
151                   this.destination_.extensionId + '/48/1) 2x)';
152         extensionIconEl.title = loadTimeData.getStringF(
153             'extensionDestinationIconTooltip',
154             this.destination_.extensionName);
155         extensionIconEl.onclick = this.onExtensionIconClicked_.bind(this);
156         extensionIconEl.onkeydown = this.onExtensionIconKeyDown_.bind(this);
157       }
159       var extensionIndicatorEl =
160           this.getChildElement('.extension-controlled-indicator');
161       setIsVisible(extensionIndicatorEl, this.destination_.isExtension);
163       // Initialize the element which renders the destination's offline status.
164       this.getElement().classList.toggle('stale', this.destination_.isOffline);
165       var offlineStatusEl = this.getChildElement('.offline-status');
166       offlineStatusEl.textContent = this.destination_.offlineStatusText;
167       setIsVisible(offlineStatusEl, this.destination_.isOffline);
169       // Initialize registration promo element for Privet unregistered printers.
170       setIsVisible(
171           this.getChildElement('.register-promo'),
172           this.destination_.connectionStatus ==
173               print_preview.Destination.ConnectionStatus.UNREGISTERED);
174     },
176     /**
177      * Adds text to parent element wrapping search query matches in highlighted
178      * spans.
179      * @param {!Element} parent Element to build the text in.
180      * @param {string} text The text string to highlight segments in.
181      * @private
182      */
183     addTextWithHighlight_: function(parent, text) {
184       var sections = text.split(this.query_);
185       for (var i = 0; i < sections.length; ++i) {
186         if (i % 2 == 0) {
187           parent.appendChild(document.createTextNode(sections[i]));
188         } else {
189           var span = document.createElement('span');
190           span.className = 'destination-list-item-query-highlight';
191           span.textContent = sections[i];
192           parent.appendChild(span);
193         }
194       }
195     },
197     /**
198      * Called when the destination item is activated. Dispatches a SELECT event
199      * on the given event target.
200      * @private
201      */
202     onActivate_: function() {
203       if (this.destination_.id ==
204               print_preview.Destination.GooglePromotedId.FEDEX &&
205           !this.destination_.isTosAccepted) {
206         if (!this.fedexTos_) {
207           this.fedexTos_ = new print_preview.FedexTos();
208           this.fedexTos_.render(this.getElement());
209           this.tracker.add(
210               this.fedexTos_,
211               print_preview.FedexTos.EventType.AGREE,
212               this.onTosAgree_.bind(this));
213         }
214         this.fedexTos_.setIsVisible(true);
215       } else if (this.destination_.connectionStatus !=
216                      print_preview.Destination.ConnectionStatus.UNREGISTERED) {
217         var selectEvt = new Event(DestinationListItem.EventType.SELECT);
218         selectEvt.destination = this.destination_;
219         this.eventTarget_.dispatchEvent(selectEvt);
220       }
221     },
223     /**
224      * Called when the key is pressed on the destination item. Dispatches a
225      * SELECT event when Enter is pressed.
226      * @param {KeyboardEvent} e Keyboard event to process.
227      * @private
228      */
229     onKeyDown_: function(e) {
230       if (!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey) {
231         if (e.keyCode == 13) {
232           var activeElementTag = document.activeElement ?
233               document.activeElement.tagName.toUpperCase() : '';
234           if (activeElementTag == 'LI') {
235             e.stopPropagation();
236             e.preventDefault();
237             this.onActivate_();
238           }
239         }
240       }
241     },
243     /**
244      * Called when the user agrees to the print destination's terms-of-service.
245      * Selects the print destination that was agreed to.
246      * @private
247      */
248     onTosAgree_: function() {
249       var selectEvt = new Event(DestinationListItem.EventType.SELECT);
250       selectEvt.destination = this.destination_;
251       this.eventTarget_.dispatchEvent(selectEvt);
252     },
254     /**
255      * Called when the registration promo is clicked.
256      * @private
257      */
258     onRegisterPromoClicked_: function() {
259       var promoClickedEvent = new Event(
260           DestinationListItem.EventType.REGISTER_PROMO_CLICKED);
261       promoClickedEvent.destination = this.destination_;
262       this.eventTarget_.dispatchEvent(promoClickedEvent);
263     },
265     /**
266      * Handles click and 'Enter' key down events for the extension icon element.
267      * It opens extensions page with the extension associated with the
268      * destination highlighted.
269      * @param {MouseEvent|KeyboardEvent} e The event to handle.
270      * @private
271      */
272     onExtensionIconClicked_: function(e) {
273       e.stopPropagation();
274       window.open('chrome://extensions?id=' + this.destination_.extensionId);
275     },
277     /**
278      * Handles key down event for the extensin icon element. Keys different than
279      * 'Enter' are ignored.
280      * @param {KeyboardEvent} e The event to handle.
281      * @private
282      */
283     onExtensionIconKeyDown_: function(e) {
284       if (e.shiftKey || e.ctrlKey || e.altKey || e.metaKey)
285         return;
286       if (e.keyCode != 13 /* Enter */)
287         return;
288       this.onExtensionIconClicked_(event);
289     }
290   };
292   // Export
293   return {
294     DestinationListItem: DestinationListItem
295   };