Add checkId() for PyButton and PyInputBox, add id check for tags with pys- Event handlers (#400)

* Add id generation to PyButton and PyInputBox components

* Refactor init handlers and add check for id
This commit is contained in:
Yannick Funk
2022-05-16 23:05:11 +02:00
committed by GitHub
parent ca909b4f6b
commit eba42ad9b4
3 changed files with 28 additions and 13 deletions

View File

@@ -37,6 +37,7 @@ export class PyButton extends BaseEvalElement {
}
connectedCallback() {
this.checkId();
this.code = htmlDecode(this.innerHTML);
this.mount_name = this.id.split('-').join('_');
this.innerHTML = '';

View File

@@ -17,6 +17,7 @@ export class PyInputBox extends BaseEvalElement {
}
connectedCallback() {
this.checkId();
this.code = htmlDecode(this.innerHTML);
this.mount_name = this.id.split('-').join('_');
this.innerHTML = '';

View File

@@ -127,17 +127,36 @@ export class PyScript extends BaseEvalElement {
}
}
/** Initialize all elements with py-onClick handlers attributes */
/** Defines all possible pys-on* and their corresponding event types */
const pysAttributeToEvent: Map<string, string> = new Map<string, string>([
["pys-onClick", "click"],
["pys-onKeyDown", "keydown"]
]);
/** Initialize all elements with pys-on* handlers attributes */
async function initHandlers() {
console.log('Collecting nodes...');
const pyodide = await pyodideReadyPromise;
let matches: NodeListOf<HTMLElement> = document.querySelectorAll('[pys-onClick]');
let output;
let source;
for (const pysAttribute of pysAttributeToEvent.keys()) {
await createElementsWithEventListeners(pyodide, pysAttribute);
}
}
/** Initializes an element with the given pys-on* attribute and its handler */
async function createElementsWithEventListeners(pyodide: any, pysAttribute: string) {
const matches: NodeListOf<HTMLElement> = document.querySelectorAll(`[${pysAttribute}]`);
for (const el of matches) {
const handlerCode = el.getAttribute('pys-onClick');
source = `Element("${el.id}").element.onclick = ${handlerCode}`;
output = await pyodide.runPythonAsync(source);
if (el.id.length === 0) {
throw new TypeError(`<${el.tagName.toLowerCase()}> must have an id attribute, when using the ${pysAttribute} attribute`)
}
const handlerCode = el.getAttribute(pysAttribute);
const event = pysAttributeToEvent.get(pysAttribute);
const source = `
from pyodide import create_proxy
Element("${el.id}").element.addEventListener("${event}", create_proxy(${handlerCode}))
`;
await pyodide.runPythonAsync(source);
// TODO: Should we actually map handlers in JS instead of Python?
// el.onclick = (evt: any) => {
@@ -154,12 +173,6 @@ async function initHandlers() {
// }
}
matches = document.querySelectorAll('[pys-onKeyDown]');
for (const el of matches) {
const handlerCode = el.getAttribute('pys-onKeyDown');
source = `Element("${el.id}").element.addEventListener("keydown", ${handlerCode})`;
output = await pyodide.runPythonAsync(source);
}
}
/** Mount all elements with attribute py-mount into the Python namespace */