| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- unit UJSExec;
- interface
- uses
- MSHTML, ShDocVw;
- type
- TJSExec = class(TObject)
- private
- fWB: TWebBrowser;
- function GetDocWindow: IHTMLWindow2;
- function GetElementById(const ID: string): IHTMLElement;
- function GetRetValContainer: IHTMLElement;
- function CreateRetValContainer: IHTMLElement;
- public
- constructor Create(const WB: TWebBrowser);
- procedure RunJSProc(const Fn: string);
- function RunJSFn(const Fn: string): string;
- end;
- implementation
- uses
- SysUtils;
- const
- // unique id that should clash with anything in the doc
- cRetValElemId = 'id58A3A2A46539468A943D00FDD6A4FF08';
- { TJSExec }
- constructor TJSExec.Create(const WB: TWebBrowser);
- begin
- inherited Create;
- fWB := WB;
- end;
- function TJSExec.CreateRetValContainer: IHTMLElement;
- var
- Doc: IHTMLDocument2;
- begin
- if not Supports(fWB.Document, IHTMLDocument2, Doc) then
- raise Exception.Create('Invalid document');
- Result := Doc.createElement('input');
- Result.id := cRetValElemId;
- Result.setAttribute('name', cRetValElemId, 0);
- Result.setAttribute('type', 'hidden', 0);
- Result.setAttribute('value', '', 0);
- end;
- function TJSExec.GetDocWindow: IHTMLWindow2;
- var
- Doc: IHTMLDocument2;
- begin
- if not Supports(fWB.Document, IHTMLDocument2, Doc) then
- raise Exception.Create('Invalid document');
- Result := Doc.parentWindow;
- if not Assigned(Result) then
- raise Exception.Create('No document window');
- end;
- function TJSExec.GetElementById(const ID: string): IHTMLElement;
- var
- Doc: IHTMLDocument3;
- begin
- if not Supports(fWB.Document, IHTMLDocument3, Doc) then
- raise Exception.Create('Invalid document');
- Result := Doc.getElementById(ID);
- end;
- function TJSExec.GetRetValContainer: IHTMLElement;
- var
- NewNode: IHTMLDOMNode;
- BodyNode: IHTMLDOMNode;
- Doc: IHTMLDocument2;
- begin
- Result := GetElementById(cRetValElemId);
- if not Assigned(Result) then
- begin
- if not Supports(fWB.Document, IHTMLDocument2, Doc) then
- raise Exception.Create('Invalid document');
- if not Supports(Doc.body, IHTMLDOMNode, BodyNode) then
- raise Exception.Create('Invalid body node');
- Result := CreateRetValContainer;
- if not Supports(Result, IHTMLDOMNode, NewNode) then
- raise Exception.Create('Invalid new node');
- BodyNode.appendChild(NewNode);
- end;
- end;
- function TJSExec.RunJSFn(const Fn: string): string;
- var
- EmbedFn: string;
- WrapperFn: string;
- HiddenElem: IHTMLElement;
- const
- WrapperFnTplt = 'eval("'
- + 'id = document.getElementById(''' + cRetValElemId + '''); '
- + 'id.value = %s;'
- + '")';
- begin
- EmbedFn := StringReplace(Fn, '"', '\"', [rfReplaceAll]);
- EmbedFn := StringReplace(EmbedFn, '''', '\''', [rfReplaceAll]);
- HiddenElem := GetRetValContainer;
- WrapperFn := Format(WrapperFnTplt, [EmbedFn]);
- RunJSProc(WrapperFn);
- Result := HiddenElem.getAttribute('value', 0);
- end;
- procedure TJSExec.RunJSProc(const Fn: string);
- var
- Wdw: IHTMLWindow2;
- begin
- try
- Wdw := GetDocWindow;
- Wdw.execScript(Fn, 'JavaScript'); // execute function
- except
- // swallow exception to prevent JS error dialog
- end;
- end;
- end.
|