将脚本元素添加到现有 TWebBrowser 文档中
Adding a script element to an existing TWebBrowser document
本周末在几个 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>
我将其作为脚本参数传递给下面的 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 有关。
FWIW #2:我使用了 Element.innerHtml 路由,因为 TWebBrowser/MSHTML。帕斯抵制了我的尝试在代码中创建 IHtmlScriptElement;AFAICS,尝试使用任何CohtmlXXXElement routines in MSHTML.Pas引发了"班级未注册"的异常,这似乎证实了我在@kobik教区的某个地方遇到的评论。
(顺便说一句,在Win7 64位上使用D7 + IE11)
这里有一个完整的示例如何使用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.
- 使用promise和mongoose对文档进行排序
- document.open/document.write没有正确地清除chrome中的文档——这是chrome的错误吗
- Ajax请求文档就绪会导致jquery加载缓慢
- MongoDB (php) - 以数组而不是多个属性的形式返回文档属性
- 谷歌文档表面引擎
- 来自文档或下一个静态父级的事件委派
- 如何将childNodes用于XML文档
- 文档就绪提供了错误的选择器高度
- 将当前用户的 ID 推送到 meteorjs 中集合/文档的内部数组
- 未捕获的语法错误:无法在“文档”上执行“查询选择器”
- BrowserId登录请求在文档加载时被调用
- 从Javascript和Php变量创建Html模板文档
- 如何通过谷歌应用程序脚本从谷歌文档中的位置确定命名范围
- 在jquery文档准备好之前加载Modernizr
- 如何判断何时将dom节点添加到文档中
- 无法获取文档.GetElementById工作正常
- 为什么是文档.旧版应用程序中的DOM-object.properties为null
- 有没有一种方法可以在没有文档或jQuery的情况下使用javascript解码html实体
- 是否存在Javascript Liferay Service库的文档?如何处理错误情况
- 将脚本元素添加到现有 TWebBrowser 文档中