Simplify Font Awesome loading to scan three candidate paths for all.css, register whichever exists via WebAssetManager, then call useStyle(). Falls back to joomla.asset.json registry if no local file found. Covers both standard Joomla media path and SFTP deploy layout. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
568 lines
21 KiB
PHP
568 lines
21 KiB
PHP
<?php
|
|
/* Copyright (C) 2025 Moko Consulting <hello@mokoconsulting.tech>
|
|
|
|
This file is part of a Moko Consulting project.
|
|
|
|
SPDX-License-Identifier: GPL-3.0-or-later
|
|
*/
|
|
|
|
|
|
defined('_JEXEC') or die;
|
|
|
|
use Joomla\CMS\Factory;
|
|
use Joomla\CMS\HTML\HTMLHelper;
|
|
use Joomla\CMS\Language\Text;
|
|
use Joomla\CMS\Uri\Uri;
|
|
use Joomla\CMS\Component\ComponentHelper;
|
|
|
|
/** @var Joomla\CMS\Document\HtmlDocument $this */
|
|
|
|
$app = Factory::getApplication();
|
|
$input = $app->getInput();
|
|
$document = $app->getDocument();
|
|
$wa = $document->getWebAssetManager();
|
|
|
|
// Template params
|
|
$params_LightColorName = (string) $this->params->get('colorLightName', 'standard'); // standard|custom
|
|
|
|
$params_DarkColorName = (string) $this->params->get('colorDarkName', 'standard'); // standard|custom
|
|
|
|
$params_googletagmanager = $this->params->get('googletagmanager', false);
|
|
$params_googletagmanagerid = $this->params->get('googletagmanagerid', null);
|
|
$params_googleanalytics = $this->params->get('googleanalytics', false);
|
|
$params_googleanalyticsid = $this->params->get('googleanalyticsid', null);
|
|
$params_googlesitekey = $this->params->get('googlesitekey', null);
|
|
$params_custom_head_start = $this->params->get('custom_head_start', null);
|
|
$params_custom_head_end = $this->params->get('custom_head_end', null);
|
|
$params_developmentmode = $this->params->get('developmentmode', false) || $app->get('debug', false);
|
|
$params_favicon_source = (string) $this->params->get('favicon_source', '');
|
|
|
|
// Theme params
|
|
$params_theme_enabled = $this->params->get('theme_enabled', 1);
|
|
$params_theme_control_type = (string) $this->params->get('theme_control_type', 'radios');
|
|
$params_theme_fab_enabled = $this->params->get('theme_fab_enabled', 1);
|
|
$params_theme_fab_pos = $this->params->get('theme_fab_pos', 'br');
|
|
|
|
// Accessibility params
|
|
$params_a11y_toolbar = $this->params->get('a11y_toolbar_enabled', 1);
|
|
$params_a11y_resize = $this->params->get('a11y_text_resize', 1);
|
|
$params_a11y_invert = $this->params->get('a11y_color_inversion', 1);
|
|
$params_a11y_contrast = $this->params->get('a11y_high_contrast', 1);
|
|
$params_a11y_links = $this->params->get('a11y_highlight_links', 1);
|
|
$params_a11y_font = $this->params->get('a11y_readable_font', 1);
|
|
$params_a11y_animations = $this->params->get('a11y_pause_animations', 1);
|
|
$params_a11y_pos = (string) $this->params->get('a11y_toolbar_pos', 'tl');
|
|
|
|
// Detecting Active Variables
|
|
$option = $input->getCmd('option', '');
|
|
$view = $input->getCmd('view', '');
|
|
$layout = $input->getCmd('layout', '');
|
|
$task = $input->getCmd('task', '');
|
|
$itemid = $input->getCmd('Itemid', '');
|
|
$sitenameR = $app->get('sitename'); // raw for title composition
|
|
$sitename = htmlspecialchars($sitenameR, ENT_QUOTES, 'UTF-8');
|
|
$menu = $app->getMenu()->getActive();
|
|
$pageclass = $menu !== null ? $menu->getParams()->get('pageclass_sfx', '') : '';
|
|
|
|
// Template/Media path
|
|
$templatePath = 'media/templates/site/mokocassiopeia';
|
|
|
|
// Favicon generation
|
|
$faviconHeadTags = '';
|
|
if ($params_favicon_source) {
|
|
require_once __DIR__ . '/helper/favicon.php';
|
|
$faviconSourceAbs = JPATH_ROOT . '/' . ltrim($params_favicon_source, '/');
|
|
$faviconOutputDir = JPATH_ROOT . '/images/favicons';
|
|
$faviconUrlBase = Uri::root(true) . '/images/favicons';
|
|
|
|
if (MokoFaviconHelper::generate($faviconSourceAbs, $faviconOutputDir)) {
|
|
$faviconHeadTags = MokoFaviconHelper::getHeadTags($faviconUrlBase);
|
|
}
|
|
}
|
|
|
|
// Minification: dev mode ON → delete .min files; OFF → regenerate if stale
|
|
require_once __DIR__ . '/helper/minify.php';
|
|
MokoMinifyHelper::sync(JPATH_ROOT . '/' . $templatePath, (bool) $params_developmentmode);
|
|
|
|
// Core template CSS + JS — use minified when not in development mode
|
|
if ($params_developmentmode) {
|
|
$wa->useStyle('template.base'); // css/template.css
|
|
$wa->useScript('template.js'); // js/template.js
|
|
} else {
|
|
$wa->useStyle('template.base.min'); // css/template.min.css
|
|
$wa->useScript('template.js.min'); // js/template.min.js
|
|
}
|
|
|
|
// Load Osaka font for site title
|
|
$wa->useStyle('template.font.osaka');
|
|
|
|
// Load GTM script if GTM is enabled
|
|
if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) {
|
|
$wa->useScript('gtm.js');
|
|
}
|
|
|
|
/**
|
|
* VirtueMart detection:
|
|
* - Component must exist and be enabled
|
|
*/
|
|
$isVirtueMartActive = ComponentHelper::isEnabled('com_virtuemart', true);
|
|
|
|
if ($isVirtueMartActive) {
|
|
/**
|
|
* Load a VirtueMart-specific stylesheet defined in your template manifest.
|
|
* This assumes you defined an asset named "template.virtuemart".
|
|
*/
|
|
$wa->useStyle('vendor.vm');
|
|
}
|
|
|
|
// Font scheme (external or local) + CSS custom properties
|
|
$params_FontScheme = $this->params->get('useFontScheme', false);
|
|
$fontStyles = '';
|
|
|
|
if ($params_FontScheme) {
|
|
if (stripos($params_FontScheme, 'https://') === 0) {
|
|
$this->getPreloadManager()->preload($params_FontScheme, ['as' => 'style', 'crossorigin' => 'anonymous']);
|
|
$wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, [], [
|
|
'media' => 'print',
|
|
'rel' => 'lazy-stylesheet',
|
|
'onload' => 'this.media=\'all\'',
|
|
'crossorigin' => 'anonymous'
|
|
]);
|
|
|
|
if (preg_match_all('/family=([^?:]*):/i', $params_FontScheme, $matches) > 0) {
|
|
$fontStyles = '--font-family-body: "' . str_replace('+', ' ', $matches[1][0]) . '", sans-serif;' . "\n";
|
|
$fontStyles .= '--font-family-headings: "' . str_replace('+', ' ', isset($matches[1][1]) ? $matches[1][1] : $matches[1][0]) . '", sans-serif;' . "\n";
|
|
$fontStyles .= '--font-weight-normal: 400;' . "\n";
|
|
$fontStyles .= '--font-weight-headings: 700;';
|
|
}
|
|
} else {
|
|
$wa->registerAndUseStyle('fontscheme.current', $params_FontScheme, ['version' => 'auto'], [
|
|
'media' => 'print',
|
|
'rel' => 'lazy-stylesheet',
|
|
'onload' => 'this.media=\'all\''
|
|
]);
|
|
$this->getPreloadManager()->preload(
|
|
$wa->getAsset('style', 'fontscheme.current')->getUri() . '?' . $this->getMediaVersion(),
|
|
['as' => 'style']
|
|
);
|
|
}
|
|
}
|
|
|
|
// -------------------------------------
|
|
// Brand: logo from params OR siteTitle
|
|
// -------------------------------------
|
|
$brandHtml = '';
|
|
$logoFile = (string) $this->params->get('logoFile');
|
|
|
|
if ($logoFile !== '') {
|
|
$brandHtml = HTMLHelper::_(
|
|
'image',
|
|
Uri::root(false) . htmlspecialchars($logoFile, ENT_QUOTES, 'UTF-8'),
|
|
$sitename,
|
|
['class' => 'logo d-inline-block', 'loading' => 'eager', 'decoding' => 'async'],
|
|
false,
|
|
0
|
|
);
|
|
} else {
|
|
// If no logo file, show the title (defaults to "MokoCassiopeia" if not set)
|
|
$siteTitle = $this->params->get('siteTitle', 'MokoCassiopeia');
|
|
$brandHtml = '<span class="site-title" title="' . $sitename . '">'
|
|
. htmlspecialchars($siteTitle, ENT_COMPAT, 'UTF-8')
|
|
. '</span>';
|
|
}
|
|
|
|
// Layout flags
|
|
$hasClass = '';
|
|
if ($this->countModules('sidebar-left', true)) { $hasClass .= ' has-sidebar-left'; }
|
|
if ($this->countModules('sidebar-right', true)) { $hasClass .= ' has-sidebar-right'; }
|
|
if ($this->countModules('drawer-left', true)) { $hasClass .= ' has-drawer-left'; }
|
|
if ($this->countModules('drawer-right', true)) { $hasClass .= ' has-drawer-right'; }
|
|
|
|
// Smart Bootstrap component loading - only load what's needed
|
|
if ($this->countModules('drawer-left', true) || $this->countModules('drawer-right', true)) {
|
|
// Load Bootstrap Offcanvas component for drawers
|
|
HTMLHelper::_('bootstrap.offcanvas');
|
|
}
|
|
|
|
// Container
|
|
$wrapper = $this->params->get('fluidContainer') ? 'wrapper-fluid' : 'wrapper-static';
|
|
$stickyHeader = $this->params->get('stickyHeader') ? 'position-sticky sticky-top' : '';
|
|
|
|
// Meta
|
|
$this->setMetaData('viewport', 'width=device-width, initial-scale=1');
|
|
if (!empty($params_googlesitekey)) {
|
|
$this->setMetaData('google-site-verification', htmlspecialchars($params_googlesitekey, ENT_QUOTES, 'UTF-8'));
|
|
}
|
|
|
|
// Font Awesome 7 — Kit (CDN) or local files
|
|
$faKitCode = trim((string) $this->params->get('fA6KitCode', ''));
|
|
if ($faKitCode !== '') {
|
|
HTMLHelper::_('script', 'https://kit.fontawesome.com/' . $faKitCode . '.js', ['crossorigin' => 'anonymous']);
|
|
} else {
|
|
// Load local FA7 Free — all.css via WebAsset
|
|
// Resolve the actual filesystem path: media dir (Joomla install) or template dir (SFTP deploy)
|
|
$faCssFile = $params_developmentmode ? 'vendor/fa7free/css/all.css' : 'vendor/fa7free/css/all.min.css';
|
|
$faCandidates = [
|
|
$templatePath . '/' . $faCssFile, // media/templates/site/mokocassiopeia/...
|
|
'templates/site/' . $this->template . '/media/' . $faCssFile, // templates/site/mokocassiopeia/media/...
|
|
];
|
|
|
|
// Also check via __DIR__ for edge cases
|
|
$faFromDir = __DIR__ . '/media/' . $faCssFile;
|
|
if (is_file($faFromDir)) {
|
|
$faCandidates[] = ltrim(str_replace('\\', '/', str_replace(JPATH_ROOT, '', $faFromDir)), '/');
|
|
}
|
|
|
|
$faRegistered = false;
|
|
foreach ($faCandidates as $faPath) {
|
|
if (is_file(JPATH_ROOT . '/' . $faPath)) {
|
|
$wa->registerStyle('vendor.fa7free.all', $faPath);
|
|
$faRegistered = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Use the asset — either our dynamic registration or the one from joomla.asset.json
|
|
try {
|
|
$wa->useStyle('vendor.fa7free.all');
|
|
} catch (\Throwable $e) {
|
|
// All paths exhausted — FA icons will rely on the IcoMoon compat layer
|
|
}
|
|
}
|
|
$params_leftIcon = htmlspecialchars($this->params->get('drawerLeftIcon', 'fa-solid fa-chevron-left'), ENT_COMPAT, 'UTF-8');
|
|
$params_rightIcon = htmlspecialchars($this->params->get('drawerRightIcon', 'fa-solid fa-chevron-right'), ENT_COMPAT, 'UTF-8');
|
|
|
|
// Load theme palette stylesheets — minified when not in development mode
|
|
$suffix = $params_developmentmode ? '' : '.min';
|
|
$wa->useStyle('template.light.standard' . $suffix);
|
|
$wa->useStyle('template.dark.standard' . $suffix);
|
|
|
|
// Load custom palettes only if selected in template configuration AND files exist
|
|
if ($params_LightColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/light.custom.css'))
|
|
{
|
|
$wa->useStyle('template.light.custom' . $suffix);
|
|
}
|
|
if ($params_DarkColorName === 'custom' && file_exists(JPATH_ROOT . '/media/templates/site/mokocassiopeia/css/theme/dark.custom.css'))
|
|
{
|
|
$wa->useStyle('template.dark.custom' . $suffix);
|
|
}
|
|
|
|
// Load user assets last (after all other styles and scripts)
|
|
$wa->useStyle('template.user'); // css/user.css
|
|
$wa->useScript('user.js'); // js/user.js
|
|
?>
|
|
<!DOCTYPE html>
|
|
<html lang="<?php echo $this->language; ?>" dir="<?php echo $this->direction; ?>">
|
|
<head>
|
|
<?php if (trim($params_custom_head_start)) : ?><?php echo $params_custom_head_start; ?><?php endif; ?>
|
|
<jdoc:include type="head" />
|
|
<?php if ($faviconHeadTags) : ?>
|
|
<?php echo $faviconHeadTags; ?>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($params_theme_enabled) : ?>
|
|
<script>
|
|
// Early theme application to avoid FOUC
|
|
(function () {
|
|
try {
|
|
var stored = localStorage.getItem('theme');
|
|
var prefersDark = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
var theme = stored ? stored : (prefersDark ? 'dark' : 'light');
|
|
document.documentElement.setAttribute('data-bs-theme', theme);
|
|
document.documentElement.setAttribute('data-aria-theme', theme);
|
|
} catch (e) {}
|
|
})();
|
|
</script>
|
|
<?php endif; ?>
|
|
|
|
<script>
|
|
// Facebook in-app browser warning banner
|
|
window.addEventListener('DOMContentLoaded', function () {
|
|
var ua = navigator.userAgent || navigator.vendor || window.opera;
|
|
var isFacebookBrowser = ua.indexOf('FBAN') > -1 || ua.indexOf('FBAV') > -1;
|
|
if (isFacebookBrowser) {
|
|
var warning = document.createElement('div');
|
|
warning.textContent = '⚠️ KNOWN ISSUE: Images do not load in Facebook Web browser. Please open in external browser for full experience.';
|
|
warning.style.position = 'fixed';
|
|
warning.style.top = '0';
|
|
warning.style.left = '0';
|
|
warning.style.right = '0';
|
|
warning.style.zIndex = '10000';
|
|
warning.style.backgroundColor = '#007bff';
|
|
warning.style.color = '#fff';
|
|
warning.style.padding = '15px';
|
|
warning.style.textAlign = 'center';
|
|
warning.style.fontWeight = 'bold';
|
|
warning.style.fontSize = '16px';
|
|
warning.style.boxShadow = '0 2px 5px rgba(0,0,0,0.2)';
|
|
document.body.appendChild(warning);
|
|
}
|
|
});
|
|
</script>
|
|
|
|
|
|
<?php if (trim($params_custom_head_end)) : ?><?php echo $params_custom_head_end; ?><?php endif; ?>
|
|
</head>
|
|
<body data-bs-spy="scroll" data-bs-target="#toc"
|
|
data-theme-fab-enabled="<?php echo $params_theme_fab_enabled ? '1' : '0'; ?>"
|
|
data-theme-fab-pos="<?php echo htmlspecialchars($params_theme_fab_pos, ENT_QUOTES, 'UTF-8'); ?>"
|
|
data-a11y-toolbar="<?php echo $params_a11y_toolbar ? '1' : '0'; ?>"
|
|
data-a11y-resize="<?php echo $params_a11y_resize ? '1' : '0'; ?>"
|
|
data-a11y-invert="<?php echo $params_a11y_invert ? '1' : '0'; ?>"
|
|
data-a11y-contrast="<?php echo $params_a11y_contrast ? '1' : '0'; ?>"
|
|
data-a11y-links="<?php echo $params_a11y_links ? '1' : '0'; ?>"
|
|
data-a11y-font="<?php echo $params_a11y_font ? '1' : '0'; ?>"
|
|
data-a11y-animations="<?php echo $params_a11y_animations ? '1' : '0'; ?>"
|
|
data-a11y-pos="<?php echo htmlspecialchars($params_a11y_pos, ENT_QUOTES, 'UTF-8'); ?>"
|
|
class="site <?php
|
|
echo $option . ' ' . $wrapper
|
|
. ' view-' . $view
|
|
. ($layout ? ' layout-' . $layout : ' no-layout')
|
|
. ($task ? ' task-' . $task : ' no-task')
|
|
. ($itemid ? ' itemid-' . $itemid : '')
|
|
. ($pageclass ? ' ' . $pageclass : '')
|
|
. $hasClass
|
|
. ($this->direction == 'rtl' ? ' rtl' : '');
|
|
?>">
|
|
<?php if (!empty($params_googletagmanager) && !empty($params_googletagmanagerid)) :
|
|
$gtmID = htmlspecialchars($params_googletagmanagerid, ENT_QUOTES, 'UTF-8'); ?>
|
|
<!-- Google Tag Manager -->
|
|
<script>
|
|
(function(w,d,s,l,i){
|
|
w[l]=w[l]||[];
|
|
w[l].push({'gtm.start': new Date().getTime(), event:'gtm.js'});
|
|
var f=d.getElementsByTagName(s)[0],
|
|
j=d.createElement(s),
|
|
dl=l!='dataLayer'?'&l='+l:'';
|
|
j.async=true;
|
|
j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;
|
|
f.parentNode.insertBefore(j,f);
|
|
})(window,document,'script','dataLayer','<?php echo $gtmID; ?>');
|
|
</script>
|
|
<!-- End Google Tag Manager -->
|
|
|
|
<!-- Google Tag Manager (noscript) -->
|
|
<noscript>
|
|
<iframe src="https://www.googletagmanager.com/ns.html?id=<?php echo $gtmID; ?>"
|
|
height="0" width="0" style="display:none;visibility:hidden"></iframe>
|
|
</noscript>
|
|
<!-- End Google Tag Manager (noscript) -->
|
|
<?php endif; ?>
|
|
|
|
<?php if (!empty($params_googleanalytics) && !empty($params_googleanalyticsid)) :
|
|
$gaId = htmlspecialchars($params_googleanalyticsid, ENT_QUOTES, 'UTF-8'); ?>
|
|
<!-- Google Analytics (gtag.js) -->
|
|
<script async src="https://www.googletagmanager.com/gtag/js?id=<?php echo $gaId; ?>"></script>
|
|
<script>
|
|
window.dataLayer = window.dataLayer || [];
|
|
function gtag(){dataLayer.push(arguments);}
|
|
gtag('js', new Date());
|
|
gtag('consent', 'default', {
|
|
'ad_storage': 'denied',
|
|
'analytics_storage': 'granted',
|
|
'ad_user_data': 'denied',
|
|
'ad_personalization': 'denied'
|
|
});
|
|
(function(id){
|
|
if (/^G-/.test(id)) {
|
|
gtag('config', id, { 'anonymize_ip': true });
|
|
} else if (/^UA-/.test(id)) {
|
|
gtag('config', id, { 'anonymize_ip': true });
|
|
console.warn('Using a UA- ID. Universal Analytics is sunset; consider migrating to GA4.');
|
|
} else {
|
|
console.warn('Unrecognized Google Analytics ID format:', id);
|
|
}
|
|
})('<?php echo $gaId; ?>');
|
|
</script>
|
|
<!-- End Google Analytics -->
|
|
<?php endif; ?>
|
|
|
|
<header id="top" class="header container-header full-width<?php echo $stickyHeader ? ' ' . $stickyHeader : ''; ?>" role="banner">
|
|
|
|
<?php if ($this->countModules('topbar')) : ?>
|
|
<div class="container-topbar">
|
|
<jdoc:include type="modules" name="topbar" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="header-top">
|
|
<?php if ($this->countModules('below-topbar')) : ?>
|
|
<div class="grid container-below-topbar">
|
|
<jdoc:include type="modules" name="below-topbar" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->params->get('brand', 1)) : ?>
|
|
<div class="grid-child header-brand-wrap">
|
|
<div class="navbar-brand">
|
|
<a class="brand-logo" href="<?php echo $this->baseurl; ?>/">
|
|
<?php echo $brandHtml; ?>
|
|
</a>
|
|
<?php if ($this->params->get('siteDescription')) : ?>
|
|
<div class="site-description">
|
|
<?php echo htmlspecialchars($this->params->get('siteDescription'), ENT_QUOTES, 'UTF-8'); ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php if ($this->countModules('brand-aside', true)) : ?>
|
|
<div class="container-brand-aside">
|
|
<jdoc:include type="modules" name="brand-aside" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('below-logo')) : ?>
|
|
<div class="grid container-below-logo">
|
|
<jdoc:include type="modules" name="below-logo" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<!-- Drawer Toggle Buttons -->
|
|
<?php if ($this->countModules('drawer-left')) : ?>
|
|
<button class="drawer-toggle-left btn btn-outline-secondary me-2"
|
|
type="button"
|
|
data-bs-toggle="offcanvas"
|
|
data-bs-target="#drawer-left"
|
|
aria-controls="drawer-left">
|
|
<span class="<?php echo $params_leftIcon; ?>"></span>
|
|
</button>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('drawer-right')) : ?>
|
|
<button class="drawer-toggle-right btn btn-outline-secondary"
|
|
type="button"
|
|
data-bs-toggle="offcanvas"
|
|
data-bs-target="#drawer-right"
|
|
aria-controls="drawer-right">
|
|
<span class="<?php echo $params_rightIcon; ?>"></span>
|
|
</button>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('menu', true) || $this->countModules('search', true)) : ?>
|
|
<div class="grid-child container-nav">
|
|
<?php if ($this->countModules('menu', true)) : ?>
|
|
<nav role="navigation" aria-label="Primary">
|
|
<jdoc:include type="modules" name="menu" style="none" />
|
|
</nav>
|
|
<?php endif; ?>
|
|
<?php if ($this->countModules('search', true)) : ?>
|
|
<div class="container-search">
|
|
<jdoc:include type="modules" name="search" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
<?php endif; ?>
|
|
</header>
|
|
|
|
<div class="site-grid">
|
|
<?php if ($this->countModules('banner', true)) : ?>
|
|
<div class="container-banner full-width">
|
|
<jdoc:include type="modules" name="banner" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('top-a', true)) : ?>
|
|
<div class="grid-child container-top-a">
|
|
<jdoc:include type="modules" name="top-a" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('top-b', true)) : ?>
|
|
<div class="grid-child container-top-b">
|
|
<jdoc:include type="modules" name="top-b" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('sidebar-left', true)) : ?>
|
|
<div class="grid-child container-sidebar-left">
|
|
<jdoc:include type="modules" name="sidebar-left" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<div class="grid-child container-component">
|
|
<jdoc:include type="modules" name="breadcrumbs" style="none" />
|
|
<?php if ($this->countModules('main-top', true)) : ?>
|
|
<div class="container-main-top">
|
|
<jdoc:include type="modules" name="main-top" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
<jdoc:include type="message" />
|
|
<main id="maincontent" role="main">
|
|
<jdoc:include type="component" />
|
|
</main>
|
|
<?php if ($this->countModules('main-bottom', true)) : ?>
|
|
<div class="container-main-bottom">
|
|
<jdoc:include type="modules" name="main-bottom" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php if ($this->countModules('sidebar-right', true)) : ?>
|
|
<div class="grid-child container-sidebar-right">
|
|
<jdoc:include type="modules" name="sidebar-right" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('bottom-a', true)) : ?>
|
|
<div class="grid-child container-bottom-a">
|
|
<jdoc:include type="modules" name="bottom-a" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('bottom-b', true)) : ?>
|
|
<div class="grid-child container-bottom-b">
|
|
<jdoc:include type="modules" name="bottom-b" style="card" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<footer class="container-footer footer full-width">
|
|
<?php if ($this->countModules('footer-menu', true)) : ?>
|
|
<div class="grid-child footer-menu">
|
|
<jdoc:include type="modules" name="footer-menu" />
|
|
</div>
|
|
<?php endif; ?>
|
|
<?php if ($this->countModules('footer', true)) : ?>
|
|
<div class="grid-child">
|
|
<jdoc:include type="modules" name="footer" style="none" />
|
|
</div>
|
|
<?php endif; ?>
|
|
</footer>
|
|
|
|
<?php if ($this->params->get('backTop') == 1) : ?>
|
|
<a href="#top" id="back-top" class="back-to-top-link" aria-label="<?php echo Text::_('TPL_MOKOCASSIOPEIA_BACKTOTOP'); ?>">
|
|
<span class="fa-solid fa-arrow-up" aria-hidden="true"></span>
|
|
</a>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('drawer-left', true)) : ?>
|
|
<!-- Left Offcanvas Drawer -->
|
|
<aside class="offcanvas offcanvas-start" tabindex="-1" id="drawer-left">
|
|
<div class="offcanvas-header justify-content-end">
|
|
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"><span class="fa fa-close"></span></button>
|
|
</div>
|
|
<div class="offcanvas-body">
|
|
<jdoc:include type="modules" name="drawer-left" style="none" />
|
|
</div>
|
|
</aside>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($this->countModules('drawer-right', true)) : ?>
|
|
<!-- Right Offcanvas Drawer -->
|
|
<aside class="offcanvas offcanvas-end" tabindex="-1" id="drawer-right">
|
|
<div class="offcanvas-header justify-content-start">
|
|
<button type="button" class="btn-close text-reset" data-bs-dismiss="offcanvas" aria-label="<?php echo Text::_('JLIB_HTML_BEHAVIOR_CLOSE'); ?>"><span class="fa fa-close"></span></button>
|
|
</div>
|
|
<div class="offcanvas-body">
|
|
<jdoc:include type="modules" name="drawer-right" style="none" />
|
|
</div>
|
|
</aside>
|
|
<?php endif; ?>
|
|
|
|
<jdoc:include type="modules" name="debug" style="none" />
|
|
|
|
</body>
|
|
</html>
|