我使用Prototype / Javascript来实现一个寻呼机小部件,该小部件在我的PHP网站上的搜索结果的详细视图之间移动。
要显示详细信息视图,浏览器会对后端PHP页面(在同一主机上)进行AJAX调用,该页面将详细信息作为JSON返回并在浏览器窗口中呈现。
我有两个触发此行为的函数:一个绑定到后退链接,一个绑定到前进链接。我遇到的问题是,虽然当我从转发链接触发行为时一切正常,但当我使用返回链接尝试时transport.responseText
为空,状态为0。
以下是进行AJAX调用的Javascript代码:
function displayCardDetails(cardid, index) {
openOverlay('View Card', 800, 500);
var url = 'php/card_service.php?action=getCardDetails&multiverseid='
+ cardid;
var transport = null;
new Ajax.Request(url, {
method : 'Get',
requestHeader : {
accept : 'application/json'
},
onSuccess : function(transport) {
if ($('transportFrame') != null) {
$('transportFrame').innerHTML = JSON.stringify(transport);
}
var response = transport.responseText.evalJSON(false);
if (response.status != 'Error') {
var card = response.data;
drawCardDetails(card);
drawDetailsPager(card, index);
} else {
setOverlayContent('<p><strong>Error: </strong>'
+ status.message + '</p>');
setOverlayTitle('Error');
}
}
});
}
正如您所看到的,我暂时将其请求/响应的详细信息写入我的UI中的调试窗口。
以下是transport
变量的JSON编码视图,两者都是相同的搜索结果。
第一个是从转发链接调用displayCard(212578, 2)
时:
{
"request" : {
"options" : {
"method" : "get",
"asynchronous" : true,
"contentType" : "application/x-www-form-urlencoded",
"encoding" : "UTF-8",
"parameters" : "",
"evalJSON" : true,
"evalJS" : true,
"requestHeader" : {
"accept" : "application/json"
}
},
"transport" : {
"statusText" : "OK",
"status" : 200,
"response" : "{\"status\":\"OK\",\"message\":\"Retrieved Card\",\"data\":{\"multiverseid\":212578,\"name\":\"A Display of My Dark Power\",\"layout\":\"Common\",\"rarity\":\"scheme\",\"setCode\":\"ARC\",\"setName\":\"Archenemy\",\"cardsInSet\":195,\"block\":null,\"releaseDate\":\"2010-06-18\",\"castables\":[{\"castableid\":null,\"name\":\"A Display of My Dark Power\",\"type\":\"Scheme\",\"manacost\":null,\"text\":\"When you set this scheme in motion, until your next turn, whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced.\",\"power\":\"0\",\"toughness\":\"0\",\"loyalty\":0,\"life\":0,\"hand\":0,\"artist\":\"Jim Nelson\",\"number\":\"8\",\"flavor\":\"\\\"What would you say is my greatest attribute? Is it my gluttonous lust for power?\\\"\"}]}}",
"responseType" : "",
"responseXML" : null,
"responseText" : "{\"status\":\"OK\",\"message\":\"Retrieved Card\",\"data\":{\"multiverseid\":212578,\"name\":\"A Display of My Dark Power\",\"layout\":\"Common\",\"rarity\":\"scheme\",\"setCode\":\"ARC\",\"setName\":\"Archenemy\",\"cardsInSet\":195,\"block\":null,\"releaseDate\":\"2010-06-18\",\"castables\":[{\"castableid\":null,\"name\":\"A Display of My Dark Power\",\"type\":\"Scheme\",\"manacost\":null,\"text\":\"When you set this scheme in motion, until your next turn, whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced.\",\"power\":\"0\",\"toughness\":\"0\",\"loyalty\":0,\"life\":0,\"hand\":0,\"artist\":\"Jim Nelson\",\"number\":\"8\",\"flavor\":\"\\\"What would you say is my greatest attribute? Is it my gluttonous lust for power?\\\"\"}]}}",
"upload" : {
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"withCredentials" : false,
"readyState" : 4,
"timeout" : 0,
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"url" : "php/card_service.php?action=getCardDetails&multiverseid=212578",
"method" : "get",
"parameters" : {},
"body" : null,
"_complete" : true
},
"transport" : {
"statusText" : "OK",
"status" : 200,
"response" : "{\"status\":\"OK\",\"message\":\"Retrieved Card\",\"data\":{\"multiverseid\":212578,\"name\":\"A Display of My Dark Power\",\"layout\":\"Common\",\"rarity\":\"scheme\",\"setCode\":\"ARC\",\"setName\":\"Archenemy\",\"cardsInSet\":195,\"block\":null,\"releaseDate\":\"2010-06-18\",\"castables\":[{\"castableid\":null,\"name\":\"A Display of My Dark Power\",\"type\":\"Scheme\",\"manacost\":null,\"text\":\"When you set this scheme in motion, until your next turn, whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced.\",\"power\":\"0\",\"toughness\":\"0\",\"loyalty\":0,\"life\":0,\"hand\":0,\"artist\":\"Jim Nelson\",\"number\":\"8\",\"flavor\":\"\\\"What would you say is my greatest attribute? Is it my gluttonous lust for power?\\\"\"}]}}",
"responseType" : "",
"responseXML" : null,
"responseText" : "{\"status\":\"OK\",\"message\":\"Retrieved Card\",\"data\":{\"multiverseid\":212578,\"name\":\"A Display of My Dark Power\",\"layout\":\"Common\",\"rarity\":\"scheme\",\"setCode\":\"ARC\",\"setName\":\"Archenemy\",\"cardsInSet\":195,\"block\":null,\"releaseDate\":\"2010-06-18\",\"castables\":[{\"castableid\":null,\"name\":\"A Display of My Dark Power\",\"type\":\"Scheme\",\"manacost\":null,\"text\":\"When you set this scheme in motion, until your next turn, whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced.\",\"power\":\"0\",\"toughness\":\"0\",\"loyalty\":0,\"life\":0,\"hand\":0,\"artist\":\"Jim Nelson\",\"number\":\"8\",\"flavor\":\"\\\"What would you say is my greatest attribute? Is it my gluttonous lust for power?\\\"\"}]}}",
"upload" : {
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"withCredentials" : false,
"readyState" : 4,
"timeout" : 0,
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"readyState" : 4,
"status" : 200,
"statusText" : "OK",
"responseText" : "{\"status\":\"OK\",\"message\":\"Retrieved Card\",\"data\":{\"multiverseid\":212578,\"name\":\"A Display of My Dark Power\",\"layout\":\"Common\",\"rarity\":\"scheme\",\"setCode\":\"ARC\",\"setName\":\"Archenemy\",\"cardsInSet\":195,\"block\":null,\"releaseDate\":\"2010-06-18\",\"castables\":[{\"castableid\":null,\"name\":\"A Display of My Dark Power\",\"type\":\"Scheme\",\"manacost\":null,\"text\":\"When you set this scheme in motion, until your next turn, whenever a player taps a land for mana, that player adds one mana to his or her mana pool of any type that land produced.\",\"power\":\"0\",\"toughness\":\"0\",\"loyalty\":0,\"life\":0,\"hand\":0,\"artist\":\"Jim Nelson\",\"number\":\"8\",\"flavor\":\"\\\"What would you say is my greatest attribute? Is it my gluttonous lust for power?\\\"\"}]}}",
"headerJSON" : null,
"responseXML" : null,
"responseJSON" : null
}
第二个是从后面链接调用displayCard(212578, 2)
时:
{
"request" : {
"options" : {
"method" : "get",
"asynchronous" : true,
"contentType" : "application/x-www-form-urlencoded",
"encoding" : "UTF-8",
"parameters" : "",
"evalJSON" : true,
"evalJS" : true,
"requestHeader" : {
"accept" : "application/json"
}
},
"transport" : {
"statusText" : "",
"status" : 0,
"response" : "",
"responseType" : "",
"responseXML" : null,
"responseText" : "",
"upload" : {
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"withCredentials" : false,
"readyState" : 4,
"timeout" : 0,
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"url" : "php/card_service.php?action=getCardDetails&multiverseid=212578",
"method" : "get",
"parameters" : {},
"body" : null,
"_complete" : true
},
"transport" : {
"statusText" : "",
"status" : 0,
"response" : "",
"responseType" : "",
"responseXML" : null,
"responseText" : "",
"upload" : {
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"withCredentials" : false,
"readyState" : 4,
"timeout" : 0,
"ontimeout" : null,
"onprogress" : null,
"onloadstart" : null,
"onloadend" : null,
"onload" : null,
"onerror" : null,
"onabort" : null
},
"readyState" : 4,
"status" : 0,
"statusText" : "",
"responseText" : "",
"headerJSON" : null,
"responseXML" : null,
"responseJSON" : null
}
我通过Diff运行这两个JSON转储,它发现的两个唯一区别在于响应文本和状态。从request.url
可以看出,在这两种情况下,用于调用后端PHP文件的URL都是相同的。当我从后退请求中复制URL并从浏览器手动调用它时,它会返回我期望的搜索结果。
奇怪的是,使用哪个链接进行通话似乎有所不同。将后退行为切换为转发链接会导致转发链接转到上一个结果。
绘制寻呼机的功能和分页的绑定功能是:
function drawDetailsPager(card, index) {
var foot = '';
index = parseInt(index);
var displayIndex = index
+ (searchResults ? searchResults.startResults + 1 : 1);
if ((displayIndex - 1) > 0) {
foot += '<a href="javacript:void(0)" id="cardDetailsPager_'
+ (index - 1) + '">Back</a>';
}
var totalResults = (searchResults ? searchResults.totalResults : 1);
foot += ' ';
foot += displayIndex + ' of ' + totalResults;
foot += ' ';
if (displayIndex < totalResults) {
foot += '<a href="javascript:void(0)" id="cardDetailsPager_'
+ (index + 1) + '">Forward</a>';
}
setOverlayFoot(foot);
// Set event handlers on forward / back arrows
if ($('cardDetailsPager_' + (index + 1)) != null) {
$('cardDetailsPager_' + (index + 1)).on('click', '', pageCardDisplay);
}
if ($('cardDetailsPager_' + (index - 1)) != null) {
$('cardDetailsPager_' + (index - 1)).on('click', '', pageCardDisplay);
}
}
function pageCardDisplay(event) {
var target = event.target || event.srcElement;
var linkId = target.id;
var indexExpr = /cardDetailsPager_([0-9]*)/m;
var match = indexExpr.exec(linkId);
if (match != null) {
var index = match[1];
var cardid = searchResults.cards[index].multiverseid;
displayCardDetails(cardid, index);
}
}
(对于混乱的道歉 - 我打算稍后再进行修改)
显然,这让我感到困惑。任何人都可以解释这个问题吗?感谢任何人都能给我的任何帮助:)
附录:这已在Google Chrome中进行了大量测试,在我的Windows 8笔记本电脑上的WAMP服务器上运行了PHP 5.4.16。我的生产服务器在Debian下运行PHP 5.3.27,并给出完全相同的结果。
更新
经过一些游戏后,似乎只有在displayCardDetails(cardid, index)
事件处理函数调用pageCardDisplay(event)
函数时才会出现错误。
寻呼机小部件现在按预期工作,drawDetailsPager(card, index)
功能改变如下:
function drawDetailsPager(card, index) {
var foot = '';
index = parseInt(index);
var displayIndex = index
+ (searchResults ? searchResults.startResults + 1 : 1);
if ((displayIndex - 1) > 0) {
var backIndex = index - 1;
var backId = searchResults.cards[backIndex].multiverseid;
foot += '<a href="javascript:void(displayCardDetails('
+ backId + ','
+ backIndex + '))"><</a>';
}
var totalResults = (searchResults ? searchResults.totalResults : 1);
foot += ' ';
foot += displayIndex + ' of ' + totalResults;
foot += ' ';
if (displayIndex < totalResults) {
var forwardIndex = index + 1;
var forwardId = searchResults.cards[forwardIndex].multiverseid;
foot += '<a href="javascript:void(displayCardDetails('
+ forwardId + ','
+ forwardIndex + '))">></a>';
}
setOverlayFoot(foot);
}
此版本的功能会删除事件处理程序,并将displayCardDetails(card, index)
的调用直接发送到后退 / 前进链接:例如<a href=javascript:void(displayCardDetails(212578,2))"><</a>
。
显然,这不是最优雅的解决方案 - 我仍然欢迎任何问题为什么从事件处理程序调用函数可能会导致问题。