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