I'm using an iframe as an html editor and I load its content by setting iframe's src attribute. Afterwards, I turn on iframe's designMode so I can edit the loaded html content.
Once user is done, he'll press a save button and I'll try to retrieve the edited html content and sending it to the server. It's just that I need the full content of the iframe, including the <html> and <!doctype>. The problem I've faced is that when I retrieve the iframe's content, its embedded javascript code has encoded all < into <, even within Javascript code!
Here's 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><>&');
$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 output:
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
</head>
<body>
<script>var x = 1 < 2;</script><>&
</body>
</html>
As you can see the result is unusable because there's no way I can tell apart which < should be replaced with < (unless the text is parsed)!!
Does anyone have any idea how to retrieve the contents of an iframe completely without ruining it?
First of all - you don't need XMLSerializer. You try to serialize html like xml. I think you need a html. So it will be better to use $iframe.contents().get(0).documentElement.outerHTML. This will return whole html of 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><>&');
$iframe.contents().prop('designMode', 'on');
$("button").click(function() {
var iframeDocument = $iframe.contents().get(0);
$textarea.val(getDoctypeString(iframeDocument) + iframeDocument.documentElement.outerHTML);
});
});
</script>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With