I’m working on a ‘get code’ function which I have writing to but will use Clipboard API after we figure this out! I want to update the string value of a const based on whether a checkbox is checked. If checked the CSS vars are prepended with the namespace "typecsset-", e.g., –_typecsset-text-typeface, if not, the namespace const is blank, e.g., –_text-typeface.
Search "$HELP" for the spot I’m stuck. Thanks! 🙏
// main element (target) for typesetting output
const typesetOutput = document.getElementById("typesetting");
// font size input and sub label
const textSizeRemInput = document.getElementById("text-size-rem");
textSizeRemInput.addEventListener("input", updateTextSize);
const textSizePxOutput = document.getElementById("text-size-px");
function updateTextSize(event) {
typesetOutput.style.setProperty(
"--_text-size",
`${textSizeRemInput.value}rem`
);
textSizePxOutput.textContent = parseFloat(textSizeRemInput.value * 16).toFixed(1);
}
// font leading input and sub label
const textLeadingInput = document.getElementById("text-leading");
textLeadingInput.addEventListener("input", updateLeading);
const textLeadingPxOutput = document.getElementById("text-leading-px");
function updateLeading(event) {
typesetOutput.style.setProperty(
"--_text-leading",
`${textLeadingInput.value}`
);
textLeadingPxOutput.textContent = parseFloat(textLeadingInput.value * 16).toFixed(1);
}
// text measure input
const textMeasureRemInput = document.getElementById("text-measure-rem");
textMeasureRemInput.addEventListener("input", updateMeasure);
// draggable label (parent) container
const textMeasureResize = document.getElementById("text-measure-resize");
// update measure CSS prop
function updateMeasure(event) {
document.documentElement.style.setProperty(
"--_text-measure",
`${textMeasureRemInput.value}rem`
);
// update width of draggable label (parent) container
textMeasureResize.style.width = `${textMeasureRemInput.value}rem`;
}
// watch for width changes to draggable label (parent) container
let observeMeasure = new ResizeObserver(function (mutations) {
// convert to rem
const sizeInRem =
mutations[0].contentRect.width /
parseInt(getComputedStyle(document.documentElement).fontSize);
// update measure CSS prop
document.documentElement.style.setProperty('--_text-measure', sizeInRem + 'rem');
// update input value
textMeasureRemInput.value = sizeInRem.toFixed(1);
});
let draggable = textMeasureResize;
observeMeasure.observe(draggable);
// theme switcher
const invertButton = document.getElementById("invert");
invertButton.addEventListener("click", invertTheme);
const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
// CSS does the rest
function invertTheme(event) {
if (prefersDarkScheme.matches) {
document.body.classList.toggle("light-theme");
} else {
document.body.classList.toggle("dark-theme");
}
};
// $HELP get code function
const preElementRepo = document.getElementById("code");
const copyButton = document.getElementById("copy");
//const textFontOutput = textFontInput.value;
const textFontOutput = "'Cormorant Garamond'";
const textSizeOutput = textSizeRemInput.value;
const textLeadingOutput = textLeadingInput.value;
const textMeasureOutput = textMeasureRemInput.value;
const nameSpacedCheckbox = document.getElementById("namespaced");
const nameSpace = 'typecsset-';
copyButton.addEventListener("click", getCode);
function getCode(event) {
// $HELP
let nameSpace = '';
if (nameSpacedCheckbox.checked) {
nameSpace = 'typecsset-';
}
preElementRepo.textContent = `:where(html) {\n /* Get your head tag font emebed codes at https://fonts.google.com/specimen/Name+Name */\n --_${nameSpace}text-typeface: var(--${nameSpace}text-typeface, ${textFontOutput});\n --_${nameSpace}text-size: var(--${nameSpace}text-size, ${textSizeOutput}rem);\n --_${nameSpace}text-leading: var(--${nameSpace}text-leading, ${textLeadingOutput});\n --_${nameSpace}text-measure: var(--${nameSpace}text-measure, ${textMeasureOutput}rem); \n\nbody {\n font-family: var(--_${nameSpace}text-typeface);\n font-size: var(--_${nameSpace}text-size);\n line-height: var(--_${nameSpace}text-leading);\n inline-size: var(--_${nameSpace}text-measure);\n}`;
alert(`CSS copied to the clipboard. Paste away!`);
}
* {
/* layout debugger */
outline: deeppink dotted 0.5px;
}
:where(html),
:root {
--_text-size: var(--text-size, 1rem);
--_text-leading: var(--text-leading, 1.5);
--_text-measure: var(--text-measure, 80rem);
--_color-light: var(--color-light, #fff);
--_color-dark: var(--color-dark, #000);
--_color-neutral: var(--color-neutral, gray);
--_space: var(--space, 1rem);
font-family: sans-serif;
}
body {
background-color: var(--color-light);
color: var(--_color-dark);
}
main {
font-size: var(--_text-size);
line-height: var(--_text-leading);
inline-size: var(--_text-measure);
}
button,
input {
font: inherit;
}
@media (prefers-color-scheme: dark) {
body {
background-color: var(--_color-dark);
color: var(--_color-light);
}
#theme::after {
content: '#FFF on #000';
}
}
@media (prefers-color-scheme: light) {
#theme::after {
content: '#000 on #FFF';
}
}
body.dark-theme {
background-color: var(--_color-dark);
color: var(--_color-light);
}
body.dark-theme #theme::after {
content: '#FFF on #000';
}
body.light-theme {
background-color: var(--_color-light);
color: var(--_color-dark);
}
body.light-theme #theme::after {
content: '#000 on #FFF';
}
/* layout ptimitives */
.center {
box-sizing: content-box;
margin-inline: auto;
max-inline-size: var(--_text-measure);
padding-inline-start: 3rem;
padding-inline-end: 3rem;
}
.cluster {
display: flex;
flex-wrap: wrap;
gap: var(--_space);
justify-content: flex-start;
align-items: center;
}
.vertical-rhythm {
display: flex;
flex-direction: column;
justify-content: flex-start;
}
.vertical-rhythm * {
margin-block: 0;
}
.vertical-rhythm *+* {
margin-block-start: calc(var(--_space)/3.14)
}
/* utils */
.resizable {
resize: inline;
overflow: scroll;
}
.justify-content\:space-between {
justify-content: space-between;
}
/* visually hidden, but not from screen readers: https://gist.github.com/Heydon/c8d46c0dd18ce96b5833b3b564e9f472 */
.hide {
clip-path: inset(100%) !important;
clip: rect(1px, 1px, 1px, 1px) !important;
height: 1px !important;
overflow: hidden !important;
position: absolute !important;
white-space: nowrap !important;
width: 1px !important;
}
<body class="center vertical-rhythm">
<nav class="cluster">
<label class="vertical-rhythm">
<h2>Size</h2>
<input id="text-size-rem" name="text-size" data-uom="rem" type="number" value="1.00" step="0.01" min="0.5" max="3.0">
<h4>rem: <span id="text-size-px">16.0</span> px</h4>
</label>
<label class="vertical-rhythm">
<h2>Leading</h2>
<input id="text-leading" name="text-leading" data-uom="" type="number" value="1.50" step="0.01" min="0.01" max="10">
<h4>Unitless: <span id="text-leading-px">24.0</span> px</h4>
</label>
<label class="vertical-rhythm">
<h2>Ground</h2>
<button id="invert">Invert</button>
<h4 id="theme"></h4>
</label>
<label class="vertical-rhythm">
<h2>Code</h2>
<button id="copy">Copy</button>
<h4>CSS<input id="namespaced" type="checkbox" checked><label for="" style="font-size: .75em;"> Namespaced</label></h4>
</label>
</nav>
<label id="text-measure-resize" class="resizable vertical-rhythm">
<h2>Measure</h2>
<input id="text-measure-rem" name="text-measure" data-uom="rem" type="number" value="80" step="0.1" min="10" max="150">
<div class="cluster justify-content:space-between">
<h4>rem</h4>
<h4>drag ↘ </h4>
</div>
</label>
<main id="typesetting">
<p>The density of texture in a written or typeset page is called it*s <em>color</em>. This has nothing to do with red or green ink; it refers only to the darkness or blackness of the letterforms in mass. Once the demands of legibilty and logical order are satisfied, <em>eveness of color</em> is the typographer's normal aim. And color depends on four things: the design of the type, the spacing between the letters, the spacing between the words, and the spacing between the lines. None is independent of the others.</p>
<p>Anything from <em>45 to 75</em> characters is widely regarded as a satisfactory length of line for a single-column page set in a serifed text face in a text size. The 66-character line (counting both letters and spaces) is widely regarded as ideal. For multiple column work, a better average is 40 to 50 characters.</p>
</main>
</body>
>Solution :
The scope of a const is the block containing the declaration. So if you use it in an if block it will not be visible outside the if. Use a let declaration outside the if, then assign the variable inside the if.
function getCode(event) {
let nameSpace = '';
// $HELP
if (nameSpacedCheckbox.checked) {
nameSpace = 'typecsset-';
}
preElementRepo.textContent = `:where(html) {\n /* Get your head tag font emebed codes at https://fonts.google.com/specimen/Name+Name */\n --_${nameSpace}text-typeface: var(--${nameSpace}text-typeface, ${textFontOutput});\n --_${nameSpace}text-size: var(--${nameSpace}text-size, ${textSizeOutput}rem);\n --_${nameSpace}text-leading: var(--${nameSpace}text-leading, ${textLeadingOutput});\n --_${nameSpace}text-measure: var(--${nameSpace}text-measure, ${textMeasureOutput}rem); \n\nbody {\n font-family: var(--_${nameSpace}text-typeface);\n font-size: var(--_${nameSpace}text-size);\n line-height: var(--_${nameSpace}text-leading);\n inline-size: var(--_${nameSpace}text-measure);\n}`;
alert(`CSS copied to the clipboard. Paste away!`);
}