]> git.mxchange.org Git - friendica.git/commitdiff
Merge pull request #5773 from MrPetovan/task/rewrite-js-hooks
authorMichael Vogel <icarus@dabo.de>
Mon, 1 Oct 2018 17:10:30 +0000 (17:10 +0000)
committerGitHub <noreply@github.com>
Mon, 1 Oct 2018 17:10:30 +0000 (17:10 +0000)
Rewrite JS hooks

33 files changed:
doc/Addons.md
include/conversation.php
include/text.php
index.php
mod/cal.php
mod/contacts.php
mod/editpost.php
mod/events.php
mod/message.php
mod/profile_photo.php
mod/profiles.php
mod/settings.php
mod/videos.php
mod/wallmessage.php
src/App.php
view/js/addon-hooks.js [deleted file]
view/js/main.js
view/templates/contact_end.tpl [deleted file]
view/templates/contacts-end.tpl [deleted file]
view/templates/cropend.tpl [deleted file]
view/templates/end.tpl [deleted file]
view/templates/event_end.tpl [deleted file]
view/templates/footer.tpl [new file with mode: 0644]
view/templates/head.tpl
view/templates/jot-end.tpl [deleted file]
view/templates/message-end.tpl [deleted file]
view/templates/msg-end.tpl [deleted file]
view/templates/profed_end.tpl [deleted file]
view/templates/videos_end.tpl [deleted file]
view/templates/wallmsg-end.tpl [deleted file]
view/theme/frio/php/default.php
view/theme/frio/templates/footer.tpl [new file with mode: 0644]
view/theme/frio/templates/head.tpl

index 2465db7307f0654cf5ffa400c5fd48a2312e9ab7..011bca0737a6f96a2c4f6667c49cdd9d8f9129b9 100644 (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.
 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
 
@@ -260,6 +272,11 @@ Called after conversion of bbcode to HTML.
 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.
@@ -294,6 +311,11 @@ No hook data.
 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:
 
@@ -389,14 +411,9 @@ Hook data:
     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
 
@@ -571,6 +588,8 @@ Here is a complete list of all hook callbacks with file locations (as of 01-Apr-
 ### src/App.php
 
     Addon::callHooks('load_config');
+    Addon::callHooks('head');
+    Addon::callHooks('footer');
 
 ### 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
 
-    callAddonHooks("postprocess_liveupdate");
+    document.dispatchEvent(new Event('postprocess_liveupdate'));
index e41b697b547824d869ad487107b05503bb80e956..59ee5ed8248cbdd4b2b7be65c74c6b3382bc2182 100644 (file)
@@ -1091,21 +1091,6 @@ function status_editor(App $a, $x, $notes_cid = 0, $popup = false)
                '$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);
 
index 97baee7f60b551a76089ba31efbd66e573bb3412..7013c2c91b493baeba1d2cb8b22e7e08e6a37573 100644 (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'), [
                                        '$baseurl' => System::baseUrl(),
                                ]);
-                               $a->page['end'] .= replace_macros(get_markup_template('videos_end.tpl'), [
-                                       '$baseurl' => System::baseUrl(),
-                               ]);
                        }
 
                        $url_parts = explode('/', $the_url);
index 8b0bd472513fd9c5a1ca9bbd457a60ce963682d3..184a195924cc8acb715dc2f7654dfb8301b847b2 100644 (file)
--- a/index.php
+++ b/index.php
@@ -91,7 +91,7 @@ if (!$a->is_backend()) {
  * 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'])) {
@@ -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'];
        L10n::loadTranslationTable($lang);
 }
@@ -125,12 +125,12 @@ if (!empty($_GET['zrl']) && $a->mode == App::MODE_NORMAL) {
                        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);
@@ -149,14 +149,10 @@ if ((x($_GET,'owt')) && $a->mode == App::MODE_NORMAL) {
 
 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', []);
@@ -295,11 +291,11 @@ if (strlen($a->module)) {
 
        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']);
                }
@@ -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);
                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.')
+               ]);
        }
 }
 
@@ -326,10 +320,6 @@ if (file_exists($theme_info_file)) {
 
 /* 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']);
 }
@@ -405,24 +395,13 @@ if ($a->module_loaded) {
  * 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
@@ -444,36 +423,9 @@ if ($a->module != 'install' && $a->module != 'maintenance') {
        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();
 
@@ -502,7 +454,7 @@ if (isset($_GET["mode"]) && ($_GET["mode"] == "raw")) {
 
        echo substr($target->saveHTML(), 6, -8);
 
-       killme();
+       exit();
 }
 
 $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
 require_once $template;
-
-killme();
index bdedaaacfa8afb99d1d3b3d1952728eafa3cec18..ae1060c47ad5d36a1a76e774857ffd6c4f25e939 100644 (file)
@@ -94,11 +94,6 @@ function cal_content(App $a)
                '$i18n' => $i18n,
        ]);
 
-       $etpl = get_markup_template('event_end.tpl');
-       $a->page['end'] .= replace_macros($etpl, [
-               '$baseurl' => System::baseUrl(),
-       ]);
-
        $mode = 'view';
        $y = 0;
        $m = 0;
index 1604f0b6605ec43d6f0e936972ad2394a45c11f2..68dbbd59ddbb4e904ed5b57f087c9751be8a177b 100644 (file)
@@ -117,12 +117,6 @@ function contacts_init(App $a)
                '$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)
@@ -509,9 +503,6 @@ function contacts_content(App $a, $update = 0)
                $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());
index 9f4aee31d6c63421a2692990b123a3926ac17ec8..d6493b3c0c1a8aa34f4d9c547ca1688fe3ca8759 100644 (file)
@@ -57,15 +57,6 @@ function editpost_content(App $a)
                '$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");
 
        if (strlen($item['allow_cid']) || strlen($item['allow_gid']) || strlen($item['deny_cid']) || strlen($item['deny_gid'])) {
index 38b632cf49e46d9a0fa0eda12966d61c0235af06..d04aac3761267d05515e61d7d1d5e51a16e7b4ea 100644 (file)
@@ -231,11 +231,6 @@ function events_content(App $a)
                '$i18n' => $i18n,
        ]);
 
-       $etpl = get_markup_template('event_end.tpl');
-       $a->page['end'] .= replace_macros($etpl, [
-               '$baseurl' => System::baseUrl(),
-       ]);
-
        $o = '';
        $tabs = '';
        // tabs
index d0a583967b047c3a61a6261f5dd10f9f6657693c..7dc42177635fcf6885dafb843c843738b4970062 100644 (file)
@@ -46,12 +46,6 @@ function message_init(App $a)
                '$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)
@@ -199,13 +193,6 @@ function message_content(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 = '';
@@ -344,13 +331,6 @@ function message_content(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:')
-               ]);
-
                $mails = [];
                $seen = 0;
                $unknown = false;
index 567a7f3a2512b3e05c79edb68a57546637a47f76..984ebfed6f39fc27bfa6bc157d903e5be905953a 100644 (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['end'] .= replace_macros(get_markup_template("cropend.tpl"), []);
 
        $imagecrop = [
                'hash'       => $hash,
index d951a470d7605db79ea8f97af1eeba3278b39c0e..76491c553edf8cb3c7e3f0b481488aaad4907b2a 100644 (file)
@@ -527,9 +527,6 @@ function profiles_content(App $a) {
                $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,[
index 84bc230e30ec23c0c943d4d3af8e27ff1d727845..78fa446ce0372dd0fa65a419db4286e79fd1848b 100644 (file)
@@ -982,11 +982,6 @@ function settings_content(App $a)
                        '$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;
        }
 
index e00df10a24b48d171fa05287c7456b86875a795d..a0c9d0d16edfeb8cd4e761a2784f02104b212799 100644 (file)
@@ -105,12 +105,6 @@ function videos_init(App $a)
                $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;
index 5606b6feede6a6ed35c26f5512ae5cf7cb403303..5e08420ecb109f6cd16767574f51815982038c9e 100644 (file)
@@ -120,13 +120,6 @@ function wallmessage_content(App $a) {
                '$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'),
index 0dc4b86b95f6520f14bb966e45f552ff6e8ad511..7622a1a0ce3aacb5e2795fbdd6b9c1e7b572e78e 100644 (file)
@@ -96,6 +96,41 @@ class App
        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
         *
@@ -309,7 +344,6 @@ class App
                        'aside' => '',
                        'bottom' => '',
                        'content' => '',
-                       'end' => '',
                        'footer' => '',
                        'htmlhead' => '',
                        'nav' => '',
@@ -738,7 +772,17 @@ class App
                $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);
 
@@ -759,24 +803,14 @@ class App
                        $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';
@@ -788,9 +822,15 @@ class App
                }
 
                // 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(),
@@ -801,21 +841,56 @@ class App
                        '$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)
diff --git a/view/js/addon-hooks.js b/view/js/addon-hooks.js
deleted file mode 100644 (file)
index 3e1cb48..0000000
+++ /dev/null
@@ -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();
-                               }
-                       }
-               }
-       }
-}
index 83086c82b037b4f322bf832b98e233fcde979f18..7e726248d3fd0f3c939dc7957a407ec4a266cbee 100644 (file)
@@ -485,14 +485,12 @@ function liveUpdate(src) {
                $('.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) {
@@ -676,6 +674,7 @@ function preview_post() {
                        if (data.preview) {
                                $("#jot-preview-content").html(data.preview);
                                $("#jot-preview-content" + " a").click(function() {return false;});
+                               document.dispatchEvent(new Event('postprocess_liveupdate'));
                        }
                },
                "json"
@@ -742,6 +741,8 @@ function loadScrollContent() {
                } else {
                        $("#scroll-end").fadeIn('normal');
                }
+
+               document.dispatchEvent(new Event('postprocess_liveupdate'));
        });
 }
 
diff --git a/view/templates/contact_end.tpl b/view/templates/contact_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/contacts-end.tpl b/view/templates/contacts-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/cropend.tpl b/view/templates/cropend.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/end.tpl b/view/templates/end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/event_end.tpl b/view/templates/event_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/footer.tpl b/view/templates/footer.tpl
new file mode 100644 (file)
index 0000000..1b9d700
--- /dev/null
@@ -0,0 +1,3 @@
+{{foreach $footerScripts as $scriptUrl}}
+<script type="text/javascript" src="{{$scriptUrl}}"></script>
+{{/foreach}}
index 7da270d3ff1ed8b6a0b59905178766ee874a7f43..6c55f99771e63beb58ed9f61852136bfb32f896e 100644 (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/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>
 
diff --git a/view/templates/jot-end.tpl b/view/templates/jot-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/message-end.tpl b/view/templates/message-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/msg-end.tpl b/view/templates/msg-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/profed_end.tpl b/view/templates/profed_end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/view/templates/videos_end.tpl b/view/templates/videos_end.tpl
deleted file mode 100644 (file)
index e69de29..0000000
diff --git a/view/templates/wallmsg-end.tpl b/view/templates/wallmsg-end.tpl
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
index cb683285313c04fb9546d27f49ceefaed0d38e7c..d9ecb7cf0dac0341eebfda149940e38c946f3808 100644 (file)
@@ -138,27 +138,7 @@ if (!isset($minimal)) {
                </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">
-                                                               &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>
-
+                       <?php echo defaults($page, 'footer', ''); ?>
                </footer>
 <?php } ?> <!-- End of condition if $minimal else the rest -->
        </body>
diff --git a/view/theme/frio/templates/footer.tpl b/view/theme/frio/templates/footer.tpl
new file mode 100644 (file)
index 0000000..4d58ff8
--- /dev/null
@@ -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}}
index 9d26a61b45595fa204124ebb52f8ec8fe9bb7baf..d8f8b1d82dc531bc1e7906d81eb534226e1606fc 100644 (file)
 <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>