Added content JSON structure parser base, Added images, Added Glider.js, Fixed typos

Update .gitignore, content.php, and 21 more files...
This commit is contained in:
2022-04-15 20:17:28 +02:00
parent e2adc41bad
commit 01ceb1b89b
23 changed files with 1221 additions and 101 deletions

5
.gitignore vendored
View File

@@ -2,10 +2,9 @@
.idea/ .idea/
# Static resources # Static resources
resources/Azias/imgs/*.exe
resources/Azias/imgs/*.url
resources/FontAwesomePro/ resources/FontAwesomePro/
resources/GoogleFonts/ *.exe
*.url
# Other folders (Will be removed once the content system is finished !) # Other folders (Will be removed once the content system is finished !)
# /files/*/ # /files/*/

View File

@@ -11,12 +11,14 @@ include_once 'langs.php';
// This helper requires PHP 8 or newer ! // This helper requires PHP 8 or newer !
$SHOW_CONTENT_DEBUG_CARD = false; $SHOW_CONTENT_DEBUG_CARD = false;
$PRINT_CONTENT_DEBUG_INFO_TEXT_ELEMENTS = true;
$PRINT_CONTENT_DEBUG_ERROR_TEXT_ELEMENTS = true;
// Defining constants and enums. // Defining constants and enums.
abstract class ContentDisplayType { abstract class ContentDisplayType {
const NONE = 0; const NONE = 0;
const SEARCH = 1; const SEARCH = 1;
const CONTENT = 2; const CONTENT = 2;
} }
// Preparing default variables. // Preparing default variables.
@@ -130,4 +132,211 @@ function endMainCard() {
echo('</div>'); echo('</div>');
} }
function getContentItemText(array $contentNode, bool $italicOnError = true, bool $returnMissingAsEmpty = false) : string {
global $user_language, $default_language;
if(array_key_exists("key", $contentNode)) {
return localize($contentNode["key"]);
} elseif(array_key_exists($user_language, $contentNode)) {
return $contentNode[$user_language];
} elseif(array_key_exists($default_language, $contentNode)) {
return $contentNode[$default_language];
} else {
if($returnMissingAsEmpty) {
return "";
}
if($italicOnError) {
return '<i>'.localize("error.content.data.no.title").'</i>';
} else {
return localize("error.content.data.no.title");
}
}
}
function printInfoTextElement(string $text) : void {
global $PRINT_CONTENT_DEBUG_INFO_TEXT_ELEMENTS;
if($PRINT_CONTENT_DEBUG_INFO_TEXT_ELEMENTS) {
echo('<h3 class="m-0 font-size-20 text-primary font-weight-semi-bold">'.$text.'</h3>');
}
}
function printErrorTextElement(string $text) : void {
global $PRINT_CONTENT_DEBUG_ERROR_TEXT_ELEMENTS;
if($PRINT_CONTENT_DEBUG_ERROR_TEXT_ELEMENTS) {
echo('<h3 class="m-0 font-size-20 text-center text-danger font-weight-semi-bold">'.$text.'</h3>');
}
}
function createElementNode(mixed $elementNode) : void {
// Checking if we actually have a JSON object.
if(!is_array($elementNode)) {
echo('<p>Not array node !</p>');
return;
}
if(!array_key_exists("type", $elementNode)) {
echo('<p>No "type" member found in node !</p>');
return;
}
switch($elementNode["type"]) {
case "table":
//printInfoTextElement('table item type');
// Reading and processing the modifiers
$_modNoOuterPadding = false;
$_modStriped = false;
$_modHover = false;
$_modInnerBordered = false;
if(array_key_exists("modifiers", $elementNode)) {
for ($i = 0; $i < count($elementNode["modifiers"]); $i++) {
//printInfoTextElement('&gt;&gt; Modifier: '.$elementNode["modifiers"][$i]);
switch($elementNode["modifiers"][$i]) {
case "no-outer-padding":
// Removes the rounding on the external edges.
$_modNoOuterPadding = true;
break;
case "striped":
// Removes the internal padding and adds 0.01em to the top to prevent gaps from margins.
$_modStriped = true;
break;
case "hover":
// Removes the standard top margin.
$_modHover = true;
break;
case "inner-bordered":
// Removes the standard top margin.
$_modInnerBordered = true;
break;
}
}
}
// Preparing table
echo('<table class="table'.($_modNoOuterPadding?" table-no-outer-padding":"").($_modStriped?" table-striped":"").
($_modHover?" table-hover":"").($_modInnerBordered?" table-inner-bordered":"").'">');
// Creating "thead"
if(array_key_exists("head", $elementNode)) {
echo('<thead><tr>');
for ($iTableHead = 0; $iTableHead < count($elementNode["head"]); $iTableHead++) {
echo('<th>');
if(array_key_exists("parts", $elementNode["head"][$iTableHead])) {
for ($iPart = 0; $iPart < count($elementNode["head"][$iTableHead]["parts"]); $iPart++) {
createElementNode($elementNode["head"][$iTableHead]["parts"][$iPart]);
}
} else {
echo(getContentItemText($elementNode["head"][$iTableHead], false, true));
}
echo('</th>');
}
echo('</tr></thead>');
}
// Creating "tbody"
if(array_key_exists("body", $elementNode)) {
echo('<tbody>');
for ($iTableBodyRow = 0; $iTableBodyRow < count($elementNode["body"]); $iTableBodyRow++) {
echo('<tr>');
for ($iTableBodyCell = 0; $iTableBodyCell < count($elementNode["body"][$iTableBodyRow]); $iTableBodyCell++) {
$_cellColSpan = 1;
$_cellRowSpan = 1;
if(array_key_exists("colspan", $elementNode["body"][$iTableBodyRow][$iTableBodyCell])) {
$_cellColSpan = $elementNode["body"][$iTableBodyRow][$iTableBodyCell]["colspan"];
}
if(array_key_exists("rowspan", $elementNode["body"][$iTableBodyRow][$iTableBodyCell])) {
$_cellRowSpan = $elementNode["body"][$iTableBodyRow][$iTableBodyCell]["rowspan"];
}
echo('<td'.($_cellColSpan>1?' colspan="'.$_cellColSpan.'"':'').($_cellRowSpan>1?' rowspan="'.$_cellRowSpan.'"':'').'>');
if(array_key_exists("parts", $elementNode["body"][$iTableBodyRow][$iTableBodyCell])) {
for ($iPart = 0; $iPart < count($elementNode["body"][$iTableBodyRow][$iTableBodyCell]["parts"]); $iPart++) {
createElementNode($elementNode["body"][$iTableBodyRow][$iTableBodyCell]["parts"][$iPart]);
}
} else {
echo(getContentItemText($elementNode["body"][$iTableBodyRow][$iTableBodyCell], false, true));
}
echo('</td>');
}
echo('</tr>');
}
echo('</tbody>');
}
// Ending table
echo('</table>');
break;
case "collapse":
//printInfoTextElement('collapse item type');
// Preparing some stuff
$_title = '<i>'.localize("error.content.data.no.title").'</i>';
$_subtitle = '';
if(array_key_exists("title", $elementNode)) {
$_title = getContentItemText($elementNode["title"], true, true);
}
if(array_key_exists("subtitle", $elementNode)) {
$_subtitle = getContentItemText($elementNode["subtitle"], true, true);
}
//printInfoTextElement('&gt; title: "'.$_title);
//printInfoTextElement('&gt; subtitle: "'.$_subtitle);
// Reading and processing the modifiers
$_modNoRounding = false;
$_modNoContentPadding = false;
$_modNoTopMargin = false;
$_modIsClosed = false;
if(array_key_exists("modifiers", $elementNode)) {
for ($i = 0; $i < count($elementNode["modifiers"]); $i++) {
//printInfoTextElement('&gt;&gt; Modifier: '.$elementNode["modifiers"][$i]);
switch($elementNode["modifiers"][$i]) {
case "no-rounding":
// Removes the rounding on the external edges.
$_modNoRounding = true;
break;
case "no-padding-content":
// Removes the internal padding and adds 0.01em to the top to prevent gaps from margins.
$_modNoContentPadding = true;
break;
case "no-top-margin":
// Removes the standard top margin.
$_modNoTopMargin = true;
break;
case "closed":
// Close the collapse by default.
$_modIsClosed = true;
break;
}
}
}
// Starting the collapse
echo('<details class="collapse-panel w-full'.($_modNoTopMargin?"":" mt-20").'" '.($_modIsClosed?"closed":"open").'>');
echo('<summary class="collapse-header p-10 px-15 text-truncate without-arrow'.($_modNoRounding?" rounded-0":"").' border-left-0 border-right-0">');
echo('<h4 class="font-size-16 m-0 align-middle no-select"><i class="fad fa-angle-down hidden-collapse-open font-size-24"></i>');
echo('<i class="fad fa-angle-up hidden-collapse-closed font-size-24"></i>');
echo('<span class="font-weight-semi-bold align-top">&nbsp;&nbsp;'.$_title.'<span class="ml-20 text-muted">'.$_subtitle.'</span></span>');
echo('</h4></summary><div class="collapse-content'.($_modNoContentPadding?" p-0 py-01":"").($_modNoRounding?" rounded-0":"").' border-0 border-bottom">');
// Rendering sub-elements
if(array_key_exists("parts", $elementNode)) {
//printInfoTextElement('&gt; Processing sub-parts');
for ($i = 0; $i < count($elementNode["parts"]); $i++) {
createElementNode($elementNode["parts"][$i]);
}
//printInfoTextElement('&gt; Done processing sub-parts');
} else {
printErrorTextElement(localize("error.content.data.no.subpart"));
}
// Ending the collapse
echo('</div></details>');
//printInfoTextElement('end of collapse');
break;
default:
printErrorTextElement(sprintf(localize("error.content.data.part.unknown"), $elementNode["type"]));
break;
}
}
?> ?>

View File

@@ -106,8 +106,12 @@
"error.content.tags.alphanumeric": "One of the tags given in the \"tags\" URL parameter is not a valid alphanumeric string.", "error.content.tags.alphanumeric": "One of the tags given in the \"tags\" URL parameter is not a valid alphanumeric string.",
"error.content.detect.type": "The type of requested content couldn't be determined.", "error.content.detect.type": "The type of requested content couldn't be determined.",
"error.content.id.alphanumeric": "The requested resource's ID isn't valid.", "error.content.id.alphanumeric": "The requested resource's ID isn't valid.",
"error.content.data.not.exist": "The requested resource's doesn't have an associated item file.", "error.content.data.not.exist": "The requested content doesn't have an internal item file.",
"error.content.data.no.title": "No title found !", "error.content.data.no.title": "No title found !",
"error.content.data.no.tags": "No tags found !",
"error.content.data.no.parts": "No content parts were found for this content !",
"error.content.data.no.subpart": "No sub-element were found for this element !",
"error.content.data.part.unknown": "Unknown element: \"%s\" !",
"content.title.error": "Error", "content.title.error": "Error",
"content.title.content": "Content", "content.title.content": "Content",
@@ -118,6 +122,18 @@
"content.search.count.single": "result", "content.search.count.single": "result",
"content.search.count.multiple": "results", "content.search.count.multiple": "results",
"content.commons.version.current": "Current version",
"content.commons.version.previous.single": "Previous version",
"content.commons.version.previous.multiple": "Previous versions",
"content.commons.version.old.single": "Old version",
"content.commons.version.old.multiple": "Old versions",
"content.commons.cpu": "CPU Architecture",
"content.commons.cpu.x64": "x64",
"content.commons.cpu.x86": "x86",
"content.commons.lang": "Language",
"content.commons.download.single": "Download",
"content.commons.download.multiple": "Downloads",
"about.biography.title": "Who am I ?", "about.biography.title": "Who am I ?",
"about.philosophy.title": "Projects philosophy", "about.philosophy.title": "Projects philosophy",
"about.skills.title": "Skills", "about.skills.title": "Skills",
@@ -235,8 +251,12 @@
"error.content.tags.alphanumeric": "Un des tags donné dans le paramètre d'URL \"tags\" n'est pas une chaîne de texte alphanumérique valide.", "error.content.tags.alphanumeric": "Un des tags donné dans le paramètre d'URL \"tags\" n'est pas une chaîne de texte alphanumérique valide.",
"error.content.detect.type": "Le type de contenu désiré n'as pas pu être détecté.", "error.content.detect.type": "Le type de contenu désiré n'as pas pu être détecté.",
"error.content.id.alphanumeric": "L'ID de la ressource demandée n'est pas valide.", "error.content.id.alphanumeric": "L'ID de la ressource demandée n'est pas valide.",
"error.content.data.not.exist": "La ressource demandée n'a pas de fichier de données associé.", "error.content.data.not.exist": "Le contenu demandée n'a pas de fichier de données interne associé.",
"error.content.data.no.title": "Aucun titre trouvé !", "error.content.data.no.title": "Aucun titre trouvé !",
"error.content.data.no.tags": "Aucun tag trouvé !",
"error.content.data.no.parts": "Aucun élément à présenter n'a été trouvé !",
"error.content.data.no.subpart": "Aucun sous-élément n'a été trouvé pour cet élément !",
"error.content.data.part.unknown": "Élément inconnu: \"%s\" !",
"content.title.error": "Erreur de contenu", "content.title.error": "Erreur de contenu",
"content.title.content": "Content", "content.title.content": "Content",
@@ -247,6 +267,18 @@
"content.search.count.single": "résultat", "content.search.count.single": "résultat",
"content.search.count.multiple": "résultats", "content.search.count.multiple": "résultats",
"content.commons.version.current": "Version actuelle",
"content.commons.version.previous.single": "Version précédente",
"content.commons.version.previous.multiple": "Versions précédentes",
"content.commons.version.old.single": "Ancienne version",
"content.commons.version.old.multiple": "Anciennes versions",
"content.commons.cpu": "Architecture de CPU",
"content.commons.cpu.x64": "x64",
"content.commons.cpu.x86": "x86",
"content.commons.lang": "Langue",
"content.commons.download.single": "Téléchargement",
"content.commons.download.multiple": "Téléchargements",
"about.biography.title": "Qui suis-je ?", "about.biography.title": "Qui suis-je ?",
"about.philosophy.title": "Philosophie des projets", "about.philosophy.title": "Philosophie des projets",
"about.skills.title": "Compétences", "about.skills.title": "Compétences",

View File

@@ -1,47 +1,47 @@
[ [
{
"id": "test01",
"title": {
"en": "Test article",
"fr": "Article de test"
},
"preamble": {
"en": "This is a test article, please ignore it",
"fr": "Ceci est un article de test, veuillez l'ignorer."
},
"image": "/resources/Azias/imgs/angry-alchool-pussy.png",
"tags": [
"test", "programming", "purebasic"
]
},
{
"id": "test02",
"title": {
"en": "Test article #2",
"fr": "Article de test #2"
},
"preamble": {
"en": "This is a test article, please ignore it",
"fr": "Ceci est un article de test, veuillez l'ignorer."
},
"image": "test.jpg",
"tags": [
"test", "programming", "docker"
]
},
{ {
"id": "lscom-cli", "id": "lscom-cli",
"title": { "title": {
"en": "PB-ListComPort - CLI COM port enumerator", "en": "PB-ListComPort",
"fr": "PB-ListComPort - Enumérateur de port COM pour invité de commande" "fr": "PB-ListComPort"
}, },
"preamble": { "preamble": {
"en": "A simple tool that can list COM ports with their name, friendly name and device name easily and cleanly.<br>This tool is intended to replace the tedious task of having to use the <code>mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.", "en": "A simple CLI tool that can list COM ports with their name, friendly name and device name easily and cleanly.<br>This tool is intended to replace the tedious task of having to use the <code>mode</code> command, and the <i>Device Manager</i> to find a newly plugged-in device that provides a COM port.",
"fr": "..." "fr": "..."
}, },
"image": "/resources/Azias/imgs/lscom-v2-text-01-bkgd-cli.png", "image": "/resources/Azias/imgs/lscom-v2-text-01-bkgd-cli.png",
"tags": [ "tags": [
"application", "lscom", "purebasic", "windows" "application", "lscom", "purebasic", "windows"
] ]
},
{
"id": "youtube-auto-archiver",
"title": {
"en": "Youtube-Auto-Archiver",
"fr": "Youtube-Auto-Archiver"
},
"preamble": {
"en": "...",
"fr": "..."
},
"image": "/resources/Azias/imgs/placeholder.jpg",
"tags": [
"docker", "web", "python"
]
},
{
"id": "excel-worksheet-password-remover",
"title": {
"en": "Excel-Worksheet-Password-Remover",
"fr": "Excel-Worksheet-Password-Remover"
},
"preamble": {
"en": "Small web page from which you can easily remove a password from an Excel worksheet without uploading any file, directly in your browser.<br>It works by leaving the task of editing the XML files on an Excel document to your browser instead to keep everything local.",
"fr": "Petite application web qui permet de facilement retirer le mot de passe d'une feuille de calcul Excel depuis votre navigateur web sans avoir à uploader le fichier sur internet.<br>Cette application laisse votre navigateur modifier les fichiers XML du fichier Excel afin de tout garder en local."
},
"image": "/resources/Azias/imgs/excel-password-remover.png",
"tags": [
"tool", "web"
]
} }
] ]

View File

@@ -8,11 +8,8 @@ include_once 'content.php';
// Checking if an error occurred while loading data and parsing the URL. // Checking if an error occurred while loading data and parsing the URL.
$content_error_code = 200; $content_error_code = 200;
if($content_has_error) { if($content_has_error) {
if(is_null($requested_tags)) { // TODO: Add condition for the lack of data for an item.
// Failed to parse URL and detect a default category. if(is_null($filtered_content_index_data)) {
header("HTTP/1.1 400 Bad Request");
$content_error_code = 400;
} elseif(is_null($filtered_content_index_data)) {
// Failed to get a display type or to extract types. // Failed to get a display type or to extract types.
header("HTTP/1.1 400 Bad Request"); header("HTTP/1.1 400 Bad Request");
$content_error_code = 400; $content_error_code = 400;
@@ -35,6 +32,7 @@ if($content_has_error) {
<meta property="og:image" content="<?php echo($host_uri); ?>/resources/Azias/logos/rect1750-9-7-3-shaded.png"/> <meta property="og:image" content="<?php echo($host_uri); ?>/resources/Azias/logos/rect1750-9-7-3-shaded.png"/>
<meta property="og:image:type" content="image/png"/> <meta property="og:image:type" content="image/png"/>
<meta property="og:description" content="???"/> <meta property="og:description" content="???"/>
<link href="/resources/GliderJs/1.7.6/glider.min.css" rel="stylesheet" />
</head> </head>
<body class="with-custom-webkit-scrollbars with-custom-css-scrollbars dark-mode" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true"> <body class="with-custom-webkit-scrollbars with-custom-css-scrollbars dark-mode" data-dm-shortcut-enabled="true" data-sidebar-shortcut-enabled="true">
<?php include 'body-root.php'; ?> <?php include 'body-root.php'; ?>
@@ -56,7 +54,15 @@ if($content_has_error) {
} elseif($requested_content_display_type == ContentDisplayType::SEARCH) { } elseif($requested_content_display_type == ContentDisplayType::SEARCH) {
echo(localize("content.title.content").'<span class="mx-10">❱</span>'.localize("content.title.search")); echo(localize("content.title.content").'<span class="mx-10">❱</span>'.localize("content.title.search"));
} elseif($requested_content_display_type == ContentDisplayType::CONTENT) { } elseif($requested_content_display_type == ContentDisplayType::CONTENT) {
echo(localize("content.title.content").'<span class="mx-10">❱</span>$TODO'); $_nav_title_text = '<i>' . localize("error.content.data.no.title") . '</i>';
if (array_key_exists("page", $requested_item_data["title"])) {
if (array_key_exists($user_language, $requested_item_data["title"]["page"])) {
$_nav_title_text = $requested_item_data["title"]["page"][$user_language];
} elseif (array_key_exists($default_language, $requested_item_data["title"]["page"])) {
$_nav_title_text = $requested_item_data["title"]["page"][$user_language];
}
}
echo(localize("content.title.content").'<span class="mx-10">❱</span>'.$_nav_title_text);
} }
?> ?>
</h2> </h2>
@@ -74,6 +80,9 @@ if($content_has_error) {
endMainCard(); endMainCard();
if($SHOW_CONTENT_DEBUG_CARD) { if($SHOW_CONTENT_DEBUG_CARD) {
// ################
// Debugging card
// ################
echo('<div class="card p-0 mx-0"> echo('<div class="card p-0 mx-0">
<div class="px-card py-10 border-bottom px-20"> <div class="px-card py-10 border-bottom px-20">
<div class="container-fluid"> <div class="container-fluid">
@@ -108,12 +117,15 @@ if($content_has_error) {
// Checking if an error occurred. // Checking if an error occurred.
if($content_error_code != 200) { if($content_error_code != 200) {
// #############
// Error card
// #############
startMainCard("fad fa-exclamation-triangle", localize('error.content.title.generic'), ""); startMainCard("fad fa-exclamation-triangle", localize('error.content.title.generic'), "");
echo('<div class="py-20 bg-light-lm rounded-bottom px-0 bg-very-dark title-bkgd">'); echo('<div class="py-20 bg-light-lm rounded-bottom px-0 bg-very-dark title-bkgd">');
echo('<h3 class="m-0 font-size-20 text-center font-weight-semi-bold">'.$content_error_message.'</h3>'); echo('<h3 class="m-0 font-size-20 text-center font-weight-semi-bold">'.$content_error_message.'</h3>');
echo('</div>'); echo('</div>');
echo('<div class="px-card py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">'. echo('<div class="px-card py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">'.
'<p class="font-size-12 m-0">'. '<p class="font-size-12 m-0 text-super-muted">'.
'Card footer here.'. 'Card footer here.'.
'</p></div>'); '</p></div>');
endMainCard(); endMainCard();
@@ -122,6 +134,10 @@ if($content_has_error) {
// Printing the containers // Printing the containers
if($requested_content_display_type == ContentDisplayType::SEARCH) { if($requested_content_display_type == ContentDisplayType::SEARCH) {
// #############
// Search page
// #############
// Creating the start of the card, only a "</div>" should be required afterward. // Creating the start of the card, only a "</div>" should be required afterward.
startMainCard( startMainCard(
"fad fa-file-search", "fad fa-file-search",
@@ -154,7 +170,8 @@ if($content_has_error) {
echo('<div class="content-tag-container">'); echo('<div class="content-tag-container">');
echo('<i class="fad fa-tags"></i>'); echo('<i class="fad fa-tags"></i>');
for($j = 0; $j < count($filtered_content_index_data[$i]["tags"]); $j++) { for($j = 0; $j < count($filtered_content_index_data[$i]["tags"]); $j++) {
echo('<a href="#" class="content-tag">#'.$filtered_content_index_data[$i]["tags"][$j].'</a>'); echo('<a href="'.l10n_url_abs("/content/?tags=".$filtered_content_index_data[$i]["tags"][$j]).'" class="content-tag">#');
echo($filtered_content_index_data[$i]["tags"][$j].'</a>');
} }
echo('</div>'); echo('</div>');
echo('</div>'); echo('</div>');
@@ -163,38 +180,88 @@ if($content_has_error) {
} }
echo('</div>'); echo('</div>');
echo('<div class="px-card py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">'. echo('<div class="px-card py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">'.
'<p class="font-size-12 m-0">'. '<p class="font-size-12 m-0 text-super-muted">'.
'Card footer here.'. 'Card footer here.'.
'</p></div>'); '</p></div>');
endMainCard(); endMainCard();
} elseif($requested_content_display_type == ContentDisplayType::CONTENT) { } elseif($requested_content_display_type == ContentDisplayType::CONTENT) {
// ##############
// Content page
// ##############
// Preparing soma variables for the icon, title and subtitle.
$_title_icon = "fad fa-question"; $_title_icon = "fad fa-question";
$_title_text = '<i>' . localize("error.content.data.no.title") . '</i>'; $_title_text_main = '<i>'.localize("error.content.data.no.title").'</i>';
$_title_text_sub = NULL;
// Attempting to read the card's icon, title and subtitle.
if (array_key_exists("title", $requested_item_data)) { if (array_key_exists("title", $requested_item_data)) {
if (array_key_exists("icon", $requested_item_data["title"])) { if (array_key_exists("icon", $requested_item_data["title"])) {
$_title_icon = $requested_item_data["title"]["icon"]; $_title_icon = $requested_item_data["title"]["icon"];
} }
if (array_key_exists("card", $requested_item_data["title"])) {
if (array_key_exists($user_language, $requested_item_data["title"])) { if (array_key_exists("main", $requested_item_data["title"]["card"])) {
$_title_text = $requested_item_data["title"][$user_language]; $_title_text_main = getContentItemText($requested_item_data["title"]["card"]["main"], true);
} elseif (array_key_exists($default_language, $requested_item_data["title"])) { }
$_title_text = $requested_item_data["title"][$user_language]; if (array_key_exists("sub", $requested_item_data["title"]["card"])) {
$_title_text_sub = getContentItemText($requested_item_data["title"]["card"]["sub"], true);
}
} }
} }
startMainCard($_title_icon, $_title_text, ""); // Opening the card.
startMainCard($_title_icon, $_title_text_main, (is_null($_title_text_sub) ? "" : $_title_text_sub));
// Opening the content container.
echo('<div class="py-20 bg-light-lm rounded-bottom px-0 bg-very-dark title-bkgd">'); echo('<div class="py-20 bg-light-lm rounded-bottom px-0 bg-very-dark title-bkgd">');
echo('<div class="content m-0 mx-20">');
echo('<p class="my-0">Text will go here...</p>'); // Adding elements defined in the JSON file.
echo('</div>'); if(array_key_exists("parts", $requested_item_data)) {
for ($i = 0; $i < count($requested_item_data["parts"]); $i++) {
createElementNode($requested_item_data["parts"][$i]);
}
} else {
echo('<h3 class="m-0 font-size-20 text-center text-danger font-weight-semi-bold">');
echo(localize("error.content.data.no.parts").'</h3>');
}
// New elements test zone. - START
/*echo('<div class="content m-0 mx-20">');
echo('<p class="my-0">Text will go here...</p>');
echo('</div>'); echo('</div>');
echo('<div class="px-card py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">' . echo('<div class="sidebar-divider m-20 mx-0"></div>');/**/
'<p class="font-size-12 m-0">' . //echo('<hr class="subtle">');
'Card footer here.' .
'</p></div>'); /*<td>
<a href="#" class="d-flex justify-content-center align-items-center">
<p class="m-0 p-0 text-monospace">lscom_fra_x86.exe</p>
<button class="btn btn-sm btn-success font-size-18 px-5 ml-15" type="button">
<i class="fad fa-save"></i>
</button>
</a>
</td>*/
// New elements test zone. - END
// Closing the content container.
echo('</div>');
// Printing the tags' section at the end of the card
echo('<div class="px-20 py-10 bg-light-lm bg-dark-dm rounded-bottom border-top">');
echo('<div class="content-tag-container"><i class="fad fa-tags"></i>');
if(array_key_exists("tags", $requested_item_data)) {
for($i = 0; $i < count($requested_item_data["tags"]); $i++) {
echo('<a href="'.l10n_url_abs("/content/?tags=".$requested_item_data["tags"][$i]).'" class="content-tag">#');
echo($requested_item_data["tags"][$i].'</a>');
}
} else {
echo('<i>'.localize("error.content.data.no.tags").'</i>');
}
echo('</div></div>');
// Closing the card.
endMainCard(); endMainCard();
} }
@@ -205,7 +272,8 @@ if($content_has_error) {
</div> </div>
<?php include 'footer.php'; ?> <?php include 'footer.php'; ?>
</div> </div>
<script src="/resources/HalfMoon/1.1.1/js/halfmoon.min.js"></script> <script src="/resources/HalfMoon/1.1.1/js/halfmoon.min.js"></script>
<script src="/resources/GliderJs/1.7.6/glider-compat.min.js"></script>
<script src="/resources/Azias/js/nibblepoker.lu.js"></script> <script src="/resources/Azias/js/nibblepoker.lu.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,13 +1,100 @@
{ {
"title": { "title": {
"icon": "fad fa-terminal", "icon": "fad fa-terminal",
"en": "PB-ListComPort - CLI COM port enumerator", "page": {
"fr": "PB-ListComPort - Enumérateur de port COM pour invité de commande" "en": "PB-ListComPort",
"fr": "PB-ListComPort"
},
"card": {
"main": {
"en": "PB-ListComPort",
"fr": "PB-ListComPort"
},
"sub": {
"en": "CLI COM port enumerator",
"fr": "Enumérateur de port COM pour invité de commande"
}
}
}, },
"tags": [ "parts": [
"programming", "lscom" {
"type": "collapse",
"title": {
"key": "content.commons.version.current"
},
"subtitle": {
"en": "v2.1.0",
"fr": "v2.1.0"
},
"modifiers": [
"no-rounding",
"no-padding-content"
],
"parts": [
{
"type": "table",
"modifiers": [
"striped",
"inner-bordered"
],
"head": [
{
"key": "content.commons.cpu"
},
{
"key": "content.commons.lang"
},
{
"key": "content.commons.download.single"
}
],
"body": [
[
{
"key": "content.commons.cpu.x64",
"rowspan": 2
},
{
"key": "lang.english"
},
{
"en": "URL here"
}
],
[
{
"key": "lang.french"
},
{
"en": "URL here"
}
],
[
{
"key": "content.commons.cpu.x86",
"rowspan": 2
},
{
"key": "lang.english"
},
{
"en": "URL here"
}
],
[
{
"key": "lang.french"
},
{
"en": "URL here"
}
]
]
}
]
}
], ],
"toggles": { "tags": [
"downloads": true "application", "lscom", "purebasic", "windows"
} ]
} }

View File

@@ -4,11 +4,6 @@
src: url("/resources/Quantum/Quantum.otf") format('opentype'); src: url("/resources/Quantum/Quantum.otf") format('opentype');
} }
/* Preventing images from being saved with the right-click */
img.no-save {
pointer-events: none;
}
/* Background for the main container and its cards */ /* Background for the main container and its cards */
div#body-overlay { div#body-overlay {
position: absolute; position: absolute;
@@ -28,13 +23,11 @@ div#body-overlay {
background-image: url("/resources/Azias/imgs/3px-tile-0.1.png"); background-image: url("/resources/Azias/imgs/3px-tile-0.1.png");
} }
/* Helpers */ /* Utilities, helpers & misc */
img.no-save {
pointer-events: none;
}
.no-select { .no-select {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none; user-select: none;
} }
.quantum { .quantum {
@@ -59,7 +52,6 @@ div#body-overlay {
font-size: 3.0rem!important; font-size: 3.0rem!important;
} }
.text-super-muted { .text-super-muted {
/*color: #6E6E6E;/**/
color: #89898A; color: #89898A;
} }
.square-corners { .square-corners {
@@ -68,6 +60,10 @@ div#body-overlay {
.stretch-align-items { .stretch-align-items {
align-items: stretch; align-items: stretch;
} }
.py-01 {
padding-top: 0.01rem!important;
padding-bottom: 0.01rem!important;
}
/* Unique rules */ /* Unique rules */
#copyright-text { #copyright-text {
@@ -101,7 +97,6 @@ div#body-overlay {
filter: invert(100%); filter: invert(100%);
image-rendering: pixelated; image-rendering: pixelated;
} }
hr, hr.dark-mde, hr.subtle { hr, hr.dark-mde, hr.subtle {
background-color: rgba(0, 0, 0, 0) !important; background-color: rgba(0, 0, 0, 0) !important;
background: rgb(93,95,97); background: rgb(93,95,97);
@@ -111,7 +106,8 @@ hr, hr.dark-mde, hr.subtle {
margin-bottom: 5px; margin-bottom: 5px;
} }
/* Content search */ /* Content */
/* Content > Search */
@media (max-width: 992px) { @media (max-width: 992px) {
:root { :root {
--content-search-image-size: 96px; --content-search-image-size: 96px;
@@ -161,6 +157,7 @@ div.content-tag-container a:not(:first-child) {
margin-left: 10px; margin-left: 10px;
} }
/* Gradient used on home page's applications card */
@media (min-width: 993px) { @media (min-width: 993px) {
.l-lab-web { .l-lab-web {
background: linear-gradient(90deg, rgba(101,144,134,0.3) 0%, rgba(101,144,134,0.2) 1.5px, rgba(101,144,134,0.0) 7px); background: linear-gradient(90deg, rgba(101,144,134,0.3) 0%, rgba(101,144,134,0.2) 1.5px, rgba(101,144,134,0.0) 7px);
@@ -176,7 +173,7 @@ div.content-tag-container a:not(:first-child) {
} }
} }
/* Custom dynamic sizing */ /* Custom dynamic sizing for main containers in primary ".content-wrapper" */
.w-lg-p90 { .w-lg-p90 {
width: 95% !important; width: 95% !important;
} }
@@ -192,26 +189,16 @@ div.content-tag-container a:not(:first-child) {
} }
/* Fixes */ /* Fixes */
/* TODO: Fix it when it is closed */ /* No idea where this is used */
div.last-inner-collapse-border-fix { div.last-inner-collapse-border-fix {
/* TODO: Fix it when it is closed */
border: var(--collapse-content-border-width) solid var(--dm-collapse-content-border-color) !important; border: var(--collapse-content-border-width) solid var(--dm-collapse-content-border-color) !important;
border-top: 0 !important; border-top: 0 !important;
border-bottom-left-radius: var(--collapse-content-border-radius) !important; border-bottom-left-radius: var(--collapse-content-border-radius) !important;
border-bottom-right-radius: var(--collapse-content-border-radius) !important; border-bottom-right-radius: var(--collapse-content-border-radius) !important;
} }
/* Fix for ".content-wrapper" on mobile which can be too large due to the main title */
/* Trash */ .content-wrapper {
/*.lang-icon { max-width: 100vw;
height: var(--base-line-height); }
max-height: var(--base-line-height);
height: var(--base-font-size);
max-height: var(--base-font-size);
}*/
/*.page-wrapper.with-transitions.with-sidebar .content-wrapper {
transition: none;
}/**/
/*div#body-overlay.error {
background-image: url("/resources/Azias/imgs/psychedelic.png");
opacity: 0.075;
}/**/

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -0,0 +1,5 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -0,0 +1,11 @@
"document"in self&&("classList"in document.createElement("_")&&(!document.createElementNS||"classList"in document.createElementNS("http://www.w3.org/2000/svg","g"))||!function(b){if("Element"in b){b=b.Element.prototype;var d=Object,g=String.prototype.trim||function(){return this.replace(/^\s+|\s+$/g,"")},a=Array.prototype.indexOf||function(l){for(var f=0,a=this.length;a>f;f++)if(f in this&&this[f]===l)return f;return-1},c=function(a,f){this.name=a;this.code=DOMException[a];this.message=f},h=function(l,
f){if(""===f)throw new c("SYNTAX_ERR","The token must not be empty.");if(/\s/.test(f))throw new c("INVALID_CHARACTER_ERR","The token must not contain space characters.");return a.call(l,f)},k=function(a){var f=g.call(a.getAttribute("class")||"");f=f?f.split(/\s+/):[];for(var b=0,h=f.length;h>b;b++)this.push(f[b]);this._updateClassName=function(){a.setAttribute("class",this.toString())}},e=k.prototype=[],m=function(){return new k(this)};if(c.prototype=Error.prototype,e.item=function(a){return this[a]||
null},e.contains=function(a){return~h(this,a+"")},e.add=function(){var a=arguments,f=0,b=a.length,c=!1;do{var e=a[f]+"";~h(this,e)||(this.push(e),c=!0)}while(++f<b);c&&this._updateClassName()},e.remove=function(){var a,b=arguments,c=0,e=b.length,k=!1;do{var d=b[c]+"";for(a=h(this,d);~a;)this.splice(a,1),k=!0,a=h(this,d)}while(++c<e);k&&this._updateClassName()},e.toggle=function(a,b){var h=this.contains(a),c=h?!0!==b&&"remove":!1!==b&&"add";return c&&this[c](a),!0===b||!1===b?b:!h},e.replace=function(a,
b){var c=h(a+"");~c&&(this.splice(c,1,b),this._updateClassName())},e.toString=function(){return this.join(" ")},d.defineProperty){e={get:m,enumerable:!0,configurable:!0};try{d.defineProperty(b,"classList",e)}catch(l){void 0!==l.number&&-2146823252!==l.number||(e.enumerable=!1,d.defineProperty(b,"classList",e))}}else d.prototype.__defineGetter__&&b.__defineGetter__("classList",m)}}(self),function(){var b=document.createElement("_");if(b.classList.add("c1","c2"),!b.classList.contains("c2")){var d=function(a){var b=
DOMTokenList.prototype[a];DOMTokenList.prototype[a]=function(a){var c,h=arguments.length;for(c=0;h>c;c++)a=arguments[c],b.call(this,a)}};d("add");d("remove")}if(b.classList.toggle("c3",!1),b.classList.contains("c3")){var g=DOMTokenList.prototype.toggle;DOMTokenList.prototype.toggle=function(a,b){return 1 in arguments&&!this.contains(a)==!b?b:g.call(this,a)}}"replace"in document.createElement("_").classList||(DOMTokenList.prototype.replace=function(a,b){var c=this.toString().split(" "),d=c.indexOf(a+
"");~d&&(c=c.slice(d),this.remove.apply(this,c),this.add(b),this.add.apply(this,c.slice(1)))});b=null}());
(function(){if("undefined"!==typeof window)try{var b=new window.CustomEvent("test",{cancelable:!0});b.preventDefault();if(!0!==b.defaultPrevented)throw Error("Could not prevent default");}catch(d){b=function(b,a){a=a||{bubbles:!1,cancelable:!1,detail:void 0};var c=document.createEvent("CustomEvent");c.initCustomEvent(b,a.bubbles,a.cancelable,a.detail);var d=c.preventDefault;c.preventDefault=function(){d.call(this);try{Object.defineProperty(this,"defaultPrevented",{get:function(){return!0}})}catch(k){this.defaultPrevented=
!0}};return c},b.prototype=window.Event.prototype,window.CustomEvent=b}})();
Object.assign||Object.defineProperty(Object,"assign",{enumerable:!1,configurable:!0,writable:!0,value:function(b){if(void 0===b||null===b)throw new TypeError("Cannot convert first argument to object");for(var d=Object(b),g=1;g<arguments.length;g++){var a=arguments[g];if(void 0!==a&&null!==a){a=Object(a);for(var c=Object.keys(Object(a)),h=0,k=c.length;h<k;h++){var e=c[h],m=Object.getOwnPropertyDescriptor(a,e);void 0!==m&&m.enumerable&&(d[e]=a[e])}}}return d}});
(function(){for(var b=0,d=["ms","moz","webkit","o"],g=0;g<d.length&&!window.requestAnimationFrame;++g)window.requestAnimationFrame=window[d[g]+"RequestAnimationFrame"],window.cancelAnimationFrame=window[d[g]+"CancelAnimationFrame"]||window[d[g]+"CancelRequestAnimationFrame"];window.requestAnimationFrame||(window.requestAnimationFrame=function(a,c){var d=(new Date).getTime(),g=Math.max(0,16-(d-b)),e=window.setTimeout(function(){a(d+g)},g);b=d+g;return e});window.cancelAnimationFrame||(window.cancelAnimationFrame=
function(a){clearTimeout(a)})})();

View File

@@ -0,0 +1,129 @@
.glider-contain {
width: 100%;
margin: 0 auto;
position: relative;
}
.glider {
margin: 0 auto;
position: relative;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
-ms-overflow-style: none;
transform: translateZ(0);
}
.glider-track {
transform: translateZ(0);
width: 100%;
margin: 0;
padding: 0;
display: flex;
z-index: 1;
}
.glider.draggable {
user-select: none;
cursor: -webkit-grab;
cursor: grab;
}
.glider.draggable .glider-slide img {
user-select: none;
pointer-events: none;
}
.glider.drag {
cursor: -webkit-grabbing;
cursor: grabbing;
}
.glider-slide {
user-select: none;
justify-content: center;
align-content: center;
width: 100%;
}
.glider-slide img {
max-width: 100%;
}
.glider::-webkit-scrollbar {
opacity: 0;
height: 0;
}
.glider-prev,.glider-next {
user-select: none;
position: absolute;
outline: none;
background: none;
padding: 0;
z-index: 2;
font-size: 40px;
text-decoration: none;
left: -23px;
border: 0;
top: 30%;
cursor: pointer;
color: #666;
opacity: 1;
line-height: 1;
transition: opacity .5s cubic-bezier(.17,.67,.83,.67),
color .5s cubic-bezier(.17,.67,.83,.67);
}
.glider-prev:hover,
.glider-next:hover,
.glider-prev:focus,
.glider-next:focus {
color: #a89cc8;
}
.glider-next {
right: -23px;
left: auto;
}
.glider-next.disabled,
.glider-prev.disabled {
opacity: .25;
color: #666;
cursor: default;
}
.glider-slide {
min-width: 150px;
}
.glider-hide {
opacity: 0;
}
.glider-dots {
user-select: none;
display: flex;
flex-wrap: wrap;
justify-content: center;
margin: 0 auto;
padding: 0;
}
.glider-dot {
border: 0;
padding: 0;
user-select: none;
outline: none;
display: block;
cursor: pointer;
color: #ccc;
border-radius: 999px;
background: #ccc;
width: 12px;
height: 12px;
margin: 7px;
}
.glider-dot:hover,
.glider-dot:focus,
.glider-dot.active {
background: #a89cc8;
}
@media(max-width: 36em){
.glider::-webkit-scrollbar {
opacity: 1;
-webkit-appearance: none;
width: 7px;
height: 3px;
}
.glider::-webkit-scrollbar-thumb {
opacity: 1;
border-radius: 99px;
background-color: rgba(156, 156, 156, 0.25);
box-shadow: 0 0 1px rgba(255,255,255,.25);
}
}

View File

@@ -0,0 +1,576 @@
/* @preserve
_____ __ _ __ _
/ ___// /(_)___/ /___ ____ (_)___
/ (_ // // // _ // -_)/ __/_ / /(_-<
\___//_//_/ \_,_/ \__//_/ (_)__/ //___/
|___/
Version: 1.7.4
Author: Nick Piscitelli (pickykneee)
Website: https://nickpiscitelli.com
Documentation: http://nickpiscitelli.github.io/Glider.js
License: MIT License
Release Date: October 25th, 2018
*/
/* global define */
(function (factory) {
typeof define === 'function' && define.amd
? define(factory)
: typeof exports === 'object'
? (module.exports = factory())
: factory()
})(function () {
('use strict') // eslint-disable-line no-unused-expressions
/* globals window:true */
var _window = typeof window !== 'undefined' ? window : this
var Glider = (_window.Glider = function (element, settings) {
var _ = this
if (element._glider) return element._glider
_.ele = element
_.ele.classList.add('glider')
// expose glider object to its DOM element
_.ele._glider = _
// merge user setting with defaults
_.opt = Object.assign(
{},
{
slidesToScroll: 1,
slidesToShow: 1,
resizeLock: true,
duration: 0.5,
// easeInQuad
easing: function (x, t, b, c, d) {
return c * (t /= d) * t + b
}
},
settings
)
// set defaults
_.animate_id = _.page = _.slide = _.scrollLeft = 0
_.arrows = {}
// preserve original options to
// extend breakpoint settings
_._opt = _.opt
if (_.opt.skipTrack) {
// first and only child is the track
_.track = _.ele.children[0]
} else {
// create track and wrap slides
_.track = document.createElement('div')
_.ele.appendChild(_.track)
while (_.ele.children.length !== 1) {
_.track.appendChild(_.ele.children[0])
}
}
_.track.classList.add('glider-track')
// start glider
_.init()
// set events
_.resize = _.init.bind(_, true)
_.event(_.ele, 'add', {
scroll: _.updateControls.bind(_)
})
_.event(_window, 'add', {
resize: _.resize
})
})
var gliderPrototype = Glider.prototype
gliderPrototype.init = function (refresh, paging) {
var _ = this
var width = 0
var height = 0
_.slides = _.track.children;
[].forEach.call(_.slides, function (_, i) {
_.classList.add('glider-slide')
_.setAttribute('data-gslide', i)
})
_.containerWidth = _.ele.clientWidth
var breakpointChanged = _.settingsBreakpoint()
if (!paging) paging = breakpointChanged
if (
_.opt.slidesToShow === 'auto' ||
typeof _.opt._autoSlide !== 'undefined'
) {
var slideCount = _.containerWidth / _.opt.itemWidth
_.opt._autoSlide = _.opt.slidesToShow = _.opt.exactWidth
? slideCount
: Math.floor(slideCount)
}
if (_.opt.slidesToScroll === 'auto') {
_.opt.slidesToScroll = Math.floor(_.opt.slidesToShow)
}
_.itemWidth = _.opt.exactWidth
? _.opt.itemWidth
: _.containerWidth / _.opt.slidesToShow;
// set slide dimensions
[].forEach.call(_.slides, function (__) {
__.style.height = 'auto'
__.style.width = _.itemWidth + 'px'
width += _.itemWidth
height = Math.max(__.offsetHeight, height)
})
_.track.style.width = width + 'px'
_.trackWidth = width
_.isDrag = false
_.preventClick = false
_.opt.resizeLock && _.scrollTo(_.slide * _.itemWidth, 0)
if (breakpointChanged || paging) {
_.bindArrows()
_.buildDots()
_.bindDrag()
}
_.updateControls()
_.emit(refresh ? 'refresh' : 'loaded')
}
gliderPrototype.bindDrag = function () {
var _ = this
_.mouse = _.mouse || _.handleMouse.bind(_)
var mouseup = function () {
_.mouseDown = undefined
_.ele.classList.remove('drag')
if (_.isDrag) {
_.preventClick = true
}
_.isDrag = false
}
var events = {
mouseup: mouseup,
mouseleave: mouseup,
mousedown: function (e) {
e.preventDefault()
e.stopPropagation()
_.mouseDown = e.clientX
_.ele.classList.add('drag')
},
mousemove: _.mouse,
click: function (e) {
if (_.preventClick) {
e.preventDefault()
e.stopPropagation()
}
_.preventClick = false
}
}
_.ele.classList.toggle('draggable', _.opt.draggable === true)
_.event(_.ele, 'remove', events)
if (_.opt.draggable) _.event(_.ele, 'add', events)
}
gliderPrototype.buildDots = function () {
var _ = this
if (!_.opt.dots) {
if (_.dots) _.dots.innerHTML = ''
return
}
if (typeof _.opt.dots === 'string') {
_.dots = document.querySelector(_.opt.dots)
} else _.dots = _.opt.dots
if (!_.dots) return
_.dots.innerHTML = ''
_.dots.classList.add('glider-dots')
for (var i = 0; i < Math.ceil(_.slides.length / _.opt.slidesToShow); ++i) {
var dot = document.createElement('button')
dot.dataset.index = i
dot.setAttribute('aria-label', 'Page ' + (i + 1))
dot.className = 'glider-dot ' + (i ? '' : 'active')
_.event(dot, 'add', {
click: _.scrollItem.bind(_, i, true)
})
_.dots.appendChild(dot)
}
}
gliderPrototype.bindArrows = function () {
var _ = this
if (!_.opt.arrows) {
Object.keys(_.arrows).forEach(function (direction) {
var element = _.arrows[direction]
_.event(element, 'remove', { click: element._func })
})
return
}
['prev', 'next'].forEach(function (direction) {
var arrow = _.opt.arrows[direction]
if (arrow) {
if (typeof arrow === 'string') arrow = document.querySelector(arrow)
if (arrow) {
arrow._func = arrow._func || _.scrollItem.bind(_, direction)
_.event(arrow, 'remove', {
click: arrow._func
})
_.event(arrow, 'add', {
click: arrow._func
})
_.arrows[direction] = arrow
}
}
})
}
gliderPrototype.updateControls = function (event) {
var _ = this
if (event && !_.opt.scrollPropagate) {
event.stopPropagation()
}
var disableArrows = _.containerWidth >= _.trackWidth
if (!_.opt.rewind) {
if (_.arrows.prev) {
_.arrows.prev.classList.toggle(
'disabled',
_.ele.scrollLeft <= 0 || disableArrows
)
_.arrows.prev.classList.contains('disabled')
? _.arrows.prev.setAttribute('aria-disabled', true)
: _.arrows.prev.setAttribute('aria-disabled', false)
}
if (_.arrows.next) {
_.arrows.next.classList.toggle(
'disabled',
Math.ceil(_.scrollLeft + _.containerWidth) >=
Math.floor(_.trackWidth) || disableArrows
)
_.arrows.next.classList.contains('disabled')
? _.arrows.next.setAttribute('aria-disabled', true)
: _.arrows.next.setAttribute('aria-disabled', false)
}
}
_.slide = Math.round(_.scrollLeft / _.itemWidth)
_.page = Math.round(_.scrollLeft / _.containerWidth)
var middle = _.slide + Math.floor(Math.floor(_.opt.slidesToShow) / 2)
var extraMiddle = Math.floor(_.opt.slidesToShow) % 2 ? 0 : middle + 1
if (Math.floor(_.opt.slidesToShow) === 1) {
extraMiddle = 0
}
// the last page may be less than one half of a normal page width so
// the page is rounded down. when at the end, force the page to turn
if (_.scrollLeft + _.containerWidth >= Math.floor(_.trackWidth)) {
_.page = _.dots ? _.dots.children.length - 1 : 0
}
[].forEach.call(_.slides, function (slide, index) {
var slideClasses = slide.classList
var wasVisible = slideClasses.contains('visible')
var start = _.scrollLeft
var end = _.scrollLeft + _.containerWidth
var itemStart = _.itemWidth * index
var itemEnd = itemStart + _.itemWidth;
[].forEach.call(slideClasses, function (className) {
/^left|right/.test(className) && slideClasses.remove(className)
})
slideClasses.toggle('active', _.slide === index)
if (middle === index || (extraMiddle && extraMiddle === index)) {
slideClasses.add('center')
} else {
slideClasses.remove('center')
slideClasses.add(
[
index < middle ? 'left' : 'right',
Math.abs(index - (index < middle ? middle : extraMiddle || middle))
].join('-')
)
}
var isVisible =
Math.ceil(itemStart) >= Math.floor(start) &&
Math.floor(itemEnd) <= Math.ceil(end)
slideClasses.toggle('visible', isVisible)
if (isVisible !== wasVisible) {
_.emit('slide-' + (isVisible ? 'visible' : 'hidden'), {
slide: index
})
}
})
if (_.dots) {
[].forEach.call(_.dots.children, function (dot, index) {
dot.classList.toggle('active', _.page === index)
})
}
if (event && _.opt.scrollLock) {
clearTimeout(_.scrollLock)
_.scrollLock = setTimeout(function () {
clearTimeout(_.scrollLock)
// dont attempt to scroll less than a pixel fraction - causes looping
if (Math.abs(_.ele.scrollLeft / _.itemWidth - _.slide) > 0.02) {
if (!_.mouseDown) {
// Only scroll if not at the end (#94)
if (_.trackWidth > _.containerWidth + _.ele.scrollLeft) {
_.scrollItem(_.getCurrentSlide())
}
}
}
}, _.opt.scrollLockDelay || 250)
}
}
gliderPrototype.getCurrentSlide = function () {
var _ = this
return _.round(_.ele.scrollLeft / _.itemWidth)
}
gliderPrototype.scrollItem = function (slide, dot, e) {
if (e) e.preventDefault()
var _ = this
var originalSlide = slide
++_.animate_id
if (dot === true) {
slide = slide * _.containerWidth
slide = Math.round(slide / _.itemWidth) * _.itemWidth
} else {
if (typeof slide === 'string') {
var backwards = slide === 'prev'
// use precise location if fractional slides are on
if (_.opt.slidesToScroll % 1 || _.opt.slidesToShow % 1) {
slide = _.getCurrentSlide()
} else {
slide = _.slide
}
if (backwards) slide -= _.opt.slidesToScroll
else slide += _.opt.slidesToScroll
if (_.opt.rewind) {
var scrollLeft = _.ele.scrollLeft
slide =
backwards && !scrollLeft
? _.slides.length
: !backwards &&
scrollLeft + _.containerWidth >= Math.floor(_.trackWidth)
? 0
: slide
}
}
slide = Math.max(Math.min(slide, _.slides.length), 0)
_.slide = slide
slide = _.itemWidth * slide
}
_.scrollTo(
slide,
_.opt.duration * Math.abs(_.ele.scrollLeft - slide),
function () {
_.updateControls()
_.emit('animated', {
value: originalSlide,
type:
typeof originalSlide === 'string' ? 'arrow' : dot ? 'dot' : 'slide'
})
}
)
return false
}
gliderPrototype.settingsBreakpoint = function () {
var _ = this
var resp = _._opt.responsive
if (resp) {
// Sort the breakpoints in mobile first order
resp.sort(function (a, b) {
return b.breakpoint - a.breakpoint
})
for (var i = 0; i < resp.length; ++i) {
var size = resp[i]
if (_window.innerWidth >= size.breakpoint) {
if (_.breakpoint !== size.breakpoint) {
_.opt = Object.assign({}, _._opt, size.settings)
_.breakpoint = size.breakpoint
return true
}
return false
}
}
}
// set back to defaults in case they were overriden
var breakpointChanged = _.breakpoint !== 0
_.opt = Object.assign({}, _._opt)
_.breakpoint = 0
return breakpointChanged
}
gliderPrototype.scrollTo = function (scrollTarget, scrollDuration, callback) {
var _ = this
var start = new Date().getTime()
var animateIndex = _.animate_id
var animate = function () {
var now = new Date().getTime() - start
_.scrollLeft =
_.scrollLeft +
(scrollTarget - _.scrollLeft) *
_.opt.easing(0, now, 0, 1, scrollDuration)
_.ele.scrollLeft = _.scrollLeft
if (now < scrollDuration && animateIndex === _.animate_id) {
_window.requestAnimationFrame(animate)
} else {
_.ele.scrollLeft = _.scrollLeft = scrollTarget
callback && callback.call(_)
}
}
_window.requestAnimationFrame(animate)
}
gliderPrototype.removeItem = function (index) {
var _ = this
if (_.slides.length) {
_.track.removeChild(_.slides[index])
_.refresh(true)
_.emit('remove')
}
}
gliderPrototype.addItem = function (ele) {
var _ = this
_.track.appendChild(ele)
_.refresh(true)
_.emit('add')
}
gliderPrototype.handleMouse = function (e) {
var _ = this
if (_.mouseDown) {
_.isDrag = true
_.scrollLeft += (_.mouseDown - e.clientX) * (_.opt.dragVelocity || 3.3)
_.mouseDown = e.clientX
_.ele.scrollLeft = _.scrollLeft
}
}
// used to round to the nearest 0.XX fraction
gliderPrototype.round = function (double) {
var _ = this
var step = _.opt.slidesToScroll % 1 || 1
var inv = 1.0 / step
return Math.round(double * inv) / inv
}
gliderPrototype.refresh = function (paging) {
var _ = this
_.init(true, paging)
}
gliderPrototype.setOption = function (opt, global) {
var _ = this
if (_.breakpoint && !global) {
_._opt.responsive.forEach(function (v) {
if (v.breakpoint === _.breakpoint) {
v.settings = Object.assign({}, v.settings, opt)
}
})
} else {
_._opt = Object.assign({}, _._opt, opt)
}
_.breakpoint = 0
_.settingsBreakpoint()
}
gliderPrototype.destroy = function () {
var _ = this
var replace = _.ele.cloneNode(true)
var clear = function (ele) {
ele.removeAttribute('style');
[].forEach.call(ele.classList, function (className) {
/^glider/.test(className) && ele.classList.remove(className)
})
}
// remove track
replace.children[0].outerHTML = replace.children[0].innerHTML
clear(replace);
[].forEach.call(replace.getElementsByTagName('*'), clear)
_.ele.parentNode.replaceChild(replace, _.ele)
_.event(_window, 'remove', {
resize: _.resize
})
_.emit('destroy')
}
gliderPrototype.emit = function (name, arg) {
var _ = this
var e = new _window.CustomEvent('glider-' + name, {
bubbles: !_.opt.eventPropagate,
detail: arg
})
_.ele.dispatchEvent(e)
}
gliderPrototype.event = function (ele, type, args) {
var eventHandler = ele[type + 'EventListener'].bind(ele)
Object.keys(args).forEach(function (k) {
eventHandler(k, args[k])
})
}
return Glider
})

View File

@@ -0,0 +1 @@
.glider,.glider-contain{margin:0 auto;position:relative}.glider,.glider-track{transform:translateZ(0)}.glider-dot,.glider-next,.glider-prev{border:0;padding:0;user-select:none;outline:0}.glider-contain{width:100%}.glider{overflow-y:hidden;-webkit-overflow-scrolling:touch;-ms-overflow-style:none}.glider-track{width:100%;margin:0;padding:0;display:flex;z-index:1}.glider.draggable{user-select:none;cursor:-webkit-grab;cursor:grab}.glider.draggable .glider-slide img{user-select:none;pointer-events:none}.glider.drag{cursor:-webkit-grabbing;cursor:grabbing}.glider-slide{user-select:none;justify-content:center;align-content:center;width:100%;min-width:150px}.glider-slide img{max-width:100%}.glider::-webkit-scrollbar{opacity:0;height:0}.glider-next,.glider-prev{position:absolute;background:0 0;z-index:2;font-size:40px;text-decoration:none;left:-23px;top:30%;cursor:pointer;color:#666;opacity:1;line-height:1;transition:opacity .5s cubic-bezier(.17,.67,.83,.67),color .5s cubic-bezier(.17,.67,.83,.67)}.glider-next:focus,.glider-next:hover,.glider-prev:focus,.glider-prev:hover{color:#ccc}.glider-next{right:-23px;left:auto}.glider-next.disabled,.glider-prev.disabled{opacity:.25;color:#666;cursor:default}.glider-hide{opacity:0}.glider-dots{user-select:none;display:flex;flex-wrap:wrap;justify-content:center;margin:0 auto;padding:0}.glider-dot{display:block;cursor:pointer;color:#ccc;border-radius:999px;background:#ccc;width:12px;height:12px;margin:7px}.glider-dot:focus,.glider-dot:hover{background:#ddd}.glider-dot.active{background:#a89cc8}@media(max-width:36em){.glider::-webkit-scrollbar{opacity:1;-webkit-appearance:none;width:7px;height:3px}.glider::-webkit-scrollbar-thumb{opacity:1;border-radius:99px;background-color:rgba(156,156,156,.25);-webkit-box-shadow:0 0 1px rgba(255,255,255,.25);box-shadow:0 0 1px rgba(255,255,255,.25)}}

16
resources/GliderJs/1.7.6/glider.min.js vendored Normal file

File diff suppressed because one or more lines are too long