PageSourceSearch

https://bucks-wmiddx-ramblers.org.uk/media/lib_ramblers/js/ra.paginatedDataList.js?rev=1788599531

js bucks-wmiddx-ramblers.org.uk collected 2026-10-08 11:46:28 UTC 14,369 bytes, 378 lines download raw bytes

1/* 
2 * Copyright (C) 2025 chris vaughan
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 */
18
19var ra;
20if (typeof (ra) === "undefined") {
21    ra = {};
22}
23
24ra.paginatedTable = function (tag, userOptions = null) {
25    this.options = {
26        className: "paginatedList"
27    };
28    this.defaultOptions = {pagination: {
29            "10 per page": 10,
30            "20 per page": 20,
31            "25 per page": 25,
32            "50 per page": 50,
33            "100 per page": 100,
34            "View all": 0
35        },
36        itemsPerPage: 20
37    };
38    this.cvListOptions = {...this.defaultOptions, ...userOptions};
39    this.fields = [];
40    this.format = null;
41    this.defaultSort = [];
42    this.noColumns = 1;
43    var tags = [
44        {name: 'home', parent: 'root', tag: 'div', attrs: {class: this.options.className}},
45        {name: 'filtersDiv', parent: 'home', tag: 'div', attrs: {class: 'filter'}},
46        {name: 'rapagination1', parent: 'home', tag: 'div', attrs: {class: 'pagination top'}},
47        {name: 'items1', parent: 'rapagination1', tag: 'div'},
48        {name: 'pagination1', parent: 'rapagination1', tag: 'div'},
49        {name: 'itemsSelect1', parent: 'rapagination1', tag: 'div'},
50        {name: 'table', parent: 'home', tag: 'table', attrs: {class: 'table'}},
51        {name: 'thead', parent: 'table', tag: 'thead'},
52        {name: 'tbody', parent: 'table', tag: 'tbody'},
53        {name: 'blank', parent: 'home', tag: 'div'},
54        {name: 'rapagination2', parent: 'home', tag: 'div', attrs: {class: 'pagination bottom'}},
55        {name: 'items2', parent: 'rapagination2', tag: 'div'},
56        {name: 'pagination2', parent: 'rapagination2', tag: 'div'},
57        {name: 'itemsSelect2', parent: 'rapagination2', tag: 'div'}
58    ];
59
60    this.elements = ra.html.generateTags(tag, tags);
61
62    this.list = new cvList(this.elements.tbody);
63
64    var pag = this.list.createPagination(this.cvListOptions);
65    pag.addPaginationDisplayText(this.elements.items1, 'Item {startItem} to {endItem} of {itemsNumber}');
66    pag.addPaginationDisplayButton(this.elements.pagination1, 'paginationButtons');
67    pag.addPaginationDisplayButton(this.elements.itemsSelect1, 'itemsPerPage');
68    pag.addPaginationDisplayText(this.elements.items2, 'Item {startItem} to {endItem} of {itemsNumber}');
69    pag.addPaginationDisplayButton(this.elements.pagination2, 'paginationButtons');
70    pag.addPaginationDisplayButton(this.elements.itemsSelect2, 'itemsPerPage');
71    var self = this;
72    this.elements.tbody.addEventListener("cvList-after-display", function (e) {
73        self._hideBlankColumns(self.elements.table);
74    });
75    this.elements.tbody.addEventListener('cvList-reportPagination', function (e) {
76        let ev = new Event("reportPagination");
77        ev.cvList = e.cvList;
78        tag.dispatchEvent(ev);
79    });
80
81    this._createFields = function (format) {
82        format.forEach(item => {
83            if ('field' in item) {
84                this.fields[item.title] = this.list.createField(item.title, item.field.type);
85            }
86        });
87    };
88    this._createFilters = function (format) {
89        format.forEach(item => {
90            if ('field' in item) {
91                var field = item.field;
92                if (field.filter) {
93                    this.fields[item.title].setFilter(this.elements.filtersDiv);
94                }
95            }
96        });
97    };
98// var format =   [ {
99//        "title": "Running No",
100//        "options": {
101//            "align": "right"
102//            "view": "notTablet" or "notMobile"
103//            "style": {"min-width":"60px",...}
104//        },
105//        "field": {
106//            "type": "number","text","date"
107//            "filter": false,
108//            "sort": true,
109//            "defaultSort": 'Asc' or 'Desc' 
110//        },
111//        "ignore": true If set then that column is not displayed
112//        view: 'notTablet' or 'notMobile'
113//    }, {...}
114//    ];
115    this.tableHeading = function (format) {
116        this.format = format;
117        this._createFields(format);
118        this._createFilters(format);
119        var row = document.createElement("tr");
120        this.noColumns = 0;
121        format.forEach(item => {
122            if ('ignore' in item) {
123                if (item.ignore) {
124                    return;
125                }
126            }
127            this.noColumns += 1;
128            var th = document.createElement("th");
129            th.innerText = item.title;
130            row.appendChild(th);
131            if ('options' in item) {
132                if ('align' in item.options) {
133                    th.classList.add(item.options.align);
134                }
135                if ('view' in item.options) {
136                    th.classList.add(item.options.view);
137                }
138                if ('style' in item.options) {
139                    var items = item.options.style;
140                    for (let item in items) {
141                        th.style.setProperty(item, items[item]);
142                    }
143                }
144            }
145            if ('field' in item) {
146                if (item.field.sort) {
147                    var field = this.fields[item.title];
148                    field.addSortArrows(th);
149                    if (item.field.defaultSort) {
150                        var item = {field: field, direction: item.field.defaultSort};
151                        this.defaultSort.push(item);
152                    }
153                }
154            }
155        }
156        );
157        this.elements.thead.appendChild(row);
158    };
159    this.tableRowStart = function () {
160        this.row = document.createElement("tr");
161        return this.row;
162    };
163    this.tableRowItem = function (value, item = null, sortValue = null) {
164        if (item !== null) {
165            if ('ignore' in item) {
166                if (item.ignore) {
167                    return null;
168                }
169            }
170        }
171        var td = document.createElement("td");
172        ra.html.setTag(td, value);
173        this.row.appendChild(td);
174        if (item !== null) {
175            if ('field' in item) {
176                var field = this.fields[item.title];
177                field.setValue(td, value);
178                if (sortValue !== null) {
179                    field.setSortValue(td, sortValue);
180                }
181            }
182            if ('options' in item) {
183                var options = item.options;
184                if ('align' in options) {
185                    td.classList.add(options.align);
186                }
187                if ('view' in item.options) {
188                    td.classList.add(item.options.view);
189                }
190            }
191        }
192        return td;
193    };
194    this.tableRowEnd = function (extraItem = null, cssClass = '') {
195        if (extraItem !== null) {
196            var nonPaginatedItem = document.createElement('tr');
197            if (cssClass !== '') {
198                nonPaginatedItem.setAttribute('class', cssClass);
199            }
200            var td = document.createElement('td');
201            td.setAttribute('colspan', this.noColumns);
202            nonPaginatedItem.appendChild(td);
203            td.appendChild(extraItem);
204            this.list.addItem(this.row, nonPaginatedItem);
205        } else {
206            this.list.addItem(this.row);
207        }
208        this.row = null;
209    };
210    this.tableEnd = function () {
211        this.list.display();
212        if (this.list.getNumberItems() < 20) {
213            this.elements.rapagination1.style.display = 'none';
214            this.elements.rapagination2.style.display = 'none';
215        }
216        this.defaultSort.forEach(item => {
217            switch (item.direction) {
218                case 'Asc':
219                    item.field.sort(1);
220                    break;
221                case 'Desc':
222                    item.field.sort(-1);
223                    break;
224                default:
225                    alert('order error');
226            }
227        });
228    };
229    this.sort = function (param, order) {
230        var field = this.fields[param];
231        if (field) {
232            switch (order) {
233                case 'Asc':
234                    field.sort(1);
235                    break;
236                case 'Desc':
237                    field.sort(-1);
238                    break;
239                default:
240                    alert('order error');
241            }
242        }
243    };
244    this.getPrintAll = function () {
245        var div = document.createElement('div');
246        div.classList.add(this.options.className);
247        var table = document.createElement('table');
248        div.appendChild(table);
249        table.appendChild(this.elements.thead.cloneNode(true));
250        var tbody = document.createElement('tbody');
251        table.appendChild(tbody);
252        this.list.appendPrintItems(tbody);
253        this.resetColumnDisplay(div);
254        this._hideBlankColumns(table);
255        return div;
256    };
257    this._hideBlankColumns = function (table) {
258        var cols = [];
259        var thead = table.childNodes[0];
260        var tbody = table.childNodes[1];
261        var nodeList = thead.childNodes[0].childNodes;
262        for (let i = 0; i < nodeList.length; i++) {
263            cols.push(i);
264        }
265        var trs = tbody.childNodes;
266        var len = cols.length;
267        for (let j = 0; j < len; j++) {
268            var col = len - j - 1;
269            for (let i = 0; i < trs.length; i++) {
270                var tr = trs[i];
271                var td = tr.childNodes[col];
272
273                if (typeof (td) !== "undefined") {
274                    var value = td.innerHTML;
275                    if (value !== '') {
276                        cols.splice(col, 1);
277                        break;
278                    }
279                }
280            }
281        }
282
283        this.resetColumnDisplay(this.elements.table);
284        this._removeColumns(cols);
285    };
286    this.resetColumnDisplay = function (tag) {
287        var elements = tag.getElementsByClassName('paginationRemoveCol');
288        // elements is a live list!
289        for (let i = elements.length - 1; i >= 0; i--) {
290            elements[i].classList.remove('paginationRemoveCol');
291        }
292        this.elements.blank.innerHTML = '';
293    };
294    this._removeColumns = function (cols) {
295        var nodeList = this.elements.thead.childNodes[0].childNodes;
296        var colNames = [];
297        for (let i = 0; i < cols.length; i++) {
298            var col = cols[i];
299            nodeList[col].classList.add('paginationRemoveCol');
300            colNames.push(this.format[col].title);
301        }
302        if (colNames.length > 0) {
303            this.elements.blank.innerHTML = "Blank columns not displayed: " + colNames.join();
304        }
305        var trs = this.elements.tbody.childNodes;
306        for (let j = 0; j < trs.length; j++) {
307            var tr = trs[j];
308            var tds = tr.childNodes;
309            for (let i = 0; i < cols.length; i++) {
310                var col = cols[i];
311                tds[col].classList.add('paginationRemoveCol');
312            }
313        }
314    };
315};
316ra.paginatedList = function (tag, userOptions = null) {
317    this.options = {
318        className: "paginatedList"
319    };
320    this.defaultOptions = {pagination: {
321            "10 per page": 10,
322            "20 per page": 20,
323            "25 per page": 25,
324            "50 per page": 50,
325            "100 per page": 100,
326            "View all": 0
327        },
328        itemsPerPage: 20
329    };
330    this.cvListOptions = {...this.defaultOptions, ...userOptions};
331    this.fields = [];
332    var tags = [
333        {name: 'home', parent: 'root', tag: 'div', attrs: {class: this.options.className}},
334        {name: 'filtersDiv', parent: 'home', tag: 'div', attrs: {class: 'filter'}},
335        {name: 'rapagination1', parent: 'home', tag: 'div', attrs: {class: 'pagination top'}},
336        {name: 'items1', parent: 'rapagination1', tag: 'div'},
337        {name: 'pagination1', parent: 'rapagination1', tag: 'div'},
338        {name: 'itemsSelect1', parent: 'rapagination1', tag: 'div'},
339        {name: 'content', parent: 'home', tag: 'div'},
340        {name: 'rapagination2', parent: 'home', tag: 'div', attrs: {class: 'pagination bottom'}},
341        {name: 'items2', parent: 'rapagination2', tag: 'div'},
342        {name: 'pagination2', parent: 'rapagination2', tag: 'div'},
343        {name: 'itemsSelect2', parent: 'rapagination2', tag: 'div'}
344    ];
345
346    this.elements = ra.html.generateTags(tag, tags);
347
348    this.list = new cvList(this.elements.content);
349    var pag = this.list.createPagination(this.cvListOptions);
350    pag.addPaginationDisplayText(this.elements.items1, 'Items {startItem} to {endItem} of {itemsNumber}');
351    pag.addPaginationDisplayButton(this.elements.pagination1, 'paginationButtons');
352    pag.addPaginationDisplayButton(this.elements.itemsSelect1, 'itemsPerPage');
353    pag.addPaginationDisplayText(this.elements.items2, 'Items {startItem} to {endItem} of {itemsNumber}');
354    pag.addPaginationDisplayButton(this.elements.pagination2, 'paginationButtons');
355    pag.addPaginationDisplayButton(this.elements.itemsSelect2, 'itemsPerPage');
356    this.elements.content.addEventListener('cvList-reportPagination', function (e) {
357        let ev = new Event("reportPagination");
358        ev.cvList = e.cvList;
359        tag.dispatchEvent(ev);
360    });
361
362    this.listItem = function (tag) {
363        this.list.addItem(tag);
364    };
365    this.listEnd = function () {
366        this.list.display();
367        if (this.list.getNumberItems() < 20) {
368            this.elements.rapagination1.style.display = 'none';
369            this.elements.rapagination2.style.display = 'none';
370        }
371    };
372    this.getPrintAll = function () {
373        var div = document.createElement('div');
374        div.classList.add(this.options.className);
375        this.list.appendPrintItems(div);
376        return div;
377    };
378};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.