259 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			259 lines
		
	
	
		
			9.5 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| 
								 | 
							
								/**
							 | 
						||
| 
								 | 
							
								 * @file
							 | 
						||
| 
								 | 
							
								 * Block behaviors.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								(function ($, window, Drupal, once) {
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Provide the summary information for the block settings vertical tabs.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @type {Drupal~behavior}
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @prop {Drupal~behaviorAttach} attach
							 | 
						||
| 
								 | 
							
								   *   Attaches the behavior for the block settings summaries.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  Drupal.behaviors.blockSettingsSummary = {
							 | 
						||
| 
								 | 
							
								    attach() {
							 | 
						||
| 
								 | 
							
								      // The drupalSetSummary method required for this behavior is not available
							 | 
						||
| 
								 | 
							
								      // on the Blocks administration page, so we need to make sure this
							 | 
						||
| 
								 | 
							
								      // behavior is processed only if drupalSetSummary is defined.
							 | 
						||
| 
								 | 
							
								      if (typeof $.fn.drupalSetSummary === 'undefined') {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /**
							 | 
						||
| 
								 | 
							
								       * Create a summary for checkboxes in the provided context.
							 | 
						||
| 
								 | 
							
								       *
							 | 
						||
| 
								 | 
							
								       * @param {Document|HTMLElement} context
							 | 
						||
| 
								 | 
							
								       *   A context where one would find checkboxes to summarize.
							 | 
						||
| 
								 | 
							
								       *
							 | 
						||
| 
								 | 
							
								       * @return {string}
							 | 
						||
| 
								 | 
							
								       *   A string with the summary.
							 | 
						||
| 
								 | 
							
								       */
							 | 
						||
| 
								 | 
							
								      function checkboxesSummary(context) {
							 | 
						||
| 
								 | 
							
								        const values = [];
							 | 
						||
| 
								 | 
							
								        const $checkboxes = $(context).find(
							 | 
						||
| 
								 | 
							
								          'input[type="checkbox"]:checked + label',
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        const il = $checkboxes.length;
							 | 
						||
| 
								 | 
							
								        for (let i = 0; i < il; i++) {
							 | 
						||
| 
								 | 
							
								          values.push($($checkboxes[i]).html());
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (!values.length) {
							 | 
						||
| 
								 | 
							
								          values.push(Drupal.t('Not restricted'));
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return values.join(', ');
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      $(
							 | 
						||
| 
								 | 
							
								        '[data-drupal-selector="edit-visibility-node-type"], [data-drupal-selector="edit-visibility-entity-bundlenode"], [data-drupal-selector="edit-visibility-language"], [data-drupal-selector="edit-visibility-user-role"], [data-drupal-selector="edit-visibility-response-status"]',
							 | 
						||
| 
								 | 
							
								      ).drupalSetSummary(checkboxesSummary);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      $(
							 | 
						||
| 
								 | 
							
								        '[data-drupal-selector="edit-visibility-request-path"]',
							 | 
						||
| 
								 | 
							
								      ).drupalSetSummary((context) => {
							 | 
						||
| 
								 | 
							
								        const $pages = $(context).find(
							 | 
						||
| 
								 | 
							
								          'textarea[name="visibility[request_path][pages]"]',
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        if (!$pages.length || !$pages[0].value) {
							 | 
						||
| 
								 | 
							
								          return Drupal.t('Not restricted');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        return Drupal.t('Restricted to certain pages');
							 | 
						||
| 
								 | 
							
								      });
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /**
							 | 
						||
| 
								 | 
							
								   * Move a block in the blocks table between regions via select list.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * This behavior is dependent on the tableDrag behavior, since it uses the
							 | 
						||
| 
								 | 
							
								   * objects initialized in that behavior to update the row.
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @type {Drupal~behavior}
							 | 
						||
| 
								 | 
							
								   *
							 | 
						||
| 
								 | 
							
								   * @prop {Drupal~behaviorAttach} attach
							 | 
						||
| 
								 | 
							
								   *   Attaches the tableDrag behavior for blocks in block administration.
							 | 
						||
| 
								 | 
							
								   */
							 | 
						||
| 
								 | 
							
								  Drupal.behaviors.blockDrag = {
							 | 
						||
| 
								 | 
							
								    attach(context, settings) {
							 | 
						||
| 
								 | 
							
								      // tableDrag is required and we should be on the blocks admin page.
							 | 
						||
| 
								 | 
							
								      if (typeof Drupal?.tableDrag?.blocks === 'undefined') {
							 | 
						||
| 
								 | 
							
								        return;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /**
							 | 
						||
| 
								 | 
							
								       * Function to check empty regions and toggle classes based on this.
							 | 
						||
| 
								 | 
							
								       *
							 | 
						||
| 
								 | 
							
								       * @param {jQuery} table
							 | 
						||
| 
								 | 
							
								       *   The jQuery object representing the table to inspect.
							 | 
						||
| 
								 | 
							
								       * @param {Drupal.tableDrag.row} rowObject
							 | 
						||
| 
								 | 
							
								       *   Drupal table drag row dropped.
							 | 
						||
| 
								 | 
							
								       */
							 | 
						||
| 
								 | 
							
								      function checkEmptyRegions(table, rowObject) {
							 | 
						||
| 
								 | 
							
								        table.find('tr.region-message').each(function () {
							 | 
						||
| 
								 | 
							
								          const $this = $(this);
							 | 
						||
| 
								 | 
							
								          // If the dragged row is in this region, but above the message row,
							 | 
						||
| 
								 | 
							
								          // swap it down one space.
							 | 
						||
| 
								 | 
							
								          if ($this.prev('tr').get(0) === rowObject.element) {
							 | 
						||
| 
								 | 
							
								            // Prevent a recursion problem when using the keyboard to move rows
							 | 
						||
| 
								 | 
							
								            // up.
							 | 
						||
| 
								 | 
							
								            if (
							 | 
						||
| 
								 | 
							
								              rowObject.method !== 'keyboard' ||
							 | 
						||
| 
								 | 
							
								              rowObject.direction === 'down'
							 | 
						||
| 
								 | 
							
								            ) {
							 | 
						||
| 
								 | 
							
								              rowObject.swap('after', this);
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          // This region has become empty.
							 | 
						||
| 
								 | 
							
								          if (
							 | 
						||
| 
								 | 
							
								            $this.next('tr').length === 0 ||
							 | 
						||
| 
								 | 
							
								            !$this.next('tr')[0].matches('.draggable')
							 | 
						||
| 
								 | 
							
								          ) {
							 | 
						||
| 
								 | 
							
								            $this.removeClass('region-populated').addClass('region-empty');
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          // This region has become populated.
							 | 
						||
| 
								 | 
							
								          else if (this.matches('.region-empty')) {
							 | 
						||
| 
								 | 
							
								            $this.removeClass('region-empty').addClass('region-populated');
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /**
							 | 
						||
| 
								 | 
							
								       * Function to update the last placed row with the correct classes.
							 | 
						||
| 
								 | 
							
								       *
							 | 
						||
| 
								 | 
							
								       * @param {jQuery} table
							 | 
						||
| 
								 | 
							
								       *   The jQuery object representing the table to inspect.
							 | 
						||
| 
								 | 
							
								       * @param {Drupal.tableDrag.row} rowObject
							 | 
						||
| 
								 | 
							
								       *   Drupal table drag row dropped.
							 | 
						||
| 
								 | 
							
								       */
							 | 
						||
| 
								 | 
							
								      function updateLastPlaced(table, rowObject) {
							 | 
						||
| 
								 | 
							
								        // Remove the color-success class from new block if applicable.
							 | 
						||
| 
								 | 
							
								        table.find('.color-success').removeClass('color-success');
							 | 
						||
| 
								 | 
							
								        const $rowObject = $(rowObject);
							 | 
						||
| 
								 | 
							
								        if (!rowObject.element.matches('.drag-previous')) {
							 | 
						||
| 
								 | 
							
								          table.find('.drag-previous').removeClass('drag-previous');
							 | 
						||
| 
								 | 
							
								          $rowObject.addClass('drag-previous');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      /**
							 | 
						||
| 
								 | 
							
								       * Update block weights in the given region.
							 | 
						||
| 
								 | 
							
								       *
							 | 
						||
| 
								 | 
							
								       * @param {jQuery} table
							 | 
						||
| 
								 | 
							
								       *   Table with draggable items.
							 | 
						||
| 
								 | 
							
								       * @param {string} region
							 | 
						||
| 
								 | 
							
								       *   Machine name of region containing blocks to update.
							 | 
						||
| 
								 | 
							
								       */
							 | 
						||
| 
								 | 
							
								      function updateBlockWeights(table, region) {
							 | 
						||
| 
								 | 
							
								        // Calculate minimum weight.
							 | 
						||
| 
								 | 
							
								        let weight = -Math.round(table.find('.draggable').length / 2);
							 | 
						||
| 
								 | 
							
								        // Update the block weights.
							 | 
						||
| 
								 | 
							
								        table
							 | 
						||
| 
								 | 
							
								          .find(`.region-${region}-message`)
							 | 
						||
| 
								 | 
							
								          .nextUntil('.region-title')
							 | 
						||
| 
								 | 
							
								          .find('select.block-weight')
							 | 
						||
| 
								 | 
							
								          .each(function () {
							 | 
						||
| 
								 | 
							
								            // Increment the weight before assigning it to prevent using the
							 | 
						||
| 
								 | 
							
								            // absolute minimum available weight. This way we always have an
							 | 
						||
| 
								 | 
							
								            // unused upper and lower bound, which makes manually setting the
							 | 
						||
| 
								 | 
							
								            // weights easier for users who prefer to do it that way.
							 | 
						||
| 
								 | 
							
								            this.value = ++weight;
							 | 
						||
| 
								 | 
							
								          });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      const table = $('#blocks');
							 | 
						||
| 
								 | 
							
								      // Get the blocks tableDrag object.
							 | 
						||
| 
								 | 
							
								      const tableDrag = Drupal.tableDrag.blocks;
							 | 
						||
| 
								 | 
							
								      // Add a handler for when a row is swapped, update empty regions.
							 | 
						||
| 
								 | 
							
								      tableDrag.row.prototype.onSwap = function (swappedRow) {
							 | 
						||
| 
								 | 
							
								        checkEmptyRegions(table, this);
							 | 
						||
| 
								 | 
							
								        updateLastPlaced(table, this);
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Add a handler so when a row is dropped, update fields dropped into
							 | 
						||
| 
								 | 
							
								      // new regions.
							 | 
						||
| 
								 | 
							
								      tableDrag.onDrop = function () {
							 | 
						||
| 
								 | 
							
								        const dragObject = this;
							 | 
						||
| 
								 | 
							
								        const $rowElement = $(dragObject.rowObject.element);
							 | 
						||
| 
								 | 
							
								        // Use "region-message" row instead of "region" row because
							 | 
						||
| 
								 | 
							
								        // "region-{region_name}-message" is less prone to regexp match errors.
							 | 
						||
| 
								 | 
							
								        const regionRow = $rowElement.prevAll('tr.region-message').get(0);
							 | 
						||
| 
								 | 
							
								        const regionName = regionRow.className.replace(
							 | 
						||
| 
								 | 
							
								          /([^ ]+[ ]+)*region-([^ ]+)-message([ ]+[^ ]+)*/,
							 | 
						||
| 
								 | 
							
								          '$2',
							 | 
						||
| 
								 | 
							
								        );
							 | 
						||
| 
								 | 
							
								        const regionField = $rowElement.find('select.block-region-select');
							 | 
						||
| 
								 | 
							
								        // Check whether the newly picked region is available for this block.
							 | 
						||
| 
								 | 
							
								        if (regionField.find(`option[value=${regionName}]`).length === 0) {
							 | 
						||
| 
								 | 
							
								          // If not, alert the user and keep the block in its old region
							 | 
						||
| 
								 | 
							
								          // setting.
							 | 
						||
| 
								 | 
							
								          window.alert(Drupal.t('The block cannot be placed in this region.'));
							 | 
						||
| 
								 | 
							
								          // Simulate that there was a selected element change, so the row is
							 | 
						||
| 
								 | 
							
								          // put back to from where the user tried to drag it.
							 | 
						||
| 
								 | 
							
								          regionField.trigger('change');
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        // Update region and weight fields if the region has been changed.
							 | 
						||
| 
								 | 
							
								        if (!regionField[0].matches(`.block-region-${regionName}`)) {
							 | 
						||
| 
								 | 
							
								          const weightField = $rowElement.find('select.block-weight');
							 | 
						||
| 
								 | 
							
								          const oldRegionName = weightField[0].className.replace(
							 | 
						||
| 
								 | 
							
								            /([^ ]+[ ]+)*block-weight-([^ ]+)([ ]+[^ ]+)*/,
							 | 
						||
| 
								 | 
							
								            '$2',
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								          regionField
							 | 
						||
| 
								 | 
							
								            .removeClass(`block-region-${oldRegionName}`)
							 | 
						||
| 
								 | 
							
								            .addClass(`block-region-${regionName}`);
							 | 
						||
| 
								 | 
							
								          weightField
							 | 
						||
| 
								 | 
							
								            .removeClass(`block-weight-${oldRegionName}`)
							 | 
						||
| 
								 | 
							
								            .addClass(`block-weight-${regionName}`);
							 | 
						||
| 
								 | 
							
								          regionField[0].value = regionName;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        updateBlockWeights(table, regionName);
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								      // Add the behavior to each region select list.
							 | 
						||
| 
								 | 
							
								      $(once('block-region-select', 'select.block-region-select', context)).on(
							 | 
						||
| 
								 | 
							
								        'change',
							 | 
						||
| 
								 | 
							
								        function (event) {
							 | 
						||
| 
								 | 
							
								          // Make our new row and select field.
							 | 
						||
| 
								 | 
							
								          const row = $(this).closest('tr');
							 | 
						||
| 
								 | 
							
								          const select = $(this);
							 | 
						||
| 
								 | 
							
								          // Find the correct region and insert the row as the last in the
							 | 
						||
| 
								 | 
							
								          // region.
							 | 
						||
| 
								 | 
							
								          tableDrag.rowObject = new tableDrag.row(row[0]);
							 | 
						||
| 
								 | 
							
								          const regionMessage = table.find(
							 | 
						||
| 
								 | 
							
								            `.region-${select[0].value}-message`,
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								          const regionItems = regionMessage.nextUntil(
							 | 
						||
| 
								 | 
							
								            '.region-message, .region-title',
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								          if (regionItems.length) {
							 | 
						||
| 
								 | 
							
								            regionItems.last().after(row);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          // We found that regionMessage is the last row.
							 | 
						||
| 
								 | 
							
								          else {
							 | 
						||
| 
								 | 
							
								            regionMessage.after(row);
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          updateBlockWeights(table, select[0].value);
							 | 
						||
| 
								 | 
							
								          // Modify empty regions with added or removed fields.
							 | 
						||
| 
								 | 
							
								          checkEmptyRegions(table, tableDrag.rowObject);
							 | 
						||
| 
								 | 
							
								          // Update last placed block indication.
							 | 
						||
| 
								 | 
							
								          updateLastPlaced(table, tableDrag.rowObject);
							 | 
						||
| 
								 | 
							
								          // Show unsaved changes warning.
							 | 
						||
| 
								 | 
							
								          if (!tableDrag.changed) {
							 | 
						||
| 
								 | 
							
								            $(Drupal.theme('tableDragChangedWarning'))
							 | 
						||
| 
								 | 
							
								              .insertBefore(tableDrag.table)
							 | 
						||
| 
								 | 
							
								              .hide()
							 | 
						||
| 
								 | 
							
								              .fadeIn('slow');
							 | 
						||
| 
								 | 
							
								            tableDrag.changed = true;
							 | 
						||
| 
								 | 
							
								          }
							 | 
						||
| 
								 | 
							
								          // Remove focus from selectbox.
							 | 
						||
| 
								 | 
							
								          select.trigger('blur');
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    },
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								})(jQuery, window, Drupal, once);
							 |