I've been trying to GET a HTML file and assign it to a variable as a jQuery object. To no avail. I'm not sure if Stack Snippets allow GET requests, so here is a JSFiddle link as well.
var html = '<!DOCTYPE html><html lang="en"><head><title>Template</title></head><body itemscope itemtype="http://schema.org/WebPage"><main><header itemscope itemtype="http://schema.org/Country" itemprop="about"><h1 itemprop="name">Dummy heading</h1><p><span class="capital" title="Capital" itemprop="containsPlace"></span><span title="Dummy title" itemprop="additionalProperty" itemscope itemtype="http://schema.org/PropertyValue"><meta itemprop="name" content="Member of the EU since"><span itemprop="value" class="member-since">Dummy year</span></span></p></header><div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList"><meta itemprop="description" content=""><article class="recipe loading" itemprop="itemListElement" itemscope itemtype="http://schema.org/Recipe"><meta itemprop="position" content=""><aside class="media"><div class="img-gallery" itemscope itemtype="http://schema.org/ImageGallery"></div><div itemscope itemtype="http://schema.org/VideoObject" class="youtube"><a itemprop="contentUrl" href="#" title=""><meta itemprop="name" content=""><meta itemprop="uploadDate" content=""><meta itemprop="description" content=""><img itemprop="thumbnailUrl" src="#" alt=""></a><div class="youtube-player"></div></div></aside><div class="text"><div class="wiki-text"><h1 itemprop="name">Dummy heading</h1><p itemprop="description"></p><p class="read-more">For more information about <span class="recipe-name"></span>, read the <a href="#" title="" itemprop="sameAs">Wiki</a>.</p></div><div class="rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">Rated <span itemprop="ratingValue">3.5</span>/5 based on <span itemprop="reviewCount">11</span> customer reviews</div><div class="cooking"><h2>Bake it yourself!</h2><div><meta itemprop="cookTime" content=""><span>Bake time: <span class="bake-time"></span></span></div><div class="ingredients-wrapper"><h3>Ingredients <small>for <span itemprop="recipeYield"></span></small></h3><div class="ingredients"><h4>Dummy heading</h4><ul></ul></div></div><div class="how-to"><h3>Steps</h3><ol></ol></div></div></div></article></div></main></body></html>';
$.ajax({
type: 'post',
url: "/echo/html/",
dataType: "html",
data: {
html: html,
delay: 1
}
}).done(function(data) {
// string
console.log(data);
// array
console.log($(data));
// array
console.log($.parseHTML(data));
// array
console.log($($.parseHTML(data)));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The HTML is valid. Yet, I can't get it in an object. The returned data is, as expected, a string. But when I try to parse that string as HTML using $.parseHTML() or putting it in a jQuery selector $() or even try both I always get the same result: an array containing the title and main element.
So some way some how jQuery still parses it and makes an array of the element in the head and the one element in the body. But why? And how can I remedy this, and transform it into a jQuery object? I am only interested in the contents of the body.
There is a similar question, but the accepted solution doesn't help as it goes into JSFiddle and I'm also experiencing this problem locally with XAMPP.
document.querySelector("body").innerHTML = +
'<object type="text/html" data="'+html+'" ></object>';
...just works. So I'd have expected:
let parsedHtml = $('<object />', {
type:'text/html',
data:html
}).html()
to also just work, But I'm guessing some magic happens when one actually adds it to DOM. It parses it, builds CSSOM and DOM for it and loads all dependencies, basically what you'd expect a browser to do with an .html resource.
So here's a way to do it:
<object> inside, .contents() of <object> (on it's onload event), let html = '// your valid html...',
dummyDiv = $('<div />',{
html: '<object type="text/html" data="'+html+'" ></object>',
style:"height:0;overflow:hidden;"
});
$('html').append(dummyDiv);
console.log(dummyDiv.find('object').contents());
Note Chrome is already smart enough to detect a display:none on a parent and not load the <object>. That's why I used height:0;overflow:hidden;. You will notice the contents of this element doesn't have a typical stucture of a jQuery object, because it's a document. you'll find the juice in
dummyDiv.find('object').contents()[1].innerHTML
When the html string is already in a variable, it loads instantly, but in reality you'll need to place an onload listener on the <object> and only run 4. and 5. when the listener triggers.
Set jQuery.ajax() processData option to false. Use DOMParser() to parse string to an html document; XMLSerizlizer() to get DOCTYPE declaration; document.write() to write DOCTYPE and parsed document .documentElement.outerHTML to current or other html document.
processData (default:
true)Type: Boolean
By default, data passed in to the
dataoption as an object (technically, anything other than a string) will be processed and transformed into a query string, fitting to the default content-type "application/x-www-form-urlencoded". If you want to send a DOMDocument, or other non-processed data, set this option tofalse.
I'm not sure if Stack Snippets allow GET requests
Yes. It is possible to echo GET request by setting url to data URI or Blob URL representation of resource at $.ajax(), XMLHttpRequest() or fetch(), see Does Stack Overflow have an “echo page” to test AJAX requests, inside a code snippet?
var html = `<!DOCTYPE html>
<html lang="en">
<head>
<title>Template</title>
</head>
<body itemscope itemtype="http://schema.org/WebPage">
<main>
<header itemscope itemtype="http://schema.org/Country" itemprop="about">
<h1 itemprop="name">Dummy heading</h1>
<p><span class="capital" title="Capital" itemprop="containsPlace"></span><span title="Dummy title" itemprop="additionalProperty" itemscope itemtype="http://schema.org/PropertyValue"><meta itemprop="name" content="Member of the EU since"><span itemprop="value" class="member-since">Dummy year</span></span>
</p>
</header>
<div itemprop="mainEntity" itemscope itemtype="http://schema.org/ItemList">
<meta itemprop="description" content="">
<article class="recipe loading" itemprop="itemListElement" itemscope itemtype="http://schema.org/Recipe">
<meta itemprop="position" content="">
<aside class="media">
<div class="img-gallery" itemscope itemtype="http://schema.org/ImageGallery"></div>
<div itemscope itemtype="http://schema.org/VideoObject" class="youtube">
<a itemprop="contentUrl" href="#" title="">
<meta itemprop="name" content="">
<meta itemprop="uploadDate" content="">
<meta itemprop="description" content=""><img itemprop="thumbnailUrl" src="#" alt=""></a>
<div class="youtube-player"></div>
</div>
</aside>
<div class="text">
<div class="wiki-text">
<h1 itemprop="name">Dummy heading</h1>
<p itemprop="description"></p>
<p class="read-more">For more information about <span class="recipe-name"></span>, read the <a href="#" title="" itemprop="sameAs">Wiki</a>.</p>
</div>
<div class="rating" itemprop="aggregateRating" itemscope itemtype="http://schema.org/AggregateRating">Rated <span itemprop="ratingValue">3.5</span>/5 based on <span itemprop="reviewCount">11</span> customer reviews</div>
<div class="cooking">
<h2>Bake it yourself!</h2>
<div>
<meta itemprop="cookTime" content=""><span>Bake time: <span class="bake-time"></span></span>
</div>
<div class="ingredients-wrapper">
<h3>Ingredients <small>for <span itemprop="recipeYield"></span></small></h3>
<div class="ingredients">
<h4>Dummy heading</h4>
<ul></ul>
</div>
</div>
<div class="how-to">
<h3>Steps</h3>
<ol></ol>
</div>
</div>
</div>
</article>
</div>
</main>
</body>
</html>`;
$.ajax({
type: "GET",
url: "data:text/html," + html,
processData: false
})
.then(function(data) {
// string
console.log(data);
var parser = new DOMParser();
// document
var d = parser.parseFromString(data, "text/html");
// `document`, `document` as jQuery object
console.log(d, $(d));
// get elements having `itemscope` attribute
console.log($(d).find("[itemscope]"));
// do stuff
var dt = new XMLSerializer().serializeToString(d.doctype);
document.write(dt, d.documentElement.outerHTML);
})
.fail(function(jqxhr, textStatus, errorThrown) {
console.log(errorThrown);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
It is also possible to import an html document to current document using <link> element with rel attribute set to "import", see How to append a whole html file with jquery.
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