我对任何AJAX都很陌生并遇到了以下问题。我希望有人能够帮助我。我确定这是一个简单的修复,但我只是没有看到它:(
我要做的是动态更改元素的onmouseover和onmouseout事件,这里是相关的代码位:
HTML元素(请注意其中有多个,因此是其ID的动态部分)
<?
if (ownsgame($id, $userid)) {?>
<a><img src="images/collection/got.gif" id="ownedimage<?=$id?>" title="<?=$itemtitle?> (<?=$platformdisplay?>) is in your collection" alt="You own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/del.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/got.gif')"/></a>
<? } else { ?>
<a><img src="images/collection/add.gif" id="ownedimage<?=$id?>" title="Add <?=$itemtitle?> (<?=$platformdisplay?>) to your collection" alt="You do not own this game" align="center" width="62" height="22" onclick="changeOwned('<?=$id?>')" onmouseover="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')" onmouseout="changeImageSrc('ownedimage<?=$id?>', 'images/collection/add.gif')"/></a>
<?} ?>
JavaScript函数:
function changeImageSrc(id, src) {
document.getElementById(id).src = src;
}
(相关)AJAX代码:
var http = createRequestObject();
var jsid = "";
function changeOwned(id) {
http.open('get', 'changeowned.php?id=' + id + '&user=<?=$userid?>');
jsid = id;
http.onreadystatechange = processResponse;
http.send(null);
}
function processResponse() {
if((http.readyState == 4) && (http.status == 200)){
var response = http.responseText;
var elementid = 'ownedimage' + jsid;
var element = document.getElementById(elementid);
if (response == "1") {
image = "images/collection/got.gif";
alt = "you own this game";
mouseoverstr = 'images/collection/del.gif';
mouseoutstr = 'images/collection/got.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/add.gif')}, false);
} else {
image = "images/collection/add.gif";
alt = "add this game to your collection";
mouseoverstr = 'images/collection/add.gif';
mouseoutstr = 'images/collection/add.gif';
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
element.removeEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/del.gif')}, false);
}
element.src = image;
element.alt = alt;
element.addEventListener('mouseover', function(){changeImageSrc('ownedimage' + jsid, mouseoverstr)}, false);
element.addEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, mouseoutstr)}, false);
}
}
一开始似乎工作正常,但会产生一些奇怪的行为。引用的PHP工作正常并产生正确的响应。图像的src和alt也会发生变化。事实上,它首先看起来像新的鼠标悬停/外出工作。但是,当您点击网站上的多个图像(具有不同的ID)时,它们会突然开始相互影响。当鼠标悬停在一个上时,另一个会更改其图像。为什么会这样?我真的很无能,因为jsid部分很好,我不明白为什么mouseover会突然改变两个图像。看起来好像将不同ID的多个事件处理程序分配给同一个图像元素。不知道为什么会这样。我希望有一些掌握更多AJAX知识的人可以帮助我,非常沮丧:(
答案 0 :(得分:2)
那里有几件事: - )
1)addEventListener
和removeEventListener
使用较新的DOM2处理程序链,它与旧的“DOM0”样式(onXYZ
属性)完全分开。因此,您无法通过最初通过removeEventListener
attriubte分配的onXYZ
删除处理程序。为此,请为属性的反射属性指定“”。
element.onmouseover = "";
2)当您使用removeEventListener
时,您必须传入您最初使用的相同的函数引用。所以这永远不会删除任何东西:
element.removeEventListener('mouseout', function(){changeImageSrc('ownedimage' + jsid, 'images/collection/got.gif')}, false);
...因为它创建了一个全新的函数来传递给removeEventListener
,并且因为该函数不在事件处理程序链上,所以忽略了调用。
我可能通过使用单个事件处理程序来解决问题,但随后更改它使用的数据。您可以使用data-xyz
属性(例如data-oversrc
和data-stdsrc
或其他类似内容)将备用图片网址存储在实际元素本身上。然后你的两个函数(一个用于mouseover,一个用于mouseout)根据图像更改URL:
function handleMouseOver() {
this.src = this.getAttribute('data-oversrc');
}
function handleMouseOut() {
this.src = this.getAttribute('data-stdsrc');
}
我会完全从元素中删除onXYZ
个处理程序,并将它们替换为一次性addEventListener
(IE上为attachEvent
),并分配这两个。
data-xyz
属性在HTML4及更早版本中无效。从HTML5开始,他们会进行验证,因为无论如何主要浏览器都无法解决无效属性问题,您可以立即开始使用它们。
偏离主题#1 :现在,我通常建议您使用JavaScript库来平滑浏览器差异并为您实现有用的功能。例如,使用addEventListener
和removeEventListener
的代码在IE9之前的IE上会失败,因为它根本就没有这些方法。如果您使用的是jQuery,Prototype,YUI,Closure或any of several others等库,他们会为您处理这些内容,以便您可以专注在你自己的增值上。
偏离主题#2 :当鼠标经过元素时,mouseover
事件会重复发生,并且mouseout
和/ mouseenter
都会在DOM中冒泡。这意味着对于像你这样的悬停效果,如果你不能使用CSS(你不能在IE6上),你最好使用mouseleave
和mouseenter
事件,大部分时间。但这些是大多数其他浏览器不支持的IE特定事件。输入任何体面的JavaScript库。 :-)他们会在不直接支持它们的浏览器上模仿mouseleave
和{{1}}。在上面的列表中,我确信jQuery和Prototype可以做到这一点;如果其他人没有类似的功能,我会感到惊讶。
答案 1 :(得分:2)
问题是removeEventListener
,它不像您认为的那样工作。当你这样做时发生了什么:
element.removeEventListener('mouseout',function(){/* handlers */},false);
function() { }
是您刚刚创建的新匿名函数,而不是作为侦听器的元素上的现有函数...所以当它去除时> em> listener,它只是不存在,因为那是一个不同的匿名函数(即使它具有完全相同的代码,它是一个不同的引用),您通过addEventListener
分配。
有一些解决办法,因为你正在制作AJAX请求我假设你没有在这里制作数百/数千,所以你可以存储你指定的处理程序以便以后删除它们,比如这样:
var http = createRequestObject();
var jsid = "";
var handlers = {};
function changeOwned(id) {
http.open('get', 'changeowned.php?id=' + id + '&user=<?=$userid?>');
jsid = id;
http.onreadystatechange = processResponse;
http.send(null);
}
function processResponse() {
if((http.readyState == 4) && (http.status == 200)){
var response = http.responseText,
elementid = 'ownedimage' + jsid,
element = document.getElementById(elementid),
image, alt, mouseoverstr, mouseoutstr;
if (response == "1") {
element.src = "images/collection/got.gif";
element.alt = "you own this game";
mouseoverstr = 'images/collection/del.gif';
mouseoutstr = 'images/collection/got.gif';
} else {
element.src = "images/collection/add.gif";
element.alt = "add this game to your collection";
mouseoverstr = 'images/collection/add.gif';
mouseoutstr = 'images/collection/add.gif';
}
//Create a holder if this is the first time for this elementid
if(!handlers[elementid]) handlers[elementid] = {};
//Remove old handlers
element.removeEventListener('mouseover', handers[elementid].mouseover, false);
element.removeEventListener('mouseout', handers[elementid].mouseout, false);
//Store new handlers
handlers[elementid].mouseover = function(){changeImageSrc('ownedimage' + jsid, mouseoverstr)};
handlers[elementid].mouseout = function(){changeImageSrc('ownedimage' + jsid, mouseoutstr)};
//Add hew handlers as listeners
element.addEventListener('mouseover', handers[elementid].mouseover, false);
element.addEventListener('mouseout', handers[elementid].mouseout, false);
}
}