Skip to content

Commit

Permalink
Fix multi-facet selection on older browsers.
Browse files Browse the repository at this point in the history
This includes all browsers pre-2023 (e.g. Safari on iSO 16.x).
  • Loading branch information
EreMaijala committed Dec 18, 2024
1 parent 75c18d0 commit 080c87f
Show file tree
Hide file tree
Showing 4 changed files with 180 additions and 34 deletions.
69 changes: 68 additions & 1 deletion themes/bootstrap3/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,70 @@ var VuFind = (function VuFind() {
elem.style.transitionDuration = state;
}

/**
* Check if URLSearchParams contains the given key+value
*
* URLSearchParams.has(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_has_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to check
* @param {string} key Key
* @param {string} value Value
*
* @returns boolean
*/
function inURLSearchParams(params, key, value) {
for (const [paramsKey, paramsValue] of params) {
if (paramsKey === key && paramsValue === value) {
return true;
}
}
return false;
}

/**
* Delete a key+value from URLSearchParams
*
* URLSearchParams.delete(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_delete_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to delete from
* @param {string} deleteKey Key to delete
* @param {string} deleteValue Value to delete
*
* @returns URLSearchParams
*/
function deletePairFromURLSearchParams(params, deleteKey, deleteValue) {
const newParams = new URLSearchParams();
for (const [key, value] of params) {
if (key !== deleteKey || value !== deleteValue) {
newParams.append(key, value);
}
}
return newParams;
}

/**
* Delete a set of parameters from URLSearchParams
*
* URLSearchParams.delete(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_delete_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to delete from
* @param {URLSearchParams} deleteParams URLSearchParams containing all params to delete
*
* @returns URLSearchParams
*/
function deleteParamsFromURLSearchParams(params, deleteParams) {
const newParams = new URLSearchParams();
for (const [key, value] of params) {
if (!inURLSearchParams(deleteParams, key, value)) {
newParams.append(key, value);
}
}
return newParams;
}

//Reveal
return {
defaultSearchBackend: defaultSearchBackend,
Expand Down Expand Up @@ -519,7 +583,10 @@ var VuFind = (function VuFind() {
setElementContents: setElementContents,
getBootstrapMajorVersion: getBootstrapMajorVersion,
disableTransitions: disableTransitions,
restoreTransitions: restoreTransitions
restoreTransitions: restoreTransitions,
inURLSearchParams: inURLSearchParams,
deletePairFromURLSearchParams: deletePairFromURLSearchParams,
deleteParamsFromURLSearchParams: deleteParamsFromURLSearchParams
};
})();

Expand Down
38 changes: 22 additions & 16 deletions themes/bootstrap3/js/facets.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,15 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
initialParams.append(key, normalizeValue(key, value));
}

// Update query params for every date range selector
/**
* Update query params for every date range selector
*
* @param {URLSearchParams} queryParams
*
* @returns {URLSearchParams}
*/
function processRangeSelector(queryParams) {
let newParams = new URLSearchParams(queryParams.toString());
for (const form of rangeSelectorForms) {
const rangeName = form.dataset.name;
const rangeFilterField = form.dataset.filterField;
Expand All @@ -184,24 +191,25 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
if (valuesExist) {
// Update query params:
for (const input of dateInputs) {
queryParams.set(input.name, input.value);
newParams.set(input.name, input.value);
}
queryParams.set(rangeFilterField, rangeName);
newParams.set(rangeFilterField, rangeName);
} else {
// Delete from query params:
for (const input of dateInputs) {
queryParams.delete(input.name);
newParams.delete(input.name);
}
queryParams.delete(rangeFilterField, rangeName);
newParams = VuFind.deletePairFromURLSearchParams(newParams, rangeFilterField, rangeName);
}
// Remove any filter[]=rangeName:... from query params:
const paramStart = rangeName + ':';
for (const value of queryParams.getAll('filter[]')) {
for (const value of newParams.getAll('filter[]')) {
if (value.startsWith(paramStart)) {
queryParams.delete('filter[]', value);
newParams = VuFind.deletePairFromURLSearchParams(newParams, 'filter[]', value);
}
}
}
return newParams;
}

// Goes through all modified facets to compile into 2 arrays of added and removed URL parameters
Expand All @@ -215,13 +223,14 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {

// Add parameters that did not initially exist:
for (const [key, value] of elemParams) {
if (!initialParams.has(key, value)) {
// URLSearchParams.has(key, value) seems to be broken on iOS 16, so check with our own method:
if (!VuFind.inURLSearchParams(initialParams, key, value)) {
globalAddedParams.append(key, value);
}
}
// Remove parameters that this URL no longer has:
for (const [key, value] of initialParams) {
if (!elemParams.has(key, value)) {
if (!VuFind.inURLSearchParams(elemParams, key, value)) {
globalRemovedParams.append(key, value);
}
}
Expand All @@ -232,19 +241,16 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
function getHrefWithNewParams() {
processModifiedFacets();

const newParams = new URLSearchParams(initialParams);
// Remove parameters:
for (const [key, value] of globalRemovedParams) {
newParams.delete(key, value);
}
// Create params without the removed parameters:
const newParams = VuFind.deleteParamsFromURLSearchParams(initialParams, globalRemovedParams);
// Add newly added parameters:
for (const [key, value] of globalAddedParams) {
newParams.append(key, value);
}
processRangeSelector(newParams);

// Take base url from data attribute if present (standalone full facet list):
const baseUrl = defaultContext.dataset.searchUrl || window.location.pathname;
return baseUrl + '?' + newParams.toString();
return baseUrl + '?' + processRangeSelector(newParams).toString();
}

function applyMultiFacetsSelection() {
Expand Down
69 changes: 68 additions & 1 deletion themes/bootstrap5/js/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,70 @@ var VuFind = (function VuFind() {
elem.style.transitionDuration = state;
}

/**
* Check if URLSearchParams contains the given key+value
*
* URLSearchParams.has(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_has_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to check
* @param {string} key Key
* @param {string} value Value
*
* @returns boolean
*/
function inURLSearchParams(params, key, value) {
for (const [paramsKey, paramsValue] of params) {
if (paramsKey === key && paramsValue === value) {
return true;
}
}
return false;
}

/**
* Delete a key+value from URLSearchParams
*
* URLSearchParams.delete(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_delete_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to delete from
* @param {string} deleteKey Key to delete
* @param {string} deleteValue Value to delete
*
* @returns URLSearchParams
*/
function deletePairFromURLSearchParams(params, deleteKey, deleteValue) {
const newParams = new URLSearchParams();
for (const [key, value] of params) {
if (key !== deleteKey || value !== deleteValue) {
newParams.append(key, value);
}
}
return newParams;
}

/**
* Delete a set of parameters from URLSearchParams
*
* URLSearchParams.delete(key, value) support is not yet widespread enough to be used
* (see https://caniuse.com/mdn-api_urlsearchparams_delete_value_parameter)
*
* @param {URLSearchParams} params URLSearchParams to delete from
* @param {URLSearchParams} deleteParams URLSearchParams containing all params to delete
*
* @returns URLSearchParams
*/
function deleteParamsFromURLSearchParams(params, deleteParams) {
const newParams = new URLSearchParams();
for (const [key, value] of params) {
if (!inURLSearchParams(deleteParams, key, value)) {
newParams.append(key, value);
}
}
return newParams;
}

//Reveal
return {
defaultSearchBackend: defaultSearchBackend,
Expand Down Expand Up @@ -519,7 +583,10 @@ var VuFind = (function VuFind() {
setElementContents: setElementContents,
getBootstrapMajorVersion: getBootstrapMajorVersion,
disableTransitions: disableTransitions,
restoreTransitions: restoreTransitions
restoreTransitions: restoreTransitions,
inURLSearchParams: inURLSearchParams,
deletePairFromURLSearchParams: deletePairFromURLSearchParams,
deleteParamsFromURLSearchParams: deleteParamsFromURLSearchParams
};
})();

Expand Down
38 changes: 22 additions & 16 deletions themes/bootstrap5/js/facets.js
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,15 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
initialParams.append(key, normalizeValue(key, value));
}

// Update query params for every date range selector
/**
* Update query params for every date range selector
*
* @param {URLSearchParams} queryParams
*
* @returns {URLSearchParams}
*/
function processRangeSelector(queryParams) {
let newParams = new URLSearchParams(queryParams.toString());
for (const form of rangeSelectorForms) {
const rangeName = form.dataset.name;
const rangeFilterField = form.dataset.filterField;
Expand All @@ -184,24 +191,25 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
if (valuesExist) {
// Update query params:
for (const input of dateInputs) {
queryParams.set(input.name, input.value);
newParams.set(input.name, input.value);
}
queryParams.set(rangeFilterField, rangeName);
newParams.set(rangeFilterField, rangeName);
} else {
// Delete from query params:
for (const input of dateInputs) {
queryParams.delete(input.name);
newParams.delete(input.name);
}
queryParams.delete(rangeFilterField, rangeName);
newParams = VuFind.deletePairFromURLSearchParams(newParams, rangeFilterField, rangeName);
}
// Remove any filter[]=rangeName:... from query params:
const paramStart = rangeName + ':';
for (const value of queryParams.getAll('filter[]')) {
for (const value of newParams.getAll('filter[]')) {
if (value.startsWith(paramStart)) {
queryParams.delete('filter[]', value);
newParams = VuFind.deletePairFromURLSearchParams(newParams, 'filter[]', value);
}
}
}
return newParams;
}

// Goes through all modified facets to compile into 2 arrays of added and removed URL parameters
Expand All @@ -215,13 +223,14 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {

// Add parameters that did not initially exist:
for (const [key, value] of elemParams) {
if (!initialParams.has(key, value)) {
// URLSearchParams.has(key, value) seems to be broken on iOS 16, so check with our own method:
if (!VuFind.inURLSearchParams(initialParams, key, value)) {
globalAddedParams.append(key, value);
}
}
// Remove parameters that this URL no longer has:
for (const [key, value] of initialParams) {
if (!elemParams.has(key, value)) {
if (!VuFind.inURLSearchParams(elemParams, key, value)) {
globalRemovedParams.append(key, value);
}
}
Expand All @@ -232,19 +241,16 @@ VuFind.register('multiFacetsSelection', function multiFacetsSelection() {
function getHrefWithNewParams() {
processModifiedFacets();

const newParams = new URLSearchParams(initialParams);
// Remove parameters:
for (const [key, value] of globalRemovedParams) {
newParams.delete(key, value);
}
// Create params without the removed parameters:
const newParams = VuFind.deleteParamsFromURLSearchParams(initialParams, globalRemovedParams);
// Add newly added parameters:
for (const [key, value] of globalAddedParams) {
newParams.append(key, value);
}
processRangeSelector(newParams);

// Take base url from data attribute if present (standalone full facet list):
const baseUrl = defaultContext.dataset.searchUrl || window.location.pathname;
return baseUrl + '?' + newParams.toString();
return baseUrl + '?' + processRangeSelector(newParams).toString();
}

function applyMultiFacetsSelection() {
Expand Down

0 comments on commit 080c87f

Please sign in to comment.