Comment stocker des données arbitraires pour certaines balises HTML

338

Je crée une page qui a une certaine interaction fournie par javascript. À titre d'exemple: des liens qui envoient une demande AJAX pour obtenir le contenu des articles, puis afficher ces données dans une div. Évidemment, dans cet exemple, j'ai besoin de chaque lien pour stocker un peu d'informations supplémentaires: l'id de l'article. La façon dont je l'ai géré au cas où était de mettre ces informations dans le lien href ceci:

<a class="article" href="#5">

J'utilise ensuite jQuery pour trouver les éléments a.article et attacher le gestionnaire d'événements approprié. (ne vous attardez pas trop sur la convivialité ou la sémantique ici, c'est juste un exemple)

Quoi qu'il en soit, cette méthode fonctionne, mais elle sent un peu et n'est pas extensible du tout (que se passe-t-il si la fonction de clic a plus d'un paramètre? Et si certains de ces paramètres sont facultatifs?)

La réponse immédiatement évidente a été d'utiliser des attributs sur l'élément. Je veux dire, c'est pour ça qu'ils sont, non? (En quelque sorte).

<a articleid="5" href="link/for/non-js-users.html">

Dans ma récente question, j'ai demandé si cette méthode était valide, et il s'avère qu'à défaut de définir ma propre DTD (je ne le fais pas), alors non, elle n'est pas valide ou fiable. Une réponse courante a été de mettre les données dans l' classattribut (bien que cela ait pu être dû à mon exemple mal choisi), mais pour moi, cela sent encore plus. Oui, c'est techniquement valable, mais ce n'est pas une excellente solution.

Une autre méthode que j'avais utilisée dans le passé était de générer un JS et de l'insérer dans la page dans une <script>balise, créant une structure qui s'associerait à l'objet.

var myData = {
    link0 : {
        articleId : 5,
        target : '#showMessage'
        // etc...
    },
    link1 : {
        articleId : 13
    }
};

<a href="..." id="link0">

Mais cela peut être vraiment pénible à entretenir et est généralement très désordonné.

Donc, pour passer à la question, comment stockez-vous des informations arbitraires pour les balises HTML ?

nickf
la source
2
Question connexe: stackoverflow.com/questions/209428/…
Tamas Czinege

Réponses:

361

Quelle version de HTML utilisez-vous?

En HTML 5, il est totalement valide d'avoir des attributs personnalisés préfixés avec data- , par exemple

<div data-internalid="1337"></div>

En XHTML, ce n'est pas vraiment valide. Si vous êtes en mode XHTML 1.1, le navigateur s'en plaindra probablement, mais en mode 1.0, la plupart des navigateurs l'ignoreront silencieusement.

Si j'étais vous, je suivrais l'approche basée sur un script. Vous pouvez le faire générer automatiquement côté serveur afin que ce ne soit pas une douleur dans le dos à maintenir.

Tamas Czinege
la source
5
@Tchalvak: C'est vrai, mais ce bit fonctionnera néanmoins sur la plupart des navigateurs.
Tamas Czinege
2
D'autres ont affirmé qu'il n'y avait aucune raison d'attendre le support, car le seul problème que cela provoque est l'échec de la validation et il ne casse pas IE. Voir la réponse de TJ Crowler ici: stackoverflow.com/questions/1923278/…
Chris
42
Si vous utilisez des attributs data-xxx et que vous souhaitez les récupérer, vous pouvez simplement utiliser le "domElement.getAttribute ('data-any' ')" sans aucun framework tiers.
Ohad Kravchick
5
Gardez à l'esprit les performances! jsperf.com/jquery-data-vs-jqueryselection-data/19
FilmJ
19
Rappel: Afin de récupérer les données, 1337, via jquery, assurez-vous de supprimer «données» du nom de la variable. Par exemple, utilisez: $(this).data('internalid'); Au lieu de:$(this).data('data-internalid');
Gideon Rosenthal
134

Si vous utilisez déjà jQuery, vous devez utiliser la méthode "data" qui est la méthode recommandée pour stocker des données arbitraires sur un élément dom avec jQuery.

Pour stocker quelque chose:

$('#myElId').data('nameYourData', { foo: 'bar' });

Pour récupérer des données:

var myData = $('#myElId').data('nameYourData');

C'est tout ce qu'il y a à faire mais jetez un œil à la documentation jQuery pour plus d'informations / exemples.

Prestaul
la source
20

Juste une autre façon, personnellement, je ne l'utiliserais pas mais cela fonctionne (assurez-vous que votre JSON est valide car eval () est dangereux).

<a class="article" href="link/for/non-js-users.html">
    <span style="display: none;">{"id": 1, "title":"Something"}</span>
    Text of Link
</a>

// javascript
var article = document.getElementsByClassName("article")[0];
var data = eval(article.childNodes[0].innerHTML);
Luca Matteis
la source
1
+1 pour la réflexion latérale. Je suis d'accord que je ne voudrais probablement pas utiliser cette méthode, mais c'est une option vaguement viable!
nickf le
9
@nickf Vous pouvez vous débarrasser de l' evalutilisation à la JSON.parseplace jsfiddle.net/EAXmY
Simon
12

Les attributs arbitraires ne sont pas valides, mais sont parfaitement fiables dans les navigateurs modernes. Si vous définissez les propriétés via javascript, vous n'avez pas à vous soucier de la validation également.

Une alternative consiste à définir des attributs en javascript. jQuery a une belle méthode utilitaire juste à cet effet, ou vous pouvez rouler la vôtre.

Eran Galperin
la source
3
Pourquoi ne pas utiliser des data-attributs à la place?
Flimm
10

Un hack qui fonctionnera avec à peu près tous les navigateurs possibles consiste à utiliser des classes ouvertes comme ceci: <a class='data\_articleid\_5' href="link/for/non-js-users.html>;

Ce n'est pas si élégant pour les puristes, mais c'est universellement pris en charge, conforme aux normes et très facile à manipuler. Cela semble vraiment être la meilleure méthode possible. Si vous serialize, modifiez , copiez vos balises ou faites à peu près autre chose, datarestez attaché, copié, etc.

Le seul problème est que vous ne pouvez pas stocker les objets non sérialisables de cette façon , et il peut y avoir des limites si vous y mettez quelque chose de vraiment énorme.

Une deuxième façon consiste à utiliser de faux attributs comme:<a articleid='5' href="link/for/non-js-users.html">

C'est plus élégant, mais ne respecte pas la norme, et je ne suis pas sûr à 100% du support. De nombreux navigateurs le prennent entièrement en charge, je pense que IE6 prend en charge l' JSaccès mais pas CSS selectors(ce qui n'a pas vraiment d'importance ici), peut-être que certains navigateurs seront complètement confus, vous devez le vérifier.

Faire des choses drôles comme la sérialisation et la désérialisation serait encore plus dangereux.

En utilisant ids de JShash pur fonctionne principalement, sauf lorsque vous essayez de copier vos balises. Si c'est le cas tag <a href="..." id="link0">, copiez-le via des JSméthodes standard , puis essayez de modifier dataattaché à une seule copie, l'autre copie sera modifiée.

Ce n'est pas un problème si vous ne copiez pas de tags ou n'utilisez que la lecture seule données en . Si vous copiez des tags et qu'ils sont modifiés, vous devrez les gérer manuellement.

taw
la source
stocker valse en classe est génial
Saravanan Rajaraman
10

En utilisant jquery,

ranger: $('#element_id').data('extra_tag', 'extra_info');

à récupérer: $('#element_id').data('extra_tag');

user2458978
la source
6

Je sais que vous utilisez actuellement jQuery, mais que se passe-t-il si vous définissez le gestionnaire onclick en ligne. Ensuite, vous pourriez faire:

 <a href='/link/for/non-js-users.htm' onclick='loadContent(5);return false;'>
     Article 5</a>
tvanfosson
la source
6

Vous pouvez utiliser des balises d'entrée masquées. Je n'ai aucune erreur de validation sur w3.org avec ceci:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html lang='en' xml:lang='en' xmlns='http://www.w3.org/1999/xhtml'>
  <head>
    <meta content="text/html;charset=UTF-8" http-equiv="content-type" />
    <title>Hello</title>
  </head>
  <body>
    <div>
      <a class="article" href="link/for/non-js-users.html">
        <input style="display: none" name="articleid" type="hidden" value="5" />
      </a>
    </div>
  </body>
</html>

Avec jQuery, vous obtiendrez l'ID d'article avec quelque chose comme (non testé):

$('.article input[name=articleid]').val();

Mais je recommanderais HTML5 si c'est une option.

phylae
la source
13
En fait, je ne pense pas que ce style="display: none"soit nécessaire pour les champs de saisie cachés.
phylae
1
Bonne approche, totalement valable dans toutes les versions HTML. Je déconseille fortement le codage en supposant que tous vos utilisateurs auront un navigateur totalement compatible HTML5. Et affichage: aucun n'est nécessaire pour les champs cachés.
andreszs
Très agréable. C'est la meilleure solution que j'ai trouvée pour XHTML où les attributs de données ne sont pas une option valide. OMI, il n'abuse pas des balises / attributs de manière involontaire, il n'a presque aucune "odeur" du tout. Et comme les autres l'ont dit: affichage: aucun n'est vraiment nécessaire.
Arahman
4

Pourquoi ne pas utiliser les données significatives déjà présentes au lieu d'ajouter des données arbitraires?

c'est à dire utiliser <a href="https://stackoverflow.com/articles/5/page-title" class="article-link"> , et vous pouvez obtenir tous les liens programme d'article sur la page (via le nom de classe) et l'article ID (correspondant à l'expression rationnelle /articles\/(\d+)/contre this.href).


la source
2
Le problème est que ce n'est pas non plus vraiment extensible
ehdv
4

En tant qu'utilisateur jQuery, j'utiliserais le plugin Metadata . Le HTML a l'air propre, il valide et vous pouvez intégrer tout ce qui peut être décrit en utilisant la notation JSON.

Robin Smidsrød
la source
3

Il devrait donc y avoir quatre choix:

  1. Mettez les données dans l'attribut id.
  2. Mettez les données dans l'attribut arbitraire
  3. Placer les données dans l'attribut class
  4. Mettez vos données dans une autre balise

http://www.shanison.com/?p=321

Shanison
la source
@ h4ck3rm1k3 ... pas dans l'attribut id car il doit être unique avec le document, et il devrait être répété si nécessaire dans une barre latérale, ou quelque chose ... C'est une vieille question, mais elle est toujours valide
miguel-svq
2

Je préconise l'utilisation de l'attribut "rel". Le XHTML valide, l'attribut lui-même est rarement utilisé et les données sont récupérées efficacement.

demonkoryu
la source
ne peux pas faire ça id casser l'attribut nofollow sur les liens
Carter Cole
2

C'est un bon conseil. Merci à @Prestaul

Si vous utilisez déjà jQuery, vous devez utiliser la méthode "data" qui est la méthode recommandée pour stocker des données arbitraires sur un élément dom avec jQuery.

Très vrai, mais que faire si vous souhaitez stocker des données arbitraires dans du HTML ancien? Voici encore une autre alternative ...

<input type="hidden" name="whatever" value="foobar"/>

Placez vos données dans les attributs de nom et de valeur d'un élément d'entrée masqué. Cela peut être utile si le serveur génère du HTML (c'est-à-dire un script PHP ou autre), et votre code JavaScript va utiliser ces informations plus tard.

Certes, pas le plus propre, mais c'est une alternative. Il est compatible avec tous les navigateurs et est valide en XHTML. Vous ne devez PAS utiliser d'attributs personnalisés, ni vraiment utiliser des attributs avec le préfixe «data-», car cela pourrait ne pas fonctionner sur tous les navigateurs. Et, en plus, votre document ne passera pas la validation W3C.

BMiner
la source
Je ne sais pas exactement, mais certains navigateurs peuvent se plaindre si vous utilisez des attributs personnalisés avec un doctype "strict". Quoi qu'il en soit, ce n'est pas du XHTML valide.
BMiner
2

Vous pouvez utiliser le préfixe de données de votre propre attribut made d'un élément aléatoire ( <span data-randomname="Data goes here..."></span>), mais cela n'est valable qu'en HTML5. Ainsi, les navigateurs peuvent se plaindre de la validité.

Vous pouvez également utiliser une <span style="display: none;">Data goes here...</span>balise. Mais de cette façon, vous ne pouvez pas utiliser les fonctions d'attribut, et si css et js sont désactivés, ce n'est pas vraiment une bonne solution non plus.

Mais ce que je préfère personnellement, c'est ce qui suit:

<input type="hidden" title="Your key..." value="Your value..." />

L'entrée sera dans tous les cas cachée, les attributs sont complètement valides et ne seront pas envoyés s'ils se trouvent dans une <form>balise, car ils n'ont pas de nom, non? Surtout, les attributs sont vraiment faciles à mémoriser et le code est joli et facile à comprendre. Vous pouvez même y mettre un attribut ID, afin que vous puissiez également y accéder facilement avec JavaScript et accéder à la paire valeur-clé avec input.title; input.value.

Yeti
la source
Je suis sûr que vous n'avez pas assez travaillé avec les tables html et la sélection. Vous utiliserez l'attribut data plus souvent pour économiser du travail.
1
J'utilise beaucoup l'attribut 'data-' en fait. Mais cela dépend de vos besoins. Par exemple, avec <input /> vous pouvez avoir n'importe quelle clé, tandis que pour 'data-' cela est limité de préférence à une chaîne minuscule sans aucun caractère non alphanumérique.
Yeti
1

Une possibilité pourrait être:

  • Créer un nouveau div pour contenir toutes les données étendues / arbitraires
  • Faites quelque chose pour vous assurer que ce div est invisible (par exemple CSS plus un attribut de classe du div)
  • Placez les données étendues / arbitraires dans des balises HTML [X] (par exemple sous forme de texte dans les cellules d'un tableau, ou tout autre élément que vous pourriez aimer) dans cette div invisible
ChrisW
la source
1

Une autre approche peut être de stocker une paire clé: valeur en tant que classe simple en utilisant la syntaxe suivante:

<div id="my_div" class="foo:'bar'">...</div>

Ceci est valide et peut facilement être récupéré avec les sélecteurs jQuery ou une fonction personnalisée.

Raphaël
la source
0

Chez mon ancien employeur, nous utilisions constamment des balises HTML personnalisées pour conserver des informations sur les éléments du formulaire. Le hic: nous savions que l'utilisateur était obligé d'utiliser IE.

Cela ne fonctionnait pas bien pour FireFox à l'époque. Je ne sais pas si FireFox a changé cela ou non, mais sachez que l'ajout de vos propres attributs aux éléments HTML peut ou non être pris en charge par le navigateur de votre lecteur.

Si vous pouvez contrôler le navigateur utilisé par votre lecteur (c'est-à-dire une applet Web interne pour une entreprise), essayez par tous les moyens. Qu'est-ce que ça peut faire mal, non?

Jerry
la source
0

Voilà comment je vous ajax pages ... c'est une méthode assez simple ...

    function ajax_urls() {
       var objApps= ['ads','user'];
        $("a.ajx").each(function(){
               var url = $(this).attr('href');
               for ( var i=0;i< objApps.length;i++ ) {
                   if (url.indexOf("/"+objApps[i]+"/")>-1) {
                      $(this).attr("href",url.replace("/"+objApps[i]+"/","/"+objApps[i]+"/#p="));
                   }
               }
           });
}

Comment cela fonctionne-t-il, il regarde essentiellement toutes les URL qui ont la classe "ajx" et il remplace un mot-clé et ajoute le signe # ... donc si js est désactivé, les URL agiront comme d'habitude ... tout " apps "(chaque section du site) a son propre mot-clé ... donc tout ce que je dois faire est d'ajouter au tableau js ci-dessus pour ajouter plus de pages ...

Ainsi, par exemple, mes paramètres actuels sont définis sur:

 var objApps= ['ads','user'];

Donc, si j'ai une URL telle que:

www.domain.com/ads/3923/bla/dada/bla

le script js remplacerait la partie / ads / donc mon URL finirait par être

www.domain.com/ads/#p=3923/bla/dada/bla

Ensuite, j'utilise le plugin jquery bbq pour charger la page en conséquence ...

http://benalman.com/projects/jquery-bbq-plugin/

Jason
la source
0

J'ai trouvé que le plugin de métadonnées était une excellente solution au problème de stockage de données arbitraires avec la balise html d'une manière qui facilite la récupération et l'utilisation avec jQuery.

Important : le fichier réel que vous incluez ne fait que 5 Ko et non 37 Ko (ce qui correspond à la taille du package de téléchargement complet)

Voici un exemple de son utilisation pour stocker les valeurs que j'utilise lors de la génération d'un événement de suivi Google Analytics (remarque: data.label et data.value sont des paramètres facultatifs)

$(function () {
    $.each($(".ga-event"), function (index, value) {
        $(value).click(function () {
            var data = $(value).metadata();
            if (data.label && data.value) {
                _gaq.push(['_trackEvent', data.category, data.action, data.label, data.value]);
            } else if (data.label) {
                _gaq.push(['_trackEvent', data.category, data.action, data.label]);
            } else {
                _gaq.push(['_trackEvent', data.category, data.action]);
            }
        });
    });
});

<input class="ga-event {category:'button', action:'click', label:'test', value:99}" type="button" value="Test"/>
biofractal
la source
0

En html, nous pouvons stocker des attributs personnalisés avec le préfixe 'data-' avant le nom de l'attribut comme

<p data-animal='dog'>This animal is a dog.</p>. Vérifier la documentation

Nous pouvons utiliser cette propriété pour définir dynamiquement et obtenir des attributs en utilisant jQuery comme: Si nous avons une balise ap comme

<p id='animal'>This animal is a dog.</p>

Ensuite, pour créer un attribut appelé «race» pour la balise ci-dessus, nous pouvons écrire:

$('#animal').attr('data-breed', 'pug');

Pour récupérer les données à tout moment, nous pouvons écrire:

var breedtype = $('#animal').data('breed');

Akash Ghosh
la source
0

Tant que votre travail est effectué côté serveur, pourquoi auriez-vous quand même besoin d'informations personnalisées dans les balises html de la sortie? tout ce que vous devez savoir sur le serveur est un index dans n'importe quel type de liste de structures avec vos informations personnalisées. Je pense que vous cherchez à stocker les informations au mauvais endroit.

Je reconnais, même si c'est malheureux, que dans bien des cas, la bonne solution n'est pas la bonne. Dans ce cas, je suggère fortement de générer du javascript pour contenir les informations supplémentaires.

Plusieurs années plus tard:

Cette question a été publiée environ trois ans avant que les data-...attributs ne deviennent une option valide avec l'avènement du HTML 5, la vérité a donc changé et la réponse originale que j'ai donnée n'est plus pertinente. Maintenant, je suggère d'utiliser des attributs de données à la place.

<a data-articleId="5" href="link/for/non-js-users.html">

<script>
    let anchors = document.getElementsByTagName('a');
    for (let anchor of anchors) {
        let articleId = anchor.dataset.articleId;
    }
</script>
Kris
la source
comment êtes-vous censé transmettre les données à javascript alors?
nickf