Attributs personnalisés – Ouais-tu ou non?

Récemment, j'ai lu de plus en plus sur les personnes utilisant des attributs personnalisés dans leurs balises HTML, principalement dans le but d'intégrer des données supplémentaires à utiliser dans le code javascript.

J'espérais recueillir des commentaires sur la question de savoir si l'utilisation d'attributs personnalisés est une bonne pratique, et aussi quelles sont les alternatives possibles.

Il semble qu'il puisse vraiment simplifier le côté du serveur et le code côté client, mais il n'est pas compatible W3C.

Devrions-nous utiliser des attributs HTML personnalisés dans nos applications Web? Pourquoi ou pourquoi pas?

Pour ceux qui pensent que les attributs personnalisés sont une bonne chose: quelles sont les choses à garder à l'esprit lors de leur utilisation?

Pour ceux qui pensent que les attributs personnalisés sont mauvais: quelles alternatives utilisez-vous pour accomplir quelque chose de similaire?

Mise à jour: Je suis surtout intéressé par le raisonnement derrière les différentes méthodes, ainsi que par des points sur la raison pour laquelle une méthode est meilleure qu'une autre. Je pense que nous pouvons trouver 4 à 5 façons différentes d'accomplir la même chose. (Éléments cachés, scripts en ligne, classes supplémentaires, analyse d'informations à partir d'identifiants, etc.).

Mise à jour 2: Il semble que la fonctionnalité d'attributs de data- HTML 5 ait beaucoup de soutien ici (et j'ai tendance à convenir, cela ressemble à une option solide). Jusqu'à présent, je n'ai pas vu beaucoup de réfutations pour cette suggestion. Y a-t-il des problèmes / des pièges à craindre d'utiliser cette approche? Ou est-ce simplement une invalidation «inoffensive» des spécifications W3C actuelles?

Le HTML 5 permet explicitement des attributs personnalisés qui commencent par les data . Ainsi, par exemple, <p data-date-changed="Jan 24 5:23 pm">Hello</p> est valide. Étant donné qu'il est officiellement pris en charge par une norme, je pense que c'est la meilleure option pour les attributs personnalisés. Et il ne nécessite pas de surcharger d'autres attributs avec des hacks, donc votre HTML peut rester sémantique.

Source: http://www.w3.org/TR/html5/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes

Voici une technique que j'ai utilisée récemment:

 <div id="someelement"> <!-- { someRandomData: {a:1,b:2}, someString: "Foo" } --> <div>... other regular content...</div> </div> 

L'objet-commentaire s'attache à l'élément parent (c'est-à-dire #someelement).

Voici l'analyseur: http://pastie.org/511358

Pour obtenir les données pour un élément particulier, appelez simplement parseData avec une référence à cet élément passé comme le seul argument:

 var myElem = document.getElementById('someelement'); var data = parseData( myElem ); data.someRandomData.a; // <= Access the object staight away 

Il peut être plus succinct que cela:

 <li id="foo"> <!--{specialID:245}--> ... content ... </li> 

Y accéder:

 parseData( document.getElementById('foo') ).specialID; // <= 245 

Le seul inconvénient de l'utiliser est qu'il ne peut pas être utilisé avec des éléments à fermeture automatique (p <img/> Ex. <img/> ), car les commentaires doivent être considérés comme les données de cet élément.


EDIT :

Avantages notables de cette technique:

  • Facile à mettre en œuvre
  • Ne pas invalider HTML / XHTML
  • Facile à utiliser / à comprendre (notation JSON basique)
  • Brouillard et sémantiquement plus propre que la plupart des alternatives

Voici le code de l'analyseur (copié du lien http://pastie.org/511358 ci-dessus, au cas où il ne serait plus disponible sur pastie.org):

 var parseData = (function(){ var getAllComments = function(context) { var ret = [], node = context.firstChild; if (!node) { return ret; } do { if (node.nodeType === 8) { ret[ret.length] = node; } if (node.nodeType === 1) { ret = ret.concat( getAllComments(node) ); } } while( node = node.nextSibling ); return ret; }, cache = [0], expando = 'data' + +new Date(), data = function(node) { var cacheIndex = node[expando], nextCacheIndex = cache.length; if(!cacheIndex) { cacheIndex = node[expando] = nextCacheIndex; cache[cacheIndex] = {}; } return cache[cacheIndex]; }; return function(context) { context = context || document.documentElement; if ( data(context) && data(context).commentJSON ) { return data(context).commentJSON; } var comments = getAllComments(context), len = comments.length, comment, cData; while (len--) { comment = comments[len]; cData = comment.data.replace(/\n|\r\n/g, ''); if ( /^\s*?\{.+\}\s*?$/.test(cData) ) { try { data(comment.parentNode).commentJSON = (new Function('return ' + cData + ';'))(); } catch(e) {} } } return data(context).commentJSON || true; }; })(); 

Vous pouvez créer n'importe quel attribut si vous spécifiez un schéma pour votre page.

Par exemple:

Ajoute ça

 <html xmlns="http://www.w3.org/1999/xhtml" xmlns:addthis="http://www.addthis.com/help/api-spec"> ... <a addthis:title="" addthis:url="" ...> 

Facebook (tags pairs)

 <html xmlns:og="http://opengraphprotocol.org/schema/" xmlns:fb="http://www.facebook.com/2008/fbml"> ... <fb:like href="http://developers.facebook.com/" width="450" height="80"/> 

Le moyen le plus simple d'éviter l'utilisation d'attributs personnalisés est d'utiliser les attributs existants.

Utiliser des noms de classe pertinents et pertinents.
Par exemple, faites quelque chose comme: type='book' et type='cd' , pour représenter les livres et les CD. Les cours sont beaucoup mieux pour représenter ce que quelque chose est .

Par exemple class='book'

J'ai utilisé des attributs personnalisés dans le passé, mais honnêtement, il n'est vraiment pas nécessaire pour eux si vous utilisez des attributs existants d'une manière sémantiquement significative.

Pour donner un exemple plus concret, disons que vous avez un site qui donne des liens vers différents types de magasins. Vous pouvez utiliser ce qui suit:

 <a href='wherever.html' id='bookstore12' class='book store'>Molly's books</a> <a href='whereverelse.html' id='cdstore3' class='cd store'>James' Music</a> 

Le style css pourrait utiliser des classes comme:

 .store { } .cd.store { } .book.store { } 

Dans l'exemple ci-dessus, nous voyons que les deux sont des liens vers les magasins (par opposition aux autres liens non liés sur le site) et l'un est un magasin de CD et l'autre est une librairie.

Intégrez les données dans dom et utilisez les métadonnées pour jQuery .

Tous les bons plug-ins prennent en charge le plugin de métadonnées (permettant des options par étiquette).

Il permet également des structures de données / données infiniment complexes, ainsi que des paires de valeurs-clés.

 <li class="someclass {'some': 'random,'json':'data'} anotherclass">...</li> 

OU

 <li class="someclass" data="{'some':'random', 'json': 'data'}">...</li> 

OU

 <li class="someclass"><script type="data">{"some":"random","json":"data"}</script> ...</li> 

Ensuite, obtenez les données comme suit:

 var data = $('li.someclass').metadata(); if ( data.some && data.some == 'random' ) alert('It Worked!'); 

Je ne vois pas de problème lors de l'utilisation des fonctions XHTML existantes sans casser ni prolonger votre espace de noms. Jetons un coup d'oeil à un petit exemple:

 <div id="some_content"> <p>Hi!</p> </div> 

Comment ajouter des informations supplémentaires à some_content sans attributs supplémentaires? Qu'en est-il de l'ajout d'une autre étiquette comme celle-ci?

 <div id="some_content"> <div id="some_content_extended" class="hidden"><p>Some alternative content.</p></div> <p>Hi!</p> </div> 

Il conserve la relation via un identifiant / extension bien définie "développé" de votre choix et par sa position dans la hiérarchie. J'utilise souvent cette approche avec jQuery et sans utiliser les techniques Ajax.

Non. Essayez plutôt ceci:

 <div id="foo"/> <script type="text/javascript"> document.getElementById('foo').myProperty = 'W00 H00! I can add JS properties to DOM nodes without using custom attributes!'; </script> 

Je ne fais pas l'utilisation d'attributs personnalisés, car je suis en train de délivrer XHTML, car je veux que les données soient lisibles par machine par un logiciel tiers (bien que je pourrais étendre le schéma XHTML si je le voulais).

En alternative aux attributs personnalisés, je trouve principalement les attributs d'identification et de classe (par exemple, comme mentionné dans d'autres réponses) suffisants.

Aussi, considérez ceci:

  • Si les données supplémentaires doivent être lisibles par l'utilisateur et lisibles par machine, elles doivent être encodées à l'aide de balises HTML (visibles) et de texte plutôt que comme attributs personnalisés.

  • Si cela n'a pas besoin d'être lisible par l'homme, alors peut-être qu'il peut être encodé à l'aide de tags et de textes HTML invisibles .

Certaines personnes font une exception: elles permettent des attributs personnalisés, ajoutés au DOM par Javascript du côté client au moment de l'exécution. Ils considèrent que cela est correct: parce que les attributs personnalisés ne sont ajoutés qu'au DOM au moment de l'exécution, le HTML ne contient aucun attribut personnalisé.

Nous avons créé un éditeur Web qui comprend un sous-ensemble de HTML – un sous-ensemble très strict (qui a été compris presque universellement par les clients de messagerie). Nous devons exprimer des choses comme <td width="@INSWIDTH_42@"> dans la base de données, mais nous ne pouvons pas l'avoir dans le DOM, sinon le navigateur où l'éditeur s'exécute, fait peur (ou est plus susceptible de devenir fous que Il est vraisemblablement évident sur les attributs personnalisés). Nous voulions faire glisser-déposer, de sorte que le purement dans le DOM était hors, comme c'était le cas .data() de jquery (les données supplémentaires n'ont pas été copiées correctement). Nous devrions probablement avoir besoin de données supplémentaires pour venir pour le trajet dans .html() . À la fin, nous nous sommes installés en utilisant <td width="1234" rs-width="@INSWIDTH_42@"> pendant le processus d'édition, puis, lorsque nous le POSTONS tout, nous supprimons la width et faisons une recherche et détruire regex s/rs-width=/width=/g .

Au début, le gars qui écrivait la plupart de cela était la validation-nazi sur ce problème et essayé tout pour éviter notre attribut personnalisé, mais à la fin acquiescé lorsque rien d'autre ne semblait fonctionner pour TOUTES nos exigences. Il a aidé quand il s'est rendu compte que l'attribut personnalisé n'apparaîtrait jamais dans un courrier électronique. Nous avons envisagé de coder nos données supplémentaires en class , mais avons décidé que ce serait le plus grand de deux maux.

Personnellement, je préfère avoir des choses nettes et passer des validateurs, etc., mais en tant qu'employé de la société, je dois me rappeler que ma responsabilité principale est d'avancer la cause de l'entreprise (gagner autant d'argent que possible), et non celle de mon désir égoïste de Pureté technique. Les outils devraient fonctionner pour nous; Pas nous pour eux.

Spec: Créez un contrôle de TextBox ASP.NET qui forme automatiquement son texte en tant que nombre, selon les propriétés "DecimalSeparator" et "ThousandsSeparator", en utilisant JavaScript.

Une façon de transférer ces propriétés du contrôle vers JavaScript consiste à faire contrôler le contrôle des propriétés personnalisées:

 <input type="text" id="" decimalseparator="." thousandsseparator="," /> 

Les propriétés personnalisées sont facilement accessibles par JavaScript. Et même si une page utilisant des éléments avec des propriétés personnalisées ne sera pas validée , le rendu de cette page ne sera pas affecté.

J'utilise uniquement cette approche lorsque je veux associer des types simples, comme les chaînes et les entiers, aux éléments HTML à utiliser avec JavaScript. Si je veux que les éléments HTML soient plus faciles à identifier, j'utiliserai la classe et les propriétés de l' ID .

J'utilise des champs personnalisés tout le temps par exemple <ai = "" …. Puis référence à i avec jquery. Html invalide, oui. Ça marche bien, oui.

Pour les applications Web complexes, je dépose des attributs personnalisés partout.

Pour plus de pages tournées vers le public, j'utilise l'attribut "rel" et je jette toutes mes données dans JSON, puis décodez-le avec MooTools ou jQuery:

 <a rel="{color:red, awesome:true, food: tacos}">blah</a> 

J'essaie de rester avec l'attribut de données HTML 5 récemment pour "préparer", mais il n'est pas encore venu naturellement.

Je sais que les gens sont contre, mais j'ai trouvé une solution superbe pour cela. Si vous souhaitez utiliser un attribut personnalisé comme "mine", par exemple:

 <a href="test.html" mine-one="great" mine-two="awesome">Test</a> 

Ensuite, vous pouvez exécuter ce code pour récupérer un objet comme jquery.data ().

 var custom_props = {} ; $.each($(".selector")[0].attributes, function(i,x) { if (this.specified && x.name.indexOf("mine-") !== -1) self.new_settings[x.name.replace("modal-","")] = x.value; }); 

Les attributs personnalisés, à mon humble avis, ne devraient pas être utilisés car ils ne valident pas. Alternativement, vous pouvez définir plusieurs classes pour un seul élément comme:

 <div class='class1 class2 class3'> Lorem ipsum </div>