9

I am simply trying to parse and append a JavaScript string as a DOM element. I have found two quick ways to do this, one of which is using DOMParser as seen in this popular SO answer. Both methods work, however, the DOMParser approach for some reason is not respecting the inline styles I define - even though both methods inject the exact same dynamic markup. Consider the following...

<div></div>

var parent = document.getElementsByTagName('div')[0]

// ---- case 1 ---------------

var parser = new DOMParser();
var node = parser.parseFromString('<p style="color: red">foo</p>', 'text/xml').firstChild;
parent.appendChild(node);

// ---- case 2 ---------------

var wrapper= document.createElement('div');
wrapper.innerHTML= '<p style="color: red">foo</p>';
var node2 = wrapper.firstChild;
parent.appendChild(node2);

Each method injects the node accordingly and the DOM reflects the following...

<div>
    <p style="color: red">foo</p>
    <p style="color: red">foo</p>
</div>

However, only the last is red! Any idea what can possibly be going on here?


JSFiddle - reproduction demo

Community
  • 1
  • 1
scniro
  • 16,844
  • 8
  • 62
  • 106

3 Answers3

6

That's because you didn't set a namespace. style attributes don't have any special meaning in XML:

var str = '<p xmlns="http://www.w3.org/1999/xhtml" style="color: red">foo</p>';
var node = new DOMParser().parseFromString(str, 'text/xml').firstChild;
document.body.appendChild(node);
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • aw snap! Nice one. That does indeed explain why thank you very much :) The other solution by @Deep does work as well, however involved a whole html document and a bit more traversing – scniro Jul 12 '16 at 18:05
  • Just so I understand, without the `xmln=`, does the browser not know that the parsed text is HTML at all? In the OP Fiddle, Firefox doesn't realize the `p` is a `p` (No browser styles are applied, like margin). – Kelderic Jul 12 '16 at 19:42
  • @AndyM Yes, since the parser parses as `text/xml`, elements do not have the semantics of HTML. In the DOM, the `p` will only be an `Element` instance, not a `HTMLElement` one, so it won't have properties like `style`. – Oriol Jul 12 '16 at 22:10
1

CSS will be applied if you use the method like below.

var node = parser.parseFromString('<p style="color: red">foo</p>', 'text/html').firstChild.lastChild.firstChild;

here i am using 'text/html' As per the docs https://developer.mozilla.org/en/docs/Web/API/DOMParser using text/html returns a HTMLDocument.

fiddle: https://jsfiddle.net/wLnesqrb/8/

Deep
  • 9,594
  • 2
  • 21
  • 33
  • hmm, that method seems to be injecting a whole html document if you inspect the nodes. Either way that can be worked around, and yes I can see the style. Any idea why the dynamic node using `text/xml` isn't styled even though it should be according to inspecting the DOM? – scniro Jul 12 '16 at 18:02
  • This wraps the paragraph inside a `html` and `body` elements. `firstChild` will be that `html` element. – Oriol Jul 12 '16 at 18:06
  • +1, after checking out the answer from @Oriol, I have a total understanding of _why_ this is happening regarding the styles but this did help, thank you! – scniro Jul 12 '16 at 18:06
  • @scniro you are welcome, however you already got the answer but i edited mine just to resolve your traversing issue to reach the

    element.

    – Deep Jul 13 '16 at 02:00
0
var str = '<p style="color: red">foo</p>';
var frag = new DocumentFragment();
frag.innerHTML = str;
document.body.appendChild(frag);

But adding namespaces is safer if you want your code to work in XML documents too and not just HTML.

the8472
  • 40,999
  • 5
  • 70
  • 122