Cómo almacenar datos arbitrarios para algunas etiquetas HTML

338

Estoy haciendo una página que tiene alguna interacción proporcionada por javascript. Solo como un ejemplo: enlaces que envían una solicitud AJAX para obtener el contenido de los artículos y luego mostrar esos datos en un div. Obviamente, en este ejemplo, necesito que cada enlace almacene un bit adicional de información: la identificación del artículo. La forma en que lo he estado manejando en caso fue poner esa información en el enlace href esto:

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

Luego uso jQuery para encontrar los elementos a.article y adjuntar el controlador de eventos apropiado. (no se obsesione con la usabilidad o la semántica aquí, es solo un ejemplo)

De todos modos, este método funciona, pero huele un poco y no es extensible en absoluto (¿qué sucede si la función de clic tiene más de un parámetro? ¿Qué pasa si algunos de esos parámetros son opcionales?)

La respuesta inmediatamente obvia fue usar atributos en el elemento. Quiero decir, para eso están, ¿verdad? (Mas o menos).

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

En mi pregunta reciente , pregunté si este método era válido, y resulta que, aparte de definir mi propio DTD (no lo hago), entonces no, no es válido ni confiable. Una respuesta común fue poner los datos en el classatributo (aunque podría haber sido por mi ejemplo mal elegido), pero para mí, esto huele aún más. Sí, es técnicamente válido, pero no es una gran solución.

Otro método que utilicé en el pasado era generar algunos JS e insertarlos en la página en una <script>etiqueta, creando una estructura que se asociaría con el objeto.

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

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

Pero esto puede ser realmente difícil de mantener y, en general, es muy complicado.

Entonces, para llegar a la pregunta, ¿cómo almacena información arbitraria para etiquetas HTML ?

nickf
fuente
2
Pregunta relacionada: stackoverflow.com/questions/209428/…
Tamas Czinege

Respuestas:

361

¿Qué versión de HTML estás usando?

En HTML 5, es totalmente válido tener atributos personalizados con prefijos de datos , por ejemplo

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

En XHTML, esto no es realmente válido. Si está en modo XHTML 1.1, el navegador probablemente se quejará, pero en el modo 1.0, la mayoría de los navegadores lo ignorarán en silencio.

Si fuera usted, seguiría el enfoque basado en guiones. Puede hacer que se genere automáticamente en el lado del servidor para que no sea un problema mantenerlo en la parte posterior.

Tamas Czinege
fuente
55
@Tchalvak: Cierto, pero este bit funcionará en la mayoría de los navegadores, sin embargo.
Tamas Czinege
2
Otros han afirmado que no hay razón para esperar en el soporte, ya que el único problema que esto causa es la falla de validación y no rompe el IE. Vea la respuesta de TJ Crowler aquí: stackoverflow.com/questions/1923278/…
Chris
42
Si utiliza atributos data-xxx y desea recuperarlos, simplemente puede usar "domElement.getAttribute ('data-whatever')" sin ningún marco de terceros.
Ohad Kravchick
55
¡Tenga en cuenta el rendimiento! jsperf.com/jquery-data-vs-jqueryselection-data/19
FilmJ
19
Recordatorio: para recuperar los datos, 1337, a través de jquery, asegúrese de eliminar 'datos' del nombre de la variable. Por ejemplo, use: $(this).data('internalid'); En lugar de:$(this).data('data-internalid');
Gideon Rosenthal
134

Si ya está utilizando jQuery, debe aprovechar el método de "datos", que es el método recomendado para almacenar datos arbitrarios en un elemento dom con jQuery.

Para almacenar algo:

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

Para recuperar datos:

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

Eso es todo lo que hay que hacer, pero eche un vistazo a la documentación de jQuery para obtener más información / ejemplos.

Prestaul
fuente
20

Solo de otra manera, personalmente no usaría esto, pero funciona (asegúrese de que su JSON sea válido porque eval () es peligroso).

<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
fuente
1
+1 para pensamiento lateral. Estoy de acuerdo en que probablemente no quiera usar este método, ¡pero es una opción vagamente viable!
nickf
99
@nickf Usted puede deshacerse de evalusar JSON.parseen lugar jsfiddle.net/EAXmY
Simon
12

Los atributos arbitrarios no son válidos, pero son perfectamente confiables en los navegadores modernos. Si está configurando las propiedades a través de javascript, entonces tampoco tiene que preocuparse por la validación.

Una alternativa es establecer atributos en javascript. jQuery tiene un buen método de utilidad solo para ese propósito, o puede usar el suyo propio.

Eran Galperin
fuente
3
¿Por qué no usar data-atributos en su lugar?
Flimm
10

Un truco que funcionará con casi todos los navegadores posibles es usar clases abiertas como esta: <a class='data\_articleid\_5' href="link/for/non-js-users.html>;

Esto no es tan elegante para los puristas, pero es universalmente compatible, cumple con los estándares y es muy fácil de manipular. Realmente parece el mejor método posible. Si usted serialize, modifica , copia sus etiquetas, o hace casi cualquier otra cosa, datapermanecerá adjunto, copiado, etc.

El único problema es que no puede almacenar objetos no serializables de esa manera , y puede haber límites si coloca algo realmente grande allí.

Una segunda forma es usar atributos falsos como:<a articleid='5' href="link/for/non-js-users.html">

Esto es más elegante, pero rompe el estándar, y no estoy 100% seguro sobre el soporte. Muchos navegadores lo admiten por completo, creo que IE6 admite el JSacceso pero noCSS selectors (lo que realmente no importa aquí), tal vez algunos navegadores estarán completamente confundidos, debe verificarlo.

Hacer cosas divertidas como serializar y deserializar sería aún más peligroso.

El uso idsde JShash puro funciona principalmente, excepto cuando intenta copiar sus etiquetas. Si es así tag <a href="..." id="link0">, cópielo mediante JSmétodos estándar y luego intente modificar dataadjunto a una sola copia, la otra copia se modificará.

No es un problema si no copia tags, o usa datos de solo lectura . Si copia tagsy se modifican, deberá manejarlo manualmente.

taw
fuente
almacenar valse en clase es increíble
Saravanan Rajaraman
10

Usando jquery,

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

para recuperar: $('#element_id').data('extra_tag');

usuario2458978
fuente
6

Sé que actualmente estás usando jQuery, pero qué pasa si definiste el controlador onclick en línea. Entonces podrías hacer:

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

Podrías usar etiquetas de entrada ocultas. No obtengo errores de validación en w3.org con esto:

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

Con jQuery obtendría la ID del artículo con algo como (no probado):

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

Pero recomendaría HTML5 si esa es una opción.

phylae
fuente
13
De hecho, no creo que style="display: none"sea ​​necesario para los campos de entrada ocultos.
phylae
1
Buen enfoque, totalmente válido en todas las versiones HTML. Desaconsejo encarecidamente la codificación suponiendo que todos sus usuarios tendrán un navegador totalmente compatible con HTML5. Y pantalla: no se necesita ninguno para los campos ocultos.
andreszs
Muy agradable. Esta es la mejor solución que he encontrado para XHTML donde los atributos de datos no son una opción válida. En mi opinión, no abusa de las etiquetas / atributos de manera involuntaria, casi no tiene "olor" en absoluto. Y como dijeron los demás: display: ninguno no es realmente necesario.
Arahman
4

¿Por qué no hacer uso de los datos significativos que ya existen, en lugar de agregar datos arbitrarios?

es decir, usar <a href="https://stackoverflow.com/articles/5/page-title" class="article-link"> , , y luego puede obtener mediante programación todos los enlaces de artículos en la página (a través del nombre de clase) y la ID del artículo (que coincida con la expresión regular /articles\/(\d+)/contra this.href).


fuente
2
El problema con esto es que tampoco es realmente extensible
ehdv el
4

Como usuario de jQuery, usaría el complemento Metadata . El HTML se ve limpio, se valida y puede incrustar cualquier cosa que pueda describirse utilizando la notación JSON.

Robin Smidsrød
fuente
3

Entonces debería haber cuatro opciones para hacerlo:

  1. Ponga los datos en el atributo id.
  2. Ponga los datos en el atributo arbitrario
  3. Poner los datos en el atributo de clase
  4. Pon tus datos en otra etiqueta

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

Shanison
fuente
@ h4ck3rm1k3 ... no en el atributo id porque debe ser único con el documento, y debe repetirse si es necesario en una barra lateral, o algo así ... Es una pregunta antigua, pero aún es válida
miguel-svq
2

Abogo por el uso del atributo "rel". El XHTML valida, el atributo en sí rara vez se usa y los datos se recuperan de manera eficiente.

demonkoryu
fuente
no puedo hacer que esa identificación rompa el atributo nofollow en los enlaces
Carter Cole
2

Este es un buen consejo. Gracias a @Prestaul

Si ya está utilizando jQuery, debe aprovechar el método de "datos", que es el método recomendado para almacenar datos arbitrarios en un elemento dom con jQuery.

Muy cierto, pero ¿qué pasa si desea almacenar datos arbitrarios en HTML simple? Aquí hay otra alternativa ...

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

Ponga sus datos en los atributos de nombre y valor de un elemento de entrada oculto. Esto podría ser útil si el servidor está generando HTML (es decir, un script PHP o lo que sea), y su código JavaScript usará esta información más adelante.

Es cierto que no es el más limpio, pero es una alternativa. Es compatible con todos los navegadores y es XHTML válido. NO debe usar atributos personalizados, ni debe usar atributos con el prefijo 'data-', ya que podría no funcionar en todos los navegadores. Y, además, su documento no pasará la validación W3C.

BMiner
fuente
no estoy seguro exactamente, pero algunos navegadores pueden quejarse si usa atributos personalizados con un tipo de documento "estricto". De cualquier manera, no es XHTML válido.
BMiner
2

Puede usar el prefijo de datos de su propio atributo hecho de un elemento aleatorio ( <span data-randomname="Data goes here..."></span>), pero esto solo es válido en HTML5. Por lo tanto, los navegadores pueden quejarse de la validez.

También podrías usar una <span style="display: none;">Data goes here...</span>etiqueta. Pero de esta manera no puede usar las funciones de atributo, y si css y js están desactivados, esta tampoco es una buena solución.

Pero lo que personalmente prefiero es lo siguiente:

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

La entrada en todos los casos estará oculta, los atributos son completamente válidos y no se enviarán si está dentro de una <form>etiqueta, ya que no tiene ningún nombre, ¿verdad? Sobre todo, los atributos son realmente fáciles de recordar y el código se ve bien y fácil de entender. Incluso podría poner un atributo ID en él, para que también pueda acceder fácilmente con JavaScript y acceder al par clave-valor con input.title; input.value.

Yeti
fuente
Estoy seguro de que no trabajó con tablas html y selección lo suficiente. Utilizará el atributo de datos con más frecuencia para ahorrar algo de trabajo.
1
En realidad, uso mucho el atributo 'data-'. Pero depende de cuáles sean sus requisitos. Por ejemplo, con <input /> puede tener cualquier clave, mientras que para 'datos-' se limita preferiblemente a una cadena en minúscula sin ningún carácter no alfanumérico.
Yeti
1

Una posibilidad podría ser:

  • Cree un nuevo div para contener todos los datos extendidos / arbitrarios
  • Haga algo para asegurarse de que este div sea invisible (por ejemplo, CSS más un atributo de clase del div)
  • Coloque los datos extendidos / arbitrarios dentro de las etiquetas [X] HTML (por ejemplo, como texto dentro de las celdas de una tabla, o cualquier otra cosa que desee) dentro de este div invisible
ChrisW
fuente
1

Otro enfoque puede ser almacenar un par clave: valor como una clase simple usando la siguiente sintaxis:

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

Esto es válido y se puede recuperar fácilmente con los selectores jQuery o una función personalizada.

Raphaël
fuente
0

En mi empleador anterior, usábamos etiquetas HTML personalizadas todo el tiempo para guardar información sobre los elementos del formulario. El problema: sabíamos que el usuario se vio obligado a usar IE.

No funcionó bien para Firefox en ese momento. No sé si FireFox ha cambiado esto o no, pero tenga en cuenta que agregar o no sus propios atributos a los elementos HTML puede o no ser compatible con el navegador de su lector.

Si puede controlar qué navegador está utilizando su lector (es decir, un applet web interno para una corporación), entonces, por todos los medios, pruébelo. ¿Qué puede doler, verdad?

alemán
fuente
0

Así es como te hago páginas ajax ... es un método bastante fácil ...

    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="));
                   }
               }
           });
}

Lo que funciona es que básicamente analiza todas las URL que tienen la clase 'ajx' y reemplaza una palabra clave y agrega el signo # ... así que si js está desactivado, las URL actuarán como lo hacen normalmente ... todo " aplicaciones "(cada sección del sitio) tiene su propia palabra clave ... así que todo lo que necesito hacer es agregar a la matriz js anterior para agregar más páginas ...

Entonces, por ejemplo, mi configuración actual está establecida en:

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

Entonces, si tengo una URL como:

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

el script js reemplazaría la parte / ads / para que mi URL termine siendo

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

Luego uso el complemento jquery bbq para cargar la página en consecuencia ...

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

jason
fuente
0

He encontrado que el complemento de metadatos es una excelente solución al problema de almacenar datos arbitrarios con la etiqueta html de manera que sea fácil de recuperar y usar con jQuery.

Importante : el archivo real que incluye es de solo 5 kb y no 37 kb (que es el tamaño del paquete de descarga completo)

Aquí hay un ejemplo de cómo se usa para almacenar valores que uso al generar un evento de seguimiento de Google Analytics (nota: data.label y data.value son parámetros opcionales)

$(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
fuente
0

En html, podemos almacenar atributos personalizados con el prefijo 'data-' antes del nombre del atributo como

<p data-animal='dog'>This animal is a dog.</p>. Consultar documentación

Podemos usar esta propiedad para establecer dinámicamente y obtener atributos usando jQuery como: Si tenemos una etiqueta ap como

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

Luego, para crear un atributo llamado 'raza' para la etiqueta anterior, podemos escribir:

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

Para recuperar los datos en cualquier momento, podemos escribir:

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

Akash Ghosh
fuente
0

Mientras su trabajo real se realice en el servidor, ¿por qué necesitaría información personalizada en las etiquetas html en la salida de todos modos? todo lo que necesita saber en el servidor es un índice en cualquier tipo de lista de estructuras con su información personalizada. Creo que está buscando almacenar la información en el lugar equivocado.

Reconoceré, por desafortunado que sea, que en muchos casos la solución correcta no es la solución correcta. En cuyo caso, sugeriría generar algunos javascript para guardar la información adicional.

Muchos años después:

Esta pregunta se publicó aproximadamente tres años antes de que los data-...atributos se convirtieran en una opción válida con el advenimiento de html 5, por lo que la verdad cambió y la respuesta original que di ya no es relevante. Ahora sugeriría usar atributos de datos en su lugar.

<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
fuente
¿Cómo se supone que pasarás los datos a JavaScript entonces?
nickf