Bug Tracker

Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#10066 closed bug (invalid)

Double referencing jQuery deletes all assigned plugins.

Reported by: adsood Owned by:
Priority: low Milestone: None
Component: misc Version: 1.5.1
Keywords: Cc:
Blocked by: Blocking:

Description

Scenario:

  • A web page loads external HTML page and displays it in the Dialog using jQuery UI library.

What happens:

  • When a formatted (HTML) page is loaded into existing document (using .load() function) browser build DOM and loads any scripts if they are referenced on the loaded page.

if both the host page and the loaded page refer to jQuery library, the jQuery script will be executed twice.

As jQuery script executes it re-initializes $ and $.prototype, which removes all existing plug-ins. The host page stops working.

Example: The following example is simplified version of the issue (jquery explicitly loaded twice):

<html>
<head>
    <title>jQuery double reference</title>
    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script type="text/javascript">
        $.fn.test = function(method) {
		alert('test');
	}
    </script>

    <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js"></script>
    <script type="text/javascript">
	$(function() {
		$('body').test();
	});
    </script>
</head>

<body>
</body>
</html> 

No alert has been displayed and an error reported in the console: "Uncaught TypeError: Object [object Object] has no method 'test'" or "$("body").test is not a function" ...

Solution: At the beginning of jQuery script add verification if jQuery has been loaded already:

...
if (typeof jQuery === 'undefined')

(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
...

Similar approach has been utilized by jQueryUI.

tested in: Chrome - 5.0.375.9 Chrome - 13.0.782.112 m Firefox - 3.6.18 Firefox - 5.0 IE - 9.0.8112.16421

Change History (4)

comment:1 Changed 8 years ago by Rick Waldron

Component: unfiledmisc
Priority: undecidedlow
Resolution: invalid
Status: newclosed

Use $.noConflict().

Also, this will happen in any programming language that allows for the declaration and assignment of variables.

comment:2 Changed 8 years ago by adsood

There is no conflict here with any other libraries. It is not a matter of using $ sign or not using. The problem is that jQuery (and its alias - $) get completely wiped out and replaced with the new copy. "jQuery" variable get re-initialized as well.

We develop our own plug-in and follow all the recommendations from jQuery documentation. However, the plug-in get removed from jQuery prototype. $.noConflict() will not help here.

I do not fully understand the reference to other programming languages and its relevance to the problem. If, however, we look at other JavaScript libraries that can suffer from the same issue, then we can see that they use simple verification against double-loading case.

An example is jQueryUI library:

$.ui = $.ui || {};
if ( $.ui.version ) {
	return;
}

This is a valid issue. Please open the ticket.

Last edited 8 years ago by adsood (previous) (diff)

comment:3 Changed 8 years ago by ajpiano

The fact that jQuery UI does not allow multiple instantiations of the library is not germane to this discussion. jQuery has historically allowed you to have as many copies of jQuery on the page as you like/need, and loading jQuery again will destroy the existing jQuery, unless you've aliased to somewhere else beforehand, perhaps using noConflict.

I certainly understand why this issue is annoying - it was the first big "jQuery Bug" I had a number of years ago when I was getting started that drove me into the community in the first place. WHERE ARE MY PLUGINS GOING? Turned out I was accidentally AJAX'ing whole pages and thus reloading and clobbering jQuery when I didn't even intend to.

However, I am now of the mind that it is the developer's responsibility to ensure that their assets are loading properly and reliably. Because of the various use cases for loading multiple copies of jQuery on a page, we simply cannot block multiple instantiations with the technique you've described here and thus will not reopen this ticket.

comment:4 Changed 8 years ago by adsood

@ajpiano: I understand your ground in general. The statement "Because of the various use cases for loading multiple copies of jQuery on a page, we simply cannot block multiple instantiations" intrigues me.

Could you provide a one or two real-life (or practically useful) examples of using "loading multiple copies of jQuery on a page" technique?

Thanks.

Note: See TracTickets for help on using tickets.