252 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			252 lines
		
	
	
		
			9.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * @file
 | 
						|
 * tabledrag.js overrides and functionality extensions.
 | 
						|
 */
 | 
						|
 | 
						|
(($, Drupal) => {
 | 
						|
  /**
 | 
						|
   * Extends core's Tabledrag functionality.
 | 
						|
   *
 | 
						|
   * @type {Drupal~behavior}
 | 
						|
   */
 | 
						|
  Drupal.behaviors.claroTableDrag = {
 | 
						|
    attach(context, settings) {
 | 
						|
      /**
 | 
						|
       * Refactors the table row markup to improve item label text wrapping.
 | 
						|
       *
 | 
						|
       * This addresses an issue specific to item labels that are long enough
 | 
						|
       * to be wrapped to a new line. Without this fix, a new line may start
 | 
						|
       * at the beginning of the table row, instead of the expected behavior of
 | 
						|
       * starting at the x axis of the first line.
 | 
						|
       *
 | 
						|
       * Addressing this issue requires changing the structure of a tabledrag
 | 
						|
       * cell's first row.
 | 
						|
       * @example
 | 
						|
       *   <!-- Default tabledrag structure, which has the wrapping problem. -->
 | 
						|
       *   <tr class="draggable">
 | 
						|
       *     <td>
 | 
						|
       *       <!--
 | 
						|
       *         Indentations are next to each other because they are styled as
 | 
						|
       *         `float: left;`
 | 
						|
       *       -->
 | 
						|
       *       <div class="indentation"></div>
 | 
						|
       *       <div class="indentation"></div>
 | 
						|
       *       <a class="tabledrag-handle"></a>
 | 
						|
       *       <!-- If the text in this link wraps enough times that the element
 | 
						|
       *         is taller than the floated elements preceding it, some lines
 | 
						|
       *         will wrap to the beginning of the row instead of aligning with
 | 
						|
       *         the beginning of the link text.
 | 
						|
       *       -->
 | 
						|
       *       <a class="menu-item__link">A longer label that may require wrapping</a>
 | 
						|
       *     </td>
 | 
						|
       *     <!-- etc. -->
 | 
						|
       *   </tr>
 | 
						|
       * @example
 | 
						|
       * <!-- Claro tabledrag structure, this fixes the wrapping problem. -->
 | 
						|
       *   <tr class="draggable">
 | 
						|
       *     <td class="tabledrag-cell">
 | 
						|
       *       <div class="tabledrag-cell-content">
 | 
						|
       *          <!-- Indentations are next to each other because
 | 
						|
       *            .table-drag-cell-content is styled as `display: table-row;`
 | 
						|
       *            and .table-drag-cell-content > * is styled as
 | 
						|
       *            `display: table-cell;`
 | 
						|
       *          -->
 | 
						|
       *         <div class="indentation"></div>
 | 
						|
       *         <div class="indentation"></div>
 | 
						|
       *         <a class="tabledrag-handle"></a>
 | 
						|
       *         <div class="tabledrag-cell-content__item">
 | 
						|
       *           <!-- Placing the link inside a div styled as
 | 
						|
       *             `display: table-cell;` allows the text to wrap within
 | 
						|
       *             the boundaries of the "cell".
 | 
						|
       *           -->
 | 
						|
       *           <a class="menu-item__link">A longer label that may require wrapping</a>
 | 
						|
       *         </div>
 | 
						|
       *      </div>
 | 
						|
       *    </td>
 | 
						|
       *    <!-- additional <td> -->
 | 
						|
       *   </tr>
 | 
						|
       *
 | 
						|
       * @param {number} index
 | 
						|
       *   The index in the loop, as provided by `jQuery.each`.
 | 
						|
       * @param {HTMLElement} row
 | 
						|
       *   A draggable table row.
 | 
						|
       *
 | 
						|
       * @todo this may be removable as part of https://drupal.org/node/3083044
 | 
						|
       */
 | 
						|
      const createItemWrapBoundaries = (row) => {
 | 
						|
        const $row = $(row);
 | 
						|
        const $firstCell = $row
 | 
						|
          .find('td:first-of-type')
 | 
						|
          .eq(0)
 | 
						|
          .wrapInner(Drupal.theme('tableDragCellContentWrapper'))
 | 
						|
          .wrapInner(
 | 
						|
            $(Drupal.theme('tableDragCellItemsWrapper')).addClass(
 | 
						|
              'js-tabledrag-cell-content',
 | 
						|
            ),
 | 
						|
          );
 | 
						|
 | 
						|
        const $targetElem = $firstCell.find('.js-tabledrag-cell-content');
 | 
						|
 | 
						|
        // Move handle into the '.js-tabledrag-cell-content' target.
 | 
						|
        $targetElem
 | 
						|
          .eq(0)
 | 
						|
          .find(
 | 
						|
            '> .tabledrag-cell-content__item > .js-tabledrag-handle, > .tabledrag-cell-content__item > .js-indentation',
 | 
						|
          )
 | 
						|
          .prependTo($targetElem);
 | 
						|
      };
 | 
						|
 | 
						|
      // Find each row in a draggable table and process it with
 | 
						|
      // createItemWrapBoundaries().
 | 
						|
      Object.keys(settings.tableDrag || {}).forEach((base) => {
 | 
						|
        once(
 | 
						|
          'claroTabledrag',
 | 
						|
          $(context)
 | 
						|
            .find(`#${base}`)
 | 
						|
            .find('> tr.draggable, > tbody > tr.draggable'),
 | 
						|
        ).forEach(createItemWrapBoundaries);
 | 
						|
      });
 | 
						|
    },
 | 
						|
  };
 | 
						|
  $.extend(Drupal.tableDrag.prototype.row.prototype, {
 | 
						|
    /**
 | 
						|
     * Add an asterisk or other marker to the changed row.
 | 
						|
     *
 | 
						|
     * @todo this may be removable as part of https://drupal.org/node/3084910
 | 
						|
     */
 | 
						|
    markChanged() {
 | 
						|
      const marker = $(Drupal.theme('tableDragChangedMarker')).addClass(
 | 
						|
        'js-tabledrag-changed-marker',
 | 
						|
      );
 | 
						|
      const cell = $(this.element).find('td:first-of-type');
 | 
						|
      if (cell.find('.js-tabledrag-changed-marker').length === 0) {
 | 
						|
        cell.find('.js-tabledrag-handle').after(marker);
 | 
						|
      }
 | 
						|
      Drupal.tableDrag[this.table.id].changedRowIds.add(this.element.id);
 | 
						|
    },
 | 
						|
 | 
						|
    /**
 | 
						|
     * Moves added indents into Claro's wrapper element.
 | 
						|
     *
 | 
						|
     * For indents to work properly, they must be inside the wrapper
 | 
						|
     * created by createItemWrapBoundaries(). When an indent is added via
 | 
						|
     * dragging, core's tabledrag functionality does not add it inside the
 | 
						|
     * wrapper. This function fires immediately after an indent is added, which
 | 
						|
     * moves the indent into that wrapper.
 | 
						|
     *
 | 
						|
     * @see Drupal.tableDrag.prototype.row.prototype.indent
 | 
						|
     *
 | 
						|
     * @todo this may be removable as part of https://drupal.org/node/3083044
 | 
						|
     */
 | 
						|
    onIndent() {
 | 
						|
      $(this.table)
 | 
						|
        .find('.tabledrag-cell > .js-indentation')
 | 
						|
        .each((index, indentToMove) => {
 | 
						|
          const $indentToMove = $(indentToMove);
 | 
						|
          const $cellContent = $indentToMove.siblings(
 | 
						|
            '.tabledrag-cell-content',
 | 
						|
          );
 | 
						|
          $indentToMove.prependTo($cellContent);
 | 
						|
        });
 | 
						|
    },
 | 
						|
  });
 | 
						|
 | 
						|
  $.extend(
 | 
						|
    Drupal.theme,
 | 
						|
    /** @lends Drupal.theme */ {
 | 
						|
      /**
 | 
						|
       * Constructs the table drag changed marker.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   Markup for the indentation.
 | 
						|
       */
 | 
						|
      tableDragIndentation() {
 | 
						|
        return '<div class="js-indentation indentation"><svg xmlns="http://www.w3.org/2000/svg" class="tree" width="25" height="25" viewBox="0 0 25 25"><path class="tree__item tree__item-child-ltr tree__item-child-last-ltr tree__item-horizontal tree__item-horizontal-right" d="M12,12.5 H25" stroke="#888"/><path class="tree__item tree__item-child-rtl tree__item-child-last-rtl tree__item-horizontal tree__horizontal-left" d="M0,12.5 H13" stroke="#888"/><path class="tree__item tree__item-child-ltr tree__item-child-rtl tree__item-child-last-ltr tree__item-child-last-rtl tree__vertical tree__vertical-top" d="M12.5,12 v-99" stroke="#888"/><path class="tree__item tree__item-child-ltr tree__item-child-rtl tree__vertical tree__vertical-bottom" d="M12.5,12 v99" stroke="#888"/></svg></div>';
 | 
						|
      },
 | 
						|
 | 
						|
      /**
 | 
						|
       * Constructs the table drag changed warning.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   Markup for the warning.
 | 
						|
       */
 | 
						|
      tableDragChangedWarning() {
 | 
						|
        return `<div class="tabledrag-changed-warning messages messages--warning" role="alert">${Drupal.theme(
 | 
						|
          'tableDragChangedMarker',
 | 
						|
        )} ${Drupal.t('You have unsaved changes.')}</div>`;
 | 
						|
      },
 | 
						|
 | 
						|
      /**
 | 
						|
       * Constructs the table drag handle.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   A string representing a DOM fragment.
 | 
						|
       */
 | 
						|
      tableDragHandle: (dragOrientation = 'drag') => {
 | 
						|
        const title =
 | 
						|
          dragOrientation === 'drag-y'
 | 
						|
            ? Drupal.t('Change order')
 | 
						|
            : Drupal.t('Move in any direction');
 | 
						|
        return `<a href="#" title="${title}" class="tabledrag-handle js-tabledrag-handle"></a>`;
 | 
						|
      },
 | 
						|
 | 
						|
      /**
 | 
						|
       * The button for toggling table row weight visibility.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   HTML markup for the weight toggle button and its container.
 | 
						|
       */
 | 
						|
      tableDragToggle: () =>
 | 
						|
        `<div class="tabledrag-toggle-weight-wrapper" data-drupal-selector="tabledrag-toggle-weight-wrapper">
 | 
						|
            <button type="button" class="link action-link tabledrag-toggle-weight" data-drupal-selector="tabledrag-toggle-weight"></button>
 | 
						|
            </div>`,
 | 
						|
 | 
						|
      /**
 | 
						|
       * Constructs contents of the toggle weight button.
 | 
						|
       *
 | 
						|
       * @param {boolean} show
 | 
						|
       *   If the table weights are currently displayed.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *  HTML markup for the weight toggle button content.
 | 
						|
       */
 | 
						|
      toggleButtonContent: (show) => {
 | 
						|
        const classes = [
 | 
						|
          'action-link',
 | 
						|
          'action-link--extrasmall',
 | 
						|
          'tabledrag-toggle-weight',
 | 
						|
        ];
 | 
						|
        let text = '';
 | 
						|
        if (show) {
 | 
						|
          classes.push('action-link--icon-hide');
 | 
						|
          text = Drupal.t('Hide row weights');
 | 
						|
        } else {
 | 
						|
          classes.push('action-link--icon-show');
 | 
						|
          text = Drupal.t('Show row weights');
 | 
						|
        }
 | 
						|
        return `<span class="${classes.join(' ')}">${text}</a>`;
 | 
						|
      },
 | 
						|
 | 
						|
      /**
 | 
						|
       * Constructs the wrapper for the initial content of the drag cell.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   A string representing a DOM fragment.
 | 
						|
       */
 | 
						|
      tableDragCellContentWrapper() {
 | 
						|
        return '<div class="tabledrag-cell-content__item"></div>';
 | 
						|
      },
 | 
						|
 | 
						|
      /**
 | 
						|
       * Constructs the wrapper for the whole table drag cell.
 | 
						|
       *
 | 
						|
       * @return {string}
 | 
						|
       *   A string representing a DOM fragment.
 | 
						|
       */
 | 
						|
      tableDragCellItemsWrapper() {
 | 
						|
        return '<div class="tabledrag-cell-content"></div>';
 | 
						|
      },
 | 
						|
    },
 | 
						|
  );
 | 
						|
})(jQuery, Drupal);
 |