PK s{!] K images/akeeba-logo.svgnu &1i PK s{!]k images/akeeba-logo-white.svgnu &1i PK s{!]MS<( images/modal-close.pngnu &1i PNG
IHDR ^IDATxm C-ނhOΪJ/JHCw"y(\-beۡ>ރ@//wχ~_>/mKsKa IENDB`PK s{!]S H H images/loading.gifnu &1i GIF89a "Eu> b;N^r !NETSCAPE2.0 ! , @- d9 l Ls7h*+am6sDB ! , $`,`(ʒ©ҧX/(; ! ,
+ ҲHmeaZs=L۽|:1yK#I ! , 5 @SL0"E8Nuy;
Ȅ>bG̑s9y*R! ! ,
) d9PDYUe H4ULϵ[>e4T&R ! , 4 d9 E*qQ-BpՂϗL.:kN+LfB ! , &UU UU[7,紬۾7
n+ըtZ ;PK s{!]
7$9 $9 fef.phpnu &1i loadCSSFramework($withReset, $dark);
}
/**
* Loads the Akeeba FEF JavaScript Framework
*
* @param bool $minimal Should I load the minimal framework (without optional features linked to FEF CSS?)
*
* @return void
* @since 2.0.0
*/
public static function loadJSFramework(bool $minimal = false)
{
self::getLoader()->loadJSFramework($minimal);
}
/**
* Legacy (FEF 1.1.x) alias to loadFEFScript.
*
* @param string $name
*
* @see self::loadFEFScript
* @deprecated 3.0
* @since 1.1.0
*/
public static function loadScript(string $name): void
{
self::loadFEFScript($name, true);
}
/**
* Load an Akeeba FEF JavaScript file and its dependencies.
*
* @param string $name The basename of the file, e.g. "Tabs"
* @param bool $defer Should I defer loading of the file?
*
* @since 2.0.0
*/
public static function loadFEFScript(string $name, bool $defer = true): void
{
self::getLoader()->loadFEFScript($name, $defer);
}
/**
* Is this Joomla 4 or later?
*
* @return bool
* @since 2.0.0
*/
private static function isJoomla4(): bool
{
if (!is_bool(self::$isJoomla4))
{
self::$isJoomla4 = version_compare(JVERSION, '3.999.999', 'gt');
}
return self::$isJoomla4;
}
/**
* Load a JavaScript file using the Joomla! API.
*
* Special considerations:
*
* We always load the minified version of the file. Joomla! will automatically use the non-minified one if Debug
* Site is enabled.
*
* You can have browser-specific files, e.g. foo_firefox.min.js, foo_firefox_57.min.js etc. These are loaded
* automatically instead of the foo.js file as needed.
*
* This method goes through Joomla's script loader, thus allowing template media overrides. The media overrides are
* supposed to be in the templates/YOUR_TEMPLATE/js/fef folder for FEF.
*
* @param string $name The Joomla!-coded path of the file, e.g. 'foo/bar.min.js' for the JavaScript file
* media/foo/js/bar.min.js
*
* @param bool $defer Should I load the script defered?
*
* @return void
* @since 1.0.3
*/
private static function loadJS(string $name, bool $defer = true): void
{
$options = [
'version' => self::getMediaVersion(),
'relative' => true,
'detectDebug' => false,
'framework' => false,
'pathOnly' => false,
'detectBrowser' => true,
];
HTMLHelper::_('script', 'fef/' . $name . '.min.js', $options, [
'defer' => $defer,
'async' => false,
]);
/**
* Preload the static resource we are definitely asking the browser to use for better performance.
*
* Yes, this is also useful for deferred scripts! On Joomla 4 this goes through Preload Manager which does an
* HTTP/2 Push for the script files. This is **far** faster than the browser making a number of HEAD requests
* to see if the scripts are cached then an equal (or smaller) number of GET requests to fetch the scripts.
*/
$options['pathOnly'] = 'true';
$path = HTMLHelper::_('script', 'fef/' . $name . '.min.js', $options);
if (empty($path))
{
return;
}
self::preloadResource($path . '?' . self::getMediaVersion(), ['as' => 'script']);
}
/**
* Load a CSS file using the Joomla! API.
*
* Special considerations:
*
* We always as Joomla to load the minified version of a file. Joomla! will automatically use the non-minified one
* if Debug Site is enabled.
*
* You can have browser-specific files, e.g. foo_firefox.min.css, foo_firefox_57.min.css etc. These are loaded
* automatically instead of the foo.css file as needed.
*
* This method goes through Joomla's script loader, thus allowing template media overrides. The media overrides are
* supposed to be in the templates/YOUR_TEMPLATE/css/fef folder for FEF.
*
* We are instructing the browser to preload the CSS file we are inserting in the HTML. This can cause a small
* performance increase. On Joomla 4 the increase is most noticeable because we go through the Preload Manager
* which can leverage HTTP/2 Push.
*
* When loading the main CSS file (joomla-fef) we preload the WOFF font files which will be most likely used by the
* browser consuming the CSS. This allows the browser to fetch the font files before fully parsing the stylesheet,
* saving some time.
*
* @param string $name The Joomla!-coded path of the file, e.g. 'foo/bar.min.css' for the stylesheet file
* media/foo/css/bar.min.css
*
* @return void
* @since 1.0.3
*/
private static function loadCSS(string $name): void
{
/**
* IMPORTANT! The $attribs (final parameter) MUST ALWAYS be non-empty. Otherwise Joomla! 3.x bugs out.
*/
$options = [
'version' => self::getMediaVersion(),
'relative' => true,
'detectDebug' => false,
'pathOnly' => false,
'detectBrowser' => true,
];
HTMLHelper::_('stylesheet', 'fef/' . $name . '.min.css', $options, [
'type' => 'text/css',
]);
// Preload the static resource we are definitely asking the browser to use for better performance
$options['pathOnly'] = 'true';
$path = HTMLHelper::_('stylesheet', 'fef/' . $name . '.min.css', $options, [
'type' => 'text/css',
]);
if (empty($path))
{
return;
}
self::preloadResource($path . '?' . self::getMediaVersion(), ['as' => 'style']);
// Special case: loading the fef-joomla stylesheet. Preload the font files as well
if ($name == 'fef-joomla')
{
$fontPath = dirname(dirname($path)) . '/fonts/akeeba/Akeeba-Products.woff';
self::preloadResource($fontPath, ['as' => 'font', 'crossorigin' => 'anonymous']);
$fontPath = dirname(dirname($path)) . '/fonts/Ionicon/ionicons.woff';
self::preloadResource($fontPath, ['as' => 'font', 'crossorigin' => 'anonymous']);
}
}
/**
* Preload a resource.
*
* On Joomla 3 this adds a LINK tag to the HTML document, instructing the browser to preload the resource.
*
* On Joomla 4 we are using the document object's Preload Manager to leverage HTTP/2 Push if available.
*
* @param string $url The absolute or relative URL of the resource to preload.
* @param array $options Preload options. You need to specify 'as' as the bare minimum.
*
* @return void
* @see https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content
*
* @since 2.0.0
*/
private static function preloadResource(string $url, array $options): void
{
if (!self::isJoomla4() || !self::preloadResourceJoomla4($url, $options))
{
self::preloadResourceJoomla3($url, $options);
}
}
/**
* Preload a resource on Joomla 3.
*
* This adds a LINK tag to the HTML document, instructing the browser to preload the resource.
*
* @param string $url The absolute or relative URL of the resource to preload.
* @param array $options Preload options. You need to specify 'as' as the bare minimum.
*
* @return bool True if successful; false if we can't get the document, or can't add a LINK tag e.g. this is not
* an HTMLDocument
* @since 2.0.0
*/
private static function preloadResourceJoomla3(string $url, array $options): bool
{
// Try to get Joomla's document object
$document = self::getDocument();
// Make sure the document object implements addCustomTag
if (!is_object($document) || !method_exists($document, 'addCustomTag'))
{
return false;
}
$options['rel'] = 'preload';
$options['href'] = self::relativeToAbsoluteURL($url);
$document->addCustomTag('');
return true;
}
/**
* Preload a resource on Joomla 4.
*
* We are using the document object's Preload Manager to leverage HTTP/2 Push if available.
*
* @param string $url The absolute or relative URL of the resource to preload.
* @param array $options Preload options. You need to specify 'as' as the bare minimum.
*
* @return bool True if successful; false if we can't get the document, or can't add a LINK tag e.g. this is not
* an HTMLDocument
* @since 2.0.0
*/
private static function preloadResourceJoomla4(string $url, array $options): bool
{
// Make sure we're in a version of Joomla which has support for the Preload Manager
if (!interface_exists('\\Joomla\CMS\Document\PreloadManagerInterface'))
{
return false;
}
// Try to get Joomla's document object
$document = self::getDocument();
// Make sure the document object implements getPreloadManager
if (!is_object($document) || !method_exists($document, 'getPreloadManager'))
{
return false;
}
// Try to get the preload manager
try
{
$preloadManager = $document->getPreloadManager();
}
catch (Throwable $e)
{
return false;
}
// Make sure the preload manager is an object implementing the PreloadManagerInterface
if (!is_object($preloadManager) || !($preloadManager instanceof PreloadManagerInterface))
{
return false;
}
$absoluteUrl = self::relativeToAbsoluteURL($url);
$preloadManager->preload($absoluteUrl, $options);
return true;
}
/**
* Get the Joomla document object
*
* @return JDocument|\Joomla\CMS\Document\Document|null NULL if we can't retrieve the document object.
*
* @since 2.0.0
*/
private static function getDocument()
{
// Get the CMS application
try
{
$app = Factory::getApplication();
}
catch (Throwable $e)
{
return null;
}
// Make sure it's an object implementing getDocument
if (!is_object($app) || !method_exists($app, 'getDocument'))
{
return null;
}
// Try to get the document
try
{
$document = $app->getDocument();
}
catch (Throwable $e)
{
return null;
}
return $document;
}
/**
* Convert a relative URL to an absolute URL for the current site
*
* @param string $url The possibly relative URL.
*
* @return string The definitely absolute URL.
*
* @since 2.0.0
*/
private static function relativeToAbsoluteURL(string $url): string
{
static $baseUri;
static $basePath;
// Get the base URI, e.g. 'https://localhost/test'
if (empty($baseUri))
{
$baseUri = $baseUri ?? Uri::base();
if (substr($baseUri, -15) === '/administrator/')
{
$baseUri = substr($baseUri, 0, -15);
}
elseif (substr($baseUri, -14) === '/administrator')
{
$baseUri = substr($baseUri, 0, -14);
}
}
// Get the base path, e.g. 'test'
if (empty($basePath))
{
$basePath = $basePath ?? Uri::base(true);
$basePath = empty($basePath) ? '' : trim($basePath, '/');
if ($basePath === 'administrator')
{
$basePath = '';
}
elseif (substr($basePath, -14) == '/administrator')
{
$basePath = trim(substr($basePath, 0, -14), '/');
}
}
if ((substr($url, 0, 2) == '//') ||
(substr($url, 0, 7) == 'http://') ||
(substr($url, 0, 8) == 'https://') ||
(substr($url, 0, strlen($baseUri)) == $baseUri))
{
return $url;
}
$url = ltrim($url, '/');
if ((strlen($basePath) != 0) && (substr($url, 0, strlen($basePath)) === $basePath))
{
$url = ltrim(substr($url, strlen($basePath)), '/');
$url = ltrim($url, '/');
}
return rtrim($baseUri, '/') . '/' . $url;
}
/**
* Get the media versioning tag. If it's not set, create one first.
*
* @return string
* @since 1.1.0
*/
private static function getMediaVersion(): string
{
if (empty(self::$tag))
{
self::$tag = md5(AKEEBAFEF_VERSION . AKEEBAFEF_DATE . self::getApplicationSecret());
}
return self::$tag;
}
/**
* Return the secret key for the Joomla! installation. Falls back to an MD5 of our file mod time.
*
* @return string
* @since 1.1.0
*/
private static function getApplicationSecret(): string
{
$secret = md5(filemtime(__FILE__));
// Get the site's secret
try
{
$app = Factory::getApplication();
if (method_exists($app, 'get'))
{
return $app->get('secret', $secret);
}
}
catch (Exception $e)
{
}
return $secret;
}
/**
* Returns or creates the Akeeba FEF Loader object.
*
* IMPORTANT: DO NOT SET A RETURN VALUE TYPE HINT. The AkeebaFEFLoader class is undefined until we load it in this
* method. This causes a chicken and egg problem which results in a Fatal Error!
*
* @return AkeebaFEFLoader
* @since 2.0.0
*/
private static function getLoader()
{
if (!is_null(self::$loader))
{
return self::$loader;
}
if (!class_exists('AkeebaFEFLoader'))
{
require_once __DIR__ . '/php/AkeebaFEFLoader.php';
}
self::$loader = new AkeebaFEFLoader(function (string $name) {
self::loadCSS($name);
}, function (string $name, bool $defer) {
self::loadJS($name, $defer);
}, 'joomla');
return self::$loader;
}
}
PK s{!]RT)T T version.phpnu &1i a elements in the NAV
var linkList = elNav.querySelectorAll('section > a');
if (linkList.length === 0)
{
return;
}
/**
* Clicking on each link will do two things:
* - It will set the clicked link's class to “current”
* - It will unset the “current” class on every other link
* - It will trigger a virtual click on the drop-down button (to close the drop-down).
*/
akeeba.fef.forEach(linkList, function(i, elLink) {
elLink.addEventListener('click', function (event) {
// Close the drop-down
akeeba.fef.triggerEvent(elButton, 'click');
// Remove the “current” class from all links
akeeba.fef.forEach(linkList, function(i, element) {
var currentClasses = element.className.split(' ');
var newClass = '';
for (var property in currentClasses)
{
if (!currentClasses.hasOwnProperty(property) || (currentClasses[property] === 'current'))
{
continue;
}
newClass += currentClasses[property] + ' ';
}
if (newClass.trim)
{
newClass = newClass.trim();
}
element.className = newClass;
});
// Add the “current” class to the current link
this.className += ' current';
event.preventDefault();
});
});
});
};
PK s{!]6b;>
>
js/dropdown.min.mapnu &1i {
"version":3,
"file":"/Users/nicholas/Projects/akeeba/fef/out/js/dropdown.min.js",
"lineCount":4,
"mappings":"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",
"sources":["/Users/nicholas/Projects/akeeba/fef/out/js/dropdown.js"],
"names":["akeeba","fef","forEach","akeeba.fef.forEach","array","callback","scope","i","length","call","triggerEvent","akeeba.fef.triggerEvent","element","eventName","document","getElementById","Element","window","jQuery","trigger","fireEvent","Event","event","createEvent","initEvent","dispatchEvent","dropdown","akeeba.fef.dropdown","selector","navList","querySelectorAll","elNav","buttonList","elButton","addEventListener","isOpen","currentClasses","className","split","newClass","property","hasOwnProperty","trim","preventDefault","linkList","elLink"]
}
PK s{!]L}u( ( js/darkmode.jsnu &1i /*
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2020 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*
* Created by Crystal Dionysopoulou for Akeeba Ltd, https://www.akeeba.com
*/
if (typeof akeeba === 'undefined')
{
akeeba = {};
}
if (typeof akeeba.fef === 'undefined')
{
akeeba.fef = {};
}
akeeba.fef.darkMode = function(status)
{
if (status == null)
{
status = true;
}
var elNodes = document.querySelectorAll('.akeeba-renderer-fef');
for (var i = 0; i < elNodes.length; i++) {
var elNode = elNodes[i];
var currentClasses = elNode.className.split(' ');
elNode.className = '';
for (var j = 0; j < currentClasses.length; j++) {
var thisClass = currentClasses[j];
if (thisClass === 'akeeba-renderer-fef--dark')
{
continue;
}
elNode.className += ' ' + thisClass;
}
if (status)
{
elNode.className += ' akeeba-renderer-fef--dark';
}
if (elNode.className.trim)
{
elNode.className = elNode.className.trim();
}
}
};PK s{!]