62

I know that you can add new jQuery functions by $.fn.someFunction = function()

However, I want to add functions to specific elements only. I tried this syntax and it doesn't work $('.someElements').fn.someFunction = function()

I want to do this so that I can call the function like this somewhere in the code $('someElements').someFunction();

  • I'm not sure if this is even possible, but if it was, why would you want to cripple your code? If you want to restrict it to certain selectors, use those selectors. Or, cache the result from `$('.someElements')` and call the function as that variable plus `.someFunction()` later. – Robert Jan 17 '11 at 03:37
  • The problem is $(...).fn doesn't exist, only $.fn. And just setting $(...).someFunction doesn't have the same effect, because it won't run it on each element in its own context. – crimson_penguin Jan 17 '11 at 03:41
  • @Robert I don't know why the OP wanted it, but I want to bind functions to elements so that the calling function doesn't need to differentiate between the elements. I have multiple field types each calling for it's own validation method -- since my AJAX call is mostly replicating what the form does without AJAX, it makes sense to write a single function that could call the validate function, then just use the name attribute and value to build up the POST data that would be sent if I used the HTML submit button. It just seems more OOP that way. – RonLugge Jan 14 '13 at 22:33
  • 1
    Simple: `var someElements = $('.someElements'); someElements.myFunc = function() { /* code here */ };` – jbyrd Aug 20 '15 at 03:05
  • Possible duplicate of [How to limit a jQuery plugin function to only some elements?](http://stackoverflow.com/questions/8519637/how-to-limit-a-jquery-plugin-function-to-only-some-elements) – Jonathan Hall Jan 04 '16 at 08:10

9 Answers9

59

For jQuery 1.7 and later, use .on() and .trigger()

$('button').on('someFunction',function() {
    alert('go away!')
});


$('button').click(function(){
    $(this).trigger('someFunction');
});

Before jQuery 1.7 we used .bind() method for attaching event handlers (instead of .on()).

Top-Master
  • 7,611
  • 5
  • 39
  • 71
Reigel Gallarde
  • 64,198
  • 21
  • 121
  • 139
  • 2
    and to get data returned by the function instead of jquery chaining use triggerHandler method – r043v Mar 25 '13 at 13:19
  • 9
    just an update here, 'bind' is deprecated and replaced with 'on' – DMTintner Jul 13 '15 at 07:26
  • 4
    It is not `someFunction`. It is `someEvent`. You bind an event handler for your custom event and triggers an event. To trigger an event and to invoke a plugin function are two different things. – Green Jun 27 '16 at 14:29
21

yo can do the above with this:

$.fn.testFn = function(){
    this.each(function(){
        var className = $(this).attr('class');
        $(this).html(className);
    });    
};

$('li').testFn(); //or any element you want

Test: http://jsfiddle.net/DarkThrone/nUzJN/

DarkThrone
  • 1,954
  • 1
  • 14
  • 14
  • 3
    there should be a return this in order to chain – qwertymk Jan 17 '11 at 03:55
  • @qwertymk: I know, it was to make a point, not to define an entire jQuery plugin. @Reigil: ibidem, I was trying to maka point, that this can already be achieved through jQuery. The entire answer makes no sense. You could select the exact set with $(..) instead of traversing all the matched DOM to eliminate via a new criteria. – DarkThrone Jan 17 '11 at 04:03
  • @DarkThrone what if i'd like to add a parameter to the function? I've tried to put it in the function() but it doesn't work. – javal88 Sep 21 '17 at 09:54
11

Yo, needed to do the same thing, came up with this. its nice cause you destroy the element and function goes poof! I think...

var snippet=jQuery(".myElement");
snippet.data('destructor', function(){
    //do something
});
snippet.data('destructor')();
BenMorel
  • 34,448
  • 50
  • 182
  • 322
Drizzel
  • 297
  • 3
  • 5
  • your destructor function will not be available inside other functions and events, if `snippet` is not global which is the case in most UI codes – AaA Jul 01 '20 at 09:42
10

@Reigel's answer is great! However you could also use the $.fn syntax and let your function only handle certain elements:

$.fn.someFunction = function(){
    this.each(function(){
        // only handle "someElement"
        if (false == $(this).hasClass("someElement")) {
            return; // do nothing
        }

        $(this).append(" some element has been modified");

        return $(this); // support chaining
    });    
};

// now you can call your function like this
$('.someElement').someFunction();            

See working jsfiddle: http://jsfiddle.net/AKnKj/3/

Friederike
  • 1,252
  • 15
  • 29
9

If you're wanting this function only for particular selectors, the following will work for you. I've just had a scenario where I've needed this and it works nicely.

$('.my-selector').each(function(){

    $(this).init.prototype.getUrl = function(){
        // do things
    };
})

then later on you can do

$('.my-selector').getUrl()

without having to define it as a plugin, or use data or bind/on/trigger events.

Obviously you can change the function to return the containing object if you want to use it in chaining by returning this

$('.my-selector').each(function(){

    $(this).init.prototype.getUrl = function(){
        // do things
        return this;
    };
})
dan richardson
  • 3,871
  • 4
  • 31
  • 38
  • 3
    this will attach getUrl to jquery not just for that element – Jithin Jose Sep 24 '14 at 05:32
  • Would love to why after 3 years, someone down-votes this. An explanation would be nice – dan richardson Nov 16 '17 at 10:09
  • 1
    I wasn't the one downvoting, but the downvote is probably 'cause this will NOT attach this function only for particular selectors, it will attach it to ALL elements (like commented by @JithinJose, this will attach getURL to jQuery, not just the element). There's a jsfiddle here: http://jsfiddle.net/xpvt214o/563274/ – patrick Aug 07 '18 at 10:31
  • @patrick I honestly don't know if it did previously, but did you stop to think that in 3-4 years that the framework may have actually also changed? After 7 years, I do not think stackoverflow should be the oracle of technical information for current releases of software! Think about it. – dan richardson Aug 07 '18 at 14:42
  • 2
    @danrichardson, I still found this answer when I was looking for an answer to a problem, so, no, I don't think it was a bad idea to tell others that have the same problem that the solution you posted isn't working, and apparently wasn't working in Sep '14 either... – patrick Aug 07 '18 at 21:39
  • For me this approach was the only one that worked ok, I needed to add a specific function to decorate a textbox result, so I did domObject.init.prototype.MyFunc... and then call MyFunc(), it worked sweet. Thanks. – Yogurtu Aug 26 '18 at 18:41
  • This is actually like https://learn.jquery.com/plugins/basic-plugin-creation/ like Jose said. It's important to note that `$({}).getUrl()` would also be valid. There's nothing wrong with this approach, as long as you don't call `getUrl` on objects that do not support it ;) – DerpyNerd Apr 09 '19 at 20:25
8

I actually had this use case as well, but with a cached object. So I already had a jQuery object, a toggle-able menu, and I wanted to attach two functions to that object, "open" and "close". The functions needed to preserve the scope of the element itself and that was it, so I wanted this to be the menu object. Anyway, you can just add functions and variables all willy nilly, just like any other javascript object. Sometimes I forget that.

var $menu = $('#menu');
$menu.open = function(){
   this.css('left', 0);
   this.is_open = true; // you can also set arbitrary values on the object
};
$menu.close = function(){
   this.css('left', '-100%');
   this.is_open = false;
};

$menu.close();
charltoons
  • 1,951
  • 2
  • 18
  • 24
  • This is a great way to handle it. Particularly this is useful if you've added something to the DOM (i.e. a pop-over window) and you only want the functions to be present for that one DOM element. So when you later remove the pop-over, the functions disappear along with it. You could also do it this way: `$('#menu')[0].open = function(){ ... };` So that you can get a handle and assign an arbitrary function to it all in one step. – JaredC Apr 18 '14 at 15:18
  • Nice idea, that I was looking for. Unfortunally it does not work. I get `open() is not a function` when I call it later in code. The problem is, that you bind your function to the jQuery object, not to the DOM. What means, when you access this DOM element later via another selector will no longer have a connection to the assigned function. – Radon8472 Feb 23 '23 at 08:43
  • Thx @JaredC your comment helped me to rework the code above for my desires – Radon8472 Feb 23 '23 at 09:33
2

The most obvious solution is to assign a function as the object's property:

obj.prop("myFunc", function() {
  return (function(arg) {
    alert("It works! " + arg);
  });
});

Then call it on the object this way:

obj.prop("myFunc")("Cool!");

Note: your function is the return value of the outer one, see: http://api.jquery.com/prop/#prop-propertyName-function

Snegh
  • 21
  • 1
1

I'm not also sure with my answer if this will help you but just a try how about using .live?

$(selector).live(click,function(){
    //some codes here
});
Carls Jr.
  • 3,088
  • 7
  • 37
  • 57
-1

I did this and its working fine..

 function do_write(){
     $("#script").append("<script> $(\'#t"+(id_app+4)+"\').change(function(){  alert('Write Your Code here');    });<\/script>");
     console.log("<script> $(\'#t"+(id_app+4)+"\').change(function(){  alert('hello');    });<\/script>");
}

and call function from your dynamic function which is creating a dynamic control in html

Raging Bull
  • 18,593
  • 13
  • 50
  • 55
dsk
  • 615
  • 1
  • 7
  • 19