Skip to Main Content

APEX

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

[BUG][BUG FIX] Including jQuery UI menu widget from server breaks apex menu widget

jason.lyleMar 27 2020 — edited Mar 27 2020

Just wanted to provide a solution to the problem stated in the title. By including the jQuery UI menu widget, which is shipped with APEX and included on the server after an install, certain APEX functionality will break. The jQuery UI menu widget is required for both the jQuery UI autocomplete widget and the jQuery UI select menu widget (at the time of writing this). I have done testing and this problem exists since APEX 5.0 up to, and including, APEX 20.1 on apex.oracle.com.  I have tested this by including the server provided jQuery UI menu widget with the following includes:

APEX 5.0, 5.1

#JQUERYUI_DIRECTORY#ui/#MIN_DIRECTORY#jquery.ui.menu#MIN#.js

APEX 18.1+

#JQUERYUI_DIRECTORY#ui/widgets/#MIN_DIRECTORY#menu#MIN#.js

The issue is that including the jQuery UI menu widget file overwrites the jQuery function binding for menu and changes it from APEX's menu widget ($.apex.menu) to jQuery UI's menu widget ($.ui.menu). In other words, $('#myobject').menu() function now references the jQuery UI menu widget instead of APEX's menu widget. Different items in APEX depend on the menu function referencing APEX's menu widget (IR/IG menus, top navigation, possibly more). So, you are effectively unable to include jQuery UI's menu, autocomplete, or select menu widget without breaking functionality.

After doing some searching, I found a few different posts over the years that have detailed the problem, but never found an actual solution listed. Thanks to John at this site, I was steered in the right direction and able to figure out a way to easily detect the issue and develop a fix for it as well. The below code can be placed on any/every page to be executed when the page is ready. Having it execute when jQuery UI menu is not loaded will not cause any harm as it is smart enough to realize this and not take any actions. I believe the code below is well commented, but please don't hesitate to reach out with any questions.

I hope anyone who wants to use jQuery UI's menu, autocomplete, or select menu widgets find this useful! Hopefully this might even make it into the APEX product itself to make use of these included features as smooth as possible!

/*******************************************************************************

As of current testing, the below code is necessary in APEX 5.0 - 20.1.

APEX 20.1 is the most recent release as of writing this, so it could be

needed in future releases as well.

This code is necessary because of a widget name conflict between APEX and

jQuery UI. The full widget names are apex-menu and ui-menu. However, both of

these, by default, would be exposed as .menu() on jQuery objects, hence the

conflict.

APEX does not load the jQuery UI menu widget by default. Because of this, we

first do the conditional check to see if $.ui.menu exists

Affected files:

APEX 5.0, 5.1

    #JQUERYUI_DIRECTORY#ui/#MIN_DIRECTORY#jquery.ui.menu#MIN#.js

    #JQUERYUI_DIRECTORY#ui/#MIN_DIRECTORY#jquery.ui.autocomplete#MIN#.js

    #JQUERYUI_DIRECTORY#ui/#MIN_DIRECTORY#jquery.ui.selectmenu#MIN#.js

APEX 18.1+

    #JQUERYUI_DIRECTORY#ui/widgets/#MIN_DIRECTORY#menu#MIN#.js

    #JQUERYUI_DIRECTORY#ui/widgets/#MIN_DIRECTORY#autocomplete#MIN#.js

    #JQUERYUI_DIRECTORY#ui/widgets/#MIN_DIRECTORY#selectmenu#MIN#.js

*******************************************************************************/

(function fixApexjQueryMenuCollision($, undefined) {

    "use strict";

    //Check to see if the jQuery UI menu widget is loaded

    if ($.ui.menu) {

        //Regiser .menu() to use $.apex.menu

        //This would be default behavior, but is overridden by adding the jQuery UI

        //menu widget file

        $.widget.bridge("menu", $.apex.menu);

        //Register .ui_menu() to use $.ui.menu

        //This allows developers to directly use the jQuery UI menu widget

        //if they want to

        $.widget.bridge("ui_menu", $.ui.menu);

        //Check to see if the jQuery UI autocoplete widget is loaded

        if ($.ui.autocomplete) {

            //Extend the autocomplete widget. The _create function is the only

            //place .menu() is used. So, here we override the default _create

            //function. In our over-ridden version of the _create function, first

            //we register .menu() with $.ui.menu (as jQuery UI and the autocomplete

            //widget expect). Then we call the original _create function. Finally,

            //we re-register .menu() with $.apex.menu as the rest of the APEX

            //page/calls would expect.

            $.widget( "ui.autocomplete", $.ui.autocomplete, {

                _create: function() {

                    $.widget.bridge("menu", $.ui.menu);

                    this._super();

                    $.widget.bridge("menu", $.apex.menu);

                }

            });

        }

        //Check to see if the jQuery UI selectmenu widget is loaded

        if ($.ui.selectmenu) {

            //Extend the selectmenu widget. The _drawMenu function is the only

            //place .menu() is used. So, here we override the default _drawMenu

            //function. In our over-ridden version of the _drawMenu function, first

            //we register .menu() with $.ui.menu (as jQuery UI and the selectmenu

            //widget expect). Then we call the original _drawMenu function. Finally,

            //we re-register .menu() with $.apex.menu as the rest of the APEX

            //page/calls would expect.

            $.widget("ui.selectmenu", $.ui.selectmenu, {

                _drawMenu: function() {

                    $.widget.bridge("menu", $.ui.menu);

                    this._super();

                    $.widget.bridge("menu", $.apex.menu);

                }

            });

        }

    }

})(apex.jQuery);

Comments
Post Details
Added on Mar 27 2020
1 comment
338 views