views:

122

answers:

5

What is the best way to embed data in html elements for later use?

As an example, let's say we have jQuery returning some JSON from the server, and we want to dump that datat out to the user as paragraphs. However, we want to be able to attach meta-data to these elements, so we can events for these later.

The way I tend to handle this, is with some ugly prefixing

function handle_response(data) {
    var html = '';
    for (var i in data) {
        html += '<p id="prefix_' + data[i].id + '">' + data[i].message + '</p>';
    }
    jQuery('#log').html(html).find('p').click(function(){
            alert('The ID is: ' + $(this).attr('id').substr(7));
    });
}

Alternatively, one can build a Form in the paragraph, and store your meta-data there. But, that often feels like overkill.

This has been asked before in different ways, but I do not feel it's been answered well:

+1  A: 

depending on what the metadata is for, you could start adding classes to the paragraphs:

<p class="some-paragraph meta meta2 meta3">

This shouldn't affect the styling of your page negatively, unless there are collisions between the metadata and existing CSS classes.

Carson Myers
This works well when you want to store some fact about each element, for instance <p class="prefix-has-specialness">. But, not so well when you want to retrieve store data, for instance a unique-id.
Rob Colburn
+2  A: 

Assuming that you are staying on the page...

jQuery has a data function which allows you to store data on an element by key. eg

$('#mydiv').data('mykey', mydata);

Use the following syntax to retrieve the data:

var x = $('#mydiv').data('mykey');

If you don't know which element to use just use $(document)

James Westgate
You could use data function for (var i in data) { $('#log').append($('<p>'+data[i].message+'</p>').data('d',data[i])); } $('#log').find('p').click(function(){ alert('The ID is: '+$(this).data('d').id); });Or, bind individually function format(d) { return $('<p>'+d.message+'</p>').click(function(){ alert('The ID is: '+d.id); }); } for (var i in data) { $('#log').append(format(data[i])); }Not sure which performs better, especially for larger datasets.
Rob Colburn
Ugh - bad Stack Exchange, see the code better here: http://tinypaste.com/7b0f9
Rob Colburn
+4  A: 

HTML5 now supports the data-name syntax for storing abitrary data without non-standard custom attributes

This will of course break validation if your doctype is anything other than HTML5 (although there are ways around this) but it wont affect the rendering or parsing in any browsers I've come across.

Here is an excellent article by John Resig on the matter

Neil Aitken
+1 This is the best way to do it - your validation won't break if you prefix the attribute with "data-". I believe jQuery's metadata plugin (http://plugins.jquery.com/project/metadata) uses this method
Jeriko
A bit concerned about validation, but more concerned about legacy browsers. I believe some browsers may treat unrecognized element attributes as invalid code, and discard them - thereby preventing their retrieval in javascript.
Rob Colburn
A: 

One method that I commonly use (in lieu of HTML5's data features) is to make use of hidden input tags eg.

<a href="#" id="containing_element">
Content
<input type="hidden" id="key" value="value" />
</a>

Then, if you don't mind a jQuery example..

$('a#containing_element').click(function(){
     var data = $(this).children('input#key').attr('value');
});

Simple, it validates, it works now and you can use this to store whatever sort of information you like (even arrays if you serialize and htmlencode them)

FelixHCat
A: 

As an alternative to the other methods mentioned, if you're willing to exclude IE6 (it's about that time), you can use DOM storage (i.e. the globalStorage, sessionStorage and localStorage objects) to store your JSON string. These objects are key value stores, so if the browsers you're targeting support this feature (part of the HTML5 specs), then this is probably easier than storing data in arbitrary HTML elements. See here for more info.

wsanville