简体   繁体   中英

html & javascript: How to store data referring to html elements

I'm working on a web application that uses ajax to communicate to the server. My specific situation is the following:

I have a list of users lined out in the html page. On each of these users i can do the following: change their 'status' or 'remove' them from the account.

What's a good practice for storing information in the page about the following:

  • the user id
  • the current status of the user

PS: I'm using jQuery.

There is jQuery's data function

$('li').data('userid',uid); // sets the value of userid
uid = $('li').data('userid'); // retrieves the value of userid

official documentation: http://docs.jquery.com/Data

There is a lot of debate as to what is best to use. You can store the data a lot of ways, and they all make someone happy - custom attributes will of course not validate if you use XHTML, and using classes to store one or two bits of data is clumsy at best and only gets worse with the amount of things you want to know. Personally, not only am I not a big fan of XHTML, I am also not much of a validation nazi, so I recommend going with the custom attributes.

There is, however, an option that reconciles custom attributes with standards: data- attributes. As John Resig (the author of jQuery) writes about in his blog , this is a new attribute being introduced in HTML5 that allows you to specify custom data attributes with the data- prefix. So a perfectly valid element might look like this:

<ul>
    <li data-userid='5' data-status='active'>Paolo Bergantino</li>
</ul>

This has the upside that while you are still using custom attributes which may be bad if you are using XHTML, your code is going to age very well as this is the way that we will be storing data related to a particular item in the future.

Some further reading is Attributes > Classes: Custom DOM Attributes for Fun and Profit.

Perhaps using custom attributes, so for a user's list element, add attributes for the variables:

<li uid="theuserid" ustatus="thestatus"></li>

The values can then be got with the attr function:

$("li").attr("uid")

And

$("li").attr("ustatus")

Note: The selectors will need to be changed, obviously

Please note that there are differing opinions on the use of custom attributes - however, this should be fine for every major browser. It is also the least complex solution I can think of. It doesn't require jumping to sibling elements to get data, or finding elements nearby, which can all add a small amount of overhead to processing - I try to minimise the amount of extra bloat I add to the DOM when doing such things.

jQuery Data

If you want to store custom data against a jQuery object, use the data function .

$('#myField').data('name', 'Jack');
var name = $('#myField').data('name');

HTML5 data-* Attributes

You can also use the HTML5 data-* attributes, though the APIs for accessing these are only partially supported by the different browsers. Here's some more information about that .

<div data-userid="123" class="user-row">

programmatically:

$('#myElement').attr('data-fruit', 'apple');
// or
document.getElementById('myElement').dataset.fruit = 'apple';

Hidden Fields

If you want to do things the old browser-compatible way and stuff the metadata directly into your html, you can use hidden fields. It's a bit cruder but easy enough to do.

<input type="hidden" name="UserID" value="[userid]" />

You can easily use jQuery selectors to query your list and find html blocks that contain user items that have the relevant hidden fields that match the metadata you are querying for.

In this case, I think custom attributes might be overkill. You can store the user-id in the id -attribute, since there will only be one instance of the user in the list, right? Also, the status of the user could be stored in the class -attribute. In this way, each user could be given different styling in CSS, such as green for active, yellow for a non-activated account, and red for a suspended account.

The code for fetching the status will, however, be a little more complex compared to using a custom attribute (But only if you also want to have multiple classes). On a more positive note, the HTML will validate with this approach whereas it would not with custom attributes.

<ul id="userList">
    <li id="uid123" class="active">UserName X</li>
    <li id="uid456" class="suspended">Mr. Troll</li>
</ul>

/**
 * Simple function for searching (strict) for a value in an array
 * @param array arr The array to look in
 * @param mixed val The value to look for in arr. Note that the value is looked for using strict comparison
 * @return boolean true if val is found in arr, else false
 */
function searchArray(arr, val) {
    for(var i = 0, len = arr.length; i < len; i++) {
        if(arr[i] === val) {
            return true;
        }
    }
    return false;
}

/**
 * Gets a known status from a string of class names. Each class name should be separated
 * by a space.
 * @param string classNames The string to check for a known status
 * @return string|false The status if found in classNames, else false
 */
function getStatus(classNames) {
    // The different statuses a user can have. Change this into your own!
    var statuses = ['active', 'suspended', 'inactive'], 
        nameArr = classNames.split(" ");
    for(var i = 0, nameLen = nameArr.length; i < nameLen; i++) {
        // If we find a valid status among the class names, return it
        if(searchArray(statuses, nameArr[i])) {
            return nameArr[i];
        }
    }
    return false; // We didn't find any known status in classNames
}

var id = $("li").attr("id"); // Fetches the id for the first user
var status = getStatus($("li").attr("class")); // Fetches the status of the first user

The metadata plugin to jquery is your answer.

<html >
<head>
<script src="/js/jquery-1.3.2.js"></script>
<script src="/js/jquery.metadata.js"></script>
</head>
<body>
<ul>
<li type="text" class="{UID:'1',status:'alive'}">Adam</li>
<li type="text" class="{UID:'2',status:'alive'}">Bob</li>
<li type="text" class="{UID:'3',status:'alive'}">Carol</li>
</ul>
<script>
$('li').each(function(){window.console.log($(this).metadata().UID)});
</script>
</body>
</html>

There are various ways of doing it depending on the kind of data you are storing and how much information you are storing in the page in general. It's best to devise a consistent scheme so you can write a simple library call to do the work. For example,

You can store data in the class of a particular element. This may require additional wrapper elements in order to be able to provide an additional class to drive your CSS. This also restricts the storable content format. User ID may well fit into a class attribute.

You can store data in an unused href of a Javascript activated link. This has the additional feature of showing the data in the status bar as part of the URL on rollover. For instance you can store '#userid' or even just 'userid' in the href.

You can store data in additional elements. For instance you can have a nested div with a class that indicates storage which also triggers CSS to take the element out of the display. This is the most general and extensive support you can probably arrange in page.

Rather than a nested div you could also use nested input tags with type="hidden". This is kind of more expected / traditional and doesn't require CSS to take them out of the display. You can use the id attribute to identify these inputs, or you can use the location on the page. For instance, put them inside the link that the user clicks and then just search inside the current link in the onclick handler.

To answer the question of "how to get it into the document in the first place", I suggest a layout similar to this:

<ul id="users">
    <li id="someUserId" class="someStatus">Some Username</li>
    <li id="someOtherUserId" class="someOtherStatus">Some Username</li>
</ul>

This allows you to easily select a lot of info about your users:

$('#users > li') // all user elements
$('.someStatus') // all users of a particular status

Then in your event handlers it's also easy to get the current status:

$(this).attr('class') //get current status once you have a user element selected.

Another alternative is to dump javascript to the page and simply have it use the jquery data functionality to store the data as soon as the page loads. You'd still need an id on the element in order to find the right one though.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM