Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bootstrap-collapse.js shouldn't rely only on transition end event #5462

Closed
victor-homyakov opened this issue Oct 9, 2012 · 2 comments
Closed
Labels

Comments

@victor-homyakov
Copy link

Currently methods Collapse#show(), Collapse#hide(), Collapse#transition() rely only on transition end event, and will have broken inner state and stop work if such event wasn't fired for some reason:

  1. Element has method hide(), which actually hides element, thus preventing transition (http://api.prototypejs.org/dom/Element/prototype/hide/).
  2. Transition is aborted because the animating property's value is changed before the transition is completed (https://developer.mozilla.org/en-US/docs/CSS/Using_CSS_transitions#Detecting_the_completion_of_a_transition).
  3. Browser vendor changes transition end event name/event system, as it already was with Opera (http://www.ianlunn.co.uk/blog/articles/opera-12-otransitionend-bugs-and-workarounds/).

(for more info please read my answer to http://stackoverflow.com/questions/12715254/twitter-bootstrap-transition-conflict-prototypejs)

Invokation of callback complete() in Collapse#transition() should be guaranteed even if transition event wasn't fired, e.g. via setTimeout().

@fat
Copy link
Member

fat commented Oct 18, 2012

Agreed - please open a pull request. thanks!

@fat fat closed this as completed Oct 18, 2012
victor-homyakov pushed a commit to victor-homyakov/bootstrap that referenced this issue Oct 22, 2012
Transition end event isn't reliable (browser may not fire it, or delay its firing until next transition, in many circumstances, read more in related issue twbs#5462 twbs#5462).

In order to guarantee proper inner state of `Collapse` object (especially `Collapse#transitioning`, because its invalid state will block all successive transitions) additional callback invokation is added with `setTimeout()`.

Timeout value for `setTimeout()` is equal to transition time from `component-animation.less` - I cannot find a better solution for now.
@rnicholus
Copy link

I recently ran into this issue as we have several applications that utilize both Prototype jQuery, and Bootstrap. For various reasons, it is not currently possible for us to completely remove the dependency on Prototype. We are using a web framework that uses Prototype. and have lots of legacy code that also uses Prototype. So, our goal was to coexist with the existing Prototype code, but not have to write any new Prototype code, even when interfacing with legacy client-side code.

My solution was to create a "custom" event bridge that allows us to , from jQuery, trigger handlers that have been attached to elements using Prototype's "observe" function for "custom" event. The reverse is also, true, we are able to fire "custom" events using Prototype and hit any event handlers bound to the affected elements via jQuery.

Note that a "custom" event is an event includes events with a name in the following format: "namespace:eventname". This is the only type of event you can fire using Prototype.

As the creator of this issue pointed out, jQuery will invoke any function on an event target that matches the event type/name, provided preventDefault has not been set. Since Prototype extends DOM elements by adding functions such as hide to each element, this becomes a problem when Twitter Bootstrap is introduced and transitions are enabled.

I decided that I am not ever comfortable allowing jQuery to execute functions, contributed by Prototype to an element, that have the same name as a jQuery event type. The best way to prevent this is in the jQuery/Prototype event bridge I wrote. If we are handling a jQuery triggered event, and it is not a "custom" event, I remove the matching Prototype-contributed function from the event target if one exists before delegating to the jQuery trigger function. After jQuery's trigger function has executed, I re-attach the function to the element.

If you are interested, you can see this drop-in at https://github.com/Widen/jquery-prototype-custom-event-bridge. I have written a full suite of QUnit tests that can be run by clicking on the URL near the top of the repo. I have also linked to the tests in the readme.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants