N°3379 - Introduce more modern tooltip lib. in the backoffice

- Allow usage of quotes, especially in attributes description
- Allow line breaks, especially in attributes description
- Allow better positioning (automatic) when close to the screen limits
- Allow HTML (careful about XSS), content is sanitized by default
This commit is contained in:
Molkobain
2020-10-16 11:10:51 +02:00
parent 9a47e3cf74
commit 6edb308480
3 changed files with 70 additions and 6 deletions

View File

@@ -882,8 +882,14 @@ EOF
$aArgs).'';
}
$aFieldsMap[$sAttCode] = $sInputId;
// Attribute description
$sDescription = $oAttDef->GetDescription();
$sDescriptionForHTMLTag = utils::HtmlEntities($sDescription);
$sDescriptionHTMLTag = (empty($sDescriptionForHTMLTag)) ? '' : 'class="ibo-has-description" data-tooltip-content="'.$sDescriptionForHTMLTag.'"';
$val = array(
'label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>',
'label' => '<span '.$sDescriptionHTMLTag.' >'.$oAttDef->GetLabel().'</span>',
'value' => $sHTMLValue,
'comments' => $sComments,
'infos' => $sInfos,
@@ -892,8 +898,13 @@ EOF
}
else
{
// Attribute description
$sDescription = $oAttDef->GetDescription();
$sDescriptionForHTMLTag = utils::HtmlEntities($sDescription);
$sDescriptionHTMLTag = (empty($sDescriptionForHTMLTag)) ? '' : 'class="ibo-has-description" data-tooltip-content="'.$sDescriptionForHTMLTag.'"';
$val = array(
'label' => '<span title="'.$oAttDef->GetDescription().'">'.$oAttDef->GetLabel().'</span>',
'label' => '<span '.$sDescriptionHTMLTag.' >'.$oAttDef->GetLabel().'</span>',
'value' => "<span id=\"field_{$sInputId}\">".$this->GetAsHTML($sAttCode)."</span>",
'comments' => $sComments,
'infos' => $sInfos,
@@ -3240,9 +3251,14 @@ EOF
$sDisplayValue = $this->GetAsHTML($sAttCode);
}
}
// Attribute description
$sDescription = $oAttDef->GetDescription();
$sDescriptionForHTMLTag = utils::HtmlEntities($sDescription);
$sDescriptionHTMLTag = (empty($sDescriptionForHTMLTag)) ? '' : 'class="ibo-has-description" data-tooltip-content="'.$sDescriptionForHTMLTag.'"';
$retVal = array(
'label' => '<span title="'.MetaModel::GetDescription($sClass,
$sAttCode).'">'.MetaModel::GetLabel($sClass, $sAttCode).'</span>',
'label' => '<span '.$sDescriptionHTMLTag.' >'.MetaModel::GetLabel($sClass, $sAttCode).'</span>',
'value' => $sDisplayValue,
);
}

View File

@@ -6,6 +6,10 @@
$ibo-field--sibling-spacing: 16px !default;
$ibo-field--value--color: $ibo-color-grey-700 !default;
$ibo-field--label--description--content: "?" !default;
$ibo-field--label--description--padding-left: 2px !default;
$ibo-field--label--description--color: $ibo-color-grey-700 !default;
.ibo-field {
@extend %ibo-font-ral-nor-150;
@@ -37,6 +41,18 @@ $ibo-field--value--color: $ibo-color-grey-700 !default;
max-width: 145px;
width: 30%;
padding-right: 10px;
> .ibo-has-description {
&::after {
content: $ibo-field--label--description--content;
padding-left: $ibo-field--label--description--padding-left;
vertical-align: top;
cursor: pointer;
color: $ibo-field--label--description--color;
@extend %ibo-font-ral-bol-100;
}
}
}
.ibo-field--value {

View File

@@ -68,14 +68,46 @@ const CombodoBackofficeToolbox = {
// Instanciate tooltips (abstraction layer between iTop markup and tooltip plugin to ease its replacement in the future)
/**
* Instanciate a tooltip on oElem from its data attributes
*
* Note: Content SHOULD be HTML entity encoded to avoid markup breaks (eg. when using a double quote in a sentence)
*
* @param oElem
* @constructor
*/
InitTooltipFromMarkup: function(oElem)
{
const oOptions = {};
const oOptions = {
allowHTML: true, // Always true so line breaks can work. Don't worry content will be sanitized.
};
// Content must be reworked before getting into the tooltip
// - Should we enable HTML content or keep text as is
const bEnableHTML = oElem.attr('data-tooltip-html-enabled') === 'true';
// - Content should be sanitized unless the developer says otherwise
// Note: Condition is inversed on purpose. When the developer is instanciating a tooltip,
// we want him/her to explicitly declare that he/she wants the sanitizer to be skipped.
// Whereas in this code, it's easier to follow the logic with the variable oriented this way.
const bSanitizeContent = oElem.attr('data-tooltip-sanitizer-skipped') !== 'true';
// - Sanitize content and make sure line breaks are kept
const oTmpContentElem = $('<div />').html(oElem.attr('data-tooltip-content'));
let sContent = '';
if(bEnableHTML)
{
sContent = oTmpContentElem.html();
if(bSanitizeContent)
{
sContent = sContent.replace(/<script/g, '&lt;script WARNING: scripts are not allowed in tooltips');
}
}
else
{
sContent = oTmpContentElem.text();
sContent = sContent.replace(/(\r\n|\n\r|\r|\n)/g, '<br/>');
}
oOptions['content'] = sContent;
oOptions['content'] = oElem.attr('data-tooltip-content');
oOptions['placement'] = oElem.attr('data-tooltip-placement') ?? 'top';
oOptions['trigger'] = oElem.attr('data-tooltip-trigger') ?? 'mouseenter focus';