Create an Array from a single HTML5 "data-" attribute
Asked Answered
W

2

11

I have this HTML:

<section id="SSID" data-texts="'Text1', 'Text2', 'Text3'"></section>

I want to create an Array variable in jQuery and my jQuery code is:

$(document).ready(function() {
    var Selection = $("#SSID").data("texts");
    var Texts = [ Selection ];

    console.log(Texts.length);
});

For my example, the result I expect is:

Texts[0] = 'Text1'
Texts[1] = 'Text2'
Texts[2] = 'Text3'

...and that the length of the array Texts is 3.

However, what I am seeing is that the length of Texts is 1 and that the entire string is being loaded into Texts[0]:

Texts[0] = "'Text1', 'Text2', 'Text3'"

I think my problem is being caused by the " (quotation mark) characters. How can overcome this problem and achieve my objective?

Whitish answered 1/3, 2014 at 11:28 Comment(0)
L
8

You can use JSON.parse()

HTML :

<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>

JQUERY :

var Selection = JSON.parse('[' + $("#SSID").data("texts") + ']');

Fiddle Demo

or

HTML :

<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>

JQUERY :

var Selection = JSON.parse($("#SSID").data("texts"));

FYI : But it would be better to store the actual JSON as the data attribute value. For eg : data-texts='["Text1", "Text2", "Text3"]' and parse it directly.


UPDATE : Or you can do it using Array#map method and String#split method.

var Selection = $("#SSID").data("texts").split(',').map(JSON.parse);

console.log(Selection);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>
Liquefy answered 1/3, 2014 at 11:33 Comment(2)
Is there any way to use data-texts=" 'a', 'b', 'c' " format instead of data-texts=' "a", "b", "c" '?Whitish
@Whitish Note that this is the technically inferior solution. Use actual JSON, not some string with manually added square brackets.Starwort
S
20

data- attributes can contain JSON.

jQuery will automatically parse them for you, if they are syntactically valid.

<section id="SSID" data-texts='["Text1", "Text2", "Text3"]'></section>

and

$(function() {
    var texts = $("#SSID").data("texts");

    console.log(texts.length);  // logs "3"
});

See: http://jsfiddle.net/5mtre/


Security hint: You must encode the JSON correctly on the server.

This means that you need to do JSON encoding and HTML encoding, here shown examplary using PHP:

<section id="SSID" data-texts="<?=htmlspecialchars(json_encode($data), ENT_QUOTES, 'UTF-8')?>"></section>
Starwort answered 1/3, 2014 at 11:40 Comment(10)
You should also add flags and encoding, see this answer. Fixed my issue https://mcmap.net/q/447358/-escaping-encoding-single-quotes-in-json-encoded-html5-data-attributesAcarid
@Tim Just for reference, can you shed light on the circumstances under which omitting ENT_QUOTES, 'UTF-8' would lead to wrong results?Starwort
when you have a single qoute in your JSON data, for example: data-texts='["Text1", "'Text2", "Text3"]'. This wil break at 'Text2.Acarid
You can also just do json_encode($data, JSON_HEX_QUOT) to change quotes to &quot;.Aileneaileron
@Nicholas No, that is not enough. All this does is encode the JSON itself differently. {"key": "value with \"quotes\"..."} becomes {"key": "value with \u0022quotes\u0022..."}, which is technically the same thing. But the JSON string will still contain <, >, & and " unencoded and this will break the HTML. Preventing to HTML breakage is the whole point of htmlspecialchars(). General advice: Don't try to be smart about this kind of thing. Always use the proper functions. Rigorously encode for the medium you are using, layer by layer, in this case: Raw Data -> JSON -> HTML.Starwort
@Tomalak, Works for me, but you might have different requirements: jsbin.com/tuwazotono/edit?html,js,outputAileneaileron
@NicholasRuunu It works because modern HTML parsers are incredibly forgiving and clever in making sense of horribly broken input. Don't let that fool you into thinking that <div data-test="Something > something&Else < <tag>"> would not be horribly broken input. It is. Don't produce this kind of thing. And don't make any generalizations based on "works for me". It's either correct - or it is not. And this stuff is not.Starwort
@Tomalak, Ok, to me that's totally valid. The contents within quotes is a string and you should be able to put any string there and it should not be resolved into tags.Aileneaileron
"Ok, to me that's totally valid." - That is because you lack fundamental knowledge about how HTML works. Also, this whole thing is not a matter of personal opinions.Starwort
@Tomalak, Ok, you're just being rude. Data-attribute values are strings, see: developer.mozilla.org/en-US/docs/Web/Guide/HTML/… Could you point me to a point in the HTML spec where it says otherwise?Aileneaileron
L
8

You can use JSON.parse()

HTML :

<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>

JQUERY :

var Selection = JSON.parse('[' + $("#SSID").data("texts") + ']');

Fiddle Demo

or

HTML :

<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>

JQUERY :

var Selection = JSON.parse($("#SSID").data("texts"));

FYI : But it would be better to store the actual JSON as the data attribute value. For eg : data-texts='["Text1", "Text2", "Text3"]' and parse it directly.


UPDATE : Or you can do it using Array#map method and String#split method.

var Selection = $("#SSID").data("texts").split(',').map(JSON.parse);

console.log(Selection);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<section id="SSID" data-texts='"Text1", "Text2", "Text3"'></section>
Liquefy answered 1/3, 2014 at 11:33 Comment(2)
Is there any way to use data-texts=" 'a', 'b', 'c' " format instead of data-texts=' "a", "b", "c" '?Whitish
@Whitish Note that this is the technically inferior solution. Use actual JSON, not some string with manually added square brackets.Starwort

© 2022 - 2024 — McMap. All rights reserved.