feat(demo): Open permalink button and restore params from URL (#311)

pull/312/head
Jonah Lawrence 2 months ago committed by GitHub
parent d0db5c8262
commit 2df85256ab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -49,7 +49,7 @@
<form class="parameters three-columns lines">
<!-- Lines are added in JavaScript -->
</form>
<button class="add-line btn" onclick="return preview.addLine();">+ Add line</button>
<button class="add-line btn" onclick="return preview.addLines(1);">+ Add line</button>
<h2>Options</h2>
<form class="parameters two-columns options">
@ -131,6 +131,8 @@
</span>
<input type="button" class="btn" value="Reset" onclick="preview.reset();">
<button type="button" class="copy-button btn tooltip" onclick="clipboard.copyPermalink(this);" onmouseout="tooltip.reset(this);" disabled>Copy Permalink</button>
</form>
</div>
@ -152,7 +154,7 @@
<code></code>
</div>
<button class="copy-button btn tooltip" onclick="clipboard.copy(this);" onmouseout="tooltip.reset(this);" disabled>
<button class="copy-button btn tooltip" onclick="clipboard.copyCode(this);" onmouseout="tooltip.reset(this);" disabled>
Copy To Clipboard
</button>
</div>
@ -163,7 +165,7 @@
<code></code>
</div>
<button class="copy-button btn tooltip" onclick="clipboard.copy(this);" onmouseout="tooltip.reset(this);" disabled>
<button class="copy-button btn tooltip" onclick="clipboard.copyCode(this);" onmouseout="tooltip.reset(this);" disabled>
Copy To Clipboard
</button>
</div>

@ -1,5 +1,5 @@
const preview = {
// default values
// default values for Readme Typing SVG parameters
defaults: {
font: "monospace",
weight: "400",
@ -18,6 +18,12 @@ const preview = {
random: "false",
separator: ";",
},
// input field initial values that differ from the defaults
overrides: {
font: "Fira Code",
pause: "1000",
width: "435",
},
// dummy text for default line values
dummyText: [
"The five boxing wizards jump quickly",
@ -30,11 +36,11 @@ const preview = {
],
/**
* Update the preview image and markdown
* Get the current parameters from the form
* @returns {object} The current parameters
*/
update() {
const copyButtons = document.querySelectorAll(".copy-button");
// get parameter values from all .param elements
getParams() {
// get all parameters from the .param fields
const params = Array.from(document.querySelectorAll(".param:not([data-index])")).reduce((acc, next) => {
// copy accumulator into local object
let obj = acc;
@ -72,14 +78,20 @@ const preview = {
}
}
params.lines = mergeLines(lineInputs, params.separator);
// function to URI encode string but keep semicolons as ';' and spaces as '+'
const encode = (str) => {
return encodeURIComponent(str).replace(/%3B/g, ";").replace(/%20/g, "+");
};
return params;
},
/**
* Update the preview image and markdown
*/
update() {
const copyButtons = document.querySelectorAll(".copy-button");
// get parameter values
const params = this.getParams();
// convert parameters to query string
const query = Object.keys(params)
.filter((key) => params[key] !== this.defaults[key]) // skip if default value
.map((key) => encode(key) + "=" + encode(params[key])) // encode keys and values
.map((key) => this.customEncode(key) + "=" + this.customEncode(params[key])) // encode keys and values
.join("&"); // join lines with '&' delimiter
// generate links and markdown
const imageURL = `${window.location.origin}?${query}`;
@ -102,13 +114,26 @@ const preview = {
htmlElement.innerText = html;
// disable copy button if no lines are filled in
copyButtons.forEach((el) => (el.disabled = !params.lines.length));
// update URL to match parameters
this.openPermalink();
},
/**
* Add a new line to the input fields
* Encode a string for use in a URL but keep semicolons as ';' and spaces as '+'
* @param {string} str The string to encode
* @returns The encoded string
*/
customEncode(str) {
return encodeURIComponent(str).replace(/%3B/g, ";").replace(/%20/g, "+");
},
/**
* Add new line input fields
* @param {number} count The number of lines to add
* @returns {false} Always returns false to prevent form submission
*/
addLine() {
addLines(count) {
for (let i = 0; i < count; i++) {
const parent = document.querySelector(".lines");
const index = parent.querySelectorAll("input").length + 1;
// label
@ -140,6 +165,7 @@ const preview = {
// disable button if only 1
parent.querySelector(".delete-line.btn").disabled = index == 1;
}
// update and exit
this.update();
@ -147,7 +173,7 @@ const preview = {
},
/**
* Remove a line from the input fields
* Remove a line input field
* @param {number} index The index of the line to remove
* @returns {false} Always returns false to prevent form submission
*/
@ -192,19 +218,14 @@ const preview = {
},
/**
* Reset all input fields to default values
* Reset all input fields to their initial values
* @returns {false} Always returns false to prevent form submission
*/
reset() {
const overrides = {
font: "Fira Code",
pause: "1000",
width: "435",
};
// reset all inputs
const inputs = document.querySelectorAll(".param");
inputs.forEach((input) => {
let value = overrides[input.name] || this.defaults[input.name];
let value = this.overrides[input.name] || this.defaults[input.name];
if (value) {
if (["color", "background"].includes(input.name)) {
input.jscolor.fromString(value);
@ -214,20 +235,89 @@ const preview = {
}
});
},
/**
* Get the current parameters in a permalink format
* @returns {string} The permalink URL
*/
getPermalink() {
// get parameters from form
const params = this.getParams();
// convert parameters to query string
const defaultInputs = { ...this.defaults, ...this.overrides };
defaultInputs.lines = this.dummyText[0];
const query = Object.keys(params)
.filter((key) => params[key] !== defaultInputs[key]) // skip if default value
.map((key) => this.customEncode(key) + "=" + this.customEncode(params[key])) // encode keys and values
.join("&"); // join lines with '&' delimiter
// return permalink
return `${window.location.origin}${window.location.pathname}` + (query ? `?${query}` : "");
},
/**
* Save the current parameters to the URL
*/
openPermalink() {
window.history.replaceState({}, "", this.getPermalink());
},
/**
* Restore the last saved parameters from the URL
*/
restore() {
// get parameters from URL
const urlParams = new URLSearchParams(window.location.search);
const params = { ...this.defaults, ...this.overrides, ...Object.fromEntries(urlParams) };
// set all parameters
const inputs = document.querySelectorAll(".param");
inputs.forEach((input) => {
let value = params[input.name];
if (value) {
if (["color", "background"].includes(input.name)) {
input.jscolor.fromString(value);
} else {
input.value = value;
}
}
});
// add lines
const lines = params.lines || this.dummyText[0];
const lineInputs = lines.split(params.separator);
this.addLines(lineInputs.length);
lineInputs.forEach((line, index) => {
document.querySelector(`#line-${index + 1}`).value = line;
});
},
};
const clipboard = {
/**
* Copy the text from a code block to the clipboard
* @param {HTMLElement} el The element that was clicked
* Copy text to the clipboard
* @param {HTMLElement} btn The element that was clicked
* @param {String} text The text to copy
*/
copy(el) {
const textToCopy = el.parentElement.querySelector("code").innerText;
navigator.clipboard.writeText(textToCopy).then(() => {
copy(btn, text) {
navigator.clipboard.writeText(text).then(() => {
// set tooltip text
el.title = "Copied!";
btn.title = "Copied!";
});
},
/**
* Copy the text from a code block to the clipboard
* @param {HTMLElement} btn The element that was clicked
*/
copyCode(btn) {
this.copy(btn, btn.parentElement.querySelector("code").innerText);
},
/**
* Copy the permalink to the clipboard
* @param {HTMLElement} btn The element that was clicked
*/
copyPermalink(btn) {
this.copy(btn, preview.getPermalink());
},
};
const tooltip = {
@ -255,9 +345,8 @@ document.querySelector(".show-border input").addEventListener("change", function
window.addEventListener(
"load",
() => {
// add first line
preview.addLine();
preview.update();
preview.restore(); // restore parameters
preview.update(); // update preview
},
false
);

Loading…
Cancel
Save