Upgrading jQuery version from 1.8 to 3.7 in a Web application

0.00 avg. rating (0% score) - 0 votes

Recently I was tasked with upgrading jQuery in a web portal which was last maintained in 2013 to the latest version of jQuery, which is version 3.7 as at March 2024. A quick check revealed that there were more than 2000+ places in the code having references to jQuery 1.8.3:

<script src="/js/jquery-1.8.3.js"></script>
<script src="/js/jquery-ui-1.9.1.js"></script>

After spending one whole day just to update all these references across hundreds of pages to point to the latest jQuery versions, and also to add reference to jQuery Migrate plugin, which can help with deprecated code, I was greeted with a landing page with a non-responsive Login button, with an error “cannot call methods on dialog prior to initialization – attempted to call method close”:

jquery init

The stack trace pointed at the following line, which is the event handler for the Close button of a jQuery UI dialog:

.click(function() {
	$(this).dialog('close');
	location.reload();
})

It took me a while to realize that when running on jQuery 3, $(this) in the above code no longer refers to the active jQuery UI dialog. As a result, $(this).dialog() is undefined and the error message asks you to initialize the dialog first prior to calling method close. To fix this, we add .closest(‘.ui-dialog-content’) to locate the nearest jQuery UI dialog:

.click(function() {
	$(this).closest('.ui-dialog-content').dialog('close');
	location.reload();
})

With this, the landing page worked, but one of the button on the subsequent pages failed with a similar message, “cannot call methods on dialog prior to initialization – attempted to call method enable”:

$('#remove-button').toolbarbutton(
'enable',
function()
{
...
});

Here toolbarbutton is a custom UI control used in the code. After some debugging I determined that for some reasons $(‘#remove-button’) had not been initialized to be toolbarbutton() prior to calling method enable, despite the initializing code being present in the $(document).ready() method. I worked around the issue by simply initializing the button again before calling enable:

$('#remove-button').toolbarbutton({
	state : 'enabled'
});
$('#remove-button').toolbarbutton(
'enable',
function()
{
...
});

There was then this stubborn jQuery spinner control, which complained of being uninitialized when the spinner-up method was called despite the above tricks. I fixed it for now simply by catching the exception. As the method simply disables the spinner under certain circumstances, which is optional anyway, there appeared to be no affects on the UI:

try {
   $(this.element).next().next('.spinner-up').setElementDisabled(false);
}
catch (err) { console.log("spinner error: " + err); }

I seldom try/catch in JavaScript, but in this instance catching the exception and ignoring the error is the only way I could make things work.

After fixing other similar occurrences, my page appeared to be partially functional, with the exception of check boxes. I then have to replace the deprecated .attr() to .prop() before my check boxes worked again:

// element.attr('checked', false); // old version
element.prop('checked', false); // new version

I then also updated several calls to .live() (which has been removed) to .on() (which is supported by jQuery v3), for event binding to work. Next, I encountered a JavaScript error on $.browser.msie which is a boolean determining if user is on Microsoft Internet Explorer. This property has been removed in the latest jQuery version since IE is no longer supported. I fixed this by declaring a custom method which returns false for $.browser.msie:

(function($) {
    // Define an empty object for $.browser
    $.browser = {}

    // Extend jQuery.browser with a dummy msie property
    $.extend($.browser, {
        msie: false
    });

    // Override the access to $.browser.msie
    Object.defineProperty($.browser, 'msie', {
        get: function() {
            return false;
        }
    });
})(jQuery);

With this, the code that parsed the user agent now worked properly. The final challenge which is also the most difficult one is the occasionally empty OK/Cancel buttons for a jQuery dialog as demonstrated in the following sample screenshot:
Screenshot 2024-06-02 000959

The two buttons were supposed to be OK and Cancel and while empty, they still worked as designed. According to this report, this problem will appear if the page loads multiple conflicting jQuery versions, e.g. loading the .js file for both version 1.8 and version 3 at the same time. After a lot of troubleshooting efforts it turned out that while I had updated all jQuery references in my code to the latest version, this part of the portal loaded the application from a remote site, which still contained the outdated jQuery library. Since I had no way to update the remote jQuery library, I resorted to using CSS to add ❌ for Cancel button and ✓ for OK button so that the button won’t look empty:

button.okbutton::before {
   content: "\2713"
button.cancelbutton::before {
   content: "\274C"
}

The icons on the dialog buttons now display properly, allowing user to know what they are for:

Screenshot 2024-06-02 001924

Why can’t I just add “OK” and “Cancel” via CSS, instead of the Unicode characters? The reason is that the issue does not always happen and at other places, the buttons display properly. Hence, we must use icons to ensure that the icons will look nice next to the text at other places where the button labels are properly displayed:

Screenshot 2024-06-02 002440

With all above tricks I was able to satisfactorily port the web portal to jQuery 3, after several weeks of laborious development work. I hope these tricks will assist others in their own journey to successfully port their projects to jQuery 3.

0.00 avg. rating (0% score) - 0 votes
ToughDev

ToughDev

A tough developer who likes to work on just about anything, from software development to electronics, and share his knowledge with the rest of the world.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>