这个错误不断出现在我的JavaScript错误记录中,在IE 7和8中。但是我无法在我的生活中重现它!
“guid”为null或不是对象
我正在使用jQuery 1.4.1,因此不是谷歌搜索中出现的.hover()
问题。
错误发生在这里(第1570行):
if (!handler.guid) {
handler.guid = jQuery.guid++;
}
它正在发生的页面真的非常复杂,对话框,ajax内容,标签,手风琴,你的名字,它就在那里。更糟糕的是,它是内部的,所以我不能给你们一个玩它的链接。
我不能做小提琴b / c我无法重现问题:(
我知道这是一个很长的镜头,当我能够做的时候,我更愿意为此付出赏金。
有没有人对我应该寻找什么来解决这个问题? 我也使用jquery Ui 1.8.11和各种插件。
编辑:这是抛出错误的jquery代码的较大部分。它是jquery事件的一部分。
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;
}
编辑: 我花了大约25分钟试图产生这个错误而没有运气。我正在打开和关闭标签(ajax加载),试图让它们在加载之前进行更改等等。还打开和关闭对话框(ajax加载)和做ajaxly添加和删除内容的事情。什么都不会破坏!
不确定这是否有用,但这是导致错误的用户代理字符串:
Mozilla / 4.0(兼容; 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)
这是另一个:
Mozilla / 4.0(兼容; 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(我们的javascript错误日志服务)似乎没有保留个人用户代理,所以我只有两个。
编辑: 我想我已将其缩小到我们的快速搜索范围。它使用jquery ui Auto Complete和jquery.jail(异步图像加载)。 我已经调整了jquery ui auto完成了一下。并且我正在使用HTML扩展程序。
以下是代码:
/*
* 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 ));
在这里您可以找到JAIL: https://github.com/sebarmeli/JAIL
我尝试通过快速输入,使用鼠标和箭头,点击,点击esc,hiting ctrl,tab,各种各样的东西来打破它。仍然没有打破。
编辑:我已经添加了250个代表奖金!必须有人在那里遇到过这个。
编辑:
我刚看到这个错误的版本略有不同,现在来自IE 9! 无法获取属性“guid”的值:object为null或undefined 与“guid”完全相同的行是null或不是对象。
所以,处理程序为null,或者jQuery为null。我将使用处理程序,因为如果jQuery为null,我还有很多其他问题。
所以这意味着,我正在尝试将一个guid附加到一个不存在的处理程序中。怎么可能呢?
编辑:
以下是设置自动完成小部件的代码:
<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>
也许它来自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();
}
})
}
我没有看到任何真正明显的东西,但也许我错过了一些东西。
以下是我记录错误的原因:
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);
}
答案 0 :(得分:6)
问题很可能是一个不正确的事件处理程序,因为:
$('body').click(1);
在IE中重现那个确切的错误。但是,如果没有看到所有代码,就无法找到具体的错误。
我建议尝试的是你修改jQuery代码(暂时)以添加以下行:
if (typeof handler != 'function') {alert(handler); alert(type); alert(data); alert(this);}
(如果那些还不够,可能会添加更多警报)。
在所有参数解析之后但在行jQuery.each(["bind", "one"], function( i, name ) {
之前,它应该进入var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
。对我来说这是2324行,但对你来说可能有所不同。
一旦你添加了这一行,你应该能够使用你的网站,当你做出错误的事件连接时(错误发生之前),你应该得到一连串警告(希望)告诉你出了什么问题
或者,最糟糕的情况是,如果你尝试这个并且找不到任何不良事件连接,至少你可以将其排除在外作为问题的可能原因。
答案 1 :(得分:3)
当我遇到像这样的奇怪错误时,我检查的快速可能性是为了确保jQuery不被多次包含。
如果您尝试了机器人建议的内容(修改jQuery源代码)并且您发现它没有记录,或者它在某个点停止记录那将是一个赠品。或者只是在Firebug / Chrome的网络分析器中查看您的http请求;)
一些基本原理:有时候这些事情会最终导致依赖性。例如,如果附加包含<script src="some_other_jquery"></script>
的标记片段。
将jQuery对象上的全局属性设置为null或以其他方式删除是很奇怪的。
下次重现错误时,您需要稍微检查一下jQuery对象。检查jQuery.guid(应该为null,但只是自己确认)。 jQuery.fn.jquery将为您提供jQuery库的版本号。
只是浏览了评论,看到你已经检查了这个。
答案 2 :(得分:3)
如何修补你的jQuery版本:
if (!handler.guid) {
handler.guid = jQuery.guid = (jQuery.guid||0) + 1;
}
代码是等效的,但与IE7更兼容。如果可以的话,我建议先尝试重现问题。但这应该可以防止它在将来发生。
答案 3 :(得分:2)
我问这个已经有一年了,我放弃了。然后,我不得不ajaxly加载一些图片的新功能和BAM我看到这发生在我的开发环境中!
这是由jQuery.Jail plugin造成的,正如我所怀疑但无法证明的那样。我有一个旧版本(0.9.5)。当我升级到1.0时,错误消失了。奇怪的是,即使发生错误,插件也会表现良好。
我不知道插件究竟是什么导致了它。 handler
实际上是空的,而不是GUID
,所以这将解决我在日志中出现的很多错误!
只是给其他人一个注释,对于未来,如果你使用这个旧版本,你可能也使用旧版本的jQuery,所以当你切换到1.0版本时,它使用.on
代替.bind
。所以请确保你有一个支持它的jQuery版本,或者只是编辑插件并将所有.on
更改为.bind
。
答案 4 :(得分:1)
更新
当然,这两个都是运行IE7的XP并且.NET库可以追溯的事实告诉我,他们并没有完全用气体做饭。我会尝试复制XP和IE7,但也会研究降低测试机器处理速度的工具。在9之前的IE中速度足够慢的情况下,您可能会遇到某种时间问题,其中某些不应该被假定为已准备好或已加载或可用的内容通常是在现代浏览器上但未能在旧版浏览器上准备就绪就像奔腾或386或TRS-80之类的东西。 IE7和今天的浏览器之间的速度差异(即使是仍然是现代最慢的IE9)也是惊人的。如果做不到这一点,那么在XP上的IE7是新的时代,将RAM大幅减少到我们正在使用的任何东西。所有的UI都在一个页面上飞来飞去,对于旧的Vista之前的机器而言可能太过分了。
糟糕。 NM。我之前在这里写过它是U-A字符串中的Windows NT但NT 5.1实际上是XP。尽管如此,尝试使用类似设置复制错误以匹配U-A可能会有所帮助。此外,我相信许多MS的其他应用程序的内置浏览器只是将IE7拼凑在一起并塞进一个窗格,因此它可能实际上不是IE7浏览器。我不知道如何制作所有这些.NET版本。我不会花很多时间分析U-A琴弦,但这似乎很多。
添加了问题:
我希望elem var尝试使用以下对jquery代码的修改来确定精确的上下文:
try{
if (!handler.guid) {
handler.guid = jQuery.guid++;
}
} catch(e){
var alertMsg = [];
alertMsg.push('GUID FAIL');
if(elem.id) { alertMsg.push('ID: ' + elem.id); }
if(elem.className) { alertMsg.push('CLASS: ' + elem.id); }
if(!elem.id && !elem.className){
alertMsg.push('CONSTRUCTOR: ' + elem.constructor.toString().match(/^[^(]*/));
}
alert(alertMsg.join('\n'));
}
如果这有助于您找出问题的确切来源,那么我会检查您传递给作为源的JQ方法的args。