-
Notifications
You must be signed in to change notification settings - Fork 60
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Offline mode #70
Comments
Hi @BBassi , yes that is something that I would like to see supported in the future. Do you think you you could help us with this, I mean, do you think you could author a PR in that direction? Thanks |
@mwouts We do not have the bandwidth to do this internally BUT am happy to pay someone do it |
Oh that is very kind of you ! Let me invite @AllanJard in this issue. Allan is the founder of SpryMedia, and the author of the (Javascript) datatables library. Allan, would you like to be working on this question of allowing the offline use of datatables in the context of Jupyter Notebooks ? If so, would you like to propose a quote to @BBassi ? I am happy to help with the python packaging (e.g. include the datatables files in the python package), but I don't have the know-how on how to build an offline web page. Also, there are two other issues that we might have to address before this one, they are:
|
Hi :) You'll need to forgive me, by I've not used a Jupyter Notebook yet (still on my list to fire up sometime!), so I'm not familar with how its offline mode works. Is there a package manager that installs packages for offline use or something? Are there other Javascript libraries (e.g. Bootstrap, jQuery, etc) that have an offline mode for Jupyter Notebooks? |
Hi @AllanJard , well sure no problem. I'll try to give a few pointers and they we'll see if there is any direction that looks easier than others.
If you're never used a notebook before maybe you might want to try this directly on https://colab.research.google.com/.
|
Just Jupyterlab |
Okay, so if I understand correctly, we'd need to package DataTables in a Python library? That would get installed on the notebook and can be referenced by the python package? Is it not possible to reference npm packages? I guess another way of wording that is what is the end user installation of this? Presumably they aren't installing a python module, but rather a package that happens to contain Python software (and whatever else is needed - e.g. Javascript)? |
Hi @AllanJard , yes the fact that @BBassi wants this in Jupyter Lab only should allow us to provide the functionality through a "Jupyter Lab extension". Maybe we can do something like this: load datatables as a dependency of the jupyter lab extension, and detect in the notebook whether datatables is already available (in Jupyter Lab), or not (in other contexts). I see this example Jupyter Lab extension: https://github.com/jupyterlab/extension-examples/tree/master/datagrid that might be of some inspiration to us (though I have not looked into the details) @BBassi , would you mind to contact @AllanJard - maybe through his website (https://sprymedia.co.uk/) - to make him an offer for solving this issue ? Thanks ! |
Done |
Awesome. Thank you both! Allan, I think the next steps could be as follow:
Does that seems alright to you? |
Sounds good to me - let me know how you get on :-) |
I plan to start working on 1. and 2. soon, maybe tonight. For 2. I'll try to follow this tutorial. Maybe Allan you can help me with TypeScript - what would be the syntax for importing import { ICommandPalette, MainAreaWidget } from '@jupyterlab/apputils'; what should we write to import |
@jptio, @fcollonval, the tutorial on Jupyter Lab extensions is great, but I am struggling to add the extension to the current I moved parts of the The issue that I am facing is that the build process looks for the
Could you please point out at what I need to change in my setup.py ? Also, do you think creating an extension is the right thing to do to provide a npm library (here, |
Hi @AllanJard , I am trying again to build a very simple extension. For simplicity I have created another project at https://github.com/mwouts/jupyterlab-itables2 (and when it starts working I will merge it with the main So I wrote something like this: initDataTables();
// This is not the final code - but say that we want to turn
// any HTML table into an interactive table
$(document).ready(() => {
const tables = document.getElementsByTagName('table');
for (let i = 0; i < tables.length; i++) {
const table = tables[i];
table.DataTable();
}
}); but the problem is that I cannot build the package (
Do you see how should I change |
I may have found a syntactically correct fix at mwouts/jupyterlab-itables2@fae71ca. Now the question is how I can use the |
I see that this extension provides the mathjax library in Jupyter Lab, it might be a good starting point |
At some point I have been able to expose With the extension enabled I have been able to load the libraries locally in Jupyter Lab with e.g.
I'll have to confirm that this really works (seems to be a slight issue at the moment), and also we will have to find out how to update |
Hi _ sorry I wasn't able to reply over the weekend. That looks good to me - statically including local files. I couldn't see the Javascript initialisation in the latest repo though, although I might just be clean missing it on a Monday morning! |
Hi @AllanJard , Yes you're right the JS files are not included in the repo - it is only when the python package is build that they are included. I have a few questions about this by the way:
Other than the above, what I need from you is a change to I'd like the template file to work in three different settings:
|
It would certainly be cleaner to do so, yes. The only thing I can think of that might be an issue is if you decide to use Bootstrap or something else in future, you'd just need to remember to copy those files across as well.
I can't speak officially for jQuery, but yes, that is absolutely fine. As long as the copyright notice at the top of the Javascript files is retained, which it will be with a straight copy, then it is within the licensing requirements (MIT for both jQuery and DataTables). The Allan |
Hi Allan, thanks for the above. Then I'll package a first version of the extension (with just the static files) tonight or tomorrow. The datatables template file is in this repository (itables). I am afraid I will have to keep the static files in another repo as they will have to be installed at a different location (static files on the jupyter server python environment , itables on the python environment used as a kernel), but maybe for you you just need to consider that you are working on a simple html file plus static libraries. With the static files included as above I got a few errors, like require is not defined and $ is not defined - the only way I got datatables to work in Jupyter Lab being with the ES imports until now. |
Hi @AllanJard , I've tried to take a few more steps on this project...
|
Thanks! Given that the Javascript is just being run directly in the browser, and no bundler is being used, I wonder if you might be best just importing the static files in the same way as you do for the CSS files - e.g.: <script src="/static/itables/datatables.net/js/jquery.dataTables.js"></script> It will then work immediately, since when included by a browser it will make itself available on the global |
Well, I am afraid Javascript will always remain so mysterious for me... As suggested, I have added I have also updated the In some cases that works (restart kernel and run all cells?) but in some others (Ctrl+R on a saved notebook?) it does not: The problem is with the jQuery global variable: Here is the HTML for the reloaded notebook - it still seems to have the jQuery script: @AllanJard , do you see how to address this? Last but not least I'd like the |
Part of the problem might be that the Otherwise I am also aware of the |
I've spent long hours trying to make the I would by much prefer to use local imports - @AllanJard , is it possible to use |
Hi - sorry this is taking so much of your time!
Unfortunately no - the esm file isn't included in the package. I'll get that in for the 1.12 release which is up coming. Since you have static files, you could just grap the content from here though. That might be a good option to get a PoC while I get the 1.12 release ready. I should note that I don't currently have esm plans for the extensions for DataTables though. As noted in the issue you linked, the dependency loading when using esm in the browser is not clear. So this approach would be limited until we can solve that. I'm afraid I have no idea about the jQuery load issue. What you've done is what I would expect to work in a browser, so I suspect there is perhaps something specific about the Jupyter Notebook (perhaps the framework?) that is causing that issue. Is there a Jupyter support forum / channel? |
Thank you @AllanJard. Oh that's great news that you already have an ES module at https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.mjs ! Sure no problem I can add the file to the static files (done at mwouts/jupyterlab-itables@36ec441). I'll give a try to the import approach, I think it has the potential to make the table template short and self contained. Hopefully your ES module will work even when No worries if we cannot get the extensions immediately, I much prefer to have a simple and clear template ! |
Well, we're not done yet... At https://datatables.net/manual/installation#NPM the instructions to import datatables are
but in Jupyter Lab I don't have So I tried this:
but then @AllanJard would you have an example for importing BTW I noticed that import 'https://cdn.datatables.net/1.11.5/js/jquery.dataTables.min.mjs' or similar causes the following error:
Maybe a MIME type for .mjs files should be set on the CDN? |
@AllanJard , do you have a minimal example that shows how to import the |
Oof - sorry about loosing track of this one. Try this:
(I've added the mime type handler for it now). |
Thank you @AllanJard . Actually I am afraid I also need some help on the example HTML... I've tried this minimal example: <table id="table"><thead><tr><th>A</th></tr></thead></table>
<link href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css" rel="stylesheet">
<script type="module">
import 'https://code.jquery.com/jquery-3.5.1.min.js';
import 'https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.mjs';
$(document).ready(function () {
$('#table').DataTable(dt_args);
});
</script> but I get this error:
Is this something that you know how to fix? Or more importantly, what should I import exactly from import {$} from 'https://code.jquery.com/jquery-3.5.1.min.js';
import {initDataTables} from 'https://cdn.datatables.net/1.12.1/js/jquery.dataTables.min.mjs';
initDataTables($); Thanks ! |
This is how to do it: import 'https://code.jquery.com/jquery-3.5.1.min.js';
import dt from 'https://cdn.datatables.net/1.12.1/js/jquery.dataTables.mjs';
dt($);
$(document).ready(function () {
$('#table').DataTable({});
}); http://live.datatables.net/yecukepe/1/edit Live example. It looks like the |
Thanks @AllanJard ! I've tested the code snippet just above and I can confirm that it works (BTW may I suggest you had a new section on this at https://datatables.net/manual/installation ?) Now I need to find out how to replace the fixed urls with dynamic ones (either distant or local). My naive attempt below results in an error "$ is not a function", so I guess the problem is with the jQuery import. Maybe on this point I can ask once more for @fwouts' help, he's so good at solving these kind of issues! let jQuery_url = 'https://code.jquery.com/jquery-3.5.1.min.js';
let datatables_url = 'https://cdn.datatables.net/1.12.1/js/jquery.dataTables.mjs';
const { default: $ } = await import(jQuery_url);
const { default: dt } = await import(datatables_url);
// works
dt($);
// fails with error "$ is not a function"
$(document).ready(function () {$('#table_id').DataTable();}); |
Thanks! As soon as I figure out how to load in the extensions and styling integration files with ES modules, then yes, it will go up there as fully supported. I've made no progress or found a way to do dependencies with ES modules in a way that would be suitable (like we discussing in the other thread). Until something for that becomes available, it would require a big long list of import statements which isn't ideal. Recarding the error - what happens if you |
@AllanJard , yes when I do
with If I interpolate with the current working version of Still I'd prefer to not use |
Regarding your questions on how to load the extensions and styling with ES modules, I am afraid I can't help here, but maybe @fwouts will have a pointer for you? The SO thread says
but if I replace the first line with |
@mwouts I think it should be: import jQuery from 'jquery';
window.$ = jQuery;
window.jQuery = jQuery; |
I've spent some more time on this, here are a few findings:
|
Hi again... good news, I think we're almost ready! I have a release candidate ready, @BBassi would you like to test it? You will need to install the development version
Also you will need to install separately the static files, which is documented at https://github.com/mwouts/itables/blob/offline_mode_always_use_import/docs/quick_start.md#offline-mode (@BBassi can you tell me if it is clear enough that one needs to install the extension in the Python env used to launch Jupyter Lab?) Then I'd like to know who I can thank in the changelog... @BBassi, @AllanJard was then any sponsoring involved in the end? Kind regards |
That's awesome - nice one! Nope - no sponsoring in the end. |
Thanks Allan! Indeed getting rid of the switch between |
@AllanJard, we are currently studying yet another option with @fwouts at #77 - we are considering to just inject the JS code in the notebook (=HTML file). I prefer this approach as the user will not need to install another Python package (but we still have to fix some issues probably related to the constraint that our scripts are injected in the HTML body, not head...) When doing the above, we noticed that we can load <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script> but we can't do that for That seems to be the only reason why we want to import datatables using an ES import (the ES import is robust to the presence of require). Is that something that you would be willing to fix? A MRE is this HTML file (it works when you delete the require.js script) <!DOCTYPE html>
<html>
<head>
<title>DataTables</title>
</head>
<body>
<link href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.css" rel="stylesheet" type="text/css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.12.1/js/jquery.dataTables.js"></script>
<script>
$(document).ready(function () {
$('#table').DataTable({});
});
</script>
<div class="container">
<table id="table" class="display nowrap" width="100%">
<thead>
<atr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Age</th>
<th>Start date</th>
<th>Salary</th>
</tr>
</tfoot>
<tbody>
<tr>
<td>Tiger Nixon</td>
<td>System Architect</td>
<td>Edinburgh</td>
<td>61</td>
<td>2011/04/25</td>
<td>$3,120</td>
</tr>
<tr>
<td>Donna Snider</td>
<td>System Architect</td>
<td>New York</td>
<td>27</td>
<td>2011/01/25</td>
<td>$3,120</td>
</tr>
</tbody>
</table>
</div>
</body>
</html> |
I'm not sure that is going to be a "proper" change in DataTables. jQuery is somewhat unique in the AMD world in that is exports itself as a named module, and it looks like in an AMD environment it will also register to the browser's global scope. That rather goes against the modularisation that AMD tries to achieve. This is what DataTables does if we detect that require.js is present (as an AMD loader): if ( typeof define === 'function' && define.amd ) {
// AMD
define( ['jquery'], function ( $ ) {
return factory( $, window, document );
} );
} Whereas with jQuery, if you look at their loader they only make a distinction between CommonJS and everything else, with an AMD / Require.js loader being added later on in their code: if ( typeof define === "function" && define.amd ) {
define( "jquery", [], function() {
return jQuery;
} );
} When Require.js is present, I've assumed that DataTables will be used only via Require.js. I could change that, but I'm not convinced that it would be the correct decision to make. |
If a remote URL is acceptable (perhaps at build stage) perhaps something like: ?
|
Hi @AllanJard , thank you for the detailed answer !
Yes that is exactly the problem that I am facing. In some environments the notebook will have require.js, in some others it won't, and I have no choice on that (and I cannot generate the notebook accordingly - I need that the same notebook works in both cases). Thanks also for the suggestion to use Maybe what we can do is to document this issue on datatables' issue tracker and when you find the proper approach (sorry again for not being able to help you with this) I'll get a notification and will reconsider using the non-ES script ? |
Sounds good to me! I've just been reading about Import maps which would be the business for this I think. Chrome based browsers only for now though (is that an issue on Jupyter Notebooks - can they run Firefox?) |
Very good, thanks Allan! Done at DataTables/DataTablesSrc#213.
Oh I'm afraid that's still a long way to extensions then... Jupyter Notebooks are supposed to work in all browsers, and sometime in very exotic browsers like VS Code or PyCharm, so we might not be able to use import maps in all these environments for a while... That's a strong argument for going back to plain JS scripts when the require.js issue is solved, isn't it? 😄 |
Its probably a strong argument to use a pre-processing bundler to generate a single <script> file that you load in. |
This is not something that I am familiar with, but apparently my brother is, so maybe indeed we will see that at a later stage. But I guess this is for the vanilla JS version of datatables.net, so maybe we will have to fix DataTables/DataTablesSrc#213 first? Regarding this issue I am super happy to let you know that we have integrated #77 and that |
@fwouts and @AllanJard thank you again for your lovely help here... Thanks to the more uniform loading of the JS libraries (and a much shorter template file), I've been able to proceed with other little developments like the column filters (#81), and now I am even seeing some partial success with datatables plugins (#83)! |
At the moment itables does not have an offline mode. While the table data is embedded in the notebook, the jquery and datatables.net are loaded from a CDN, see require.config and table template, so an internet connection is required to display the tables.
Is there a way to add offline usage?
The text was updated successfully, but these errors were encountered: