0

I am trying to create a jQuery plugin. When configuring the plugin, I wish to define an object which will be posted via Ajax. One of the properties in the object value2 is based on the element which the plugin was applied to (a.myClass), and I thought I would try something like the following:

post:{value1:1,value2:function(t){return $(t).data('id');},value3:3}  

But, within the plugin, the object is equal to { value1=1, value3=3, value2=function()}, and if posted, value2 is sent as undefined. I've found that I could access the value using settings.post.value2(this), however, I don't know how this helps me. I suppose I could loop through the object and evaluate each property, but this just doesn't seem right.

What is the proper way of doing this? Thank you

http://jsbin.com/sedoqeluni/1/

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>editSelect</title>  
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.js" type="text/javascript"></script>
        <script type="text/javascript"> 
            (function($){
                var methods = {
                    init : function (settings) {
                        return this.each(function () {
                            $(this).click(function(e) {
                                console.log(settings.post);
                                console.log(settings.post.value2(this));
                                $.post('testing.php',settings.post);
                            });
                        });
                    }
                };
                $.fn.testit = function(method) {
                    if (methods[method]) {
                        return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
                    } else if (typeof method === 'object' || ! method) {
                        return methods.init.apply(this, arguments);
                    } else {
                        $.error('Method ' +  method + ' does not exist on jQuery.testit');
                    }    
                };
                }(jQuery)
            );
            $(function(){
                $('.myClass').testit({
                    foo:'bar',
                    post:{value1:1,value2:function(t){return $(t).data('id');},value3:3}
                });
            });
        </script>
    </head>

    <body>
        <a class="myClass" href="javascript:void(0)" data-id="2">hello</a>
        <a class="myClass" href="javascript:void(0)" data-id="222">hello</a>
    </body>
</html>
user1032531
  • 24,767
  • 68
  • 217
  • 387

1 Answers1

1

Your inline function should be called to return a value:

post:{value1:1, value2: (function(t){return $(t).data('id');})(t), value3:3}

Or using not inline function to be more readable:

var getValue2 = function(t) {
    return $(t).data('id');
};
....
post:{value1:1, value2: getValue2(t), value3:3}

UPDATE

Guess t should be the same element .myClass. So the code will be

 $(function(){
   $('.myClass').each(function() {
     $(this).testit({
       foo:'bar',
       post:{
         value1:1,
         value2: (function(t){return $(t).data('id');})(this),
         value3:3
       }
     });
   });
 });

UPDATE#2

But code from UPDATE may be simplified to read data-id directly without any inline functions:

 $(function(){
   $('.myClass').each(function() {
     var $this = $(this);
     var id = $this.data('id');
     $this.testit({
       foo:'bar',
       post:{
         value1: 1,
         value2: id,
         value3: 3
       }
     });
   });
 });

UPDATE#3

I've found that I could access the value using settings.post.value2(this), however, I don't know how this helps me. I suppose I could loop through the object and evaluate each property, but this just doesn't seem right.

Well it's quite normal approach if your plugin should accept functions as parameters. So it's up to you how to handle parameters.

There may be some enchantment to be made to improve function determination. Refer How can I check if a javascript variable is function type?.

$(this).click(function(e) {
  console.log(settings.post);
  console.log(settings.post.value2(this)); // <--- here you can add a check if value2 is a simple parameter or function
  // and replace value
  // something like this
  if (isFunction(settings.post.value2)) {
    settings.post.value2 = settings.post.value2(this)
  }
  $.post('testing.php',settings.post);
});
Community
  • 1
  • 1
phts
  • 3,889
  • 1
  • 19
  • 31
  • Haven't tried your second solution yet, but the first returns `t is not defined` error. http://jsbin.com/pupiposami/1/ – user1032531 Mar 28 '15 at 21:46
  • Well because `t` was not defined in your code initialy :) I don't know your logic and where `t` should be taken from – phts Mar 28 '15 at 21:50
  • `t` should be some element which `data('id')` will be returned – phts Mar 28 '15 at 21:51
  • Maybe I am going about this all wrong. I just wish to post `data('id')` to the server. But want this scope to be in the configuration, and not in the main plugin. – user1032531 Mar 28 '15 at 21:52
  • http://jsbin.com/pupiposami/1/ `this` is not the element, but the window I think. – user1032531 Mar 28 '15 at 21:59
  • Ah, I didn't originally notice you changed it from how I had it to adding the `each` method. Yes it seems to work. Thank you. Why is the `each` method needed? – user1032531 Mar 28 '15 at 22:03
  • *Why is the each method needed* - To get `id` data from every element found in `$('.myClass')` – phts Mar 28 '15 at 22:09
  • Ah, I had been looking on that same post referenced by your Update #3. Didn't know if it was a normal approach to cycle through them, but don't see why it wouldn't. Thanks for your help. – user1032531 Mar 28 '15 at 22:17