119 lines
5.5 KiB
JavaScript
119 lines
5.5 KiB
JavaScript
/**
|
|
* A generic card view class.
|
|
*
|
|
* Subclasses can override any of the following:
|
|
* - configuration (string or function): Sets the display style of the card as square or list. Can take values of
|
|
* "square_card" or "list_card". Defaults to "square_card".
|
|
* - action (function): Action to take when the action button is clicked. Defaults to a no-op.
|
|
* - cardClass (string or function): Class name for this card's DOM element. Defaults to the empty string.
|
|
* - pennant (string or function): Text of the card's pennant. No pennant is displayed if this value is falsy.
|
|
* - title (string or function): Title of the card. Defaults to the empty string.
|
|
* - description (string or function): Description of the card. Defaults to the empty string.
|
|
* - details (array or function): Array of child views to be rendered as details of this card. The class "meta-detail"
|
|
* is automatically added to each rendered child view to ensure appropriate styling. Defaults to an empty list.
|
|
* - actionClass (string or function): Class name for the action DOM element. Defaults to the empty string.
|
|
* - actionUrl (string or function): URL to navigate to when the action button is clicked. Defaults to the empty string.
|
|
* - actionContent: Content of the action button. This may include HTML. Default to the empty string.
|
|
*/
|
|
(function(define) {
|
|
'use strict';
|
|
define(['jquery',
|
|
'underscore',
|
|
'backbone',
|
|
'text!templates/components/card/card.underscore',
|
|
'edx-ui-toolkit/js/utils/html-utils'
|
|
],
|
|
function($, _, Backbone, cardTemplate, HtmlUtils) {
|
|
var CardView = Backbone.View.extend({
|
|
tagName: 'li',
|
|
|
|
events: {
|
|
'click .action': 'action'
|
|
},
|
|
|
|
/**
|
|
* constructor is needed in addition to initialize because of Backbone's initialization order.
|
|
* initialize seems to run last in the initialization process, after className. However, className
|
|
* depends on this.configuration being set to pick the appropriate class. Therefore, configuration
|
|
* is set in the constructor, but the rest of the initialization happens in initialize.
|
|
*/
|
|
constructor: function(options) {
|
|
if (!this.configuration) {
|
|
this.configuration = (options && options.configuration) ? options.configuration : 'square_card';
|
|
}
|
|
Backbone.View.prototype.constructor.apply(this, arguments);
|
|
},
|
|
|
|
initialize: function() {
|
|
this.render();
|
|
},
|
|
|
|
template: HtmlUtils.template(cardTemplate),
|
|
|
|
switchOnConfiguration: function(square_result, list_result) {
|
|
return this.callIfFunction(this.configuration) === 'square_card' ?
|
|
square_result : list_result;
|
|
},
|
|
|
|
callIfFunction: function(value) {
|
|
if ($.isFunction(value)) {
|
|
return value.call(this);
|
|
} else {
|
|
return value;
|
|
}
|
|
},
|
|
|
|
className: function() {
|
|
var result = 'card ' +
|
|
this.switchOnConfiguration('square-card', 'list-card') + ' ' +
|
|
this.callIfFunction(this.cardClass);
|
|
if (this.callIfFunction(this.pennant)) {
|
|
result += ' has-pennant';
|
|
}
|
|
return result;
|
|
},
|
|
|
|
render: function() {
|
|
var maxLength = 72,
|
|
description = this.callIfFunction(this.description);
|
|
if (description.length > maxLength) {
|
|
description = description.substring(0, maxLength).trim() + '...';
|
|
}
|
|
HtmlUtils.setHtml(
|
|
this.$el,
|
|
this.template({
|
|
pennant: this.callIfFunction(this.pennant),
|
|
title: this.callIfFunction(this.title),
|
|
description: description,
|
|
action_class: this.callIfFunction(this.actionClass),
|
|
action_url: this.callIfFunction(this.actionUrl),
|
|
action_content: this.callIfFunction(this.actionContent),
|
|
configuration: this.callIfFunction(this.configuration),
|
|
srInfo: this.srInfo
|
|
})
|
|
);
|
|
var detailsEl = this.$el.find('.card-meta');
|
|
_.each(this.callIfFunction(this.details), function(detail) {
|
|
// Call setElement to rebind event handlers
|
|
detail.setElement(detail.el).render();
|
|
detail.$el.addClass('meta-detail');
|
|
detailsEl.append(detail.el);
|
|
});
|
|
return this;
|
|
},
|
|
|
|
action: function() { },
|
|
cardClass: '',
|
|
pennant: '',
|
|
title: '',
|
|
description: '',
|
|
details: [],
|
|
actionClass: '',
|
|
actionUrl: '',
|
|
actionContent: ''
|
|
});
|
|
|
|
return CardView;
|
|
});
|
|
}).call(this, define || RequireJS.define);
|