UJSExec.pas 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. unit UJSExec;
  2. interface
  3. uses
  4. MSHTML, ShDocVw;
  5. type
  6. TJSExec = class(TObject)
  7. private
  8. fWB: TWebBrowser;
  9. function GetDocWindow: IHTMLWindow2;
  10. function GetElementById(const ID: string): IHTMLElement;
  11. function GetRetValContainer: IHTMLElement;
  12. function CreateRetValContainer: IHTMLElement;
  13. public
  14. constructor Create(const WB: TWebBrowser);
  15. procedure RunJSProc(const Fn: string);
  16. function RunJSFn(const Fn: string): string;
  17. end;
  18. implementation
  19. uses
  20. SysUtils;
  21. const
  22. // unique id that should clash with anything in the doc
  23. cRetValElemId = 'id58A3A2A46539468A943D00FDD6A4FF08';
  24. { TJSExec }
  25. constructor TJSExec.Create(const WB: TWebBrowser);
  26. begin
  27. inherited Create;
  28. fWB := WB;
  29. end;
  30. function TJSExec.CreateRetValContainer: IHTMLElement;
  31. var
  32. Doc: IHTMLDocument2;
  33. begin
  34. if not Supports(fWB.Document, IHTMLDocument2, Doc) then
  35. raise Exception.Create('Invalid document');
  36. Result := Doc.createElement('input');
  37. Result.id := cRetValElemId;
  38. Result.setAttribute('name', cRetValElemId, 0);
  39. Result.setAttribute('type', 'hidden', 0);
  40. Result.setAttribute('value', '', 0);
  41. end;
  42. function TJSExec.GetDocWindow: IHTMLWindow2;
  43. var
  44. Doc: IHTMLDocument2;
  45. begin
  46. if not Supports(fWB.Document, IHTMLDocument2, Doc) then
  47. raise Exception.Create('Invalid document');
  48. Result := Doc.parentWindow;
  49. if not Assigned(Result) then
  50. raise Exception.Create('No document window');
  51. end;
  52. function TJSExec.GetElementById(const ID: string): IHTMLElement;
  53. var
  54. Doc: IHTMLDocument3;
  55. begin
  56. if not Supports(fWB.Document, IHTMLDocument3, Doc) then
  57. raise Exception.Create('Invalid document');
  58. Result := Doc.getElementById(ID);
  59. end;
  60. function TJSExec.GetRetValContainer: IHTMLElement;
  61. var
  62. NewNode: IHTMLDOMNode;
  63. BodyNode: IHTMLDOMNode;
  64. Doc: IHTMLDocument2;
  65. begin
  66. Result := GetElementById(cRetValElemId);
  67. if not Assigned(Result) then
  68. begin
  69. if not Supports(fWB.Document, IHTMLDocument2, Doc) then
  70. raise Exception.Create('Invalid document');
  71. if not Supports(Doc.body, IHTMLDOMNode, BodyNode) then
  72. raise Exception.Create('Invalid body node');
  73. Result := CreateRetValContainer;
  74. if not Supports(Result, IHTMLDOMNode, NewNode) then
  75. raise Exception.Create('Invalid new node');
  76. BodyNode.appendChild(NewNode);
  77. end;
  78. end;
  79. function TJSExec.RunJSFn(const Fn: string): string;
  80. var
  81. EmbedFn: string;
  82. WrapperFn: string;
  83. HiddenElem: IHTMLElement;
  84. const
  85. WrapperFnTplt = 'eval("'
  86. + 'id = document.getElementById(''' + cRetValElemId + '''); '
  87. + 'id.value = %s;'
  88. + '")';
  89. begin
  90. EmbedFn := StringReplace(Fn, '"', '\"', [rfReplaceAll]);
  91. EmbedFn := StringReplace(EmbedFn, '''', '\''', [rfReplaceAll]);
  92. HiddenElem := GetRetValContainer;
  93. WrapperFn := Format(WrapperFnTplt, [EmbedFn]);
  94. RunJSProc(WrapperFn);
  95. Result := HiddenElem.getAttribute('value', 0);
  96. end;
  97. procedure TJSExec.RunJSProc(const Fn: string);
  98. var
  99. Wdw: IHTMLWindow2;
  100. begin
  101. try
  102. Wdw := GetDocWindow;
  103. Wdw.execScript(Fn, 'JavaScript'); // execute function
  104. except
  105. // swallow exception to prevent JS error dialog
  106. end;
  107. end;
  108. end.