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;
+}