diff --git a/src/pyj/ajax.pyj b/src/pyj/ajax.pyj
index 6321ffa696..2701e02e95 100644
--- a/src/pyj/ajax.pyj
+++ b/src/pyj/ajax.pyj
@@ -4,6 +4,14 @@
from gettext import gettext as _
def ajax(path, on_complete, on_progress=None, bypass_cache=True, method='GET', query=None, timeout=30*1000, ok_code=200):
+ # Run an AJAX request. on_complete must be a function that accepts three
+ # arguments: end_type, xhr, ev where end_type is one of 'abort', 'error',
+ # 'load', 'timeout'. In case end_type is anything other than 'load' you can
+ # get a descriptive error message via `xhr.error_html`. on_progress, if
+ # provided must be a function accepting three arguments: loaded, total, xhr
+ # where loaded is the number of bytes received, total is the total size.
+ #
+ # Returns the xhr object, call xhr.send() to start the request.
query = query or {}
xhr = XMLHttpRequest()
keys = Object.keys(query)
@@ -19,16 +27,16 @@ def ajax(path, on_complete, on_progress=None, bypass_cache=True, method='GET', q
path += ('&' if has_query else '?') + Date().getTime()
xhr.request_path = path
- xhr.error_string = ''
+ xhr.error_html = ''
def set_error(event):
if event == 'timeout':
- xhr.error_string = str.format(_('Failed to communicate with "{}", timed out after: {} seconds'), xhr.request_path, timeout/1000)
+ xhr.error_html = str.format(_('Failed to communicate with "{}", timed out after: {} seconds'), xhr.request_path, timeout/1000)
elif event == 'abort':
- xhr.error_string = str.format(_('Failed to communicate with "{}", aborted'), xhr.request_path)
+ xhr.error_html = str.format(_('Failed to communicate with "{}", aborted'), xhr.request_path)
else:
rtext = xhr.responseText or ''
- xhr.error_string = str.format(_('Failed to communicate with "{}", with status: [{}] {}
{}'), xhr.request_path, xhr.status, xhr.statusText, rtext[:200])
+ xhr.error_html = str.format(_('Failed to communicate with "{}", with status: [{}] {}
{}'), xhr.request_path, xhr.status, xhr.statusText, rtext[:200])
def progress_callback(ev):
if ev.lengthComputable:
@@ -40,7 +48,7 @@ def ajax(path, on_complete, on_progress=None, bypass_cache=True, method='GET', q
ul = int(ul)
except Exception:
return
- on_progress(ev.loaded, ul)
+ on_progress(ev.loaded, ul, xhr)
def complete_callback(end_type, ev):
if xhr.status != ok_code and end_type == 'load':
diff --git a/src/pyj/modals.pyj b/src/pyj/modals.pyj
index 44d46afdb9..c9a90e1346 100644
--- a/src/pyj/modals.pyj
+++ b/src/pyj/modals.pyj
@@ -1,6 +1,7 @@
# vim:fileencoding=utf-8
# License: GPL v3 Copyright: 2015, Kovid Goyal
+from ajax import ajax
from elementmaker import E
from dom import set_css, clear, build_rule
from gettext import gettext as _
@@ -162,7 +163,7 @@ def create_progress_dialog(msg, on_close):
# def test_progress():
# counter = 0
-# pd = progress_dialog('Testing progress dialog', def():
+# pd = progress_dialog('Testing progress dialog, please wait...', def():
# nonlocal counter
# counter = 101
# console.log('pd canceled')
@@ -203,4 +204,23 @@ def warning_dialog(title, msg, details=None):
create_simple_dialog(title, msg, details, 'warning', _('Warning:'))
def progress_dialog(msg, on_close=None):
+ # Show a modal dialog with a progress bar and an optional close button.
+ # If the user clicks the close button, on_close is called and the dialog is closed.
+ # Returns an object with the methods: close(), update_progress(amount, total), set_msg()
+ # Call update_progress() to update the progress bar
+ # Call set_msg() to change the displayed message
+ # Call close() once the task being performed is finished
return create_progress_dialog(msg, on_close)
+
+def ajax_progress_dialog(path, on_complete, msg, **kw):
+ pd = None
+ def on_complete_callback(event_type, xhr, ev):
+ nonlocal pd
+ pd.close()
+ pd = undefined
+ return on_complete(event_type, xhr, ev)
+ def on_progress_callback(loaded, total, xhr):
+ pd.update_progress(loaded, total)
+ xhr = ajax(path, on_complete_callback, on_progress=on_progress_callback, **kw)
+ pd = progress_dialog(msg, xhr.abort)
+ return xhr, pd