Source code for streamlitextras.webutils

import time
import html
import uuid
import base64
import streamlit as st
from io import BytesIO
from typing import Union, Optional
from streamlit_javascript import st_javascript
from streamlit.runtime.uploaded_file_manager import UploadedFile


[docs]def stxs_javascript(source: str) -> None: """ Runs javascript on the top level context of the page. Does this by embedding an iframe that attaches a script tag to its parent. :param str source: The script source to embed in the <script></script> element """ div_id = uuid.uuid4() st.markdown( f""" <div style="display:none" id="{div_id}"> <iframe src="javascript: \ var script = document.createElement('script'); \ script.type = 'text/javascript'; \ script.text = {html.escape(repr(source))}; \ var thisDiv = window.parent.document.getElementById('{div_id}'); \ var rootDiv = window.parent.parent.parent.parent.document.getElementById('root'); \ rootDiv.appendChild(script); \ thisDiv.parentElement.parentElement.parentElement.style.display = 'none'; \ "/> </div> """, unsafe_allow_html=True, ) time.sleep(0.1) return True
[docs]def get_user_timezone(default_tz: Optional[str] = None) -> Optional[str]: """ Uses javascript to get the tz database name for the browser/users timezone :param Optional[str] default_tz: value to return if the operation fails. Defaults to UTC :returns Optional[str]: The tz database name for the timezone, or None if the operation fails and default_tz isn't set, or isn't supported by the browser (unlikely) """ if not default_tz: default_tz = "Etc/UTC" timezone = st_javascript( """await (async () => { const userTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone console.log(userTimezone) return userTimezone })().then(returnValue => returnValue)""" ) if timezone == 0: # st_javascript returns 0 for null/undefined timezone = default_tz return timezone
[docs]def scroll_page(x: int = 0, y: int = 0): """ Runs javascript to scroll the streamlit main section Defaults to scrolling to the top if no arguments are passed :param int x: the x coordinate to scroll to :param int y: the y coordinate to scroll to """ stxs_javascript( f"""parent.document.querySelector(`section[class*="main"`).scroll({x}, {y})""" )
[docs]def bytes_to_data_uri( byteslike_object: Union[BytesIO, UploadedFile, bytes], mime_type: Optional[str] = None, ) -> str: """ Creates a data URI from a bytesIO object :param Union[BytesIO, UploadedFile] byteslike_object: BytesIO or bytes or any class that inherits them :param str mime_type: The mimetype to set on the data URI :returns: The data URI as a string """ data = None try: data = byteslike_object.getvalue() except: data = byteslike_object if not mime_type: mime_type = "application/octet-stream" uri = f"data:{mime_type};base64,{base64.b64encode(data).decode()}" return uri
[docs]def trigger_download(download_uri: str, filename: str): """ Uses javascript and a data URI on a link element to trigger a download for the user :param str download_uri: properly formatted data uri to place on link elements href :param str filename: filename to be placed on the link elements download attribute """ auto_downloaded = stxs_javascript( f"""(async () => {{ console.log("Creating download link..") var link = document.createElement('a'); link.innerText = "" link.href = "{download_uri}"; link.target = "_blank"; link.download = "{filename}"; link.click(); await new Promise(r => setTimeout(r, 2000)); //window.open(link.href, "_blank") }})();""" ) time.sleep( 1 ) # Give the page some time to render the element before the page rerenders return auto_downloaded
[docs]def convert_millis(milliseconds: int, always_include_hours: bool = False) -> str: """ Convert milliseconds to a string timestamp in the format HH:MM:SS or MM:SS :param int milliseconds: The amount of milliseconds to convert to a timestamp :param bool always_include_hours: Always include the HH: part of the timestamp even if 00. """ seconds = int((milliseconds / 1000) % 60) minutes = int((milliseconds / (1000 * 60)) % 60) hours = int((milliseconds / (1000 * 60 * 60)) % 24) timestamp_text = "" if hours > 0: timestamp_text += f"{hours:02d}:{minutes:02d}:{seconds:02d}" else: if always_include_hours: timestamp_text += f"{hours:02d}:" timestamp_text += f"{minutes:02d}:{seconds:02d}" return timestamp_text