jQuery "guid" is null or not an object

Pat*_*cia 15 javascript jquery jquery-ui

This error keeps coming up in my JavaScript error logging, In IE 7 and 8. But I can't reproduce it for the life in me!

"guid" is null or not an object

I'm using jQuery 1.4.1 so it's not the .hover() problem that comes up in google searches.

the error is happening here (around line 1570 ):

  if (!handler.guid) {
        handler.guid = jQuery.guid++;
  }
Run Code Online (Sandbox Code Playgroud)

The page it's happening on is really really complex, dialogs, ajax content, tabs, accordions, you name it, it's on there. and worse, it's internal, so I can't give you guys a link to play with it.

I can't make a fiddle b/c I can't reproduce the problem :(

I know this is a long shot, and I'm more then willing to put up a bounty for this when I am able to.

Does anyone have any ideas of what I should be looking for to solve this? I'm also using jquery Ui 1.8.11 and a variety of plugins.

Edit: Here is the larger part of the jquery code that is throwing the error. it's part of jquery's event stuff.

add: function (elem, types, handler, data) {
            if (elem.nodeType === 3 || elem.nodeType === 8) {
                return;
            }

            // For whatever reason, IE has trouble passing the window object
            // around, causing it to be cloned in the process
            if (elem.setInterval && (elem !== window && !elem.frameElement)) {
                elem = window;
            }

            // Make sure that the function being executed has a unique ID
            if (!handler.guid) {
                handler.guid = jQuery.guid++;
            }

            // if data is passed, bind to handler
            if (data !== undefined) {
                // Create temporary function pointer to original handler
                var fn = handler;

                // Create unique handler function, wrapped around original handler
                handler = jQuery.proxy(fn);

                // Store data in unique handler
                handler.data = data;
            }

            // Init the element's event structure
            var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
            handle = jQuery.data(elem, "handle"), eventHandle;

            if (!handle) {
                eventHandle = function () {
                    // Handle the second event of a trigger and when
                    // an event is called after a page has unloaded
                    return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
                    jQuery.event.handle.apply(eventHandle.elem, arguments) :
                    undefined;
                };

                handle = jQuery.data(elem, "handle", eventHandle);
            }

            // If no handle is found then we must be trying to bind to one of the
            // banned noData elements
            if (!handle) {
                return;
            }

            // Add elem as a property of the handle function
            // This is to prevent a memory leak with non-native
            // event in IE.
            handle.elem = elem;

            // Handle multiple events separated by a space
            // jQuery(...).bind("mouseover mouseout", fn);
            types = types.split(/\s+/);

            var type, i = 0;

            while ((type = types[i++])) {
                // Namespaced event handlers
                var namespaces = type.split(".");
                type = namespaces.shift();

                if (i > 1) {
                    handler = jQuery.proxy(handler);

                    if (data !== undefined) {
                        handler.data = data;
                    }
                }

                handler.type = namespaces.slice(0).sort().join(".");

                // Get the current list of functions bound to this event
                var handlers = events[type],
                special = this.special[type] || {};

                // Init the event handler queue
                if (!handlers) {
                    handlers = events[type] = {};

                    // Check for a special event handler
                    // Only use addEventListener/attachEvent if the special
                    // events handler returns false
                    if (!special.setup || special.setup.call(elem, data, namespaces, handler) === false) {
                        // Bind the global event handler to the element
                        if (elem.addEventListener) {
                            elem.addEventListener(type, handle, false);
                        } else if (elem.attachEvent) {
                            elem.attachEvent("on" + type, handle);
                        }
                    }
                }

                if (special.add) {
                    var modifiedHandler = special.add.call(elem, handler, data, namespaces, handlers);
                    if (modifiedHandler && jQuery.isFunction(modifiedHandler)) {
                        modifiedHandler.guid = modifiedHandler.guid || handler.guid;
                        modifiedHandler.data = modifiedHandler.data || handler.data;
                        modifiedHandler.type = modifiedHandler.type || handler.type;
                        handler = modifiedHandler;
                    }
                }

                // Add the function to the element's handler list
                handlers[handler.guid] = handler;

                // Keep track of which events have been used, for global triggering
                this.global[type] = true;
            }

            // Nullify elem to prevent memory leaks in IE
            elem = null;
        }
Run Code Online (Sandbox Code Playgroud)

EDIT: I spent about 25 minutes trying to produce this error with no luck. I was opening and closing tabs(ajax loaded), trying to get them to change before the loaded and whatnot. also opening and closing dialogs (ajax loaded) and doing things that added and removed content ajaxly. nothing would break!

Not sure if this is helpful, but here is a user agent string that is causing the error:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; GTB7.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)

and here is another:

Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; InfoPath.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; MS-RTC LM 8; MS-RTC LM 8)

errorception (our javascript error logging service) doesn't seem to keep individual user agents, so i only have the two.

EDIT: I think i've narrowed it down to our quick search. which uses jquery ui Auto Complete, and jquery.jail (async image loading). I have tweaked jquery ui auto complete a bit. and am using the HTML extension.

Here is the code:

    /*
     * jQuery UI Autocomplete 1.8.11
     *
     * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
     * Dual licensed under the MIT or GPL Version 2 licenses.
     * http://jquery.org/license
     *
     * http://docs.jquery.com/UI/Autocomplete
     *
     * Depends:
     *  jquery.ui.core.js
     *  jquery.ui.widget.js
     *  jquery.ui.position.js

 */

(function( $, undefined ) {

// used to prevent race conditions with remote data sources
var requestIndex = 0;

$.widget( "ui.autocomplete", {
    options: {
        appendTo: "body",
        autoFocus: false,
        delay: 300,
        minLength: 1,
        position: {
            my: "left top",
            at: "left bottom",
            collision: "none"
        },
        source: null
    },

    pending: 0,

    _create: function() {
        var self = this,
            doc = this.element[ 0 ].ownerDocument,
            suppressKeyPress;

        this.element
            .addClass( "ui-autocomplete-input" )
            .attr( "autocomplete", "off" )
            // TODO verify these actually work as intended
            .attr({
                role: "textbox",
                "aria-autocomplete": "list",
                "aria-haspopup": "true"
            })
            .bind( "keydown.autocomplete", function( event ) {
                if ( self.options.disabled || self.element.attr( "readonly" ) ) {
                    return;
                }

                suppressKeyPress = false;
                var keyCode = $.ui.keyCode;
                switch( event.keyCode ) {
                case keyCode.PAGE_UP:
                    self._move( "previousPage", event );
                    break;
                case keyCode.PAGE_DOWN:
                    self._move( "nextPage", event );
                    break;
                case keyCode.UP:
                    self._move( "previous", event );
                    // prevent moving cursor to beginning of text field in some browsers
                    event.preventDefault();
                    break;
                case keyCode.DOWN:
                    self._move( "next", event );
                    // prevent moving cursor to end of text field in some browsers
                    event.preventDefault();
                    break;
                case keyCode.ENTER:
                case keyCode.NUMPAD_ENTER:
                    // when menu is open and has focus
                    if ( self.menu.active ) {
                        // #6055 - Opera still allows the keypress to occur
                        // which causes forms to submit
                        suppressKeyPress = true;
                        event.preventDefault();
                    }
                    //passthrough - ENTER and TAB both select the current element
                case keyCode.TAB:
                    if ( !self.menu.active ) {
                        return;
                    }
                    self.menu.select( event );
                    break;
                case keyCode.ESCAPE:

                    //This is changed by ME!   added self.term = ''; and also self.element.blur();  //this was so that when you hit esc, it clears the box, and puts it back to an empty state.

                    self.term = '';
                    self.element.val( self.term );
                    self.close( event );
                    self.element.blur();
                    break;
                default:
                    // keypress is triggered before the input value is changed
                    clearTimeout( self.searching );
                    self.searching = setTimeout(function() {
                        // only search if the value has changed
                        if ( self.term != self.element.val() ) {
                            self.selectedItem = null;
                            self.search( null, event );
                        }
                    }, self.options.delay );
                    break;
                }
            })
            .bind( "keypress.autocomplete", function( event ) {
                if ( suppressKeyPress ) {
                    suppressKeyPress = false;
                    event.preventDefault();
                }
            })
            .bind( "focus.autocomplete", function() {
                if ( self.options.disabled ) {
                    return;
                }

                self.selectedItem = null;
                self.previous = self.element.val();
            })
            .bind( "blur.autocomplete", function( event ) {
                if ( self.options.disabled ) {
                    return;
                }

                clearTimeout( self.searching );
                // clicks on the menu (or a button to trigger a search) will cause a blur event
                self.closing = setTimeout(function() {
                    self.close( event );
                    self._change( event );
                }, 150 );
            });
        this._initSource();
        this.response = function() {
            return self._response.apply( self, arguments );
        };
        this.menu = $( "<ul></ul>" )
            .addClass( "ui-autocomplete" )
            .appendTo( $( this.options.appendTo || "body", doc )[0] )
            // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
            .mousedown(function( event ) {
                // clicking on the scrollbar causes focus to shift to the body
                // but we can't detect a mouseup or a click immediately afterward
                // so we have to track the next mousedown and close the menu if
                // the user clicks somewhere outside of the autocomplete
                var menuElement = self.menu.element[ 0 ];
                if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
                    setTimeout(function() {
                        $( document ).one( 'mousedown', function( event ) {
                            if ( event.target !== self.element[ 0 ] &&
                                event.target !== menuElement &&
                                !$.ui.contains( menuElement, event.target ) ) {
                                self.close();
                            }
                        });
                    }, 1 );
                }

                // use another timeout to make sure the blur-event-handler on the input was already triggered
                setTimeout(function() {
                    clearTimeout( self.closing );
                }, 13);
            })
            .menu({
                focus: function( event, ui ) {
                    var item = ui.item.data( "item.autocomplete" );
                    if ( false !== self._trigger( "focus", event, { item: item } ) ) {
                        // use value to match what will end up in the input, if it was a key event
                        if ( /^key/.test(event.originalEvent.type) ) {
                            //self.element.val( item.value );       //changed by me, if they use the keys, don't change the text! don't want a textbox with a number in it.

                        }
                    }
                },
                selected: function( event, ui ) {
                    var item = ui.item.data( "item.autocomplete" ),
                        previous = self.previous;

                    // only trigger when focus was lost (click on menu)
                    if ( self.element[0] !== doc.activeElement ) {
                        self.element.focus();
                        self.previous = previous;
                        // #6109 - IE triggers two focus events and the second
                        // is asynchronous, so we need to reset the previous
                        // term synchronously and asynchronously :-(
                        setTimeout(function() {
                            self.previous = previous;
                            self.selectedItem = item;
                        }, 1);
                    }

                    if ( false !== self._trigger( "select", event, { item: item } ) ) {
                        self.element.val( item.value );
                    }
                    // reset the term after the select event
                    // this allows custom select handling to work properly
                    self.term = self.element.val();

                    self.close( event );
                    self.selectedItem = item;
                },
                blur: function( event, ui ) {
                    // don't set the value of the text field if it's already correct
                    // this prevents moving the cursor unnecessarily
                    if ( self.menu.element.is(":visible") &&
                        ( self.element.val() !== self.term ) ) {
                        self.element.val( self.term );
                    }
                }
            })
            .zIndex( this.element.zIndex() + 1 )
            // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
            .css({ top: 0, left: 0 })
            .hide()
            .data( "menu" );
        if ( $.fn.bgiframe ) {
             this.menu.element.bgiframe();
        }
    },

    destroy: function() {
        this.element
            .removeClass( "ui-autocomplete-input" )
            .removeAttr( "autocomplete" )
            .removeAttr( "role" )
            .removeAttr( "aria-autocomplete" )
            .removeAttr( "aria-haspopup" );
        this.menu.element.remove();
        $.Widget.prototype.destroy.call( this );
    },

    _setOption: function( key, value ) {
        $.Widget.prototype._setOption.apply( this, arguments );
        if ( key === "source" ) {
            this._initSource();
        }
        if ( key === "appendTo" ) {
            this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
        }
        if ( key === "disabled" && value && this.xhr ) {
            this.xhr.abort();
        }
    },

    _initSource: function() {
        var self = this,
            array,
            url;
        if ( $.isArray(this.options.source) ) {
            array = this.options.source;
            this.source = function( request, response ) {
                response( $.ui.autocomplete.filter(array, request.term) );
            };
        } else if ( typeof this.options.source === "string" ) {
            url = this.options.source;
            this.source = function( request, response ) {
                if ( self.xhr ) {
                    //added try catch
                    try{
                        if(self.xhr.abort != null){ 
                            self.xhr.abort();
                        }
                    }
                    catch(err){

                    }

                    delete self.xhr;

                }

                self.xhr = $.ajax({
                    url: url,
                    data: request,
                    dataType: "json",
                    autocompleteRequest: ++requestIndex,
                    success: function( data, status ) {
                        if ( this.autocompleteRequest === requestIndex ) {
                            response( data );
                        }
                    },
                    error: function() {
                        if ( this.autocompleteRequest === requestIndex ) {
                            response( [] );
                        }
                    }
                });
            };
        } else {
            this.source = this.options.source;
        }
    },

    search: function( value, event ) {
        value = value != null ? value : this.element.val();

        // always save the actual value, not the one passed as an argument
        this.term = this.element.val();

        if ( value.length < this.options.minLength ) {
            return this.close( event );
        }

        clearTimeout( this.closing );
        if ( this._trigger( "search", event ) === false ) {
            return;
        }

        return this._search( value );
    },

    _search: function( value ) {
        this.pending++;
        this.element.addClass( "ui-autocomplete-loading" );

        this.source( { term: value }, this.response );
    },

    _response: function( content ) {
        if ( !this.options.disabled && content && content.length ) {
            content = this._normalize( content );
            this._suggest( content );
            this._trigger( "open" );
        } else {
            this.close();
        }
        this.pending--;
        if ( !this.pending ) {
            this.element.removeClass( "ui-autocomplete-loading" );
        }
    },

    close: function( event ) {
        clearTimeout( this.closing );
        if ( this.menu.element.is(":visible") ) {
            this.menu.element.hide();
            this.menu.deactivate();
            this._trigger( "close", event );
        }
    },

    _change: function( event ) {
        if ( this.previous !== this.element.val() ) {
            this._trigger( "change", event, { item: this.selectedItem } );
        }
    },

    _normalize: function( items ) {
        // assume all items have the right format when the first item is complete
        if ( items.length && items[0].label && items[0].value ) {
            return items;
        }
        return $.map( items, function(item) {
            if ( typeof item === "string" ) {
                return {
                    label: item,
                    value: item
                };
            }
            return $.extend({
                label: item.label || item.value,
                value: item.value || item.label
            }, item );
        });
    },

    _suggest: function( items ) {
        var ul = this.menu.element
            .empty()
            .zIndex( this.element.zIndex() + 1 );
        this._renderMenu( ul, items );
        // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
        this.menu.deactivate();
        this.menu.refresh();

        // size and position menu
        ul.show();
        this._resizeMenu();
        ul.position( $.extend({
            of: this.element
        }, this.options.position ));

        if ( this.options.autoFocus ) {
            this.menu.next( new $.Event("mouseover") );
        }
    },

    _resizeMenu: function() {
        var ul = this.menu.element;
        ul.outerWidth( Math.max(
            ul.width( "" ).outerWidth(),
            this.element.outerWidth()
        ) );
    },

    _renderMenu: function( ul, items ) {
        var self = this;
        $.each( items, function( index, item ) {
            self._renderItem( ul, item );
        });
    },

    _renderItem: function( ul, item) {
        return $( "<li></li>" )
            .data( "item.autocomplete", item )
            .append( $( "<a></a>" ).text( item.label ) )
            .appendTo( ul );
    },

    _move: function( direction, event ) {
        if ( !this.menu.element.is(":visible") ) {
            this.search( null, event );
            return;
        }
        if ( this.menu.first() && /^previous/.test(direction) ||
                this.menu.last() && /^next/.test(direction) ) {
            this.element.val( this.term );
            this.menu.deactivate();
            return;
        }
        this.menu[ direction ]( event );
    },

    widget: function() {
        return this.menu.element;
    }
    });

    $.extend( $.ui.autocomplete, {
        escapeRegex: function( value ) {
            return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
        },
        filter: function(array, term) {
            var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
            return $.grep( array, function(value) {
                return matcher.test( value.label || value.value || value );
            });
        }
    });

    }( jQuery ));
Run Code Online (Sandbox Code Playgroud)

the html extension: https://github.com/scottgonzalez/jquery-ui-extensions/blob/e34c9457619a13a01774f7954175320ac1e283c1/autocomplete/jquery.ui.autocomplete.html.js

and here is where you can find JAIL: https://github.com/sebarmeli/JAIL

I tried breaking it by typing fast, using the mouse and arrows, clicking around, hitting esc, hiting ctrl, tab, all sorts of things. still doesn't break.

Edit: I've added a 250 rep bounty! There has to be someone out there who has come across this.

EDIT:

I've just seen a slightly different version of this error, now from IE 9! Unable to get value of the property "guid": object is null or undefined exact same line as the "guid" is null or not an object.

so, either handler is null, or jQuery is null. i'm going to go with handler, since if jQuery was null, i'd have a lot of other problems.

so this means, i'm trying to attach a guid, to a handler that doesn't exist. how could that even be possible?

Edit:

Here is the code that is setting up the auto complete widget:

<div class="watermarkText" >
    <label for="UserLookUp" class="over" id="UserLookUpLable"  ><%= Web.QuickSearchGhostText.HtmlEncode%></label>
    <input type="text" id="UserLookUp" name="UserLookUp" style="width:250px;vertical-align:middle;" />
</div>

<img src="ClearLookUp.jpg" alt="Clear Text" id="ClearLookUp"  />

<script type="text/javascript">

    $(function () {
        $("#UserLookUp").autocomplete({
            source: 'aurl',
            minLength: 2,
            delay: 2,
            autoFocus: true,
            html: true,
            select: function (event, ui) {
                window.location = "a url".replace("0", ui.item.value);
                return false;
            },
            open: function (event, ui) {

                $('img.LookUpControlPicture').jail();
            }
        });

        $('#UserLookUpLable').labelOver('over');

        $('#ClearLookUp').click(function () {
            $('#UserLookUp').val('');
            $('#UserLookUp').autocomplete("search");
            $('#UserLookUp').blur();
        });
    });

</script>
Run Code Online (Sandbox Code Playgroud)

也许它来自labelOver插件(我已经改变了很多).

这是它的代码:

jQuery.fn.labelOver = function (overClass) {
    ///<summary> 
    ///    applied to the label(s) to be ghosted over a textbox.  
    //     generally used like so: $('.watermarkText').find('label').labelOver('over'); 
    ///</summary>
    ///<param name="overClass" type="string">the class to apply to the label to style it as ghosted text.</param>
    ///<returns>nothing</returns>

    return this.each(function () {
        var label = jQuery(this);
        var f = label.attr('for');
        if (f) {
            var input = jQuery('#' + f);

            this.hide = function () {
                // label.css({ textIndent: -10000 })
                label.css('visibility', 'hidden');
            }

            this.show = function () {
                if (input.val() == '') label.css('visibility', 'visible');     //{ textIndent: 0 }
            }

            // handlers
            input.focus(this.hide);
            input.blur(this.show);

            //added by me
            input.change(function () {
                if (input.val() == '') {
                    label.css('visibility', 'visible');
                }
                else {
                    label.css('visibility', 'hidden');
                }
            });
            label.addClass(overClass).click(function () { input.focus() });

            if (input.val() != '') this.hide();
        }
    })
}
Run Code Online (Sandbox Code Playgroud)

我没有看到任何真正明显的东西,但也许我错过了一些东西.

以下是我记录错误的方法:

try {
    if (!handler.guid) {
          handler.guid = jQuery.guid++;
    }
}
catch (err) {
                var message = "handler.guid = jQuery.guid++ Error! \n";
                message += 'types: ' + types + '\n';
                if (typeof data != 'undefined') {
                    if (typeof data == 'object') {

                        $.each(data, function (i, v) {
                            message += i + ' : ' + v + '\n';
                        });
                    }
                    else {
                        message += 'elem id:' + $(elem).attr('id') + 'elem class: ' + $(elem).attr('class');
                    }
                }
                else {
                    message += 'data is undefined';
                }

                var url = window.location.href;
                var linenumber = 1579;
                v2LogTheErrorToElmah(message, url, linenumber, 0);

   }
Run Code Online (Sandbox Code Playgroud)

mac*_*ost 6

似乎问题很可能是一个不正确的事件处理程序,因为:

$('body').click(1);
Run Code Online (Sandbox Code Playgroud)

在IE中重现那个确切的错误.但是,如果没有看到所有代码,就无法找到特定错误.

我建议尝试的是你修改jQuery代码(暂时)以添加以下行:

if (typeof handler != 'function') {alert(handler); alert(type); alert(data); alert(this);}
Run Code Online (Sandbox Code Playgroud)

(如果这些还不够,可能会添加更多警报).

jQuery.each(["bind", "one"], function( i, name ) {在所有参数解析之后但在行之前,这应该进入内部var handler = name === "one" ? jQuery.proxy( fn, function( event ) {.对我来说这是第2324行,但对你来说可能有所不同.

一旦添加了这条线,你应该能够使用你的网站,当你做不好的事件联播(错误不断发生之前),你应该得到警报的攻势是(希望)告诉你什么地方出了错.

或者,最糟糕的情况是,如果你尝试这个并且找不到任何不良事件连接,至少你将能够将其排除为可能的问题原因.

  • 我不能用警报填写我的生产代码!你可以使用事件处理程序. (2认同)
  • 您当然也可以使用console.log,或者更好的是使用错误到服务器报告机制. (2认同)

Pat*_*cia 3

自从我问这个问题以来已经一年了,我已经放弃了。然后,我必须为新功能加载一些图片,然后我在我的开发环境中看到了这种情况!

正如我怀疑的那样,它是由jQuery.Jail 插件引起的,但无法证明。我有一个旧版本(0.9.5)。当我升级到 1.0 时,错误消失了。奇怪的是,即使发生错误,该插件也表现良好。

我不知道插件中到底是什么原因导致的。它handler实际上是 null,而不是GUID,所以这将解决我日志中的很多错误!

只是给其他人的提示,对于未来,如果你使用这个旧版本,你可能也在使用旧版本的 jQuery,所以当你切换到 1.0 版本时,它使用而.on不是.bind. 因此,请确保您有支持该功能的 jQuery 版本,或者只需编辑插件并将所有内容更改.on.bind.