web-dev-qa-db-fra.com

Citations d'échappement dans l'attribut de données HTML5 à l'aide de Javascript

J'utilise la fonction .data() de jQuery pour utiliser des attributs de données HTML5 personnalisés, dans lesquels la valeur de l'attribut doit pouvoir contenir des guillemets simples et des guillemets doubles: 

<p class="example" data-example="She said "WTF" on last night's show.">

Je sais que l’utilisation de codes de caractères tels que &quot; dans la valeur de l’attribut de données pourrait faire en sorte que ce qui précède fonctionne, mais je ne peux pas toujours contrôler le mode de saisie des valeurs. De plus, je dois pouvoir utiliser les balises HTML dans le balisage, comme ceci: 

<p class="example" data-example="
She said "<abbr title="What The F***">WTF</abbr>" on last night's show.
">

Si une forme de .replace() est la réponse, il faut alors le faire avant que la valeur ne soit lue par .data() - peut-être en l'appliquant à l'ensemble du <body>?

Les barres obliques inverses normales telles que <abbr title="te\'st">WTF</abbr> ne fonctionnent pas non plus.

Idéalement, cela permettrait de travailler avec les deux:

data-example="..." et data-example='...'

Mais si ce n’est possible que dans un sens, je pourrais au moins y répondre. Des idées?

Update - un peu plus de contexte:

Je travaille sur ceci pour responsejs.com . Une application réelle de ceci pourrait être de ne charger qu'une barre latérale pour les navigateurs au-dessus d'une certaine largeur (et de la gérer dans le navigateur plutôt qu'avec PHP). Dans le cas de WordPress, par exemple, la barre latérale peut contenir des widgets, des images, etc. Les guillemets contenus dans les balises PHP ne sont pas un problème car ils sont analysés en HTML avant de parvenir au navigateur. Exemple:

<aside id="primary" class="sidebar" 

        data-oweb=' 

            <?php dynamic_sidebar( 'primary' ); ?>

        '
    >

    optional default markup for mobile and no-js browsers here

</aside>
27
ryanve

Il n'y a aucun moyen de le contourner, vous devez échapper correctement aux valeurs ou le code HTML ne peut pas être analysé correctement. Vous ne pouvez pas utiliser Javascript pour corriger le code après son analyse, car il a déjà échoué.

Votre exemple avec un codage HTML approprié serait:

<p class="example" data-example="She said &quot;&lt;abbr title=&quot;What The F***&quot;&gt;WTF&lt;/abbr&gt;&quot; on last night's show.">

Vous ne pouvez pas utiliser de barre oblique inverse pour échapper des caractères, car ce n'est pas du code Javascript. Vous utilisez des entités HTML pour échapper des caractères dans le code HTML.

Si vous ne pouvez pas contrôler la manière dont les données sont entrées, vous êtes foutu. Vous devez simplement trouver un moyen de prendre le contrôle.

27
Guffa

Utilisez encodeURI pour échapper les guillemets dans votre objet JSON. Analyser la chaîne avec decodeURI.

var popup = document.getElementById('popup'),
    msgObj = JSON.parse(decodeURI(popup.dataset.message));

console.log(msgObj);
<a id="popup" href="#" data-message="%7B%22title%22:%22Print%22,%22message%22:%22Printing%20not%20yet%20implemented%22%7D" />

3
Dan Smith

Si elles doivent être des chaînes HTML avec " et ' et ainsi de suite, pourquoi ne pas simplement leur créer des éléments HTML séparés: http://jsfiddle.net/N7XXu/ .

Par exemple. le HTML:

<p class="example" data-which="1">a</p>

<p class="example-data" data-which="1">She said "<abbr title="What The F***">WTF</abbr>" on last night's show.</p>

en combinaison avec le code JavaScript suivant:

$('.example').each(function() {
    var correspondingElem = $('.example-data[data-which="'
                              + $(this).data('which')
                              + '"]');
    $(this).data('example', correspondingElem.html());
});

alert($('.example').data('example'));

Bien sûr, cachez les éléments .example-data.

3
pimvdb

Pour que ce soit du bon HTML, vous devez échapper aux caractères gênants. Je leur échapperais avec des entités HTML. Cela signifie que quel que soit l'outil utilisé pour entrer ces informations, il devrait les stocker correctement et/ou que les récupérer à l'arrière du système les échapperait.

Ensuite, si vous souhaitez les utiliser dans votre JS, vous devez exécuter certaines fonctions de recherche et remplacement pour reconvertir les caractères en HTML et en guillemets. 

La plupart des langages de développement back-end ont une sorte de fonctionnalité 'htmlescape/unescape', donc cela ne devrait pas être trop difficile.

Pour résoudre ce problème via jQuery, voici ce que nous avons trouvé via un rapide Google: http://www.naveen.com.au/javascript/jquery/encode-or-decode-html-entities-with-jquery/289 ​​

1
DA.

Voici un outil simple que j'ai créé et que vous pouvez utiliser pour encoder du code HTML:

L'astuce consiste à y échapper deux fois.

J'ai ajouté un\n remplacement supplémentaire pour préserver le texte multiligne puisqu'il est ignoré par text ().

De plus, vous devez échapper les guillemets pour sécuriser un attribut de données.

<div id="esc"></div>
<textarea id="escinput" placeholder="Enter text"></textarea>
<script>
    $("#escinput").bind("change paste keyup", function(){
        $("#esc").text($(this).val().replace(/\n/g,'\\n'));
        $("#esc").text($("#esc").html().replace(/"/g, '&quot;'));
    });            
</script>

Cela devrait créer une chaîne sécurisée pour l'attribut de données.

Vous pouvez le tester ici: http://jsfiddle.net/SplicePHP/n6HFq/

Pour le décoder en HTML, utilisez simplement:

<script>
    var attr = $("#idOfElement").data('attribute');
    var decoded = $('<textarea/>').html(attr).val();
</script>
1
Dieter Gribnitz

Comme j'utilise l'attribut data pour transporter certaines données avec l'élément html de PHP Vers JavaScript, j'utilise simplement base64_encode sur le backend, puis côté client, utilisez base64Decode(input) pour récupérer les données. De cette façon, j'évite toute orgie qui s'échappe. Le code JavasScript que j'utilise se trouve ici http://www.webtoolkit.info/

1
Heinz

J'aime stocker les données en javascript directement. Au lieu de cela:

<p class="example" data-oweb="<?=str_replace('\'', '\\\'', $var)?>">Content</p>
<script>
  var example = $('.example').data("example");
  DoSomething(example);
</script>

Faire ceci:

<p class="example">Content</p>
<script>
  var example = '<?=str_replace('\'', '\\\'', $var)?>';
  DoSomething(example); 
</script>

Ou si l'utilisation est dans un script distant que vous contrôlez, stockez la ou les valeurs dans un fichier global:

<p class="example">Content</p>
<script>
  window.MyDataValues={};
  window.MyDataValues.Example = '<?=str_replace('\'', '\\\'', $var)?>';
</script>

Ou si vous ne pouvez pas contrôler le script distant et que les informations doivent être stockées en tant qu'attribut de données, vous pouvez les définir avec javascript après avoir trouvé un moyen de cibler le paragraphe:

<p id="example" data-oweb>Content</p>
<script>
    document.getElementById("example");
    element.dataset.oweb = '<?=str_replace('\'', '\\\'', $var)?>';
</script>
0
Nenotlep

Nouveau sur Stack Overflow, je n'ai donc pas assez de points de repère pour voter, mais je voulais clarifier la solution car j'avais mal interprété la réponse acceptée par @Guffa selon laquelle j'avais été foutu. 

J'avais une question similaire concernant les caractères d'échappement/spéciaux dans les attributs de données HTML5. La question/solution: Escape/Caractères spéciaux de l'entrée utilisateur aux attributs de données HTML5 à l'aide de l'URL Encode/Decode

Dan Smith a fourni la solution que j'ai utilisée avec encodeURI ()/decodeURI (). Cependant, je l'ai écarté au départ parce qu'il était si bas avec seulement 1 point de représentation.

Toutes les réponses avec échappement manuel des personnages deviennent compliquées et prennent du temps. 

Toutes les réponses avec la méthode escape () sont maintenant obsolètes. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/escape

0
CreatordotJS

C'est un peu délicat, mais vous pouvez sélectionner des objets dom avec leurs attributs data qui contiennent des guillemets simples. L'astuce est \\'

<div id="text" data-message="Stanley Kubrick's Oranges">Hello</div>

<script>
    var message = "Stanley Kubrick\\'s Oranges";
    $("#text[data-message='"+message+"']").fadeOut("slow");
</script>

Fiddle

0
kastelli