Webtalk is a web-implementation of HyperTalk. That doesn't mean you have to be online to run it. You can download it and run it from a computer with no internet connection.
So what does webtalk do?
Webtalk is loosely based on the HyperTalk scripting language, and the goal is to be compatible in most major respects. There are additions to it and perhaps things missing from it. The boring bit is I'm not implying it's fit for any particular purpose, and there's no guarantees implied or otherwise about how it might run on your system. (Being based on Javascript and CSS, it heavily relies on what your browser is capable of).
The point of it is it's a programming language that's easy to type and understand.
For example, If I wanted to output the current date in javascript, I'd have to type:
Javascript Code:
const now = new Date();
const days = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
const dayName = days[now.getDay()];
const dateTimeString = now.toLocaleString();
document.getElementById('datetime').textContent = `${dayName}, ${dateTimeString}`;
Javascript Result:
And although to do that in Python is simpler, it's not as readable:
Python Code:
from datetime import datetime
now = datetime.now()
formatted = now.strftime("%A, %d/%m/%Y, %H:%M:%S")
print(formatted)
Which again, gives us this:
Python Result:
Whereas, if I want to do that in HyperTalk, I'd be able to use:
Hypertalk Script:
put item 1 of the long date & "," && the date & "," && the time
Hypertalk Result:
However, the great thing about hyperTalk (and webtalk), is that it can also be quite flexible:
put item 1 of the long date & "," && dateFormat(the dateitems, "%d/%m/%Y") & "," && the time
HyperTalk script
HyperTalk was the programming language created in 1987 by Dan Winkler, and used in the HyperCard application, created by Bill Atkinson. Creating programs in HyperTalk was known as "scripting". HyperTalk scripts were much more similar to written English than many languages available at the time.
Webtalk script
A simple example of webtalk scripting:
This gives you an idea of what I'm aiming for here, to have something that is platform-agnostic which is capable of running HyperTalk scripts.
I'm trying to give a comparable set of features that were available in Hypertalk, but in Webtalk - so they are available to everyone. As such, there won't be specific Mac-only, Windows-only or Linux-only features implemented on this project. If I add a feature, it will be supported across all platforms.
Current progress:
The current documentation containing the release notes are here, as a PDF
You might also want to read the license agreement on that last page of the documentation too.
Download
You can download a copy of webtalk, (current version), from here. You don't need anything special to run it. Just a recent browser (if you are using Safari, needs to be version 17 or above)
Alternatively, if you prefer, you can try it as an online live demo here. You might also want to check out the testing pages, which give you a list of commands and handlers that are currently implemented.
Overview
A project overview (text file) is also available, which covers how this all works at a quick glance.
I should really mention, you can load JSON stacks with:
load stack "" -- if it can't find the file, it will ask you
Recent additions:
v181
Just a quick bit of tidy-up, improving fixes for browsers interfering with text field objects. Not much to say, other than multi-line text fields should be a lot more reliable to edit manually - however, this isn't perfect and I'm still refining it. (changes to "field-fix.js")
v182
Added the lastkeys([number]) for getting a list of the last pressed keys.
put the lastKeys(5) -- might return )5(sy
Implemented deleting lines of variable by variable line x:
put "3" into myLine
delete line myLine of myVariable
Text formatting now reapplies to multi-line fields on stack reopen.
Object IDs are now retained upon stack reopen.
Referencing objects by IDs is now much better:
put the loc of button id 2
put the number of lines in field id 1
Scrollbars no longer revert to 150px wide when you change their thumbPosition property:
set the width of scrollbar "Scrollbar 1" to 250
set the thumbPosition of scrollbar "Scrollbar 1" to 52
v183
Added vScroll position function for when you scroll a field.
on scrollbarDrag newValue
put newValue
end scrollbarDrag
Also added the clickLine function:
on mouseDown
put "Clicked on line: " & the clickLine of me
end mouseDown
vscroll-clickline.json
Please see the documentation for more information.
v184
Added referencing objects by ID (every combination I could think of).
Added the ability to count the number of controls of this card as well:
put the number of controls of this card
I implemented changing a button into a checkbox (the isCheckbox property on the inspector).
(You can do this through the inspector, or you can do this via script):
set the isCheckbox of btn "newcheck" to true -- turns a button into a checkbox
Buttons now also support highlighted states.
Please see the documentation for more information.
checkbox-test.json
v185
Added a couple more features today:
Added a function called angleAndDistance.
put angleAndDistance(the loc of graphic "A",the loc of graphic "B")
put angleAndDistance(the loc of graphic "A",the loc of graphic "B",diagonal)
angleAndDistance.json (or a live demo if you prefer)
I'll cover this more in the documentation. I also added a hasBattery function:
put the hasBattery
There is a gotcha with this though. It seems to work on all browsers except Firefox.
In the screenshot above, we have Firefox 140 on the left and Chromium/Chrome on the right.
Lastly, I implemented something else called closestControl:
closestControl.json
v186
I've refined the if, then, else conditional statements. They should be much improved. This now has it's own dedicated file (expressionparser.js) to work out what is actually meant in if statements, and properly parse them.
This is quite a large change, even though it won't visually seem like much has been modified. I've also been working on a few more examples and adding to the live demos.
conditional.json (or a live stack demo if you prefer)
v187
Implemented "the last object", so it's now possible to reference the last object created.
Create an object, or if you drag an object from the tools palette, you can now run:
put the last object
put the name of the last object
put the width of the last object
put the textColour of the last object
You would get back the following (as an example):
field "New field 1"
New field 1
200
black
last-object.json (live demo)
v188
I've added the ability to rotate scrollbar objects. It turns out, this is handier than I first thought.
scrollbar-rotation.json (live demo)
I've also added the export image command, although more will follow on this at a later stage.
export-tests.json (live demo)
As always, the detail is in the documentation.
v189
I've expanded the export image function I made earlier. It now supports exporting rects of things.
export the rect of button "test" to file "testbutton" as JPEG
export-tests2.json (live demo)
I've also added another type of alert dialog, which I'll explain more about in the documentation.
Lastly, objects now support having their blendLevel (transparency/alpha) set to a value between 0 and 100.
v190
I added the print command, so you can print a card or you can print a field.
More information in the documentation.
v191
A few additions in v191 are:
Gridsize
Setting the gridSize to a numerical value means that objects will snap to this when using the edit tool to move or resize them.
Stackmargin
This new command can be used to hide or show the outer card border in a webtalk stack.
locktext
I finally added the locktext option for fields. I'd actually totally forgotten about this after adding it as a placeholder a while ago.
More information in the documentation.
v192
I've added a new function called "roll image"
roll image("myimage", "new", "old", 300, bottom)
As always, more information can be found in the documentation.
roll-image.json
v193
Added to the offset functions with the addition of "lineOffset" and "itemOffset":
put lineOffset(ThingToFind,myData)
put itemOffset("yourthing",myData)
More information in the documentation on this function.
I've also been continuing work on supporting multiple cards, although this is highly experimental at the moment and is a work in progress. More to follow on this at a later date.
Added preload sound function:
preload sound "https://cdn.freesound.org/previews/554/554554_12197619-lq.mp3"
then later, use:
play "https://cdn.freesound.org/previews/554/554554_12197619-lq.mp3" -- already loaded
Then it also made sense to unload a sound too:
unload sound "https://cdn.freesound.org/previews/554/554554_12197619-lq.mp3"
v194
Continuing with my focus on sounds for the moment, you can now run the following:
put "https://mydomain.com/mysound.mp3" into myURL
get isloaded myURL
-- would return "false (0%)" if not loaded
-- would return "true (100%)" if loaded
You can also now stop, pause or resume a preloaded sound:
put "https://mydomain.com/mysound.mp3" into myURL
stop myURL -- would stop the sound if playing
pause myURL -- would pause the sound
resume myURL -- would resume playing the sound from the last paused position
You can also skip to any current position of a preloaded sound (in milliseconds):
put "https://mydomain.com/mysound.mp3" into myURL
put 14980 into myskip -- sets the skip position to 14.98 seconds
playatpos(myskip) myURL -- plays the above mp3 sound at this position
preload-sound.json (live demo)
Finally, I added VERY preliminary multi-card support. Much much more to follow on this as time progresses. As you'd expect though, you can use:
create card 2 -- creates a second card
create card "newcard" -- creates a new card after the current card, called "newcard"
delete card 3 -- deletes card 3 if it exists
put "hi" into line 1 of field "data" of card 2 -- when on card 1 currently, for example
set the backgroundColor of card 1 to "30,40,50" -- when on card 2 currently
multi-card.json
v195
I've implemented a couple more properties (well, actually a few extras too):
get the currentPlayPos "https://www.mydomain.co.uk/soundfile.mp3" -- returns current pos
get the totalPlayDuration "https://www.mydomain.co.uk/soundfile.mp3" -- returns duration
preload-sound-2.json
I then implemented the ability to retrieve waveforms of sounds, and store sounds (embed them) in a stack:
soundData.json
Please see the documentation for more details.
v196
In previous release notes, I've sometimes mentioned there's just too much to list here and "please see the documentation". Well, this time I really mean it. I've been quite busy in version 196. Please see page 79 of the documentation for all the changes.
v197
I've added an "Overview" palette. You can hide or show this by using:
show overview -- shows the palette
hide overview -- hides the palette
toggle overview -- toggles the palette
As you create objects, the palette will be populated. The idea is that you can easily see what makes up a stack, even if certain objects are hidden. If you click an object in the overview palette, it'll switch to edit mode, select the object, and show the inspector for that object.
v198
A spot of bug fixing in this version, and a couple of miniscule additions:
I noticed that the middle-click stopped working once a stack was loaded from a JSON file. I also noticed that adding new objects to a stack after being reloaded was confusing things - I fixed this, and the problem was in the clearCurrentStack() function. It now properly maintains the DOM references at all times.
What does that actually mean?
Middle mouse-click: Event listeners such as opencard, closecard, etc no longer get broken upon stack loading. Object creation: New objects will now be properly added to the stack after loading a JSON, since we're not dealing with stale references to parts of a stack that no longer exist.
Also, this means that loading a new stack from file properly replaces the content of the previous stack (this got broken somewhere).
I also added a new function:
put the isTainted -- returns true or false
This is handy in a browser context, so you can tell if you've overstepped the line with CORS restrictions (and tainted your canvas).
Added a new tweak to the answer command. We now have:
answer font -- a prompt for the user to select a font file.
We could use it like this:
on mousedown
answer font
if it is "" then exit mousedown
start using font it -- starts using the selected font
put the lastLoadedFont -- if you want a debug output of the loaded font.
put "The Quick Brown Fox Jumps Over The Lazy Dog" into field "test"
set the textFont of field "test" to the lastLoadedFont -- apply the font to the field
end mousedown
We could unload it (stop using that font) like this:
on mousedown
put the lastLoadedFont into removeFont -- can be any variable name
stop using font removeFont -- we close (stop using) the font here
end mousedown
This is all detailed on page 87 and 88 of the documentation.
v199
I added dateParse as a synonym to parseDate, and I added padCenter as a synoym for Center, so you can also use:
put dateParse("25/12/2024", "dd/mm/yyyy") -- outputs 12/25/2024
put padCenter("test", 10, "-") -- outputs "---test---" without quotes
I also tweaked the tools palette slightly with the addition of this icon:
When you click this icon, it'll change the orientation of the tools palette from horizontal to vertical (or back again).
I also made this a bit more intelligent, so if you have the palette arranged vertically, and you drag it to the left or the far right edges of the screen; the card div and the message box will move out of it's way:

Click for a larger image
v200
I've added quite a bit this time around, and I detailed all this on page 89 of the documentation.
I've also tried to give live demos of all my changes too:
continuation-character.json or live demo here.
fullscreen.json or live demo here.
more-dates.json or live demo here.
Along with a few tweaks to the UI (inspector palette and overview palette), and a few bug fixes for good measure.
v201
I've been working on pathfinding abilities of webtalk. This has taken me a while to work out, but you can see a demo of it here and try it out with the stack below. Updates to the documentation can be viewed here.
pathfind-gfx.json or live demo here.
v202
Added property retrieval for objects:
put the properties of btn "mybtn" -- returns a list of properties
You can now right-click an object in edit mode, and choose "Duplicate" from the contextual popup menu.
I also improved the evaluateExpression (core logic) to be a lot more 'fuzzy' - more hypertalk-esque for a few commands.
See the documentation, specifically page 90.
I use some of this expanded syntax in this example password generator stack:
pass-gen.json or live demo here.
v203
This week, I've added the styledText property to fields:
set the styledText of field "myfield" to true
As we are already in a browser instance, setting the styledText of a field will tell the browser to process the field formatting as HTML tags, so should support whatever the browser supports.
See a live example of using styledText here.
v204
Quite a lot added this time around, and too much to list here - so I've added it to the documentation on page 92 and onwards.
Probably the most important change is a change to the file format I'm using (don't worry, the JSON is still going to remain as an option)
This is only to create smaller files if working on larger more graphical stacks.
Here's a live demo of that tiny-town stack shown above.
v205
It turns out that making a calculator is a very good way to debug a few things in the interpreter! As a result of making one, I've discovered:
There was a nasty bug with the try/catch statement, so have fixed this.
Also, it became clear the sum() function did not support variables (also fixed)
I added a new function called perc() to mimic how a calculator works out percentages.
put perc(87,12) -- 87 is our base number (total),
-- and 12 is our amount, so this returns 10.44%
-- (12% of 87 = 10.44)
This was worth doing for that try/catch fix alone.
calculator.json or live demo here.
Example stacks:
Live demos and tools: