返回首页 - Notes - 2018

跨 Frame 执行 JS 代码


需求描述

页面由多个 Frame 组成,需要在其中一个 Frame 中触发一段代码,实现在另一个 Frame 中弹出一个对话框

原本这事一个 alert 就可以解决,但 alert 会阻塞后续 JS 代码的执行,不满足需求

所以必须使用自定义的弹出框,不能阻塞后续的 JS 代码


代码示例

// 弹出不会阻塞 JS 进程的对话框
function show_message_box(message, url) {
    var iframe = top.document.getElementById('mainFrame').contentWindow;
    var body = iframe.document.getElementsByTagName('body')[0];

    // 已存在弹窗跳过
    if (iframe.document.getElementsByClassName('messagebox_overlay').length >= 1) {
        return false;
    }

    $.get('/messagebox/messagebox.min.css', function (css_content) {
        $.get('/messagebox/messagebox.min.js', function (js_content) {
            var css1 = document.createElement('style');
            css1.type = 'text/css';
            css1.innerText = css_content;
            body.appendChild(css1);

            var css2 = document.createElement('style');
            css2.type = 'text/css';
            css2.innerText = 'div.messagebox_content { font-weight: bold; color: red; }';
            body.appendChild(css2);

            var js1 = document.createElement('script');
            js1.type = 'text/javascript';
            js1.text = js_content;
            body.appendChild(js1);

            var js2 = document.createElement('script');
            js2.type = 'text/javascript';
            js2.text = '$.MessageBox({buttonDone: \'确定\', buttonFail: \'取消\', message: \'' + message + '\'})' +
                '.done(function () { top.document.getElementById(\'mainFrame\').src = \'' + url + '\' })' +
                '.fail(function () {})';
            body.appendChild(js2);
        });
    });
}

// 轮询获取最新消息
function get_last_message () {
    $.getJSON('xyz.php?action=get_last_message', function (data) {
        if (data.length == 0) {
            return false;
        }

        var url = 'xyz.php?id=' + data.id;
        show_message_box('您有新的消息,是否立即跳转查看?', url);
    });
}

setInterval('get_last_message()', 10000);  // 每10秒轮询一次

代码解读

mainFrame 就是想要弹出内容的目标 Frame,上述代码放置在想要触发效果的另一个 Frame 中,弹出框将在 mainFrame 的区域呈现

这里使用了一个名为 messageboxjquery 插件,其中 messagebox.min.js 的顶部我已经集成了 jquery 的代码

这里需要注意的是,一定要先将弹出框所需的 cssjs 文件加载进来,文件加载到位后再用 appendChildcssjs 文件的文本内容插入目标 Frame

如果插入的不是文本内容,而是一个 cssjs 文件的 URL,则这些文件并不会真正加载


date:2018-12-09