Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 | 37x 37x 37x 37x 238x 238x 238x 238x 238x 238x 96x 14x 110x 110x 142x 37x 37x 105x 105x 110x 107x 89x 95x | import { buildUrlFromParams, ParamTypes, parseQueryString } from "../url-params.js";
import { debounce } from "../debounce.js";
// A slider fires for every pixel of a drag, and each URL update is a history entry.
const UrlSettleMs = 300;
/** The parameters that have the page do something once it is up, rather than describe it. */
const StartupActionTypes = {
autoboot: ParamTypes.BOOL,
autochain: ParamTypes.BOOL,
autorun: ParamTypes.BOOL,
autotype: ParamTypes.STRING,
loadBasic: ParamTypes.STRING,
embedBasic: ParamTypes.STRING,
patch: ParamTypes.STRING,
};
export const StartupActionParams = Object.keys(StartupActionTypes);
/** How each parameter the page understands is parsed and written back. */
export const UrlParamTypes = {
...StartupActionTypes,
// Array parameters
rom: ParamTypes.ARRAY,
// Boolean parameters
embed: ParamTypes.BOOL,
fasttape: ParamTypes.BOOL,
noseek: ParamTypes.BOOL,
hasMusic5000: ParamTypes.BOOL,
hasTeletextAdaptor: ParamTypes.BOOL,
hasEconet: ParamTypes.BOOL,
glEnabled: ParamTypes.BOOL,
lowLatency: ParamTypes.BOOL,
fakeVideo: ParamTypes.BOOL,
logFdcCommands: ParamTypes.BOOL,
logFdcStateChanges: ParamTypes.BOOL,
coProcessor: ParamTypes.BOOL,
mouseJoystickEnabled: ParamTypes.BOOL,
speechOutput: ParamTypes.BOOL,
audioDebug: ParamTypes.BOOL,
// Numeric parameters
stationId: ParamTypes.INT,
frameSkip: ParamTypes.INT,
videoCyclesBatch: ParamTypes.INT,
audiofilterfreq: ParamTypes.FLOAT,
audiofilterq: ParamTypes.FLOAT,
speakerAmount: ParamTypes.FLOAT,
palPersistenceMs: ParamTypes.FLOAT,
rgbPersistenceMs: ParamTypes.FLOAT,
audioLatencyMs: ParamTypes.FLOAT,
cpuMultiplier: ParamTypes.FLOAT,
tubeCpuMultiplier: ParamTypes.FLOAT,
microphoneChannel: ParamTypes.INT,
// String parameters (these are the default but listed for clarity)
model: ParamTypes.STRING,
disc: ParamTypes.STRING,
disc1: ParamTypes.STRING,
disc2: ParamTypes.STRING,
tape: ParamTypes.STRING,
mmc: ParamTypes.STRING,
keyLayout: ParamTypes.STRING,
displayMode: ParamTypes.STRING,
audioOutput: ParamTypes.STRING,
drive0Tracks: ParamTypes.STRING,
drive1Tracks: ParamTypes.STRING,
sbLeft: ParamTypes.STRING,
sbRight: ParamTypes.STRING,
sbBottom: ParamTypes.STRING,
};
/**
* The page's settings as carried in its URL. `params` is the one parsed
* object: whoever changes a setting hands the change to set(), which edits
* it in place and writes the URL in one step.
*/
export class UrlState {
constructor(location, history, paramTypes = UrlParamTypes) {
this.history = history;
this.paramTypes = paramTypes;
this.baseUrl = location.origin + location.pathname;
// Parameters may be given after the hash as well as in the query.
const queryString = location.search.substring(1) + "&" + location.hash.substring(1);
this.params = parseQueryString(queryString, paramTypes);
this.updateUrlOnceSettled = debounce(() => this.updateUrl(), UrlSettleMs);
}
/** The page's URL with the parameters as they are now. */
url() {
return buildUrlFromParams(this.baseUrl, this.params, this.paramTypes);
}
/** The page's URL with some parameters changed, leaving `params` as it is. */
urlWith(overrides) {
return buildUrlFromParams(this.baseUrl, { ...this.params, ...overrides }, this.paramTypes);
}
/**
* Apply `changes` to the parameters (undefined deletes a key) and push the
* new URL; `settle: true` lets a burst of changes finish before pushing one
* history entry for the lot.
*/
set(changes, { settle = false } = {}) {
let changed = false;
for (const [key, value] of Object.entries(changes)) {
if (value === undefined) {
if (key in this.params) changed = true;
delete this.params[key];
} else {
if (this.params[key] !== value) changed = true;
this.params[key] = value;
}
}
if (!changed) return;
if (settle) this.updateUrlOnceSettled();
else this.updateUrl();
}
updateUrl() {
this.history.pushState(null, null, this.url());
}
}
|