diff --git a/css/backoffice/components/popover-menu/_popover-menu.scss b/css/backoffice/components/popover-menu/_popover-menu.scss index 2febbe791..77ee385d6 100644 --- a/css/backoffice/components/popover-menu/_popover-menu.scss +++ b/css/backoffice/components/popover-menu/_popover-menu.scss @@ -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--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{ +.ibo-popover-menu { display: none; padding: $ibo-popover-menu--padding; 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; flex-direction: column; align-self: flex-start; @@ -47,10 +52,11 @@ $ibo-popover-menu--section-border-radius: $ibo-popover-menu--border-radius !defa width: 100%; white-space: nowrap; 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; } + &:last-child { border-radius: 0 0 $ibo-popover-menu--section-border-radius $ibo-popover-menu--section-border-radius; } diff --git a/js/components/popover-menu.js b/js/components/popover-menu.js index 6b494c7ae..46c145a3c 100644 --- a/js/components/popover-menu.js +++ b/js/components/popover-menu.js @@ -33,56 +33,74 @@ $(function() opened: 'ibo-is-opened', }, js_selectors: - { - menu: '[data-role="ibo-popover-menu"]', - section: '[data-role="ibo-popover-menu--section"]', - item: '[data-role="ibo-popover-menu--item"]', - }, + { + menu: '[data-role="ibo-popover-menu"]', + section: '[data-role="ibo-popover-menu--section"]', + item: '[data-role="ibo-popover-menu--item"]', + }, // the constructor - _create: function() - { + _create: function () { this._bindEvents(); this._closePopup(); + + if (true === this.options.add_visual_hint_to_toggler) { + this._addVisualHintToToggler(); + } }, // events bound via _bind are removed automatically // revert other modifications here - _destroy: function() - { + _destroy: function () { }, - _bindEvents: function() - { + _bindEvents: function () { const me = this; 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(); }); - + // Mostly for outside clicks that should close elements - oBodyElem.on('click', function(oEvent){ + oBodyElem.on('click', function (oEvent) { me._onBodyClick(oEvent); }); }, - // Methods - _onBodyClick: function(oEvent) - { - if($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0) - { + // Events callbacks + _onBodyClick: function (oEvent) { + if ($(oEvent.target.closest(this.js_selectors.menu)).length === 0 && $(oEvent.target.closest(this.options.toggler)).length === 0) { 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($(``)); + + return true; + }, + _openPopup: function () { this.element.addClass(this.css_classes.opened); }, - _closePopup: function() - { + _closePopup: function () { this.element.removeClass(this.css_classes.opened); }, - openPopup: function() - { + openPopup: function () { this._openPopup(); }, closePopup: function() diff --git a/sources/application/UI/Base/Component/PopoverMenu/PopoverMenu.php b/sources/application/UI/Base/Component/PopoverMenu/PopoverMenu.php index 12e7e52ad..988e2c10f 100644 --- a/sources/application/UI/Base/Component/PopoverMenu/PopoverMenu.php +++ b/sources/application/UI/Base/Component/PopoverMenu/PopoverMenu.php @@ -37,10 +37,15 @@ class PopoverMenu extends UIBlock // Overloaded constants public const BLOCK_CODE = 'ibo-popover-menu'; 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 = [ '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 */ protected $aSections; @@ -52,9 +57,62 @@ class PopoverMenu extends UIBlock public function __construct(?string $sId = null) { parent::__construct($sId); + $this->sTogglerJSSelector = ''; + $this->bAddVisualHintToToggler = false; $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. * Important: It does not reset the section. diff --git a/templates/base/components/popover-menu/layout.js.twig b/templates/base/components/popover-menu/layout.js.twig new file mode 100644 index 000000000..54169a62d --- /dev/null +++ b/templates/base/components/popover-menu/layout.js.twig @@ -0,0 +1,4 @@ +$('#{{ oUIBlock.GetId() }}').popover_menu({ + toggler: {{ oUIBlock.GetTogglerJSSelector()|json_encode|raw }}, + add_visual_hint_to_toggler: {{ oUIBlock.HasVisualHintToAddToToggler()|var_export }} +}); \ No newline at end of file