Een jaar of wat geleden heb ik al is een poging gedaan om deze feature aan te vragen, echter was 'ie toen ondergebracht in een topic met een andere context. Nu ga ik het nog een keer proberen.
Waar het op neer komt is dat ik wil filteren binnen de lange lijsten die je krijgt bij het klikken op "Alle opties". Het voorbeeld wat ik eerder gebruikte was het CPU-filter voor laptops. In die lijst staan zo'n 200 opties. Dat is zoeken naar een speld in een hooiberg. Wat ik voorstel is het volgende:
Allereerst een plaatje (die nog oude stijl gebruikt).

1: Precies zoals het nu ook al is, standaard lijst met populaire keuzes
2: Alle keuzes zichtbaar gemaakt, extra is nu een tekstveld en een checkbox "Alles Selecteren"
3: Typen in het veld filtert de lijst on-the-fly.
4: Vinkje zetten bij "Alles Selecteren" en dan worden de keuzes ook gechecked, en kan de lijst worden gefilterd.
Ik speel veel met de Custom CSS hier op Tweakers, dit keer heb ik de Javascript aar is aangepakt. Dus hallelujah, hierbij een volledig werkende versie van wat ik bereiken wil
. Hoop dat jullie je voordeel ermee doen. IIg heb ik een leuke knutsel projectje gehad 
Waar het op neer komt is dat ik wil filteren binnen de lange lijsten die je krijgt bij het klikken op "Alle opties". Het voorbeeld wat ik eerder gebruikte was het CPU-filter voor laptops. In die lijst staan zo'n 200 opties. Dat is zoeken naar een speld in een hooiberg. Wat ik voorstel is het volgende:
Allereerst een plaatje (die nog oude stijl gebruikt).

1: Precies zoals het nu ook al is, standaard lijst met populaire keuzes
2: Alle keuzes zichtbaar gemaakt, extra is nu een tekstveld en een checkbox "Alles Selecteren"
3: Typen in het veld filtert de lijst on-the-fly.
4: Vinkje zetten bij "Alles Selecteren" en dan worden de keuzes ook gechecked, en kan de lijst worden gefilterd.
Ik speel veel met de Custom CSS hier op Tweakers, dit keer heb ik de Javascript aar is aangepakt. Dus hallelujah, hierbij een volledig werkende versie van wat ik bereiken wil
JavaScript:
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
| function FilterFormExtended(filterForm) { this.filterForm = filterForm; this.originalHandleAjaxResponse = null; } Object.extend(FilterFormExtended.prototype, { init: function () { this.hideMoreLinks(); }, hideMoreLinks: function () { if (!filterForm.listing) return; // find all the links more/less options link var links = Selector('.showLink, .hideLink'); var i = 0, link; while ((link = links[i++])) { //this is the id of the div element of the current filter var filterName = link.parentNode.parentNode.id; //just a check to see the scipt is working if (window.debug) link.innerHTML = link.innerHTML + " extended"; // we want additional things to happen when the user clicks on the link this.addSimpleEvent(link, 'onclick', this.toggleHideMore); // creating HTML, could be rendered at the server this.generateHtml(link, filterName); //select the ul element of the extended filter var ul = Selector('#' + filterName + '_extendedFilter', link.parentNode)[0]; // get the actual filter element var filter = Selector('#' + filterName + '_filter', ul)[0]; filter.onkeyup = this.filterList; // get the actual select all element var selectAllCheckbox = Selector('#' + filterName + '_selectall', ul)[0]; selectAllCheckbox.onclick = this.selectAll; // create a options bag to store key references into var options = {}; options.filterName = filterName; options.filterElement = filter; options.filterContainer = ul; options.selectAllCheckbox = selectAllCheckbox; // figure out what option values there are in the filer // we need to exclude the li elements from the extended filter options.optionsElements = Selector('li', link.parentNode); var j = 0, li; while ((li = options.optionsElements[j++])) { if (li.parentNode == ul) options.optionsElements.splice(--j, 1); } filter.options = options; selectAllCheckbox.options = options; link.options = options; // trigger the initial visibility this.toggleHideMore.call(link); } // replace the original handleAjaxResponse method so we can inject our onw code first. this.originalHandleAjaxResponse = this.filterForm.handleAjaxResponse; this.filterForm.handleAjaxResponse = this.handleAjaxResponse; }, generateHtml: function (link, filterName) { var html = ('<li>' + '<input type="text" id="{filterName}_filter" name="extendedFilter" class="text" placehoder="Filter">' + '</li>' + '<li>' + '<label for="{filterName}_selectall" class="checkbox">' + '<span class="inputWrapper">' + '<input type="checkbox" name="extendedSelectall" id="{filterName}_selectall" value="{filterName}_selectall">' + '</span>' + '<span title="Alles Selecteren" class="facetLabel"><b>Alles Selecteren</b></span>' + '</label>' + '</li>').replace(/{filterName}/g, filterName); // add the a new ul to the page // ul used so that is can be easily hidden var ul = document.createElement('ul'); link.parentNode.insertBefore(ul, link.previousSibling.previousSibling); // before the link there ar two ul elements, we place it above these two elements ul.id = filterName + "_extendedFilter"; ul.innerHTML = html; }, handleAjaxResponse: function (response) { // validate the data is OK var data = checkJsonResponse(response); // because the querystring returned from the server does not include the extended field these need to be added // otherwise the original handleAjaxResponse will clear the form, and not reset the values if ('querystring' in data) { // first we do all the select all comboboxes var selectAlls = Selector("[name='extendedSelectall']"); var i = 0, selectAll; data.querystring.extendedSelectall = []; while ((selectAll = selectAlls[i++])) { if (selectAll.checked) data.querystring.extendedSelectall[data.querystring.extendedSelectall.length] = selectAll.value; } // now the do the user typed filer var filters = Selector("[name='extendedFilter']"); var j = 0, filter; // we check if there is a value filled in and then add it to the query string. while ((filter = filters[j++])) { if (filter.value !== '' && filter.value !== undefined) data.querystring[filter.id] = filter.value; } } // call the original method filterFormExtended.originalHandleAjaxResponse.call(this, response); }, // 'this' is the 'a'-element of the show/hide more link toggleHideMore: function (e) { // because the original code has already run the check is the other way around if (this.className != /*==*/ 'showLink') { removeClass(this.options.filterContainer, 'hideMore'); } else { addClass(this.options.filterContainer, 'hideMore'); // reset the filter and make sure all options are visible again removeClass(this.options.selectAllCheckbox.parentNode.parentNode, 'selected'); this.options.selectAllCheckbox.checked = false; this.options.filterElement.value = ''; filterFormExtended.filterList.call(this.options.filterElement, e); } }, // onKeyUp event of the filter box // 'this' is the 'input'-element text filter filterList: function (e) { // we don't want to be case sensitive var searchString = this.value.toLowerCase(); var i = 0, li, needsScreenUpdate = false, shownItems = 0, checkedItems = 0; // loop over all options within this filter to see if they match // if they don't match we hide them, oterwise we show them // it also keeps track of the state of the checkbox before it was hidden // so then when it is shown again we can reset the correct state while ((li = this.options.optionsElements[i++])) { var label = singleOrNull(Selector('.facetLabel', li)); var checkbox = singleOrNull(Selector('input', li)); if (label !== null && checkbox !== null) { // do the string comparision, also here lower case if (label.innerText.toLowerCase().contains(searchString)) { // if it is currently hidden, we need to make it visible if (li.className == 'hideMore') { removeClass(li, 'hideMore'); // restore the state of check box from before the filter if (checkbox.checkedBeforeFilter) checkbox.checked = checkbox.checkedBeforeFilter; checkbox.checkedBeforeFilter = checkbox.checked; // if a checked option is now visible we need to refresh the screen needsScreenUpdate |= checkbox.checked; } shownItems++; if (checkbox.checked) checkedItems++; } // only hide it if it is not already hidden // otherwise we override the checkedBeforeFilter state else if (li.className != 'hideMore') { addClass(li, 'hideMore'); // if a checked option is now hidden we need to refresh the screen needsScreenUpdate |= checkbox.checked; checkbox.checkedBeforeFilter = checkbox.checked; // make sure the option in no longer checked checkbox.checked = false; } } } // finally update the page with the selected options if needed if (needsScreenUpdate) filterForm.ajaxTimer(); // disable the select all button if there are no options this.options.selectAllCheckbox.disabled = shownItems === 0; // show the selected all button as selected if all filter options are selected if (shownItems > 0 && checkedItems == shownItems) { addClass(this.options.selectAllCheckbox.parentNode.parentNode, 'selected'); this.options.selectAllCheckbox.checked = true; } else { removeClass(this.options.selectAllCheckbox.parentNode.parentNode, 'selected'); this.options.selectAllCheckbox.checked = false; } }, // onClick event of the selected all combobox // 'this' is sthe 'input'-element combobox selectAll: function (e) { var i = 0, li, needsScreenUpdate = false; // loop over all options, check if there are not hidden due to the text filter // then check the options while ((li = this.options.optionsElements[i++])) { if (!this.checked || li.className != 'hideMore') { var checkbox = singleOrNull(Selector('input', li)); if (checkbox !== null) { // only update the screen if the checkbox is switched from state needsScreenUpdate |= (checkbox.checked != this.checked); checkbox.checked = this.checked; } } } // finally update the page with the selected options if needed if (needsScreenUpdate) filterForm.ajaxTimer(); }, // fixed helper funtion available in T.net code // now actually supplies the eventargs to the functions addSimpleEvent: function (element, event, func) { if (element[event]) { var oldFunction = element[event]; element[event] = function(e) { oldFunction.call(this, e); func.call(this, e); }; } else element[event] = func; } }); // little helper function to get the first element from an array function singleOrNull(array) { if (Array.isArray(array) && array.length == 1) return array[0]; return null; } window.debug = true; // init the code if (filterForm) { var filterFormExtended = new FilterFormExtended(filterForm); filterFormExtended.init(); } |
[ Voor 0% gewijzigd door remyblok op 08-06-2015 13:30 . Reden: Wat puntcomma's toegevoegd ]