"use strict";
define(["underscore", "backbone", "text!templates/maps/expansion-panel.html"], (
_,
Backbone,
Template,
) => {
// The base classname to use for this View's template elements.
const BASE_CLASS = "expansion-panel";
// The HTML classes to use for this view's HTML elements.
const CLASS_NAMES = {
title: `${BASE_CLASS}__title`,
content: `${BASE_CLASS}__content`,
toggle: `${BASE_CLASS}__toggle`,
icon: `${BASE_CLASS}__icon`,
iconToggle: `${BASE_CLASS}__icon-toggle`,
};
/**
* @class ExpansionPanelView
* @classdesc Allow expand and collapse content in a panel.
* @classcategory Views/Maps/Viewfinder
* @name ExpansionPanelView
* @augments Backbone.View
* @screenshot views/maps/ExpansionPanelView.png
* @since 2.29.0
* @constructs ExpansionPanelView
*/
const ExpansionPanelView = Backbone.View.extend(
/** @lends ExpansionPanelView.prototype */ {
/**
* The type of View this is
* @type {string}
*/
type: "ExpansionPanelView",
/** @inheritdoc */
className: BASE_CLASS,
/**
* The events this view will listen to and the associated function to call.
* @type {object}
*/
events() {
return {
[`click .${CLASS_NAMES.toggle}`]: "toggle",
};
},
/**
* @typedef {object} ExpansionPanelViewOptions
* @property {string} title The displayed label for this panel.
* @property {string} icon The icon displayed in the panel's clickable
* label.
* @property {Backbone.View} contentViewInstance The Backbone.View that
* will be displayed when the content of the panel is toggled to be
* visible.
* @property {ExpansionPanelsModel} [panelsModel] Optional model for
* coordinating the expanded/collapsed state among many panels.
* @property {boolean} startOpen Whether the panel should be expanded by
* default.
*/
/**
* Initialize the view with the given options.
* @param {ExpansionPanelViewOptions} options The options for this view.
*/
initialize({
title,
contentViewInstance,
icon,
panelsModel,
startOpen,
isSvgIcon,
}) {
this.templateVars = {
classNames: CLASS_NAMES,
icon,
isSvgIcon,
title,
};
this.contentViewInstance = contentViewInstance;
this.panelsModel = panelsModel;
this.startOpen = !!startOpen;
this.panelsModel?.register(this);
},
/**
* Getter function for the content div.
* @returns {HTMLDivElement} Returns the content element.
*/
getContent() {
return this.$el.find(`.${CLASS_NAMES.content}`);
},
/** Force the panel's content to be hidden. */
collapse() {
this.$el.removeClass("show-content");
},
/** Force the panel's content to be shown. */
open() {
this.$el.addClass("show-content");
this.panelsModel?.maybeCollapseOthers(this);
},
/** Toggle the visibility of the panel's content. */
toggle() {
if (this.$el.hasClass("show-content")) {
this.collapse();
} else {
this.open();
}
},
/**
* Render the view by updating the HTML of the element.
* The new HTML is computed from an HTML template that
* is passed an object with relevant view state.
* */
render() {
this.el.innerHTML = _.template(Template)(this.templateVars);
this.contentViewInstance.render();
this.getContent().append(this.contentViewInstance.el);
if (this.startOpen) {
this.open();
}
},
},
);
return ExpansionPanelView;
});