How to create a HTML document DOM object from code? - javascript

Currently I'm doing this:
var newdoc = document.implementation.createHTMLDocument("Wrong title");
newdoc.open();
newdoc.write('<!doctype html><html><head><title>Right title</title></head><body><div id="a_div">Right content</div></body></html>');
newdoc.close();
And then I try to get some info about the document loaded, for example:
> newdoc.title
Right title
> newdoc.getElementById("a_div").innerHTML
Right content
The issue is that it only works in Chrome. On Firefox and Opera the DOM does not seem to be loaded after document close. What am I doing wrong?
I wrote this little fiddle to demonstrate the problem: http://jsfiddle.net/uHz2m/

Okay, after reading the docs I noticed createHTMLDocument() does not create a zero byte-length document object but a basic HTML scaffolding like this:
<!DOCTYPE html>
<html>
<head>
<title>Wrong title</title>
</head>
<body></body>
</html>
That's why newdoc.write() does not work as expected.
Instead, I can just take the html element and change its HTML code (corrected fiddle).
var newdoc = document.implementation.createHTMLDocument("Wrong title");
newdoc.documentElement.innerHTML = '\
<!doctype html>\
<html>\
<head>\
<title>Right title</title>\
</head>\
<body>\
<div id="a_div">Right content</div>\
</body>\
</html>';

Related

Chrome Extension - Get the true raw HTML document before JavaScript rendering

I'm using a content script (loaded with run_at: document_start to try and grab the exact source of the page before any DOM modifications take place from JavaScript.
I want the pure HTML - exactly what you'd get from Right Click > View Source in the browser.
I've tried two methods which both nearly work but not quite.
Here's the actual raw source of the page, from Right Click > View Source
<!doctype html>
<html lang="en">
<head>
<title>Raw HTML title</title>
</head>
<body>
<p>Something here.</p>
<script>
document.title = 'Title injected by JS';
</script>
</body>
</html>
Things I've tried:
new XMLSerializer().serializeToString(document)
This produces the following:
<!DOCTYPE html><html xmlns="http://www.w3.org/1999/xhtml" lang="en"><head>
<title>Raw HTML title</title>
</head>
<body>
<p>Something here.</p>
<script>
document.title = 'Title injected by JS';
</script></body></html>
It's close, but for some reason the formatting isn't correct, 'doctype' is capitalised and the xmlns attribute added to the <html> tag.
document.documentElement.outerHTML
Produces the following:
<html lang="en"><head>
<title>Raw HTML title</title>
</head>
<body>
<p>Something here.</p>
<script>
document.title = 'Title injected by JS';
</script></body></html>
</body></html>
It's missing the doctype and the formatting is also not as per the original.
Doesn't seem you can get the 'pure' HTML as seen in view source. The closest you can get is what's given back by
new XMLSerializer().serializeToString(document)
If you trigger the above in a content script run at run_at: document_start (before anything exists in DOM at all) and monitor for DOM mutations you can grab the first mutation with something like this:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
var rawHTML = new XMLSerializer().serializeToString(document);
console.log(rawHTML);
});
});
var config = { attributes: true, childList: true, characterData: true }
observer.observe(target, config);
XMLSerializer() has solid browser support: https://caniuse.com/#feat=xml-serializer

document.getElementById can't find qUnit DOM elements

I'm trying to get a reference to a DOM object created by qUnit, with no luck. It works just fine with a "home made" DOM element. I have made a test site to illustrate the problem. Turn on Firebug or other logging window when visiting the site.
This is the code of the website:
window.onload = function() {
var qunitTestrunnerToolbar_element = document.getElementById("qunit-testrunner-toolbar");
console.log("qunitTestrunnerToolbar_element: ", qunitTestrunnerToolbar_element);
var test_element = document.getElementById("test_element");
console.log("test_element: ", test_element);
};
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Testing 'require' error</title>
</head>
<body>
<p>See console for output</p>
<script src="index.js"></script>
<script src="http://code.jquery.com/jquery-2.2.0.js"></script>
<p id="test_element">Test element</p>
</body>
</html>
It won't work like this
I am not talking about qunit but document.getElementById("qunit-testrunner-toolbar"); will return null because there are no element present in this html.
If you are particularly asking how to get actual id and not null
You may, add your original script file in this html and then var qunitTestrunnerToolbar_element = document.getElementById("qunit-testrunner-toolbar"); will console it in indexjs or if you can include <iframe> in your test html you can do
<iframe src="urlWithinYourDomain.html" style="display:none" id="iframeId"></iframe>
and in indexjs
var qunitTestrunnerToolbar_element = document.getElementById('iframeId').contentWindow.document.getElementById('qunit-testrunner-toolbar'); if you like html way.

Script only runs in some browsers when head tags are removed

I'm using a tumblr theme which is structured like this:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<style>
</style>
<body>
</body>
</html>
There are no head tags which I thought was strange but it works fine; because when you run the site it places head tags automatically. However, since I'm using plugins I added the head tags myself to give me better control as some required me to place it in <head>. This worked fine in chrome and safari but it disabled one of my scripts in firefox and IE:
$(document).ready(function () {
var speed = 25,
timer;
$("#hoverscroll").hover(function () {
$(this).css({cursor: 'none'});
$(this).css({opacity: '0'});
var div = $('body');
(function startscrolling(){
timer = setTimeout(function () {
var pos = div.scrollTop();
div.scrollTop(pos + 1);
startscrolling();
}, speed);
})();
},
function () {
$("#hoverscroll").css({opacity: '1'});
clearTimeout(timer);
speed = 25;
})
.click(function(){
speed = 1;
});
});
It's a simple script where it scrolls the page when an element is hovered.
I reproduced the problem in these 2 demo-sites:
http://testmycode.tumblr.com/ This site has head tag, scrolls in chrome, does not scroll in Firefox.
http://testmycode2.tumblr.com/ This site has no head tag, works perfectly and scrolls in all browsers.
you can add code to your head tag using JQuery like below
$("head").append("<script src=\"mypluginscript.js\"></script>");
this will let you add any new code to it without having to write the head tag
an example!
'However, since I'm using plugins I added the head tags myself to give
me better control'
What you mean by that?
Most of the times there is an alternative solution.
A proper html needs a html tag a head tag and a body tag
inside the head tag you put meta,script and style tags
minimal structure is
<html>
<head>
</head>
<body>
</body>
</html>
Else it's not a html file.
Almost TEN years html5 was launched....
and as it is similar to the basic structure it works on all browsers.
<!doctype html> // html5
<html lang="en"> // language set to english
<head>
<meta charset="utf-8"> // can decode almost al charachters éçàò..
<style></style>
<script></script>
<title>Title</title>
</head>
<body>
</body>
</html>
now reguarding your code.
<script>
goes inside head (or at the end of the body [or just after each element])
if you put the code in the head..
to handle elements inside the body
you need to add a window.onload // DOMContentLoaded
else you have no access to the dom elements.
Now looking at your code from Chrome the errors starts on the html tag..
Why the html has a webkit animation?
Then your talking about the doctype tag and not the head tag.
So if you tell us why you need that we can probably find a solution.

Javascript: Can't get element using getElementById [duplicate]

This question already has answers here:
Why does jQuery or a DOM method such as getElementById not find the element?
(6 answers)
Closed 6 years ago.
Ok. I need fresh eyes because I'm still on this s***d problem for one hour!
Here is my simple HTML code (testssio.html) that include javascript script:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
var ssio = document.getElementById('ssio');
ssio.html = "it finally works!";
</script>
</head>
<body>
<div id="ssio"></div>
</body>
</html>
But it doesn't work! Using the debugger, I get:
Uncaught TypeError: Cannot set property 'html' of null /testssio/:6
Does anyone get it? I know it's not the correct place to look for debugging help, but I'll be crazy if I don't get it! So please, any help?
Tahnks in advance.
The reason for this is that scripts in the head load before the page is rendered. This means your content is not yet rendered and therefore not a part of document.
If you want to see this work, try moving your script below the element renders, like this:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="ssio"></div>
<script type="text/javascript">
var ssio = document.getElementById('ssio');
ssio.innerHTML = "it finally works!";
</script>
</body>
</html>
A more standardized way of doing this is with events. Many people use jQuery but it can be done with plain js. This would mean changing your script like this:
<script type="text/javascript">
function WinLoad() {
var ssio = document.getElementById('ssio');
ssio.innerHTML = "It finally works!";
}
window.onload = WinLoad;
</script>
This way you can still leave it in the <head>.
Also, using .html is from jQuery. It is generally used as .html(content). If you want to use the plain javascript version use .innerHTML = content.
I mention jQuery so much because it is a highly used API. This quote is from their site:
jQuery is a fast and concise JavaScript Library that simplifies HTML document traversing, event handling, animating, and Ajax interactions for rapid web development. jQuery is designed to change the way that you write JavaScript.
Your code is running too early before the DOM is loaded and thus document.getElementById() doesn't find the element in the document yet.
You can either move your script tag down to right before the </body> tag or you can wait for the DOM to load before running your code with either the window onload event or a DOMReady event.
There are two errors here. First, you need to put the SCRIPT tag after the element. Second, it's not .html, but .innerHTML. So here is the corrected code:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="ssio"></div>
<script type="text/javascript">
var ssio = document.getElementById('ssio');
ssio.innerHTML = "it finally works!";
</script>
</body>
</html>
you can use something like this
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
document.onload= function(){
var ssio = document.getElementById('ssio');
ssio.html = "it finally works!";
}
</script>
</head>
<body>
<div id="ssio"></div>

Open a new browser window/iframe and create new document from HTML in TEXTAREA?

I'm trying to write a web application using the new offline capabilities of HTML5. In this application, I'd like to be able to edit some HTML—a full document, not a fragment—in a <textarea>, press a button and then populate a new browser window (or <iframe>, haven't decided yet) with the HTML found in the <textarea>. The new content is not persisted anywhere except the local client, so setting the source on the window.open call or the src attribute on an <iframe> is not going to work.
I found the following question on StackOverflow: "Putting HTML from the current page into a new window", which got me part of the way there. It seems this technique works well with fragments, but I was unsuccessful in getting an entirely new HTML document loaded. The strange thing is when I view the DOM in Firebug, I see the new HTML—it just doesn't render.
Is it possible to render a generated HTML document in a new window or <iframe>?
EDIT: Here's a "working" example of how I'm attempting to accomplish this:
<!doctype html>
<html>
<head>
<title>Test new DOM</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
function runonload() {
return $("#newcode")[0].value;
}
$(function() {
$("#runit").click(function() {
w=window.open("");
$(w.document).ready(function() {
$(w.document).html(w.opener.runonload());
});
});
});
</script>
</head>
<body>
<textarea id="newcode">
<!doctype html>
<html>
<head>
<title>New Page Test</title>
</head>
<body>
<h1>Testing 1 2 3</h1>
</body>
</html>
</textarea>
<br/>
<button id="runit">Run it!</button>
</body>
</html>
I think you are overcomplicating this...
try this:
<SCRIPT LANGUAGE="JavaScript">
function displayHTML(form) {
var inf = form.htmlArea.value;
win = window.open(", ", 'popup', 'toolbar = no, status = no'); win.document.write("" + inf + ""); } // </script>
<form>
<textarea name="htmlArea" cols=60 rows=12> </textarea> <br> <input type="button" value=" Preview HTML (New Window)" onclick="displayHTML(this.form)"> </form>
$(w.document).html(w.opener.runonload());
You can't set innerHTML—or, consequently, jQuery's html()—on a Document object itself.
Even if you could, you wouldn't be able to do it using html(), because that parses the given markup in the context of an element (usually <div>) from the current document. The doctype declaration won't fit/work, putting <html>/<body>/etc inside a <div> is invalid, and trying to insert the elements it creates from the current ownerDocument into a different document should give a WRONG_DOCUMENT_ERR DOMException. (Some browsers let you get away with that bit though.)
This is a case where the old-school way is still the best:
w= window.open('', '_blank');
w.document.write($('#newcode').val());
w.document.close();
Whilst you can inject innerHTML into a pop-up's document.documentElement, if you do it that way you don't get the chance to set a <!DOCTYPE>, which means the page is stuck in nasty old Quirks Mode.

Categories

Resources