chris
chris

Reputation: 36937

jQuery Plugin - How to add / bind events

Ok this is my first stab at creating a jQuery plugin so I am going off tutorials currently.

This far I have

(function($)
{
    $.tippedOff = function(selector, settings)
    {
        var config = {
            'top':0,
            'left':0,
            'wait':3000
        };
        if(settings){$.extend(config, settings);}

        var $elem = $(selector);
        if($elem.length > 0)
        {
            $elem.each(function()
            {
                $(this).css({"color":"#F00"});
            })
        }

        return this;
    };
})(jQuery);

Which works for changing the text color of the provided elements. However. I want to add functionality to elements that the plugin takes effect on. Such as a hover or click event. But I can't wrap my head around that idea at the moment, seeing as the selector can be anything. So its not like I can hardcode something in per say thats specific like I would through normal jQuery methods.

So, with that, how do I go about adding that type of functionality to things after its been rendered?

Upvotes: 6

Views: 6985

Answers (2)

Dimi
Dimi

Reputation: 269

I have not enough reputation points to comment and fully agree with Dom, who is very knowledgeable. I only would like to add that within the changed code it would be better to create a local variable by using the var keyword:
var $this = $(this);
This will make the plugin better and allows you to apply the plugin to multiple elements one the page as for example:
$('#testX').tippedOff2();
$('#testY').tippedOff2();
$('#testZ').tippedOff2();

Upvotes: 4

Dom
Dom

Reputation: 40459

When creating plugins, it is very easy to over-complicate things, so try to keep things nice and simple.

I have provided you with TWO examples of the tippedOff plugin. Here is also a jsfiddle demo of both plugins.

The first uses your original code as is (NO SIGNIFICANT CHANGES MADE):

$.tippedOff = function(selector, settings)
    {
        var config = {
            'top':0,
            'left':0,
            'wait':3000
        };
        if(settings){$.extend(config, settings);}

        var $elem = $(selector);
        if($elem.length > 0)
        {
            $elem.each(function()
            {
              //bind mouseenter, mouseleave, click event
                $(this).css({"color":"#F00"})
                .mouseenter(function(){
                  $(this).css({"color":"green"});
                })
                .mouseleave(function(){
                  $(this).css({"color":"#F00"});
                })
                .click(function(){
                  $(this).html('clicked');
                });

            })
        }

        return this;
    };

This one, however, is based on your original code. Basically, I have reconstructed your original code using these tips. This is how I would personally go about it. I have also provided you with a breakdown below of changes made. (SIGNIFICANT CHANGES MADE):

$.fn.tippedOff = function(settings) {
      var config = $.extend( {
          'top':0,
          'left':0,
          'wait':3000,
          'color': 'orange',
          'hoverColor': 'blue'
      }, settings);

      return this.each(function() {
          $this = $(this);
          $this.css({ 'color': config.color})
          .mouseenter(function(){
             $this.css({ 'color': config.hoverColor });
          })
          .mouseleave(function(){
             $this.css({ 'color': config.color });
          })
          .click(function(){
             $this.html('clicked');
          });
      });
    }

----------------------------------------

Breakdown:

Original Code:

$.tippedOff = function(selector, settings) {

Changed:

$.fn.tippedOff = function( settings ) { 

Comments:

The difference between $.tippedOff and $.fn.tippedOff is huge! Adding your plugin to the $.fn namespace rather than the $ namespace will prevent you from having to provide a selector and makes life simplier.

I personally like this answer, in which @Chad states:

My rule of thumb I follow is: use $. when it is not DOM related (like ajax), and use $.fn. when it operates on elements grabbed with a selector (like DOM/XML elements).


Original Code:

if(settings){$.extend(config, settings);}

Changed:

var config = $.extend( {
          'top':0,
          'left':0,
          'wait':3000
      }, settings);

Comments:

Having an if statement is redundant. .extend() does all the work for you.


Original Code:

var $elem = $(selector);
        if($elem.length > 0)
        {
            $elem.each(function()
            {
                $(this).css({"color":"#F00"});
            })
        }

        return this;

Changed:

return this.each(function() {
          $this = $(this);
          $this.css({ 'color': config.color});
});

Comments:

Using return this.each(function(){}) is good practice and maintains chainability. Not only that, you will no longer need to worry about the selector's length.


*NOTE: If you want to add additional events, then use different methods within your plugin: jQuery Doc Reference - Authoring Plugins.

I hope this helps and please let me know if you have any questions!

Upvotes: 21

Related Questions