Вставить функцию javascript в iframe
Эта ссылка (заархивированная версия) описывает как ввести код из script в iframe:
function injectJS() {
var iFrameHead = window.frames["myiframe"].document.getElementsByTagName("head")[0];
var myscript = document.createElement('script');
myscript.type = 'text/javascript';
myscript.src = 'myscript.js'; // replace this with your SCRIPT
iFrameHead.appendChild(myscript);
}
Это нормально, но что, если я хочу вставить объект функции в iframe и выполнить его в контексте iframe? Скажем, у меня есть:
function foo () {
console.log ("Look at me, executed inside an iframe!", window);
}
и я хочу вставить foo-код внутри iframe? (функция foo может быть динамически загружена, я не могу просто ее обернуть в кавычки)
Я наивно пробовал:
var scriptFooString = "<script>" + foo.toString() + "</script>"
чтобы получить код внутри функции, но
- Я не знаю, как вставить его в iframe HEAD (возможно, с jquery?)
- Я не знаю, правильно ли это.
- Я не знаю, что произойдет, если функция намного сложнее, чем
- Я не знаю, что происходит с двойными и одинарными кавычками в
scriptFooString
Любые подсказки?
Ответы
Ответ 1
Прежде всего, вы можете выполнить это только в том случае, если ваш фрейм и страница, отображающая его, находятся в одном домене (из-за правил междоменного доступа)
во-вторых, вы можете манипулировать объектами dom и window фрейма непосредственно через JS:
frames[0].window.foo = function(){
console.log ("Look at me, executed inside an iframe!", window);
}
чтобы получить кадр из объекта DOMElement, который вы можете использовать:
var myFrame = document.getElementById('myFrame');
myFrame.contentWindow.foo = function(){
console.log ("Look at me, executed inside an iframe!");
}
Обратите внимание, что область в foo не изменяется, поэтому окно все еще является родительским окном и т.д. внутри foo.
Если вы хотите ввести некоторый код, который должен быть запущен в контексте другого фрейма, вы можете вставить тег script или eval it:
frames[0].window.eval('function foo(){ console.log("Im in a frame",window); }');
Хотя общий консенсус заключается в том, чтобы никогда не использовать eval, я считаю его лучшей альтернативой, чем инъекция DOM, если вам действительно нужно выполнить это.
Итак, в вашем конкретном случае вы можете сделать что-то вроде:
frames[0].window.eval(foo.toString());
Ответ 2
Вот мое решение. Я использую jquery для вставки содержимого, а затем используя eval для выполнения тегов script в контексте этого iframe:
var content = $($.parseHTML(source, document, true));
$("#content").contents().find("html").html(content);
var cw = document.getElementById("content").contentWindow;
[].forEach.call(cw.document.querySelectorAll("script"), function (el, idx) {
cw.eval(el.textContent);
});