@@ -15,38 +15,54 @@ $.fn.extend({
1515 */
1616 buttons_popover : function ( buttons , options ) {
1717 this . each ( function ( i , elem ) {
18- const this_buttons = typeof buttons === "function" ?
19- buttons ( elem ) :
20- buttons ;
18+ const this_buttons = typeof buttons === "function" ? buttons ( elem ) : buttons ;
2119 const default_options = {
2220 html : true ,
2321 sanitize : false ,
2422 placement : 'bottom' ,
2523 trigger : 'focus' ,
26- }
24+ container : 'body' ,
25+ } ;
2726 const all_options = $ . extend ( { } , default_options , options ) ;
2827
2928 const buttons_html = this_buttons . map ( function ( btn ) {
3029 return ( '<button id="' + btn . id + '" class="btn ' + btn . classes +
3130 '" ' + ( btn . extra_attrs || "" ) + ">" + btn . text + "</button>" )
3231 } ) . join ( ' ' ) ;
33- // We have to attach the event handlers to body because the buttons are
34- // created only when the popover is open and are destroyed when it is closed
32+
3533 const $elem = $ ( elem ) ;
34+ // Make focusable for trigger: 'focus'
35+ $elem . attr ( { 'tabindex' : 0 } ) ;
36+
37+ // Attach delegated handlers for dynamically created buttons
38+ // Namespace per-button id to avoid duplicate handlers on re-init
3639 this_buttons . forEach ( function ( btn ) {
37- $ ( 'body' ) . on ( 'click' , 'button#' + btn . id , function ( ) {
38- // Close this popover by triggering a click
39- $elem . trigger ( 'click' ) ;
40- return btn . onclick ( ) ;
41- } ) ;
40+ const ev = 'click.buttonsPopover.' + btn . id ;
41+ $ ( 'body' )
42+ . off ( ev , 'button#' + btn . id )
43+ . on ( ev , 'button#' + btn . id , function ( ) {
44+ // Hide popover then execute action
45+ try {
46+ const inst = bootstrap . Popover . getInstance ( $elem [ 0 ] ) ;
47+ if ( inst ) inst . hide ( ) ;
48+ } catch ( e ) { /* ignore */ }
49+ return btn . onclick ( ) ;
50+ } ) ;
4251 } ) ;
4352
44- $elem . attr ( {
45- 'data-bs-toggle' : 'popover' ,
46- 'data-content' : buttons_html ,
47- 'tabindex' : 0
48- } ) ;
49- $elem . popover ( all_options ) ;
53+ // Initialize Bootstrap 5 popover (idempotent)
54+ try {
55+ const existing = bootstrap . Popover . getInstance ( $elem [ 0 ] ) ;
56+ if ( ! existing ) {
57+ new bootstrap . Popover ( $elem [ 0 ] , $ . extend ( { } , all_options , { content : buttons_html } ) ) ;
58+ } else {
59+ // Update content attribute for existing instance
60+ $elem . attr ( 'data-bs-content' , buttons_html ) ;
61+ }
62+ } catch ( e ) {
63+ // As a fallback, set data attributes for any legacy initializers
64+ $elem . attr ( { 'data-bs-toggle' : 'popover' , 'data-bs-content' : buttons_html } ) ;
65+ }
5066 } ) ;
5167 } ,
5268} ) ;
0 commit comments