diff --git a/INSTALL.txt b/INSTALL.txt index 71671af3f..08bd41c8d 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -154,18 +154,6 @@ Friendica also supports a number on non-standard headers in common use. X-Forwarded-Ssl: on It is however preferable to use the standard approach if configuring a new server. -In Nginx, this can be done as follows (assuming Friendica runs on port 8080). - - location / { - if ( $scheme != https ) { # Force Redirect to HTTPS - return 302 https://$host$uri; - } - proxy_pass http://localhost:8080; - proxy_redirect off; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Forwarded "for=$proxy_add_x_forwarded_for; proto=$scheme"; - } ##################################################################### diff --git a/mod/admin.php b/mod/admin.php index 2303d3b9c..36b2ca730 100644 --- a/mod/admin.php +++ b/mod/admin.php @@ -165,7 +165,7 @@ function admin_content(&$a) { /* get plugins admin page */ - $r = q("SELECT `name` FROM `addon` WHERE `plugin_admin`=1 ORDER BY `name`"); + $r = q("SELECT `name` FROM `addon` WHERE `plugin_admin` = 1 ORDER BY `name`"); $aside_tools['plugins_admin']=array(); foreach ($r as $h){ $plugin =$h['name']; @@ -271,7 +271,7 @@ function admin_page_federation(&$a) { // displayed on the stats page. $platforms = array('Friendica', 'Diaspora', '%%red%%', 'Hubzilla', 'GNU Social', 'StatusNet'); $colors = array('Friendica' => '#ffc018', // orange from the logo - 'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray + 'Diaspora' => '#a1a1a1', // logo is black and white, makes a gray '%%red%%' => '#c50001', // fire red from the logo 'Hubzilla' => '#43488a', // blue from the logo 'GNU Social'=> '#a22430', // dark red from the logo @@ -282,17 +282,17 @@ function admin_page_federation(&$a) { foreach ($platforms as $p) { // get a total count for the platform, the name and version of the // highest version and the protocol tpe - $c = q('SELECT count(*) AS total, platform, network, version FROM gserver - WHERE platform LIKE "%s" AND last_contact > last_failure AND `version` != "" - ORDER BY version ASC;', $p); + $c = q('SELECT COUNT(*) AS `total`, `platform`, `network`, `version` FROM `gserver` + WHERE `platform` LIKE "%s" AND `last_contact` > `last_failure` AND `version` != "" + ORDER BY `version` ASC;', $p); $total = $total + $c[0]['total']; // what versions for that platform do we know at all? // again only the active nodes - $v = q('SELECT count(*) AS total, version FROM gserver - WHERE last_contact > last_failure AND platform LIKE "%s" AND `version` != "" - GROUP BY version - ORDER BY version;', $p); + $v = q('SELECT COUNT(*) AS `total, version` FROM `gserver` + WHERE `last_contact` > `last_failure` AND `platform` LIKE "%s" AND `version` != "" + GROUP BY `version` + ORDER BY `version`;', $p); // // clean up version numbers @@ -386,7 +386,10 @@ function admin_page_federation(&$a) { */ function admin_page_queue(&$a) { // get content from the queue table - $r = q("SELECT c.name,c.nurl,q.id,q.network,q.created,q.last from queue as q, contact as c where c.id=q.cid order by q.cid, q.created;"); + $r = q("SELECT `c`.`name`, `c`.`nurl`, `q`.`id`, `q`.`network`, `q`.`created`, `q`.`last` + FROM `queue` AS `q`, `contact` AS `c` + WHERE `c`.`id` = `q`.`cid` + ORDER BY `q`.`cid`, `q`.`created`;"); $t = get_markup_template("admin_queue.tpl"); return replace_macros($t, array( @@ -416,7 +419,7 @@ function admin_page_queue(&$a) { * @return string */ function admin_page_summary(&$a) { - $r = q("SELECT `page-flags`, COUNT(uid) as `count` FROM `user` GROUP BY `page-flags`"); + $r = q("SELECT `page-flags`, COUNT(`uid`) AS `count` FROM `user` GROUP BY `page-flags`"); $accounts = array( array(t('Normal Account'), 0), array(t('Soapbox Account'), 0), @@ -431,21 +434,21 @@ function admin_page_summary(&$a) { logger('accounts: '.print_r($accounts,true),LOGGER_DATA); - $r = q("SELECT COUNT(id) as `count` FROM `register`"); + $r = q("SELECT COUNT(`id`) AS `count` FROM `register`"); $pending = $r[0]['count']; - $r = q("select count(*) as total from deliverq where 1"); + $r = q("SELECT COUNT(*) AS `total` FROM `deliverq` WHERE 1"); $deliverq = (($r) ? $r[0]['total'] : 0); - $r = q("select count(*) as total from queue where 1"); + $r = q("SELECT COUNT(*) AS `total` FROM `queue` WHERE 1"); $queue = (($r) ? $r[0]['total'] : 0); - if (get_config('system','worker')) { - $r = q("select count(*) as total from workerqueue where 1"); - $workerqueue = (($r) ? $r[0]['total'] : 0); - } else { - $workerqueue = 0; - } + if (get_config('system','worker')) { + $r = q("SELECT COUNT(*) AS `total` FROM `workerqueue` WHERE 1"); + $workerqueue = (($r) ? $r[0]['total'] : 0); + } else { + $workerqueue = 0; + } // We can do better, but this is a quick queue status @@ -543,7 +546,7 @@ function admin_page_site_post(&$a) { set_config('system','url',$new_url); // send relocate - $users = q("SELECT uid FROM user WHERE account_removed = 0 AND account_expired = 0"); + $users = q("SELECT `uid` FROM `user` WHERE `account_removed` = 0 AND `account_expired` = 0"); foreach ($users as $user) { proc_run('php', 'include/notifier.php', 'relocate', $user['uid']); @@ -558,10 +561,10 @@ function admin_page_site_post(&$a) { $sitename = ((x($_POST,'sitename')) ? notags(trim($_POST['sitename'])) : ''); $hostname = ((x($_POST,'hostname')) ? notags(trim($_POST['hostname'])) : ''); $sender_email = ((x($_POST,'sender_email')) ? notags(trim($_POST['sender_email'])) : ''); - $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false); + $banner = ((x($_POST,'banner')) ? trim($_POST['banner']) : false); $shortcut_icon = ((x($_POST,'shortcut_icon')) ? notags(trim($_POST['shortcut_icon'])) : ''); $touch_icon = ((x($_POST,'touch_icon')) ? notags(trim($_POST['touch_icon'])) : ''); - $info = ((x($_POST,'info')) ? trim($_POST['info']) : false); + $info = ((x($_POST,'info')) ? trim($_POST['info']) : false); $language = ((x($_POST,'language')) ? notags(trim($_POST['language'])) : ''); $theme = ((x($_POST,'theme')) ? notags(trim($_POST['theme'])) : ''); $theme_mobile = ((x($_POST,'theme_mobile')) ? notags(trim($_POST['theme_mobile'])) : ''); @@ -647,41 +650,41 @@ function admin_page_site_post(&$a) { if($ssl_policy != intval(get_config('system','ssl_policy'))) { if($ssl_policy == SSL_POLICY_FULL) { - q("update `contact` set - `url` = replace(`url` , 'http:' , 'https:'), - `photo` = replace(`photo` , 'http:' , 'https:'), - `thumb` = replace(`thumb` , 'http:' , 'https:'), - `micro` = replace(`micro` , 'http:' , 'https:'), - `request` = replace(`request`, 'http:' , 'https:'), - `notify` = replace(`notify` , 'http:' , 'https:'), - `poll` = replace(`poll` , 'http:' , 'https:'), - `confirm` = replace(`confirm`, 'http:' , 'https:'), - `poco` = replace(`poco` , 'http:' , 'https:') - where `self` = 1" + q("UPDATE `contact` SET + `url` = REPLACE(`url` , 'http:' , 'https:'), + `photo` = REPLACE(`photo` , 'http:' , 'https:'), + `thumb` = REPLACE(`thumb` , 'http:' , 'https:'), + `micro` = REPLACE(`micro` , 'http:' , 'https:'), + `request` = REPLACE(`request`, 'http:' , 'https:'), + `notify` = REPLACE(`notify` , 'http:' , 'https:'), + `poll` = REPLACE(`poll` , 'http:' , 'https:'), + `confirm` = REPLACE(`confirm`, 'http:' , 'https:'), + `poco` = REPLACE(`poco` , 'http:' , 'https:') + WHERE `self` = 1" ); - q("update `profile` set - `photo` = replace(`photo` , 'http:' , 'https:'), - `thumb` = replace(`thumb` , 'http:' , 'https:') - where 1 " + q("UPDATE `profile` SET + `photo` = REPLACE(`photo` , 'http:' , 'https:'), + `thumb` = REPLACE(`thumb` , 'http:' , 'https:') + WHERE 1 " ); } elseif($ssl_policy == SSL_POLICY_SELFSIGN) { - q("update `contact` set - `url` = replace(`url` , 'https:' , 'http:'), - `photo` = replace(`photo` , 'https:' , 'http:'), - `thumb` = replace(`thumb` , 'https:' , 'http:'), - `micro` = replace(`micro` , 'https:' , 'http:'), - `request` = replace(`request`, 'https:' , 'http:'), - `notify` = replace(`notify` , 'https:' , 'http:'), - `poll` = replace(`poll` , 'https:' , 'http:'), - `confirm` = replace(`confirm`, 'https:' , 'http:'), - `poco` = replace(`poco` , 'https:' , 'http:') - where `self` = 1" + q("UPDATE `contact` SET + `url` = REPLACE(`url` , 'https:' , 'http:'), + `photo` = REPLACE(`photo` , 'https:' , 'http:'), + `thumb` = REPLACE(`thumb` , 'https:' , 'http:'), + `micro` = REPLACE(`micro` , 'https:' , 'http:'), + `request` = REPLACE(`request`, 'https:' , 'http:'), + `notify` = REPLACE(`notify` , 'https:' , 'http:'), + `poll` = REPLACE(`poll` , 'https:' , 'http:'), + `confirm` = REPLACE(`confirm`, 'https:' , 'http:'), + `poco` = REPLACE(`poco` , 'https:' , 'http:') + WHERE `self` = 1" ); - q("update `profile` set - `photo` = replace(`photo` , 'https:' , 'http:'), - `thumb` = replace(`thumb` , 'https:' , 'http:') - where 1 " + q("UPDATE `profile` SET + `photo` = REPLACE(`photo` , 'https:' , 'http:'), + `thumb` = REPLACE(`thumb` , 'https:' , 'http:') + WHERE 1 " ); } } @@ -876,7 +879,7 @@ function admin_page_site(&$a) { /* get user names to make the install a personal install of X */ $user_names = array(); $user_names['---'] = t('Multi user instance'); - $users = q("SELECT username, nickname FROM `user`"); + $users = q("SELECT `username`, `nickname` FROM `user`"); foreach ($users as $user) { $user_names[$user['nickname']] = $user['username']; } @@ -1084,7 +1087,7 @@ function admin_page_dbsync(&$a) { } $failed = array(); - $r = q("select k, v from config where `cat` = 'database' "); + $r = q("SELECT `k`, `v` FROM `config` WHERE `cat` = 'database' "); if(count($r)) { foreach($r as $rr) { $upd = intval(substr($rr['k'],7)); @@ -1123,7 +1126,7 @@ function admin_page_users_post(&$a){ $pending = (x($_POST, 'pending') ? $_POST['pending'] : array()); $users = (x($_POST, 'user') ? $_POST['user'] : array()); $nu_name = (x($_POST, 'new_user_name') ? $_POST['new_user_name'] : ''); - $nu_nickname = (x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : ''); + $nu_nickname = (x($_POST, 'new_user_nickname') ? $_POST['new_user_nickname'] : ''); $nu_email = (x($_POST, 'new_user_email') ? $_POST['new_user_email'] : ''); check_form_security_token_redirectOnErr('/admin/users', 'admin_users'); @@ -1180,7 +1183,7 @@ function admin_page_users_post(&$a){ if(x($_POST,'page_users_block')) { foreach($users as $uid){ - q("UPDATE `user` SET `blocked`=1-`blocked` WHERE `uid`=%s", + q("UPDATE `user` SET `blocked` = 1-`blocked` WHERE `uid` = %s", intval($uid) ); } @@ -1225,7 +1228,7 @@ function admin_page_users_post(&$a){ function admin_page_users(&$a){ if($a->argc>2) { $uid = $a->argv[3]; - $user = q("SELECT username, blocked FROM `user` WHERE `uid`=%d", intval($uid)); + $user = q("SELECT `username`, `blocked` FROM `user` WHERE `uid` = %d", intval($uid)); if(count($user)==0) { notice('User not found'.EOL); goaway('admin/users'); @@ -1242,7 +1245,7 @@ function admin_page_users(&$a){ }; break; case "block":{ check_form_security_token_redirectOnErr('/admin/users', 'admin_users', 't'); - q("UPDATE `user` SET `blocked`=%d WHERE `uid`=%s", + q("UPDATE `user` SET `blocked` = %d WHERE `uid` = %s", intval(1-$user[0]['blocked']), intval($uid) ); @@ -1262,7 +1265,7 @@ function admin_page_users(&$a){ /* get users */ - $total = q("SELECT count(*) as total FROM `user` where 1"); + $total = q("SELECT COUNT(*) AS `total` FROM `user` WHERE 1"); if(count($total)) { $a->set_pager_total($total[0]['total']); $a->set_pager_itemspage(100); @@ -1855,11 +1858,11 @@ function admin_page_logs_post(&$a) { function admin_page_logs(&$a){ $log_choices = array( - LOGGER_NORMAL => 'Normal', - LOGGER_TRACE => 'Trace', - LOGGER_DEBUG => 'Debug', - LOGGER_DATA => 'Data', - LOGGER_ALL => 'All' + LOGGER_NORMAL => 'Normal', + LOGGER_TRACE => 'Trace', + LOGGER_DEBUG => 'Debug', + LOGGER_DATA => 'Data', + LOGGER_ALL => 'All' ); $t = get_markup_template("admin_logs.tpl"); diff --git a/mod/contacts.php b/mod/contacts.php index 4897663a0..3d8b44b71 100644 --- a/mod/contacts.php +++ b/mod/contacts.php @@ -787,7 +787,7 @@ function contacts_content(&$a) { '$total' => $total, '$search' => $search_hdr, '$desc' => t('Search your contacts'), - '$finding' => (($searching) ? t('Finding: ') . "'" . $search . "'" : ""), + '$finding' => (($searching) ? sprintf(t('Results for: %s'),$search) : ""), '$submit' => t('Find'), '$cmd' => $a->cmd, '$contacts' => $contacts, diff --git a/mod/directory.php b/mod/directory.php index 9050a050a..a6a9cb8ab 100644 --- a/mod/directory.php +++ b/mod/directory.php @@ -206,7 +206,7 @@ function directory_content(&$a) { '$gdirpath' => $gdirpath, '$desc' => t('Find on this site'), '$contacts' => $entries, - '$finding' => t('Finding:'), + '$finding' => t('Results for:'), '$findterm' => (strlen($search) ? $search : ""), '$title' => t('Site Directory'), '$submit' => t('Find'), diff --git a/mod/dirfind.php b/mod/dirfind.php index f6f50f65c..0638fe14f 100644 --- a/mod/dirfind.php +++ b/mod/dirfind.php @@ -33,6 +33,7 @@ function dirfind_content(&$a, $prefix = "") { if(strpos($search,'@') === 0) { $search = substr($search,1); + $header = sprintf( t('People Search - %s'), $search); if ((valid_email($search) AND validate_email($search)) OR (substr(normalise_link($search), 0, 7) == "http://")) { $user_data = probe_url($search); @@ -43,6 +44,7 @@ function dirfind_content(&$a, $prefix = "") { if(strpos($search,'!') === 0) { $search = substr($search,1); $community = true; + $header = sprintf( t('Forum Search - %s'), $search); } $o = ''; @@ -228,7 +230,7 @@ function dirfind_content(&$a, $prefix = "") { $tpl = get_markup_template('viewcontact_template.tpl'); $o .= replace_macros($tpl,array( - 'title' => sprintf( t('People Search - %s'), $search), + 'title' => $header, '$contacts' => $entries, '$paginate' => paginate($a), )); diff --git a/mods/sample-nginx-reverse-proxy.config b/mods/sample-nginx-reverse-proxy.config new file mode 100644 index 000000000..fbbbc4880 --- /dev/null +++ b/mods/sample-nginx-reverse-proxy.config @@ -0,0 +1,30 @@ +# +# Example of NGINX as reverse-proxy terminating an HTTPS connection. +# +# This is not a complete NGINX config. +# +# Please refer to NGINX docs +# + +... + +server { + + ... + + # assuming Friendica runs on port 8080 + location / { + if ( $scheme != https ) { + # Force Redirect to HTTPS + return 302 https://$host$uri; + } + proxy_pass http://localhost:8080; + proxy_redirect off; + proxy_set_header Host $host; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Forwarded "for=$proxy_add_x_forwarded_for; proto=$scheme"; + } + + ... + +} diff --git a/view/theme/frio/css/style.css b/view/theme/frio/css/style.css index 0ecb56441..cc667c2b9 100644 --- a/view/theme/frio/css/style.css +++ b/view/theme/frio/css/style.css @@ -581,6 +581,9 @@ nav.navbar a { margin: 0px; padding: 10px 15px; } +#search-mobile .navbar-form { + margin: 0; +} #topbar-first #search-box .form-search { height: 25px; font-size: 13px; @@ -941,6 +944,55 @@ aside .vcard #dfrn-request-link, aside .vcard #wallmessage-link { width: 100%; } +/* vcard-short-info */ +#vcard-short-info, +#nav-short-info .contact-wrapper { + margin-top: 2px; + height: 40px; + white-space: nowrap; + overflow: hidden; + padding-right: 20px; + margin-left: -14px; +} +#vcard-short-photo-wrapper img, +#nav-short-info .contact-wrapper img { + height: 34px; + width: 34px; + border-radius: 3px; +} +#vcard-short-desc, +#nav-short-info .contact-wrapper .media-body { + display: block; + height: 34px; + width: 100%; + text-overflow: ellipsis; +} +#vcard-short-desc > .media-heading, +#vcard-short-desc > .vcard-short-addr, +#nav-short-info .contact-wrapper .media-heading, +#nav-short-info .contact-wrapper #contact-entry-url-network { + text-overflow: ellipsis; + overflow: hidden; +} +#vcard-short-desc > .media-heading, +#nav-short-info .contact-wrapper .media-heading { + margin-bottom: 1px; + font-weight: bold; +} +#nav-short-info .contact-wrapper .media-heading a { + color: #555; + font-size: 14px !important; +} +#vcard-short-desc > .vcard-short-addr, +#nav-short-info .contact-wrapper #contact-entry-url-network { + color: #777; + font-size: 12px; +} +.network-content-wrapper > #viewcontact_wrapper-network, +#nav-short-info .contact-wrapper .contact-photo-overlay, +#nav-short-info .contact-wrapper .contact-actions{ + display: none +} aside #peoplefind-sidebar input, aside #follow-sidebar input { @@ -1531,6 +1583,11 @@ img.acpopup-img { /*margin-left: -15px;*/ padding: 0; } +#tabmenu .search-heading { + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} ul.tabs { list-style: none; height: 100%; @@ -1661,6 +1718,15 @@ ul.dropdown-menu li:hover { color: $link_color; font-size: 20px; } +.search-content-wrapper > #search-header-wrapper { + display: none; +} +.search-content-wrapper > .section-title-wrapper { + display: none; +} +#navbar-button > #search-save-form > #search-save { + margin-top: 3px; +} /* Section-Content-Wrapper */ #search-header-wrapper { padding: 15px; diff --git a/view/theme/frio/frameworks/jquery-scrollspy/README.md b/view/theme/frio/frameworks/jquery-scrollspy/README.md new file mode 100644 index 000000000..5707f31fe --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/README.md @@ -0,0 +1,183 @@ +# NOTE: This is the latest version of ScrollSpy, which includes a ton of bug fixes and efficiency improvements. It's recommended that you use this version for now instead of the official (which hasn't been updated in a while). + +# jQuery-ScrollSpy + +An adaptation of the Mootools Scrollspy (http://davidwalsh.name/mootools-scrollspy) plugin for jQuery + +(c) 2011 Samuel Alexander (https://github.com/sxalexander/jquery-scrollspy) + +(c) 2015 SoftwareSpot + +Released under The MIT License. + +## Description: + +ScrollSpy is a simple jQuery plugin for firing events based on where the user has scrolled to in a page. + +## Homepage: + +https://github.com/softwarespot/jquery-scrollspy + +## Source: + +Hosted at GitHub; browse at: + + https://github.com/softwarespot/jquery-scrollspy/tree/master + +Or clone from: + + git://github.com/softwarespot/jquery-scrollspy.git + +## Usage: + +1. Insert the necessary elements in to your document's `` section, e.g.: + +```html + + +``` + +2. Initialise ScrollSpy once the DOM has been loaded: + +```javascript + +``` + +Check out the /examples for more info ! + +## Documentation: + +ScrollSpy function signature: +```javascript + $('container').scrollspy(options, action) +``` + +Default options for ScrollSpy: +```javascript +// default options for ScrollSpy +var defaults = { + // the offset to be applied to the left and top positions of the container + buffer: 0, + + // the element to apply the 'scrolling' event to (default window) + container: window, + + // the maximum value of the X or Y coordinate, depending on mode the selected + max: 0, + + // the maximum value of the X or Y coordinate, depending on mode the selected + min: 0, + + // whether to listen to the X (horizontal) or Y (vertical) scrolling + mode: 'vertical', + + // namespace to append to the 'scroll' event + namespace: 'scrollspy', + + // call the following callback function every time the user enters the min / max zone + onEnter: null, + + // call the following callback function every time the user leaves the min / max zone + onLeave: null, + + // call the following callback function every time the user leaves the top zone + onLeaveTop: null, + + // call the following callback function every time the user leaves the bottom zone + onLeaveBottom: null, + + // call the following callback function on each scroll event within the min and max parameters + onTick: null, + + // call the following callback function on each scroll event when the element is inside the viewable view port + onView: null +}; +``` + +Events are triggered by ScrollSpy are: + + scrollTick: Fires on each scroll event within the min and max parameters: + position: an object with the current X and Y position. + inside: a Boolean value for whether or not the user is within the min and max parameters + enters: the number of times the min / max has been entered. + leaves: the number of times the min / max has been left. + + scrollEnter: Fires every time the user enters the min / max zone: + position: an object with the current X and Y position. + enters: the number of times the min / max has been entered. + + scrollLeave: Fires every time the user leaves the min / max zone: + position: an object with the current X and Y position. + leaves: the number of times the min / max has been left. + + scrollLeaveTop: Fires every time the user leaves the top zone: + position: an object with the current X and Y position. + leaves: the number of times the min / max has been left. + + scrollLeaveBottom: Fires every time the user leaves the bottom zone: + position: an object with the current X and Y position. + leaves: the number of times the min / max has been left. + + scrollView: Fires every time the element is inside the viewable view port: + position: an object with the current X and Y position. + leaves: the number of times the min / max has been left. + +### Tidy up + +To destroy ScrollSpy for a particular container, simple pass 'destroy' as the action parameter. The only options that will be honoured are `container` and `namespace`. + +## A note about forking: + +By forking this project you hereby grant permission for any commits to your fork to be +merged back into this repository and, with attribution, be released under the terms of +the MIT License. + +## Contribute + +To contribute to the project, you will first need to install [node](https://nodejs.org) globally on your system. Once installation has completed, change the working directory to the plugin's location and run the following command: + +```shell + npm install +``` + +After installation of the local modules, you're ready to start contributing to the project. Before you submit your PR, please don't forget to call `gulp`, which will run against [JSHint](http://jshint.com) for any errors, but will also minify the plugin. + +##### Watch +Call the following command to start 'watching' for any changes to the main JavaScript file(s). This will automatically invoke JSHint and Uglify. +```shell + gulp watch +``` + +##### JSHint +Call the following command to invoke JSHint and check that the changes meet the requirements set in .jshintrc. +```shell + gulp jshint +``` + +##### Uglify +Call the following command to invoke Uglify, which will minify the main JavaScript file(s) and output to a .min.js file respectively. +```shell + gulp uglify +``` + +##### Build +Call the following command to invoke both JSHint and Uglify. +```shell + gulp +``` diff --git a/view/theme/frio/frameworks/jquery-scrollspy/bower.json b/view/theme/frio/frameworks/jquery-scrollspy/bower.json new file mode 100644 index 000000000..8257ebdd8 --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/bower.json @@ -0,0 +1,18 @@ +{ + "name": "jquery-scrollspy", + "homepage": "https://github.com/sxalexander/jquery-scrollspy/", + "description": "scrollspy is a simple jQuery plugin for firing events based on where the user has scrolled to in a page.", + "main": "jquery-scrollspy.min.js", + "keywords": [ + "scrolling", + "scroll" + ], + "license": "MIT", + "ignore": [ + ], + "dependencies": { + "jquery": ">=1.7.0" + }, + "devDependencies": { + } +} diff --git a/view/theme/frio/frameworks/jquery-scrollspy/gulpfile.js b/view/theme/frio/frameworks/jquery-scrollspy/gulpfile.js new file mode 100644 index 000000000..4c7563c5d --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/gulpfile.js @@ -0,0 +1,65 @@ +/* global require */ + +var gulp = require('gulp'); +var eslint = require('gulp-eslint'); +var gulpIf = require('gulp-if'); +var rename = require('gulp-rename'); +var uglify = require('gulp-uglify'); + +// Assets for the project +var Assets = { + main: './jquery-scrollspy.js', + minified: './jquery-scrollspy.min.js', + package: './package.json', + readme: './README.md', + source: './', +}; + +// See the uglify documentation for more details +var _uglifySettings = { + compress: { + comparisons: true, + conditionals: true, + /* jscs: disable */ + dead_code: true, + drop_console: true, + /* jscs: enable */ + unsafe: true, + unused: true, + }, +}; + +// Check the main js file(s) meets the following standards outlined in .eslintrc +gulp.task('eslint', function esLintTask() { + // Has ESLint fixed the file contents? + function isFixed(file) { + return file.eslint !== undefined && file.eslint !== null && file.eslint.fixed; + } + + return gulp.src(Assets.main) + .pipe(eslint({ + fix: true, + useEslintrc: '.eslintrc', + })) + .pipe(eslint.format()) + .pipe(gulpIf(isFixed, gulp.dest(Assets.source))); +}); + +// Uglify aka minify the main file +gulp.task('uglify', function uglifyTask() { + return gulp.src(Assets.main) + .pipe(uglify(_uglifySettings)) + .pipe(rename(Assets.minified)) + .pipe(gulp.dest(Assets.source)); +}); + +// Watch for changes to the main file +gulp.task('watch', function watchTask() { + gulp.watch(Assets.main, ['eslint', 'uglify']); +}); + +// Register the default task +gulp.task('default', ['eslint', 'uglify']); + +// 'gulp eslint' to check the syntax of the main js file(s) +// 'gulp uglify' to uglify the main file diff --git a/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.js b/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.js new file mode 100644 index 000000000..4fd4f53a6 --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.js @@ -0,0 +1,267 @@ +/* + * jQuery ScrollSpy Plugin + * Author: @sxalexander, softwarespot + * Licensed under the MIT license + */ +(function jQueryScrollspy(window, $) { + // Plugin Logic + + $.fn.extend({ + scrollspy: function scrollspy(options, action) { + // If the options parameter is a string, then assume it's an 'action', therefore swap the parameters around + if (_isString(options)) { + var tempOptions = action; + + // Set the action as the option parameter + action = options; + + // Set to be the reference action pointed to + options = tempOptions; + } + + // override the default options with those passed to the plugin + options = $.extend({}, _defaults, options); + + // sanitize the following option with the default value if the predicate fails + _sanitizeOption(options, _defaults, 'container', _isObject); + + // cache the jQuery object + var $container = $(options.container); + + // check if it's a valid jQuery selector + if ($container.length === 0) { + return this; + } + + // sanitize the following option with the default value if the predicate fails + _sanitizeOption(options, _defaults, 'namespace', _isString); + + // check if the action is set to DESTROY/destroy + if (_isString(action) && action.toUpperCase() === 'DESTROY') { + $container.off('scroll.' + options.namespace); + return this; + } + + // sanitize the following options with the default values if the predicates fails + _sanitizeOption(options, _defaults, 'buffer', $.isNumeric); + _sanitizeOption(options, _defaults, 'max', $.isNumeric); + _sanitizeOption(options, _defaults, 'min', $.isNumeric); + + // callbacks + _sanitizeOption(options, _defaults, 'onEnter', $.isFunction); + _sanitizeOption(options, _defaults, 'onLeave', $.isFunction); + _sanitizeOption(options, _defaults, 'onLeaveTop', $.isFunction); + _sanitizeOption(options, _defaults, 'onLeaveBottom', $.isFunction); + _sanitizeOption(options, _defaults, 'onTick', $.isFunction); + + if ($.isFunction(options.max)) { + options.max = options.max(); + } + + if ($.isFunction(options.min)) { + options.min = options.min(); + } + + // check if the mode is set to VERTICAL/vertical + var isVertical = window.String(options.mode).toUpperCase() === 'VERTICAL'; + + return this.each(function each() { + // cache this + var _this = this; + + // cache the jQuery object + var $element = $(_this); + + // count the number of times a container is entered + var enters = 0; + + // determine if the scroll is with inside the container + var inside = false; + + // count the number of times a container is left + var leaves = 0; + + // create a scroll listener for the container + $container.on('scroll.' + options.namespace, function onScroll() { + // cache the jQuery object + var $this = $(this); + + // create a position object literal + var position = { + top: $this.scrollTop(), + left: $this.scrollLeft(), + }; + + var containerHeight = $container.height(); + + var max = options.max; + + var min = options.min; + + var xAndY = isVertical ? position.top + options.buffer : position.left + options.buffer; + + if (max === 0) { + // get the maximum value based on either the height or the outer width + max = isVertical ? containerHeight : $container.outerWidth() + $element.outerWidth(); + } + + // if we have reached the minimum bound, though are below the max + if (xAndY >= min && xAndY <= max) { + // trigger the 'scrollEnter' event + if (!inside) { + inside = true; + enters++; + + // trigger the 'scrollEnter' event + $element.trigger('scrollEnter', { + position: position, + }); + + // call the 'onEnter' function + if (options.onEnter !== null) { + options.onEnter(_this, position); + } + } + + // trigger the 'scrollTick' event + $element.trigger('scrollTick', { + position: position, + inside: inside, + enters: enters, + leaves: leaves, + }); + + // call the 'onTick' function + if (options.onTick !== null) { + options.onTick(_this, position, inside, enters, leaves); + } + } else { + if (inside) { + inside = false; + leaves++; + + // trigger the 'scrollLeave' event + $element.trigger('scrollLeave', { + position: position, + leaves: leaves, + }); + + // call the 'onLeave' function + if (options.onLeave !== null) { + options.onLeave(_this, position); + } + + if (xAndY <= min) { + // trigger the 'scrollLeaveTop' event + $element.trigger('scrollLeaveTop', { + position: position, + leaves: leaves, + }); + + // call the 'onLeaveTop' function + if (options.onLeaveTop !== null) { + options.onLeaveTop(_this, position); + } + } else if (xAndY >= max) { + // trigger the 'scrollLeaveBottom' event + $element.trigger('scrollLeaveBottom', { + position: position, + leaves: leaves, + }); + + // call the 'onLeaveBottom' function + if (options.onLeaveBottom !== null) { + options.onLeaveBottom(_this, position); + } + } + } else { + // Idea taken from: http://stackoverflow.com/questions/5353934/check-if-element-is-visible-on-screen + var containerScrollTop = $container.scrollTop(); + + // Get the element height + var elementHeight = $element.height(); + + // Get the element offset + var elementOffsetTop = $element.offset().top; + + if ((elementOffsetTop < (containerHeight + containerScrollTop)) && (elementOffsetTop > (containerScrollTop - elementHeight))) { + // trigger the 'scrollView' event + $element.trigger('scrollView', { + position: position, + }); + + // call the 'onView' function + if (options.onView !== null) { + options.onView(_this, position); + } + } + } + } + }); + }); + }, + }); + + // Fields (Private) + + // Defaults + + // default options + var _defaults = { + // the offset to be applied to the left and top positions of the container + buffer: 0, + + // the element to apply the 'scrolling' event to (default window) + container: window, + + // the maximum value of the X or Y coordinate, depending on mode the selected + max: 0, + + // the maximum value of the X or Y coordinate, depending on mode the selected + min: 0, + + // whether to listen to the X (horizontal) or Y (vertical) scrolling + mode: 'vertical', + + // namespace to append to the 'scroll' event + namespace: 'scrollspy', + + // call the following callback function every time the user enters the min / max zone + onEnter: null, + + // call the following callback function every time the user leaves the min / max zone + onLeave: null, + + // call the following callback function every time the user leaves the top zone + onLeaveTop: null, + + // call the following callback function every time the user leaves the bottom zone + onLeaveBottom: null, + + // call the following callback function on each scroll event within the min and max parameters + onTick: null, + + // call the following callback function on each scroll event when the element is inside the viewable view port + onView: null, + }; + + // Methods (Private) + + // check if a value is an object datatype + function _isObject(value) { + return $.type(value) === 'object'; + } + + // check if a value is a string datatype with a length greater than zero when whitespace is stripped + function _isString(value) { + return $.type(value) === 'string' && $.trim(value).length > 0; + } + + // check if an option is correctly formatted using a predicate; otherwise, return the default value + function _sanitizeOption(options, defaults, property, predicate) { + // set the property to the default value if the predicate returned false + if (!predicate(options[property])) { + options[property] = defaults[property]; + } + } +}(window, window.jQuery)); diff --git a/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.min.js b/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.min.js new file mode 100644 index 000000000..2782536b3 --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.min.js @@ -0,0 +1 @@ +!function(e,n){function o(e){return"object"===n.type(e)}function i(e){return"string"===n.type(e)&&n.trim(e).length>0}function t(e,n,o,i){i(e[o])||(e[o]=n[o])}n.fn.extend({scrollspy:function(l,s){if(i(l)){var a=s;s=l,l=a}l=n.extend({},r,l),t(l,r,"container",o);var c=n(l.container);if(0===c.length)return this;if(t(l,r,"namespace",i),i(s)&&"DESTROY"===s.toUpperCase())return c.off("scroll."+l.namespace),this;t(l,r,"buffer",n.isNumeric),t(l,r,"max",n.isNumeric),t(l,r,"min",n.isNumeric),t(l,r,"onEnter",n.isFunction),t(l,r,"onLeave",n.isFunction),t(l,r,"onLeaveTop",n.isFunction),t(l,r,"onLeaveBottom",n.isFunction),t(l,r,"onTick",n.isFunction),n.isFunction(l.max)&&(l.max=l.max()),n.isFunction(l.min)&&(l.min=l.min());var u="VERTICAL"===e.String(l.mode).toUpperCase();return this.each(function(){var e=this,o=n(e),i=0,t=!1,r=0;c.on("scroll."+l.namespace,function(){var s=n(this),a={top:s.scrollTop(),left:s.scrollLeft()},f=c.height(),p=l.max,m=l.min,v=u?a.top+l.buffer:a.left+l.buffer;if(0===p&&(p=u?f:c.outerWidth()+o.outerWidth()),v>=m&&p>=v)t||(t=!0,i++,o.trigger("scrollEnter",{position:a}),null!==l.onEnter&&l.onEnter(e,a)),o.trigger("scrollTick",{position:a,inside:t,enters:i,leaves:r}),null!==l.onTick&&l.onTick(e,a,t,i,r);else if(t)t=!1,r++,o.trigger("scrollLeave",{position:a,leaves:r}),null!==l.onLeave&&l.onLeave(e,a),m>=v?(o.trigger("scrollLeaveTop",{position:a,leaves:r}),null!==l.onLeaveTop&&l.onLeaveTop(e,a)):v>=p&&(o.trigger("scrollLeaveBottom",{position:a,leaves:r}),null!==l.onLeaveBottom&&l.onLeaveBottom(e,a));else{var g=c.scrollTop(),L=o.height(),h=o.offset().top;f+g>h&&h>g-L&&(o.trigger("scrollView",{position:a}),null!==l.onView&&l.onView(e,a))}})})}});var r={buffer:0,container:e,max:0,min:0,mode:"vertical",namespace:"scrollspy",onEnter:null,onLeave:null,onLeaveTop:null,onLeaveBottom:null,onTick:null,onView:null}}(window,window.jQuery); \ No newline at end of file diff --git a/view/theme/frio/frameworks/jquery-scrollspy/package.json b/view/theme/frio/frameworks/jquery-scrollspy/package.json new file mode 100644 index 000000000..27ca19663 --- /dev/null +++ b/view/theme/frio/frameworks/jquery-scrollspy/package.json @@ -0,0 +1,21 @@ +{ + "name": "jquery-scrollspy", + "version": "1.0.0", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/softwarespot/jquery-scrollspy.git" + }, + "devDependencies": { + "del": "^2.1.0", + "eslint": "^2.5.1", + "eslint-config-airbnb": "^6.2.0", + "gulp": "^3.9.1", + "gulp-eslint": "^2.0.0", + "gulp-if": "^2.0.0", + "gulp-rename": "~1.2.2", + "gulp-replace": "^0.5.4", + "gulp-uglify": "^1.5.3", + "merge2": "^1.0.1" + } +} diff --git a/view/theme/frio/js/modal.js b/view/theme/frio/js/modal.js index f1efbd752..0a881f10f 100644 --- a/view/theme/frio/js/modal.js +++ b/view/theme/frio/js/modal.js @@ -19,7 +19,7 @@ $(document).ready(function(){ // restore cached jot at its hidden position ("#jot-content") $("#jot-content").append(jotcache); // clear the jotcache - jotcache = '' + jotcache = ''; }); // Add Colorbox for viewing Network page images @@ -50,7 +50,11 @@ $(document).ready(function(){ } }); - + // Navbar login + $("body").on("click", "#nav-login", function(e){ + e.preventDefault(); + Dialog.show(this.href, this.dataset.originalTitle || this.title); + }); // Jot nav menu. $("body").on("click", "#jot-modal .jot-nav li a", function(e){ @@ -60,7 +64,7 @@ $(document).ready(function(){ // Open filebrowser for elements with the class "image-select" // The following part handles the filebrowser for field_fileinput.tpl - $("body").on("click", ".image-select", function(e){ + $("body").on("click", ".image-select", function(){ // set a extra attribute to mark the clicked button this.setAttribute("image-input", "select"); Dialog.doImageBrowser("input"); @@ -69,7 +73,7 @@ $(document).ready(function(){ // Insert filebrowser images into the input field (field_fileinput.tpl) $("body").on("fbrowser.image.input", function(e, filename, embedcode, id, img) { // select the clicked button by it's attribute - var elm = $("[image-input='select']") + var elm = $("[image-input='select']"); // select the input field which belongs to this button var input = elm.parent(".input-group").children("input"); // remove the special indicator attribut from the button @@ -81,8 +85,9 @@ $(document).ready(function(){ }); // overwrite Dialog.show from main js to load the filebrowser into a bs modal -Dialog.show = function(url) { +Dialog.show = function(url, title="") { var modal = $('#modal').modal(); + modal.find("#modal-header h4").html(title); modal .find('#modal-body') .load(url, function (responseText, textStatus) { @@ -129,12 +134,13 @@ Dialog._load = function(url) { // try to fetch the hash form the url var match = url.match(/fbrowser\/[a-z]+\/\?mode=none(.*)/); + if (match===null) return; //not fbrowser var hash = match[1]; // initialize the filebrowser var jsbrowser = function() { FileBrowser.init(nickname, type, hash); - } + }; loadScript("view/theme/frio/js/filebrowser.js", jsbrowser); }; @@ -166,7 +172,7 @@ function loadModalTitle() { function addToModal(url) { var char = qOrAmp(url); - var url = url + char + 'mode=none'; + url = url + char + 'mode=none'; var modal = $('#modal').modal(); modal @@ -182,7 +188,7 @@ function addToModal(url) { loadModalTitle(); } }); -}; +} // function to load the html from the edit post page into // the jot modal @@ -201,7 +207,7 @@ function editpost(url) { } var modal = $('#jot-modal').modal(); - var url = url + " #profile-jot-form"; + url = url + " #profile-jot-form"; //var rand_num = random_digits(12); $(".jot-nav #jot-perms-lnk").parent("li").hide(); diff --git a/view/theme/frio/js/theme.js b/view/theme/frio/js/theme.js index 9be1b9456..45966e011 100644 --- a/view/theme/frio/js/theme.js +++ b/view/theme/frio/js/theme.js @@ -40,7 +40,7 @@ $(document).ready(function(){ $(".field.select > select, .field.custom > select").addClass("form-control"); // move the tabbar to the second nav bar - if( $("ul.tabbar")) { + if( $("ul.tabbar").length ) { $("ul.tabbar").appendTo("#topbar-second > .container > #tabmenu"); } @@ -50,7 +50,7 @@ $(document).ready(function(){ // to the friendica logo (the mask is in nav.tpl at the botom). To make it work we need to apply the // correct url. The only way which comes to my mind was to do this with js // So we apply the correct url (with the link to the id of the mask) after the page is loaded. - if($("#logo-img")) { + if($("#logo-img").length ) { var pageurl = "url('" + window.location.href + "#logo-mask')"; $("#logo-img").css({"mask": pageurl}); } @@ -66,7 +66,7 @@ $(document).ready(function(){ }); // add Jot botton to the scecond navbar - if( $("section #jotOpen")) { + if( $("section #jotOpen").length ) { $("section #jotOpen").appendTo("#topbar-second > .container > #navbar-button"); if( $("#jot-popup").is(":hidden")) $("#topbar-second > .container > #navbar-button #jotOpen").hide(); } @@ -94,13 +94,6 @@ $(document).ready(function(){ }); } }); - - // add search-heading to the scecond navbar - if( $(".search-heading")) { - $(".search-heading").appendTo("#topbar-second > .container > #tabmenu"); - } - - //$('ul.flex-nav').flexMenu(); @@ -120,7 +113,72 @@ $(document).ready(function(){ // initialize the bootstrap-select $('.selectpicker').selectpicker(); + // add search-heading to the seccond navbar + if( $(".search-heading").length) { + $(".search-heading").appendTo("#topbar-second > .container > #tabmenu"); + } + // add search results heading to the second navbar + // and insert the search value to the top nav search input + if( $(".search-content-wrapper").length ) { + // get the text of the heading (we catch the plain text because we don't + // want to have a h4 heading in the navbar + var searchText = $(".section-title-wrapper > h2").text(); + // insert the plain text in a

heading and give it a class + var newText = '

'+searchText+'

'; + // append the new heading to the navbar + $("#topbar-second > .container > #tabmenu").append(newText); + + // try to get the value of the original search input to insert it + // as value in the nav-search-input + var searchValue = $("#search-wrapper .form-group-search input").val(); + + // if the orignal search value isn't available use the location path as value + if( typeof searchValue === "undefined") { + // get the location path + var urlPath = window.location.search + // and split it up in its parts + var splitPath = urlPath.split(/(\?search?=)(.*$)/); + + if(typeof splitPath[2] !== 'undefined') { + // decode the path (e.g to decode %40 to the character @) + var searchValue = decodeURIComponent(splitPath[2]); + } + } + + if( typeof searchValue !== "undefined") { + $("#nav-search-input-field").val(searchValue); + } + } + + // move the "Save the search" button to the second navbar + $(".search-content-wrapper #search-save-form ").appendTo("#topbar-second > .container > #navbar-button"); + + // append the vcard-short-info to the second nav after passing the element + // with .p-addr (vcard). Use scrollspy to get the scroll position. + if( $("aside .vcard .p-addr").length) { + $(".vcard .p-addr").scrollspy({ + min: $(".vcard .p-addr").position().top - 50, + onLeaveTop: function onLeave(element) { + $("#vcard-short-info").fadeOut(500, function () { + $("#vcard-short-info").appendTo("#vcard-short-info-wrapper"); + }); + }, + onEnter: function(element) { + $("#vcard-short-info").appendTo("#nav-short-info"); + $("#vcard-short-info").fadeIn(500); + }, + }); + } + + // move the forum contact information of the network page into the second navbar + if( $(".network-content-wrapper > #viewcontact_wrapper-network").length) { + // get the contact-wrapper element and append it to the second nav bar + // Note: We need the first() element with this class since at the present time we + // store also the js template information in the html code and thats why + // there are two elements with this class but we don't want the js template + $(".network-content-wrapper > #viewcontact_wrapper-network .contact-wrapper").first().appendTo("#nav-short-info"); + } }); //function commentOpenUI(obj, id) { // $(document).unbind( "click.commentOpen", handler ); diff --git a/view/theme/frio/templates/field_openid.tpl b/view/theme/frio/templates/field_openid.tpl new file mode 100644 index 000000000..00520b06a --- /dev/null +++ b/view/theme/frio/templates/field_openid.tpl @@ -0,0 +1,7 @@ + +
+ + + {{$field.3}} +
+
\ No newline at end of file diff --git a/view/theme/frio/templates/field_password_1.tpl b/view/theme/frio/templates/field_password_1.tpl new file mode 100644 index 000000000..6bf16dacd --- /dev/null +++ b/view/theme/frio/templates/field_password_1.tpl @@ -0,0 +1,7 @@ + +
+ + + {{$field.3}} +
+
\ No newline at end of file diff --git a/view/theme/frio/templates/head.tpl b/view/theme/frio/templates/head.tpl index afdfaa785..57148736d 100644 --- a/view/theme/frio/templates/head.tpl +++ b/view/theme/frio/templates/head.tpl @@ -73,6 +73,7 @@ + {{* own js files *}} diff --git a/view/theme/frio/templates/login.tpl b/view/theme/frio/templates/login.tpl new file mode 100644 index 000000000..1615294c8 --- /dev/null +++ b/view/theme/frio/templates/login.tpl @@ -0,0 +1,40 @@ + + +
+
+ + +
{{$login}}
+ +
+ {{include file="field_input.tpl" field=$lname}} + {{include file="field_password.tpl" field=$lpassword}} +
+ + {{if $openid}} +
+ {{include file="field_openid.tpl" field=$lopenid}} +
+ {{/if}} + + {{include file="field_checkbox.tpl" field=$lremember}} + + + +
+ +
+
+ + {{foreach $hiddens as $k=>$v}} + + {{/foreach}} + +
+
+ + + diff --git a/view/theme/frio/templates/nav.tpl b/view/theme/frio/templates/nav.tpl index b8d5b2307..a72a29a38 100644 --- a/view/theme/frio/templates/nav.tpl +++ b/view/theme/frio/templates/nav.tpl @@ -27,7 +27,7 @@ Toggle navigation - @@ -240,17 +240,34 @@ + {{/if}} +{{* provide a a search input for mobile view, which expands by pressing the search icon *}} + + {{* The second navbar which contains nav points of the actual page - (nav points are actual handled by this theme throug js *}}
- +
diff --git a/view/theme/frio/templates/nav_head.tpl b/view/theme/frio/templates/nav_head.tpl index f00ff0355..d7b50a58d 100644 --- a/view/theme/frio/templates/nav_head.tpl +++ b/view/theme/frio/templates/nav_head.tpl @@ -1,6 +1,6 @@ diff --git a/view/theme/frio/templates/profile_vcard.tpl b/view/theme/frio/templates/profile_vcard.tpl index e0babdc3a..de448b82b 100644 --- a/view/theme/frio/templates/profile_vcard.tpl +++ b/view/theme/frio/templates/profile_vcard.tpl @@ -20,7 +20,19 @@
+ {{* The short information which will appended to the second navbar by scrollspy *}} +
diff --git a/view/theme/frio/templates/searchbox.tpl b/view/theme/frio/templates/searchbox.tpl index cc39ba6dc..8f6354b26 100644 --- a/view/theme/frio/templates/searchbox.tpl +++ b/view/theme/frio/templates/searchbox.tpl @@ -1,4 +1,7 @@ +{{* important notes: The frio theme hides under certain conditions some parts of the templates through css. +Some parts of this template will be moved by js to other places (see theme.js) - E.g. the save-search button}} +
@@ -15,7 +18,7 @@
{{* The button to save searches *}} {{if $savedsearch}} - + {{/if}} {{* The select popup menu to select what kind of results the user would like to search for *}} @@ -43,4 +46,9 @@
+ {{* This form is inserted as experiment to move the search-save button to the second navbar with js *}} +
+ + +
diff --git a/view/theme/frio/templates/vcard-widget.tpl b/view/theme/frio/templates/vcard-widget.tpl index e5aebecc8..472dced2b 100644 --- a/view/theme/frio/templates/vcard-widget.tpl +++ b/view/theme/frio/templates/vcard-widget.tpl @@ -6,6 +6,20 @@
{{$name}}
{{/if}} + {{* The short information which will appended to the second navbar by scrollspy *}} + +
{{$name}}
{{if $addr}}
{{$addr}}
{{/if}}