Source: src/js/views/maps/LayerDetailView.js

'use strict';

define(
  [
    'jquery',
    'underscore',
    'backbone',
    'models/maps/assets/MapAsset',
    'text!templates/maps/layer-detail.html',
  ],
  function (
    $,
    _,
    Backbone,
    MapAsset,
    Template
  ) {

    /**
    * @class LayerDetailView
    * @classdesc A LayerDetailView creates a section to be inserted into a
    * LayerDetailsView. It renders a label and a toggle to collapse and expand the
    * section's contents. The contents of the Detail section can be rendered by any other
    * view, but the view should be one that shows details about a MapAsset or allows
    * editing elements of the MapAsset.
    * @classcategory Views/Maps
    * @name LayerDetailView
    * @extends Backbone.View
    * @screenshot views/maps/LayerDetailView.png
    * @since 2.18.0
    * @constructs
    */
    var LayerDetailView = Backbone.View.extend(
      /** @lends LayerDetailView.prototype */{

        /**
        * The type of View this is
        * @type {string}
        */
        type: 'LayerDetailView',

        /**
        * The HTML classes to use for this view's element
        * @type {string}
        */
        className: 'layer-detail',

        /**
        * The model that this view uses
        * @type {MapAsset}
        */
        model: undefined,

        /**
         * The primary HTML template for this view
         * @type {Underscore.template}
         */
        template: _.template(Template),

        /**
         * CSS classes for HTML elements within this view.
         * @property {string} toggle The element in the template that acts as a toggle to
         * expand or collapse this Layer Detail section.
         * @property {string} open The class to add to the view when the contents are
         * visible (i.e. the section is expanded)
         * @property {string} noHeader The class to add to the view when there is no
         * title/label and the view is not collapsible.
         * @property {string} label The element that holds the view's label text
         * @property {string} contentContainer The container into which the contentView's
         * rendered content will be placed
         */
        classes: {
          open: 'layer-detail--open',
          noHeader: 'layer-detail--no-header',
          label: 'layer-detail__label',
          toggle: 'layer-detail__toggle',
          contentContainer: 'layer-detail__content'
        },

        /**
         * Indicates whether this section is collapsed or expanded
         * @type {Boolean}
         */
        isOpen: true,

        /**
         * The name to display for the Layer Detail section
         * @type {string}
         */
        label: null,

        /**
         * The sub-view that will show details about, or allow editing of, the given Layer
         * model. The contentView will be passed the Layer model.
         * @type {Backbone.View}
         */
        contentView: null,

        /**
        * Creates an object that gives the events this view will listen to and the
        * associated function to call. Each entry in the object has the format 'event
        * selector': 'function'.
        * @returns {Object}
        */
        events: function () {
          var events = {};
          // Collapse or expand this Detail section when the toggle button is clicked. Get
          // the class of the toggle button from the classes property set in this view.
          events['click .' + this.classes.toggle] = 'toggle'
          return events
        },

        /**
        * Executed when a new LayerDetailView is created
        * @param {Object} [options] - A literal object with options to pass to the view
        */
        initialize: function (options) {

          try {
            // Get all the options and apply them to this view
            if (typeof options == 'object') {
              for (const [key, value] of Object.entries(options)) {
                this[key] = value;
              }
            }
          } catch (e) {
            console.log('A LayerDetailView failed to initialize. Error message: ' + e);
          }

        },

        /**
        * Renders this view
        * @return {LayerDetailView} Returns the rendered view element
        */
        render: function () {

          try {

            // Save a reference to this view
            var view = this;
            
            // Ensure the view's main element has the given class name
            this.el.classList.add(this.className);

            // Display the section's contents depending on the view's initial setting
            if (this.isOpen) {
              this.el.classList.add(this.classes.open);
            }

            // Insert the template into the view
            this.$el.html(this.template({
              label: this.label,
              collapsible: this.collapsible,
              showTitle: this.showTitle
            }));

            // Render the content for this Layer Detail section
            if (this.contentView) {
              var contentContainer = this.el.querySelector(
                '.' + this.classes.contentContainer
              )
              this.renderedContentView = new this.contentView({
                model: this.model
              })
              contentContainer.append(this.renderedContentView.el)
              this.renderedContentView.render()
            }

            if (!this.collapsible && !this.showTitle) {
              this.el.classList.add(this.classes.noHeader);
            }

            return this

          }
          catch (error) {
            console.log(
              'There was an error rendering a LayerDetailView' +
              '. Error details: ' + error
            );
          }
        },

        /**
         * Show or hide this section's contents by adding or removing the open class.
         */
        toggle : function(){
          try {
            this.el.classList.toggle(this.classes.open)
            if (this.isOpen) {
              this.isOpen = false
            } else {
              this.isOpen = true
            }
          }
          catch (error) {
            console.log(
              'There was an error toggling a LayerDetailView' +
              '. Error details: ' + error
            );
          }
        },

        /**
         * Perform clean-up functions when this view is about to be removed from the page
         * or navigated away from.
         */
        onClose: function () {
          try {
            if (
              this.renderedContentView &&
              typeof this.renderedContentView.onClose === 'function'
            ) {
              this.renderedContentView.onClose()
            }
          }
          catch (error) {
            console.log(
              'There was an error performing clean up functions in a LayerDetailView' +
              '. Error details: ' + error
            );
          }
        }

      }
    );

    return LayerDetailView;

  }
);