diff --git a/js/builder.es6.js b/js/builder.es6.js index 4d003ef1612ff221dc865253acaf645cc609155a..c5fa474434570fb4f4042a0d4995fbbf7beb0665 100644 --- a/js/builder.es6.js +++ b/js/builder.es6.js @@ -5,17 +5,15 @@ * Attaches UI elements to $container. * @param {jQuery} $container * The container. - * @param {string} id - * The container id. * @param {Object} settings * The settings object. */ function attachUiElements($container, settings) { - const id = $container[0].id; + const { id } = $container[0]; const lpbBuilderSettings = settings.lpBuilder || {}; const uiElements = lpbBuilderSettings.uiElements || {}; const containerUiElements = uiElements[id] || []; - Object.entries(containerUiElements).forEach(([key, uiElement]) => { + Object.values(containerUiElements).forEach((uiElement) => { const { element, method } = uiElement; $container[method]($(element).addClass('js-lpb-ui')); }); @@ -43,9 +41,10 @@ } $dialogs.each((i, dialog) => { const bounding = dialog.getBoundingClientRect(); - const viewPortHeight = window.innerHeight || document.documentElement.clientHeight; + const viewPortHeight = + window.innerHeight || document.documentElement.clientHeight; if (bounding.bottom > viewPortHeight) { - const $dialog = $('.ui-dialog-content', dialog); + const $dialog = $('.ui-dialog-content', dialog); const pos = $dialog.dialog('option', 'position'); $dialog.dialog('option', 'position', pos); } @@ -79,11 +78,12 @@ }, error: () => { // Fail silently to prevent console errors. - } - }) - .execute(); + }, + }).execute(); } + const reorderComponents = debounce(doReorderComponents); + /** * Returns a list of errors for the attempted move, or an empty array if there are no errors. * @param {Element} settings The builder settings. @@ -100,6 +100,7 @@ ) .filter((errors) => errors !== false && errors !== undefined); } + /** * Updates move buttons to reflect current state. * @param {jQuery} $element The builder element. @@ -112,6 +113,7 @@ ) .attr('tabindex', '-1'); } + /** * Hides the add content button in regions that contain components. * @param {jQuery} $element The builder element. @@ -126,6 +128,7 @@ } }); } + /** * Updates the UI based on currently state. * @param {jQuery} $element The builder element. @@ -135,6 +138,7 @@ updateMoveButtons($element); hideEmptyRegionButtons($element); } + /** * Moves a component up or down within a simple list of components. * @param {jQuery} $moveItem The item to move. @@ -180,6 +184,7 @@ $('html, body').animate({ scrollTop: destScroll }); } } + /** * Moves the focused component up or down the DOM to the next valid position * when an arrow key is pressed. Unlike move(), nav()can fully navigate @@ -238,6 +243,7 @@ .closest(`[${idAttr}]`) .trigger('lpb-component:move', [$item.attr('data-uuid')]); } + function startNav($item) { const $msg = $( `<div id="lpb-navigating-msg" class="lpb-tooltiptext lpb-tooltiptext--visible js-lpb-tooltiptext">${Drupal.t( @@ -255,6 +261,7 @@ .prepend($msg); $item.before('<div class="lpb-navigating-placeholder"></div>'); } + function stopNav($item) { $item .removeClass('is-navigating') @@ -267,12 +274,14 @@ .find('.lpb-navigating-placeholder') .remove(); } + function cancelNav($item) { const $builder = $item.closest(`[${idAttr}]`); $builder.find('.lpb-navigating-placeholder').replaceWith($item); updateUi($builder); stopNav($item); } + /** * Prevents user from navigating away and accidentally loosing changes. * @param {jQuery} $element The jQuery layout paragraphs builder object. @@ -300,6 +309,7 @@ $element.removeClass('is_changed'); }); } + /** * Attaches event listeners/handlers for builder ui. * @param {jQuery} $element The layout paragraphs builder object. @@ -349,6 +359,7 @@ } }); } + function initDragAndDrop($element, settings) { const drake = dragula( $element @@ -400,11 +411,12 @@ }); return drake; } + // An array of move error callback functions. Drupal._lpbMoveErrors = []; /** * Registers a move validation function. - * @param {Funciton} f The validator function. + * @param {Function} f The validator function. */ Drupal.registerLpbMoveError = (f) => { Drupal._lpbMoveErrors.push(f); @@ -440,13 +452,58 @@ const $element = $(`[data-lpb-id="${layoutId}"]`); $element.trigger(`lpb-${eventName}`, [componentUuid]); }; + + /* + * Moves the main form action buttons into the jQuery modal button pane. + * @param {jQuery} context + * The context to search for dialog buttons. + * @return {void} + */ + function updateDialogButtons(context) { + // Determine if this context is from within dialog content. + const $lpDialog = $(context).closest('.ui-dialog-content'); + + if (!$lpDialog) { + return; + } + + const buttons = []; + const $buttons = $lpDialog.find('input[type=submit], a.button'); + + if ($buttons.length === 0) { + return; + } + + $buttons.each((_i, el) => { + const $originalButton = $(el).css({ display: 'none' }); + buttons.push({ + text: $originalButton.html() || $originalButton.attr('value'), + class: $originalButton.attr('class'), + click(e) { + // If the original button is an anchor tag, triggering the "click" + // event will not simulate a click. Use the click method instead. + if ($originalButton.is('a')) { + $originalButton[0].click(); + } else { + $originalButton + .trigger('mousedown') + .trigger('mouseup') + .trigger('click'); + e.preventDefault(); + } + }, + }); + }); + + $lpDialog.dialog('option', 'buttons', buttons); + } + Drupal.behaviors.layoutParagraphsBuilder = { attach: function attach(context, settings) { // Add UI elements to the builder, each component, and each region. - $(once('lpb-ui-elements', '[data-has-js-ui-element]')) - .each((i, el) => { - attachUiElements($(el), settings); - }); + $(once('lpb-ui-elements', '[data-has-js-ui-element]')).each((i, el) => { + attachUiElements($(el), settings); + }); // Listen to relevant events and update UI. const events = [ 'lpb-builder:init.lpb', @@ -456,11 +513,10 @@ 'lpb-component:drop.lpb', 'lpb-component:delete.lpb', ].join(' '); - $(once('lpb-events', '[data-lpb-id]')) - .on(events, (e) => { - const $element = $(e.currentTarget); - updateUi($element); - }); + $(once('lpb-events', '[data-lpb-id]')).on(events, (e) => { + const $element = $(e.currentTarget); + updateUi($element); + }); // Initialize the editor drag and drop ui. $(`.has-components[${idAttr}]`).each((index, element) => { const $element = $(once('lpb-enabled', element)); @@ -481,6 +537,7 @@ drake.containers.push(c); }); }); + updateDialogButtons(context); }, }; // Move the main form action buttons into the jQuery modal button pane. @@ -492,39 +549,10 @@ // @see https://www.drupal.org/project/layout_paragraphs/issues/3216981 $(window).on('dialog:aftercreate', (event, dialog, $dialog) => { if ($dialog.attr('id').indexOf('lpb-dialog-') === 0) { - // If buttons have already been added to the buttonpane, do not continue. - if ($dialog.dialog('option', 'buttons').length > 0) { - return; - } - const buttons = []; - const $buttons = $dialog.find( - '.layout-paragraphs-component-form > .form-actions input[type=submit], .layout-paragraphs-component-form > .form-actions a.button', - ); - $buttons.each((_i, el) => { - const $originalButton = $(el).css({ display: 'none' }); - buttons.push({ - text: $originalButton.html() || $originalButton.attr('value'), - class: $originalButton.attr('class'), - click(e) { - // If the original button is an anchor tag, triggering the "click" - // event will not simulate a click. Use the click method instead. - if ($originalButton.is('a')) { - $originalButton[0].click(); - } else { - $originalButton - .trigger('mousedown') - .trigger('mouseup') - .trigger('click'); - e.preventDefault(); - } - }, - }); - }); - if (buttons.length) { - $dialog.dialog('option', 'buttons', buttons); - } + updateDialogButtons($dialog); } }); + // Repositions open dialogs. // @see https://www.drupal.org/project/layout_paragraphs/issues/3252978 // @see https://stackoverflow.com/questions/5456298/refresh-jquery-ui-dialog-position @@ -532,7 +560,10 @@ $(window).on('dialog:aftercreate', (event, dialog, $dialog) => { if ($dialog[0].id.indexOf('lpb-dialog-') === 0) { clearInterval(lpDialogInterval); - lpDialogInterval = setInterval(repositionDialog.bind(null, lpDialogInterval), 500); + lpDialogInterval = setInterval( + repositionDialog.bind(null, lpDialogInterval), + 500, + ); } }); })(jQuery, Drupal, Drupal.debounce, dragula, once); diff --git a/js/builder.js b/js/builder.js index 8f864134574d5d6a7c96383ddd4feaef91f00d27..ae47e6b343ff7e3c06bd4a03883ca3d136d77cfb 100644 --- a/js/builder.js +++ b/js/builder.js @@ -4,12 +4,8 @@ * https://www.drupal.org/node/2815083 * @preserve **/ -function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } -function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } -function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } -function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } -function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0) { ; } } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } } -function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } +"use strict"; + (function ($, Drupal, debounce, dragula, once) { var idAttr = 'data-lpb-id'; function attachUiElements($container, settings) { @@ -17,10 +13,7 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } var lpbBuilderSettings = settings.lpBuilder || {}; var uiElements = lpbBuilderSettings.uiElements || {}; var containerUiElements = uiElements[id] || []; - Object.entries(containerUiElements).forEach(function (_ref) { - var _ref2 = _slicedToArray(_ref, 2), - key = _ref2[0], - uiElement = _ref2[1]; + Object.values(containerUiElements).forEach(function (uiElement) { var element = uiElement.element, method = uiElement.method; $container[method]($(element).addClass('js-lpb-ui')); @@ -301,6 +294,35 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } var $element = $("[data-lpb-id=\"".concat(layoutId, "\"]")); $element.trigger("lpb-".concat(eventName), [componentUuid]); }; + function updateDialogButtons(context) { + var $lpDialog = $(context).closest('.ui-dialog-content'); + if (!$lpDialog) { + return; + } + var buttons = []; + var $buttons = $lpDialog.find('input[type=submit], a.button'); + if ($buttons.length === 0) { + return; + } + $buttons.each(function (_i, el) { + var $originalButton = $(el).css({ + display: 'none' + }); + buttons.push({ + text: $originalButton.html() || $originalButton.attr('value'), + class: $originalButton.attr('class'), + click: function click(e) { + if ($originalButton.is('a')) { + $originalButton[0].click(); + } else { + $originalButton.trigger('mousedown').trigger('mouseup').trigger('click'); + e.preventDefault(); + } + } + }); + }); + $lpDialog.dialog('option', 'buttons', buttons); + } Drupal.behaviors.layoutParagraphsBuilder = { attach: function attach(context, settings) { $(once('lpb-ui-elements', '[data-has-js-ui-element]')).each(function (i, el) { @@ -325,35 +347,12 @@ function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } drake.containers.push(c); }); }); + updateDialogButtons(context); } }; $(window).on('dialog:aftercreate', function (event, dialog, $dialog) { if ($dialog.attr('id').indexOf('lpb-dialog-') === 0) { - if ($dialog.dialog('option', 'buttons').length > 0) { - return; - } - var buttons = []; - var $buttons = $dialog.find('.layout-paragraphs-component-form > .form-actions input[type=submit], .layout-paragraphs-component-form > .form-actions a.button'); - $buttons.each(function (_i, el) { - var $originalButton = $(el).css({ - display: 'none' - }); - buttons.push({ - text: $originalButton.html() || $originalButton.attr('value'), - class: $originalButton.attr('class'), - click: function click(e) { - if ($originalButton.is('a')) { - $originalButton[0].click(); - } else { - $originalButton.trigger('mousedown').trigger('mouseup').trigger('click'); - e.preventDefault(); - } - } - }); - }); - if (buttons.length) { - $dialog.dialog('option', 'buttons', buttons); - } + updateDialogButtons($dialog); } }); var lpDialogInterval;