i'm trying to write a script to update URLs with colon-separated parameters in JS, because page content is loaded via AJAX.
The Document structure is like this:
Format:
<div class="filter" id="formats">
<a class="active" href="https://cdpn.io/page/">All</a>
<a href="https://cdpn.io/page/format:foo">Foo</a>
<a href="https://cdpn.io/page/format:bar">Bar</a>
<a href="https://cdpn.io/page/format:baz">Baz</a>
<div>
<br>
Topic:
<div class="filter" id="topics">
<a class="active" href="https://cdpn.io/page/">All</a>
<a href="https://cdpn.io/page/topic:foo">Foo</a>
<a href="https://cdpn.io/page/topic:bar">Bar</a>
<a href="https://cdpn.io/page/topic:baz">Baz</a>
</div>
<br>
Sort By:
<div class="filter" id="sort">
<a href="https://cdpn.io/page/sort:topic-asc">Topic Asc</a>
<a href="https://cdpn.io/page/sort:topic-desc">Topic Desc</a>
<br>
<a href="https://cdpn.io/page/sort:title-asc">Title Asc</a>
<a href="https://cdpn.io/page/sort:title-desc">Title Desc</a>
</div>
<br>
Url loaded:
<div id="content">
https://cdpn.io/page
</div>
only #content
is updated by the AJAX library, all links need to be changed "manually".
For example: if I click on a filter-link like https://example.com/page/topic:foo
, page content is refreshed, but all filters need to be updated: https://example.com/page/format:bar
should become https://example.com/page/topic:foo/format:bar
etc. Whenever any of the filters is clicked, existing parameters need to be overwritten or appended if they're not there yet, and removed when they don't exist.
I thought I had it figured out by mapping all params in an array of objects, then merging using a snippet I found on StackOverflow and returning the string, but there seems to be an error in my logic and I can't put my finger on it…
const mergeByProperty = (target, source, prop) => {
source.forEach(sourceElement => {
let targetElement = target.find(targetElement => {
return sourceElement[prop] === targetElement[prop];
})
targetElement ? Object.assign(targetElement, sourceElement) : target.push(sourceElement);
})
}
for (el of document.querySelectorAll('a')) {
el.addEventListener('click', (e) => {
e.preventDefault();
loadNewContent(e.target);
})
}
const loadNewContent = (target) => {
document.querySelector('#content').innerText = target
// this is where page content is fetched & appended etc, then:
updateLinks(target)
}
const updateLinks = (trigger) => {
document.querySelectorAll('a').forEach(linkToUpdate => {
linkToUpdate.href = mergeURLs(linkToUpdate.href, trigger.href);
})
}
function mergeURLs(url1, url2) {
let params1 = getParams(url1)
let params2 = getParams(url2)
mergeByProperty(params1, params2, 'param')
let newParamString = params1.map(s => `${s.param}:${s.value}`).join('/');
return `${window.location.origin}/page/${newParamString}`;
}
Here's a link to a codepen where I tried around.
https://codepen.io/moevbiz/pen/OJRNNex?editors=0011
Thankful for any hints or suggestions…
Solution: Instead of creating an object from URL parameters and trying to merge them, I'm using regex to replace existing parameters.
Codepen: https://codepen.io/moevbiz/pen/gOwrKYO?editors=0011
Links get data attributes like the following:
the working code: