Merge pull request #5773 from MrPetovan/task/rewrite-js-hooks

Rewrite JS hooks
This commit is contained in:
Michael Vogel 2018-10-01 17:10:30 +00:00 committed by GitHub
commit 103535d620
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 213 additions and 318 deletions

View file

@ -67,55 +67,67 @@ $b can be called anything you like.
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. 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. 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.
In your addon install function, add:
```php ```php
Addon::registerHook('template_vars', __FILE__, '<addon_name>_template_vars'); function <addon>_install()
```
In your addon uninstall function, add:
```php
Addon::unregisterHook('template_vars', __FILE__, '<addon_name>_template_vars');
```
Then, add your addon name to the *addon_hooks* template variable array:
```php
function <addon_name>_template_vars($a, &$arr)
{ {
if (!array_key_exists('addon_hooks', $arr['vars'])) Addon::registerHook('head', __FILE__, '<addon>_head');
{ ...
$arr['vars']['addon_hooks'] = array(); }
}
$arr['vars']['addon_hooks'][] = "<addon_name>";
function <addon>_head(App $a)
{
$a->registerStylesheet(__DIR__ . '/relative/path/to/addon/stylesheet.css');
} }
``` ```
### JavaScript part `__DIR__` is the folder path of your addon.
Register your addon hooks in file `addon/*addon_name*/*addon_name*.js`. ## JavaScript
### Global scripts
If your addon requires adding a script on all pages of Friendica, add the following hook:
```php
function <addon>_install()
{
Addon::registerHook('footer', __FILE__, '<addon>_footer');
...
}
function <addon>_footer(App $a)
{
$a->registerFooterScript(__DIR__ . '/relative/path/to/addon/script.js');
}
```
`__DIR__` is the folder path of your addon.
### JavaScript hooks
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 ```js
Addon_registerHook(type, hookfnstr); document.addEventListener(name, callback);
``` ```
*type* is the name of the hook and corresponds to a known Friendica JavaScript hook. - *name* is the name of the hook and corresponds to a known Friendica JavaScript hook.
*hookfnstr* is the name of your JavaScript function to execute. - *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 #### Current JavaScript hooks
function myhook_function() {
} ##### postprocess_liveupdate
``` Called at the end of the live update process (XmlHttpRequest) and on a post preview.
No additional data is provided.
## Modules ## Modules
@ -260,6 +272,11 @@ Called after conversion of bbcode to HTML.
Called after tag conversion of HTML to bbcode (e.g. remote message posting) Called after tag conversion of HTML to bbcode (e.g. remote message posting)
`$b` is a string converted text `$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 ### page_header
Called after building the page navigation section. Called after building the page navigation section.
`$b` is a string HTML of nav region. `$b` is a string HTML of nav region.
@ -294,6 +311,11 @@ No hook data.
Called after HTML content functions have completed. Called after HTML content functions have completed.
`$b` is (string) HTML of content div. `$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 ### avatar_lookup
Called when looking up the avatar. `$b` is an array: Called when looking up the avatar. `$b` is an array:
@ -389,14 +411,9 @@ Hook data:
visitor => array with the contact record of the visitor visitor => array with the contact record of the visitor
url => the query string url => the query string
## Current JavaScript hooks
### postprocess_liveupdate
Called at the end of the live update process (XmlHttpRequest)
## Complete list of hook callbacks ## 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 ### index.php
@ -571,6 +588,8 @@ Here is a complete list of all hook callbacks with file locations (as of 01-Apr-
### src/App.php ### src/App.php
Addon::callHooks('load_config'); Addon::callHooks('load_config');
Addon::callHooks('head');
Addon::callHooks('footer');
### src/Model/Item.php ### src/Model/Item.php
@ -704,4 +723,4 @@ Here is a complete list of all hook callbacks with file locations (as of 01-Apr-
### view/js/main.js ### view/js/main.js
callAddonHooks("postprocess_liveupdate"); document.dispatchEvent(new Event('postprocess_liveupdate'));

View file

@ -1091,21 +1091,6 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
'$delitems' => L10n::t("Delete item\x28s\x29?") '$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 = ''; $jotplugins = '';
Addon::callHooks('jot_tool', $jotplugins); Addon::callHooks('jot_tool', $jotplugins);

View file

@ -1191,9 +1191,6 @@ function prepare_body(array &$item, $attach = false, $is_preview = false)
$a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [ $a->page['htmlhead'] .= replace_macros(get_markup_template('videos_head.tpl'), [
'$baseurl' => System::baseUrl(), '$baseurl' => System::baseUrl(),
]); ]);
$a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
'$baseurl' => System::baseUrl(),
]);
} }
$url_parts = explode('/', $the_url); $url_parts = explode('/', $the_url);

View file

@ -91,7 +91,7 @@ if (!$a->is_backend()) {
* Language was set earlier, but we can over-ride it in the session. * 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. * 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; $_SESSION['language'] = $lang;
// we haven't loaded user data yet, but we need user language // we haven't loaded user data yet, but we need user language
if (!empty($_SESSION['uid'])) { if (!empty($_SESSION['uid'])) {
@ -102,7 +102,7 @@ if (x($_SESSION, 'authenticated') && !x($_SESSION, 'language')) {
} }
} }
if (x($_SESSION, 'language') && ($_SESSION['language'] !== $lang)) { if (!empty($_SESSION['language']) && $_SESSION['language'] !== $lang) {
$lang = $_SESSION['language']; $lang = $_SESSION['language'];
L10n::loadTranslationTable($lang); L10n::loadTranslationTable($lang);
} }
@ -125,12 +125,12 @@ if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) {
logger("Invalid ZRL parameter " . $_GET['zrl'], LOGGER_DEBUG); logger("Invalid ZRL parameter " . $_GET['zrl'], LOGGER_DEBUG);
header('HTTP/1.1 403 Forbidden'); header('HTTP/1.1 403 Forbidden');
echo "<h1>403 Forbidden</h1>"; 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']; $token = $_GET['owt'];
$a->query_string = Profile::stripQueryParam($a->query_string, 'owt'); $a->query_string = Profile::stripQueryParam($a->query_string, 'owt');
Profile::openWebAuthInit($token); Profile::openWebAuthInit($token);
@ -149,14 +149,10 @@ if ((x($_GET,'owt')) && $a->mode == App::MODE_NORMAL) {
Login::sessionAuth(); Login::sessionAuth();
if (! x($_SESSION, 'authenticated')) { if (empty($_SESSION['authenticated'])) {
header('X-Account-Management-Status: none'); 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'] = defaults($_SESSION, 'sysmsg' , []);
$_SESSION['sysmsg_info'] = defaults($_SESSION, 'sysmsg_info' , []); $_SESSION['sysmsg_info'] = defaults($_SESSION, 'sysmsg_info' , []);
$_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []); $_SESSION['last_updated'] = defaults($_SESSION, 'last_updated', []);
@ -295,11 +291,11 @@ if (strlen($a->module)) {
if (! $a->module_loaded) { 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. // 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(); 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']); logger('index.php: dreamhost_error_hack invoked. Original URI =' . $_SERVER['REQUEST_URI']);
goaway(System::baseUrl() . $_SERVER['REQUEST_URI']); goaway(System::baseUrl() . $_SERVER['REQUEST_URI']);
} }
@ -307,11 +303,9 @@ if (strlen($a->module)) {
logger('index.php: page not found: ' . $_SERVER['REQUEST_URI'] . ' ADDRESS: ' . $_SERVER['REMOTE_ADDR'] . ' QUERY: ' . $_SERVER['QUERY_STRING'], LOGGER_DEBUG); 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')); header($_SERVER["SERVER_PROTOCOL"] . ' 404 ' . L10n::t('Not Found'));
$tpl = get_markup_template("404.tpl"); $tpl = get_markup_template("404.tpl");
$a->page['content'] = replace_macros( $a->page['content'] = replace_macros($tpl, [
$tpl, '$message' => L10n::t('Page not found.')
[ ]);
'$message' => L10n::t('Page not found.')]
);
} }
} }
@ -326,10 +320,6 @@ if (file_exists($theme_info_file)) {
/* initialise content region */ /* initialise content region */
if (! x($a->page, 'content')) {
$a->page['content'] = '';
}
if ($a->mode == App::MODE_NORMAL) { if ($a->mode == App::MODE_NORMAL) {
Addon::callHooks('page_content_top', $a->page['content']); Addon::callHooks('page_content_top', $a->page['content']);
} }
@ -405,24 +395,13 @@ if ($a->module_loaded) {
* theme choices made by the modules can take effect. * 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 * Build the page ending -- this is stuff that goes right before
* the closing </body> tag * the closing </body> tag
*/ */
$a->init_page_end(); $a->initFooter();
// 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>';
}
/* /*
* now that we've been through the module content, see if the page reported * now that we've been through the module content, see if the page reported
@ -444,36 +423,9 @@ if ($a->module != 'install' && $a->module != 'maintenance') {
Nav::build($a); 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 * 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"))) { if (isset($_GET["mode"]) && (($_GET["mode"] == "raw") || ($_GET["mode"] == "minimal"))) {
$doc = new DOMDocument(); $doc = new DOMDocument();
@ -502,7 +454,7 @@ if (isset($_GET["mode"]) && ($_GET["mode"] == "raw")) {
echo substr($target->saveHTML(), 6, -8); echo substr($target->saveHTML(), 6, -8);
killme(); exit();
} }
$page = $a->page; $page = $a->page;
@ -540,5 +492,3 @@ if (empty($template)) {
/// @TODO Looks unsafe (remote-inclusion), is maybe not but Theme::getPathForFile() uses file_exists() but does not escape anything /// @TODO Looks unsafe (remote-inclusion), is maybe not but Theme::getPathForFile() uses file_exists() but does not escape anything
require_once $template; require_once $template;
killme();

View file

@ -94,11 +94,6 @@ function cal_content(App $a)
'$i18n' => $i18n, '$i18n' => $i18n,
]); ]);
$etpl = get_markup_template('event_end.tpl');
$a->page['end'] .= replace_macros($etpl, [
'$baseurl' => System::baseUrl(),
]);
$mode = 'view'; $mode = 'view';
$y = 0; $y = 0;
$m = 0; $m = 0;

View file

@ -117,12 +117,6 @@ function contacts_init(App $a)
'$baseurl' => System::baseUrl(true), '$baseurl' => System::baseUrl(true),
'$base' => $base '$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) function contacts_batch_actions(App $a)
@ -509,9 +503,6 @@ function contacts_content(App $a, $update = 0)
$a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [ $a->page['htmlhead'] .= replace_macros(get_markup_template('contact_head.tpl'), [
'$baseurl' => System::baseUrl(true), '$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['blocked'] = Contact::isBlockedByUser($contact['id'], local_user());
$contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user()); $contact['readonly'] = Contact::isIgnoredByUser($contact['id'], local_user());

View file

@ -57,15 +57,6 @@ function editpost_content(App $a)
'$nickname' => $a->user['nickname'] '$nickname' => $a->user['nickname']
]); ]);
$tpl = get_markup_template('jot-end.tpl');
$a->page['end'] .= replace_macros($tpl, [
'$baseurl' => System::baseUrl(),
'$ispublic' => '&nbsp;', // L10n::t('Visible to <strong>everybody</strong>'),
'$geotag' => $geotag,
'$nickname' => $a->user['nickname']
]);
$tpl = get_markup_template("jot.tpl"); $tpl = get_markup_template("jot.tpl");
if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) { if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {

View file

@ -231,11 +231,6 @@ function events_content(App $a)
'$i18n' => $i18n, '$i18n' => $i18n,
]); ]);
$etpl = get_markup_template('event_end.tpl');
$a->page['end'] .= replace_macros($etpl, [
'$baseurl' => System::baseUrl(),
]);
$o = ''; $o = '';
$tabs = ''; $tabs = '';
// tabs // tabs

View file

@ -46,12 +46,6 @@ function message_init(App $a)
'$baseurl' => System::baseUrl(true), '$baseurl' => System::baseUrl(true),
'$base' => $base '$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) function message_post(App $a)
@ -199,13 +193,6 @@ function message_content(App $a)
'$linkurl' => L10n::t('Please enter a link URL:') '$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]] : []; $preselect = isset($a->argv[2]) ? [$a->argv[2]] : [];
$prename = $preurl = $preid = ''; $prename = $preurl = $preid = '';
@ -344,13 +331,6 @@ function message_content(App $a)
'$linkurl' => L10n::t('Please enter a link URL:') '$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 = []; $mails = [];
$seen = 0; $seen = 0;
$unknown = false; $unknown = false;

View file

@ -317,7 +317,6 @@ function profile_photo_crop_ui_head(App $a, Image $image)
} }
$a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []); $a->page['htmlhead'] .= replace_macros(get_markup_template("crophead.tpl"), []);
$a->page['end'] .= replace_macros(get_markup_template("cropend.tpl"), []);
$imagecrop = [ $imagecrop = [
'hash' => $hash, 'hash' => $hash,

View file

@ -527,9 +527,6 @@ function profiles_content(App $a) {
$a->page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), [ $a->page['htmlhead'] .= replace_macros(get_markup_template('profed_head.tpl'), [
'$baseurl' => System::baseUrl(true), '$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"); $opt_tpl = get_markup_template("profile-hide-friends.tpl");
$hide_friends = replace_macros($opt_tpl,[ $hide_friends = replace_macros($opt_tpl,[

View file

@ -982,11 +982,6 @@ function settings_content(App $a)
'$theme_config' => $theme_config, '$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; return $o;
} }

View file

@ -105,12 +105,6 @@ function videos_init(App $a)
$a->page['htmlhead'] .= replace_macros($tpl,[ $a->page['htmlhead'] .= replace_macros($tpl,[
'$baseurl' => System::baseUrl(), '$baseurl' => System::baseUrl(),
]); ]);
$tpl = get_markup_template("videos_end.tpl");
$a->page['end'] .= replace_macros($tpl,[
'$baseurl' => System::baseUrl(),
]);
} }
return; return;

View file

@ -120,13 +120,6 @@ function wallmessage_content(App $a) {
'$linkurl' => L10n::t('Please enter a link URL:') '$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'); $tpl = get_markup_template('wallmessage.tpl');
$o = replace_macros($tpl, [ $o = replace_macros($tpl, [
'$header' => L10n::t('Send Private Message'), '$header' => L10n::t('Send Private Message'),

View file

@ -96,6 +96,41 @@ class App
public $force_max_items = 0; public $force_max_items = 0;
public $theme_events_in_profile = true; 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 * @brief An array for all theme-controllable parameters
* *
@ -309,7 +344,6 @@ class App
'aside' => '', 'aside' => '',
'bottom' => '', 'bottom' => '',
'content' => '', 'content' => '',
'end' => '',
'footer' => '', 'footer' => '',
'htmlhead' => '', 'htmlhead' => '',
'nav' => '', 'nav' => '',
@ -738,7 +772,17 @@ class App
$this->pager['start'] = ($this->pager['page'] * $this->pager['itemspage']) - $this->pager['itemspage']; $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); $interval = ((local_user()) ? PConfig::get(local_user(), 'system', 'update_interval') : 40000);
@ -759,23 +803,13 @@ class App
$this->page['title'] = $this->config['sitename']; $this->page['title'] = $this->config['sitename'];
} }
/* put the head template at the beginning of page['htmlhead'] if (!empty($this->theme['stylesheet'])) {
* since the code added by the modules frequently depends on it $stylesheet = $this->theme['stylesheet'];
* being first } else {
*/ $stylesheet = $this->getCurrentThemeStylesheetPath();
if (!isset($this->page['htmlhead'])) {
$this->page['htmlhead'] = '';
} }
// If we're using Smarty, then doing replace_macros() will replace $this->registerStylesheet($stylesheet);
// 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');
} else {
$stylesheet = '$stylesheet';
}
$shortcut_icon = Config::get('system', 'shortcut_icon'); $shortcut_icon = Config::get('system', 'shortcut_icon');
if ($shortcut_icon == '') { if ($shortcut_icon == '') {
@ -788,9 +822,15 @@ class App
} }
// get data wich is needed for infinite scroll on the network page // 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'); $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, [ $this->page['htmlhead'] = replace_macros($tpl, [
'$baseurl' => $this->get_baseurl(), '$baseurl' => $this->get_baseurl(),
'$local_user' => local_user(), '$local_user' => local_user(),
@ -801,21 +841,56 @@ class App
'$update_interval' => $interval, '$update_interval' => $interval,
'$shortcut_icon' => $shortcut_icon, '$shortcut_icon' => $shortcut_icon,
'$touch_icon' => $touch_icon, '$touch_icon' => $touch_icon,
'$stylesheet' => $stylesheet, '$infinite_scroll' => $infinite_scroll,
'$infinite_scroll' => $invinite_scroll,
'$block_public' => intval(Config::get('system', 'block_public')), '$block_public' => intval(Config::get('system', 'block_public')),
'$stylesheets' => $this->stylesheets,
]) . $this->page['htmlhead']; ]) . $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'])) { // If you're just visiting, let javascript take you home
$this->page['end'] = ''; if (!empty($_SESSION['visitor_home'])) {
$homebase = $_SESSION['visitor_home'];
} elseif (local_user()) {
$homebase = 'profile/' . $this->user['nickname'];
} }
$tpl = get_markup_template('end.tpl');
$this->page['end'] = replace_macros($tpl, [ if (isset($homebase)) {
'$baseurl' => $this->get_baseurl() $this->page['footer'] .= '<script>var homebase="' . $homebase . '";</script>' . "\n";
]) . $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) public function set_curl_code($code)

View file

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

View file

@ -485,14 +485,12 @@ function liveUpdate(src) {
$('.wall-item-body', data).imagesLoaded(function() { $('.wall-item-body', data).imagesLoaded(function() {
updateConvItems(data); updateConvItems(data);
document.dispatchEvent(new Event('postprocess_liveupdate'));
// Update the scroll position. // Update the scroll position.
$(window).scrollTop($(window).scrollTop() + $("section").height() - orgHeight); $(window).scrollTop($(window).scrollTop() + $("section").height() - orgHeight);
}); });
callAddonHooks("postprocess_liveupdate");
}); });
} }
function imgbright(node) { function imgbright(node) {
@ -676,6 +674,7 @@ function preview_post() {
if (data.preview) { if (data.preview) {
$("#jot-preview-content").html(data.preview); $("#jot-preview-content").html(data.preview);
$("#jot-preview-content" + " a").click(function() {return false;}); $("#jot-preview-content" + " a").click(function() {return false;});
document.dispatchEvent(new Event('postprocess_liveupdate'));
} }
}, },
"json" "json"
@ -742,6 +741,8 @@ function loadScrollContent() {
} else { } else {
$("#scroll-end").fadeIn('normal'); $("#scroll-end").fadeIn('normal');
} }
document.dispatchEvent(new Event('postprocess_liveupdate'));
}); });
} }

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -0,0 +1,3 @@
{{foreach $footerScripts as $scriptUrl}}
<script type="text/javascript" src="{{$scriptUrl}}"></script>
{{/foreach}}

View file

@ -8,12 +8,10 @@
<link rel="stylesheet" href="view/asset/jquery-datetimepicker/build/jquery.datetimepicker.min.css" type="text/css" media="screen" /> <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" 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="shortcut icon" href="{{$shortcut_icon}}" />
<link rel="apple-touch-icon" href="{{$touch_icon}}"/> <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
@ -44,12 +42,6 @@
<script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script> <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/js/acl.js" ></script>
<script type="text/javascript" src="view/asset/base64/base64.min.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/js/main.js" ></script>
<script> <script>

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -1 +0,0 @@

View file

@ -138,27 +138,7 @@ if (!isset($minimal)) {
</main> </main>
<footer> <footer>
<?php if (x($page, 'footer')) echo $page['footer']; ?> <?php echo defaults($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">
&times;
</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>
</footer> </footer>
<?php } ?> <!-- End of condition if $minimal else the rest --> <?php } ?> <!-- End of condition if $minimal else the rest -->
</body> </body>

View file

@ -0,0 +1,23 @@
<!-- 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">
&times;
</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}}

View file

@ -25,17 +25,14 @@
<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/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"/> <link rel="stylesheet" href="view/theme/frio/font/open_sans/open-sans.css" type="text/css" media="screen"/>
{{* The own style.css *}} {{foreach $stylesheets as $stylesheetUrl}}
<link rel="stylesheet" type="text/css" href="{{$stylesheet}}" media="all" /> <link rel="stylesheet" href="{{$stylesheetUrl}}" type="text/css" media="screen" />
{{/foreach}}
{{* own css files *}} {{* 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/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="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="shortcut icon" href="{{$shortcut_icon}}" />
<link rel="apple-touch-icon" href="{{$touch_icon}}"/> <link rel="apple-touch-icon" href="{{$touch_icon}}"/>
@ -68,12 +65,6 @@
<script type="text/javascript" src="view/asset/imagesloaded/imagesloaded.pkgd.min.js"></script> <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/js/acl.js"></script>
<script type="text/javascript" src="view/asset/base64/base64.min.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/js/main.js"></script>
<script type="text/javascript" src="view/theme/frio/frameworks/bootstrap/js/bootstrap.min.js"></script> <script type="text/javascript" src="view/theme/frio/frameworks/bootstrap/js/bootstrap.min.js"></script>