Search code examples
jqueryjquery-pluginschainingjquery-chaining

Write a jQuery Plugin that return values


I'm writing a jQuery plugin that stores some data in some cases.

I'd like to write it in a very flexible way, where I'll can change an input parameter to obtain some value that were stored by the plugin.

Explanation:

When I call $("#any").myPlugin(), my plugin initializes creating a div and some a inside. Clicking on an a will store it .index() using the .data() method. If I call $("#any").myPlugin("getSelection") then I would like to get the value stored with .data().

What I'd tried:

(function ($) {
    $.fn.myPlugin = function (action) {
        if (action == null) action = "initialize";

        return this.each(function ($this) {
            $this = $(this);

            if (action == "initialize") {
                $this.html('<div></div>');
                var div = $("div", $this);

                div.append('<a>A</a>').append('<a>B</a>').append('<a>C</a>');

                div.children("a").each(function (i) {
                    $(this).click(function (event) {
                        // Here I store the index.
                        $this.data($(this).index());
                        event.preventDefault();
                        return false;
                    });
                });

                return $this;
            } else if (action == "getSelection") {
                // With this action, I tried to get the stored value.
                return $this.data("selectedValue");
            }
        });
    };
})(jQuery);

Simple call to create the elements:

$("#someElement").myPlugin();

And here I'd tried to get the index, without sucess:

alert($("#someElement").myPlugin("getSelection"));

So, is possible to do what I'm trying?


Solution

  • You need to change up the order a bit, like this:

    (function ($) {
        $.fn.myPlugin = function (action) {
            action = action || "initialize";
    
            if (action == "getSelection") {
              return this.data('index');
            }
    
            return this.each(function ($this) {
                $this = $(this);
    
                if (action == "initialize") {
                    $this.html('<div></div>');
                    var div = $("div", $this);
    
                    div.append('<a>A</a>').append('<a>B</a>').append('<a>C</a>');
    
                    div.children("a").each(function (i) {
                        $(this).click(function (event) {
                            // Here I store the index.
                            $this.data('index', $(this).index());
                            event.preventDefault();
                            return false;
                        });
                    });
    
                    return $this;
                }
            });
        };
    })(jQuery);
    

    The you can get the clicked index out like this:

    alert($("#someElement").myPlugin("getSelection"));
    

    You can give it a try here, the fundamental problem is you're trying to return a single value out of a .each() loop, which doesn't work. This instead grabs the data off the first object that matches the selector (#someElement in the example). Also .data() stores other things, so you need to give your value a key, like I'm using 'index' in the version above.