2

I'm kinda new to TChromium. I gathered specific examples codes, made my own test program. Now I have met problems which as I hope someone can help me to solve it:
First of all. I'm using OnLoadEnd to catch the moment when page have loaded, but it doesn't work proper. At least with my code below. How to catch that moment correctly?
As long as VisitDom is asynchronous I can't get how to call it right after page loaded and before next page will be loaded inside cycle. OR! It will be ok if each pages are loaded one by one and asynchronous VisitDom is executed exactly for each loaded page's snap of DOM
Than. The similar situation with the scripts (haven't implemented that in my test program yet). On each page after it loaded there will be script execution and DOM would be changed so that I will need to parse it too. Help me please with any solution: Catch when script is done and than parse page right after it or catch scirpt is done and parse page asynchronous exact for DOM resulted by this script.

Shorter the cycle looks like: loading page
page loaded
parse this DOM
executig script
script executed
parse this DOM
where parse DOM could be executed either right at the moment in cycle or asynchronous with the exact DOM at that specific moments.

Simplified questions are look like: how to catch events 'page loaded' and 'script done', and how to visit snaps of DOM generated exact at this particular moments (synch or asynch)

Thank you for your help!

type
  TElementNameVisitor = class(TCefDomVisitorOwn)
  private
    FMemo: TMemo;
  protected
    procedure visit(const document: ICefDomDocument); override;
  public
    constructor Create(AMemo:TMemo); reintroduce;
  end;


implementation

constructor TElementNameVisitor.Create(AMemo:TMemo);
begin
  inherited Create;
  FMemo := AMemo;
end;

procedure TElementNameVisitor.Visit(const document: ICefDomDocument);
  procedure ProcessNode(ANode: ICefDomNode);
  var
    Node: ICefDomNode;
  begin
    if Assigned(ANode) then
    begin
      Node := ANode.FirstChild;
      while Assigned(Node) do
      begin
        if Node.ElementTagName='DIV' then
        begin
          if Node.GetElementAttribute('id')='type-tabs' then
            FMemo.Lines.Add('FOUND');
        end;
        ProcessNode(Node);
        Node := Node.NextSibling;
      end;
    end;
  end;

begin
  FMemo.Lines.Add('START');
  ProcessNode(document.Body);
end;

procedure ProcessElementsByName(const AFrame: ICefFrame; AMemo:TMemo);
var
  Visitor: TElementNameVisitor;
begin
  if Assigned(AFrame) then
  begin
    Visitor := TElementNameVisitor.Create(AMemo);
    AFrame.VisitDom(Visitor);
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Links:TStringList;
    i:integer;
begin
  Links:=TStringList.Create;
  Memo1.Lines.Clear;

  Links.Add('www.link1.com');
  Links.Add('www.link2.com');
  Links.Add('www.link3.com');

  for i:=0 to Links.Count-1 do begin
    Chromium1.Load(Links.Strings[i]);
    repeat Application.ProcessMessages until FLoaded;
    Memo1.Lines.Add('Loaded #'+IntToStr(i));
    for j := 0 to 20 do begin
      Sleep(100); Application.ProcessMessages;
    end;
    ProcessElementsByName(Chromium1.Browser.MainFrame, Memo1);
    for j := 0 to 20 do begin
      Sleep(100); Application.ProcessMessages;
    end;
  end;

  Memo1.Lines.Add('end of btnClick');
end;

procedure TForm1.Chromium1LoadEnd(Sender: TObject; const browser: ICefBrowser;
  const frame: ICefFrame; httpStatusCode: Integer; out Result: Boolean);
begin
  FLoaded:=True;
end;

procedure TForm1.Chromium1LoadStart(Sender: TObject; const browser: ICefBrowser;
  const frame: ICefFrame);
begin
  FLoaded:=False;
end;
Alex
  • 51
  • 6
  • If it is impossible for any reasons to catch the moment right after script has been executed than I think I will manage that situation just forcing application to wait couple of seconds. I know it's harsh solution, but fine for my purposes. The main problem for me is to undestand how exact vistDOM works. Which exact DOM snap it takes. BTW is there any documentation on TChromium and concurrent classes? – Alex Nov 02 '13 at 12:47
  • Well. Actually I moving forward with my problem. I would like to post an answer to my post so that I can implement new code in it, but I dont know how :(. At this moment I have solved the problem with `OnLoadEnd` using `Frame.IsMain` check inside this event handler. Also I have added 2 variabels into visitor class: pointer to `boolean` (which is initializing within proc `ProcessElementsByName`) and TObject. So I've managed to solve asynchronicity problem: `ProcessElementsByName` initializes `boolean` var with `false` value, calls `VisitDOM`, and posts `ProcessMessages` while it false. – Alex Nov 03 '13 at 00:30
  • At that time asynchronous `VisitDOM` does its job, writes its results to `TObject` which is differs on parsing task and in the end sets this `bool` to true. So the program waiting while VisitDOM isn't done. But! :) I haven't solved "find out when script is done" problem. And it has become the main for now. The main question is how to catch `document.ready` event. I found small c# example with the solution ([http://magpcss.org/ceforum/viewtopic.php?f=6&t=10277]). They suggest to use within `Visitor` `document.document.AddEventListener('DOMContentLoaded')`. But I tried and it didn't work proper. – Alex Nov 03 '13 at 00:38
  • I ran application several times and this event handeled only ones. That is strange :(. Moreover there is TLama post where he mentions that "The difference of using the VisitDom method is that it makes a copy (a snapshot) of the current DOM state. In my example the TElementNameVisitor.visit works with a copy of the document, not with the document itself (which can be changed at the time you iterate)". So I don't understand if the document I have within Visitor can be changed later. – Alex Nov 03 '13 at 00:48
  • If it can than where I will get right DOM when EventListener handled to HandleEvent procedure which is outside of Visitor class. If it can't as TLama said than why in the c# example listener is implemented within Visitor class and how to solve next situation. OnLoadEnd have handled, and ProcessElementsByName called, but there is still DOM changing script execution. – Alex Nov 03 '13 at 01:04

0 Answers0