'use strict';
define(
[
'jquery',
'underscore',
'backbone',
'text!templates/maps/layer-category-item.html',
'models/maps/AssetCategory',
'common/IconUtilities',
// Sub-views
'views/maps/LayerListView',
],
function (
$,
_,
Backbone,
Template,
AssetCategory,
IconUtilities,
// Sub-views
LayerListView,
) {
const BASE_CLASS = 'layer-category-item';
const CLASS_NAMES = {
metadata: `${BASE_CLASS}__metadata`,
icon: `${BASE_CLASS}__icon`,
expanded: `${BASE_CLASS}__expanded`,
collapsed: `${BASE_CLASS}__collapsed`,
layers: `${BASE_CLASS}__layers`,
};
/**
* @class LayerCategoryItemView
* @classdesc One item in a Category List: shows some basic information about the
* layer category, including label and icon. Also has a button that expands the
* nested layers list.
* @classcategory Views/Maps
* @name LayerCategoryItemView
* @extends Backbone.View
* @screenshot views/maps/LayerCategoryItemView.png
* @since 2.28.0
* @constructs
*/
const LayerCategoryItemView = Backbone.View.extend(
/** @lends LayerCategoryItemView.prototype */{
/**
* The type of View this is
* @type {string}
*/
type: 'LayerCategoryItemView',
/**
* The HTML classes to use for this view's element
* @type {string}
*/
className: BASE_CLASS,
/**
* The model that this view uses
* @type {AssetCategory}
*/
model: undefined,
/**
* The primary HTML template for this view
* @type {Underscore.template}
*/
template: _.template(Template),
/** @inheritdoc */
events() {
return {[`click .${CLASS_NAMES.metadata}`]: 'toggleExpanded'};
},
/**
* Executed when a new LayerCategoryItemView is created
* @param {Object} options - A literal object with options to pass to the view
*/
initialize(options) {
if (options?.model instanceof AssetCategory) {
this.model = options.model;
}
},
/**
* Renders this view
* @return {LayerCategoryItemView} Returns the rendered view element
*/
render() {
if (!this.model) {
return;
}
// Insert the template into the view
this.$el.html(this.template({
classNames: CLASS_NAMES,
label: this.model.get('label'),
}));
// Insert the icon on the left
this.insertIcon();
this.layerListView = new LayerListView({
collection: this.model.get('mapAssets'),
isCategorized: true,
});
this.layerListView.render();
this.$(`.${CLASS_NAMES.layers}`).append(this.layerListView.el);
// Show the category as expanded or collapsed depending on the model
// properties.
this.updateLayerList();
this.listenTo(this.model, 'change:expanded', this.updateLayerList);
return this;
},
/**
* Inserts the icon before the label.
*/
insertIcon() {
const icon = this.model.get('icon');
if (icon && typeof icon === 'string' && IconUtilities.isSVG(icon)) {
this.$(`.${CLASS_NAMES.icon}`).html(icon);
}
},
/**
* Sets the model's 'expanded' status attribute to true if it's false, and
* to false if it's true. Executed when a user clicks on this CategoryItem in a
* CategoryListView.
*/
toggleExpanded() {
this.model.set('expanded', !this.model.get('expanded'));
},
/**
* Show or hide the layer list based on the category's expand status.
*/
updateLayerList() {
const expanded = this.$(`.${CLASS_NAMES.expanded}`);
const collapsed = this.$(`.${CLASS_NAMES.collapsed}`);
const layers = this.$(`.${CLASS_NAMES.layers}`);
if (this.model.get('expanded')) {
expanded.show();
collapsed.hide();
layers.addClass('open');
} else {
expanded.hide();
collapsed.show();
layers.removeClass('open');
}
},
/**
* Searches and only displays self if layers match the text.
* @param {string} [text] - The search text from user input.
* @returns {boolean} - True if a layer item matches the text
*/
search(text) {
const matched = this.layerListView.search(text);
if (matched) {
this.$el.show();
this.model.set('expanded', text !== '');
} else {
this.$el.hide();
this.model.set('expanded', false);
}
return matched;
},
}
);
return LayerCategoryItemView;
}
);