PageSourceSearch

https://www.grantforward.com/public/js/grant-result-selection.js?v=284

js grantforward.com collected 2026-09-24 18:37:12 UTC 13,359 bytes, 335 lines download raw bytes

1
2var GrantResultSelection = GrantResultSelection || function () {
3    const selectedGrants = new Set([]);
4    const excludedGrants = new Set([]);
5    let currentPageGrantIds = new Set([]);
6    const LIMIT = 500;
7
8    const VIEW_MODES = {
9        origin: "1",
10        compact: "2",
11        table: "4" 
12    }
13    
14    let currentMode = "1"; // default mode is origin
15    let currentSearchMode = "search"; // default search mode
16    let prevQuery = null;
17
18    const markShowSelectionClass = "show-selection"
19    const markHideWithOpacityClass = "hide-opacity";
20    const elements = {
21        "selectAllCheckbox": "input[type='checkbox'].js-grant-select-all",
22        "selectAllCheckbox.wrapper": ".js-grant-select-all-wrapper",
23        "selectAllCheckbox.wrapper.compact": ".js-grant-select-all-wrapper.js-compact-mode",
24        "selectAllCheckbox.wrapper.table": ".js-grant-select-all-wrapper.js-table-mode",
25        "selectAllCheckbox.colHeader": ".js-grant-header-checkbox",
26
27        "selectAllCheckbox.label": ".grant-select-all-label",
28        "resultsWrapper": ".js-search-result",
29        "grantItemCheckboxes": ".search-result input[type='checkbox'].js-grant-checkbox",
30        "grantItemCheckbox": function (option) {return `.search-result input[type='checkbox'][value='${option.grantId}'].js-grant-checkbox`},
31        // tools box
32        "toolbox.countSelectionText": ".js-grant-selection-toolbox-text",
33        "toolbox.uncheckAll": ".js-selected-action-uncheck-all",
34        "toolbox": ".grant-selection-toolbox",
35
36        "batchGrantTagBtn": ".grant-selection-toolbox .js-result-add-tag-button",
37        "batchToggleFavoriteBtn": ".grant-selection-toolbox .js-batch-result-item-fav",
38        "batchUnwantBtn": ".grant-selection-toolbox .js-result-item-unw"
39
40    }
41
42
43    function elm(key, optionElements) {
44        const selector = elements[key];
45        if (typeof selector === 'function') {
46            return $(selector(optionElements));
47        }
48        return $(elements[key]);
49    }
50
51    const renderer = {
52        renderSelectAllGrants: function (triggerByAllCheckbox = false) {
53            const shouldShow = selectedGrants.size > 0;
54            if (!shouldShow) {
55                // For compact Mode
56                elm("selectAllCheckbox").prop("checked", false);
57                elm("resultsWrapper").removeClass(markShowSelectionClass);
58
59                // Still show select-all buttons until mouse leave event
60                if (!triggerByAllCheckbox) {
61                    elm("selectAllCheckbox.wrapper.compact").addClass("hidden");
62                    elm("selectAllCheckbox.wrapper.table").addClass(markHideWithOpacityClass);
63                }
64                return
65            }
66
67            if (currentMode == VIEW_MODES.compact) {
68                elm("selectAllCheckbox.wrapper.compact").removeClass("hidden");
69                elm("selectAllCheckbox.wrapper.table").addClass(markHideWithOpacityClass);
70            }
71            if (currentMode === VIEW_MODES.table) {
72                elm("selectAllCheckbox.wrapper.table").removeClass(markHideWithOpacityClass);
73                elm("selectAllCheckbox.wrapper.compact").addClass("hidden");
74            }
75            elm("resultsWrapper").addClass(markShowSelectionClass);
76        },
77        _getIsCurrnentPageAllSelected: function () {
78            const selectableGrantsIds = getCurrentPageSelectableGrantIds()
79            const isAllChecked = selectableGrantsIds.every(function (grantId) {
80                return selectedGrants.has(grantId);
81            })
82
83            return isAllChecked;
84        },
85        renderSelectedAllCheckbox: function () {
86            elm("selectAllCheckbox").prop("checked", renderer._getIsCurrnentPageAllSelected());
87        },
88        renderSelections: function () {
89            currentPageGrantIds.forEach(function (grantId) {
90                const isSelected = selectedGrants.has(grantId);
91
92                if (isSelected) {
93                    elm("grantItemCheckbox", {grantId}).prop("checked", true);
94                }
95                else {
96                    elm("grantItemCheckbox", {grantId}).prop("checked", false);
97                }
98            })
99        },
100        renderToolbox: function () {
101            // const shouldShowToolbox = 
102            const shouldShowToolbox = selectedGrants.size >= 1;
103            if (!shouldShowToolbox) {
104                elm("toolbox").addClass("hidden");
105                return
106            }
107            elm("toolbox").removeClass("hidden");
108            elm("toolbox.countSelectionText").text(`${selectedGrants.size} grants selected`);
109        },
110        toggleDisableActions: function (disable) {
111            elm("selectAllCheckbox.wrapper").toggleClass("disabled", disable);
112            elm("selectAllCheckbox").attr("disabled", disable);
113            
114            elm("batchGrantTagBtn").attr("disabled", disable);
115            elm("batchToggleFavoriteBtn").attr("disabled", disable);
116            elm("batchUnwantBtn").attr("disabled", disable);
117        },
118        toggleVisibleExcludeBtn: function (visible) {
119            elm("batchUnwantBtn").toggleClass("hidden", !visible);
120        },
121        _clearAllSelect: function () {
122            // clear all checkboxes
123            selectedGrants.clear();
124            elm("grantItemCheckboxes").prop("checked", false);
125            $(document).trigger("czd_grant_selection_change", {selectedGrants})
126        },
127    }
128
129    const eventHandlers = {
130        toggleGrantCheckbox: function (e) {
131            const checkbox = $(e.target);
132            const grantId = checkbox.prop("value");
133            const isChecked = e.target.checked;
134
135            if (isChecked && selectedGrants.size >= LIMIT) {
136                e.target.checked = false;
137                showAlert(`You can only select up to ${LIMIT} grants.`);
138                return;
139            }
140
141            if (isChecked) {
142                selectedGrants.add(grantId);
143            } else {
144                selectedGrants.delete(grantId);
145            }
146
147            renderer.renderSelectAllGrants();
148            renderer.renderSelectedAllCheckbox();
149            renderer.renderToolbox();
150            $(document).trigger("czd_grant_selection_change", {selectedGrants})
151        },
152        onCheckAllCurrentPageChanged: function (e) {
153            const isCheck = e.target.checked;
154            const selectableGrantsIds = getCurrentPageSelectableGrantIds();
155
156            for (let i = 0; i < selectableGrantsIds.length; i++) {
157                const grantId = selectableGrantsIds[i];
158                if (isCheck) {
159                    if (selectedGrants.size >= LIMIT) {
160                        showAlert(`You can only select up to ${LIMIT} grants. Some grants were not selected.`);
161                        break;
162                    }
163                    selectedGrants.add(grantId);
164                }
165                else {
166                    selectedGrants.delete(grantId);
167                }
168                elm("grantItemCheckbox", {grantId}).prop("checked", isCheck);
169            }
170
171            // const isAllChecked = renderer._getIsCurrnentPageAllSelected()
172            // e.target.checked = isAllChecked;
173
174            $(document).trigger("czd_grant_selection_change", {selectedGrants})
175
176            renderer.renderSelectAllGrants(true);
177            renderer.renderSelectedAllCheckbox();
178            renderer.renderToolbox();
179        },
180        onMouseLeaveSelectAllLabel: function (e) {
181            // This is to prevent the "Select All" disappear when uncheck it.
182            renderer.renderSelectAllGrants();
183        },
184        onToolboxUncheckAllClicked: function (e) {
185            renderer._clearAllSelect();
186            renderer.renderSelectAllGrants();
187            renderer.renderSelectedAllCheckbox();
188            renderer.renderToolbox();
189            renderer.renderSelectAllGrants();
190        },
191        unSelectAllGrants: function () {
192            // This is to uncheck all selected grants
193            renderer._clearAllSelect(); 
194            renderer.renderSelectAllGrants();
195            renderer.renderSelectedAllCheckbox();
196            renderer.renderToolbox();
197        },
198        onShouldUnselectGrant: function (_event, data) {
199            // Unselect these grant but not put them in excluded list
200            const toUnselectGrantIds = data.toUnselectGrantIds;
201
202            toUnselectGrantIds.forEach(function (grantId) {
203                if (selectedGrants.has(String(grantId))) {
204                    selectedGrants.delete(String(grantId));
205                }
206            })
207
208            renderer.renderSelectAllGrants();
209            renderer.renderSelectedAllCheckbox();
210            renderer.renderSelections();
211            renderer.renderToolbox();
212
213            $(document).trigger("czd_grant_selection_change", {selectedGrants})
214        },
215        onExcludedGrantsChange: function (_event, data) {
216            const toExcludeGrantIds = data.toExcludeGrantIds;
217
218            toExcludeGrantIds.forEach(function (toExcludeGID) {
219                if (!excludedGrants.has(toExcludeGID)) {
220                    excludedGrants.add(toExcludeGID);
221                }
222            })
223
224            // exclude the grants from selectedGrants
225            excludedGrants.forEach(function(grantId) {
226                if (selectedGrants.has(grantId)) {
227                    selectedGrants.delete(String(grantId));
228                }
229            });
230
231            renderer.renderSelectAllGrants();
232            renderer.renderSelectedAllCheckbox();
233            renderer.renderSelections();
234            renderer.renderToolbox();
235            $(document).trigger("czd_grant_selection_change", {selectedGrants})
236        }
237    }
238
239    function getCurrentPageSelectableGrantIds() {
240        return Array.from(currentPageGrantIds).filter(function (grantId) {
241            return !excludedGrants.has(grantId);
242        });
243    }
244
245    function onGrantsLoaded (granIds, viewMode = "2", searchMode="search") {
246            // Use when grant search results are loaded
247            const idsStr = granIds.map(function(id) {return String(id)});
248            currentPageGrantIds = new Set(idsStr);
249            currentMode = viewMode;
250            currentSearchMode = searchMode;
251
252            renderer.toggleVisibleExcludeBtn(currentSearchMode !== "handpick");
253            renderer.renderSelectAllGrants();
254            renderer.renderSelectedAllCheckbox();
255            renderer.renderSelections();
256            renderer.renderToolbox();
257            renderer.toggleDisableActions(false);
258    }
259
260   function shouldResetSelection (newQuery) {
261        if (!prevQuery) {
262            prevQuery = newQuery;
263            return true;
264        }
265        const shouldReset = JSON.stringify(newQuery) !== JSON.stringify(prevQuery);
266        if (shouldReset) {
267            prevQuery = newQuery;
268        }
269        return shouldReset;
270}
271
272    function onLoadingGrants(viewMode, query, searchMode="search") {
273        const selectedMode = Object.values(VIEW_MODES).includes(viewMode) ? viewMode : null;
274
275        if (!selectedMode) {
276            console.error(`Unknown view mode: ${viewMode}`);
277            return
278        }
279        
280        renderer.toggleVisibleExcludeBtn(currentSearchMode !== "handpick");
281
282        const shouldReset = shouldResetSelection(query);
283        if (shouldReset) {
284            renderer._clearAllSelect();
285            renderer.renderToolbox();
286        }
287
288        currentMode = selectedMode;
289        currentSearchMode = searchMode;
290
291        renderer.renderSelectAllGrants();
292        renderer.toggleDisableActions(true);
293    }
294
295
296    function showAlert(msg){
297        if (typeof bootbox !== 'undefined'){
298            bootbox.alert(msg);
299        }else{
300            alert(msg);
301        }
302    }
303
304    function bindEvents () {
305
306        // Remove all previous events
307
308        elm("grantItemCheckboxes").off("change", eventHandlers.toggleGrantCheckbox);
309        elm("selectAllCheckbox").off("change", eventHandlers.onCheckAllCurrentPageChanged);
310        elm("selectAllCheckbox.label").off("mouseleave", eventHandlers.onMouseLeaveSelectAllLabel);
311        elm("selectAllCheckbox.colHeader").off("mouseleave", eventHandlers.onMouseLeaveSelectAllLabel);
312        elm("toolbox.uncheckAll").off("click", eventHandlers.onToolboxUncheckAllClicked);
313        $(document).off("czd_grant_excluded_change", eventHandlers.onExcludedGrantsChange)
314        $(document).off("czd_grant_should_unselect", eventHandlers.onShouldUnselectGrant)
315        
316        // Bind events
317        elm("grantItemCheckboxes").on("change", eventHandlers.toggleGrantCheckbox);
318        elm("selectAllCheckbox").on("change", eventHandlers.onCheckAllCurrentPageChanged);
319        elm("selectAllCheckbox.label").on("mouseleave", eventHandlers.onMouseLeaveSelectAllLabel);
320        elm("selectAllCheckbox.colHeader").on("mouseleave", eventHandlers.onMouseLeaveSelectAllLabel);
321        elm("toolbox.uncheckAll").on("click", eventHandlers.onToolboxUncheckAllClicked);
322        $(document).on("czd_grant_excluded_change", eventHandlers.onExcludedGrantsChange)
323        $(document).on("czd_grant_should_unselect", eventHandlers.onShouldUnselectGrant)
324    }
325
326    return {
327        onGrantsLoaded: onGrantsLoaded,
328        bindEvents: bindEvents,
329        onLoadingGrants: onLoadingGrants, 
330    }
331}
332
333$(document).ready(function () {
334    window.grantResultSelection = new GrantResultSelection();
335})

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.