Skip to main content

Bug Tracker

Side navigation

#164 closed bug (fixed)

Opened September 01, 2006 09:01AM UTC

Closed April 06, 2007 03:08PM UTC

Last modified March 15, 2012 07:37PM UTC

IE throws errors for $(this) in nested each loops

Reported by: klaus.hartl@stilbuer Owned by:
Priority: critical Milestone:
Component: plugin Version:
Keywords: each loop ie xml Cc: woodbri@swoodbridge.com
Blocked by: Blocking:
Description

Consider the following XML:

<dashboard>
    <locations>
        <location>
            <infowindowtab>
                <tab title="Location">
                    <![CDATA[ ... ]]>
		</tab>
                <tab title="Users">
                    <![CDATA[ ... ]]>
		</tab>
            </infowindowtab>
        </location>
    </locations>
</dashboard>

And that JavaScript (both simplified):

$.get(..., function(xml) {
    $('location', xml).each(function() {
        var content = [];
        var infoWindowTabs = $('infowindowtab', this);
            $('tab', infoWindowTabs[0]).each(function(k) {
            // workaround for IE needed here, $(this).text() throws an error
            content[k] = this.firstChild.data || $(this).text());
        });
    });
});

In that case IE fails on $(this).text() and throws an error (object does not support that property or method).

Attachments (0)
Change History (16)

Changed September 05, 2006 09:11PM UTC by john comment:1

priority: minorcritical

Changed September 19, 2006 09:50AM UTC by joern comment:2

There is now a test for this in SVN.

Changed October 06, 2006 01:13PM UTC by joern comment:3

resolution: → wontfix
status: newclosed

I see no way to solve this within the text() implementation. It seems impossible to guess when the workarounded is necessary.

Changed October 10, 2006 09:15PM UTC by john comment:4

milestone: 1.0
resolution: wontfix
status: closedreopened
version: 1.0

All the necessary fixes have been posted by Peter to the mailing list:

The current version of jQuery has trouble when trying to access methods such as text() or parent() or attr() inside an each statement within the context of an XML document. For a test case, see Bug #164. The general assumption with this bug has been that the problem lies in methods such as text(), and therefore it would be impossible to determine whether the object in question was an XML object or a HTML object and act on it accordingly. While this bug has been closed, it is crucial for what I'm using jQuery for, so I decided to debug it and have found a simple yet (as far as I can tell) effective solution to the bug which works in both IE and Firefox, and should work fine in other browsers as well.

The problem itself does not actually lie within the text() method, but instead is caused by this statement within the primary jQuery function body:

// Handle HTML strings

var m = /^[^<]*(<.+>)[^>]*$/.exec(a);

As such, any time $(this) is called within the each function body the error is thrown, not just when specific methods such as text() or parent() are called. The error seems to be caused by 'a' being an object instead of a string and IE barfing when trying to execute the regular expression on 'a'.

The fix is quite simple, as far as I can tell... simply replace the line in question with this:

// Handle HTML strings

var m;

if (typeof a == "string") m = /^[^<]*(<.+>)[^>]*$/.exec(a);

Because the regular expression should only be effective when it's executed on a string anyway, this prevents the IE error from being thrown and still preserves the functionality otherwise. In my limited testing so far, I have yet to find any other side effects to this.

Replacing the statement above fixes the text() and parent() functions, however the attr() function still requires some prodding to make it work correctly in an XML context within IE. The troublesome lines within the attr: declaration are (~line 706):

} else if ( elem.getAttribute != undefined ) {

if ( value != undefined ) elem.setAttribute( name, value );

return elem.getAttribute( name, 2 );

For whatever reason, IE throws an error when checking whether elem.getAttribute is defined, complaining about an invalid parameter list (despite the fact that it's just a check for existence). When typeof elem.getAttribute is called in IE, the type is reported as "unknown", which certainly doesn't help things. IE also doesn't like the function call to elem.getAttribute with two parameters, so the return statement would have to be changed too. The fix once again is relatively simple. Before the block above, add another similar block that looks like this:

} else if ( jQuery.browser.msie && elem.getAttribute(name) != undefined ) {

if ( value != undefined ) elem.setAttribute( name, value );

return elem.getAttribute( name );

This makes attr() work in both IE and Firefox, although I haven't tested in other browsers as of yet.

One last XML related fix I've found within jQuery. When using Xpath expressions, jQuery has a custom expression which allows matching against the content of an element, such as $("p:contains('test')"), which will match all <p> tags which contain text in their body. Once again, IE has trouble with this when processing it in an XML context. The fix is simple, change this line (~line 520):

contains: "(a.innerText||a.innerHTML).indexOf(m[3])>=0",

to this:

contains: "((a.firstChild && a.firstChild.nodeValue)||a.innerText||a.innerHTML).indexOf(m[3])>=0",

And it works as expected in Firefox and IE (and, once again, presumably in other browsers too).

I hope these fixes are as much a lifesaver for others as they are for me--most of what I'm doing in jQuery is based on processing XML, and not having the ability to use jQuery functionality within each loops was proving a major pain. I'm not familiar enough yet with SVN or the jQuery checkin process to check these changes into SVN myself--if it's better for me to check them in than for someone more familiar with the process, let me know and I'll work on that tonight.

Any testing in browsers other than IE or Firefox would also be appreciated--the modifications shouldn't really affect any browser other than IE, but I'm not yet familiar enough with Javascript to say that with any degree of certainty.

Changed October 11, 2006 01:26PM UTC by joern comment:5

Added two of three fixes. The original issue is tested and solved. The third proposed fix doesn't break anything else but isn't tested yet.

The second proposed fix breaks quite a lot of other code.

Changed October 12, 2006 04:44PM UTC by john comment:6

resolution: → fixed
status: reopenedclosed

I made some more changes and fixed the remaining code. Everything seems to be working correctly now.

Changed October 13, 2006 06:22PM UTC by joern comment:7

resolution: fixed
status: closedreopened

From Stephan Woodbridge:

I see that Bug #164 has closed. I just downloaded the current Bug and

this does not fix the problem I am having. To test it hit:

http://imaptools.com:8081/maps/demo.html?address=01863

and double click on the map.

see /js/imaptools-demo.js line: 229

Maybe I should be using different functions to do this, I'm open to

suggestions, but this works fine in FF.

Changed October 14, 2006 10:04AM UTC by joern comment:8

These three lines cause lots of trouble when working with XML in IE:

} else if ( elem.getAttribute != undefined && elem.tagName ) { // IE elem.getAttribute passes even for style
	if ( value != undefined ) elem.setAttribute( name, value );
	return elem.getAttribute( name, 2 );

Test attr(String, Object)x does not fail, instead IE hangs and skips the test. In addition, it indicates an error on the first line, but only the first time the page is loaded. Something about "Wrong number of arguments or illegal property assignment".

Changed October 27, 2006 07:55PM UTC by anonymous comment:9

cc: ""woodbri@swoodbridge.com
component: → ajax
priority: → blocker
type: → bug

Changed October 31, 2006 04:51PM UTC by anonymous comment:10

Got the same problem that joern pointed out. The .attr() crash in IE7 with xml object. Any fix comming?

Changed November 07, 2006 11:20AM UTC by joern comment:11

resolution: → fixed
status: newclosed

According to the test suite, this is now fixed. I wonder if there will be any side effects: If you discover one, please report it here and reopen the ticket.

Changed April 03, 2007 09:05PM UTC by spinal007 comment:12

resolution: fixed
status: closedreopened

I'm still experiencing this problem in IE.

var xml = $('<xml><letters><a>a</a><b>b</b><c>c</c><d>d</d></letters></xml>');

var b = $('letters/b', xml); returns [ b ]

var b = $('letters b', xml); returns [ b ]

var b = $('letters > b', xml); // returns [ b ]

All the above work perfectly in FF but I still get an error in IE.

Changed April 04, 2007 02:36PM UTC by spinal007 comment:13

I believe I found a solution for this problem.

I've posted it on my blog where I'll post related updates and developments in the future.

http://fyneworks.blogspot.com/2007/04/fix-for-jquery-bug-in-ie-working-with.html

View blog post.

The Error

Lines 101 - 105 in the Metadata plugin.

    if ( $.meta.single )
        this[ $.meta.single ] = data; // Throws error on XML documents in IE
    else
        $.extend( this, data ); // Throws error on XML documents in IE

    this.metaDone = true; // Throws error on XML documents in IE

The fix

Find lines 75-77 in the Metadata plugin:


    $.fn.setArray = function(){
        return setArray.apply( this, arguments ).each(function(){
            if ( this.metaDone ) return;

And make the following change: (add line)

    $.fn.setArray = function(){
        return setArray.apply( this, arguments ).each(function(){
            try{ this['meta']=null; }catch(e){ return; } // Detect and trap error
            if ( this.metaDone ) return;

Changed April 05, 2007 02:05AM UTC by john comment:14

component: ajaxplugin
need: → Review
priority: blockercritical

Changed April 05, 2007 02:05AM UTC by john comment:15

This now relates to the Metadata plugin, instead of jQuery core.

Changed April 06, 2007 03:08PM UTC by joern comment:16

resolution: → fixed
status: reopenedclosed

It looks like a few other people experienced the same problem and we came up with a different but very similar solution. I've already commited that to the repository (see [1631]), please check out and try the latest revision. Just reopen this (once more) if it doesn't work for you, and I'll try your fix.