pushpop-rails 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +42 -0
- data/Rakefile +29 -0
- data/lib/generators/pushpop/install/install_generator.rb +17 -0
- data/lib/pushpop-rails.rb +4 -0
- data/lib/pushpop/rails.rb +8 -0
- data/lib/pushpop/rails/engine.rb +7 -0
- data/lib/pushpop/rails/version.rb +5 -0
- data/vendor/assets/Pushpop/background.png +0 -0
- data/vendor/assets/Pushpop/background@2x.png +0 -0
- data/vendor/assets/Pushpop/externals/scrollkit/background.png +0 -0
- data/vendor/assets/Pushpop/externals/scrollkit/scrollkit.css +202 -0
- data/vendor/assets/Pushpop/externals/scrollkit/scrollkit.js +924 -0
- data/vendor/assets/Pushpop/font/pushpop-glyphs-webfont.eot +0 -0
- data/vendor/assets/Pushpop/font/pushpop-glyphs-webfont.svg +57 -0
- data/vendor/assets/Pushpop/font/pushpop-glyphs-webfont.ttf +0 -0
- data/vendor/assets/Pushpop/font/pushpop-glyphs-webfont.woff +0 -0
- data/vendor/assets/Pushpop/pushpop-modal-view-stack/pushpop-modal-view-stack.css +148 -0
- data/vendor/assets/Pushpop/pushpop-modal-view-stack/pushpop-modal-view-stack.js +306 -0
- data/vendor/assets/Pushpop/pushpop-popover-view-stack/pushpop-popover-view-stack.css +170 -0
- data/vendor/assets/Pushpop/pushpop-popover-view-stack/pushpop-popover-view-stack.js +278 -0
- data/vendor/assets/Pushpop/pushpop-split-view/pushpop-split-view.css +38 -0
- data/vendor/assets/Pushpop/pushpop-split-view/pushpop-split-view.js +33 -0
- data/vendor/assets/Pushpop/pushpop-tab-view/pushpop-tab-view.css +130 -0
- data/vendor/assets/Pushpop/pushpop-tab-view/pushpop-tab-view.js +298 -0
- data/vendor/assets/Pushpop/pushpop-table-view/pushpop-table-view.css +1273 -0
- data/vendor/assets/Pushpop/pushpop-table-view/pushpop-table-view.js +2275 -0
- data/vendor/assets/Pushpop/pushpop.css +2243 -0
- data/vendor/assets/Pushpop/pushpop.js +1554 -0
- data/vendor/assets/javascripts/pushpop_rails.js +7 -0
- data/vendor/assets/stylesheets/pushpop_rails.css +9 -0
- metadata +92 -0
data/README.md
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
pushpop-rails
|
2
|
+
=============
|
3
|
+
|
4
|
+
pushpop-rails integrates Entropi's Pushpop HTML5 Web Development Framework in to the Rails Asset Pipeline. For more information on the Pushpop framework, please [view the Pushpop project page](https://github.com/entropillc/Pushpop) on GitHub
|
5
|
+
|
6
|
+
Installation
|
7
|
+
-------------
|
8
|
+
|
9
|
+
Add the following to your Gemfile
|
10
|
+
|
11
|
+
gem "pushpop-rails", :git => "git://github.com/entropillc/pushpop-rails.git"
|
12
|
+
|
13
|
+
Then install the bundle
|
14
|
+
|
15
|
+
bundle install
|
16
|
+
|
17
|
+
Finally, run the install generator
|
18
|
+
|
19
|
+
rails g pushpop:install
|
20
|
+
|
21
|
+
Understanding pushpop-rails
|
22
|
+
-------------
|
23
|
+
|
24
|
+
pushpop-rails provides a way for easy integration between PushPop and the Rails asset pipeline. If you are using the source of this gem, the Pushpop project is stored under vendor/assets/Pushpop. When working with the source, make sure to initialize all git submodules
|
25
|
+
|
26
|
+
git submodule update --init --recurisve
|
27
|
+
|
28
|
+
This should pull all dependent submodules in to the project for use.
|
29
|
+
|
30
|
+
There are two manifest files: vendor/assets/javascripts/pushpop_rails.js and vendor/assets/stylesheets/pushpop_rails.css. These manifest files include various javascript and css dependencies in to one file, to make it easier to require in the main manifest file of your rails application. These are also put in place by the installer
|
31
|
+
|
32
|
+
You can also make these includes manually if you wish. For javascript the includes would be
|
33
|
+
|
34
|
+
//= require externals/scrollkit/scrollkit
|
35
|
+
//= require pushpop
|
36
|
+
//= require pushpop-tableview/pushpop-tableview
|
37
|
+
|
38
|
+
And for CSS the includes would be
|
39
|
+
|
40
|
+
*= require externals/scrollkit/scrollkit
|
41
|
+
*= require pushpop.css
|
42
|
+
*= require pushpop-tableview/pushpop-tableview.css
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'pushpop-rails'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
24
|
+
load 'rails/tasks/engine.rake'
|
25
|
+
|
26
|
+
|
27
|
+
|
28
|
+
Bundler::GemHelper.install_tasks
|
29
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
|
3
|
+
module Pushpop
|
4
|
+
module Generators
|
5
|
+
class InstallGenerator < ::Rails::Generators::Base
|
6
|
+
|
7
|
+
def add_javascript
|
8
|
+
insert_into_file "app/assets/javascripts/application.js","//= require pushpop_rails\n", :before => "//= require_tree ."
|
9
|
+
end
|
10
|
+
|
11
|
+
def add_css
|
12
|
+
insert_into_file "app/assets/stylesheets/application.css", " *= require pushpop_rails\n", :after => "*= require_tree .\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,202 @@
|
|
1
|
+
* {
|
2
|
+
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
3
|
+
-webkit-text-size-adjust: none;
|
4
|
+
-webkit-touch-callout: none;
|
5
|
+
-webkit-user-drag: none;
|
6
|
+
}
|
7
|
+
|
8
|
+
html {
|
9
|
+
background: #000;
|
10
|
+
width: 100%;
|
11
|
+
height: 100%;
|
12
|
+
margin: 0;
|
13
|
+
padding: 0;
|
14
|
+
overflow: hidden;
|
15
|
+
-webkit-text-size-adjust: 100%;
|
16
|
+
-moz-text-size-adjust: 100%;
|
17
|
+
-ms-text-size-adjust: 100%;
|
18
|
+
-o-text-size-adjust: 100%;
|
19
|
+
text-size-adjust: 100%;
|
20
|
+
}
|
21
|
+
|
22
|
+
body {
|
23
|
+
background: #000;
|
24
|
+
position: absolute;
|
25
|
+
width: 100%;
|
26
|
+
height: 100%;
|
27
|
+
margin: 0;
|
28
|
+
padding: 0;
|
29
|
+
overflow: hidden;
|
30
|
+
}
|
31
|
+
|
32
|
+
.sk-scroll-view {
|
33
|
+
background: #333 url('background.png');
|
34
|
+
background-size: 256px 256px;
|
35
|
+
position: absolute;
|
36
|
+
width: 100%;
|
37
|
+
height: 100%;
|
38
|
+
top: 0;
|
39
|
+
left: 0;
|
40
|
+
margin: 0;
|
41
|
+
padding: 0;
|
42
|
+
overflow: hidden;
|
43
|
+
-webkit-user-select: none;
|
44
|
+
-moz-user-select: none;
|
45
|
+
-ms-user-select: none;
|
46
|
+
-o-user-select: none;
|
47
|
+
user-select: none;
|
48
|
+
-webkit-backface-visibility: hidden;
|
49
|
+
-moz-backface-visibility: hidden;
|
50
|
+
-ms-backface-visibility: hidden;
|
51
|
+
-o-backface-visibility: hidden;
|
52
|
+
backface-visibility: hidden;
|
53
|
+
-webkit-transform: translate3d(0, 0, 0);
|
54
|
+
-moz-transform: translate(0, 0);
|
55
|
+
-ms-transform: translate(0, 0);
|
56
|
+
-o-transform: translate(0, 0);
|
57
|
+
transform: translate(0, 0);
|
58
|
+
}
|
59
|
+
|
60
|
+
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
|
61
|
+
.sk-scroll-view {
|
62
|
+
background: #333 url('background@2x.png');
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
.sk-scroll-view.sk-scroll-view-plain, .sk-scroll-view.sk-scroll-view-plain > .sk-scroll-content {
|
67
|
+
background: none;
|
68
|
+
}
|
69
|
+
|
70
|
+
.sk-scroll-view.sk-no-touch {
|
71
|
+
overflow: auto;
|
72
|
+
-webkit-transform: none;
|
73
|
+
-moz-transform: none;
|
74
|
+
-ms-transform: none;
|
75
|
+
-o-transform: none;
|
76
|
+
transform: none;
|
77
|
+
}
|
78
|
+
|
79
|
+
.sk-no-touch::-webkit-scrollbar {
|
80
|
+
background: #ddd;
|
81
|
+
width: 12px;
|
82
|
+
height: 12px;
|
83
|
+
}
|
84
|
+
|
85
|
+
.sk-no-touch::-webkit-scrollbar-thumb {
|
86
|
+
background: rgba(0, 0, 0, 0.5);
|
87
|
+
-webkit-border-radius: 10px;
|
88
|
+
border-radius: 10px;
|
89
|
+
}
|
90
|
+
|
91
|
+
.sk-no-touch::-webkit-scrollbar-track {
|
92
|
+
-webkit-box-shadow: inset 0 0 6px 0 rgba(0, 0, 0, 0.3);
|
93
|
+
box-shadow: inset 0 0 6px 0 rgba(0, 0, 0, 0.3);
|
94
|
+
-webkit-border-radius: 10px;
|
95
|
+
border-radius: 10px;
|
96
|
+
}
|
97
|
+
|
98
|
+
.sk-scroll-content {
|
99
|
+
background: #ddd;
|
100
|
+
position: absolute;
|
101
|
+
min-width: 100%;
|
102
|
+
width: auto;
|
103
|
+
min-height: 100%;
|
104
|
+
height: auto;
|
105
|
+
top: 0;
|
106
|
+
left: 0;
|
107
|
+
margin: 0;
|
108
|
+
padding: 0;
|
109
|
+
overflow: visible;
|
110
|
+
-webkit-backface-visibility: hidden;
|
111
|
+
-moz-backface-visibility: hidden;
|
112
|
+
-ms-backface-visibility: hidden;
|
113
|
+
-o-backface-visibility: hidden;
|
114
|
+
backface-visibility: hidden;
|
115
|
+
-webkit-transform: translate3d(0, 0, 0);
|
116
|
+
-moz-transform: translate(0, 0);
|
117
|
+
-ms-transform: translate(0, 0);
|
118
|
+
-o-transform: translate(0, 0);
|
119
|
+
transform: translate(0, 0);
|
120
|
+
-webkit-transition: -webkit-transform 0s ease;
|
121
|
+
-moz-transition: -moz-transform 0s ease;
|
122
|
+
-ms-transition: -ms-transform 0s ease;
|
123
|
+
-o-transition: -o-transform 0s ease;
|
124
|
+
transition: transform 0s ease;
|
125
|
+
}
|
126
|
+
|
127
|
+
.sk-no-touch > .sk-scroll-content {
|
128
|
+
-webkit-transform: none;
|
129
|
+
-moz-transform: none;
|
130
|
+
-ms-transform: none;
|
131
|
+
-o-transform: none;
|
132
|
+
transform: none;
|
133
|
+
-webkit-transition: none;
|
134
|
+
-moz-transition: none;
|
135
|
+
-ms-transition: none;
|
136
|
+
-o-transition: none;
|
137
|
+
transition: none;
|
138
|
+
}
|
139
|
+
|
140
|
+
.sk-scroll-indicator {
|
141
|
+
background: rgba(0, 0, 0, 1);
|
142
|
+
border: 1px solid rgba(255, 255, 255, 0.8);
|
143
|
+
position: absolute;
|
144
|
+
width: 5px;
|
145
|
+
height: 5px;
|
146
|
+
margin: 2px;
|
147
|
+
opacity: 0.5;
|
148
|
+
-webkit-border-radius: 5px;
|
149
|
+
-moz-border-radius: 5px;
|
150
|
+
border-radius: 5px;
|
151
|
+
-webkit-backface-visibility: hidden;
|
152
|
+
-moz-backface-visibility: hidden;
|
153
|
+
-ms-backface-visibility: hidden;
|
154
|
+
-o-backface-visibility: hidden;
|
155
|
+
backface-visibility: hidden;
|
156
|
+
-webkit-transform: translate3d(0, 0, 0);
|
157
|
+
-moz-transform: translate(0, 0);
|
158
|
+
-ms-transform: translate(0, 0);
|
159
|
+
-o-transform: translate(0, 0);
|
160
|
+
transform: translate(0, 0);
|
161
|
+
-webkit-transition: opacity 0.1s ease 0s, -webkit-transform 0s ease;
|
162
|
+
-moz-transition: opacity 0.1s ease 0s, -moz-transform 0s ease;
|
163
|
+
-ms-transition: opacity 0.1s ease 0s, -ms-transform 0s ease;
|
164
|
+
-o-transition: opacity 0.1s ease 0s, -o-transform 0s ease;
|
165
|
+
transition: opacity 0.1s ease 0s, transform 0s ease;
|
166
|
+
}
|
167
|
+
|
168
|
+
.sk-scroll-indicator.sk-hidden {
|
169
|
+
opacity: 0;
|
170
|
+
-webkit-transition: opacity 0.3s ease 0.3s, -webkit-transform 0s ease;
|
171
|
+
-moz-transition: opacity 0.3s ease 0.3s, -moz-transform 0s ease;
|
172
|
+
-ms-transition: opacity 0.3s ease 0.3s, -ms-transform 0s ease;
|
173
|
+
-o-transition: opacity 0.3s ease 0.3s, -o-transform 0s ease;
|
174
|
+
transition: opacity 0.3s ease 0.3s, transform 0s ease;
|
175
|
+
}
|
176
|
+
|
177
|
+
.sk-page-container-horizontal {
|
178
|
+
display: inline-block;
|
179
|
+
float: left;
|
180
|
+
list-style: none;
|
181
|
+
margin: 0;
|
182
|
+
padding: 0;
|
183
|
+
white-space: nowrap;
|
184
|
+
min-width: 100%;
|
185
|
+
width: auto;
|
186
|
+
height: 100%;
|
187
|
+
overflow: hidden;
|
188
|
+
overflow-x: auto;
|
189
|
+
position: relative;
|
190
|
+
}
|
191
|
+
|
192
|
+
.sk-page-container-horizontal > li {
|
193
|
+
display: inline-block;
|
194
|
+
float: left;
|
195
|
+
list-style-type: none;
|
196
|
+
margin: 0;
|
197
|
+
padding: 0;
|
198
|
+
white-space: normal;
|
199
|
+
width: 100%;
|
200
|
+
height: 100%;
|
201
|
+
position: relative;
|
202
|
+
}
|
@@ -0,0 +1,924 @@
|
|
1
|
+
;'use strict';
|
2
|
+
|
3
|
+
// Polyfill for window.requestAnimationFrame and window.cancelAnimationFrame.
|
4
|
+
(function(){var a=0;var b=['webkit','moz','ms','o'];for(var c=0;c<b.length&&!window.requestAnimationFrame;c++){window.requestAnimationFrame=window[b[c]+'RequestAnimationFrame'];window.cancelAnimationFrame=window[b[c]+'CancelAnimationFrame']||window[b[c]+'RequestCancelAnimationFrame'];}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(b,c){var d=Date['now']?Date.now():+(new Date());var e=Math.max(0,16-(d-a));var f=window.setTimeout(function(){b(d+e);},e);a=d+e;return f;};}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(a){window.clearTimeout(a);};}})();
|
5
|
+
|
6
|
+
// The base ScrollKit object.
|
7
|
+
var ScrollKit = window['ScrollKit'] || {};
|
8
|
+
|
9
|
+
ScrollKit.Params = {
|
10
|
+
bounceTransitionDuration: 0.3,
|
11
|
+
accelerationTimeout: 250,
|
12
|
+
acceleration: 20,
|
13
|
+
elasticDeceleration: 0.03,
|
14
|
+
elasticAcceleration: 0.18,
|
15
|
+
minimumDecelerationVelocity: 1,
|
16
|
+
decelerationFactor: 0.85,
|
17
|
+
minimumVelocity: 0.01,
|
18
|
+
minimumDeltaForScrollEvent: 0.5,
|
19
|
+
minimumPageTurnVelocity: 5
|
20
|
+
};
|
21
|
+
|
22
|
+
/**
|
23
|
+
|
24
|
+
*/
|
25
|
+
ScrollKit.Util = {
|
26
|
+
|
27
|
+
/**
|
28
|
+
|
29
|
+
*/
|
30
|
+
getCoordinatesForEvent: function(evt, identifier) {
|
31
|
+
if (evt.type.indexOf('mouse') !== -1) return { x: evt.pageX, y: evt.pageY };
|
32
|
+
|
33
|
+
evt = evt.originalEvent;
|
34
|
+
|
35
|
+
var touch = (identifier) ? this.getTouchWithIdentifier(evt.touches, identifier) : this.getTouchWithIdentifier(evt.targetTouches);
|
36
|
+
return { x: touch.pageX, y: touch.pageY };
|
37
|
+
},
|
38
|
+
|
39
|
+
/**
|
40
|
+
|
41
|
+
*/
|
42
|
+
getTouchWithIdentifier: function(touches, identifier) {
|
43
|
+
if (touches.length === 0) return null;
|
44
|
+
if (!identifier) return touches[0];
|
45
|
+
|
46
|
+
for (var i = 0, length = touches.length, touch; i < length; i++) {
|
47
|
+
if ((touch = touches[i]).identifier === identifier) return touch;
|
48
|
+
}
|
49
|
+
|
50
|
+
return null;
|
51
|
+
},
|
52
|
+
|
53
|
+
/**
|
54
|
+
|
55
|
+
*/
|
56
|
+
getDeltaForCoordinates: function(coordA, coordB) {
|
57
|
+
return { x: coordA.x - coordB.x, y: coordA.y - coordB.y };
|
58
|
+
},
|
59
|
+
|
60
|
+
/**
|
61
|
+
|
62
|
+
*/
|
63
|
+
getVendorPrefix: function() {
|
64
|
+
if ('result' in arguments.callee) return arguments.callee.result;
|
65
|
+
|
66
|
+
var regExp = /^(Moz|Webkit|Khtml|O|ms|Icab)(?=[A-Z])/;
|
67
|
+
var script = document.createElement('script');
|
68
|
+
|
69
|
+
for (var prop in script.style) {
|
70
|
+
if (regExp.test(prop)) return arguments.callee.result = prop.match(regExp)[0];
|
71
|
+
}
|
72
|
+
|
73
|
+
if ('WebkitOpacity' in script.style) return arguments.callee.result = 'Webkit';
|
74
|
+
if ('KhtmlOpacity' in script.style) return arguments.callee.result = 'Khtml';
|
75
|
+
|
76
|
+
return arguments.callee.result = '';
|
77
|
+
}
|
78
|
+
};
|
79
|
+
|
80
|
+
/**
|
81
|
+
|
82
|
+
*/
|
83
|
+
ScrollKit.ScrollView = function ScrollView(element) {
|
84
|
+
if (!element) return;
|
85
|
+
|
86
|
+
var $element = this.$element = $(element);
|
87
|
+
element = this.element = $element[0];
|
88
|
+
|
89
|
+
var scrollView = element.scrollView;
|
90
|
+
if (scrollView) return scrollView;
|
91
|
+
|
92
|
+
var self = element.scrollView = this;
|
93
|
+
|
94
|
+
var Params = ScrollKit.Params;
|
95
|
+
var Util = ScrollKit.Util;
|
96
|
+
|
97
|
+
var $window = $(window['addEventListener'] ? window : document.body);
|
98
|
+
|
99
|
+
var $content = this.$content = $('<div class="sk-scroll-content"/>').append($element.contents()).appendTo($element);
|
100
|
+
var $horizontalScrollIndicator = this.$horizontalScrollIndicator = $('<div class="sk-scroll-indicator sk-hidden" style="bottom: 0; left: 0;"/>').appendTo($element);
|
101
|
+
var $verticalScrollIndicator = this.$verticalScrollIndicator = $('<div class="sk-scroll-indicator sk-hidden" style="top: 0; right: 0;"/>').appendTo($element);
|
102
|
+
|
103
|
+
var alwaysBounceHorizontal = $element.attr('data-always-bounce-horizontal') || 'false';
|
104
|
+
alwaysBounceHorizontal = this._alwaysBounceHorizontal = alwaysBounceHorizontal !== 'false';
|
105
|
+
|
106
|
+
var alwaysBounceVertical = $element.attr('data-always-bounce-vertical') || 'false';
|
107
|
+
alwaysBounceVertical = this._alwaysBounceVertical = alwaysBounceVertical !== 'false';
|
108
|
+
|
109
|
+
var alwaysHideHorizontalScrollIndicator = this._alwaysHideHorizontalScrollIndicator = $element.attr('data-always-hide-horizontal-scroll-indicator') || 'false';
|
110
|
+
alwaysHideHorizontalScrollIndicator = this._alwaysHideHorizontalScrollIndicator = alwaysHideHorizontalScrollIndicator !== 'false';
|
111
|
+
|
112
|
+
var alwaysHideVerticalScrollIndicator = this._alwaysHideVerticalScrollIndicator = $element.attr('data-always-hide-vertical-scroll-indicator') || 'false';
|
113
|
+
alwaysHideVerticalScrollIndicator = this._alwaysHideVerticalScrollIndicator = alwaysHideVerticalScrollIndicator !== 'false';
|
114
|
+
|
115
|
+
var pagingEnabled = $element.attr('data-paging-enabled') || 'false';
|
116
|
+
pagingEnabled = this._pagingEnabled = pagingEnabled !== 'false';
|
117
|
+
|
118
|
+
var useMouseDragScrolling = $element.attr('data-use-mouse-drag-scrolling') || 'false';
|
119
|
+
useMouseDragScrolling = this._useMouseDragScrolling = useMouseDragScrolling !== 'false';
|
120
|
+
|
121
|
+
var size = this._size = { width: 0, height: 0 };
|
122
|
+
var contentSize = this._contentSize = { width: 0, height: 0 };
|
123
|
+
var margin = this._margin = { top: 0, right: 0, bottom: 0, left: 0 };
|
124
|
+
var scrollPosition = this._scrollPosition = { x: 0, y: 0 };
|
125
|
+
var maximumScrollPosition = this._maximumScrollPosition = { x: 0, y: 0 };
|
126
|
+
var pageIndexes = this._pageIndexes = { horizontal: 0, vertical: 0 };
|
127
|
+
|
128
|
+
window.setTimeout(function() { self.recalculateDimensions(); }, 1);
|
129
|
+
|
130
|
+
var isTouchSupported = !!('ontouchstart' in window);
|
131
|
+
if (!isTouchSupported && !useMouseDragScrolling) {
|
132
|
+
$element.addClass('sk-no-touch');
|
133
|
+
$element.bind('scroll', function(evt) {
|
134
|
+
scrollPosition.x = this.scrollLeft;
|
135
|
+
scrollPosition.y = this.scrollTop;
|
136
|
+
});
|
137
|
+
|
138
|
+
return this;
|
139
|
+
}
|
140
|
+
|
141
|
+
else if (isTouchSupported) {
|
142
|
+
useMouseDragScrolling = this._useMouseDragScrolling = true;
|
143
|
+
}
|
144
|
+
|
145
|
+
var isDragging = false;
|
146
|
+
var lastTouchPosition = null;
|
147
|
+
var lastTouchIdentifier = null;
|
148
|
+
|
149
|
+
var startAccelerateTimeStamp = null;
|
150
|
+
var startAccelerateScrollPosition = null;
|
151
|
+
var isDecelerating = false;
|
152
|
+
var decelerationAnimationInterval = null;
|
153
|
+
|
154
|
+
var resetStartAccelerate = function(timeStamp) {
|
155
|
+
startAccelerateTimeStamp = timeStamp;
|
156
|
+
startAccelerateScrollPosition = {
|
157
|
+
x: scrollPosition.x,
|
158
|
+
y: scrollPosition.y
|
159
|
+
};
|
160
|
+
};
|
161
|
+
|
162
|
+
var startDeceleration = function(startTimeStamp) {
|
163
|
+
var shouldScrollHorizontal = self.getShouldScrollHorizontal();
|
164
|
+
var shouldScrollVertical = self.getShouldScrollVertical();
|
165
|
+
var acceleration = (startAccelerateTimeStamp - startTimeStamp) / Params.acceleration;
|
166
|
+
var accelerateDelta = Util.getDeltaForCoordinates(scrollPosition, startAccelerateScrollPosition);
|
167
|
+
var velocity = {
|
168
|
+
x: accelerateDelta.x / acceleration,
|
169
|
+
y: accelerateDelta.y / acceleration
|
170
|
+
};
|
171
|
+
|
172
|
+
var stepAnimation = function (currentFrameTimeStamp) {
|
173
|
+
if (!isDecelerating) return;
|
174
|
+
|
175
|
+
var animationDelta = {
|
176
|
+
x: (shouldScrollHorizontal ? velocity.x : 0),
|
177
|
+
y: (shouldScrollVertical ? velocity.y : 0)
|
178
|
+
};
|
179
|
+
|
180
|
+
velocity.x *= Params.decelerationFactor;
|
181
|
+
velocity.y *= Params.decelerationFactor;
|
182
|
+
|
183
|
+
if (Math.abs(velocity.x) <= Params.minimumVelocity && Math.abs(velocity.y) <= Params.minimumVelocity) {
|
184
|
+
stopDeceleration();
|
185
|
+
stopScroll();
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
|
189
|
+
self.setScrollPosition(scrollPosition.x - velocity.x, scrollPosition.y - velocity.y);
|
190
|
+
|
191
|
+
decelerationAnimationInterval = window.requestAnimationFrame(stepAnimation);
|
192
|
+
|
193
|
+
if (self.getIsScrollPositionInBounds()) return;
|
194
|
+
|
195
|
+
var elastic = {
|
196
|
+
x: (scrollPosition.x < 0) ? scrollPosition.x : (scrollPosition.x > maximumScrollPosition.x) ? scrollPosition.x - maximumScrollPosition.x : 0,
|
197
|
+
y: (scrollPosition.y < 0) ? scrollPosition.y : (scrollPosition.y > maximumScrollPosition.y) ? scrollPosition.y - maximumScrollPosition.y : 0
|
198
|
+
};
|
199
|
+
|
200
|
+
if (elastic.x) velocity.x = (elastic.x * velocity.x <= 0) ? velocity.x + (elastic.x * Params.elasticDeceleration) : elastic.x * Params.elasticAcceleration;
|
201
|
+
if (elastic.y) velocity.y = (elastic.y * velocity.y <= 0) ? velocity.y + (elastic.y * Params.elasticDeceleration) : elastic.y * Params.elasticAcceleration;
|
202
|
+
};
|
203
|
+
|
204
|
+
if (Math.abs(velocity.x) > Params.minimumDecelerationVelocity || Math.abs(velocity.y) > Params.minimumDecelerationVelocity) {
|
205
|
+
isDecelerating = true;
|
206
|
+
decelerationAnimationInterval = window.requestAnimationFrame(stepAnimation);
|
207
|
+
} else {
|
208
|
+
self.bounceScrollPositionInBounds();
|
209
|
+
stopScroll();
|
210
|
+
}
|
211
|
+
};
|
212
|
+
|
213
|
+
var stopDeceleration = function() {
|
214
|
+
if (!isDecelerating) return;
|
215
|
+
|
216
|
+
isDecelerating = false;
|
217
|
+
window.cancelAnimationFrame(decelerationAnimationInterval);
|
218
|
+
};
|
219
|
+
|
220
|
+
var snapToPage = function(startTimeStamp) {
|
221
|
+
var acceleration = (startAccelerateTimeStamp - startTimeStamp) / Params.acceleration;
|
222
|
+
var accelerateDelta = Util.getDeltaForCoordinates(scrollPosition, startAccelerateScrollPosition);
|
223
|
+
var velocity = {
|
224
|
+
x: accelerateDelta.x / acceleration,
|
225
|
+
y: accelerateDelta.y / acceleration
|
226
|
+
};
|
227
|
+
|
228
|
+
var pageCounts = self.getPageCounts();
|
229
|
+
var currentPageIndexes = {
|
230
|
+
horizontal: Math.round(scrollPosition.x / size.width),
|
231
|
+
vertical: Math.round(scrollPosition.y / size.height)
|
232
|
+
};
|
233
|
+
|
234
|
+
if (currentPageIndexes.horizontal === pageIndexes.horizontal && Math.abs(velocity.x) > Params.minimumPageTurnVelocity) currentPageIndexes.horizontal += (velocity.x > 0) ? -1 : 1;
|
235
|
+
if (currentPageIndexes.vertical === pageIndexes.vertical && Math.abs(velocity.y) > Params.minimumPageTurnVelocity) currentPageIndexes.vertical += (velocity.y > 0) ? -1 : 1;
|
236
|
+
|
237
|
+
currentPageIndexes.horizontal = Math.min(Math.max(0, currentPageIndexes.horizontal), pageCounts.horizontal - 1);
|
238
|
+
currentPageIndexes.vertical = Math.min(Math.max(0, currentPageIndexes.vertical), pageCounts.vertical - 1);
|
239
|
+
|
240
|
+
self.setPageIndexes(currentPageIndexes.horizontal, currentPageIndexes.vertical);
|
241
|
+
};
|
242
|
+
|
243
|
+
var startScroll = function() {
|
244
|
+
if (self._scrolling) return;
|
245
|
+
self._scrolling = true;
|
246
|
+
|
247
|
+
self.setHorizontalScrollIndicatorHidden(false);
|
248
|
+
self.setVerticalScrollIndicatorHidden(false);
|
249
|
+
$element.trigger(ScrollKit.ScrollView.EventType.ScrollStart);
|
250
|
+
};
|
251
|
+
|
252
|
+
var stopScroll = function() {
|
253
|
+
if (!self._scrolling) return;
|
254
|
+
self._scrolling = false;
|
255
|
+
|
256
|
+
var roundedScrollPosition = {
|
257
|
+
x: Math.round(scrollPosition.x),
|
258
|
+
y: Math.round(scrollPosition.y)
|
259
|
+
};
|
260
|
+
|
261
|
+
self.setHorizontalScrollIndicatorHidden(true);
|
262
|
+
self.setVerticalScrollIndicatorHidden(true);
|
263
|
+
|
264
|
+
if (scrollPosition.x !== roundedScrollPosition.x || scrollPosition.y !== roundedScrollPosition.y) {
|
265
|
+
self.setScrollPosition(Math.round(scrollPosition.x), Math.round(scrollPosition.y));
|
266
|
+
}
|
267
|
+
|
268
|
+
$element.trigger(ScrollKit.ScrollView.EventType.ScrollStop);
|
269
|
+
};
|
270
|
+
|
271
|
+
$element.bind(isTouchSupported ? 'touchstart' : 'mousedown', function(evt) {
|
272
|
+
if (isDragging) return;
|
273
|
+
|
274
|
+
isDragging = true;
|
275
|
+
lastTouchPosition = Util.getCoordinatesForEvent(evt);
|
276
|
+
lastTouchIdentifier = (isTouchSupported) ? evt.originalEvent.targetTouches[0].identifier : null;
|
277
|
+
|
278
|
+
stopDeceleration();
|
279
|
+
resetStartAccelerate(evt.timeStamp);
|
280
|
+
|
281
|
+
self.recalculateDimensions();
|
282
|
+
|
283
|
+
$window.bind(isTouchSupported ? 'touchmove' : 'mousemove', touchMoveHandler);
|
284
|
+
$window.bind(isTouchSupported ? 'touchend' : 'mouseup', touchEndHandler);
|
285
|
+
});
|
286
|
+
|
287
|
+
var touchMoveHandler = function(evt) {
|
288
|
+
evt.preventDefault();
|
289
|
+
|
290
|
+
if (!isDragging) return;
|
291
|
+
|
292
|
+
if (!self._scrolling) startScroll();
|
293
|
+
|
294
|
+
var touchPosition = Util.getCoordinatesForEvent(evt, lastTouchIdentifier);
|
295
|
+
var touchDelta = Util.getDeltaForCoordinates(touchPosition, lastTouchPosition);
|
296
|
+
|
297
|
+
if (!self.getIsScrollPositionInBounds()) {
|
298
|
+
touchDelta.x /= 2;
|
299
|
+
touchDelta.y /= 2;
|
300
|
+
}
|
301
|
+
|
302
|
+
self.setScrollPosition(scrollPosition.x - touchDelta.x, scrollPosition.y - touchDelta.y);
|
303
|
+
|
304
|
+
var timeStamp = evt.timeStamp;
|
305
|
+
var accelerationTime = timeStamp - startAccelerateTimeStamp;
|
306
|
+
if (accelerationTime > Params.accelerationTimeout) resetStartAccelerate(timeStamp);
|
307
|
+
|
308
|
+
lastTouchPosition = touchPosition;
|
309
|
+
};
|
310
|
+
|
311
|
+
var touchEndHandler = function(evt) {
|
312
|
+
if (!isDragging) return;
|
313
|
+
|
314
|
+
isDragging = false;
|
315
|
+
lastTouchIdentifier = null;
|
316
|
+
|
317
|
+
$window.unbind(isTouchSupported ? 'touchmove' : 'mousemove', touchMoveHandler);
|
318
|
+
$window.unbind(isTouchSupported ? 'touchend' : 'mouseup', touchEndHandler);
|
319
|
+
|
320
|
+
var timeStamp = evt.timeStamp;
|
321
|
+
var accelerationTime = timeStamp - startAccelerateTimeStamp;
|
322
|
+
|
323
|
+
if (self._pagingEnabled) {
|
324
|
+
snapToPage(timeStamp);
|
325
|
+
stopScroll();
|
326
|
+
}
|
327
|
+
|
328
|
+
else if (accelerationTime < Params.accelerationTimeout) {
|
329
|
+
startDeceleration(timeStamp);
|
330
|
+
}
|
331
|
+
|
332
|
+
else if (!self.getIsScrollPositionInBounds()) {
|
333
|
+
self.bounceScrollPositionInBounds();
|
334
|
+
stopScroll();
|
335
|
+
}
|
336
|
+
|
337
|
+
else {
|
338
|
+
stopScroll();
|
339
|
+
}
|
340
|
+
};
|
341
|
+
};
|
342
|
+
|
343
|
+
/**
|
344
|
+
Event types for ScrollKit.ScrollView.
|
345
|
+
*/
|
346
|
+
ScrollKit.ScrollView.EventType = {
|
347
|
+
ScrollStart: 'ScrollKit:ScrollView:ScrollStart',
|
348
|
+
ScrollStop: 'ScrollKit:ScrollView:ScrollStop',
|
349
|
+
WillScrollToTop: 'ScrollKit:ScrollView:WillScrollToTop',
|
350
|
+
DidScrollToTop: 'ScrollKit:ScrollView:DidScrollToTop',
|
351
|
+
PageChanged: 'ScrollKit:ScrollView:PageChanged',
|
352
|
+
DidPullToRefresh: 'ScrollKit:ScrollView:DidPullToRefresh'
|
353
|
+
};
|
354
|
+
|
355
|
+
ScrollKit.ScrollView.prototype = {
|
356
|
+
constructor: ScrollKit.ScrollView,
|
357
|
+
|
358
|
+
element: null,
|
359
|
+
$element: null,
|
360
|
+
$content: null,
|
361
|
+
$horizontalScrollIndicator: null,
|
362
|
+
$verticalScrollIndicator: null,
|
363
|
+
|
364
|
+
_useMouseDragScrolling: false,
|
365
|
+
_vendorPrefix: ScrollKit.Util.getVendorPrefix().toLowerCase(),
|
366
|
+
|
367
|
+
_scrolling: false,
|
368
|
+
|
369
|
+
/**
|
370
|
+
|
371
|
+
*/
|
372
|
+
getScrolling: function() { return this._scrolling; },
|
373
|
+
|
374
|
+
_alwaysBounceHorizontal: false,
|
375
|
+
|
376
|
+
/**
|
377
|
+
|
378
|
+
*/
|
379
|
+
getAlwaysBounceHorizontal: function() { return this._alwaysBounceHorizontal; },
|
380
|
+
|
381
|
+
/**
|
382
|
+
|
383
|
+
*/
|
384
|
+
setAlwaysBounceHorizontal: function(alwaysBounceHorizontal) { this._alwaysBounceHorizontal = alwaysBounceHorizontal; },
|
385
|
+
|
386
|
+
/**
|
387
|
+
|
388
|
+
*/
|
389
|
+
getShouldScrollHorizontal: function() { return this._alwaysBounceHorizontal || this._contentSize.width > this._size.width; },
|
390
|
+
|
391
|
+
_alwaysBounceVertical: false,
|
392
|
+
|
393
|
+
/**
|
394
|
+
|
395
|
+
*/
|
396
|
+
getAlwaysBounceVertical: function() { return this._alwaysBounceVertical; },
|
397
|
+
|
398
|
+
/**
|
399
|
+
|
400
|
+
*/
|
401
|
+
setAlwaysBounceVertical: function(alwaysBounceVertical) { this._alwaysBounceVertical = alwaysBounceVertical; },
|
402
|
+
|
403
|
+
/**
|
404
|
+
|
405
|
+
*/
|
406
|
+
getShouldScrollVertical: function() { return this._alwaysBounceVertical || this._contentSize.height > this._size.height; },
|
407
|
+
|
408
|
+
_alwaysHideHorizontalScrollIndicator: false,
|
409
|
+
|
410
|
+
/**
|
411
|
+
|
412
|
+
*/
|
413
|
+
getAlwaysHideHorizontalScrollIndicator: function() { return this._alwaysHideHorizontalScrollIndicator; },
|
414
|
+
|
415
|
+
/**
|
416
|
+
|
417
|
+
*/
|
418
|
+
setAlwaysHideHorizontalScrollIndicator: function(alwaysHideHorizontalScrollIndicator) { this._alwaysHideHorizontalScrollIndicator = alwaysHideHorizontalScrollIndicator; },
|
419
|
+
|
420
|
+
_alwaysHideVerticalScrollIndicator: false,
|
421
|
+
|
422
|
+
/**
|
423
|
+
|
424
|
+
*/
|
425
|
+
getAlwaysHideVerticalScrollIndicator: function() { return this._alwaysHideVerticalScrollIndicator; },
|
426
|
+
|
427
|
+
/**
|
428
|
+
|
429
|
+
*/
|
430
|
+
setAlwaysHideVerticalScrollIndicator: function(alwaysHideVerticalScrollIndicator) { this._alwaysHideVerticalScrollIndicator = alwaysHideVerticalScrollIndicator; },
|
431
|
+
|
432
|
+
_pagingEnabled: false,
|
433
|
+
|
434
|
+
/**
|
435
|
+
|
436
|
+
*/
|
437
|
+
getPagingEnabled: function() { return this._pagingEnabled; },
|
438
|
+
|
439
|
+
/**
|
440
|
+
|
441
|
+
*/
|
442
|
+
setPagingEnabled: function(pagingEnabled) { this._pagingEnabled = pagingEnabled; },
|
443
|
+
|
444
|
+
_pageIndexes: null, // { horizontal: 0, vertical: 0 }
|
445
|
+
|
446
|
+
/**
|
447
|
+
|
448
|
+
*/
|
449
|
+
getPageIndexes: function() { return this._pageIndexes; },
|
450
|
+
|
451
|
+
/**
|
452
|
+
|
453
|
+
*/
|
454
|
+
setPageIndexes: function(horizontalPageIndex, verticalPageIndex) {
|
455
|
+
var pageIndexes = this._pageIndexes;
|
456
|
+
var size = this._size;
|
457
|
+
|
458
|
+
var previousIndexes = {
|
459
|
+
horizontal: pageIndexes.horizontal,
|
460
|
+
vertical: pageIndexes.vertical
|
461
|
+
};
|
462
|
+
|
463
|
+
pageIndexes.horizontal = horizontalPageIndex;
|
464
|
+
pageIndexes.vertical = verticalPageIndex;
|
465
|
+
|
466
|
+
this.setScrollPosition(horizontalPageIndex * size.width, verticalPageIndex * size.height, ScrollKit.Params.bounceTransitionDuration);
|
467
|
+
|
468
|
+
if (horizontalPageIndex !== previousIndexes.horizontal || verticalPageIndex !== previousIndexes.vertical) {
|
469
|
+
this.$element.trigger($.Event(ScrollKit.ScrollView.EventType.PageChanged, {
|
470
|
+
previousIndexes: previousIndexes,
|
471
|
+
currentIndexes: {
|
472
|
+
horizontal: horizontalPageIndex,
|
473
|
+
vertical: verticalPageIndex
|
474
|
+
}
|
475
|
+
}));
|
476
|
+
}
|
477
|
+
},
|
478
|
+
|
479
|
+
/**
|
480
|
+
|
481
|
+
*/
|
482
|
+
getPageCounts: function() {
|
483
|
+
var contentSize = this._contentSize;
|
484
|
+
var size = this._size;
|
485
|
+
var pageCounts = {
|
486
|
+
horizontal: Math.floor(contentSize.width / size.width),
|
487
|
+
vertical: Math.floor(contentSize.height / size.height)
|
488
|
+
};
|
489
|
+
|
490
|
+
return pageCounts;
|
491
|
+
},
|
492
|
+
|
493
|
+
_minimumHorizontalScrollIndicatorLength: 12,
|
494
|
+
|
495
|
+
/**
|
496
|
+
|
497
|
+
*/
|
498
|
+
getMinimumHorizontalScrollIndicatorLength: function() { return this._minimumHorizontalScrollIndicatorLength; },
|
499
|
+
|
500
|
+
/**
|
501
|
+
|
502
|
+
*/
|
503
|
+
setMinimumHorizontalScrollIndicatorLength: function(minimumHorizontalScrollIndicatorLength) {
|
504
|
+
this._minimumHorizontalScrollIndicatorLength = minimumHorizontalScrollIndicatorLength;
|
505
|
+
this.updateHorizontalScrollIndicator();
|
506
|
+
},
|
507
|
+
|
508
|
+
_horizontalScrollIndicatorThickness: 7,
|
509
|
+
|
510
|
+
/**
|
511
|
+
|
512
|
+
*/
|
513
|
+
getHorizontalScrollIndicatorThickness: function() { return this._horizontalScrollIndicatorThickness; },
|
514
|
+
|
515
|
+
/**
|
516
|
+
|
517
|
+
*/
|
518
|
+
setHorizontalScrollIndicatorThickness: function(horizontalScrollIndicatorThickness) {
|
519
|
+
this._horizontalScrollIndicatorThickness = horizontalScrollIndicatorThickness;
|
520
|
+
this.updateHorizontalScrollIndicator();
|
521
|
+
},
|
522
|
+
|
523
|
+
_horizontalScrollIndicatorHidden: true,
|
524
|
+
|
525
|
+
/**
|
526
|
+
|
527
|
+
*/
|
528
|
+
getHorizontalScrollIndicatorHidden: function() { return this._horizontalScrollIndicatorHidden; },
|
529
|
+
|
530
|
+
/**
|
531
|
+
|
532
|
+
*/
|
533
|
+
setHorizontalScrollIndicatorHidden: function(horizontalScrollIndicatorHidden) {
|
534
|
+
this._horizontalScrollIndicatorHidden = horizontalScrollIndicatorHidden;
|
535
|
+
|
536
|
+
if (horizontalScrollIndicatorHidden || this._alwaysHideHorizontalScrollIndicator || !this.getShouldScrollHorizontal()) {
|
537
|
+
this.$horizontalScrollIndicator.addClass('sk-hidden');
|
538
|
+
} else {
|
539
|
+
this.$horizontalScrollIndicator.removeClass('sk-hidden');
|
540
|
+
}
|
541
|
+
},
|
542
|
+
|
543
|
+
/**
|
544
|
+
|
545
|
+
*/
|
546
|
+
updateHorizontalScrollIndicator: function() {
|
547
|
+
if (this._horizontalScrollIndicatorHidden) return;
|
548
|
+
|
549
|
+
var scrollPosition = this._scrollPosition.x;
|
550
|
+
var size = this._size.width;
|
551
|
+
var contentSize = this._contentSize.width;
|
552
|
+
var maximumScrollPosition = this._maximumScrollPosition.x;
|
553
|
+
var minimumScrollIndicatorLength = this._minimumHorizontalScrollIndicatorLength;
|
554
|
+
var scrollIndicatorThickness = this._horizontalScrollIndicatorThickness;
|
555
|
+
var scrollIndicatorMargin = this.getShouldScrollVertical() ? scrollIndicatorThickness * 2 : scrollIndicatorThickness - 2;
|
556
|
+
var scrollIndicatorLength = Math.max(minimumScrollIndicatorLength, (size / contentSize) * (size - scrollIndicatorMargin));
|
557
|
+
var scrollIndicatorPosition = (scrollPosition / maximumScrollPosition) * (size - scrollIndicatorMargin - scrollIndicatorLength);
|
558
|
+
|
559
|
+
if (scrollPosition <= 0) {
|
560
|
+
scrollIndicatorLength = Math.max(scrollIndicatorThickness - 2, scrollPosition + scrollIndicatorLength);
|
561
|
+
scrollIndicatorPosition = 0;
|
562
|
+
}
|
563
|
+
|
564
|
+
else if (scrollPosition >= maximumScrollPosition) {
|
565
|
+
scrollIndicatorLength = Math.max(scrollIndicatorThickness - 2, (maximumScrollPosition - scrollPosition) + scrollIndicatorLength);
|
566
|
+
scrollIndicatorPosition = size - scrollIndicatorLength - scrollIndicatorMargin;
|
567
|
+
}
|
568
|
+
|
569
|
+
var translation = scrollIndicatorPosition + 'px, 0';
|
570
|
+
var vendorPrefix = this._vendorPrefix;
|
571
|
+
var styles = this._horizontalScrollIndicatorStyles = this._horizontalScrollIndicatorStyles || {};
|
572
|
+
|
573
|
+
styles['width'] = scrollIndicatorLength + 'px';
|
574
|
+
|
575
|
+
// TODO: Change this test to look for 3D transform capability instead of Webkit only.
|
576
|
+
if (vendorPrefix === 'webkit') {
|
577
|
+
styles['-webkit-transform'] = styles['transform'] = 'translate3d(' + translation + ', 0)';
|
578
|
+
}
|
579
|
+
|
580
|
+
else {
|
581
|
+
styles['-' + vendorPrefix + '-transform'] = styles['transform'] = 'translate(' + translation + ')';
|
582
|
+
}
|
583
|
+
|
584
|
+
this.$horizontalScrollIndicator.css(styles);
|
585
|
+
},
|
586
|
+
|
587
|
+
_minimumVerticalScrollIndicatorLength: 12,
|
588
|
+
|
589
|
+
/**
|
590
|
+
|
591
|
+
*/
|
592
|
+
getMinimumVerticalScrollIndicatorLength: function() { return this._minimumVerticalScrollIndicatorLength; },
|
593
|
+
|
594
|
+
/**
|
595
|
+
|
596
|
+
*/
|
597
|
+
setMinimumVerticalScrollIndicatorLength: function(minimumVerticalScrollIndicatorLength) {
|
598
|
+
this._minimumVerticalScrollIndicatorLength = minimumVerticalScrollIndicatorLength;
|
599
|
+
this.updateVerticalScrollIndicator();
|
600
|
+
},
|
601
|
+
|
602
|
+
_verticalScrollIndicatorThickness: 7,
|
603
|
+
|
604
|
+
/**
|
605
|
+
|
606
|
+
*/
|
607
|
+
getVerticalScrollIndicatorThickness: function() { return this._verticalScrollIndicatorThickness; },
|
608
|
+
|
609
|
+
/**
|
610
|
+
|
611
|
+
*/
|
612
|
+
setVerticalScrollIndicatorThickness: function(verticalScrollIndicatorThickness) {
|
613
|
+
this._verticalScrollIndicatorThickness = verticalScrollIndicatorThickness;
|
614
|
+
this.updateVerticalScrollIndicator();
|
615
|
+
},
|
616
|
+
|
617
|
+
_verticalScrollIndicatorHidden: true,
|
618
|
+
|
619
|
+
/**
|
620
|
+
|
621
|
+
*/
|
622
|
+
getVerticalScrollIndicatorHidden: function() { return this._verticalScrollIndicatorHidden; },
|
623
|
+
|
624
|
+
/**
|
625
|
+
|
626
|
+
*/
|
627
|
+
setVerticalScrollIndicatorHidden: function(verticalScrollIndicatorHidden) {
|
628
|
+
this._verticalScrollIndicatorHidden = verticalScrollIndicatorHidden;
|
629
|
+
|
630
|
+
if (verticalScrollIndicatorHidden || this._alwaysHideVerticalScrollIndicator || !this.getShouldScrollVertical()) {
|
631
|
+
this.$verticalScrollIndicator.addClass('sk-hidden');
|
632
|
+
} else {
|
633
|
+
this.$verticalScrollIndicator.removeClass('sk-hidden');
|
634
|
+
}
|
635
|
+
},
|
636
|
+
|
637
|
+
/**
|
638
|
+
|
639
|
+
*/
|
640
|
+
updateVerticalScrollIndicator: function() {
|
641
|
+
if (this._verticalScrollIndicatorHidden) return;
|
642
|
+
|
643
|
+
var scrollPosition = this._scrollPosition.y;
|
644
|
+
var size = this._size.height;
|
645
|
+
var contentSize = this._contentSize.height;
|
646
|
+
var maximumScrollPosition = this._maximumScrollPosition.y;
|
647
|
+
var minimumScrollIndicatorLength = this._minimumVerticalScrollIndicatorLength;
|
648
|
+
var scrollIndicatorThickness = this._verticalScrollIndicatorThickness;
|
649
|
+
var scrollIndicatorMargin = this.getShouldScrollHorizontal() ? scrollIndicatorThickness * 2 : scrollIndicatorThickness - 2;
|
650
|
+
var scrollIndicatorLength = Math.max(minimumScrollIndicatorLength, (size / contentSize) * (size - scrollIndicatorMargin));
|
651
|
+
var scrollIndicatorPosition = (scrollPosition / maximumScrollPosition) * (size - scrollIndicatorMargin - scrollIndicatorLength);
|
652
|
+
|
653
|
+
if (scrollPosition <= 0) {
|
654
|
+
scrollIndicatorLength = Math.max(scrollIndicatorThickness - 2, scrollPosition + scrollIndicatorLength);
|
655
|
+
scrollIndicatorPosition = 0;
|
656
|
+
}
|
657
|
+
|
658
|
+
else if (scrollPosition >= maximumScrollPosition) {
|
659
|
+
scrollIndicatorLength = Math.max(scrollIndicatorThickness - 2, (maximumScrollPosition - scrollPosition) + scrollIndicatorLength);
|
660
|
+
scrollIndicatorPosition = size - scrollIndicatorLength - scrollIndicatorMargin;
|
661
|
+
}
|
662
|
+
|
663
|
+
var translation = '0, ' + scrollIndicatorPosition + 'px';
|
664
|
+
var vendorPrefix = this._vendorPrefix;
|
665
|
+
var styles = this._verticalScrollIndicatorStyles = this._verticalScrollIndicatorStyles || {};
|
666
|
+
|
667
|
+
styles['height'] = scrollIndicatorLength + 'px';
|
668
|
+
|
669
|
+
// TODO: Change this test to look for 3D transform capability instead of Webkit only.
|
670
|
+
if (vendorPrefix === 'webkit') {
|
671
|
+
styles['-webkit-transform'] = styles['transform'] = 'translate3d(' + translation + ', 0)';
|
672
|
+
}
|
673
|
+
|
674
|
+
else {
|
675
|
+
styles['-' + vendorPrefix + '-transform'] = styles['transform'] = 'translate(' + translation + ')';
|
676
|
+
}
|
677
|
+
|
678
|
+
this.$verticalScrollIndicator.css(styles);
|
679
|
+
},
|
680
|
+
|
681
|
+
_size: null, // { width: 0, height: 0 }
|
682
|
+
|
683
|
+
/**
|
684
|
+
|
685
|
+
*/
|
686
|
+
getSize: function() { return this._size; },
|
687
|
+
|
688
|
+
_contentSize: null, // { width: 0, height: 0 }
|
689
|
+
|
690
|
+
/**
|
691
|
+
|
692
|
+
*/
|
693
|
+
getContentSize: function() { return this._contentSize; },
|
694
|
+
|
695
|
+
_margin: null, // { top: 0, right: 0, bottom: 0, left: 0 }
|
696
|
+
|
697
|
+
/**
|
698
|
+
|
699
|
+
*/
|
700
|
+
getMargin: function() { return this._margin; },
|
701
|
+
|
702
|
+
/**
|
703
|
+
|
704
|
+
*/
|
705
|
+
setMargin: function(marginTop, marginRight, marginBottom, marginLeft) {
|
706
|
+
var scrollPosition = this._scrollPosition;
|
707
|
+
var margin = this._margin;
|
708
|
+
margin.top = (marginTop !== 0) ? (marginTop || margin.top) : 0;
|
709
|
+
margin.right = (marginRight !== 0) ? (marginRight || margin.right) : 0;
|
710
|
+
margin.bottom = (marginBottom !== 0) ? (marginBottom || margin.bottom) : 0;
|
711
|
+
margin.left = (marginLeft !== 0) ? (marginLeft || margin.left) : 0;
|
712
|
+
|
713
|
+
if (this._useMouseDragScrolling) {
|
714
|
+
this.translate(scrollPosition.x, scrollPosition.y);
|
715
|
+
} else {
|
716
|
+
this.$content.css('padding', margin.top + 'px ' + margin.right + 'px ' + margin.bottom + 'px ' + margin.left + 'px');
|
717
|
+
}
|
718
|
+
|
719
|
+
this.recalculateDimensions();
|
720
|
+
},
|
721
|
+
|
722
|
+
_scrollPosition: null, // { x: 0, y: 0 }
|
723
|
+
|
724
|
+
/**
|
725
|
+
|
726
|
+
*/
|
727
|
+
getScrollPosition: function() { return this._scrollPosition; },
|
728
|
+
|
729
|
+
/**
|
730
|
+
|
731
|
+
*/
|
732
|
+
setScrollPosition: function(x, y, animationDuration) {
|
733
|
+
var $element = this.$element;
|
734
|
+
var scrollPosition = this._scrollPosition;
|
735
|
+
var minimumDeltaForScrollEvent = ScrollKit.Params.minimumDeltaForScrollEvent;
|
736
|
+
var shouldTriggerScrollEvent = (Math.abs(scrollPosition.x - x) > minimumDeltaForScrollEvent || Math.abs(scrollPosition.y - y) > minimumDeltaForScrollEvent);
|
737
|
+
|
738
|
+
x = scrollPosition.x = (this.getShouldScrollHorizontal()) ? x : 0;
|
739
|
+
y = scrollPosition.y = (this.getShouldScrollVertical()) ? y : 0;
|
740
|
+
|
741
|
+
if (!this._useMouseDragScrolling) {
|
742
|
+
$element.scrollLeft(x);
|
743
|
+
$element.scrollTop(y);
|
744
|
+
return;
|
745
|
+
}
|
746
|
+
|
747
|
+
this.translate(x, y, animationDuration);
|
748
|
+
|
749
|
+
if (!shouldTriggerScrollEvent) return;
|
750
|
+
|
751
|
+
this.updateHorizontalScrollIndicator();
|
752
|
+
this.updateVerticalScrollIndicator();
|
753
|
+
|
754
|
+
$element.trigger('scroll');
|
755
|
+
},
|
756
|
+
|
757
|
+
/**
|
758
|
+
|
759
|
+
*/
|
760
|
+
scrollToTop: function() {
|
761
|
+
if (this._scrolling) return;
|
762
|
+
|
763
|
+
var $element = this.$element;
|
764
|
+
$element.trigger(ScrollKit.ScrollView.EventType.WillScrollToTop);
|
765
|
+
|
766
|
+
var margin = this._margin;
|
767
|
+
margin.bottom += margin.top;
|
768
|
+
margin.top = 0;
|
769
|
+
|
770
|
+
var bounceTransitionDuration = ScrollKit.Params.bounceTransitionDuration;
|
771
|
+
|
772
|
+
if (!this._useMouseDragScrolling) {
|
773
|
+
this.$content.css('padding', margin.top + 'px ' + margin.right + 'px ' + margin.bottom + 'px ' + margin.left + 'px');
|
774
|
+
|
775
|
+
$element.animate({
|
776
|
+
scrollTop: 0
|
777
|
+
}, bounceTransitionDuration * 500, function() {
|
778
|
+
$element.trigger(ScrollKit.ScrollView.EventType.DidScrollToTop);
|
779
|
+
});
|
780
|
+
|
781
|
+
return;
|
782
|
+
}
|
783
|
+
|
784
|
+
var scrollPosition = this._scrollPosition;
|
785
|
+
scrollPosition.x = 0;
|
786
|
+
scrollPosition.y = 0;
|
787
|
+
|
788
|
+
this.setHorizontalScrollIndicatorHidden(false);
|
789
|
+
this.setVerticalScrollIndicatorHidden(false);
|
790
|
+
|
791
|
+
this.updateHorizontalScrollIndicator();
|
792
|
+
this.updateVerticalScrollIndicator();
|
793
|
+
|
794
|
+
this.setScrollPosition(0, 0, bounceTransitionDuration);
|
795
|
+
|
796
|
+
var self = this;
|
797
|
+
window.setTimeout(function() {
|
798
|
+
self.setHorizontalScrollIndicatorHidden(true);
|
799
|
+
self.setVerticalScrollIndicatorHidden(true);
|
800
|
+
|
801
|
+
$element.trigger(ScrollKit.ScrollView.EventType.DidScrollToTop);
|
802
|
+
}, bounceTransitionDuration * 250);
|
803
|
+
},
|
804
|
+
|
805
|
+
_maximumScrollPosition: null, // { x: 0, y: 0 }
|
806
|
+
|
807
|
+
/**
|
808
|
+
|
809
|
+
*/
|
810
|
+
getMaximumScrollPosition: function() { return this._maximumScrollPosition; },
|
811
|
+
|
812
|
+
/**
|
813
|
+
|
814
|
+
*/
|
815
|
+
getIsScrollPositionInBounds: function() {
|
816
|
+
var scrollPosition = this._scrollPosition;
|
817
|
+
var maximumScrollPosition = this._maximumScrollPosition;
|
818
|
+
var clampedX = Math.min(Math.max(0, scrollPosition.x), maximumScrollPosition.x);
|
819
|
+
var clampedY = Math.min(Math.max(0, scrollPosition.y), maximumScrollPosition.y);
|
820
|
+
|
821
|
+
return (scrollPosition.x === clampedX && scrollPosition.y === clampedY);
|
822
|
+
},
|
823
|
+
|
824
|
+
/**
|
825
|
+
|
826
|
+
*/
|
827
|
+
bounceScrollPositionInBounds: function() {
|
828
|
+
var scrollPosition = this._scrollPosition;
|
829
|
+
var maximumScrollPosition = this._maximumScrollPosition;
|
830
|
+
var clampedX = Math.min(Math.max(0, scrollPosition.x), maximumScrollPosition.x);
|
831
|
+
var clampedY = Math.min(Math.max(0, scrollPosition.y), maximumScrollPosition.y);
|
832
|
+
|
833
|
+
this.setScrollPosition(clampedX, clampedY, ScrollKit.Params.bounceTransitionDuration);
|
834
|
+
},
|
835
|
+
|
836
|
+
_lastTransitionDuration: '0s',
|
837
|
+
|
838
|
+
/**
|
839
|
+
|
840
|
+
*/
|
841
|
+
translate: function(x, y, animationDuration) {
|
842
|
+
var margin = this._margin;
|
843
|
+
var translation = (margin.left - x) + 'px, ' + (margin.top - y) + 'px';
|
844
|
+
var duration = (animationDuration || '0') + 's';
|
845
|
+
var vendorPrefix = this._vendorPrefix;
|
846
|
+
var styles = this._contentStyles = this._contentStyles || {};
|
847
|
+
|
848
|
+
// TODO: Change this test to look for 3D transform capability instead of Webkit only.
|
849
|
+
if (vendorPrefix === 'webkit') {
|
850
|
+
if (duration !== this._lastTransitionDuration) this._lastTransitionDuration = styles['-webkit-transition-duration'] = styles['transition-duration'] = duration;
|
851
|
+
styles['-webkit-transform'] = styles['transform'] = 'translate3d(' + translation + ', 0)';
|
852
|
+
}
|
853
|
+
|
854
|
+
else {
|
855
|
+
if (duration !== this._lastTransitionDuration) this._lastTransitionDuration = styles['-' + vendorPrefix + '-transition-duration'] = styles['transition-duration'] = duration;
|
856
|
+
styles['-' + vendorPrefix + '-transform'] = styles['transform'] = 'translate(' + translation + ')';
|
857
|
+
}
|
858
|
+
|
859
|
+
this.$content.css(styles);
|
860
|
+
},
|
861
|
+
|
862
|
+
/**
|
863
|
+
|
864
|
+
*/
|
865
|
+
recalculateDimensions: function() {
|
866
|
+
var $element = this.$element;
|
867
|
+
var $content = this.$content;
|
868
|
+
var size = this._size;
|
869
|
+
var contentSize = this._contentSize;
|
870
|
+
var margin = this._margin;
|
871
|
+
var maximumScrollPosition = this._maximumScrollPosition;
|
872
|
+
|
873
|
+
size.width = $element.width();
|
874
|
+
size.height = $element.height();
|
875
|
+
|
876
|
+
contentSize.width = Math.max($content.width(), size.width) + margin.left + margin.right;
|
877
|
+
contentSize.height = Math.max($content.height(), size.height) + margin.top + margin.bottom;
|
878
|
+
|
879
|
+
maximumScrollPosition.x = contentSize.width - size.width;
|
880
|
+
maximumScrollPosition.y = contentSize.height - size.height;
|
881
|
+
|
882
|
+
$element.trigger('scroll');
|
883
|
+
},
|
884
|
+
|
885
|
+
/**
|
886
|
+
Convenience accessor for jQuery's .bind() method.
|
887
|
+
*/
|
888
|
+
$bind: function() { this.$element.bind.apply(this.$element, arguments); },
|
889
|
+
|
890
|
+
/**
|
891
|
+
Convenience accessor for jQuery's .unbind() method.
|
892
|
+
*/
|
893
|
+
$unbind: function() { this.$element.unbind.apply(this.$element, arguments); },
|
894
|
+
|
895
|
+
/**
|
896
|
+
Convenience accessor for jQuery's .delegate() method.
|
897
|
+
*/
|
898
|
+
$delegate: function() { this.$element.delegate.apply(this.$element, arguments); },
|
899
|
+
|
900
|
+
/**
|
901
|
+
Convenience accessor for jQuery's .undelegate() method.
|
902
|
+
*/
|
903
|
+
$undelegate: function() { this.$element.undelegate.apply(this.$element, arguments); },
|
904
|
+
|
905
|
+
/**
|
906
|
+
Convenience accessor for jQuery's .trigger() method.
|
907
|
+
*/
|
908
|
+
$trigger: function() { this.$element.trigger.apply(this.$element, arguments); }
|
909
|
+
};
|
910
|
+
|
911
|
+
$(function() {
|
912
|
+
$('.sk-scroll-view').each(function(index, element) { new ScrollKit.ScrollView(element); });
|
913
|
+
|
914
|
+
// Set up horizontal page containers to automatically adjust their size when the window resizes.
|
915
|
+
var $window = $(window['addEventListener'] ? window : document.body).bind('resize', function(evt) {
|
916
|
+
resizePageContainers();
|
917
|
+
});
|
918
|
+
var $style = $('<style/>').appendTo($(document.head));
|
919
|
+
var resizePageContainers = function() {
|
920
|
+
$style.html('.sk-page-container-horizontal > li { width: ' + $window.width() + 'px !important; }');
|
921
|
+
};
|
922
|
+
|
923
|
+
resizePageContainers();
|
924
|
+
});
|