views:

57

answers:

1

Hi everyone,

I have a strange jquery problem with multiple event handlers. What I'm trying to achieve is this:

  1. User selects some text on the page
  2. If the selection is not empty - show a context menu
  3. If user clicks somewhere else - the context menu should disappear

I'm having troubles with the above i.e. sometimes the context menu appears correctly, sometimes it appears and disappears straight after user makes a selection. Please help. See the relevant parts of my code below. Also when user selects a paragraph or a word by double clicking - context menu appears and quickly disappears again.

var ContextMenu = {
   ...
        show: function(e) {
            var z = this;
            if (!this.shown) {
                if (this.contextMenu) {
                    this.contextMenu.css({
                        left: e.pageX,
                        top: e.pageY
                    }).slideDown('fast');
                    this.shown = true;
                }
                var hideHandler = function() {
                    z.hide(this);
                };
                $(document.body).bind("click", hideHandler);
            }
        },
        hide: function(hideHandler) {
            if (this.contextMenu && this.shown) {
                this.contextMenu.slideUp('fast');
                this.shown = false;
                $(document.body).unbind("click", hideHandler);

            }
        }
};
    // Context menu display logic
    $(document.body).bind("mousedown mouseup", function(e) {
        if ((window.getSelection().toString() != "") && (!ContextMenu.shown)) {
            ContextMenu.show(e);
        }
    });
A: 

See if binding the event only to mouseup helps:

$(document.body).bind("mouseup", function(e) {
     if ((window.getSelection().toString() != "") && (!ContextMenu.shown)) {
         ContextMenu.show(e);
     }
 });

From what I unserstand you don't need to bind it to the mousedown event.

I think, if you bind it to the mousedown event and the user makes a selection by dragging the mouse (and pressing the button), your context menu is shown (mousedown) and the click handler is bound to the document while the mouse button is still pressed. Thus, after releasing the mouse button (as of finishing the selection), a click is performed and the previously bound click handler gets executed, making the menu disappear again.

I could be wrong though ;)

Felix Kling
Thanks for the answer Felix, unfortunately that didn't solve it :( After changing to 'mouseup' - my context menu appears and immediately disappears 100% of times. Don't know what to do about it.
Greg
@Felix - I'd try a `setTimeout()` on binding the hide click handler ;)
Nick Craver
Following Nick Craver's advice I tried changing this line: $(document.body).bind("click", hideHandler);to: setTimeout(function() { $(document.body).bind("click", hideHandler); }, 2000);It works only once - and the context menu exhibits correct behavior. However, after that things roll back to "appear/disappear immediately".Any other thoughts?I kinda added a 'close' button to my context menu and it works fine, though it is not very elegant.
Greg