I'm trying to fetch an HTML document object, not the text of the page, given its URL, via Javascript. The reason I need the Document object is so I can look for a given classname and take a certain action if it exists.
If the page is in the same domain (i.e. a relative path) you could load it inside a hidden iframe, and access the document from window.frames as shown here
function saveDataToVariable(data) {
var html = data;
// do something
}
$.get('any.html', saveDataToVariable);
this will give you the complete html output of a given html page... also including the html or div tags an anything else will be included and you can parse it afterwards as you need
Related
First question, so please correct me if this is in the wrong format.
I need to retrieve html for two dynamic elements from a dynamically created iframe, the below code returns "undefined". But I'm probably missing something really obvious.
$("#frame0").contents().find(elementID).html();
I am loading a same domain page into an iframe, two elements in the iframe are created from its jquery, the rest is static content in the iframe. The iframe is created and appended on a button click. The iframe in page looks and loads perfectly.
Below is the relevant code from within my button click:
$("#frameWrapper").append($('<iframe id="frame0" src="' + url + '"/>'));
$("#frame0").bind("load",function(){
var html = $(this).contents().find('#content').html();
var data = $(this).contents().find(elementID).html();
var table = $(this).contents().find(elementID).parent().find("table").html();
console.log(html);
console.log(data);
console.log(table);
});
#frameWrapper is a dynamically added container in the current page.
#frame0 is the actual iframe.
Of the three console.logs in the above code, html always returns the source code which is not the same as the actual view in the iframe on the page, data and table are always undefined, they are the two dynamic elements.
If I remove .html() from the above code, then all three elements are found and returned in the console.log.
I have tried too many things to list, as many answers on here as I can find, including checking all the suggested ones while I was writing this. But some of the ideas include, using plain javascript and adding a timeout to ensure load has completed, always the same response.
EDIT: Added the basic iframe code:
<div id="content">
<div class="wrap">
<div id="elementID"></div>
<table class="table"></table>
</div>
</div>
#elementID and .table are empty in the source and are only populated via a jquery function on load.
EDIT2: jsfiddle obviously it's having issues with Cross-domain policy so it's not really a good example, but it is a start.
Use this:
$("#frameWrapper").on("load", "#frame0", function () {
var html = $(this).contents().find('#content').html();
var data = $(this).contents().find(elementID).html();
var table = $(this).contents().find(elementID).parent().find("table").html();
console.log(html);
console.log(data);
console.log(table);
});
...instead of $("#frame0").bind("load",function(){...
This is called delegated events and should be used since the iframe is dynamically generated.
I don't have a working code to test for your issue, therefore the above is my guess to resolve your problem.
I am trying to read the particular contents of an child IFrame wrapped in a div tag from parent window. I am using
detailsValue = window.frames['myIframe'].document.getElementById('result').innerHTML;
with this I'm able to access the entire content of that frame. But I need to access only a portion of that content. The problem is that the div which wraps the content that I am looking for contains only class and no ID.
<div class="watINeed"> <table class="details"> </table> </div>
I am unable to access the content which is in a form of table (with no id and only class).
Any help.
Edit1: I need to access the content of the table to check for char length and also for some html tags present in that content.
You can do this either using plain Javascript (as mentioned by Notulysses):
window.frames['myIframe'].document.querySelector('.watINeed .details')
or using jQuery (since you aded jquery) by specifying the iframe's document as context to $:
$(".watINeed .details", window.frames['myIframe'].document)
In the latter case you've a fullfeatured jQuery object.
Note that in either case the iframe's document has to be on the same domain otherwise you'd run into cross origin issues.
Tested against jQuery 2.0.x
Update
If you're running the selector during page load of the including page, you'll have to listen to the load event of the iframe before accessing its content:
$(window.frames['myIframe']).on("load", function(){
// above query here
});
If your are looking for a vanilla Javascript, and your target div is a direct children of starting selector, it is a simple task
var detailsValue = window.frames['myIframe'].document.getElementById('result').innerHTML;
var target;
for(var i = 0; i< detailsValue.children.lenght; i ++){
if(detailsValue.children[i].getAttribute('class')== 'watINeed'){
target = detailsValue.children[i] ;
}
}
otherwise, have to write a recursive method to scrap all children of structure
As i wrote above, it can be done using the following:
document.querySelectorAll(".className")[0] or $(".className")[0]
those are basically the same as both return a list of nodes and the [0] simply means taking the first result from the list.
there are 2 things to pay attention to:
the iframe loads the content asynchronously therefore when you execute the query its most likely that the elements you are searching for did not load yet.
executing the code after DOM loads is not enough.
the solution is simply put your code in a block that executes once all the asynchronous content is loaded:
window.onload=function(){
window.frames['myIframe'].document.querySelectorAll(".watINeed")[0];
}
or the jQuery alternative:
$(window).load(function(){
window.frames['myIframe'].document.querySelectorAll(".watINeed")[0];
});
the second thing is, according to the page Here, you can access the iframe's document using contentWindow.document:
window.onload=function(){
window.frames['myIframe'].contentWindow.document.querySelectorAll(".watINeed")[0];
}
or the jQuery alternative:
$(window).load(function(){
window.frames['myIframe'].contentWindow.document.querySelectorAll(".watINeed")[0];
});
live example: Fiddle
I have an array filled with the HTML contents I want, as well as a way to map each of the contents to the proper iframe.
Here is the chunk of code I am using
function replaceFrames(docElement) {
Array.prototype.forEach.call(docElement.querySelectorAll("iframe, frame"), function (node) {
var name = node.getAttribute("name");
var blah = singlefile.test[name];
node.setAttribute("srcdoc",blah);
});
}
The docElement parameter is a standard DOM Element
I would use JQUERY, but I feel like I wont be able to modify what I want, since I dont have access to the Document, just the specific element/node.
The problem is, in my output document I have ">'; and <'; instead of the tags (ignore the quotes there, it was just to make it pop up.)
I am currently using Jquery's .load() function to insert a page fragment asynchronously. In the URL that I am loading the page fragment from, I also set a Javascript global variable value (in the script tag).
var loaded_variable = 'value1'
Is there a way I can use the .load() function to insert the page fragment AND retrieve the value of loaded_variable, something like the following code:
function loadProducts(url) {
$('#mainplace').load(url + ' #submain', function() {
current_variable = loaded_variable;
});
}
I am aware that script blocks are used when a selector expression is appended to the URL, so if the .load() function won't work, I'm open to other Jquery functions that can accomplish this.
Extra Info: The URL that I am loading from is written in HTML and Python (Web2py); the same Python variables are used to render the page fragment and set the loaded_variable value.
If you want to both fetch a fragment from a page and execute a script on it, you'll need a different approach. This is a bit hacky, but works.
$.ajax({url: 'fetch_page.html', dataType: 'text'}).done(function(html) {
var dom = $('<html />').prop('innerHTML', html);
$('body').append(dom.find('body p'));
$('head').append(dom.find('script'));
});
That fetches a p tag from our fetched pages and inserts it into the body of the parent page. It also executes any scripts in the fetched page.
If you're wondering about the prop('innerHTML... bit, that's because if I'd used jQuery's .html() method, it sanitises the input string and so we don't get the result we want.
My first thought was a document fragment, but you can't insert an HTML string into a doc frag - you have to append via DOM methods. Even then in this case it wouldn't really offer any saving over simply using an element to parse the dom (dom) as I have.
Bit hacky, as I say, but works.
I think I have a similar question. I have create a page that will hold a newsletter sign up. I want to load this page at the bottom of every blog post on my site. I don't want it in the footer because it is specific to my blog page and I want the ability to edit it without having to edit every blog post.
I created this page with the url /blog-newsletter-form which includes some code from an Email CRM.
I then added a div with a "blog-newsletter-form" class at the end of my blog posts and put the following in the page header to load the content from the first page section inside my blog posts.
$( document ).ready(function() {
$('.blog-newsletter-form').load("/blog-newsletter-signup #page .page-section:nth-of-type(1) .content");
});
This worked great except.. the load function is stripping the script from the newsletter page which is required for my newsletter form to work.
How do I load a page fragment but also keep the script for the newsletter. I tried using your sample code above and couldn't get it to work.
I remember using a plugin in the past where I could use AJax to load a page and update only part of the DOM. The AJax request returns the entire HTML page, but only a small portion of it replaces part of the currently loaded DOM.
For example, SO can use this function to fetch http://stackoverflow.com and only update #content. SO would make an AJax request to fetch http://stackoverflow.com, fetch #content from the returned string, and update #content of the DOM.
Sorry if my question is confusing. How would I do this without a plugin?
The .load() function is designed to do this. Just include a selector for an element along with the URL, like so:
$('#content').load('http://stackoverflow.com #content', optionalCallbackFunction);
That will replace the content of the element with ID content on the current page, with the contents of the element with ID content on the page returned by an AJAX request to http://stackoverflow.com, then run the function called optionalCallbackFunction. Assuming, of course, that the request was successful.
Without the AJAX, you can parse a raw string like this:
var str = "<div><h1>Page Title</h1><div id='content'>This is new.</div></div>";
var text = $("#content",$(str)).html();
$('#content').html(text);