From f18d172fdf5a396f8f5f70370cd98e80cba46e6b Mon Sep 17 00:00:00 2001 From: MinRK Date: Wed, 30 Nov 2011 15:10:31 -0800 Subject: [PATCH 1/4] don't swallow regular key events in read-only mode --- IPython/frontend/html/notebook/static/js/notebook.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IPython/frontend/html/notebook/static/js/notebook.js b/IPython/frontend/html/notebook/static/js/notebook.js index d8b287683..1b973b2a5 100644 --- a/IPython/frontend/html/notebook/static/js/notebook.js +++ b/IPython/frontend/html/notebook/static/js/notebook.js @@ -59,7 +59,7 @@ var IPython = (function (IPython) { var that = this; $(document).keydown(function (event) { // console.log(event); - if (that.read_only) return false; + if (that.read_only) return true; if (event.which === 27) { // Intercept escape at highest level to avoid closing // websocket connection with firefox From 36024bcf833d2bb593fcff2aea5ae5dd57b00f84 Mon Sep 17 00:00:00 2001 From: MinRK Date: Wed, 30 Nov 2011 20:11:37 -0800 Subject: [PATCH 2/4] allow the notebook to run without MathJax * add `--no-mathjax` flag for disabling mathjax in the notebook server * A jQuery dialog with our 'no mathjax' message will appear if mathjax is unavailable, but the notebook will be fully functional after dismissal. * Various calls to MathJax.Hub.typeset moved to Cell.typeset, which checks for MathJax existence and is a no-op without it. closes #1071 --- IPython/frontend/html/notebook/handlers.py | 2 + IPython/frontend/html/notebook/notebookapp.py | 24 ++++++- .../html/notebook/static/css/notebook.css | 12 ++++ .../frontend/html/notebook/static/js/cell.js | 7 ++ .../html/notebook/static/js/codecell.js | 4 +- .../html/notebook/static/js/notebookmain.js | 66 ++++++++++++++++--- .../html/notebook/static/js/textcell.js | 6 +- .../html/notebook/templates/notebook.html | 44 +++---------- 8 files changed, 115 insertions(+), 50 deletions(-) diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index ca92d5967..02357112e 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -219,6 +219,7 @@ class NewHandler(AuthenticatedHandler): base_project_url=u'/', base_kernel_url=u'/', kill_kernel=False, read_only=False, + enable_mathjax=self.application.ipython_app.enable_mathjax, ) @@ -237,6 +238,7 @@ class NamedNotebookHandler(AuthenticatedHandler): base_project_url=u'/', base_kernel_url=u'/', kill_kernel=False, read_only=self.read_only, + enable_mathjax=self.application.ipython_app.enable_mathjax, ) diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py index 1d1795984..f78519632 100644 --- a/IPython/frontend/html/notebook/notebookapp.py +++ b/IPython/frontend/html/notebook/notebookapp.py @@ -128,6 +128,17 @@ flags['no-browser']=( {'NotebookApp' : {'open_browser' : False}}, "Don't open the notebook in a browser after startup." ) +flags['no-mathjax']=( + {'NotebookApp' : {'enable_mathjax' : False}}, + """Disable MathJax + + MathJax is the javascript library IPython uses to render math/LaTeX. It is + very large, so you may want to disable it if you have a slow internet + connection, or for offline use of the notebook. + + When disabled, equations etc. will appear as their untransformed TeX source. + """ +) flags['read-only'] = ( {'NotebookApp' : {'read_only' : True}}, """Allow read-only access to notebooks. @@ -144,7 +155,7 @@ flags['read-only'] = ( # the flags that are specific to the frontend # these must be scrubbed before being passed to the kernel, # or it will raise an error on unrecognized flags -notebook_flags = ['no-browser', 'read-only'] +notebook_flags = ['no-browser', 'no-mathjax', 'read-only'] aliases = dict(ipkernel_aliases) @@ -230,6 +241,17 @@ class NotebookApp(BaseIPythonApplication): read_only = Bool(False, config=True, help="Whether to prevent editing/execution of notebooks." ) + + enable_mathjax = Bool(True, config=True, + help="""Whether to enable MathJax for typesetting math/TeX + + MathJax is the javascript library IPython uses to render math/LaTeX. It is + very large, so you may want to disable it if you have a slow internet + connection, or for offline use of the notebook. + + When disabled, equations etc. will appear as their untransformed TeX source. + """ + ) def parse_command_line(self, argv=None): super(NotebookApp, self).parse_command_line(argv) diff --git a/IPython/frontend/html/notebook/static/css/notebook.css b/IPython/frontend/html/notebook/static/css/notebook.css index 01d376c27..2e894ccc2 100644 --- a/IPython/frontend/html/notebook/static/css/notebook.css +++ b/IPython/frontend/html/notebook/static/css/notebook.css @@ -415,6 +415,18 @@ div.text_cell_render { font-family: monospace; } +pre.dialog { + background-color: #f7f7f7; + border: 1px solid #ddd; + border-radius: 3px; + padding: 0.4em; + padding-left: 2em; +} + +p.dialog{ + padding : 0.2em; +} + @media print { body { overflow: visible !important; } .ui-widget-content { border: 0px; } diff --git a/IPython/frontend/html/notebook/static/js/cell.js b/IPython/frontend/html/notebook/static/js/cell.js index 6806dd3cf..2667ec0a2 100644 --- a/IPython/frontend/html/notebook/static/js/cell.js +++ b/IPython/frontend/html/notebook/static/js/cell.js @@ -88,6 +88,13 @@ var IPython = (function (IPython) { // Subclasses must implement create_element. Cell.prototype.create_element = function () {}; + // typeset with MathJax if MathJax is available + Cell.prototype.typeset = function () { + if (window.MathJax){ + MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + } + }; + IPython.Cell = Cell; return IPython; diff --git a/IPython/frontend/html/notebook/static/js/codecell.js b/IPython/frontend/html/notebook/static/js/codecell.js index d17bd61d4..2d6b2968d 100644 --- a/IPython/frontend/html/notebook/static/js/codecell.js +++ b/IPython/frontend/html/notebook/static/js/codecell.js @@ -520,7 +520,7 @@ var IPython = (function (IPython) { this.element.find('div.output').append(toinsert); // If we just output latex, typeset it. if ((json.latex !== undefined) || (json.html !== undefined)) { - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + this.typeset(); }; }; @@ -572,7 +572,7 @@ var IPython = (function (IPython) { this.element.find('div.output').append(toinsert); // If we just output latex, typeset it. if ( (json.latex !== undefined) || (json.html !== undefined) ) { - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + this.typeset(); }; }; diff --git a/IPython/frontend/html/notebook/static/js/notebookmain.js b/IPython/frontend/html/notebook/static/js/notebookmain.js index c3cb70aca..7d1f49bf4 100644 --- a/IPython/frontend/html/notebook/static/js/notebookmain.js +++ b/IPython/frontend/html/notebook/static/js/notebookmain.js @@ -12,16 +12,62 @@ $(document).ready(function () { - MathJax.Hub.Config({ - tex2jax: { - inlineMath: [ ['$','$'], ["\\(","\\)"] ], - displayMath: [ ['$$','$$'], ["\\[","\\]"] ] - }, - displayAlign: 'left', // Change this to 'center' to center equations. - "HTML-CSS": { - styles: {'.MathJax_Display': {"margin": 0}} - } - }); + if (window.MathJax == undefined){ + // MathJax undefined, but expected. Draw warning. + window.MathJax = null; + var dialog = $('
').html( + "

"+ + "We were unable to retrieve MathJax. Math/LaTeX rendering will be disabled."+ + "

"+ + "

"+ + "With a working internet connection, you can run the following at a Python"+ + " or IPython prompt, which will install a local copy of MathJax:"+ + "

"+ + "
"+
+            ">>> from IPython.external import mathjax; mathjax.install_mathjax()"+
+            "
"+ + "

"+ + "This will try to install MathJax into the directory where you installed"+ + " IPython. If you installed IPython to a location that requires"+ + " administrative privileges to write, you will need to make this call as"+ + " an administrator."+ + "

"+ + "

"+ + "On OSX/Linux/Unix, this can be done at the command-line via:"+ + "

"+ + "
"+
+            "$ sudo python -c 'from IPython.external import mathjax; mathjax.install_mathjax()'"+
+            "
"+ + "

"+ + "Or you can instruct the notebook server to start without MathJax support, with:"+ + "

"+
+            "

"+ + "$ ipython notebook --no-mathjax"+ + "
"+ + "

"+ + "in which case, equations will not be rendered."+ + "

" + ).dialog({ + title: 'MathJax disabled', + width: "70%", + modal: true, + }) + }else if (window.MathJax){ + MathJax.Hub.Config({ + tex2jax: { + inlineMath: [ ['$','$'], ["\\(","\\)"] ], + displayMath: [ ['$$','$$'], ["\\[","\\]"] ] + }, + displayAlign: 'left', // Change this to 'center' to center equations. + "HTML-CSS": { + styles: {'.MathJax_Display': {"margin": 0}} + } + }); + }else{ + // window.MathJax == null + // --no-mathjax mode + } + IPython.markdown_converter = new Markdown.Converter(); IPython.read_only = $('meta[name=read_only]').attr("content") == 'True'; diff --git a/IPython/frontend/html/notebook/static/js/textcell.js b/IPython/frontend/html/notebook/static/js/textcell.js index 55a9887e7..601de0f8b 100644 --- a/IPython/frontend/html/notebook/static/js/textcell.js +++ b/IPython/frontend/html/notebook/static/js/textcell.js @@ -175,7 +175,7 @@ var IPython = (function (IPython) { var text = this.get_source(); if (text === "") { text = this.placeholder; } this.set_rendered(text); - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + this.typeset(); this.element.find('div.text_cell_input').hide(); this.element.find("div.text_cell_render").show(); this.rendered = true; @@ -201,7 +201,7 @@ var IPython = (function (IPython) { if (text === "") { text = this.placeholder; } var html = IPython.markdown_converter.makeHtml(text); this.set_rendered(html); - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + this.typeset() this.element.find('div.text_cell_input').hide(); this.element.find("div.text_cell_render").show(); var code_snippets = this.element.find("pre > code"); @@ -255,7 +255,7 @@ var IPython = (function (IPython) { RSTCell.prototype.handle_render = function (data, status, xhr) { this.set_rendered(data); - MathJax.Hub.Queue(["Typeset",MathJax.Hub]); + this.typeset(); this.rendered = true; }; diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html index 0655e5b10..95e4de495 100644 --- a/IPython/frontend/html/notebook/templates/notebook.html +++ b/IPython/frontend/html/notebook/templates/notebook.html @@ -6,25 +6,24 @@ IPython Notebook + {% if enable_mathjax %} + {% else %} + + {% end %} @@ -45,7 +44,7 @@ - @@ -71,29 +70,6 @@ Idle - -
From 72fb49b7c7074d4c20159ae7217f3adffe650ef7 Mon Sep 17 00:00:00 2001 From: MinRK Date: Thu, 1 Dec 2011 15:59:02 -0800 Subject: [PATCH 3/4] adjust missing mathjax handling per review * use jQuery syntax to construct dialog * server determines where MathJax comes from via mathjax_url configurable (default local/CDN priority unchanged) --- IPython/frontend/html/notebook/handlers.py | 4 +- IPython/frontend/html/notebook/notebookapp.py | 25 ++++++ .../html/notebook/static/js/notebookmain.js | 88 +++++++++---------- .../html/notebook/templates/notebook.html | 18 +--- 4 files changed, 75 insertions(+), 60 deletions(-) diff --git a/IPython/frontend/html/notebook/handlers.py b/IPython/frontend/html/notebook/handlers.py index 02357112e..242d47bec 100644 --- a/IPython/frontend/html/notebook/handlers.py +++ b/IPython/frontend/html/notebook/handlers.py @@ -219,7 +219,7 @@ class NewHandler(AuthenticatedHandler): base_project_url=u'/', base_kernel_url=u'/', kill_kernel=False, read_only=False, - enable_mathjax=self.application.ipython_app.enable_mathjax, + mathjax_url=self.application.ipython_app.mathjax_url, ) @@ -238,7 +238,7 @@ class NamedNotebookHandler(AuthenticatedHandler): base_project_url=u'/', base_kernel_url=u'/', kill_kernel=False, read_only=self.read_only, - enable_mathjax=self.application.ipython_app.enable_mathjax, + mathjax_url=self.application.ipython_app.mathjax_url, ) diff --git a/IPython/frontend/html/notebook/notebookapp.py b/IPython/frontend/html/notebook/notebookapp.py index f78519632..d2bdcf6d0 100644 --- a/IPython/frontend/html/notebook/notebookapp.py +++ b/IPython/frontend/html/notebook/notebookapp.py @@ -252,6 +252,31 @@ class NotebookApp(BaseIPythonApplication): When disabled, equations etc. will appear as their untransformed TeX source. """ ) + def _enable_mathjax_changed(self, name, old, new): + """set mathjax url to empty if mathjax is disabled""" + if not new: + self.mathjax_url = u'' + + mathjax_url = Unicode("", config=True, + help="""The url for MathJax.js.""" + ) + def _mathjax_url_default(self): + if not self.enable_mathjax: + return u'' + static_path = os.path.join(os.path.dirname(__file__), "static") + if os.path.exists(os.path.join(static_path, 'mathjax', "MathJax.js")): + self.log.info("Using local MathJax") + return u"static/mathjax/MathJax.js" + else: + self.log.info("Using MathJax from CDN") + return u"http://cdn.mathjax.org/mathjax/latest/MathJax.js" + + def _mathjax_url_changed(self, name, old, new): + if new and not self.enable_mathjax: + # enable_mathjax=False overrides mathjax_url + self.mathjax_url = u'' + else: + self.log.info("Using MathJax: %s", new) def parse_command_line(self, argv=None): super(NotebookApp, self).parse_command_line(argv) diff --git a/IPython/frontend/html/notebook/static/js/notebookmain.js b/IPython/frontend/html/notebook/static/js/notebookmain.js index 7d1f49bf4..1d9d041c8 100644 --- a/IPython/frontend/html/notebook/static/js/notebookmain.js +++ b/IPython/frontend/html/notebook/static/js/notebookmain.js @@ -11,48 +11,8 @@ $(document).ready(function () { - - if (window.MathJax == undefined){ - // MathJax undefined, but expected. Draw warning. - window.MathJax = null; - var dialog = $('
').html( - "

"+ - "We were unable to retrieve MathJax. Math/LaTeX rendering will be disabled."+ - "

"+ - "

"+ - "With a working internet connection, you can run the following at a Python"+ - " or IPython prompt, which will install a local copy of MathJax:"+ - "

"+ - "
"+
-            ">>> from IPython.external import mathjax; mathjax.install_mathjax()"+
-            "
"+ - "

"+ - "This will try to install MathJax into the directory where you installed"+ - " IPython. If you installed IPython to a location that requires"+ - " administrative privileges to write, you will need to make this call as"+ - " an administrator."+ - "

"+ - "

"+ - "On OSX/Linux/Unix, this can be done at the command-line via:"+ - "

"+ - "
"+
-            "$ sudo python -c 'from IPython.external import mathjax; mathjax.install_mathjax()'"+
-            "
"+ - "

"+ - "Or you can instruct the notebook server to start without MathJax support, with:"+ - "

"+
-            "

"+ - "$ ipython notebook --no-mathjax"+ - "
"+ - "

"+ - "in which case, equations will not be rendered."+ - "

" - ).dialog({ - title: 'MathJax disabled', - width: "70%", - modal: true, - }) - }else if (window.MathJax){ + if (window.MathJax){ + // MathJax loaded MathJax.Hub.Config({ tex2jax: { inlineMath: [ ['$','$'], ["\\(","\\)"] ], @@ -63,9 +23,49 @@ $(document).ready(function () { styles: {'.MathJax_Display': {"margin": 0}} } }); + }else if (window.mathjax_url != ""){ + // Don't have MathJax, but should. Show dialog. + var dialog = $('
') + .append( + $("

").addClass('dialog').html( + "Math/LaTeX equation rendering will be disabled." + ) + ).append( + $("

").addClass('dialog').html( + "With a working internet connection, you can install a local copy" + + " of MathJax for offline use with the following command at a Python" + + " or IPython prompt:" + ) + ).append( + $("
").addClass('dialog').html(
+                    ">>> from IPython.external import mathjax; mathjax.install_mathjax()"
+                )
+            ).append(
+                $("

").addClass('dialog').html( + "This will try to install MathJax into the directory where you installed"+ + " IPython. If you installed IPython to a location that requires"+ + " administrative privileges to write, you will need to make this call as"+ + " an administrator, via 'sudo'." + ) + ).append( + $("

").addClass('dialog').html( + "Or you can instruct the notebook server to disable MathJax support altogether:" + ) + ).append( + $("
").addClass('dialog').html(
+                    "$ ipython notebook --no-mathjax"
+                )
+            ).append(
+                $("

").addClass('dialog').html( + "which will prevent this dialog from appearing." + ) + ).dialog({ + title: "Failed to retrieve MathJax from '" + window.mathjax_url + "'", + width: "70%", + modal: true, + }) }else{ - // window.MathJax == null - // --no-mathjax mode + // No MathJax, but none expected. No dialog. } IPython.markdown_converter = new Markdown.Converter(); diff --git a/IPython/frontend/html/notebook/templates/notebook.html b/IPython/frontend/html/notebook/templates/notebook.html index 95e4de495..7049b5c9b 100644 --- a/IPython/frontend/html/notebook/templates/notebook.html +++ b/IPython/frontend/html/notebook/templates/notebook.html @@ -6,24 +6,14 @@ IPython Notebook - {% if enable_mathjax %} - - - - {% else %} + {% if mathjax_url %} + + {% end %} - {% end %} From d6ac9f3ec323ed11267ec17dcac330012f18b509 Mon Sep 17 00:00:00 2001 From: MinRK Date: Mon, 5 Dec 2011 15:21:49 -0800 Subject: [PATCH 4/4] add server/permission info in failed-mathjax dialog It's now more clear that offline mathjax info is server-related. --- .../html/notebook/static/js/notebookmain.js | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/IPython/frontend/html/notebook/static/js/notebookmain.js b/IPython/frontend/html/notebook/static/js/notebookmain.js index 1d9d041c8..8326b68c4 100644 --- a/IPython/frontend/html/notebook/static/js/notebookmain.js +++ b/IPython/frontend/html/notebook/static/js/notebookmain.js @@ -28,13 +28,14 @@ $(document).ready(function () { var dialog = $('
') .append( $("

").addClass('dialog').html( - "Math/LaTeX equation rendering will be disabled." + "Math/LaTeX rendering will be disabled." ) ).append( $("

").addClass('dialog').html( - "With a working internet connection, you can install a local copy" + - " of MathJax for offline use with the following command at a Python" + - " or IPython prompt:" + "If you have administrative access to the notebook server and" + + " a working internet connection, you can install a local copy" + + " of MathJax for offline use with the following command on the server" + + " at a Python or IPython prompt:" ) ).append( $("
").addClass('dialog').html(
@@ -42,14 +43,17 @@ $(document).ready(function () {
                 )
             ).append(
                 $("

").addClass('dialog').html( - "This will try to install MathJax into the directory where you installed"+ - " IPython. If you installed IPython to a location that requires"+ - " administrative privileges to write, you will need to make this call as"+ + "This will try to install MathJax into the IPython source directory." + ) + ).append( + $("

").addClass('dialog').html( + "If IPython is installed to a location that requires" + + " administrative privileges to write, you will need to make this call as" + " an administrator, via 'sudo'." ) ).append( $("

").addClass('dialog').html( - "Or you can instruct the notebook server to disable MathJax support altogether:" + "When you start the notebook server, you can instruct it to disable MathJax support altogether:" ) ).append( $("
").addClass('dialog').html(