WebSDK: error (again) updating to bootstrap 5

Hi,

I’m still updating my websdk to bootstrap 5. it seems the last one to give me headaches…
it is for a webbutton I can’t have them a tooltip or a popover.
I narrowed toe problem to : I cannot set the btn property “data-bs-toggle” to the value “tooltip”
it is on the line :

btn.setAttributes( “data-bs-toggle” , “tooltip”);

it gives me an error “setattribute is not a function”.
if I use instead, for the same line,

btn.data.bs.toggle = ‘tooltip’;

it gives me an error “cannot set property bs is undefined”.
see the javascript code below, and can you tell me where is my mistake ?
setting data-toggle property in the same code under boostrap 4 works fine …

thanks.

var VNSWeb;
(

    function (VNSWeb) {

    // IE does not know about the target attribute. It looks for srcElement
    // This function will get the event target in a browser-compatible way
    function getEventTarget(e) {
        e = e || window.event;
        return e.target || e.srcElement; 
    }

    function getBootstrapMajorVersion() {
        // Obtenir la version majeure de Bootstrap du fichier JavaScript chargé
        return parseInt($.fn.modal.Constructor.VERSION);
    }

    class VNSWebButtonWithIcon extends XojoWeb.XojoVisualControl {

        constructor(id, events) {
            super(id, events);
            this.mCaption = "";
            this.mSize = "";
            this.mIconNames = {};
            this.mIsGlyphicon = false;
            this.mIndic = "";
            this.mDisabled = false;
            this.mActive = false;
            this.mbuttonShadow = "";
            this.mButtonOutline = false;
            this.mButtonCircle = false;
            this.btTooltip = "";
            this.mPopoverTitle = "";
            this.mPopoverContent = "";
            this.mPopoverFocus = false;
            this.mButtonBackgroundIndicator = "";
        }

        pressAction(event) {
            if (event.innerHTML=="") { event = event.parentNode }
            if (!event.classList.contains('vnswebbutton')) { // envoie event si ce n'est pas la liste complete
                let target = event.innerHTML;
                var i = 0;
                while( (event = event.previousSibling) != null ) i++;
                this.triggerServerEvent("buttonClick", {"index": i, "target": target});
            }
        }

        render() {
            super.render();
            let el = this.DOMElement();
            if (!el)
                return;
            while (el.hasChildNodes()) {  
                el.removeChild(el.firstChild);
            }
            if (!el.classList.contains('vnswebbutton')) {
                if (this.mButtonBackgroundIndicator!="") {
                    el.classList.add(this.mButtonBackgroundIndicator);
                }
                el.classList.add('vnswebbutton');
                el.classList.add('btn-group');
                let classInstance = this;
                el.addEventListener( "click", function(event){
                    var target = getEventTarget(event);
                    classInstance.pressAction(target);
                });
            }
            this.setAttributes();
            //[focus] //el.style.outline = "none";
            el.style.cursor = "default";
            var sh = this.mButtonShadow;
            if ((sh!="") && (sh!="shadow-none")) { el.classList.add (sh) }

            var btn = document.createElement('BUTTON');
            btn.classList.add('btn');
            btn.id = this.mControlID + "_vnswebbutton";
            if (getBootstrapMajorVersion()>=5) {
                var bsbtn = new bootstrap.Button(btn);
            }
            btn.style.padding = 'unset';
            if (this.mButtonOutline) {
                btn.classList.add('btn-outline'+this.mIndic);
            } else {
                btn.classList.add('btn'+this.mIndic);
            }
            if (this.mButtonCircle) {
                btn.classList.add('rounded-circle');
            }
            if (this.mFontSize != '') {
                btn.style.fontSize = this.mFontSize;
            }
            if (this.mSize!="") {btn.classList.add(this.mSize);}
            if (this.mActive) {btn.classList.add("active");}
            btn.disabled = this.mDisabled;
            btn.type = 'button';
            el.appendChild(btn);

            var btnpopover;
            var btntooltip;
            if ((this.mPopoverTitle != "") || (this.mPopoverContent != "")) {
                if (getBootstrapMajorVersion()<5) {
                    btn.dataset.toggle = 'popover';
                    if (this.mPopoverFocus) {
                        btn.dataset.trigger = 'focus';
                        btn.tabindex = '0';
                    }
                    btn.dataset.content = this.mPopoverContent;
                    btn.dataset.originalTitle = this.mPopoverTitle;
                } else {
                    if (!btnpopover) {
                        btnpopover = new bootstrap.Popover(btn,
                            {
                                content: this.mPopoverContent,
                                title: this.mPopoverTitle
                            });
                        if (this.mPopoverFocus) {
                            btnpopover._config.trigger = 'focus';
                            btnpopover.setContent({
                              '.popover-dismiss': { trigger: 'focus'}
                            });
                            btn.tabindex = '0';
                        }
                    }
                }
            } else {
                if (this.mTooltip!="") {
                    if (getBootstrapMajorVersion()<5) {
                        btn.dataset.toggle = 'tooltip';
                        btn.dataset.placement = 'auto';
                        btn.dataset.html = 'true';
                        btn.dataset.originalTitle = this.mTooltip;
                        btn.title = this.mTooltip;
                    } else {
                        btn.setAttributes( "data-bs-toggle" , "tooltip");
                        if (!btntooltip) {
                            btntooltip = new bootstrap.Tooltip(btn,
                                {
                                    title: this.mTooltip,
                                    html: true,
                                    placement: 'auto',
                                    trigger: 'hover'
                                }
                            );
                        }
                    }
                }
            }
            var bi;
            if (this.mIsGlyphicon) {
                bi = document.createElement('SPAN');
            } else {
                bi = document.createElement('I');
            }
            var i=0;
            for ( i in this.mIconNames) {
                bi.className += this.mIconNames[i]+" ";
            }
            btn.appendChild(bi);
            btn.appendChild(document.createTextNode(this.mCaption));

            if (getBootstrapMajorVersion()<5) {
                $("[data-toggle=popover]").popover();
            } else {
                // initialize all the popovers
                //const popoverTriggerList = document.querySelectorAll('[data-bs-toggle="popover"]');
                //const popoverList = [...popoverTriggerList].map(popoverTriggerEl => new bootstrap.Popover(popoverTriggerEl));

                // initialize all the tooltips
                const tooltipTriggerList = document.querySelectorAll('[data-bs-toggle="tooltip"]');
                const tooltipList = [...tooltipTriggerList].map(tooltipTriggerEl => new bootstrap.Tooltip(tooltipTriggerEl));
            }
            if (this.mPopoverFocus) {
                if (getBootstrapMajorVersion()<5) {
                    $('.popover-dismiss').popover({trigger: 'focus'});
                } else {
                    //const popover = new bootstrap.Popover('.popover-dismiss', { trigger: 'focus'});
                }
            }

            el.appendChild(btn);
            this.applyUserStyle();
            }

        updateControl(data) {
            super.updateControl(data);
            let js = $.parseJSON(data);
            this.mCaption = js.caption;
            this.mSize = js.btsize;
            this.mIconNames = js.iconName;
            this.mIsGlyphicon = js.isGlyphicon;
            this.mIndic = js.indic;
            this.mDisabled = js.buttonDisabled;
            this.mActive = js.buttonActive;
            this.mButtonShadow = js.buttonShadow;
            this.mButtonOutline = js.buttonOutline;
            this.mButtonCircle = js.buttonCircle;
            this.mFontSize = js.fontSize;
            this.mTooltip = js.btTooltip;
            this.mPopoverTitle = js.popoverTitle;
            this.mPopoverContent = js.popoverContent;
            this.mPopoverFocus = js.popoverFocus;
            this.mButtonBackgroundIndicator = js.buttonBackgroundIndicator;
            this.refresh();
        }
    }
    VNSWeb.VNSWebButtonWithIcon = VNSWebButtonWithIcon;
})(VNSWeb || (VNSWeb = {}));

I also have the almost same error to set the popover a few lines before the tooltip …

I forgot to say that I include this in the head event

res = res + "<link rel=""stylesheet"" href=""https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.2/font/bootstrap-icons.min.css"">"
res = res + "<link rel=""stylesheet"" href=""https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css"" integrity=""sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN"" crossorigin=""anonymous"">"
res = res + "<script src=""https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.6/dist/umd/popper.min.js"" crossorigin=""anonymous""></script>"

found the problem: you must remove the lines

if (getBootstrapMajorVersion()>=5) {
                var bsbtn = new bootstrap.Button(btn);
            }

or it gets doubled with the lines where you create the tooltip or the popover later
and you get the error

2 Likes