In the past few months we've seen the Bootstrap framework became more and more popular among web developers. The reasons are fairly obvious, we're talking about a powerful CSS/JS enhancement library featuring a lot of useful stuff to build a responsive, mobile-friendly webpage fully compatible with every major browser/device. The most recent version of the framework (v3.3.1 by the time of this post) contains a lot of useful javascript plugin requiring JQuery v1.9.0 or higher in order to work: there's no doubt that some of these websites are also running JQuery UI.
These 2 frameworks are indeed able to work togheter, but we need to pay attention to at least two naming conflicts between them which need to be fixed in order to avoid JS errors and, most importantly, get them to work properly. We're talking about the tooltip and button plugins, which happen to exist in both of these libraries with the exact same name.
The Issue.
Let's take the tooltip plugin as an example. Open the address http://jqueryui.com/tooltip/ and look at the sample code - by clicking on the "view source" link - to see how the JQuery UI tooltip plugin actually works:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <title>jQuery UI Tooltip - Default functionality</title> <link rel="stylesheet" href="//code.jquery.com/ui/1.11.2/themes/smoothness/jquery-ui.css"> <script src="//code.jquery.com/jquery-1.10.2.js"></script> <script src="//code.jquery.com/ui/1.11.2/jquery-ui.js"></script> <link rel="stylesheet" href="/resources/demos/style.css"> <script> $(function() { $( document ).tooltip(); }); </script> <style> label { display: inline-block; width: 5em; } </style> </head> <br> |
The highlighted text shows a call to the tooltip function which, thanks to JQuery UI, is added at runtime to any JQuery object. Bootstrap does the exact same job, as shown in the official tutorial:
1 |
$('#example').tooltip(options) |
This nasty naming conflict prevents the plugins to work an might also generates some Javascript errors depending on the framework <script> references order inside the web page. For example, here's what you'll most likely get in your Javascript Console if Boostrap is inserted after JQuery UI and the latter's tooltip plugin is being used:
Uncaught TypeError: Cannot read property 'documentElement' of null
We get this message because the tooltip plugin provided by JQueryUI has a completely different - and hardly compatible - interface than the Bootstrap plugin sharing its name.
The Solution.
The best way to make the 2 libraries blend togheter and "constructively" fix the aforementioned naming conflicts is to use the not-so-well-known $.widget.bridge plugin, which allows us to re-define each previously assigned prototype function name. The plugin is already included inside the JQuery UI standard distribution package, so we won't add any additional stuff to our website. The usage is quite simple:
1 2 3 |
// Change JQueryUI plugin names to fix name collision with Bootstrap. $.widget.bridge('uitooltip', $.ui.tooltip); $.widget.bridge('uibutton', $.ui.button); |
These commands need to be executed after the JQueryUI and before the Bootstrap js file references. In the following example we can see a full implementation example in the <head> block of a common webpage:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
<html> <head> <title>My JqueryUI + Boostrap page</title> <script type="text/javascript" src="cdn/or/local/path/to/jquery.ui.js"></script> <script type="text/javascript"> // Change JQueryUI plugin names to fix name collision with Bootstrap. $.widget.bridge('uitooltip', $.ui.tooltip); $.widget.bridge('uibutton', $.ui.button); </script> <script type="text/javascript" src="cdn/or/local/path/to/bootstrap.js"></script> </head> <body> [...] </body> </html> |
After you do this, the tooltip and button prototype methods will be univocally routed to the Bootstrap ones: those provided by JQuery UI will also be usable as long as we call them by using the new alias we gave them: uitooltip and uibutton.
References:
http://stackoverflow.com/a/27745464/1233379 (my answer on StackOverflow which kinda inspired this post).
Thank You! been looking for this solution.
great solution, thx man.
Thank you it was useful
It’s what I have been looking for, thank you!
Perfect – wish I’d found this 4 hours ago!
Muy buena aportación gracias
you saved me !!!! Perfert solution !!!!
Glad to be helpful: thanks to you and take care!
Just suffered from this. Since I use the BS tooltip I simply removed it from jQuery-ui. Luckily you can customize your download to include/exclude widgets.
hi
Dear Ryan,
I cannot solve my issue. I created a navbar with some buttons. One of this button has bootstrap tooltip specs.
However, the style and positioning inherited by the tooltip comes from a jquery.ui.css file stored into /pubic_html ; therefore I downloaded the proper bootstrap css and min.css and uploaded in the same directory. Then, I added to the frame_chat.inc.php (where my navbar is) all the references to bootstrap as per blow.
The tricky part, I think based on what I noticed, is that wen I inspect the tooltip, what I find is this:
Button
While if I inspect an element on the bootstrap page, the tooltip is wrapped in the following div:
Tooltip on top
Any idea? Many thanks my friend.
***** Scripts in my file .php
http://public_html/includes/jquery-1.10.2.min.js
// Change JQueryUI plugin names to fix name collision with Bootstrap.
$.widget.bridge(‘ui.tooltip’, $.ui.tooltip);
$.widget.bridge(‘ui.button’, $.ui.button);
http://public_html/includes/bootstrap.js
< content etc. etc. >
https://code.jquery.com/jquery-3.2.1.slim.min.js
https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js
https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js
Hello there,
from what you’re showing on your code, it definitely seems to me that you’re loading two different jquery versions: 1.10.2.min and 3.2.1.slim.
You can’t do that: pick a single jQuery version and stick with it, otherwise you’ll mess up your jQuery classes and the $.widget.bridge won’t work as expected.