Dynamically change icon in HTA - image

NOTE: This question is not a duplicate of Can I embed an icon to a .hta file? - For more details, compare the issues and read the comments
I am trying to build an HTA that will automatically perform certain tasks when executed, without user action. The reason I want to use an HTA instead of just a bare VBScript is to inform the user of progress as the routine executes, since it takes some time, and I don't want the user wondering if it hung, maybe restarting it, and so on. There are ten tasks, and I would like to have ten lines in my HTA display, each one with a few words describing what is happening at that point. So far, so good – that is simple enough.
I would also like to have a small icon before each line, that would initially display one icon. When the task on that line begins, it would switch to a second icon, and when it completes it would switch to a third icon.
For several reasons not pertinent to my question, I want to keep it ALL in my HTA – no references to external files. I found a site that led me to using a tag like:
<img src='data:image/gif;base64,R0lGODlhIAAgAOY…'/>
to display a green check mark. It does that very nicely, but I would like to change that dynamically, and there I am running aground. In my HTA, I have VBScript that does this:
x="<img src='data:image/gif;base64,R0lGODlhIAAgAOY…'/>"
(Shortened – the actual image string is quite long.)
and then I have:
img1.InnerHTML = x
to refer to this placeholder in my HTML code:
<span id = "img1"></span>
The code executes, but does not display the green check, only a small black square with a white 'x'. Am I doing something wrong, or is this just not possible? It seems like it should be possible, but no syntax I have tried so far has worked.

It seems that this question is now unlocked, so I am posting the two answers that I posted in the comments.
The first answer is more imperative, in that we need Javascript to convert SVG into a data URI via the svgToDataURL() function. This example is good because you can see the SVG definition in clear text which makes it easier to maintain and change.
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<script>
function svgToDataURL(svg) {
return "data:image/svg+xml;charset=utf-8," + encodeURIComponent(svg);
//return "data:image/svg+xml;base64," + btoa(svg); // this works too!
//return "data:image/svg+xml;charset=utf-8," + svg; // this only works in modern browsers
}
var assets = {
redCross: svgToDataURL('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path stroke="red" d="M23.985 8.722L16.707 16l7.278 7.278-.707.707L16 16.707l-7.278 7.278-.707-.707L15.293 16 8.015 8.722l.707-.707L16 15.293l7.278-7.278z"/></svg>'),
greenTick: svgToDataURL('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32"><path stroke="green" d="M13.5 22.142L7.59 16.42l.636-.636L13.5 20.87 26.721 7.8l.637.637z"/></svg>')
};
</script>
</style>
</head>
<body>
1 + 1 = 2 <img id="demoSVG" width="16" height="16"> <p>
<script>
var demoSVG = document.getElementById("demoSVG");
demoSVG.src = assets.redCross;
</script>
<button type="button" onclick="demoSVG.src = assets.greenTick">Change SVG!</button>
</body>
</html>
The second answer uses CSS style to configure the image as a background style. This means the Javascript required to change the image is shorter. However, it requires you to URL encode your SVG. Note that this full encoding requirement exists because HTA is more sensitive to what it accepts as a URL. If this was an HTML question instead of HTA, the URL encoding requirement is relaxed and you could have used unencoded SVG in this solution as well.
<html>
<head>
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<style>
div.redCross {
display: inline-block;
width: 16px;
height: 16px;
background-image: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20stroke%3D%22red%22%20d%3D%22M23.985%208.722L16.707%2016l7.278%207.278-.707.707L16%2016.707l-7.278%207.278-.707-.707L15.293%2016%208.015%208.722l.707-.707L16%2015.293l7.278-7.278z%22%2F%3E%3C%2Fsvg%3E);
}
div.greenTick {
display: inline-block;
width: 16px;
height: 16px;
background-image: url(data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20viewBox%3D%220%200%2032%2032%22%3E%3Cpath%20stroke%3D%22green%22%20d%3D%22M13.5%2022.142L7.59%2016.42l.636-.636L13.5%2020.87%2026.721%207.8l.637.637z%22%2F%3E%3C%2Fsvg%3E);
}
</style>
</head>
<body>
<div>1 + 1 = 2 <div id="demo2" class="redCross"></div></div> <p>
<script>
var demo2 = document.getElementById("demo2");
</script>
<button type="button" onclick="demo2.className = 'greenTick'; ">Change SVG!</button>
</body>
</html>

Below, are two examples that demonstrate how to dynamically select among different base64 embedded images (icons) in an HTA file. The first one switches the display style from none to inline to cycle through the images. The second one changes the image by replacing the innerHTML contents. The complete examples are here.
Here are the examples with the base64 code truncated:
Example 1:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<script language="VBScript">
window.resizeTo 250,350
Dim Text,TextIndex
Text = "ABCD"
TextIndex = 1
Sub window_onLoad
idTitle.innerText = Text
document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
Sub GoLeft
If TextIndex=1 Then Exit Sub
document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "none"
TextIndex = TextIndex - 1
document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
Sub GoRight
If TextIndex=Len(Text) Then Exit Sub
document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "none"
TextIndex = TextIndex + 1
document.getElementById(Mid(Text,TextIndex,1)).Style.Display = "inline"
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
</script>
<style>
body {background-color:Black; color:White}
.NoShow {display:none}
.Show {display:inline}
.LgFont {font-size:24pt}
</style>
</head>
<body>
<h2 id=idTitle></h2>
<img id=A class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
<img id=B class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
<img id=C class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
<img id=D class=NoShow src='data:image/gif;base64,iVBORw0KGgo...'>
<br><br>
<input class=LgFont id=GL type=button value=👈 onClick=GoLeft()>
<input class=LgFont id=GR type=button value=👉 onClick=GoRight()>
<span class=LgFont id=idLetter>
</body>
</html>
Example 2:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<script language="VBScript">
window.resizeTo 250,350
Const BeginTag = "<img src='data:image/gif;base64,"
Const EndTag = "'>"
Dim Text,TextIndex
ReDim AImg(128)
AImg(65) = "iVBORw0KGgo..."
AImg(66) = "iVBORw0KGgo..."
AImg(67) = "iVBORw0KGgo..."
AImg(68) = "iVBORw0KGgo..."
Text = "ABCD"
TextIndex = 1
Sub window_onLoad
idTitle.innerText = Text
idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
Sub GoLeft
If TextIndex=1 Then Exit Sub
TextIndex = TextIndex - 1
idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
Sub GoRight
If TextIndex=Len(Text) Then Exit Sub
TextIndex = TextIndex + 1
idImage.innerHTML = BeginTag & AImg(Asc(Mid(Text,TextIndex,1))) & EndTag
idLetter.innerText = Mid(Text,TextIndex,1)
End Sub
</script>
<style>
body {background-color:Black; color:White}
.LgFont {font-size:24pt}
</style>
</head>
<body>
<h2 id=idTitle></h2>
<div id=idImage></div>
<br><br>
<input class=LgFont id=GL type=button value=👈 onClick=GoLeft()>
<input class=LgFont id=GR type=button value=👉 onClick=GoRight()>
<span class=LgFont id=idLetter>
</body>
</html>

Related

Activate and Focus HTA window using VBscripting

I have developed several HTA files where each file calls the other.
There is one HTA file that i need (if called) to stay as the "Always on top" window while it is open.
I have tried "AppActivate" function thru an infinite loop using Vb script however i always find that it activates the window in the taskbar but does not make the HTA file always on top.
Searched up and down, couldn't find working way to get it working in reliable way that does not involve 3rd party applications.
My HTA file code:
<html>
<hta:application id="oHTA"
border="none"
caption="no"
contextmenu="no"
innerborder="no"
scroll="no"
showintaskbar="no"
/>
<script language="VBScript">
Sub Window_OnLoad
'Resize and position the window
width = 133 : height = 25
window.resizeTo width, height
window.moveTo ((Screen.Width / 3)*2),0
End Sub
Sub CallMain ()
Set objShell = CreateObject("WScript.Shell")
objShell.Run("Main.hta")
window.close 'close this HTA
End Sub
</script>
<body background="Strt.png" onclick="CallMain">
</html>
Any suggestions would be appreciated.
Here's an example HTA with multiple pages. This should simplify the issue of focus.
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<meta charset="UTF-8" http-equiv="X-UA-Compatible" content="IE=9">
<hta:application id=oHTA
border=none
caption=no
contextmenu=no
innerborder=no
scroll=no
showintaskbar=no
>
<script language="VBScript">
Set oWSH = CreateObject("Wscript.Shell")
Set oFSO = CreateObject("Scripting.FileSystemObject")
MyPath = Mid(document.URL,8)
MyFolder = oFSO.GetParentFolderName(MyPath)
oWSH.CurrentDirectory = MyFolder
Sub window_onLoad
StartPage
End Sub
Sub StartPage
HideAllPages
window.document.body.background = "Strt.png"
iStartPage.style.display = "inline"
window.resizeTo 133, 25
window.moveTo ((screen.availWidth / 3)*2),0
End Sub
Sub MainPage
HideAllPages
window.document.body.background = "Main.png"
iMainPage.style.display = "inline"
CenterWindow 800,600
End Sub
Sub SubPage1
HideAllPages
window.document.body.background = "Sub1.png"
iSubPage1.style.display = "inline"
CenterWindow 640,480
End Sub
Sub SubPage2
HideAllPages
window.document.body.background = "Sub2.png"
iSubPage1.style.display = "inline"
CenterWindow 640,480
End Sub
Sub HideAllPages
iStartPage.style.display = "none"
iMainPage.style.display = "none"
iSubPage1.style.display = "none"
iSubPage2.style.display = "none"
End Sub
Sub CenterWindow(x,y)
window.resizeTo x, y
window.moveTo (screen.availWidth - x)/2, (screen.availHeight - y)/2
End Sub
</script>
<style>
body {background-size:cover; background-attachment:fixed; background-repeat:no-repeat}
.sb {background-color:transparent; background-repeat:no-repeat; border:none;
cursor:pointer; overflow:hidden; outline:none; width:100%}
</style>
<body>
<div id=iStartPage>
<input class=sb type=button onclick=MainPage()>
</div>
<div id=iMainPage>
<input type=button value=Back onclick=StartPage()>
<input type=button value=SubPage1 onclick=SubPage1()>
<input type=button value=SubPage2 onclick=SubPage2()>
</div>
<div id=iSubPage1>
<input type=button value=Back onclick=MainPage()>
</div>
<div id=iSubPage2>
<input type=button value=Back onclick=MainPage()>
</div>
</body>
</html>

Classic ASP Auto complete

I'm using classic ASP to create an auto-complete page. I have two different pages, autocomplete.asp and source.asp. My code as below:
autocomplete.asp
<%# language="VBScript" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>jQuery UI Autocomplete - Default functionality</title>
<link rel="stylesheet" href="//code.jquery.com/ui/1.11.1/themes/smoothness/jquery-ui.css">
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
<script src="//code.jquery.com/ui/1.11.1/jquery-ui.js"></script>
<link rel="stylesheet" href="/resources/demos/style.css">
<!-- SCRIPT FOR AUTOCOMPETE SEARCH BOX //-->
<script type="text/javascript" language="javascript">
$(function () {
$("#productname").autocomplete({
source: "source.asp",
minLength: 2
});
});
</script>
</head>
<body>
<p> </p>
<div class="ui-widget">
<label for="tags">Tags: </label>
<input id="productname">
</div>
<p> </p>
</body>
</html>
sourse.asp
<%# language="VBScript" %>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2 /jquery.js" ></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/jquery-ui.js" ></script>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/base/jquery-ui.css"/>
<!-- SCRIPT FOR AUTOCOMPETE SEARCH BOX //-->
</head>
<%
Dim keywords, keywords_cmd, output, firstItem
Set keywords_cmd = Server.CreateObject ("ADODB.Command")
keywords_cmd.ActiveConnection = "DRIVER={SQL Server};SERVER=wsgpdba4.sgp.is.keysight.com;UID=kportal;PWD=q1w2e3r4;DATABASE=A_Sys"
keywords_cmd.CommandText = "SELECT ProductId FROM Product where ProductId like '%" & Request.QueryString("term") & "%'"
keywords_cmd.Prepared = true
Set keywords = keywords_cmd.Execute
output = "["
While (NOT keywords.EOF)
output = output & "{""ProductId"":""" & keywords.Fields.item("ProductId") & """},"
keywords.MoveNext()
Wend
keywords.Close()
Set keywords = Nothing
output=Left(output,Len(output)-1)
output = output & "]"
response.write output
%>
<body>
</body>
</html>
The source.asp return me like this:
[{"ProductId":"111 "}]
Please help
I had to work on a legacy program recently. I had to get autosuggest to work with SQL and ASP. This is what I came up with.
<%# Language=VBScript %>
<!-- #include File="CarrierAutocomplete.inc"-->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<link href="jquery-ui-1.12.1.custom/jquery-ui.css">
<script src="jquery-ui-1.12.1.custom/external/jquery/jquery.js"></script>
<script src="jquery-ui-1.12.1.custom/jquery-ui.js"></script>
<script>
$(function() {
var strCarriers = [<%=getListOfCarriers()%>];
$( "#carrier_name" ).autocomplete({
source: strCarriers
});
});
</script>
</head>
<body>
<table>
<tr>
<td align="right"><p><b>CARRIER:</b></td>
<label for="carrier_name"></label></td>
<td><input id="carrier_name" name="carrier_name"></td>
</tr>
</table>
</body>
</html>
'CarrierAutoComplete.inc
<!--#include file="ConnStrings.inc"--> 'you won't need this
<%
Function getListOfCarriers()
Set conn = Server.CreateObject("ADODB.Connection")
Set rs = Server.CreateObject("ADODB.Recordset")
Dim sql
Dim allCarriers
Dim strCarriers
Dim n
'conn.Open ConnString 'PRODUCTION
conn.Open ConnString 'DEVELOPMENT
sql = "SELECT [carrier] FROM [dbo].[VerifiedCarriers] order by carrier"
Set RS = Conn.Execute(sql)
if not rs.eof and err.number=0 then
allCarriers = rs.getrows
End If
colStart = LBound(allCarriers, 1)
colEnd = UBound(allCarriers, 1)
rowStart = LBound(allCarriers, 2)
rowEnd = UBound(allCarriers, 2)
For row=rowStart to rowEnd
For col=colStart to colEnd
strCarriers = strCarriers + """" & "" & allCarriers(col,row) & """," & chr(13)
Next
Next
strCarriers = Left(strCarriers,Len(strCarriers) - 2) 'REMOVE THE LAST COMMA
response.write strCarriers
End Function
%>
I'm not 100% clear on the issue here, but the jquery ui control needs to have data in an expected form of value and label:
[{"value":"111", "label":"sample product"}]
Or you can just supply an array of strings if you're not concerned about the values:
["product one", "product two"]
You're also not selecting the product name from your db, just the Id, as I assume your autocomplete needs to show a list of product names?

put a mouseover on text display image in div in java script

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function show1() {
document.getElementById("img1").display = 'block';
}
function hide1() {
document.getElementById("img1").display = 'none';
}
</script>
</head>
<body>
<span onMouseOver="show1()" onMouseOut="hide1()">Corporate Team Outing - LNT</span>
<div id="img1" style="display:none">
<img src="" alt="image 1" />
<img src="" alt="image 2" />
</div>
</body>
</html>
i want that when u put mouse on text it show image in div i m trying to do it but it not working.
Forget javascript for this one! CSS is the answer. Put a hover state on ID:img1 and the images inside the div (if u don't do the latter, mousing over the images will cancel out the div mouse over. So it will look like this (not inline styles due to mouse over states declaration):
#img1 {
Background-image: none;
}
#img1:hover, img1:hover img {
Background-image: url(your URL);
}
You could change the IDs to classes, so the CSS can be reused and keep the IDs for coding (javascript etc)

Add image to page onclick

I want a button to add an image to the current page on each click. For example, the first time you open the page, there is one picture. Then you click the button and the same picture appears on the page and now you have two same pictures. Then you keep on pressing on the button and more and more same pictures appear. This is the code I tried that didn't work:
<script type="text/javascript">
function addimage() {<img src="http://bricksplayground.webs.com/brick.PNG" height="50" width="100">}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>
</html>
Please help! Thanks.
You should probably know that javascript can create html elements, but you cannot directly embed html inside javascript (they are two completely separate things with different grammars and keywords). So it's not valid to have a function that only contains html -- you need to create the elements you want, and then append them to the dom elements that you want them to. In this case, you create a new image and then append it to the body.
<html>
<body>
<script type="text/javascript">
function addimage() {
var img = document.createElement("img");
img.src = "http://bricksplayground.webs.com/brick.PNG";
img.height = 50;
img.width = 100;
//optionally set a css class on the image
var class_name = "foo";
img.setAttribute("class", class_name);
document.body.appendChild(img);
}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>
</html>
All you're missing is a method to write the element on the page
<script type="text/javascript">
function addimage() {
document.write('<img src="http://bricksplayground.webs.com/brick.PNG" height="50" width="100">')
}
</script>
</head>
<body>
<button onclick="addimage();">Click</button>
</body>

AJAX options box when clicking on a word?

Is this possible ? like I have this phrase on a textbox:
"I went home"
then when I click "home" an options box shows up like:
"I entered home"
|garden|
| motel|
|______|
sorry for my ugly way to show it, couldn't think about anything better lol
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(function(){
$("#fieldName").focus(function(){
var el = $(this);
var coords = el.offset();
var div = $("<div>").addClass("dropdown").html("<span>garden</span><span>motel</span>").css({"top":coords.top+18+"px","left":coords.left+45+"px"});
el.after(div);
$(".dropdown span").click(function(){
var newText = "I entered the " + $(this).text();
$("#fieldName").val(newText);
$("div.dropdown").remove();
});
});
});
</script>
<style>
.text {width:120px;}
.dropdown {width:75px; text-align:right; position:absolute; padding:2px; background:#eee; border:1px solid #aaa;}
.dropdown span {display:block; cursor:pointer;}
</style>
</head>
<body>
<input type="text" class="text" name="fieldName" id="fieldName" value="I entered the home" />
</body>
</html>
You'll need a copy of jquery (or point to Google's CDN of it) for this to work. This example's pretty primitive, but hopefully it'll get you where you want to go.

Resources