Serialize iframe content from head to toe with HTML special characters in Javascript

I am using an iframe as my html editor and I load its content by setting the iframe src attribute. Afterwards I include the iframe designMode

so I can edit the loaded html content.

Once the user is ready, he will click the save button and I will try to get the edited html content and send it to the server. I just need the full content of the iframe including <html>

and <!doctype>

. The problem I am facing is that when I fetch the content of the iframe its inline javascript code has encoded everything <

in &lt;

even in the Javascript code!

This is how I wrote my code:

<!DOCTYPE html>
<body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<iframe src="about: blank"></iframe>
<button>Save to textarea</button>
<textarea></textarea>
<script>
$(document).ready(function() {
  var $iframe = $("iframe");
  var $iframeBody = $iframe.contents().find('body');
  $iframeBody.html('<scr'+'ipt>var x = 1 < 2;</scr'+'ipt>&lt;&gt;&amp;');
  $iframe.contents().prop('designMode','on');
  $("button").click(function() {
    var serializer = new XMLSerializer();
    var html = serializer.serializeToString($iframe.contents()[0])
    $("textarea").val(html);
  });
});
</script>
</body>
</html>

      

Pressing the save button will display:

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script>var x = 1 &lt; 2;</script>&lt;&gt;&amp;
</body>
</html>

      

As you can see, the result is unusable because I cannot tell what &lt;

should be replaced with <

(unless the text is parsing) !!

Does anyone know how to completely restore the content of an iframe without destroying it?

+3


source to share


3 answers


First of all - you don't need to XMLSerializer

. You are trying to serialize html

as xml

. I think you need one html

. Therefore it is better to use $iframe.contents().get(0).documentElement.outerHTML

. This will return the whole html

iframe without doctype

. For doctype, you can use this function:

function getDoctypeString (doc) {
    var doctypeNode = doc.doctype;
    if (!doctypeNode) {
        return '';
    }
    return "<!DOCTYPE "
         + doctypeNode.name
         + (doctypeNode.publicId ? ' PUBLIC "' + doctypeNode.publicId + '"' : '')
         + (!doctypeNode.publicId && doctypeNode.systemId ? ' SYSTEM' : '') 
         + (doctypeNode.systemId ? ' "' + doctypeNode.systemId + '"' : '')
         + '>';
}

      



And all together :

<!DOCTYPE html>

<body>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
  <iframe src="about: blank"></iframe><br>
  <button>Save to textarea</button><br>
  <textarea cols=55 rows=10></textarea>
  <script>
    $(function() {
      function getDoctypeString(doc) {
        var doctypeNode = doc.doctype;
        if (!doctypeNode) {
          return '';
        }
        return "<!DOCTYPE " + doctypeNode.name + (doctypeNode.publicId ? ' PUBLIC "' + doctypeNode.publicId + '"' : '') + (!doctypeNode.publicId && doctypeNode.systemId ? ' SYSTEM' : '') + (doctypeNode.systemId ? ' "' + doctypeNode.systemId + '"' : '') + '>';
      }
      var $iframe = $("iframe");
      var $iframeBody = $iframe.contents().find('body');
      var $textarea = $("textarea");
      $iframeBody.html('<scr' + 'ipt>var x = 1 < 2;</scr' + 'ipt>&lt;&gt;&amp;');
      $iframe.contents().prop('designMode', 'on');
      $("button").click(function() {
        var iframeDocument = $iframe.contents().get(0);
        $textarea.val(getDoctypeString(iframeDocument) + iframeDocument.documentElement.outerHTML);
      });
    });
  </script>
</body>

</html>

      

+3


source


You can get html iframe without character replacement using:

document.getElementById('iframe').contentDocument.documentElement.outerHTML;

      

This is where JSBIN works .

The reason why you cannot find the doctype of the iframe may be because the iframe does not have a doctype.



Adding a doctype to an iframe is optional according to the W3C .

I took a look at the iframe in Firefox v33 and Chrome v39 and it didn't have a doctype. Only the owner document had a doctype. Try it in your browser with this JSBIN .

Also, doctypes are used for legacy reasons and if you are worried about older browsers you can simply add the doctype tag to your html line:

var html = document.getElementById('iframe').contentDocument.documentElement.outerHTML;
html = '<!DOCTYPE html>' + html;
$("textarea").val(html);

      

0


source


You can decode HTML by following these steps:

var text = '&lt;p&gt;name&lt;/p&gt;&lt;p&gt;&lt;span style="font-size:xx-small;"&gt;ajde&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;em&gt;da&lt;/em&gt;&lt;/p&gt;';
var decoded = $('<div/>').html(text).text();
alert(decoded);

      

0


source







All Articles