toolshed-8.x-1.x-dev/assets/widgets/Pane.es6.js

assets/widgets/Pane.es6.js
(({ Toolshed: ts }) => {
  /**
   * A Pane is floating DIV with manageable content.
   *
   * It is designed to be the base of dialogs, pop-ups or other elements
   * that attach to other content.
   */
  class Pane extends ts.Element {
    static defaultOptions() {
      return {
        classes: [],
      };
    }

    /**
     * Create a new instance of the a display pane.
     *
     * @param {Object} options
     *   The configuration options for how to handle pane behaviors.
     */
    constructor(options = {}) {
      super('div', null, document.body);

      this.opts = {
        ...Pane.defaultOptions(),
        ...options,
      };

      this.content = new ts.Element('div', { class: 'pane__content' }, this);

      this.addClass(this.opts.classes.concat('ts-pane', 'pane'));
      this.setStyles({
        display: 'none',
        position: 'absolute',
        zIndex: this.opts.zIndex,
      });

      this.append = !this.opts.onAddItem ? this.appendItem : (item) => {
        const el = this.opts.onAddItem(item);
        this.appendItem(el || item);
      };

      this.remove = !this.opts.onRemoveItem ? this.removeItem : (item) => {
        const el = this.opts.onRemoveItem(item);
        this.removeItem(el || item);
      };
    }

    /**
     * Adds and element to the start of the content container.
     *
     * @param {Node} item
     *   Item to add to the start of the pane content.
     */
    prependItem(item) {
      this.content.prependChild(item);
      return this;
    }

    /**
     * Add an element to the content container.
     *
     * @param {Node} item
     *   The node to add to the content container.
     */
    appendItem(item) {
      this.content.appendChild(item);
      return this;
    }

    /**
     * Remove an element from the content container.
     *
     * @param {Node} item
     *   The node to remove from the content container.
     */
    removeItem(item) {
      this.content.removeChild(item);
      return this;
    }

    /**
     * Clear the content container of all nodes and elements.
     */
    clear() {
      this.content.empty();
      return this;
    }

    /**
     * Is the suggestion window open?
     *
     * @return {Boolean}
     *   TRUE if the suggestions window is open, otherwise FALSE.
     */
    isVisible() {
      return this.style.display !== 'none';
    }

    /**
     * Position the pane before displaying it.
     */
    // eslint-disable-next-line class-methods-use-this
    positionPane() {
      // TODO: position based on pane options.
    }

    /**
     * Position and expose the suggestions window if it is not already open.
     *
     * @return {bool}
     *   Always returns true, to indicate that the dialog is open.
     */
    open() {
      if (!this.isVisible()) {
        this.style.display = '';

        this.positionPane();
      }
      return true;
    }

    /**
     * Close the content pane.
     *
     * @return {bool}
     *   Always returns false, to indicate that the pane is closed.
     */
    close() {
      this.style.display = 'none';
      return false;
    }

    /**
     * Toggle to open and close status of the pane.
     *
     * @return {bool}
     *   Returns true if result is pane is open, and false if it is closed.
     */
    toggle() {
      return this.isVisible() ? this.close() : this.open();
    }

    /**
     * Teardown and clean-up of Pane contents.
     */
    destroy() {
      this.clear();
      super.destroy(true);
    }
  }

  /**
   * A pane, that attaches itself to another element in the document.
   *
   * AttachedPanes are a good base for pop-ups, toolbars or other elements
   * that display content and anchor themselves to other screen elements.
   */
  class AttachedPane extends Pane {
    /**
     * Create a new instance of an AttachedPane.
     *
     * @param {DOMElement} attachTo
     *   The element containing the pane content.
     * @param {Object} options
     *   The configuration options for how to handle pane behaviors.
     */
    constructor(attachTo, options = {}) {
      super(options);

      this.attachTo = attachTo;
    }

    /**
     * @override
     */
    positionPane() {
      const rect = this.attachTo.getBoundingClientRect();
      const scroll = {
        x: document.documentElement.scrollLeft || document.body.scrollLeft,
        y: document.documentElement.scrollTop || document.body.scrollTop,
      };

      this.style.top = (rect.top > this.el.clientHeight)
        ? `${(scroll.y - this.el.clientHeight) + rect.bottom}px`
        : `${scroll.y + rect.top}px`;

      this.style.left = `${scroll.x + rect.right}px`;

      // Calculate the z-index of the attached button, this becomes important,
      // when dealing with form elements in pop-up dialogs. Only calculate this
      // if not already explicitly set by the options.
      if (!this.opts.zIndex && !this.style.zIndex) {
        let cur = this.attachTo;
        let zIndex = 10;

        while (cur) {
          const z = (cur.style || {}).zIndex || window.getComputedStyle(cur).getPropertyValue('z-index');

          if (Number.isInteger(z) || /\d+/.test(z)) {
            const tz = (ts.isString(z) ? parseInt(z, 10) : z) + 10;
            if (tz > zIndex) zIndex = tz;
          }

          cur = cur.parentElement;
        }

        this.style.zIndex = zIndex;
      }
    }
  }

  ts.Pane = Pane;
  ts.AttachedPane = AttachedPane;
})(Drupal);

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc