Saving OuterHTML using Await Implementation with TWebView
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:
Function List
AWait_QuerySelector(oWeb, cQuery, nSecond)
AWait_QuerySelectAll(oWeb, cQuery, nSecond)
AWait_GetOuterHTML(oWeb, cSelector, nSecond)
6.The example scenario is as follows:
Navigate to google.com.
Use AWait_QuerySelector() to wait until the document’s readyState becomes ‘complete’.
Once complete, use AWait_GetOuterHTML() to display the outer HTML.
sample Code
/*
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
TAWaitWeb.prg
/*
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