Skip to content

Commit

Permalink
Added documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
Madman10K committed Nov 4, 2023
1 parent 11dd276 commit 10db17c
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 37 deletions.
67 changes: 61 additions & 6 deletions deck-new.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,11 @@ window.bUsingPinyinConversion = false;

window.writer = null;

// Convert each word in a sentence to pinyin
/**
* Convert each word in a sentence to pinyin
* @param {string} string - The input non-pinyin string
* @returns {string} - The output pinyin-ified string
*/
function pinyinify(string) {
// Ugly af but it's the only way we can do it ig
const pinyin =
Expand Down Expand Up @@ -63,6 +67,14 @@ function pinyinify(string) {
return arr.join(" ");
}

/**
* Constructs a preview card HTML element for a phrase or card
* @param { number } index - The index into "it"
* @param { Object? } it - The struct that whose data will be used to construct the preview card
* @param { HTMLElement } owner - Parent HTML element
* @returns { Object } - Reference to the current modified object. Could be "it", a card from local storage(if "it" is
* a phrase reference, or it's null) or a new card.
*/
function constructPreviewCardGeneric(index, it, owner)
{
let root = addElement("div", "", `character-preview-${index}`, "card centered", "", owner);
Expand Down Expand Up @@ -129,6 +141,18 @@ function constructPreviewCardGeneric(index, it, owner)
return lit;
}

/**
* Constructs an input element
* @param {HTMLElement} container - The parent HTML element to attach to
* @param { string } id - ID for the input element
* @param { string } classT - Class for the input element
* @param { string } type - Type attribute of the input element
* @param { string } ariaLabel - Aria label attribute of the input element
* @param { string } name - Name attribute of the input element
* @param { string } previewID - ID of the text field in the preview card that corresponds to the owning edit card
* @param { function } callback - Callback function when the data is changed
* @returns { HTMLElement } - The resulting input element
*/
function constructInputElement(container, id, classT, type, ariaLabel, name, previewID, callback)
{
let input = addElement("input", "", id, classT, "", container);
Expand Down Expand Up @@ -171,11 +195,27 @@ function constructPhraseEditCardPreview(it) {
return lit;
}

/**
* Checks if a given character variant exists
* @param { string } character - The character in question
* @param { string } postfix - Variant postfix, like "-jp" or "-ko" for Japanese and Korean respectively
* @returns {Promise<undefined|Object>} - JSON data about the given character
*/
async function testVariantExists(character, postfix)
{
return await charDataLoader(character + postfix, null, null);
}

/**
* Constructs the character variant select box
* @param { HTMLElement } container - The parent HTML element
* @param { string } id - ID for the select box
* @param { string } classT - Class for the select box
* @param { string } ariaLabel - Aria label attribute for the select box
* @param { string } name - Name attribute for the select box
* @param { Object } it - Card object this corresponds to. Used to change the character's value in the change callback
* @returns {Promise<void>}
*/
async function constructCharacterVariantSelect(container, id, classT, ariaLabel, name, it)
{
let select = addElement("select", "", id, classT, "", container);
Expand All @@ -194,6 +234,14 @@ async function constructCharacterVariantSelect(container, id, classT, ariaLabel,
});
}

/**
* Reconstructs the definition list for a given card or phrase
* @param { HTMLElement } previewList - The HTML element that contains the definitions list inside its corresponding preview card
* @param { HTMLElement } editList - The HTML element that contains the definitions list inside its corresponding edit card
* @param { string[] } definitions - The list of definition strings
* @param { boolean } bReadOnly - Whether the definition list is read only, i.e. when editing a phrase and a character
* from it has a corresponding card that is already in the deck
*/
function reconstructDefinitionList(previewList, editList, definitions, bReadOnly)
{
if (previewList === null || editList === null)
Expand Down Expand Up @@ -224,6 +272,13 @@ function reconstructDefinitionList(previewList, editList, definitions, bReadOnly
}
}

/**
* Constructs an edit card
* @param { string|number } index - Index into the array that holds "it"
* @param { Object } it - Object whose data will be used to construct an edit card
* @param { HTMLElement } root - The root element, to which the edit card should be attached to
* @param { boolean } bPhrase - Whether you're editing a phrase
*/
function constructEditCard(index, it, root, bPhrase)
{
let lit = it;
Expand Down Expand Up @@ -321,7 +376,7 @@ function constructEditCard(index, it, root, bPhrase)
for (let i in lit.phrase)
{
constructPreviewCardGeneric(i, lit, phrasePreviewContainer);
constructEditCard(i, lit, cardEditSection);
constructEditCard(i, lit, cardEditSection, false);
}
});
}
Expand Down Expand Up @@ -379,7 +434,7 @@ function constructListElements()

if (it["character"])
{
constructPreviewCardGeneric(0, it, cardEditSection, false);
constructPreviewCardGeneric(0, it, cardEditSection);
constructEditCard(0, it, cardEditSection, true);
for (let i = 0; i < cardEditSection.childNodes.length; i++)
cardEditSection.insertBefore(cardEditSection.childNodes[i], cardEditSection.firstChild);
Expand All @@ -391,7 +446,7 @@ function constructListElements()
constructEditCard("phrase", it, cardEditSection, true);
for (let i in it["phrase"])
{
constructPreviewCardGeneric(i, it, phrasePreviewSectionContainer, true)
constructPreviewCardGeneric(i, it, phrasePreviewSectionContainer)
constructEditCard(i, it, cardEditSection, false);
}
}
Expand All @@ -405,8 +460,8 @@ function constructListElements()
}
else
{
let lit = constructPreviewCardGeneric(0, null, cardEditSection, false);
constructEditCard("0", lit, cardEditSection, false);
let lit = constructPreviewCardGeneric(0, null, cardEditSection);
constructEditCard(0, lit, cardEditSection, false);

// Reverse children of $("card-edit-section") because we display the preview before the edit widget
for (let i = 0; i < cardEditSection.childNodes.length; i++)
Expand Down
39 changes: 31 additions & 8 deletions deck.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ window.HOUR_UNIX = 36000000;
window.MINUTE_UNIX = 60000;
window.SECOND_UNIX = 1000;

/**
* The export button callback. Stringifies the current data and exports it.
*/
function updateExportButton()
{
const dt = window.localStorageData.cards;
const dt = window.localStorageData;
const data = {
cards: dt.cards,
phrases: dt.phrases
}

let file = new Blob([JSON.stringify(dt)], { type: "application/json;charset=utf-8" });
let file = new Blob([JSON.stringify(data)], { type: "application/json;charset=utf-8" });

const link = document.createElement("a");
link.href = URL.createObjectURL(file);
Expand All @@ -17,14 +24,21 @@ function updateExportButton()
URL.revokeObjectURL(link.href);
}

/**
* The import deck button callback. Imports a deck from a file.
* @param {string} f - The element in question
*/
function importDeck(f) {
let bExecuted = confirm(lc.import_deck_confirm_text);
if (bExecuted)
{
const reader = new FileReader();
reader.addEventListener("load", function(){
reader.addEventListener("load", (e) => {
let dt = window.localStorageData;
dt.cards.push.apply(dt.cards, JSON.parse(this.result.toString()));
let data = JSON.parse(e.target.result.toString());

dt.cards.push.apply(dt.cards, data.cards);
dt.phrases.push.apply(dt.phrases, data.phrases);

saveToLocalStorage(dt);
document.location.reload();
Expand All @@ -45,6 +59,9 @@ function clearDeck() {
}
}

/**
* Sets data about the current user. Deals with calculating most of the statistics and showcasing them
*/
function setProfileCardData()
{
$("total-sessions-field").textContent += window.localStorageData.sessions;
Expand Down Expand Up @@ -107,10 +124,13 @@ function setProfileCardData()
averageKnowledge.textContent = `${lc.average_knowledge_level}: ${knowledge.toFixed(2)}/${window.MAX_KNOWLEDGE_LEVEL}`;
}

// it - struct
// index - used to create UUIDs. For normal cards, its offset by the number of phrases
// constainer - container element
// localIndex - non-unique index
/**
* Constructs a card HTML element
* @param { Object } it - Struct for the card data
* @param { int } index - Used to create UUIDs. For normal cards, it's offset by the number of phrases
* @param { HTMLElement } container - HTML element to attach to
* @param { int } localIndex - non-unique index
*/
function constructCard(it, index, container, localIndex)
{
// Add parent div
Expand Down Expand Up @@ -189,6 +209,9 @@ function constructCard(it, index, container, localIndex)
}
}

/**
* Main function for the deck page
*/
function deckmain()
{
setProfileCardData();
Expand Down
54 changes: 45 additions & 9 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
// ------------------- CONSTANT BLOCK EDIT IF RUNNING ON A CUSTOM SYSTEM ------------------
window.MAX_KNOWLEDGE_LEVEL = 4;
window.MAX_POINTS_ON_CHARACTER = 0.25;
window.ADD_POINTS_ON_ERROR_3_4 = 0.1875; // 3/4 of 0.25
window.ADD_POINTS_ON_ERROR_1_2 = 0.125; // 1/2 or 2/4 of 0.25
window.ADD_POINTS_ON_ERROR_1_3 = 0.0625; // 1/3 of 0.25
window.ADD_POINTS_ON_ERROR_3_4 = 0.1875; // 3/4 of 0.25
window.ADD_POINTS_ON_ERROR_1_2 = 0.125; // 1/2 or 2/4 of 0.25
window.ADD_POINTS_ON_ERROR_1_3 = 0.0625; // 1/3 of 0.25

window.CARD_WRITER_SIZE = 100;
window.CARD_WRITER_STROKE_ANIMATION_SPEED = 1.25;
Expand All @@ -14,20 +14,31 @@ window.CARD_DEFAULT_PREVIEW_NAME = "Preview Name"

window.WRITER_PADDING = 5;
window.WRITER_RADICAL_COLOUR = "#c87e74";
window.WRITER_SLEEP_AFTER_COMPLETE = 1200; // In ms
window.WRITER_SLEEP_AFTER_COMPLETE = 1200; // In ms

window.WRITER_SHOW_HINT_ON_ERRORS = 3;
window.WRITER_SHOW_HINT_ON_ERRORS_LVL_3 = 1;
// ---------------------------------- CONSTANT BLOCK END ----------------------------------

window.localStorageData = null;

// Troll jQuery developers
/**
* Troll jQuery developers. Returns the element with the given id
* @param {string} x - ID of the element
* @returns {HTMLElement} - The element in question
*/
function $(x)
{
return document.getElementById(x);
}

/**
* Given an element, an event and a function to execute, tracks the given event and executes the provided callback
* function when the animation or transition on the given element has finished playing
* @param { HTMLElement } element - Element on which to track the event
* @param { string } event - Event type, like "click"
* @param { function } f - Function to run after animation
*/
function runEventAfterAnimation(element, event, f)
{
element.bWaitForAnimation = false;
Expand All @@ -47,6 +58,11 @@ function runEventAfterAnimation(element, event, f)
element.addEventListener("transitionend", func);
}

/**
* Adds a text node to an element
* @param { HTMLElement } container - Parent element of the text node
* @param { string } text - The text that the node contains
*/
function addTextNode(container, text)
{
container.appendChild(document.createTextNode(text));
Expand All @@ -58,18 +74,31 @@ async function charDataLoader(character, _, __)
let response = await fetch(`https://cdn.jsdelivr.net/gh/MadLadSquad/hanzi-writer-data-youyin/data/${character}.json`)
if (response.status !== 200)
{
console.error(`Bad response from the character database, this is mainly caused by missing characters. Response code: ${response.status}`);
console.warn(`Bad response from the character database, this is mainly caused by missing characters. Response code: ${response.status}`);
return;
}
return await response.json();
}

function saveToLocalStorage(string)
/**
* Saves an object to the "youyinCardData" entry in the browser's local storage
* @param { Object } obj - The object in question
*/
function saveToLocalStorage(obj)
{
window.localStorage.setItem("youyinCardData", JSON.stringify(string));
window.localStorage.setItem("youyinCardData", JSON.stringify(obj));
}

// Returns an element, creates an element with the given parameters and appends it
/**
* Utility function to create an HTML element in a single line
* @param { string } elType - Type of the new element
* @param { string } content - Text content of the new element
* @param { string } id - ID of the new element
* @param { string } classType - Class of the new element
* @param { string } data - Data that will be stored as the value of the "arbitrary-data" attribute
* @param { HTMLElement } parentEl - Element to become the parent of the new element
* @returns { HTMLElement } - The element that was created
*/
function addElement(elType, content, id, classType, data, parentEl)
{
let el = document.createElement(elType);
Expand Down Expand Up @@ -113,6 +142,7 @@ function fisherYates(array)
}
}

// Some legacy users may be lacking variants as part of their character card objects, so this function fixes this
function fixLegacyCharacterVariants()
{
for (let i in window.localStorageData.cards)
Expand All @@ -126,6 +156,12 @@ function fixLegacyCharacterVariants()
}
}

/**
* Redirects the user when selecting a new language from the language select box
* @param { HTMLElement } selectWidget - The select box widget
* @param { string } localStorageLang - Current language
* @param { string|null } previous - Previous language
*/
function redirectWithLanguage(selectWidget, localStorageLang, previous)
{
let url = location.href.split("/");
Expand Down
Loading

0 comments on commit 10db17c

Please sign in to comment.