From 2e60baeaa9f135f358d6333487696ba22771a2e1 Mon Sep 17 00:00:00 2001 From: Andreas Gohr Date: Thu, 20 Apr 2023 11:51:49 +0200 Subject: Avoid flicker when highlighting a section Previously, elements were wrapped in a div on hover and unwrapped when the mouse was moved again. This generally worked okay, but led to problems where the wrapped section contained elements with their own rendering context (video, object, iframe, ...). The wrapping caused rerendering of these elements resulting in flicker and layoutshift: splitbrain/dokuwiki-plugin-vshare#13 cosmocode/dokuwiki-plugin-diagrams#4 This patch changes the higlighting mechanism to always wrap *all* sections in a div and only toggle classes on hover. Class names have been chosen to be backwardscompatible, so this should continue to work as before in all templates. --- lib/scripts/page.js | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) (limited to 'lib/scripts/page.js') diff --git a/lib/scripts/page.js b/lib/scripts/page.js index 77d644a38..baacee238 100644 --- a/lib/scripts/page.js +++ b/lib/scripts/page.js @@ -21,29 +21,37 @@ dw_page = { */ sectionHighlight: function() { jQuery('form.btn_secedit') - .on('mouseover', function(){ - var $tgt = jQuery(this).parent(), - nr = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2], - $highlight = jQuery(), // holder for elements in the section to be highlighted - $highlightWrap = jQuery('
'); // section highlight wrapper + /* + * wrap the editable section in a div + */ + .each(function () { + let $tgt = jQuery(this).parent(); + const nr = $tgt.attr('class').match(/(\s+|^)editbutton_(\d+)(\s+|$)/)[2]; + let $highlight = jQuery(); // holder for elements in the section to be highlighted + const $highlightWrap = jQuery('
'); + + // the edit button should be part of the highlight + $highlight = $highlight.add($tgt); // Walk the dom tree in reverse to find the sibling which is or contains the section edit marker - while($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) { + while ($tgt.length > 0 && !($tgt.hasClass('sectionedit' + nr) || $tgt.find('.sectionedit' + nr).length)) { $tgt = $tgt.prev(); $highlight = $highlight.add($tgt); } - // insert the section highlight wrapper before the last element added to $highlight - $highlight.filter(':last').before($highlightWrap); - // and move the elements to be highlighted inside the section highlight wrapper - $highlight.detach().appendTo($highlightWrap); + // wrap the elements to be highlighted in the section highlight wrapper + $highlight.wrapAll($highlightWrap); }) - .on('mouseout', function(){ - // find the section highlight wrapper... - var $highlightWrap = jQuery('.section_highlight'); - // ...move its children in front of it (as siblings)... - $highlightWrap.before($highlightWrap.children().detach()); - // ...and remove the section highlight wrapper - $highlightWrap.detach(); + /* + * highlight the section + */ + .on('mouseover', function () { + jQuery(this).parents('.section_highlight_wrapper').addClass('section_highlight'); + }) + /* + * remove highlight + */ + .on('mouseout', function () { + jQuery(this).parents('.section_highlight_wrapper').removeClass('section_highlight'); }); }, -- cgit v1.2.3