15

I'm trying to set some data on my buttons such that it can be accessed onclick. I'm having no problem using JSON in a button's data attribute where the key value is a string. However, I can't figure out how to set the values to be a function.

What I'd like to happen upon clicking the button in this demo code is for the click event to call the function option1() which will alert the string "hello outside".

The error I'm getting is this:

Uncaught TypeError: Property 'option1' of object #<Object> is not a function

HTML (JSFiddle is here: http://jsfiddle.net/NDaEh/32/):

<button type='button' data-button='{"option1": "option1", "option2": 
"option2"}'>click1</button>

JS:

var data='hello outside';
var option1=function(data){
    alert(data)
}  

$('button').click(function(){
  //var data='hello inside';
  $(this).data('button').option1(data); // should alert 'hello outside'
});

Thoughts?

tim peterson
  • 23,653
  • 59
  • 177
  • 299

3 Answers3

31

Use the following code to get the values in your HTML:

$('button').click(function(){
  var data = $.parseJSON($(this).attr('data-button'));
  alert(data.option1)
});

This code is specifically for your requirement. By this way, you can store data in HTML and retrieve in JavaScript code.

Updated the JSFiddle code, working code is available at: http://jsfiddle.net/NDaEh/51/

EDIT:

Solution to call a function dynamically: http://jsfiddle.net/NDaEh/70/ HTML:

<button type='button' data-button='{"func": "func1"}'>click1</button>
<button type='button' data-button='{"func": "func2"}'>click2</button>

JS:

var myFuncs = {
  func1: function () { alert('Function 1'); },
  func2: function () { alert('Function 2'); },
};

$('button').click(function(){
  var data = $.parseJSON($(this).attr('data-button'));

  myFuncs[data.func]();
});
tim peterson
  • 23,653
  • 59
  • 177
  • 299
IvenMS
  • 525
  • 5
  • 19
  • thanks @IvenMS but the key thing I want is that data.option1 is itself a function and not just a string. So writing data.option1(data) calls the alert function and not vice versa. – tim peterson Oct 11 '12 at 09:41
  • Try this: `var alert_data='hello outside'; function option1 (data){ alert(data) } $('button').click(function(){ var data = $.parseJSON($(this).attr('data-button')); window[data.option1](alert_data); });` – IvenMS Oct 11 '12 at 09:51
  • The idea is to run the function declared in your document with `window["function_name"](arguments);`. Please check.... – IvenMS Oct 11 '12 at 09:57
  • I understand the concept but your code is not working, its giving same error of `option1` not being a function as I was first getting – tim peterson Oct 11 '12 at 10:05
  • 1
    Try this link: http://jsfiddle.net/NDaEh/66/ It is working. The concept is little different, but the same logic. – IvenMS Oct 12 '12 at 05:33
  • that is exactly what I was looking for, can you put this jsfiddle in your answer, I'll accept it, thanks for pursuing this, really appreciate it! – tim peterson Oct 12 '12 at 10:36
7

Dont save objects as JSON strings in the html tag property value. Use the data() method instead.

$('input[type="button"]').data({ option1: 'o1', option2: 'o2' });

Also, when youre writing this:

$(this).data('button').option1(data);

option1 would need to be a plugin in order to be chained on to the data method (or any jquery method for that matter). You would need tomething like this:

jQuery.fn.option1 = function () {

   alert($(this).data('option1'));

   return this;
}

Fiddle

Johan
  • 35,120
  • 54
  • 178
  • 293
  • why can't i save objects as JSON strings? also i don't want to generate this data using JS b/c it will be highly variable across my app and i've already spent the time to generate it with server side code (logic is wired in my mysql database) – tim peterson Oct 11 '12 at 09:05
  • 1
    @timpeterson Well, html tags property values should be wrapped with double quotes. JSON strings should be as well. So I wouldnt recommend it. You would end up with either invalid html or json. – Johan Oct 11 '12 at 09:10
  • @timpeterson How are you fetching the data from the server? By ajax? Or are you just printing it directly in to the html? And what serverside language are you using? – Johan Oct 11 '12 at 09:12
  • I'm just printing the HTML. I don't want to do that and then write all these $('button').data() assignments across my entire app since there are many different buttons and many different assignments. – tim peterson Oct 11 '12 at 09:15
  • @timpeterson Ok, if you insist on sticking with inline string objects, you could use the code that i posted and format then using `var myObject = $.parseJSON($(this).attr('data-button'))` – Johan Oct 11 '12 at 09:19
  • ok thanks yes i see $.parseJSON but using `myObject.option1(data)` still isn't alerting "hello outside". would you mind adding what you think works to this jsfiddle: http://jsfiddle.net/NDaEh/32/ ? – tim peterson Oct 11 '12 at 09:27
  • 1
    @timpeterson Sorry about the delay, i went for lunch. Check out the fiddle that i posted. Is this what you need? – Johan Oct 11 '12 at 10:30
  • yes that' s on the right track, I don't need to extend the jquery object, it could extend some smaller object using a similar syntax right? – tim peterson Oct 11 '12 at 10:35
  • 1
    @timpeterson If you want to write a custom jquery method (aka plugin), thats how its done (In other words, as long as you want to use your method directly on the jquery object). If you dont want to do that you could extract the data object and pass it to your regular function and handle it there. – Johan Oct 11 '12 at 10:52
2

Use the jQuery data as shown below:

$('input[type=button]').data('button-data', { option1: 'option1', option2: 'option2});

Use:

$('input[type=button]').data('button-data');  //{ option1: 'option1', option2: 'option2}

In order to get the data from the element

udidu
  • 8,269
  • 6
  • 48
  • 68