Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / print_preview / search / destination_list.js
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.
4
5 cr.define('print_preview', function() {
6   'use strict';
7
8   /**
9    * Component that displays a list of destinations with a heading, action link,
10    * and "Show All..." button. An event is dispatched when the action link is
11    * activated.
12    * @param {!cr.EventTarget} eventTarget Event target to pass to destination
13    *     items for dispatching SELECT events.
14    * @param {string} title Title of the destination list.
15    * @param {string=} opt_actionLinkLabel Optional label of the action link. If
16    *     no label is provided, the action link will not be shown.
17    * @constructor
18    * @extends {print_preview.Component}
19    */
20   function DestinationList(eventTarget, title, opt_actionLinkLabel) {
21     print_preview.Component.call(this);
22
23     /**
24      * Event target to pass to destination items for dispatching SELECT events.
25      * @type {!cr.EventTarget}
26      * @private
27      */
28     this.eventTarget_ = eventTarget;
29
30     /**
31      * Title of the destination list.
32      * @type {string}
33      * @private
34      */
35     this.title_ = title;
36
37     /**
38      * Label of the action link.
39      * @type {?string}
40      * @private
41      */
42     this.actionLinkLabel_ = opt_actionLinkLabel || null;
43
44     /**
45      * Backing store for the destination list.
46      * @type {!Array.<print_preview.Destination>}
47      * @private
48      */
49     this.destinations_ = [];
50
51     /**
52      * Current query used for filtering.
53      * @type {RegExp}
54      * @private
55      */
56     this.query_ = null;
57
58     /**
59      * Whether the destination list is fully expanded.
60      * @type {boolean}
61      * @private
62      */
63     this.isShowAll_ = false;
64
65     /**
66      * Maximum number of destinations before showing the "Show All..." button.
67      * @type {number}
68      * @private
69      */
70     this.shortListSize_ = DestinationList.DEFAULT_SHORT_LIST_SIZE_;
71   };
72
73   /**
74    * Enumeration of event types dispatched by the destination list.
75    * @enum {string}
76    */
77   DestinationList.EventType = {
78     // Dispatched when the action linked is activated.
79     ACTION_LINK_ACTIVATED: 'print_preview.DestinationList.ACTION_LINK_ACTIVATED'
80   };
81
82   /**
83    * Default maximum number of destinations before showing the "Show All..."
84    * button.
85    * @type {number}
86    * @const
87    * @private
88    */
89   DestinationList.DEFAULT_SHORT_LIST_SIZE_ = 4;
90
91   /**
92    * Height of a destination list item in pixels.
93    * @type {number}
94    * @const
95    * @private
96    */
97   DestinationList.HEIGHT_OF_ITEM_ = 30;
98
99   DestinationList.prototype = {
100     __proto__: print_preview.Component.prototype,
101
102     /** @param {boolean} isShowAll Whether the show-all button is activated. */
103     setIsShowAll: function(isShowAll) {
104       this.isShowAll_ = isShowAll;
105       this.renderDestinations_();
106     },
107
108     /**
109      * @return {number} Size of list when destination list is in collapsed
110      *     mode (a.k.a non-show-all mode).
111      */
112     getShortListSize: function() {
113       return this.shortListSize_;
114     },
115
116     /** @return {number} Count of the destinations in the list. */
117     getDestinationsCount: function() {
118       return this.destinations_.length;
119     },
120
121     /**
122      * Gets estimated height of the destination list for the given number of
123      * items.
124      * @param {number} Number of items to render in the destination list.
125      * @return {number} Height (in pixels) of the destination list.
126      */
127     getEstimatedHeightInPixels: function(numItems) {
128       numItems = Math.min(numItems, this.destinations_.length);
129       var headerHeight =
130           this.getChildElement('.destination-list > header').offsetHeight;
131       return headerHeight + (numItems > 0 ?
132           numItems * DestinationList.HEIGHT_OF_ITEM_ :
133           // To account for "No destinations found" message.
134           DestinationList.HEIGHT_OF_ITEM_);
135     },
136
137     /** @param {boolean} isVisible Whether the throbber is visible. */
138     setIsThrobberVisible: function(isVisible) {
139       setIsVisible(this.getChildElement('.throbber-container'), isVisible);
140     },
141
142     /**
143      * @param {number} size Size of list when destination list is in collapsed
144      *     mode (a.k.a non-show-all mode).
145      */
146     updateShortListSize: function(size) {
147       size = Math.max(1, Math.min(size, this.destinations_.length));
148       if (size == 1 && this.destinations_.length > 1) {
149         // If this is the case, we will only show the "Show All" button and
150         // nothing else. Increment the short list size by one so that we can see
151         // at least one print destination.
152         size++;
153       }
154       this.setShortListSizeInternal(size);
155     },
156
157     /** @override */
158     createDom: function() {
159       this.setElementInternal(this.cloneTemplateInternal(
160           'destination-list-template'));
161       this.getChildElement('.title').textContent = this.title_;
162       if (this.actionLinkLabel_) {
163         var actionLinkEl = this.getChildElement('.action-link');
164         actionLinkEl.textContent = this.actionLinkLabel_;
165         setIsVisible(actionLinkEl, true);
166       }
167     },
168
169     /** @override */
170     enterDocument: function() {
171       print_preview.Component.prototype.enterDocument.call(this);
172       this.tracker.add(
173           this.getChildElement('.action-link'),
174           'click',
175           this.onActionLinkClick_.bind(this));
176       this.tracker.add(
177           this.getChildElement('.show-all-button'),
178           'click',
179           this.setIsShowAll.bind(this, true));
180     },
181
182     /**
183      * Updates the destinations to render in the destination list.
184      * @param {!Array.<print_preview.Destination>} destinations Destinations to
185      *     render.
186      */
187     updateDestinations: function(destinations) {
188       this.destinations_ = destinations;
189       this.renderDestinations_();
190     },
191
192     /** @param {?string} query Query to update the filter with. */
193     updateSearchQuery: function(query) {
194       if (!query) {
195         this.query_ = null;
196       } else {
197         // Generate regexp-safe query by escaping metacharacters.
198         var safeQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
199         this.query_ = new RegExp('(' + safeQuery + ')', 'ig');
200       }
201       this.renderDestinations_();
202     },
203
204     /**
205      * @param {string} text Text to set the action link to.
206      * @protected
207      */
208     setActionLinkTextInternal: function(text) {
209       this.actionLinkLabel_ = text;
210       this.getChildElement('.action-link').textContent = text;
211     },
212
213     /**
214      * Sets the short list size without constraints.
215      * @protected
216      */
217     setShortListSizeInternal: function(size) {
218       this.shortListSize_ = size;
219       this.renderDestinations_();
220     },
221
222     /**
223      * Renders all destinations in the given list.
224      * @param {!Array.<print_preview.Destination>} destinations List of
225      *     destinations to render.
226      * @protected
227      */
228     renderListInternal: function(destinations) {
229       setIsVisible(this.getChildElement('.no-destinations-message'),
230                    destinations.length == 0);
231       setIsVisible(this.getChildElement('.destination-list > footer'), false);
232       var numItems = destinations.length;
233       if (destinations.length > this.shortListSize_ && !this.isShowAll_) {
234         numItems = this.shortListSize_ - 1;
235         this.getChildElement('.total').textContent =
236             localStrings.getStringF('destinationCount', destinations.length);
237         setIsVisible(this.getChildElement('.destination-list > footer'), true);
238       }
239       for (var i = 0; i < numItems; i++) {
240         var destListItem = new print_preview.DestinationListItem(
241             this.eventTarget_, destinations[i], this.query_);
242         this.addChild(destListItem);
243         destListItem.render(this.getChildElement('.destination-list > ul'));
244       }
245     },
246
247     /**
248      * Renders all destinations in the list that match the current query. For
249      * each render, all old destination items are first removed.
250      * @private
251      */
252     renderDestinations_: function() {
253       this.removeChildren();
254
255       if (!this.query_) {
256         this.renderListInternal(this.destinations_);
257       } else {
258         var filteredDests = this.destinations_.filter(function(destination) {
259           return destination.matches(this.query_);
260         }, this);
261         this.renderListInternal(filteredDests);
262       }
263     },
264
265     /**
266      * Called when the action link is clicked. Dispatches an
267      * ACTION_LINK_ACTIVATED event.
268      * @private
269      */
270     onActionLinkClick_: function() {
271       cr.dispatchSimpleEvent(this,
272                              DestinationList.EventType.ACTION_LINK_ACTIVATED);
273     }
274   };
275
276   // Export
277   return {
278     DestinationList: DestinationList
279   };
280 });