mirror of
https://github.com/shoelace-style/webawesome.git
synced 2026-01-12 04:09:12 +00:00
80 lines
1.8 KiB
JavaScript
80 lines
1.8 KiB
JavaScript
|
|
const IDENTITY = x => x;
|
|||
|
|
|
|||
|
|
export default class Permalink extends URLSearchParams {
|
|||
|
|
/** Params changed since last URL I/O */
|
|||
|
|
changed = false;
|
|||
|
|
|
|||
|
|
constructor(params) {
|
|||
|
|
super(location.search);
|
|||
|
|
this.params = params;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
toJSON() {
|
|||
|
|
return Object.fromEntries(this.entries());
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
#mappings = new WeakMap();
|
|||
|
|
|
|||
|
|
mapObject(obj, mapping = {}) {
|
|||
|
|
this.#mappings.set(obj, mapping);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
readFrom(obj) {
|
|||
|
|
let mapping = this.#mappings.get(obj) ?? {};
|
|||
|
|
let { keyFrom = IDENTITY, valueFrom = IDENTITY } = mapping;
|
|||
|
|
|
|||
|
|
for (let key in obj) {
|
|||
|
|
let value = obj[key];
|
|||
|
|
let mappedValue = valueFrom(value);
|
|||
|
|
let mappedKey = keyFrom(key);
|
|||
|
|
this.set(mappedKey, mappedValue);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
writeTo(obj) {
|
|||
|
|
let mapping = this.#mappings.get(obj) ?? {};
|
|||
|
|
let { keyTo = IDENTITY, valueTo = IDENTITY, canExtend = false } = mapping;
|
|||
|
|
|
|||
|
|
for (let [key, value] of this) {
|
|||
|
|
let mappedKey = keyTo(key);
|
|||
|
|
let mappedValue = valueTo(value);
|
|||
|
|
|
|||
|
|
if (canExtend || mappedKey in obj) {
|
|||
|
|
obj[mappedKey] = mappedValue;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
set(key, value, defaultValue) {
|
|||
|
|
let oldValue = this.get(key);
|
|||
|
|
|
|||
|
|
if (!value || value == defaultValue) {
|
|||
|
|
super.delete(key);
|
|||
|
|
|
|||
|
|
if (oldValue) {
|
|||
|
|
this.changed = true;
|
|||
|
|
}
|
|||
|
|
} else {
|
|||
|
|
super.set(key, value);
|
|||
|
|
|
|||
|
|
if (String(value) !== String(oldValue)) {
|
|||
|
|
this.changed = true;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/**
|
|||
|
|
* Update page URL if it has changed since last time
|
|||
|
|
*/
|
|||
|
|
updateLocation() {
|
|||
|
|
if (this.changed) {
|
|||
|
|
// If there’s already a search, replace it.
|
|||
|
|
// We don’t want to clog the user’s history while they iterate
|
|||
|
|
let search = this.toString();
|
|||
|
|
let historyAction = location.search && search ? 'replaceState' : 'pushState';
|
|||
|
|
history[historyAction](null, '', `?${search}`);
|
|||
|
|
this.changed = false;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|