JustAnotherDeveloper
JustAnotherDeveloper

Reputation: 3199

Function being called multiple times in jQuery plugin

Excuse the title, didn't know how to describe it really, as I'm not sure what's happening:

http://jsfiddle.net/KpmyR/7/

If you look at that JS fiddle, I am attempting to create my own nudging control to understand how plugins work. My plugin is called by $("#textbox1").DTJS()

With one item on the page, my plugin seems to work ok, when I add multiple instances of it to the page, the code appears to be firing exponentially. (I'm basically waiting for a onClick event in my plugin).

As it is at the moment, I have called my $("#textbox1").DTJS() Three times like below:

$(document).ready(function () {
$("#textbox1").DTJS({
    'width': '75px',
    'max': '15',
    'min': '5'
});

$("#textbox2").DTJS({
    'width': '75px',
    'max': '15',
    'min': '5'
});


$("#textbox3").DTJS({
    'width': '75px',
    'max': '15',
    'min': '5'
});
});

If I click on the bottom one, it increments/deincremements by 1, if I click the middle it does it by 2, and if I click the top one it does it by 3.

Could someone please outline why this is happening?

Upvotes: 3

Views: 1426

Answers (3)

lbstr
lbstr

Reputation: 2832

just change this:

$('.valueUp').click(...);

to this:

$(this).siblings('.valueUp').click(...);

The same is true for .valueDown.

By binding an event to just .valueUp, you are binding it to any .valueUp on the page, which explains why the event gets bound 3 times on the first one and 2 times on the second one.


A couple of other tips:

  • this is already a jQuery object

    As Snuffleupagus pointed out, this is already a jQuery object, so you don't need to call $(this). This is true for any function you add to $.fn.

  • return this

    By returning this at the end of the plugin, you maintain chainability. For example, if you add return this to the end of your plugin, you could do something like this:

    $("#textbox1").DTJS({'width':'75px', 'max':'15', 'min':'5'}).fadeIn();

Upvotes: 2

Giles Smith
Giles Smith

Reputation: 1972

I think the problem that you are having is with the click event handler:

$(".valueUp").click( function() {...})

The selector that is used in this line selects all elements with a class of valueUp. However as you add more nudge controls to the page, the event handler is run for each button on the page - resulting in the value being nudged by as many as there are controls on the page.

There are a couple of options:

Change the selector to be id based to a unique id, or change the selector so that it is relative to the input control itself.

Here is a working example in jsFiddle: http://jsfiddle.net/Xfp8a/

Upvotes: 0

Snuffleupagus
Snuffleupagus

Reputation: 6755

You're applying your events via a class, so each time you call your plugin you're binding another event to all instances of .valueUp and .valueDown.

Consider keeping a copy when you create your buttons and binding the events from your stored copy. (If you're selecting the same element multiple times in the same scope you're better off storing it in memory.)

e.g.,

var up = $('<button class="valueUp valueHoldDown btn-mini btn-primary' + settings.btnClass + '">-></button>');
this.after(up);
up.click(function(){ 
    // code 
});

Also note that when jQuery calls a function from jQuery.fn, this refers to the jQuery object rather than raw elements so you don't need to do $(this).

Upvotes: 3

Related Questions