Skip to content

Commit 96ab1d4

Browse files
authored
Merge pull request #1240 from benelot/cell_filter
Cell filter extension
2 parents 83bfd3e + c54b560 commit 96ab1d4

File tree

4 files changed

+147
-0
lines changed

4 files changed

+147
-0
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ Repo-level stuff:
6464

6565
New features and bugfixes:
6666

67+
- `cell_filter` __new nbextension added!__
68+
[#1240](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/pull/1240)
69+
[@benelot](https://github.com/benelot)
6770
- `execution_dependencies` __new nbextension added!__
6871
[#1213](https://github.com/ipython-contrib/jupyter_contrib_nbextensions/pull/1213)
6972
[@benelot](https://github.com/benelot)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Cell filter
2+
===========
3+
4+
An extension that allows you to filter cells by tags. Keywords entered into the search bar separated by spaces joins them with logical AND.
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/**
2+
* cell_filter.js
3+
* An extension that allows you to filter cells by tags. Keywords entered into the search bar separated by spaces joins them with logical AND.
4+
*
5+
*
6+
* @version 0.1.0
7+
* @author Benjamin Ellenberger, https://github.com/benelot
8+
* @updated 2018-02-16
9+
*
10+
*
11+
*/
12+
define([
13+
'require',
14+
'jqueryui',
15+
'base/js/namespace',
16+
'base/js/utils',
17+
'services/config'
18+
], function (
19+
requirejs,
20+
$,
21+
Jupyter,
22+
utils
23+
) {
24+
'use strict';
25+
26+
function filterRows (filterText, caseSensitive, useRegex) {
27+
var input = $('#filterkeyword');
28+
var btnRegex = $('#filterisreg');
29+
30+
filterText = filterText !== undefined ? filterText : input.val();
31+
useRegex = useRegex !== undefined ? useRegex : btnRegex.attr('aria-pressed') === 'true';
32+
caseSensitive = caseSensitive !== undefined ? caseSensitive : $('#filtercase').attr('aria-pressed') === 'true';
33+
34+
if (!useRegex) {
35+
// escape any regex special chars
36+
filterText = filterText.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
37+
var keywords = filterText.split(' '); // get all space separated keywords
38+
filterText = '.*'; // catch all stuff before the keywords
39+
keywords.forEach(function(keyword){ // find all keywords we are looking for with regex (?=.*keyword)
40+
filterText += '(?=.*' + keyword + ')';
41+
});
42+
filterText += '.*'; // catch all stuff after the keywords
43+
}
44+
var matchExpr;
45+
try {
46+
matchExpr = new RegExp(filterText, caseSensitive ? '' : 'i'); // prepare regex
47+
}
48+
catch (err) {
49+
// do nothing, error is handled based on undefined matchExpr
50+
}
51+
52+
var invalidRegex = matchExpr === undefined; // indicate invalid regex
53+
btnRegex.toggleClass('btn-danger', invalidRegex);
54+
btnRegex.toggleClass('btn-default', !invalidRegex);
55+
btnRegex.closest('.form-group').toggleClass('has-error has-feedback', invalidRegex);
56+
57+
Jupyter.notebook.get_cells().forEach(function (cell, idx, cells) { // toggle visibility of cells depending on their tags
58+
var tags = cell.metadata.tags || [];
59+
tags = tags.join(' ');
60+
if(filterText === ".*(?=.*).*" || filterText === "" || tags.search(matchExpr) !== -1 && tags.length > 0){ // empty filter or match expression on non-zero tags
61+
cell.element.show(); // cell.element.style.display = '';
62+
//cell.element.find("div.inner_cell").show();
63+
}
64+
else{
65+
cell.element.hide(); // cell.element.style.display = 'none';
66+
//cell.element.find("div.inner_cell").hide();
67+
}
68+
});
69+
}
70+
71+
function filterRowsDefaultParams () {
72+
return filterRows();
73+
}
74+
75+
function load_ipython_extension () {
76+
77+
var form_tgrp = $('<div/>')
78+
.addClass('btn-group') // insert a top form-group to make the form appear next to the buttons
79+
.appendTo('#maintoolbar-container');
80+
81+
var frm_grp = $('<div/>')
82+
.addClass('form-group') // insert a form-group
83+
.css('margin-bottom', 0)
84+
.appendTo(form_tgrp);
85+
86+
var grp = $('<div/>')
87+
.addClass('input-group') // insert an input-group
88+
.appendTo(frm_grp);
89+
90+
$('<input/>') // insert search bar
91+
.attr('type', 'text')
92+
.addClass('form-control input-sm')
93+
.attr('title', 'Keyword for filtering cells by tags')
94+
.attr('id', 'filterkeyword')
95+
.attr('placeholder', 'Cell Tag Filter')
96+
.css('font-weight', 'bold')
97+
.css('width', '70%')
98+
.css('height', '24px')
99+
.on('focus', function (evt) { Jupyter.notebook.keyboard_manager.disable();})
100+
.on('blur', function (evt) { Jupyter.notebook.keyboard_manager.enable();})
101+
.appendTo(grp);
102+
103+
$('<button/>')
104+
.attr('type', 'button') // insert regex button
105+
.attr('id', 'filterisreg')
106+
.addClass('btn btn-default btn-sm')
107+
.attr('data-toggle', 'button')
108+
.css('font-weight', 'bold')
109+
.attr('title', 'Use regex (JavaScript regex syntax)')
110+
.text('.*')
111+
.on('click', function (evt) { setTimeout(filterRowsDefaultParams); })
112+
.appendTo(grp);
113+
114+
$('<button/>') // insert case sensitive button
115+
.attr('type', 'button')
116+
.attr('id', 'filtercase')
117+
.addClass('btn btn-default btn-sm')
118+
.attr('data-toggle', 'button')
119+
.attr('tabindex', '0')
120+
.attr('title', 'Match case')
121+
.css('font-weight', 'bold')
122+
.text('Aa')
123+
.on('click', function (evt) { setTimeout(filterRowsDefaultParams); })
124+
.appendTo(grp);
125+
126+
$('#filterkeyword').on('keyup', filterRowsDefaultParams); // trigger filtering right with typing
127+
}
128+
129+
return {
130+
load_ipython_extension : load_ipython_extension
131+
};
132+
133+
});
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
Type: Jupyter Notebook Extension
2+
Compatibility: 4.x, 5.x
3+
Name: Cell Filter
4+
Main: cell_filter.js
5+
Link: README.md
6+
Description: |
7+
An extension that allows you to filter cells by tags. Keywords entered into the search bar separated by spaces joins them with logical AND.

0 commit comments

Comments
 (0)