views:

22

answers:

1

In the application that we have, we're doing some AJAX response. Once in a while we get back a response that isn't fully contained Test 3 in the code below. While it's possible to beat people into submission, I would like to just build in some belt and suspenders in the code to handle the case.

The key is the findself() function which is designed to take any response html block via the $('...html...') string and then do the appropriate magic to it. This works just find for some cases, but in case #3 it dies with a getAttribute error in the browser.

Any good ideas of how to extend the findself() function to handle case #3?

var html;

function findself(sel, html) {
    return html.is(sel) ? html.find(sel).add(h) : html.find(sel);
}

html = $('<span rel="toggle">foo</span>');

findself('[rel="toggle"]', html).each(function () {
    console.log('ok 1');
});
console.log('done case 1');

findself('[rel="toggle"]', $('testing of a text node')).each(function () {
    console.log('ok 2');
});
console.log('done case 2');

html = $('<span>foo</span>some text<div rel="toggle">xx</div>');

findself('[rel="toggle"]', html).each(function () {
    console.log('ok 2');
});
console.log('done case 3');
A: 

Quick version: You can side-step your current issue by ensuring that text element isn't in-between 2 ones and at the root, like this:

function findself(sel, html) {
    var h = $("<div />").append(html);
    return h.is(sel) ? h.find(sel).add(h) : h.find(sel);
}

You can test it out here.


Explanation: This is a bug in jQuery core it looks like. It's detecting it as a HTML string, because of the opening/closing tags, but it's not a single element. It's 3 nodes one being a text, due to this incorrect detection it's incorrectly treating it as an element string, rather than a collection of children, for example:

jQuery.filter('[rel="t"]', $('<span>foo</span>some text'));            //works
jQuery.filter('[rel="t"]', $('<div><span>foo</span>some text</div>')); //works
jQuery.filter('[rel="t"]', $('<span>foo</span>text<div>xx</div>'));    //fails

So currently, jquery.filter() (which .is() uses) doesn't work with a text node in the middle.

Nick Craver
Interesting, when I try that code snippet in the application it dies a horrible death (all the content is gone from the page). I think it has to do with reparenting large swaths of the document.
koblas
@koblas - You're trying just the top code block right? Check for JavaScript errors, sounds like one's being thrown, look in the console to check.
Nick Craver