La fonction attr () de jQuery casse html avec des caractères spéciaux html?

Veuillez consulter le code suivant:

Http://jsfiddle.net/htdTg/2/

Dans le premier lien, il existe un attribut de titre contenant le caractère spécial html &lt; suivi par "!" (Peu importe le caractère auquel il est suivi). Lorsque nous prenons la valeur de cet attribut de titre avec la fonction attr () de jQuery, le html est brisé (vous pouvez voir qu'il n'y a pas de caractère "<" imprimé tant que le texte suivant est également manquant.

Dans le deuxième lien, la seule différence est que j'ai ajouté un espace après &lt; Et maintenant ça fonctionne comme prévu.

Pensez-vous que c'est un bug dans jQuery ou que je ne comprend pas quelque chose?

PS. Si vous pensez que je fais quelque chose d'étrange – c'est juste une partie du code d'un plugin tooltip.

HTML:

 <a href="#" title="<div style='color:red'>This is the less than sign: &lt;! Now you know it?</div>">This is a link</a><br> <a href="#" title="<div style='color:red'>This is the less than sign: &lt; ! Now you know it?</div>">This is a link</a><br>​ 

JQuery:

 $('a').each(function() { $('body').append($(this).attr('title')); }); // just to exclude that it's append() function's fault :) $('body').append("<div style='color:red'>This is the less than sign: &lt;! Now you know it?</div>");​ 

C'est très intéressant. J'ai cherché quel texte peut être dans un attribut de title et la référence dit:

Les agents utilisateurs doivent interpréter les valeurs d'attribut comme suit:

  1. Remplacer les entités de caractères par des caractères,
  2. Ignorer les flux de ligne,
  3. Remplacez chaque retour de chariot ou onglet avec un seul espace.

Apparemment, c'est le comportement attendu. &lt; Est analysé comme < par le navigateur, qui peut être interprété comme HTML par jQuery.

Vous devriez également échapper à l'amperse:

 &amp;lt; 

Demo: http://jsfiddle.net/htdTg/9/

Une meilleure démo: http://jsfiddle.net/PsZeY/6/

Pourquoi se passe-t-il?

Cela se produit parce que &lt;! Now you know it? </div> &lt;! Now you know it? </div> &lt;! Now you know it? </div> est converti en <! Now you know it? </div--> <! Now you know it? </div-->

Selon la norme HTML <! Et > est la structure de début et de fin de commentaire . Notez ceci que la structure des commentaires ne fait pas de commentaire . Par conséquent, Browwer convertit le reste en commentaire à moins qu'il n'ait un délimiteur final.

Du W3C

 <!-- this is a comment --> <!-- and so is this one, which occupies more than one line --> 

L'espace blanc n'est pas autorisé entre le délimiteur d' ouverture de la déclaration de marquage ( <! ) Et le délimiteur ouvert du commentaire ( -- ), mais est autorisé entre le délimiteur étroit de commentaire ( -- ) et le délimiteur de fermeture de la déclaration de balisage (">"). Une erreur commune consiste à inclure une chaîne d'hyphens ( --- ) dans un commentaire. Les auteurs doivent éviter de mettre deux ou plusieurs traits d'union adjacents à l'intérieur des commentaires.

Aussi ici

La syntaxe des déclarations de commentaires dans SGML est

  comment declaration = MDO ("<!"), (comment, ( s | comment )* )?, MDC (">") comment = COM ("--"), SGML character*, COM ("--") 

Comment le résoudre?

Tu le sais deja. Utiliser &amp; À remplacer & . Alors écris &amp;lt;! Au lieu de &lt;! . Cela rendra &lt; Ajouté à l'élément du corps au lieu de <! Qui est l'ouverture de la structure des commentaires.

Dans ce cas…

 title="<div style='color:red'>This is the less than sign: &lt;! Now you know it?</div>" 

&lt;! Est converti en <! Qui est le début d'un commentaire HTML et exactement pourquoi il n'est pas rendu dans la fenêtre du navigateur.

Pour tous les cas, vous ne devriez pas avoir des entités HTML contenues dans un attribut. Utilisez-le plutôt …

 title="&lt;div style='color:red'&gt;This is the less than sign: &amp;lt;! Now you know it?&lt;/div&gt;" 

http://jsfiddle.net/htdTg/5/

Si vous souhaitez conserver les entités HTML, utilisez &lt;div&gt; Pour être traité comme <div> . Alternativement, &amp;lt;div&amp;gt; Rendra <div> dans la fenêtre du navigateur.

Voir: http://jsfiddle.net/htdTg/8/

Donc, si vous voulez que le navigateur affiche effectivement un <! , Puis utilisez ceci: &amp;lt!

Le texte ne manque pas le problème, c'est qu'il soit commenté parce que &lt;! Est le même de <! Qui est traduit en <!-- (ne sais pas pourquoi) qui commence un commentaire en html .

Si vous inspectez votre html, vous verrez ce qui suit.

 <div style='color:red'>This is the less than sign: <!-- Now you know it? --></div> <div style='color:red'>This is the less than sign: < ! Now you know it?</div> 

Je ne suis pas sûr de poser la question ou de chercher une solution au problème. Si ce dernier, étrangement, cela semble fonctionner bien: &amp;lt;

Code mis à jour:

HTML:

 <a href="#" title="<div style='color:red'>This is the less than sign: &amp;lt;! Now you know it?</div>">This is a link</a><br> <a href="#" title="<div style='color:red'>This is the less than sign: &amp;lt; ! Now you know it?</div>">This is a link</a><br>​ 

JQuery:

 $('a').each(function() { $('body').append($(this).attr('title')); }); // just to exclude that it's append() function's fault :) $('body').append("<div style='color:red'>This is the less than sign: &lt;! Now you know it?</div>");​ 

Violoncelle mise à jour: http://jsfiddle.net/htdTg/3/

Rien n'est vraiment mal …

Le problème est que les attributs html inside doivent être encodés. Vous avez déjà codé le < as &lt; Et cela signifie qu'il sera lu comme < .

Donc .attr() renverra un caractère < pure et non codé ..

La raison pour laquelle il ne s'affiche pas est avec .append qui tentera d'analyser le html si il pense qu'il y a html. Il trouve le <! Texte et il le considère comme un commentaire html. En fait, cela se fait directement par le navigateur .


Si vous regardez

 var e = document.createElement('div'); e.innerHTML = '<!'; console.log(e.innerHTML); 

Vous verrez que le HTML interne de la div après l'avoir réglé sur <! Est <!----> .

C'est ainsi que les navigateurs interprètent ce code … il n'a rien à voir avec jQuery ..