Added interpreter for pseudocode for displaying exhibitions, events.
Added basic search. Added object pages.
This commit is contained in:
parent
a49746ab10
commit
80485a98ab
29
apiMirror.php
Normal file
29
apiMirror.php
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?PHP
|
||||
/**
|
||||
* The main display file for standalone pages.
|
||||
*
|
||||
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
|
||||
*/
|
||||
|
||||
// Include functions and settings.
|
||||
|
||||
require_once __DIR__ . "/inc/functions.php";
|
||||
|
||||
// Check validity of request.
|
||||
|
||||
if (!isset($_GET['args']) || !isset($_GET['area'])) {
|
||||
echo printErrorPage("File does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!in_array($_GET['area'], ['events', 'exhibitions'])) {
|
||||
echo printErrorPage("Using a disallowed value for area.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure working environment for frontend.
|
||||
|
||||
ensureEnvironment();
|
||||
|
||||
echo queryCachePage($settings['mdVersion'] . "?" . urldecode($_GET['args']), $_GET['area'], $settings);
|
||||
|
|
@ -36,7 +36,7 @@ function printBackendHead(string $page = "home", string $title = "Home", string
|
|||
$output .= '
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script type="text/javascript" src="./js/newToolTip.js"></script>
|
||||
<script type="text/javascript" src="./js/newToolTip.js" defer></script>
|
||||
<script type="text/javascript" src="./js/main.js"></script>
|
||||
<script type="text/javascript" src="../js/main.js"></script>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function removeElement(elem) {
|
||||
async function removeElement(elem) {
|
||||
while (elem.firstChild) {
|
||||
elem.removeChild(elem.firstChild);
|
||||
}
|
||||
|
@ -32,12 +32,24 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
"uploadFile" : "Upload file",
|
||||
"submit" : "Submit",
|
||||
"generate" : "Generate",
|
||||
"embedCodeGenerator" : "Generator for embed code",
|
||||
"helpEmbedCode" : "Here you can create embed code.",
|
||||
"singleObjectTile" : "Single object (tile)",
|
||||
"singleObjectDetails": "Single object (details)",
|
||||
"singleCollection" : "Single collection",
|
||||
"exhibitionCalendar" : "Exhibition calendar",
|
||||
"eventCalendar" : "Event calendar",
|
||||
},
|
||||
"de" : {
|
||||
"uploadFile" : "Eine Datei heraufladen",
|
||||
"submit" : "Abschicken",
|
||||
"generate" : "Generieren",
|
||||
"embedCodeGenerator" : "Generator für Einbettungen",
|
||||
"helpEmbedCode" : "Hier können sie den embed-code generieren.",
|
||||
"singleObjectTile" : "Einzelobjekt (Kachel)",
|
||||
"singleObjectDetails": "Einzelobjekt (Details)",
|
||||
"singleCollection" : "Einzelsammlung",
|
||||
"exhibitionCalendar" : "Ausstellungskalender",
|
||||
"eventCalendar" : "Veranstaltungen (Kalender)",
|
||||
}
|
||||
};
|
||||
|
@ -159,7 +171,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
(async function() {
|
||||
|
||||
let trigger = document.getElementById("uploadFile");
|
||||
if (trigger === undefined || trigger === null) return;
|
||||
|
@ -206,7 +218,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
overlay.appendChild(uploadForm);
|
||||
document.getElementsByTagName("body")[0].appendChild(overlay);
|
||||
|
||||
document.getElementsByTagName("body")[0].addEventListener('keydown', function(e) {
|
||||
document.getElementsByTagName("body")[0].addEventListener('keydown', async function(e) {
|
||||
if (e.keyCode != 27) return;
|
||||
removeElement(overlay);
|
||||
});
|
||||
|
@ -214,7 +226,7 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
queryPage(
|
||||
encodeURI('./files.php'),
|
||||
function (request) {
|
||||
let allFiles = request.response;
|
||||
let allFiles = JSON.parse(request.response);
|
||||
|
||||
for (let i = 0, max = allFiles.length; i < max; i++) {
|
||||
console.log(allFiles[i]);
|
||||
|
@ -231,14 +243,56 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
*/
|
||||
(function() {
|
||||
|
||||
function generateToolTip(toolTipID, toolTipText, toolTipTitle = "", triggerId = "") {
|
||||
|
||||
let trigger = document.createElement("span");
|
||||
|
||||
trigger.classList.add("newToolTipTag");
|
||||
trigger.classList.add("helpToolTip");
|
||||
trigger.setAttribute("data-for", toolTipID);
|
||||
|
||||
let toolTip = document.createElement("div");
|
||||
toolTip.id = "tooltip_" + toolTipID;
|
||||
toolTip.classList.add("newToolTip");
|
||||
toolTip.setAttribute("data-title", toolTipTitle);
|
||||
|
||||
let toolTipCont = document.createElement("p");
|
||||
toolTipCont.textContent = toolTipText;
|
||||
toolTip.appendChild(toolTipCont);
|
||||
|
||||
trigger.appendChild(toolTip);
|
||||
|
||||
return trigger;
|
||||
|
||||
}
|
||||
|
||||
let generator = document.getElementById("embedGenerator");
|
||||
if (generator === undefined || generator === null) return;
|
||||
|
||||
// Define generator types
|
||||
|
||||
let generatorTypes = [
|
||||
["", "", false, "text"],
|
||||
["eventCalendar", getTranslation(translations, "eventCalendar"), true, "number"],
|
||||
["", "", false],
|
||||
["singleObjectTile", getTranslation(translations, "singleObjectTile"), true],
|
||||
["singleObjectDetails", getTranslation(translations, "singleObjectDetails"), true],
|
||||
["singleCollectionTile", getTranslation(translations, "singleCollection"), true],
|
||||
["exhibitionCalendar", getTranslation(translations, "exhibitionCalendar"), true],
|
||||
["eventCalendar", getTranslation(translations, "eventCalendar"), true],
|
||||
];
|
||||
|
||||
// Add help tooltip
|
||||
|
||||
let generatorLabelSpan = document.createElement("span");
|
||||
generatorLabelSpan.classList.add("labelLine");
|
||||
|
||||
let generatorLabel = document.createElement("label");
|
||||
generatorLabel.textContent = getTranslation(translations, "embedCodeGenerator");
|
||||
|
||||
generatorLabelSpan.appendChild(generatorLabel);
|
||||
generatorLabelSpan.appendChild(generateToolTip("embedGeneratorToolTip", getTranslation(translations, "helpEmbedCode"), getTranslation(translations, "embedCodeGenerator")));
|
||||
|
||||
generator.appendChild(generatorLabelSpan);
|
||||
|
||||
let selectType = document.createElement("select");
|
||||
|
||||
for (let i = 0, max = generatorTypes.length; i < max; i++) {
|
||||
|
@ -246,7 +300,6 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
generatorOption.value = generatorTypes[i][0];
|
||||
generatorOption.textContent = generatorTypes[i][1];
|
||||
generatorOption.setAttribute("data-useSpecifier", generatorTypes[i][2]);
|
||||
generatorOption.setAttribute("data-inputType", generatorTypes[i][3]);
|
||||
selectType.appendChild(generatorOption);
|
||||
}
|
||||
|
||||
|
@ -274,7 +327,6 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
generatorSpecifier.value = "";
|
||||
if (selectType.options[selectType.selectedIndex].getAttribute("data-useSpecifier") == "true") {
|
||||
generatorSpecifier.classList.remove("invisible");
|
||||
generatorSpecifier.type = selectType.options[selectType.selectedIndex].getAttribute("data-inputType");
|
||||
}
|
||||
else generatorSpecifier.classList.add("invisible");
|
||||
|
||||
|
@ -283,13 +335,20 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
|
||||
});
|
||||
|
||||
buttonGenerate.addEventListener('click', function(e) {
|
||||
function runGenerator() {
|
||||
if (selectType.value == "") return;
|
||||
generatorFieldCont.textContent = "[" + selectType.value + "]";
|
||||
if (generatorSpecifier.value != "") {
|
||||
generatorFieldCont.textContent += "{" + generatorSpecifier.value + "}";
|
||||
}
|
||||
}
|
||||
|
||||
generatorSpecifier.addEventListener('keydown', function(e) {
|
||||
if (e.keyCode != 13) return;
|
||||
e.stopPropagation(); e.preventDefault();
|
||||
runGenerator();
|
||||
});
|
||||
buttonGenerate.addEventListener('click', function() { runGenerator(); });
|
||||
|
||||
generator.appendChild(generatorField);
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ $pages = loadPages(); // Load overview of pages.
|
|||
*/
|
||||
|
||||
// Check for vars.
|
||||
loadHttpToGlobals(["task", "startPage", "pageTitle", "logo", "url", "mdVersion", "maxFileSize", "defaultLang"]);
|
||||
loadHttpToGlobals(["task", "startPage", "pageTitle", "logo", "url", "mdVersion", "mdImgFolder", "cacheRefreshInterval", "maxFileSize", "defaultLang"]);
|
||||
|
||||
if (isset($task) and $task == "update") { // Adding new users.
|
||||
|
||||
|
@ -32,11 +32,10 @@ if (isset($task) and $task == "update") { // Adding new users.
|
|||
}
|
||||
|
||||
// Ensure that URLs end with a trailing slash.
|
||||
if (isset($mdVersion)) {
|
||||
$mdVersion = rtrim($mdVersion, "/") . "/";
|
||||
}
|
||||
if (isset($mdVersion)) $mdVersion = rtrim($mdVersion, "/") . "/";
|
||||
if (isset($mdImgFolder)) $mdImgFolder = rtrim($mdImgFolder, "/") . "/";
|
||||
|
||||
foreach (["startPage", "pageTitle", "logo", "url", "mdVersion", "maxFileSize", "defaultLang"] as $var) {
|
||||
foreach (["startPage", "pageTitle", "logo", "url", "mdVersion", "mdImgFolder", "cacheRefreshInterval", "maxFileSize", "defaultLang"] as $var) {
|
||||
if (isset($$var)) $settings[$var] = $$var;
|
||||
}
|
||||
|
||||
|
@ -117,6 +116,20 @@ echo '
|
|||
<td>' . generateHelpToolTip("helpMDVersion", $translations['mdVersion'], $translations['helpMDVersion']) . '</td>
|
||||
</tr>
|
||||
|
||||
<!-- MD Image Folder -->
|
||||
<tr>
|
||||
<th><label for="mdImgFolder">' . $translations['mdImgFolder'] . '</label></th>
|
||||
<td><input type="url" id="mdImgFolder" name="mdImgFolder" placeholder="' . $translations['mdImgFolder']. '" value="'.$settings['mdImgFolder'].'" required /></td>
|
||||
<td>' . generateHelpToolTip("helpMDimgFolder", $translations['mdImgFolder'], $translations['helpMDimgFolder']) . '</td>
|
||||
</tr>
|
||||
|
||||
<!-- Refresh Interval -->
|
||||
<tr>
|
||||
<th><label for="cacheRefreshInterval">' . $translations['cacheRefreshInterval'] . '</label></th>
|
||||
<td><input type="number" id="cacheRefreshInterval" name="cacheRefreshInterval" placeholder="' . $translations['cacheRefreshInterval']. '" value="'.$settings['cacheRefreshInterval'].'" required /></td>
|
||||
<td>' . generateHelpToolTip("helpCacheRefreshInterval", $translations['cacheRefreshInterval'], $translations['helpCacheRefreshInterval']) . '</td>
|
||||
</tr>
|
||||
|
||||
<!-- Max Upload Size -->
|
||||
<tr>
|
||||
<th><label for="maxFileSize">' . $translations['maxFileSize'] . '</label></th>
|
||||
|
|
|
@ -222,22 +222,28 @@ main { padding: .5em 5em 3em 3em; }
|
|||
*/
|
||||
|
||||
#staticPageOptions > * { display: block; padding: .5em 1rem; }
|
||||
#staticPageOptions > .labelLine { display: table; width: 100%; }
|
||||
#staticPageOptions .helpToolTip { width: 2em; text-align: center; }
|
||||
#staticPageOptions > .labelLine > * { display: table-cell; }
|
||||
#staticPageOptions label { font-weight: bold; }
|
||||
#staticPageOptions select { display: block; width: 100%; }
|
||||
#staticPageOptions button { display: block; width: 100%; background: #0277BD; color: #FFF; transition: background .4s; }
|
||||
#staticPageOptions button:hover { background: #039BE5; }
|
||||
|
||||
#embedGenerator .helpToolTip,
|
||||
#staticPageOptions .helpToolTip { width: 2em; text-align: center; }
|
||||
|
||||
#pageTools > #embedGenerator { display: block;
|
||||
margin-bottom: 1em; padding-bottom: 1em;
|
||||
box-sizing: content-box; border-bottom: 1px solid #D6D6D6; }
|
||||
#embedGenerator > * { display: block; width: 100%; }
|
||||
#embedGenerator .buttonLike { cursor: pointer; }
|
||||
#embedGenerator > .labelLine { margin-bottom: .5em; }
|
||||
|
||||
#pageTools > * { padding: 0 1rem; }
|
||||
|
||||
#staticPageOptions > .labelLine,
|
||||
#embedGenerator > .labelLine,
|
||||
.labelLine { display: table; width: 100%; }
|
||||
.labelLine > * { display: table-cell; }
|
||||
.labelLine label { font-weight: bold; }
|
||||
|
||||
/************
|
||||
* Login Page
|
||||
*/
|
||||
|
|
|
@ -29,6 +29,8 @@ $translations = [
|
|||
"helpURL" => "<p>URL of the page. Filling out this field helps with optimization for search engines.</p>",
|
||||
"startPage" => "Start page",
|
||||
"helpStartPage" => "<p>The start page of the public site.</p>",
|
||||
"mdImgFolder" => "Image folder (md)",
|
||||
"helpMDimgFolder" => "<p>The folder in which image files are stored in the given instance of museum-digital.</p>",
|
||||
"logo" => "Logo",
|
||||
"helpLogo" => "<p>The logo of the site. Is mainly used for the little icon you see in the browser, right next to the title of the tab.</p>",
|
||||
"mdVersion" => "Version of Museum-Digital",
|
||||
|
@ -41,6 +43,14 @@ $translations = [
|
|||
"helpLanguage" => "<p>The default language of this instance of md:cms.</p>",
|
||||
"maxFileSize" => "Maximum upload size",
|
||||
"helpMaxFileSize" => "<p>The maximum file size of file uploads.</p>",
|
||||
"cacheRefreshInterval" => "Cache Refresh Interval",
|
||||
"helpCacheRefreshInterval" => "<p>This setting determines how often contents fetched from museum-digital should be refreshed (the number equals X seconds).
|
||||
<ul>
|
||||
<li>Setting it to <code>0</code> disables it</li>
|
||||
<li>Using a low value, means more accurate data, but slower loading time.</li>
|
||||
<li>Using a high value, means data could be slightly outdated, but makes loading much faster.</li>
|
||||
</ul>
|
||||
</p>",
|
||||
|
||||
"IDatMD" => "ID at museum-digital",
|
||||
"embedFromMD" => "Embed from museum-digital",
|
||||
|
|
|
@ -73,7 +73,9 @@ function ensureEnvironment() {
|
|||
"pageTitle" => "md:cms",
|
||||
"logo" => "",
|
||||
"url" => "",
|
||||
"mdVersion" => "https://www.museum-digital.de/nat/",
|
||||
"cacheRefreshInterval" => 0,
|
||||
"mdVersion" => "https://rlp.museum-digital.de/",
|
||||
"mdImgFolder" => "https://rlp.museum-digital.de/data/rlp/",
|
||||
"maxFileSize" => 300000,
|
||||
"defaultLang" => "en"
|
||||
],
|
||||
|
@ -109,6 +111,42 @@ function loadPublicPages() {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query or cache pages.
|
||||
*
|
||||
* @param string $url URL to query.
|
||||
* @param string $area The type of the queried page. If caching is enabled, renew cache every X seconds.
|
||||
* @param array $settings Settings variable.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function queryCachePage(string $url, string $area = "", array $settings = ['cacheRefreshInterval' => 0]) {
|
||||
|
||||
// Ignore caching if cacheRefreshInterval equals zero.
|
||||
if ($settings['cacheRefreshInterval'] == 0) {
|
||||
return file_get_contents($url);
|
||||
}
|
||||
|
||||
$fileDir = __DIR__ . "/../data/caches/$area";
|
||||
ensureDir($fileDir);
|
||||
|
||||
$fileName = md5($url);
|
||||
$filePath = "$fileDir/$fileName.json";
|
||||
|
||||
// Load from cache.
|
||||
if (file_exists($filePath) && time() - filemtime($filePath) < $settings['cacheRefreshInterval']) {
|
||||
return file_get_contents($filePath);
|
||||
}
|
||||
|
||||
// Refresh cache.
|
||||
|
||||
$contents = file_get_contents($url);
|
||||
file_put_contents($filePath, $contents, LOCK_EX);
|
||||
|
||||
return $contents;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function scanDirConts is a wrapper around scandir(), which removes [".", ".."].
|
||||
*
|
||||
|
@ -320,4 +358,78 @@ function checkPreviewAccess($sessionStarted = false) {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function checking if a string starts with another.
|
||||
*
|
||||
* @param string $haystack String to check.
|
||||
* @param string $needle Potential start of $haystack.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function startswith(string $haystack, string $needle):bool {
|
||||
if (substr($haystack, 0, strlen($needle)) == $needle) return (true);
|
||||
else return (false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function checking if a string starts with any input from the input array.
|
||||
*
|
||||
* @param string $haystack String to check.
|
||||
* @param string[] $needles Array containing potential start values of $haystack.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
function startswithAny(string $haystack, array $needles):bool {
|
||||
$output = false;
|
||||
foreach ($needles as $needle) {
|
||||
$output = startswith($haystack, $needle);
|
||||
if ($output == true) return $output;
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Curling web pages.
|
||||
* Function to check errors.
|
||||
*
|
||||
* @param string $url URL to query.
|
||||
* @param string $host Authentication data. Optional.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function runCurl(string $url, string $host = ""):string {
|
||||
|
||||
$curl = curl_init();
|
||||
|
||||
curl_setopt($curl, CURLOPT_URL, $url);
|
||||
// curl_setopt($curl, CURLOPT_RESOLVE, ["www.example.com:443:172.16.1.1"]);
|
||||
curl_setopt($curl, CURLOPT_ENCODING, '');
|
||||
if ($host) curl_setopt($ch, CURLOPT_HTTPHEADER, array("Host: $host"));
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
$result = curl_exec($curl);
|
||||
|
||||
curl_close($curl);
|
||||
return $result;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This function cuts down a string and adds a period in case it's longer than length to create a snippet.
|
||||
*
|
||||
* @param string $string Input text to cut down
|
||||
* @param int $length Length of the snippet to create
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function createTextSnippet($string, $length) {
|
||||
|
||||
if (strlen($string) > $length) {
|
||||
$string = substr($string, 0, $length);
|
||||
$string = substr($string, 0, strrpos($string, ' '));
|
||||
$string .= ' ...';
|
||||
}
|
||||
return $string;
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
334
inc/mdEmbeds.php
334
inc/mdEmbeds.php
|
@ -12,12 +12,17 @@
|
|||
* for embedding from museum-digital.
|
||||
*
|
||||
* @param string $text Input string.
|
||||
* @param array $settings General settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function checkForEmbeds(string $text):string {
|
||||
function checkForEmbeds(string $text, array $settings):string {
|
||||
|
||||
$embedOptions = [
|
||||
"singleObjectTile",
|
||||
"singleObjectDetails",
|
||||
"singleCollectionTile",
|
||||
"exhibitionCalendar",
|
||||
"eventCalendar"
|
||||
];
|
||||
|
||||
|
@ -26,13 +31,32 @@ function checkForEmbeds(string $text):string {
|
|||
if (strpos($text, $option) === false) continue;
|
||||
$position = strpos($text, $option) - 1;
|
||||
|
||||
$nextTag = strpos($text, "<", $position);
|
||||
$nextWhitespace = strpos($text, " ", $position);
|
||||
$nextTag = $nextWhitespace = strlen($text);
|
||||
if (strpos($text, "<", $position) !== false) $nextTag = strpos($text, "<", $position);
|
||||
if (strpos($text, " ", $position) !== false) $nextWhitespace = strpos($text, " ", $position);
|
||||
|
||||
$end = min($nextTag, $nextWhitespace, strlen($text));
|
||||
$end = min($nextTag, $nextWhitespace);
|
||||
|
||||
$pseudocode = substr($text, $position, $position + $end);
|
||||
echo $pseudocode;
|
||||
$pseudocode = substr($text, $position, $end - $position);
|
||||
|
||||
$command = substr($pseudocode, 1, strpos($pseudocode, "]") - 1);
|
||||
$arguments = [];
|
||||
if (strpos($pseudocode, "{") !== false) $arguments = explode("&", substr($pseudocode, strpos($pseudocode, "{") + 1, -1));
|
||||
|
||||
switch ($command) {
|
||||
case "singleObjectTile":
|
||||
$text = str_replace($pseudocode, embedObject($arguments, $settings), $text);
|
||||
break;
|
||||
case "singleObjectDetails":
|
||||
$text = str_replace($pseudocode, embedObject($arguments, $settings, true), $text);
|
||||
break;
|
||||
case "exhibitionCalendar":
|
||||
$text = str_replace($pseudocode, embedExhibitionCalendar($arguments), $text);
|
||||
break;
|
||||
case "eventCalendar":
|
||||
$text = str_replace($pseudocode, embedEventCalendar($arguments), $text);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -40,4 +64,302 @@ function checkForEmbeds(string $text):string {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function drawObjectTile creates a tile with just the most basic information on an object.
|
||||
*
|
||||
* @param string[] $contents Input data fetched from the object API at museum-digital.
|
||||
* @param array $settings Settings variable.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function drawObjectTile(array $contents, array $settings):string {
|
||||
|
||||
$output = '
|
||||
<div class="objTile">
|
||||
';
|
||||
|
||||
if (count($contents['object_images']) > 0) {
|
||||
foreach ($contents['object_images'] as $image) {
|
||||
if ($image['is_main'] != "j") continue;
|
||||
$output .= '
|
||||
<img src="' . $settings['mdImgFolder'] . $image['folder'] . '/' . $image['preview'] . '" />';
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '
|
||||
<div>
|
||||
|
||||
<h4>' . $contents['object_name'] . '</h4>
|
||||
|
||||
<div>
|
||||
<a href="./object.php?id=' . $contents['object_id'] . '" class="toTranslate" data-content="More"></a>
|
||||
<a href="' . $settings['mdVersion'] . '?t=objekt&oges=' . $contents['object_id'] . '" class="toTranslate" data-content="MoreAtMuseumDigital">' . $contents['object_name'] . '</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
';
|
||||
|
||||
return $output;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function drawObjectDetails creates a tile with just the most basic information on an object.
|
||||
*
|
||||
* @param string[] $contents Input data fetched from the object API at museum-digital.
|
||||
* @param array $settings Settings variable.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function drawObjectDetails(array $contents, array $settings):string {
|
||||
|
||||
$output = '
|
||||
<div class="objDetails">
|
||||
|
||||
<h2>' . $contents['object_name'] . '</h2>
|
||||
';
|
||||
|
||||
if (count($contents['object_images']) > 0) {
|
||||
foreach ($contents['object_images'] as $image) {
|
||||
if ($image['is_main'] != "j") continue;
|
||||
$output .= '
|
||||
<img class="objMainImg" src="' . $settings['mdImgFolder'] . $image['folder'] . '/' . $image['filename_loc'] . '" />';
|
||||
}
|
||||
}
|
||||
|
||||
$output .= '
|
||||
<div>
|
||||
';
|
||||
|
||||
$output .= '
|
||||
<p>
|
||||
' . $contents['object_description'] . '
|
||||
</p>';
|
||||
|
||||
$simpleDefinedConts = [
|
||||
"object_material_technique",
|
||||
"object_dimensions",
|
||||
];
|
||||
|
||||
$output .= "
|
||||
<dl>";
|
||||
if (count($contents['object_collection']) > 0) {
|
||||
$output .= '
|
||||
<dt class="toTranslate" data-content="Collection"></dt>';
|
||||
foreach ($contents['object_collection'] as $collection) {
|
||||
$output .= '
|
||||
<dd>' . $collection['collection_name'] . '</dd>
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($simpleDefinedConts as $value) {
|
||||
$output .= "
|
||||
<dt class='toTranslate' data-content='" . $value . "'></dt>
|
||||
<dd>" . $contents[$value] . "</dd>
|
||||
";
|
||||
}
|
||||
|
||||
if (count($contents['object_tags']) > 0) {
|
||||
$output .= '
|
||||
<dt class="toTranslate" data-content="Tags"></dt>';
|
||||
foreach ($contents['object_tags'] as $tag) {
|
||||
$output .= '
|
||||
<dd>' . $tag['tag_name'] . '</dd>
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
if (count($contents['object_relation_places']) > 0) {
|
||||
$output .= '
|
||||
<dt class="toTranslate" data-content="Places"></dt>';
|
||||
foreach ($contents['object_relation_places'] as $place) {
|
||||
$output .= '
|
||||
<dd>' . $place['place']['place_name'] . '</dd>
|
||||
';
|
||||
}
|
||||
}
|
||||
|
||||
if (count($contents['object_relation_people']) > 0) {
|
||||
$output .= '
|
||||
<dt class="toTranslate" data-content="People"></dt>';
|
||||
foreach ($contents['object_relation_people'] as $people) {
|
||||
$output .= '
|
||||
<dd>' . $people['people']['displayname'] . '</dd>
|
||||
';
|
||||
}
|
||||
}
|
||||
$output .= "
|
||||
</dl>";
|
||||
|
||||
if (count($contents['object_events']) > 0) {
|
||||
$output .= "
|
||||
<div class='events'>";
|
||||
foreach ($contents['object_events'] as $event) {
|
||||
$output .= '
|
||||
|
||||
<div class="objevent">
|
||||
<h5 class="toTranslate" data-content="eventType' . $event['event_type'] . '"></h5>
|
||||
<table>
|
||||
';
|
||||
|
||||
if (isset($event['people'])) $output .= '
|
||||
<tr>
|
||||
<th class="toTranslate" data-content="... who"></th>
|
||||
<td class="vcard h-card">
|
||||
<a rel="tag" class="u-url fn p-name url">' . $event['people']['displayname'] . '</a>
|
||||
</td>
|
||||
</tr>';
|
||||
|
||||
if (isset($event['time'])) $output .= '
|
||||
<tr>
|
||||
<th class="toTranslate" data-content="... when"></th>
|
||||
<td>
|
||||
<a>' . $event['time']['time_name'] . '</a>
|
||||
</td>
|
||||
</tr>';
|
||||
|
||||
if (isset($event['place'])) $output .= '
|
||||
<tr>
|
||||
<th class="toTranslate" data-content="... where"></th>
|
||||
<td class="h-geo geo">
|
||||
<a rel="tag">' . $event['place']['place_name'] . '</a>
|
||||
</td>
|
||||
</tr>';
|
||||
$output .= '
|
||||
</table>
|
||||
</div>
|
||||
';
|
||||
}
|
||||
$output .= '
|
||||
</div>
|
||||
';
|
||||
}
|
||||
|
||||
$output .= '
|
||||
<p class="metadataLine">
|
||||
<span><span class="toTranslate" data-content="Metadata"></span></span>
|
||||
<span><span class="toTranslate" data-content="LastUpdated"></span>: ' . $contents['object_last_updated'] . '</span>
|
||||
<span><span class="toTranslate" data-content="Licence"></span>: ' . $contents['licence']['metadata_rights_status'] . '</span>
|
||||
<span><a class="toTranslate" data-content="ObjectAtMuseumDigital" href="' . $settings['mdVersion'] . '?t=objekt&oges=' . $contents['object_id'] . '"></a></span>
|
||||
</p>
|
||||
</div>
|
||||
';
|
||||
|
||||
$output .= '
|
||||
</div>
|
||||
';
|
||||
|
||||
return $output;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for displaying objects.
|
||||
*
|
||||
* @param array $arguments Arguments / GET parameters for urls to query.
|
||||
* @param array $settings Settings variable.
|
||||
* @param boolean $showDetails Optional. By default, only a tile with most basic information is displayed.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function embedObject(array $arguments, array $settings, bool $showDetails = false):string {
|
||||
|
||||
$toIgnore = ["t=", "output="];
|
||||
$srcArgs = "t=objekt";
|
||||
foreach ($arguments as $arg) {
|
||||
if (startsWithAny($arg, $toIgnore)) continue;
|
||||
$srcArgs .= "&" . $arg;
|
||||
}
|
||||
$srcArgs .= "&output=json";
|
||||
|
||||
$contents = json_decode(queryCachePage($settings['mdVersion'] . "?$srcArgs", "object", $settings), true);
|
||||
|
||||
if (!$showDetails) return drawObjectTile($contents, $settings);
|
||||
else return drawObjectDetails($contents, $settings);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for embedding event calendar.
|
||||
*
|
||||
* @param array $arguments Arguments / GET parameters for urls to query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function embedExhibitionCalendar(array $arguments):string {
|
||||
|
||||
$toIgnore = ["t=", "calendar=", "output="];
|
||||
$srcArgs = "t=exhibitions_overview&calendar=1";
|
||||
foreach ($arguments as $arg) {
|
||||
if (startsWithAny($arg, $toIgnore)) continue;
|
||||
$srcArgs .= "&" . $arg;
|
||||
}
|
||||
$srcArgs .= "&output=json";
|
||||
|
||||
$srcURL = "apiMirror.php?area=exhibitions&args=" . urlencode($srcArgs);
|
||||
|
||||
if (isset($_GET['y'])) $y = $_GET['y'];
|
||||
else $y = date("Y");
|
||||
if (isset($_GET['m'])) $m = $_GET['m'];
|
||||
else $m = date("m");
|
||||
|
||||
$prevMonth = strtotime('-1 month', strtotime("$y-$m-01"));
|
||||
$nextMonth = strtotime('+1 month', strtotime("$y-$m-01"));
|
||||
|
||||
$output = '
|
||||
<section class="mdCalendar"
|
||||
data-year="'.$y.'" data-month="'.$m.'" data-colored="1"
|
||||
data-today="./index.php?id=' . $GLOBALS['id'] . '&' . date("Y").'&m='.date("m") . '"
|
||||
data-prev="./index.php?id=' . $GLOBALS['id'] . '&y=' . date("Y", $prevMonth).'&m='.date("m", $prevMonth) . '"
|
||||
data-next="./index.php?id=' . $GLOBALS['id'] . '&y=' . date("Y", $nextMonth).'&m='.date("m", $nextMonth) . '"
|
||||
data-src="' . $srcURL . '&y='.date("Y", $nextMonth).'&m='.date("m", $nextMonth) . '">
|
||||
</section>
|
||||
';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for embedding event calendar.
|
||||
*
|
||||
* @param array $arguments Arguments / GET parameters for urls to query.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function embedEventCalendar(array $arguments):string {
|
||||
|
||||
$toIgnore = ["t=", "calendar=", "output="];
|
||||
$srcArgs = "t=events&calendar=1";
|
||||
foreach ($arguments as $arg) {
|
||||
if (startsWithAny($arg, $toIgnore)) continue;
|
||||
$srcArgs .= "&" . $arg;
|
||||
}
|
||||
$srcArgs .= "&output=json";
|
||||
|
||||
$srcURL = "apiMirror.php?area=events&args=" . urlencode($srcArgs);
|
||||
|
||||
if (isset($_GET['y'])) $y = $_GET['y'];
|
||||
else $y = date("Y");
|
||||
if (isset($_GET['m'])) $m = $_GET['m'];
|
||||
else $m = date("m");
|
||||
|
||||
$prevMonth = strtotime('-1 month', strtotime("$y-$m-01"));
|
||||
$nextMonth = strtotime('+1 month', strtotime("$y-$m-01"));
|
||||
|
||||
$output = '
|
||||
<section class="mdCalendar"
|
||||
data-year="'.$y.'" data-month="'.$m.'" data-colored="1"
|
||||
data-today="./index.php?id=' . $GLOBALS['id'] . '&' . date("Y").'&m='.date("m") . '"
|
||||
data-prev="./index.php?id=' . $GLOBALS['id'] . '&y=' . date("Y", $prevMonth).'&m='.date("m", $prevMonth) . '"
|
||||
data-next="./index.php?id=' . $GLOBALS['id'] . '&y=' . date("Y", $nextMonth).'&m='.date("m", $nextMonth) . '"
|
||||
data-src="' . $srcURL . '&y='.date("Y", $nextMonth).'&m='.date("m", $nextMonth) . '">
|
||||
</section>
|
||||
';
|
||||
|
||||
return $output;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
52
inc/search.php
Normal file
52
inc/search.php
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?PHP
|
||||
/**
|
||||
* This file provides search functions.
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function for searching in all static pages.
|
||||
*
|
||||
* @param string $searchTerm Search term.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
function searchInPages(string $searchTerm) {
|
||||
|
||||
$files = scanDirConts(__DIR__ . "/../data/static");
|
||||
|
||||
$results = [];
|
||||
foreach ($files as $file) {
|
||||
|
||||
$curResults = [];
|
||||
$contents = json_decode(file_get_contents(__DIR__ . "/../data/static/$file"), true);
|
||||
|
||||
if (!$contents['public']) continue; // Don't display non-public files.
|
||||
|
||||
$curResults['inTitle'] = substr_count($contents['title'], $searchTerm);
|
||||
$curResults['inDescription'] = substr_count($contents['content'], $searchTerm);
|
||||
$curResults['priority'] = $curResults['inTitle'] * 3 + $curResults['inDescription'];
|
||||
|
||||
if ($curResults['priority'] == 0) continue;
|
||||
|
||||
$curResults['title'] = $contents['title'];
|
||||
// Sanitize content for snippets.
|
||||
$snippet = preg_replace('/[\[{\(].*[\]}\)]/U' , '', strip_tags($contents['content']));
|
||||
$curResults['snippet'] = createTextSnippet($snippet, 180);
|
||||
$results[$file] = $curResults;
|
||||
|
||||
}
|
||||
|
||||
usort($results, function($a, $b) {
|
||||
if ($a == $b) return 0;
|
||||
return ($a > $b) ? -1 : 1;
|
||||
});
|
||||
|
||||
return $results;
|
||||
|
||||
}
|
||||
|
||||
?>
|
|
@ -10,25 +10,30 @@
|
|||
/**
|
||||
* Prints the head element of an HTML page in the public frontend.
|
||||
*
|
||||
* @param array $settings Settings variable.
|
||||
* @param string $page ID of the current page.
|
||||
* @param string $title Title of the page.
|
||||
* @param string $icon The icon of the website.
|
||||
* @param string $additional Additional HTML to inject.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function printPublicHead(string $page = "home", string $title = "Home", string $icon = ""):string {
|
||||
function printPublicHead(array $settings, string $page = "home", string $title = "Home", string $icon = "", $additional = ""):string {
|
||||
|
||||
$output = '<!DOCTYPE html>
|
||||
<html lang="en" id="' . $page . '">
|
||||
<head>
|
||||
|
||||
<!-- Content Security policies -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'self\'; connect-src \'self\'; img-src \'self\'; style-src \'self\' \'unsafe-inline\'; font-src \'self\';" />
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src \'none\'; script-src \'self\'; connect-src \'self\' ' . $settings['mdVersion'] . '; img-src \'self\' ' . $settings['mdVersion'] . '; style-src \'self\' \'unsafe-inline\'; font-src \'self\';" />
|
||||
|
||||
<title>' . $title . '</title>
|
||||
<link rel="stylesheet" type="text/css" href="themes/default/default.css">
|
||||
<link rel="stylesheet" type="text/css" href="themes/imports.css">
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8">';
|
||||
|
||||
$output .= $additional;
|
||||
|
||||
if ($icon) {
|
||||
$output .= '
|
||||
<link rel="shortcut icon" sizes="16x16 32x32" href="' . $icon . '" />
|
||||
|
@ -39,6 +44,7 @@ function printPublicHead(string $page = "home", string $title = "Home", string $
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<script type="text/javascript" src="./js/main.js"></script>
|
||||
<script type="text/javascript" src="./js/mdCalendar.js" defer></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
@ -151,4 +157,37 @@ function printErrorPage(string $content):string {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function for generating the standard navigation of the public parts of the page.
|
||||
*
|
||||
* @param array $pages List of all pages.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function generatePublicNav($pages):string {
|
||||
$output = '<nav>';
|
||||
$output .= buildPageOrder(
|
||||
$pages,
|
||||
function() {
|
||||
return "<ul>";
|
||||
},
|
||||
function() {
|
||||
return "</ul>";
|
||||
},
|
||||
function($inputs, string $toAdd) {
|
||||
$output = "
|
||||
<li";
|
||||
if (!$inputs['public']) $output .= " class='notPublic'";
|
||||
$output .= ">
|
||||
<a href='./?id=" . $inputs['id'] . "'>" . $inputs['title'] . "</a>
|
||||
$toAdd
|
||||
</li>
|
||||
";
|
||||
return $output;
|
||||
}
|
||||
);
|
||||
$output .= '</nav>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
?>
|
||||
|
|
37
index.php
37
index.php
|
@ -5,6 +5,10 @@
|
|||
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
|
||||
*/
|
||||
|
||||
// Include functions and settings.
|
||||
|
||||
require_once __DIR__ . "/inc/functions.php";
|
||||
|
||||
// Check validity of request.
|
||||
|
||||
if (isset($_GET['id']) and !file_exists(__DIR__ . "/data/static/" . $_GET['id'] . ".json")) {
|
||||
|
@ -12,10 +16,6 @@ if (isset($_GET['id']) and !file_exists(__DIR__ . "/data/static/" . $_GET['id']
|
|||
return;
|
||||
}
|
||||
|
||||
// Include functions and settings.
|
||||
|
||||
require __DIR__ . "/inc/functions.php";
|
||||
|
||||
// Ensure working environment for frontend.
|
||||
|
||||
ensureEnvironment();
|
||||
|
@ -25,8 +25,6 @@ $pages = loadPublicPages(); // Load overview of pages.
|
|||
* Load data.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @var array $tPage The variable contains the main data on the displayed page.
|
||||
*/
|
||||
|
@ -53,32 +51,11 @@ if (!$tPage['public']) {
|
|||
* Output
|
||||
*/
|
||||
|
||||
echo printPublicHead($id, $settings['pageTitle'], $settings['logo']);
|
||||
echo printPublicHead($settings, $id, $settings['pageTitle'], $settings['logo']);
|
||||
echo printPublicHeader($settings['pageTitle']);
|
||||
echo printStaticPagePart("banner", "header"); // Print aside (if need be)
|
||||
|
||||
echo '<nav>';
|
||||
echo buildPageOrder(
|
||||
$pages,
|
||||
function() {
|
||||
return "<ul>";
|
||||
},
|
||||
function() {
|
||||
return "</ul>";
|
||||
},
|
||||
function($inputs, string $toAdd) {
|
||||
$output = "
|
||||
<li";
|
||||
if (!$inputs['public']) $output .= " class='notPublic'";
|
||||
$output .= ">
|
||||
<a href='./?id=" . $inputs['id'] . "'>" . $inputs['title'] . "</a>
|
||||
$toAdd
|
||||
</li>
|
||||
";
|
||||
return $output;
|
||||
}
|
||||
);
|
||||
echo '</nav>';
|
||||
echo generatePublicNav($pages);
|
||||
|
||||
echo '
|
||||
<div id="mainWrapper">
|
||||
|
@ -89,7 +66,7 @@ echo '
|
|||
<main>';
|
||||
|
||||
echo '<h1>' . $tPage['title'] . '</h1>';
|
||||
echo checkForEmbeds($tPage['content']);
|
||||
echo checkForEmbeds($tPage['content'], $settings);
|
||||
|
||||
echo '
|
||||
</main>
|
||||
|
|
49
js/main.js
49
js/main.js
|
@ -14,12 +14,46 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
|
||||
let translations = {
|
||||
"en" : {
|
||||
"More" : "More",
|
||||
"MoreAtMuseumDigital" : "museum-digital",
|
||||
"ObjectAtMuseumDigital" : "Object entry at museum-digital",
|
||||
"Collection" : "Collection",
|
||||
"object_material_technique" : "Material / Technique",
|
||||
"object_dimensions" : "Dimensions",
|
||||
"Metadata" : "Metadata",
|
||||
"LastUpdated" : "Last Updated",
|
||||
"Licence" : "Licence",
|
||||
"Tags" : "Tags",
|
||||
"People" : "People",
|
||||
"Places" : "Places",
|
||||
"Times" : "Times",
|
||||
"Search" : "Search",
|
||||
"SearchingFor" : "Searching for",
|
||||
"... who" : "... who",
|
||||
"... where" : "... where",
|
||||
"... when" : "... when",
|
||||
"eventType1" : "Created",
|
||||
},
|
||||
"de" : {
|
||||
|
||||
},
|
||||
"hu" : {
|
||||
|
||||
"More" : "Mehr",
|
||||
"MoreAtMuseumDigital" : "museum-digital",
|
||||
"ObjectAtMuseumDigital" : "Objekt bei museum-digital",
|
||||
"Collection" : "Sammlung",
|
||||
"object_material_technique" : "Material / Technik",
|
||||
"object_dimensions" : "Ausmaße",
|
||||
"Metadata" : "Metadaten",
|
||||
"LastUpdated" : "Zuletzt geupdatet",
|
||||
"Licence" : "Lizenz",
|
||||
"Tags" : "Schlagworte",
|
||||
"People" : "Personen",
|
||||
"Places" : "Orte",
|
||||
"Times" : "Zeiten",
|
||||
"Search" : "Suche",
|
||||
"SearchingFor" : "Suche nach",
|
||||
"... who" : "... wer",
|
||||
"... where" : "... wo",
|
||||
"... when" : "... wann",
|
||||
"eventType1" : "Hergestellt",
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -108,6 +142,13 @@ document.addEventListener("DOMContentLoaded", function() {
|
|||
}
|
||||
}
|
||||
|
||||
(function() {
|
||||
let toTranslate = document.getElementsByClassName("toTranslate");
|
||||
for (let i = 0, max = toTranslate.length; i < max; i++) {
|
||||
console.log(toTranslate[i].getAttribute("data-content"));
|
||||
toTranslate[i].textContent = getTranslation(translations, toTranslate[i].getAttribute("data-content"));
|
||||
}
|
||||
})();
|
||||
|
||||
});
|
||||
|
||||
|
|
480
js/mdCalendar.js
Normal file
480
js/mdCalendar.js
Normal file
|
@ -0,0 +1,480 @@
|
|||
/**
|
||||
* mdCalendar.js
|
||||
*/
|
||||
|
||||
document.addEventListener("DOMContentLoaded", function() {
|
||||
|
||||
/**
|
||||
* @var {array} translations Array of all translations.
|
||||
*/
|
||||
let translations = {
|
||||
"en" : {
|
||||
"dow0" : "Sunday",
|
||||
"dow1" : "Monday",
|
||||
"dow2" : "Tuesday",
|
||||
"dow3" : "Wednesday",
|
||||
"dow4" : "Thursday",
|
||||
"dow5" : "Friday",
|
||||
"dow6" : "Saturday",
|
||||
"mon0" : "January",
|
||||
"mon1" : "February",
|
||||
"mon2" : "March",
|
||||
"mon3" : "April",
|
||||
"mon4" : "May",
|
||||
"mon5" : "June",
|
||||
"mon6" : "July",
|
||||
"mon7" : "August",
|
||||
"mon8" : "September",
|
||||
"mon9" : "October",
|
||||
"mon10" : "November",
|
||||
"mon11" : "December",
|
||||
"Today" : "Today",
|
||||
"Title" : "Title",
|
||||
"Start" : "Start",
|
||||
"End" : "End",
|
||||
"Location" : "Location"
|
||||
},
|
||||
"de" : {
|
||||
"dow0" : "Sonntag",
|
||||
"dow1" : "Montag",
|
||||
"dow2" : "Dienstag",
|
||||
"dow3" : "Mittwoch",
|
||||
"dow4" : "Donnerstag",
|
||||
"dow5" : "Freitag",
|
||||
"dow6" : "Samstag",
|
||||
"mon0" : "Januar",
|
||||
"mon1" : "Februar",
|
||||
"mon2" : "März",
|
||||
"mon3" : "April",
|
||||
"mon4" : "Mai",
|
||||
"mon5" : "Juni",
|
||||
"mon6" : "Juli",
|
||||
"mon7" : "August",
|
||||
"mon8" : "September",
|
||||
"mon9" : "Oktober",
|
||||
"mon10" : "November",
|
||||
"mon11" : "Dezember",
|
||||
"Today" : "Jetzt",
|
||||
"Title" : "Titel",
|
||||
"Start" : "Beginn",
|
||||
"End" : "Ende",
|
||||
"Location" : "Ort"
|
||||
},
|
||||
"hu" : {
|
||||
"dow0": "Vas\u00e1rnap",
|
||||
"dow1": "H\u00e9tf\u0151",
|
||||
"dow2": "Kedd",
|
||||
"dow3": "Szerda",
|
||||
"dow4": "Cs\u00fct\u00f6rt\u00f6k",
|
||||
"dow5": "P\u00e9ntek",
|
||||
"dow6": "Szombat",
|
||||
"mon0": "Janu\u00e1r",
|
||||
"mon1": "Febru\u00e1r",
|
||||
"mon2": "M\u00e1rcius",
|
||||
"mon3": "\u00c1prilis",
|
||||
"mon4": "M\u00e1jus",
|
||||
"mon5": "J\u00fanius",
|
||||
"mon6": "J\u00falius",
|
||||
"mon7": "Augusztus",
|
||||
"mon8": "Szeptember",
|
||||
"mon9": "Okt\u00f3ber",
|
||||
"mon10": "November",
|
||||
"mon11": "December",
|
||||
"Today": "Ma",
|
||||
"Title": "C\u00edm",
|
||||
"Start": "Nyit",
|
||||
"End": "Bez\u00e1r",
|
||||
"Location": "Helysz\u00edn"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @var {boolean} Toggle debugging.
|
||||
*/
|
||||
let debugging = false;
|
||||
|
||||
/**
|
||||
* Function queryPage queries a web page and runs the specified function over the output.
|
||||
*
|
||||
* @param {string} url URL to query.
|
||||
* @param {function} func Callback function to run on the request after loading.
|
||||
* @param {boolean} debug Enable / disable debug mode.
|
||||
*
|
||||
* @return {boolean}
|
||||
*/
|
||||
function queryPage(url, func, debug = false) {
|
||||
|
||||
let request = new XMLHttpRequest();
|
||||
request.open('GET', url);
|
||||
request.setRequestHeader("Cache-Control", "no-cache");
|
||||
request.responseType = 'htm';
|
||||
request.send();
|
||||
request.onload = function() {
|
||||
|
||||
func(request, debug);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all children of an element.
|
||||
*
|
||||
* @param {string} id ID of the element to tear down.
|
||||
*
|
||||
* @return {void}
|
||||
*/
|
||||
function emptyElement(element) {
|
||||
while (element.firstChild) {
|
||||
emptyElement(element.firstChild);
|
||||
}
|
||||
element.parentNode.removeChild(element);
|
||||
if (debugging === true) {
|
||||
console.log("Removed element:");
|
||||
console.log(element);
|
||||
}
|
||||
}
|
||||
|
||||
function tearDownById(id) {
|
||||
let target = document.getElementById(id);
|
||||
if (target !== null) emptyElement(target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a requested translation from an array in the currently used language.
|
||||
*
|
||||
* @param {mixed[]} list Translation variable.
|
||||
* @param {string} specifier Specifies which translation to get.
|
||||
*
|
||||
* @return {string}
|
||||
*/
|
||||
function getTranslation(list, specifier) {
|
||||
|
||||
let preferedLang = document.getElementsByTagName("html")[0].getAttribute("lang");
|
||||
|
||||
if (list[preferedLang] !== undefined && list[preferedLang][specifier] !== null) return list[preferedLang][specifier];
|
||||
return list["en"][specifier];
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to create calendar.
|
||||
*/
|
||||
function createCalendarTable(target, events) {
|
||||
|
||||
let startOfWeek = 1; // The week starts on Monday.
|
||||
let endOfWeek = 0; // The week ends on Sunday.
|
||||
|
||||
let calLocale = document.getElementsByTagName("html")[0].getAttribute("lang");
|
||||
if (calLocale === undefined || calLocale === null) calLocale = "en";
|
||||
|
||||
function removeToolTips() {
|
||||
let toolTips = document.getElementsByClassName("mdCToolTip");
|
||||
for (let i = 0, max = toolTips.length; i < max; i++) {
|
||||
emptyElement(toolTips[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all days to display per month.
|
||||
* Adapted version of function described in https://stackoverflow.com/a/13146828.
|
||||
*
|
||||
* @param {int} The month number, 0 based
|
||||
* @param {int} The year, not zero based, required to account for leap years
|
||||
*
|
||||
* @return {Date[]} List with date objects for each day of the month
|
||||
*/
|
||||
function getDaysInMonth(month, year) {
|
||||
|
||||
var date = new Date(year, month, 1);
|
||||
var days = [];
|
||||
|
||||
// If the weekday of the first of the month does not equal 1 (Monday),
|
||||
// get days until the last monday before the month.
|
||||
if (date.getDay() !== startOfWeek) {
|
||||
while (date.getDay() !== startOfWeek) {
|
||||
date.setDate(date.getDate() - 1);
|
||||
days.unshift(new Date(date));
|
||||
}
|
||||
}
|
||||
|
||||
date = new Date(year, month, 1);
|
||||
// Get days of the month
|
||||
while (date.getMonth() === month) {
|
||||
days.push(new Date(date));
|
||||
date.setDate(date.getDate() + 1);
|
||||
}
|
||||
|
||||
// If the weekday of the first of the month does not equal 1 (Monday),
|
||||
// get days until the last monday before the month.
|
||||
while (date.getDay() !== startOfWeek) {
|
||||
days.push(new Date(date));
|
||||
date.setDate(date.getDate() + 1);
|
||||
}
|
||||
return days;
|
||||
}
|
||||
|
||||
events = (function() {
|
||||
|
||||
let colorSchemeLength = 29;
|
||||
for (var i = 0, max = events.length; i < max; i++) {
|
||||
let hash = 0;
|
||||
for (var j = 0, maxj = events[i].name.length; j < maxj; j++) {
|
||||
hash = events[i].name.charCodeAt(j) + hash;
|
||||
}
|
||||
hash = hash % (colorSchemeLength) - 1;
|
||||
|
||||
events[i].color = hash;
|
||||
}
|
||||
return events;
|
||||
|
||||
})();
|
||||
|
||||
let d = new Date();
|
||||
|
||||
let year;
|
||||
if (target.getAttribute("data-year") !== null) year = parseInt(target.getAttribute("data-year"));
|
||||
else year = d.getFullYear();
|
||||
|
||||
let month;
|
||||
if (target.getAttribute("data-month") !== null) month = parseInt(target.getAttribute("data-month") - 1);
|
||||
else month = d.getMonth();
|
||||
|
||||
// Create outer div
|
||||
let mdCalDiv = document.createElement("div");
|
||||
mdCalDiv.classList.add("mdCalendar");
|
||||
|
||||
/**
|
||||
* Creater header line of the calendar.
|
||||
*/
|
||||
(function() {
|
||||
|
||||
let mdCalTitleLine = document.createElement("header");
|
||||
mdCalTitleLine.classList.add("mdCTitleLine");
|
||||
|
||||
let mdCalTitle = document.createElement("h3");
|
||||
mdCalTitle.textContent = getTranslation(translations, "mon" + month.toString());
|
||||
if (year != d.getFullYear()) mdCalTitle.textContent = mdCalTitle.textContent + " (" + year + ")";
|
||||
mdCalTitleLine.appendChild(mdCalTitle);
|
||||
|
||||
let mdCalNav = document.createElement("div");
|
||||
mdCalNav.classList.add("mdCNav");
|
||||
mdCalTitleLine.appendChild(mdCalNav);
|
||||
|
||||
let mdCalNavPrev = document.createElement("a");
|
||||
mdCalNavPrev.href = target.getAttribute("data-prev");
|
||||
mdCalNavPrev.rel = "prev";
|
||||
mdCalNavPrev.classList.add("mdCNavPrev");
|
||||
mdCalNav.appendChild(mdCalNavPrev);
|
||||
|
||||
let mdCalNavNext = document.createElement("a");
|
||||
mdCalNavNext.href = target.getAttribute("data-next");
|
||||
mdCalNavNext.rel = "next";
|
||||
mdCalNavNext.classList.add("mdCNavNext");
|
||||
mdCalNav.appendChild(mdCalNavNext);
|
||||
|
||||
let mdCalNavToday = document.createElement("a");
|
||||
mdCalNavToday.href = target.getAttribute("data-today");
|
||||
mdCalNavToday.textContent = getTranslation(translations, "Today");
|
||||
mdCalNav.appendChild(mdCalNavToday);
|
||||
|
||||
mdCalTitleLine.appendChild(mdCalNav);
|
||||
mdCalDiv.appendChild(mdCalTitleLine);
|
||||
|
||||
})();
|
||||
|
||||
/**
|
||||
* Create table.
|
||||
*/
|
||||
let table = document.createElement("table");
|
||||
table.classList.add("mdCTable");
|
||||
|
||||
let thead = document.createElement("thead");
|
||||
let theadTr = document.createElement("tr");
|
||||
|
||||
for (let i = 1, max = 7; i < max; i++) {
|
||||
let th = document.createElement("th");
|
||||
th.textContent = getTranslation(translations, "dow" + i.toString());
|
||||
theadTr.appendChild(th);
|
||||
}
|
||||
let th = document.createElement("th");
|
||||
th.textContent = getTranslation(translations, "dow0");
|
||||
theadTr.appendChild(th);
|
||||
|
||||
thead.appendChild(theadTr);
|
||||
table.appendChild(thead);
|
||||
|
||||
let tbody = document.createElement("tbody");
|
||||
|
||||
let days = getDaysInMonth(month, year);
|
||||
let tr;
|
||||
|
||||
let daysTDs = [];
|
||||
|
||||
function createSingleEventOverlay(e, parentElement, data) {
|
||||
|
||||
let toolTip = document.createElement("table");
|
||||
toolTip.classList.add("mdCToolTip");
|
||||
|
||||
let tableData = [];
|
||||
tableData.push(["Title", data["name"]]);
|
||||
if (data["start"] !== undefined) tableData.push(["Start", data["start"]]);
|
||||
if (data["end"] !== undefined) tableData.push(["End", data["end"]]);
|
||||
if (data["place"] !== undefined) tableData.push(["Location", data["place"]]);
|
||||
|
||||
for (let i = 0, max= tableData.length; i < max; i++) {
|
||||
let nameRow = document.createElement("tr");
|
||||
let nameTh = document.createElement("th");
|
||||
nameTh.textContent = getTranslation(translations, tableData[i][0]);
|
||||
nameRow.appendChild(nameTh);
|
||||
let nameTd = document.createElement("td");
|
||||
nameTd.textContent = tableData[i][1];
|
||||
nameRow.appendChild(nameTd);
|
||||
toolTip.appendChild(nameRow);
|
||||
}
|
||||
|
||||
parentElement.appendChild(toolTip);
|
||||
|
||||
}
|
||||
|
||||
for (let i = 0, max= days.length; i < max; i++) {
|
||||
|
||||
// Begin a new table row every Monday.
|
||||
if (days[i].getDay() === startOfWeek) {
|
||||
tr = document.createElement("tr");
|
||||
tbody.appendChild(tr);
|
||||
}
|
||||
|
||||
// Create new TD per day and add appropriate classes.
|
||||
let td = document.createElement("td");
|
||||
if (days[i].getMonth() !== month) td.classList.add("mdCOtherMonth");
|
||||
if (days[i].getYear() == d.getYear() && days[i].getMonth() == d.getMonth() && days[i].getDate() == d.getDate()) td.classList.add("mdCToday");
|
||||
|
||||
tdTitle = document.createElement("time");
|
||||
tdTitle.textContent = days[i].getDate();
|
||||
|
||||
td.appendChild(tdTitle);
|
||||
tr.appendChild(td);
|
||||
|
||||
// Append dates.
|
||||
let dayTime = days[i].getTime();
|
||||
let dayTimeMinusDay = days[i].getTime() + 24 * 3600 * 1000;
|
||||
let dayTimePlusDay = days[i].getTime() - 0 * 3600 * 1000;
|
||||
for (let j = 0, maxj = events.length; j < maxj; j++) {
|
||||
if (Date.parse(events[j].start) > dayTimeMinusDay || Date.parse(events[j].end) < dayTimePlusDay) continue;
|
||||
|
||||
let eventSignifier = document.createElement("a");
|
||||
eventSignifier.classList.add("color" + events[j].color.toString());
|
||||
if (events[j].link) eventSignifier.href = events[j].link;
|
||||
|
||||
let eventSignifierText = document.createElement("span");
|
||||
eventSignifierText.textContent = events[j].name;
|
||||
eventSignifier.appendChild(eventSignifierText);
|
||||
|
||||
eventSignifier.addEventListener('mouseover', function(e) {
|
||||
createSingleEventOverlay(e, eventSignifier, events[j]);
|
||||
});
|
||||
eventSignifier.addEventListener('mouseout', function(e) {
|
||||
removeToolTips();
|
||||
});
|
||||
|
||||
td.appendChild(eventSignifier);
|
||||
|
||||
}
|
||||
|
||||
// Add posibility for overlay.
|
||||
tdTitle.addEventListener('click', function(e) {
|
||||
|
||||
tearDownById("mdCOverlay");
|
||||
|
||||
let overlay = document.createElement("div");
|
||||
overlay.id = "mdCOverlay";
|
||||
|
||||
let eventTitleBar = document.createElement("div");
|
||||
eventTitleBar.classList.add("mdCOverlayTitleBar");
|
||||
overlay.appendChild(eventTitleBar);
|
||||
|
||||
let title = document.createElement("span");
|
||||
title.classList.add("mdCOverlayTitle");
|
||||
title.textContent = days[i].toLocaleDateString(calLocale);
|
||||
eventTitleBar.appendChild(title);
|
||||
|
||||
let closer = document.createElement("span");
|
||||
closer.classList.add("mdCOverlayClose");
|
||||
closer.addEventListener('click', function(e) {
|
||||
if (debugging === true) console.log("Clicked close button: Tearing down daily agenda.");
|
||||
tearDownById("mdCOverlay");
|
||||
});
|
||||
eventTitleBar.appendChild(closer);
|
||||
|
||||
let ul = document.createElement("ul");
|
||||
|
||||
// Append events.
|
||||
for (let j = 0, maxj = events.length; j < maxj; j++) {
|
||||
|
||||
let start = new Date(events[j].start);
|
||||
let end = new Date(events[j].end);
|
||||
|
||||
if (start.getTime() > dayTime || end.getTime() < dayTimePlusDay) continue;
|
||||
|
||||
let eventLi = document.createElement("li");
|
||||
|
||||
let eventSignifier = document.createElement("a");
|
||||
eventSignifier.textContent = events[j].name;
|
||||
if (events[j].link) eventSignifier.href = events[j].link;
|
||||
eventLi.appendChild(eventSignifier);
|
||||
|
||||
let eventP = document.createElement("p");
|
||||
eventP.textContent = start.toLocaleDateString(calLocale) + " - " + end.toLocaleDateString(calLocale);
|
||||
if (events[j].place !== undefined) eventP.textContent = eventP.textContent + ", " + events[j].place;
|
||||
eventLi.appendChild(eventP);
|
||||
|
||||
let eventDesc = document.createElement("p");
|
||||
eventDesc.textContent = events[j].description;
|
||||
eventLi.appendChild(eventDesc);
|
||||
|
||||
ul.appendChild(eventLi);
|
||||
|
||||
}
|
||||
|
||||
overlay.appendChild(ul);
|
||||
document.getElementsByTagName("body")[0].appendChild(overlay);
|
||||
|
||||
});
|
||||
|
||||
if (td.childElementCount > 6) td.classList.add("mdCManyElements");
|
||||
daysTDs[days[i].getFullYear() + "-" + days[i].getMonth() + "-" + days[i].getDate()] = td;
|
||||
|
||||
}
|
||||
|
||||
table.appendChild(tbody);
|
||||
mdCalDiv.appendChild(table);
|
||||
|
||||
target.appendChild(mdCalDiv);
|
||||
|
||||
// Enable closing overlay by pressing escape.
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.keyCode !== 27) return;
|
||||
if (debugging === true) console.log("Pressed escape: Tearing down daily agenda.");
|
||||
tearDownById("mdCOverlay");
|
||||
});
|
||||
|
||||
return daysTDs;
|
||||
}
|
||||
|
||||
(function() {
|
||||
|
||||
let calendars = document.getElementsByClassName("mdCalendar");
|
||||
for (let i = 0, max = calendars.length; i < max; i++) {
|
||||
|
||||
queryPage(
|
||||
encodeURI(calendars[i].getAttribute("data-src")),
|
||||
function (request) {
|
||||
if (debugging === true) console.log("Loaded\n" + request.response);
|
||||
let elements = JSON.parse(request.response);
|
||||
let tCalendar = createCalendarTable(calendars[i], elements);
|
||||
});
|
||||
}
|
||||
}
|
||||
)();
|
||||
|
||||
});
|
66
object.php
Normal file
66
object.php
Normal file
|
@ -0,0 +1,66 @@
|
|||
<?PHP
|
||||
/**
|
||||
* This file displays object detail pages as fetched from museum-digital.
|
||||
*
|
||||
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
|
||||
*/
|
||||
|
||||
// Include functions and settings.
|
||||
|
||||
require_once __DIR__ . "/inc/functions.php";
|
||||
|
||||
// Check validity of request.
|
||||
|
||||
if (!isset($_GET['id']) or !is_numeric($_GET['id'])) {
|
||||
echo printErrorPage("Object does not exist.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ensure working environment for frontend.
|
||||
|
||||
ensureEnvironment();
|
||||
$pages = loadPublicPages(); // Load overview of pages.
|
||||
|
||||
$contents = json_decode(queryCachePage($settings['mdVersion'] . "?t=objekt&oges=" . urlencode($_GET['id']) . "&output=json", "object", $settings), true);
|
||||
|
||||
if (!$contents || (isset($contents[0]) and $contents[0] == "There is no object with this ID yet.")) {
|
||||
echo printErrorPage("Temporarily unavailable.");
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Output
|
||||
*/
|
||||
$addToHead = '
|
||||
<link rel="canonical" href="' . $settings['mdVersion'] . 'index.php?t=objekt&oges=' . $contents['object_id'] . '" />';
|
||||
|
||||
echo printPublicHead($settings, $_GET['id'], $settings['pageTitle'] . " - " . $contents['object_name'], $settings['logo'], $addToHead);
|
||||
echo printPublicHeader($settings['pageTitle']);
|
||||
echo printStaticPagePart("banner", "header"); // Print aside (if need be)
|
||||
|
||||
echo generatePublicNav($pages);
|
||||
|
||||
echo '
|
||||
<div id="mainWrapper">
|
||||
';
|
||||
|
||||
// Print main content
|
||||
echo '
|
||||
<main>';
|
||||
|
||||
echo drawObjectDetails($contents, $settings);
|
||||
|
||||
echo '
|
||||
</main>
|
||||
';
|
||||
|
||||
echo printStaticPagePart("aside", "aside"); // Print aside (if need be)
|
||||
|
||||
echo '
|
||||
</div>';
|
||||
|
||||
echo printStaticPagePart("footer", "footer"); // Print footer (if need be)
|
||||
|
||||
echo printPublicEnd();
|
||||
|
||||
?>
|
73
search.php
Normal file
73
search.php
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?PHP
|
||||
/**
|
||||
* This file runs the search.
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Joshua Ramon Enslin <joshua@jrenslin.de>
|
||||
*/
|
||||
|
||||
// Include functions and settings.
|
||||
|
||||
require_once __DIR__ . "/inc/functions.php";
|
||||
require_once __DIR__ . "/inc/search.php";
|
||||
|
||||
// Ensure working environment for frontend.
|
||||
|
||||
ensureEnvironment();
|
||||
$pages = loadPublicPages(); // Load overview of pages.
|
||||
|
||||
/*
|
||||
* Load data.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Output
|
||||
*/
|
||||
|
||||
echo printPublicHead($settings, "search", $settings['pageTitle'], $settings['logo']);
|
||||
echo printPublicHeader($settings['pageTitle']);
|
||||
echo printStaticPagePart("banner", "header"); // Print aside (if need be)
|
||||
|
||||
echo generatePublicNav($pages);
|
||||
|
||||
echo '
|
||||
<div id="mainWrapper">
|
||||
';
|
||||
|
||||
// Print main content
|
||||
echo '
|
||||
<main>';
|
||||
|
||||
if (!isset($_GET['q'])) {
|
||||
|
||||
echo '
|
||||
<h1><span class="toTranslate" data-content="Search"></span></h1>
|
||||
<form action="" method="GET">
|
||||
<input type="search" name="q" />
|
||||
</form>
|
||||
';
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
echo '<h1><span class="toTranslate" data-content="SearchingFor"></span> "' . $_GET['q'] . '"</h1>';
|
||||
$resultsInPages = searchInPages($_GET['q']);
|
||||
print_r($resultsInPages);
|
||||
|
||||
}
|
||||
|
||||
echo '
|
||||
</main>
|
||||
';
|
||||
|
||||
echo printStaticPagePart("aside", "aside"); // Print aside (if need be)
|
||||
|
||||
echo '
|
||||
</div>';
|
||||
|
||||
echo printStaticPagePart("footer", "footer"); // Print footer (if need be)
|
||||
|
||||
echo printPublicEnd();
|
||||
|
||||
?>
|
|
@ -2,6 +2,12 @@
|
|||
* Default theme for the backend of md:cms.
|
||||
*/
|
||||
|
||||
/****************************
|
||||
* Imports
|
||||
*/
|
||||
|
||||
@import 'mdEmbeds.css';
|
||||
|
||||
/****************************
|
||||
* Load fonts
|
||||
*/
|
||||
|
@ -82,7 +88,7 @@ aside > * { display: block; padding: 1em; border: 1px solid #D6D6D6; }
|
|||
|
||||
body > header:nth-child(2) { margin: 0; padding: 0; }
|
||||
body > header:nth-child(2) p { margin: 0; padding: 0; }
|
||||
body > header:nth-child(2) img { width: 100vw; height: 20vh; object-fit: cover; margin-bottom: -.4em; }
|
||||
body > header:nth-child(2) img { width: 100%; height: 20vh; object-fit: cover; margin-bottom: -.4em; }
|
||||
|
||||
/************
|
||||
* Main wrapper
|
||||
|
@ -104,7 +110,7 @@ body > nav { display: block; background: #212121; color: #EEE;
|
|||
border: 1px solid #D6D6D6; border-width: 0; padding: 0 5vw; }
|
||||
body > nav ul { list-style: none; margin: 0; padding: 0 0; }
|
||||
body > nav li { position: relative; }
|
||||
body > nav > ul { display: block; border-bottom: 1px solid #D6D6D6; }
|
||||
body > nav > ul { display: block; }
|
||||
body > nav > ul > li { display: inline-block; }
|
||||
body > nav > ul > li ul { position: absolute; left: 0; top: 100%;
|
||||
background: #424242; color: #EEE; z-index: 2; animation: fade-in .4s; }
|
||||
|
|
54
themes/default/mdEmbeds.css
Normal file
54
themes/default/mdEmbeds.css
Normal file
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* Default theme for the backend of md:cms:
|
||||
* Styles for data embedded from museum-digital.
|
||||
*/
|
||||
|
||||
/**********
|
||||
* Simple tiles for displaying an object.
|
||||
*/
|
||||
|
||||
div.objTile { display: inline-block; width: 200px; border: 1px solid #D6D6D6; text-align: center;
|
||||
transition: background .4s, box-shadow .4s; }
|
||||
div.objTile > div { position: relative; padding: .5em .5em 1.5em .5em; }
|
||||
div.objTile h4 { margin: 0; padding: 0 .5em; }
|
||||
div.objTile img { max-width: 198px; }
|
||||
div.objTile:hover { background: #F2F2F2; box-shadow: 1px 1px 3px #D6D6D6, -1px -1px 3px #D6D6D6; }
|
||||
|
||||
div.objTile > div > div { color: #888; font-size: .8em; }
|
||||
div.objTile > div > div > a { position: absolute; top: 100%; left: -1px;
|
||||
display: none; max-width: 50%; padding: .3em;
|
||||
background: #FFF; text-align: left; border: 1px solid #D6D6D6;
|
||||
transition: background .4s, color .4s; }
|
||||
|
||||
div.objTile:hover > div > div > a { display: block; animation: fade-in .4s; }
|
||||
div.objTile > div > div > a:last-child { left: initial; right: -1px; text-align: right; }
|
||||
div.objTile > div > div > a:hover { background: #EEE; color: #212121; }
|
||||
|
||||
/**********
|
||||
* Object details.
|
||||
*/
|
||||
|
||||
div.objDetails { }
|
||||
div.objDetails dt { font-weight: bold; margin-top: .5em; }
|
||||
div.objDetails dd { margin-left: 0; padding-left: 0; }
|
||||
div.objDetails .objMainImg { max-width: 200px; margin: .5em 1em 1em 0; float: left;
|
||||
border: 1px solid #D6D6D6; transition: max-width .4s; }
|
||||
div.objDetails .objMainImg:hover { max-width: 100vw; max-height: 80vh; float: initial; }
|
||||
|
||||
.metadataLine { margin-top: 2.5em; color: #666; border-top: 1px solid #D6D6D6; }
|
||||
.metadataLine > span { margin-right: 2em; font-size: .95em; font-style: italic; }
|
||||
|
||||
/*****
|
||||
* Events on object detail page.
|
||||
*/
|
||||
|
||||
.events { display: block; max-width: 100%; width: auto; margin: 0 0 1em 0; }
|
||||
.events > * { display: inline-block; margin: 0 1em 1em 0; padding: 0 1em; border: 1px solid #D6D6D6;
|
||||
vertical-align: top; transition: box-shadow .4s; }
|
||||
.events h5 { margin: 0; padding: .5em 1em; font-size: .9em; background: #F2F2F2; color: #646464; }
|
||||
.events tr * { padding: .1em .5em; vertical-align: middle; font-size: .95em; }
|
||||
.events th { font-weight: normal; color: #646464; }
|
||||
.events table { margin: .5em 0; }
|
||||
|
||||
.events > *:hover { box-shadow: 1px 1px 3px #D6D6D6, -1px -1px 3px #D6D6D6; }
|
||||
.events tr:hover { background: initial; }
|
1
themes/imports.css
Normal file
1
themes/imports.css
Normal file
|
@ -0,0 +1 @@
|
|||
@import 'mdCalendar.css';
|
151
themes/mdCalendar.css
Normal file
151
themes/mdCalendar.css
Normal file
|
@ -0,0 +1,151 @@
|
|||
/**
|
||||
* CSS file for mdCalendar.
|
||||
*/
|
||||
|
||||
.mdCalendar { display: block; }
|
||||
.mdCTable { width: 100%; table-layout: fixed; font-size: .9em; }
|
||||
|
||||
/**
|
||||
* Table
|
||||
*/
|
||||
|
||||
.mdCTable thead tr { border: 1px solid #D6D6D6; }
|
||||
|
||||
.mdCTable th { color: #646464; font-weight: normal; text-align: center; }
|
||||
.mdCTable td { padding: 0; height: 10em; background: #FFF; border: 1px solid #D6D6D6; vertical-align: top; }
|
||||
.mdCTable *:hover { z-index: 2; }
|
||||
|
||||
.mdCTable time { display: block; color: #646464; border-bottom: 1px dashed #D6D6D6; font-weight: bold;
|
||||
cursor: pointer; transition: background .4s, color .4s; }
|
||||
.mdCTable time:hover { background: #03A9F4; color: #FFF; }
|
||||
.mdCTable td > * { display: block; padding: .3em .5em; line-height: 1.2em; }
|
||||
|
||||
.mdCTable td > a { position: relative; margin: .2em; padding-left: .7em;
|
||||
background: rgba(240, 240, 240, .2); color: #424242; border: 1px solid #D6D6D6;
|
||||
cursor: pointer; transition: background .4s, color .4s; }
|
||||
.mdCTable td > a:hover { background: #333; color: #FFF; z-index: 2; }
|
||||
|
||||
.mdCTable td > a:before { content: " "; position: absolute; left: 0; top: 0; width: .5em; height: 100%; }
|
||||
|
||||
.mdCTable .mdCToday { background: #FAFAFA; }
|
||||
.mdCTable .mdCOtherMonth { color: #646464; background: #EEE; }
|
||||
|
||||
/**
|
||||
* Table head.
|
||||
*/
|
||||
|
||||
.mdCTitleLine { display: table; width: 100%; margin: .5em 0; padding: 0; }
|
||||
.mdCTitleLine > * { display: table-cell; vertical-align: middle; }
|
||||
|
||||
.mdCTitleLine > h3 { font-weight: normal; color: #424242; }
|
||||
|
||||
.mdCNav { width: 200px; color: #424242; text-align: right; }
|
||||
|
||||
.mdCNav > * { transition: background .4s, color .4s; font-size: 1em; padding: .5em; }
|
||||
.mdCNav > *:hover { background: #F2F2F2; color: #000; }
|
||||
.mdCNavPrev:before { content: "<"; }
|
||||
.mdCNavNext:before { content: ">"; }
|
||||
|
||||
/**
|
||||
* Alternative display of events in case there are too many for a day.
|
||||
*/
|
||||
|
||||
.mdCTable td.mdCManyElements > a { display: inline-block; height: 1.1em; width: 1.1em; }
|
||||
.mdCTable td.mdCManyElements > a:before { width: 100%; }
|
||||
.mdCTable td.mdCManyElements > a span { display: none; }
|
||||
|
||||
@media screen and (max-width: 75em) {
|
||||
.mdCTable td > a { display: inline-block; height: 1.1em; width: 1.1em; }
|
||||
.mdCTable td > a span { display: none; }
|
||||
.mdCTable td > a:before { width: 100%; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Tooltips
|
||||
*/
|
||||
.mdCToolTip { position: absolute; top: calc(100% + 22px); left: 50%; transform: translate(-50%, 0);
|
||||
width: 300px; padding: 1em 0;
|
||||
background: #FFF; border: 1px solid #646464;
|
||||
z-index: 1000; animation: fade-in-tooltip .4s; }
|
||||
|
||||
.mdCToolTip:before,
|
||||
.mdCToolTip:after { content: " "; position: absolute; bottom: calc(100% - 1px); left: 50%; transform: translate(-50%, 0);
|
||||
display: block; width: 0; height: 0;
|
||||
border-left: 21px solid transparent; border-right: 21px solid transparent;
|
||||
border-bottom: 21px solid #FFF; z-index: 1002; }
|
||||
.mdCToolTip:after { border-left: 22px solid transparent; border-right: 22px solid transparent;
|
||||
border-bottom: 22px solid #646464; z-index: 1001; }
|
||||
.mdCToolTip tr * { height: auto; padding: .5em; vertical-align: top; text-align: left; color: #424242; border: 0; }
|
||||
.mdCToolTip tr:first-child * { padding-top: 1em; }
|
||||
.mdCToolTip tr:last-child * { padding-bottom: 1em; }
|
||||
|
||||
/**
|
||||
* Overlay
|
||||
*/
|
||||
|
||||
#mdCOverlay { position: fixed; left: 50%; top: 50%; transform: translate(-50%, -50%);
|
||||
max-height: 80vh; width: 600px; max-width: 80vw; background: #FFF;
|
||||
box-shadow: 2px 2px 4px #D6D6D6, -2px -2px 4px #D6D6D6;
|
||||
overflow-y: auto; z-index: 1003; }
|
||||
|
||||
.mdCOverlayTitleBar { display: table; width: 100%; }
|
||||
.mdCOverlayTitleBar > * { display: table-cell; padding: .5rem 1.5rem; background: #EEE; color: #000; }
|
||||
|
||||
.mdCOverlayClose { width: 5em; text-align: right; }
|
||||
.mdCOverlayClose:before { content: "x"; display: inline-block; padding: .1em .7em .3em .7em;
|
||||
background: #03A9F4; color: #FFF; text-align: center;
|
||||
border-radius: 100%; cursor: pointer; transition: background .4s; color .4s; }
|
||||
.mdCOverlayClose:hover:before { background: #FFF; color: #03A9F4; }
|
||||
|
||||
#mdCOverlay ul { list-style: none; margin: 1em 1.5rem; padding: 0; }
|
||||
#mdCOverlay li { margin: 0; padding: 1em 0; border-bottom: 1px solid #D6D6D6; }
|
||||
#mdCOverlay li > a:first-child { color: #424242; font-weight: bold; }
|
||||
|
||||
/**
|
||||
* @var {string[]} colorScheme Material design colors as taken from https://material.io/design/color/the-color-system.html#tools-for-picking-colors
|
||||
*/
|
||||
|
||||
.color0:before { background: #F44336; }
|
||||
.color1:before { background: #E53935; }
|
||||
.color2:before { background: #D32F2F; }
|
||||
.color3:before { background: #C62828; }
|
||||
.color4:before { background: #B71C1C; }
|
||||
|
||||
.color5:before { background: #3F51B5; }
|
||||
.color6:before { background: #3949AB; }
|
||||
.color7:before { background: #303F9F; }
|
||||
.color8:before { background: #283593; }
|
||||
.color9:before { background: #1A237E; }
|
||||
|
||||
.color10:before { background: #2196F3; }
|
||||
.color11:before { background: #1E88E5; }
|
||||
.color12:before { background: #1976D2; }
|
||||
.color13:before { background: #1565C0; }
|
||||
.color14:before { background: #0D47A1; }
|
||||
|
||||
.color15:before { background: #03A9F4; }
|
||||
.color16:before { background: #039BE5; }
|
||||
.color17:before { background: #0288D1; }
|
||||
.color18:before { background: #0277BD; }
|
||||
.color19:before { background: #01579B; }
|
||||
|
||||
.color20:before { background: #00BCD4; }
|
||||
.color21:before { background: #00ACC1; }
|
||||
.color22:before { background: #0097A7; }
|
||||
.color23:before { background: #00838F; }
|
||||
.color24:before { background: #006064; }
|
||||
|
||||
.color25:before { background: #4CAF50; }
|
||||
.color26:before { background: #43A047; }
|
||||
.color27:before { background: #388E3C; }
|
||||
.color28:before { background: #2E7D32; }
|
||||
.color29:before { background: #1B5E20; }
|
||||
|
||||
/**
|
||||
* Animations
|
||||
*/
|
||||
|
||||
@keyframes fade-in-tooltip {
|
||||
from { top: calc(100% + 19px); opacity: 0.1; }
|
||||
to { top: calc(100% + 22px); opacity: 1.0; }
|
||||
}
|
Reference in New Issue
Block a user