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>
I have been working through a yt tutorial on Web Components by Brad Traversy, a great teacher with great content, as I'm sure many of you already know :)
I've gotten up to the 17 minute mark, though the problem I'm having is that the images are not displaying as they are in the tutorial...
They are being added to the document flow... I can tell this because the layout re-adjusts to accommodate the space for an image... it's just that the image is not displayed...
Just for comparison, I added a image of a similar nature directly in the html and it works fine.
Anyway, here is my code...
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Web Components Example</title>
<style>
h3 {
color: purple;
}
</style>
</head>
<body>
<h3>Hello World... where's the images?!?!?</h3>
<!-- <user-card name="you oddo" avatar="https://randomuser.me/api/portraits/men/1.jpg"></user-card> -->
<user-card name="huik popp" avatar="38.jpg"></user-card>
<user-card name="som otha"></user-card>
<img src="95.jpg">
<style>h3 {color: green}</style>
<script src="userCard.js"></script>
</body>
</html>
and the Javascript...
UserCard.js:
const template = document.createElement('template');
template.innerHTML = `
<style>
h3 {
color: coral;
}
</style>
<div class="user-card">
<img />
<div>
<h3></h3>
</div>
</div>
`;
class UserCard extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
this.shadowRoot.querySelector('h3').innerText = this.getAttribute('name');
this.shadowRoot.querySelector('img').innerText = this.getAttribute('avatar');
}
}
window.customElements.define('user-card', UserCard);
I'd appreciate any help with this very much. I've been enjoying following along with this tutorial so far and well, would like to keep up with how things look in the video.
Many thanks.
I'm answering my question here...
In userCard.js, I have:
this.shadowRoot.querySelector('img').innerText = this.getAttribute('avatar');
It should be:
this.shadowRoot.querySelector('img').src = this.getAttribute('avatar');
Tell Brad he can shorten the code to:
class UserCard extends HTMLElement {
constructor() {
super()
.attachShadow({ mode: 'open'})
.innerHTML = `
<style>
h3 {
color: coral;
}
</style>
<div class="user-card">
<img />
<div>
<h3></h3>
</div>
</div>
`;
...
}
);
If I surround an img tag with a span and put the mouseover in the span it works. If I don't have the span and just put the mouseover in the img, it doesn't (see single line of html in body).
Can I not append a child directly to an image?
<html>
<script type="text/javascript">
function showMsg(obj) {
var spn;
spn = document.createElement('span');
spn.innerHTML = "test message";
obj.appendChild(spn);
obj.onmouseout = function() {obj.removeChild(spn)};
}
</script>
<body>
<img onmouseover="showMsg(this)" src="http://www.w3schools.com/jsref/smiley.gif">
<!--
<span onmouseover="showMsg(this)"><img src="http://www.w3schools.com/jsref/smiley.gif"></span>
-->
</body>
</html>
No, an <img> is a void element.
What you could do, however, is use a transparent div that covers the imageand append it to that.
I have a DOM and I want to insert a new node using Hpricot. Here my DOM structure:
<html>
<head>
</head>
<body>
...
...
</body>
</html>
What I want is I have to insert a script tag as a last child of <body> something like:
<body>
...
<script>
console.log(document.cookie)
</script>
</body>
This is what I have:
doc = Hpricot.XML(%{<html>
<head>
</head>
<body>
...
...
</body>
</html>
})
doc.at('body')
But now I'm not getting any desired method to move forward and the documentation of hpricot sucks. Has anyone done this before?
Achieved but using Nokigiri pasting it incase if someone want to do this
Here the HTML
h1 = Nokogiri::XML.parse %{<html>
<head>
<script>
alert("hello");
</script>
</head>
<body>
<p> THIS IS WAR </p>
</body>
</html>}
apend your tag (my case script tag) as last child of body
h1.search('body').children.after(%{<script> alert ('Hello') </script>})
Hope this help to some
Now i done the ADD /Remove Elements
How to add/remove elements dynamically, pease find the image attachment, which shows the better understand,
category which populate records from database category table, and when user select the particular category than sub category will populate from datbase sub category table,
am looking one jquery or some open which do this same work,
refer some good plugins,
How to add the element when i click the ADD Elment, please chekc my code below
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<title>Untitled Document</title>
<script type="text/javascript" src="jquery-1.3.2.min.js"></script>
<script type="text/javascript" >
$(document).ready(function(){
var hdn_add_element_cnt = $("#hdn_add_element_cnt").val();
hdn_add_element_cnt = parseInt(hdn_add_element_cnt);
var app_str = "<div id=element_"+hdn_add_element_cnt+">New Element "+hdn_add_element_cnt+" Delete</div>";
$('#element_area').append(app_str);
$("#add_element").click(function(){
var hdn_add_element_cnt = $("#hdn_add_element_cnt").val();
hdn_add_element_cnt = parseInt(hdn_add_element_cnt);
hdn_add_element_cnt = hdn_add_element_cnt+1;
var app_str = "<div id=element_"+hdn_add_element_cnt+">New Element "+hdn_add_element_cnt+" Delete</div>";
$('#element_area').fadeIn(10000).append(app_str);
//Increment Elemenet ID Count +1
document.getElementById("hdn_add_element_cnt").value = hdn_add_element_cnt;
})
})
function delete_element(element_id_no){
var get_element_hidden_cnt = $("#hdn_add_element_cnt").val();
$("#element_"+element_id_no).fadeOut(100).remove();
}
</script>
</head>
<body>
<div style="width:500px; height:200px; background-color:#FF0000;">
<div id="add_element" style="width:400px; height:75px;">
ADD Element
</div>
<div id="element_area">
</div>
</div>
<input type="hidden" id="hdn_add_element_cnt" value="1" />
</body>
</html>
jQuery doesn't need plugins to do this. Standard functions work well:
.append() adds elements, so to add a <div> to the <body>, just do this:
$('body').append('<div id="foobar">This is my text</div>');
.remove() similarly removes elements, so to remove that <div> that you added, just do this:
$('#foobar').remove();
.html() and .text() can be used to set the contents of an element. .text() is usually for setting the displayed text, and .html() is for adding content elements:
$('#foobar').text('Hello');
$('#foobar').html('<h1 class="foo">Hello</h1>');
Your question is really vague, so I'm not sure what else to say.