-1

In a page I am getting from a server, part of the html code has this

<div class="item" />

Apparently browsers don't like the self closed div, and renders as if the slash is not there, which means there is a unclosed div tag. This results on the whole page looking terrible.

Also we can assume that I can't modify the code in the server side that returns that. So basically I am looking for a javascript hack that can fix it.

I tried a string replace on the innerHTML, but it seems to not reform and fix the page after. After it loads the first time, it seems like its permanent.

Does anyone know anyway to fix this?

Thanks

omega
  • 40,311
  • 81
  • 251
  • 474
  • That explains the problem but no solution... – omega Oct 25 '16 at 21:56
  • right, to handle some elements properly with javascript, they really have to be valid `element`s that answer said that in HTML5 autoclose depends on the element types, So, while parsing the page, they are not treated as elements, that's why it is (maybe) not possible to close them automatically by javascript or handle the errors. – Towkir Oct 25 '16 at 22:00
  • I'm not sure i understand, can you show code – omega Oct 25 '16 at 22:01
  • check the first answer of that question from comment 1. At third bullet point it says: "On HTML elements that are designated as void elements, it is allowed, but has no meaning. It is just syntactic sugar for people (and syntax highlighters) that are addicted to XML." reference: https://www.w3.org/TR/html5/syntax.html#start-tags – Towkir Oct 25 '16 at 22:04
  • Yes but how does this relate to a solution? – omega Oct 25 '16 at 22:05
  • Maybe it said it is not possible, that is what I tried to point out :) – Towkir Oct 25 '16 at 22:06
  • you wont be able to "hack" the html in the browser, the browser has rendered it into the DOM ... you need to take that div, and move all of it's children to be siblings of the div – Jaromanda X Oct 25 '16 at 22:07
  • 3
    Honestly, you need to fix your server code so that it sends valid html. Trying to fix it on the client is going to be full of holes as not every browser is going to treat the invalid html the same – Wesley Smith Oct 25 '16 at 22:13
  • Just serve as XHTML... – Oriol Oct 25 '16 at 22:20
  • Cant modify the server – omega Oct 25 '16 at 22:20

3 Answers3

0

This will "fix" all divs with class item

[].forEach.call(document.querySelectorAll('.item'), function(root) {
    var frag = document.createDocumentFragment();
    while(root.firstChild) {
        frag.appendChild(root.firstChild);
    }
    root.parentNode.insertBefore(frag, root.nextSibling);
});
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
-1

You can't fix it properly with JS. JS accesses the DOM resulting from parsing the source code. And then it's too late, the HTML parser has alredy messed up your well-formed XHTML.

What you should do is serve your XHTML as XHTML, not as HTML.

If you can't do that, and really want a JS solution, I guess you could use AJAX to retrieve the source code of the same page, parse it with a DOMParser, and replace the malformed tree with that one.

var ajax = new XMLHttpRequest();
ajax.addEventListener("load", function() {
  var code = this.responseText;
  var doc = new DOMParser().parseFromString(code, "application/xhtml+xml");
  document.replaceChild(doc.documentElement, document.documentElement);
});
ajax.open("GET", location.href);
ajax.send();

But that would download the same code twice, what a waste. And it's not foolproof, HTML parsers are allowed to abort at the first parse error that they encounter.

Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Pretty sure that would not be valid XHTML, as `div` is not defined as empty element according to the doctype... – Heretic Monkey Oct 25 '16 at 22:38
  • 1
    @MikeMcCaughan HTML5 accepts a XHTML syntax, which conforms to XML. And [XML says](https://www.w3.org/TR/xml/#d0e2480) "*Empty-element tags may be used for any element which has no content, whether or not it is declared using the keyword EMPTY*" – Oriol Oct 25 '16 at 22:46
-2

If you have access to the source code, say:

function fixClosedDivs(src) {
    return src.replace(new RegExp('<div([^<]*)\/>', 'gi'), '<div$1></div>');
}
var htm = '<div class="item"/>Hi<br/>Bye<div class="item"/>Hi<div/>Bye';
console.log(fixClosedDivs(htm));
// <div class="item"></div>Hi<br/>Bye<div class="item"></div>Hi<div></div>Bye
Javier Rey
  • 1,539
  • 17
  • 27