1. Fivewin features a powerful Web Control class called TWebView.
2. The web rendering operates in async mode.
3. Consequently, users familiar with procedural synchronous modes are facing difficulties in retrieving information from the web.
4. Therefore, I have implemented a synchronous class for TWebView, which is supported by the 'await' technique in other languages.
5. The implementation is named TAWaitWeb. To facilitate more convenient usage, I have created user-friendly functions using TAWaitWeb as follows:
AWait_QuerySelector(oWeb, cQuery, nSecond)
AWait_QuerySelectAll(oWeb, cQuery, nSecond)
AWait_GetOuterHTML(oWeb, cSelector, nSecond)
6. The example scenario is as follows:
6-1.Navigate to google.com.
6-2.Use AWait_QuerySelector() to wait until the document's readyState becomes 'complete'.
6-3.Once complete, use AWait_GetOuterHTML() to display the outer HTML.
Reagrds,
Charles KWON
- Code: Select all Expand view RUN
/*
c)copyright 2023- charleskwonohjun@gmail.com ( Seoul, Korea )
*/
#include "FiveWin.ch"
STATIC oWebView
FUNCTION Main()
LOCAL oDlg
DEFINE DIALOG oDlg TITLE "WebView Test" SIZE 1200, 700
oDlg:bStart := { || GetOuterHtml( oDlg ) }
ACTIVATE DIALOG oDlg CENTER
RETURN NIL
STATIC FUNCTION GetOuterHtml( oDlg )
LOCAL cStr
LOCAL nCounter := 0
LOCAL lOk := .f.
oWebView := TWebView():New( , oDlg:hWnd )
oWebView:Navigate( "https://www.google.com/" )
Sleep(300)
SysWait()
WHILE .T.
++nCounter
cStr := AWait_QuerySelector( oWebView, "document.readyState", 3000 )
IF cStr == "complete"
lOk := .t.
EXIT
ENDIF
IF nCounter == 6
EXIT
ENDIF
ENDDO
IF !lOk
MsgStop("Timeout! Try again")
RETURN NIL
ENDIF
?AWait_GetOuterHTML( oWebView, "html", 3000 )
RETURN NIL
- Code: Select all Expand view RUN
/*
TAWaitWeb.prg
This is a class for Fivewin TWebView that retrieves data from the WebView in Sync mode.
c)copyright 2023- charleskwonohjun@gmail.com ( Seoul, Korea )
*/
#include "fivewin.ch"
FUNCTION AWait_QuerySelector( oWeb, cQuery, nSecond )
LOCAL oFunc
LOCAL cReturn := ""
oFunc := TAWaitWeb():New( oWeb )
oFunc:Query( cQuery, nSecond )
cReturn := oFunc:cReturn
RETURN cReturn
FUNCTION AWait_QuerySelectAll( oWeb, cQuery, nSecond )
LOCAL oFunc
LOCAL cReturn := ""
oFunc := TAWaitWeb():New( oWeb )
oFunc:QuerySelectAll( cQuery, nSecond )
cReturn := oFunc:cReturn
RETURN cReturn
FUNCTION AWait_GetOuterHTML( oWeb, cSelector, nSecond )
LOCAL oFunc
LOCAL cReturn := ""
oFunc := TAWaitWeb():New( oWeb )
oFunc:getOuterHTML( cSelector, nSecond )
cReturn := oFunc:cReturn
RETURN cReturn
CLASS TAWaitWeb
DATA bOldBind
DATA oWeb
DATA cQuery
DATA nSecond
DATA cReturn
METHOD New( oWeb, cQuery, nSecond ) CONSTRUCTOR
METHOD GetBind( cJson, cCalls, ... )
METHOD Query( cQuery, nSecond )
METHOD QuerySelectAll( cQuery, nSecond )
METHOD GetOuterHtml( cSelecter, nSecond )
ENDCLASS
METHOD New( oWeb ) CLASS TAWaitWeb
::oWeb := oWeb
::oWeb:Bind( "SendToFWH" )
RETURN Self
METHOD Query( cQuery, nSecond, cReturn ) CLASS TAWaitWeb
LOCAL nCounter := 0
LOCAL lReturn := .f.
LOCAL cEval := "SendToFWH($QUERY$, 'WebFunc')"
LOCAL nStartSec := GetTickCount()
DEFAULT nSecond := 500
::bOldBind := ::oWeb:bOnBind
::oWeb:bOnBind := { | cJson, cCalls, ... | ::GetBind( cJson, cCalls, ... ) }
cEval := STRTRAN( cEval, "$QUERY$", cQuery )
::cReturn := ""
WHILE .T.
::oWeb:Eval( cEval )
sleep(100)
SysWait()
IF !EMPTY( ::cReturn )
lReturn := .t.
EXIT
ENDIF
IF GetTickCount() - nStartSec >= nSecond
EXIT
ENDIF
ENDDO
cReturn := ::cReturn
::oWeb:bOnBind := ::bOldBind
RETURN lReturn
METHOD QuerySelectAll( cQuery, nSecond, cReturn ) CLASS TAWaitWeb
LOCAL nCounter := 0
LOCAL lReturn := .f.
LOCAL cEval := "SendToFWH(querySelectorAll($QUERY$), 'WebFunc')"
LOCAL nStartSec := GetTickCount()
DEFAULT nSecond := 500
::bOldBind := ::oWeb:bOnBind
::oWeb:bOnBind := { | cJson, cCalls, ... | ::GetBind( cJson, cCalls, ... ) }
cEval := STRTRAN( cEval, "$QUERY$", cQuery )
::cReturn := ""
WHILE .T.
::oWeb:Eval( cEval )
sleep(100)
SysWait()
IF !EMPTY( ::cReturn )
lReturn := .t.
EXIT
ENDIF
IF GetTickCount() - nStartSec >= nSecond
EXIT
ENDIF
ENDDO
cReturn := ::cReturn
::oWeb:bOnBind := ::bOldBind
RETURN lReturn
METHOD GetOuterHtml( cSelecter, nSecond ) CLASS TAWaitWeb
LOCAL cQuery := "SendToFWH( document.querySelector('$SELECTER$').outerHTML, 'savehtml')"
LOCAL cEval
LOCAL nStartSec := GetTickCount()
LOCAL lReturn := .f.
DEFAULT nSecond := 500
::bOldBind := ::oWeb:bOnBind
::oWeb:bOnBind := { | cJson, cCalls, ... | ::GetBind( cJson, cCalls, ... ) }
cEval := STRTRAN( cQuery , "$SELECTER$", cSelecter )
::cReturn := ""
WHILE .T.
::oWeb:Eval( cEval )
sleep(100)
SysWait()
IF !EMPTY( ::cReturn )
lReturn := .t.
EXIT
ENDIF
IF GetTickCount() - nStartSec >= nSecond
EXIT
ENDIF
ENDDO
::oWeb:bOnBind := ::bOldBind
RETURN lReturn
METHOD GetBind( cJson, cCalls, ... ) CLASS TAWaitWeb
LOCAL hResponse := hash()
hb_jsondecode(cJson ,@hResponse )
::cReturn := ""
IF LEN( hResponse ) >= 1
::cReturn := hResponse[1]
ENDIF
RETURN NIL