diff --git a/libraries/cms/html/bootstrap.php b/libraries/cms/html/bootstrap.php index 8b8854b354a13..82b8edc44e750 100644 --- a/libraries/cms/html/bootstrap.php +++ b/libraries/cms/html/bootstrap.php @@ -277,18 +277,21 @@ public static function renderModal($selector = 'modal', $params = array(), $body * @param string $selector Selector for the popover * @param array $params An array of options for the popover. * Options for the popover can be: - * animation boolean apply a css fade transition to the popover - * html boolean Insert HTML into the popover. If false, jQuery's text method will be used to insert - * content into the dom. - * placement string|function how to position the popover - top | bottom | left | right - * selector string If a selector is provided, popover objects will be delegated to the specified targets. - * trigger string how popover is triggered - hover | focus | manual - * title string|function default title value if `title` tag isn't present - * content string|function default content value if `data-content` attribute isn't present - * delay number|object delay showing and hiding the popover (ms) - does not apply to manual trigger type - * If a number is supplied, delay is applied to both hide/show - * Object structure is: delay: { show: 500, hide: 100 } - * container string|boolean Appends the popover to a specific element: { container: 'body' } + * animation boolean apply a css fade transition to the popover + * container string|boolean Appends the popover to a specific element: { container: 'body' } + * content string|function default content value if `data-content` attribute isn't present + * delay number|object delay showing and hiding the popover (ms) - does not apply to manual trigger type + * If a number is supplied, delay is applied to both hide/show + * Object structure is: delay: { show: 500, hide: 100 } + * html boolean Insert HTML into the popover. If false, jQuery's text method will be used to insert + * content into the dom. + * placement string|function how to position the popover - top | bottom | left | right + * selector string If a selector is provided, popover objects will be delegated to the specified targets. + * template string Base HTML to use when creating the popover. + * title string|function default title value if `title` tag isn't present + * trigger string how popover is triggered - hover | focus | manual + * constraints array An array of constraints - passed through to Tether. + * offset string Offset of the popover relative to its target. * * @return void * @@ -305,21 +308,26 @@ public static function popover($selector = '.hasPopover', $params = array()) // Include Bootstrap framework JHtml::_('bootstrap.framework'); - $opt['animation'] = isset($params['animation']) ? $params['animation'] : null; - $opt['html'] = isset($params['html']) ? $params['html'] : true; - $opt['placement'] = isset($params['placement']) ? $params['placement'] : null; - $opt['selector'] = isset($params['selector']) ? $params['selector'] : null; - $opt['title'] = isset($params['title']) ? $params['title'] : null; - $opt['trigger'] = isset($params['trigger']) ? $params['trigger'] : 'hover focus'; - $opt['content'] = isset($params['content']) ? $params['content'] : null; - $opt['delay'] = isset($params['delay']) ? $params['delay'] : null; - $opt['container'] = isset($params['container']) ? $params['container'] : 'body'; - - $options = JHtml::getJSObject($opt); + $opt['animation'] = isset($params['animation']) ? $params['animation'] : null; + $opt['container'] = isset($params['container']) ? $params['container'] : 'body'; + $opt['content'] = isset($params['content']) ? $params['content'] : null; + $opt['delay'] = isset($params['delay']) ? $params['delay'] : null; + $opt['html'] = isset($params['html']) ? $params['html'] : true; + $opt['placement'] = isset($params['placement']) ? $params['placement'] : null; + $opt['selector'] = isset($params['selector']) ? $params['selector'] : null; + $opt['template'] = isset($params['template']) ? $params['template'] : null; + $opt['title'] = isset($params['title']) ? $params['title'] : null; + $opt['trigger'] = isset($params['trigger']) ? $params['trigger'] : 'hover focus'; + $opt['constraints'] = isset($params['constraints']) ? $params['constraints'] : ['to' => 'scrollParent', 'attachment' => 'together', 'pin' => true]; + $opt['offset'] = isset($params['offset']) ? $params['offset'] : '0 0'; + + $opt = (object) array_filter((array) $opt); + $options = json_encode($opt); // Attach the popover to the document JFactory::getDocument()->addScriptDeclaration( - 'jQuery(function($){ $(' . json_encode($selector) . ').popover(' . $options . '); });' + 'var popoverOptions = ' . $options . '; popoverOptions.constraints = [popoverOptions.constraints]; + jQuery(function($){ $(' . json_encode($selector) . ').popover(popoverOptions); });' ); static::$loaded[__METHOD__][$selector] = true; @@ -374,17 +382,21 @@ public static function scrollspy($selector = 'navbar', $params = array()) * @param string $selector The ID selector for the tooltip. * @param array $params An array of options for the tooltip. * Options for the tooltip can be: - * - animation boolean Apply a CSS fade transition to the tooltip - * - html boolean Insert HTML into the tooltip. If false, jQuery's text method will be used to insert - * content into the dom. - * - placement string|function How to position the tooltip - top | bottom | left | right - * - selector string If a selector is provided, tooltip objects will be delegated to the specified targets. - * - title string|function Default title value if `title` tag isn't present - * - trigger string How tooltip is triggered - hover | focus | manual - * - delay integer Delay showing and hiding the tooltip (ms) - does not apply to manual trigger type - * If a number is supplied, delay is applied to both hide/show - * Object structure is: delay: { show: 500, hide: 100 } - * - container string|boolean Appends the popover to a specific element: { container: 'body' } + * animation boolean apply a css fade transition to the popover + * container string|boolean Appends the popover to a specific element: { container: 'body' } + * delay number|object delay showing and hiding the popover (ms) - does not apply to manual trigger type + * If a number is supplied, delay is applied to both hide/show + * Object structure is: delay: { show: 500, hide: 100 } + * html boolean Insert HTML into the popover. If false, jQuery's text method will be used to insert + * content into the dom. + * placement string|function how to position the popover - top | bottom | left | right + * selector string If a selector is provided, popover objects will be + * delegated to the specified targets. + * template string Base HTML to use when creating the popover. + * title string|function default title value if `title` tag isn't present + * trigger string how popover is triggered - hover | focus | manual + * constraints array An array of constraints - passed through to Tether. + * offset string Offset of the popover relative to its target. * * @return void * @@ -398,24 +410,27 @@ public static function tooltip($selector = '.hasTooltip', $params = array()) JHtml::_('bootstrap.framework'); // Setup options object - $opt['animation'] = isset($params['animation']) ? (boolean) $params['animation'] : null; - $opt['html'] = isset($params['html']) ? (boolean) $params['html'] : true; - $opt['placement'] = isset($params['placement']) ? (string) $params['placement'] : null; - $opt['selector'] = isset($params['selector']) ? (string) $params['selector'] : null; - $opt['title'] = isset($params['title']) ? (string) $params['title'] : null; - $opt['trigger'] = isset($params['trigger']) ? (string) $params['trigger'] : null; - $opt['delay'] = isset($params['delay']) ? (is_array($params['delay']) ? $params['delay'] : (int) $params['delay']) : null; - $opt['container'] = isset($params['container']) ? $params['container'] : 'body'; - $opt['template'] = isset($params['template']) ? (string) $params['template'] : null; - $onShow = isset($params['onShow']) ? (string) $params['onShow'] : null; - $onShown = isset($params['onShown']) ? (string) $params['onShown'] : null; - $onHide = isset($params['onHide']) ? (string) $params['onHide'] : null; - $onHidden = isset($params['onHidden']) ? (string) $params['onHidden'] : null; - - $options = JHtml::getJSObject($opt); + $opt['animation'] = isset($params['animation']) ? $params['animation'] : null; + $opt['container'] = isset($params['container']) ? $params['container'] : 'body'; + $opt['delay'] = isset($params['delay']) ? $params['delay'] : null; + $opt['html'] = isset($params['html']) ? $params['html'] : true; + $opt['placement'] = isset($params['placement']) ? $params['placement'] : null; + $opt['selector'] = isset($params['selector']) ? $params['selector'] : null; + $opt['template'] = isset($params['template']) ? $params['template'] : null; + $opt['title'] = isset($params['title']) ? $params['title'] : null; + $opt['trigger'] = isset($params['trigger']) ? $params['trigger'] : 'hover focus'; + $opt['constraints'] = isset($params['constraints']) ? $params['constraints'] : ['to' => 'scrollParent', 'attachment' => 'together', 'pin' => true]; + $opt['offset'] = isset($params['offset']) ? $params['offset'] : '0 0'; + $onShow = isset($params['onShow']) ? (string) $params['onShow'] : null; + $onShown = isset($params['onShown']) ? (string) $params['onShown'] : null; + $onHide = isset($params['onHide']) ? (string) $params['onHide'] : null; + $onHidden = isset($params['onHidden']) ? (string) $params['onHidden'] : null; + + $opt = (object) array_filter((array) $opt); + $options = json_encode($opt); // Build the script. - $script = array('$(' . json_encode($selector) . ').tooltip(' . $options . ')'); + $script = array('$(' . json_encode($selector) . ').tooltip(tooltipOptions)'); if ($onShow) { @@ -438,7 +453,10 @@ public static function tooltip($selector = '.hasTooltip', $params = array()) } // Attach tooltips to document - JFactory::getDocument()->addScriptDeclaration('jQuery(function($){ ' . implode('.', $script) . '; });'); + JFactory::getDocument()->addScriptDeclaration( + 'var tooltipOptions = ' . $options . '; tooltipOptions.constraints = [tooltipOptions.constraints]; + jQuery(function($){ ' . implode('.', $script) . '; });' + ); // Set static array static::$loaded[__METHOD__][$selector] = true; diff --git a/tests/unit/suites/libraries/cms/html/JHtmlBootstrapTest.php b/tests/unit/suites/libraries/cms/html/JHtmlBootstrapTest.php index c92e860aa58f4..76146f858ae62 100644 --- a/tests/unit/suites/libraries/cms/html/JHtmlBootstrapTest.php +++ b/tests/unit/suites/libraries/cms/html/JHtmlBootstrapTest.php @@ -348,7 +348,7 @@ public function testPopover() $this->assertEquals( $document->_script['text/javascript'], - 'jQuery(function($){ $(".hasPopover").popover({"html": true,"trigger": "hover focus","container": "body"}); });', + 'var popoverOptions = {"container":"body","html":true,"trigger":"hover focus","constraints":{"to":"scrollParent","attachment":"together","pin":true},"offset":"0 0"}; popoverOptions.constraints = [popoverOptions.constraints];' . "\n\t\t\t" . 'jQuery(function($){ $(".hasPopover").popover(popoverOptions); });', 'Verify that the popover script is initialised' ); } @@ -416,7 +416,7 @@ public function testTooltip() $this->assertEquals( $document->_script['text/javascript'], - 'jQuery(function($){ $(".hasTooltip").tooltip({"html": true,"container": "body"}); });', + 'var tooltipOptions = {"container":"body","html":true,"trigger":"hover focus","constraints":{"to":"scrollParent","attachment":"together","pin":true},"offset":"0 0"}; tooltipOptions.constraints = [tooltipOptions.constraints];' . "\n\t\t\t\t" . 'jQuery(function($){ $(".hasTooltip").tooltip(tooltipOptions); });', 'Verify that the tooltip script is initialised' ); }