This is information specific to the hook currently being processed, and generally contains information that is being immediately processed or acted on that you can use, display, or alter.
Remember to declare it with `&` if you wish to alter it.
-## JavaScript addon hooks
+## Global stylesheets
-### PHP part
+If your addon requires adding a stylesheet on all pages of Friendica, add the following hook:
-Make sure your JavaScript addon file (addon/*addon_name*/*addon_name*.js) is listed in the document response.
+```php
+function <addon>_install()
+{
+ Addon::registerHook('head', __FILE__, '<addon>_head');
+ ...
+}
-In your addon install function, add:
-```php
-Addon::registerHook('template_vars', __FILE__, '<addon_name>_template_vars');
+function <addon>_head(App $a)
+{
+ $a->registerStylesheet(__DIR__ . '/relative/path/to/addon/stylesheet.css');
+}
```
-In your addon uninstall function, add:
+`__DIR__` is the folder path of your addon.
-```php
-Addon::unregisterHook('template_vars', __FILE__, '<addon_name>_template_vars');
-```
+## JavaScript
+
+### Global scripts
+
+If your addon requires adding a script on all pages of Friendica, add the following hook:
-Then, add your addon name to the *addon_hooks* template variable array:
```php
-function <addon_name>_template_vars($a, &$arr)
+function <addon>_install()
{
- if (!array_key_exists('addon_hooks', $arr['vars']))
- {
- $arr['vars']['addon_hooks'] = array();
- }
- $arr['vars']['addon_hooks'][] = "<addon_name>";
+ Addon::registerHook('footer', __FILE__, '<addon>_footer');
+ ...
+}
+
+function <addon>_footer(App $a)
+{
+ $a->registerFooterScript(__DIR__ . '/relative/path/to/addon/script.js');
}
```
-### JavaScript part
+`__DIR__` is the folder path of your addon.
+
+### JavaScript hooks
-Register your addon hooks in file `addon/*addon_name*/*addon_name*.js`.
+The main Friendica script provides hooks via events dispatched on the `document` property.
+In your Javascript file included as described above, add your event listener like this:
```js
-Addon_registerHook(type, hookfnstr);
+document.addEventListener(name, callback);
```
-*type* is the name of the hook and corresponds to a known Friendica JavaScript hook.
-*hookfnstr* is the name of your JavaScript function to execute.
+- *name* is the name of the hook and corresponds to a known Friendica JavaScript hook.
+- *callback* is a JavaScript anonymous function to execute.
-No arguments are provided to your JavaScript callback function. Example:
+More info about Javascript event listeners: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
-```javascript
-function myhook_function() {
+#### Current JavaScript hooks
-}
-```
+##### postprocess_liveupdate
+Called at the end of the live update process (XmlHttpRequest) and on a post preview.
+No additional data is provided.
## Modules
Called after tag conversion of HTML to bbcode (e.g. remote message posting)
`$b` is a string converted text
+### head
+Called when building the `<head>` sections.
+Stylesheets should be registered using this hook.
+`$b` is an HTML string of the `<head>` tag.
+
### page_header
Called after building the page navigation section.
`$b` is a string HTML of nav region.
Called after HTML content functions have completed.
`$b` is (string) HTML of content div.
+### footer
+Called after HTML content functions have completed.
+Deferred Javascript files should be registered using this hook.
+`$b` is (string) HTML of footer div/element.
+
### avatar_lookup
Called when looking up the avatar. `$b` is an array:
visitor => array with the contact record of the visitor
url => the query string
-## Current JavaScript hooks
-
-### postprocess_liveupdate
-Called at the end of the live update process (XmlHttpRequest)
-
## Complete list of hook callbacks
-Here is a complete list of all hook callbacks with file locations (as of 01-Apr-2018). Please see the source for details of any hooks not documented above.
+Here is a complete list of all hook callbacks with file locations (as of 24-Sep-2018). Please see the source for details of any hooks not documented above.
### index.php
### src/App.php
Addon::callHooks('load_config');
+ Addon::callHooks('head');
+ Addon::callHooks('footer');
### src/Model/Item.php
### view/js/main.js
- callAddonHooks("postprocess_liveupdate");
+ document.dispatchEvent(new Event('postprocess_liveupdate'));
'$delitems' => L10n::t("Delete item\x28s\x29?")
]);
- $tpl = get_markup_template('jot-end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$newpost' => 'true',
- '$baseurl' => System::baseUrl(true),
- '$geotag' => $geotag,
- '$nickname' => $x['nickname'],
- '$ispublic' => L10n::t('Visible to <strong>everybody</strong>'),
- '$linkurl' => L10n::t('Please enter a link URL:'),
- '$vidurl' => L10n::t("Please enter a video link/URL:"),
- '$audurl' => L10n::t("Please enter an audio link/URL:"),
- '$term' => L10n::t('Tag term:'),
- '$fileas' => L10n::t('Save to Folder:'),
- '$whereareu' => L10n::t('Where are you right now?')
- ]);
-
$jotplugins = '';
Addon::callHooks('jot_tool', $jotplugins);
$a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
'$baseurl' => System::baseUrl(),
]);
- $a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
- '$baseurl' => System::baseUrl(),
- ]);
}
$url_parts = explode('/', $the_url);
* Language was set earlier, but we can over-ride it in the session.
* We have to do it here because the session was just now opened.
*/
-if (x($_SESSION, 'authenticated') && !x($_SESSION, 'language')) {
+if (!empty($_SESSION['authenticated']) && empty($_SESSION['language'])) {
$_SESSION['language'] = $lang;
// we haven't loaded user data yet, but we need user language
if (!empty($_SESSION['uid'])) {
}
}
-if (x($_SESSION, 'language') && ($_SESSION['language'] !== $lang)) {
+if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) {
$lang = $_SESSION['language'];
L10n::loadTranslationTable($lang);
}
logger("Invalid ZRL parameter " . $_GET['zrl'], LOGGER_DEBUG);
header('HTTP/1.1 403 Forbidden');
echo "<h1>403 Forbidden</h1>";
- killme();
+ exit();
}
}
}
-if ((x($_GET,'owt')) && $a->mode == App::MODE_NORMAL) {
+if (!empty($_GET['owt']) && $a->mode == App::MODE_NORMAL) {
$token = $_GET['owt'];
$a->query_string = Profile::stripQueryParam($a->query_string, 'owt');
Profile::openWebAuthInit($token);
Login::sessionAuth();
-if (! x($_SESSION, 'authenticated')) {
+if (empty($_SESSION['authenticated'])) {
header('X-Account-Management-Status: none');
}
-/* set up page['htmlhead'] and page['end'] for the modules to use */
-$a->page['htmlhead'] = '';
-$a->page['end'] = '';
-
$_SESSION['sysmsg'] = defaults($_SESSION, 'sysmsg' , []);
$_SESSION['sysmsg_info'] = defaults($_SESSION, 'sysmsg_info' , []);
$_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
if (! $a->module_loaded) {
// Stupid browser tried to pre-fetch our Javascript img template. Don't log the event or return anything - just quietly exit.
- if ((x($_SERVER, 'QUERY_STRING')) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
+ if (!empty($_SERVER['QUERY_STRING']) && preg_match('/{[0-9]}/', $_SERVER['QUERY_STRING']) !== 0) {
killme();
}
- if ((x($_SERVER, 'QUERY_STRING')) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
+ if (!empty($_SERVER['QUERY_STRING']) && ($_SERVER['QUERY_STRING'] === 'q=internal_error.html') && isset($dreamhost_error_hack)) {
logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
goaway(System::baseUrl() . $_SERVER['REQUEST_URI']);
}
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG);
header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . L10n::t('Not Found'));
$tpl = get_markup_template("404.tpl");
- $a->page['content'] = replace_macros(
- $tpl,
- [
- '$message' => L10n::t('Page not found.')]
- );
+ $a->page['content'] = replace_macros($tpl, [
+ '$message' => L10n::t('Page not found.')
+ ]);
}
}
/* initialise content region */
-if (! x($a->page, 'content')) {
- $a->page['content'] = '';
-}
-
if ($a->mode == App::MODE_NORMAL) {
Addon::callHooks('page_content_top', $a->page['content']);
}
* theme choices made by the modules can take effect.
*/
-$a->init_pagehead();
+$a->initHead();
/*
* Build the page ending -- this is stuff that goes right before
* the closing </body> tag
*/
-$a->init_page_end();
-
-// If you're just visiting, let javascript take you home
-if (x($_SESSION, 'visitor_home')) {
- $homebase = $_SESSION['visitor_home'];
-} elseif (local_user()) {
- $homebase = 'profile/' . $a->user['nickname'];
-}
-
-if (isset($homebase)) {
- $a->page['content'] .= '<script>var homebase="' . $homebase . '" ; </script>';
-}
+$a->initFooter();
/*
* now that we've been through the module content, see if the page reported
Nav::build($a);
}
-/*
- * Add a "toggle mobile" link if we're using a mobile device
- */
-if ($a->is_mobile || $a->is_tablet) {
- if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
- $link = 'toggle_mobile?address=' . curPageURL();
- } else {
- $link = 'toggle_mobile?off=1&address=' . curPageURL();
- }
- $a->page['footer'] = replace_macros(
- get_markup_template("toggle_mobile_footer.tpl"),
- [
- '$toggle_link' => $link,
- '$toggle_text' => L10n::t('toggle mobile')]
- );
-}
-
/**
* Build the page - now that we have all the components
*/
-
-if (!$a->theme['stylesheet']) {
- $stylesheet = $a->getCurrentThemeStylesheetPath();
-} else {
- $stylesheet = $a->theme['stylesheet'];
-}
-
-$a->page['htmlhead'] = str_replace('{{$stylesheet}}', $stylesheet, $a->page['htmlhead']);
-//$a->page['htmlhead'] = replace_macros($a->page['htmlhead'], array('$stylesheet' => $stylesheet));
-
if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "minimal"))) {
$doc = new DOMDocument();
echo substr($target->saveHTML(), 6, -8);
- killme();
+ exit();
}
$page = $a->page;
/// @TODO Looks unsafe (remote-inclusion), is maybe not but Theme::getPathForFile() uses file_exists() but does not escape anything
require_once $template;
-
-killme();
'$i18n' => $i18n,
]);
- $etpl = get_markup_template('event_end.tpl');
- $a->page['end'] .= replace_macros($etpl, [
- '$baseurl' => System::baseUrl(),
- ]);
-
$mode = 'view';
$y = 0;
$m = 0;
'$baseurl' => System::baseUrl(true),
'$base' => $base
]);
-
- $tpl = get_markup_template("contacts-end.tpl");
- $a->page['end'] .= replace_macros($tpl, [
- '$baseurl' => System::baseUrl(true),
- '$base' => $base
- ]);
}
function contacts_batch_actions(App $a)
$a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [
'$baseurl' => System::baseUrl(true),
]);
- $a->page['end'] .= replace_macros(get_markup_template('contact_end.tpl'), [
- '$baseurl' => System::baseUrl(true),
- ]);
$contact['blocked'] = Contact::isBlockedByUser($contact['id'], local_user());
$contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user());
'$nickname' => $a->user['nickname']
]);
- $tpl = get_markup_template('jot-end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$baseurl' => System::baseUrl(),
- '$ispublic' => ' ', // L10n::t('Visible to <strong>everybody</strong>'),
- '$geotag' => $geotag,
- '$nickname' => $a->user['nickname']
- ]);
-
-
$tpl = get_markup_template("jot.tpl");
if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
'$i18n' => $i18n,
]);
- $etpl = get_markup_template('event_end.tpl');
- $a->page['end'] .= replace_macros($etpl, [
- '$baseurl' => System::baseUrl(),
- ]);
-
$o = '';
$tabs = '';
// tabs
'$baseurl' => System::baseUrl(true),
'$base' => $base
]);
-
- $end_tpl = get_markup_template('message-end.tpl');
- $a->page['end'] .= replace_macros($end_tpl, [
- '$baseurl' => System::baseUrl(true),
- '$base' => $base
- ]);
}
function message_post(App $a)
'$linkurl' => L10n::t('Please enter a link URL:')
]);
- $tpl = get_markup_template('msg-end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$baseurl' => System::baseUrl(true),
- '$nickname' => $a->user['nickname'],
- '$linkurl' => L10n::t('Please enter a link URL:')
- ]);
-
$preselect = isset($a->argv[2]) ? [$a->argv[2]] : [];
$prename = $preurl = $preid = '';
'$linkurl' => L10n::t('Please enter a link URL:')
]);
- $tpl = get_markup_template('msg-end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$baseurl' => System::baseUrl(true),
- '$nickname' => $a->user['nickname'],
- '$linkurl' => L10n::t('Please enter a link URL:')
- ]);
-
$mails = [];
$seen = 0;
$unknown = false;
}
$a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []);
- $a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), []);
$imagecrop = [
'hash' => $hash,
$a->page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), [
'$baseurl' => System::baseUrl(true),
]);
- $a->page['end'] .= replace_macros(get_markup_template('profed_end.tpl'), [
- '$baseurl' => System::baseUrl(true),
- ]);
$opt_tpl = get_markup_template("profile-hide-friends.tpl");
$hide_friends = replace_macros($opt_tpl,[
'$theme_config' => $theme_config,
]);
- $tpl = get_markup_template('settings/display_end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$theme' => ['theme', L10n::t('Display Theme:'), $theme_selected, '', $themes]
- ]);
-
return $o;
}
$a->page['htmlhead'] .= replace_macros($tpl,[
'$baseurl' => System::baseUrl(),
]);
-
- $tpl = get_markup_template("videos_end.tpl");
- $a->page['end'] .= replace_macros($tpl,[
- '$baseurl' => System::baseUrl(),
- ]);
-
}
return;
'$linkurl' => L10n::t('Please enter a link URL:')
]);
- $tpl = get_markup_template('wallmsg-end.tpl');
- $a->page['end'] .= replace_macros($tpl, [
- '$baseurl' => System::baseUrl(true),
- '$nickname' => $user['nickname'],
- '$linkurl' => L10n::t('Please enter a link URL:')
- ]);
-
$tpl = get_markup_template('wallmessage.tpl');
$o = replace_macros($tpl, [
'$header' => L10n::t('Send Private Message'),
public $force_max_items = 0;
public $theme_events_in_profile = true;
+ public $stylesheets = [];
+ public $footerScripts = [];
+
+ /**
+ * Register a stylesheet file path to be included in the <head> tag of every page.
+ * Inclusion is done in App->initHead().
+ * The path can be absolute or relative to the Friendica installation base folder.
+ *
+ * @see App->initHead()
+ *
+ * @param string $path
+ */
+ public function registerStylesheet($path)
+ {
+ $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path);
+
+ $this->stylesheets[] = trim($url, '/');
+ }
+
+ /**
+ * Register a javascript file path to be included in the <footer> tag of every page.
+ * Inclusion is done in App->initFooter().
+ * The path can be absolute or relative to the Friendica installation base folder.
+ *
+ * @see App->initFooter()
+ *
+ * @param string $path
+ */
+ public function registerFooterScript($path)
+ {
+ $url = str_replace($this->get_basepath() . DIRECTORY_SEPARATOR, '', $path);
+
+ $this->footerScripts[] = trim($url, '/');
+ }
+
/**
* @brief An array for all theme-controllable parameters
*
'aside' => '',
'bottom' => '',
'content' => '',
- 'end' => '',
'footer' => '',
'htmlhead' => '',
'nav' => '',
$this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage'];
}
- public function init_pagehead()
+ /**
+ * Initializes App->page['htmlhead'].
+ *
+ * Includes:
+ * - Page title
+ * - Favicons
+ * - Registered stylesheets (through App->registerStylesheet())
+ * - Infinite scroll data
+ * - head.tpl template
+ */
+ public function initHead()
{
$interval = ((local_user()) ? PConfig::get(local_user(), 'system', 'update_interval') : 40000);
$this->page['title'] = $this->config['sitename'];
}
- /* put the head template at the beginning of page['htmlhead']
- * since the code added by the modules frequently depends on it
- * being first
- */
- if (!isset($this->page['htmlhead'])) {
- $this->page['htmlhead'] = '';
- }
-
- // If we're using Smarty, then doing replace_macros() will replace
- // any unrecognized variables with a blank string. Since we delay
- // replacing $stylesheet until later, we need to replace it now
- // with another variable name
- if ($this->theme['template_engine'] === 'smarty3') {
- $stylesheet = $this->get_template_ldelim('smarty3') . '$stylesheet' . $this->get_template_rdelim('smarty3');
+ if (!empty($this->theme['stylesheet'])) {
+ $stylesheet = $this->theme['stylesheet'];
} else {
- $stylesheet = '$stylesheet';
+ $stylesheet = $this->getCurrentThemeStylesheetPath();
}
+ $this->registerStylesheet($stylesheet);
+
$shortcut_icon = Config::get('system', 'shortcut_icon');
if ($shortcut_icon == '') {
$shortcut_icon = 'images/friendica-32.png';
}
// get data wich is needed for infinite scroll on the network page
- $invinite_scroll = infinite_scroll_data($this->module);
+ $infinite_scroll = infinite_scroll_data($this->module);
+
+ Core\Addon::callHooks('head', $this->page['htmlhead']);
$tpl = get_markup_template('head.tpl');
+ /* put the head template at the beginning of page['htmlhead']
+ * since the code added by the modules frequently depends on it
+ * being first
+ */
$this->page['htmlhead'] = replace_macros($tpl, [
'$baseurl' => $this->get_baseurl(),
'$local_user' => local_user(),
'$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon,
- '$stylesheet' => $stylesheet,
- '$infinite_scroll' => $invinite_scroll,
+ '$infinite_scroll' => $infinite_scroll,
'$block_public' => intval(Config::get('system', 'block_public')),
+ '$stylesheets' => $this->stylesheets,
]) . $this->page['htmlhead'];
}
- public function init_page_end()
+ /**
+ * Initializes App->page['footer'].
+ *
+ * Includes:
+ * - Javascript homebase
+ * - Mobile toggle link
+ * - Registered footer scripts (through App->registerFooterScript())
+ * - footer.tpl template
+ */
+ public function initFooter()
{
- if (!isset($this->page['end'])) {
- $this->page['end'] = '';
+ // If you're just visiting, let javascript take you home
+ if (!empty($_SESSION['visitor_home'])) {
+ $homebase = $_SESSION['visitor_home'];
+ } elseif (local_user()) {
+ $homebase = 'profile/' . $this->user['nickname'];
+ }
+
+ if (isset($homebase)) {
+ $this->page['footer'] .= '<script>var homebase="' . $homebase . '";</script>' . "\n";
}
- $tpl = get_markup_template('end.tpl');
- $this->page['end'] = replace_macros($tpl, [
- '$baseurl' => $this->get_baseurl()
- ]) . $this->page['end'];
+
+ /*
+ * Add a "toggle mobile" link if we're using a mobile device
+ */
+ if ($this->is_mobile || $this->is_tablet) {
+ if (isset($_SESSION['show-mobile']) && !$_SESSION['show-mobile']) {
+ $link = 'toggle_mobile?address=' . curPageURL();
+ } else {
+ $link = 'toggle_mobile?off=1&address=' . curPageURL();
+ }
+ $this->page['footer'] .= replace_macros(get_markup_template("toggle_mobile_footer.tpl"), [
+ '$toggle_link' => $link,
+ '$toggle_text' => Core\L10n::t('toggle mobile')
+ ]);
+ }
+
+ Core\Addon::callHooks('footer', $this->page['footer']);
+
+ $tpl = get_markup_template('footer.tpl');
+ $this->page['footer'] = replace_macros($tpl, [
+ '$baseurl' => $this->get_baseurl(),
+ '$footerScripts' => $this->footerScripts,
+ ]) . $this->page['footer'];
}
public function set_curl_code($code)
+++ /dev/null
-/**
- * @file addon-hooks.js
- * @brief Provide a way for add-ons to register a JavaScript hook
- */
-
-var addon_hooks = {};
-
-/**
- * @brief Register a JavaScript hook to be called from other Javascript files
- * @pre the .js file from which the hook will be called is included in the document response
- * @param type which type of hook i.e. where should it be called along with other hooks of the same type
- * @param hookfnstr name of the JavaScript function name that needs to be called
- */
-function Addon_registerHook(type, hookfnstr)
-{
- if (!addon_hooks.hasOwnProperty(type)) {
- addon_hooks[type] = [];
- }
-
- addon_hooks[type].push(hookfnstr);
-}
-
-/**
- * @brief Call all registered hooks of a certain type, i.e. at the same point of the JavaScript code execution
- * @param typeOfHook string indicating which type of hooks to be called among the registered hooks
- */
-function callAddonHooks(typeOfHook)
-{
- if (typeof addon_hooks !== 'undefined') {
- var myTypeOfHooks = addon_hooks[typeOfHook];
- if (typeof myTypeOfHooks !== 'undefined') {
- for (addon_hook_idx = 0; addon_hook_idx < myTypeOfHooks.length; addon_hook_idx++) {
- var hookfnstr = myTypeOfHooks[addon_hook_idx];
- var hookfn = window[hookfnstr];
- if (typeof hookfn === "function") {
- hookfn();
- }
- }
- }
- }
-}
$('.wall-item-body', data).imagesLoaded(function() {
updateConvItems(data);
+ document.dispatchEvent(new Event('postprocess_liveupdate'));
+
// Update the scroll position.
$(window).scrollTop($(window).scrollTop() + $("section").height() - orgHeight);
});
-
- callAddonHooks("postprocess_liveupdate");
-
});
-
}
function imgbright(node) {
if (data.preview) {
$("#jot-preview-content").html(data.preview);
$("#jot-preview-content" + " a").click(function() {return false;});
+ document.dispatchEvent(new Event('postprocess_liveupdate'));
}
},
"json"
} else {
$("#scroll-end").fadeIn('normal');
}
+
+ document.dispatchEvent(new Event('postprocess_liveupdate'));
});
}
--- /dev/null
+{{foreach $footerScripts as $scriptUrl}}
+<script type="text/javascript" src="{{$scriptUrl}}"></script>
+{{/foreach}}
<link rel="stylesheet" href="view/asset/jquery-datetimepicker/build/jquery.datetimepicker.min.css" type="text/css" media="screen" />
<link rel="stylesheet" href="view/asset/perfect-scrollbar/css/perfect-scrollbar.min.css" type="text/css" media="screen" />
-<link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+{{foreach $stylesheets as $stylesheetUrl}}
+<link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+{{/foreach}}
-<!--
-<link rel="shortcut icon" href="images/friendica-32.png" />
-<link rel="apple-touch-icon" href="images/friendica-128.png"/>
--->
<link rel="shortcut icon" href="{{$shortcut_icon}}" />
<link rel="apple-touch-icon" href="{{$touch_icon}}"/>
<script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
<script type="text/javascript" src="view/js/acl.js" ></script>
<script type="text/javascript" src="view/asset/base64/base64.min.js" ></script>
-<script type="text/javascript" src="view/js/addon-hooks.js" ></script>
-{{if is_array($addon_hooks)}}
-{{foreach $addon_hooks as $addon_hook}}
-<script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
-{{/foreach}}
-{{/if}}
<script type="text/javascript" src="view/js/main.js" ></script>
<script>
</main>
<footer>
- <?php if (x($page, 'footer')) echo $page['footer']; ?>
- <!-- Modal -->
- <div id="modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
- <div class="modal-dialog modal-full-screen">
- <div class="modal-content">
- <div id="modal-header" class="modal-header">
- <button id="modal-cloase" type="button" class="close" data-dismiss="modal" aria-hidden="true">
- ×
- </button>
- <h4 id="modal-title" class="modal-title"></h4>
- </div>
- <div id="modal-body" class="modal-body">
- <!-- /# content goes here -->
- </div>
- </div>
- </div>
- </div>
-
- <!-- Dummy div to append other div's when needed (e.g. used for js function editpost() -->
- <div id="cache-container"></div>
-
+ <?php echo defaults($page, 'footer', ''); ?>
</footer>
<?php } ?> <!-- End of condition if $minimal else the rest -->
</body>
--- /dev/null
+ <!-- Modal -->
+ <div id="modal" class="modal fade" tabindex="-1" role="dialog" aria-hidden="true">
+ <div class="modal-dialog modal-full-screen">
+ <div class="modal-content">
+ <div id="modal-header" class="modal-header">
+ <button id="modal-cloase" type="button" class="close" data-dismiss="modal" aria-hidden="true">
+ ×
+ </button>
+ <h4 id="modal-title" class="modal-title"></h4>
+ </div>
+ <div id="modal-body" class="modal-body">
+ <!-- /# content goes here -->
+ </div>
+ </div>
+ </div>
+ </div>
+
+ <!-- Dummy div to append other div's when needed (e.g. used for js function editpost() -->
+ <div id="cache-container"></div>
+
+{{foreach $footerScripts as $scriptUrl}}
+ <script type="text/javascript" src="{{$scriptUrl}}"></script>
+{{/foreach}}
<link rel="stylesheet" href="view/theme/frio/frameworks/bootstrap-toggle/css/bootstrap-toggle.min.css" type="text/css" media="screen"/>
<link rel="stylesheet" href="view/theme/frio/font/open_sans/open-sans.css" type="text/css" media="screen"/>
-{{* The own style.css *}}
-<link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" />
+{{foreach $stylesheets as $stylesheetUrl}}
+<link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
+{{/foreach}}
{{* own css files *}}
<link rel="stylesheet" href="view/theme/frio/css/hovercard.css" type="text/css" media="screen"/>
<link rel="stylesheet" href="view/theme/frio/css/font-awesome.custom.css" type="text/css" media="screen"/>
-<!--
-<link rel="shortcut icon" href="images/friendica-32.png" />
-<link rel="apple-touch-icon" href="images/friendica-128.png"/>
--->
<link rel="shortcut icon" href="{{$shortcut_icon}}" />
<link rel="apple-touch-icon" href="{{$touch_icon}}"/>
<script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script>
<script type="text/javascript" src="view/js/acl.js"></script>
<script type="text/javascript" src="view/asset/base64/base64.min.js"></script>
-<script type="text/javascript" src="view/js/addon-hooks.js" ></script>
-{{if is_array($addon_hooks)}}
-{{foreach $addon_hooks as $addon_hook}}
-<script type="text/javascript" src="addon/{{$addon_hook}}/{{$addon_hook}}.js"></script>
-{{/foreach}}
-{{/if}}
<script type="text/javascript" src="view/js/main.js"></script>
<script type="text/javascript" src="view/theme/frio/frameworks/bootstrap/js/bootstrap.min.js"></script>