Browse Source

Improve scrolls behaviour

Migrate to nanoscroller 0.8.0
Fixed history scrollbar. Closes #341
Fixed mobile view infinite scroll. Closes #353
master
Igor Zhukov 10 years ago
parent
commit
afc066e3bc
  1. 40
      app/css/app.css
  2. 14
      app/css/app_mobile.css
  3. 37
      app/js/directives.js
  4. 2
      app/partials/contacts_modal.html
  5. 2
      app/partials/country_select_modal.html
  6. 4
      app/partials/im.html
  7. 2
      app/partials/peer_select.html
  8. 2
      app/partials/phonebook_modal.html
  9. 2
      app/vendor/jquery.emojiarea/jquery.emojiarea.js
  10. 24
      app/vendor/jquery.nanoscroller/nanoscroller.css
  11. 425
      app/vendor/jquery.nanoscroller/nanoscroller.js

40
app/css/app.css

@ -804,7 +804,7 @@ a.tg_radio_on:hover i.icon-radio { @@ -804,7 +804,7 @@ a.tg_radio_on:hover i.icon-radio {
}
.im_dialogs_col .nano > .pane {
.im_dialogs_col .nano > .nano-pane {
background : rgba(0,0,0,0.0);
width : 12px;
right: 0px;
@ -820,7 +820,7 @@ a.tg_radio_on:hover i.icon-radio { @@ -820,7 +820,7 @@ a.tg_radio_on:hover i.icon-radio {
-o-transition : none;
transition : none;
}
.im_dialogs_col .nano > .pane > .slider {
.im_dialogs_col .nano > .nano-pane > .nano-slider {
background: #A5B1B9;
margin: 0 5px;
-moz-border-radius : 0;
@ -1076,9 +1076,9 @@ a.im_dialog_selected .im_dialog_date { @@ -1076,9 +1076,9 @@ a.im_dialog_selected .im_dialog_date {
.im_history_col {
}
.im_history_col .nano > .pane,
.contacts_modal_col .nano > .pane,
.im_dialogs_modal_col .nano > .pane {
.im_history_col .nano > .nano-pane,
.contacts_modal_col .nano > .nano-pane,
.im_dialogs_modal_col .nano > .nano-pane {
background : rgba(3,36,64,0.08);
width : 9px;
right: 0;
@ -1097,12 +1097,12 @@ a.im_dialog_selected .im_dialog_date { @@ -1097,12 +1097,12 @@ a.im_dialog_selected .im_dialog_date {
transition : none;
}
.contacts_modal_col .nano > .pane {
.contacts_modal_col .nano > .nano-pane {
width: 6px;
right: 7px;
}
.im_dialogs_modal_col .nano > .pane {
.im_dialogs_modal_col .nano > .nano-pane {
width: 6px;
right: 2px;
}
@ -1110,13 +1110,13 @@ a.im_dialog_selected .im_dialog_date { @@ -1110,13 +1110,13 @@ a.im_dialog_selected .im_dialog_date {
padding: 0 12px 0 12px;
}
.im_history_col .nano > .pane {
.im_history_col .nano > .nano-pane {
top: 10px;
right: 8px;
}
.im_history_col .nano > .pane > .slider,
.contacts_modal_col .nano > .pane > .slider,
.im_dialogs_modal_col .nano > .pane > .slider {
.im_history_col .nano > .nano-pane > .nano-slider,
.contacts_modal_col .nano > .nano-pane > .nano-slider,
.im_dialogs_modal_col .nano > .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22);
margin: 0;
-moz-border-radius : 2px;
@ -1219,7 +1219,7 @@ a.im_dialog_selected .im_dialog_date { @@ -1219,7 +1219,7 @@ a.im_dialog_selected .im_dialog_date {
.im_history_wrap {
overflow: hidden;
/*overflow: hidden;*/
/*overflow-y: scroll;*/
}
.im_history_scrollable_wrap {
@ -1251,11 +1251,13 @@ a.im_dialog_selected .im_dialog_date { @@ -1251,11 +1251,13 @@ a.im_dialog_selected .im_dialog_date {
}
.im_history_typing_wrap {
margin-top: 13px;
height: 18px;
/*margin-top: 13px;*/
/*height: 18px;*/
line-height: 18px;
width: 100%;
margin-bottom: 13px;
height: 49px;
/*margin-bottom: 13px;*/
padding: 13px 0 18px;
overflow: hidden;
-webkit-user-select: none;
}
@ -2447,11 +2449,11 @@ img.chat_modal_participant_photo { @@ -2447,11 +2449,11 @@ img.chat_modal_participant_photo {
}
.emoji-menu .nano > .pane {
.emoji-menu .nano > .nano-pane {
background : rgba(255,255,255,0.0);
right: -2px;
}
.emoji-menu .nano > .pane > .slider {
.emoji-menu .nano > .nano-pane > .nano-slider {
background: #d1d1d1;
margin: 0 3px 0 4px;
}
@ -3261,7 +3263,7 @@ ce671b orange @@ -3261,7 +3263,7 @@ ce671b orange
padding: 14px 0;
}
.countries_modal_col .nano > .pane {
.countries_modal_col .nano > .nano-pane {
background : rgba(3,36,64,0.08);
width : 3px;
right: 6px;
@ -3274,7 +3276,7 @@ ce671b orange @@ -3274,7 +3276,7 @@ ce671b orange
-webkit-border-radius : 0;
border-radius : 0;
}
.countries_modal_col .nano > .pane > .slider {
.countries_modal_col .nano > .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22);
margin: 0;
-moz-border-radius : 0;

14
app/css/app_mobile.css

@ -135,7 +135,9 @@ html { @@ -135,7 +135,9 @@ html {
font-size: 14px;
color: #FFF;
white-space: nowrap;
max-width: 100px;
overflow: hidden;
text-overflow: ellipsis;
margin: 0;
}
.navbar-quick-media-back h4 {
@ -268,14 +270,14 @@ html { @@ -268,14 +270,14 @@ html {
margin: 0 5px;
padding-bottom: 18px;
}
.im_history_col .nano > .pane {
.im_history_col .nano > .nano-pane {
top: 3px;
right: 3px;
width: 6px;
}
.im_history_col .nano > .pane > .slider,
.contacts_modal_col .nano > .pane > .slider,
.im_dialogs_modal_col .nano > .pane > .slider {
.im_history_col .nano > .nano-pane > .nano-slider,
.contacts_modal_col .nano > .nano-pane > .nano-slider,
.im_dialogs_modal_col .nano > .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22);
border-radius: 3px;
margin: 0;
@ -305,11 +307,11 @@ html { @@ -305,11 +307,11 @@ html {
.im_dialogs_col {
margin-right: 0;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane {
.im_page_peer_not_selected .im_dialogs_col_wrap .nano-pane {
width: 6px;
right: 3px;
}
.im_page_peer_not_selected .im_dialogs_col_wrap .pane > .slider {
.im_page_peer_not_selected .im_dialogs_col_wrap .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22);
border-radius: 3px;
margin: 0;

37
app/js/directives.js

@ -254,6 +254,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -254,6 +254,7 @@ angular.module('myApp.directives', ['myApp.filters'])
});
$(scrollableWrap).on('scroll', function (e) {
if (!element.is(':visible')) return;
// console.log('scroll', moreNotified);
if (!moreNotified && scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight - 300) {
// console.log('emit need more');
@ -421,13 +422,16 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -421,13 +422,16 @@ angular.module('myApp.directives', ['myApp.filters'])
if (!atBottom && !options.my) {
return;
}
var curAnimated = animated && !$rootScope.idle.isIDLE,
var curAnimated = animated &&
!$rootScope.idle.isIDLE &&
historyMessagesEl.clientHeight > 0,
wasH;
if (!curAnimated) {
if (curAnimated) {
wasH = scrollableWrap.scrollHeight;
} else {
$(scrollable).css({bottom: 0});
$(scrollableWrap).addClass('im_history_to_bottom');
} else {
wasH = scrollableWrap.scrollHeight;
}
onContentLoaded(function () {
@ -450,7 +454,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -450,7 +454,6 @@ angular.module('myApp.directives', ['myApp.filters'])
$(scrollable).css({bottom: ''});
scrollableWrap.scrollTop = scrollableWrap.scrollHeight;
updateBottomizer();
$(historyWrap).nanoScroller();
}
});
});
@ -501,15 +504,16 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -501,15 +504,16 @@ angular.module('myApp.directives', ['myApp.filters'])
$scope.$on('ui_history_prepend', function () {
var sh = scrollableWrap.scrollHeight,
st = scrollableWrap.scrollTop,
pr = parseInt($(scrollableWrap).css('paddingRight')),
ch = scrollableWrap.clientHeight;
$(scrollableWrap).addClass('im_history_to_bottom');
scrollableWrap.scrollHeight; // Some strange Chrome bug workaround
$(scrollable).css({bottom: -(sh - st - ch)});
$(scrollable).css({bottom: -(sh - st - ch), marginLeft: -Math.ceil(pr / 2)});
onContentLoaded(function () {
$(scrollableWrap).removeClass('im_history_to_bottom');
$(scrollable).css({bottom: ''});
$(scrollable).css({bottom: '', marginLeft: ''});
scrollableWrap.scrollTop = st + scrollableWrap.scrollHeight - sh;
updateBottomizer();
@ -569,10 +573,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -569,10 +573,9 @@ angular.module('myApp.directives', ['myApp.filters'])
var atBottom = true;
$(scrollableWrap).on('scroll', function (e) {
if ($(scrollableWrap).hasClass('im_history_to_bottom')) {
return cancelEvent(e);
}
if (curAnimation) {
if (!element.is(':visible') ||
$(scrollableWrap).hasClass('im_history_to_bottom') ||
curAnimation) {
return;
}
atBottom = scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight;
@ -607,9 +610,6 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -607,9 +610,6 @@ angular.module('myApp.directives', ['myApp.filters'])
$(historyWrap).css({
height: historyH
});
$(historyEl).css({
minHeight: historyH - 44
});
updateBottomizer();
@ -626,8 +626,9 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -626,8 +626,9 @@ angular.module('myApp.directives', ['myApp.filters'])
function updateBottomizer () {
$(historyMessagesEl).css({marginTop: 0});
if (historyMessagesEl.offsetHeight > 0 && historyMessagesEl.offsetHeight <= scrollableWrap.offsetHeight) {
$(historyMessagesEl).css({marginTop: (scrollableWrap.offsetHeight - historyMessagesEl.offsetHeight - 20 - 44) + 'px'});
var marginTop = scrollableWrap.offsetHeight - historyMessagesEl.offsetHeight - 20 - 49;
if (historyMessagesEl.offsetHeight > 0 && marginTop > 0) {
$(historyMessagesEl).css({marginTop: marginTop});
}
$(historyWrap).nanoScroller();
}
@ -741,7 +742,8 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -741,7 +742,8 @@ angular.module('myApp.directives', ['myApp.filters'])
lastLength;
$(editorElement).on('keyup', function (e) {
var now = tsNow(),
length = (editorElement[richTextarea ? 'innerText' : 'value']).length;
length = (editorElement[richTextarea ? 'textContent' : 'value']).length;
if (now - lastTyping > 5000 && length != lastLength) {
lastTyping = now;
@ -1405,6 +1407,7 @@ angular.module('myApp.directives', ['myApp.filters']) @@ -1405,6 +1407,7 @@ angular.module('myApp.directives', ['myApp.filters'])
moreNotified = false;
$(scrollableWrap).on('scroll', function (e) {
if (!element.is(':visible')) return;
if (!moreNotified &&
scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight - 300) {
moreNotified = true;

2
app/partials/contacts_modal.html

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
<div my-contacts-list class="contacts_modal_col">
<div class="contacts_wrap nano" my-infinite-scroller>
<div class="contacts_scrollable_wrap content">
<div class="contacts_scrollable_wrap nano-content">
<ul class="contacts_modal_members_list nav nav-pills nav-stacked">

2
app/partials/country_select_modal.html

@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
<div class="countries_modal_col" my-countries-list>
<div class="countries_wrap nano" my-infinite-scroller>
<div class="countries_scrollable_wrap content">
<div class="countries_scrollable_wrap nano-content">
<ul class="countries_modal_members_list nav nav-pills nav-stacked">

4
app/partials/im.html

@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
<div my-dialogs-list class="im_dialogs_col">
<div class="im_dialogs_wrap nano">
<div class="im_dialogs_scrollable_wrap content">
<div class="im_dialogs_scrollable_wrap nano-content">
<div class="im_dialogs_empty_wrap" ng-if="isEmpty.contacts">
<h3 class="im_dialogs_empty_header">No contacts yet</h3>
@ -153,7 +153,7 @@ @@ -153,7 +153,7 @@
<div class="im_history_wrap nano">
<div class="im_history_scrollable_wrap content">
<div class="im_history_scrollable_wrap nano-content">
<div class="im_history_scrollable">
<div class="im_history" ng-class="{im_history_selectable: selectActions}">

2
app/partials/peer_select.html

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
</div>
<div my-dialogs-list modal="true" class="im_dialogs_modal_col">
<div class="im_dialogs_wrap nano">
<div class="im_dialogs_scrollable_wrap content">
<div class="im_dialogs_scrollable_wrap nano-content">
<ul class="nav nav-pills nav-stacked">
<li class="im_dialog_wrap" my-dialog dialog-message="dialogMessage" ng-repeat="dialogMessage in dialogs track by dialogMessage.peerID"></li>
</ul>

2
app/partials/phonebook_modal.html

@ -15,7 +15,7 @@ @@ -15,7 +15,7 @@
<div my-contacts-list class="contacts_modal_col">
<div class="contacts_wrap nano" my-infinite-scroller>
<div class="contacts_scrollable_wrap content">
<div class="contacts_scrollable_wrap nano-content">
<ul class="contacts_modal_members_list nav nav-pills nav-stacked">

2
app/vendor/jquery.emojiarea/jquery.emojiarea.js vendored

@ -488,7 +488,7 @@ @@ -488,7 +488,7 @@
'<td><a class="emoji-menu-tab icon-grid"></a></td>' +
'</tr></table>').appendTo(this.$itemsTailWrap);
this.$itemsWrap = $('<div class="emoji-items-wrap nano"></div>').appendTo(this.$itemsTailWrap);
this.$items = $('<div class="emoji-items content">').appendTo(this.$itemsWrap);
this.$items = $('<div class="emoji-items nano-content">').appendTo(this.$itemsWrap);
$('<div class="emoji-menu-tail">').appendTo(this.$menu);
/*! MODIFICATION END */

24
app/vendor/jquery.nanoscroller/nanoscroller.css vendored

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
height : 100%;
overflow : hidden;
}
.nano .content {
.nano > .nano-content {
position : absolute;
overflow : scroll;
overflow-x : hidden;
@ -14,23 +14,17 @@ @@ -14,23 +14,17 @@
bottom : 0;
left : 0;
}
.nano .content:focus {
.nano > .nano-content:focus {
outline: thin dotted;
}
.nano .content::-webkit-scrollbar {
.nano > .nano-content::-webkit-scrollbar {
visibility: hidden;
}
.has-scrollbar .content::-webkit-scrollbar {
.has-scrollbar > .nano-content::-webkit-scrollbar {
visibility: visible;
}
.nano .content::-moz-scrollbar {
visibility: hidden;
}
.has-scrollbar .content::-moz-scrollbar {
visibility: visible;
}
.nano > .pane {
background : rgba(0,0,0,.1);
.nano > .nano-pane {
background : rgba(0,0,0,.25);
position : absolute;
width : 10px;
right : 0;
@ -46,16 +40,16 @@ @@ -46,16 +40,16 @@
-webkit-border-radius : 5px;
border-radius : 5px;
}
.nano > .pane > .slider {
.nano > .nano-pane > .nano-slider {
background: #444;
background: rgba(0,0,0,.4);
background: rgba(0,0,0,.5);
position : relative;
margin : 0 1px;
-moz-border-radius : 3px;
-webkit-border-radius : 3px;
border-radius : 3px;
}
.nano:hover > .pane, .pane.active, .pane.flashed {
.nano:hover > .nano-pane, .nano-pane.active, .nano-pane.flashed {
visibility : visible\9; /* Target only IE7 and IE8 with this hack */
opacity : 0.99;
}

425
app/vendor/jquery.nanoscroller/nanoscroller.js vendored

@ -1,266 +1,266 @@ @@ -1,266 +1,266 @@
/*! nanoScrollerJS - v0.7.6 - 2013
/*! nanoScrollerJS - v0.8.0 - 2014
* http://jamesflorentino.github.com/nanoScrollerJS/
* Copyright (c) 2013 James Florentino; Licensed MIT */
* Copyright (c) 2014 James Florentino; Licensed MIT */
(function($, window, document) {
"use strict";
var BROWSER_IS_IE7, BROWSER_SCROLLBAR_WIDTH, DOMSCROLL, DOWN, DRAG, KEYDOWN, KEYUP, MOUSEDOWN, MOUSEMOVE, MOUSEUP, MOUSEWHEEL, NanoScroll, PANEDOWN, RESIZE, SCROLL, SCROLLBAR, TOUCHMOVE, UP, WHEEL, cAF, defaults, getBrowserScrollbarWidth, hasTransform, isFFWithBuggyScrollbar, rAF, transform, _elementStyle, _prefixStyle, _vendor;
defaults = {
/**
a classname for the pane element.
@property paneClass
@type String
@default 'pane'
*/
@default 'nano-pane'
*/
paneClass: 'nano-pane',
paneClass: 'pane',
/**
a classname for the slider element.
@property sliderClass
@type String
@default 'slider'
*/
@default 'nano-slider'
*/
sliderClass: 'nano-slider',
sliderClass: 'slider',
/**
a classname for the content element.
@property contentClass
@type String
@default 'content'
*/
@default 'nano-content'
*/
contentClass: 'nano-content',
contentClass: 'content',
/**
a setting to enable native scrolling in iOS devices.
@property iOSNativeScrolling
@type Boolean
@default false
*/
*/
iOSNativeScrolling: false,
/**
a setting to prevent the rest of the page being
scrolled when user scrolls the `.content` element.
@property preventPageScrolling
@type Boolean
@default false
*/
*/
preventPageScrolling: false,
/**
a setting to disable binding to the resize event.
@property disableResize
@type Boolean
@default false
*/
*/
disableResize: false,
/**
a setting to make the scrollbar always visible.
@property alwaysVisible
@type Boolean
@default false
*/
*/
alwaysVisible: false,
/**
a default timeout for the `flash()` method.
@property flashDelay
@type Number
@default 1500
*/
*/
flashDelay: 1500,
/**
a minimum height for the `.slider` element.
@property sliderMinHeight
@type Number
@default 20
*/
*/
sliderMinHeight: 20,
/**
a maximum height for the `.slider` element.
@property sliderMaxHeight
@type Number
@default null
*/
*/
sliderMaxHeight: null,
/**
an alternate document context.
@property documentContext
@type Document
@default null
*/
*/
documentContext: null,
/**
an alternate window context.
@property windowContext
@type Window
@default null
*/
*/
windowContext: null
};
/**
@property SCROLLBAR
@type String
@static
@final
@private
*/
*/
SCROLLBAR = 'scrollbar';
/**
@property SCROLL
@type String
@static
@final
@private
*/
*/
SCROLL = 'scroll';
/**
@property MOUSEDOWN
@type String
@final
@private
*/
*/
MOUSEDOWN = 'mousedown';
/**
@property MOUSEMOVE
@type String
@static
@final
@private
*/
*/
MOUSEMOVE = 'mousemove';
/**
@property MOUSEWHEEL
@type String
@final
@private
*/
*/
MOUSEWHEEL = 'mousewheel';
/**
@property MOUSEUP
@type String
@static
@final
@private
*/
*/
MOUSEUP = 'mouseup';
/**
@property RESIZE
@type String
@final
@private
*/
*/
RESIZE = 'resize';
/**
@property DRAG
@type String
@static
@final
@private
*/
*/
DRAG = 'drag';
/**
@property UP
@type String
@static
@final
@private
*/
*/
UP = 'up';
/**
@property PANEDOWN
@type String
@static
@final
@private
*/
*/
PANEDOWN = 'panedown';
/**
@property DOMSCROLL
@type String
@static
@final
@private
*/
*/
DOMSCROLL = 'DOMMouseScroll';
/**
@property DOWN
@type String
@static
@final
@private
*/
*/
DOWN = 'down';
/**
@property WHEEL
@type String
@static
@final
@private
*/
*/
WHEEL = 'wheel';
/**
@property KEYDOWN
@type String
@static
@final
@private
*/
*/
KEYDOWN = 'keydown';
/**
@property KEYUP
@type String
@static
@final
@private
*/
*/
KEYUP = 'keyup';
/**
@property TOUCHMOVE
@type String
@static
@final
@private
*/
*/
TOUCHMOVE = 'touchmove';
/**
@property BROWSER_IS_IE7
@type Boolean
@static
@final
@private
*/
*/
BROWSER_IS_IE7 = window.navigator.appName === 'Microsoft Internet Explorer' && /msie 7./i.test(window.navigator.appVersion) && window.ActiveXObject;
/**
@property BROWSER_SCROLLBAR_WIDTH
@type Number
@static
@default null
@private
*/
*/
BROWSER_SCROLLBAR_WIDTH = null;
rAF = window.requestAnimationFrame;
cAF = window.cancelAnimationFrame;
@ -288,14 +288,14 @@ @@ -288,14 +288,14 @@
};
transform = _prefixStyle('transform');
hasTransform = transform !== false;
/**
Returns browser's native scrollbar width
@method getBrowserScrollbarWidth
@return {Number} the scrollbar width in pixels
@static
@private
*/
*/
getBrowserScrollbarWidth = function() {
var outer, outerStyle, scrollbarWidth;
outer = document.createElement('div');
@ -323,13 +323,13 @@ @@ -323,13 +323,13 @@
}
return isOSXFF && +version > 23;
};
/**
@class NanoScroll
@param element {HTMLElement|Node} the main element
@param options {Object} nanoScroller's options
@constructor
*/
*/
NanoScroll = (function() {
function NanoScroll(el, options) {
this.el = el;
@ -341,6 +341,7 @@ @@ -341,6 +341,7 @@
this.$content = this.$el.children("." + options.contentClass);
this.$content.attr('tabindex', this.options.tabIndex || 0);
this.content = this.$content[0];
this.previousPosition = 0;
if (this.options.iOSNativeScrolling && (this.el.style.WebkitOverflowScrolling != null)) {
this.nativeScrolling();
} else {
@ -351,15 +352,15 @@ @@ -351,15 +352,15 @@
this.reset();
}
/**
Prevents the rest of the page being scrolled
when user scrolls the `.content` element.
when user scrolls the `.nano-content` element.
@method preventScrolling
@param event {Event}
@param direction {String} Scroll direction (up or down)
@private
*/
*/
NanoScroll.prototype.preventScrolling = function(e, direction) {
if (!this.isActive) {
@ -379,12 +380,12 @@ @@ -379,12 +380,12 @@
}
};
/**
Enable iOS native scrolling
@method nativeScrolling
@private
*/
*/
NanoScroll.prototype.nativeScrolling = function() {
this.$content.css({
@ -394,44 +395,48 @@ @@ -394,44 +395,48 @@
this.isActive = true;
};
/**
Updates those nanoScroller properties that
are related to current scrollbar position.
@method updateScrollValues
@private
*/
*/
NanoScroll.prototype.updateScrollValues = function() {
var content;
var content, direction;
content = this.content;
this.maxScrollTop = content.scrollHeight - content.clientHeight;
this.prevScrollTop = this.contentScrollTop || 0;
this.contentScrollTop = content.scrollTop;
direction = this.contentScrollTop > this.previousPosition ? "down" : this.contentScrollTop < this.previousPosition ? "up" : "same";
this.previousPosition = this.contentScrollTop;
if (direction !== "same") {
this.$el.trigger('update', {
position: this.contentScrollTop,
maximum: this.maxScrollTop,
direction: direction
});
}
if (!this.iOSNativeScrolling) {
// console.log(this.maxScrollTop, this.contentScrollTop, this.maxSliderTop, this.maxScrollTop);
// console.trace();
this.maxSliderTop = this.paneHeight - this.sliderHeight;
this.sliderTop = this.maxScrollTop === 0 ? 0 : this.contentScrollTop * this.maxSliderTop / this.maxScrollTop;
}
};
/**
Updates CSS styles for current scroll position.
Uses CSS 2d transfroms and `window.requestAnimationFrame` if available.
@method setOnScrollStyles
@private
*/
*/
NanoScroll.prototype.setOnScrollStyles = function() {
var cssValue,
_this = this;
var cssValue;
if (hasTransform) {
cssValue = {};
cssValue[transform] = "translate(0, " + this.sliderTop + "px)";
// console.log(this.sliderTop, cssValue, this.scrollRAF, rAF);
} else {
cssValue = {
top: this.sliderTop
@ -439,109 +444,122 @@ @@ -439,109 +444,122 @@
}
if (rAF) {
if (!this.scrollRAF) {
this.scrollRAF = rAF(function() {
// console.log('raf called', cssValue);
_this.scrollRAF = null;
_this.slider.css(cssValue);
});
this.scrollRAF = rAF((function(_this) {
return function() {
_this.scrollRAF = null;
_this.slider.css(cssValue);
};
})(this));
}
} else {
this.slider.css(cssValue);
}
};
/**
Creates event related methods
@method createEvents
@private
*/
*/
NanoScroll.prototype.createEvents = function() {
var _this = this;
this.events = {
down: function(e) {
_this.isBeingDragged = true;
_this.offsetY = e.pageY - _this.slider.offset().top;
_this.pane.addClass('active');
_this.doc.bind(MOUSEMOVE, _this.events[DRAG]).bind(MOUSEUP, _this.events[UP]);
return false;
},
drag: function(e) {
_this.sliderY = e.pageY - _this.$el.offset().top - _this.offsetY;
_this.scroll();
_this.updateScrollValues();
if (_this.contentScrollTop >= _this.maxScrollTop && _this.prevScrollTop !== _this.maxScrollTop) {
_this.$el.trigger('scrollend');
} else if (_this.contentScrollTop === 0 && _this.prevScrollTop !== 0) {
_this.$el.trigger('scrolltop');
}
return false;
},
up: function(e) {
_this.isBeingDragged = false;
_this.pane.removeClass('active');
_this.doc.unbind(MOUSEMOVE, _this.events[DRAG]).unbind(MOUSEUP, _this.events[UP]);
return false;
},
resize: function(e) {
_this.reset();
},
panedown: function(e) {
_this.sliderY = (e.offsetY || e.originalEvent.layerY) - (_this.sliderHeight * 0.5);
_this.scroll();
_this.events.down(e);
return false;
},
scroll: function(e) {
if (_this.isBeingDragged) {
return;
}
_this.updateScrollValues();
if (!_this.iOSNativeScrolling) {
_this.sliderY = _this.sliderTop;
_this.setOnScrollStyles();
}
if (e == null) {
return;
}
if (_this.contentScrollTop >= _this.maxScrollTop) {
if (_this.options.preventPageScrolling) {
_this.preventScrolling(e, DOWN);
}
if (_this.prevScrollTop !== _this.maxScrollTop) {
down: (function(_this) {
return function(e) {
_this.isBeingDragged = true;
_this.offsetY = e.pageY - _this.slider.offset().top;
_this.pane.addClass('active');
_this.doc.bind(MOUSEMOVE, _this.events[DRAG]).bind(MOUSEUP, _this.events[UP]);
return false;
};
})(this),
drag: (function(_this) {
return function(e) {
_this.sliderY = e.pageY - _this.$el.offset().top - _this.offsetY;
_this.scroll();
if (_this.contentScrollTop >= _this.maxScrollTop && _this.prevScrollTop !== _this.maxScrollTop) {
_this.$el.trigger('scrollend');
} else if (_this.contentScrollTop === 0 && _this.prevScrollTop !== 0) {
_this.$el.trigger('scrolltop');
}
} else if (_this.contentScrollTop === 0) {
if (_this.options.preventPageScrolling) {
_this.preventScrolling(e, UP);
return false;
};
})(this),
up: (function(_this) {
return function(e) {
_this.isBeingDragged = false;
_this.pane.removeClass('active');
_this.doc.unbind(MOUSEMOVE, _this.events[DRAG]).unbind(MOUSEUP, _this.events[UP]);
return false;
};
})(this),
resize: (function(_this) {
return function(e) {
_this.reset();
};
})(this),
panedown: (function(_this) {
return function(e) {
_this.sliderY = (e.offsetY || e.originalEvent.layerY) - (_this.sliderHeight * 0.5);
_this.scroll();
_this.events.down(e);
return false;
};
})(this),
scroll: (function(_this) {
return function(e) {
_this.updateScrollValues();
if (_this.isBeingDragged) {
return;
}
if (_this.prevScrollTop !== 0) {
_this.$el.trigger('scrolltop');
if (!_this.iOSNativeScrolling) {
_this.sliderY = _this.sliderTop;
_this.setOnScrollStyles();
}
}
},
wheel: function(e) {
var delta;
if (e == null) {
return;
}
delta = e.delta || e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail || (e.originalEvent && -e.originalEvent.detail);
if (delta) {
_this.sliderY += -delta / 3;
}
_this.scroll();
return false;
}
if (e == null) {
return;
}
if (_this.contentScrollTop >= _this.maxScrollTop) {
if (_this.options.preventPageScrolling) {
_this.preventScrolling(e, DOWN);
}
if (_this.prevScrollTop !== _this.maxScrollTop) {
_this.$el.trigger('scrollend');
}
} else if (_this.contentScrollTop === 0) {
if (_this.options.preventPageScrolling) {
_this.preventScrolling(e, UP);
}
if (_this.prevScrollTop !== 0) {
_this.$el.trigger('scrolltop');
}
}
};
})(this),
wheel: (function(_this) {
return function(e) {
var delta;
if (e == null) {
return;
}
delta = e.delta || e.wheelDelta || (e.originalEvent && e.originalEvent.wheelDelta) || -e.detail || (e.originalEvent && -e.originalEvent.detail);
if (delta) {
_this.sliderY += -delta / 3;
}
_this.scroll();
return false;
};
})(this)
};
};
/**
Adds event listeners with jQuery.
@method addEvents
@private
*/
*/
NanoScroll.prototype.addEvents = function() {
var events;
@ -557,12 +575,12 @@ @@ -557,12 +575,12 @@
this.$content.bind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
};
/**
Removes event listeners with jQuery.
@method removeEvents
@private
*/
*/
NanoScroll.prototype.removeEvents = function() {
var events;
@ -575,19 +593,19 @@ @@ -575,19 +593,19 @@
this.$content.unbind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
};
/**
Generates nanoScroller's scrollbar and elements for it.
@method generate
@chainable
@private
*/
*/
NanoScroll.prototype.generate = function() {
var contentClass, cssRule, currentPadding, options, paneClass, sliderClass;
var contentClass, cssRule, currentPadding, options, pane, paneClass, sliderClass;
options = this.options;
paneClass = options.paneClass, sliderClass = options.sliderClass, contentClass = options.contentClass;
if (!this.$el.find("." + paneClass).length && !this.$el.find("." + sliderClass).length) {
if (!(pane = this.$el.children("." + paneClass)).length && !pane.children("." + sliderClass).length) {
this.$el.append("<div class=\"" + paneClass + "\"><div class=\"" + sliderClass + "\" /></div>");
}
this.pane = this.$el.children("." + paneClass);
@ -610,11 +628,11 @@ @@ -610,11 +628,11 @@
return this;
};
/**
@method restore
@private
*/
*/
NanoScroll.prototype.restore = function() {
this.stopped = false;
@ -624,17 +642,17 @@ @@ -624,17 +642,17 @@
this.addEvents();
};
/**
Resets nanoScroller's scrollbar.
@method reset
@chainable
@example
$(".nano").nanoScroller();
*/
*/
NanoScroll.prototype.reset = function() {
var content, contentHeight, contentStyle, contentStyleOverflowY, paneBottom, paneHeight, paneOuterHeight, paneTop, parentMaxHeight, sliderHeight;
var content, contentHeight, contentPosition, contentStyle, contentStyleOverflowY, paneBottom, paneHeight, paneOuterHeight, paneTop, parentMaxHeight, right, sliderHeight;
if (this.iOSNativeScrolling) {
this.contentHeight = this.content.scrollHeight;
return;
@ -693,16 +711,26 @@ @@ -693,16 +711,26 @@
opacity: (this.options.alwaysVisible ? 1 : ''),
visibility: (this.options.alwaysVisible ? 'visible' : '')
});
contentPosition = this.$content.css('position');
if (contentPosition === 'static' || contentPosition === 'relative') {
right = parseInt(this.$content.css('right'), 10);
if (right) {
this.$content.css({
right: '',
marginRight: right
});
}
}
return this;
};
/**
@method scroll
@private
@example
$(".nano").nanoScroller({ scroll: 'top' });
*/
*/
NanoScroll.prototype.scroll = function() {
if (!this.isActive) {
@ -718,6 +746,7 @@ @@ -718,6 +746,7 @@
return this;
};
/**
Scroll at the bottom with an offset value
@method scrollBottom
@ -725,18 +754,18 @@ @@ -725,18 +754,18 @@
@chainable
@example
$(".nano").nanoScroller({ scrollBottom: value });
*/
*/
NanoScroll.prototype.scrollBottom = function(offsetY) {
if (!this.isActive) {
return;
}
this.reset();
this.$content.scrollTop(this.contentHeight - this.$content.height() - offsetY).trigger(MOUSEWHEEL);
this.stop().restore();
return this;
};
/**
Scroll at the top with an offset value
@method scrollTop
@ -744,18 +773,18 @@ @@ -744,18 +773,18 @@
@chainable
@example
$(".nano").nanoScroller({ scrollTop: value });
*/
*/
NanoScroll.prototype.scrollTop = function(offsetY) {
if (!this.isActive) {
return;
}
this.reset();
this.$content.scrollTop(+offsetY).trigger(MOUSEWHEEL);
this.stop().restore();
return this;
};
/**
Scroll to an element
@method scrollTo
@ -763,18 +792,17 @@ @@ -763,18 +792,17 @@
@chainable
@example
$(".nano").nanoScroller({ scrollTo: $('#a_node') });
*/
*/
NanoScroll.prototype.scrollTo = function(node) {
if (!this.isActive) {
return;
}
this.reset();
this.scrollTop($(node).get(0).offsetTop);
this.scrollTop(this.$el.find(node).get(0).offsetTop);
return this;
};
/**
To stop the operation.
This option will tell the plugin to disable all event bindings and hide the gadget scrollbar from the UI.
@ -782,12 +810,12 @@ @@ -782,12 +810,12 @@
@chainable
@example
$(".nano").nanoScroller({ stop: true });
*/
*/
NanoScroll.prototype.stop = function() {
if (cAF) {
if (cAF && this.scrollRAF) {
cAF(this.scrollRAF);
this.scrollRAF = null;
}
this.stopped = true;
this.removeEvents();
@ -797,14 +825,14 @@ @@ -797,14 +825,14 @@
return this;
};
/**
Destroys nanoScroller and restores browser's native scrollbar.
@method destroy
@chainable
@example
$(".nano").nanoScroller({ destroy: true });
*/
*/
NanoScroll.prototype.destroy = function() {
if (!this.stopped) {
@ -826,6 +854,7 @@ @@ -826,6 +854,7 @@
return this;
};
/**
To flash the scrollbar gadget for an amount of time defined in plugin settings (defaults to 1,5s).
Useful if you want to show the user (e.g. on pageload) that there is more content waiting for him.
@ -833,11 +862,9 @@ @@ -833,11 +862,9 @@
@chainable
@example
$(".nano").nanoScroller({ flash: true });
*/
*/
NanoScroll.prototype.flash = function() {
var _this = this;
if (this.iOSNativeScrolling) {
return;
}
@ -846,9 +873,11 @@ @@ -846,9 +873,11 @@
}
this.reset();
this.pane.addClass('flashed');
setTimeout(function() {
_this.pane.removeClass('flashed');
}, this.options.flashDelay);
setTimeout((function(_this) {
return function() {
_this.pane.removeClass('flashed');
};
})(this), this.options.flashDelay);
return this;
};

Loading…
Cancel
Save