Skip to content

Commit

Permalink
Add example to download a file
Browse files Browse the repository at this point in the history
  • Loading branch information
laffra committed Nov 29, 2024
1 parent 2246a53 commit 8193f41
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 14 deletions.
8 changes: 6 additions & 2 deletions examples/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ def change(event):

@ltk.callback
def loaded_file(file, content):
feedback(f"{file.name}: {content[:20]}...")
feedback(f"Loaded '{file.name}': {file.size:,} bytes.")
ltk.File.download(file.name, content)

@ltk.callback
def switched(event):
Expand Down Expand Up @@ -73,6 +74,10 @@ def open_popup(event):
).show(ltk.find("#popup"))

widgets = [
ltk.HBox(
ltk.Text("Load a file:").css("margin-right", 8),
ltk.File(loaded_file),
),
ltk.VBox(
ltk.Text("Choose your favorite theme:"),
ltk.Select(themes, 0, choose_theme),
Expand Down Expand Up @@ -109,7 +114,6 @@ def open_popup(event):
ltk.Button("Open Popup", open_popup).attr("id", "popup"),
),
ltk.Switch("Python is great:", True).on("change", switched),
ltk.File(loaded_file),
ltk.ColorPicker().on("change", change),
ltk.DatePicker().on("change", change),
ltk.Input("This is an input. Change me!", {
Expand Down
14 changes: 14 additions & 0 deletions ltk/jquery.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,20 @@ def to_py(jsobj):
return str(jsobj)


class object_url(): # pylint: disable=invalid-name
"""
Create a temporary Object URL for the given content.
"""
def __init__(self, content, content_type="text/plain"):
self.url = window.URL.createObjectURL(window.Blob.new([content]), content_type)

def __enter__(self):
return self.url

def __exit__(self, *args):
window.URL.revokeObjectURL(self.url)


def schedule(python_function, key, timeout_seconds=0):
"""
Schedules the given Python function to run after the given timeout.
Expand Down
35 changes: 24 additions & 11 deletions ltk/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
import logging
import math

from ltk.jquery import callback
from ltk.jquery import find
from ltk.jquery import get_time
from ltk.jquery import inject_css
from ltk.jquery import inject_script
from ltk.jquery import object_url
from ltk.jquery import proxy
from ltk.jquery import schedule
from ltk.jquery import to_js
Expand Down Expand Up @@ -889,19 +891,30 @@ class File(Widget):
classes = [ "ltk-file" ]
tag = "input"

def __init__(self, handler=None, kind="Text", style=None):
def __init__(self, handler=None, style=None):
Widget.__init__(self, style or DEFAULT_CSS)
self.element.attr("type", "file")
self.handler = handler
self.kind = kind
self.on("change", proxy(lambda event: self.get_file(event.target.files.item(0))))

def get_file(self, file):
""" Get the value of the file """
# see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
reader = window.FileReader.new()
reader.onload = proxy(lambda event: self.handler(file, event.target.result))
getattr(reader, f"readAs{self.kind}")(file)

@callback
def _handle_content(event):
# see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
file = event.target.files.item(0)
reader = window.FileReader.new()
reader.onload = proxy(lambda event: handler(file, event.target.result))
if file.type == "text/plain":
reader.readAsText(file)
else:
reader.readAsArrayBuffer(file)

self.on("change", _handle_content)

@classmethod
def download(cls, filename, content, content_type="text/plain"):
"""
Downloads a file from the client's browser.
"""
with object_url(content, content_type) as url:
Link(url).attr("download", filename)[0].click()


class DatePicker(Widget):
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "pyscript-ltk"
version = "0.2.8"
version = "0.2.9"
description = "A little toolkit for writing UIs in PyScript"
readme = "README.md"
authors = [{ name = "Chris Laffra", email = "chris@chrislaffra.com" }]
Expand Down

0 comments on commit 8193f41

Please sign in to comment.