65.9K
CodeProject is changing. Read more.
Home

Open xml document in Iframe in Chrome

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0 vote)

Jul 19, 2012

CPOL
viewsIcon

31428

Code to open XML document in iFrame in Chrome.

Introduction

There is a bug in Chrome browser that it does not open XML document in an iFrame as it does in a new page. When it opens XML in new page it actually creates a custom HTML based on XML. If we copy the whole content from a new window to our iFrame then the problem is solved. 

The code 

<html>
<body>
<script type="text/javascript">
function drawArrows(doc) {
    var ctx = doc.getCSSCanvasContext("2d", "arrowRight", 10, 11);
    ctx.fillStyle = "rgb(90,90,90)";
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(0, 8);
    ctx.lineTo(7, 4);
    ctx.lineTo(0, 0);
    ctx.fill();
    ctx.closePath();

    var ctx = doc.getCSSCanvasContext("2d", "arrowDown", 11, 10);

    ctx.fillStyle = "rgb(90,90,90)";
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.lineTo(8, 0);
    ctx.lineTo(4, 7);
    ctx.lineTo(0, 0);
    ctx.fill();
    ctx.closePath();
}

function loadXml(src) {
    var win = window.open (src,"",
      "toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=no,
        resizable=no,copyhistory=no,width=1,height=1,top=5000,left=5000");

    window.setTimeout(populateXml(win, 0), 100);
}

function populateXml(win, counter) {
    return function() {
        var doc = document.getElementById("xml").contentDocument;
        var head = doc.getElementsByTagName("head")[0];
        var fromStyle = win.document.getElementsByTagName("style")[0];
        if(!fromStyle) {
            if(counter < 50) {
                window.setTimeout(populateXml(win, counter + 1), 100);
            } else {
                doc.location = win.location;
                win.close();
            }
            return;
        }
        var style = doc.createElement("style");
        style.type = "text/css";
        style.id = fromStyle.id;
        style.appendChild(doc.createTextNode(fromStyle.textContent));
        head.appendChild(style);
        $(doc.body).html($(win.document.body).children());

        style = doc.createElement("style");
        style.type = "text/css";
        style.appendChild(doc.createTextNode(
          ".webkit-html-tag {color: #881280;}.webkit-html-attribute-name {color: 
           #994500;}.webkit-html-attribute-value {color: #1A1AA6;}"));
        head.appendChild(style);

        var arr = doc.getElementsByClassName("button collapse-button");
        for(var i = 0; i < arr.length; i++) {
            var o = arr[i];
            var p = $(o).parents("div.collapsible:first").get(0);

            if(p) {
                o.onclick = (function(document, sectionId) {
                    return eval("(" + o.onclick.toString() + ")");
                })(doc, p.id);
            }
        }

        arr = doc.getElementsByClassName("button expand-button");
        for(var i = 0; i < arr.length; i++) {
            var o = arr[i];
            var p = $(o).parents("div.collapsible:first").get(0);

            if(p) {
                o.onclick = (function(document, sectionId) {
                    return eval("(" + o.onclick.toString() + ")");
                })(doc, p.id);
            }
        }
        win.close();
        drawArrows(doc);
    };
}
</script>
<iframe src="about:blank" id="xml" 
      width="500px" height="500px"></iframe>
<br>
<input type="button" value="Load Xml" onclick="loadXml('index.xml')">
</body>
</html>

You can use any index.xml for testing. You need to host the HTML and index.xml to see it work (does not work on file: protocol) 

Limitations

  1. Only works if XML is in the same domain otherwise you cannot read contents of the new window.
  2. A new window popping up may be irritating.
  3. Works by reverse engineering Chrome's implementation which may change in future.