SASS Inputs HW
Popcorn Hack: Refactor Base Inputs
<!-- Reusable UI Runner Component -->
<div class="ui-runner-container" id="ui-runner-inputs-popcorn-runner" data-storage-key="_sass_inputs-hw__inputs-popcorn-runner">
<div class="challenge-box">
<h3>Challenge</h3>
<p>
Refactor non-standard inline styles and made-up classes using the official OCS input grammar.
</p>
</div>
<div class="editor-container">
<div class="control-panel">
<button type="button" class="ocs__btn utility run" data-hook="run" title="Run" aria-label="Run"></button>
<button type="button" class="ocs__btn utility stop" data-hook="stop" title="Stop" aria-label="Stop"></button>
<button type="button" class="ocs__btn utility copy" data-hook="copy" title="Copy Code" aria-label="Copy Code"></button>
<button type="button" class="ocs__btn utility save" data-hook="save" title="Save Code" aria-label="Save Code"></button>
<button type="button" class="ocs__btn utility clear" data-hook="clear" title="Clear Storage" aria-label="Clear Storage"></button>
</div>
<textarea class="editor-textarea"></textarea>
<div class="control-panel">
<span class="lineCount">Lines: 1</span>
<span class="charCount">Characters: 0</span>
</div>
</div>
<div class="output-container">
<div class="control-panel">
<span>UI Output</span>
<button type="button" class="ocs__btn utility reset" data-hook="reset" title="Reset" aria-label="Reset"></button>
</div>
<div class="ui-output" id="ui-output-inputs-popcorn-runner"></div>
</div>
</div>
<script type="module">
import { BaseRunner, UiExecutor } from '/assets/js/pages/runners/index.js';
(function() {
const container = document.getElementById('ui-runner-inputs-popcorn-runner');
if (!container) return;
const defaultCode = `
// UI_RUNNER: Inputs Popcorn Base
outputElement.innerHTML = [
'<label for="search-input" class="ocs__label">Search</label>',
'<input id="search-input" type="text" class="ocs__input ocs__input--large ocs__input--gradient" placeholder="Search PVO resources...">',
'<br><br>',
'<label for="first-name" class="ocs__label">First Name</label>',
'<input id="first-name" type="text" class="ocs__input ocs__input--small" placeholder="Volunteer First Name">'
].join('');
`.trim();
const autostart = "true" === "true";
const editorHeight = "";
const outputHeight = "";
const storageKey = container.dataset.storageKey;
const runner = new BaseRunner(container, { storageKey });
const editor = runner.initializeEditor({
defaultCode,
editorHeight,
fallbackCode: "// Write your JavaScript code here",
codeMirrorOptions: {
lineNumbers: true,
mode: "javascript",
theme: "darcula",
indentUnit: 2,
tabSize: 4,
styleSelectedText: true
}
});
if (outputHeight) {
runner.applyScopedStyle(`#ui-output-inputs-popcorn-runner { min-height: ${outputHeight}; max-height: ${outputHeight}; height: ${outputHeight}; }`);
}
const uiOutput = container.querySelector('.ui-output');
const uiExecutor = new UiExecutor({
editor,
outputElement: uiOutput,
});
runner.bindEditorButtons({
resetValue: defaultCode || "// Write your JavaScript code here",
onClear: () => {
stopExecution();
},
saveFeedback: '✔',
copyFeedback: '✔'
});
// Stop execution
function stopExecution() {
uiExecutor.stop();
}
// Reset button
container.querySelector('[data-hook="reset"]').onclick = () => {
stopExecution();
};
// Stop button
container.querySelector('[data-hook="stop"]').onclick = () => {
stopExecution();
};
// Run button logic
function runCode() {
return uiExecutor.run();
}
runner.bindButton('', runCode, 'run');
// Keyboard shortcut
runner.bindShortcut(runCode);
if (autostart) {
// Defer to next tick so output container is present before execution.
setTimeout(() => {
runCode();
}, 0);
}
})();
</script>
Homework Hack
<!-- Reusable UI Runner Component -->
<div class="ui-runner-container" id="ui-runner-inputs-hw-runner" data-storage-key="_sass_inputs-hw__inputs-hw-runner">
<div class="challenge-box">
<h3>Challenge</h3>
<p>
Refactor the signup form by removing inline styles and made-up classes, using proper ocs__input modifiers and accessible labels.
</p>
</div>
<div class="editor-container">
<div class="control-panel">
<button type="button" class="ocs__btn utility run" data-hook="run" title="Run" aria-label="Run"></button>
<button type="button" class="ocs__btn utility stop" data-hook="stop" title="Stop" aria-label="Stop"></button>
<button type="button" class="ocs__btn utility copy" data-hook="copy" title="Copy Code" aria-label="Copy Code"></button>
<button type="button" class="ocs__btn utility save" data-hook="save" title="Save Code" aria-label="Save Code"></button>
<button type="button" class="ocs__btn utility clear" data-hook="clear" title="Clear Storage" aria-label="Clear Storage"></button>
</div>
<textarea class="editor-textarea"></textarea>
<div class="control-panel">
<span class="lineCount">Lines: 1</span>
<span class="charCount">Characters: 0</span>
</div>
</div>
<div class="output-container">
<div class="control-panel">
<span>UI Output</span>
<button type="button" class="ocs__btn utility reset" data-hook="reset" title="Reset" aria-label="Reset"></button>
</div>
<div class="ui-output" id="ui-output-inputs-hw-runner"></div>
</div>
</div>
<script type="module">
import { BaseRunner, UiExecutor } from '/assets/js/pages/runners/index.js';
(function() {
const container = document.getElementById('ui-runner-inputs-hw-runner');
if (!container) return;
const defaultCode = `
// UI_RUNNER: Inputs Homework Base
outputElement.innerHTML = [
'<form class="ocs__form">',
' <div class="ocs__field">',
' <label for="hw-category" class="ocs__label">Assistance Category</label>',
' <input id="hw-category" type="text" class="ocs__input ocs__input--large ocs__input--gradient" placeholder="Assistance Category">',
' </div>',
' <br>',
' <div class="ocs__field">',
' <label for="hw-first-name" class="ocs__label">Volunteer First Name</label>',
' <input id="hw-first-name" type="text" class="ocs__input ocs__input--small" placeholder="Volunteer First Name">',
' </div>',
' <br>',
' <div class="ocs__field">',
' <label for="hw-email" class="ocs__label">Volunteer Email</label>',
' <input id="hw-email" type="email" class="ocs__input ocs__input--medium" placeholder="Volunteer Email">',
' </div>',
'</form>'
].join('');
`.trim();
const autostart = "true" === "true";
const editorHeight = "";
const outputHeight = "";
const storageKey = container.dataset.storageKey;
const runner = new BaseRunner(container, { storageKey });
const editor = runner.initializeEditor({
defaultCode,
editorHeight,
fallbackCode: "// Write your JavaScript code here",
codeMirrorOptions: {
lineNumbers: true,
mode: "javascript",
theme: "darcula",
indentUnit: 2,
tabSize: 4,
styleSelectedText: true
}
});
if (outputHeight) {
runner.applyScopedStyle(`#ui-output-inputs-hw-runner { min-height: ${outputHeight}; max-height: ${outputHeight}; height: ${outputHeight}; }`);
}
const uiOutput = container.querySelector('.ui-output');
const uiExecutor = new UiExecutor({
editor,
outputElement: uiOutput,
});
runner.bindEditorButtons({
resetValue: defaultCode || "// Write your JavaScript code here",
onClear: () => {
stopExecution();
},
saveFeedback: '✔',
copyFeedback: '✔'
});
// Stop execution
function stopExecution() {
uiExecutor.stop();
}
// Reset button
container.querySelector('[data-hook="reset"]').onclick = () => {
stopExecution();
};
// Stop button
container.querySelector('[data-hook="stop"]').onclick = () => {
stopExecution();
};
// Run button logic
function runCode() {
return uiExecutor.run();
}
runner.bindButton('', runCode, 'run');
// Keyboard shortcut
runner.bindShortcut(runCode);
if (autostart) {
// Defer to next tick so output container is present before execution.
setTimeout(() => {
runCode();
}, 0);
}
})();
</script>