Thank you joedf!
I'm trying to log very long script steps...
Code: Select all
class HtmlLogClass {
__New(GuiName := "HtmlLog", W := "", H := "", MyCss := ""){
static
if FileExist(MyCss)
FileRead, MyCss, % MyCss
MyCss := RegExReplace(MyCss, "i)\<(\/|)style.*?\>")
HTML=
(
<html>
<head>
<title>%GuiName%</title>
<style type="text/css">
body { font-family: Segoe UI,Frutiger,Frutiger Linotype,Dejavu Sans,Helvetica Neue,Arial,sans-serif; font-size:15px;}
img { vertical-align: text-baseline; padding-right:5px;}
a img { border: 0 none; }
#Content { Margin-bottom:30px;}
#StatusBar { overflow: hidden; background-color: silver; position: fixed; left:0; width: 100`%; bottom: 0; }
%MyCss%
</style>
</head>
<body><div class="Content" id="Content"></div><div id="StatusBar"></div></body>
</html>
)
this.Name := GuiName
Gui, % this.Name ":New"
Gui, % this.Name ":Default"
Gui, Margin, 0, 0
Gui, +hwndhGui +Resize -DPIScale
this.hGui := hGui
Gui, Add, ActiveX, % "vWB HWNDhWb +VScroll +HScroll " . " w" (W ? W : "400") . " h" (H ? H : "300"), about:<!DOCTYPE html><meta http-equiv="X-UA-Compatible" content="IE=edge" charset="UTF-8">
ComObjConnect(Wb, new HtmlLogEvents)
this.Wb := Wb
this.Wb.silent := True
this.hWb := hWb
Wb.Document.write(HTML)
this.StatusBar := this.Wb.Document.GetElementById("StatusBar")
this.Doc := this.Wb.Document.GetElementById("Content")
OnMessage(WM_SIZE := 0x05 , objbindmethod(this, "GuiSize"))
OnMessage(WM_SYSCOMMAND:=0x112 , objbindmethod(this, "GuiClose"))
}
Show(X := "Center", Y := "Center", Title := ""){
Gui, % this.Name ":Show", % "AutoSize" . " x" X . " y" Y, % this.Title := Title
}
; https://autohotkey.com/board/topic/90598-simple-custom-gui-close-events-onmessage/
; ==================================================================================
GuiClose(wP, lP, msg, hwnd) {
if (wp = 0xF060) && (this.hGui = Hwnd)
this.Hide()
}
; https://autohotkey.com/boards/viewtopic.php?f=5&t=42292
; =======================================================
GuiSize(wParam, lParam, msg, hwnd){
if this.hGui != Hwnd
Return
w := lParam & 0xFFFF, h := lParam >> 16
Gui, % this.Name ":Default"
GuiControl, MoveDraw, % this.hWb, % "w" w " h" h
}
Hide(){
Gui, % this.Name ":Hide"
this.IsHide := 1
}
Timeout(ms){
Sleep, % ms
this.Hide()
}
OnTop(OnOff){
WinSet, AlwaysOnTop, % OnOff, % "ahk_id" this.hGui
}
Clear(){
this.Doc.innerhtml := ""
}
WaitClose(){
WinWaitClose, % "ahk_id" this.hGui
}
Activate(){
WinActivate, % "ahk_id" this.hGui
}
Add(HTML){
this.Doc.InnerHTML .= this.MyHtml(html)
this.OnEdit()
}
AddToLastTag(HTML, LastTag, StartNewTag := ""){
if StartNewTag
this.Add(StartNewTag)
this.Doc.GetElementsByTagname(this.CleanTag(LastTag))[this.Doc.GetElementsByTagname(this.CleanTag(LastTag)).Length-1].innerhtml .= this.MyHtml(HTML)
this.OnEdit()
}
; HTML must include tags to replace outerHTML
; ===========================================
ReplaceLastTag(HTML, LastTag, StartNewTag := ""){
if StartNewTag
this.Add(StartNewTag)
this.Doc.GetElementsByTagname(this.CleanTag(LastTag))[this.Doc.GetElementsByTagname(this.CleanTag(LastTag)).Length-1].Outerhtml := this.MyHtml(HTML)
this.OnEdit()
}
DeleteLastTag(LastTag){
this.Doc.GetElementsByTagname(this.CleanTag(LastTag))[this.Doc.GetElementsByTagname(this.CleanTag(LastTag)).Length-1].Outerhtml := ""
this.OnEdit()
}
OnEdit(){
this.onClick("")
this.ScrollDown()
}
CleanTag(LastTag){
Return RegExReplace(LastTag, "[</>\s]")
}
MyHtml(html){
Return RegExReplace(html, "href=""(?!#)", "href=""GETTHISLINK://") ; no anchor
}
ScrollDown(){
this.wb.document.documentElement.ScrollTop := this.wb.document.body.scrollHeight
}
Save(HtmlFile, OverWrite := 0){
;MsgBox, % Path ; ???? show C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\
SplitPath, % HtmlFile,, HtmlDir,, HtmlNameNoExt
ImgsDest := HtmlDir "\" HtmlNameNoExt "_files"
if OverWrite
{
FileDelete, % HtmlFile
FileRemoveDir, % ImgsDest, 1
}
if !FileExist(ImgsDest)
FileCreateDir, % ImgsDest
html := this.wb.document.documentElement.OuterHTML
; i cant loop img src because it shows full paths in case of A_ScriptDir "\..\FolderUp"
; =====================================================================================
obj := [], pos := 1
While pos := RegExMatch(html, "i)src\=\""(file:/+|)\K.*?(?=\"")", src, StrLen(src)+pos)
obj.Push(src)
for i, _Path in obj
{
SplitPath, % _Path, FileName
if FileExist(_Path)
FileCopy, % _Path, % ImgsDest "\" FileName
else if RegexMatch(_Path, "i)(https?://|www\.|)[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(/\S*)?")
UrlDownloadToFile, % _Path, % ImgsDest "\" FileName
;MsgBox, % "Copy <" _Path ">`n`n<" ImgsDest "\" FileName ">`n`nError " ErrorLevel
html := StrReplace(html, _Path, HtmlNameNoExt "_files\" FileName)
}
FileAppend, % StrReplace(Html, "href=""GETTHISLINK://", "href="""), % HtmlFile
}
; https://autohotkey.com/boards/viewtopic.php?f=7&t=4588&start=20
; https://www.w3schools.com/jsref/dom_obj_event.asp
; i dont know why i must rebind all ids on html changes for working binds
; =======================================================================
onClick(Id){
static Ids := []
if id
Ids.Push(id)
for i, id in Ids
this.wb.document.getElementById(Id).onclick := Func(Id).Bind(this.wb)
}
}
class HtmlLogEvents
{
BeforeNavigate2(wb, NewURL)
{
wb.Stop()
if RegExMatch(NewURL, "i)^GETTHISLINK://\K.*", Link)
if Link := StrReplace(Link, "%20", A_Space)
Try
Run % Link
}
DocumentComplete(wb, NewURL){
wb.Stop()
}
NavigateComplete2(wb){
wb.Stop()
static doc
ComObjConnect(doc:=wb.document, new HtmlLogEvents)
}
; https://autohotkey.com/board/topic/76777-help-with-copy-and-pasting-with-shellexplorer/?p=488306
; ================================================================================================
OnKeyPress(doc) {
static keys := {1:"selectall", 3:"copy", 22:"paste", 24:"cut"}
;static keys := {1:"selectall", 3:"copy"}
keyCode := doc.parentWindow.event.keyCode
if keys.HasKey(keyCode)
Doc.ExecCommand(keys[keyCode])
}
}
Code: Select all
#SingleInstance, force
#include, %A_ScriptDir%\HtmlLogClass.ahk
MyCss=
(
body {font-family:Consolas,'DejaVu Sans Mono', "Courier New", Courier, monospace; color: white; background-color: #272822;}
.BlueLink, a {color: #66D9EF; font-style: normal; text-decoration: underline;}
.Red {color: #F92672;}
.Green {color: #A6E22E;}
.Pink {color: #EB939A;}
.Yellow {color: #E6DB74; font-style: normal;}
.Red2 {color: #FF00FF; font-style: italic;}
.Gray {color: #75715E; font-style: normal; font-style: italic;}
.Orange {color:#FF8000;}
.Orange2 {font-style: bold; color:#CF2F0F;}
.Replace {text-align: center; font-size:30px; border-style: dashed;}
#MyDiv {border-style: dashed; border-color: #75715E; text-align: Center; border-radius: 10px; width: 80`%;}
)
Global Log := New HtmlLogClass(GuiName := "Sample", W := "600", H := "600", MyCss) ; or "D:\css.css"
Log.Show(X := "10", Y := "10", Title := "HtmlLogClass Sample")
log.Add("<p class='Red2'>" SpanNow() " <span class='Yellow'>Reading </span>'Mycss'</p>")
log.Add("<p class='Yellow'>" . SpanNow() . "Adding Autohotkey.com logo homepage and forum community links on a new div id #MyDiv <span class='Gray'>AddToLastTag()</span>" . "</p>")
log.AddToLastTag("<p>" . "<img id='Anchor' src=""https://autohotkey.com/assets/images/ahk-logo-no-text241x78-180.png"" alt=""ahk logo"" style=""width:241px;height:78px;"">" . "</p>", "div", "<div id=MyDiv></div>")
Log.AddToLastTag("<p>" . "<a href=""https://autohotkey.com"">Home</a>" . " <a href=""https://autohotkey.com/boards/""> Forum</a>" . "</p>", "div")
Log.Add("<H1 class='Orange'>" SpanNow() " Some text to H1 tag</H1>")
; Link to file, open it by "Run"
; ===============================
UrlDownloadToFile, https://www.google.com/s2/favicons?domain=https://autohotkey.com/, % ahkfavicon := A_ScriptDir "\ahk.png" ; save() cant find file extension and fails
img := "<img src=""" ahkfavicon """ alt''>"
File := A_ScriptDir "\HtmlLogClassSampleFile.html"
FileDelete, % File
FileAppend, % SpanNow() " file open test from HtmlLogClass!", % File
Log.Add("<p>" SpanNow() "<span class='Yellow'>Link to <span class='Pink'>HtmlLogClassSample.txt</span> in favicon </span>" . "<a href=""" File """>" . img . "</a>" . "</p")
*/
; Status bar
; ==========
Log.Add("<p>" . SpanNow() . "Write to default <span class='Red'>Status Bar<br /></span><span class='Gray'>Log.StatusBar (Document.GetElementById(StatusBar))</span>" . "</p>")
Log.StatusBar.Style.textAlign := "center"
Log.StatusBar.Innertext := "Some text to status bar"
Sleep, 500
Log.StatusBar.Innertext := ""
Loop % n := 2
{
Log.StatusBar.InnerHtml := "<span style='font-size:30px; color: black;'>Index " . A_Index "/" n . "</span>"
Sleep, 500
}
Sleep, 500
Log.StatusBar.InnerHtml := "<b>status bar still here.</b>"
*/
; List
; ====
Log.Add("<p class='Yellow'>" . SpanNow() . "Fill lists <span class='Gray'>AddToLastTag()</span>" . "</p>")
for i, list in [{l: "ul", title: "Unordered List"}, {l: "ol", title: "Ordered List"}]
{
Log.Add("<p class='Orange2'>" SpanNow() "<b> " list.title "</b></p>")
Log.Add("<" list.l ">")
Loop 2
{
Log.AddToLastTag("<li class='Yellow'>" list.title " row n. " . A_Index . "</li>", list.l)
Sleep, 500
}
}
*/
/*
; Clear LOG
; =========
Log.Clear()
Sleep, 500
Log.Add("<h3>Restart...</h3>")
*/
; Table and style
; ===============
log.Add("<br /><h4>" . SpanNow() . "Add table and style <span class='Gray'>Add()</span>" . "</h4>")
css=
(
<style>
table {border-collapse: collapse; width: 50`%;}
td, th {border: 1px solid #dddddd; text-align: left; padding: 8px;}
table, td, th {border-style: double; border-color: #75715E;}
table {border-radius: 10px;}
</style>
)
html := "<table>"
. "<tr class='Red'>" . "<th>Time</th>" . "<th>Text</th>" . "</tr>"
. "<tr>" . "<td>" SpanNow() "</td>" . "<td class='Yellow'>text to row 1 col 2</td>" . "</tr>"
. "<tr>" . "<td>" SpanNow() "</td>" . "<td class='Yellow'>text to row 2 col 2</td>" . "</tr>"
. "</table>"
Log.Add(html . css)
*/
; ReplaceLastTag can create new tag to replace
; ============================================
log.Add("<p class='Red'><br /><br />" . SpanNow() . "Replace last tag creating new one <span class='Gray'>ReplaceLastTag()</span>" . "</p>")
for i, TEXT in ["THIS TEXT", "WILL BE", "REPLACED", "OR DELETED"]
{
Log.ReplaceLastTag("<p class='Replace'>" . TEXT . "</p>", "p", StartNewTag := ((i=1) ? "<p>" : 0))
Sleep, 1000
}
Log.DeleteLastTag("p")
Log.ReplaceLastTag("<p class='Red'>Delete this tag too</p>", "p")
Sleep, 2000
Log.DeleteLastTag("p")
*/
; Connect ids to local functions
; ==============================
log.Add("<br /><h4>" . SpanNow() . "Connect ids to local functions <span class='Gray'>OnClick()</span>" . "</h4>")
Log.Add("<p>" SpanNow() "<span class='Yellow'>Connect <input type=""button"" id=""CenterThisWin"" value=""CenterThisWin""> to <span Class='Green'>CenterThisWin()</span></p>")
Log.OnClick("CenterThisWin")
Log.Add("<p>" SpanNow() "<span class='Yellow'>Connect <input type=""button"" id='CloseStatusBar' value=""CloseStatusBar""> to <span Class='Green'>CloseStatusBar()</span></p>")
Log.OnClick("CloseStatusBar")
Log.Add("<p>" SpanNow() "<span class='Yellow'>Connect <a id=""SaveLog"" href="""">Save log as html</a> to <span Class='Green'>SaveLog()</span></p>")
Log.OnClick("SaveLog")
*/
;log.Add("<p style='border: 1px solid #cc342e; border-radius: 15px; font-size: 25px;'>TExt</p>")
/*
; Timeout
; =======
Log.StatusBar.InnerHtml := "<b style='color: Red; font-size:30px;'>TIMEOUT 5 sec</b>"
Log.Timeout(Ms := "5000")
*/
Log.Add("<br /><br /><a class=""Menu"" href=""#Anchor"">Autohotkey logo<a>")
Log.Add(" <a class=""Menu"" href='' id='Reload'>Reload<a>")
Log.OnClick("Reload")
Log.Add("<p class='Gray'>" SpanNow() "Waiting close to exit...</p>")
*/
Log.WaitClose()
ExitApp
SpanNow(){
FormatTime, Now, A_Now, hh:mm:ss
Return "<span style='font-size:13px;' class='Gray'>" . Now . " </span>"
}
CenterThisWin(wb){
Log.Show(,, "")
}
CloseStatusBar(wb){
Log.StatusBar.Innertext := ""
}
SaveLog(wb){
FileSelectFolder, Folder, A_ScriptDir
if ErrorLevel
Return
Log.Save(File := Folder "\HtmlLogClassSample.html")
Log.Add("<p>" . "<a href=""" File """>Page saved here " File " </a>" . "</p>")
Log.Add("<p>" . "<a href=""" Folder """>Open folder " Folder " </a>" . "</p>")
}
Reload(){
Reload
}