Getting the Error Illegal Invocation at Object

I’m learning Bootstrap 5 and I created a simple web page to test out the creation, opening, and closing of modals without using jQuery. In this page there are a few modals, when the page loads a modal pops up to give the user an instruction on how to bring up a menu.

When the user brings up the menu modal, he/she can see that there are a couple menu items they can select. Each menu item that is clicked will open a modal which tells the user the menu item that he/she selected. The problem I’m having is that each menu item can be clicked only once without throwing the error “Uncaught error:Illegal invocation at Object.findone”. After that, this error is thrown with every click.

I have tried researching the cause of this error but I haven’t found any post that deals specifically with my scenario. Please see my code here. Unfortunately the Bootstrap CDNs I used are not working in jsFiddle.

I can’t really help with the JS but I put your code onto a working codepen to help others look at the problem.

I can’t actually see the problem in that codepen though unless I am missing something :slight_smile:

1 Like

Thanks Paul, For your reply. You said you did not see the error I mentioned when you tested my script in Codepen but I am still getting the error. First I thought it had to do with the browser I’m using so I tested my page in Chrome, Edge, and Firefox. In Firefox when I click on the same menu item more than once I see the error
“Uncaught TypeError: ‘querySelector’ called on an object that does not implement interface Element.
findOne selector-engine.js:26”

In Edge I’m seeing the following error when selecting the same menu item more than once
" Uncaught TypeError: Illegal invocation at Object.findOne (selector-engine.js:26)
at new o (modal.js:88)"

Ok I tested outside of codepen in Firefox and I can see the error message.

I also note that each time you click you are getting an extra backdrop added that is never removed and you can see in the devtools numerous backdrops.

The bootstrap5 documentations states that they only support one modal at a time so if you want multiple modals you would be better off rolling your own code to handle the functionality that you want.

I’m afraid my JS is not good enough to help debug that error so hopefully one of the JS gurus around here will drop by now to give some better advice :slight_smile:

I exported the codepen code but can’t seem to experience the problem on my Chrome, Firefox, or Edge. I’m on windows though, so it might take someone on a mac to experience it instead.

Hi Paul, Thanks for replying. I’m also on Windows but I was able to get the error. PaulOB said that Bootstrap only supports 1 modal at a time and that would really be bad for me as I was hoping to create a web page that allows multiple modals to show at the same time. Any help will be greatly appreciated, thanks.

Multiple modals are very bad UI and really you should only open 1 modal at a time. You can have multiple modals but only as long as only one is open at any time. i.e. close any other modals when you open a new one.

I can see the error you described and its exactly as you say that when you click the same element again you get the error message in the console which points to code in the bootstrap.min js and says
this_element is undefined . However the code seems to continue to run.

Also I find it very annoying that you have disabled the context menu and also that you want a double click to activate the selection. I think you may need to re-think your UI as its very awkward at the moment.

I know this is only a demo but you also need to place those elements better as they are disappearing if I don’t have the window open tall enough.

If you are just checking which item has been clicked then you can open the appropriate modal without any js and just using the data attributes that bootstrap supplies. This seems to work without displaying an error and seems to have the same functionality that your demo has.

The only js was to open the instructions modal and set up the context menu click.

As I said I find it quite awkward to use and it would be better if the instructions automatically disappeared when you click outside them rather than having to dismiss them yourself (which I have added to the demo above).

Hi Paul, thanks for responding. I think I will use the data attributes to open the modals just as you’ve suggested. I know that if I place the data attributes in a button which targets a modal, the target modal will be opened when the button is clicked. However, there is one concern I have with that.

What if I want to call other functions to do something which requires the modal to be opened and all of its parts rendered when I click on the button? Will I be able to ensure that all the required parts are rendered before calling those other functions since I opened the modal without using any script?

I’m not quite sure what you mean as surely you will be interacting with content in the modal once the modal is open and that code will have its own routines which can’t be invoked until you have opened the modal.

Maybe if you had a rough demo of what you had in mind it might be easier to give advice. Usually a modal does one thing so be careful with your UI otherwise it may confuse the user.

Hi Paul, I’ve decided to go with your suggestion of not using javacript to open the modals but I thought it would be nice if I know why I’m getting the error “this_element is undefine”. I started by deleting components one by one and see what would happen but I’ve not been able to pin point the exact cause of the error.

It would be simple to just throw my hands up and say I give up and just move on but I won’t learn anything by doing that. Could you please give me a couple suggestions on how to solve this types of issues where you’re using a third party’s software and you don’t know its code well. Thanks.

@Paul_Wilkins would be better equipped to answer these JS problems as my JS is pretty basic.

The way I usually debug in CSS is as you mentioned and reduce the code down to the minimum test case so hat there is less to look at in order to find the problem and then just test individual elements to se if the problem goes away or reappears.

With JS you have the developer tools giving you the error and in your case it does seem to be the bootstrap code is expecting something to be present that is not there. I’m guessing that the backdrop is the issue as your code was giving multiple backdrops and that would be a cause of confusion.

The bootstrap documents say they don’t really support multiple modals (except as shown in my demo) so I’m guessing the reason for the error is you are doing something you shouldn’t be doing. I don’t really follow the logic of your code either as you continually declare new modals and continually add click events to them when I would have though you only needed to do that once.

Hopefully @Paul_Wilkins will drop by and have another look as he is expert at problems like this. :slight_smile:

1 Like

This discussion has been helpful. Thanks Paul for helping to reveal that the error occurs when you click on the same element again.

I’ve noticed that nothing happens the first time that you click on an element. That problem occurs because the switch code in the click handler creates a new click handler on the element. Later on when you click on that element again, it triggers the click handler, but it also causes another click handler to also be created.

Remove unwanted click handlers

Removing the click handlers that are created in the switch code,results in the following simpler code. I’ve also removed global variables and just defined the variable where they’re used.

    var currentEl = e.target || e.srcElement;
    switch (currentEl.id) {
        case "choice":
            OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
            OptionsModal.show();
            break;
        case "choice1":

            OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
            OptionsModal.show();
            break;
        case "choice2":

            OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
            OptionsModal.show();
            break;
        case "choice3":
            OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
            OptionsModal.show();
            break;

        case 'choice4':
            OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
            OptionsModal.show();
            break;
    }

That code works well with no errors.

Solving problems by deletion - I love it.

Remove duplicate switch statements

Those switch statements are all the same now, so we can remove the switch code and use a simple guard clause instead:

    var currentEl = e.target || e.srcElement;
    if (!currentEl.id.includes("choice")) {
        return;
    }
    var OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
    OptionsModal.show();

Remove the need for a guard clause

Can we get rid of the guard clause? It’s protecting against non-choice clicks. We should be able to update the click handler so that only the choice elements are involved:

Here I’ve moved the event handler function out to a separately named function, so that it’s the same function that gets assigned each time in the loop.

As each choice element is a div inside of the choices body, and there are no other divs to confuse things, we can just loop through each of those divs assigning the same showModal click handler to them.

function showModal(e) {
    var currentEl = e.target || e.srcElement;
    var OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
    OptionsModal.show();
}
document.querySelectorAll("#choices .modal-body div").forEach(function (div) {
    div.addEventListener("click", showModal, false);
});

Conclusion

There doesn’t seem to be anything else worth removing. The problem looks to be solved, and we have reduced all of the JS code to just the following:

var instructionsModal = new bootstrap.Modal(document.getElementById("instructions"));
instructionsModal.show();
window.addEventListener('contextmenu', (event) => {
    event.preventDefault();
    var choicesModal = new bootstrap.Modal(document.getElementById("choices"));
    choicesModal.show();
});

function showModal(e) {
    var currentEl = e.target || e.srcElement;
    var OptionsModal = new bootstrap.Modal(document.getElementById(currentEl.id + "Modal"));
    OptionsModal.show();
}
document.querySelectorAll("#choices .modal-body div").forEach(function (div) {
    div.addEventListener("click", showModal, false);
});
1 Like