320 lines
15 KiB
JavaScript
320 lines
15 KiB
JavaScript
//Variale `list` is imported from JSON with query_handler.php.
|
|
//var lists = JSON.parse(document.getElementById("lists-json").innerText);
|
|
var list_id = document.getElementById("query-list").innerText;
|
|
//Get list id from <var> tag created in query-handler.php.
|
|
var selected_list = null;
|
|
if(lists.hasOwnProperty(list_id)){
|
|
selected_list = lists[list_id];
|
|
} else {
|
|
selected_list = lists["master"];
|
|
//If the list id in the query is invalid, go back to the main list.
|
|
}
|
|
|
|
|
|
|
|
function gen_list_html(list){
|
|
//This function creates HTML from a list's JSON object by iterativel calling the gen_item_html function to convert individual items. This design paradigm facilitates the construction of nested lists or lists with sections.
|
|
var html = "";
|
|
if(!list.hasOwnProperty("type")){
|
|
list.type = "default";
|
|
}
|
|
|
|
if(!list.hasOwnProperty("subtype")){
|
|
list.subtype = "default";
|
|
}
|
|
|
|
var list_type = list.type;
|
|
|
|
if(list.hasOwnProperty("sections")){
|
|
list_type = "sectioned";
|
|
//Lists that have separate sections require special handling involving recursion.
|
|
}
|
|
|
|
switch(list_type){
|
|
case "master":
|
|
for(id in lists){
|
|
html += gen_item_html(id,type="list-id");
|
|
}
|
|
html = `<ul>${html}</ul>`;
|
|
break;
|
|
|
|
case "quotes":
|
|
html += "<hr />";
|
|
for(quote of list.list){
|
|
html += gen_item_html(quote,type="quote");
|
|
}
|
|
break;
|
|
|
|
case "key-value":
|
|
for(pair of list.list){
|
|
html += gen_item_html(pair,type="kv-pair");
|
|
}
|
|
html = (list.hasOwnProperty("ordered") && list.ordered) ? `<ol>${html}</ol>` : `<ul>${html}</ul>`;
|
|
//Create an ordered list if list has the property "ordered".
|
|
break;
|
|
|
|
|
|
case "gallery":
|
|
document.getElementById("lists").style.textAlign="center";
|
|
//Center the rows of exhibits on the page.
|
|
if(!list.hasOwnProperty("subtype")){
|
|
list.subtype="default";
|
|
}
|
|
for(exhibit of list.list){
|
|
html += gen_item_html(exhibit,type="exhibit",subtype=list.subtype);
|
|
}
|
|
break;
|
|
|
|
case "external":
|
|
//This branch will only run if someone manually enters the list name into the query; clicking an external-type list from the Master List will just open the link in a new tab.
|
|
setTimeout(function(){location.assign(list["link"])}, 600);
|
|
//If the list specified in the query has the external property, then redirect to the external link. I use setTimeout in order to allow the rest of the code to run.
|
|
list.title = `Redirecting to List of ${list.title}...`;
|
|
list.list = [];
|
|
//It takes a second to redirect, so put some filler on the page while the reader waits.
|
|
break;
|
|
|
|
case "sectioned":
|
|
if(!list.hasOwnProperty("section-level")){
|
|
list["section-level"] = 1;
|
|
//Section-level defines the heading level of the section. Top level is 1.
|
|
}
|
|
if(!list.hasOwnProperty("dropdown")){
|
|
list.dropdown = true;
|
|
//By default, sections ARE in details/summary tags.
|
|
}
|
|
for(section of list.sections){
|
|
var section_html = "";
|
|
var level = list["section-level"] + 1;
|
|
section["section-level"] = level;
|
|
//Nested secions are of lower levels.
|
|
if(!section.hasOwnProperty("type")){
|
|
section.type = list.type;
|
|
//This branch transfers the list type down from higher levels. By default, the bottom-level lists will inherit the type of the top-level object unless otherwise specified.
|
|
}
|
|
if(!section.hasOwnProperty("subtype")){
|
|
section.subtype = list.subtype;
|
|
//Sections should also inherit subtypes.
|
|
}
|
|
if(!section.hasOwnProperty("dropdown")){
|
|
section.dropdown = list.dropdown;
|
|
//Inherit dropdown-ness unless otherwise specified.
|
|
}
|
|
var description = (section.hasOwnProperty("description")) ? `<p>${section.description}</p>` : "";
|
|
//Sections can have their own descriptions.
|
|
|
|
var title = `<h${level}>${section.title}</h${level}>`;
|
|
//Wrap the section title in a header tag.
|
|
|
|
if(section.hasOwnProperty("dropdown") && section.dropdown){
|
|
//If the section is marked with the "dropdown" attribute, then nest the section's data in a details/summary tag.
|
|
section_html = `<details class="heading" open><summary>${title}</summary>${description}${gen_list_html(section)}</details>`;
|
|
} else {
|
|
section_html = `${title}${description}${gen_list_html(section)}`;
|
|
}
|
|
//Sectioned
|
|
html += `<section id="${section.title}">${section_html}</section>`;
|
|
//Assigning ids allows for the possibility of fragment linking.
|
|
}
|
|
break;
|
|
|
|
default:
|
|
for(item of list.list){
|
|
html += gen_item_html(item);
|
|
}
|
|
|
|
html = (list.hasOwnProperty("ordered") && list.ordered) ? `<ol>${html}</ol>` : `<ul>${html}</ul>`;
|
|
//Create an ordered list if list has the property "ordered".
|
|
}
|
|
|
|
return html;
|
|
|
|
}
|
|
|
|
function gen_item_html(item,type="default",subtype=null){
|
|
var item_html = "";
|
|
switch(type){
|
|
case "list-id":
|
|
if(lists[item].hasOwnProperty("hidden") && lists[item].hidden){
|
|
return "";
|
|
//Lists marked with the "hidden" attribute are in-development and should not be displayed on the Master List.
|
|
}
|
|
if(!lists[item].hasOwnProperty("title")){
|
|
lists[item].title = item;
|
|
//If a title is not set for the list, then just use its id.
|
|
}
|
|
var tooltip = "";
|
|
if(lists[item].hasOwnProperty("description")){
|
|
tooltip=lists[item]["description"];
|
|
//When hovering over a list in the directory, display its description as a tooltip.
|
|
}
|
|
var link = `href='index.php?page=lists&list=${item}' target='self_'`;
|
|
//By default, lists have internal links that change the query value to that list's title. Internal links should open in the same tab.
|
|
if(lists[id].hasOwnProperty("type") && lists[item].type=="external"){
|
|
link = `href='${lists[item]["link"]}' target='blank_'`;
|
|
//For external lists, use their link instead of an internal link. External links should open in a new tab.
|
|
}
|
|
item_html = `<li title="${tooltip}"><a ${link}>${lists[item].title}</a></li>`;
|
|
//The Master List contains a link to every other list in the JSON file.
|
|
break;
|
|
|
|
case "quote":
|
|
//Format quotes like they are formatted on Goodreads.
|
|
if(!item.hasOwnProperty("quote")){
|
|
//If the quote is blank, then things are going to get real weird. Most likely, this will be caused by a typo, so this branch is a safeguard against any resulting errors.
|
|
return "";
|
|
}
|
|
item_html = "<p>";
|
|
if(item.hasOwnProperty("title")){
|
|
item_html += `<b>${item.title}</b><br />`;
|
|
//Add a title if the quote has one (e.g. "The Litany Against Fear").
|
|
}
|
|
item_html += `“${item.quote}”<br>`;
|
|
//Add the text of the quote.
|
|
if(item.hasOwnProperty("card") && !item.hasOwnProperty("quotee")){
|
|
item.quotee="";
|
|
//If a flavor text doesn't have a quotee, don't write "Unknown".
|
|
}
|
|
|
|
item_html += ` — ${item.hasOwnProperty("quotee") ? item.quotee : "Unknown"}`;
|
|
//Add the quotee's name, or "Unknown" if one is not specified.
|
|
if(item.hasOwnProperty("source")){
|
|
if(item.hasOwnProperty("quotee") && item.quotee!=""){
|
|
item_html += ", ";
|
|
//Unless there is no quotee, separate the quotee from the source with ", "
|
|
}
|
|
item_html += item.source;
|
|
//Add the source if the quote has one.
|
|
}
|
|
|
|
if(item.hasOwnProperty("card")){
|
|
if(item.quotee!=""||item.hasOwnProperty("source")){
|
|
item_html += `, `;
|
|
//Separate quotee or source from card title with ", "
|
|
}
|
|
item_html += `<a target='_blank' href='https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=${item.multiverseid}'>${item.card}</a> (Magic: the Gathering)`;
|
|
}
|
|
item_html += "</p><hr />";
|
|
//Delimit the quotes with a horizontal rule.
|
|
break;
|
|
|
|
case "kv-pair":
|
|
console.log(item);
|
|
if(!(item.hasOwnProperty("k")&&item.hasOwnProperty("v"))||Object.keys(item).length==1){
|
|
var key = Object.keys(item)[0];
|
|
item["k"] = key;
|
|
item["v"] = item[key];
|
|
//If the item is an object containing a single key-value pair, then use that pair as the k and v for displaying.
|
|
}
|
|
if(item.hasOwnProperty("link")){
|
|
item_html = `<span class="list-key"><a href="${item.link}" target="blank_">${item["k"]}</a></span>`;
|
|
} else {
|
|
item_html = `<span class="list-key">${item["k"]}</span>`;
|
|
}
|
|
item_html += ` — ${item["v"]}`;
|
|
item_html = `<li>${item_html}</li>`;
|
|
break;
|
|
|
|
|
|
case "exhibit":
|
|
var tooltip, alt, text, img_src;
|
|
tooltip = text = img_src = "";
|
|
switch(subtype){
|
|
case "album":
|
|
tooltip = `${item.title} (${item.year}) - ${item.artist}`;
|
|
alt = tooltip;
|
|
img_src = item.cover;
|
|
text = `${item.title}<br />${item.artist}<br />${item.year}`;
|
|
break;
|
|
case "mtg-card":
|
|
if(item.hasOwnProperty("multiverseid")&&!item.hasOwnProperty("link")){
|
|
item.link = `https://gatherer.wizards.com/pages/card/Details.aspx?multiverseid=${item.multiverseid}`;
|
|
//If there's no alternate link specified, then use the multiverseid to generate the Gatherer link.
|
|
}
|
|
if(item.hasOwnProperty("multiverseid")&&!item.hasOwnProperty("image")){
|
|
img_src = `https://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=${item.multiverseid}&type=card`;
|
|
//If there's no alternate link specified, then use the multiverseid to generate the Gatherer link for the image.
|
|
} else {
|
|
img_src = item.image;
|
|
}
|
|
if(item.hasOwnProperty("name")){
|
|
alt = tooltip = item.name;
|
|
}
|
|
break;
|
|
default:
|
|
}
|
|
var image = `<img title="${tooltip}" alt="${tooltip}" src="${img_src}" class="gallery exhibit-${subtype}" />`;
|
|
//Gallery items must have an image.
|
|
if(item.hasOwnProperty("link")){
|
|
image = `<a href='${item.link}' target='blank_'>${image}</a>`;
|
|
//If there's a link associated with the exhibit, put it on the image.
|
|
}
|
|
item_html = (text=="") ? image : `${image}<br />${text}`;
|
|
//If there's no text, then there's no need for a line break.
|
|
item_html = `<div class="gallery exhibit-${subtype}">${item_html}</div>`
|
|
|
|
break;
|
|
|
|
case "sublist":
|
|
//Sublists can be any type (most likely default or key-value), so the best way to deal with them is recursion.
|
|
if(item.hasOwnProperty("dropdown") && item.dropdown){
|
|
item_html = `<li><details><summary>${item.title}</summary>${gen_list_html(item)}</details></li>`;
|
|
} else {
|
|
item_html = `<li>${item.title}${gen_list_html(item)}</li>`;
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
default:
|
|
if(["string","number"].includes(typeof item)){
|
|
item_html = `<li>${item}</li>`;
|
|
//If the element is a simple string or number, then we don't need to do any special formatting.
|
|
} else if (typeof item === "object"){
|
|
var keys = Object.keys(item);
|
|
if(keys.length == 1){
|
|
if (Array.isArray(item[keys[0]])){
|
|
//An item that is a dictionary only containing a list is probably a sublist. Format it as such, and pass it back through this switch statement.
|
|
var temp = {
|
|
"title":keys[0],
|
|
"type":"default",
|
|
"list":item[keys[0]]
|
|
};
|
|
item_html = gen_item_html(temp,"sublist");
|
|
} else {
|
|
item_html = gen_item_html(item,"kv-pair");
|
|
//A item that is dictionary with one key, whose value is not a list, is to be treated as a term-explanation type key-value pair.
|
|
}
|
|
} else {
|
|
item_html = gen_item_html(item,"sublist");
|
|
//At this point, if there is no other specification, an item that's an object is probably a sublist.
|
|
}
|
|
}
|
|
}
|
|
return item_html;
|
|
}
|
|
|
|
function str2html(md){
|
|
//This function replaces escapes commands and Markdown with their HTML equivalents.
|
|
html = md.replaceAll("\n","<br />");
|
|
return html;
|
|
}
|
|
|
|
|
|
document.getElementById("list-title").innerHTML = selected_list.title;
|
|
if(selected_list.hasOwnProperty("description")){
|
|
document.getElementById("list-description").innerHTML = selected_list.description;
|
|
} else {
|
|
document.getElementById("list-description").style.display = "none";
|
|
//If the list has no description, hide the element to remove the awkward space from the padding.
|
|
}
|
|
//Generate the article header from the list's title and description.
|
|
|
|
document.getElementById("list-container").innerHTML += str2html(gen_list_html(selected_list));
|
|
//Call the gen_list_html function to convert the list from a JSON object to sophisticated HTML.
|
|
|
|
if(list_id != "master"){
|
|
document.getElementById("lists").innerHTML += "<br /><p><a id='list-return-link' href='index.php?page=lists&list=master'>Return to Master List ↩</a></p>";
|
|
//Add a return link to the bottom of the article.
|
|
}
|