JS from Python
Imperative JS
Execute JavaScript in the browser from Python event handlers. This is useful for DOM manipulation, browser APIs, or any client-side operation that cannot run on the server.
Recipe
import pulse as ps
from pulse.js import document, window
@ps.javascript
def focus_element(selector: str):
document.querySelector(selector).focus()
@ps.javascript
def scroll_to_top():
window.scrollTo(0, 0)
@ps.javascript
def show_alert(message: str):
window.alert(message)
@ps.component
def MyForm():
with ps.init():
state = FormState()
def on_submit():
state.save()
# Fire and forget - no need to await
ps.run_js(focus_element("#next-field"))
async def on_complete():
await state.finalize()
ps.run_js(scroll_to_top())
ps.run_js(show_alert("Saved!"))
return ps.form(onSubmit=on_submit)[
ps.input(id="next-field", type="text"),
ps.button("Save", type="submit"),
ps.button("Complete", onClick=on_complete),
]Getting values from the browser
Use result=True to await a value from JavaScript:
@ps.javascript
def get_scroll_position():
return {"x": window.scrollX, "y": window.scrollY}
@ps.javascript
def get_selected_text():
return window.getSelection().toString()
@ps.javascript
def get_viewport_size():
return {"width": window.innerWidth, "height": window.innerHeight}
class TrackerState(ps.State):
scroll_x: int = 0
scroll_y: int = 0
selection: str = ""
async def check_scroll(self):
pos = await ps.run_js(get_scroll_position(), result=True)
self.scroll_x = pos["x"]
self.scroll_y = pos["y"]
async def capture_selection(self):
self.selection = await ps.run_js(get_selected_text(), result=True)Available browser APIs
Import type-safe wrappers from pulse.js:
from pulse.js import (
document, # DOM manipulation
window, # Window object, scrolling, alerts
console, # Logging to browser console
navigator, # Browser info, clipboard
Math, # Math functions
JSON, # JSON.parse, JSON.stringify
Date, # Date handling
)Example: Copy to clipboard
from pulse.js import navigator
@ps.javascript
async def copy_to_clipboard(text: str):
await navigator.clipboard.writeText(text)
class ShareState(ps.State):
copied: bool = False
async def copy_link(self, url: str):
await ps.run_js(copy_to_clipboard(url), result=True)
self.copied = TrueExample: Local storage
from pulse.js import window
@ps.javascript
def save_to_storage(key: str, value: str):
window.localStorage.setItem(key, value)
@ps.javascript
def load_from_storage(key: str):
return window.localStorage.getItem(key)
class PreferencesState(ps.State):
theme: str = "light"
async def load_theme(self):
stored = await ps.run_js(load_from_storage("theme"), result=True)
if stored:
self.theme = stored
def save_theme(self, theme: str):
self.theme = theme
ps.run_js(save_to_storage("theme", theme))Error handling
Catch JavaScript errors in Python when awaiting results:
from pulse.render_session import JsExecError
async def safe_js_call():
try:
result = await ps.run_js(some_js_function(), result=True)
except JsExecError as e:
print(f"JavaScript error: {e}")