2019-02-07 10:30:04 +00:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* Attaches the behaviors for the Layout Builder module.
|
|
|
|
*/
|
|
|
|
|
|
|
|
(($, Drupal) => {
|
|
|
|
const { ajax, behaviors, debounce, announce, formatPlural } = Drupal;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Boolean that tracks if block listing is currently being filtered. Declared
|
|
|
|
* outside of behaviors so value is retained on rebuild.
|
|
|
|
*/
|
|
|
|
let layoutBuilderBlocksFiltered = false;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides the ability to filter the block listing in Add Block dialog.
|
|
|
|
*
|
|
|
|
* @type {Drupal~behavior}
|
|
|
|
*
|
|
|
|
* @prop {Drupal~behaviorAttach} attach
|
|
|
|
* Attach block filtering behavior to Add Block dialog.
|
|
|
|
*/
|
|
|
|
behaviors.layoutBuilderBlockFilter = {
|
|
|
|
attach(context) {
|
|
|
|
const $categories = $('.js-layout-builder-categories', context);
|
|
|
|
const $filterLinks = $categories.find('.js-layout-builder-block-link');
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Filters the block list.
|
|
|
|
*
|
|
|
|
* @param {jQuery.Event} e
|
|
|
|
* The jQuery event for the keyup event that triggered the filter.
|
|
|
|
*/
|
|
|
|
const filterBlockList = e => {
|
|
|
|
const query = $(e.target)
|
|
|
|
.val()
|
|
|
|
.toLowerCase();
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Shows or hides the block entry based on the query.
|
|
|
|
*
|
|
|
|
* @param {number} index
|
|
|
|
* The index in the loop, as provided by `jQuery.each`
|
|
|
|
* @param {HTMLElement} link
|
|
|
|
* The link to add the block.
|
|
|
|
*/
|
|
|
|
const toggleBlockEntry = (index, link) => {
|
|
|
|
const $link = $(link);
|
|
|
|
const textMatch =
|
|
|
|
$link
|
|
|
|
.text()
|
|
|
|
.toLowerCase()
|
|
|
|
.indexOf(query) !== -1;
|
|
|
|
$link.toggle(textMatch);
|
|
|
|
};
|
|
|
|
|
|
|
|
// Filter if the length of the query is at least 2 characters.
|
|
|
|
if (query.length >= 2) {
|
|
|
|
// Attribute to note which categories are closed before opening all.
|
|
|
|
$categories
|
|
|
|
.find('.js-layout-builder-category:not([open])')
|
|
|
|
.attr('remember-closed', '');
|
|
|
|
|
|
|
|
// Open all categories so every block is available to filtering.
|
|
|
|
$categories.find('.js-layout-builder-category').attr('open', '');
|
|
|
|
// Toggle visibility of links based on query.
|
|
|
|
$filterLinks.each(toggleBlockEntry);
|
|
|
|
|
|
|
|
// Only display categories containing visible links.
|
|
|
|
$categories
|
|
|
|
.find(
|
|
|
|
'.js-layout-builder-category:not(:has(.js-layout-builder-block-link:visible))',
|
|
|
|
)
|
|
|
|
.hide();
|
|
|
|
|
|
|
|
announce(
|
|
|
|
formatPlural(
|
|
|
|
$categories.find('.js-layout-builder-block-link:visible').length,
|
|
|
|
'1 block is available in the modified list.',
|
|
|
|
'@count blocks are available in the modified list.',
|
|
|
|
),
|
|
|
|
);
|
|
|
|
layoutBuilderBlocksFiltered = true;
|
|
|
|
} else if (layoutBuilderBlocksFiltered) {
|
|
|
|
layoutBuilderBlocksFiltered = false;
|
|
|
|
// Remove "open" attr from categories that were closed pre-filtering.
|
|
|
|
$categories
|
|
|
|
.find('.js-layout-builder-category[remember-closed]')
|
|
|
|
.removeAttr('open')
|
|
|
|
.removeAttr('remember-closed');
|
|
|
|
$categories.find('.js-layout-builder-category').show();
|
|
|
|
$filterLinks.show();
|
|
|
|
announce(Drupal.t('All available blocks are listed.'));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
$('input.js-layout-builder-filter', context)
|
|
|
|
.once('block-filter-text')
|
|
|
|
.on('keyup', debounce(filterBlockList, 200));
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Provides the ability to drag blocks to new positions in the layout.
|
|
|
|
*
|
|
|
|
* @type {Drupal~behavior}
|
|
|
|
*
|
|
|
|
* @prop {Drupal~behaviorAttach} attach
|
|
|
|
* Attach block drag behavior to the Layout Builder UI.
|
|
|
|
*/
|
|
|
|
behaviors.layoutBuilderBlockDrag = {
|
Issue #2905922 by tim.plunkett, tedbow, xjm, EclipseGc, webchick, vijaycs85, larowlan, andrewmacpherson, droplet, Bojhan, mgifford, drpal, phenaproxima, DyanneNova, japerry: Implementation issue for Layout Builder
2017-11-17 19:01:26 +00:00
|
|
|
attach(context) {
|
2018-08-09 15:49:18 +00:00
|
|
|
$(context)
|
|
|
|
.find('.layout-builder--layout__region')
|
|
|
|
.sortable({
|
|
|
|
items: '> .draggable',
|
|
|
|
connectWith: '.layout-builder--layout__region',
|
|
|
|
placeholder: 'ui-state-drop',
|
Issue #2905922 by tim.plunkett, tedbow, xjm, EclipseGc, webchick, vijaycs85, larowlan, andrewmacpherson, droplet, Bojhan, mgifford, drpal, phenaproxima, DyanneNova, japerry: Implementation issue for Layout Builder
2017-11-17 19:01:26 +00:00
|
|
|
|
2018-08-09 15:49:18 +00:00
|
|
|
/**
|
|
|
|
* Updates the layout with the new position of the block.
|
|
|
|
*
|
|
|
|
* @param {jQuery.Event} event
|
|
|
|
* The jQuery Event object.
|
|
|
|
* @param {Object} ui
|
|
|
|
* An object containing information about the item being sorted.
|
|
|
|
*/
|
|
|
|
update(event, ui) {
|
|
|
|
// Check if the region from the event and region for the item match.
|
|
|
|
const itemRegion = ui.item.closest(
|
|
|
|
'.layout-builder--layout__region',
|
|
|
|
);
|
|
|
|
if (event.target === itemRegion[0]) {
|
|
|
|
// Find the destination delta.
|
|
|
|
const deltaTo = ui.item
|
|
|
|
.closest('[data-layout-delta]')
|
|
|
|
.data('layout-delta');
|
|
|
|
// If the block didn't leave the original delta use the destination.
|
|
|
|
const deltaFrom = ui.sender
|
|
|
|
? ui.sender.closest('[data-layout-delta]').data('layout-delta')
|
|
|
|
: deltaTo;
|
|
|
|
ajax({
|
|
|
|
url: [
|
|
|
|
ui.item
|
|
|
|
.closest('[data-layout-update-url]')
|
|
|
|
.data('layout-update-url'),
|
|
|
|
deltaFrom,
|
|
|
|
deltaTo,
|
|
|
|
itemRegion.data('region'),
|
|
|
|
ui.item.data('layout-block-uuid'),
|
|
|
|
ui.item
|
|
|
|
.prev('[data-layout-block-uuid]')
|
|
|
|
.data('layout-block-uuid'),
|
|
|
|
]
|
|
|
|
.filter(element => element !== undefined)
|
|
|
|
.join('/'),
|
|
|
|
}).execute();
|
|
|
|
}
|
|
|
|
},
|
|
|
|
});
|
Issue #2905922 by tim.plunkett, tedbow, xjm, EclipseGc, webchick, vijaycs85, larowlan, andrewmacpherson, droplet, Bojhan, mgifford, drpal, phenaproxima, DyanneNova, japerry: Implementation issue for Layout Builder
2017-11-17 19:01:26 +00:00
|
|
|
},
|
|
|
|
};
|
2019-02-21 17:22:25 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Disables interactive elements in previewed blocks.
|
|
|
|
*
|
|
|
|
* @type {Drupal~behavior}
|
|
|
|
*
|
|
|
|
* @prop {Drupal~behaviorAttach} attach
|
|
|
|
* Attach disabling interactive elements behavior to the Layout Builder UI.
|
|
|
|
*/
|
|
|
|
behaviors.layoutBuilderDisableInteractiveElements = {
|
|
|
|
attach() {
|
|
|
|
// Disable interactive elements inside preview blocks.
|
|
|
|
const $blocks = $('#layout-builder [data-layout-block-uuid]');
|
|
|
|
$blocks.find('input, textarea, select').prop('disabled', true);
|
|
|
|
$blocks.find('a').on('click mouseup touchstart', e => {
|
|
|
|
e.preventDefault();
|
|
|
|
e.stopPropagation();
|
|
|
|
});
|
|
|
|
|
|
|
|
/*
|
|
|
|
* In preview blocks, remove from the tabbing order all input elements
|
|
|
|
* and elements specifically assigned a tab index, other than those
|
|
|
|
* related to contextual links.
|
|
|
|
*/
|
|
|
|
$blocks
|
|
|
|
.find(
|
|
|
|
'button, [href], input, select, textarea, iframe, [tabindex]:not([tabindex="-1"]):not(.tabbable)',
|
|
|
|
)
|
|
|
|
.not(
|
|
|
|
(index, element) =>
|
|
|
|
$(element).closest('[data-contextual-id]').length > 0,
|
|
|
|
)
|
|
|
|
.attr('tabindex', -1);
|
|
|
|
},
|
|
|
|
};
|
Issue #2905922 by tim.plunkett, tedbow, xjm, EclipseGc, webchick, vijaycs85, larowlan, andrewmacpherson, droplet, Bojhan, mgifford, drpal, phenaproxima, DyanneNova, japerry: Implementation issue for Layout Builder
2017-11-17 19:01:26 +00:00
|
|
|
})(jQuery, Drupal);
|