Skip to content

Commit 4a7da79

Browse files
authored
feat: Add options for renderer and stackConnections (#199)
Introduce getOptions function (replacing most of loadScenario) to parse query parameters for the scenario, renderer and stackConnection options and update the form controls to match (after a short delay so that Chrome does not later restore incorrect form state when page navigation has occurred). N.B.: Because checkbox inputs do not send any parameter when not checked, it is not possible (without considerable extra trouble) to have a checkbox default to checked, so the checkbox for stackConnections is inverted from the option and is labelled accordingly. Fixes #179.
1 parent 32c2751 commit 4a7da79

File tree

2 files changed

+70
-28
lines changed

2 files changed

+70
-28
lines changed

test/index.html

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,15 +107,32 @@
107107
<div id="p5output"></div>
108108
<div id="scenarioForm">
109109
<form id="options">
110-
<label for="scenarioSelect">Scenario:</label>
110+
<label for="scenario">Scenario:</label>
111111
<select
112112
name="scenario"
113-
id="scenarioSelect"
113+
id="scenario"
114114
onchange="document.forms.options.submit()">
115115
<option value="simpleCircle">simple circle</option>
116116
<option value="sun">sun</option>
117117
<option value="blank">blank canvas</option>
118118
</select>
119+
<br />
120+
<label for="renderer">Renderer:</label>
121+
<select
122+
name="renderer"
123+
id="renderer"
124+
onchange="document.forms.options.submit()">
125+
<option value="geras">Geras</option>
126+
<option value="thrasos">Thrasos</option>
127+
<option value="zelos">Zelos</option>
128+
</select>
129+
<br />
130+
<label for="stackConnections">Disable stack connections:</label>
131+
<input
132+
type="checkbox"
133+
name="noStack"
134+
id="noStack"
135+
onChange="document.forms.options.submit()" />
119136
</form>
120137
</div>
121138
</div>

test/index.ts

Lines changed: 51 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,23 +24,49 @@ import {load} from './loadTestBlocks';
2424
import {runCode, registerRunCodeShortcut} from './runCode';
2525

2626
/**
27-
* Load initial workspace state based on the value in the scenario dropdown.
27+
* Parse query params for inject and navigation options and update
28+
* the fields on the options form to match.
2829
*
29-
* @param workspace The workspace to load blocks into.
30+
* @returns An options object with keys for each supported option.
3031
*/
31-
function loadScenario(workspace: Blockly.WorkspaceSvg) {
32-
const scenarioSelector = location.search.match(/scenario=([^&]+)/);
33-
// Default to the sunny day example.
34-
const scenarioString = scenarioSelector
35-
? scenarioSelector[1]
36-
: 'simpleCircle';
37-
const selector = document.getElementById(
38-
'scenarioSelect',
39-
) as HTMLSelectElement;
40-
selector.value = scenarioString;
41-
42-
// Load the initial state from storage and run the code.
43-
load(workspace, scenarioString);
32+
function getOptions() {
33+
const params = new URLSearchParams(window.location.search);
34+
35+
const scenarioParam = params.get('scenario');
36+
const scenario = scenarioParam ?? 'simpleCircle';
37+
38+
const rendererParam = params.get('renderer');
39+
let renderer = 'zelos';
40+
// For backwards compatibility with previous behaviour, support
41+
// (e.g.) ?geras as well as ?renderer=geras:
42+
if (rendererParam) {
43+
renderer = rendererParam;
44+
} else if (params.get('geras')) {
45+
renderer = 'geras';
46+
} else if (params.get('thrasos')) {
47+
renderer = 'thrasos';
48+
}
49+
50+
const noStackParam = params.get('noStack');
51+
const stackConnections = !noStackParam;
52+
53+
// Update form inputs to match params, but only after the page is
54+
// fully loaded as Chrome (at least) tries to restore previous form
55+
// values and does so _after_ DOMContentLoaded has fired, which can
56+
// result in the form inputs being out-of-sync with the actual
57+
// options when doing browswer page navigation.
58+
window.addEventListener('load', () => {
59+
(document.getElementById('renderer') as HTMLSelectElement).value = renderer;
60+
(document.getElementById('scenario') as HTMLSelectElement).value = scenario;
61+
(document.getElementById('noStack') as HTMLInputElement).checked =
62+
!stackConnections;
63+
});
64+
65+
return {
66+
scenario,
67+
stackConnections,
68+
renderer,
69+
};
4470
}
4571

4672
/**
@@ -50,26 +76,25 @@ function loadScenario(workspace: Blockly.WorkspaceSvg) {
5076
* @returns The created workspace.
5177
*/
5278
function createWorkspace(): Blockly.WorkspaceSvg {
53-
console.log(location.search);
54-
const renderer = location.search.includes('geras')
55-
? 'geras'
56-
: location.search.includes('thrasos')
57-
? 'thrasos'
58-
: 'zelos';
59-
const options = {
79+
const {scenario, stackConnections, renderer} = getOptions();
80+
81+
const injectOptions = {
6082
toolbox: toolboxCategories,
6183
renderer,
6284
};
6385
const blocklyDiv = document.getElementById('blocklyDiv')!;
64-
const workspace = Blockly.inject(blocklyDiv, options);
86+
const workspace = Blockly.inject(blocklyDiv, injectOptions);
6587

66-
new KeyboardNavigation(workspace, {});
88+
const navigationOptions = {
89+
cursor: {stackConnections},
90+
};
91+
new KeyboardNavigation(workspace, navigationOptions);
6792
registerRunCodeShortcut();
6893

6994
// Disable blocks that aren't inside the setup or draw loops.
7095
workspace.addChangeListener(Blockly.Events.disableOrphans);
7196

72-
loadScenario(workspace);
97+
load(workspace, scenario);
7398
runCode();
7499

75100
return workspace;
@@ -88,7 +113,7 @@ function addP5() {
88113
javascriptGenerator.addReservedWords('sketch');
89114
}
90115

91-
document.addEventListener('DOMContentLoaded', function () {
116+
document.addEventListener('DOMContentLoaded', () => {
92117
addP5();
93118
createWorkspace();
94119
document.getElementById('run')?.addEventListener('click', runCode);

0 commit comments

Comments
 (0)