primo commit

This commit is contained in:
2024-12-17 17:34:10 +01:00
commit e650f8df99
16435 changed files with 2451012 additions and 0 deletions

7
media/fef/css/dark.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
media/fef/css/fef-joomla.min.css vendored Normal file

File diff suppressed because one or more lines are too long

7
media/fef/css/fef-reset.min.css vendored Normal file
View File

@ -0,0 +1,7 @@
/*!
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/.akeeba-renderer-fef div,.akeeba-renderer-fef span,.akeeba-renderer-fef applet,.akeeba-renderer-fef object,.akeeba-renderer-fef iframe,.akeeba-renderer-fef h1,.akeeba-renderer-fef h2,.akeeba-renderer-fef h3,.akeeba-renderer-fef h4,.akeeba-renderer-fef h5,.akeeba-renderer-fef h6,.akeeba-renderer-fef p,.akeeba-renderer-fef blockquote,.akeeba-renderer-fef pre,.akeeba-renderer-fef a,.akeeba-renderer-fef abbr,.akeeba-renderer-fef acronym,.akeeba-renderer-fef address,.akeeba-renderer-fef big,.akeeba-renderer-fef cite,.akeeba-renderer-fef code,.akeeba-renderer-fef del,.akeeba-renderer-fef dfn,.akeeba-renderer-fef em,.akeeba-renderer-fef img,.akeeba-renderer-fef ins,.akeeba-renderer-fef kbd,.akeeba-renderer-fef q,.akeeba-renderer-fef s,.akeeba-renderer-fef samp,.akeeba-renderer-fef small,.akeeba-renderer-fef strike,.akeeba-renderer-fef strong,.akeeba-renderer-fef sub,.akeeba-renderer-fef sup,.akeeba-renderer-fef tt,.akeeba-renderer-fef var,.akeeba-renderer-fef b,.akeeba-renderer-fef u,.akeeba-renderer-fef center,.akeeba-renderer-fef dl,.akeeba-renderer-fef dt,.akeeba-renderer-fef dd,.akeeba-renderer-fef fieldset,.akeeba-renderer-fef form,.akeeba-renderer-fef label,.akeeba-renderer-fef legend,.akeeba-renderer-fef table,.akeeba-renderer-fef caption,.akeeba-renderer-fef tbody,.akeeba-renderer-fef tfoot,.akeeba-renderer-fef thead,.akeeba-renderer-fef tr,.akeeba-renderer-fef th,.akeeba-renderer-fef td,.akeeba-renderer-fef article,.akeeba-renderer-fef aside,.akeeba-renderer-fef canvas,.akeeba-renderer-fef details,.akeeba-renderer-fef embed,.akeeba-renderer-fef figure,.akeeba-renderer-fef figcaption,.akeeba-renderer-fef footer,.akeeba-renderer-fef header,.akeeba-renderer-fef hgroup,.akeeba-renderer-fef menu,.akeeba-renderer-fef nav,.akeeba-renderer-fef output,.akeeba-renderer-fef ruby,.akeeba-renderer-fef section,.akeeba-renderer-fef summary,.akeeba-renderer-fef time,.akeeba-renderer-fef mark,.akeeba-renderer-fef audio,.akeeba-renderer-fef video,.akeeba-renderer-fef input[type=submit]{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;box-sizing:border-box;line-height:inherit}.akeeba-renderer-fef article,.akeeba-renderer-fef aside,.akeeba-renderer-fef details,.akeeba-renderer-fef figcaption,.akeeba-renderer-fef figure,.akeeba-renderer-fef footer,.akeeba-renderer-fef header,.akeeba-renderer-fef hgroup,.akeeba-renderer-fef menu,.akeeba-renderer-fef nav,.akeeba-renderer-fef section{display:block}.akeeba-renderer-fef blockquote,.akeeba-renderer-fef q{quotes:none}.akeeba-renderer-fef blockquote:before,.akeeba-renderer-fef blockquote:after,.akeeba-renderer-fef q:before,.akeeba-renderer-fef q:after{content:"";content:none}.akeeba-renderer-fef table{border-spacing:0}.akeeba-renderer-fef input[type=text],.akeeba-renderer-fef input[type=password],.akeeba-renderer-fef input[type=number],.akeeba-renderer-fef input[type=email],.akeeba-renderer-fef input[type=color],.akeeba-renderer-fef input[type=date],.akeeba-renderer-fef input[type=datetime-local],.akeeba-renderer-fef input[type=month],.akeeba-renderer-fef input[type=range],.akeeba-renderer-fef input[type=search],.akeeba-renderer-fef input[type=tel],.akeeba-renderer-fef input[type=time],.akeeba-renderer-fef input[type=url],.akeeba-renderer-fef input[type=week],.akeeba-renderer-fef select,.akeeba-renderer-fef input[type=file]{height:2.25em}.akeeba-renderer-fef select{background-color:#fff}/*# sourceMappingURL=fef-reset.min.css.map */

9
media/fef/css/reset.min.css vendored Normal file
View File

@ -0,0 +1,9 @@
/*!
* Akeeba Frontend Framework (FEF)
* Copyright (c) 2017-2019 Nicholas K. Dionysopoulos / Akeeba Ltd
*
* Created by Crystal Harris for Akeeba Ltd, https://www.akeeba.com
*
* Licensed under the GNU General Public License (GPL) version 3 or, at your option, any later version of the license
* published by the Free Software Foundation, https://www.gnu.org/licenses/gpl-3.0.en.html
*/.akeeba-renderer-fef div,.akeeba-renderer-fef span,.akeeba-renderer-fef applet,.akeeba-renderer-fef object,.akeeba-renderer-fef iframe,.akeeba-renderer-fef h1,.akeeba-renderer-fef h2,.akeeba-renderer-fef h3,.akeeba-renderer-fef h4,.akeeba-renderer-fef h5,.akeeba-renderer-fef h6,.akeeba-renderer-fef p,.akeeba-renderer-fef blockquote,.akeeba-renderer-fef pre,.akeeba-renderer-fef a,.akeeba-renderer-fef abbr,.akeeba-renderer-fef acronym,.akeeba-renderer-fef address,.akeeba-renderer-fef big,.akeeba-renderer-fef cite,.akeeba-renderer-fef code,.akeeba-renderer-fef del,.akeeba-renderer-fef dfn,.akeeba-renderer-fef em,.akeeba-renderer-fef img,.akeeba-renderer-fef ins,.akeeba-renderer-fef kbd,.akeeba-renderer-fef q,.akeeba-renderer-fef s,.akeeba-renderer-fef samp,.akeeba-renderer-fef small,.akeeba-renderer-fef strike,.akeeba-renderer-fef strong,.akeeba-renderer-fef sub,.akeeba-renderer-fef sup,.akeeba-renderer-fef tt,.akeeba-renderer-fef var,.akeeba-renderer-fef b,.akeeba-renderer-fef u,.akeeba-renderer-fef center,.akeeba-renderer-fef dl,.akeeba-renderer-fef dt,.akeeba-renderer-fef dd,.akeeba-renderer-fef fieldset,.akeeba-renderer-fef form,.akeeba-renderer-fef label,.akeeba-renderer-fef legend,.akeeba-renderer-fef table,.akeeba-renderer-fef caption,.akeeba-renderer-fef tbody,.akeeba-renderer-fef tfoot,.akeeba-renderer-fef thead,.akeeba-renderer-fef tr,.akeeba-renderer-fef th,.akeeba-renderer-fef td,.akeeba-renderer-fef article,.akeeba-renderer-fef aside,.akeeba-renderer-fef canvas,.akeeba-renderer-fef details,.akeeba-renderer-fef embed,.akeeba-renderer-fef figure,.akeeba-renderer-fef figcaption,.akeeba-renderer-fef footer,.akeeba-renderer-fef header,.akeeba-renderer-fef hgroup,.akeeba-renderer-fef menu,.akeeba-renderer-fef nav,.akeeba-renderer-fef output,.akeeba-renderer-fef ruby,.akeeba-renderer-fef section,.akeeba-renderer-fef summary,.akeeba-renderer-fef time,.akeeba-renderer-fef mark,.akeeba-renderer-fef audio,.akeeba-renderer-fef video,.akeeba-renderer-fef input[type=submit]{margin:0;padding:0;border:0;font-size:100%;vertical-align:baseline;box-sizing:border-box;line-height:inherit}.akeeba-renderer-fef article,.akeeba-renderer-fef aside,.akeeba-renderer-fef details,.akeeba-renderer-fef figcaption,.akeeba-renderer-fef figure,.akeeba-renderer-fef footer,.akeeba-renderer-fef header,.akeeba-renderer-fef hgroup,.akeeba-renderer-fef menu,.akeeba-renderer-fef nav,.akeeba-renderer-fef section{display:block}.akeeba-renderer-fef blockquote,.akeeba-renderer-fef q{quotes:none}.akeeba-renderer-fef blockquote:before,.akeeba-renderer-fef blockquote:after,.akeeba-renderer-fef q:before,.akeeba-renderer-fef q:after{content:"";content:none}.akeeba-renderer-fef table{border-spacing:0}.akeeba-renderer-fef input[type=text],.akeeba-renderer-fef input[type=password],.akeeba-renderer-fef input[type=number],.akeeba-renderer-fef input[type=email],.akeeba-renderer-fef input[type=color],.akeeba-renderer-fef input[type=date],.akeeba-renderer-fef input[type=datetime-local],.akeeba-renderer-fef input[type=month],.akeeba-renderer-fef input[type=range],.akeeba-renderer-fef input[type=search],.akeeba-renderer-fef input[type=tel],.akeeba-renderer-fef input[type=time],.akeeba-renderer-fef input[type=url],.akeeba-renderer-fef input[type=week],.akeeba-renderer-fef select,.akeeba-renderer-fef input[type=file]{height:2.25em}.akeeba-renderer-fef select{background-color:#fff}/*# sourceMappingURL=reset.css.map */

9
media/fef/css/style.min.css vendored Normal file

File diff suppressed because one or more lines are too long

542
media/fef/fef.php Normal file
View File

@ -0,0 +1,542 @@
<?php
/**
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
// Protect from unauthorized access
use Joomla\CMS\Document\PreloadManagerInterface;
use Joomla\CMS\Factory;
use Joomla\CMS\HTML\HTMLHelper;
use Joomla\CMS\Uri\Uri;
use Joomla\Utilities\ArrayHelper;
defined('_JEXEC') || die();
if (@file_exists(__DIR__ . '/version.php') && @is_file(__DIR__ . '/version.php') && @is_readable(__DIR__ . '/version.php'))
{
@include_once(__DIR__ . '/version.php');
}
if (!defined('AKEEBAFEF_VERSION'))
{
define('AKEEBAFEF_VERSION', 'dev');
define('AKEEBAFEF_DATE', gmdate('Y-m-d'));
}
class AkeebaFEFHelper
{
/**
* Media versioning tag
*
* @var string
* @since 1.0.3
*/
public static $tag = null;
/**
* The Akeeba FEF Loader object
*
* @var AkeebaFEFLoader
* @since 2.0.0
*/
private static $loader;
/**
* Is this Joomla 4?
*
* @var bool|null
* @since 2.0.0
*/
private static $isJoomla4 = null;
/**
* Loads the Akeeba Frontend Framework, both CSS and JS
*
* @param bool $withReset Should I also load the CSS reset for the FEF container?
* @param bool $dark Include Dark Mode CSS?
*
* @return void
* @since 1.0.3
*/
public static function load(bool $withReset = true, bool $dark = false)
{
self::loadCSSFramework();
self::loadJSFramework();
}
/**
* Loads the Akeeba FEF CSS Framework
*
* @param bool $withReset Should I also load the CSS reset for the FEF container?
* @param bool $dark Include Dark Mode CSS?
*
* @return void
* @since 1.0.3
*/
public static function loadCSSFramework(bool $withReset = true, bool $dark = false)
{
self::getLoader()->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('<link ' . ArrayHelper::toString($options) . '>');
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;
}
}

43
media/fef/file_fef.xml Normal file
View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--~
~ Akeeba Frontend Framework (FEF)
~
~ @package fef
~ @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
~ @license GNU General Public License version 3, or later
-->
<extension type="file" version="3.3" method="upgrade">
<!-- Generic Metadata -->
<name>file_fef</name>
<author>Nicholas K. Dionysopoulos</author>
<authorEmail>nicholas@dionysopoulos.me</authorEmail>
<authorUrl>https://www.akeeba.com</authorUrl>
<copyright>(C) 2017-2021 Akeeba Ltd.</copyright>
<license>GNU GPL v3 or later</license>
<version>2.1.0</version>
<creationDate>2022-02-17</creationDate>
<description>Akeeba Frontend Framework - The CSS framework for Akeeba Ltd extensions.</description>
<!-- Fileset definition -->
<fileset>
<files target="media/fef">
<folder>css</folder>
<folder>fonts</folder>
<folder>images</folder>
<folder>js</folder>
<folder>php</folder>
<filename>fef.php</filename>
<filename>version.php</filename>
<filename>version.txt</filename>
</files>
</fileset>
<!-- Installation / uninstallation script file -->
<scriptfile>script.fef.php</scriptfile>
<!-- Update server -->
<updateservers>
<server type="extension" priority="1" name="Akeeba FEF">http://cdn.akeeba.com/updates/fef.xml</server>
</updateservers>
</extension>

Binary file not shown.

Binary file not shown.

15
media/fef/js/Ajax.min.js vendored Normal file
View File

@ -0,0 +1,15 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};window.akeeba.Ajax=window.akeebaAjax||{xhrSuccessStatus:{0:200,1223:204},requestArray:[],processingQueue:!1};
akeeba.Ajax.ajax=function(b,a){"undefined"==typeof a&&(a=b,b=a.url);var c="undefined"==typeof a.type?"POST":a.type;c=c.toUpperCase();var e="undefined"==typeof a.data?{}:a.data,h=null,k="undefined"==typeof a.success?null:a.success,f="undefined"==typeof a.error?null:a.error;if("undefined"==typeof a.cache||!a.url){var l=(new Date).getTime()/1E3,m=parseInt(l,10);e._cacheBustingJunk=Math.round(1E3*(l-m))/1E3}"POST"==c||"PUT"==c?h=this.interpolateParameters(e):(b+=-1==b.indexOf("?")?"?":"&",b+=this.interpolateParameters(e));
var d=new XMLHttpRequest;d.open(c,b);"POST"!=c&&"PUT"!=c||d.setRequestHeader("Content-Type","application/x-www-form-urlencoded");d.onload=function(g){g=akeeba.Ajax.xhrSuccessStatus[d.status]||d.status;var n=d.statusText,p="text"!==(d.responseType||"text")||"string"!==typeof d.responseText?d.response:d.responseText;d.getAllResponseHeaders();200===g?null!=k&&akeeba.Ajax.triggerCallbacks(k,p,n,d):f&&akeeba.Ajax.triggerCallbacks(f,d,"error",null)};d.onerror=function(g){f&&akeeba.Ajax.triggerCallbacks(f,
d,"error",null)};window.attachEvent&&!window.addEventListener&&(d.onreadystatechange=function(){if(4===this.readyState){var g=akeeba.Ajax.xhrSuccessStatus[this.status]||this.status;if(200<=g&&400>g)d.onload();else d.onerror()}});d.ontimeout=function(){f&&akeeba.Ajax.triggerCallbacks(f,d,"timeout",null)};d.onabort=function(){f&&akeeba.Ajax.triggerCallbacks(f,d,"abort",null)};b="undefined"==typeof a.timeout?6E5:a.timeout;0<b&&(d.timeout=b);"undefined"!=typeof a.beforeSend&&!1===a.beforeSend(d,a)||d.send(h)};
akeeba.Ajax.enqueue=function(b,a){"undefined"==typeof a&&(a=b,b=a.url);a.url=b;akeeba.Ajax.requestArray.push(a);akeeba.Ajax.processQueue()};akeeba.Ajax.interpolateParameters=function(b,a){a=a||"";var c="",e;for(e in b)b.hasOwnProperty(e)&&(0<c.length&&(c+="&"),c="object"!==typeof b[e]?""===a?c+(encodeURIComponent(e)+"="+encodeURIComponent(b[e])):c+(encodeURIComponent(a)+"["+encodeURIComponent(e)+"]="+encodeURIComponent(b[e])):c+akeeba.Ajax.interpolateParameters(b[e],e));return c};
akeeba.Ajax.triggerCallbacks=function(){var b=Array.prototype.slice.call(arguments),a=b.shift();if("function"==typeof a)return a.apply(null,b);if(a instanceof Array)for(var c=0;c<a.length;c++)if(!1===a[c].apply(null,b))return!1;return null};akeeba.Ajax.processQueueHelper=function(){akeeba.Ajax.processingQueue=!1;setTimeout(akeeba.Ajax.processQueue,50)};
akeeba.Ajax.processQueue=function(){if(!akeeba.Ajax.requestArray.length)akeeba.Ajax.processingQueue=!1;else if(!akeeba.Ajax.processingQueue){var b=akeeba.Ajax.requestArray.shift(),a=b.url,c="undefined"==typeof b.success?[]:b.success,e="undefined"==typeof b.error?[]:b.error;"object"==typeof c&&c instanceof Array||(c=[c]);"object"==typeof e&&e instanceof Array||(e=[e]);c.unshift(akeeba.Ajax.processQueueHelper);e.unshift(akeeba.Ajax.processQueueHelper);b.success=c;b.error=e;akeeba.Ajax.processingQueue=
!0;akeeba.Ajax.ajax(a,b)}}; //# sourceMappingURL=Ajax.map

35
media/fef/js/Modal.min.js vendored Normal file
View File

@ -0,0 +1,35 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
jsModal - A pure JavaScript modal dialog engine v1.0d
http://jsmodal.com/
Author: Henry Rune Tang Kai <henry@henrys.se>
(c) Copyright 2013 Henry Tang Kai.
License: http://www.opensource.org/licenses/mit-license.php
Date: 2013-7-11
Modified by Akeeba Ltd:
- [Oct 2016] Prefix "akeeba-modal-" instead of generic "modal-" to avoid conflicts with 3PD software e.g. Bootstrap.
- [Oct 2016] Remove support for AJAX content. We use our own AJAX handlers which work around 3PD plugins corrupting content.
? [Oct 2016] Added method show() which just calls open() for backwards compatibility reasons.
? [Oct 2016] Added parameter "inherit" where you can give a query selector for an element whose content will be inherited by the modal.
? [Oct 2016] open() returns the Modal object so that we can interact with it through external code.
? [Nov 2016] Added parameter "iframe" where you can give a URL to load inside an IFRAME.
*/
window.akeeba=window.akeeba||{};
"undefined"==typeof akeeba.Modal&&(akeeba.Modal=function(){var e={},b={},f=document.createElement("div"),d=document.createElement("div"),k=document.createElement("div"),h=document.createElement("div"),m=document.createElement("div"),n=null,l,v;e.show=function(a){try{console.log("Using akeeba.Modal.show() is deprecated. Use .open() instead.")}catch(c){}return e.open(a)};e.open=function(a){b.width=a.width||"auto";b.height=a.height||"auto";b.lock=a.lock||!1;b.hideClose=a.hideClose||!1;b.draggable=a.draggable||
!1;b.closeAfter=a.closeAfter||0;b.closeCallback=a.closeCallback||!1;b.openCallback=a.openCallback||!1;b.hideOverlay=a.hideOverlay||!1;l=function(){e.center({})};h.innerHTML="";var c=null;if(a.content)h.innerHTML=a.content;else if(a.inherit){if(c=a.inherit,"string"==typeof a.inherit&&(c=window.document.querySelector(a.inherit)),null!=c&&c.innerHTML)for(n=c;0<n.childNodes.length;)h.appendChild(n.childNodes[0])}else a.iframe&&(c=window.document.createElement("iframe"),c.setAttribute("src",a.iframe),
c.setAttribute("width",a.width),c.setAttribute("height",a.height),c.setAttribute("frameborder",0),c.setAttribute("marginheight",0),c.setAttribute("marginwidth",0),h.appendChild(c));d.style.width=b.width;d.style.height=b.height;e.center({});if(b.lock||b.hideClose)m.style.visibility="hidden";b.hideOverlay||(f.style.visibility="visible");d.style.visibility="visible";document.onkeypress=function(g){27===g.keyCode&&!0!==b.lock&&e.close()};m.onclick=function(){if(b.hideClose)return!1;e.close()};f.onclick=
function(){if(b.lock)return!1;e.close()};window.addEventListener?(window.addEventListener("resize",l,!1),window.addEventListener("load",l,!1)):window.attachEvent&&(window.attachEvent("onresize",l),window.attachEvent("onload",l));b.draggable?(k.style.cursor="move",k.onmousedown=function(g){e.drag(g);return!1}):k.onmousedown=function(){return!1};0<b.closeAfter&&(v=window.setTimeout(function(){e.close()},1E3*b.closeAfter));b.openCallback&&b.openCallback();return this};e.drag=function(a){var c=void 0!==
window.event?window.event.clientX:a.clientX,g=void 0!==window.event?window.event.clientY:a.clientY,r=c-d.offsetLeft,p=g-d.offsetTop;document.onmousemove=function(q){c=void 0!==window.event?window.event.clientX:q.clientX;g=void 0!==window.event?window.event.clientY:q.clientY;d.style.left=0<c-r?c-r+"px":0;d.style.top=0<g-p?g-p+"px":0;document.onmouseup=function(){window.document.onmousemove=null}}};e.close=function(){if(!function(a){var c;if(""===a||0===a||"0"===a||null===a||!1===a||"undefined"===typeof a)return!0;
if("object"==typeof a){for(c in a)return!1;return!0}return!1}(n)){for(;0<h.childNodes.length;)n.appendChild(h.childNodes[0]);n=null}h.innerHTML="";f.setAttribute("style","");f.style.cssText="";f.style.visibility="hidden";d.setAttribute("style","");d.style.cssText="";d.style.visibility="hidden";k.style.cursor="default";m.setAttribute("style","");m.style.cssText="";v&&window.clearTimeout(v);b.closeCallback&&b.closeCallback();window.removeEventListener?window.removeEventListener("resize",l,!1):window.detachEvent&&
window.detachEvent("onresize",l)};e.center=function(a){var c=Math.max(document.body.scrollHeight,document.documentElement.scrollHeight),g=Math.max(d.clientWidth,d.offsetWidth),r=Math.max(d.clientHeight,d.offsetHeight),p=0,q=0,t=0,u=0;"number"===typeof window.innerWidth?(p=window.innerWidth,q=window.innerHeight):document.documentElement&&document.documentElement.clientWidth&&(p=document.documentElement.clientWidth,q=document.documentElement.clientHeight);"number"===typeof window.pageYOffset?(u=window.pageYOffset,
t=window.pageXOffset):document.body&&document.body.scrollLeft?(u=document.body.scrollTop,t=document.body.scrollLeft):document.documentElement&&document.documentElement.scrollLeft&&(u=document.documentElement.scrollTop,t=document.documentElement.scrollLeft);a.horizontalOnly||(d.style.top=u+q/2-r/2+"px");d.style.left=t+p/2-g/2+"px";f.style.height=c+"px";f.style.width="100%"};f.setAttribute("id","akeeba-modal-overlay");d.setAttribute("id","akeeba-modal-container");k.setAttribute("id","akeeba-modal-header");
h.setAttribute("id","akeeba-modal-content");m.setAttribute("id","akeeba-modal-close");k.appendChild(m);d.appendChild(k);d.appendChild(h);f.style.visibility="hidden";d.style.visibility="hidden";window.addEventListener?window.addEventListener("load",function(){document.body.appendChild(f);document.body.appendChild(d)},!1):window.attachEvent&&window.attachEvent("onload",function(){document.body.appendChild(f);document.body.appendChild(d)});return e}()); //# sourceMappingURL=Modal.map

48
media/fef/js/System.min.js vendored Normal file
View File

@ -0,0 +1,48 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
Math.uuid.js (v1.4)
http://www.broofa.com
mailto:robert@broofa.com
Copyright (c) 2009 Robert Kieffer
Dual licensed under the MIT and GPL licenses.
Usage: Math.uuid()
*/
window.akeeba=window.akeeba||{};"undefined"===typeof akeeba.System&&(akeeba.System={},akeeba.System.documentReady=function(a,b){},akeeba.System.notification={hasDesktopNotification:!1,iconURL:""},akeeba.System.params={AjaxURL:"",errorCallback:akeeba.System.modalErrorHandler,password:"",errorDialogId:"errorDialog",errorDialogMessageId:"errorDialogPre"},akeeba.System.modalDialog=null,akeeba.System.optionsStorage=null);
"undefined"===typeof Math.uuid&&(Math.uuid=function(){var a="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".split("");return function(b,c){var d=[];c=c||a.length;if(b)for(var e=0;e<b;e++)d[e]=a[0|Math.random()*c];else for(d[8]=d[13]=d[18]=d[23]="-",d[14]="4",e=0;36>e;e++)d[e]||(b=0|16*Math.random(),d[e]=a[19===e?b&3|8:b]);return d.join("")}}());akeeba.System.forEach=function(a,b,c){for(var d=0;d<a.length;d++)b.call(c,d,a[d])};
akeeba.System.array_merge=function(){var a=Array.prototype.slice.call(arguments),b={},c,d;var e=!0;for(d=0;d<a.length;d++)if(!(a[d]instanceof Array)){e=!1;break}if(e){e=[];for(d=0;d<a.length;d++)e=e.concat(a[d]);return e}var f;for(f=d=0;d<a.length;d++)if(a[d]instanceof Array)for(e=0;e<a[d].length;e++)b[f++]=a[d][e];else for(c in a[d])a[d].hasOwnProperty(c)&&(parseInt(c,10)+""===c?b[f++]=a[d][c]:b[c]=a[d][c]);return b};
akeeba.System.array_diff=function(a){var b={},c=arguments.length,d="",e,f="";a:for(d in a)for(e=1;e<c;e++){var l=arguments[e];for(f in l)if(l[f]===a[d])continue a;b[d]=a[d]}return b};akeeba.System.findElement=function(a){if("undefined"===typeof a||null===a)return null;"string"===typeof a&&(a=document.getElementById(a));return"object"===typeof a&&a instanceof Element?a:null};
akeeba.System.getOptions=function(a,b){"undefined"==typeof b&&(b=null);akeeba.System.optionsStorage||(akeeba.System.loadJoomlaOptions(),akeeba.System.loadOptions());return void 0!==akeeba.System.optionsStorage[a]?akeeba.System.optionsStorage[a]:"undefined"!==typeof Joomla&&"undefined"!==typeof Joomla.getOptions?Joomla.getOptions(a,b):b};
akeeba.System.loadJoomlaOptions=function(){var a=document.querySelectorAll(".joomla-script-options");akeeba.System.iterateNodes(a,function(b){if(!akeeba.System.hasClass(b,"akeebaImported")){var c;str=b.text||b.textContent;(c=JSON.parse(str))&&akeeba.System.loadOptions(c);akeeba.System.addClass(b,"akeebaImported")}})};
akeeba.System.loadOptions=function(a){if(!a){for(var b=document.querySelectorAll(".akeeba-script-options.new"),c,d,e=0,f=0,l=b.length;f<l;f++){d=b[f];c=d.text||d.textContent;if(c=JSON.parse(c))akeeba.System.loadOptions(c),e++;akeeba.System.removeClass(d,"new");akeeba.System.addClass(d,"loaded")}if(e)return}if(!akeeba.System.optionsStorage)akeeba.System.optionsStorage=a||{};else if(a)for(var g in a)a.hasOwnProperty(g)&&(akeeba.System.optionsStorage[g]=a[g])};
akeeba.System.defaultErrorHandler=function(a){null!=a&&"undefined"!=typeof a&&alert("An error has occurred\n"+a)};
akeeba.System.modalErrorHandler=function(a){var b=akeeba.System.getOptions("akeeba.System.params.errorDialogId",akeeba.System.params.errorDialogId),c=akeeba.System.getOptions("akeeba.System.params.errorDialogMessageId",akeeba.System.params.errorDialogMessageId);b=document.getElementById(b);var d="error";null!=b&&(document.getElementById(c).innerHTML=a,d=b.innerHTML);akeeba.Modal.open({content:d,width:"80%"})};
akeeba.System.doAjax=function(a,b,c,d,e){null==d&&(d=!0);var f=(new Date).getTime()/1E3,l=parseInt(String(f),10);a._cacheBustingJunk=Math.round(1E3*(f-l))/1E3;null==e&&(e=6E5);f=akeeba.System.getOptions("akeeba.System.params.AjaxURL",akeeba.System.params.AjaxURL);a.hasOwnProperty("ajaxURL")&&(f=a.ajaxURL,delete a.url);var g=!0;a.hasOwnProperty("useTripleHash")&&(g=a.useTripleHash,delete a.useTripleHash);a.hasOwnProperty("parseResponseAsJSON")&&delete a.parseResponseAsJSON;null==c&&(c=akeeba.System.getOptions("akeeba.System.params.errorCallback",
akeeba.System.params.errorCallback));null==c&&(c=akeeba.System.defaultErrorHandler);var p={type:"POST",url:f,cache:!1,data:a,timeout:e,success:function(h){if(g){var m=h.indexOf("###");if(-1===m){h=akeeba.System.sanitizeErrorMessage(h);c("Invalid AJAX data: "+h);return}}var k=h;g&&(0!==m&&(k=h.substr(m)),k=k.substr(3),m=k.lastIndexOf("###"),k=k.substr(0,m));try{var n=JSON.parse(k)}catch(q){k=akeeba.System.sanitizeErrorMessage(k);h=q.message+"\n<br/>\n<pre>\n"+k+"\n</pre>";c(h);return}b(n)},error:function(h,
m,k){k=h.responseText?h.responseText:"";var n="<strong>AJAX Loading Error</strong><br/>HTTP Status: "+h.status+" ("+h.statusText+")<br/>";n=n+"Internal status: "+m+"<br/>XHR ReadyState: "+h.readyState+"<br/>";n=n+"Raw server response:<br/>"+akeeba.System.sanitizeErrorMessage(k);c(n)}};d?akeeba.Loader.add("akeeba.Ajax",function(){akeeba.Ajax.enqueue(p)}):akeeba.Loader.add("akeeba.Ajax",function(){akeeba.Ajax.ajax(p)})};
akeeba.System.sanitizeErrorMessage=function(a){-1<a.indexOf("<script")&&(a="(HTML containing script tags)");return a};akeeba.System.notification.askPermission=function(){akeeba.System.getOptions("akeeba.System.notification.hasDesktopNotification",akeeba.System.notification.hasDesktopNotification)&&void 0!==window.Notification&&"default"===window.Notification.permission&&window.Notification.requestPermission()};
akeeba.System.notification.notify=function(a,b,c){void 0!==window.Notification&&"granted"===window.Notification.permission&&(void 0===c&&(c=5E3),void 0===b&&(b=""),a=new window.Notification(a,{body:b,icon:akeeba.System.getOptions("akeeba.System.notification.iconURL",akeeba.System.notification.iconURL)}),0<c&&setTimeout(function(d){return function(){d.close()}}(a),c))};
akeeba.System.data=function(){var a=0,b={};return{set:function(c,d,e){if(c.dataset)c.dataset[d]=e,null==e&&delete c.dataset[d];else{if(void 0===c.myCustomDataTag){var f=a++;c.myCustomDataTag=f}"undefined"==typeof b[f]&&(b[f]={});b[f][d]=e;var l="data-"+d.split(/(?=[A-Z])/).join("-").toLowerCase();c.setAttribute&&c.setAttribute(l,e);if(null==e)try{delete b[f][d],c.removeAttribute(l)}catch(g){b[f][d]=null}}},get:function(c,d,e){if(c.dataset)return"undefined"==typeof c.dataset[d]&&(c.dataset[d]=e),c.dataset[d];
"undefined"==typeof e&&(e=null);"undefined"==typeof b[c.myCustomDataTag]&&(b[c.myCustomDataTag]={});var f="data-"+d.split(/(?=[A-Z])/).join("-").toLowerCase();"undefined"!==typeof c[f]&&(b[c.myCustomDataTag][d]=c[f]);"undefined"==typeof b[c.myCustomDataTag][d]&&this.set(c,d,e);return b[c.myCustomDataTag][d]}}}();
akeeba.System.addEventListener=function(a,b,c){function d(e){var f=c.apply(this,arguments);!1===f&&(e.stopPropagation()&&e.stopPropagation(),e.preventDefault?e.preventDefault():e.returnValue=!1);return f}(a=akeeba.System.findElement(a))&&(a.addEventListener?a.addEventListener(b,d,!1):a.attachEvent("on"+b,function(){var e=c.call(a,window.event);!1===e&&(window.event.returnValue=!1,window.event.cancelBubble=!0);return e}))};
akeeba.System.removeEventListener=function(a,b,c){(a=akeeba.System.findElement(a))&&(a.removeEventListener?a.removeEventListener(b,c):a.detachEvent("on"+b,c))};akeeba.System.triggerEvent=function(a,b){if(a=akeeba.System.findElement(a))if("click"===b&&"function"===typeof a.click)a.click();else if(document.fireEvent&&"undefined"==typeof window.Event)a.fireEvent("on"+b);else{var c=document.createEvent("Event");c.initEvent(b,!0,!0);a.dispatchEvent(c)}};
(function(a,b){function c(){if(!f){f=!0;for(var g=0;g<e.length;g++)e[g].fn.call(window,e[g].ctx);e=[]}}function d(){"complete"===document.readyState&&c()}b=b||akeeba.System;var e=[],f=!1,l=!1;b[a||"documentReady"]=function(g,p){f?setTimeout(function(){g(p)},1):(e.push({fn:g,ctx:p}),"complete"===document.readyState||!document.attachEvent&&"interactive"===document.readyState?setTimeout(c,1):l||(l=!0,document.addEventListener?(document.addEventListener("DOMContentLoaded",c,!1),window.addEventListener("load",
c,!1)):(document.attachEvent("onreadystatechange",d),window.attachEvent("onload",c))))}})("documentReady",akeeba.System);akeeba.System.addClass=function(a,b){if(a){try{var c=a.className.split(" ")}catch(d){return}"string"==typeof b&&(b=b.split(" "));c=akeeba.System.array_merge(c,b);a.className="";for(property in c)c.hasOwnProperty(property)&&(a.className+=c[property]+" ");a.className.trim&&(a.className=a.className.trim())}};
akeeba.System.removeClass=function(a,b){if(a){try{var c=a.className.split(" ")}catch(d){return}"string"==typeof b&&(b=b.split(" "));c=akeeba.System.array_diff(c,b);a.className="";for(property in c)c.hasOwnProperty(property)&&(a.className+=c[property]+" ");a.className.trim&&(a.className=a.className.trim())}};akeeba.System.hasClass=function(a,b){if(!a)return!1;try{var c=a.className.split(" ")}catch(d){return!1}for(i=0;i<c.length;i++)if(c[i]===b)return!0;return!1};
akeeba.System.toggleClass=function(a,b){akeeba.System.hasClass(a,b)?akeeba.System.removeClass(a,b):akeeba.System.addClass(a,b)};akeeba.System.tableOrdering=function(a,b,c,d){"undefined"===typeof d&&(d=document.getElementById("adminForm"));d.filter_order.value=a;d.filter_order_Dir.value=b;akeeba.System.submitForm(c,d)};
akeeba.System.submitForm=function(a,b,c){b||(b=document.getElementById("adminForm"));a&&(b.task.value=a);b.noValidate=!c;c?b.hasAttribute("novalidate")&&b.removeAttribute("novalidate"):b.setAttribute("novalidate","");a=document.createElement("input");a.style.display="none";a.type="submit";b.appendChild(a);a.click();b.removeChild(a)};
akeeba.System.orderTable=function(){var a=document.getElementById("sortTable"),b=document.getElementById("directionTable");a=a.options[a.selectedIndex].value;var c="asc";a===akeeba.System.getOptions("akeeba.System.tableOrder","asc")&&(c=b.options[b.selectedIndex].value);akeeba.System.tableOrdering(a,c)};
akeeba.System.iterateNodes=function(a,b,c){if("function"==typeof b&&("string"===typeof a&&(a=document.querySelectorAll(a)),0!==a.length)){var d;for(d=0;d<a.length;d++){var e=a[d];"undefined"!==typeof c?b(e,c):b(e)}}};
akeeba.System.assignDefaultErrorHandler=function(){akeeba.System.params.errorCallback=akeeba.System.modalErrorHandler;if("undefined"===typeof akeeba.Modal)akeeba.System.params.errorCallback=akeeba.System.defaultErrorHandler;else{var a=akeeba.System.getOptions("akeeba.System.params.errorDialogId",akeeba.System.params.errorDialogId),b=akeeba.System.getOptions("akeeba.System.params.errorDialogMessageId",akeeba.System.params.errorDialogMessageId);if(""===a||null===a||""===b||null===b)akeeba.System.params.errorCallback=
akeeba.System.defaultErrorHandler;else if(a=document.getElementById(a),b=document.getElementById(b),null===a||null===b)akeeba.System.params.errorCallback=akeeba.System.defaultErrorHandler}};
akeeba.System.documentReady(function(){akeeba.System.assignDefaultErrorHandler();akeeba.System.iterateNodes(".akeebaGridViewCheckAll",function(a){akeeba.System.addEventListener(a,"click",function(){Joomla.checkAll(this)})});akeeba.System.iterateNodes(".akeebaGridViewOrderTable",function(a){akeeba.System.addEventListener(a,"change",akeeba.System.orderTable)});akeeba.System.iterateNodes(".akeebaGridViewAutoSubmitOnChange",function(a){akeeba.System.addEventListener(a,"change",function(){akeeba.System.submitForm()})})});
akeeba.System.Text={strings:{},_:function(a,b){["akeeba.text","joomla.jtext"].forEach(function(c){var d=akeeba.System.getOptions(c);d&&(akeeba.System.Text.load(d),d={},d[c]=null,akeeba.System.loadOptions(d))});b=void 0===b?"":b;a=a.toUpperCase();return void 0!==akeeba.System.Text.strings[a]?akeeba.System.Text.strings[a]:"undefined"!=typeof Joomla.JText?Joomla.JText._(a,b):"undefined"!=typeof Joomla.Text?Joomla.Text._(a,b):b},load:function(a){for(var b in a)a.hasOwnProperty(b)&&(this.strings[b.toUpperCase()]=
a[b]);return this}};
akeeba.System.CommonEvents={onEventSubmit:function(a){var b=akeeba.System.data.get(a.currentTarget,"akeebasubmittarget",""),c=document.forms.adminForm?document.forms.adminForm:null;""!==b&&(c=document.getElementById(b));if(!c)return!0;c.submit();a.preventDefault();return!1},onClickConfirm:function(a){var b=akeeba.System.data.get(a.currentTarget,"akeebaconfirmmessage","");if(""===b||confirm(Joomla.Text._(b)))return!0;a.preventDefault();return!1},onEventOrderTable:function(a){a.preventDefault();Joomla.orderTable();
return!1},init:function(){akeeba.System.iterateNodes(".akeebaCommonEventsOnChangeSubmit",function(a){akeeba.System.addEventListener(a,"change",akeeba.System.CommonEvents.onEventSubmit)});akeeba.System.iterateNodes(".akeebaCommonEventsOnClickSubmit",function(a){akeeba.System.addEventListener(a,"click",akeeba.System.CommonEvents.onEventSubmit)});akeeba.System.iterateNodes(".akeebaCommonEventsOnClickConfirm",function(a){akeeba.System.addEventListener(a,"click",akeeba.System.CommonEvents.onClickConfirm)});
akeeba.System.iterateNodes(".akeebaCommonEventsOnChangeOrderTable",function(a){akeeba.System.addEventListener(a,"change",akeeba.System.CommonEvents.onEventOrderTable)})}};akeeba.System.CommonEvents.init(); //# sourceMappingURL=System.map

15
media/fef/js/Tooltip.min.js vendored Normal file
View File

@ -0,0 +1,15 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
if("undefined"==typeof akeeba)var akeeba={};"undefined"==typeof akeeba.Tooltip&&(akeeba.Tooltip={});akeeba.Tooltip.enableFor=function(a,b){if("undefined"==typeof b||null===b)b=!0;if("object"==typeof a&&NodeList.prototype.isPrototypeOf(a))for(i=0;i<a.length;i++)akeeba.Tooltip.enableFor(a[i],b);else akeeba.System.addEventListener(a,"mouseenter",akeeba.Tooltip.onMouseEnter),akeeba.System.addEventListener(a,"mouseleave",akeeba.Tooltip.onMouseLeave),b&&akeeba.System.addEventListener(a,"click",akeeba.Tooltip.onClick)};
akeeba.Tooltip.simpleTooltip=function(a){if(a.hasAttribute("title")){var b=a.getAttribute("title"),c="right";a.hasAttribute("data-akeeba-tooltip-position")&&(c=a.getAttribute("data-akeeba-tooltip-position"));akeeba.System.addClass(a,"akeeba-hasTooltip");var d=document.createElement("div");d.className="akeeba-tooltip-text akeeba-tooltip-text-"+c;d.innerHTML=b;a.appendChild(d);a.removeAttribute("title")}};
akeeba.Tooltip.onMouseEnter=function(a){if(a.target.hasAttribute("data-content")){if(a.target.hasAttribute("data-tooltip-uuid"))var b=a.target.getAttribute("data-tooltip-uuid");else b=Math.uuid(),a.target.setAttribute("data-tooltip-uuid",b);if(null==document.getElementById("akeeba-tooltip-"+b)){var c=a.target.getAttribute("data-position")||"center bottom",d=c.split(" ")[0],e=c.split(" ")[1],f=document.createElement("div");f.className="akeeba-popover";f.id="akeeba-tooltip-"+b;f.style.display="block";
f.className+=" "+c;f.insertAdjacentHTML("afterbegin",'<div class="arrow"></div>');b=document.createElement("div");b.className="akeeba-popover-inner";f.appendChild(b);a.target.hasAttribute("data-original-title")&&(c=document.createElement("h3"),c.className="akeeba-popover-title",c.innerHTML=a.target.getAttribute("data-original-title"),b.appendChild(c));c=document.createElement("div");c.className="akeeba-popover-content";c.innerHTML=a.target.getAttribute("data-content");b.appendChild(c);document.body.appendChild(f);
akeeba.Tooltip.positionAt(a.target,f,d,e)}}};akeeba.Tooltip.onMouseLeave=function(a){a.target.hasAttribute("data-tooltip-noclose")||akeeba.Tooltip.hideTooltip(a.target)};akeeba.Tooltip.onClick=function(a){if(a.target.hasAttribute("data-tooltip-uuid"))if(a.target.hasAttribute("data-tooltip-noclose"))a.target.removeAttribute("data-tooltip-noclose");else{var b=a.target.getAttribute("data-tooltip-uuid");null!=document.getElementById("akeeba-tooltip-"+b)&&a.target.setAttribute("data-tooltip-noclose",1)}};
akeeba.Tooltip.hideTooltip=function(a){a.hasAttribute("data-tooltip-uuid")&&(a=a.getAttribute("data-tooltip-uuid"),(a=document.getElementById("akeeba-tooltip-"+a))&&document.body.removeChild(a))};
akeeba.Tooltip.positionAt=function(a,b,c,d){var e=a.getBoundingClientRect();switch(c){case "left":a=parseInt(e.left)-10-b.offsetWidth;0>parseInt(e.left)-b.offsetWidth&&(a=10);break;case "right":a=e.right+10;parseInt(e.right)+b.offsetWidth>document.documentElement.clientWidth&&(a=document.documentElement.clientWidth-b.offsetWidth-10);break;default:case "center":a=parseInt(e.left)+(a.offsetWidth-b.offsetWidth)/2}switch(d){case "center":d=(parseInt(e.top)+parseInt(e.bottom))/2-b.offsetHeight/2;break;
case "bottom":d=parseInt(e.bottom)+10;break;default:case "top":d=parseInt(e.top)-b.offsetHeight-10}a=0>a?parseInt(e.left):a;d=0>d?parseInt(e.bottom)+10:d;b.style.left=a+"px";b.style.top=d+pageYOffset+"px"}; //# sourceMappingURL=Tooltip.map

56
media/fef/js/darkmode.js Normal file
View File

@ -0,0 +1,56 @@
/*
* 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();
}
}
};

8
media/fef/js/darkmode.min.js vendored Normal file
View File

@ -0,0 +1,8 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};window.akeeba.fef=window.akeeba.fef||{};akeeba.fef.darkMode=function(a){null==a&&(a=!0);a=document.querySelectorAll(".akeeba-renderer-fef");0!==a.length&&akeeba.System.forEach(a,function(c,b){akeeba.System.toggleClass(b,"akeeba-renderer-fef--dark")})}; //# sourceMappingURL=Darkmode.map

View File

@ -0,0 +1,8 @@
{
"version":3,
"file":"/Users/nicholas/Projects/akeeba/fef/out/js/darkmode.min.js",
"lineCount":1,
"mappings":"AAUsB,WAAtB,GAAI,MAAOA,OAAX,GAECA,MAFD,CAEU,EAFV,CAK0B,YAA1B,GAAI,MAAOA,OAAAC,IAAX,GAECD,MAAAC,IAFD,CAEc,EAFd,CAKAD,OAAAC,IAAAC,SAAA,CAAsBC,QAAQ,CAACC,CAAD,CAC9B,CACe,IAAd,EAAIA,CAAJ,GAECA,CAFD,CAEU,CAAA,CAFV,CAOA,KAFA,IAAIC,EAAUC,QAAAC,iBAAA,CAA0B,sBAA1B,CAAd,CAESC,EAAI,CAAb,CAAgBA,CAAhB,CAAoBH,CAAAI,OAApB,CAAoCD,CAAA,EAApC,CAAyC,CACxC,IAAIE,EAASL,CAAA,CAAQG,CAAR,CAAb,CACIG,EAAiBD,CAAAE,UAAAC,MAAA,CAAuB,GAAvB,CACrBH,EAAAE,UAAA,CAAmB,EAEnB,KAAK,IAAIE,EAAI,CAAb,CAAgBA,CAAhB,CAAoBH,CAAAF,OAApB,CAA2CK,CAAA,EAA3C,CAAgD,CAC/C,IAAIC,EAAYJ,CAAA,CAAeG,CAAf,CAEE,4BAAlB,GAAIC,CAAJ,GAKAL,CAAAE,UALA,EAKoB,GALpB,CAK0BG,CAL1B,CAH+C,CAW5CX,CAAJ,GAECM,CAAAE,UAFD,EAEqB,4BAFrB,CAKIF,EAAAE,UAAAI,KAAJ,GAECN,CAAAE,UAFD,CAEoBF,CAAAE,UAAAI,KAAA,EAFpB,CArBwC,CAR1C;",
"sources":["/Users/nicholas/Projects/akeeba/fef/out/js/darkmode.js"],
"names":["akeeba","fef","darkMode","akeeba.fef.darkMode","status","elNodes","document","querySelectorAll","i","length","elNode","currentClasses","className","split","j","thisClass","trim"]
}

View File

@ -0,0 +1,11 @@
{
"Ajax": [],
"Darkmode": ["System"],
"Dropdown": ["System"],
"Loader": [],
"Menu": [],
"Modal": [],
"System": ["Loader", "Ajax", "Modal"],
"Tabs": ["System"],
"Tooltip": ["System"]
}

205
media/fef/js/dropdown.js Normal file
View File

@ -0,0 +1,205 @@
/*
* 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 = {};
}
if (typeof akeeba.fef.forEach === 'undefined')
{
akeeba.fef.forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
}
if (typeof akeeba.fef.triggerEvent === 'undefined')
{
akeeba.fef.triggerEvent = function (element, eventName)
{
if (typeof element === 'undefined')
{
return;
}
if (element === null)
{
return;
}
// Allow the passing of an element ID string instead of the DOM elem
if (typeof element === "string")
{
element = document.getElementById(element);
}
if (typeof element !== 'object')
{
return;
}
if (!(element instanceof Element))
{
return;
}
// Use jQuery and be done with it!
if (typeof window.jQuery === 'function')
{
window.jQuery(element).trigger(eventName);
return;
}
// Internet Explorer way
if (document.fireEvent && (typeof window.Event === 'undefined'))
{
element.fireEvent('on' + eventName);
return;
}
// This works on Chrome and Edge but not on Firefox. Ugh.
var event = null;
event = document.createEvent("Event");
event.initEvent(eventName, true, true);
element.dispatchEvent(event);
};
}
/**
* Activates the dropdown interface for specific HTML elements
*
* @param {String} [selector] CSS selector for the tab-set wrapper(s). Default: 'nav.akeeba-dropdown'
*/
akeeba.fef.dropdown = function(selector)
{
// Use the default selector, if necessary
if ((typeof selector === 'undefined') || (selector === ''))
{
selector = 'nav.akeeba-dropdown';
}
// Get all outer wrappers (NAV elements)
var navList = document.querySelectorAll(selector);
if (navList.length === 0)
{
return;
}
// Loop for the first button inside each wrapper (the NAV)
akeeba.fef.forEach(navList, function(i, elNav) {
// Get the first button inside the NAV wrapper. That's our drop-down toggle.
var buttonList = elNav.querySelectorAll('button');
if (buttonList.length === 0)
{
return;
}
var elButton = buttonList[0];
// Add an event listener to toggle the "open" class whenever the button is clicked.
elButton.addEventListener('click', function (event) {
var isOpen = false;
var currentClasses = this.className.split(' ');
var newClass = '';
for (var property in currentClasses)
{
if (!currentClasses.hasOwnProperty(property))
{
continue;
}
if (currentClasses[property] === 'open')
{
isOpen = true;
continue;
}
newClass += currentClasses[property] + ' ';
}
if (newClass.trim)
{
newClass = newClass.trim();
}
if (!isOpen)
{
newClass += ' open';
}
this.className = newClass;
event.preventDefault();
});
// Loop through all section > 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();
});
});
});
};

10
media/fef/js/dropdown.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};window.akeeba.fef=window.akeeba.fef||{};
akeeba.fef.dropdown=function(a){if("undefined"===typeof a||""===a)a="nav.akeeba-dropdown";a=document.querySelectorAll(a);0!==a.length&&akeeba.System.forEach(a,function(b,d){b=d.querySelectorAll("button");if(0!==b.length){var e=b[0];e.addEventListener("click",function(f){akeeba.System.toggleClass(this,"open");f.preventDefault()});var c=d.querySelectorAll("section > a");0!==c.length&&akeeba.System.forEach(c,function(f,g){g.addEventListener("click",function(h){akeeba.System.triggerEvent(e,"click");akeeba.System.forEach(c,
function(l,k){akeeba.System.removeClass(k,"current")});akeeba.System.addClass(this,"current");h.preventDefault()})})}})}; //# sourceMappingURL=Dropdown.map

View File

@ -0,0 +1,8 @@
{
"version":3,
"file":"/Users/nicholas/Projects/akeeba/fef/out/js/dropdown.min.js",
"lineCount":4,
"mappings":"AAUsB,WAAtB,GAAI,MAAOA,OAAX,GAEIA,MAFJ,CAEa,EAFb,CAK0B,YAA1B,GAAI,MAAOA,OAAAC,IAAX,GAEID,MAAAC,IAFJ,CAEiB,EAFjB,CAKkC,YAAlC,GAAI,MAAOD,OAAAC,IAAAC,QAAX,GAECF,MAAAC,IAAAC,QAFD,CAEsBC,QAAS,CAACC,CAAD,CAAQC,CAAR,CAAkBC,CAAlB,CAAyB,CACtD,IAAK,IAAIC,EAAI,CAAb,CAAgBA,CAAhB,CAAoBH,CAAAI,OAApB,CAAkCD,CAAA,EAAlC,CACCF,CAAAI,KAAA,CAAcH,CAAd,CAAqBC,CAArB,CAAwBH,CAAA,CAAMG,CAAN,CAAxB,CAFqD,CAFxD,CASuC;WAAvC,GAAI,MAAOP,OAAAC,IAAAS,aAAX,GAECV,MAAAC,IAAAS,aAFD,CAE2BC,QAAS,CAACC,CAAD,CAAUC,CAAV,CACnC,CACC,GAAuB,WAAvB,GAAI,MAAOD,EAAX,EAKgB,IALhB,GAKIA,CALJ,GAWuB,QAKnB,GALA,MAAOA,EAKP,GAHHA,CAGG,CAHOE,QAAAC,eAAA,CAAwBH,CAAxB,CAGP,EAAmB,QAAnB,GAAA,MAAOA,EAAP,EAKEA,CALF,WAKqBI,QArBzB,EA2BA,GAA6B,UAA7B,GAAI,MAAOC,OAAAC,OAAX,CAECD,MAAAC,OAAA,CAAcN,CAAd,CAAAO,QAAA,CAA+BN,CAA/B,CAFD,KAQA,IAAIC,QAAAM,UAAJ,EAAmD,WAAnD,GAA2B,MAAOH,OAAAI,MAAlC,CAECT,CAAAQ,UAAA,CAAkB,IAAlB,CAAyBP,CAAzB,CAFD,KAAA,CAUA,IAAAS,EAAQR,QAAAS,YAAA,CAAqB,OAArB,CACRD,EAAAE,UAAA,CAAgBX,CAAhB,CAA2B,CAAA,CAA3B,CAAiC,CAAA,CAAjC,CACAD,EAAAa,cAAA,CAAsBH,CAAtB,CAZA,CApCD,CAHD,CA4DAtB;MAAAC,IAAAyB,SAAA,CAAsBC,QAAQ,CAACC,CAAD,CAC9B,CAEI,GAAyB,WAAzB,GAAK,MAAOA,EAAZ,EAAuD,EAAvD,GAA0CA,CAA1C,CAEIA,CAAA,CAAW,qBAIXC,EAAAA,CAAUf,QAAAgB,iBAAA,CAA0BF,CAA1B,CAES,EAAvB,GAAIC,CAAArB,OAAJ,EAMAR,MAAAC,IAAAC,QAAA,CAAmB2B,CAAnB,CAA4B,QAAQ,CAACtB,CAAD,CAAIwB,CAAJ,CAAW,CAEvCC,CAAAA,CAAaD,CAAAD,iBAAA,CAAuB,QAAvB,CAEjB,IAA0B,CAA1B,GAAIE,CAAAxB,OAAJ,CAAA,CAKA,IAAIyB,EAAWD,CAAA,CAAW,CAAX,CAGrBC,EAAAC,iBAAA,CAA0B,OAA1B,CAAmC,QAAS,CAACZ,CAAD,CAAQ,CAChD,IAAIa,EAAS,CAAA,CAAb,CACCC,EAAiB,IAAAC,UAAAC,MAAA,CAAqB,GAArB,CADlB,CAECC,EAAW,EAFZ,CAIMC,CAAT,KAASA,CAAT,GAAqBJ,EAArB,CAEMA,CAAAK,eAAA,CAA8BD,CAA9B,CAAL,GAK6C,MAAjC,GAAIJ,CAAA,CAAeI,CAAf,CAAJ,CAEIL,CAFJ,CAEa,CAAA,CAFb,CAOZI,CAPY,EAOAH,CAAA,CAAeI,CAAf,CAPA,CAO2B,GAZvC,CAeGD,EAAAG,KAAJ,GAECH,CAFD,CAEYA,CAAAG,KAAA,EAFZ,CAKKP,EAAL,GAEaI,CAFb,EAEyB,OAFzB,CAKA,KAAAF,UAAA,CAAiBE,CAEjBjB,EAAAqB,eAAA,EAlCmD,CAApD,CAsCM,KAAIC,EAAWb,CAAAD,iBAAA,CAAuB,aAAvB,CAES,EAAxB,GAAIc,CAAApC,OAAJ;AAWNR,MAAAC,IAAAC,QAAA,CAAmB0C,CAAnB,CAA6B,QAAQ,CAACrC,CAAD,CAAIsC,CAAJ,CAAY,CAChDA,CAAAX,iBAAA,CAAwB,OAAxB,CAAiC,QAAS,CAACZ,CAAD,CAAQ,CAEjDtB,MAAAC,IAAAS,aAAA,CAAwBuB,CAAxB,CAAkC,OAAlC,CAGAjC,OAAAC,IAAAC,QAAA,CAAmB0C,CAAnB,CAA6B,QAAQ,CAACrC,CAAD,CAAIK,CAAJ,CAAa,CAC7CwB,CAAAA,CAAiBxB,CAAAyB,UAAAC,MAAA,CAAwB,GAAxB,CACrB,KAAIC,EAAW,EAAf,CAESC,CAAT,KAASA,CAAT,GAAqBJ,EAArB,CAEMA,CAAAK,eAAA,CAA8BD,CAA9B,CAAL,EAA8E,SAA9E,GAAiDJ,CAAA,CAAeI,CAAf,CAAjD,GAKAD,CALA,EAKYH,CAAA,CAAeI,CAAf,CALZ,CAKuC,GALvC,CAQGD,EAAAG,KAAJ,GAECH,CAFD,CAEYA,CAAAG,KAAA,EAFZ,CAKA9B,EAAAyB,UAAA,CAAoBE,CAnB6B,CAAlD,CAuBA,KAAAF,UAAA,EAAkB,UAElBf,EAAAqB,eAAA,EA9BiD,CAAlD,CADgD,CAAjD,CA3DM,CAJ2C,CAA/C,CAhBJ;",
"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"]
}

10
media/fef/js/loader.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};
(function(h,r){function m(){n=!0;p()}function p(){n&&null===f&&(f=setInterval(t,200))}function q(a){a=a.split(".");for(var b=window,c=0;c<a.length;c++){if("object"!==typeof b||"undefined"===typeof b[a[c]])return!1;b=b[a[c]]}return!0}function t(){if(!k)if(d.length){k=!0;for(var a=[],b=0;b<d.length;b++){var c=d[b],e=c[0];c=c[1];if("string"===typeof e)var g=q(e);else{g=!0;for(var l=0;l<e.length;l++)g=g&&q(e[l])}g?c():a[a.length]=[e,c]}d=a;k=!1}else clearInterval(f),f=null}var n=!1,d=[],f=null,k=!1;h.Loader=
h.Loader||{};h.Loader.add=function(a,b){d[d.length]=[a,b];p()};r.addEventListener("DOMContentLoaded",m,!1);window.addEventListener("load",m,!1)})(akeeba,document); //# sourceMappingURL=Loader.map

50
media/fef/js/menu.js Normal file
View File

@ -0,0 +1,50 @@
/*
* 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.menuButton = function(selector)
{
// Use the default selector, if necessary
if ((typeof selector === 'undefined') || (selector === ''))
{
selector = 'a.akeeba-menu-button';
}
var menuButtonsList = document.querySelectorAll(selector);
if (menuButtonsList.length === 0)
{
return;
}
menuButtonsList.forEach(function(elButton) {
elButton.addEventListener('click', function(event) {
var elNav = elButton.parentElement.parentElement.querySelector('nav');
if (elNav.style.display !== 'flex')
{
elNav.style.display = 'flex';
return;
}
elNav.style.display = null;
});
});
};

8
media/fef/js/menu.min.js vendored Normal file
View File

@ -0,0 +1,8 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};window.akeeba.fef=window.akeeba.fef||{};akeeba.fef.menuButton=function(a){if("undefined"===typeof a||""===a)a="a.akeeba-menu-button";a=document.querySelectorAll(a);0!==a.length&&a.forEach(function(c){c.addEventListener("click",function(b){b=c.parentElement.parentElement.querySelector("nav");b.style.display="flex"!==b.style.display?"flex":null})})}; //# sourceMappingURL=Menu.map

View File

@ -0,0 +1,8 @@
{
"version":3,
"file":"/Users/nicholas/Projects/akeeba/fef/out/js/menu.min.js",
"lineCount":1,
"mappings":"AAUsB,WAAtB,GAAI,MAAOA,OAAX,GAEIA,MAFJ,CAEa,EAFb,CAK0B,YAA1B,GAAI,MAAOA,OAAAC,IAAX,GAEID,MAAAC,IAFJ,CAEiB,EAFjB,CAKAD,OAAAC,IAAAC,WAAA,CAAwBC,QAAQ,CAACC,CAAD,CAChC,CAEI,GAAyB,WAAzB,GAAK,MAAOA,EAAZ,EAAuD,EAAvD,GAA0CA,CAA1C,CAEIA,CAAA,CAAW,sBAGXC,EAAAA,CAAkBC,QAAAC,iBAAA,CAA0BH,CAA1B,CAES,EAA/B,GAAIC,CAAAG,OAAJ,EAKAH,CAAAI,QAAA,CAAwB,QAAQ,CAACC,CAAD,CAAW,CACvCA,CAAAC,iBAAA,CAA0B,OAA1B,CAAmC,QAAQ,CAACC,CAAD,CAAQ,CAC3CC,CAAAA,CAAQH,CAAAI,cAAAA,cAAAC,cAAA,CAAmD,KAAnD,CAIRF,EAAAG,MAAAC,QAAA,CAFwB,MAA5B,GAAIJ,CAAAG,MAAAC,QAAJ,CAE0B,MAF1B,CAOsB,IAVyB,CAAnD,CADuC,CAA3C,CAdJ;",
"sources":["/Users/nicholas/Projects/akeeba/fef/out/js/menu.js"],
"names":["akeeba","fef","menuButton","akeeba.fef.menuButton","selector","menuButtonsList","document","querySelectorAll","length","forEach","elButton","addEventListener","event","elNav","parentElement","querySelector","style","display"]
}

128
media/fef/js/tabs.js Normal file
View File

@ -0,0 +1,128 @@
/*
* 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 = {};
}
if (typeof akeeba.fef.forEach === 'undefined')
{
akeeba.fef.forEach = function (array, callback, scope) {
for (var i = 0; i < array.length; i++) {
callback.call(scope, i, array[i]);
}
};
}
/**
* Activates the tab interface for specific HTML elements
*
* @param {String} [selector] CSS selector for the tab-set wrapper(s). Default: 'div.akeeba-tabs'
*/
akeeba.fef.tabs = function(selector)
{
// Use the default selector, if necessary
if ((typeof selector === 'undefined') || (selector === ''))
{
selector = 'div.akeeba-tabs';
}
var wrappersList = document.querySelectorAll(selector);
if (wrappersList.length === 0)
{
return;
}
// Loop for every tab set matching the selector
akeeba.fef.forEach(wrappersList, function(i, elWrapper) {
// Sort the child elements of the selector to tabs (label) and panels (section)
var tabList = elWrapper.querySelectorAll('label');
var tabId = elWrapper.id;
var tabPreselected = '';
if (tabList.length === 0)
{
return;
}
if (tabId != '')
{
tabPreselected = window.sessionStorage.getItem('akeeba.tabs.' + tabId);
}
akeeba.fef.forEach(tabList, function(k, elTab) {
if (elTab.parentElement !== elWrapper)
{
return;
}
elTab.addEventListener('click', function (event) {
var selectedId = this.getAttribute('for');
akeeba.fef.forEach(tabList, function(q, element) {
if (element.parentElement !== elWrapper)
{
return;
}
var currentClasses = element.className.split(' ');
var newClass = '';
for (var property in currentClasses)
{
if (!currentClasses.hasOwnProperty(property) || (currentClasses[property] === 'active'))
{
continue;
}
newClass += currentClasses[property] + ' ';
}
if (newClass.trim)
{
newClass = newClass.trim();
}
// If the 'for' attribute matches add back the "active" class
if (element.getAttribute('for') === selectedId)
{
window.sessionStorage.setItem('akeeba.tabs.' + tabId, selectedId);
newClass += ' active';
}
element.className = newClass;
});
});
});
if (tabPreselected != '')
{
akeeba.fef.forEach(tabList, function(k, elTab) {
if (elTab.parentElement !== elWrapper)
{
return;
}
if (elTab.getAttribute('for') == tabPreselected)
{
var clickEvent = new MouseEvent('click');
elTab.dispatchEvent(clickEvent);
}
});
}
});
};

10
media/fef/js/tabs.min.js vendored Normal file
View File

@ -0,0 +1,10 @@
/*
Akeeba Frontend Framework (FEF)
@package fef
@copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
@license GNU General Public License version 3, or later
*/
window.akeeba=window.akeeba||{};window.akeeba.fef=window.akeeba.fef||{};
akeeba.fef.tabs=function(a){if("undefined"===typeof a||""===a)a="div.akeeba-tabs";a=document.querySelectorAll(a);0!==a.length&&akeeba.System.forEach(a,function(l,c){var d=c.querySelectorAll("label"),f=c.id,g="";0!==d.length&&(""!=f&&(g=window.sessionStorage.getItem("akeeba.tabs."+f)),akeeba.System.forEach(d,function(k,b){b.parentElement===c&&b.addEventListener("click",function(m){var h=this.getAttribute("for");akeeba.System.forEach(d,function(n,e){e.parentElement===c&&(e.getAttribute("for")===h?(window.sessionStorage.setItem("akeeba.tabs."+
f,h),akeeba.System.addClass(e,"active")):akeeba.System.removeClass(e,"active"))})})}),""!=g&&akeeba.System.forEach(d,function(k,b){b.parentElement===c&&b.getAttribute("for")===g&&akeeba.System.triggerEvent(b,"click")}))})}; //# sourceMappingURL=Tabs.map

View File

@ -0,0 +1,8 @@
{
"version":3,
"file":"/Users/nicholas/Projects/akeeba/fef/out/js/tabs.min.js",
"lineCount":3,
"mappings":"AAUsB,WAAtB,GAAI,MAAOA,OAAX,GAEIA,MAFJ,CAEa,EAFb,CAK0B,YAA1B,GAAI,MAAOA,OAAAC,IAAX,GAEID,MAAAC,IAFJ,CAEiB,EAFjB,CAKkC,YAAlC,GAAI,MAAOD,OAAAC,IAAAC,QAAX,GAECF,MAAAC,IAAAC,QAFD,CAEsBC,QAAS,CAACC,CAAD,CAAQC,CAAR,CAAkBC,CAAlB,CAAyB,CACtD,IAAK,IAAIC,EAAI,CAAb,CAAgBA,CAAhB,CAAoBH,CAAAI,OAApB,CAAkCD,CAAA,EAAlC,CACCF,CAAAI,KAAA,CAAcH,CAAd,CAAqBC,CAArB,CAAwBH,CAAA,CAAMG,CAAN,CAAxB,CAFqD,CAFxD,CAcAP;MAAAC,IAAAS,KAAA,CAAkBC,QAAQ,CAACC,CAAD,CAC1B,CAEI,GAAyB,WAAzB,GAAK,MAAOA,EAAZ,EAAuD,EAAvD,GAA0CA,CAA1C,CAEIA,CAAA,CAAW,iBAGXC,EAAAA,CAAeC,QAAAC,iBAAA,CAA0BH,CAA1B,CAES,EAA5B,GAAIC,CAAAL,OAAJ,EAMAR,MAAAC,IAAAC,QAAA,CAAmBW,CAAnB,CAAiC,QAAQ,CAACN,CAAD,CAAIS,CAAJ,CAAe,CAEpD,IAAIC,EAAUD,CAAAD,iBAAA,CAA2B,OAA3B,CAAd,CACIG,EAAQF,CAAAG,GADZ,CAEIC,EAAiB,EAEE,EAAvB,GAAIH,CAAAT,OAAJ,GAKa,EAkDnB,EAlDUU,CAkDV,GAhDUE,CAgDV,CAhD2BC,MAAAC,eAAAC,QAAA,CAA8B,cAA9B,CAA+CL,CAA/C,CAgD3B,EA7CMlB,MAAAC,IAAAC,QAAA,CAAmBe,CAAnB,CAA4B,QAAQ,CAACO,CAAD,CAAIC,CAAJ,CAAW,CACvCA,CAAAC,cAAJ,GAA4BV,CAA5B,EAKAS,CAAAE,iBAAA,CAAuB,OAAvB,CAAgC,QAAS,CAACC,CAAD,CAAQ,CAC7C,IAAIC,EAAa,IAAAC,aAAA,CAAkB,KAAlB,CAEjB9B,OAAAC,IAAAC,QAAA,CAAmBe,CAAnB,CAA4B,QAAQ,CAACc,CAAD,CAAIC,CAAJ,CAAa,CAC7C,GAAIA,CAAAN,cAAJ,GAA8BV,CAA9B,CAAA,CAKIiB,CAAAA,CAAiBD,CAAAE,UAAAC,MAAA,CAAwB,GAAxB,CACrB,KAAIC,EAAW,EAAf;AAESC,CAAT,KAASA,CAAT,GAAqBJ,EAArB,CAESA,CAAAK,eAAA,CAA8BD,CAA9B,CAAL,EAA8E,QAA9E,GAAiDJ,CAAA,CAAeI,CAAf,CAAjD,GAKAD,CALA,EAKYH,CAAA,CAAeI,CAAf,CALZ,CAKuC,GALvC,CAQAD,EAAAG,KAAJ,GAEIH,CAFJ,CAEeA,CAAAG,KAAA,EAFf,CAMIP,EAAAF,aAAA,CAAqB,KAArB,CAAJ,GAAoCD,CAApC,GAEdR,MAAAC,eAAAkB,QAAA,CAA8B,cAA9B,CAA+CtB,CAA/C,CAAsDW,CAAtD,CACkB,CAAAO,CAAA,EAAY,SAHhB,CAMAJ,EAAAE,UAAA,CAAoBE,CA9BpB,CAD6C,CAAjD,CAH6C,CAAjD,CAN2C,CAA/C,CA6CN,CAAsB,EAAtB,EAAIhB,CAAJ,EAECpB,MAAAC,IAAAC,QAAA,CAAmBe,CAAnB,CAA4B,QAAQ,CAACO,CAAD,CAAIC,CAAJ,CAAW,CAC1CA,CAAAC,cAAJ,GAA4BV,CAA5B,EAKIS,CAAAK,aAAA,CAAmB,KAAnB,CALJ,EAKiCV,CALjC,GAOKqB,CACJ,CADiB,IAAIC,UAAJ,CAAe,OAAf,CACjB,CAAAjB,CAAAkB,cAAA,CAAoBF,CAApB,CARD,CAD8C,CAA/C,CAzDK,CANoD,CAAxD,CAfJ;",
"sources":["/Users/nicholas/Projects/akeeba/fef/out/js/tabs.js"],
"names":["akeeba","fef","forEach","akeeba.fef.forEach","array","callback","scope","i","length","call","tabs","akeeba.fef.tabs","selector","wrappersList","document","querySelectorAll","elWrapper","tabList","tabId","id","tabPreselected","window","sessionStorage","getItem","k","elTab","parentElement","addEventListener","event","selectedId","getAttribute","q","element","currentClasses","className","split","newClass","property","hasOwnProperty","trim","setItem","clickEvent","MouseEvent","dispatchEvent"]
}

View File

@ -0,0 +1,316 @@
<?php
/**
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2021 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
/**
* Loads Akeeba FEF CSS and JavaScript files. Cross-platform.
*/
class AkeebaFEFLoader
{
/**
* Script dependencies, as loaded from dependencies.json
*
* @var array
* @since 2.0.0
*/
private $dependenciesCache = [];
/**
* Is the Akeeba FEF CSS Framework already loaded?
*
* @var bool
* @since 2.0.0
*/
private $loadedCSSFramework = false;
/**
* Is the Akeeba FEF JavaScript Framework already loaded?
*
* 0: no; 1: minimal; 2: full
*
* @var int
* @since 2.0.0
*/
private $loadedJSFramework = 0;
/**
* The platform-specific callback for loading an FEF CSS file given its basename.
*
* @var callable
* @since 2.0.0
*/
private $cssLoaderCallback;
/**
* The platform-specific callback for loading an FEF JavaScript file given its basename.
*
* @var callable
* @since 2.0.0
*/
private $jsLoaderCallback;
/**
* The platform we are currently running under. Auto-detected if not set.
*
* @var null|string
* @since 2.0.0
*/
private $platform;
/**
* Records the FEF JS files which have already been loaded.
*
* @var array
* @since 2.0.0
*/
private $loadedScripts = [];
public function __construct(callable $cssLoaderCallback, callable $jsLoaderCallback, ?string $platform)
{
$this->cssLoaderCallback = $cssLoaderCallback;
$this->jsLoaderCallback = $jsLoaderCallback;
$this->platform = $platform ?? $this->getPlatform();
if (!in_array($this->platform, ['joomla', 'wordpress', 'standalone']))
{
$this->platform = $this->getPlatform();
}
}
/**
* Loads the Akeeba Frontend Framework, both CSS and JS
*
* @param bool $withReset Should I also load the CSS reset for the FEF container? (Only applies to Joomla)
* @param bool $dark Include Dark Mode CSS?
*
* @return void
* @since 1.0.3
*/
public function loadCSSFramework(bool $withReset = true, bool $dark = false)
{
if ($this->loadedCSSFramework)
{
return;
}
$this->loadedCSSFramework = true;
if ($withReset && ($this->platform === 'joomla'))
{
call_user_func($this->cssLoaderCallback, 'fef-reset');
}
call_user_func($this->cssLoaderCallback, 'fef-' . $this->platform);
if ($dark)
{
call_user_func($this->cssLoaderCallback, '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 function loadJSFramework(bool $minimal = false): void
{
$requested = $minimal ? 1 : 2;
if ($this->loadedJSFramework >= $requested)
{
return;
}
// Should I load Akeeba.Loader? Check performed before I change the loadedJSFramework value.
$initLoader = $this->loadedJSFramework === 0;
// Update $this->loadedJSFramework so that loadFEFScript actually loads the scripts we tell it!
$this->loadedJSFramework = $requested;
// Always load the Akeeba.Loader script first.
if ($initLoader)
{
$this->loadFEFScript('Loader', false);
}
if ($requested === 1)
{
// Minimal framework: only load System
$this->loadFEFScript('System');
}
else
{
// Full framework. Load the core FEF scripts. This pulls in System and its dependencies.
if ($this->platform !== 'joomla')
{
$this->loadFEFScript('Menu');
}
$this->loadFEFScript('Tabs');
$this->loadFEFScript('Dropdown');
}
}
/**
* Has Akeeba FEF been already loaded?
*
* @return bool
* @since 2.0.0
*/
public function isLoadedCSSFramework(): bool
{
return $this->isLoadedCSSFramework();
}
/**
* 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 function loadFEFScript(string $name, bool $defer = true): void
{
// Make sure FEF is loaded at all
if (!$this->loadedJSFramework)
{
return;
}
// If the script is already loaded return early.
if (in_array($name, $this->loadedScripts))
{
return;
}
$this->loadedScripts[] = $name;
// Never defer loading for the Akeeba.Loader
$defer = $defer && ($name !== 'Loader');
// Try to find the requested file
$testFile = sprintf("%s/../js/%s.min.js", __DIR__, $name);
if (!@is_file($testFile))
{
// Did someone use the legacy name of a JS file?
$name = ucfirst($name);
$testFile = sprintf("%s/../js/%s.min.js", __DIR__, $name);
}
if (!@is_file($testFile))
{
return;
}
// Load any dependencies before the script itself
$dependencies = $this->getDependencies($name);
foreach ($dependencies as $dependency)
{
$this->loadFEFScript($dependency);
}
// Use the platform-specific callback to actually load the script
call_user_func($this->jsLoaderCallback, $name, $defer);
}
/**
* Returns the auto-detected platform FEF is running under: joomla, wordpress or standalone.
*
* @return string
* @since 2.0.0
* @see self::setPlatform
*/
private function getPlatform(): string
{
if (defined('_JEXEC'))
{
return 'joomla';
}
if (defined('WPINC'))
{
return 'wordpress';
}
return 'standalone';
}
/**
* Get the dependencies of an FEF script
*
* @param string $script
*
* @return array
* @since 2.0.0
*/
private function getDependencies(string $script): array
{
if (empty($this->dependenciesCache))
{
self::loadDependencies();
}
$dependencies = $this->dependenciesCache[$script] ?? [];
return is_array($dependencies) ? $dependencies : [$dependencies];
}
/**
* Load the FEF script dependencies
*
* @return void
* @since 2.0.0
*/
private function loadDependencies(): void
{
// Reset the dependencies cache
$this->dependenciesCache = [];
// Make sure dependencies.json exists
$sourceFile = __DIR__ . '/../js/dependencies.json';
if (!@file_exists($sourceFile) || !@is_file($sourceFile) || !@is_readable($sourceFile))
{
return;
}
// Try to load the JSON file contents
$dependenciesJSON = @file_get_contents($sourceFile);
if (($dependenciesJSON === false) || empty(trim($dependenciesJSON)))
{
return;
}
// Try to decode the JSON file
try
{
$this->dependenciesCache = @json_decode($dependenciesJSON, true, 512);
}
catch (Exception $e)
{
$this->dependenciesCache = null;
}
// Make sure the dependencies cache is an array
$this->dependenciesCache = $this->dependenciesCache ?? [];
if (!is_array($this->dependenciesCache))
{
$this->dependenciesCache = [];
}
}
}

562
media/fef/script.fef.php Normal file
View File

@ -0,0 +1,562 @@
<?php
/**
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
defined('_JEXEC') or die();
use Joomla\CMS\Date\Date as JDate;
use Joomla\CMS\Factory as JFactory;
use Joomla\CMS\Filesystem\File;
use Joomla\CMS\Filesystem\Folder;
use Joomla\CMS\Installer\Adapter\FileAdapter as JInstallerAdapterFile;
use Joomla\CMS\Installer\Installer as JInstaller;
use Joomla\CMS\Log\Log as JLog;
if (class_exists('file_fefInstallerScript'))
{
// WTAF?!
return;
}
/**
* Akeeba FEF Installation Script
*
* @noinspection PhpUnused
*/
class file_fefInstallerScript
{
/**
* The minimum PHP version required to install this extension
*
* @var string
*/
protected $minimumPHPVersion = '7.2.0';
/**
* The minimum Joomla! version required to install this extension
*
* @var string
*/
protected $minimumJoomlaVersion = '3.9.0';
/**
* The maximum Joomla! version this extension can be installed on
*
* @var string
*/
protected $maximumJoomlaVersion = '4.999.999';
/**
* Joomla! pre-flight event. This runs before Joomla! installs or updates the component. This is our last chance to
* tell Joomla! if it should abort the installation.
*
* @param string $type Installation type (install, update, discover_install)
* @param JInstaller|JInstallerAdapterFile $parent Parent object
*
* @return boolean True to let the installation proceed, false to halt the installation
*/
public function preflight($type, $parent)
{
// Do not run on uninstall.
if ($type === 'uninstall')
{
return true;
}
// Check the minimum PHP version
if (!empty($this->minimumPHPVersion))
{
if (defined('PHP_VERSION'))
{
$version = PHP_VERSION;
}
elseif (function_exists('phpversion'))
{
$version = phpversion();
}
else
{
$version = '5.0.0'; // all bets are off!
}
if (!version_compare($version, $this->minimumPHPVersion, 'ge'))
{
$msg = "<p>You need PHP $this->minimumPHPVersion or later to install this package but you are currently using PHP $version</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
}
// Check the minimum Joomla! version
if (!empty($this->minimumJoomlaVersion) && !version_compare(JVERSION, $this->minimumJoomlaVersion, 'ge'))
{
$jVersion = JVERSION;
$msg = "<p>You need Joomla! $this->minimumJoomlaVersion or later to install this package but you only have $jVersion installed.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// Check the maximum Joomla! version
if (!empty($this->maximumJoomlaVersion) && !version_compare(JVERSION, $this->maximumJoomlaVersion, 'le'))
{
$jVersion = JVERSION;
$msg = <<< HTML
<h3>FEF is no longer needed on Joomla 5</h3>
<p>
<strong>Summary: FEF is no longer used on Joomla 5. Please uninstall it.</strong>
</p>
<hr/>
<p>
Akeeba FEF a.k.a. the Akeeba Front-End Framework was a CSS and JavaScript framework used by Akeeba Ltd with the Joomla 3 versions of our software.
</p>
<p>
Akeeba Ltd has stopped using the FEF framework for developing extensions. All of our extensions have new, Joomla 4 and later native versions which use the Bootstrap library, included in Joomla itself.
</p>
<p>
You can no longer install or update FEF on Joomla 5.0 and later (you have {$jVersion}). In fact, you just need to uninstall it.
</p>
HTML;
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// In case of an update, discovery etc I need to check if I am an update
if (($type == 'update') && !$this->amIAnUpdate($parent))
{
$msg = "<p>You already have a newer version of Akeeba Frontend Framework installed. If you want to downgrade please uninstall Akeeba Frontend Framework and install the older version.</p><p>If you see this message during the installation or update of an Akeeba extension please ignore it <em>and</em> the immediately following “Files Install: Custom install routine failure” message. They are expected but Joomla! won't allow us to prevent them from showing up.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
return false;
}
// Delete obsolete font files and folders
if ($type == 'update')
{
// Use pathnames relative to your site's root
$removeFiles = [
'files' => [
// Non-WOFF fonts are not shipped as of 1.0.1 since all modern browsers we target use WOFF
'media/fef/fonts/akeeba/Akeeba-Products.eot',
'media/fef/fonts/akeeba/Akeeba-Products.svg',
'media/fef/fonts/akeeba/Akeeba-Products.ttf',
'media/fef/fonts/Ionicon/ionicons.eot',
'media/fef/fonts/Ionicon/ionicons.svg',
'media/fef/fonts/Ionicon/ionicons.ttf',
// Files renamed in 1.0.8
'css/reset.min.css',
'css/style.min.css',
// JavaScript: Irrelevant for Joomla
'js/darkmode.js',
'js/darkmode.min.js',
'js/darkmode.map',
'js/Darkmode.min.js',
'js/Darkmode.map',
'js/menu.js',
'js/menu.min.js',
'js/menu.map',
'js/Menu.min.js',
'js/Menu.map',
// JavaScript: Uncompressed and map files
'js/dropdown.js',
'js/dropdown.map',
'js/Dropdown.map',
'js/loader.js',
'js/loader.map',
'js/Loader.map',
'js/tabs.js',
'js/tabs.map',
'js/Tabs.map',
],
'folders' => [
],
];
// Remove obsolete files and folders
$this->removeFilesAndFolders($removeFiles);
}
return true;
}
/**
* Runs after install, update or discover_update. In other words, it executes after Joomla! has finished installing
* or updating your component. This is the last chance you've got to perform any additional installations, clean-up,
* database updates and similar housekeeping functions.
*
* @param string $type install, update or discover_update
* @param JInstallerAdapterFile $parent Parent object
*
* @throws Exception
*
* @noinspection PhpUnusedParameterInspection
*/
public function postflight($type, JInstallerAdapterFile $parent)
{
// Do not run on uninstall.
if ($type === 'uninstall')
{
return true;
}
// Auto-uninstall this package when it is no longer needed.
if (($type != 'install') && ($this->countHardcodedDependencies() === 0))
{
$this->uninstallSelf($parent);
return true;
}
$this->bugfixFilesNotCopiedOnUpdate($parent);
return true;
}
/**
* Runs on uninstallation
*
* @param JInstallerAdapterFile $parent The parent object
*
* @throws RuntimeException If the uninstallation is not allowed
*
* @noinspection PhpUnusedParameterInspection
*/
public function uninstall($parent)
{
if (version_compare(JVERSION, '4.1.0', 'ge'))
{
return false;
}
// Check dependencies on FEF
$dependencyCount = $this->countHardcodedDependencies();
if ($dependencyCount)
{
$msg = "<p>You have $dependencyCount extension(s) depending on Akeeba Frontend Framework. The package cannot be uninstalled unless these extensions are uninstalled first.</p>";
JLog::add($msg, JLog::WARNING, 'jerror');
throw new RuntimeException($msg, 500);
}
Folder::delete(JPATH_SITE . '/media/fef');
return true;
}
/**
* Removes obsolete files and folders
*
* @param array $removeList The files and directories to remove
*/
protected function removeFilesAndFolders($removeList)
{
// Remove files
if (isset($removeList['files']) && !empty($removeList['files']))
{
foreach ($removeList['files'] as $file)
{
$f = JPATH_ROOT . '/' . $file;
if (!is_file($f))
{
continue;
}
File::delete($f);
}
}
// Remove folders
if (isset($removeList['folders']) && !empty($removeList['folders']))
{
foreach ($removeList['folders'] as $folder)
{
$f = JPATH_ROOT . '/' . $folder;
if (!is_dir($f))
{
continue;
}
Folder::delete($f);
}
}
}
/**
* Is this package an update to the currently installed FEF? If not (we're a downgrade) we will return false
* and prevent the installation from going on.
*
* @param JInstallerAdapterFile $parent The parent object
*
* @return bool Am I an update to an existing version>
*/
protected function amIAnUpdate($parent)
{
$grandpa = $parent->getParent();
$source = $grandpa->getPath('source');
$target = JPATH_ROOT . '/media/fef';
if (!Folder::exists($source))
{
// WTF? I can't find myself. I can't install anything.
return false;
}
// If FEF is not really installed (someone removed the directory instead of uninstalling?) I have to install it.
if (!Folder::exists($target))
{
return true;
}
$fefVersion = [];
if (File::exists($target . '/version.txt'))
{
$rawData = @file_get_contents($target . '/version.txt');
$rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData;
$info = explode("\n", $rawData);
$fefVersion['installed'] = [
'version' => trim($info[0]),
'date' => new JDate(trim($info[1])),
];
}
else
{
$fefVersion['installed'] = [
'version' => '0.0',
'date' => new JDate('2011-01-01'),
];
}
$rawData = @file_get_contents($source . '/version.txt');
$rawData = ($rawData === false) ? "0.0.0\n2011-01-01\n" : $rawData;
$info = explode("\n", $rawData);
$fefVersion['package'] = [
'version' => trim($info[0]),
'date' => new JDate(trim($info[1])),
];
return $fefVersion['package']['date']->toUNIX() >= $fefVersion['installed']['date']->toUNIX();
}
/**
* Fix for Joomla bug: sometimes files are not copied on update.
*
* We have observed that ever since Joomla! 1.5.5, when Joomla! is performing an extension update some files /
* folders are not copied properly. This seems to be a bit random and seems to be more likely to happen the more
* added / modified files and folders you have. We are trying to work around it by retrying the copy operation
* ourselves WITHOUT going through the manifest, based entirely on the conventions we follow.
*
* @param \Joomla\CMS\Installer\Adapter\FileAdapter $parent
*/
protected function bugfixFilesNotCopiedOnUpdate($parent)
{
$source = $parent->getParent()->getPath('source');
$target = JPATH_SITE . '/media/fef';
$this->recursiveConditionalCopy($source, $target);
}
/**
* Recursively copy a bunch of files, but only if the source and target file have a different size.
*
* @param string $source Path to copy FROM
* @param string $dest Path to copy TO
* @param array $ignored List of entries to ignore (first level entries are taken into account)
*
* @return void
*/
protected function recursiveConditionalCopy($source, $dest, $ignored = [])
{
// Make sure source and destination exist
if (!@is_dir($source))
{
return;
}
if (!@is_dir($dest))
{
if (!@mkdir($dest, 0755))
{
Folder::create($dest, 0755);
}
}
if (!@is_dir($dest))
{
// Cannot create folder $dest
return;
}
// List the contents of the source folder
try
{
$di = new DirectoryIterator($source);
}
catch (Exception $e)
{
return;
}
// Process each entry
foreach ($di as $entry)
{
// Ignore dot dirs (. and ..)
if ($entry->isDot())
{
continue;
}
$sourcePath = $entry->getPathname();
$fileName = $entry->getFilename();
// Do not copy ignored files
if (!empty($ignored) && in_array($fileName, $ignored))
{
continue;
}
// If it's a directory do a recursive copy
if ($entry->isDir())
{
$this->recursiveConditionalCopy($sourcePath, $dest . DIRECTORY_SEPARATOR . $fileName);
continue;
}
// If it's a file check if it's missing or identical
$mustCopy = false;
$targetPath = $dest . DIRECTORY_SEPARATOR . $fileName;
if (!@is_file($targetPath))
{
$mustCopy = true;
}
else
{
$sourceSize = @filesize($sourcePath);
$targetSize = @filesize($targetPath);
$mustCopy = $sourceSize != $targetSize;
if ((substr($targetPath, -4) === '.php') && function_exists('opcache_invalidate'))
{
opcache_invalidate($targetPath);
}
}
if (!$mustCopy)
{
continue;
}
if (!@copy($sourcePath, $targetPath))
{
File::copy($sourcePath, $targetPath);
}
}
}
/**
* Count the number of old FOF + FEF based extensions installed on this site
*
* @return int
*/
private function countHardcodedDependencies()
{
// Look for fof.xml in the backend directories of the following components
$hardcodedDependencies = [
'com_admintools',
'com_akeeba',
'com_ars',
'com_ats',
'com_compatibility',
'com_datacompliance',
'com_contactus',
'com_docimport',
'com_loginguard',
];
$count = 0;
foreach ($hardcodedDependencies as $component)
{
$filePath = JPATH_ADMINISTRATOR . '/components/' . $component . '/fof.xml';
if (@file_exists($filePath))
{
$count++;
}
}
return $count;
}
/**
* Uninstall this package.
*
* This runs on update when there are no more dependencies left.
*
* @param \Joomla\CMS\Installer\Adapter\FileAdapter $adapter
*
* @return void
*/
private function uninstallSelf($adapter)
{
$parent = $adapter->getParent();
if (empty($parent) || !property_exists($parent, 'extension'))
{
return;
}
if (version_compare(JVERSION, '4.0', 'lt'))
{
$db = \Joomla\CMS\Factory::getDbo();
}
else
{
$db = \Joomla\CMS\Factory::getContainer()->get('DatabaseDriver');
}
try
{
$query = $db->getQuery(true)
->select($db->quoteName('extension_id'))
->from($db->quoteName('#__extensions'))
->where($db->quoteName('type') . ' = ' . $db->quote('file'))
->where($db->quoteName('name') . ' = ' . $db->quote('file_fef'));
$id = $db->setQuery($query)->loadResult();
}
catch (Exception $e)
{
return;
}
if (empty($id))
{
return;
}
$msg = 'Automatically uninstalling FEF; this package is no longer required on your site.';
\Joomla\CMS\Log\Log::add($msg, \Joomla\CMS\Log\Log::INFO, 'jerror');
$parent->uninstall('file', $id);
}
}

14
media/fef/version.php Normal file
View File

@ -0,0 +1,14 @@
<?php
/**
* Akeeba Frontend Framework (FEF)
*
* @package fef
* @copyright (c) 2017-2022 Nicholas K. Dionysopoulos / Akeeba Ltd
* @license GNU General Public License version 3, or later
*/
// Protect from unauthorized access
defined('_JEXEC') or die;
define('AKEEBAFEF_VERSION', '2.1.1');
define('AKEEBAFEF_DATE', '2022-10-24');

2
media/fef/version.txt Normal file
View File

@ -0,0 +1,2 @@
2.1.1
2022-10-24