Mimic the IPython notebook cell execution

  |   Source   |   Minimap

Yesterday, I was visiting the Jake VanderPlas's Scientific Python Course site because of some issues raised at the ipython-dev mailing list (and obviously, because Jake usually do amazing things).

To build his site, Jake wrote an Hyde plugin to render ipynb files to static html files using the IPython.convert platform. You can see an example of the final rendered document here.

When I saw the final document, I wondered if we could have hidden output cells which automatically get visible after a click over the input cell... and then, I made some experiments using the power of the IPython.nbconvert library ;-)

NOTE: From here, to see the output of each cell, please click on the input area and surprise yourself!

First, we needed to rewrite some things at the Jinja template level:

In [1]:
!sed -n 1,7p /media/datos/Ejemplos/toggle.tpl
  Click me to hide the output
{%- extends 'html_full.tpl' -%}

{% block output_group %}
<div class="output_hidden">
{{ super() }}
</div>
{% endblock output_group %}

We had to rewrite the output_group block to encompass it with a new output_hidden-classed div, which we would use in a simple Javascript function later.

Second, we needed to write that little Javascript snippet:

In [2]:
!sed -n 25,29p /media/datos/Ejemplos/toggle.tpl
  Click me to hide the output
$(document).ready(function(){
  $(".input").click(function(){
      $(this).next('.output_hidden').slideToggle();
  });
})

Here, we used the .slideToggle() method to display or hide the output_hidden-classed div elements (with a nice sliding motion) when the user makes a click on the input cells. We was using jQuery, so we needed to load jQquery, ie. using the following line:

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>

Finally, we added some css to make the output_hidden-classed div not visible (hidden by default):

In [3]:
!sed -n 18,21p /media/datos/Ejemplos/toggle.tpl
  Click me to hide the output
.output_hidden {
  display: none;
  margin-top: 5px;
}

If you put all these snippets together, you will get the following template:

In [4]:
!cat -n /media/datos/Ejemplos/toggle.tpl
  Click me to hide the output
     1	{%- extends 'html_full.tpl' -%}
     2	
     3	{% block output_group %}
     4	<div class="output_hidden">
     5	{{ super() }}
     6	</div>
     7	{% endblock output_group %}
     8	
     9	{%- block header -%}
    10	{{ super() }}
    11	
    12	<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    13	
    14	<style type="text/css">
    15	div.output_wrapper {
    16	  margin-top: 0px;
    17	}
    18	.output_hidden {
    19	  display: none;
    20	  margin-top: 5px;
    21	}
    22	</style>
    23	
    24	<script>
    25	$(document).ready(function(){
    26	  $(".input").click(function(){
    27	      $(this).next('.output_hidden').slideToggle();
    28	  });
    29	})
    30	</script>
    31	{%- endblock header -%}
    32	

To use it, just add --template toggle to your ipython nbconvert call, ie:

ipython nbconvert your_notebook.ipynb --to html --template toggle --post serve

or add the toggle.tpl file to you IPython nbconvert config file.

If you are reading this line, you probably have already experienced the demo in this post (btw, I like to do demos explaining the tools with the tools themselves).

Obviously, I quickly implemented this functionality inside Nikola and, as a consequence, in Nikola master, you now have the possibility to pass an IPython config dict to your Nikola conf.py file, making the ipynb plugin for Nikola more powerful than before ;-)

To conclude, the possibility to mimic the IPython notebook execution is very useful for introductory courses and to publish content in a shorter but more interactive way.

Hope you enjoy it!

Damián

Did you like the content? Great!

Or visit my support page for more information.


Btw, don't forget this blog post is an ipynb file itself! So, you can download it from the "Source" link at the top of the post if you want to play with it ;-)

Comments powered by Disqus