1

$("<html><head></head><body>Hello</body></html>").html()

Returns undefined. Of course, my situation is a little more complex than this, but this line of code shows the issue. How can I fix this?

This gives an idea of what I'm trying to do:

var $theSite = $(myHTMLString);//myHTMLString is an external web site (string)
$theSite.filter('input').remove();
alert($myHTMLString.html());
7
  • 2
    what's that supposed to do? Commented Sep 2, 2013 at 13:54
  • @hex4 like I said my situation is more complex Commented Sep 2, 2013 at 13:55
  • can you recreate it in jsfiddle.net for us? Commented Sep 2, 2013 at 13:55
  • @Hope4You Well, try to put some effort in your question, honestly what you're trying to do makes no sense at the moment, maybe you can give us some context. Commented Sep 2, 2013 at 13:57
  • @Opentuned jsfiddle.net/m8N4k does not return the entire html Commented Sep 2, 2013 at 13:57

5 Answers 5

7

That's because there's no renderable HTML

Note that .text() returns a value

$("<html><head></head><body>Hello</body></html>").text();

And if we add some HTML in the body tag we get a result too!

$("<html><head></head><body><h1>Hello</h1></body></html>").html();

Update based on OP comments

No need to use JQuery to resolve your problem. Treat the HTML as a string and then use a regular expression to remove input tags:

var x = '<html><head></head><body><input type="text" />Hello<input type="button" /><p>p</p></body></html>';

alert(x);

var regX = /(<input([^>]+)>)/ig;

alert(x.replace(regX, ""));
Sign up to request clarification or add additional context in comments.

5 Comments

This is the right answer. There is no html (markup) at all, therefore undefined is returned. Insert markup or use text() instead.
@davidkonrad that still does not return the tags, like I want.
@hope4You - jQuery's html()-function uses the browsers innerHTML-function, which vary from browser to browser. Some browsers strips / ignores <html>, <head>, <script> and so on. Google the details. Quite sure you'll ge different results in IE, Chrome, Opera and FireFox.
So basically is what I'm trying to accomplish not possible using jQuery? (See my updated question)
@Hope4You It is and it isn't - see my answer
3

You could use a DOMParser - something like this:

var pageStr = "<html><head></head><body><h1>Hello</h1><span>YO</span></body></html>";
var dp = new DOMParser();
var doc = dp.parseFromString(pageStr,'text/html');
alert(doc.documentElement.outerHTML);//"<html><head></head><body><h1>Hello</h1><span>YO</span></body></html>"
$(doc).find("span").remove();
alert($(doc).get(0).documentElement.outerHTML);//"<html><head></head><body><h1>Hello</h1></body></html>"

JSFiddle

Update: answer now implements a DOMParser polyfill

/*
 * DOMParser HTML extension
 * 2012-09-04
 * 
 * By Eli Grey, http://eligrey.com
 * Public domain.
 * NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
 */

/*! @source https://gist.github.com/1129031 */
/*global document, DOMParser*/

(function(DOMParser) {
    "use strict";

    var
      DOMParser_proto = DOMParser.prototype
    , real_parseFromString = DOMParser_proto.parseFromString
    ;

    // Firefox/Opera/IE throw errors on unsupported types
    try {
        // WebKit returns null on unsupported types
        if ((new DOMParser).parseFromString("", "text/html")) {
            // text/html parsing is natively supported
            return;
        }
    } catch (ex) {}

    DOMParser_proto.parseFromString = function(markup, type) {
        if (/^\s*text\/html\s*(?:;|$)/i.test(type)) {
            var
              doc = document.implementation.createHTMLDocument("")
            ;
                if (markup.toLowerCase().indexOf('<!doctype') > -1) {
                    doc.documentElement.innerHTML = markup;
                }
                else {
                    doc.body.innerHTML = markup;
                }
            return doc;
        } else {
            return real_parseFromString.apply(this, arguments);
        }
    };
}(DOMParser));

3 Comments

Uncaught TypeError: Cannot read property 'documentElement' of null (Chrome 29)
@Hope4You Indeed - very strange. A DOMParser polyfill seems to sort out that issue. See updated JSFiddle.
This is working for me, however I need .filter instead of .find (for at least one of my PhoneGap platforms) (stackoverflow.com/questions/17688002/…)
3

There are restrictions on the HTML that you can create with jQuery(htmlString). As explained in the documentation:

If the HTML is more complex than a single tag without attributes, as it is in the above example, the actual creation of the elements is handled by the browser's innerHTML mechanism. In most cases, jQuery creates a new <div> element and sets the innerHTML property of the element to the HTML snippet that was passed in.

When passing in complex HTML, some browsers may not generate a DOM that exactly replicates the HTML source provided. As mentioned, jQuery uses the browser"s .innerHTML property to parse the passed HTML and insert it into the current document. During this process, some browsers filter out certain elements such as <html>, <title>, or <head> elements. As a result, the elements inserted may not be representative of the original string passed.

This is what's happening in your case. You can't use jQuery(htmlString) to parse a complete web page, because it has to be something that can be put inside a DIV. You should use the DOMParser API instead.

Comments

0
var $html=$("<html><head></head><body>
             <input type='text' value='hello'><p>hi</p></body></html>");
$("div").html($html.filter('*:not("input")'));

http://jsfiddle.net/tSUFc/1/

Comments

-3

You are using this wrong. The first part is a selector, you select one or more elements with it, like this:

$('html,body') // selects both html and body
$('body div') // selects all 'divs' in 'body' (just like css)

The .html() works like this:

// a setter
$('#someElement').html('<strong>This is the new html in #someElement</strong');
// or, as getter:
console.log( $('#someElement').html() ); // returns " '<strong>This is the new html in #someElement</strong' " 

3 Comments

jQuery is overloaded. You can also pass a string containing HTML to it: api.jquery.com/jQuery/#jQuery2.
I'm aware of that, but I'm not sure about that html() part. Does that trigger some callback which adds (in your answer) the h1 to the body?
No, it returns the HTML of the element that you created.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.