2

I used the code suggested from Download CSV from an iPython Notebook to dynamically build the javascript code and pass it to the browser using Javascript() in python when called from a jupyter notebook. Code works great. If I embed the same code in a python function and call the python function from the same jupyter notebook, the call Javascript() in python no longer works. How can I make the reusable function work?

I am trying this on Chrome Version 73.0.3683.103 (Official Build) (64-bit) running on Windows 10. Apologies if already answered. I have scoured SO and google.

This works..

from IPython.display import Javascript
js_download = """
var csv = '%s';

var filename = 'results.csv';
var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
if (navigator.msSaveBlob) { // IE 10+
    navigator.msSaveBlob(blob, filename);
} else {
    var link = document.createElement("a");
    if (link.download !== undefined) { // feature detection
        // Browsers that support HTML5 download attribute
        var url = URL.createObjectURL(blob);
        link.setAttribute("href", url);
        link.setAttribute("download", filename);
        link.style.visibility = 'hidden';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }
}
""" % data_in_dataframes.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'")
Javascript(js_download)

This does not work, it fails to execute Javascript(js_download), but neither does it give any error that I can see in the jupyter notebook nor the java console in the browser. It is as if it never executed Javascript(js_download).

from IPython.display import Javascript
def js_download_csv(df_download, s_filename='results.csv'):
    js_download =   """
    var csv = '%s';
    var filename = '%s';
    var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
    """ % (df_download.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'"), s_filename)
    Javascript(js_download)
    return None
js_download_csv(df_download, s_filename)

Apologies if I have left anything obvious out. I can find no errors or logs with any information regarding what is happening.

Any suggestions welcome.

gatomulato
  • 81
  • 5
  • Is there no output? – DarthCadeus Apr 20 '19 at 12:53
  • There is no output in the jupyter notebook, there is no output in the browser java console, there is no output in the anaconda server window.. I have added a print statement in the function just prior to the JavaScript() call and the string prints out fine and can be used directlly in the notebook. – gatomulato Apr 20 '19 at 14:01
  • It is as if JavaScript() works fine interactively in a jupytwr notebook but cannot be called from withing a function in the same jupyter notebook. I do not know why. – gatomulato Apr 20 '19 at 14:02
  • Python doesn't really have a JavaScript interpreter built into itself. But if you want to call JavaScript from Python you should use [PythonWebKit](https://wiki.python.org/moin/PythonWebKit). – user11385924 Apr 20 '19 at 13:13
  • I found something very strange. If I add a semi-colon to the end of the call to Javascript(js_download) to the code that works in the notebook. It stops working! I thought the semi-colon was redundant in python. Why would this affect the call to Javascript()? – gatomulato Apr 21 '19 at 04:04

1 Answers1

6

I have found a partial answer, in that while I do not why this problem occurs, I have found how to overcome it. In https://medium.com/@tomgrek/reactive-python-javascript-communication-in-jupyter-notebook-e2a879e25906 we see in the article the following gotcha:

A big gotcha: something somewhere needs to return Javascript as its output, otherwise it doesn’t get executed in the notebook.

So, if we change the code to the following (i.e. return the Javascript call), it works.

from IPython.display import Javascript
def js_download_csv(df_download, s_filename='results.csv'):
    js_download =   """
    var csv = '%s';
    var filename = '%s';
    var blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' });
    if (navigator.msSaveBlob) { // IE 10+
        navigator.msSaveBlob(blob, filename);
    } else {
        var link = document.createElement("a");
        if (link.download !== undefined) { // feature detection
            // Browsers that support HTML5 download attribute
            var url = URL.createObjectURL(blob);
            link.setAttribute("href", url);
            link.setAttribute("download", filename);
            link.style.visibility = 'hidden';
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        }
    }
    """ % (df_download.to_csv(index=False).replace('\r','\\r').replace('\n','\\n').replace("'","\'"), s_filename)
    return Javascript(js_download)
js_download_csv(df_download, s_filename)
gatomulato
  • 81
  • 5