Como armazenar dados arbitrários para algumas tags HTML

338

Estou criando uma página que possui alguma interação fornecida por javascript. Apenas como exemplo: links que enviam uma solicitação AJAX para obter o conteúdo dos artigos e, em seguida, exibem esses dados em uma div. Obviamente, neste exemplo, preciso de cada link para armazenar um pouco mais de informação: a identificação do artigo. A maneira como eu tenho lidado com isso no caso foi colocar essas informações no link href:

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

Em seguida, uso o jQuery para encontrar os elementos a.article e anexar o manipulador de eventos apropriado. (não fique muito preocupado com a usabilidade ou semântica aqui, é apenas um exemplo)

De qualquer forma, esse método funciona, mas cheira um pouco e não é extensível (o que acontece se a função click tiver mais de um parâmetro? E se alguns desses parâmetros forem opcionais?)

A resposta imediatamente óbvia foi usar atributos no elemento. Quero dizer, é para isso que servem, certo? (Mais ou menos).

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

Na minha pergunta recente , perguntei se esse método era válido, e acontece que, além de definir meu próprio DTD (não), não, não é válido ou confiável. Uma resposta comum foi colocar os dados no classatributo (embora isso possa ter acontecido por causa do meu exemplo mal escolhido), mas para mim isso cheira ainda mais. Sim, é tecnicamente válido, mas não é uma ótima solução.

Outro método que eu usei no passado foi realmente gerar JS e inseri-lo na página em uma <script>tag, criando uma estrutura que se associaria ao objeto.

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

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

Mas isso pode ser uma verdadeira dor de cabeça para manter e geralmente é apenas muito confuso.

Então, para chegar à pergunta, como você armazena informações arbitrárias para tags HTML ?

nickf
fonte
2
Pergunta relacionada: stackoverflow.com/questions/209428/…
Tamas Czinege

Respostas:

361

Qual versão do HTML você está usando?

No HTML 5, é totalmente válido ter atributos personalizados prefixados com dados - por exemplo,

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

No XHTML, isso não é realmente válido. Se você estiver no modo XHTML 1.1, o navegador provavelmente reclamará, mas no modo 1.0, a maioria dos navegadores o ignorará silenciosamente.

Se eu fosse você, seguiria a abordagem baseada em script. Você pode fazer com que seja gerado automaticamente no lado do servidor, para que não seja difícil manter as costas.

Tamas Czinege
fonte
5
@Tchalvak: Verdade, mas esse bit funcionará na maioria dos navegadores, no entanto.
Tamas Czinege
2
Outros alegaram que não há razão para esperar pelo suporte, pois o único problema que isso causa é a falha na validação e o software não quebra o IE. Veja a resposta de TJ Crowler aqui: stackoverflow.com/questions/1923278/…
Chris
42
Se você usa os atributos data-xxx e deseja recuperá-los, pode simplesmente usar o "domElement.getAttribute ('data-seja o que for')" sem nenhuma estrutura de terceiros.
Ohad Kravchick
5
Tenha em mente o desempenho! O que você precisa
saber é que você pode
19
Lembrete: para recuperar os dados, 1337, via jquery, remova 'data' do nome da variável. Por exemplo, use: $(this).data('internalid'); Em vez de:$(this).data('data-internalid');
Gideon Rosenthal
134

Se você já estiver usando o jQuery, use o método "data", que é o método recomendado para armazenar dados arbitrários em um elemento dom com o jQuery.

Para armazenar algo:

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

Para recuperar dados:

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

Isso é tudo o que existe, mas dê uma olhada na documentação do jQuery para obter mais informações / exemplos.

Prestaul
fonte
20

Apenas de outra maneira, eu pessoalmente não usaria isso, mas funciona (assegure que seu JSON é válido porque eval () é perigoso).

<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
fonte
11
+1 para o pensamento lateral. Concordo que provavelmente não gostaria de usar esse método, mas é uma opção vagamente viável!
nickf
9
@nickf Você pode se livrar de evalusar JSON.parseem vez jsfiddle.net/EAXmY
Simon
12

Atributos arbitrários não são válidos, mas são perfeitamente confiáveis ​​em navegadores modernos. Se você estiver configurando as propriedades via javascript, não precisará se preocupar com a validação também.

Uma alternativa é definir atributos em javascript. O jQuery possui um bom método utilitário apenas para esse fim, ou você pode criar o seu próprio.

Eran Galperin
fonte
3
Por que não usar data-atributos?
Flimm
10

Um hack que funcionará com praticamente todos os navegadores possíveis é usar classes abertas como esta: <a class='data\_articleid\_5' href="link/for/non-js-users.html>;

Isso não é tão elegante para os puristas, mas é universalmente suportado, compatível com os padrões e muito fácil de manipular. Parece realmente o melhor método possível. Se você serialize, modificar , copiar suas tags, ou fazer praticamente qualquer outra coisa, datavai ficar ligado, copiado etc.

O único problema é que você não pode armazenar objetos não serializáveis ​​dessa maneira , e pode haver limites se você colocar algo realmente grande lá.

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

Isso é mais elegante, mas quebra o padrão, e não tenho 100% de certeza sobre o suporte. Muitos navegadores suportam totalmente, acho que o IE6 suporta o JSacesso, mas não CSS selectors(o que realmente não importa aqui), talvez alguns navegadores fiquem completamente confusos, é preciso verificar.

Fazer coisas engraçadas como serializar e desserializar seria ainda mais perigoso.

O uso idsdo JShash puro funciona principalmente, exceto quando você tenta copiar suas tags. Se você tiver tag <a href="..." id="link0">, copie-o por JSmétodos padrão e tente modificar dataanexado a apenas uma cópia, a outra cópia será modificada.

Não é um problema se você não copiar tags ou usar dados somente leitura . Se você copiar se tageles forem modificados, precisará lidar com isso manualmente.

taw
fonte
armazenar valse na classe é incrível
Saravanan Rajaraman
10

Usando jquery,

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

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

user2458978
fonte
6

Sei que atualmente você está usando jQuery, mas e se você definisse o manipulador onclick inline. Então você poderia fazer:

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

Você pode usar tags de entrada ocultas. Não recebo erros de validação no w3.org com isso:

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

Com o jQuery, você obteria o ID do artigo com algo como (não testado):

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

Mas eu recomendaria o HTML5 se essa for uma opção.

filos
fonte
13
Na verdade, acho que não style="display: none"é necessário para campos de entrada ocultos.
phylae
11
Boa abordagem, totalmente válida em todas as versões HTML. Eu desencorajo totalmente a codificação com a suposição de que todos os seus usuários terão um navegador totalmente compatível com HTML5. E display: nenhum é necessário para campos ocultos.
andreszs
Muito agradável. Esta é a melhor solução que encontrei para o XHTML, em que atributos de dados não são uma opção válida. OMI não abuse de tags / atributos de maneira não intencional, quase não tem "cheiro". E como os outros disseram: display: nenhum é realmente necessário.
Arahman 17/02
4

Por que não fazer uso dos dados significativos já existentes, em vez de adicionar dados arbitrários?

ou seja <a href="https://stackoverflow.com/articles/5/page-title" class="article-link">, use e, em seguida, você pode obter programaticamente todos os links de artigos na página (através do nome da classe) e o ID do artigo (comparando o regex /articles\/(\d+)/com o this.href).


fonte
2
Problema com este é que ele também não é realmente extensível
ehdv
4

Como usuário do jQuery, usaria o plugin Metadata . O HTML parece limpo, valida e você pode incorporar qualquer coisa que possa ser descrita usando a notação JSON.

Robin Smidsrød
fonte
3

Portanto, deve haver quatro opções para fazer isso:

  1. Coloque os dados no atributo id.
  2. Coloque os dados no atributo arbitrário
  3. Coloque os dados no atributo class
  4. Coloque seus dados em outra tag

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

Shanison
fonte
@ h4ck3rm1k3 ... não está no atributo id porque deve ser único no documento e deve ser repetido, se necessário, em uma barra lateral ou algo assim ... É uma pergunta antiga, mas ainda é válida
miguel-svq
2

Defendo o uso do atributo "rel". O XHTML valida, o próprio atributo raramente é usado e os dados são recuperados com eficiência.

demonkoryu
fonte
não posso fazer isso ID de quebrar o atributo nofollow nos links
Carter Cole
2

Este é um bom conselho. Graças a @Prestaul

Se você já estiver usando o jQuery, use o método "data", que é o método recomendado para armazenar dados arbitrários em um elemento dom com o jQuery.

É verdade, mas e se você quiser armazenar dados arbitrários em HTML simples? Aqui está mais uma alternativa ...

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

Coloque seus dados nos atributos de nome e valor de um elemento de entrada oculto. Isso pode ser útil se o servidor estiver gerando HTML (ou seja, um script PHP ou o que for), e seu código JavaScript usará essas informações posteriormente.

É certo que não é o mais limpo, mas é uma alternativa. É compatível com todos os navegadores e é XHTML válido. Você NÃO deve usar atributos personalizados, nem deve usar atributos com o prefixo 'data-', pois pode não funcionar em todos os navegadores. Além disso, seu documento não passará na validação do W3C.

BMiner
fonte
não tenho certeza exatamente, mas alguns navegadores podem reclamar se você usar atributos personalizados com um tipo de documento "estrito". De qualquer forma, não é XHTML válido.
BMiner 11/11
2

Você pode usar o prefixo de dados do seu próprio atributo criado de um elemento aleatório ( <span data-randomname="Data goes here..."></span>), mas isso é válido apenas no HTML5. Assim, os navegadores podem reclamar da validade.

Você também pode usar uma <span style="display: none;">Data goes here...</span>tag. Mas dessa forma, você não pode usar as funções de atributo e, se css e js estiverem desativados, também não será uma solução interessante.

Mas o que eu pessoalmente prefiro é o seguinte:

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

Em todos os casos, a entrada ficará oculta, os atributos serão completamente válidos e não serão enviados se estiver dentro de uma <form>tag, pois não possui nenhum nome, certo? Acima de tudo, os atributos são realmente fáceis de lembrar e o código parece bom e fácil de entender. Você pode até colocar um atributo de ID nele, para poder acessá-lo facilmente também com JavaScript e acessar o par de valores-chave input.title; input.value.

Yeti
fonte
Tenho certeza que você não trabalhou com tabelas e seleção html o suficiente. Você usará o atributo de dados com mais frequência para economizar algum trabalho.
11
Na verdade, eu uso muito o atributo 'data-'. Mas isso depende de quais são suas necessidades. Por exemplo, com o <input /> você pode ter qualquer chave, enquanto que para 'data-' isso é limitado a preferencialmente uma string em minúscula sem nenhum caractere não alfanumérico.
Yeti
1

Uma possibilidade pode ser:

  • Crie uma nova div para armazenar todos os dados estendidos / arbitrários
  • Faça algo para garantir que essa div seja invisível (por exemplo, CSS mais um atributo de classe da div)
  • Coloque os dados estendidos / arbitrários dentro das tags HTML [X] (por exemplo, como texto nas células de uma tabela ou qualquer outra coisa que você queira) dentro desta div invisível
ChrisW
fonte
1

Outra abordagem pode ser armazenar uma chave: par de valores como uma classe simples usando a seguinte sintaxe:

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

Isso é válido e pode ser facilmente recuperado com seletores jQuery ou uma função personalizada.

Raphaël
fonte
0

No meu empregador anterior, usamos tags HTML personalizadas o tempo todo para armazenar informações sobre os elementos do formulário. O problema: sabíamos que o usuário era forçado a usar o IE.

Não funcionou bem para o FireFox na época. Não sei se o FireFox mudou isso ou não, mas lembre-se de que adicionar seus próprios atributos aos elementos HTML pode ou não ser suportado pelo navegador do seu leitor.

Se você pode controlar qual navegador o seu leitor está usando (por exemplo, um applet da Web interno para uma corporação), tente de todos os modos. O que pode doer, certo?

Jerry
fonte
0

É assim que eu faço as páginas ajax ... é um 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="));
                   }
               }
           });
}

Como isso funciona, ele basicamente analisa todos os URLs que têm a classe 'ajx' e substitui uma palavra-chave e adiciona o sinal # ... então, se js estiver desativado, os URLs agirão como normalmente ... todos " apps "(cada seção do site) tem sua própria palavra-chave ... então tudo o que preciso fazer é adicionar à matriz js acima para adicionar mais páginas ...

Por exemplo, minhas configurações atuais estão definidas para:

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

Então, se eu tiver um URL como:

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

o script js substituiria o / ads / part para que meu URL acabasse sendo

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

Então eu uso o plugin jquery bbq para carregar a página de acordo ...

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

Jason
fonte
0

Eu achei o plug-in de metadados uma excelente solução para o problema de armazenar dados arbitrários com a tag html de uma maneira que facilite a recuperação e o uso com o jQuery.

Importante : O arquivo real que você inclui é de apenas 5 KB e não 37 KB (que é o tamanho do pacote completo de download)

Aqui está um exemplo dele sendo usado para armazenar valores que eu uso ao gerar um evento de rastreamento do Google Analytics (observação: data.label e data.value são parâmetros opcionais)

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

No html, podemos armazenar atributos personalizados com o prefixo 'data-' antes do nome do atributo, como

<p data-animal='dog'>This animal is a dog.</p>. Verifique a documentação

Podemos usar essa propriedade para definir e obter dinamicamente atributos usando jQuery como: Se tivermos uma tag ap como

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

Em seguida, para criar um atributo chamado 'raça' para a tag acima, podemos escrever:

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

Para recuperar os dados a qualquer momento, podemos escrever:

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

Akash Ghosh
fonte
0

Desde que o trabalho real seja feito no servidor, por que você precisaria de informações personalizadas nas tags html na saída? tudo o que você precisa saber no servidor é um índice para qualquer tipo de lista de estruturas com suas informações personalizadas. Acho que você deseja armazenar as informações no lugar errado.

Reconheço, ainda que infeliz, que em muitos casos a solução certa não é a solução certa. Nesse caso, eu sugeriria fortemente a geração de algum javascript para armazenar as informações extras.

Muitos anos depois:

Esta pergunta foi publicada aproximadamente três anos antes de os data-...atributos se tornarem uma opção válida com o advento do html 5, portanto a verdade mudou e a resposta original que eu dei não é mais relevante. Agora, sugiro usar atributos de dados .

<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
fonte
como você deve passar dados para javascript então?
nickf