Parsing returned HTML from jQuery AJAX request - javascript

What I'm trying to do seems simple: get an HTML page through $.ajax() and pull out a value from it.
$(function () {
$.ajax({
url: "/echo/html",
dataType: "html",
success: function (data) {
$('#data').text(data);
$('#wtf').html($(data).find('#link').text());
},
data: {
html: '<!DOCTYPE html><head><title><\/title><link href="../css/popup.css" rel="stylesheet" /><\/head><body><ul><li><a id="link">content<\/a><\/li><\/ul><\/body><\/html>'
}
});
});
The problem is that jQuery refuses to parse the returned HTML.
The fiddle I'm play with this in isn't working in the mean time, so there's little else I can do to provide a working example.
UPDATE: My new fiddle is working fine, but it seems the problem is that in my actual project I'm trying to parse a large, complex bit of HTML. Is this a known problem?

Your code works fine. You just aren't using jsFiddle's API correctly. Check the docs for /echo/html/ (http://doc.jsfiddle.net/use/echo.html#html):
URL: /echo/html/
Data has to be provided via POST
So, you need to update your AJAX call to use POST. Also the trailing slash is needed.
$(function () {
$.ajax({
url: "/echo/html/",
type: "post",
dataType: "html",
success: function (data) {
$('#data').text(data);
$('#wtf').html($(data).find('#link').text());
},
data: {
html: '<!DOCTYPE html><head><title><\/title><link href="../css/popup.css" rel="stylesheet" /><\/head><body><ul><li><a id="link">content<\/a><\/li><\/ul><\/body><\/html>'
}
});
});
DEMO: http://jsfiddle.net/hcrM8/6/

If you would like to parse it, jquery has a nifty trick :)
ParsedElements = $(htmlToParse);
Console.log(ParsedElements);
You now have DOM elements you can traverse without placing them in the body of the document.

jQuery.parseHTML()
http://api.jquery.com/jQuery.parseHTML/
str = "hello, <b>my name is</b> jQuery.",
html = $.parseHTML( str ),
nodeNames = [];
// Gather the parsed HTML's node names
$.each( html, function( i, el ) {
nodeNames[ i ] = "<li>" + el.nodeName + "</li>";
});
Some thing is wrong with your ajax on fiddle
http://jsfiddle.net/hcrM8/5/
var html= '<!DOCTYPE html><head><title><\/title><link href="../css/popup.css" rel="stylesheet" /><\/head><body><ul><li><a class="disabled" id="link">content<\/a><\/li><\/ul><\/body><\/html>';
h = $.parseHTML(html);
$('#data').text(h);
$('#wtf').html($(h).find('#link').text());

Why don't you just use the load method?
$( "#wtf" ).load( "/echo/html #link" );
Or, here's your fiddle fixed and working:
http://jsfiddle.net/hcrM8/4/

I had the same problem and i fixed encapsulating requested html code into just one container element.
Bad Example:
Linkname
<p>Hello world</p>
Jquery couldnt convert this to element, because it wishes to convert a single element tree. But those are not having a container. Following example should work:
Right Example:
<div>
Linkname
<p>Hello world</p>
</div>

All answers do not point to the real problem, jQuery seems to ignore the head and body tag and creates an array of nodes. What you normally want is, extract the body and parse it.
Take a look at this helpful answer, I do not want to copy his work: https://stackoverflow.com/a/12848798/2590616.

I am facing the same problem, and it is not because you are doing something wrong.
it's because the "link" tag is not supposed to have any innerHTML returned, it's explicitly excluded in jquery, you will find some where this line:
rnoInnerhtml = /<(?:script|style|link)/i,
This tag in HTML is supposed to link to external style sheet.

Related

Add loaded text to other loaded text

In Javascript, to add text to an already existing div I would use
document.getElementById("container").innerHTML = document.getElementById("container").innerHTML + "Text";
So that the text that is already present in the div wouldn't be deleted and to be able to reset what is written in the div by just using:
document.getElementById("container").innerHTML = "Text";
But, since I'm using jquery to load the text from a txt file with
$( "#container" ).load( "text.txt" );
That doesn't seem possible.
I'm not a big expert on neither JS or Jquery, but is there a way to mix the two to still be able to reset the text in a div or add text to it, while still fetching that text from an external file?
Hope I've been clear enough in explaining what I'm trying to do
Try using AJAX to fetch your data but not populate it:
$.ajax({
url: 'text.txt',
success: function(text){
document.getElementById("container").innerHTML += text;
}
});
Ajax is a lot more full featured - it's the 'harder' cousin of load(), so you can also add an error catcher (as well as a raft of other things):
$.ajax({
url: 'text.txt',
success: function(text){
document.getElementById("container").innerHTML += text;
},
error: function(e){
document.getElementById("container").innerHTML += 'Data could not be loaded! (' + e.statusText + ')';
}
});
You can learn more about AJAX at jQuery docs: http://api.jquery.com/jquery.ajax/
First of all:
You run the risk of loading a file, which may or may not be available. Meaning you could get a file load error. In order to stick with jQuery I would leverage AJAX to load the file like so:
JQuery code:
$(document).ready(function() {
$.ajax({
url : "text.txt",
dataType: "text",
success: function (data) {
data.appendTo("#container")
},
error: function(e){
// Show some error, for example:
alert("Data failed to load from text.txt file")
}
});
});
I believe that appendTo will be a much simpler version of what you've tried to accomplish via document.getElementById("container").innerHTML in order to replace the text. Give it a try and modify this to work exactly as you like. Let me know if you have any questions about it.
To make it clear to you, JQuery is an extension of the existing JavaScript language. Meaning, you can always use your JavaScript within your perceived JQuery code. You can learn how to use the strengths of JQuery to support your JavaScript code with added functionality, a great example of one is the AJAX implementation of file loading you see here. To learn more visit: Learn JQuery.

How to display returned html page in a div using javascript and/or html

I want to build a url, send the url and display the returned html page in a div or any block element on the same page.
Ultimately, what I want to do is send a request as soon as the user enters a name, create a div to display the response,
fill the div with the response, hide the div then display a button or tab for the user to click to see the returned document.
But for now I'm just trying to figure out how to get the response into a div on the same page.
This seems like a fundamental HTML activity but I can't figure out how to direct the returned page to a div instead of having it replace the original page.
I would prefer to do this with plain HTML5 and javascript, not JQuery, but if JQuery is the only way I'll tackle that learning curve.
<html>
<body onload="buildPage()">
<div id="documents"></div>
</body>
<script>
function buildPage() {
var name="somename" ; // this will eventually come from user input and be passed in
var documentName = name + ".html";
var url ="http://localhost:8080/docserver/getpage?name=" + documentName;
// create a div to display the requested document
var newDiv = document.createElement("div");
newDiv.id = documentName;
newDiv.style.visibility = "hidden";
// ... probably need to do something here to direct the url response into the new div
// nest the newDiv in the existing div
document.getElementById("documents").appendChild(newDiv) ;
//TBD create a button to display the returned document
}
</script>
</html>
It sounds like you want to make an ajax request, which returns html, then render that html in a div?
I would also recommend using jQuery if you are not. It will make your life a lot easier.
Your file(s) will need to look something like this:
HTML
....
<div id="mydiv"></div>
....
JQUERY
$( document ).ready(function() {
$.ajax({
'type': 'get',
'contentType': 'text/plain',
'url': 'path/to/your/script/',
'dataType': 'html',
'timeout': 50000
}).done(function (data) {
// success
$('#mydiv').html(data);
}).fail(function (error) {
// something went wrong
console.log(error);
});
});
For the sake of simplicity, Let's say your html that is returned is:
HTML
<p>Hello World!</p>
Your page (after the ajax request runs) will look like this:
HTML
....
<div id="mydiv"><p>Hello World!</p></div>
....
This should get you rolling.
To expand on my comment, this code will pretty much do it for you
$.ajax({
url: "mypage.html",
cache: false
})
.done(function( html ) {
$( "#results" ).append( html );
});
With really good supporting documentation found here http://api.jquery.com/jquery.ajax/
Thanks to all that answered my query. Especially jonny who did some impressive hand holding. I really don't understand JQuery so I wanted a pure html/js solution. Here is what I ended up doing.
function buildPage() {
var name="somename" ; // this will eventually come from user input and be passed in
var documentName = name + ".html";
var url="http://localhost:8080/FDS/documents?filename=" + documentName ;
// create a div to display the requested document
var newDiv = document.createElement("div");
newDiv.id = documentName;
//newDiv.style.visibility = "hidden";
// create an iframe to place in the div
var newIframe = document.createElement("iframe") ;
newIframe.src = url ;
// nest the iframe in the div just created
newDiv.appendChild(newIframe) ;
// nest the newDiv in the existing div
document.getElementById("documents").appendChild(newDiv) ;
The missing component was an iframe. I thought I saw JQuery using iframes in the tabs widget but I did not pursue that avenue until it looked like I was going to get only JQuery based replies.

Javascript: Get current page CURRENT source

I have HTML and I need to get page source of this html.
document.documentElement.outerHTML
or
$.ajax({
async: true,
type: 'GET',
cache: false,
url: window.location.href,
success: function(data) {
alert(data);
}
});
is working, but they display originally source. If I change html (by jQuery, for example), they don't read my changes.
Is it possible read CURRENT source of page?
Tried it on chrome and it works. Use
document.documentElement.innerHTML
Funnily enough your code also worked
document.documentElement.outerHTML
Check out the html printed to the console in this fiddle. It actually contains the changes made by jQuery.
Using jQuery you can do this by:
$( 'body' ).html();
For example.
Or convert to String:
$( 'body' ).html().toString();
You just need to grab the element and use the html method:
$('.selector').html();
Simple solution, source of a document usually embedded in html tag
so use $('html').html(), you will get everything between html tags.

Where are scripts loaded after an ajax call?

suppose you have a simple web page that dynamically loads content that looks like this:
- main.html -
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript">
$(function() {
$.ajax({
type: 'get', cache: false, url: '/svc.html',
success: function(h) {
$('#main').html(h);
}
});
});
</script>
</head>
<body>
<div id='main'>
loading...
</div>
</body>
</html>
and that the page it loads uses a little Javascript in a separate file:
- svc.html -
<script type="text/javascript"
src="https://ajax.aspnetcdn.com/ajax/jquery/jquery-1.6.2.js">
</script>
<script type="text/javascript" src="/plugin.js" css="/plugin.css"></script>
<div id='inner'>
dynamically loaded content
</div>
notice the css attribute on the script tag - it indicates a style-sheet that belongs to the script and which the script will load for us. Here's the script:
- plugin.js -
var css = $('<link />', {
rel: "stylesheet", type: "text/css", href: $('script:last').attr('css')
});
$('head').append(css);
and, finally, the style-sheet, which merely colours the inner div that gets loaded, as proof that it all works:
- plugin.css -
#inner
{
border: solid 1px blue;
}
now, you'll notice the way the style-sheet gets loaded: we look at $('script') and pick off the last one, then we grab the css attribute and attach a link item to the head of the document.
I can visit /svc.html and the javascript runs, loads my style-sheet, all's cool - however, if I visit /main.html, the javascript runs but fails to find the loading of the plugin.js in the array of $('script') (and therefore fails to load the stylesheet). Note that the plugin script does run, it just doesn't see itself.
Is this a bug? a limitation of the jQuery AJAX method? shouldn't $('script') reflect all scripts that have been loaded?
* edit *
after much wailing and gnashing of teeth, I decided to go for Kevin B's solution, however, I can't get it to work, basically because the plugin.js code runs at the time the scriptNode gets inserted, but within the plugin code, the node has not yet been inserted and is thus not available in the $('script') array - so I'm still SOL. I've put all the code for review here:
http://www.arix.com/tmp/loadWithJs/
The jQuery code that adds HTML to the DOM always strips out <script> tags. It runs them and then throws them away.
An exception to that behavior is when you use "$.load()" with the hack that allows you to load a fragment of a page:
$.load("http://something.com/whatever #stuff_I_want", function() { ... });
In that case, the scripts are stripped and not evaluated/run.
you can use $.ajax to get the html, strip out the script tags yourself, append the content, and then append the script tag to the location in the dom where you want it so that it executes the way you want it to.
$.ajax({...}).done(function(html){
var htmlToAppend = html;
// replace all script tags with divs
htmlToAppend.replace(/<script/ig,"<div class='script'");
htmlToAppend.replace(/<\/script>/ig,"</div>");
// detach script divs from html
htmlToAppend = $(htmlToAppend);
var scripts = htmlToAppend.find(".script").detach();
// append html to target div
htmlToAppend.appendTo("#target");
// loop through scripts and append them to the dom
scripts.each(function(){
var $script = $(this),
scriptText = $script.html(),
scriptNode = document.createElement('script');
$(scriptNode).attr('css', $script.attr('css');
scriptNode.appendChild(document.createTextNode(scriptText));
$("#target")[0].appendChild(scriptNode);
});
});
I haven't tested this code, but it is based on code from history.js
Edit: here's a simpler solution more tailored for your needs:
$("#target").load(url,function(obj){
// get css attribute from script tag using the raw returned html
var cssPath = obj.responseText.match(/css="(.*)"/i)[1];
$('<link />', {
rel: "stylesheet", type: "text/css", href: cssPath
}).appendTo('head');
});
since .load() strips the script tags and then executes them, this will read the raw response text and get the css path from it, then add the link element.
I'm not entirely sure why it is handled this way.
Edit: see comment.
$.ajax({...}).done(function(html){
$("#target")[0].innerHTML = html;
});
My solution would be rather simple
Why not load the the files needed in main, on the first load all together? Then simply have a listener event. (Check if the content is simply loaded?)
The only solution for loading on demand...
You simply has to AJAX call the script file itself...
<script type="text/javascript">
$(function () {
$.ajax({
type: 'get',
cache: false,
url: 'svc.html',
success: function(response) {
if (response) { // If any response aka, loaded the svc.html file...
$('#main').html(response);
$.ajax({
url: 'plugin.js',
dataType: 'script',
success: function(reponse) {
// You can now do something with the response here even...
}
});
}
}
});
});
</script>
My way
Make some type of loader instead on the actual page on load before displaying anything. (Plenty of tutorials with jQuery around the web for this.)
On of the problems here is that you CANNOT reload the jQuery in every page. Just the main page
should have the jQuery call:
<script type='text/javascript' src='jQuery-url'></script>
Or only one page can call it and ONLY THE CHILDREN (yes, the pages .LOADed from there) will be able to use jQuery.
I've ran into that a few times before I learned my lesson. This might not be the entire answer for your problems but could be the beginning of solving them.
ok, after many struggles, I've implemented Kevin B's solution into a plugin useful to others. Improvements welcome! (should I maybe put it in github?)
- loadWithJs.js -
// inspired by Kevin B's suggestions
// at: http://stackoverflow.com/questions/8234215/where-are-scripts-loaded-after-an-ajax-call
(function ($) {
$.fn.loadWithJs = function (o) {
var target = this;
var success = o.success;
o.success = function (html) {
// convert script tags
html = $('<div />').append(
html.replace(/<(\/)?script/ig, "<$1codex")
);
// detach script divs from html
var scripts = html.find("codex").detach();
// populate target
target.html(html.children());
// loop through scripts and append them to the dom
scripts.each(function () {
var script = $(this)[0];
var scriptNode = document.createElement('script');
for (var i = 0; i < script.attributes.length; i++) {
var attr = script.attributes[i];
$(scriptNode).attr(attr.name, attr.value);
}
scriptNode.appendChild(
document.createTextNode($(script).html())
);
target[0].appendChild(scriptNode);
});
if (success) success();
};
$.ajax(o);
};
})(jQuery);
then the caller can do:
$(function() {
$('#main').loadWithJs({
type: 'get', cache: false,
url: '/svc.html',
success: function() { console.log('loaded'); }
});
});

IE doesn't apply css styles to a dynamically added div

I have this weird problem on IE8. My application get a div via ajax and append it to the HTML.
$('#formPromocao').submit(function () {
persistPageIndex();
var postData = $(this).serialize();
$.post($(this).attr('action'), postData, function (data) {
$('#lista').empty();
$('#lista').append(data);
prepareNewForm();
});
return false;
});
This works perfectly on all browsers except IE8 the appended HTML is not stylized by the browser and I cant figure out why.
Has anyone here stumbled upon this issue before? Any help would be appreciated.
EDIT:
I have found the problem: The HTML people used HTML5 for the application and on IE8 there's a script that handles HTML5: http://html5shiv.googlecode.com/
I have to find a way to make this script run again when the HTML is updated. Can I safely do this?
Use the shiv function before appending to the document:
html = innerShiv(html, false);
$('something').append(html);
This is usually because you are appending invalid HTML, or there is already invalid HTML in the page.
Here is how I managed to append HTML5 in IE.
I found this amazing script: http://jdbartlett.github.com/innershiv/#download and then all I had to to was to append the result of innerShiv to the HTML:
$('#formPromocao').submit(function () {
persistPageIndex();
var postData = $(this).serialize();
$.post($(this).attr('action'), postData, function (data) {
$('#lista').empty();
$('#lista').append(innerShiv(data));
prepareNewForm();
});
return false;
});

Categories

Resources