ALYB
December 21, 2023, 9:28am
1
I asked ChatGPT to "Write the code for an html page that contains two vertical multi-line edit boxes next to each other, a Cancel button and an OK button. The width of the page should be 1000 px". It did a good job and returned a page that looks like this in Safari:
Now I'd like to use this html code in an html prompt, and I have the following questions
How to adjust the html code / macro to display both edit boxes?
How to preset both edit boxes with Local_sourceTerms and Local_targetTerms upon calling the form?
How to save any edits to Local_sourceTerms and Local_targetTerms upon clicking OK
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two Vertical Multi-line Textboxes</title>
<style>
body {
width: 1000px;
margin: 20px auto; /* Center the content */
font-family: Arial, sans-serif;
}
.textbox {
width: 45%; /* Set the width of each textbox */
height: 150px; /* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
}
.button-container {
display: flex;
justify-content: space-between;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<textarea class="textbox" placeholder="Textbox 1"></textarea>
<textarea class="textbox" placeholder="Textbox 2"></textarea>
<div class="button-container">
<button onclick="cancelClicked()">Cancel</button>
<button onclick="okClicked()">OK</button>
</div>
<script>
function cancelClicked() {
alert('Cancel button clicked!');
}
function okClicked() {
alert('OK button clicked!');
}
</script>
</body>
</html>
Test - Add new term pairs via form.kmmacros (2.7 KB)
If you decorate each of those two textareas with a distinct id attribute,
you can obtain a reference to their .value
(i.e. to any entered text)
with document.getElementById(idString).value
.
e.g.
Expand disclosure triangle to view HTML source
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two Vertical Multi-line Textboxes</title>
<style>
body {
width: 1000px;
margin: 20px auto;
/* Center the content */
font-family: Arial, sans-serif;
}
.textbox {
width: 45%;
/* Set the width of each textbox */
height: 150px;
/* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
}
.button-container {
display: flex;
justify-content: space-between;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<textarea id="leftBox" class="textbox" placeholder="Textbox 1"></textarea>
<textarea id="rightBox" class="textbox" placeholder="Textbox 2"></textarea>
<div class="button-container">
<button onclick="cancelClicked()">Cancel</button>
<button onclick="okClicked()">OK</button>
</div>
<script>
function cancelClicked() {
alert('Cancel button clicked!');
}
function okClicked() {
const
[leftText, rightText] = [
"leftBox", "rightBox"
]
.map(k => document.getElementById(k).value);
alert(`${leftText}\n\n${rightText}`);
}
</script>
</body>
</html>
ALYB
December 21, 2023, 12:42pm
3
Thank you. But my knowledge is so poor that I cannot combine this to a macro. Could you please help?
Clicking Help
in the Floating HTML Prompt action's gearwheel takes us to:
action:Custom HTML Prompt [Keyboard Maestro Wiki]
Where we get details for:
Setting height and width (e.g. by supplying a value string to a data-kmwindow
attribute in the HTML <body>
tag
Initialising values in the body of a custom KMInit
function
Reading HTML page values and updating KM variable values in the body of a custom KMWillCloseWindow
function.
Others, with more experience of these prompts, can probably show something closer to best practice, but roughly:
Parallel editable text areas (in KM HTML prompt).kmmacros (8.7 KB)
Expand disclosure triangle to view HTML source
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two Vertical Multi-line Textboxes</title>
<style>
body {
width: 1000px;
margin: 20px auto;
/* Center the content */
font-family: Arial, sans-serif;
}
.textbox {
width: 45%;
/* Set the width of each textbox */
height: 150px;
/* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
}
.button-container {
display: flex;
justify-content: space-between;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body data-kmwindow="SCREEN(Main,Left,20%),SCREEN(Main,Top,20%),1000,500">
<textarea id="leftBox" class="textbox"></textarea>
<textarea id="rightBox" class="textbox"></textarea>
<div class="button-container">
<button
name="Cancel"
type="button"
onclick="window.KeyboardMaestro.Cancel('Cancel')">Cancel</button>
<button name="OK" type="button" onclick="window.KeyboardMaestro.Submit('OK')">OK</button>
</div>
<script>
function KMInit() {
const kmVar = window.KeyboardMaestro.GetVariable;
document.getElementById("leftBox").value = (
kmVar("Local_sourceTerms")
);
document.getElementById("rightBox").value = (
kmVar("Local_targetTerms")
);
}
function KMWillCloseWindow() {
const
km = window.KeyboardMaestro,
boxValue = k =>
document.getElementById(k).value;
km.SetVariable(
"Local_updatedSourceTerms",
boxValue("leftBox")
);
km.SetVariable(
"Local_updatedTargetTerms",
boxValue("rightBox")
);
}
</script>
</body>
</html>
Or expressing the (initial) write and (final) read events in terms of .forEach
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Two Vertical Multi-line Textboxes</title>
<style>
body {
width: 1000px;
margin: 20px auto;
/* Center the content */
font-family: Arial, sans-serif;
}
.textbox {
width: 45%;
/* Set the width of each textbox */
height: 150px;
/* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
}
.button-container {
display: flex;
justify-content: space-between;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body data-kmwindow="SCREEN(Main,Left,20%),SCREEN(Main,Top,20%),1000,500">
<textarea id="leftBox" class="textbox"></textarea>
<textarea id="rightBox" class="textbox"></textarea>
<div class="button-container">
<button name="Cancel" type="button" onclick="window.KeyboardMaestro.Cancel('Cancel')">Cancel</button>
<button name="OK" type="button" onclick="window.KeyboardMaestro.Submit('OK')">OK</button>
</div>
<script>
function KMInit() {
[
["leftBox", "Local_sourceTerms"],
["rightBox", "Local_targetTerms"]
]
.forEach(
([boxName, kmVarName]) =>
document.getElementById(boxName)
.value = window.KeyboardMaestro
.GetVariable(kmVarName)
)
}
function KMWillCloseWindow() {
[
["leftBox", "Local_updatedSourceTerms"],
["rightBox", "Local_updatedTargetTerms"]
]
.forEach(
([boxName, kmVarName]) =>
window.KeyboardMaestro.SetVariable(
kmVarName,
document.getElementById(boxName)
.value
)
);
}
</script>
</body>
</html>
1 Like
ALYB
December 21, 2023, 8:34pm
5
Thank you so much for your great help. I can now do beautiful things with this code.
1 Like
ALYB
December 23, 2023, 10:29am
6
"Beautiful things" like this:
Add new term pairs via form.kmmacros (13.5 KB)
One last improvement that I want to make and for which I cannot find the answer on the web: How to horizontally center these two edit boxes, since the form is quite ugly now:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>New term pairs</title>
<style>
body {
width: 800px;
margin: 20px auto;
/* Center the content */
font-family: Arial, sans-serif;
}
.textbox {
width: 45%;
/* Set the width of each textbox */
height: 300px;
/* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
font-size: 15px;
}
.button-container {
display: flex;
justify-content: center;
width: 90%;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body data-kmwindow="SCREEN(Main,Left,30%),SCREEN(Main,Top,30%),800,390">
<textarea id="leftBox" class="textbox"></textarea>
<textarea id="rightBox" class="textbox"></textarea>
<div class="button-container">
<button
name="Cancel"
type="button"
onclick="window.KeyboardMaestro.Cancel('Cancel')">Cancel</button>
<button name="OK" type="button" onclick="window.KeyboardMaestro.Submit('OK')">OK</button>
</div>
<script>
function KMInit() {
const kmVar = window.KeyboardMaestro.GetVariable;
document.getElementById("leftBox").value = (
kmVar("Local_sourceTerms")
);
document.getElementById("rightBox").value = (
kmVar("Local_targetTerms")
);
}
function KMWillCloseWindow() {
const
km = window.KeyboardMaestro,
boxValue = k =>
document.getElementById(k).value;
km.SetVariable(
"Local_updatedSourceTerms",
boxValue("leftBox")
);
km.SetVariable(
"Local_updatedTargetTerms",
boxValue("rightBox")
);
}
</script>
</body>
</html>
1 Like
ALYB
December 23, 2023, 11:48am
7
And then I thought, why not ask ChatGPT again, about how to horizontally center the two text boxes:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Centered Multi-line Textboxes and Buttons</title>
<style>
body {
width: 1000px;
margin: 20px auto; /* Center the content horizontally */
font-family: Arial, sans-serif;
}
.container {
text-align: center; /* Center the children horizontally */
}
.textbox {
width: 45%; /* Set the width of each textbox */
height: 150px; /* Set the height of each textbox */
box-sizing: border-box;
padding: 8px;
margin-bottom: 10px;
}
.button-container {
display: inline-block; /* Maintain inline block to center */
margin-top: 10px;
}
.button-container button {
padding: 10px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<textarea class="textbox" placeholder="Textbox 1"></textarea>
<textarea class="textbox" placeholder="Textbox 2"></textarea>
<div class="button-container">
<button onclick="cancelClicked()">Cancel</button>
<button onclick="okClicked()">OK</button>
</div>
</div>
<script>
function cancelClicked() {
alert('Cancel button clicked!');
}
function okClicked() {
alert('OK button clicked!');
}
</script>
</body>
</html>
Nice!