frio: a short contact informations will be provided at the second nav bar by scrolling down (on pages where vcard is available)

This commit is contained in:
rabuzarus 2016-06-11 01:28:25 +02:00
parent 710822dca7
commit 53fb8b1181
12 changed files with 652 additions and 1 deletions

View file

@ -941,6 +941,51 @@ aside .vcard #dfrn-request-link,
aside .vcard #wallmessage-link { aside .vcard #wallmessage-link {
width: 100%; width: 100%;
} }
/* vcard-short-info */
#vcard-short-info,
#nav-short-info .contact-wrapper {
margin-top: 3px;
height: 40px;
white-space: nowrap;
overflow: hidden;
padding-right: 20px;
}
#vcard-short-photo-wrapper img,
#nav-short-info .contact-wrapper img {
height: 34px;
width: 34px;
}
#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;
}
#nav-short-info .contact-wrapper #contact-entry-url-network {
color: #777;
}
.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 #peoplefind-sidebar input,
aside #follow-sidebar input { aside #follow-sidebar input {

View file

@ -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 `<head>` section, e.g.:
```html
<script src="jquery.min.js"></script>
<script src="jquery.scrollspy.min.js"></script>
```
2. Initialise ScrollSpy once the DOM has been loaded:
```javascript
<script>
$(function() {
var $nav = $('#nav');
$('#sticky-navigation').scrollspy({
min: $nav.offset().top,
onEnter: function(element, position) {
$nav.addClass('fixed');
},
onLeave: function(element, position) {
$nav.removeClass('fixed');
}
});
});
</script>
```
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
```

View file

@ -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": {
}
}

View file

@ -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

View file

@ -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));

View file

@ -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);

View file

@ -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"
}
}

View file

@ -120,7 +120,31 @@ $(document).ready(function(){
// initialize the bootstrap-select // initialize the bootstrap-select
$('.selectpicker').selectpicker(); $('.selectpicker').selectpicker();
// 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").appendTo("#vcard-short-info-wrapper");
$("#vcard-short-info").fadeOut(500);
},
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) { //function commentOpenUI(obj, id) {
// $(document).unbind( "click.commentOpen", handler ); // $(document).unbind( "click.commentOpen", handler );

View file

@ -73,6 +73,7 @@
<script type="text/javascript" src="view/theme/frio/frameworks/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js"></script> <script type="text/javascript" src="view/theme/frio/frameworks/bootstrap-colorpicker/js/bootstrap-colorpicker.min.js"></script>
<script type="text/javascript" src="view/theme/frio/frameworks/flexMenu/flexmenu.custom.js"></script> <script type="text/javascript" src="view/theme/frio/frameworks/flexMenu/flexmenu.custom.js"></script>
<script type="text/javascript" src="view/theme/frio/frameworks/jsmart/jsmart.custom.js"></script> <script type="text/javascript" src="view/theme/frio/frameworks/jsmart/jsmart.custom.js"></script>
<script type="text/javascript" src="view/theme/frio/frameworks/jquery-scrollspy/jquery-scrollspy.js"></script>
{{* own js files *}} {{* own js files *}}
<script type="text/javascript" src="view/theme/frio/js/theme.js"></script> <script type="text/javascript" src="view/theme/frio/js/theme.js"></script>

View file

@ -250,7 +250,7 @@
{{* The second navbar which contains nav points of the actual page - (nav points are actual handled by this theme throug js *}} {{* The second navbar which contains nav points of the actual page - (nav points are actual handled by this theme throug js *}}
<div id="topbar-second" class="topbar"> <div id="topbar-second" class="topbar">
<div class="container"> <div class="container">
<div class="col-lg-3 col-md-3 hidden-sm hidden-xs"></div> <div class="col-lg-3 col-md-3 hidden-sm hidden-xs" id="nav-short-info"></div>
<div class="col-lg-7 col-md-7 col-sm-11 col-xs-10" id="tabmenu"></div> <div class="col-lg-7 col-md-7 col-sm-11 col-xs-10" id="tabmenu"></div>
<div class="col-lg-2 col-md-2 col-sm-1 col-xs-2" id="navbar-button"></div> <div class="col-lg-2 col-md-2 col-sm-1 col-xs-2" id="navbar-button"></div>
</div> </div>

View file

@ -20,7 +20,19 @@
</div> </div>
{{* The short information which will appended to the second navbar by scrollspy *}}
<div id="vcard-short-info-wrapper" style="display: none;">
<div id="vcard-short-info" class="media" style="display: none">
<div id="vcard-short-photo-wrapper" class="pull-left">
<img class="media-object" src="{{$profile.photo}}" alt="{{$profile.name}}" />
</div>
<div id="vcard-short-desc" class="media-body">
<h4 class="media-heading">{{$profile.name}}</h4>
{{if $profile.addr}}<div class="vcard-short-addr">{{$profile.addr}}</div>{{/if}}
</div>
</div>
</div>
<div class="panel-body"> <div class="panel-body">
<div class="profile-header"> <div class="profile-header">

View file

@ -6,6 +6,20 @@
<div id="profile-photo-wrapper" class="thumbnail"><img class="vcard-photo photo" src="{{$photo}}" alt="{{$name}}" /></div> <div id="profile-photo-wrapper" class="thumbnail"><img class="vcard-photo photo" src="{{$photo}}" alt="{{$name}}" /></div>
{{/if}} {{/if}}
{{* The short information which will appended to the second navbar by scrollspy *}}
<div id="vcard-short-info-wrapper" style="display: none;">
<div id="vcard-short-info" class="media" style="display: none">
<div id="vcard-short-photo-wrapper" class="pull-left">
<img class="media-object" src="{{$photo}}" alt="{{$name}}" />
</div>
<div id="vcard-short-desc" class="media-body">
<h4 class="media-heading">{{$name}}</h4>
{{if $addr}}<div class="vcard-short-addr">{{$addr}}</div>{{/if}}
</div>
</div>
</div>
<div class="panel-body"> <div class="panel-body">
<div class="fn">{{$name}}</div> <div class="fn">{{$name}}</div>
{{if $addr}}<div class="p-addr">{{$addr}}</div>{{/if}} {{if $addr}}<div class="p-addr">{{$addr}}</div>{{/if}}