Skip to content

Commit 91d4244

Browse files
authored
Merge pull request #1025 from jcb91/collapsible_headings
[collapsible_headings] add new (un)collapse-all actions, shortcuts, button
2 parents fdc151b + b15cd5c commit 91d4244

File tree

5 files changed

+90
-13
lines changed

5 files changed

+90
-13
lines changed

src/jupyter_contrib_nbextensions/nbconvert_support/collapsible_headings.py

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,7 @@ def __init__(self, *args, **kwargs):
3232
'collapsible_headings')
3333

3434
with open(os.path.join(ch_dir, 'main.css'), 'r') as f:
35-
main_css = f.read()
36-
self.inliner_resources['css'].append(main_css)
35+
self.inliner_resources['css'].append(f.read())
3736

3837
self.inliner_resources['css'].append("""
3938
/* no local copies of fontawesome fonts from basic templates, so get them from cdn */
@@ -50,11 +49,7 @@ def __init__(self, *args, **kwargs):
5049
""") # noqa: E501
5150

5251
with open(os.path.join(ch_dir, 'main.js'), 'r') as f:
53-
self.inliner_resources['js'].append(
54-
f.read().replace(
55-
"define([",
56-
"define('nbextensions/collapsible_headings/main', [")
57-
)
52+
self.inliner_resources['js'].append(f.read())
5853

5954
cm = ConfigManager()
6055
collapsible_headings_options = cm.get('notebook').get(

src/jupyter_contrib_nbextensions/nbconvert_support/exporter_inliner.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def default_config(self):
4040
contrib_templates_dir = templates_directory()
4141

4242
template_path = c.TemplateExporter.setdefault('template_path', [])
43-
if templates_directory not in template_path:
43+
if contrib_templates_dir not in template_path:
4444
template_path.append(contrib_templates_dir)
4545

4646
return c

src/jupyter_contrib_nbextensions/nbextensions/collapsible_headings/collapsible_headings.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ Parameters:
1010
description: Add a toolbar button to collapse the closest header cell
1111
input_type: checkbox
1212
default: false
13+
- name: collapsible_headings.add_all_cells_button
14+
description: Add a toolbar button to collapse/uncollapse all header cells
15+
input_type: checkbox
16+
default: false
1317
- name: collapsible_headings.add_insert_header_buttons
1418
description: Add toolbar buttons to insert heading cells above/below the selected cell
1519
input_type: checkbox
@@ -62,6 +66,14 @@ Parameters:
6266
description: Command-mode shortcut to uncollapse (expand) the selected heading cell
6367
input_type: hotkey
6468
default: right
69+
- name: collapsible_headings.shortcuts.collapse_all
70+
description: Command-mode shortcut to collapse all heading cells
71+
input_type: hotkey
72+
default: ctrl-shift-left
73+
- name: collapsible_headings.shortcuts.uncollapse_all
74+
description: Command-mode shortcut to uncollapse (expand) all heading cells
75+
input_type: hotkey
76+
default: ctrl-shift-right
6577
- name: collapsible_headings.shortcuts.select
6678
description: Command-mode shortcut to select all cells in the selected heading cell's section
6779
input_type: hotkey

src/jupyter_contrib_nbextensions/nbextensions/collapsible_headings/main.js

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
define(['jquery', 'require'], function ($, require) {
1+
(require.specified('base/js/namespace') ? define : function (deps, callback) {
2+
// if here, the Jupyter namespace hasn't been specified to be loaded.
3+
// This means that we're probably embedded in a page, so we need to make
4+
// our definition with a specific module name
5+
return define('nbextensions/collapsible_headings/main', deps, callback);
6+
})(['jquery', 'require'], function ($, require) {
27
"use strict";
38

49
var mod_name = 'collapsible_headings';
@@ -15,6 +20,7 @@ define(['jquery', 'require'], function ($, require) {
1520
// define default values for config parameters
1621
var params = {
1722
add_button : false,
23+
add_all_cells_button: false,
1824
add_insert_header_buttons: false,
1925
use_toggle_controls : true,
2026
make_toggle_controls_buttons : false,
@@ -25,7 +31,9 @@ define(['jquery', 'require'], function ($, require) {
2531
use_shortcuts : true,
2632
shortcuts: {
2733
collapse: 'left',
34+
collapse_all: 'ctrl-shift-left',
2835
uncollapse: 'right',
36+
uncollapse_all: 'ctrl-shift-right',
2937
select: 'shift-right',
3038
insert_above: 'shift-a',
3139
insert_below: 'shift-b',
@@ -171,6 +179,11 @@ define(['jquery', 'require'], function ($, require) {
171179
// Restrict the search to cells that are of the same level and lower
172180
// than the currently selected cell by index.
173181
var ref_cell = _get_cell_at_index(index);
182+
// ref_cell may be null, if we've attempted to extend selection beyond
183+
// the existing cells
184+
if (!ref_cell) {
185+
return;
186+
}
174187
var pivot_level = get_cell_level(ref_cell);
175188
var cells = _get_cells();
176189
while (index > 0 && pivot_level > 1) {
@@ -629,7 +642,7 @@ define(['jquery', 'require'], function ($, require) {
629642
var filter_func;
630643
if (is_h) {
631644
var lvl = get_cell_level(cell);
632-
filter_func = function (c) { return get_cell_level(c) < lvl; }
645+
filter_func = function (c) { return get_cell_level(c) < lvl; };
633646
}
634647
cell = find_header_cell(cell, filter_func);
635648
if (cell !== undefined) {
@@ -644,6 +657,27 @@ define(['jquery', 'require'], function ($, require) {
644657
'collapse_heading', mod_name
645658
);
646659

660+
action_names.collapse_all = Jupyter.keyboard_manager.actions.register({
661+
handler : function (env) {
662+
env.notebook.get_cells().forEach(function (c, idx, arr) {
663+
toggle_heading(c, true);
664+
});
665+
var cell = env.notebook.get_selected_cell();
666+
if (cell.element.is(':hidden')) {
667+
cell = find_header_cell(cell, function (c) { return c.element.is(':visible'); });
668+
if (cell !== undefined) {
669+
Jupyter.notebook.select(Jupyter.notebook.find_cell_index(cell));
670+
cell.focus_cell();
671+
}
672+
}
673+
},
674+
help : "Collapse all heading cells' sections",
675+
icon : params.toggle_closed_icon,
676+
help_index: 'c2'
677+
},
678+
'collapse_all_headings', mod_name
679+
);
680+
647681
action_names.uncollapse = Jupyter.keyboard_manager.actions.register({
648682
handler : function (env) {
649683
var cell = env.notebook.get_selected_cell();
@@ -664,11 +698,25 @@ define(['jquery', 'require'], function ($, require) {
664698
},
665699
help : "Un-collapse (expand) the selected heading cell's section",
666700
icon : params.toggle_open_icon,
667-
help_index: 'c2'
701+
help_index: 'c3'
668702
},
669703
'uncollapse_heading', mod_name
670704
);
671705

706+
action_names.uncollapse_all = Jupyter.keyboard_manager.actions.register({
707+
handler : function (env) {
708+
env.notebook.get_cells().forEach(function (c, idx, arr) {
709+
toggle_heading(c, false);
710+
});
711+
env.notebook.get_selected_cell().focus_cell();
712+
},
713+
help : "Un-collapse (expand) all heading cells' sections",
714+
icon : params.toggle_open_icon,
715+
help_index: 'c4'
716+
},
717+
'uncollapse_all_headings', mod_name
718+
);
719+
672720
action_names.select = Jupyter.keyboard_manager.actions.register({
673721
handler : function (env) {
674722
var cell = env.notebook.get_selected_cell();
@@ -807,6 +855,25 @@ define(['jquery', 'require'], function ($, require) {
807855
}
808856
}]);
809857
}
858+
if (params.add_all_cells_button) {
859+
Jupyter.toolbar.add_buttons_group([{
860+
label: 'toggle all headings',
861+
icon: 'fa-angle-double-up',
862+
callback: function () {
863+
/**
864+
* Collapse/uncollapse all heading cells based on status of first
865+
*/
866+
var cells = Jupyter.notebook.get_cells();
867+
for (var ii = 0; ii < cells.length; ii++) {
868+
if (is_heading(cells[ii])) {
869+
Jupyter.keyboard_manager.actions.call(action_names[
870+
is_collapsed_heading(cells[ii]) ? 'uncollapse_all' : 'collapse_all']);
871+
return;
872+
}
873+
}
874+
}
875+
}]);
876+
}
810877
if (params.add_insert_header_buttons) {
811878
Jupyter.toolbar.add_buttons_group([
812879
action_names.insert_above, action_names.insert_below
@@ -968,7 +1035,7 @@ define(['jquery', 'require'], function ($, require) {
9681035
add_buttons_and_shortcuts();
9691036
})
9701037
.catch(function on_reject (reason) {
971-
console.error(log_prefix, 'error:', reason)
1038+
console.error(log_prefix, 'error:', reason);
9721039
});
9731040
}
9741041

src/jupyter_contrib_nbextensions/nbextensions/collapsible_headings/readme.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,9 @@ the nbextensions config page:
2121

2222
* Command-mode keyboard shortcuts, (enabled by default, and set to left and
2323
right arrow keys to collapse/expand sections, or go to the previous/next
24-
heading, plus shift-right to select a heading cell's section).
24+
heading, plus shift-right to select a heading cell's section, shift-a/b to
25+
insert a heading above/below the current cell, ctrl-shift-left and
26+
ctrl-shift-right to collapse/uncollapse all headings).
2527
Bindings are also configurable from the config page
2628
* A toggle control in the input prompt area of each heading cell (as seen in
2729
the screenshot below, enabled by default)
@@ -38,6 +40,7 @@ the nbextensions config page:
3840
indicating hidden content (disabled by default)
3941
* A toolbar button to collapse the nearest heading to the curently selected
4042
cell (disabled by default)
43+
* A toolbar button to collapse/uncollapse all headings (disabled by default)
4144

4245

4346
css

0 commit comments

Comments
 (0)