Atributos personalizados-Sí o no?


Recientemente he estado leyendo más y más sobre las personas que usan atributos personalizados en sus etiquetas HTML, principalmente con el propósito de incrustar algunos bits adicionales de datos para su uso en código javascript.

Esperaba reunir algunos comentarios sobre si el uso de atributos personalizados es una buena práctica o no, y también cuáles son algunas alternativas.

Parece que realmente puede simplificar tanto el código del lado del servidor como el del lado del cliente, pero tampoco es compatible con W3C.

Deberíamos estar haciendo uso de atributos HTML personalizados en nuestras aplicaciones web? Por qué o por qué no?

Para aquellos que piensan que los atributos personalizados son algo bueno: ¿cuáles son algunas cosas a tener en cuenta al usarlos?

Para aquellos que piensan que los atributos personalizados son algo malo: ¿qué alternativas utiliza para lograr algo similar?

Actualización: Estoy principalmente interesado en el razonamiento detrás de los diversos métodos, así como puntos en cuanto a por qué un método es mejor que otro. Me creo que todos podemos llegar a 4-5 diferentes maneras de lograr la misma cosa. (elementos ocultos, scripts en línea, clases adicionales, análisis de información de ids, etc.).

Actualización 2: Parece que la característica de atributo HTML 5 data- tiene mucho soporte aquí (y tiendo a estar de acuerdo, parece una opción sólida). Hasta ahora no he visto mucho en el camino de refutaciones para esta sugerencia. ¿Hay algún problema/escollo por el que preocuparse utilizando este enfoque? O es simplemente un 'inofensivo' ¿invalidación de las especificaciones actuales del W3C?

Author: surfmuggle, 2009-06-14

14 answers

HTML 5 permite explícitamente atributos personalizados que comienzan con data. Así, por ejemplo, <p data-date-changed="Jan 24 5:23 p.m.">Hello</p> es válido. Dado que está soportado oficialmente por un estándar, creo que esta es la mejor opción para atributos personalizados. Y no requiere que sobrecargues otros atributos con hacks, por lo que tu HTML puede permanecer semántico.

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

 245
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-23 15:37:46

He aquí una técnica que he estado usando recientemente:

<div id="someelement">

    <!-- {
        someRandomData: {a:1,b:2},
        someString: "Foo"
    } -->

    <div>... other regular content...</div>
</div>

El comment-object se vincula al elemento padre (es decir, #someelement).

Aquí está el analizador: http://pastie.org/511358

Para obtener los datos de cualquier elemento en particular, simplemente llame parseData con una referencia a ese elemento pasado como único argumento:

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

var data = parseData( myElem );

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

Puede ser más sucinto que eso:

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

Acceder a él:

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

La única desventaja de usar esto es que no se puede usar con elementos de cierre automático (por ejemplo, <img/>), ya que los comentarios deben estar dentro de el elemento para ser considerado como los datos de ese elemento.


EDIT :

Beneficios notables de esta técnica:

  • Fácil de implementar
  • Hace no invalida HTML/XHTML
  • Fácil de usar / entender (notación JSON básica)
  • Discreto y semánticamente más limpio que la mayoría alternativas

Aquí está el código del analizador (copiado del http://pastie.org/511358 hipervínculo anterior, en caso de que alguna vez no esté disponible en 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
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 08:43:36

Puede crear cualquier atributo si especifica un esquema para su página.

Por ejemplo:

Addthis

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

Facebook (incluso etiquetas)

<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
Author: BrunoLM,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 02:36:51

La forma más fácil de evitar el uso de atributos personalizados es usar atributos existentes.

Utilice nombres de clase significativos y relevantes.
Por ejemplo, haga algo como: type='book' y type='cd', representar libros y CD. Las clases son mucho mejores para representar lo que algo ES.

Por ejemplo class='book'

He utilizado atributos personalizados en el pasado, pero honestamente, realmente no es necesario para ellos si usted hace uso de atributos existentes en un semánticamente significativo manera.

Para dar un ejemplo más concreto, digamos que tienes un sitio que ofrece enlaces a diferentes tipos de tiendas. Puedes usar lo siguiente:

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

El estilo Css podría usar clases como:

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

En el ejemplo anterior vemos que ambos son enlaces a tiendas (a diferencia de los otros enlaces no relacionados en el sitio) y uno es una tienda de CD, y el otro es una tienda de libros.

 10
Author: Jonathan Fingland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-07-22 16:29:03

Incruste los datos en el dom y use metadatospara jQuery.

Todos los plug-ins buenos soportan el plugin de metadatos(permitiendo opciones por etiqueta).

También permite estructuras de datos/datos infinitamente complejas, así como pares clave-valor.

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

O

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

O

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

Luego obtener los datos de esta manera:

var data = $('li.someclass').metadata();
if ( data.some && data.some == 'random' )
alert('It Worked!');
 6
Author: antony.trupe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 08:44:39

No veo ningún problema en usar características XHTML existentes sin romper nada o extender su espacio de nombres. Echemos un vistazo a un pequeño ejemplo:

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

¿Cómo agregar información adicional a some_content sin atributos adicionales? ¿Qué hay de agregar otra etiqueta como la siguiente?

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

Mantiene la relación a través de un id/extensión bien definido "_extended" de su elección y por su posición en la jerarquía. A menudo uso este enfoque junto con jQuery y sin realmente usando técnicas como Ajax.

 4
Author: merkuro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 04:11:39

No estoy usando atributos personalizados, porque estoy emitiendo XHTML, porque quiero que los datos sean legibles por máquina por software de terceros (aunque, podría extender el esquema XHTML si quisiera).

Como alternativa a los atributos personalizados, sobre todo estoy encontrando los atributos id y class (por ejemplo, como se mencionó en otras respuestas) suficientes.

También, considere esto:

  • Si los datos adicionales deben ser legibles tanto por humanos como por máquinas, entonces deben ser codificado usando etiquetas HTML (visibles) y texto en lugar de como atributos personalizados.

  • Si no necesita ser legible por humanos, entonces tal vez pueda codificarse usando etiquetas HTML y texto invisibles.

Algunas personas hacen una excepción: permiten atributos personalizados, agregados al DOM por Javascript en el lado del cliente en tiempo de ejecución. Consideran que esto está bien: debido a que los atributos personalizados solo se agregan al DOM en tiempo de ejecución, el HTML no contiene ningún atributo personalizado atributo.

 2
Author: ChrisW,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 04:12:41

No. Intente algo como esto:

<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
Author: Anon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-14 04:12:14

Hemos creado un editor basado en la web que entiende un subconjunto de HTML-un subconjunto muy estricto (que entiende casi universalmente por los clientes de correo). Necesitamos expresar cosas como <td width="@INSWIDTH_42@"> en la base de datos, pero no podemos tener eso en el DOM, de lo contrario el navegador donde se ejecuta el editor, se vuelve loco (o es más probable que se asuste de lo que es probable que se asuste sobre los atributos personalizados). Queríamos arrastrar y soltar, por lo que ponerlo puramente en el DOM estaba fuera, al igual que el .data() de jquery (los datos adicionales no obtuvieron copiado correctamente). Probablemente también necesitábamos los datos adicionales para el viaje en .html(). Al final nos decidimos por usar <td width="1234" rs-width="@INSWIDTH_42@"> durante el proceso de edición, y luego cuando lo publicamos todo, eliminamos width y hacemos una búsqueda regex-and-destroy s/rs-width=/width=/g.

Al principio, el tipo que escribió la mayor parte de esto fue el nazi de validación sobre este tema e intentó todo para evitar nuestro atributo personalizado, pero al final accedió cuando nada más parecía funcionar para TODOS nuestros requisitos. Ayudó cuando él nos dimos cuenta de que el atributo personalizado nunca aparecería en un correo electrónico Consideramos codificar nuestros datos adicionales en class, pero decidimos que sería el mayor de los dos males.

Personalmente, yo prefiero tener las cosas limpias y pasando validadores, etc., pero como empleado de la empresa tengo que recordar que mi principal responsabilidad es hacer avanzar la causa de la empresa (ganar tanto dinero lo más rápido posible), no la de mi deseo egoísta de pureza técnica. Herramienta debe trabajar para nosotros, no nosotros para ellos.

 1
Author: Bernd Jendrissek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-05-12 14:16:39

Sé que la gente está en contra, pero se me ocurrió una solución súper corta para esto. Si quieres usar un atributo personalizado como "mine" por ejemplo:

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

Entonces puede ejecutar este código para recuperar un objeto como jquery.data () lo hace.

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
Author: agrublev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-19 20:42:47

Spec: Crear un ASP.NET Control de cuadro de texto que formatea dinámicamente su texto como un número, de acuerdo con las propiedades "DecimalSeparator" y "ThousandsSeparator", utilizando JavaScript.


Una forma de transferir estas propiedades del control a JavaScript es hacer que el control muestre propiedades personalizadas:

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

Las propiedades personalizadas son fácilmente accesibles mediante JavaScript. Y mientras que una página usando elementos con propiedades personalizadas no validará , la la representación de esa página no se verá afectada.


Yo solo uso este enfoque cuando quiero asociar tipos simples como cadenas e enteros a elementos HTML para su uso con JavaScript. Si quiero hacer que los elementos HTML sean más fáciles de identificar, usaré las propiedades class y id .

 0
Author: cllpse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-11 17:33:56

Uso campos personalizados todo el tiempo, por ejemplo

 0
Author: Marius,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 00:23:37

Para aplicaciones web complejas, dejo caer atributos personalizados por todas partes.

Para más páginas públicas utilizo el atributo " rel " y volco todos mis datos allí en JSON y luego los decodifico con MooTools o jQuery:

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

Estoy tratando de seguir con el atributo de datos HTML 5 últimamente solo para "preparar", pero no ha llegado naturalmente todavía.

 0
Author: Ryan Florence,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-26 08:45:35

Los atributos personalizados, en mi humilde opinión, no deben usarse ya que no validan. Alternativa a eso, puede definir muchas clases para un solo elemento como:

<div class='class1 class2 class3'>
    Lorem ipsum
</div>
 -2
Author: Alan Haggai Alavi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-15 00:50:42