Source: src/js/views/portals/PortalSectionView.js

define([
  "jquery",
  "underscore",
  "backbone",
  "models/portals/PortalSectionModel",
  "views/MarkdownView",
  "text!templates/portals/portalSection.html",
], function ($, _, Backbone, PortalSectionModel, MarkdownView, Template) {
  /**
   * @class PortalSectionView
   * @classdesc The PortalSectionView is a generic view to render
   * portal sections, with a default rendering of a
   * MarkdownView
   * @classcategory Views/Portals
   * @module views/PortalSectionView
   * @name PortalSectionView
   * @extends Backbone.View
   * @constructor
   */
  var PortalSectionView = Backbone.View.extend(
    /** @lends PortalSectionView.prototype */ {
      /**
       * The type of View this is
       * @type {string}
       * @readonly
       */
      type: "PortalSection",

      /**
       * The display name for this Section
       * @type {string}
       */
      sectionName: "",

      /**
       * The unique label for this Section. It most likely matches the label on the model, but
       * may include a number after if more than one section has the same name.
       * @type {string}
       */
      uniqueSectionLabel: "",

      /**
       * The HTML tag name for this view's element
       * @type {string}
       */
      tagName: "div",

      /**
       * The HTML classes to use for this view's element
       * @type {string}
       */
      className: "tab-pane portal-section-view",

      /**
       * Specifies if this section is active or not
       * @type {boolean}
       */
      active: false,

      /**
       * The PortalSectionModel that is being edited
       * @type {PortalSection}
       */
      model: undefined,

      /**
       * @type {UnderscoreTemplate}
       */
      template: _.template(Template),

      /**
       * @param {Object} options - A literal object with options to pass to the view
       * @property {PortalSection} options.model - The PortalSection rendered in this view
       * @property {string} options.sectionName - The name of the portal section
       */
      initialize: function (options) {
        // Get all the options and apply them to this view
        if (typeof options == "object") {
          var optionKeys = Object.keys(options);
          _.each(
            optionKeys,
            function (key, i) {
              this[key] = options[key];
            },
            this,
          );
        }
      },

      /**
         Renders the view
        */
      render: function () {
        //Add the active class to the element
        if (this.active) {
          this.$el.addClass("active");
        }

        //Add an id to this element so links work
        this.$el.attr("id", this.getName({ linkFriendly: true }));

        this.$el.html(
          this.template({
            imageURL: this.model.get("image")
              ? this.model.get("image").get("imageURL")
              : "",
            title: this.model.get("title"),
            introduction: this.model.get("introduction"),
          }),
        );

        this.$el.data("view", this);

        //If there is Markdown, render it
        if (this.model.get("content").get("markdown")) {
          //Create a MarkdownView
          this.markdownView = new MarkdownView({
            markdown: this.model.get("content").get("markdown"),
            citations: this.model.get("literatureCited"),
            showTOC: true,
          });

          // Listen to the markdown view and when it is rendered, format the rendered markdown
          this.listenTo(
            this.markdownView,
            "mdRendered",
            this.postMarkdownRender,
          );

          // Render the view
          this.markdownView.render();

          // Add the markdown view element to this view
          this.$(".portal-section-content").html(this.markdownView.el);
        }
      },

      /**
       * This funciton is called after this view has fully rendered and is
       * visible on the webpage
       */
      postRender: function () {
        _.each(this.subviews, function (subview) {
          if (subview.postRender) {
            subview.postRender();
          }
        });

        document.body.style.removeProperty("height");

        this.markdownView?.tocView?.setAffix();
      },

      /**
       * When the portal section markdown is rendered in a MarkdownView, format the
       * resulting HTML as needed for this view
       */
      postMarkdownRender: function () {
        // If the window location has a hash, scroll to it
        if (window.location.hash && this.$(window.location.hash).length) {
          var view = this;
          // Wait 0.5 seconds to allow images time to load before we scroll down the page
          setTimeout(function () {
            // Scroll to the element specified in the hash
            MetacatUI.appView.scrollTo(view.$(window.location.hash));
          }, 500);
        }
      },

      /**
       * Gets the name of this section and returns it
       * @param {Object} [options] - Optional options for the name that is returned
       * @property {Boolean} options.linkFriendly - If true, the name will be stripped of special characters
       * @return {string} The name for this section
       */
      getName: function (options) {
        var name = "";

        //If a section name is set on the view, use that
        if (this.sectionName) {
          name = this.sectionName;
        }
        //If the model is a PortalSectionModel, use the label from the model
        else if (PortalSectionModel.prototype.isPrototypeOf(this.model)) {
          name = this.model.get("label");
        } else {
          name = "Untitled";
        }

        if (typeof options == "object") {
          if (options.linkFriendly) {
            name = name.replace(/[^a-zA-Z0-9 ]/g, "").replace(/ /g, "-");
          }
        }

        return name;
      },
    },
  );

  return PortalSectionView;
});