Javascript iframe 中的后退和前进按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3254985/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 03:53:53  来源:igfitidea点击:

Back and forward buttons in an iframe

javascriptiframe

提问by randomwebdev

How to "implement" back and forward buttons in an iframe with JS?

如何使用 JS 在 iframe 中“实现”后退和前进按钮?

回答by Andy E

Use the window.historyobject.

使用window.history对象。

// For the current window
window.history.back();     
window.history.forward();

// For an iframe's window
iframe.contentWindow.history.back(); 
iframe.contentWindow.history.forward();

or

或者

iframe.contentWindow.history.go(-1); // back
iframe.contentWindow.history.go(1);  // forward

https://developer.mozilla.org/en/dom/window.history

https://developer.mozilla.org/en/dom/window.history

回答by Adam Leggett

Update for 2017: There is no way whatsoever to do this if the origin of the iframe content is different from the origin of the enclosing page - unless you control the content at the remote origin and can have it accept postMessageevents. If the origin is the same, the older answers still work.

2017 年更新:如果 iframe 内容的来源与封闭页面的来源不同,则无法执行此操作 - 除非您控制远程来源的内容并且可以让它接受postMessage事件。如果来源相同,则较旧的答案仍然有效。

If this is in a WebView within an application you control, you can also set up a hook native side to control this.

如果这是在您控制的应用程序中的 WebView 中,您还可以设置一个钩子本机端来控制它。

回答by Pavel Strakhov

Button within frame:

框架内的按钮:

<input type="button" value="Back" onclick="history.back()">

Button within parent frame:

父框架内的按钮:

<input type="button" value="Back" onclick="frame_name.history.back()">

回答by frr

Thanks everybody for your valuable pointers :-) I've managed to start from your suggestions and build on them a little further.

感谢大家的宝贵意见:-) 我已经设法从你的建议开始,并在它们的基础上进一步发展。

I have a webpage that has two vertical frames: a narrow column on the left for a menu bar (frame name="menu"), and a main window on the right (frame name="main"), spanning most of the width. I.e., the index.htm contains just a frameset across the whole surface. Now... to address the general "back" navigation problem in my simple frameset, I managed to use Pavel Strakhov's suggestion with input type=button - only I had to elaborate the DOM path a little further. As I have the button in the "menu" frame on the left, and the content to be navigated happens in the "main" frame on the right, the two frames are siblings, rather than a parent vs. child. Thus, in my case, I had to traverse one level up in the hierarchy, before I was able to refer to the sibling frame. As a result, in my case the button element reads

我有一个包含两个垂直框架的网页:左侧的窄列用于菜单栏(框架名称 =“菜单”),右侧有一个主窗口(框架名称 =“主”),跨越大部分宽度. 即,index.htm 只包含一个跨越整个表面的框架集。现在...为了解决我的简单框架集中的一般“后退”导航问题,我设法将 Pavel Strakhov 的建议与 input type=button 结合使用——只是我必须进一步详细说明 DOM 路径。由于我在左侧的“菜单”框架中有按钮,而要导航的内容发生在右侧的“主”框架中,因此这两个框架是兄弟姐妹,而不是父级与子级。因此,就我而言,在能够引用同级框架之前,我必须遍历层次结构中的上一层。其结果,

<input type="button" value="Back in the main frame" onclick="window.parent.main.history.back()">

or you can refer to the frame by ordinal index (zero-based) in an array, rather than by name:

或者您可以通过数组中的序数索引(从零开始)而不是名称来引用框架:

<input type="button" value="Back in the main frame" onclick="window.parent.frames[1].history.back()">

I have also noticed that the whole 'onclick' property can be strapped onto pretty much any other visible element, such as an anchor/href (A), a DIV or a P. I've tried those as well, to make the "back" button look more like the rest of my menu, but ultimately went back to the crude "buttonish" look and behavior, to make the button more obvious / prominent / distinct. It looks raw but it works best.

我还注意到整个 'onclick' 属性几乎可以绑定到任何其他可见元素上,例如锚点/href (A)、DIV 或 P。我也尝试过这些元素,以制作“ “后退”按钮看起来更像我菜单的其余部分,但最终又回到了原始的“按钮式”外观和行为,使按钮更加明显/突出/清晰。它看起来很原始,但效果最好。

Actually in my case, windows.parentactually refers to the top frame - so there's another way to refer to my frame called "main" and tell it to go back: onclick="top.main.history.back()". Or, apparently, onclick="top.frames['main'].history.back()".

实际上在我的情况下,windows.parent实际上是指顶部框架 - 所以还有另一种方式来指代我的框架,称为“main”并告诉它返回:onclick="top.main.history.back()". 或者,显然,onclick="top.frames['main'].history.back()"

And then I found out, that it still doesn't work reliably. Quirks discovered so far:

然后我发现,它仍然不能可靠地工作。到目前为止发现的怪癖:

  • in Firefox around v42, if you go back and then use the browser's "forward" button, several more URL clicks down the road you can get funny results: sometimes the history.back() function in a frame will result in a history.back() on the top frame, for no apparent reason.

  • in Firefox around v42, sometimes the browser's own "back" button results in per-frame history.back(), rather than a top-frame history.back(), for no apparent reason (= inconsistent behavior of the native "back" button)

  • regardless of the browser make and version, some websites apparently clear the history of their base frame on site load. If you load such a site in a frame, the per-frame history.back() does nothing.

  • 在 v42 左右的 Firefox 中,如果你返回然后使用浏览器的“前进”按钮,在此过程中再点击几次 URL 你会得到有趣的结果:有时框架中的 history.back() 函数会导致 history.back () 在顶部框架上,没有明显的原因。

  • 在 Firefox v42 左右,有时浏览器自己的“后退”按钮会导致每帧 history.back(),而不是顶帧 history.back(),没有明显的原因(= 本地“后退”的不一致行为按钮)

  • 无论浏览器品牌和版本如何,一些网站显然会在网站加载时清除其基础框架的历史记录。如果您在框架中加载这样的站点,则每帧 history.back() 不会执行任何操作。

This is possibly another reason (apart from homogeneous styling) why hardly anyone uses the good old HTML frames anymore. The resulting behaviors are not very deterministic / foreseeable / obvious to the user. This is probably why webmasters prefer fixed columns, implemented by tables or by more modern means. Or perhaps it's just because everyone uses a CMS nowadays anyway.

这可能是另一个原因(除了同质样式)为什么几乎没有人使用旧的 HTML 框架了。由此产生的行为对用户来说不是很确定/可预见/显而易见。这可能就是网站管理员更喜欢固定列的原因,这些列由表格或更现代的方式实现。或者也许只是因为现在每个人都在使用 CMS。

回答by www-0av-Com

As others have mentioned, this is a major issue these days due to seemingly flawed security changes. In particular, as "mrec" says in a comment prior, The ugly problem here is that when your iframe is already at the start of its own history - and there's no way to detect this condition in script - doing another back() will effectively trigger a back() on the containing page instead, which is almost certainly not what you want.-- indeed, this was an insurmountable issue for me.

正如其他人所提到的,由于看似有缺陷的安全更改,这是当今的一个主要问题。特别是,正如“mrec”在之前的评论中所说,这里的丑陋问题是,当您的 iframe 已经处于其自身历史记录的开始时 - 并且无法在脚本中检测到这种情况 - 执行另一个 back() 将有效相反,在包含页面上触发 back() ,这几乎肯定不是您想要的。——的确,这对我来说是一个无法解决的问题。

This solution is a testedversion of the solution mentioned by responses here, whereby history is handled manually and the user cannot traverse back before history started. It was used in http://www.0AV.comfor inline help and has been simplified here which may have introduced errorsto the otherwise tested version. It will also likely need some refinement for your requirement.

此解决方案是此处响应中提到的解决方案的测试版本,其中历史记录是手动处理的,用户无法在历史记录开始之前返回。它在http://www.0AV.com 中用于在线帮助,并在此处进行了简化,这可能会给其他测试版本带来错误。它也可能需要根据您的要求进行一些改进。

JS in the host page..

主机页面中的 JS ..

var Hstory = [], sorc = '';

window.onmessage = function(e){ //# message fired by iFrame with onmousedown="window.top.postMessage('...','*');" or etc.
    var hilitedCrefText = e.data;    
    switch(String(hilitedCrefText)){
        case "Help_Home": //# defined in iframe
            sorc = "/index.html"; //# eg
            HistryManager(sorc); //# store
            break;
        case "Help_Back": //# defined in iframe
            sorc = HistryManager(); //# retrieve
            break;
        default: //# anything else that is generated by a link.
            HistryManager(sorc);
    }    
    if( sorc.length > 0 ) document.getElementById('your_iframe_id').src = sorc;  
}


function HistryManager(toPush) { //# history_handler
    if (toPush != undefined) {
        Hstory.push(toPush);
    }else{
        if( Hstory.length > 1 ){
            var az = Hstory[Hstory.length-2]; //..
            //# -2 is: -1 as is base 1, + -1 as it just stored this location, so must go back to PRIOR locastion.
            Hstory = Hstory.slice(0, -1); // Reduce array (Use neg num to select from end of array)
            return az;
        }else{
            alert('End of history. \n\n(Can not go further Back).');
            return '';
        }
    }
} 

JS / HTML in the iframe page..

iframe 页面中的 JS / HTML ..

    <button onclick="window.top.postMessage('Help_Back','*');">Back</button>
    <button onclick="window.top.postMessage('Help_Home','*');">Home</button>

    <button onclick="window.top.postMessage('helppage1.html','*');">HelpOn1</button>
    <button onclick="window.top.postMessage('helppage2.html','*');">HelpOn2</button>

..last 2 are examples of links user can traverse into (and add to history), in this case as buttons, but easily changed to anchors.

..last 2 是用户可以遍历(并添加到历史记录)的链接示例,在本例中为按钮,但很容易更改为锚点。

Hope that helps someone. (Tip: I misspelled some of my vars to prevent confusion with system vars). Code is an addition to Codiad, and as such is MIT License.

希望能帮助某人。(提示:我拼错了一些变量以防止与系统变量混淆)。代码是 Codiad 的补充,因此是 MIT 许可证。