browser/url.js

/**
 * Url updater
 * @module
 * @since 0.1.18
 */

/**
 * Replace query param
 * @param {string} url  url to update
 * @param {string} param_name
 * @param {string} param_value
 * @returns {string} updated string
 */
const replaceUrlParam = (
    url,
    param_name,
    param_value,
) => {
    let value = param_value;
    if (value === null) {
        value = '';
    }
    let updated_url = url;
    const pattern = new RegExp(`\\b(${param_name}=).*?(&|#|$)`);

    if (updated_url.search(pattern) >= 0) {
        return updated_url.replace(pattern, `$1${value}$2`);
    }

    updated_url = updated_url.replace(/[?#]$/, '');
    return `${updated_url + (updated_url.indexOf('?') > 0 ? '&' : '?') + param_name}=${value}`;
};

/**
 * Iterates over provided params and updates if replacement value found, new params are ignored
 * @param {string} url url to update
 * @param {array} arr_params containing structs with params to update {name: x, value: y}
 * @returns {struct} update configuration for the commit {path: ,is_popstate_update: bool}
 */
const updateURLParams = (
    url,
    arr_params,
) => {
    let updated_path = url;
    const arr_popstate_keys = ['vehicle_id', 'make', 'model', 'derivative', 'ucid', 'comcar_id'];
    let is_popstate_update = false;
    for (let i = 0; i < arr_params.length; i += 1) {
        if (url.includes(`${arr_params[i].name}=`)) {
            updated_path = replaceUrlParam(
                updated_path,
                arr_params[i].name,
                arr_params[i].value,
            );
        }
        if (arr_popstate_keys.includes(arr_params[i].name)) {
            is_popstate_update = true;
        }
    }
    return { path: updated_path, is_popstate_update };
};

/* istanbul ignore next */
/**
 * Updates current path in browser
 * @param {string} url new path to set
 * @param {boolean} is_popstate_update whether or not to override the back button
 */
const commitBrowserURLUpdate = (
    url,
    is_popstate_update,
) => {
    window.history.pushState(document.title, document.title, url);
    // when going back reload the page
    if (is_popstate_update) {
        window.onpopstate = function popStateUpdate() {
            window.location.reload();
        };
    }
};

/* istanbul ignore next */
/**
 * Abstraction to make testing easier,
 * @param {array} arr_params containing structs with params to update {name: x, value: y}
 */
const updateURL = (
    arr_params,
) => {
    const skv_update_config = updateURLParams(window.location.href, arr_params);
    commitBrowserURLUpdate(
        skv_update_config.path,
        skv_update_config.is_popstate_update,
    );
};

export {
    updateURLParams,
    replaceUrlParam,
    updateURL,
};