Mercurial > libervia-web
view libervia/pages/_browser/editor.py @ 1415:8415d882b686
browser: new `editor` module:
This module provide tools for dynamtic item edition.
For now it implements forms autosave, and a tags editor.
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 29 Apr 2021 16:45:39 +0200 |
parents | |
children | 925a7c498cda |
line wrap: on
line source
"""text edition management""" from browser import document, window, bind, timer from browser.local_storage import storage from browser.object_storage import ObjectStorage from template import Template object_storage = ObjectStorage(storage) profile = window.profile # how often we save forms, in seconds AUTOSAVE_FREQUENCY = 20 def serialise_form(form_elt): ret = {} for elt in form_elt.elements: if elt.tagName == "INPUT": if elt.type in ("hidden", "submit"): continue elif elt.type == "text": ret[elt.name] = elt.value else: print(f"elt.type not managet yet: {elt.type}") continue elif elt.tagName == "TEXTAREA": ret[elt.name] = elt.value elif elt.tagName in ("BUTTON",): continue else: print(f"tag not managet yet: {elt.tagName}") continue return ret def restore_form(form_elt, data): for elt in form_elt.elements: if elt.tagName not in ("INPUT", "TEXTAREA"): continue try: value = data[elt.name] except KeyError: continue else: elt.value = value def set_form_autosave(form_id): """Save locally form data regularly and restore it until it's submitted form is saved every AUTOSAVE_FREQUENCY seconds and when visibility is lost. Saved data is restored when the method is called. Saved data is cleared when the form is submitted. """ if profile is None: print(f"No session started, won't save and restore form {form_id}") return form_elt = document[form_id] submitted = False key = {"profile": profile, "type": "form_autosave", "form": form_id} try: form_saved_data = object_storage[key] except KeyError: last_serialised = None else: print(f"restoring content of form {form_id!r}") last_serialised = form_saved_data restore_form(form_elt, form_saved_data) def save_form(): if not submitted: nonlocal last_serialised serialised = serialise_form(form_elt) if serialised != last_serialised: last_serialised = serialised print(f"saving content of form {form_id!r}") object_storage[key] = serialised @bind(form_elt, "submit") def on_submit(evt): nonlocal submitted submitted = True print(f"clearing stored content of form {form_id!r}") try: del object_storage[key] except KeyError: print("key error") pass @bind(document, "visibilitychange") def on_visibiliy_change(evt): print("visibility change") if document.visibilityState != "visible": save_form() timer.set_interval(save_form, AUTOSAVE_FREQUENCY * 1000) class TagsEditor: def __init__(self, input_selector): print("installing Tags Editor") self.input_elt = document.select_one(input_selector) self.input_elt.style.display = "none" tags_editor_tpl = Template('editor/tags_editor.html') self.tag_tpl = Template('editor/tag.html') editor_elt = tags_editor_tpl.get_elt() self.input_elt.parent <= editor_elt self.tag_input_elt = editor_elt.select_one(".tag_input") self.tag_input_elt.bind("keydown", self.on_key_down) self._current_tags = None self.tags_map = {} for tag in self.current_tags: self.add_tag(tag, force=True) @property def current_tags(self): if self._current_tags is None: self._current_tags = { t.strip() for t in self.input_elt.value.split(',') if t.strip() } return self._current_tags @current_tags.setter def current_tags(self, tags): self._current_tags = tags def add_tag(self, tag, force=False): tag = tag.strip() if not force and (not tag or tag in self.current_tags): return self.current_tags = self.current_tags | {tag} self.input_elt.value = ','.join(self.current_tags) tag_elt = self.tag_tpl.get_elt({"label": tag}) self.tags_map[tag] = tag_elt self.tag_input_elt.parent.insertBefore(tag_elt, self.tag_input_elt) tag_elt.select_one(".click_to_delete").bind( "click", lambda evt: self.on_tag_click(evt, tag) ) def remove_tag(self, tag): try: tag_elt = self.tags_map[tag] except KeyError: print(f"trying to remove an inexistant tag: {tag}") else: self.current_tags = self.current_tags - {tag} self.input_elt.value = ','.join(self.current_tags) tag_elt.remove() def on_tag_click(self, evt, tag): evt.stopPropagation() self.remove_tag(tag) def on_key_down(self, evt): if evt.key in (",", "Enter"): evt.stopPropagation() evt.preventDefault() self.add_tag(self.tag_input_elt.value) self.tag_input_elt.value = ""