diff --git a/htdocs/admin/tools/ui/class/documentation.class.php b/htdocs/admin/tools/ui/class/documentation.class.php index 788f5213076..8c797b2b2a4 100644 --- a/htdocs/admin/tools/ui/class/documentation.class.php +++ b/htdocs/admin/tools/ui/class/documentation.class.php @@ -87,7 +87,7 @@ class Documentation // Go back to Dolibarr $this->menu['BackToDolibarr'] = array( - 'url' => DOL_URL_ROOT, + 'url' => dol_buildpath('modulebuilder/index.php', 1), 'icon' => 'fas fa-arrow-left', 'submenu' => array(), ); @@ -201,6 +201,13 @@ class Documentation 'submenu' => array(), 'summary' => array(), ), + + 'FreezeTooltip' => array( + 'url' => dol_buildpath($this->baseUrl.'/content/freeze-tooltip.php', 1), + 'icon' => 'far fa-comment', + 'submenu' => array(), + 'summary' => array(), + ), ) ); @@ -239,14 +246,6 @@ class Documentation 'ExperimentalUxContributionTitle' => '#experimental-ux-contribution', ), ), - - 'ExperimentalUxFreezeTooltip' => array( - 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/freeze-tooltip/index.php', 1), - 'icon' => 'fas fa-flask', - 'submenu' => array(), - 'summary' => array(), - ), - 'ExperimentalUxInputAjaxFeedback' => array( 'url' => dol_buildpath($this->baseUrl.'/experimental/experiments/input-feedback/index.php', 1), 'icon' => 'fas fa-flask', diff --git a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/index.php b/htdocs/admin/tools/ui/content/freeze-tooltip.php similarity index 88% rename from htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/index.php rename to htdocs/admin/tools/ui/content/freeze-tooltip.php index 82e8e1ce96c..6b76ed8102c 100644 --- a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/index.php +++ b/htdocs/admin/tools/ui/content/freeze-tooltip.php @@ -18,7 +18,7 @@ */ // Load Dolibarr environment -require '../../../../../../main.inc.php'; +require '../../../../main.inc.php'; /** * @var DoliDB $db @@ -40,22 +40,20 @@ $langs->load('uxdocumentation'); // $documentation = new Documentation($db); -$group = 'ExperimentalUx'; - -$experimentAssetsPath = $documentation->baseUrl . '/experimental/experiments/freeze-tooltip/assets/'; +$group = 'Content'; $js = [ - $experimentAssetsPath . 'freeze-by-alt-keypress.js' +// now included in Dolibarr in htdocs/core/js/lib_tooltip-freeze-by-alt-keypress.js ]; $css = [ - $experimentAssetsPath . 'freeze-by-alt-keypress.css' +// now included in Dolibarr in htdocs/theme/eldy/tooltips.inc.css ]; // Output html head + body - Param is Title -$documentation->docHeader($langs->trans('ExperimentalUxFreezeTooltip', $group), $js, $css); +$documentation->docHeader($langs->trans('FreezeTooltip', $group), $js, $css); // Set view for menu and breadcrumb -$documentation->view = [$group, 'ExperimentalUxFreezeTooltip']; +$documentation->view = [$group, 'FreezeTooltip']; // Output sidebar $documentation->showSidebar(); ?> @@ -66,7 +64,7 @@ $documentation->showSidebar(); ?>
-

trans('ExperimentalUxFreezeTooltip'); ?>

+

trans('FreezeTooltip'); ?>

showSummary(); ?> @@ -142,4 +140,3 @@ $documentation->showSidebar(); ?> docFooter(); -?> diff --git a/htdocs/core/js/lib_foot.js.php b/htdocs/core/js/lib_foot.js.php index e1c952cf550..ba568a5d441 100644 --- a/htdocs/core/js/lib_foot.js.php +++ b/htdocs/core/js/lib_foot.js.php @@ -424,3 +424,4 @@ print ' // JS CODE USED by form::getSearchFilterToolInput include __DIR__ . '/lib_foot_search_tool.js'; +include __DIR__ . '/lib_tooltip-freeze-by-alt-keypress.js'; diff --git a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.js b/htdocs/core/js/lib_tooltip-freeze-by-alt-keypress.js similarity index 50% rename from htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.js rename to htdocs/core/js/lib_tooltip-freeze-by-alt-keypress.js index bbae1c8a9f7..d5f7fa5e81d 100644 --- a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.js +++ b/htdocs/core/js/lib_tooltip-freeze-by-alt-keypress.js @@ -1,13 +1,34 @@ /** - * TOOTLTIP keep open when alt key pressed - * note alt key must be pressed after tooltip is open (because tooltip can include tooltip...) + * Tooltip: keep tooltip open when Alt key is pressed + * Note: Alt key must be pressed AFTER the tooltip is opened + * because tooltips can contain links or other tooltips */ -$(function () { // .ready() callback, is only executed when the DOM is fully loaded +$(function () { // Execute when DOM is fully loaded + + let altPressed = false; + + /** + * Track Alt key state globally + * Tooltip events do not provide keyboard state (e.altKey is always undefined), + * so we must store the real keyboard state manually. + */ + document.addEventListener("keydown", e => { + if(e.key === "Alt") altPressed = true; + }); + + document.addEventListener("keyup", e => { + if(e.key === "Alt") altPressed = false; + }); let tooltipContainerTarget = '.ui-tooltip[role="tooltip"] .ui-tooltip-content'; + let noAjaxTooltipClass = '.classfortooltip, .classfortooltipdropdown'; + let tooltipClass = noAjaxTooltipClass + ', .classforajaxtooltip'; + /** + * Close all opened tooltips from scope + */ let closeOpenedTooltips = function (){ - $(".classfortooltip, .classfortooltipdropdown").each(function() { + $(tooltipClass).each(function() { if($( this ).data('ui-tooltip')){ $( this ).tooltip( "close" ); } @@ -32,34 +53,37 @@ $(function () { // .ready() callback, is only executed when the DOM is fully loa // }); /** - * On release key tooltip vanish + * Any key release closes all tooltips + * (Alt key release ends the "stay open" behavior) */ document.addEventListener("keyup", function(evt) { closeOpenedTooltips(); }); /** - * allow click on links in tooltip but remove [alt] + [click] Download behavior + * Allow clicking links inside tooltips without triggering + * the browser's default "Alt + click = download" behavior */ $(document).on('click', tooltipContainerTarget + ' a', function(evt) { evt.preventDefault(); // no download if(evt.ctrlKey || $(this).attr('target') == '_blank' ){ + // Open link in new tab let win = window.open(this.href, '_blank'); - if (win) { - //Browser has allowed it to be opened - win.focus(); - } + if (win) win.focus(); } else{ + // Standard navigation window.location.href = this.href; } }); /** - * Tooltip in a tooltip + * Support nested tooltips (tooltip inside another tooltip) + * Create sub-tooltips dynamically on first mouse enter + * but not for ajax tooltips yet */ - $(document).on('mouseenter', tooltipContainerTarget, function(evt){ + $(document).on('mouseenter', noAjaxTooltipClass, function(evt){ $(this).find('.classfortooltip').each(function() { if(!$( this ).data("tooltipset")){ console.log('ok'); @@ -76,8 +100,13 @@ $(function () { // .ready() callback, is only executed when the DOM is fully loa }); }); - $(".classfortooltip, .classfortooltipdropdown").on("tooltipclose", function (e) { - if (e.altKey && !$(this).data('opened-after-ctrl-pressed')) { + /** + * When tooltip closes: + * If Alt is pressed and tooltip wasn't opened while Alt was already pressed, + * reopen the tooltip and keep it open (Alt-hold mode) + */ + $(tooltipClass).on("tooltipclose", function (e) { + if (altPressed && !$(this).data('opened-after-alt-pressed')) { let delay = $(this).tooltip( "option", "show.delay"); $(this).tooltip( "option", "show.delay", 0); // save appear delay $(this).tooltip( "open" ); @@ -86,7 +115,11 @@ $(function () { // .ready() callback, is only executed when the DOM is fully loa } }); - $(".classfortooltip, .classfortooltipdropdown").on("tooltipopen", function (e) { - $(this).data('opened-after-ctrl-pressed', e.altKey); + /** + * When tooltip opens, store whether Alt key was pressed at that moment + * This prevents infinite reopen loops + */ + $(tooltipClass).on("tooltipopen", function (e) { + $(this).data('opened-after-alt-pressed', altPressed); }); }); diff --git a/htdocs/langs/en_US/uxdocumentation.lang b/htdocs/langs/en_US/uxdocumentation.lang index 985ec0ca31e..aed8f1310e6 100644 --- a/htdocs/langs/en_US/uxdocumentation.lang +++ b/htdocs/langs/en_US/uxdocumentation.lang @@ -14,6 +14,7 @@ DocExampleForPHPCode=Example of code to use in PHP # Components DocComponentsTitle=Components DocComponentsMainDescription=Components section description is under development +FreezeTooltip = Tooltip freeze # Badges DocBadgeTitle=Badges @@ -164,7 +165,6 @@ ExperimentalUxContributionTxt03 = In some cases, variants may be incompatible wi ExperimentalUxContributionEnd = This structure ensures a clear and modular organization of UX experiments, making testing and future integration more efficient. # Start experiements menu title -ExperimentalUxFreezeTooltip = Tooltip freeze ExperimentalUxInputAjaxFeedback = Input feedback # End experiements manu tyile diff --git a/htdocs/theme/eldy/global.inc.php b/htdocs/theme/eldy/global.inc.php index a3d5ee8d27e..9840a247f9c 100644 --- a/htdocs/theme/eldy/global.inc.php +++ b/htdocs/theme/eldy/global.inc.php @@ -1249,9 +1249,6 @@ td.wordbreak img, td.wordbreakimp img { .cursorpointer { cursor: pointer; } -.classfortooltiponclick .fa-question-circle { - cursor: pointer; -} .cursormove { cursor: move; } @@ -9306,6 +9303,7 @@ include dol_buildpath($path.'/theme/'.$theme.'/info-box.inc.php', 0); include dol_buildpath($path.'/theme/'.$theme.'/progress.inc.php', 0); include dol_buildpath($path.'/theme/'.$theme.'/timeline.inc.php', 0); include dol_buildpath($path.'/theme/'.$theme.'/search-input.inc.css', 0); +include dol_buildpath($path.'/theme/'.$theme.'/tooltips.inc.css', 0); // Add custom CSS if defined diff --git a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.css b/htdocs/theme/eldy/tooltips.inc.css similarity index 61% rename from htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.css rename to htdocs/theme/eldy/tooltips.inc.css index 262910d50f1..0577ade3f05 100644 --- a/htdocs/admin/tools/ui/experimental/experiments/freeze-tooltip/assets/freeze-by-alt-keypress.css +++ b/htdocs/theme/eldy/tooltips.inc.css @@ -1,3 +1,11 @@ +.classfortooltiponclick .fa-question-circle { + cursor: pointer; +} + +/** +Used for tooltip freeze with alt keypress +this allow first child tooltip +**/ div.ui-tooltip.mytooltip-hover-tooltip { z-index: 999999; border: solid 1px #BBBBBB; diff --git a/htdocs/theme/md/style.css.php b/htdocs/theme/md/style.css.php index ca4d4f7a9fa..b4372bbb83d 100644 --- a/htdocs/theme/md/style.css.php +++ b/htdocs/theme/md/style.css.php @@ -1406,9 +1406,6 @@ td.wordbreak img, td.wordbreakimp img { .cursorpointer { cursor: pointer; } -.classfortooltiponclick .fa-question-circle { - cursor: pointer; -} .cursormove { cursor: move; } @@ -9019,6 +9016,7 @@ include dol_buildpath($path.'/theme/'.$theme.'/info-box.inc.php', 0); include dol_buildpath($path.'/theme/'.$theme.'/progress.inc.php', 0); include dol_buildpath($path.'/theme/eldy/timeline.inc.php', 0); // actually md use same style as eldy theme include dol_buildpath($path.'/theme/'.$theme.'/search-input.inc.css', 0); // actually md use same style as eldy theme +include dol_buildpath($path.'/theme/'.$theme.'/tooltips.inc.css', 0); if (getDolGlobalString('THEME_CUSTOM_CSS')) { print getDolGlobalString('THEME_CUSTOM_CSS'); diff --git a/htdocs/theme/md/tooltips.inc.css b/htdocs/theme/md/tooltips.inc.css new file mode 100644 index 00000000000..0577ade3f05 --- /dev/null +++ b/htdocs/theme/md/tooltips.inc.css @@ -0,0 +1,19 @@ +.classfortooltiponclick .fa-question-circle { + cursor: pointer; +} + +/** +Used for tooltip freeze with alt keypress +this allow first child tooltip +**/ +div.ui-tooltip.mytooltip-hover-tooltip { + z-index: 999999; + border: solid 1px #BBBBBB; + padding: 10px 20px; + border-radius: 0; + box-shadow: 0 0 4px grey; + margin: 2px; + font-stretch: condensed; + line-height: 1.6em; + max-width: 550px; +}