将整个文稿移动到 iframe 中
Move entire document into iframe
我正在为我们的几个网站添加聊天功能。聊天会将用户与我们帮助台的人员联系起来,以帮助他们使用网站。我们的帮助台人员希望聊天窗口看起来像页面侧面的选项卡并滑出,而不是在新窗口中弹出。但是,我希望允许用户在不丢失聊天的情况下浏览网站。
为此,我一直在尝试在聊天开始后将整个页面移动到 iframe 中(聊天在 iframe 之外),以便用户可以在 iframe 内浏览网站而不会丢失聊天。
我用这个答案开始了,这在视觉上效果很好。但是,后台的一些 JavaScript 会中断。
其中一个站点是 ASP.NET 网络表单。另一个是MVC。我一直在首先使用网络表单。一旦页面移动到 iframe 中,调用__doPostBack之类的东西就会中断,因为 javascript 上下文被留下了。
一旦用户单击链接(真正的链接,而不是__doPostBack)并且 iframe 刷新,那么一切都会完美运行。
我怎么看,我有几个选择:
- 以某种方式将所有 javascript 变量从 window.top 复制到 iframe 中。希望不必知道所有变量名称。我尝试了
this.contentWindow.__doPostBack = window.top.__doPostBack
,它有效,但缺少其他变量,因此最终失败: - 以某种方式切换 iframe 的上下文以查看顶部窗口上下文,如果可能的话?应该不会。
- 另一个想法是不要立即将页面移动到 iframe 中,而是等到页面更改,然后将新页面加载到新的 iframe 中。但我不确定如何挂钩并劫持它。
- 别的?
这些网站仅供我们的员工使用,所以我只需要支持 IE11 和 Chrome。
更新:
感谢 LGSon 让我走上使用目标属性的轨道(所以我可以使用方法 #3)。以下是我最终所做的。当我弹出聊天时,我会打电话给loadNextPageInIframe()
。我在这里使用 jQuery,因为我们已经在我们的网站上使用它,但一切都可以不用。我在所有没有指向另一个帧或_blank的目标的链接上设置目标。我省略了_parent,但我认为我们无论如何都不会使用它。
我在一个名为"聊天窗口"的全局变量中引用了我的聊天窗口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);
}
});
}
我可以建议你执行以下操作
吗- 获取所有链接
- 附加事件单击处理程序,以便在有人单击链接时进行拦截
- 在点击事件中,检查聊天是否正在进行中,如果向 iframe 提供新链接
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) 在表单中添加提交处理程序
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) 覆盖原始回发事件(来源:拦截回发事件)
// 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 进行聊天,如果用户要导航到新页面,聊天应用程序会再次使用其所有内容重新创建正在进行的聊天窗口。
我建议不要在 iframe 中加载内容 - 将聊天构建为 iframe 并在页面上使用 jQuery 模式弹出窗口进行聊天。
您可以将 jquery 模式固定为固定位置,并且默认情况下启用页面滚动。您需要相应地修改 css 以使弹出窗口保留在同一位置。
如果您沿着当前的道路走下去 - 您将需要非常担心如何将内容移动到 iframe,并且可能很难根据内容在不同页面上重复使用聊天。例如,假设您在页面上播放视频,并且用户单击聊天 - 如果您将内容加载到 iframe - 用户将失去他查看了多远的状态,等等。
,将整个网站添加为"I-Frame"不是一个好的设计实践,也不是解决问题的好方法。我的建议是:
- 确保"聊天"应用程序已加载到您网站的所有页面中
- 每当"聊天"启动时,要么建立"web-socket"连接,要么以某种方式维护服务器上的状态
- 将"聊天"配置为"最小化","打开"等,并将它们存储在您的cookie或会话存储中
- 在每次页面加载时,也调用"聊天"应用程序。从会话存储或cookie中读取与聊天相关的配置,并将其状态维护为"最小化"或"打开"等,包括X和Y位置,如果您想将其设置为"浮动" 每次,要么通过Ajax从
- 服务器获取整个对话,要么尝试从"本地存储"中存储和获取,并且仅对来自另一方的任何更新执行Ajax操作
- 使用基于 CSS 的"Float"相关属性使其浮动并位于某个侧面。
这将确保您的聊天可供用户使用,但他可以浏览整个网站。
- 当#在iFrame中使用HTML时,阻止页面移动
- 如何让iframe在设置负上边距后填充整个移动网页
- Iframe|youtube Iframe上的移动后退按钮
- 在移动应用程序上滚动iframe会在某个时刻跳到页面顶部
- 如何检测Facebook Javascript SDK'的移动iframe
- 阻止iframe加载到移动设备上
- 移动设备上的 iFrame 重定向主页问题
- 需要 iFrame 在滚动页面的其他部分时不移动
- 将整个文稿移动到 iframe 中
- 强制 iFrame 作为移动设备
- 如何在单击 iframe 中的按钮后将整个浏览器窗口移动到另一个页面
- YouTube 360 视频 iframe 在移动浏览器中不起作用
- 移动版 Chrome 上的 IFrame 播放器 API
- iframe关于光标移动问题的设计模式
- 使用jquery在dom中移动嵌入的youtube iframe会导致全屏无法在Windows8 IE10中工作
- 将整个文档移动到iframe中
- 如何在通过iFrame提交表单后更改当前url以移动到其原始url
- 在移动safari中按下后退按钮后,Javascript将停止在iframe中执行
- 如何检测iframe是否已从一个URL移动到另一个URL
- 修复了移动应用程序iframe中的底部页脚