@@ -127,17 +127,36 @@ export class PyScript extends BaseEvalElement {
127
127
}
128
128
}
129
129
130
- /** Initialize all elements with py-onClick handlers attributes */
130
+ /** Defines all possible pys-on* and their corresponding event types */
131
+ const pysAttributeToEvent : Map < string , string > = new Map < string , string > ( [
132
+ [ "pys-onClick" , "click" ] ,
133
+ [ "pys-onKeyDown" , "keydown" ]
134
+ ] ) ;
135
+
136
+ /** Initialize all elements with pys-on* handlers attributes */
131
137
async function initHandlers ( ) {
132
138
console . log ( 'Collecting nodes...' ) ;
133
139
const pyodide = await pyodideReadyPromise ;
134
- let matches : NodeListOf < HTMLElement > = document . querySelectorAll ( '[pys-onClick]' ) ;
135
- let output ;
136
- let source ;
140
+ for ( const pysAttribute of pysAttributeToEvent . keys ( ) ) {
141
+ await createElementsWithEventListeners ( pyodide , pysAttribute ) ;
142
+ }
143
+ }
144
+
145
+ /** Initializes an element with the given pys-on* attribute and its handler */
146
+ async function createElementsWithEventListeners ( pyodide : any , pysAttribute : string ) {
147
+ const matches : NodeListOf < HTMLElement > = document . querySelectorAll ( `[${ pysAttribute } ]` ) ;
137
148
for ( const el of matches ) {
138
- const handlerCode = el . getAttribute ( 'pys-onClick' ) ;
139
- source = `Element("${ el . id } ").element.onclick = ${ handlerCode } ` ;
140
- output = await pyodide . runPythonAsync ( source ) ;
149
+ if ( el . id . length === 0 ) {
150
+ throw new TypeError ( `<${ el . tagName . toLowerCase ( ) } > must have an id attribute, when using the ${ pysAttribute } attribute` )
151
+ }
152
+ const handlerCode = el . getAttribute ( pysAttribute ) ;
153
+ const event = pysAttributeToEvent . get ( pysAttribute ) ;
154
+ const source = `
155
+ from pyodide import create_proxy
156
+ Element("${ el . id } ").element.addEventListener("${ event } ", create_proxy(${ handlerCode } ))
157
+ ` ;
158
+ await pyodide . runPythonAsync ( source ) ;
159
+
141
160
142
161
// TODO: Should we actually map handlers in JS instead of Python?
143
162
// el.onclick = (evt: any) => {
@@ -154,12 +173,6 @@ async function initHandlers() {
154
173
// }
155
174
}
156
175
157
- matches = document . querySelectorAll ( '[pys-onKeyDown]' ) ;
158
- for ( const el of matches ) {
159
- const handlerCode = el . getAttribute ( 'pys-onKeyDown' ) ;
160
- source = `Element("${ el . id } ").element.addEventListener("keydown", ${ handlerCode } )` ;
161
- output = await pyodide . runPythonAsync ( source ) ;
162
- }
163
176
}
164
177
165
178
/** Mount all elements with attribute py-mount into the Python namespace */
0 commit comments