diff --git a/.gitignore b/.gitignore index 3c748e4d..ac8da4af 100644 --- a/.gitignore +++ b/.gitignore @@ -16,9 +16,6 @@ dist # Jupyter Book _build -# External dependencies -itables/external - # Quarto .jupyter_cache docs/quarto/*.html @@ -26,4 +23,5 @@ docs/quarto/*_files/ # Datatables bundle node_modules -dt_bundle +dt_bundle.js +dt_bundle.css diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b314fa9e..cfabcee3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -32,8 +32,10 @@ repos: rev: v1.14.5 hooks: - id: jupytext + exclude: dt_package/ types: ["markdown"] - args: ["--pipe", "black", "--check", "ruff check {} --ignore E402"] + args: ["--pipe", "isort {} --treat-comment-as-code '# %%' --profile black", "--pipe", "black", "--check", "ruff check {} --ignore E402"] additional_dependencies: - black==22.3.0 # Matches hook - ruff==0.3.1 + - isort==5.13.2 diff --git a/README.md b/README.md index 78c4634e..6a7c067e 100644 --- a/README.md +++ b/README.md @@ -2,13 +2,12 @@ ![CI](https://github.com/mwouts/itables/actions/workflows/continuous-integration.yml/badge.svg?branch=main) [![codecov.io](https://codecov.io/github/mwouts/itables/coverage.svg?branch=main)](https://codecov.io/github/mwouts/itables?branch=main) -[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/mwouts/itables.svg)](https://lgtm.com/projects/g/mwouts/itables/context:python) [![Pypi](https://img.shields.io/pypi/v/itables.svg)](https://pypi.python.org/pypi/itables) [![Conda Version](https://img.shields.io/conda/vn/conda-forge/itables.svg)](https://anaconda.org/conda-forge/itables) [![pyversions](https://img.shields.io/pypi/pyversions/itables.svg)](https://pypi.python.org/pypi/itables) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -## Turn your Python DataFrames into Interactive Tables +## Turn your Python DataFrames into Interactive DataTables This packages changes how Pandas and Polars DataFrames are rendered in Jupyter Notebooks. With `itables` you can display your tables as interactive [datatables](https://datatables.net/) @@ -67,6 +66,8 @@ execute `init_notebook_mode`. - Google Colab - VS Code (for both Jupyter Notebooks and Python scripts) - PyCharm (for Jupyter Notebooks) +- Quarto +- Shiny for Python ## Try ITables on Binder diff --git a/docs/_toc.yml b/docs/_toc.yml index b9355d41..1df44b5b 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -1,16 +1,25 @@ format: jb-book root: quick_start -chapters: -- file: supported_editors -- file: advanced_parameters -- file: pandas_style -- file: custom_css -- file: downsampling -- file: sample_dataframes -- file: polars_dataframes -- file: quarto -- file: references -- file: contributing -- file: developing -- file: troubleshooting -- file: changelog +parts: + - caption: How to use DataTables + chapters: + - file: advanced_parameters + - file: formatting + - file: custom_css + - file: extensions + - file: custom_extensions + - caption: ITables + chapters: + - file: supported_editors + - file: quarto + - file: downsampling + - file: references + - file: contributing + - file: developing + - file: troubleshooting + - file: changelog + - caption: Example DataFrames + chapters: + - file: sample_dataframes + - file: polars_dataframes + - file: pandas_style diff --git a/docs/advanced_parameters.md b/docs/advanced_parameters.md index af7c0b60..c043b1de 100644 --- a/docs/advanced_parameters.md +++ b/docs/advanced_parameters.md @@ -12,11 +12,11 @@ kernelspec: name: itables --- -# Advanced parameters +# The DataTable Arguments -The `itables` package is a wrapper for the Javascript [datatables.net](https://datatables.net/) library, which has a great [documentation](https://datatables.net/), a huge collection of [examples](https://datatables.net/examples/index), and a useful [forum](https://datatables.net/forums/). +ITables is a wrapper for the Javascript [datatables.net](https://datatables.net/) library, which has a great [documentation](https://datatables.net/), a huge collection of [examples](https://datatables.net/examples/index), and a useful [forum](https://datatables.net/forums/). -Below we give a few examples of how the datatables.net examples can be ported to Python with `itables`. +Below we give a series of examples of how the datatables.net examples can be ported to Python with `itables`. As always, we initialize the `itables` library with @@ -30,6 +30,7 @@ Then we create two sample dataframes: ```{code-cell} import pandas as pd + from itables.sample_dfs import get_countries df_small = pd.DataFrame({"a": [2, 1]}) @@ -54,19 +55,23 @@ You can set additional `tags` on the table like e.g. a [caption](https://datatab show(df, "Countries from the World Bank Database") ``` -The caption appears at the bottom of the table by default. This is governed by `caption-side:bottom` -in the `style` option which you can change. You can also override the location of the caption in the caption tag itself: +The caption appears at the bottom of the table by default (except +in Jupyter Book). This is governed by `caption-side:bottom` +in the [`style` option](style). + +You can also override the location of the caption in the caption tag itself: ```{code-cell} :tags: [full-width] show( df, - tags='Countries from the World Bank Database', + tags='Countries from the World Bank Database', ) ``` -## Layout +(layout)= +## Table layout By default, datatables that don't fit in one page come with a search box, a pagination control, a table summary, etc. You can select which elements are actually displayed using @@ -93,46 +98,9 @@ opt.layout = { ``` ```{tip} -The `layout` option was introduced with `datatables-net==2.0` and deprecates the -former [`dom` option](https://datatables.net/reference/option/dom). If you wish -to continue using the `dom` option, set `opt.warn_on_dom = False`. -``` - -## Buttons - -Since `itables>=2.0`, the datatables [buttons](https://datatables.net/extensions/buttons/) are supported -and let you copy the table data, or export it as CSV or Excel files. - -To display the buttons, you need to pass a `buttons` argument to the `show` function: - -```{code-cell} -show(df, buttons=["copyHtml5", "csvHtml5", "excelHtml5"]) -``` - -You can also specify a [`layout`](advanced_parameters.md#layout) modifier that will decide -the location of the buttons (the default is `layout={"topStart": "buttons"}`). And if -you want to keep the pagination control too, you can add `"pageLength"` to the list of buttons. - -As always, it is possible to set default values for these parameters by setting these on `itables.options`. - -By default, the exported file name is the name of the HTML page. To change it, set a -[`title` option](https://datatables.net/extensions/buttons/examples/html5/filename.html) on the buttons, like -here: - -```{code-cell} -show( - df, - buttons=[ - "pageLength", - {"extend": "csvHtml5", "title": "Countries"}, - {"extend": "excelHtml5", "title": "Countries"}, - ], -) -``` - -```{warning} -At this stage, the PDF button is not implemented. This is because the required PDF libraries -have a large footprint on the bundle size, so we need to study how to allow using user-specific bundles. +The `layout` option was introduced with `itables==2.0` and `datatables-net==2.0` +and deprecates the former [`dom` option](https://datatables.net/reference/option/dom). +If you wish to continue using the `dom` option, set `opt.warn_on_dom = False`. ``` ## Search @@ -190,7 +158,7 @@ show(df, footer=True) ## Column filters Use `column_filters = "header"` or `"footer"` if you wish to display individual column filters -(remove the global search box with a [`layout`](advanced_parameters.md#layout) modifier if desired). +(remove the global search box with a [`layout`](layout) modifier if desired). ```{code-cell} alpha_numeric_df = pd.DataFrame( @@ -220,112 +188,6 @@ get_dict_of_test_dfs()["multiindex"] opt.column_filters = False ``` -## Position and width - -The default value for the table CSS is `table-layout:auto;width:auto;margin:auto;caption-side:bottom`. -Without `width:auto`, tables with few columns still take the full notebook width in Jupyter. -Using `margin:auto` makes non-wide tables centered in Jupyter. - -You can change the CSS used for a single table with e.g. - -```{code-cell} -show(df_small, style="table-layout:auto;width:50%;float:right") -``` - -or you can also change it for all tables by changing `itables.options.style`: - -```python -import itables.options as opt - -opt.style = "table-layout:auto;width:auto" -``` - -## Classes - -Select how your table looks like with the `classes` argument (defaults to `"display nowrap"`) of the `show` function, or by changing `itables.options.classes`. - -Add `"compact"` if you want a denser table: - -```{code-cell} -:tags: [full-width] - -show(df, classes="display nowrap compact") -``` - -Remove `"nowrap"` if you want the cell content to be wrapped: - -```{code-cell} -:tags: [full-width] - -show(df, classes="display") -``` - -[More options](https://datatables.net/manual/styling/classes#Table-classes) like `"cell-border"` are available: - -```{code-cell} -:tags: [full-width] - -show(df, classes="display nowrap cell-border") -``` - -Last but not least, you can add custom classes and provide custom CSS for those, see - -## Pandas formatting - -`itables` builds the HTML representation of your Pandas dataframes using Pandas itself, so -you can use [Pandas' formatting options](https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html). -For instance, you can change the precision used to display floating numbers: - -```{code-cell} -import math -import pandas as pd - -with pd.option_context("display.float_format", "{:,.2f}".format): - show(pd.Series([i * math.pi for i in range(1, 6)])) -``` - -Or you can use a custom formatter: - -```{code-cell} -with pd.option_context("display.float_format", "${:,.2f}".format): - show(pd.Series([i * math.pi for i in range(1, 6)])) -``` - -```{tip} -ITables in version 1.6.0+ can also render -[Pandas Style](https://pandas.pydata.org/docs/user_guide/style.html) -objects as interactive datatables. - -This way, you can easily add background color, and even -tooltips to your dataframes, and still get them -displayed using datatables.net - see our [example](pandas_style.md). -``` - -## Javascript formatting - -Numbers are formatted using Pandas, then are converted back to float to ensure they come in the right order when sorted. -Therefore, to achieve a particular formatting you might have to resort to the -[`columns.render` option](https://datatables.net/examples/advanced_init/column_render.html) -of datatables. - -For instance, this [example](https://datatables.net/forums/discussion/61407/how-to-apply-a-numeric-format-to-a-column) -can be ported like this: - -```{code-cell} -from itables import JavascriptCode - - -show( - pd.Series([i * math.pi * 1e4 for i in range(1, 6)]), - columnDefs=[ - { - "targets": "_all", - "render": JavascriptCode("$.fn.dataTable.render.number(',', '.', 3, '$')"), - } - ], -) -``` - ## Row order Since `itables>=1.3.0`, the interactive datatable shows the rows in the same order as the original dataframe: @@ -364,130 +226,3 @@ or locally by passing an argument `showIndex` to the `show` function: df_with_range_index = pd.DataFrame({"letter": list("abcd")}) show(df_with_range_index, showIndex=True) ``` - -## Advanced cell formatting with JS callbacks - -You can use Javascript callbacks to set the cell or row style depending on the cell content. - -The example below, in which we color in red the cells with negative numbers, is directly inspired by the corresponding datatables.net [example](https://datatables.net/reference/option/columns.createdCell). - -Note how the Javascript callback is declared as `JavascriptFunction` object below. - -```{code-cell} -from itables import JavascriptFunction - -show( - pd.DataFrame([[-1, 2, -3, 4, -5], [6, -7, 8, -9, 10]], columns=list("abcde")), - columnDefs=[ - { - "targets": "_all", - "createdCell": JavascriptFunction( - """ -function (td, cellData, rowData, row, col) { - if (cellData < 0) { - $(td).css('color', 'red') - } -} -""" - ), - } - ], -) -``` - -```{tip} -Since `itables==1.6.0`, you can also render -[Pandas style](pandas_style.md) objects as interactive datatables - -that might be a simpler alternative to the JavaScript callbacks - documented here. -``` - -## Column width - -The [`columnDefs.width`](https://datatables.net/reference/option/columns.width) argument let you adjust the column widths. - -Note that the default value of `style`, or of `autoWidth` (defaults to `True`), might override custom column widths, -so you might have to change their values as in the examples below. - -You can set a fixed width for all the columns with `"targets": "_all"`: - -```{code-cell} -:tags: [full-width] - -show( - df, - columnDefs=[{"width": "120px", "targets": "_all"}], - scrollX=True, - style="width:1200px", - autoWidth=False, -) -``` - -You can also adjust the width of selected columns only: - -```{code-cell} -:tags: [full-width] - -show( - df, - columnDefs=[{"width": "30%", "targets": [2, 3]}], - style="width:100%;margin:auto", -) -``` - -If you wish you can also set a value for `columnDefs` permanently in `itables.options` as demonstrated in the cell alignment example below. - -## Cell alignment - -You can use the datatables.net [cell classes](https://datatables.net/manual/styling/classes#Cell-classes) like `dt-left`, `dt-center`, `dt-right` etc. to set the cell alignment. Specify it for one table by using the `columnDefs` argument of `show` - -```{code-cell} -show(df, columnDefs=[{"className": "dt-center", "targets": "_all"}]) -``` - -or globally by setting `opt.columnDefs`: - -```{code-cell} -opt.columnDefs = [{"className": "dt-center", "targets": "_all"}] -df -``` - -```{code-cell} -del opt.columnDefs -``` - -## HTML in cells - -```{code-cell} -pd.Series( - [ - "bold", - "italic", - 'link', - ], - name="HTML", -) -``` - -## Images in cells - -Since HTML is supported you can display images in your tables. -You can use either -- `` with an url -- `` with a [base64 encoded image](https://stackoverflow.com/a/8499716/9817073). - -```{code-cell} -pd.Series( - { - "url": 'MNIST', - "base64": 'Red dot', - }, - name="Images", -) -``` - -## Select rows - -Not currently implemented. May be made available at a later stage using the [select](https://datatables.net/extensions/select/) extension for datatables. diff --git a/docs/changelog.md b/docs/changelog.md index 4c85b510..45404edd 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -4,15 +4,16 @@ ITables ChangeLog 2.0.0 (2024-03-??) ------------------ +**Added** +- The CSV, Excel and Print buttons are now included ([#50](https://github.com/mwouts/itables/issues/50), [#155](https://github.com/mwouts/itables/issues/155)) +- We have included a few other extensions, and documented how to add more ([#178](https://github.com/mwouts/itables/issues/178), [#207](https://github.com/mwouts/itables/issues/207), [#208](https://github.com/mwouts/itables/issues/208), [#231](https://github.com/mwouts/itables/issues/231)) +- ITables is now tested with Python 3.12 + **Changed** -- ITables uses the latest version `2.0.1` of `datatables-net` ([#121](https://github.com/mwouts/itables/issues/121)) +- ITables uses the latest version `2.0.2` of `datatables-net` ([#121](https://github.com/mwouts/itables/issues/121)) - Large Python integers are now mapped to JavaScript `BigInt` ([#172](https://github.com/mwouts/itables/issues/172)) - ITables is build using `hatch` and `pyproject.toml` -**Added** -- The CSV, Excel and Print buttons are now included ([#50](https://github.com/mwouts/itables/issues/50)) -- ITables is now tested with Python 3.12 - 1.7.1 (2024-03-05) ------------------ diff --git a/docs/custom_css.md b/docs/custom_css.md index c428e8d3..ee2560fe 100644 --- a/docs/custom_css.md +++ b/docs/custom_css.md @@ -12,42 +12,82 @@ kernelspec: name: itables --- -# Custom CSS +# Styling -## Targeting all tables - -You can use CSS to alter how the interactive datatables are rendered. -Use the `.dataTable` class attribute to target all the tables in the notebook, like here: +As usual, we initialize ITables with `init_notebook_mode`, and we create two sample DataFrames: ```{code-cell} +:tags: [hide-input] + +import pandas as pd + +import itables.options as opt from itables import init_notebook_mode, show from itables.sample_dfs import get_countries +df = get_countries(html=False) +df_small = pd.DataFrame({"a": [2, 1]}) init_notebook_mode(all_interactive=True) ``` +## Classes + +Select how your table looks like with the `classes` argument (defaults to `"display nowrap"`) of the `show` function, or by changing `itables.options.classes`. + +Add `"compact"` if you want a denser table: + +```{code-cell} +:tags: [full-width] + +show(df, classes="display nowrap compact") +``` + +Remove `"nowrap"` if you want the cell content to be wrapped: + ```{code-cell} -from IPython.display import display, HTML +:tags: [full-width] + +show(df, classes="display") +``` + +[More options](https://datatables.net/manual/styling/classes#Table-classes) like `"cell-border"` are available: +```{code-cell} +:tags: [full-width] + +show(df, classes="display nowrap cell-border") +``` + +## CSS + +You can use CSS to alter how the interactive datatables are rendered: + +```{code-cell} +from IPython.display import HTML, display css = """ -.dataTable th { font-weight: bolder; } -.dataTable:not(.table_with_monospace_font) tr { font-style: italic; } +.dataTable th { + font-weight: bolder; + font-style: italic; +} """ display(HTML(f"" "")) ``` -```{code-cell} -get_countries() -``` +```{tip} +The command above turns _every datatable_ table header +in the notebook into bold/italic. -## Targeting specific classes +NB: We could have used `.dataTable:not(.table_with_monospace_font)` +to target all `dataTable` except those with the +custom class `table_with_monospace_font` in the next example. +``` -You might also want to target only specific table like in this example -(note how we add the `table_with_monospace_font` class -to the table using the [`classes`](advanced_parameters.md#classes) -argument of the `show` function): +You might also want to alter the style of specific tables only. +To do this, you just need to add a new class to the target tables. +In the example below we add a `table_with_monospace_font` class +to our table: ```{code-cell} class_specific_css = ".table_with_monospace_font { font-family: courier, monospace }" @@ -55,5 +95,85 @@ display(HTML(f"" "")) ``` ```{code-cell} -show(get_countries(), classes="display nowrap table_with_monospace_font") +show(df, classes="display nowrap table_with_monospace_font") +``` + +(style)= +## The style argument + +The `show` function has a `style` argument that determines the +style for that particular table. + +The default value for `style` is `table-layout:auto;width:auto;margin:auto;caption-side:bottom`. +Without `width:auto`, tables with few columns still take the full notebook width in Jupyter. +Using `margin:auto` makes non-wide tables centered in Jupyter. + +## Position and width + +You can set a specific width or position for a table using with the `style` argument of the show function: + +```{code-cell} +show(df_small, style="table-layout:auto;width:50%;float:right") +``` + +or you can also change it for all tables by changing `itables.options.style`: + +```python +import itables.options as opt + +opt.style = "table-layout:auto;width:auto" +``` + +```{tip} +For ajusting the height of a table, see the section on [pagination](advanced_parameters.md#pagination). +``` + +## Column width + +The [`columnDefs.width`](https://datatables.net/reference/option/columns.width) argument let you adjust the column widths. + +Note that the default value of `style`, or of `autoWidth` (defaults to `True`), might override custom column widths, +so you might have to change their values as in the examples below. + +You can set a fixed width for all the columns with `"targets": "_all"`: + +```{code-cell} +:tags: [full-width] + +show( + df, + columnDefs=[{"width": "120px", "targets": "_all"}], + scrollX=True, + style="width:1200px", + autoWidth=False, +) +``` + +You can also adjust the width of selected columns only: + +```{code-cell} +:tags: [full-width] + +show( + df, + columnDefs=[{"width": "30%", "targets": [2, 3]}], + style="width:100%;margin:auto", +) +``` + +If you wish you can also set a value for `columnDefs` permanently in `itables.options` as demonstrated in the cell alignment example below. + +## Cell alignment + +You can use the datatables.net [cell classes](https://datatables.net/manual/styling/classes#Cell-classes) like `dt-left`, `dt-center`, `dt-right` etc. to set the cell alignment. Specify it for one table by using the `columnDefs` argument of `show` + +```{code-cell} +show(df, columnDefs=[{"className": "dt-center", "targets": "_all"}]) +``` + +or globally by setting `opt.columnDefs`: + +```{code-cell} +opt.columnDefs = [{"className": "dt-center", "targets": "_all"}] +df ``` diff --git a/docs/custom_extensions.md b/docs/custom_extensions.md new file mode 100644 index 00000000..621b1bac --- /dev/null +++ b/docs/custom_extensions.md @@ -0,0 +1,123 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: itables + language: python + name: itables +--- + +# Custom Extensions + +## Connected mode + +To use custom extensions in the connected mode, you just have to go to the +[download](https://datatables.net/download/) page of DataTables, +select jQuery, DataTable, and the desired extensions, and take a note of the script URL +when using the _CDN_ download method. + +Then, you pass this custom URL as either the `dt_url` argument of the +`show` function, or you set it on `opt.dt_url`. + +```{code-cell} +from itables import show +from itables.sample_dfs import get_countries + +df = get_countries(html=False) +``` + +For instance, if you wish to use the [select](https://datatables.net/extensions/select/) +extension in the connected mode, you just have to set `dt_url` according to +the [download](https://datatables.net/download/) page of DataTables, that is: + +```{code-cell} +show( + df, + select=True, + dt_url="https://cdn.datatables.net/v/dt/jq-3.7.0/dt-2.0.2/sl-2.0.0/datatables.min.js", +) +``` + +## Internationalisation + +DataTables controls can use a different language than English. To +display the table controls in another language, go to the [internationalisation](https://datatables.net/plug-ins/i18n/) +plug-ins page and find the language URL, like e.g. + +```{code-cell} +show( + df, + language={"url": "https://cdn.datatables.net/plug-ins/2.0.2/i18n/fr-FR.json"}, +) +``` + +```tip +You can also use the internationalization in the offline mode. Download the translation file, +then set `opt.language` accordingly: + +~~~python +import json +import itables.options as opt + +with open("fr-FR.json") as fp: + opt.language = json.load(fp) +~~~ +``` + +## Offline mode + +To use custom extensions in the offline mode, you will need +to create a bundle of jQuery, DataTable, and the desired extensions. + +To do so, make a copy of +[`itables/dt_package`](https://github.com/mwouts/itables/tree/main/itables/dt_package): +```bash +$ ls itables/dt_package/ +package.json package-lock.json README.md src.js +``` + +Add or remove the desired extensions in `package.json` and `src.js`. To do this, +you can use the [DataTables download](https://datatables.net/download/) page and +follow the instructions for the _NPM_ download method. + +For instance, say you want to bundle the PDF export button. Change +`src.js` to this code: +```javascript +import JSZip from 'jszip'; +import jQuery from 'jquery'; +import pdfMake from 'pdfmake'; +import DataTable from 'datatables.net-dt'; +import 'datatables.net-dt/css/dataTables.dataTables.min.css'; + +import 'datatables.net-buttons/js/buttons.html5.mjs'; +import 'datatables.net-buttons/js/buttons.print.mjs'; +import 'datatables.net-buttons-dt/css/buttons.dataTables.min.css'; + +DataTable.Buttons.jszip(JSZip); +DataTable.Buttons.pdfMake(pdfMake); + +pdfMake.vfs = pdfFonts.pdfMake.vfs; + +export { DataTable, jQuery }; +``` + +and run these commands: +```bash +# Install the dependencies in package.json +npm install + +# Install the additional dependencies +npm install pdfmake --save + +# Create dt_bundle.js and dt_bundle.css +npm run build +``` + +Finally, copy `dt_bundle.js`, and `dt_bundle.css` to a location that can be accessed by `itables`, and +pass the path to `dt_bundle.js` as the `dt_bundle` argument of the `init_notebook_mode` method +(or change `itables.options.dt_bundle` accordingly). diff --git a/docs/downsampling.md b/docs/downsampling.md index 3136d2df..70de9a44 100644 --- a/docs/downsampling.md +++ b/docs/downsampling.md @@ -21,16 +21,15 @@ When the data in a table is larger than `maxBytes`, which is equal to 64KB by de If you wish, you can increase the value of `maxBytes` or even deactivate the limit (with `maxBytes=0`). Similarly, you can set a limit on the number of rows (`maxRows`, defaults to 0) or columns (`maxColumns`, defaults to `200`). ```{code-cell} +import itables.options as opt from itables import init_notebook_mode, show +from itables.downsample import nbytes +from itables.sample_dfs import get_indicators init_notebook_mode(all_interactive=True) ``` ```{code-cell} -from itables.sample_dfs import get_indicators -from itables.downsample import nbytes -import itables.options as opt - opt.lengthMenu = [2, 5, 10, 20, 50, 100, 200, 500] opt.maxBytes = 10000 diff --git a/docs/extensions.md b/docs/extensions.md new file mode 100644 index 00000000..0ab90638 --- /dev/null +++ b/docs/extensions.md @@ -0,0 +1,197 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: itables + language: python + name: itables +--- + +# DataTables Extensions + +DataTables comes with a series of [extensions](https://datatables.net/extensions/), which are supported by ITables since v2.0. +A selection of these extensions are included in ITables. + +As usual, we activate ITables with: + +```{code-cell} +from itables import init_notebook_mode, show + +init_notebook_mode() +``` + +and then, we create a few example dataframes: + +```{code-cell} +import string + +import numpy as np +import pandas as pd + +from itables.sample_dfs import get_countries + +df = get_countries(html=False) +# Add extra columns for the searchPanes demo +df["climate_zone"] = np.where( + df["latitude"].abs() < 23.43615, + "Tropical", + np.where( + df["latitude"].abs() < 35, + "Sub-tropical", + # Artic circle is 66.563861 but there is no capital there => using 64 + np.where(df["latitude"].abs() < 64, "Temperate", "Frigid"), + ), +) +df["hemisphere"] = np.where(df["latitude"] > 0, "North", "South") +wide_df = pd.DataFrame( + { + letter: np.random.normal(size=100) + for letter in string.ascii_lowercase + string.ascii_uppercase + } +) +``` + +## Buttons + +The datatables [buttons](https://datatables.net/extensions/buttons/) let you copy the table data, or export it as CSV or Excel files. + +To display the buttons, you need to pass a `buttons` argument to the `show` function: + +```{code-cell} +:tags: [full-width] + +show(df, buttons=["copyHtml5", "csvHtml5", "excelHtml5"]) +``` + +You can also specify a [`layout`](layout) modifier that will decide +the location of the buttons (the default is `layout={"topStart": "buttons"}`). And if +you want to keep the pagination control too, you can add `"pageLength"` to the list of buttons. + +As always, it is possible to set default values for these parameters by setting these on `itables.options`. + +By default, the exported file name is the name of the HTML page. To change it, set a +[`title` option](https://datatables.net/extensions/buttons/examples/html5/filename.html) on the buttons, like +here: + +```{code-cell} +:tags: [full-width] + +show( + df, + buttons=[ + "pageLength", + {"extend": "csvHtml5", "title": "Countries"}, + {"extend": "excelHtml5", "title": "Countries"}, + ], +) +``` + +```{warning} +The PDF button is not included in ITables's DataTable bundle. This is because the required PDF libraries +have a large footprint on the bundle size. Still, you can add it to your custom bundle, see the next chapters. +``` + +## FixedColumns + +[FixedColumn](https://datatables.net/extensions/fixedcolumns/) is an extension +that let you fix some columns as you scroll horizontally. + +```{code-cell} +:tags: [full-width] + +show( + wide_df, + fixedColumns={"start": 1, "end": 2}, + scrollX=True, +) +``` + +## RowGroup + +Use the [RowGroup](https://datatables.net/extensions/rowgroup/) extension to group +the data according to the content of one colum. Optionally, you can hide the content +of that column to avoid duplicating the information. + +```{code-cell} +:tags: [full-width] + +show( + df.sort_values("region"), + rowGroup={"dataSrc": 1}, + columnDefs=[{"targets": 1, "visible": False}], +) +``` + +## ColReorder + +The [ColReorder](https://datatables.net/extensions/colreorder/) lets you re-order the columns: + +```{code-cell} +:tags: [full-width] + +show(df, colReorder=True) +``` + +```{tip} +You can activate this option for all your tables with + +~~~python +import itables.options as opt + +opt.colReorder = True +~~~ +``` + +## KeyTable + +With the [KeyTable](https://datatables.net/extensions/keytable/) extension you can navigate in a table using the arrow keys: + +```{code-cell} +:tags: [full-width] + +show(df, keys=True) +``` + +```{warning} +The KeyTable extension works in Jupyter Book (try it here in the documentation) but not in JupyterLab. +``` + ++++ + +## SearchBuilder + +[SearchBuilder](https://datatables.net/extensions/searchbuilder/) let you build complex search queries. + +```{warning} +When searching, please keep in mind that ITables will [downsample](downsampling.md) your table if it is larger than `maxBytes`, +so you might not see the full dataset - pay attention to the downsampling message at the bottom left of the table. +``` + +```{code-cell} +:tags: [full-width] + +show(df, layout={"top1": "searchBuilder"}) +``` + +## SearchPanes + +[SearchPanes](https://datatables.net/extensions/searchpanes/) is an extension that lets you select rows based on +unique values. In the example below we have activated the cascade filtering through the +[`searchPanes.cascadePanes`](https://datatables.net/extensions/searchpanes/examples/initialisation/cascadePanes.html) argument. +Note that, in Jupyter, the [`searchPanes.layout`](https://datatables.net/extensions/searchpanes/layout) +argument is required (otherwise the search panes are far too wide). + +```{code-cell} +:tags: [full-width] + +show( + df, + layout={"top1": "searchPanes"}, + searchPanes={"layout": "columns-3", "cascadePanes": True}, +) +``` diff --git a/docs/formatting.md b/docs/formatting.md new file mode 100644 index 00000000..bae4f4e6 --- /dev/null +++ b/docs/formatting.md @@ -0,0 +1,172 @@ +--- +jupytext: + formats: md:myst + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: itables + language: python + name: itables +--- + +# Formatting + +## Formatting with Pandas + +`itables` builds the HTML representation of your Pandas dataframes using Pandas itself, so +you can use [Pandas' formatting options](https://pandas.pydata.org/pandas-docs/stable/user_guide/options.html). +For instance, you can change the precision used to display floating numbers: + +```{code-cell} +from itables import init_notebook_mode, show +from itables.sample_dfs import get_countries + +init_notebook_mode(all_interactive=True) +``` + +```{code-cell} +import math + +import pandas as pd + +with pd.option_context("display.float_format", "{:,.2f}".format): + show(pd.Series([i * math.pi for i in range(1, 6)])) +``` + +Or you can use a custom formatter: + +```{code-cell} +with pd.option_context("display.float_format", "${:,.2f}".format): + show(pd.Series([i * math.pi for i in range(1, 6)])) +``` + +## Formatting with Javascript + +Numbers are formatted using Pandas, then are converted back to float to ensure they come in the right order when sorted. +Therefore, to achieve a particular formatting you might have to resort to the +[`columns.render` option](https://datatables.net/examples/advanced_init/column_render.html) +of datatables. + +For instance, this [example](https://datatables.net/forums/discussion/61407/how-to-apply-a-numeric-format-to-a-column) +can be ported like this: + +```{code-cell} +from itables import JavascriptCode + +show( + pd.Series([i * math.pi * 1e4 for i in range(1, 6)]), + columnDefs=[ + { + "targets": "_all", + "render": JavascriptCode("$.fn.dataTable.render.number(',', '.', 3, '$')"), + } + ], +) +``` + +## Colors based on cell values + +You can use Javascript callbacks to set the cell or row style depending on the cell content. + +The example below, in which we color in red the cells with negative numbers, is directly inspired by the corresponding datatables.net [example](https://datatables.net/reference/option/columns.createdCell). + +Note how the Javascript callback is declared as `JavascriptFunction` object below. + +```{code-cell} +from itables import JavascriptFunction + +show( + pd.DataFrame([[-1, 2, -3, 4, -5], [6, -7, 8, -9, 10]], columns=list("abcde")), + columnDefs=[ + { + "targets": "_all", + "createdCell": JavascriptFunction( + """ +function (td, cellData, rowData, row, col) { + if (cellData < 0) { + $(td).css('color', 'red') + } +} +""" + ), + } + ], +) +``` + +## Formatting with Pandas style + +ITables in version 1.6 and above can render +[Pandas Style](https://pandas.pydata.org/docs/user_guide/style.html) +objects as interactive datatables. + +This way, you can easily add background color, and even +tooltips to your dataframes, and still get them +displayed using datatables.net - see our [examples](pandas_style.md). + +```{warning} +Please note that Pandas Style objects are rendered using +their `.to_html()` method, which is less efficient that +the default JS data export used by ITables. +``` + +## HTML in cells + +### A simple example + +HTML content is supported, which means that you can have formatted text, +links or even images in your tables: + +```{code-cell} +pd.Series( + [ + "bold", + "italic", + 'link', + ], + name="HTML", +) +``` + +### Images in a table + +```{code-cell} +:tags: [full-width] + +df = get_countries(html=False) + +df["flag"] = [ + '' + ''.format(code=code.lower(), country=country) + for code, country in zip(df.index, df["country"]) +] +df["country"] = [ + '{}'.format(country, country) + for country in df["country"] +] +df["capital"] = [ + '{}'.format(capital, capital) + for capital in df["capital"] +] +df +``` + +### Base64 images + +[Base64 encoded image](https://stackoverflow.com/a/8499716/9817073) are supported, too: + +```{code-cell} +pd.Series( + { + "url": 'MNIST', + "base64": 'Red dot', + }, + name="Images", +) +``` diff --git a/docs/pandas_style.md b/docs/pandas_style.md index ddc6f528..8db0feab 100644 --- a/docs/pandas_style.md +++ b/docs/pandas_style.md @@ -12,14 +12,15 @@ kernelspec: name: itables --- -# Pandas Style +# Pandas Style examples Starting with `itables>=1.6.0`, ITables provides support for [Pandas Style](https://pandas.pydata.org/docs/user_guide/style.html). ```{code-cell} -import pandas as pd import numpy as np +import pandas as pd + from itables import init_notebook_mode init_notebook_mode(all_interactive=True) diff --git a/docs/quick_start.md b/docs/quick_start.md index 8e7516a4..a388fc5d 100644 --- a/docs/quick_start.md +++ b/docs/quick_start.md @@ -16,7 +16,6 @@ kernelspec: ![CI](https://github.com/mwouts/itables/actions/workflows/continuous-integration.yml/badge.svg?branch=main) [![codecov.io](https://codecov.io/github/mwouts/itables/coverage.svg?branch=main)](https://codecov.io/github/mwouts/itables?branch=main) -[![Language grade: Python](https://img.shields.io/lgtm/grade/python/g/mwouts/itables.svg)](https://lgtm.com/projects/g/mwouts/itables/context:python) [![Pypi](https://img.shields.io/pypi/v/itables.svg)](https://pypi.python.org/pypi/itables) [![Conda Version](https://img.shields.io/conda/vn/conda-forge/itables.svg)](https://anaconda.org/conda-forge/itables) [![pyversions](https://img.shields.io/pypi/pyversions/itables.svg)](https://pypi.python.org/pypi/itables) @@ -24,7 +23,7 @@ kernelspec: Star -## Turn your Python DataFrames into Interactive Tables +## Turn your Python DataFrames into Interactive DataTables This packages changes how Pandas and Polars DataFrames are rendered in Jupyter Notebooks. With `itables` you can display your tables as interactive [datatables](https://datatables.net/) @@ -84,13 +83,12 @@ In some contexts (Jupyter Book, Jupyter Colab, etc...) you might prefer to load the libraries dynamically from the internet. To do so, add the argument `connected=True` when you execute `init_notebook_mode`. This will also make your notebook lighter by -about [500kB](https://github.com/mwouts/itables/blob/main/tests/test_connected_notebook_is_small.py). +about [700kB](https://github.com/mwouts/itables/blob/main/tests/test_connected_notebook_is_small.py). -## Formatting specific tables only +## Using ITables for specific tables only If you prefer to render only certain series or dataframes using `itables`, -or you want to use the [advanced parameters](advanced_parameters.md), then -use `init_notebook_mode(all_interactive=False)` then `show`: +then call `init_notebook_mode(all_interactive=False)` then `show`: ```{code-cell} from itables import show @@ -98,31 +96,6 @@ from itables import show show(df, lengthMenu=[2, 5, 10, 25, 50, 100, 250]) ``` -## HTML content - -HTML content is supported, which means that you can have formatted text, -links or even images in your tables: - -```{code-cell} -:tags: [full-width] - -df["flag"] = [ - '' - ''.format(code=code.lower(), country=country) - for code, country in zip(df.index, df["country"]) -] -df["country"] = [ - '{}'.format(country, country) - for country in df["country"] -] -df["capital"] = [ - '{}'.format(capital, capital) - for capital in df["capital"] -] -df -``` - ## Try ITables on Binder You can run our examples notebooks directly on [![Lab](https://img.shields.io/badge/Binder-JupyterLab-blue.svg)](https://mybinder.org/v2/gh/mwouts/itables/main?urlpath=lab/tree/docs/quick_start.md), without having to install anything on your side. diff --git a/docs/supported_editors.md b/docs/supported_editors.md index 3b455b50..9d1a5d3d 100644 --- a/docs/supported_editors.md +++ b/docs/supported_editors.md @@ -32,7 +32,7 @@ A short sample notebook is available [here](https://colab.research.google.com/dr ## VS Code -In VS Code, `itables` works both for Jupyter Notebooks and Python scripts +In VS Code, `itables` works both for Jupyter Notebooks and Python scripts. ![](images/code.png) @@ -65,6 +65,7 @@ html = to_html_datatable(df) You can use ITables in Web applications generated with [Shiny](https://shiny.rstudio.com/py/) for Python with e.g. ```python from shiny import ui + from itables.shiny import DT ui.HTML(DT(df)) diff --git a/itables/dt_package/README.md b/itables/dt_package/README.md new file mode 100644 index 00000000..33f0b1c4 --- /dev/null +++ b/itables/dt_package/README.md @@ -0,0 +1,14 @@ +This directory contains a bundle of [DataTable](https://datatables.net/) +and some of its extensions for ITables. + +To compile the bundle, run the following commands: +```bash +npm install +npm run build +``` + +To update the dependencies of the bundle, run +```bash +npm update +``` +(check whether there are any outdated package with `npm outdated`). diff --git a/itables/dt_package/package-lock.json b/itables/dt_package/package-lock.json index 3ad0c6ee..3af48e1b 100644 --- a/itables/dt_package/package-lock.json +++ b/itables/dt_package/package-lock.json @@ -1,161 +1,40 @@ { - "name": "dt", + "name": "dt_for_itables", "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "dt", + "name": "dt_for_itables", "version": "2.0.0", "license": "MIT", "dependencies": { "datatables.net-buttons": "^3.0.0", "datatables.net-buttons-dt": "^3.0.0", - "datatables.net-dt": "^2.0.1", + "datatables.net-colreorder-dt": "^2.0.0", + "datatables.net-dt": "^2.0.0", + "datatables.net-fixedcolumns-dt": "^5.0.0", + "datatables.net-keytable-dt": "^2.12.0", + "datatables.net-rowgroup-dt": "^1.5.0", + "datatables.net-searchbuilder-dt": "^1.7.0", + "datatables.net-searchpanes-dt": "^2.3.0", + "datatables.net-select-dt": "^2.0.0", "jquery": "^3.7.1", "jszip": "^3.10.1" }, "devDependencies": { - "esbuild": "^0.20.0" + "esbuild": "*" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.1.tgz", - "integrity": "sha512-m55cpeupQ2DbuRGQMMZDzbv9J9PgVelPjlcmM5kxHnrBdBx6REaEd7LamYV7Dm8N7rCyR/XwU6rVP8ploKtIkA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.1.tgz", - "integrity": "sha512-4j0+G27/2ZXGWR5okcJi7pQYhmkVgb4D7UKwxcqrjhvp5TKWx3cUjgB1CGj1mfdmJBQ9VnUGgUhign+FPF2Zgw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.1.tgz", - "integrity": "sha512-hCnXNF0HM6AjowP+Zou0ZJMWWa1VkD77BXe959zERgGJBBxB+sV+J9f/rcjeg2c5bsukD/n17RKWXGFCO5dD5A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.1.tgz", - "integrity": "sha512-MSfZMBoAsnhpS+2yMFYIQUPs8Z19ajwfuaSZx+tSl09xrHZCjbeXXMsUF/0oq7ojxYEpsSo4c0SfjxOYXRbpaA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.1.tgz", - "integrity": "sha512-Ylk6rzgMD8klUklGPzS414UQLa5NPXZD5tf8JmQU8GQrj6BrFA/Ic9tb2zRe1kOZyCbGl+e8VMbDRazCEBqPvA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.1.tgz", - "integrity": "sha512-pFIfj7U2w5sMp52wTY1XVOdoxw+GDwy9FsK3OFz4BpMAjvZVs0dT1VXs8aQm22nhwoIWUmIRaE+4xow8xfIDZA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.1.tgz", - "integrity": "sha512-UyW1WZvHDuM4xDz0jWun4qtQFauNdXjXOtIy7SYdf7pbxSWWVlqhnR/T2TpX6LX5NI62spt0a3ldIIEkPM6RHw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { + "node_modules/@esbuild/linux-x64": { "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.1.tgz", - "integrity": "sha512-itPwCw5C+Jh/c624vcDd9kRCCZVpzpQn8dtwoYIt2TJF3S9xJLiRohnnNrKwREvcZYx0n8sCSbvGH349XkcQeg==", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", + "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", "cpu": [ "x64" ], "dev": true, "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.1.tgz", - "integrity": "sha512-LojC28v3+IhIbfQ+Vu4Ut5n3wKcgTu6POKIHN9Wpt0HnfgUGlBuyDDQR4jWZUZFyYLiz4RBBBmfU6sNfn6RhLw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, "os": [ "linux" ], @@ -163,268 +42,177 @@ "node": ">=12" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.1.tgz", - "integrity": "sha512-cX8WdlF6Cnvw/DO9/X7XLH2J6CkBnz7Twjpk56cshk9sjYVcuh4sXQBy5bmTwzBjNVZze2yaV1vtcJS04LbN8w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.1.tgz", - "integrity": "sha512-4H/sQCy1mnnGkUt/xszaLlYJVTz3W9ep52xEefGtd6yXDQbz/5fZE5dFLUgsPdbUOQANcVUa5iO6g3nyy5BJiw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-2.0.2.tgz", + "integrity": "sha512-uQM+s1oXhpTajUw5DCxarpfAtQJMh0MKFCLZMCc+UWLWPg8ipe6L2zgDMbRC8n9UCwGVpHOwUYlQu2JU1/PhSg==", + "dependencies": { + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.1.tgz", - "integrity": "sha512-c0jgtB+sRHCciVXlyjDcWb2FUuzlGVRwGXgI+3WqKOIuoo8AmZAddzeOHeYLtD+dmtHw3B4Xo9wAUdjlfW5yYA==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-buttons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/datatables.net-buttons/-/datatables.net-buttons-3.0.1.tgz", + "integrity": "sha512-VjTEooHtjHW2VY5/iddTLMRy2G2TtT2GyYwN9EmaMsG4MClD5lWfYdkpv/NMwz175gx7fe1lh/NVAYT4W3jMSg==", + "dependencies": { + "datatables.net": "^2", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.1.tgz", - "integrity": "sha512-TgFyCfIxSujyuqdZKDZ3yTwWiGv+KnlOeXXitCQ+trDODJ+ZtGOzLkSWngynP0HZnTsDyBbPy7GWVXWaEl6lhA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-buttons-dt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/datatables.net-buttons-dt/-/datatables.net-buttons-dt-3.0.1.tgz", + "integrity": "sha512-kfZrc+954qpg6krz1pcVKVhxOzbZByaGHwwO0CcjKdIREBX4la4HkoIZGWsENSYSfdHUkHu9WWa84p9Rl+JtiQ==", + "dependencies": { + "datatables.net-buttons": "3.0.1", + "datatables.net-dt": "^2", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.1.tgz", - "integrity": "sha512-b+yuD1IUeL+Y93PmFZDZFIElwbmFfIKLKlYI8M6tRyzE6u7oEP7onGk0vZRh8wfVGC2dZoy0EqX1V8qok4qHaw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-colreorder": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-colreorder/-/datatables.net-colreorder-2.0.0.tgz", + "integrity": "sha512-ZsDHKxisGbdBh2IEb+AC6O3LgkBoibCbdXaZKBK6SBUEul085Zt3NUFmieTljXVkDWdewSLg4IvhkE8zKzQjVQ==", + "dependencies": { + "datatables.net": ">=2.0.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.1.tgz", - "integrity": "sha512-wpDlpE0oRKZwX+GfomcALcouqjjV8MIX8DyTrxfyCfXxoKQSDm45CZr9fanJ4F6ckD4yDEPT98SrjvLwIqUCgg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-colreorder-dt": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-colreorder-dt/-/datatables.net-colreorder-dt-2.0.0.tgz", + "integrity": "sha512-UG1Y0edaz9dDY6W2M+g7itcYnyK5oqO1YtFtRwkqcCvKA4d5+lvk9Va6utkOIsjNZZXiUFHn8ySTTND9MeOyQg==", + "dependencies": { + "datatables.net-colreorder": "2.0.0", + "datatables.net-dt": ">=2.0.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.1.tgz", - "integrity": "sha512-5BepC2Au80EohQ2dBpyTquqGCES7++p7G+7lXe1bAIvMdXm4YYcEfZtQrP4gaoZ96Wv1Ute61CEHFU7h4FMueQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-dt": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/datatables.net-dt/-/datatables.net-dt-2.0.2.tgz", + "integrity": "sha512-/Zpy7ZWGgCbCJB9qJZvaB+KFrdo+8JjjOdxL59/QiG3jquz2ZCsE9u814kbaGKTM1ARkvZVUxDB9IlH5qmHaqw==", + "dependencies": { + "datatables.net": "2.0.2", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.1.tgz", - "integrity": "sha512-5gRPk7pKuaIB+tmH+yKd2aQTRpqlf1E4f/mC+tawIm/CGJemZcHZpp2ic8oD83nKgUPMEd0fNanrnFljiruuyA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-fixedcolumns": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-fixedcolumns/-/datatables.net-fixedcolumns-5.0.0.tgz", + "integrity": "sha512-7dTJrVDkZCicx9g//N3ufuEjvwrZpcmpjbkwrtC5LiQFCnuL/hMOiOb4CBcvTg5OiTU7VmtbBuQkeAJGs3QM5g==", + "dependencies": { + "datatables.net": ">=2.0.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.1.tgz", - "integrity": "sha512-4fL68JdrLV2nVW2AaWZBv3XEm3Ae3NZn/7qy2KGAt3dexAgSVT+Hc97JKSZnqezgMlv9x6KV0ZkZY7UO5cNLCg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-fixedcolumns-dt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-fixedcolumns-dt/-/datatables.net-fixedcolumns-dt-5.0.0.tgz", + "integrity": "sha512-5KVH6EHeYSXrxrEhKq8HMKqf4iRW4T1dtiDYZRomiwfAh/0iCeaamxgT5OFN8VJ/qpiwnyrDh3SqXA8Te0kE7w==", + "dependencies": { + "datatables.net-dt": ">=2.0.0", + "datatables.net-fixedcolumns": "5.0.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.1.tgz", - "integrity": "sha512-GhRuXlvRE+twf2ES+8REbeCb/zeikNqwD3+6S5y5/x+DYbAQUNl0HNBs4RQJqrechS4v4MruEr8ZtAin/hK5iw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-keytable": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/datatables.net-keytable/-/datatables.net-keytable-2.12.0.tgz", + "integrity": "sha512-vijxMw7ZIB/fDe5FWGiDqe8CPiPXg3lvqK4lL48vQh1zoiE3+0C3za82qM9g/2zbwtIXmOLwBZc2ivrErNVPkA==", + "dependencies": { + "datatables.net": ">=1.11.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.1.tgz", - "integrity": "sha512-ZnWEyCM0G1Ex6JtsygvC3KUUrlDXqOihw8RicRuQAzw+c4f1D66YlPNNV3rkjVW90zXVsHwZYWbJh3v+oQFM9Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-keytable-dt": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/datatables.net-keytable-dt/-/datatables.net-keytable-dt-2.12.0.tgz", + "integrity": "sha512-FubrNaitx13Mq2cny2fxuV/Nk6bbmGw6VrH9Df81CT/jVfwAEkwIFirETEoL/hZfQDcD76ujj0b1wNDZ5Bsv9Q==", + "dependencies": { + "datatables.net-dt": ">=1.11.0", + "datatables.net-keytable": "2.12.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.1.tgz", - "integrity": "sha512-QZ6gXue0vVQY2Oon9WyLFCdSuYbXSoxaZrPuJ4c20j6ICedfsDilNPYfHLlMH7vGfU5DQR0czHLmJvH4Nzis/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-rowgroup": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/datatables.net-rowgroup/-/datatables.net-rowgroup-1.5.0.tgz", + "integrity": "sha512-V/CLJu7rMjxwfhZAv59emZOPw58cwnYmd8NXTTJSnqBDgOZsaC9mtVo0ejBpdqvNw5WmMPy3AJceH+ay6JQ3hA==", + "dependencies": { + "datatables.net": ">=1.11.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.1.tgz", - "integrity": "sha512-HzcJa1NcSWTAU0MJIxOho8JftNp9YALui3o+Ny7hCh0v5f90nprly1U3Sj1Ldj/CvKKdvvFsCRvDkpsEMp4DNw==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-rowgroup-dt": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/datatables.net-rowgroup-dt/-/datatables.net-rowgroup-dt-1.5.0.tgz", + "integrity": "sha512-Dmn+ToLeUXDDg58Skie25xiWDy0GfgAMbiB8CMnOWKXH/gnGRjoU1V80R7ll8HbxGB6YfppXkPsPn00XU7c2xA==", + "dependencies": { + "datatables.net-dt": ">=1.11.0", + "datatables.net-rowgroup": "1.5.0", + "jquery": ">=1.7" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.1.tgz", - "integrity": "sha512-0MBh53o6XtI6ctDnRMeQ+xoCN8kD2qI1rY1KgF/xdWQwoFeKou7puvDfV8/Wv4Ctx2rRpET/gGdz3YlNtNACSA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" + "node_modules/datatables.net-searchbuilder": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/datatables.net-searchbuilder/-/datatables.net-searchbuilder-1.7.0.tgz", + "integrity": "sha512-JGqxDVudgRxrHs/J+VM9O2rcwPgaUjpqBL1MHJAVJw+4vxvAY5Sbb0qP6ayo8h4yZyAE2+aPRm/smJ24N0nztw==", + "dependencies": { + "datatables.net": ">=1.11.0", + "jquery": ">=1.7" } }, - "node_modules/core-util-is": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", - "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + "node_modules/datatables.net-searchbuilder-dt": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/datatables.net-searchbuilder-dt/-/datatables.net-searchbuilder-dt-1.7.0.tgz", + "integrity": "sha512-FKeL5xDEO4dF0CA+Vp4KkAdOdhfoCB3KaWdHiscki/9x4r03e0lD8g0V2oynHe4EshLHxFb/ug1Rd5GLcW/yAg==", + "dependencies": { + "datatables.net-dt": ">=1.11.0", + "datatables.net-searchbuilder": "1.7.0", + "jquery": ">=1.7" + } }, - "node_modules/datatables.net": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/datatables.net/-/datatables.net-2.0.1.tgz", - "integrity": "sha512-VvAZWkjkvEF4i3GprHbXrfHoG7gZPAZ5FWXcvkiL4ELFfLIwPUjt8qzCSml7SH5hI8Lm45DYSnp9d0xl/sWrMw==", + "node_modules/datatables.net-searchpanes": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/datatables.net-searchpanes/-/datatables.net-searchpanes-2.3.0.tgz", + "integrity": "sha512-AAl03TQXatzQh6gqNot1BAzenMxQ0/mxX+Nzn770mdTUmhVy2VX8pa7/vZlwe0tRbTcZ9VZMBMErCb66i5X3rA==", "dependencies": { + "datatables.net": ">=1.11.0", "jquery": ">=1.7" } }, - "node_modules/datatables.net-buttons": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/datatables.net-buttons/-/datatables.net-buttons-3.0.0.tgz", - "integrity": "sha512-ThC7/H116bHpDFRK+TbBb/UPcxm+PzQbmnrzUGEq9O0teaA7ClAYIkzzTatKPsOHtf7qGqry5pMxuOTyocJIxQ==", + "node_modules/datatables.net-searchpanes-dt": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/datatables.net-searchpanes-dt/-/datatables.net-searchpanes-dt-2.3.0.tgz", + "integrity": "sha512-ee4sEYYPRb+uXtAGL9KmIyjyyh8Ox4EI0a/GKHsCRrO1BTrnh7lZ+z8hJUc/TZJFDkgbYHh8XGPQXLOZUpIXHA==", "dependencies": { - "datatables.net": ">=2.0.0", + "datatables.net-dt": ">=1.11.0", + "datatables.net-searchpanes": "2.3.0", "jquery": ">=1.7" } }, - "node_modules/datatables.net-buttons-dt": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/datatables.net-buttons-dt/-/datatables.net-buttons-dt-3.0.0.tgz", - "integrity": "sha512-ZEMHbUAFbXoKIxd3HIwrEkoUo2VhL0ekv8CFG8nKBW4LN+lLChtaXykSDZjWjWgT9LvddRfliEv0OvVwO5uEAw==", + "node_modules/datatables.net-select": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-select/-/datatables.net-select-2.0.0.tgz", + "integrity": "sha512-sKMNoTlJejk5FfZo6Niwdn2/bHSDYiIt5WuMSsXzMGiCTIPtnDiYjNHF843vToKiTTsi+6T0zUuWddHLGPRsxA==", "dependencies": { - "datatables.net-buttons": "3.0.0", - "datatables.net-dt": ">=2.0.0", + "datatables.net": ">=2.0.0", "jquery": ">=1.7" } }, - "node_modules/datatables.net-dt": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/datatables.net-dt/-/datatables.net-dt-2.0.1.tgz", - "integrity": "sha512-XnhFVxNBdKAnqwQa1iEG38Rlgq8jQV89GK2DZMqGX0/N+X/CdPpGGMjGmPtGyhuzt3v5xRSRsyBl8Uuo61Znuw==", + "node_modules/datatables.net-select-dt": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/datatables.net-select-dt/-/datatables.net-select-dt-2.0.0.tgz", + "integrity": "sha512-w6uP7Q4/U675dkrC2Lg0B3P7cwUTxfyUgcc+Qt4XUyAqa+6rk/YjiYHfsrDZ9vUZdu66DFdj7hNZtZfkBBPjLg==", "dependencies": { - "datatables.net": "2.0.1", + "datatables.net-dt": ">=2.0.0", + "datatables.net-select": "2.0.0", "jquery": ">=1.7" } }, diff --git a/itables/dt_package/package.json b/itables/dt_package/package.json index 60ac80c8..233e99c8 100644 --- a/itables/dt_package/package.json +++ b/itables/dt_package/package.json @@ -1,21 +1,28 @@ { - "name": "dt", + "name": "dt_for_itables", "version": "2.0.0", "description": "datatables-net bundle for itables", "main": "src.js", "scripts": { - "build": "esbuild src.js --format=esm --bundle --outfile=../dt_bundle/dt.js --minify" + "build": "esbuild src.js --format=esm --bundle --outfile=dt_bundle.js --minify" }, "author": "Marc Wouts", "license": "MIT", "dependencies": { "datatables.net-buttons": "^3.0.0", "datatables.net-buttons-dt": "^3.0.0", - "datatables.net-dt": "^2.0.1", + "datatables.net-colreorder-dt": "^2.0.0", + "datatables.net-dt": "^2.0.0", + "datatables.net-fixedcolumns-dt": "^5.0.0", + "datatables.net-keytable-dt": "^2.12.0", + "datatables.net-rowgroup-dt": "^1.5.0", + "datatables.net-searchbuilder-dt": "^1.7.0", + "datatables.net-searchpanes-dt": "^2.3.0", + "datatables.net-select-dt": "^2.0.0", "jquery": "^3.7.1", "jszip": "^3.10.1" }, "devDependencies": { - "esbuild": "^0.20.0" + "esbuild": "*" } } diff --git a/itables/dt_package/src.js b/itables/dt_package/src.js index 0d7da62b..66b61621 100644 --- a/itables/dt_package/src.js +++ b/itables/dt_package/src.js @@ -3,11 +3,31 @@ import jQuery from 'jquery'; import DataTable from 'datatables.net-dt'; import 'datatables.net-dt/css/dataTables.dataTables.min.css'; -import 'datatables.net-buttons'; import 'datatables.net-buttons/js/buttons.html5.mjs'; import 'datatables.net-buttons/js/buttons.print.mjs'; import 'datatables.net-buttons-dt/css/buttons.dataTables.min.css'; DataTable.Buttons.jszip(JSZip); +import 'datatables.net-colreorder-dt'; +import 'datatables.net-colreorder-dt/css/colReorder.dataTables.min.css'; + +import 'datatables.net-fixedcolumns-dt'; +import 'datatables.net-fixedcolumns-dt/css/fixedColumns.dataTables.min.css'; + +import 'datatables.net-keytable-dt'; +import 'datatables.net-keytable-dt/css/keyTable.dataTables.min.css'; + +import 'datatables.net-rowgroup-dt'; +import 'datatables.net-rowgroup-dt/css/rowGroup.dataTables.min.css'; + +import 'datatables.net-searchbuilder-dt'; +import 'datatables.net-searchbuilder-dt/css/searchBuilder.dataTables.min.css'; + +import 'datatables.net-searchpanes-dt'; +import 'datatables.net-searchpanes-dt/css/searchPanes.dataTables.min.css'; + +import 'datatables.net-select-dt'; +import 'datatables.net-select-dt/css/select.dataTables.min.css'; + export { DataTable, jQuery }; diff --git a/itables/html/datatables_template_connected.html b/itables/html/datatables_template_connected.html index 1928faf5..364b228d 100644 --- a/itables/html/datatables_template_connected.html +++ b/itables/html/datatables_template_connected.html @@ -1,9 +1,7 @@
A
- +