Source: src/js/views/portals/editor/PortEditorLogosView.js

define([
  "underscore",
  "jquery",
  "backbone",
  "models/portals/PortalImage",
  "views/portals/editor/PortEditorImageView",
], function (_, $, Backbone, PortalImage, ImageEdit) {
  /**
   * @class PortEditorLogosView
   * @classcategory Views/Portals/Editor
   * @extends Backbone.View
   */
  var PortEditorLogosView = Backbone.View.extend(
    /** @lends PortEditorLogosView.prototype */ {
      /**
       * The type of View this is
       * @type {string}
       */
      type: "PortEditorLogos",

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

      /**
       * The HTML classes to use for this view's element
       * @type {string}
       */
      className: "port-editor-logos",

      /**
       * The PortalModel that is being edited
       * @type {Portal}
       */
      model: undefined,

      /**
       * A reference to the PortalEditorView
       * @type {PortalEditorView}
       */
      editorView: undefined,

      /**
       * The events this view will listen to and the associated function to call.
       * @type {Object}
       */
      events: {
        "keyup .edit-image.new .basic-text": "handleNewInput",
        "click .remove": "handleRemove",
      },

      /**
       * Creates a new PortEditorLogosView
       * @param {Object} options - A literal object with options to pass to the view
       * @property {Portal} options.model - The Portal whose logos are rendered in this view
       * @property {PortalEditorView}  options.editorView - Gets set as PortalEditorLogosView.editorView
       */
      initialize: function (options) {
        try {
          if (typeof options == "object") {
            this.model = options.model || undefined;
            this.editorView = options.editorView;
          }
        } catch (e) {
          console.log(
            "PortEditorLogosView failed to initialize. Error message: " + e,
          );
        }
      },

      /**
       * Renders this view
       */
      render: function () {
        try {
          var savedLogos = this.model.get("acknowledgmentsLogos"),
            newLogo = new PortalImage({ nodeName: "acknowledgmentsLogo" });

          // If there are no acknowledgmentsLogos yet, then set a new empty logo for
          // the user to enter information into
          if (!savedLogos || !savedLogos.length) {
            this.model.set("acknowledgmentsLogos", [newLogo]);
            // If there are already logos, add a new blank logo to the end of the list.
            // Note that empty logos won't get serialized
          } else {
            savedLogos.push(newLogo);
            this.model.set("acknowledgmentsLogos", savedLogos);
          }

          // Iterate over each logo in the PortalModel and render an ImageView
          _.each(
            this.model.get("acknowledgmentsLogos"),
            function (portalImage) {
              this.renderAckLogoInput(portalImage);
            },
            this,
          );
        } catch (e) {
          console.log(
            "PortEditorLogosView failed to render, error message: " + e,
          );
        }
      },

      /**
       * renderAckLogoInput - Adds a new ImageEdit view for a specified PortalImage model for an acknowledgments logo.
       *
       * @param  {PortalImage} portalImage The PortalImage model to create an ImageEdit view for.
       */
      renderAckLogoInput: function (portalImage) {
        try {
          var view = this;

          // Check if this is a new, empty acknowledgmentsLogo
          var isNew =
            !portalImage.get("identifier") &&
            !portalImage.get("associatedURL") &&
            !portalImage.get("label");

          var imageEdit = new ImageEdit({
            parentModel: this.model,
            editorView: this.editorView,
            model: portalImage,
            imageUploadInstructions:
              "Drag & drop a partner logo or click to upload",
            imageWidth: 150,
            imageHeight: 150,
            minWidth: 100,
            minHeight: 100,
            maxHeight: 300,
            maxWidth: 300,
            nameLabel: "Organization name",
            urlLabel: "Organization URL",
            imageTagName: "img",
            removeButton: true,
          });
          $(this.el).append(imageEdit.el);
          imageEdit.render();

          // When user adds a file, this imageEdit is no longer new
          imageEdit.listenToOnce(imageEdit.uploader, "addedfile", function () {
            view.handleNewInput(this);
          });

          if (isNew) {
            $(imageEdit.el).addClass("new");
            // Don't allow users to remove the new portalImage -
            // it's the only place to add an acknowledgmentsLogo.
            $(imageEdit.el).find(".remove.icon").hide();
          }
        } catch (e) {
          console.log(
            "Could not render an ImageEdit view for an acknowledgmentsLogo. Error message: " +
              e,
          );
        }
      },

      /**
       * handleNewInput - Called when a user enters any input into a new ImageEdit
       * view. It removes the "new" class, shows the "remove" button, and adds a new
       * ImageEdit view with a blank PortalImage model.
       *
       * @param  {object} eventOrView either the keyup event when user enters text
       * into an imageEdit input, OR the imageEdit view which contains the
       * imageUploader where a user just uploaded an image.
       */
      handleNewInput: function (eventOrView) {
        try {
          // Get the relevant imageEdit view element
          var imageEditEl = eventOrView.target
            ? // when the arguement is an event
              $(eventOrView.target).closest(".edit-image.new")
            : // when the argument is a view
              eventOrView.$el;

          // This function should only modify new image-edit views
          if (!imageEditEl || !imageEditEl.hasClass("new")) {
            return;
          }

          var currentLogos = this.model.get("acknowledgmentsLogos"),
            newLogo = new PortalImage({ nodeName: "acknowledgmentsLogo" });

          // Remove the 'new' class
          imageEditEl.removeClass("new");

          // Allow users to delete this logo
          imageEditEl.find(".remove.icon").show();

          // Add a new blank portalImage
          currentLogos.push(newLogo);
          this.model.set("acknowledgmentsLogos", currentLogos);

          // Show the new EditImage view
          this.renderAckLogoInput(newLogo);

          this.editorView.showControls();
        } catch (e) {
          console.log(
            "Failed to handle user input in an acknowledgments logo imageEdit view. Error message: " +
              e,
          );
        }
      },

      /**
       * showValidation - Show validation errors for each logoView
       */
      showValidation: function () {
        var logoViews = $(this.el).find(".edit-image");

        _.each(logoViews, function (logoView) {
          $(logoView).data("view").showValidation();
        });
      },

      /**
       * This function is called when a logo is removed. The logo removal itself is done
       * by the PortEditorImageView. This function performs additional functionality that
       * should happen after the removal.
       */
      handleRemove: function () {
        this.editorView.showControls();
      },
    },
  );

  return PortEditorLogosView;
});