views:

156

answers:

5

I know how to bind multiple events and all that stuff. What I want to do is have multiple events occur to trigger a function.

Like

$(this).click and $(this).mousemove triggers a function

Is there a way to do this? Is it possible or am I just dreaming.

+2  A: 

With a better understanding now, one thing you could do is have one event bind and unbind the other:

Example: http://jsfiddle.net/ZMeUv/

$(myselector).mousedown( function() {
    $(document).mousemove(function() {
        // do something
    });

    $(document).mouseup(function() {
        $(this).unbind();  // unbind events from document
    });
});

This prevents the mousemove from constantly firing when you have no need for it.

patrick dw
No, you guys think I want to bind multiple events to the same function. What I want to do is REQUIRE certain events. Like if you want an item to hide, the user would have to invoke Click() and MouseMove(). Also, the $(this) is just a general selector. It doesn't mean anything.. just filler.
Glenn Nelson
@user - There are ways to do this. I'll change my answer with one idea.
patrick dw
+2  A: 

Try something like this?

var isDown = false;

$(sel).mousedown(function() {
    isDown = true;
});

$(sel).mouseup(function() {
    isDown = false;
});

$(sel).mousemove(function() {
    if (isDown) {
         // Mouse is clicked and is moving.
    }
});
Alexsander Akers
You should probably change the `mouseup` to run against the `document`. The way it is, if the user does `mousedown` on the selector, moves the mouse off, then does mouse up, the `isDown` variable will remain `true`.
patrick dw
A: 

If I'm reading your question correctly, you're asking about requiring the combination of multiple events to trigger a single function. It's possible to achieve this sort of thing, but I think it will depend greatly on the specific events and the logic or illogic of their combination. For example, the mousemove event:

...is triggered whenever the mouse pointer moves, even for a pixel. This means that hundreds of events can be generated over a very small amount of time.

Contrast that with the mousedown event, which is -- well, one per click. How to combine? The jQuery API goes on to state:

A common pattern is to bind the mousemove handler from within a mousedown hander [sic], and to unbind it from a corresponding mouseup handler. If implementing this sequence of events, remember that the mouseup event might be sent to a different HTML element than the mousemove event was. To account for this, the mouseup handler should typically be bound to an element high up in the DOM tree, such as <body>.

Perhaps another approach would be to create a primitive finite state machine to ingest as inputs the various relevant events you have in mind, update its state accordingly, and then trigger a custom event when appropriate states are achieved. This all smells a little bit like reinventing the wheel, but maybe your requirement is very specific or unusual.

References: jQuery API: mousemove()

Ken Redler
+2  A: 

You can use jQuery's special events to package everything nicely and optimize things in the process. A mousedown and mousemove combo also commonly goes by the name "drag", so here's an example of creating a drag event that you can bind to elements. Note, that this code is specific to jQuery 1.4.2

One of the advantages to using this is that you only bind the mousemove, mouseout, and mousedown handlers once each element, no matter how many times that element is bound to the drag event. Now this isn't the most optimal way of doing it, and you can setup just 3 handlers on the document and manage everything with it, which is equally easy to do with the special events API. It just provides a nicely packaged way of building complex interactions than would be possible with just native events or custom events, in the jQuery sense.

$("..").bind("drag", function() {
   ...
});

I will try and add more documentation on what's actually going on, as it looks pretty unintuitive, I must confess. Checkout another nice article on the topic.

See an example of this here. To create this custom special event, use:

jQuery.event.special.drag = {
    // invoked each time we bind drag to an element
    add: function(obj) {
        var originalHandler = obj.handler;

        obj.handler = function(event) {
            var el = jQuery(this);

            if(el.data('mousePressed')) {
                return originalHandler.apply(this, arguments);
            }
        };
    },

    // invoked only the first time drag is bound per element
    setup: function(data, namespaces) {
        var el = jQuery(this);

        el.data('mousePressed', false);
        el.bind('mousedown', function() {
            jQuery(this).data('mousePressed', true);
        });
        jQuery(document).bind('mouseup', function() {
            el.data('mousePressed', false);
        });
        el.bind('mousemove', jQuery.event.special.drag.handler);
    },

    // invoked when all drag events are removed from element
    teardown: function(namespaces) {
        var el = jQuery(this);

        jQuery.removeData(this, 'mousePressed');
        el.unbind('mousedown');
        el.unbind('mouseup');
    },

    // our wrapper event is bound to "mousemove" and not "bind"
    // change event type, so all attached drag handlers are fired
    handler: function(event) {
        event.type = 'drag';
        jQuery.event.handle.apply(this, arguments);
    }
};
Anurag
A: 

Alright, thanks for your idea Patrick. It reminded of a way I had done something like this in Java.

var m_down = false; $(this).mousedown(function() {

 m_down = true;

});

$(this).mouseup(function() {

 m_down = false;

});

$(this).mousemove(function() {

 // Code to occur here

});

Glenn Nelson