Improve scrolls behaviour
Migrate to nanoscroller 0.8.0 Fixed history scrollbar. Closes #341 Fixed mobile view infinite scroll. Closes #353
This commit is contained in:
parent
bafab6e250
commit
afc066e3bc
@ -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 {
|
||||
-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 {
|
||||
.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 {
|
||||
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 {
|
||||
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 {
|
||||
|
||||
|
||||
.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 {
|
||||
}
|
||||
|
||||
.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 {
|
||||
}
|
||||
|
||||
|
||||
.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
|
||||
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
|
||||
-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;
|
||||
|
@ -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 {
|
||||
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 {
|
||||
.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;
|
||||
|
@ -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'])
|
||||
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'])
|
||||
$(scrollable).css({bottom: ''});
|
||||
scrollableWrap.scrollTop = scrollableWrap.scrollHeight;
|
||||
updateBottomizer();
|
||||
$(historyWrap).nanoScroller();
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -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'])
|
||||
|
||||
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'])
|
||||
$(historyWrap).css({
|
||||
height: historyH
|
||||
});
|
||||
$(historyEl).css({
|
||||
minHeight: historyH - 44
|
||||
});
|
||||
|
||||
updateBottomizer();
|
||||
|
||||
@ -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'])
|
||||
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'])
|
||||
moreNotified = false;
|
||||
|
||||
$(scrollableWrap).on('scroll', function (e) {
|
||||
if (!element.is(':visible')) return;
|
||||
if (!moreNotified &&
|
||||
scrollableWrap.scrollTop >= scrollableWrap.scrollHeight - scrollableWrap.clientHeight - 300) {
|
||||
moreNotified = true;
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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 @@
|
||||
|
||||
<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}">
|
||||
|
@ -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>
|
||||
|
@ -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">
|
||||
|
||||
|
@ -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
24
app/vendor/jquery.nanoscroller/nanoscroller.css
vendored
@ -5,7 +5,7 @@
|
||||
height : 100%;
|
||||
overflow : hidden;
|
||||
}
|
||||
.nano .content {
|
||||
.nano > .nano-content {
|
||||
position : absolute;
|
||||
overflow : scroll;
|
||||
overflow-x : hidden;
|
||||
@ -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 @@
|
||||
-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;
|
||||
}
|
215
app/vendor/jquery.nanoscroller/nanoscroller.js
vendored
215
app/vendor/jquery.nanoscroller/nanoscroller.js
vendored
@ -1,42 +1,43 @@
|
||||
/*! 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.
|
||||
@ -44,65 +45,65 @@
|
||||
@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
|
||||
@ -110,8 +111,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
SCROLLBAR = 'scrollbar';
|
||||
|
||||
/**
|
||||
@property SCROLL
|
||||
@type String
|
||||
@ -119,16 +120,16 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
SCROLL = 'scroll';
|
||||
|
||||
/**
|
||||
@property MOUSEDOWN
|
||||
@type String
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
MOUSEDOWN = 'mousedown';
|
||||
|
||||
/**
|
||||
@property MOUSEMOVE
|
||||
@type String
|
||||
@ -136,16 +137,16 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
MOUSEMOVE = 'mousemove';
|
||||
|
||||
/**
|
||||
@property MOUSEWHEEL
|
||||
@type String
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
MOUSEWHEEL = 'mousewheel';
|
||||
|
||||
/**
|
||||
@property MOUSEUP
|
||||
@type String
|
||||
@ -153,16 +154,16 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
MOUSEUP = 'mouseup';
|
||||
|
||||
/**
|
||||
@property RESIZE
|
||||
@type String
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
RESIZE = 'resize';
|
||||
|
||||
/**
|
||||
@property DRAG
|
||||
@type String
|
||||
@ -170,8 +171,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
DRAG = 'drag';
|
||||
|
||||
/**
|
||||
@property UP
|
||||
@type String
|
||||
@ -179,8 +180,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
UP = 'up';
|
||||
|
||||
/**
|
||||
@property PANEDOWN
|
||||
@type String
|
||||
@ -188,8 +189,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
PANEDOWN = 'panedown';
|
||||
|
||||
/**
|
||||
@property DOMSCROLL
|
||||
@type String
|
||||
@ -197,8 +198,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
DOMSCROLL = 'DOMMouseScroll';
|
||||
|
||||
/**
|
||||
@property DOWN
|
||||
@type String
|
||||
@ -206,8 +207,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
DOWN = 'down';
|
||||
|
||||
/**
|
||||
@property WHEEL
|
||||
@type String
|
||||
@ -215,8 +216,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
WHEEL = 'wheel';
|
||||
|
||||
/**
|
||||
@property KEYDOWN
|
||||
@type String
|
||||
@ -224,8 +225,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
KEYDOWN = 'keydown';
|
||||
|
||||
/**
|
||||
@property KEYUP
|
||||
@type String
|
||||
@ -233,8 +234,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
KEYUP = 'keyup';
|
||||
|
||||
/**
|
||||
@property TOUCHMOVE
|
||||
@type String
|
||||
@ -242,8 +243,8 @@
|
||||
@final
|
||||
@private
|
||||
*/
|
||||
|
||||
TOUCHMOVE = 'touchmove';
|
||||
|
||||
/**
|
||||
@property BROWSER_IS_IE7
|
||||
@type Boolean
|
||||
@ -251,8 +252,8 @@
|
||||
@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
|
||||
@ -260,7 +261,6 @@
|
||||
@default null
|
||||
@private
|
||||
*/
|
||||
|
||||
BROWSER_SCROLLBAR_WIDTH = null;
|
||||
rAF = window.requestAnimationFrame;
|
||||
cAF = window.cancelAnimationFrame;
|
||||
@ -288,6 +288,7 @@
|
||||
};
|
||||
transform = _prefixStyle('transform');
|
||||
hasTransform = transform !== false;
|
||||
|
||||
/**
|
||||
Returns browser's native scrollbar width
|
||||
@method getBrowserScrollbarWidth
|
||||
@ -295,7 +296,6 @@
|
||||
@static
|
||||
@private
|
||||
*/
|
||||
|
||||
getBrowserScrollbarWidth = function() {
|
||||
var outer, outerStyle, scrollbarWidth;
|
||||
outer = document.createElement('div');
|
||||
@ -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 @@
|
||||
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,16 +352,16 @@
|
||||
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) {
|
||||
return;
|
||||
@ -379,13 +380,13 @@
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Enable iOS native scrolling
|
||||
@method nativeScrolling
|
||||
@private
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.nativeScrolling = function() {
|
||||
this.$content.css({
|
||||
WebkitOverflowScrolling: 'touch'
|
||||
@ -394,6 +395,7 @@
|
||||
this.isActive = true;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Updates those nanoScroller properties that
|
||||
are related to current scrollbar position.
|
||||
@ -401,21 +403,28 @@
|
||||
@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.
|
||||
@ -423,15 +432,11 @@
|
||||
@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,65 +444,75 @@
|
||||
}
|
||||
if (rAF) {
|
||||
if (!this.scrollRAF) {
|
||||
this.scrollRAF = rAF(function() {
|
||||
// console.log('raf called', 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) {
|
||||
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;
|
||||
},
|
||||
drag: function(e) {
|
||||
};
|
||||
})(this),
|
||||
drag: (function(_this) {
|
||||
return 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),
|
||||
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;
|
||||
},
|
||||
resize: function(e) {
|
||||
};
|
||||
})(this),
|
||||
resize: (function(_this) {
|
||||
return function(e) {
|
||||
_this.reset();
|
||||
},
|
||||
panedown: function(e) {
|
||||
};
|
||||
})(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;
|
||||
},
|
||||
scroll: function(e) {
|
||||
};
|
||||
})(this),
|
||||
scroll: (function(_this) {
|
||||
return function(e) {
|
||||
_this.updateScrollValues();
|
||||
if (_this.isBeingDragged) {
|
||||
return;
|
||||
}
|
||||
_this.updateScrollValues();
|
||||
if (!_this.iOSNativeScrolling) {
|
||||
_this.sliderY = _this.sliderTop;
|
||||
_this.setOnScrollStyles();
|
||||
@ -520,8 +535,10 @@
|
||||
_this.$el.trigger('scrolltop');
|
||||
}
|
||||
}
|
||||
},
|
||||
wheel: function(e) {
|
||||
};
|
||||
})(this),
|
||||
wheel: (function(_this) {
|
||||
return function(e) {
|
||||
var delta;
|
||||
if (e == null) {
|
||||
return;
|
||||
@ -532,17 +549,18 @@
|
||||
}
|
||||
_this.scroll();
|
||||
return false;
|
||||
}
|
||||
};
|
||||
})(this)
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Adds event listeners with jQuery.
|
||||
@method addEvents
|
||||
@private
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.addEvents = function() {
|
||||
var events;
|
||||
this.removeEvents();
|
||||
@ -557,13 +575,13 @@
|
||||
this.$content.bind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Removes event listeners with jQuery.
|
||||
@method removeEvents
|
||||
@private
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.removeEvents = function() {
|
||||
var events;
|
||||
events = this.events;
|
||||
@ -575,6 +593,7 @@
|
||||
this.$content.unbind("" + SCROLL + " " + MOUSEWHEEL + " " + DOMSCROLL + " " + TOUCHMOVE, events[SCROLL]);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Generates nanoScroller's scrollbar and elements for it.
|
||||
@method generate
|
||||
@ -582,12 +601,11 @@
|
||||
@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,12 +628,12 @@
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
@method restore
|
||||
@private
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.restore = function() {
|
||||
this.stopped = false;
|
||||
if (!this.iOSNativeScrolling) {
|
||||
@ -624,6 +642,7 @@
|
||||
this.addEvents();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Resets nanoScroller's scrollbar.
|
||||
@method reset
|
||||
@ -632,9 +651,8 @@
|
||||
$(".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,9 +711,20 @@
|
||||
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
|
||||
@ -703,7 +732,6 @@
|
||||
$(".nano").nanoScroller({ scroll: 'top' });
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.scroll = function() {
|
||||
if (!this.isActive) {
|
||||
return;
|
||||
@ -718,6 +746,7 @@
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Scroll at the bottom with an offset value
|
||||
@method scrollBottom
|
||||
@ -727,16 +756,16 @@
|
||||
$(".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
|
||||
@ -746,16 +775,16 @@
|
||||
$(".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
|
||||
@ -765,16 +794,15 @@
|
||||
$(".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.
|
||||
@ -784,10 +812,10 @@
|
||||
$(".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,6 +825,7 @@
|
||||
return this;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Destroys nanoScroller and restores browser's native scrollbar.
|
||||
@method destroy
|
||||
@ -805,7 +834,6 @@
|
||||
$(".nano").nanoScroller({ destroy: true });
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.destroy = function() {
|
||||
if (!this.stopped) {
|
||||
this.stop();
|
||||
@ -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.
|
||||
@ -835,9 +864,7 @@
|
||||
$(".nano").nanoScroller({ flash: true });
|
||||
*/
|
||||
|
||||
|
||||
NanoScroll.prototype.flash = function() {
|
||||
var _this = this;
|
||||
if (this.iOSNativeScrolling) {
|
||||
return;
|
||||
}
|
||||
@ -846,9 +873,11 @@
|
||||
}
|
||||
this.reset();
|
||||
this.pane.addClass('flashed');
|
||||
setTimeout(function() {
|
||||
setTimeout((function(_this) {
|
||||
return function() {
|
||||
_this.pane.removeClass('flashed');
|
||||
}, this.options.flashDelay);
|
||||
};
|
||||
})(this), this.options.flashDelay);
|
||||
return this;
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user