From b17e1554918f503f4d9fb825e270e3bae0db269e Mon Sep 17 00:00:00 2001 From: Artem Dmitriiev <a.dmitriiev@1xinternet.de> Date: Fri, 20 Sep 2024 14:28:14 +0200 Subject: [PATCH] Issue #3440870: Keep action links in the viewport --- config/install/frontend_editing.settings.yml | 1 + config/schema/frontend_editing.schema.yml | 3 + css/frontend_editing.css | 9 +++ frontend_editing.install | 11 ++++ frontend_editing.libraries.yml | 2 + frontend_editing.module | 6 +- js/editing_actions.js | 64 ++++++++++---------- src/Form/UiSettingsForm.php | 8 +++ 8 files changed, 70 insertions(+), 34 deletions(-) diff --git a/config/install/frontend_editing.settings.yml b/config/install/frontend_editing.settings.yml index 222e85d..a9f4cd7 100644 --- a/config/install/frontend_editing.settings.yml +++ b/config/install/frontend_editing.settings.yml @@ -12,3 +12,4 @@ ui_toggle_settings: offset_bottom: 50 offset_right: 50 offset_left: '' +actions_in_viewport: false diff --git a/config/schema/frontend_editing.schema.yml b/config/schema/frontend_editing.schema.yml index f8985c2..446dcce 100644 --- a/config/schema/frontend_editing.schema.yml +++ b/config/schema/frontend_editing.schema.yml @@ -53,3 +53,6 @@ frontend_editing.settings: offset_right: type: string label: 'Right Offset' + actions_in_viewport: + type: boolean + label: 'Keep actions in viewport' diff --git a/css/frontend_editing.css b/css/frontend_editing.css index 4bd68ea..2c3ea5a 100644 --- a/css/frontend_editing.css +++ b/css/frontend_editing.css @@ -137,6 +137,15 @@ body:not(.frontend-editing--hidden) .frontend-editing:has(.add-paragraphs.hover- z-index: 2; } +.common-actions-container.place-bottom { + top: auto; + bottom: 10px; +} + +.common-actions-container.place-fixed { + position: fixed; +} + .title-edit-container, .icons-container { margin-left: 0.5rem; diff --git a/frontend_editing.install b/frontend_editing.install index b8bfb6b..721ad07 100644 --- a/frontend_editing.install +++ b/frontend_editing.install @@ -122,3 +122,14 @@ function frontend_editing_update_11007() { ]); $config->save(TRUE); } + +/** + * Set default 'actions in viewport' setting. + */ +function frontend_editing_update_11008() { + /** @var \Drupal\Core\Config\Config $config */ + $config = \Drupal::service('config.factory') + ->getEditable('frontend_editing.settings'); + $config->set('actions_in_viewport', FALSE); + $config->save(TRUE); +} diff --git a/frontend_editing.libraries.yml b/frontend_editing.libraries.yml index d1f2121..eca7059 100644 --- a/frontend_editing.libraries.yml +++ b/frontend_editing.libraries.yml @@ -58,3 +58,5 @@ editing_actions: version: 1.6.0 js: js/editing_actions.js: {} + dependencies: + - core/drupal.debounce diff --git a/frontend_editing.module b/frontend_editing.module index dea21ed..0f43d08 100644 --- a/frontend_editing.module +++ b/frontend_editing.module @@ -247,8 +247,10 @@ function frontend_editing_entity_view_alter(&$build, EntityInterface $entity, En // Library for updating content.and listen to the messages from frontend // editing iframe that is in the sidebar. $build['frontend_editing']['#attached']['library'][] = 'frontend_editing/update_content'; - // Library for keeping editing actions in viewport. - $build['frontend_editing']['#attached']['library'][] = 'frontend_editing/editing_actions'; + if ($config->get('actions_in_viewport')) { + // Library for keeping editing actions in viewport. + $build['frontend_editing']['#attached']['library'][] = 'frontend_editing/editing_actions'; + } // Add sidebar size configuration to drupal settings. $build['frontend_editing']['#attached']['drupalSettings']['frontend_editing'] = [ 'sidebar_width' => $config->get('sidebar_width') ?? 30, diff --git a/js/editing_actions.js b/js/editing_actions.js index 72d4feb..1f8baf9 100644 --- a/js/editing_actions.js +++ b/js/editing_actions.js @@ -2,38 +2,38 @@ * @file * Keeps editing actions in viewport. */ -window.addEventListener('load', () => { - let timer - window.addEventListener('scroll', () => { - clearTimeout(timer); - const clientHeight = document.documentElement.clientHeight - timer = setTimeout(() => { - document.querySelectorAll(".frontend-editing").forEach((element) => { - const {top, bottom, left } = element.getBoundingClientRect() - const actions = element.querySelector('.common-actions-container') +(function (Drupal) { - // Reset - // element.style.backgroundColor = 'transparent' - actions.style.position = 'absolute' - actions.style.top = '10px' - actions.style.bottom = 'auto' - actions.style.left = '0' + const floatingLinks = function () { + const clientHeight = document.documentElement.clientHeight; + document.querySelectorAll(".frontend-editing").forEach((element) => { + const { top, bottom, left } = element.getBoundingClientRect() + const actions = element.querySelector('.common-actions-container') - // Top intersecting sections - if (top < 0 && bottom > 0 && bottom < clientHeight) { - // element.style.backgroundColor = 'pink' - actions.style.top = 'auto' - actions.style.bottom = '10px' - } + // Reset + actions.removeAttribute('style'); + actions.classList.remove('place-bottom'); + actions.classList.remove('place-fixed'); - // Top + bottom intersecting sections - if (top < 0 && bottom > clientHeight) { - // element.style.backgroundColor = 'yellow' - actions.style.position = 'fixed' - actions.style.top = clientHeight - actions.offsetHeight - 10 + 'px' - actions.style.left = left + 'px' - } - }) - }, 1000) // execute one second after user stops scrolling - }) -}) + // Top intersecting sections + if (top < 0 && bottom > 0 && bottom < clientHeight) { + actions.classList.add('place-bottom'); + } + + // Top + bottom intersecting sections + if (top < 0 && bottom > clientHeight) { + actions.classList.add('place-fixed'); + actions.style.position = 'fixed' + actions.style.top = clientHeight - actions.offsetHeight - 10 + 'px' + actions.style.left = left + 'px' + } + }) + } + + Drupal.behaviors.editingActionsPosition = { + attach(context, settings) { + window.addEventListener('scroll', Drupal.debounce(floatingLinks, 250, false)); + } + } + +})(Drupal); diff --git a/src/Form/UiSettingsForm.php b/src/Form/UiSettingsForm.php index baf1cb6..11090c5 100644 --- a/src/Form/UiSettingsForm.php +++ b/src/Form/UiSettingsForm.php @@ -122,6 +122,13 @@ class UiSettingsForm extends ConfigFormBase { '#description' => $this->t('Choose the primary color for the frontend editing interface. Be sure to choose a color that has enough contrast with the background color of your site.'), ]; + $form['actions_in_viewport'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Keeps action links in viewport'), + '#description' => $this->t('If element to edit is too long, this helps to keep the actions link visible.'), + '#default_value' => $config->get('actions_in_viewport'), + ]; + // Enable on/off toggle in UI. $form['ui_toggle'] = [ '#type' => 'checkbox', @@ -188,6 +195,7 @@ class UiSettingsForm extends ConfigFormBase { $config->set('hover_highlight', (bool) $form_state->getValue('hover_highlight')); $config->set('primary_color', $form_state->getValue('primary_color')); $config->set('ui_toggle', (bool) $form_state->getValue('ui_toggle')); + $config->set('actions_in_viewport', (bool) $form_state->getValue('actions_in_viewport')); $config->set('ui_toggle_settings', $form_state->getValue('ui_toggle_settings')); $exclude_fields = $form_state->getValue('exclude_fields'); $exclude_fields = explode("\r\n", $exclude_fields); -- GitLab