2013-04-24 24 views
22

This link (archived version) mô tả cách tiêm mã từ một kịch bản vào iframe:tiêm một hàm javascript vào 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); 
} 

Đó là ok, nhưng những gì nếu tôi muốn chèn một đối tượng hàm vào iframe và làm cho nó được thực thi trong ngữ cảnh iframe? Giả sử tôi có:

function foo() { 
    console.log ("Look at me, executed inside an iframe!", window); 
} 

và tôi muốn chèn mã của foo vào khung nội tuyến? (chức năng foo có thể được một cái gì đó nạp tự động, tôi không thể chỉ quấn nó trong dấu ngoặc kép)

Tôi ngây thơ thử:

var scriptFooString = "<script>" + foo.toString() + "</script>"

để lấy mã bên trong hàm, nhưng

  • Tôi không biết cách chèn nó vào HEAD khung nội tuyến (có thể với jquery?)
  • Tôi không biết đó có phải là cách thích hợp không
  • Tôi không biết những gì sẽ xảy ra khi nếu chức năng là phức tạp hơn cách mà
  • Tôi không biết điều gì xảy ra với dấu ngoặc kép và duy nhất trong scriptFooString

Bất kỳ gợi ý?

Trả lời

22

Trước hết bạn chỉ có thể thực hiện điều này nếu khung hình của bạn và trang web hiển thị nó nằm trong cùng một tên miền (Do quy tắc cross-domain)

thứ hai bạn có thể thao tác dom và cửa sổ đối tượng của khung trực tiếp thông qua JS:

frames[0].window.foo = function(){ 
    console.log ("Look at me, executed inside an iframe!", window); 
} 

để có được khung của bạn từ một DOMElement đối tượng bạn có thể sử dụng:

var myFrame = document.getElementById('myFrame'); 

myFrame.contentWindow.foo = function(){ 
     console.log ("Look at me, executed inside an iframe!"); 
} 

Lưu ý rằng phạm vi trong foo là không thay đổi, vì vậy cửa sổ vẫn là cửa sổ cha, vv bên trong foo.

Nếu bạn muốn tiêm một số mã mà cần phải được chạy trong bối cảnh của khung khác bạn có thể tiêm một thẻ script, hoặc eval nó:

frames[0].window.eval('function foo(){ console.log("Im in a frame",window); }'); 

Mặc dù sự đồng thuận chung là không bao giờ sử dụng eval , Tôi nghĩ rằng nó là một thay thế tốt hơn so với tiêm DOM nếu bạn thực sự cần phải thực hiện điều này.

Vì vậy, trong trường hợp cụ thể của bạn, bạn có thể làm điều gì đó như:

frames[0].window.eval(foo.toString()); 
+0

Ok, nhưng nếu tôi thực thi hàm từ cửa sổ chính có 'khung [0]. window.foo(); ', nó được thực thi trong bối cảnh cửa sổ chính. Chèn nó vào đầu nó sẽ được thực thi với bối cảnh khung nội tuyến, tôi có sai không? (xem http://jsfiddle.net/7rEXT/) – janesconference

+0

Vấn đề không phải là ngữ cảnh, nhưng phạm vi. Khi bạn thực hiện hàm foo, bạn làm cho nó nằm trong phạm vi hiện tại tôi tin, vì vậy cửa sổ là cửa sổ cha và không phải là khung hình. Bạn vẫn sẽ cần phải sử dụng 'myFrame.contentWindow' hoặc' frames [0] .window' bên trong chức năng truy cập phạm vi chính xác. Nếu bạn cần phải tiêm một thẻ script, bạn có thể gắn nó thông qua DOM. – EJTH

+0

Tôi đã cập nhật câu trả lời của mình để phù hợp hơn với truy vấn của bạn. Mặc dù tôi phải nói rằng nếu bạn cần phải làm một cái gì đó như thế này, rất có thể là bạn đang overcomplicating mọi thứ, và rằng bạn đang làm điều đó sai, hoặc có thể làm nó thông minh hơn. – EJTH

1

Đây là giải pháp của tôi. Tôi đang sử dụng jquery để chèn nội dung, sau đó sử dụng eval để thực thi các thẻ tập lệnh trong ngữ cảnh của 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); 
    }); 
Các vấn đề liên quan