The Decision Sieve

Check-in [28df17312c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:transferred to fossil
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | trunk
Files: files | file ages | folders
SHA3-256: 28df17312c881b0a80b06b2c11b175d9fc2fc518a6ed7e9a11e769db22e1f77c
User & Date: Cthulhux 2019-09-11 21:42:15
Context
2019-09-11
21:42
transferred to fossil Leaf check-in: 28df17312c user: Cthulhux tags: trunk
21:40
initial empty check-in check-in: 38b398d649 user: Cthulhux tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added index.htm.



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<!doctype html>
<html>
  <head>
    <title>The Decision Sieve</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

    <link rel="stylesheet" href="static/styles.css" />
    <link rel="stylesheet" type="text/css" href="static/notie.min.css" />

    <script>
      FontAwesomeConfig = { searchPseudoElements: true };
    </script>
    <script src="static/umbrella.min.js"></script>
    <script defer src="static/notie.min.js"></script>
    <script defer src="static/sieve.js"></script>
    <script defer src="https://use.fontawesome.com/releases/v5.6.3/js/all.js" integrity="sha384-EIHISlAOj4zgYieurP0SdoiBYfGJKkgWedPHH4jCzpCXLmzVsw1ouK59MuUtP4a1" crossorigin="anonymous"></script>
  </head>
  <body>
    <div id="bitbucket"><a href="https://bitbucket.org/tux_/decision-sieve" target="_blank"><img src="static/bitbucket.png" title="Fork me on Bitbucket" /></a></div>

    <h1><a href="/">The Decision Sieve</a></h1>

    <h2>Did you ever need to decide about things?</h2>

    <main>
      <input id="tab1" type="radio" name="tabs" class="tabbar" checked>
      <label for="tab1"><span class="tabtext">&nbsp;Prio Sieve</span></label>

      <input id="tab2" type="radio" name="tabs" class="tabbar">
      <label for="tab2"><span class="tabtext">&nbsp;Price Sieve</span></label>

      <input id="tab3" type="radio" name="tabs" class="tabbar">
      <label for="tab3"><span class="tabtext">&nbsp;Tutorial & FAQ</span></label>

      <section id="content1">
        <input type="button" value="Add new item" class="button" id="prio-add-new" />
        <br /><br />
        <div id="priolist">
          <div class="entry">
            <span class="counter">1</span>
            <input class="name prioname" title="Enter the name of the item" placeholder="Enter the name of the item" />
            <input type="range" class="slider" title="Priority: low, normal, high" min="0.75" max="1.25" value="1" step="0.25" />
          </div>
        </div>
        <br /><br />
        <br /><br />
        Max. items: <input type="number" placeholder="Limit" class="number" title="Define how many items you want to keep on your list." id="prio-max-items" />
        <input type="button" value="Sieve!" class="button main" id="prio-sieve" />
        <input type="button" value="(undo)" class="button main" style="display:none" id="undo-prio-sieve" />
      </section>

      <section id="content2">
        <input type="button" value="Add new item" class="button" id="price-add-new" />
        <br /><br />
        <div id="pricelist">
          <div class="entry">
            <span class="counter">1</span>
            <input class="name" title="Enter the name of the item" placeholder="Enter the name of the item" />
            <input class="price" placeholder="Price" title="Price (only numbers please)" />
          </div>
        </div>
        <br /><br />
        <br /><br />
        Max. budget: <input type="number" placeholder="Budget" class="number" title="Define how much your budget is." id="price-budget" /><span id="spent"></span>
        <input type="button" value="Sieve!" class="button main" id="price-sieve" />
        <input type="button" value="(undo)" class="button main" style="display:none" id="undo-price-sieve" />
      </section>

      <section id="content3">
        <h3>What is this?</h3>

        <p>Generally spoken, this is a web service that will help you filter your bucket list. If you have a limited budget or you need to limit your shopping to a certain number of things, the Decision Sieve can help you clean up your list to a reasonable amount. I actually wrote it to decide about which whisky to buy - and it helped me a lot.</p>

        <h3>So why did you write this as a website instead of a real application?</h3>

        <p>I needed a fast solution, and my first attempt at writing the Decision Sieve in Delphi took longer than expected. This is an emergency solution until I find the inner calmness required to do it <em>right</em>.</p>

        <h3>Do you spy me?</h3>

        <p>Of course not. The sieving logic is exclusively being performed on your machine, no data is transferred back. If you don't trust me, feel free to run the Decision Sieve locally on a web-capable computer without internet access - it is <a href="https://bitbucket.org/tux_/decision-sieve" target="_blank">Free Software</a>. Yay!</p>

        <h3>How do I use it?</h3>

        <ul><li><u><b>Priority Sieve:</b></u>
            <ol><li>Enter a list of things in your list.</li>
              <li>Optionally, mark a couple of things as "less important" or "more important" using the slider on the right side.</li>
              <li>Enter the maximum number of things that should be left after sieving.</li>
              <li>Press the button and watch the magic happen.</li></ol></li>
          <li><u><b>Price Sieve:</b></u>
            <ol><li>Enter a list of things in your list.</li>
              <li>Specify the particular price for each thing in the list.</li>
              <li>Enter the maximum budget.</li>
              <li>Press the button and watch the magic happen.</li></ol></li></ul>
      </section>
    </main>
  </body>
</html>

Added static/bitbucket.png.

cannot compute difference between binary files

Added static/notie.min.css.



>
1
.notie-container{font-size:1.6rem;height:auto;left:0;position:fixed;text-align:center;width:100%;z-index:2;box-sizing:border-box;-o-box-shadow:0 0 5px 0 rgba(0,0,0,.5);-ms-box-shadow:0 0 5px 0 rgba(0,0,0,.5);box-shadow:0 0 5px 0 rgba(0,0,0,.5)}@media screen and (max-width:900px){.notie-container{font-size:1.4rem}}@media screen and (max-width:750px){.notie-container{font-size:1.2rem}}@media screen and (max-width:400px){.notie-container{font-size:1rem}}.notie-background-success{background-color:#57bf57}.notie-background-warning{background-color:#d6a14d}.notie-background-error{background-color:#e1715b}.notie-background-info{background-color:#4d82d6}.notie-background-neutral{background-color:#a0a0a0}.notie-background-overlay{background-color:#fff}.notie-textbox{color:#fff;padding:20px}.notie-textbox-inner{margin:0 auto;max-width:900px}.notie-overlay{height:100%;left:0;opacity:0;position:fixed;top:0;width:100%;z-index:1}.notie-button{cursor:pointer}.notie-button,.notie-element{color:#fff;padding:10px}.notie-element-half{width:50%}.notie-element-half,.notie-element-third{display:inline-block;box-sizing:border-box}.notie-element-third{width:33.3333%}.notie-alert{cursor:pointer}.notie-input-field{background-color:#fff;border:0;font-family:inherit;font-size:inherit;outline:0;padding:10px;text-align:center;width:100%;box-sizing:border-box}.notie-select-choice-repeated{border-bottom:1px solid hsla(0,0%,100%,.2);box-sizing:border-box}.notie-date-selector-inner{margin:0 auto;max-width:900px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;-o-user-select:none;user-select:none}.notie-date-selector-inner [contenteditable],.notie-date-selector-inner [contenteditable]:focus{outline:0 solid transparent}.notie-date-selector-up{transform:rotate(180deg)}

Added static/notie.min.js.

cannot compute difference between binary files

Added static/sieve.js.































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
/**
 * sieve.js
 * This is the main "application" logic of the Decision Sieve.
 * It is damn ugly because JavaScript is damn ugly. Sorry.
 *
 *
 * @license WTFPL, http://www.wtfpl.net
 * @version 1.1
 * @author  Cthulhux. https://tuxproject.de
 * @updated 2019-01-07
 */

function entryPrioSort(a, b) {
    // Sorting callback for our prio entry - sorts ascending by priority.
    if (a[0] === b[0]) {
        return 0;
    }
    else {
        return (a[0] < b[0]) ? -1 : 1;
    }
}

function shuffle(array) {
    // In-place Fisher-Yates array shuffling.
    let counter = array.length;

    while (counter > 0) {
        let index = Math.floor(Math.random() * counter);
        counter--;

        // Swap:
        let temp = array[counter];
        array[counter] = array[index];
        array[index] = temp;
    }

    return array;
}

function restoreAll(parent) {
	// Undoes each sieving.
	// <parent> is the top list ID, e.g. "priolist".
	let sieved = u(".sieved");
	sieved.each(function(item) {
		u(item).removeClass("sieved");
	});
	
	// Reset the entry counters:
	let i = 1;
	let entrysel = u("#" + parent + " .entry");
	entrysel.each(function(item) {
        let appendedcounter = u(item).find(".counter");
        if (appendedcounter) {
            u(appendedcounter).html(i++);
        }
    })
}

/* ------------------ PRICE SIEVE ------ */

function price_add_new() {
    // Clone and append an empty .entry into #pricelist.
    let entrysel = u("#pricelist .entry");
    if (entrysel.first()) {
        let entryclone = entrysel.clone(); // will pick the first one

        // Append the clone:
        u("#pricelist").append(u("<div class=\"entry\">" + entryclone.html() + "</div>"));
        entrysel = u("#pricelist .entry"); // Get the new list since we have a new entry.
        let appendedentry = entrysel.last();

        // Reset the counter (= set the HTML contents of the first child).
        // Other values are reset anyway.
        let appendedcounter = u(appendedentry).find(".counter");
        if (appendedcounter) {
            u(appendedcounter).html(entrysel.length);
        }
    }
}

u(".price").on('keypress keyup', function(e) {
    if (e.which == 0) {
        // Tab pressed. Add a new price entry.
        price_add_new();
    }
});

u("#price-add-new").on("click", function() {
    price_add_new();
    u(".price").off('keypress keyup').on('keypress keyup', function(e) {
        if (e.which == 0) {
            // Tab pressed. Add a new price entry.
            price_add_new();
        }
    });
});

u("#price-sieve").on("click", function() {
    // Sieve it!
    let budget = parseFloat(u("#price-budget").first().value.replace(/,/g, ''));
    if (isNaN(budget)) {
        notie.alert({ type: 3, text: 'Please enter your budget first.', time: 2 });
        return;
    }

    // Keep a list of all entries:
    let i = 0;
    let entries = [[]];

    let entrysel = u("#pricelist .entry");
    let entrycnt = entrysel.length;
    let collected = 0; // This is the sum of all prices in the list.

    entrysel.each(function(item) {
        let price = parseFloat(u(item).find(".price").first().value.replace(/,/g, ''));
        if ((u(item).find(".name").first().value == "" || isNaN(price))
            && entrycnt > 1) {
            // Remove all (except one) empty or invalid items:
            u(item).addClass("sieved");
            entrycnt--;
        }
        else {
            // Store the prices of each kept item:
            entries[i] = [];
            entries[i][0] = price;
            entries[i][1] = u(item);

            collected += price;

            i++;
        }
    });

    // Check if there's anything left to sieve:
    if (entrycnt == 1) {
        // Nothing left to do.
        notie.alert({ type: 4, text: 'There are no items left to sieve', time: 2 })
        return;
    }

    // Shuffle:
    shuffle(entries);

    // Do the actual sieving.
    // 1) Remove all items which are more expensive than the budget:
    entries.forEach(function(entry) {
        if (entry[0] > budget) {
            collected -= entry[0];
            entry[1].addClass("sieved");
        }
    });

    // 2) Remove items until collected <= budget.
    entries.forEach(function(entry) {
        if (collected <= budget) {
            return;
        }

        collected -= entry[0];
        entry[1].addClass("sieved");
    });

    // Reset the entry counters:
    entrysel = u("#pricelist .entry");
    i = 1;

    entrysel.each(function(item) {
		if (!u(item).hasClass("sieved")) {
			let appendedcounter = u(item).find(".counter");
			if (appendedcounter) {
				u(appendedcounter).html(i++);
			}
        }
    })

    // Done.
    u("#spent").html("&nbsp;- sieved total: " + collected);
    notie.alert({ type: 1, text: 'Success!', time: 2 })
    
    // Enable Undo:
    u("#undo-price-sieve").attr("style", "display:block;margin-top:3px");
});

u("#undo-price-sieve").on("click", function() {
	// Restore the items:
	restoreAll("pricelist");
	u("#undo-price-sieve").attr("style", "display:none");
	u("#spent").html("");
});


/* ------------------ PRIO SIEVE ------- */

function prio_add_new() {
    // Clone and append an empty .entry into #priolist.
    let entrysel = u("#priolist .entry");
    if (entrysel.first()) {
        let entryclone = entrysel.clone(); // will pick the first one

        // Append the clone:
        u("#priolist").append(u("<div class=\"entry\">" + entryclone.html() + "</div>"));
        entrysel = u("#priolist .entry"); // Get the new list since we have a new entry.
        let appendedentry = entrysel.last();

        // Reset the counter (= set the HTML contents of the first child).
        // Other values are reset anyway.
        let appendedcounter = u(appendedentry).find(".counter");
        if (appendedcounter) {
            u(appendedcounter).html(entrysel.length);
        }
    }
}

u(".prioname").on('keypress keyup', function(e) {
    if (e.which == 0) {
        // Tab pressed. Add a new prio entry.
        prio_add_new();
    }
});

u("#prio-add-new").on("click", function() {
    prio_add_new();
    u(".prioname").off('keypress keyup').on('keypress keyup', function(e) {
        if (e.which == 0) {
            // Tab pressed. Add a new prio entry.
            prio_add_new();
        }
    });
});

u("#prio-sieve").on("click", function() {
    // Sieve it!
    let maxItems = parseInt(u("#prio-max-items").first().value);
    if (isNaN(maxItems)) {
        notie.alert({ type: 3, text: 'Please enter a number of max. items first.', time: 2 });
        return;
    }

    // Keep a list of all entries:
    let i = 0;
    let entries = [[]];

    let entrysel = u("#priolist .entry");
    let entrycnt = entrysel.length;
    entrysel.each(function(item) {
        if (u(item).find(".prioname").first().value == "" && entrycnt > 1) {
            // Remove all (except one) empty items:
            u(item).addClass("sieved");
            entrycnt--;
        }
        else {
            // Store the priorities of each kept item:
            let prio = u(item).find(".slider").first().value;
            if (typeof prio == undefined) {
                prio = 1;
            }

            entries[i] = [];
            entries[i][0] = prio;
            entries[i][1] = u(item);

            i++;
        }
    });

    // Check if there's anything left to sieve:
    if (entrycnt == 1 || maxItems >= entrycnt) {
        // Nothing left to do.
        notie.alert({ type: 4, text: 'There are no items left to sieve', time: 2 })
        return;
    }

    // Shuffle, then sort by priority:
    shuffle(entries);
    entries = entries.sort(entryPrioSort);

    // Do the actual sieving:
    entries.forEach(function(entry) {
        // Generally spoken, lower priorities will be removed more
        // likely if the difference between entrycnt and maxItems is
        // lower. E.g. if there is only one item left to remove, it
        // should be the one with the lowest priority. (Or an entirely
        // random one if no priority differences are found.) Since we
        // sorted our list by priority, the ones on top are those with
        // the lowest priority at this point. Grab one and remove it.
        if (entrycnt <= maxItems) {
            return;
        }

        u(entry[1]).addClass("sieved");
        entrycnt--;
    });

    // Reset the entry counters:
    entrysel = u("#priolist .entry");
    i = 1;

    entrysel.each(function(item) {
		if (!u(item).hasClass("sieved")) {
			let appendedcounter = u(item).find(".counter");
			if (appendedcounter) {
				u(appendedcounter).html(i);
				i++;
			}
		}
    })

    // Done.
    notie.alert({ type: 1, text: 'Success!', time: 2 })
    
    // Enable Undo:
    u("#undo-prio-sieve").attr("style", "display:block;margin-top:3px");
});

u("#undo-prio-sieve").on("click", function() {
	// Restore the items:
	restoreAll("priolist");
	u("#undo-prio-sieve").attr("style", "display:none");
});

Added static/styles.css.















































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,700');

/* http://www.0to255.com/d3f5d0 */

*, *:before, *:after {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    height: 100vh;
}

body {
    font: 14px/1 'Open Sans', sans-serif;
    color: #edfbec;
    background: #0e330b;
}

main {
    color: #0e330b;
}

h1, h2, h3 {
    padding: 10px 0;
    font-weight: 400;
    text-align: center;
}

h1 a {
    color: #edfbec;
    text-decoration: none;
}

p {
    margin: 0 0 20px;
    line-height: 1.5;
}

main {
    min-width: 320px;
    max-width: 800px;
    padding: 50px;
    margin: 15px auto 0;
    background: #fff;
}

section {
    display: none;
    padding: 20px 0 0;
    border-top: 1px solid #ddd;
}

ul li {
    line-height:1.5em;
    margin-left:1em;
}

ol li {
    margin-left:1.8em;
}

input.tabbar {
    display: none;
}

input.name {
    float:left;
}

input.name,
input.price {
    border:1px solid gray;
    padding:2px;
    width:300px;
    font-size:larger;
}

input.slider,
input.price {
    float:right;
    width:100px;
}

input.number {
    /* number field */
    width:80px;
    padding:2px;
    font-size:larger;
}

.entry {
    display:block;
    clear:both;
}

.entry .counter {
    float:left;
    color: darkgray;
    font-size:larger;
    font-weight:bold;
    width:3.1em;
    text-align:right;
    margin-right:0.5em;
    padding-top:3px;
}

.button {
    padding:4px;
    text-transform:lowercase;
    border:1px solid #91e68a;
    background-color:#edfbec;
    transition:all ease 0.8s;
    color:#0e330b;
}

.button.main {
    display:block;
    font-size:2em;
    width:80%;
    margin-left:auto;
    margin-right:auto;
    margin-top:1em;
}

.button:hover {
    background-color:#fafefa;
    border-color:#50d744;
}

#bitbucket {
    position:fixed;
    top:0px;
    right:0px;
}

#bitbucket > img {
    border:none;
}

label {
    display: inline-block;
    margin: 0 0 -1px;
    padding: 15px 25px;
    font-weight: 600;
    text-align: center;
    color: #bbb;
    border: 1px solid transparent;
}

label:before {
    font-family: fontawesome;
    font-weight: normal;
    margin-right: 10px;
}

label[for*='1']:before { display: none; margin-right:5px; font-family: "Font Awesome 5 Solid"; content: '\f1de'; }
label[for*='2']:before { display: none; font-family: "Font Awesome 5 Solid"; content: '\f155'; }
label[for*='3']:before { display: none; font-family: "Font Awesome 5 Solid"; content: '\f129'; }

label:hover {
    color: #888;
    cursor: pointer;
}

input:checked + label {
    color: #555;
    border: 1px solid #ddd;
    border-top: 2px solid #43d436;
    border-bottom: 1px solid #fff;
}

#tab1:checked ~ #content1,
#tab2:checked ~ #content2,
#tab3:checked ~ #content3 {
    display: block;
}

.sieved {
	display: none;
}

@media screen and (max-width: 650px) {
    label .tabtext {
        font-size: 0;
    }
    label:before {
        margin: 0;
        font-size: 18px;
        display:inline;
    }
}

@media screen and (max-width: 400px) {
    label {
        padding: 15px;
    }
}

Added static/umbrella.min.js.







>
>
>
1
2
3
/* Umbrella JS 3.1.0 umbrellajs.com */

var u=function(t,e){return this instanceof u?t instanceof u?t:("string"==typeof t&&(t=this.select(t,e)),t&&t.nodeName&&(t=[t]),void(this.nodes=this.slice(t))):new u(t,e)};u.prototype={get length(){return this.nodes.length}},u.prototype.nodes=[],u.prototype.addClass=function(){return this.eacharg(arguments,function(t,e){t.classList.add(e)})},u.prototype.adjacent=function(i,t,n){return"number"==typeof t&&(t=0===t?[]:new Array(t).join().split(",").map(Number.call,Number)),this.each(function(r,o){var e=document.createDocumentFragment();u(t||{}).map(function(t,e){var n="function"==typeof i?i.call(this,t,e,r,o):i;return"string"==typeof n?this.generate(n):u(n)}).each(function(t){this.isInPage(t)?e.appendChild(u(t).clone().first()):e.appendChild(t)}),n.call(this,r,e)})},u.prototype.after=function(t,e){return this.adjacent(t,e,function(t,e){t.parentNode.insertBefore(e,t.nextSibling)})},u.prototype.append=function(t,e){return this.adjacent(t,e,function(t,e){t.appendChild(e)})},u.prototype.args=function(t,e,n){return"function"==typeof t&&(t=t(e,n)),"string"!=typeof t&&(t=this.slice(t).map(this.str(e,n))),t.toString().split(/[\s,]+/).filter(function(t){return t.length})},u.prototype.array=function(o){o=o;var i=this;return this.nodes.reduce(function(t,e,n){var r;return o?((r=o.call(i,e,n))||(r=!1),"string"==typeof r&&(r=u(r)),r instanceof u&&(r=r.nodes)):r=e.innerHTML,t.concat(!1!==r?r:[])},[])},u.prototype.attr=function(t,e,r){return r=r?"data-":"",this.pairs(t,e,function(t,e){return t.getAttribute(r+e)},function(t,e,n){t.setAttribute(r+e,n)})},u.prototype.before=function(t,e){return this.adjacent(t,e,function(t,e){t.parentNode.insertBefore(e,t)})},u.prototype.children=function(t){return this.map(function(t){return this.slice(t.children)}).filter(t)},u.prototype.clone=function(){return this.map(function(t,e){var n=t.cloneNode(!0),r=this.getAll(n);return this.getAll(t).each(function(t,e){for(var n in this.mirror)this.mirror[n]&&this.mirror[n](t,r.nodes[e])}),n})},u.prototype.getAll=function(t){return u([t].concat(u("*",t).nodes))},u.prototype.mirror={},u.prototype.mirror.events=function(t,e){if(t._e)for(var n in t._e)t._e[n].forEach(function(t){u(e).on(n,t)})},u.prototype.mirror.select=function(t,e){u(t).is("select")&&(e.value=t.value)},u.prototype.mirror.textarea=function(t,e){u(t).is("textarea")&&(e.value=t.value)},u.prototype.closest=function(e){return this.map(function(t){do{if(u(t).is(e))return t}while((t=t.parentNode)&&t!==document)})},u.prototype.data=function(t,e){return this.attr(t,e,!0)},u.prototype.each=function(t){return this.nodes.forEach(t.bind(this)),this},u.prototype.eacharg=function(n,r){return this.each(function(e,t){this.args(n,e,t).forEach(function(t){r.call(this,e,t)},this)})},u.prototype.empty=function(){return this.each(function(t){for(;t.firstChild;)t.removeChild(t.firstChild)})},u.prototype.filter=function(e){var t=function(t){return t.matches=t.matches||t.msMatchesSelector||t.webkitMatchesSelector,t.matches(e||"*")};return"function"==typeof e&&(t=e),e instanceof u&&(t=function(t){return-1!==e.nodes.indexOf(t)}),u(this.nodes.filter(t))},u.prototype.find=function(e){return this.map(function(t){return u(e||"*",t)})},u.prototype.first=function(){return this.nodes[0]||!1},u.prototype.generate=function(t){return/^\s*<tr[> ]/.test(t)?u(document.createElement("table")).html(t).children().children().nodes:/^\s*<t(h|d)[> ]/.test(t)?u(document.createElement("table")).html(t).children().children().children().nodes:/^\s*</.test(t)?u(document.createElement("div")).html(t).children().nodes:document.createTextNode(t)},u.prototype.handle=function(){var t=this.slice(arguments).map(function(e){return"function"==typeof e?function(t){t.preventDefault(),e.apply(this,arguments)}:e},this);return this.on.apply(this,t)},u.prototype.hasClass=function(){return this.is("."+this.args(arguments).join("."))},u.prototype.html=function(e){return void 0===e?this.first().innerHTML||"":this.each(function(t){t.innerHTML=e})},u.prototype.is=function(t){return 0<this.filter(t).length},u.prototype.isInPage=function(t){return t!==document.body&&document.body.contains(t)},u.prototype.last=function(){return this.nodes[this.length-1]||!1},u.prototype.map=function(t){return t?u(this.array(t)).unique():this},u.prototype.not=function(e){return this.filter(function(t){return!u(t).is(e||!0)})},u.prototype.off=function(t){return this.eacharg(t,function(e,n){u(e._e?e._e[n]:[]).each(function(t){e.removeEventListener(n,t)})})},u.prototype.on=function(t,e,r){if("string"==typeof e){var o=e;e=function(e){var n=arguments;u(e.currentTarget).find(o).each(function(t){if(t===e.target||t.contains(e.target)){try{Object.defineProperty(e,"currentTarget",{get:function(){return t}})}catch(t){}r.apply(t,n)}})}}var n=function(t){return e.apply(this,[t].concat(t.detail||[]))};return this.eacharg(t,function(t,e){t.addEventListener(e,n),t._e=t._e||{},t._e[e]=t._e[e]||[],t._e[e].push(n)})},u.prototype.pairs=function(n,t,e,r){if(void 0!==t){var o=n;(n={})[o]=t}return"object"==typeof n?this.each(function(t){for(var e in n)r(t,e,n[e])}):this.length?e(this.first(),n):""},u.prototype.param=function(e){return Object.keys(e).map(function(t){return this.uri(t)+"="+this.uri(e[t])}.bind(this)).join("&")},u.prototype.parent=function(t){return this.map(function(t){return t.parentNode}).filter(t)},u.prototype.prepend=function(t,e){return this.adjacent(t,e,function(t,e){t.insertBefore(e,t.firstChild)})},u.prototype.remove=function(){return this.each(function(t){t.parentNode&&t.parentNode.removeChild(t)})},u.prototype.removeClass=function(){return this.eacharg(arguments,function(t,e){t.classList.remove(e)})},u.prototype.replace=function(t,e){var n=[];return this.adjacent(t,e,function(t,e){n=n.concat(this.slice(e.children)),t.parentNode.replaceChild(e,t)}),u(n)},u.prototype.scroll=function(){return this.first().scrollIntoView({behavior:"smooth"}),this},u.prototype.select=function(t,e){return t=t.replace(/^\s*/,"").replace(/\s*$/,""),/^</.test(t)?u().generate(t):(e||document).querySelectorAll(t)},u.prototype.serialize=function(){var r=this;return this.slice(this.first().elements).reduce(function(e,n){return!n.name||n.disabled||"file"===n.type?e:/(checkbox|radio)/.test(n.type)&&!n.checked?e:"select-multiple"===n.type?(u(n.options).each(function(t){t.selected&&(e+="&"+r.uri(n.name)+"="+r.uri(t.value))}),e):e+"&"+r.uri(n.name)+"="+r.uri(n.value)},"").slice(1)},u.prototype.siblings=function(t){return this.parent().children(t).not(this)},u.prototype.size=function(){return this.first().getBoundingClientRect()},u.prototype.slice=function(t){return t&&0!==t.length&&"string"!=typeof t&&"[object Function]"!==t.toString()?t.length?[].slice.call(t.nodes||t):[t]:[]},u.prototype.str=function(e,n){return function(t){return"function"==typeof t?t.call(this,e,n):t.toString()}},u.prototype.text=function(e){return void 0===e?this.first().textContent||"":this.each(function(t){t.textContent=e})},u.prototype.toggleClass=function(t,e){return!!e===e?this[e?"addClass":"removeClass"](t):this.eacharg(t,function(t,e){t.classList.toggle(e)})},u.prototype.trigger=function(t){var o=this.slice(arguments).slice(1);return this.eacharg(t,function(t,e){var n,r={bubbles:!0,cancelable:!0,detail:o};try{n=new window.CustomEvent(e,r)}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,o)}t.dispatchEvent(n)})},u.prototype.unique=function(){return u(this.nodes.reduce(function(t,e){return null!=e&&!1!==e&&-1===t.indexOf(e)?t.concat(e):t},[]))},u.prototype.uri=function(t){return encodeURIComponent(t).replace(/!/g,"%21").replace(/'/g,"%27").replace(/\(/g,"%28").replace(/\)/g,"%29").replace(/\*/g,"%2A").replace(/%20/g,"+")},u.prototype.wrap=function(t){return this.map(function(e){return u(t).each(function(t){(function(t){for(;t.firstElementChild;)t=t.firstElementChild;return u(t)})(t).append(e.cloneNode(!0)),e.parentNode.replaceChild(t,e)})})},"object"==typeof module&&module.exports&&(module.exports=u,module.exports.u=u);