Pulse
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 = True

Example: 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}")

See also

On this page