Files
edx-platform/lms/static/js/components/card/views/card.js
Peter Fogg 26bbbb967e Fix various team accessibility issues.
Authors:
  - Peter Fogg
  - Daniel Friedman

TNL-1953
2015-08-13 00:34:54 -04:00

114 lines
5.3 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'],
function ($, _, Backbone, cardTemplate) {
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: _.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() + '...'
}
this.$el.html(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);