Skip to content

Commit 9889c77

Browse files
committed
Merge pull request astropy#4197 from saimn/jsviewer-ipynb
Add method to show tables with dataTables in notebook
1 parent 4d37700 commit 9889c77

File tree

3 files changed

+87
-58
lines changed

3 files changed

+87
-58
lines changed

CHANGES.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ New Features
204204

205205
- New CSS for jsviewer table [#2917, #2982, #4174]
206206

207+
- Added a new ``Table.show_in_notebook`` method that shows an interactive view
208+
of a Table (similar to ``Table.show_in_browser(jsviewer=True)``) in an
209+
Python/Jupyter notebook. [#4197]
210+
207211
- ``astropy.tests``
208212

209213
- Added new test config options, ``config_dir`` and ``cache_dir`` (these

astropy/table/jsviewer.py

Lines changed: 37 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -43,40 +43,20 @@ class Conf(_config.ConfigNamespace):
4343

4444
IPYNB_JS_SCRIPT = """
4545
<script>
46-
function html_repr_full() {{
47-
var kernel = IPython.notebook.kernel;
48-
var button = $("#MakeTableBrowseable{tid}");
49-
var tablename = button.parents()[4].getElementsByClassName("input_area")[0].innerText;
50-
tablename = tablename.replace(/\s+/g, '');
51-
var command = "print ''.join(" + tablename + ".pformat(html=True, max_lines=1000, max_width=1000, table_id={tid}))";
52-
console.log(command);
53-
var result = kernel.execute(command, {{'output': callback}}, {{silent:false}});
54-
console.log(result);
55-
}}
56-
function callback(output_type, out) {{
57-
console.log(output_type);
58-
console.log(out);
59-
var button = $("#MakeTableBrowseable{tid}");
60-
button[0].parentNode.innerHTML = out.data;
61-
return out.data;
62-
}}
63-
function make_table_browseable() {{
64-
console.log("$('#{tid}').dataTable()");
65-
$('#{tid}').dataTable({{
66-
"iDisplayLength": {display_length},
67-
"aLengthMenu": {display_length_menu},
68-
"pagingType": "full_numbers"
69-
}});
70-
}}
71-
function replace_table() {{
72-
html_repr_full();
73-
make_table_browseable();
74-
}}
46+
require.config({{paths: {{
47+
datatables: '{datatables_url}'
48+
}}}});
49+
require(["datatables"], function(){{
50+
console.log("$('#{tid}').dataTable()");
51+
$('#{tid}').dataTable({{
52+
"iDisplayLength": {display_length},
53+
"aLengthMenu": {display_length_menu},
54+
"pagingType": "full_numbers"
55+
}});
56+
}});
7557
</script>
76-
<button id='MakeTableBrowseable{tid}' onclick="make_table_browseable()">Make Table Browseable</button>
7758
"""
7859

79-
8060
HTML_JS_SCRIPT = """
8161
$(document).ready(function() {{
8262
$('#{tid}').dataTable({{
@@ -88,13 +68,23 @@ class Conf(_config.ConfigNamespace):
8868
"""
8969

9070

71+
# Default CSS for the JSViewer writer
9172
DEFAULT_CSS = """\
9273
body {font-family: sans-serif;}
9374
table.dataTable {width: auto !important; margin: 0 !important;}
9475
.dataTables_filter, .dataTables_paginate {float: left !important; margin-left:1em}
9576
"""
9677

9778

79+
# Default CSS used when rendering a table in the IPython notebook
80+
DEFAULT_CSS_NB = """\
81+
table.dataTable {clear: both; width: auto !important; margin: 0 !important;}
82+
.dataTables_info, .dataTables_length, .dataTables_filter, .dataTables_paginate{
83+
display: inline-block; margin-right: 1em; }
84+
.paginate_button { margin-right: 5px; }
85+
"""
86+
87+
9888
class JSViewer(object):
9989
"""Provides an interactive HTML export of a Table.
10090
@@ -138,31 +128,26 @@ def css_urls(self):
138128
return conf.css_urls
139129

140130
def _jstable_file(self):
141-
# downloaded from http://datatables.net/download/build/
142-
datatables_url = conf.datatables_url
143-
if not datatables_url:
144-
datatables_url = 'file://' + join(EXTERN_JS_DIR,
145-
'jquery.dataTables.min.js')
146-
return '<script class="jsbin" src="{0}"></script>'.format(datatables_url)
147-
148-
def _css_files(self):
149-
return [
150-
'<link rel="stylesheet" href="{css}" type="text/css">'.format(css=css)
151-
for css in self.css_urls]
152-
153-
def ipynb(self, table_id):
154-
js = self._css_files()
155-
js.append(self._jstable_file())
156-
js.append(IPYNB_JS_SCRIPT.format(
131+
if self._use_local_files:
132+
return 'file://' + join(EXTERN_JS_DIR, 'jquery.dataTables.min')
133+
else:
134+
return conf.datatables_url[:-3]
135+
136+
def ipynb(self, table_id, css=None):
137+
html = '<style>{0}</style>'.format(css if css is not None
138+
else DEFAULT_CSS_NB)
139+
html += IPYNB_JS_SCRIPT.format(
157140
display_length=self.display_length,
158141
display_length_menu=self.display_length_menu,
159-
tid=table_id))
160-
return js
142+
datatables_url=self._jstable_file(),
143+
tid=table_id)
144+
return html
161145

162146
def html_js(self, table_id='table0'):
163-
return HTML_JS_SCRIPT.format(display_length=self.display_length,
164-
display_length_menu=self.display_length_menu,
165-
tid=table_id).strip()
147+
return HTML_JS_SCRIPT.format(
148+
display_length=self.display_length,
149+
display_length_menu=self.display_length_menu,
150+
tid=table_id).strip()
166151

167152

168153
def write_table_jsviewer(table, filename, table_id=None, max_lines=5000,

astropy/table/table.py

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -742,7 +742,9 @@ def _make_table_from_cols(table, cols):
742742

743743
table.columns = columns
744744

745-
def _base_repr_(self, html=False, descr_vals=None, max_width=None, tableid=None):
745+
def _base_repr_(self, html=False, descr_vals=None, max_width=None,
746+
tableid=None, show_dtype=True, max_lines=None,
747+
tableclass=None):
746748
if descr_vals is None:
747749
descr_vals = [self.__class__.__name__]
748750
if self.masked:
@@ -758,10 +760,10 @@ def _base_repr_(self, html=False, descr_vals=None, max_width=None, tableid=None)
758760
if tableid is None:
759761
tableid = 'table{id}'.format(id=id(self))
760762

761-
data_lines, outs = self.formatter._pformat_table(self, tableid=tableid, html=html,
762-
max_width=max_width,
763-
show_name=True, show_unit=None,
764-
show_dtype=True)
763+
data_lines, outs = self.formatter._pformat_table(
764+
self, tableid=tableid, html=html, max_width=max_width,
765+
show_name=True, show_unit=None, show_dtype=show_dtype,
766+
max_lines=max_lines, tableclass=tableclass)
765767

766768
out = descr + '\n'.join(data_lines)
767769
if six.PY2 and isinstance(out, six.text_type):
@@ -859,6 +861,45 @@ def pprint(self, max_lines=None, max_width=None, show_name=True,
859861
else:
860862
print(line)
861863

864+
def show_in_notebook(self, tableid=None, css=None, display_length=50,
865+
table_class='table table-striped table-bordered '
866+
'table-condensed'):
867+
"""Render the table in HTML and show it in the IPython notebook.
868+
869+
Parameters
870+
----------
871+
tableid : str or `None`
872+
An html ID tag for the table. Default is ``table{id}-XXX``, where
873+
id is the unique integer id of the table object, id(self), and XXX
874+
is a random number to avoid conflicts when printing the same table
875+
multiple times.
876+
table_class : str or `None`
877+
A string with a list of HTML classes used to style the table.
878+
Default is "table table-striped table-bordered table-condensed",
879+
using Bootstrap which is available in the notebook. See `this page
880+
<http://getbootstrap.com/css/#tables>`_ for the list of classes.
881+
css : string
882+
A valid CSS string declaring the formatting for the table. Default
883+
to ``astropy.table.jsviewer.DEFAULT_CSS_NB``.
884+
display_length : int, optional
885+
Number or rows to show. Default to 50.
886+
887+
"""
888+
889+
from .jsviewer import JSViewer
890+
from IPython.display import HTML
891+
892+
if tableid is None:
893+
tableid = 'table{0}-{1}'.format(id(self),
894+
np.random.randint(1, 1e6))
895+
896+
jsv = JSViewer(use_local_files=False, display_length=display_length)
897+
html = self._base_repr_(html=True, max_width=-1, tableid=tableid,
898+
max_lines=-1, show_dtype=False,
899+
tableclass=table_class)
900+
html += jsv.ipynb(tableid, css=css)
901+
return HTML(html)
902+
862903
def show_in_browser(self, max_lines=5000, jsviewer=False,
863904
browser='default', jskwargs={'use_local_files': True},
864905
tableid=None, table_class="display compact",
@@ -910,7 +951,6 @@ def show_in_browser(self, max_lines=5000, jsviewer=False,
910951

911952
# We can't use NamedTemporaryFile here because it gets deleted as
912953
# soon as it gets garbage collected.
913-
914954
tmpdir = tempfile.mkdtemp()
915955
path = os.path.join(tmpdir, 'table.html')
916956

0 commit comments

Comments
 (0)