JS List Filter Checkboxes


Published: 2016-06-12
Updated: 2021-05-22
Web: https://fritzthecat-blog.blogspot.com/2016/06/js-list-filter-checkboxes.html


One of the basic needs of a user is to filter information. From a table-of-contents of hundreds of articles I want to see just those that contain information about, let's say, JavaScript. I assume the article's title contains enough information to decide whether it's about JavaScript, so that filtering can happen on the client-side browser without contacting the server.

Mostly filtering is provided by one or more text-fields where the user can input a search-pattern. But using the keyboard is getting tedious nowadays when being on a mobile phone. Patterns might be even misunderstood (wildcards), moreover most words are not precise without context. It could also happen that the user inputs "JavaScript", but the title of the searched article contains the synonym "JS".

To make filtering easy and quick I came up with a set of checkboxes that describe most of the articles' contents. That means the search-patterns have been pre-defined, and the user chooses from a restricted set of filterings. This moves the responsibility to define search-terms to the page-author.

Example

The following list contains links to articles about JavaScript, CSS, HTML, Java and LINUX. If a title contains "JS", "JavaScript" or "jQuery", it is expected to be about JavaScript, "HTML" and "Page" lead to HTML, "CSS" to CSS, and so on. Should a title contain both "JavaScript" and "CSS", it would be in both search results. Should we want to see none of these categories, we can click the "Others" checkbox, this excludes all the mentioned search terms, and displays just those titles that do not refer to any of them.

Blog Archive Contents

104The JS Function-in-Loop Bug2016-06-07
103JS jQuery $(this)2016-06-06
102LINUX Terminal ls colors2016-06-06
101HTML Elements and Dimensions2016-06-04
100JS Browser Reflow and Repaint2016-05-29
99JS Semicolons2016-05-21
98CSS Width 100% and Position Absolute or Fixed2016-05-15
97JS Map Key Gotcha2016-04-30
96JS Revealing Module Pattern2016-04-24
95What's HTML label for?2016-04-18
94Three Steps Toward Progress2016-04-13
93JS Get / Set Element Width / Height2016-04-11
92JS / CSS Tabcordion2016-04-03
91JS Responsive Breakpoint Notifications2016-03-28
90JS / CSS Tabs2016-03-13
89JS Table Layout Adjustment: DIV Tables2016-03-06
88JS Table Layout Adjustment: Predefined Widths2016-02-29
87JS Element Dimensions2016-02-21
86JS Table Layout Adjustment: Elastic Column2016-02-14
85JS Table Layout Adjustment: Sizing2016-02-07
84JS Table Layout Adjustment: Naming2016-02-06
83JS clientWidth and CSS width2016-01-25
82Space in HTML Breaks Layout2016-01-19
81JS Titled Border2016-01-18
80HTML Input Focus Tab Order2016-01-16
79JS Keyboard Events2016-01-13
78JS Sticky Bar2016-01-07
77Pure CSS Push Menu2015-12-30
76Replacement for CSS fixed position2015-12-29
75Pure CSS Slide Menu2015-12-27
74Protruding CSS inline elements2015-12-26
73Receiving CSS Events2015-12-19
72CSS BorderLayout, yet another one2015-12-14
71CSS height 100% shows Browser Scrollbar2015-12-13
70JS Browser Coordinates2015-12-07
69JS Sticky Table-of-Contents2015-12-03
68CSS Layout Test Page2015-11-30
67Text Outline with GIMP2015-11-14
66Iterator in Java and JS2015-10-14
65JS Natural Sort Order2015-10-13
64Natural Sort in Java, Performance Tuned2015-10-11
63Natural Sort in Java, First Performance Tuning2015-10-07
62Natural Sort Order in Java2015-10-05
61JS Light Bulb Moments2015-10-03
60JS Poor Developer's IDE2015-09-19
59Visitor Pattern for Test Data in Java2015-09-17
58Three Notorious Software Developer Habits2015-09-09
57Videotized on LINUX2015-08-16
56JS Visibility Detection2015-08-14
55LINUX Root Password Confusion2015-08-01
54CSS Fixed Table Header2015-07-20
53CSS Position Property2015-07-19
52JS Animated Expand and Collapse2015-07-12
51Pure CSS Menu2015-07-11
50JS Asynchronous Waiting2015-06-20
49JS Swipe Gesture2015-06-11
48The Immortal AWK Language2015-05-27
47JS Document Treeification2015-05-15
46Adjust Screen Coordinates in LINUX with Xfce2015-05-09
45UNIX Shell Control Structures2015-05-01
44vi Manual2015-04-29
43JS Table of Contents2015-04-16
42JS Overrides2015-04-07
41Extract Google Blog Export using Java2015-04-04
40JS Treetable2015-03-31
39Remote Desktop from LINUX to WINDOWS2015-03-25
38JS Slide Show Aftermath2015-03-24
37JS Slide Show2015-03-14
36Yet Another JavaScript AMD Loader2015-02-28
35JS Requires Dependency Management2015-02-21
34Interrupted LINUX Upgrade to Ubuntu 14.042015-02-13
33JS Folding2015-02-10
32Many LINUX on board2015-01-24
31Installing LINUX on a DELL laptop besides WINDOWS 8.12015-01-12
30Installing LINUX without CD or USB Stick2015-01-05
29A JS Framework for Rich Text Tooltips2014-12-29
28Preserve Inputs across Page Reload via JS2014-12-25
27The Self-Displaying Page2014-12-20
26jQuery for Beginners2014-12-07
25Object Relational Mapping with Inheritance in Java2014-11-30
24The State Pattern in Multiple Selection2014-11-26
23Good Documentation2014-11-17
22Sass Over CSS2014-11-15
21The Shape of Content as CSS2014-11-06
20How to Read Cascading Style Sheets2014-11-04
19A JS Starter Kit for Beginners2014-10-29
18JS Modules2014-10-24
17JS Functional Inheritance2014-10-19
16JS Inheritance contra Encapsulation2014-10-16
15Running JS Scripts from Java with HtmlUnit2014-10-01
14JS got cha2014-09-30
13This JS new ROFLCOPTER2014-09-27
12JavaScript Best Practices2014-09-21
11JS and the Forgotten Types2014-09-20
10Omigosh, JavaScript!2014-09-19
9Unbeloved Constructors, Beloved Anemic Objects2014-09-01
8Responsive Layout without CSS media-query2014-08-22
7The Modular Homepage Story2014-07-22
6Scrum2010-04-22
5Scala Considerations2010-01-12
4Personal Problems2008-04-25
3Fashion2008-03-12
2Building Blocks2008-03-07
1Things Are Changing2008-02-26

This table-of-contents has been generated by my BlogSaver Java application, which I wrote about in a passed Blog.

HTML

Here is how checkbox-filtering works.

  <p>
<label><input type='checkbox' search-words='JS, JavaScript, jQuery' onclick='filter();'/> JavaScript </label>
<label><input type='checkbox' search-words='CSS, Cascading Style Sheets' onclick='filter();'/> CSS </label>
<label><input type='checkbox' search-words='HTML, Page' onclick='filter();'/> HTML </label>
<label><input type='checkbox' search-words='Java, Constructors' onclick='filter();'/> Java </label>
<label><input type='checkbox' search-words='LINUX, UNIX, vi, AWK, GIMP' onclick='filter();'/> LINUX </label>
<label><input type='checkbox' id='Others' onclick='filter();'/> Others </label>
</p>

<table>
<tr>
<td>104</td>
<td><a href='The_JS_Function_in_Loop_Bug.html'>The JS Function-in-Loop Bug</a></td>
<td>2016-06-07</td>
</tr>
........
<tr>
<td>1</td>
<td><a href='Things_Are_Changing.html'>Things Are Changing</a></td>
<td>2008-02-26</td>
</tr>
</table>

This is a set of checkboxes that all call the JS function filter() on click. Each of these has an attribute search-words that contains the terms that must occur in the according article title. This is what the user normally would have to input, but with these attributes I can give all synonyms in one place.

There are two types of search-words, one contains no space, the other is a phrase and thus contains space: "Cascading Style Sheets" goes with "CSS". Thus the terms are comma-separated.

Another difficulty is that the occurrence of "JavaScript" in a title must not lead to finding this as "Java" article. We need a search with word-boundaries.

The table element is (an outline of) the list to filter.

JavaScript

Here is the (preliminary) source code of the filter() function.

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<script type='text/javascript'>

var toArrayWithoutEmpty = function(csv, splitChar) {
var rawSearchPatterns = csv.split(splitChar);
var searchPatterns = [];
for (var i = 0; i < rawSearchPatterns.length; i++) {
var searchPattern = rawSearchPatterns[i].trim();
if (searchPattern !== '') {
var lastChar = searchPattern.charAt(searchPattern.length - 1);
if (lastChar === '!' || lastChar === '?' || lastChar === '.' || lastChar === ',')
searchPattern = searchPattern.substring(0, searchPattern.length - 1);
searchPatterns.push(searchPattern);
}
}
return searchPatterns;
};

var matches = function(searchPatterns, labelText, labelWords) {
for (var i = 0; i < searchPatterns.length; i++) {
var searchPattern = searchPatterns[i];
if (searchPattern.indexOf(' ') > 0) {
if (labelText.indexOf(searchPattern) >= 0)
return true;
}
else if (labelWords.indexOf(searchPattern) >= 0) {
return true;
}
}
return false;
};

var filter = function() {
var table = document.getElementsByTagName('table')[0];
var checkboxes = document.getElementsByTagName('input');

var allSearchWords = '';
var searchWords = '';
var othersIsChecked = false;

for (var i = 0; i < checkboxes.length; i++) {
var checkbox = checkboxes[i];
var thisSearchWords = checkbox.getAttribute('searchWords');
if (thisSearchWords) {
allSearchWords += ', '+thisSearchWords;
if (checkbox.checked)
searchWords += ', '+thisSearchWords;
}
else if (checkbox.checked && checkbox.getAttribute('id') === 'Others')
othersIsChecked = true;
}

var searchPatterns = toArrayWithoutEmpty(searchWords, ',');
var allSearchPatterns = toArrayWithoutEmpty(allSearchWords, ',');

var tbody = table.children[0];
for (var row = 0; row < tbody.children.length; row++) {
var tableRow = tbody.children[row];
var label = tableRow.children[1].children[0].childNodes[0];
var labelText = label.textContent.trim();
var labelWords = toArrayWithoutEmpty(labelText, ' ');
var match = false;

if (searchPatterns.length > 0 || othersIsChecked && allSearchPatterns.length > 0) {
if (othersIsChecked)
match = ! matches(allSearchPatterns, labelText, labelWords);

match = match || matches(searchPatterns, labelText, labelWords);
}
else
match = true;

tableRow.style.display = match ? '' : 'none';
}
};

</script>

Yes, you are right, this is hacker code! It contains significant code-smells, and I better should not show this here, because it could ruin my reputation as a software developer :-!

Problems are:

Thus I won't explain this source here and now line by line, because it is not worth. Moreover I will describe how to refactor this in my next Blog, and then it should also become clear how it works.

So don't copy this source code, you will have problems making it work in your page. It's just here to demonstrate how freshly written source code looks like. Find the refactored code of this in follower-Blog(s), and thereby learn how to refactor JavaScript to a reusable module.





ɔ⃝ Fritz Ritzberger, 2016-06-12