mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Popover menu: Introduce option to add a visual hint on the menu toggler
This adds a visual hint (caret down) on the toggler to help the user understand that clicking on the toggler won't do something right away, but will open a menu instead
This commit is contained in:
@@ -21,9 +21,11 @@ $ibo-popover-menu--background-color: $ibo-color-white-100 !default;
|
|||||||
$ibo-popover-menu--border-radius: $ibo-border-radius-300 !default;
|
$ibo-popover-menu--border-radius: $ibo-border-radius-300 !default;
|
||||||
$ibo-popover-menu--padding: 0 !default;
|
$ibo-popover-menu--padding: 0 !default;
|
||||||
|
|
||||||
|
$ibo-popover-menu--toggler-visual-hint--margin-left: 0.5rem !default;
|
||||||
|
|
||||||
$ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !default;
|
$ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !default;
|
||||||
|
|
||||||
.ibo-popover-menu{
|
.ibo-popover-menu {
|
||||||
display: none;
|
display: none;
|
||||||
padding: $ibo-popover-menu--padding;
|
padding: $ibo-popover-menu--padding;
|
||||||
background-color: $ibo-popover-menu--background-color;
|
background-color: $ibo-popover-menu--background-color;
|
||||||
@@ -38,8 +40,11 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ibo-popover-menu--toggler-visual-hint {
|
||||||
|
margin-left: $ibo-popover-menu--toggler-visual-hint--margin-left;
|
||||||
|
}
|
||||||
|
|
||||||
.ibo-popover-menu--section{
|
.ibo-popover-menu--section {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
@@ -47,10 +52,11 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
overflow: hidden; /* To avoid first/last entries of the menu to have no border-radius on hover */
|
overflow: hidden; /* To avoid first/last entries of the menu to have no border-radius on hover */
|
||||||
|
|
||||||
&:first-child{
|
&:first-child {
|
||||||
border-radius: $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius 0 0;
|
border-radius: $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-radius: 0 0 $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius;
|
border-radius: 0 0 $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,56 +33,74 @@ $(function()
|
|||||||
opened: 'ibo-is-opened',
|
opened: 'ibo-is-opened',
|
||||||
},
|
},
|
||||||
js_selectors:
|
js_selectors:
|
||||||
{
|
{
|
||||||
menu: '[data-role="ibo-popover-menu"]',
|
menu: '[data-role="ibo-popover-menu"]',
|
||||||
section: '[data-role="ibo-popover-menu--section"]',
|
section: '[data-role="ibo-popover-menu--section"]',
|
||||||
item: '[data-role="ibo-popover-menu--item"]',
|
item: '[data-role="ibo-popover-menu--item"]',
|
||||||
},
|
},
|
||||||
|
|
||||||
// the constructor
|
// the constructor
|
||||||
_create: function()
|
_create: function () {
|
||||||
{
|
|
||||||
this._bindEvents();
|
this._bindEvents();
|
||||||
this._closePopup();
|
this._closePopup();
|
||||||
|
|
||||||
|
if (true === this.options.add_visual_hint_to_toggler) {
|
||||||
|
this._addVisualHintToToggler();
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// events bound via _bind are removed automatically
|
// events bound via _bind are removed automatically
|
||||||
// revert other modifications here
|
// revert other modifications here
|
||||||
_destroy: function()
|
_destroy: function () {
|
||||||
{
|
|
||||||
},
|
},
|
||||||
_bindEvents: function()
|
_bindEvents: function () {
|
||||||
{
|
|
||||||
const me = this;
|
const me = this;
|
||||||
const oBodyElem = $('body');
|
const oBodyElem = $('body');
|
||||||
|
|
||||||
this.element.find(this.js_selectors.item).on('click', function(oEvent){
|
this.element.find(this.js_selectors.item).on('click', function (oEvent) {
|
||||||
me._closePopup();
|
me._closePopup();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mostly for outside clicks that should close elements
|
// Mostly for outside clicks that should close elements
|
||||||
oBodyElem.on('click', function(oEvent){
|
oBodyElem.on('click', function (oEvent) {
|
||||||
me._onBodyClick(oEvent);
|
me._onBodyClick(oEvent);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Methods
|
// Events callbacks
|
||||||
_onBodyClick: function(oEvent)
|
_onBodyClick: function (oEvent) {
|
||||||
{
|
if ($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0) {
|
||||||
if($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0)
|
|
||||||
{
|
|
||||||
this._closePopup();
|
this._closePopup();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_openPopup: function()
|
|
||||||
{
|
// Methods
|
||||||
|
/**
|
||||||
|
* Add a visual hint (caret) on the toggler
|
||||||
|
*
|
||||||
|
* @return {boolean}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
_addVisualHintToToggler: function () {
|
||||||
|
if ('' === this.options.toggler) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const oTogglerElem = $(this.options.toggler);
|
||||||
|
if (oTogglerElem.length === 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
oTogglerElem.append($(`<span class="ibo-popover-menu--toggler-visual-hint"><span class="fas fa-caret-down"></span></span>`));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
_openPopup: function () {
|
||||||
this.element.addClass(this.css_classes.opened);
|
this.element.addClass(this.css_classes.opened);
|
||||||
},
|
},
|
||||||
_closePopup: function()
|
_closePopup: function () {
|
||||||
{
|
|
||||||
this.element.removeClass(this.css_classes.opened);
|
this.element.removeClass(this.css_classes.opened);
|
||||||
},
|
},
|
||||||
openPopup: function()
|
openPopup: function () {
|
||||||
{
|
|
||||||
this._openPopup();
|
this._openPopup();
|
||||||
},
|
},
|
||||||
closePopup: function()
|
closePopup: function()
|
||||||
|
|||||||
@@ -37,10 +37,15 @@ class PopoverMenu extends UIBlock
|
|||||||
// Overloaded constants
|
// Overloaded constants
|
||||||
public const BLOCK_CODE = 'ibo-popover-menu';
|
public const BLOCK_CODE = 'ibo-popover-menu';
|
||||||
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/components/popover-menu/layout';
|
public const DEFAULT_HTML_TEMPLATE_REL_PATH = 'base/components/popover-menu/layout';
|
||||||
|
public const DEFAULT_JS_TEMPLATE_REL_PATH = 'base/components/popover-menu/layout';
|
||||||
public const DEFAULT_JS_FILES_REL_PATH = [
|
public const DEFAULT_JS_FILES_REL_PATH = [
|
||||||
'js/components/popover-menu.js',
|
'js/components/popover-menu.js',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
/** @var string JS selector for the DOM element that should trigger the menu open/close */
|
||||||
|
protected $sTogglerJSSelector;
|
||||||
|
/** @var bool Whether the menu should add a visual hint (caret down) on the toggler to help the user understand that clicking on the toggler won't do something right away, but will open a menu instead */
|
||||||
|
protected $bAddVisualHintToToggler;
|
||||||
/** @var array $aSections */
|
/** @var array $aSections */
|
||||||
protected $aSections;
|
protected $aSections;
|
||||||
|
|
||||||
@@ -52,9 +57,62 @@ class PopoverMenu extends UIBlock
|
|||||||
public function __construct(?string $sId = null)
|
public function __construct(?string $sId = null)
|
||||||
{
|
{
|
||||||
parent::__construct($sId);
|
parent::__construct($sId);
|
||||||
|
$this->sTogglerJSSelector = '';
|
||||||
|
$this->bAddVisualHintToToggler = false;
|
||||||
$this->aSections = [];
|
$this->aSections = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $sSelector
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
* @uses static::$sTogglerJSSelector
|
||||||
|
*/
|
||||||
|
public function SetTogglerJSSelector(string $sSelector)
|
||||||
|
{
|
||||||
|
$this->sTogglerJSSelector = $sSelector;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
* @uses static::$sTogglerJSSelector
|
||||||
|
*/
|
||||||
|
public function GetTogglerJSSelector(): string
|
||||||
|
{
|
||||||
|
return $this->sTogglerJSSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @uses static::$sTogglerJSSelector
|
||||||
|
*/
|
||||||
|
public function HasToggler(): bool
|
||||||
|
{
|
||||||
|
return !empty($this->sTogglerJSSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return $this
|
||||||
|
* @uses static::$bAddVisualHintToToggler
|
||||||
|
*/
|
||||||
|
public function AddVisualHintToToggler()
|
||||||
|
{
|
||||||
|
$this->bAddVisualHintToToggler = true;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @uses static::$bAddVisualHintToToggler
|
||||||
|
*/
|
||||||
|
public function HasVisualHintToAddToToggler(): bool
|
||||||
|
{
|
||||||
|
return $this->bAddVisualHintToToggler;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a section $sId if not already existing.
|
* Add a section $sId if not already existing.
|
||||||
* Important: It does not reset the section.
|
* Important: It does not reset the section.
|
||||||
|
|||||||
4
templates/base/components/popover-menu/layout.js.twig
Normal file
4
templates/base/components/popover-menu/layout.js.twig
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
$('#{{ oUIBlock.GetId() }}').popover_menu({
|
||||||
|
toggler: {{ oUIBlock.GetTogglerJSSelector()|json_encode|raw }},
|
||||||
|
add_visual_hint_to_toggler: {{ oUIBlock.HasVisualHintToAddToToggler()|var_export }}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user