Created by: simon-paris
The current implementation of dispose does not work correctly when any modal is opening, open, or closing (including the one being disposed).
To fix this, modals need to know the state of the currently open modal. I've done this by maintaining a global counter which is incremented when a modal starts showing and decrements when it is done hiding or is disposed. The counter is stored in $('body').data('bs.modal.refcount')
. I chose this approach because it also prevents the whole page from locking up if multiple modals are alive at once.
Additionally, some events needed to be cleaned up when dispose is called during or immediately after a transition. If they aren't, the backdrop, modal-open class, or resize event can be leaked or prematurely removed. It could also crash in several places. The events that have to be cleaned up are:
- Transition end handlers
- Hide/show timeouts
- Focus event
- Resize event
Support for manual removal of modals (i.e. $(".modal, .modal-backdrop").remove()
and $("body").removeClass("modal-open")
) is retained even if the user is not aware of the refcount, because manual removal leads to a state that can never be reached normally. This state can be detected and fixed.
I've added assertions afterEach test to check that there are no modals still alive. I've added new tests for dispose and for multiple open modals, and I added a test to the visual tests file for more aggressive testing of transitions in combination with dispose.
I wasn't sure about a few things:
- I needed the timeout id from emulateTransitionEnd, so I made it return it. Do you care about backwards compatibility for that method?
- Should disposing a modal add the "area-hidden" attribute?
- In the tests afterEach block, should I use assertions or throw? If I use assertions, I have to change all the
asserts.expect
calls.