ScoDoc-Lille/app/forms/multiselect.py

119 lines
3.8 KiB
Python

"""
Simplification des multiselect HTML/JS
"""
class MultiSelect:
"""
Classe pour faciliter l'utilisation du multi-select HTML/JS
Les values sont représentées en dict {
value: "...",
label:"...",
selected: True/False (default to False),
single: True/False (default to False)
}
Args:
values (dict[str, list[dict]]): Dictionnaire des valeurs
génère des <optgroup> pour chaque clef du dictionnaire
génère des <option> pour chaque valeur du dictionnaire
name (str, optional): Nom du multi-select. Defaults to "multi-select".
html_id (str, optional): Id HTML du multi-select. Defaults to "multi-select".
classname (str, optional): Classe CSS du multi-select. Defaults to "".
label (str, optional): Label du multi-select. Defaults to "".
export (str, optional): Format du multi-select (HTML/JS). Defaults to "js".
HTML : group_ids="val1"&group_ids="val2"...
JS : ["val1","val2", ...]
**kwargs: Arguments supplémentaires (appliqué au multiselect en HTML <multi-select key="value" ...>)
"""
def __init__(
self,
values: dict[str, list[dict]],
name="multi-select",
html_id="multi-select",
label="",
classname="",
**kwargs,
) -> None:
self.values: dict[str, list[dict]] = values
self._on = ""
self.name: str = name
self.html_id: str = html_id
self.classname: str = classname
self.label: str = label or name
self.args: dict = kwargs
self.js: str = ""
self.export: str = "return values"
def html(self) -> str:
"""
Génère l'HTML correspondant au multi-select
"""
opts: list[str] = []
for key, values in self.values.items():
optgroup = f"<optgroup label='{key}'>"
for value in values:
selected = "selected" if value.get("selected", False) else ""
single = "single" if value.get("single", False) else ""
opt = f"<option value='{value.get('value')}' {selected} {single} >{value.get('label')}</option>"
optgroup += opt
optgroup += "</optgroup>"
opts.append(optgroup)
args: list[str] = [f'{key}="{value}"' for key, value in self.args.items()]
js: str = "{" + self.js + "}"
export: str = "{" + self.export + "}"
return f"""
<multi-select
label="{self.label}"
id="{self.html_id}"
name="{self.name}"
class="{self.classname}"
{" ".join(args)}
>
{"".join(opts)}
</multi-select>
<script>
window.addEventListener('load', () => {{document.getElementById("{self.html_id}").on((values)=>{js});
document.getElementById("{self.html_id}").format((values)=>{export});}} );
</script>
"""
def change_event(self, js: str) -> None:
"""
Ajoute un évènement de changement au multi-select
CallBack JS : (event) => {/*actions à effectuer*/}
Sera retranscrit dans l'HTML comme :
document.getElementById(%self.id%).on((event)=>{%self.js%})
Exemple d'utilisation :
js : "console.log(event.target.value)"
"""
self.js: str = js
def export_format(self, js: str) -> None:
"""
Met à jour le format de retour de valeur du multi-select
CallBack JS : (values) => {/*actions à effectuer*/}
Sera retranscrit dans l'HTML comme :
document.getElementById(%self.id%).format((values)=>{%self.js%})
Exemple d'utilisation :
js : "return values.map(v=> 'val:'+v)"
"""
self.export: str = js