我正在为我们的几个网站添加聊天功能。聊天会将用户与我们服务台的人员联系起来,以帮助他们使用这些网站。我们的服务台人员希望聊天窗口看起来像页面侧面的标签并滑出,而不是在新窗口中弹出。但是,我希望允许用户在不丢失聊天的情况下浏览网站。
为此,我一直尝试在聊天开始后将整个页面移动到iframe(使用iframe外的聊天),这样用户就可以在iframe中浏览网站而不会丢失聊天。< / p>
我使用this answer开始,这在视觉上很有效。但是,后台的一些javascript会中断。
其中一个站点是ASP.NET Web表单。另一个是MVC。我一直在使用网络表单。一旦页面被移动到iframe中,就像调用__doPostBack一样,因为javascript上下文被遗忘了。
一旦用户点击了一个链接(一个真实的链接,而不是一个__doPostBack)并且iframe刷新,那么一切都运行良好。
我怎么看,我有几个选择:
this.contentWindow.__doPostBack = window.top.__doPostBack
,但是其他变量都没有了,所以最终失败了:这些网站仅供我们的员工使用,因此我只需支持IE11和Chrome。
更新
感谢LGSon将我置于使用目标属性的轨道上(所以我可以使用方法#3)。以下是我最终做的事情。当我弹出聊天时,我打电话给loadNextPageInIframe()
。我在这里使用jQuery,因为我们已经在我们的网站上使用它,但一切都可以在没有的情况下完成。我在所有尚未将目标指向另一个框架或_blank的链接上设置目标。我离开了_parent,但我认为无论如何我都不会使用它。
我在一个名为“chatwindow”的全局变量中引用了我的聊天窗口div。
在某些情况下仍然可能无效,例如是否有一些javascript直接设置window.location。如果我们的网站中有任何内容可以执行此操作,我将不得不添加一种方法来处理它。
function loadNextPageInIframe() {
var frame = $("<iframe id=\"mainframe\" name=\"mainframe\" />").css({
position: "fixed",
top: 0,
left: 0,
width: "100%",
height: "100%",
border: "none",
display: "none"
}).appendTo("body");
$("form, a:not([target]), a[target=''], a[target='_top'], a[target='_self']").attr("target", "mainframe");
var firstload = true;
frame.load(function () {
//Runs every time a new page in the iframe loads
if (firstload) {
$(frame).show();
//Remove all elements from the top window except the iframe and chat window
$("body").children().not(frame).not(window.top.chatwindow).remove();
firstload = false;
}
//Make the browser URL and title reflect the iframe every time it loads a new page
if (this.contentWindow && this.contentWindow.location.href && window.top.location.hostname === this.contentWindow.location.hostname && window.top.location.href !== this.contentWindow.location.href) {
var title = this.contentDocument.title;
document.title = title;
if (window.top.history.replaceState) window.top.history.replaceState(null, title, this.contentWindow.location.href);
}
});
}
答案 0 :(得分:2)
我建议您执行以下操作
var links = querySelectorAll("a");
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(e) {
if (isChatInProgress()) {
e.preventDefault(); //stop the default action
document.getElementById("your_iframe_id").src = e.target.href;
// anything else here, like toggle tabs etc
}
});
}
<强>更新强>
为了处理表格,我现在看到了4种方式
1)在表单中添加一个onsubmit处理程序
function formIsSubmitted(frm) {
if (isChatInProgress()) {
frm.target = "the iframe";
}
return true;
}
<form id="form1" runat="server" onsubmit="return formIsSubmitted(this)">
2)在按钮上添加点击处理程序
function btnClick(btn) {
if (isChatInProgress()) {
btn.form.target = "the iframe";
}
return true;
}
<asp:Button runat="server" ID="ButtonID" Text="ButtonText"
OnClick="Button_Click" OnClientClick="return btnClick(this);" />
3)当聊天开始时,您遍历每个表单并更改其目标属性
function startChat() {
var forms = querySelectorAll("form");
for (var i = 0; i < forms.length; i++) {
forms[i].target = "the iframe";
});
}
4)覆盖原始回发事件(Src:intercept-postback-event)
// get reference to original postback method before we override it
var __doPostBackOriginal = __doPostBack;
// override
__doPostBack = function (eventTarget, eventArgument) {
if (isChatInProgress()) {
theForm.target = "the iframe";
}
// call original postback
__doPostBackOriginal.call(this, eventTarget, eventArgument);
}
更新2
处理此问题的最佳方法当然是使用AJAX加载页面和聊天内容,但如果您的网站尚未使用它,这可能意味着更大的工作量。
如果您不想这样做,您仍然可以使用AJAX进行聊天,如果用户要导航到新页面,聊天应用会重新创建正在进行的聊天窗口及其所有内容。
答案 1 :(得分:1)
我建议不要在iframe中加载内容 - 将聊天内容构建为iframe,并在页面上使用jQuery模式弹出窗口进行聊天。
您可以将jquery模式修复到固定位置,默认情况下启用页面滚动。您需要相应地修改css以使弹出窗口保持在同一位置。
如果您沿着当前路径走下去 - 您将需要担心内容如何移动到iframe,并且可能很难根据内容在不同页面上重新使用聊天。例如,假设您在页面上播放视频并且用户单击聊天 - 如果您将内容加载到iframe - 用户将失去他查看的内容的状态等。
答案 2 :(得分:0)
根据我的观点,将整个网站添加为“I-Frame”并不是一个好的设计实践,也不是解决问题的好方法。我的建议是:
这将确保您的聊天对用户可用,但他可以浏览整个网站。