本周末由几个SO q提示,我决定看看我是否可以解决问题 将Html元素中的一些javascript添加到TWebBrowser中加载的文档中。这样做, 我遇到了一个奇怪的问题,也许有人可以解释一下。
这是我的Html文档
<html>
<body>
Something
<br>
<div id="forscript">some more text</div>
</body>
</html>
和我要添加的javascript元素
<script type="text/javascript" defer="false">{alert('hello');}</script>
我将Script参数传递给下面的AddScript()。
这是我的代码(doc2是从WebBrowser获取的IHtmlDocument2):
procedure TForm1.AddScript(const Script : String);
var
Element : IHtmlElement;
Doc3 : IHtmlDocument3;
begin
Doc2.QueryInterface(IHtmlDocument3, Doc3);
Element := Doc3.GetElementByID('forscript');
Element.innerHTML := Element.innerHTML + Script;
end;
这很好,但是......
分配RHS上的Element.innerHTML的原因只是我发现了 如果RHS只包含 脚本js,则js不会执行。我的问题是,为什么不,并且有一个更简单的替代方案,就像在某种程度上在代码中创建一个IHtmlScriptElement并将其插入DOM?显然,我简单易懂的解决方法就是将文本添加到文本中 元素已经包含,但我有点难以相信那些真正知道自己在做什么的人会发现必要的。
FWIW#1 :我尝试使用Element.insertAdjacentHtml来添加脚本,但是在我需要插入除了脚本之外的内容之外,还得到了与我刚刚描述的相同的行为要执行的脚本,所以我想知道是否与在更改DOM之后如何处理DOM有关。
FWIW#2 :我使用过Element.innerHtml路由,因为TWebBrowser / MSHTML.Pas拒绝了我的 尝试在代码中创建IHtmlScriptElement; AFAICS,试图使用任何一个 MSHTML.Pas中的CohtmlXXXElement例程引发了“未注册类”异常,这似乎证实了我在这个教区的@kobik某处发现的评论。
(顺便说一句,在Win7 64位上使用D7 + IE11)
答案 0 :(得分:6)
这是一个如何使用IHtmlScriptElement
的完整示例。
在应用程序启动时加载Html。
Button1Click
下的代码将javascript添加到DOM并执行它:
unit u_frm_SO27091639;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, OleCtrls, SHDocVw, MsHtml, ActiveX;
type
TForm1 = class(TForm)
WebBrowser1: TWebBrowser;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure LoadDocFromString(Webbrowser : TWebbrowser);
var
Strm : TStringStream;
Adapter : TStreamAdapter;
begin
WebBrowser.Navigate('about:blank');
// warning - don't use this trick in production code, use the `OnDocumentComplete` event
while WebBrowser.ReadyState <> READYSTATE_INTERACTIVE do
Application.ProcessMessages;
// end of warning
Strm := TStringStream.Create;
try
Strm.WriteString('<html><body>Something<br></body></html>');
Strm.Seek(0, 0);
Adapter := TStreamAdapter.Create(Strm);
(WebBrowser.Document as IPersistStreamInit).Load(Adapter) ;
finally
Strm.Free;
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Doc2 : IHtmlDocument2;
Script : IHtmlDOMNode;
HTMLWindow: IHTMLWindow2;
begin
Doc2 := Webbrowser1.Document as IHtmlDocument2;
if Assigned(Doc2.body) then
begin
Script := Doc2.createElement('script') as IHTMLDOMNode;
(Script as IHTMLScriptElement).text := 'function helloWorld() { alert("hello world!") }';
(Doc2.body as IHtmlDomNode).appendChild(Script);
HTMLWindow := Doc2.parentWindow;
if Assigned(HTMLWindow) then
HTMLWindow.execScript('helloWorld()', 'JavaScript')
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
LoadDocFromString(Webbrowser1);
end;
end.