j1-template 2022.3.0 → 2022.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (58) hide show
  1. checksums.yaml +4 -4
  2. data/_includes/themes/j1/modules/navigator/generator.html +1 -1
  3. data/assets/data/cookieconsent.html +4 -4
  4. data/assets/data/nbinteract.html +128 -0
  5. data/assets/data/quicklinks.html +15 -0
  6. data/assets/data/translator.html +15 -15
  7. data/assets/themes/j1/adapter/js/cookieConsent.js +1 -1
  8. data/assets/themes/j1/adapter/js/mmenu.js +25 -3
  9. data/assets/themes/j1/adapter/js/navigator.js +2 -2
  10. data/assets/themes/j1/adapter/js/nbinteract.js +412 -113
  11. data/assets/themes/j1/core/css/themes/unolight/bootstrap.css +27 -54
  12. data/assets/themes/j1/core/css/themes/unolight/bootstrap.min.css +1 -1
  13. data/assets/themes/j1/core/js/template.js +14 -3
  14. data/assets/themes/j1/core/js/template.min.js +1 -1
  15. data/assets/themes/j1/core/js/template.min.js.map +1 -1
  16. data/assets/themes/j1/modules/cookieConsent/js/cookieConsent.js +1 -0
  17. data/assets/themes/j1/modules/nbInteract/js/nbinteract/nbinteract-core.js +1 -1
  18. data/assets/themes/j1/modules/nbInteract/js/nbinteract/nbinteract-core.js.map +1 -1
  19. data/assets/themes/j1/modules/nbInteract/js/nbinteract/nbinteract-core.min.js +1 -1
  20. data/lib/j1/version.rb +1 -1
  21. data/lib/starter_web/Gemfile +1 -1
  22. data/lib/starter_web/_config.yml +1 -1
  23. data/lib/starter_web/_data/modules/defaults/cookieconsent.yml +55 -42
  24. data/lib/starter_web/_data/modules/defaults/navigator.yml +4 -0
  25. data/lib/starter_web/_data/modules/defaults/nbinteract.yml +99 -1
  26. data/lib/starter_web/_data/modules/defaults/translator.yml +24 -12
  27. data/lib/starter_web/_plugins/lunr_index.rb +1 -1
  28. data/lib/starter_web/package.json +1 -1
  29. data/lib/starter_web/pages/public/jupyter/docs/j1-nbinteract-doc.adoc +20 -6
  30. data/lib/starter_web/pages/public/jupyter/docs/nbi-widget-manual.adoc +6 -6
  31. data/lib/starter_web/pages/public/jupyter/docs/nbinteract-doc.adoc +24 -19
  32. data/lib/starter_web/pages/public/jupyter/examples/j1-circular-times-table.adoc +14 -16
  33. data/lib/starter_web/pages/public/jupyter/examples/j1-interactive-widgets.adoc +8 -5
  34. data/lib/starter_web/pages/public/jupyter/examples/j1-odes-in-python.adoc +11 -8
  35. data/lib/starter_web/pages/public/jupyter/examples/j1-testing-plotly.adoc +12 -4
  36. data/lib/starter_web/pages/public/jupyter/examples/j1_climate-change-forecast.adoc +8 -8
  37. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_circular_times_table-checkpoint.ipynb +12387 -0
  38. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_interactive_widgets-checkpoint.ipynb +26 -26
  39. data/lib/starter_web/pages/public/jupyter/notebooks/j1/.ipynb_checkpoints/j1_odes_in_python-checkpoint.ipynb +10 -10
  40. data/lib/starter_web/pages/public/jupyter/notebooks/j1/factor_by_factor.mp4 +0 -0
  41. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_circular_times_table.ipynb +10 -13
  42. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_interactive_widgets.ipynb +26 -26
  43. data/lib/starter_web/pages/public/jupyter/notebooks/j1/j1_odes_in_python.ipynb +15 -15
  44. data/lib/starter_web/pages/public/jupyter/notebooks/j1/line_by_line.mp4 +0 -0
  45. data/lib/starter_web/pages/public/jupyter/notebooks/j1/point_by_point.mp4 +0 -0
  46. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_examples_central_limit_theorem-checkpoint.ipynb +247 -0
  47. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/.ipynb_checkpoints/nbi_docs_recipes_graphing-checkpoint.ipynb +18 -18
  48. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/nbi_docs_examples_central_limit_theorem.ipynb +1 -2
  49. data/lib/starter_web/pages/public/jupyter/notebooks/nbi-docs/nbi_docs_recipes_graphing.ipynb +18 -18
  50. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_circular_times_table.html +6 -9
  51. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_interactive_widgets.html +919 -919
  52. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/j1_odes_in_python.html +10 -10
  53. data/lib/starter_web/pages/public/jupyter/notebooks/textbooks/nbi_docs_recipes_graphing.html +473 -473
  54. data/lib/starter_web/pages/public/jupyter/services/jupyterhub.adoc +6 -7
  55. data/lib/starter_web/pages/public/se/se-fake.adoc +47 -0
  56. data/lib/starter_web/utilsrv/_defaults/package.json +1 -1
  57. data/lib/starter_web/utilsrv/package.json +1 -1
  58. metadata +9 -2
@@ -83,6 +83,9 @@ j1.adapter.nbinteract = (function (j1, window) {
83
83
  var moduleOptions = {};
84
84
  var moduleSettings = {};
85
85
  var message = {};
86
+ var flags = {
87
+ checkURL: false
88
+ };
86
89
  var spinnerOpts = { // (default) options for a spinner
87
90
  lines: 13, // number of lines to draw
88
91
  length: 38, // length of each line
@@ -103,16 +106,23 @@ j1.adapter.nbinteract = (function (j1, window) {
103
106
  className: 'spinner', // CSS class assined to the spinner
104
107
  position: 'fixed', // element positioning: absolute|fixed
105
108
  };
109
+
110
+ var nbActions = {
111
+ "resetLocalStorage": true
112
+ };
113
+
106
114
  var spinnerStarted = false; // switch to indicate a started spinner
107
115
  var nbiContentModalInfoID = 'nbiModalInfoBody'; // ID of the content (messages) for the INFO modal
108
116
  var nbiContentModalSuccessID = 'nbiModalSuccessBody'; // ID of the content (messages) for the SUCCESS modal
109
117
  var nbiContentModalErrorID = 'nbiModalErrorBody'; // ID of the content (messages) for the SUCCESS modal
110
- var nbiModalInfoID = '#' + 'nbiModalTopInfo'; // ID of the SUCCESS modal
118
+ var nbiModalTopInfo = '#' + 'nbiModalTopInfo'; // ID of the TopInfo modal
119
+ var nbiModalTRInfo = '#' + 'nbiModalTRInfo'; // ID of the TRInfo modal
111
120
  var nbiModalSuccessID = '#' + 'nbiModalTRSuccess'; // ID of the SUCCESS modal
112
121
  var nbiModalErrorID = '#' + 'nbiModalTLDanger'; // ID of the ERROR modal
113
122
  var nbinteract_prepared = false; // switch to indicate if ???
114
123
  var nbiModalSuccessMessagesID = 'nbiModalSuccessMessages'; // UL contalner SUCCESS messages
115
- var nbiModalErrorMessagesID = 'nbiModalErrorMessages'; // UL contalner ERROR messahes
124
+ var nbiModalErrorMessagesID = 'nbiModalErrorMessages'; // UL contalner ERROR messages
125
+ var nbiCellsRendered = false; // flag indicates if all widgets in page are rendered
116
126
  var nbiShowMessages; // switch to show NBI messages
117
127
  var nbiIndicateNbiActivity; // switch to show a spinner while NBI is being initialized
118
128
  var nbiModalAutoClose; // switch to auto-close nbi message modals
@@ -129,6 +139,10 @@ j1.adapter.nbinteract = (function (j1, window) {
129
139
  var logger;
130
140
  var coreLogger;
131
141
  var logText;
142
+ var widgetCells;
143
+ var widgetCellsRendered;
144
+ var nbiNotebookReady;
145
+ var Events;
132
146
 
133
147
  // ---------------------------------------------------------------------------
134
148
  // Helper functions
@@ -144,6 +158,19 @@ j1.adapter.nbinteract = (function (j1, window) {
144
158
  // -------------------------------------------------------------------------
145
159
  init: function (options) {
146
160
 
161
+ // -----------------------------------------------------------------------
162
+ // global event handler
163
+ // -----------------------------------------------------------------------
164
+ Events = {
165
+ documentReady: function (onDocumentReady) {
166
+ if (document.readyState !== 'loading') {
167
+ onDocumentReady();
168
+ } else {
169
+ document.addEventListener('DOMContentLoaded', onDocumentReady);
170
+ }
171
+ }
172
+ };
173
+
147
174
  // -----------------------------------------------------------------------
148
175
  // Default module settings
149
176
  // -----------------------------------------------------------------------
@@ -165,6 +192,7 @@ j1.adapter.nbinteract = (function (j1, window) {
165
192
  nbiShowMessages = moduleOptions.show_nbi_messages;
166
193
  nbiIndicateNbiActivity = moduleOptions.indicate_nbi_activity;
167
194
  nbiInitMathJax = moduleOptions.nbi_init_mathjax;
195
+ nbiNotebookReady = moduleOptions.notebook_ready;
168
196
 
169
197
  // -----------------------------------------------------------------------
170
198
  // load|configure Mathjax
@@ -172,20 +200,24 @@ j1.adapter.nbinteract = (function (j1, window) {
172
200
  if (nbiInitMathJax) {
173
201
  _this.initMathJax();
174
202
  }
203
+ // -----------------------------------------------------------------------
204
+ // load|configure NBI dialog (modal)
205
+ // -----------------------------------------------------------------------
206
+ _this.loadDialog(moduleOptions);
175
207
 
176
208
  // -----------------------------------------------------------------------
177
- // load HTML data for all modals used by nbInteract
209
+ // load all modals (HTML portion) used by NBI
178
210
  // -----------------------------------------------------------------------
179
211
  _this.loadNbiModals();
180
212
 
181
213
  // -----------------------------------------------------------------------
182
- // load the HTML portion for all textbooks configured|enabled
214
+ // load all textbooks (HTML portion) configured|enabled
183
215
  // -----------------------------------------------------------------------
184
216
  _this.loadNbiTextbooks(moduleOptions);
185
217
 
186
- // -------------------------------------------------------------------
218
+ // -----------------------------------------------------------------------
187
219
  // run a spinner to indicate activity of 'nbInteract' if enabled
188
- // -------------------------------------------------------------------
220
+ // -----------------------------------------------------------------------
189
221
  $(document).ready(function() {
190
222
  if (nbiIndicateNbiActivity && !spinnerStarted) {
191
223
  spinnerStarted = true;
@@ -209,6 +241,19 @@ j1.adapter.nbinteract = (function (j1, window) {
209
241
  // -----------------------------------------------------------------------
210
242
  _this.interactNbiTextbooks(moduleOptions);
211
243
 
244
+ // toggle hide|show the FAB button, if to wait on 'last_widget' rendered
245
+ //
246
+ if (nbiNotebookReady == 'last_widget') {
247
+ var dependencies_met_page_rendered = setInterval(function() {
248
+ if (nbiCellsRendered) {
249
+ $('.fab-btn').show();
250
+ clearInterval(dependencies_met_page_rendered);
251
+ } else {
252
+ $('.fab-btn').hide();
253
+ }
254
+ }, 25); // END interval dependencies_met_page_rendered
255
+ }
256
+
212
257
  }, // END init
213
258
 
214
259
  // -------------------------------------------------------------------------
@@ -391,98 +436,124 @@ j1.adapter.nbinteract = (function (j1, window) {
391
436
  // controlled by nbinteract_prepared.
392
437
  // -------------------------------------------------------------------------
393
438
  interactNbiTextbooks: function (options) {
439
+ var state;
394
440
  var textbook = options;
395
441
 
396
442
  // initialize state flag
397
443
  _this.setState('started');
398
444
  logger.debug('\n' + 'state: ' + _this.getState());
399
445
 
446
+ // check if the Binder Service is available
447
+ //
448
+ _this.checkURL(options.baseUrl, flags);
449
+
400
450
  var log_text = '\n' + 'nbinteract is being initialized';
401
451
  logger.info(log_text);
402
452
 
403
- // var nbiButtonsFound = document.querySelectorAll('.js-nbinteract-widget')
404
-
405
- {% comment %} initialize nbinteract per textbook
406
- {% assign textbook_spec = item.textbook.spec %}
407
- {% assign textbook_baseUrl = item.textbook.baseUrl %}
408
- {% assign textbook_provider = item.textbook.provider %}
409
- -------------------------------------------------------------------------- {% endcomment %}
410
- {% for item in nbinteract_options.textbooks %} {% if item.textbook.enabled %}
411
- {% assign textbook_id = item.textbook.id %}
412
-
413
- if ($('#{{textbook_id}}').length) {
414
- var dependencies_met_nb_loaded = setInterval(function() {
415
- if ($('#{{textbook_id}}').attr('data-nb-textbook') == 'loaded') {
416
-
417
- var nbiButtonsFound = document.querySelectorAll('.js-nbinteract-widget').length
418
- if (nbiIndicateNbiActivity && nbiButtonsFound == 1) {
419
- var log_text = '\n' + 'non-nbi textbook found, skip NBI initialization for: {{textbook_id}}';
420
- logger.warn(log_text);
421
- spinner.stop();
422
- }
423
-
424
- if(!nbinteract_prepared && nbiButtonsFound > 1) {
425
- logText = '\n' + 'jupyter kernel is being generated ...';
426
- logger.info(logText);
453
+ var dependencies_met_binder_responsive = setInterval(function() {
454
+ state = _this.getState();
455
+ if (state == 'finished_checks') {
456
+ clearInterval(dependencies_met_binder_responsive);
457
+ if (flags.checkURL) {
458
+ {% comment %} initialize nbinteract per textbook
459
+ {% assign textbook_spec = item.textbook.spec %}
460
+ {% assign textbook_baseUrl = item.textbook.baseUrl %}
461
+ {% assign textbook_provider = item.textbook.provider %}
462
+ -------------------------------------------------------------------------- {% endcomment %}
463
+ {% for item in nbinteract_options.textbooks %} {% if item.textbook.enabled %}
464
+ {% assign textbook_id = item.textbook.id %}
465
+
466
+ if ($('#{{textbook_id}}').length) {
467
+ var dependencies_met_nb_loaded = setInterval(function() {
468
+ if ($('#{{textbook_id}}').attr('data-nb-textbook') == 'loaded') {
469
+
470
+ var nbiButtonsFound = document.querySelectorAll('.js-nbinteract-widget').length
471
+ if (nbiIndicateNbiActivity && nbiButtonsFound == 1) {
472
+ var log_text = '\n' + 'non-nbi textbook found, skip NBI initialization for: {{textbook_id}}';
473
+ logger.warn(log_text);
474
+ spinner.stop();
475
+ }
427
476
 
428
- // create nbInteract (core) instance
429
- //
430
- coreLogger = log4javascript.getLogger('nbinteract.core');
431
- interact = new NbInteract({
432
- spec: options.spec,
433
- baseUrl: options.baseUrl,
434
- provider: options.provider,
435
- logger: coreLogger,
436
- j1API: j1,
437
- });
438
-
439
- // generate a jupyter kernel via BinderHub
440
- interact.prepare();
441
- nbinteract_prepared = true;
442
-
443
- // issue an error if the NBI (init) button never removed by
444
- // nbInteract-core (util or manager)
445
- // TODO: The 'timeout' condition should be replaced
446
- // state-based triggered from nbInteract-core.
447
- //
448
- window.setTimeout(function() {
449
- var nbiButtonState = _this.getNbiButtonState();
450
- if (nbiButtonState) {
451
- // button NOT removed
452
- logger.warn('NBI initialialization failed on textbook: {{textbook_id}}');
453
- // hide the info modal
454
- $(nbiModalSuccessID).modal('hide');
455
-
456
- // show the error modal
457
- $(nbiModalSuccessID).on('hidden.bs.modal', function () {
458
- if ($(nbiModalErrorID).is(':hidden')) {
459
- var messageErrorUL = document.getElementById(nbiModalErrorMessagesID);
460
- _this.appendModalMessage(messageErrorUL, 'NBI initialialization failed for textbook: {{textbook_id}}')
461
- $(nbiModalErrorID).modal('show');
462
-
463
- // auto-close the error modal
464
- if (nbiModalAutoClose) {
465
- window.setTimeout(function() {
466
- $(nbiModalErrorID).modal('hide');
467
- }, nbiModalAutoCloseDelay);
477
+ if(!nbinteract_prepared && nbiButtonsFound > 1) {
478
+ logText = '\n' + 'jupyter kernel is being generated ...';
479
+ logger.info(logText);
480
+
481
+ // create nbInteract (core) instance
482
+ //
483
+ coreLogger = log4javascript.getLogger('nbinteract.core');
484
+ interact = new NbInteract({
485
+ spec: options.spec,
486
+ baseUrl: options.baseUrl,
487
+ provider: options.provider,
488
+ logger: coreLogger,
489
+ j1API: j1,
490
+ });
491
+
492
+ // generate a jupyter kernel via BinderHub
493
+ interact.prepare();
494
+ nbinteract_prepared = true;
495
+
496
+ // issue an error if the NBI (init) button never removed by
497
+ // nbInteract-core (util or manager)
498
+ // TODO: The 'timeout' condition should be replaced
499
+ // state-based triggered from nbInteract-core.
500
+ //
501
+ window.setTimeout(function() {
502
+ var nbiButtonState = _this.getNbiButtonState();
503
+ if (nbiButtonState) {
504
+ // button NOT removed
505
+ logger.warn('NBI initialialization failed on textbook: {{textbook_id}}');
506
+ // hide the info modal
507
+ $(nbiModalSuccessID).modal('hide');
508
+
509
+ // show the error modal
510
+ $(nbiModalSuccessID).on('hidden.bs.modal', function () {
511
+ if ($(nbiModalErrorID).is(':hidden')) {
512
+ var messageErrorUL = document.getElementById(nbiModalErrorMessagesID);
513
+ _this.appendModalMessage(messageErrorUL, 'NBI initialialization failed for textbook: {{textbook_id}}')
514
+ $(nbiModalErrorID).modal('show');
515
+
516
+ // auto-close the error modal
517
+ if (nbiModalAutoClose) {
518
+ window.setTimeout(function() {
519
+ $(nbiModalErrorID).modal('hide');
520
+ }, nbiModalAutoCloseDelay);
521
+ }
522
+ }
523
+ });
524
+ } else {
525
+ // button removed
526
+ logger.info('NBI initialized successfully.');
468
527
  }
469
- }
470
- });
471
- } else {
472
- // button removed
473
- logger.info('NBI initialized successfully.');
474
- }
475
- }, nbiInitTimeout);
528
+ }, nbiInitTimeout);
476
529
 
530
+ }
531
+
532
+ clearInterval(dependencies_met_nb_loaded);
533
+ } // END dependencies_met_nb_loaded
534
+ }, 25);
535
+ return;
536
+ }
537
+ // END textbook_id: {{ textbook_id }}
538
+ {% endif %} {% endfor %}
539
+ } else {
540
+ spinner.stop();
541
+ var modaBodyText = `
542
+ The <i>Binder Service</i> is currently not available or is overloaded.
543
+ All interactive components on the page are <b>not</b> available.
544
+ You can reload the page or re-open later again.
545
+ `;
546
+ logger.error('\n', 'Binder access: failed');
547
+ if ($(nbiModalTRInfo).is(':hidden')) {
548
+ document.getElementById('nbiModalTRInfoBody').innerHTML = modaBodyText;
549
+ $(nbiModalTRInfo).modal('show');
477
550
  }
551
+ clearInterval(dependencies_met_binder_responsive);
552
+ }
553
+
554
+ }
555
+ }, 25); // END dependencies_met_binder_responsive
478
556
 
479
- clearInterval(dependencies_met_nb_loaded);
480
- } // END dependencies_met_nb_loaded
481
- }, 25);
482
- return;
483
- }
484
- // END textbook_id: {{ textbook_id }}
485
- {% endif %} {% endfor %}
486
557
  },
487
558
 
488
559
  // -------------------------------------------------------------------------
@@ -533,7 +604,7 @@ j1.adapter.nbinteract = (function (j1, window) {
533
604
 
534
605
  // ------------------------------------------------------------------
535
606
  // see: https://www.codingexercises.com/replace-all-instances-of-css-class-in-vanilla-js
536
- // see: https://wiki.selfhtml.org/wiki/JavaScript/Operatoren/Rest-_oder_Spread-Operator
607
+ // see: https://wiki.thishtml.org/wiki/JavaScript/Operatoren/Rest-_oder_Spread-Operator
537
608
  // ------------------------------------------------------------------
538
609
 
539
610
  // disable (Google) translation for all HTML 'output_wrapper' elements
@@ -815,6 +886,45 @@ j1.adapter.nbinteract = (function (j1, window) {
815
886
  </div>
816
887
  </div>
817
888
  `
889
+
890
+ const nbiModalTRInfo = `
891
+ <div id="nbiModalTRInfo"
892
+ class="modal fade right"
893
+ tabindex="-1"
894
+ role="dialog"
895
+ aria-labelledby="myModalLabel" aria-hidden="true"
896
+ data-bs-keyboard="false"
897
+ data-bs-backdrop="static">
898
+ <div class="modal-dialog modal-dialog-scrollable modal-side-2x modal-top-right modal-notify modal-success" role="document">
899
+ <!-- Content -->
900
+ <div class="modal-content">
901
+ <!-- Header -->
902
+ <div class="modal-header">
903
+ <p class="lead">Information</p>
904
+ <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
905
+ <i class="mdi mdi-close mdi-dark mdi-48px"></i>
906
+ </button>
907
+ </div>
908
+ <!-- Icon -->
909
+ <div class="text-center">
910
+ <i class="mdi mdi-10x mdi-information-variant mdi-spin md-green mb-1"></i>
911
+ </div>
912
+ <!-- Body -->
913
+ <div id="nbiModalTRInfoBody" class="modal-body">
914
+ <div>
915
+ <p> Placeholder </p>
916
+ </div>
917
+ </div>
918
+ <!-- Footer -->
919
+ <div class="modal-footer justify-content-center">
920
+ <a type="button" class="btn btn-primary" data-bs-dismiss="modal">OK, thanks</a>
921
+ </div>
922
+ </div>
923
+ <!-- END Content -->
924
+ </div>
925
+ </div>
926
+ `
927
+
818
928
  const nbiModalTRSuccess = `
819
929
  <div id="nbiModalTRSuccess"
820
930
  class="modal fade right"
@@ -828,7 +938,7 @@ j1.adapter.nbinteract = (function (j1, window) {
828
938
  <div class="modal-content">
829
939
  <!-- Header -->
830
940
  <div class="modal-header">
831
- <p class="lead">Info - NbInteract</p>
941
+ <p class="lead">NBI - Information</p>
832
942
  <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
833
943
  <i class="mdi mdi-close mdi-dark mdi-48px"></i>
834
944
  </button>
@@ -853,6 +963,7 @@ j1.adapter.nbinteract = (function (j1, window) {
853
963
  </div>
854
964
  </div>
855
965
  `
966
+
856
967
  const nbiModalTLDanger = `
857
968
  <div id="nbiModalTLDanger"
858
969
  class="modal fade left"
@@ -866,7 +977,7 @@ j1.adapter.nbinteract = (function (j1, window) {
866
977
  <div id="nbiModalErrorBody" class="modal-content">
867
978
  <!--Header-->
868
979
  <div class="modal-header">
869
- <p class="lead">Error - NbInteract</p>
980
+ <p class="lead">NBI - Error</p>
870
981
  <button type="button" class="close" data-bs-dismiss="modal" aria-label="Close">
871
982
  <i class="mdi mdi-close mdi-dark mdi-48px"></i>
872
983
  </button>
@@ -897,6 +1008,12 @@ j1.adapter.nbinteract = (function (j1, window) {
897
1008
  nbiModal.innerHTML = nbiModalTopInfo;
898
1009
  document.body.appendChild(nbiModal);
899
1010
 
1011
+ nbiModal = document.createElement('div');
1012
+ nbiModal.id = 'nbi-modal-info';
1013
+ nbiModal.className = 'nbi-modal';
1014
+ nbiModal.innerHTML = nbiModalTRInfo;
1015
+ document.body.appendChild(nbiModal);
1016
+
900
1017
  nbiModal = document.createElement('div');
901
1018
  nbiModal.id = 'nbi-modal-success';
902
1019
  nbiModal.className = 'nbi-modal';
@@ -930,13 +1047,9 @@ j1.adapter.nbinteract = (function (j1, window) {
930
1047
  // -----------------------------------------------------------------------
931
1048
 
932
1049
  // -----------------------------------------------------------------------
933
- // command|nbi_init_finished
934
- //
935
- if (message.type === 'command' && message.action === 'nbi_init_finished') {
936
-
937
- _this.setState('finished');
938
- logger.debug('\n' + 'state: ' + _this.getState());
939
- logger.info('\n' + 'initializing module finished');
1050
+ // command|nbi_init_started
1051
+ // -----------------------------------------------------------------------
1052
+ if (message.type === 'command' && message.action === 'nbi_init_started') {
940
1053
 
941
1054
  if (nbiShowMessages) {
942
1055
  if (nbiModalAutoClose) {
@@ -946,21 +1059,47 @@ j1.adapter.nbinteract = (function (j1, window) {
946
1059
  }
947
1060
  }
948
1061
 
949
- if (nbiIndicateNbiActivity) {
950
- spinner.stop();
1062
+ if (nbiNotebookReady == 'first_widget') {
1063
+ if (nbiIndicateNbiActivity) spinner.stop();
1064
+ $('.fab-btn').show();
951
1065
  }
952
1066
 
953
- } // END message command/nbi_init_finished
1067
+ widgetCells = document.querySelectorAll('.output_widget_view').length;
1068
+ var dependencies_met_page_rendered = setInterval(function() {
1069
+ widgetCellsRendered = document.querySelectorAll('.widget-vbox').length;
1070
+ if (widgetCellsRendered >= widgetCells) {
1071
+ logger.info('\n' + 'widgets rendered in page (interactive|total) : ' + widgetCells + '|' + widgetCellsRendered);
1072
+ nbiCellsRendered = true;
1073
+ if (nbiIndicateNbiActivity) spinner.stop();
1074
+ _this.setState('finished');
1075
+ logger.debug('\n' + 'state: ' + _this.getState());
1076
+ logger.info('\n' + 'initializing module finished');
1077
+
1078
+ clearInterval(dependencies_met_page_rendered);
1079
+ }
1080
+ }, 25); // END interval dependencies_met_page_rendered
954
1081
 
1082
+ // ---------------------------------------------------------------------
1083
+ // show the quicklinks icon
1084
+ // ---------------------------------------------------------------------
1085
+ $('#quickLinksNotebookseButton').show();
1086
+
1087
+ } // END message command/nbi_init_started
1088
+
1089
+ // -----------------------------------------------------------------------
1090
+ // command|mathjax
1091
+ // -----------------------------------------------------------------------
955
1092
  if (message.type === 'command' && message.action === 'mathjax') {
956
1093
  logger.error('\n' + 'New Math, ID: ' + message.text);
957
1094
 
958
- MathJax.Hub.Startup.signal.Interest(function (message) {
959
- logger.error("Startup: " + message)
960
- // if (message.contains('End')) {
961
- // logger.error("Startup: " + message)
962
- // }
963
- });
1095
+ // Register a MathJax callback if page is FULLY rendered
1096
+ // TODO: Dosn't for now tha way !!!
1097
+ // MathJax.Hub.Startup.signal.Interest(function (message) {
1098
+ // logger.error("Startup: " + message)
1099
+ // if (message.contains('End')) {
1100
+ // logger.error("Startup: " + message)
1101
+ // }
1102
+ // });
964
1103
 
965
1104
  var dependencies_met_mathjax_rendered = setInterval(function() {
966
1105
  var elm = document.getElementById('MathJax-Element-6' + '-Frame');
@@ -974,15 +1113,23 @@ j1.adapter.nbinteract = (function (j1, window) {
974
1113
  clearInterval(dependencies_met_mathjax_rendered);
975
1114
  }, 25); // END interval dependencies_met_mathjax_rendered
976
1115
 
977
- } // END message command/nbi_init_finished
1116
+ } // END message command/mathjax
978
1117
 
979
1118
  // -----------------------------------------------------------------------
980
- // command|info
981
- //
1119
+ // command|info
1120
+ // TODO: count messages contain 'Pulling image'.
1121
+ // Potentially a enless loop
1122
+ // -----------------------------------------------------------------------
982
1123
  if (message.type === 'command' && message.action === 'info') {
983
1124
  // var reMessageTS = new RegExp('/(?:[1-9]\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d{1,9})?(?:Z|[+-][01]\d:[0-5]\d)/');
984
1125
  var messageTS;
985
1126
 
1127
+ // widget render info messages for logging
1128
+ //
1129
+ if (message.text.includes('Displaying widget') || message.text.includes('First widget')) {
1130
+ logger.debug('\n' + message.text);
1131
+ }
1132
+
986
1133
  // remove timestamp|loglevel from message if exists
987
1134
  //
988
1135
  messageTS = message.text.split('] ')[1];
@@ -991,7 +1138,6 @@ j1.adapter.nbinteract = (function (j1, window) {
991
1138
  }
992
1139
 
993
1140
  _this.appendModalMessage(messageSuccessUL, message.text)
994
-
995
1141
  logger.debug('\n' + message.text);
996
1142
 
997
1143
  // show the info modal
@@ -1006,10 +1152,29 @@ j1.adapter.nbinteract = (function (j1, window) {
1006
1152
 
1007
1153
  // -----------------------------------------------------------------------
1008
1154
  // command|error
1009
- //
1155
+ // -----------------------------------------------------------------------
1010
1156
  if (message.type === 'command' && message.action === 'error') {
1011
1157
  var messageTS;
1012
1158
 
1159
+ if (messageTS.contains('Too many users') ||
1160
+ messageTS.contains('Insufficent nodes') ||
1161
+ messageTS.contains('ImagePullBackOff') ||
1162
+ messageTS.contains('failed to connect')
1163
+ ) {
1164
+ var modaBodyText = `
1165
+ The <i>Binder Service</i> is currently not available or is overloaded.
1166
+ All interactive components on the page are <b>not</b> available.
1167
+ You can reload the page or re-open later again.
1168
+ `;
1169
+ logger.error('\n', 'Binder access: failed');
1170
+ if ($(nbiModalTRInfo).is(':hidden')) {
1171
+ document.getElementById('nbiModalTRInfoBody').innerHTML = modaBodyText;
1172
+ $(nbiModalTRInfo).modal('show');
1173
+ }
1174
+
1175
+ return;
1176
+ }
1177
+
1013
1178
  // remove timestamp|loglevel from message if exists
1014
1179
  //
1015
1180
  messageTS = message.text.split('] ')[1];
@@ -1018,14 +1183,13 @@ j1.adapter.nbinteract = (function (j1, window) {
1018
1183
  }
1019
1184
 
1020
1185
  _this.appendModalMessage(messageErrorUL, message.text)
1021
-
1022
1186
  logger.error('\n' + message.text);
1023
1187
 
1024
- // stop the (progress) spinner (currently NOT used)
1188
+ // stop the (progress) spinner
1025
1189
  //
1026
- // if (moduleOptions.indicate_nbi_activity) {
1027
- // spinner.stop();
1028
- // }
1190
+ if (moduleOptions.indicate_nbi_activity) {
1191
+ spinner.stop();
1192
+ }
1029
1193
 
1030
1194
  if (nbiShowMessages) {
1031
1195
  // hide the info modal if shown
@@ -1096,6 +1260,141 @@ j1.adapter.nbinteract = (function (j1, window) {
1096
1260
  return _this.state;
1097
1261
  }, // END getState
1098
1262
 
1263
+ // -------------------------------------------------------------------------
1264
+ // getState()
1265
+ // Returns the current (processing) state of the module
1266
+ // -------------------------------------------------------------------------
1267
+ checkURL: function (uri, flags) {
1268
+ _this.setState('process_checks');
1269
+ $.get(uri).done(function () {
1270
+ _this.setState('finished_checks');
1271
+ flags.checkURL = true;
1272
+ return true;
1273
+ }).fail(function () {
1274
+ _this.setState('finished_checks');
1275
+ flags.checkURL = false;
1276
+ });
1277
+
1278
+ }, // END checkURL
1279
+
1280
+ // -------------------------------------------------------------------------
1281
+ // loadDialog()
1282
+ // Loads the NBI dialog (modal)
1283
+ // -------------------------------------------------------------------------
1284
+ loadDialog: function (options) {
1285
+ Events.documentReady(function () {
1286
+
1287
+ _this.modal = document.getElementById(options.dialogContainerID);
1288
+ if (!_this.modal) {
1289
+ logger.info('\n' + 'load consent modal');
1290
+
1291
+ _this.modal = document.createElement('div');
1292
+ _this.modal.id = options.dialogContainerID;
1293
+ _this.modal.style.display = 'none';
1294
+
1295
+ _this.modal.setAttribute('class', 'modal fade');
1296
+ _this.modal.setAttribute('tabindex', '-1');
1297
+ _this.modal.setAttribute('role', 'dialog');
1298
+ _this.modal.setAttribute('aria-labelledby', options.dialogContainerID);
1299
+ document.body.append(_this.modal);
1300
+ _this.$modal = $(_this.modal);
1301
+
1302
+ // -------------------------------------------------------------------
1303
+ // load|initialize the dialog (modal content)
1304
+ // -------------------------------------------------------------------
1305
+ var templateUrl = options.contentURL + '/' + 'index.html';
1306
+ $.get(templateUrl)
1307
+ .done(function (data) {
1308
+ // load ALL modals HTML
1309
+ _this.modal.innerHTML = data;
1310
+ // select only the requested modal
1311
+ _this.modal.innerHTML = $('#' + options.xhrDataElement).eq(0).html();
1312
+
1313
+ // set dialog type to 'modal'
1314
+ //
1315
+ $(_this.modal).modal({
1316
+ backdrop: 'static',
1317
+ keyboard: false
1318
+ });
1319
+
1320
+ // register all button links
1321
+ //
1322
+ _this.$buttonDoNotAgree = $('#nbi-buttonDoNotAgree');
1323
+ _this.$buttonAgree = $('#nbi-buttonAgree');
1324
+ _this.$buttonSave = $('#nbi-buttonSave');
1325
+ _this.$buttonAgreeAll = $('#nbi-buttonAgreeAll');
1326
+
1327
+ // register all actions
1328
+ //
1329
+ _this.registerActions();
1330
+
1331
+ // register button event handler
1332
+ //
1333
+ _this.$buttonDoNotAgree.click(function () {
1334
+ _this.doNotAgree();
1335
+ });
1336
+
1337
+ _this.$buttonAgree.click(function () {
1338
+ _this.agreeAll();
1339
+ });
1340
+ })
1341
+ .fail(function () {
1342
+ logger.error('\n' + 'loading nbi dialog (modal): failed');
1343
+ logger.warn('\n' + 'probably no|wrong `contentURL` set');
1344
+ });
1345
+ }
1346
+ }.bind(_this));
1347
+ }, // END loadDialog
1348
+
1349
+ // -------------------------------------------------------------------------
1350
+ // showDialog()
1351
+ // Show the NBI dialog (modal)
1352
+ // -------------------------------------------------------------------------
1353
+ showDialog: function () {
1354
+ this.$modal.modal('show');
1355
+ }, // END showDialog
1356
+
1357
+ // -------------------------------------------------------------------------
1358
+ // registerActions()
1359
+ // register actions to run
1360
+ // -------------------------------------------------------------------------
1361
+ registerActions: function () {
1362
+
1363
+ $('input:checkbox[name="checkboxClearLocalStorage"]').on('click', function (e) {
1364
+ nbActions.resetLocalStorage = $(this).is(':checked');
1365
+ logText = '\n' + 'action ClearLocalStorage changed to: ' + value;
1366
+ logger.info(logText);
1367
+
1368
+ e.stopPropagation();
1369
+ });
1370
+
1371
+ }, // END registerActions
1372
+
1373
+ // -------------------------------------------------------------------------
1374
+ // doNotAgree()
1375
+ // action to run ...
1376
+ // -------------------------------------------------------------------------
1377
+ doNotAgree: function (elmID, msg) {
1378
+ _this.$modal.modal('hide');
1379
+ }, // END doNotAgree
1380
+
1381
+ // -------------------------------------------------------------------------
1382
+ // agreeAll()
1383
+ // caction to run ...
1384
+ // -------------------------------------------------------------------------
1385
+ agreeAll: function (elmID, msg) {
1386
+
1387
+ if (nbActions.resetLocalStorage) {
1388
+ logText = '\n' + 'run action: "Clear Binder Settings"';
1389
+ logger.info(logText);
1390
+ localStorage.removeItem('serverParams');
1391
+ localStorage.removeItem('kernelId');
1392
+ }
1393
+
1394
+ _this.$modal.modal('hide');
1395
+ location.reload(true);
1396
+ }, // END agreeAll
1397
+
1099
1398
  // -------------------------------------------------------------------------
1100
1399
  // appendModalMessage()
1101
1400
  // Appends a message to given (NBI) modal