javascriptjqueryjquery-uijquery-ui-selectmenujquery-ui-menu

jQuery UI: How to check whether another instance of widget is opened?


I've created custom widget by extending jQuery UI's Menu. It's basically needed to work with <select> HTML element like ui.selectmenu does, but display options in submenus:

$.widget("market.myMenu",$.ui.menu, {
// ...
_attachEvents: function(){
    var self = this;
    // menu is initially hidden
    self.menuWrapper.hide();
    self.button.on('click', function(){
        if (self.originalSelect.is(':disabled')) {
            self.disable();
        } else {                
            self.menuWrapper.toggle();
        }
        return false;
    });

    $(document).on('click', function(){
        self.menuWrapper.hide();
    });             
},
//...
  }
}

The problem arise when this widget attached to multiple elements like:

someSelect.myMenu();
//...
anotherSelect.myMenu();

The problem is listed in the title and you can see it in _attachEvents() method:

  1. when user clicks on someSelect it opens as should
  2. then user clicks on anotherSelect it also opens
  3. someSelect after step 2 should be closed, but it's not.

So how to check for such a case and fix this issue ?

EDIT:

  1. this.originalSelect is <select> HTML element
  2. this.button is div element. on which selected option text is displayed (basically same thing as ui.selectmenu does);

Solution

  • You can use a class to keep track of the state of your menus and use it to target instances that are opened. Something like this for example:

    _attachEvents: function(){
        var self = this;
        // menu is initially hidden
        self.menuWrapper.hide();
        self.button.on('click', function(){
            if (self.originalSelect.is(':disabled')) {
                self.disable();
            } else {
                // before you open a menu, you close the opened ones
                $('menu-opened').each(function(){
                    $(this).myMenu('instance').hideWrapper();
                });
                self.menuWrapper.toggleClass('menu-opened');                
                self.menuWrapper.toggle();
            }
            return false;
        });
    
        $(document).on('click', function(){
            self.menuWrapper.hide();
        });             
    },
    
    hideWrapper: function(){
        var self = this;
        self.menuWrapper.hide();
        self.menuWrapper.removeClass('menu-opened');
    }