Histórico da Página
...
- Disponivel em build superior à 131217A131227A.
- A comunicação entre o SmartClient e o Navegador é feita através do componente TWebSocket, conforme exemplo a seguir.
Aviso | ||||
---|---|---|---|---|
| ||||
Nas plataformas móveis não é possível sobrepor componentes ADVPL sobre o Navegador do TWenEngine, esta é uma característica da biblioteca gráfica Qt. |
Exemplo completo
Nota | ||||
---|---|---|---|---|
| ||||
É necessário baixar o arquivo totvstec.js para execução do teste. |
Informações | ||||
---|---|---|---|---|
| ||||
1. Baixe e salve os conteúdos dos arquivos: 2. Compile os três arquivos através do TDS - Totvs Development Studio. 3. Execute a função u_ webengine |
webengine.prw
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
#include "TOTVS.CH"
user function webengine()
local i
local cMultGet := ""
local nPort,lConnected, link
local aFiles := {"totvstec.js", "webengine.index.html"}
local _tempPath := GetTempPath()
PRIVATE oWebChannel
PRIVATE oWebEngine
PRIVATE oMultGet
PRIVATE oDlg := TWindow():New(10, 10, 800, 600, "Exemplo", NIL, NIL, NIL, NIL, NIL, NIL, NIL,;
CLR_BLACK, CLR_WHITE, NIL, NIL, NIL, NIL, NIL, NIL, .T. )
// Baixa arquivos do exemplo do RPO no diretorio temporario
for i := 1 to len(aFiles)
cFile := _tempPath + aFiles[i]
nHandle := fCreate(cFile)
fWrite(nHandle, getApoRes(aFiles[i]))
fClose(nHandle)
next i
// ------------------------------------------
// Prepara o conector WebSocket
// ------------------------------------------
oWebChannel := TWebChannel():New()
nPort := oWebChannel::connect() // Efetua conexão e retorna a porta do WebSocket
lConnected := oWebChannel:lConnected // Conectado ? [.T. ou .F.]
// Verifica conexão
if !lConnected
msgStop("Erro na conexão com o WebSocket")
return // Aborta aplicação
endif
// ------------------------------------------
// Define o CallBack JavaScript
// IMPORTANTE: Este é o canal de comunicação
// "vindo do Javascript para o ADVPL"
// ------------------------------------------
oWebChannel:bJsToAdvpl := {|self,codeType,codeContent| jsToAdvpl(self,codeType,codeContent) }
// Monta link para navegação local inserindo "file:///"
if subs(_tempPath,1,2) == "C:"
_tempPath := "file:///" + strTran(_tempPath, "\", "/")
endif
link := _tempPath + "webengine.index.html"
// ------------------------------------------
// Cria navegador embedado
// ------------------------------------------
oWebEngine := TWebEngine():New(oDlg, 0, 0, 100, 100,, nPort)
oWebEngine:navigate(link)
oWebEngine:Align := CONTROL_ALIGN_ALLCLIENT
// Painel inferior
@ 038, 000 MSPANEL ConOut SIZE 250, 030 OF oDlg COLORS 0, 16777215 RAISED
ConOut:Align := CONTROL_ALIGN_BOTTOM
oMultGet := TSimpleEditor():New( 0,0,ConOut, 100,100,"",, {| u | if( pCount() > 0, cMultGet := u, cMultGet )}, , .T.)
oMultGet:Align := CONTROL_ALIGN_ALLCLIENT
// ------------------------------------------
// Botão fara o disparo do método runJavaScript
// que permite a execução via ADVPL de uma função JavaScript
// ------------------------------------------
@ 000, 204 BUTTON oButton1 PROMPT "runJavaScript" SIZE 045, 041 OF ConOut;
ACTION {|| oWebEngine:runJavaScript("alert('Alert Javascript\ndisparado via ADVPL')") } PIXEL
oButton1:Align := CONTROL_ALIGN_RIGHT
oDlg:Activate("MAXIMIZED")
Return
// ------------------------------------------
// Esta função recebera todas as chamadas vindas do Javascript
// através do método dialog.jsToAdvpl(), exemplo:
// dialog.jsToAdvpl("page_started", "Pagina inicializada");
// ------------------------------------------
static function jsToAdvpl(self,codeType,codeContent)
local i
local cFunJS
local oTmpHashProg:= .F.
local cCommand := ""
if valType(codeType) == "C"
_conout("jsToAdvpl->codeType: " + codeType + " = " + codeContent)
// ------------------------------------------b
// Recebe mensagem de termino da carga da página/componente
// ------------------------------------------
if codeType == "page_started"
// ------------------------------------------
// Ao terminar a caraga da página inserimos um botão na página HTML
// que fará a execução de uma função ADVPL via JavaScript
//
// Importante: O comando BeginContent permite a criação de pequenos trechos de código
// facilitando a construção de chamadas, como neste exemplo onde montamos um trecho Javascript
// ------------------------------------------
BeginContent var cFunJS
<a onclick='totvstec.runAdvpl("DtoS(CtoD(\"" +getDate()+ "\"))", runAdvplSuccess);'>
<div>
<font size="5">runAdvpl</font><br><br>
</div>
</a>
EndContent
// ------------------------------------------
// O método AdvplToJS envia uma mensagem do ADVPL para o JavaScript, para verificar a chegada
// desta mensagem prure o trecho a seguir no arquivo webengine.index.html
// if (codeType == "html") {...
// ------------------------------------------
oWebChannel:advplToJs("html", cFunJS)
endif
// ------------------------------------------
// Este trecho vai executar um comando ADVPL vindo do JavaScript
// ------------------------------------------
if codeType == "runAdvpl"
// ------------------------------------------
// Importante:
// A informação trafegada pela chamada do metodo Javascript runADVPL é uma variável do tipo JSON
// assim é necessário seu tratamento, para tanto utilise as funções getJsonHash e getHField, documentadas neste exemplo
// ------------------------------------------
if getJsonHash(codeContent, @oTmpHashProg)
cCommand := getHField(oTmpHashProg, "codeBlock")
if !empty(cCommand)
// Transforma o texo em um bloco de código e
// em caso de sucesso executa o mesmo
xVal := &("{|| " + cCommand + "}")
if valType(xVal) == "B"
xRet := eval(xVal)
xRet := cValToChar(xRet) // Converte pra String
// ------------------------------------------
// Importante:
// Este trecho executa do callBack (mensagem de retorno) para o Javascript
// permitindo o retorno de informações ao HTML após o processamento via ADVPL
// ------------------------------------------
fnCallBack = getHField(oTmpHashProg, "callBack")+"('" +xRet+ "')"
oWebEngine:runJavaScript(fnCallBack)
endif
endif
endif
endif
endif
return
/* ---------------------------------------------------------------
Parseia o Json em um Hash
getJsonHash: recebe o conteudo no formato Texto que será parseado
oHash: é uma varivel que receberá "por referencia" o conteudo HASH
contido no Texto inicial, por ser uma variavel utilizada po referencia
ela deve ter seu valor declarado anteriormente, exemplo: oTmpHashProg:= .F.
// ---------------------------------------------------------------*/
Static Function getJsonHash(jsonData, oHash)
Local oJson := tJsonParser():New()
Local jsonfields := {}
Local nRetParser := 0
if empty(jsonData)
return .F.
endif
// Converte JSON pra Hash
return oJson:Json_Hash(jsonData, len(jsonData), @jsonfields, @nRetParser, @oHash)
return
/* ---------------------------------------------------------------
Retorna valor do campo no Hash
oHash: variável no formato HASH criada pela função getJsonHash
jsonField: nome do campono no formato Texto que se deseja recuperar
retorno: valor do campo encontrado ou "vazio" caso contrário
---------------------------------------------------------------*/
Static Function getHField(oHash, jsonField)
Local xGet := Nil
// Recupera valor do campo
if HMGet(oHash, jsonField, xGet)
return xGet
else
return ""
endif
return
// ---------------------------------------------------------------
// Exibe conout no MultiGet para auxiliar na visualização em tela
// ---------------------------------------------------------------
static function _conout(cText)
conOut(cText)
oMultGet:Load(cText)
Return
|
webengine.index.html
Bloco de código | ||||||||
---|---|---|---|---|---|---|---|---|
| ||||||||
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<style>
body { font-family: 'Calibri'; }
a { text-decoration: none; }
div { display: inline-block; float: left; background-color: #019AC4; color: #FFFFFF;
width: 250px; height: 34px; margin: 10px; padding: 10px; }
</style>
<script src="totvstec.js"></script>
<script>
onload = function () { loadEngine(); }
function loadEngine() {
// Conecta WebSocket Server
totvstec.connectWS( function(){
// Carrega mensageria exclusiva da pagina
dialog.advplToJs.connect(function (codeType, codeContent) {
if (codeType == "html") {
var page = document.getElementById("main");
page.innerHTML += codeContent;
}
});
// Envia sinal informando termino da carga da pagina
dialog.jsToAdvpl("page_started", "Pagina inicializada");
});
}
function getDate(){
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth()+1; //January is 0!
var yyyy = today.getFullYear();
return mm+'/'+dd+'/'+yyyy;
}
function runAdvplSuccess(retStr){
alert("CalBack da função runADVPL: " + retStr);
}
</script>
</head>
<body>
<font face="calibri" color="#FFFFFF">
<p id="main"></p>
</body>
</html>
|
Preview
- partir da versão 20.3.2.0 do SmartClient, o componente tem uma deficiência em sistemas operacionais Linux que ao exibir um PDF não é possível realizar o download e impressão dele pelos botões na barra superior. Esta deficiência é ocasionada por uma biblioteca de terceiros que estamos procurando solucionar.
- A partir da versão 20.3.2.6 do SmartClient, a função PrintPDF() passa a imprimir as cores de fundo de uma página HTML, porém a função Print() continua sem imprimi-las por conta de deficiência da biblioteca de terceiros.
Nota | ||
---|---|---|
| ||
Cada instância do componente TWebEngine no SmartClient Desktop se comporta como uma aba diferente de um web browser, possuindo cada uma sua própria SessionStorage. Por outro lado, no SmartClient Webapp por naturalmente já ser executado em um web browser, suas instâncias de TWebEngine se comportam como Iframes e compartilham a mesma SessionStorage. |
Nota | ||||
---|---|---|---|---|
| ||||
É possível depurar a camada HTML/JS do componente TWebEngine invocando o SmartClient via linha de comando, como no exemplo abaixo: smartclient --remote-debugging-port=8888 Onde a porta, no exemplo 8888, deverá ser chamada no navegador Chrome, permitindo então a depuração. Mais detalhes acesse o link abaixo: A partir da build 20.3.0.0 é possível habilitar um parâmetro no arquivo smartclient.ini que exibe um console JavaScript. A partir da build 20.3.2.0 é necessário informar também quem pode realizar o debug da camada HTML/JS via linha de comando: |
Informações | ||||
---|---|---|---|---|
| ||||
Exemplo
Nota |
---|
Abaixo esta disponível um exemplo documentado de uso do componente e o codigo JavaScript de apoio (twebchannel.js): Visualização do exemplo |
O TWebEngine no Youtube
Conector de Widget | ||
---|---|---|
|
Abrangência
Protheus 11 , TOTVS Application Server