web-dev-qa-db-fra.com

Attributs personnalisés - oui ou non?

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

J'espérais recueillir des informations sur la question de savoir si l'utilisation d'attributs personnalisés est une bonne pratique, ainsi que sur certaines alternatives.

Il semble que cela simplifie vraiment les codes côté serveur et côté client , mais il n’est pas non plus conforme au 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 une mauvaise chose: quelles alternatives utilisez-vous pour accomplir quelque chose de similaire?

Mise à jour: Je suis surtout intéressé par le raisonnement à la base des différentes méthodes, ainsi que par les raisons pour lesquelles une méthode est utilisée. mieux qu'un autre. Je pense que nous pouvons tous trouver quatre ou cinq manières différentes de réaliser la même chose. (éléments cachés, scripts en ligne, classes supplémentaires, informations d’analyse des identifiants, etc.).

pdate 2: Il semble que le HTML 5 data- La fonctionnalité d'attribut a beaucoup de support ici (et j'ai tendance à être d'accord, cela ressemble à une option solide). Jusqu'ici, je n'ai pas vu beaucoup de réfutations pour cette suggestion. Y a-t-il des problèmes/pièges à craindre de l'utilisation de cette approche? Ou est-ce simplement une invalidation "sans danger" des spécifications actuelles du W3C?

253
TM.

HTML 5 autorise explicitement les attributs personnalisés commençant par data. Ainsi, par exemple, <p data-date-changed="Jan 24 5:23 p.m.">Hello</p> est valable. Comme il est officiellement pris en charge par une norme, je pense que c'est la meilleure option pour les attributs personnalisés. Et cela ne vous oblige pas à surcharger d'autres attributs avec des hacks, votre HTML peut donc rester sémantique.

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

253
Chuck

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>

Le commentaire-objet est lié à l'élément parent (c'est-à-dire #selelement).

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

Pour obtenir les données d'un élément particulier, appelez simplement parseData avec une référence à cet élément passé en tant qu'argument unique:

var myElem = document.getElementById('someelement');

var data = parseData( myElem );

data.someRandomData.a; // <= Access the object staight away

Ça peut être plus succinct que ça:

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

Y accéder:

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

Son seul inconvénient est qu’il ne peut pas être utilisé avec des éléments à fermeture automatique (par exemple, <img/>), puisque les commentaires doivent être dans l'élément à considérer comme les données de cet élément.


[~ # ~] éditer [~ # ~] :

Avantages notables de cette technique:

  • Facile à mettre en œuvre
  • Est-ce que pas invalide HTML/XHTML
  • Facile à utiliser/à comprendre (notation JSON de base)
  • Plus discret et sémantiquement plus propre que la plupart des alternatives

Voici le code de l'analyseur (copié à partir du lien hypertexte http://pastie.org/511358 ci-dessus, au cas où il deviendrait jamais indisponible 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;

    };

})();
95
James

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

Par exemple:

Addthis

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

Facebook (même les tags)

<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"/>
15
BrunoLM

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

utilisez des noms de classe significatifs et pertinents.
Par exemple, faites quelque chose comme: type='book' et type='cd', pour représenter des livres et des cds. Les classes sont bien meilleures 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, ils ne sont vraiment pas nécessaires si vous utilisez les attributs existants de manière sémantique.

Pour donner un exemple plus concret, supposons que vous disposiez d’un site proposant des liens vers différents types de magasins. Vous pouvez utiliser les éléments suivants:

<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 peut utiliser des classes telles que:

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

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

10
Jonathan Fingland

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

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

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

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

OR

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

OR

<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!');
6
antony.trupe

Je ne vois aucun problème à utiliser les fonctionnalités XHTML existantes sans rien casser ou étendre 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 d'ajouter une autre balise 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 "_extended" bien défini de votre choix et par sa position dans la hiérarchie. J'utilise souvent cette approche avec jQuery et sans utiliser les techniques similaires à Ajax.

4
merkuro

Je n'utilise pas d'attributs personnalisés, car je génère du XHTML, car je veux que les données soient lisibles par la machine par un logiciel tiers (bien que je puisse étendre le schéma XHTML si je le voulais).

En guise d'alternative aux attributs personnalisés, je considère généralement que les attributs id et class (par exemple, comme indiqué dans d'autres réponses) sont suffisants.

Aussi, considérez ceci:

  • Si les données supplémentaires doivent être lisibles par l'homme et par la machine, elles doivent être codées à l'aide de balises HTML (visibles) et de texte au lieu d'attributs personnalisés.

  • S'il n'est pas nécessaire qu'il soit lisible par un humain, il peut peut-être être codé à l'aide de invisible balises HTML et texte.

Certaines personnes font une exception: elles autorisent les attributs personnalisés, ajoutés au DOM par Javascript du côté client au moment de l'exécution. Ils estiment que c'est correct: comme les attributs personnalisés ne sont ajoutés au DOM qu'à l'exécution, le code HTML ne contient aucun attribut personnalisé.

2
ChrisW

Nous avons créé un éditeur Web comprenant un sous-ensemble de HTML - un sous-ensemble très strict (compris presque universellement par les clients de messagerie). Nous devons exprimer des éléments tels que <td width="@INSWIDTH_42@"> Dans la base de données, mais nous ne pouvons pas en avoir dans le DOM, sinon le navigateur dans lequel l'éditeur est exécuté panique (ou risque davantage de paniquer qu'il ne le soit probablement). paniquer sur les attributs personnalisés). Nous voulions un glisser-déposer, il était donc inutile de le placer dans le DOM, de même que .data() de jquery (les données supplémentaires n'ont pas été copiées correctement). Nous avions probablement aussi besoin des données supplémentaires pour la balade dans .html(). En fin de compte, nous avons décidé d’utiliser <td width="1234" rs-width="@INSWIDTH_42@"> Lors du processus d’édition, puis lorsque nous POST), nous supprimons width et faisons une recherche regex - et -destroy s/rs-width=/width=/g.

Au début, le type qui écrivait le plus était la validation-nazie sur cette question et avait tout essayé pour éviter notre attribut personnalisé, mais à la fin, il a acquiescé lorsque rien d'autre ne semblait fonctionner pour TOUTES nos exigences. Cela l'a aidé lorsqu'il s'est rendu compte que l'attribut personnalisé n'apparaîtrait jamais dans un email Nous avons envisagé d'encoder nos données supplémentaires dans class, mais nous avons décidé qu'il s'agirait du plus grave des deux maux.

Personnellement, je préfère avoir les choses propres et les validants qui passent, etc., mais en tant qu'employé de l'entreprise, je dois me rappeler que ma responsabilité première est de faire avancer la cause de l'entreprise (gagner le plus d'argent possible le plus rapidement possible), pas celui de mon désir égoïste de pureté technique. Les outils devraient fonctionner pour nous. pas nous pour eux.

1
Bernd Jendrissek

Je sais que les gens sont contre, mais j'ai proposé une solution très courte pour cela. Si vous souhaitez utiliser un attribut personnalisé tel que "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 le fait 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;
});
1
agrublev

Non. Essayez quelque chose comme ceci à la place:

<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>
1
Anon

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

0
Marius

Spec: Créez un contrôle ASP.NET TextBox qui met automatiquement en forme son texte sous forme de nombre, conformément aux propriétés "DecimalSeparator" et "ThousandsSeparator", à l'aide de JavaScript.


Une façon de transférer ces propriétés du contrôle vers JavaScript consiste à faire en sorte que le contrôle rende les propriétés personnalisées:

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

Les propriétés personnalisées sont facilement accessibles par JavaScript. Et tandis qu'une page utilisant des éléments avec des propriétés personnalisées ne sera pas valider , le rendu de cette page ne sera pas affecté.


Je seulement utilise cette approche lorsque je souhaite associer des types simples, tels que des chaînes et des entiers, à des éléments HTML à utiliser avec JavaScript. Si je veux faciliter l'identification des éléments HTML, je vais utiliser les propriétés class et id.

0
cllpse

Pour les applications Web complexes, je dépose des attributs personnalisés dans tous les sens.

Pour les pages plus publiques, j'utilise l'attribut "rel" et dump toutes mes données ici en JSON, puis les décode avec MooTools ou jQuery:

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

J'essaie de m'en tenir à l'attribut HTML 5 data dernièrement pour "préparer", mais cela n'est pas encore venu naturellement.

0
Ryan Florence