blob: b96f8076f0903bf45c32510a385a217092fbb9b4 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
cr.define('print_preview', function() {
'use strict';
/**
* Component that displays a list of destinations with a heading, action link,
* and "Show All..." button. An event is dispatched when the action link is
* activated.
* @param {!cr.EventTarget} eventTarget Event target to pass to destination
* items for dispatching SELECT events.
* @param {string} title Title of the destination list.
* @param {string=} opt_actionLinkLabel Optional label of the action link. If
* no label is provided, the action link will not be shown.
* @constructor
* @extends {print_preview.Component}
*/
function DestinationList(eventTarget, title, opt_actionLinkLabel) {
print_preview.Component.call(this);
/**
* Event target to pass to destination items for dispatching SELECT events.
* @type {!cr.EventTarget}
* @private
*/
this.eventTarget_ = eventTarget;
/**
* Title of the destination list.
* @type {string}
* @private
*/
this.title_ = title;
/**
* Label of the action link.
* @type {?string}
* @private
*/
this.actionLinkLabel_ = opt_actionLinkLabel || null;
/**
* Backing store for the destination list.
* @type {!Array.<print_preview.Destination>}
* @private
*/
this.destinations_ = [];
/**
* Current query used for filtering.
* @type {RegExp}
* @private
*/
this.query_ = null;
/**
* Whether the destination list is fully expanded.
* @type {boolean}
* @private
*/
this.isShowAll_ = false;
/**
* Maximum number of destinations before showing the "Show All..." button.
* @type {number}
* @private
*/
this.shortListSize_ = DestinationList.DEFAULT_SHORT_LIST_SIZE_;
};
/**
* Enumeration of event types dispatched by the destination list.
* @enum {string}
*/
DestinationList.EventType = {
// Dispatched when the action linked is activated.
ACTION_LINK_ACTIVATED: 'print_preview.DestinationList.ACTION_LINK_ACTIVATED'
};
/**
* Default maximum number of destinations before showing the "Show All..."
* button.
* @type {number}
* @const
* @private
*/
DestinationList.DEFAULT_SHORT_LIST_SIZE_ = 4;
/**
* Height of a destination list item in pixels.
* @type {number}
* @const
* @private
*/
DestinationList.HEIGHT_OF_ITEM_ = 30;
DestinationList.prototype = {
__proto__: print_preview.Component.prototype,
/** @param {boolean} isShowAll Whether the show-all button is activated. */
setIsShowAll: function(isShowAll) {
this.isShowAll_ = isShowAll;
this.renderDestinations_();
},
/**
* @return {number} Size of list when destination list is in collapsed
* mode (a.k.a non-show-all mode).
*/
getShortListSize: function() {
return this.shortListSize_;
},
/** @return {number} Count of the destinations in the list. */
getDestinationsCount: function() {
return this.destinations_.length;
},
/**
* Gets estimated height of the destination list for the given number of
* items.
* @param {number} Number of items to render in the destination list.
* @return {number} Height (in pixels) of the destination list.
*/
getEstimatedHeightInPixels: function(numItems) {
numItems = Math.min(numItems, this.destinations_.length);
var headerHeight =
this.getChildElement('.destination-list > header').offsetHeight;
return headerHeight + (numItems > 0 ?
numItems * DestinationList.HEIGHT_OF_ITEM_ :
// To account for "No destinations found" message.
DestinationList.HEIGHT_OF_ITEM_);
},
/** @param {boolean} isVisible Whether the throbber is visible. */
setIsThrobberVisible: function(isVisible) {
setIsVisible(this.getChildElement('.throbber-container'), isVisible);
},
/**
* @param {number} size Size of list when destination list is in collapsed
* mode (a.k.a non-show-all mode).
*/
updateShortListSize: function(size) {
size = Math.max(1, Math.min(size, this.destinations_.length));
if (size == 1 && this.destinations_.length > 1) {
// If this is the case, we will only show the "Show All" button and
// nothing else. Increment the short list size by one so that we can see
// at least one print destination.
size++;
}
this.setShortListSizeInternal(size);
},
/** @override */
createDom: function() {
this.setElementInternal(this.cloneTemplateInternal(
'destination-list-template'));
this.getChildElement('.title').textContent = this.title_;
if (this.actionLinkLabel_) {
var actionLinkEl = this.getChildElement('.action-link');
actionLinkEl.textContent = this.actionLinkLabel_;
setIsVisible(actionLinkEl, true);
}
},
/** @override */
enterDocument: function() {
print_preview.Component.prototype.enterDocument.call(this);
this.tracker.add(
this.getChildElement('.action-link'),
'click',
this.onActionLinkClick_.bind(this));
this.tracker.add(
this.getChildElement('.show-all-button'),
'click',
this.setIsShowAll.bind(this, true));
},
/**
* Updates the destinations to render in the destination list.
* @param {!Array.<print_preview.Destination>} destinations Destinations to
* render.
*/
updateDestinations: function(destinations) {
this.destinations_ = destinations;
this.renderDestinations_();
},
/** @param {?string} query Query to update the filter with. */
updateSearchQuery: function(query) {
if (!query) {
this.query_ = null;
} else {
// Generate regexp-safe query by escaping metacharacters.
var safeQuery = query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
this.query_ = new RegExp('(' + safeQuery + ')', 'ig');
}
this.renderDestinations_();
},
/**
* @param {string} text Text to set the action link to.
* @protected
*/
setActionLinkTextInternal: function(text) {
this.actionLinkLabel_ = text;
this.getChildElement('.action-link').textContent = text;
},
/**
* Sets the short list size without constraints.
* @protected
*/
setShortListSizeInternal: function(size) {
this.shortListSize_ = size;
this.renderDestinations_();
},
/**
* Renders all destinations in the given list.
* @param {!Array.<print_preview.Destination>} destinations List of
* destinations to render.
* @protected
*/
renderListInternal: function(destinations) {
setIsVisible(this.getChildElement('.no-destinations-message'),
destinations.length == 0);
setIsVisible(this.getChildElement('.destination-list > footer'), false);
var numItems = destinations.length;
if (destinations.length > this.shortListSize_ && !this.isShowAll_) {
numItems = this.shortListSize_ - 1;
this.getChildElement('.total').textContent =
localStrings.getStringF('destinationCount', destinations.length);
setIsVisible(this.getChildElement('.destination-list > footer'), true);
}
for (var i = 0; i < numItems; i++) {
var destListItem = new print_preview.DestinationListItem(
this.eventTarget_, destinations[i], this.query_);
this.addChild(destListItem);
destListItem.render(this.getChildElement('.destination-list > ul'));
}
},
/**
* Renders all destinations in the list that match the current query. For
* each render, all old destination items are first removed.
* @private
*/
renderDestinations_: function() {
this.removeChildren();
if (!this.query_) {
this.renderListInternal(this.destinations_);
} else {
var filteredDests = this.destinations_.filter(function(destination) {
return destination.matches(this.query_);
}, this);
this.renderListInternal(filteredDests);
}
},
/**
* Called when the action link is clicked. Dispatches an
* ACTION_LINK_ACTIVATED event.
* @private
*/
onActionLinkClick_: function() {
cr.dispatchSimpleEvent(this,
DestinationList.EventType.ACTION_LINK_ACTIVATED);
}
};
// Export
return {
DestinationList: DestinationList
};
});