Skip to content

Commit 6e47267

Browse files
committed
Implement cell filter.
1 parent 0adfb29 commit 6e47267

File tree

3 files changed

+142
-0
lines changed

3 files changed

+142
-0
lines changed
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: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
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-03
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(tags.search(matchExpr) !== -1){
61+
cell.element.find("div.input").show(); // cell.element.style.display = '';
62+
}
63+
else{
64+
cell.element.find("div.input").hide(); // cell.element.style.display = 'none';
65+
}
66+
});
67+
}
68+
69+
function filterRowsDefaultParams () {
70+
return filterRows();
71+
}
72+
73+
function load_ipython_extension () {
74+
75+
var form = $('<form/>') // insert a form into the main toolbar container
76+
.css('padding', '0 7px 4px')
77+
.appendTo('#maintoolbar-container');
78+
79+
var frm_grp = $('<div/>')
80+
.addClass('form-group') // insert a form-group
81+
.css('margin-bottom', 0)
82+
.appendTo(form);
83+
84+
var grp = $('<div/>')
85+
.addClass('input-group') // insert an input-group
86+
.appendTo(frm_grp);
87+
88+
$('<input/>') // insert search bar
89+
.attr('type', 'text')
90+
.addClass('form-control input-sm')
91+
.attr('title', 'Keyword for filtering cells by tags')
92+
.attr('id', 'filterkeyword')
93+
.attr('placeholder', 'Filter')
94+
.css('font-weight', 'bold')
95+
.appendTo(grp);
96+
97+
var btns = $('<div/>')
98+
.addClass('input-group-btn') // insert a div to group buttons
99+
.appendTo(grp);
100+
101+
$('<button/>')
102+
.attr('type', 'button') // insert regex button
103+
.attr('id', 'filterisreg')
104+
.addClass('btn btn-default btn-sm')
105+
.attr('data-toggle', 'button')
106+
.css('font-weight', 'bold')
107+
.attr('title', 'Use regex (JavaScript regex syntax)')
108+
.text('.*')
109+
.on('click', function (evt) { setTimeout(filterRowsDefaultParams); })
110+
.appendTo(btns);
111+
112+
$('<button/>') // insert case sensitive button
113+
.attr('type', 'button')
114+
.attr('id', 'filtercase')
115+
.addClass('btn btn-default btn-sm')
116+
.attr('data-toggle', 'button')
117+
.attr('tabindex', '0')
118+
.attr('title', 'Match case')
119+
.css('font-weight', 'bold')
120+
.text('Aa')
121+
.on('click', function (evt) { setTimeout(filterRowsDefaultParams); })
122+
.appendTo(btns);
123+
124+
$('#filterkeyword').on('keyup', filterRowsDefaultParams); // trigger filtering right with typing
125+
}
126+
127+
return {
128+
load_ipython_extension : load_ipython_extension
129+
};
130+
131+
});
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)