28

Most jQuery plugins are tied/bound to a DOM node when you first initialize them.

$('#foo').bar({options: ...});

How can you check to see what plugins or objects are currently bound to a DOM node like #foo?

if($('#foo').bar)
if($.inArray('bar', $('#foo').eq(0)))
if($('#foo').eq(0).indexOf('bar'))
if($('#foo').hasOwnProperty('bar'))

For example, it's possible to get the events bound to an object like this

console.log($('#foo').data('events'));
Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • 2
    Would surely like to know this answer. It will help in debugging. – Pulkit Mittal Oct 30 '12 at 16:43
  • How exactly would you define _bound to a DOM node_? Add [jquery-ui.js](http://code.jquery.com/ui/1.9.1/jquery-ui.js) in you page and every element will have `.dialog()`, `.autocomplete()` etc added to it automatically. They get bound to _every_ node. – Salman A Oct 30 '12 at 17:29
  • @SalmanA, I just mean that a plugin is actively monitoring or affecting a DOM element. – Xeoncross Oct 30 '12 at 17:30

3 Answers3

9

Unless the plugin itself defined some way of altering the element(s) it's working on, it's not possible. For example:

$.fn.extend({
  foo: function() { console.log("I am foo!"); }
});

$('#bar').foo();

Here I defined a complete (well, more-o-less) jQuery plugin which doesn't even try to interact with its calling element. Still, you can use it as you wish, on any jQuery-wrapped collection of elements, as any jQuery-wrapped collection of elements has this method in its prototype because of this line (from jquery.js):

jQuery.fn = jQuery.prototype = { ... }

... after $.fn.extend was called to plug in that plugin, no pun intended.

But even if my plugin were required to change its calling element in some way, like this:

$.fn.extend({
  bar: function() { this.html('I am all bar now!'); }
});
$('#bar').bar();

... I would still need to, basically, handle this with some external events (DOM Mutation ones), and not just depend on some internal jQuery logging.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • 1
    While this is certainly true, (and perhaps the answer), most plugins do alter the element or log an instance back in the plugin object. They must leave some kind of generic property that can be traced. Perhaps events, classes, ID's, `.data`, or something else. – Xeoncross Oct 30 '12 at 17:13
  • @Xeoncross Why it should be a _generic_ property, if jQuery does not have any restrictions about the plugin's behaviour? – raina77ow Oct 30 '12 at 17:16
  • Perhaps it is better said as a "generic place" for a property. At any rate, there are often patterns you can employ with situations like this to detect things. For example, many plugins add something to `.data()`. – Xeoncross Oct 30 '12 at 17:19
  • 1
    @xeoncross: whatever jQuery does behind the scenes is not documented so it may change without notice. – Salman A Oct 30 '12 at 17:20
4

In my case, the plugin I was attempting to detect happens to add some data to the elements $(element).data() store. I've also seen plugins add classes or ID's with either their name - or alterations of their name in them.

Below is the code I am currently working with to solve this problem. Probably don't work for most plugins though.

$.fn.extend({
    isPluginBound: function(pluginName)
    {
        if(jQuery().pluginName)
        {
            var name = pluginName.toLowerCase();

            return this.data(pluginName) || this.data(name)
                || this.attr('class').toLowerCase().indexOf(name) !== -1 // vs hasClass()
                || this.attr('id').toLowerCase().indexOf(name) !== -1;
        }
    }
});

To use it just call $('#foo').isPluginBound('bar');

Xeoncross
  • 55,620
  • 80
  • 262
  • 364
  • 1
    Perhaps I'd replace `if (jQuery().pluginName)` with `if ($.fn[pluginName])` here, but that's just a sidenote. As a matter of fact, jQuery UI plugins do store their names in affected elements' `data`, so your approach is _probably_ valid for them. Still, that's relying on internals. – raina77ow Oct 30 '12 at 17:49
  • And as another sidenote, perhaps it'd be nice to return a boolean from `isPluginBound` in any case (with `!!`-wrapping that check expression, for example). – raina77ow Oct 30 '12 at 17:57
  • Always worth checking the .data(), thanks - helped me! – iamkeir Aug 07 '15 at 21:54
1

as far as i know all jQuery Widgets append their instance to their DOM node. im using follwing extension in my projects. it is also useful to call a method on a widget you dont know the name of ( calling a base method of an extended widget for example )

// returns first found widget instance of the first element or calls method on first widget instance of all elements
$.fn.widget = function ( method , option, value ) { 
  var wi;
  // iterate all elements 
  this.each( function() {
    var wii;
    // iterate all attached data elements, look for widget instances
    $.each( $(this).data(), function( key, data ){ 
      if ( "widgetName" in data ){ wii = data; return false } 
    })
    // if there is a widget instance but no method specified
    if ( wii && !method ) {
      wi = wii;
      return false
    }
    // if there is a widget and there is an object found with the method as the key
    else if ( wii && ( method in wii ) ) {
      // if it is truly a method of that instance, call that instance
      if ( $.isFunction( wii[method] ) ) {
        wi = wii[method].call( wii, option, value )
      } 
      // else, it is maybe a value stored in the instance you seek?
      else {
        wi = wii[method]
      }
    }
  })
  return ( wi === undefined ) ? this : wi ;
}
lordvlad
  • 5,200
  • 1
  • 24
  • 44