diff --git a/config/install/frontend_editing.settings.yml b/config/install/frontend_editing.settings.yml index 222e85d1958ca8303dadd56c160da75c98d1cff8..a9f4cd7f140c91b5d1c2738caf6962236e0f2888 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 f8985c29815f2088cbb20d9eef7fc5e92baca3f3..446dcceee75a3a554f371a97e8b5c11128171fa8 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 4bd68eab30b950959bb65137d5fc0d5e89b7341b..2c3ea5a48e9ec8791c0aef6eb88c015a1bca8554 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 b8bfb6b6e54d4145e0c51643ba8e76f96394e3a1..721ad0794f4900965d3605c875c9bd269b67a207 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 d1f212100c3d0ecc06a09fa5654d4179e45c89d3..eca705986ed7fae16354fcaddbc3b5bf89dc676c 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 dea21edf0177d880d3c099c45a79cd25e74d6c1c..0f43d08470da658e03974afa813eeb692136e7e5 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 72d4feb8a96434e7213899353feabd0fdaffc23d..1f8baf9f31a151da0e4da6319bca137c3dc06526 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 baf1cb6ed05b50e8ef1a837b2f024375633c8bbb..11090c5a1ec3f266923ef6a1ef24418d83a19f2a 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);