mirror of
https://github.com/pyscript/pyscript.git
synced 2025-12-19 18:27:29 -05:00
[next] Drop web like events (#1578)
* Use registerJSModule when available (#1573) * Updated version to publish latest
This commit is contained in:
committed by
GitHub
parent
a14e701be4
commit
c6b5ce7f55
@@ -246,40 +246,19 @@ Please read the [XWorker](#xworker) dedicated section to know more.
|
|||||||
|
|
||||||
## How Events Work
|
## How Events Work
|
||||||
|
|
||||||
Inspired by the current [HTML Standard](https://html.spec.whatwg.org/multipage/webappapis.html#event-handlers):
|
The event should contain the *interpreter* or *custom type* prefix, followed by the *event* type it'd like to handle.
|
||||||
|
|
||||||
> the event handler is exposed through a name, which is a string that always starts with "_on_" and is followed by the name of the event for which the handler is intended.
|
|
||||||
|
|
||||||
We took a similar approach, replacing that `on` prefix with whatever *interpreter* or *custom type* is available on the page, plus a *dash* `-` to avoid clashing with standards:
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script type="micropython">
|
<script type="micropython">
|
||||||
def print_type(event, double):
|
def print_type(event):
|
||||||
# logs "click 4"
|
print(event.type)
|
||||||
print(f"{event.type} {double(2)}")
|
|
||||||
</script>
|
</script>
|
||||||
<button micropython-click="print_type(event, lambda x: x * 2)">
|
<button micropython-click="print_type">
|
||||||
print type
|
print type
|
||||||
</button>
|
</button>
|
||||||
```
|
```
|
||||||
|
|
||||||
If this example felt a bit verbose, be ensured custom types would work the same:
|
Differently from *Web* inline events, there's no code evaluation at all within the attribute: it's just a globally available name that will receive the current event and nothing else.
|
||||||
|
|
||||||
```html
|
|
||||||
<!-- ℹ️ - requires py-script custom type -->
|
|
||||||
<button py-click="print(event.type)">
|
|
||||||
print type
|
|
||||||
</button>
|
|
||||||
```
|
|
||||||
|
|
||||||
What is important to understand about *events* in PyScript is that the text within the attribute is executed just like any other inline or external content is, through the very same *interpreter*, with the notably extra feature that the `event` reference is made temporarily available as *global* by *core*.
|
|
||||||
|
|
||||||
This really reflects how otherwise native Web inline events handlers work and we think it's a great feature to support ... *but*:
|
|
||||||
|
|
||||||
* if your script runs *asynchronously* the `event` might be gone on the main / UI thread and by that time any of its `event.stopPropagation()` or `event.preventDefault()` goodness will be problematic, as too late to be executed
|
|
||||||
* if your *interpreter* is *experimental*, or incapable of running *synchronous* events, the `event` reference might be less useful
|
|
||||||
|
|
||||||
ℹ️ - Please note that if your code runs via *XWorker*, hence in a different thread, there are different caveats and constraints to consider. Please read the [XWorker](#xworker) dedicated section to know more.
|
|
||||||
|
|
||||||
#### The type-env attribute
|
#### The type-env attribute
|
||||||
|
|
||||||
@@ -299,7 +278,7 @@ Just as the `env` attribute on a `<script>` tag specifies a specific instance of
|
|||||||
<!-- note the micropython-env value -->
|
<!-- note the micropython-env value -->
|
||||||
<button
|
<button
|
||||||
micropython-env="two"
|
micropython-env="two"
|
||||||
micropython-click="log()"
|
micropython-click="log"
|
||||||
>
|
>
|
||||||
log
|
log
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -7,6 +7,8 @@ export const run = (interpreter, code) => interpreter.runPython(clean(code));
|
|||||||
export const runAsync = (interpreter, code) =>
|
export const runAsync = (interpreter, code) =>
|
||||||
interpreter.runPythonAsync(clean(code));
|
interpreter.runPythonAsync(clean(code));
|
||||||
|
|
||||||
|
export const getGlobal = (interpreter, name) => interpreter.globals.get(name);
|
||||||
|
|
||||||
export const setGlobal = (interpreter, name, value) => {
|
export const setGlobal = (interpreter, name, value) => {
|
||||||
interpreter.globals.set(name, value);
|
interpreter.globals.set(name, value);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { fetchPaths, stdio } from "./_utils.js";
|
import { fetchPaths, stdio } from "./_utils.js";
|
||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
|
getGlobal,
|
||||||
setGlobal,
|
setGlobal,
|
||||||
deleteGlobal,
|
deleteGlobal,
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
@@ -22,6 +23,7 @@ export default {
|
|||||||
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
if (config.fetch) await fetchPaths(this, interpreter, config.fetch);
|
||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
|
getGlobal,
|
||||||
setGlobal,
|
setGlobal,
|
||||||
deleteGlobal,
|
deleteGlobal,
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import { fetchPaths, stdio } from "./_utils.js";
|
|||||||
import {
|
import {
|
||||||
run,
|
run,
|
||||||
runAsync,
|
runAsync,
|
||||||
|
getGlobal,
|
||||||
setGlobal,
|
setGlobal,
|
||||||
deleteGlobal,
|
deleteGlobal,
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
@@ -31,6 +32,7 @@ export default {
|
|||||||
}
|
}
|
||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
|
getGlobal,
|
||||||
setGlobal,
|
setGlobal,
|
||||||
deleteGlobal,
|
deleteGlobal,
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
|
|||||||
@@ -24,6 +24,18 @@ export default {
|
|||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
|
getGlobal(interpreter, name) {
|
||||||
|
try {
|
||||||
|
return this.run(interpreter, name);
|
||||||
|
} catch (_) {
|
||||||
|
const method = this.run(interpreter, `method(:${name})`);
|
||||||
|
return (...args) =>
|
||||||
|
method.call(
|
||||||
|
name,
|
||||||
|
...args.map((value) => interpreter.wrap(value)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
setGlobal(interpreter, name, value) {
|
setGlobal(interpreter, name, value) {
|
||||||
const id = `__pyscript_ruby_wasm_wasi_${name}`;
|
const id = `__pyscript_ruby_wasm_wasi_${name}`;
|
||||||
globalThis[id] = value;
|
globalThis[id] = value;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ export default {
|
|||||||
return interpreter;
|
return interpreter;
|
||||||
},
|
},
|
||||||
registerJSModule,
|
registerJSModule,
|
||||||
|
getGlobal: (interpreter, name) => interpreter.global.get(name),
|
||||||
setGlobal(interpreter, name, value) {
|
setGlobal(interpreter, name, value) {
|
||||||
interpreter.global.set(name, value);
|
interpreter.global.set(name, value);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -41,12 +41,8 @@ export const listener = async (event) => {
|
|||||||
el.getAttribute(`${name}-env`) || name,
|
el.getAttribute(`${name}-env`) || name,
|
||||||
);
|
);
|
||||||
const handler = registry.get(name);
|
const handler = registry.get(name);
|
||||||
try {
|
const callback = handler.getGlobal(interpreter, value);
|
||||||
handler.setGlobal(interpreter, "event", event);
|
callback(event);
|
||||||
handler.run(interpreter, value);
|
|
||||||
} finally {
|
|
||||||
handler.deleteGlobal(interpreter, "event");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@pyscript/core",
|
"name": "@pyscript/core",
|
||||||
"version": "0.0.6",
|
"version": "0.0.7",
|
||||||
"description": "PyScript Next core",
|
"description": "PyScript Next core",
|
||||||
"main": "./cjs/index.js",
|
"main": "./cjs/index.js",
|
||||||
"types": "./types/index.d.ts",
|
"types": "./types/index.d.ts",
|
||||||
@@ -66,6 +66,6 @@
|
|||||||
"coincident": "^0.8.3"
|
"coincident": "^0.8.3"
|
||||||
},
|
},
|
||||||
"worker": {
|
"worker": {
|
||||||
"blob": "sha256-71McgT96jsjEBqY19EQRYQYwwoZQ99VTYu60UU6i03w="
|
"blob": "sha256-BqPm4/IdGDQduhprGUnwdf5iumpMmkkGNsPrPZXl+mU="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -29,14 +29,14 @@
|
|||||||
|
|
||||||
const button = document.createElement("button");
|
const button = document.createElement("button");
|
||||||
button.textContent = "click";
|
button.textContent = "click";
|
||||||
button.setAttribute("mpy-click", "test_click(event)");
|
button.setAttribute("mpy-click", "test_click");
|
||||||
document.body.append(button);
|
document.body.append(button);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<mpy-script mpy-click="test_click(event)">
|
<mpy-script mpy-click="test_click">
|
||||||
def test_click(event):
|
def test_click(event):
|
||||||
print(event.type)
|
print(event.type)
|
||||||
|
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
print(sys.version)
|
print(sys.version)
|
||||||
</script>
|
</script>
|
||||||
<button
|
<button
|
||||||
pyodide-pointerdown="print_version(event)"
|
pyodide-pointerdown="print_version"
|
||||||
pyodide-click="print_version(event)"
|
pyodide-click="print_version"
|
||||||
>
|
>
|
||||||
pyodide version
|
pyodide version
|
||||||
</button>
|
</button>
|
||||||
@@ -29,8 +29,8 @@
|
|||||||
print(sys.version)
|
print(sys.version)
|
||||||
</script>
|
</script>
|
||||||
<button
|
<button
|
||||||
micropython-pointerdown="print_version(event)"
|
micropython-pointerdown="print_version"
|
||||||
micropython-click="print_version(event)"
|
micropython-click="print_version"
|
||||||
>
|
>
|
||||||
micropython version
|
micropython version
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="module" src="../esm/index.js"></script>
|
<script type="module" src="../core.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="ruby-wasm-wasi">
|
<script type="ruby-wasm-wasi">
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
print "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
print "ruby #{ RUBY_VERSION }p#{ RUBY_PATCHLEVEL }"
|
||||||
end
|
end
|
||||||
</script>
|
</script>
|
||||||
<button ruby-wasm-wasi-click="print_version($event)">
|
<button ruby-wasm-wasi-click="print_version">
|
||||||
ruby-wasm-wasi version
|
ruby-wasm-wasi version
|
||||||
</button>
|
</button>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -33,6 +33,6 @@
|
|||||||
print(read_file('/a.py'))
|
print(read_file('/a.py'))
|
||||||
end
|
end
|
||||||
</script>
|
</script>
|
||||||
<button wasmoon-click="print_version(event)">wasmoon version</button>
|
<button wasmoon-click="print_version">wasmoon version</button>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -45,7 +45,7 @@
|
|||||||
<input type="text" placeholder="loading ..." required disabled />
|
<input type="text" placeholder="loading ..." required disabled />
|
||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
micropython-click="handle_result(event)"
|
micropython-click="handle_result"
|
||||||
disabled
|
disabled
|
||||||
/>
|
/>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
Reference in New Issue
Block a user