JavaScript DSL
JWeb provides type-safe JavaScript generation. Write JS in Java with full IDE support, compile-time checks, and no context switching.
Import Statements
// Core JS DSL
import static com.osmig.Jweb.framework.js.JS.*;
// High-level UI actions
import static com.osmig.Jweb.framework.js.Actions.*;
// Event handling patterns
import static com.osmig.Jweb.framework.js.Events.*;
// Async/await and fetch
import static com.osmig.Jweb.framework.js.Async.*;Two Approaches
Use Actions DSL for common UI patterns, or JS DSL for custom logic.
Actions DSL (High-Level)
Declarative builders for common interactions.
// Form submission with loading state
onSubmit("login-form")
.loading("Signing in...")
.post("/api/login").withFormData()
.ok(navigateTo("/dashboard"))
.fail(showMessage("error").text("Invalid credentials"))
// Button click with confirmation
onClick("delete-btn")
.confirm("Delete this item?")
.post("/api/delete/" + id)
.ok(reload())
// Input change handler
onChange("search-input")
.then(fetch("/api/search?q=" + variable("this").dot("value"))
.get()
.ok(setHtml("results")))JS DSL (Low-Level)
Full control over generated JavaScript.
// Variables and values
script()
.var_("count", 0)
.let_("name", str("John"))
.const_("PI", 3.14159)
// Variable references
variable("count") // count
str("hello") // 'hello'
array(1, 2, 3) // [1,2,3]
obj("a", 1, "b", 2) // {a:1,b:2}
// Functions
func("greet", "name")
.var_("msg", str("Hello, ").plus(variable("name")))
.ret(variable("msg"))
// Callbacks (anonymous functions)
callback("item")
.ret(variable("item").times(2))Core JS DSL
Fundamental JavaScript generation with type-safe methods.
DOM Access
// Get element by ID
getElem("myId") // document.getElementById('myId')
$("myId") // Shorthand
// Query selectors
query(".my-class") // document.querySelector('.my-class')
queryAll(".items") // document.querySelectorAll('.items')
// Element manipulation
getElem("btn")
.addClass("active")
.removeClass("disabled")
.setAttribute("data-id", "123")
.setStyle("color", "red")
// Content
getElem("output").setText(variable("result"))
getElem("container").setHtml(variable("template"))
// Visibility
getElem("modal").show()
getElem("tooltip").hide()Control Flow
// If/else
func("checkAge", "age")
.if_(variable("age").gte(18))
.then_(ret(str("adult")))
.else_(ret(str("minor")))
// For loop
func("sum", "items")
.let_("total", 0)
.forOf("item", variable("items"))
.body(variable("total").addAssign(variable("item")))
.endFor()
.ret(variable("total"))
// While loop
func("countdown", "n")
.while_(variable("n").gt(0))
.body("n--", call("console.log", variable("n")))
.endWhile()
// Switch
func("handleAction", "action")
.switch_(variable("action"))
.case_("add").then_(call("add"), "break")
.case_("remove").then_(call("remove"), "break")
.default_().then_(call("noop"))
.endSwitch()Array Methods
30+ fluent array operations.
// Filter and map
variable("items")
.filter(callback("x").ret(variable("x").gt(5)))
.map(callback("x").ret(variable("x").times(2)))
.join(", ")
// Find
variable("users")
.find(callback("u").ret(variable("u").dot("id").eq(userId)))
// Reduce
variable("numbers").reduce(
callback("acc", "n").ret(variable("acc").plus(variable("n"))),
0
)
// Other methods
.forEach(callback) // Iterate
.some(predicate) // Any match?
.every(predicate) // All match?
.includes(value) // Contains?
.indexOf(value) // Find index
.slice(start, end) // Get slice
.concat(other) // Combine
.reverse() // Reverse
.sort(comparator) // Sort
.flat() // Flatten
.first() // First element
.last() // Last elementString Methods
20+ string operations.
variable("text")
.substring(0, 10)
.toLowerCase()
.trim()
// Search
.indexOf("search")
.includes("sub")
.startsWith("prefix")
.endsWith("suffix")
// Transform
.replace("old", "new")
.replaceAll("pattern", "replacement")
.split(",")
.repeat(3)
.padStart(5, "0")
.padEnd(10, " ")Object Methods
// Get properties
variable("obj").keys() // Object.keys(obj)
variable("obj").values() // Object.values(obj)
variable("obj").entries() // Object.entries(obj)
// Check property
variable("obj").hasOwnProperty("key")
// Static methods
objectAssign(variable("target"), variable("source"))
objectFreeze(variable("config"))
objectFromEntries(variable("entries"))Operators
// Comparison
variable("a").eq(variable("b")) // a === b
variable("a").neq(variable("b")) // a !== b
variable("a").gt(5) // a > 5
variable("a").gte(5) // a >= 5
variable("a").lt(10) // a < 10
variable("a").lte(10) // a <= 10
// Logical
variable("a").and(variable("b")) // a && b
variable("a").or(variable("b")) // a || b
not(variable("flag")) // !flag
// Arithmetic
variable("a").plus(variable("b")) // a + b
variable("a").minus(5) // a - 5
variable("a").times(2) // a * 2
variable("a").divide(10) // a / 10
variable("a").mod(2) // a % 2
// Optional chaining
optionalChain(variable("user"), "address", "city") // user?.address?.city
// Nullish coalescing
nullishCoalesce(variable("name"), str("Anonymous")) // name ?? 'Anonymous'Actions DSL
High-level builders for common UI interactions.
Form Submission
// Basic form submit
onSubmit("contact-form")
.post("/api/contact").withFormData()
.ok(showMessage("status").text("Sent!"))
.fail(showMessage("status").text("Error"))
// With loading state
onSubmit("login-form")
.loading("Signing in...") // Disable form, show text
.post("/api/login").withFormData()
.ok(navigateTo("/dashboard"))
.fail(showMessage("error").text("Invalid credentials"))
// With validation
onSubmit("register-form")
.validate(v -> v
.field("email").required().email()
.field("password").required().minLength(8)
)
.loading("Creating account...")
.post("/api/register").withFormData()
.ok(all(
resetForm("register-form"),
showMessage("success").text("Account created!")
))Click Handlers
// Simple click
onClick("save-btn")
.post("/api/save")
.ok(showMessage("status").text("Saved!"))
// With confirmation
onClick("delete-btn")
.confirm("Are you sure you want to delete this?")
.post("/api/delete/" + id)
.ok(reload())
// Chain actions
onClick("logout-btn")
.then(all(
clearStorage(),
navigateTo("/login")
))UI Manipulation
// Show/hide elements
show("panel")
hide("loader")
toggle("dropdown")
// Set content
setText("label", "Updated text")
setHtml("container", variable("html"))
// CSS classes
addClass("card", "highlighted")
removeClass("card", "disabled")
toggleClass("menu", "open")
// Multiple actions
all(
hide("loading"),
show("content"),
addClass("card", "loaded")
)Navigation
// Navigate to URL
navigateTo("/dashboard")
// Reload page
reload()
// Open in new tab
openInNewTab("https://example.com")
// Scroll to element
scrollTo("section-id")
// Smooth scroll
scrollTo("section-id", "smooth")Fetch Requests
// GET request
fetch("/api/users")
.get()
.ok(setHtml("user-list"))
.fail(showMessage("error").text("Failed to load"))
// POST with JSON
fetch("/api/users")
.post()
.json("name", "John", "email", "john@example.com")
.ok(callback("user").call("addUserToList", variable("user")))
// POST with form data
fetch("/api/upload")
.post()
.withFormData("upload-form")
.ok(showMessage("status").text("Uploaded!"))
// With headers
fetch("/api/protected")
.get()
.header("Authorization", "Bearer " + token)
.ok(setHtml("data"))Modals & Dialogs
// Show modal
showModal("confirm-dialog")
hideModal("confirm-dialog")
// Confirmation dialog
confirmDialog("modal")
.message("Delete this item?")
.danger()
.onConfirm(fetch("/api/delete/" + id).post().ok(reload()))
.onCancel(log("Cancelled"))
// Alert modal
alertModal("modal")
.success("Operation completed!")
alertModal("modal")
.error("Something went wrong")Messages & Toasts
// Show message in element
showMessage("status-div")
.text("Success!")
// From response
showMessage("result")
.fromResponse("message")
// Clear after delay
showMessage("notification")
.text("Saved!")
.clearAfter(3000) // 3 secondsConditional Actions
// Based on condition
when("isLoggedIn")
.then(navigateTo("/dashboard"))
.otherwise(navigateTo("/login"))
// Based on response
whenResponse("success")
.then(showMessage("status").text("Done!"))
.otherwise(showMessage("error").text("Failed"))
// Based on variable
whenVar("status")
.equals("approved").thenUrl("/success")
.equals("pending").thenUrl("/pending")
.otherwise(showMessage("error").text("Unknown status"))Event Handling
Advanced event patterns for interactive UIs.
Event Delegation
Efficient handling for dynamic lists.
// Delegate clicks within a container
delegate("todo-list", "click", "li")
.handler(callback("e", "target")
.call("toggleTodo", variable("target").getData("id"))
)
// Works for dynamically added items
// Single listener on parent, not one per childDebouncing
Delay execution until user stops typing/scrolling.
// Search input - wait 300ms after typing stops
onChange("search-input")
.then(debounce("searchTimer", 300).wrap(
fetch("/api/search?q=" + variable("this").dot("value"))
.get()
.ok(setHtml("results"))
))
// Resize handler - wait for resize to stop
onResize(debounce("resizeTimer", 200).wrap(
callback().call("recalculateLayout")
))Throttling
Limit execution frequency.
// Scroll handler - run at most every 100ms
onScroll(throttle("scrollTimer", 100).wrap(
callback().call("updateScrollPosition")
))
// Mouse move - limit to 60fps
onMouseMove("canvas", throttle("moveTimer", 16).wrap(
callback("e").call("draw", variable("e").dot("clientX"), variable("e").dot("clientY"))
))Keyboard Events
// Key combinations
onKeyCombo("ctrl+s", callback("e")
.call("preventDefault", variable("e"))
.call("save")
)
onKeyCombo("ctrl+shift+p", callback("e")
.call("openCommandPalette")
)
// Single keys
onEscape(callback().call("closeModal"))
onEnter(callback().call("submit"))
onKey("Delete", callback().call("deleteSelected"))
// Arrow navigation
onArrowKeys(callback("direction")
.call("navigate", variable("direction"))
)Touch & Swipe
// Swipe gestures
swipe(variable("carousel"))
.threshold(100) // Minimum distance in pixels
.onLeft(callback().call("nextSlide"))
.onRight(callback().call("prevSlide"))
.onUp(callback().call("openFullscreen"))
.onDown(callback().call("closeFullscreen"))
.build()
// Touch events
onTouchStart("element", callback("e")
.let_("touch", variable("e").dot("touches").at(0))
.call("startDrag", variable("touch"))
)Server-Sent Events (SSE)
Real-time server push.
// Connect to SSE endpoint
sse("/api/notifications")
.onMessage(callback("e")
.let_("data", jsonParse(variable("e").dot("data")))
.call("showNotification", variable("data"))
)
.onError(callback()
.log("SSE connection error")
)
.build()
// With auto-reconnect
sse("/api/events")
.reconnectDelay(3000)
.onOpen(callback().log("Connected"))
.onMessage(handler)
.build()Custom Events
// Create and dispatch custom event
dispatchCustomEvent(
variable("element"),
"item-selected",
obj("id", itemId, "name", itemName)
)
// Listen for custom event
on("item-selected", callback("e")
.call("handleSelection", variable("e").dot("detail"))
)Event Utilities
// Prevent default behavior
preventDefault(variable("event"))
// Stop propagation
stopPropagation(variable("event"))
// Once - remove after first call
once("button", "click", callback()
.call("initializeOnce")
)
// Remove listener
removeListener(variable("element"), "click", variable("handler"))Async/Await
Build asynchronous JavaScript with type-safe async functions.
import static com.osmig.Jweb.framework.js.Actions.*;
// Simple await
await_(fetch("/api/data").ok(processData()))
// Async function
asyncFunc("loadDashboard")
.does(
assignVar("isLoading", "true"),
await_(fetch("/api/user").ok(assignVar("user", "_data"))),
await_(fetch("/api/stats").ok(assignVar("stats", "_data"))),
assignVar("isLoading", "false"),
call("renderDashboard")
)Try-Catch-Finally
Handle errors in async operations.
asyncTry(
await_(fetch("/api/data").ok(processData()))
)
.catch_("error",
logError("error"),
showMessage("status").error("Failed to load")
)
.finally_(
hide("loading"),
assignVar("isLoading", "false")
)Promise.all
Execute multiple async operations in parallel.
// Parallel requests
promiseAll(
fetch("/api/users").ok(assignVar("users", "_data")),
fetch("/api/posts").ok(assignVar("posts", "_data")),
fetch("/api/comments").ok(assignVar("comments", "_data"))
)
// With error handling
asyncFunc("loadAll")
.does(
show("loading"),
asyncTry(
promiseAll(
fetch("/api/a").ok(assignVar("a", "_data")),
fetch("/api/b").ok(assignVar("b", "_data"))
),
call("renderAll")
)
.catch_("e", showMessage("error").error("Load failed"))
.finally_(hide("loading"))
)Sleep/Delay
Add delays for debouncing or animations.
// Simple delay
sleep(1000) // Wait 1 second
// Delay in sequence
asyncFunc("showWithDelay")
.does(
addClass("element", "fade-in"),
sleep(300),
setText("status", "Ready!")
)
// Debounced search
asyncFunc("search")
.params("query")
.does(
assignVar("searchQuery", "query"),
sleep(300),
raw("if(searchQuery !== query) return"),
await_(fetch("/api/search?q=").appendVar("query")
.ok(call("showResults", "_data")))
)Browser APIs
Type-safe access to browser APIs.
Storage
import static com.osmig.Jweb.framework.js.JSStorage.*;
// localStorage
local().set("token", "abc123")
local().get("token")
local().remove("token")
local().clear()
// JSON storage
local().setJson("user", obj("name", "John", "id", 123))
local().getJson("user")
local().getJsonOr("user", obj()) // With fallback
// sessionStorage
session().set("temp", "value")
session().get("temp")
// Cross-tab communication
onStorageChange(callback("e")
.if_(variable("e").dot("key").eq("theme"))
.then(call("updateTheme", variable("e").dot("newValue")))
)WebSocket
import static com.osmig.Jweb.framework.js.JSWebSocket.*;
// Create connection
webSocket("/ws/chat")
.onOpen(callback().log("Connected"))
.onMessage(callback("e")
.call("handleMessage", variable("e").dot("data"))
)
.onClose(callback().log("Disconnected"))
.onError(callback("e").log(variable("e")))
.autoReconnect(3000) // Auto-reconnect every 3s
.build("ws")
// Send messages
send(variable("ws"), variable("message"))
sendJson(variable("ws"), obj("type", "chat", "text", variable("msg")))
// Close
close(variable("ws"))Clipboard
import static com.osmig.Jweb.framework.js.JSClipboard.*;
// Write to clipboard
clipboardWrite(str("Copied text"))
// Copy from element
clipboardWriteFromElement(variable("inputElem"))
// Read (returns promise)
clipboardRead().then(callback("text").log(variable("text")))Notifications
import static com.osmig.Jweb.framework.js.JSNotification.*;
// Check permission
notificationPermission()
// Request permission
requestNotificationPermission()
// Show notification
showNotification("New Message", obj(
"body", "You have a new message",
"icon", "/icon.png"
))Geolocation
import static com.osmig.Jweb.framework.js.JSGeolocation.*;
// Get current position
getCurrentPosition()
.onSuccess(callback("pos")
.let_("lat", variable("pos").dot("coords").dot("latitude"))
.let_("lng", variable("pos").dot("coords").dot("longitude"))
.call("showOnMap", variable("lat"), variable("lng"))
)
.onError(callback("err").log(variable("err")))
.build()
// Watch position (continuous updates)
watchPosition(callback("pos")
.call("updatePosition", variable("pos").dot("coords"))
)Web Share
import static com.osmig.Jweb.framework.js.JSShare.*;
// Share content
share(obj(
"title", "Check this out",
"text", "Interesting article",
"url", window.location.href
))
// Check if sharing is supported
if_(canShare())
.then(showShareButton())Fullscreen
import static com.osmig.Jweb.framework.js.JSFullscreen.*;
// Enter fullscreen
requestFullscreen(variable("videoElem"))
// Exit fullscreen
exitFullscreen()
// Check state
isFullscreen()Page Visibility
import static com.osmig.Jweb.framework.js.JSVisibility.*;
// Check if visible
isPageVisible()
// Handle visibility change
onVisibilityChange(callback()
.if_(isPageVisible())
.then(call("resumeVideo"))
.else_(call("pauseVideo"))
)Observers
import static com.osmig.Jweb.framework.js.JSObservers.*;
// IntersectionObserver (lazy loading, infinite scroll)
intersectionObserver(callback("entries")
.forEach(callback("entry")
.if_(variable("entry").dot("isIntersecting"))
.then(call("lazyLoad", variable("entry").dot("target")))
)
).observe(queryAll("img[data-src]"))
// ResizeObserver
resizeObserver(callback("entries")
.forEach(callback("entry")
.call("handleResize", variable("entry").dot("contentRect"))
)
).observe(variable("container"))
// MutationObserver
mutationObserver(callback("mutations")
.call("handleDOMChanges", variable("mutations"))
).observe(variable("element"), obj(
"childList", true,
"subtree", true
))Advanced JavaScript
Powerful APIs for complex applications.
Promise Utilities
import static com.osmig.Jweb.framework.js.JSPromise.*;
// Promise combinators
promiseAll(
fetch("/api/users").get().toVal(),
fetch("/api/posts").get().toVal()
).then(callback("results").call("renderAll", variable("results")))
promiseRace(promise1, promise2) // First to finish
promiseAny(promise1, promise2) // First successful
promiseAllSettled(promises) // All, regardless of success
// Retry with exponential backoff
retry(variable("apiCall"), 3) // Max 3 attempts
.delay(1000) // 1s initial delay
.exponentialBackoff() // Double delay each retry
.onRetry(callback("attempt").log("Retry:", variable("attempt")))
.shouldRetry(callback("err").ret(variable("err").dot("status").eq(503)))
.build()
// Timeout
timeout(fetch("/api/slow").get().toVal(), 3000)
.errorMessage("Request timed out")
.build()
// Cancellable promise
cancellable(fetch("/api/data").get().toVal())
.controller("abortCtrl")
.timeout(5000)
.build("result")Web Workers
import static com.osmig.Jweb.framework.js.JSWorker.*;
// Create dedicated worker
dedicatedWorker("/worker.js")
.onMessage(callback("e").call("handleResult", variable("e").dot("data")))
.onError(callback("err").log(variable("err")))
.build("worker")
// Send data to worker
workerPostMessage(variable("worker"), obj("task", "compute", "data", bigData))
// Terminate worker
workerTerminate(variable("worker"))
// SharedWorker (multiple tabs)
sharedWorker("/shared-worker.js").build("sw")Service Workers
import static com.osmig.Jweb.framework.js.JSServiceWorker.*;
// Register service worker
registerServiceWorker("/sw.js")
.onSuccess(callback("reg").log("SW registered"))
.onError(callback("err").log(variable("err")))
// Check for updates
checkForUpdates(variable("registration"))
// Unregister
unregisterServiceWorker()Web Crypto
import static com.osmig.Jweb.framework.js.JSCrypto.*;
// Random values
cryptoRandomUUID() // UUID v4
cryptoRandomBytes(16) // Random bytes
// Hashing
sha256(variable("data")) // Returns promise
sha512(variable("data"))
// Encryption (AES)
aesEncrypt(variable("key"), variable("data"), variable("iv"))
aesDecrypt(variable("key"), variable("encrypted"), variable("iv"))
// Generate key
generateAESKey().then(callback("key").call("storeKey", variable("key")))Canvas 2D
import static com.osmig.Jweb.framework.js.JSCanvas.*;
// Get context
getContext2D(variable("canvas"))
// Drawing
fillRect(variable("ctx"), 0, 0, 100, 100)
strokeRect(variable("ctx"), 10, 10, 80, 80)
clearRect(variable("ctx"), 0, 0, width, height)
// Text
fillText(variable("ctx"), str("Hello"), 50, 50)
strokeText(variable("ctx"), str("World"), 50, 80)
// Path
beginPath(variable("ctx"))
moveTo(variable("ctx"), 0, 0)
lineTo(variable("ctx"), 100, 100)
arc(variable("ctx"), 50, 50, 30, 0, Math.PI * 2)
stroke(variable("ctx"))
fill(variable("ctx"))
// Image
drawImage(variable("ctx"), variable("img"), 0, 0)Performance API
import static com.osmig.Jweb.framework.js.JSPerformance.*;
// High-resolution timing
performanceNow()
// User timing marks
performanceMark("start")
// ... operation ...
performanceMark("end")
performanceMeasure("operation", "start", "end")
// Observe performance entries
performanceObserver(callback("entries")
.forEach(callback("entry")
.log(variable("entry").dot("name"), variable("entry").dot("duration"))
)
).observe(obj("entryTypes", array("measure")))JSON & Data
import static com.osmig.Jweb.framework.js.JSJson.*;
// Parse/stringify
jsonParse(variable("jsonString"))
jsonStringify(variable("obj"))
jsonStringifyPretty(variable("obj"), 2)
// FormData
import static com.osmig.Jweb.framework.js.JSFormData.*;
formData(variable("formElement"))
formDataEmpty()
formDataAppend(variable("fd"), "key", "value")
// URL
import static com.osmig.Jweb.framework.js.JSUrl.*;
urlParse(str("/path?q=search"))
urlSearchParams(obj("q", "search", "page", 1))
urlSearchParamsGet(variable("params"), "q")Internationalization
import static com.osmig.Jweb.framework.js.JSIntl.*;
// Number formatting
numberFormat("en-US", obj(
"style", "currency",
"currency", "USD"
)).format(variable("amount"))
// Output: $1,234.56
// Date formatting
dateTimeFormat("en-US", obj(
"dateStyle", "long",
"timeStyle", "short"
)).format(variable("date"))
// Output: January 21, 2026 at 3:30 PM
// Relative time
relativeTimeFormat("en", obj("numeric", "auto"))
.format(-1, "day") // "yesterday"New Browser APIs
Additional browser APIs for offline storage, navigation, drag-and-drop, pointer input, and speech.
IndexedDB
Client-side database for structured offline storage.
import static com.osmig.Jweb.framework.js.JSIndexedDB.*;
// Open a database (creates if not exists)
openDB("myApp", 1)
.onUpgrade(createStore(variable("db"), "users")
.keyPath("id").autoIncrement()
.index("email", "email")
.uniqueIndex("username", "username")
.build())
.onSuccess(callback("db").log(str("DB opened")))
.build()
// Transaction: add and read data
transaction(variable("db"), "users", "readwrite")
.put(obj("id", num(1), "name", str("John")))
.getAll()
.onComplete(callback("results").log(variable("results")))
.build()
// Cursor iteration with key range
cursorQuery(variable("db"), "users")
.index("email")
.bound("a", "m")
.onEach(callback("cursor")
.log(variable("cursor").dot("value")))
.build()
// Delete a database
deleteDB("myApp")History API
Browser navigation control for SPA routing patterns.
import static com.osmig.Jweb.framework.js.JSHistory.*;
// Navigate without reload
pushState("/dashboard", obj("page", str("dashboard")))
pushState("/users/42") // URL-only
// Replace current entry (no back button)
replaceState("/settings")
// Go back/forward
back()
forward()
go(-2) // Go back 2 steps
// Listen for back/forward navigation
onPopState(callback("e")
.log(variable("e").dot("state")))
// Navigation guard (prompt before leaving)
navigationGuard("You have unsaved changes. Leave?")
// Query parameter helpers
getQueryParam("page") // Read ?page=...
setQueryParam("sort", "name") // Update URL param
removeQueryParam("filter") // Remove param
queryParamsObject() // All params as objectDrag and Drop
Native HTML5 drag-and-drop with builder pattern.
import static com.osmig.Jweb.framework.js.JSDragDrop.*;
// Make an element draggable
draggable("card-1")
.data("text/plain", "Card 1 data")
.effectAllowed("move")
.onDragStart(callback("e").log(str("dragging")))
.onDragEnd(callback("e").log(str("done")))
.build()
// Create a drop zone
dropZone("drop-area")
.dropEffect("move")
.onDrop(callback("e")
.log(getData(variable("e"), "text/plain")))
.onDragEnter(callback("e")
.log(str("entered drop zone")))
.build()
// DataTransfer helpers
getData(variable("e"), "text/plain")
getFiles(variable("e"))
getTypes(variable("e"))Pointer Events
Unified mouse, touch, and pen input handling.
import static com.osmig.Jweb.framework.js.JSPointer.*;
// Listen for pointer events
onPointerDown("canvas", callback("e")
.log(pointerId(variable("e"))))
onPointerMove("canvas", callback("e")
.log(pressure(variable("e"))))
onPointerUp("canvas", callback("e")
.log(str("released")))
// Capture pointer (receive events outside element)
setPointerCapture("slider", variable("e").dot("pointerId"))
releasePointerCapture("slider", variable("e").dot("pointerId"))
// Access pointer properties
pointerId(variable("e")) // Unique pointer ID
pointerType(variable("e")) // "mouse", "touch", "pen"
pressure(variable("e")) // 0.0 to 1.0
tiltX(variable("e")) // Pen tilt angle
isPrimary(variable("e")) // Is primary pointer?
// Multi-pointer tracking (pinch, multi-touch)
multiPointer("canvas")
.onUpdate(callback("pointers")
.log(variable("pointers").dot("size")))
.build()Web Speech
Text-to-speech and speech recognition APIs.
import static com.osmig.Jweb.framework.js.JSSpeech.*;
// Text-to-Speech (simple)
speak("Hello, welcome to JWeb!")
// Text-to-Speech (with options)
speakBuilder("Hello, welcome to JWeb!")
.lang("en-US")
.rate(1.0).pitch(1.0).volume(0.8)
.onEnd(callback("e").log(str("Done speaking")))
.build()
// Control speech
pauseSpeech()
resumeSpeech()
cancelSpeech()
// Speech Recognition (speech-to-text)
recognizer()
.lang("en-US")
.continuous(true)
.interimResults(true)
.onResult(callback("e")
.log(transcript(variable("e"))))
.onError(callback("e")
.log(variable("e").dot("error")))
.build("recognizer")
// Control recognition
startRecognition(variable("recognizer"))
stopRecognition(variable("recognizer"))
// Result helpers
transcript(variable("e")) // Get text result
confidence(variable("e")) // Confidence score
isFinal(variable("e")) // Is result final?