1

I'm attempting to dynamically create a list of HTMLElements with data-* attributes that correspond to different HTML Entities, to be then picked up by CSS and used as pseudo element content like so:

li:after {
  content: attr(data-code);
}

The problem with this is that for attr() to properly render the actual entity, rather than the literal code is to prefix said code with &#x - your typical \ doesn't work.

So the desired output HTML is something like so: <li data-code="&#xENTITY"></li>. When added directly to HTML, this works exactly as expected in relation to my CSS rule. The escaped entity is placed on the page in an :after psuedo element and rendered as the entity icon.

Here's where things get curious...

As stated earlier, I'm trying to create and inject these lis dynamically through JavaScript (iterating through a list), and that's where the snag happens.

  var entities = [{code: '&#x1F602'}, ...];
  for (var i = 0; i < entitites.length; i++) {
    var entity = entitites[i],
        listItem = document.createElement('li');

    listItem.setAttribute('data-code', entity.code);
    list.appendChild(listItem);
  }

The li is correctly added to the DOM with the properly formatted entity set so it gets picked up by my CSS rule. However, rather than rendering the entity icon, the code is shown!

enter image description here

Note in the image above, the first item rendered is the HTML explicitly on the page. The second item is injected via JS (using the exact same code), then given an :after element by CSS. Chrome's web inspector even renders it differently!

enter image description here

Even curiouser still is that I can edit the HTML via WebInspector and inject the escaped data-* attribute manually - Chrome STILL renders the correct icon!

enter image description here

I'm at a loss here, so any guidance would be greatly appreciated!

Community
  • 1
  • 1
Jordan Foreman
  • 3,848
  • 7
  • 40
  • 65

1 Answers1

2

The HTML entity notation will only be parsed by an HTML parser. If your data-code attributes are "born" in JavaScript, then you need to use the JavaScript notation for getting the Unicode characters you want. Instead of &#x263A; for a smiley face, in JavaScript you use \u263A (a backslash, a lower-case "u", and four hex digits).

Whether your data-code attributes are coded directly into your HTML source (with HTML entity notation) or else created in JavaScript (with JavaScript notation), by the time the attribute value is part of the DOM, it's Unicode.

Now, things get more complicated when you have characters outside the 16-bit range, because JavaScript is kind-of terrible at dealing with that. You can look up your code point(s) at http://www.fileformat.info/info/unicode/ and that'll give you the "C/C++/Java" UTF-16 code pair you need. For example, your "tears of joy" face is the pair "\uD83D\uDE02".

Pointy
  • 405,095
  • 59
  • 585
  • 614