Come archiviare dati arbitrari per alcuni tag HTML


338

Sto realizzando una pagina con alcune interazioni fornite da JavaScript. Ad esempio: collegamenti che inviano una richiesta AJAX per ottenere il contenuto degli articoli e quindi visualizzare tali dati in un div. Ovviamente in questo esempio, ho bisogno di ogni link per memorizzare un po 'di informazioni in più: l'id dell'articolo. Il modo in cui l'ho gestita nel caso in cui è stato quello di mettere quelle informazioni nel collegamento href questo:

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

Quindi uso jQuery per trovare gli elementi a.article e allego il gestore eventi appropriato. (non impazzire troppo sull'usabilità o sulla semantica qui, è solo un esempio)

Ad ogni modo, questo metodo funziona, ma puzza un po 'e non è affatto estensibile (cosa succede se la funzione clic ha più di un parametro? Cosa succede se alcuni di questi parametri sono opzionali?)

La risposta immediatamente ovvia era usare gli attributi sull'elemento. Voglio dire, ecco a cosa servono, vero? (Tipo).

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

Nella mia recente domanda ho chiesto se questo metodo fosse valido e si scopre che a corto di definire il mio DTD (non lo faccio), quindi no, non è valido o affidabile. Una risposta comune è stata quella di inserire i dati classnell'attributo (anche se questo potrebbe essere stato a causa del mio esempio scelto male), ma per me, questo ha ancora più odore. Sì, è tecnicamente valido, ma non è un'ottima soluzione.

Un altro metodo che avevo usato in passato era generare un po 'di JS e inserirlo nella pagina in un <script>tag, creando una struttura che si associasse all'oggetto.

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

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

Ma questo può essere un vero dolore nel culo da mantenere ed è generalmente molto disordinato.

Quindi, per arrivare alla domanda, come archiviate informazioni arbitrarie per i tag HTML ?


Risposte:


361

Quale versione di HTML stai usando?

In HTML 5, è totalmente valido avere attributi personalizzati con prefisso dati , ad es

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

In XHTML, questo non è veramente valido. Se sei in modalità XHTML 1.1, probabilmente il browser si lamenterà, ma in modalità 1.0, la maggior parte dei browser lo ignorerà silenziosamente.

Se fossi in te, seguirei l'approccio basato sulla sceneggiatura. Potresti farlo generare automaticamente sul lato server in modo che non sia un dolore alla schiena da mantenere.


5
@Tchalvak: vero, ma questo bit funzionerà sulla maggior parte dei browser, comunque.
Tamas Czinege,

2
Altri hanno affermato che non c'è motivo di attendere il supporto, poiché l'unico problema che ciò causa è la mancata convalida e non interrompe IE. Vedi la risposta di TJ Crowler qui: stackoverflow.com/questions/1923278/…
Chris,

42
Se usi gli attributi data-xxx e vuoi recuperarli, puoi semplicemente usare "domElement.getAttribute ('data-qualunque')" senza alcun framework di terze parti.
Ohad Kravchick,


19
Promemoria: per recuperare i dati, 1337, tramite jquery, assicurarsi di rimuovere "dati" dal nome della variabile. Ad esempio, utilizzare: $(this).data('internalid'); Invece di:$(this).data('data-internalid');
Gideon Rosenthal,

134

Se stai già utilizzando jQuery, dovresti sfruttare il metodo "data", che è il metodo consigliato per archiviare dati arbitrari su un elemento dom con jQuery.

Per conservare qualcosa:

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

Per recuperare i dati:

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

Questo è tutto ciò che c'è da fare, ma dai un'occhiata alla documentazione di jQuery per maggiori informazioni / esempi.


20

Solo in un altro modo, personalmente non lo userei ma funziona (assicurati che il tuo JSON sia valido perché eval () è pericoloso).

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

1
+1 per il pensiero laterale. Sono d'accordo che probabilmente non vorrei usare questo metodo, ma è un'opzione vagamente praticabile!
Nickf

9
@nickf Puoi sbarazzarti di evalusare JSON.parseinvece jsfiddle.net/EAXmY
Simon

12

Gli attributi arbitrari non sono validi, ma sono perfettamente affidabili nei browser moderni. Se stai impostando le proprietà tramite javascript, non devi preoccuparti anche della convalida.

Un'alternativa è impostare gli attributi in javascript. jQuery ha un buon metodo di utilità proprio per quello scopo, oppure puoi farlo tu stesso.


3
Perché non utilizzare data-invece gli attributi?
Flimm,

10

Un hack che funzionerà praticamente con tutti i possibili browser consiste nell'utilizzare classi aperte come questa: <a class='data\_articleid\_5' href="link/for/non-js-users.html>;

Non è così elegante per i puristi, ma è universalmente supportato, conforme agli standard e molto facile da manipolare. Sembra davvero il miglior metodo possibile. Se si serialize, modificare , copiare i tag, o fare qualsiasi altra cosa, datafarà rimanere attaccato, copiato etc.

L'unico problema è che non è possibile archiviare oggetti non serializzabili in questo modo e potrebbero esserci dei limiti se si inserisce qualcosa di veramente enorme lì.

Un secondo modo è usare falsi attributi come:<a articleid='5' href="link/for/non-js-users.html">

Questo è più elegante, ma rompe gli standard e non sono sicuro al 100% del supporto. Molti browser lo supportano completamente, penso che IE6 supporti l' JSaccesso per questo ma non CSS selectors(cosa che non importa davvero qui), forse alcuni browser saranno completamente confusi, è necessario verificarlo.

Fare cose divertenti come serializzare e deserializzare sarebbe ancora più pericoloso.

L'uso dell'hash idspuro JSfunziona principalmente, tranne quando si tenta di copiare i tag. In tag <a href="..." id="link0">tal caso , copiarlo tramite JSmetodi standard e quindi provare a modificare dataallegato a una sola copia, l'altra copia verrà modificata.

Non è un problema se non si copiano messaggi di posta elettronica tago si utilizzano dati di sola lettura . Se copi tage vengono modificati, dovrai gestirlo manualmente.


archiviare valse in classe è fantastico
Saravanan Rajaraman,

10

Usando jquery,

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

recuperare: $('#element_id').data('extra_tag');


6

So che stai attualmente utilizzando jQuery, ma cosa succede se hai definito il gestore onclick in linea. Quindi potresti fare:

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

6

È possibile utilizzare tag di input nascosti. Non ricevo errori di convalida su w3.org con questo:

<!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 otterrai l'ID articolo con qualcosa del tipo (non testato):

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

Ma consiglierei HTML5 se questa è un'opzione.


13
In realtà non credo style="display: none"sia necessario per i campi di input nascosti.
phylae,

1
Buon approccio, totalmente valido in tutte le versioni HTML. Scoraggio vivamente di codificare con il presupposto che tutti i tuoi utenti disporranno di un browser con reclamo totalmente HTML5. E display: nessuno non è necessario per i campi nascosti.
andreszs

Molto bella. Questa è la migliore soluzione che ho trovato per XHTML in cui gli attributi dei dati non sono un'opzione valida. IMO non abusa di tag / attributi in modo non intenzionale, non ha quasi alcun "odore". E come hanno detto gli altri: display: nessuno non è davvero necessario.
Arahman,

4

Perché non utilizzare i dati significativi già presenti, invece di aggiungere dati arbitrari?

cioè usare <a href="https://stackoverflow.com/articles/5/page-title" class="article-link">, e quindi è possibile ottenere a livello di codice tutti i collegamenti dell'articolo sulla pagina (tramite il nome classe) e l'ID articolo (facendo corrispondere la regex /articles\/(\d+)/contro this.href).


2
Il problema è che non è nemmeno molto estensibile
ehdv,


3

Quindi ci dovrebbero essere quattro scelte per farlo:

  1. Inserisci i dati nell'attributo id.
  2. Inserisci i dati nell'attributo arbitrario
  3. Inserisci i dati nell'attributo di classe
  4. Inserisci i tuoi dati in un altro tag

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


@ h4ck3rm1k3 ... non nell'attributo id perché deve essere univoco con il documento e dovrebbe essere ripetuto se necessario in una barra laterale o qualcosa del genere ... È una vecchia domanda, ma è ancora valida
miguel-svq

2

Sostengo l'uso dell'attributo "rel". L'XHTML viene convalidato, l'attributo stesso viene utilizzato raramente e i dati vengono recuperati in modo efficiente.


non posso fare che quell'ID rompa l'attributo nofollow sui link
Carter Cole

2

Questo è un buon consiglio Grazie a @Prestaul

Se stai già utilizzando jQuery, dovresti sfruttare il metodo "data", che è il metodo consigliato per archiviare dati arbitrari su un elemento dom con jQuery.

Molto vero, ma cosa succede se si desidera archiviare dati arbitrari in HTML semplice? Ecco un'altra alternativa ...

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

Inserisci i tuoi dati nel nome e negli attributi di valore di un elemento di input nascosto. Questo potrebbe essere utile se il server sta generando HTML (cioè uno script PHP o altro) e il tuo codice JavaScript utilizzerà queste informazioni in un secondo momento.

Certo, non il più pulito, ma è un'alternativa. È compatibile con tutti i browser ed è XHTML valido. NON dovresti usare attributi personalizzati, né dovresti davvero usare attributi con il prefisso 'data-', poiché potrebbe non funzionare su tutti i browser. Inoltre, il documento non supererà la convalida W3C.


non sono sicuro esattamente, ma alcuni browser potrebbero lamentarsi se si utilizzano attributi personalizzati con un tipo di documento "rigoroso". Ad ogni modo, non è XHTML valido.
BMiner,

2

È possibile utilizzare il prefisso dati del proprio attributo creato di un elemento casuale (<span data-randomname="Data goes here..."></span> ), ma questo è valido solo in HTML5. Pertanto i browser potrebbero lamentarsi della validità.

Puoi anche usare un <span style="display: none;">Data goes here...</span>tag. Ma in questo modo non è possibile utilizzare le funzioni degli attributi e se css e js sono disattivati, questa non è nemmeno una soluzione accurata.

Ma ciò che preferisco personalmente è il seguente:

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

In ogni caso l'input verrà nascosto, gli attributi sono completamente validi e non verrà inviato se si trova all'interno di un <form>tag, dal momento che non ha alcun nome, giusto? Soprattutto, gli attributi sono davvero facili da ricordare e il codice sembra carino e facile da capire. Puoi anche inserire un attributo ID in esso, in modo da poterlo accedere facilmente anche con JavaScript e accedere alla coppia chiave-valore con input.title; input.value.


Sono sicuro che non hai lavorato abbastanza con le tabelle html e la selezione abbastanza. Utilizzerai l'attributo data più spesso per risparmiare un po 'di lavoro.

1
In realtà uso molto l'attributo 'data-'. Ma dipende dalle tue esigenze. Ad esempio, con <input /> puoi avere qualsiasi tasto, mentre per 'data-' questo è limitato preferibilmente a una stringa minuscola senza alcun carattere non alfanumerico.
Yeti,

1

Una possibilità potrebbe essere:

  • Crea un nuovo div per contenere tutti i dati estesi / arbitrari
  • Fai qualcosa per assicurarti che questo div sia invisibile (es. CSS più un attributo class del div)
  • Inserisci i dati estesi / arbitrari all'interno di tag [X] HTML (ad es. Come testo all'interno delle celle di una tabella o qualsiasi altra cosa ti possa piacere) all'interno di questo div invisibile

1

Un altro approccio può essere quello di memorizzare una chiave: coppia valore come una semplice classe usando la sintassi seguente:

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

Questo è valido e può essere facilmente recuperato con i selettori jQuery o una funzione personalizzata.


0

Nel mio precedente datore di lavoro, abbiamo sempre usato tag HTML personalizzati per contenere informazioni sugli elementi del modulo. Il problema: sapevamo che l'utente era costretto a utilizzare IE.

All'epoca non funzionava bene con FireFox. Non so se FireFox lo abbia modificato o meno, ma sappi che l'aggiunta dei tuoi attributi agli elementi HTML può o meno essere supportata dal browser del tuo lettore.

Se riesci a controllare quale browser sta utilizzando il tuo lettore (ovvero un'applet web interna per un'azienda), allora provalo. Cosa può ferire, vero?


0

Ecco come faccio ajax pages ... è un metodo abbastanza semplice ...

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

Il modo in cui funziona è fondamentalmente guardare tutti gli URL che hanno la classe "ajx" e sostituisce una parola chiave e aggiunge il segno # ... quindi se js è disattivato gli URL agiranno come fanno normalmente ... tutto " app "(ogni sezione del sito) ha una propria parola chiave ... quindi tutto ciò che devo fare è aggiungere all'array js sopra per aggiungere più pagine ...

Ad esempio, le mie impostazioni correnti sono impostate su:

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

Quindi, se ho un URL come:

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

lo script js sostituirà la / ads / parte così il mio URL finirà per essere

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

Quindi uso il plugin jquery bbq per caricare la pagina di conseguenza ...

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


0

Ho trovato che il plug-in dei metadati è un'ottima soluzione al problema della memorizzazione di dati arbitrari con il tag html in un modo che semplifica il recupero e l'utilizzo con jQuery.

Importante : il file effettivo che includi è solo 5 kb e non 37 kb (che è la dimensione del pacchetto di download completo)

Ecco un esempio del suo utilizzo per archiviare i valori che utilizzo durante la generazione di un evento di tracciamento di Google Analytics (nota: data.label e data.value sono parametri opzionali)

$(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"/>

0

In html, possiamo memorizzare attributi personalizzati con il prefisso 'data-' prima del nome dell'attributo come

<p data-animal='dog'>This animal is a dog.</p>. Dai un'occhiata documentazione

Possiamo usare questa proprietà per impostare dinamicamente e ottenere attributi usando jQuery come: Se abbiamo tag ap simili

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

Quindi per creare un attributo chiamato 'razza' per il tag sopra, possiamo scrivere:

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

Per recuperare i dati in qualsiasi momento, possiamo scrivere:

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


0

Fintanto che il tuo vero lavoro è svolto sul lato server, perché dovresti comunque avere bisogno di informazioni personalizzate nei tag html nell'output? tutto ciò che devi sapere sul server è un indice in qualsiasi tipo di elenco di strutture con le tue informazioni personalizzate. Penso che tu stia cercando di archiviare le informazioni nel posto sbagliato.

Riconoscerò, per quanto sfortunato, che in molti casi la soluzione giusta non è la soluzione giusta. Nel qual caso suggerirei fortemente di generare un po 'di javascript per contenere le informazioni extra.

Molti anni dopo:

Questa domanda è stata pubblicata circa tre anni prima che gli data-...attributi diventassero un'opzione valida con l'avvento di HTML 5, quindi la verità è cambiata e la risposta originale che ho dato non è più pertinente. Ora suggerirei invece di utilizzare gli attributi dei dati .

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

come dovresti passare i dati a JavaScript allora?
Nickf
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.