├── fullPage.js
├── images
│ ├── 1.jpg
│ ├── 2.jpg
│ ├── 3.jpg
│ └── 4.jpg
├── index3.html
├── index4.html
├── index7.html
├── index2.html
├── index11.html
├── index12.html
├── index13.html
├── index6.html
├── index5.html
├── index.html
├── css
│ └── jquery.fullPage.css
├── index8.html
└── js
│ ├── jquery.fullPage.min.js
│ └── jquery.fullPage.js
├── uploadPic
├── upload
│ └── demo.png
├── test.php
└── index.html
├── 3DRotateBanner
├── images
│ ├── ps.png
│ ├── skype.png
│ ├── word.png
│ ├── firefox.png
│ └── youtube.png
├── css
│ └── demos.css
├── index.html
└── js
│ └── jquery.roundabout.js
└── README.md
/fullPage.js/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/fullPage.js/images/1.jpg
--------------------------------------------------------------------------------
/fullPage.js/images/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/fullPage.js/images/2.jpg
--------------------------------------------------------------------------------
/fullPage.js/images/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/fullPage.js/images/3.jpg
--------------------------------------------------------------------------------
/fullPage.js/images/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/fullPage.js/images/4.jpg
--------------------------------------------------------------------------------
/uploadPic/upload/demo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/uploadPic/upload/demo.png
--------------------------------------------------------------------------------
/3DRotateBanner/images/ps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/3DRotateBanner/images/ps.png
--------------------------------------------------------------------------------
/3DRotateBanner/images/skype.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/3DRotateBanner/images/skype.png
--------------------------------------------------------------------------------
/3DRotateBanner/images/word.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/3DRotateBanner/images/word.png
--------------------------------------------------------------------------------
/3DRotateBanner/images/firefox.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/3DRotateBanner/images/firefox.png
--------------------------------------------------------------------------------
/3DRotateBanner/images/youtube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Mr-houzi/FrontCodeCollection/HEAD/3DRotateBanner/images/youtube.png
--------------------------------------------------------------------------------
/fullPage.js/index3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 背景演示
6 |
7 |
13 |
14 |
15 |
20 |
21 |
22 |
23 |
24 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/fullPage.js/index4.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 循环演示
6 |
7 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
第一屏
27 |
fullPage.js — 循环演示
28 |
29 |
30 |
第二屏
31 |
32 |
33 |
第三屏
34 |
35 |
36 |
第四屏
37 |
这是最后一屏了,继续往下滚返回第一屏
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/uploadPic/test.php:
--------------------------------------------------------------------------------
1 | $value) {
5 | //检验图片是否是通过HTTP POST上传的
6 | if (is_uploaded_file($_FILES['file']['tmp_name'][$key])) {
7 | echo $_FILES['file']['name'][$key]."文件是通过HTTP POST上传的 ";
8 | }else{
9 | echo $_FILES['file']['name'][$key]."文件不是通过HTTP POST上传的";exit;
10 | }
11 |
12 | //检验图片格式
13 | if (($_FILES['file']['type'][$key]=='image/jpeg')
14 | || ($_FILES['file']['type'][$key]=='image/gif')
15 | || ($_FILES['file']['type'][$key]=='image/png')) {
16 |
17 | }else{
18 | echo "图片格式不符合要求 ";
19 | exit;
20 | }
21 | //检验图片大小 图片大小小于1m
22 | if ($_FILES['file']['size'][$key]/1024>=1024) {
23 | echo "图片大小大于1M ";
24 | exit;
25 | }
26 | //移动图片
27 | $uploaddir = 'upload/';
28 | $uploadfile = $uploaddir.basename($_FILES['file']['name'][$key]);
29 | if(move_uploaded_file($_FILES['file']['tmp_name'][$key], $uploadfile)){
30 | echo "上传成功";
31 | }
32 |
33 | }
34 | ?>
--------------------------------------------------------------------------------
/fullPage.js/index7.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 项目导航演示
6 |
7 |
10 |
11 |
12 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
第一屏
27 |
fullPage.js — 项目导航演示
28 |
29 |
30 |
第二屏
31 |
请查看右边的圆圈
32 |
33 |
34 |
第三屏
35 |
圆圈还可以设置位置,颜色,加上 tip,点击可以控制
36 |
37 |
38 |
第四屏
39 |
这是最后一屏
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/fullPage.js/index2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 基本演示
6 |
7 |
10 |
11 |
12 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
第一屏
26 |
fullPage.js — 基本演示
27 |
28 |
29 |
第二屏的第一屏
30 |
第二屏的第二屏
31 |
第二屏的第三屏
32 |
33 |
34 |
第三屏
35 |
36 |
37 |
第四屏
38 |
这是最后一屏
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/fullPage.js/index11.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js演示-自动滚动
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
第一屏
16 |
17 |
18 |
第二屏
19 |
20 |
21 |
第三屏
22 |
23 |
24 |
第四屏
25 |
26 |
27 |
28 |
29 |
30 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/3DRotateBanner/css/demos.css:
--------------------------------------------------------------------------------
1 | html { padding: 0; margin: 0; }
2 | body {
3 | font-family: 'microsoft yahei',Arial,sans-serif;
4 | padding: 0;
5 | margin: 0;
6 | font-size: 1em;
7 | }
8 |
9 | h1 {
10 | font-size: 4em;
11 | letter-spacing: -1px;
12 | margin: 1em 0 0.5em;
13 | text-align: center;
14 | }
15 |
16 | .interact {
17 | border-top: 1px solid #ccc;
18 | margin-top: 3em;
19 | margin-bottom: 4em;
20 | padding-top: 1.5em;
21 | text-align: center;
22 | }
23 |
24 | .interact a {
25 | background-color: #2179b6;
26 | border-bottom: 1px solid #084d7d;
27 | color: #eee;
28 | font-family: "Lucida Grande", "Lucida Sans Unicode", "Helvetica Neue", Arial, sans-serif;
29 | -webkit-border-radius: 8px;
30 | -moz-border-radius: 8px;
31 | -ms-border-radius: 8px;
32 | -o-border-radius: 8px;
33 | border-radius: 8px;
34 | text-decoration: none;
35 | padding: 8px 14px;
36 | margin: 0 1em;
37 | }
38 |
39 | .interact p {
40 | font-style: italic;
41 | color: #666;
42 | }
43 |
44 | .return {
45 | font-size: 1.5em;
46 | text-align: center;
47 | }
48 | .return a {
49 | color: #2179b6;
50 | text-decoration: none;
51 | }
52 | .return a:hover {
53 | text-decoration: underline;
54 | }
--------------------------------------------------------------------------------
/fullPage.js/index12.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js演示-slide自动滚动
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
第一屏
16 |
请滚动到第二屏查看
17 |
18 |
19 |
第二屏的第一屏
20 |
第二屏的第二屏
21 |
第二屏的第三屏
22 |
23 |
24 |
第三屏
25 |
26 |
27 |
第四屏
28 |
29 |
30 |
31 |
32 |
33 |
45 |
46 |
47 |
--------------------------------------------------------------------------------
/fullPage.js/index13.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js演示-响应式
6 |
7 |
10 |
11 |
12 |
13 |
14 |
15 |
根据可视区域大小启用/关闭全屏滚动效果
16 |
17 |
18 |
如果可视区宽度小于1024,则关闭全屏滚动效果,使用自带的滚动条
19 |
20 |
21 |
请试着调整浏览器大小并查看滚动条是否出现
22 |
23 |
26 |
27 |
28 |
29 |
30 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/3DRotateBanner/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | jquery实现3D立体旋转幻灯片特效
6 |
7 |
36 |
37 |
38 | jQuery立体旋转幻灯片演示
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/fullPage.js/index6.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 绑定菜单演示
6 |
7 |
14 |
15 |
16 |
25 |
26 |
27 |
28 |
29 |
35 |
36 |
37 |
38 |
第一屏
39 |
fullPage.js — 绑定菜单演示
40 |
41 |
42 |
第二屏
43 |
请查看左上角,点击可以控制
44 |
45 |
46 |
第三屏
47 |
绑定的菜单没有默认的样式,你需要自行编写
48 |
49 |
50 |
第四屏
51 |
这是最后一屏
52 |
53 |
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/fullPage.js/index5.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — 回调函数演示
6 |
7 |
13 |
14 |
15 |
16 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
第一屏
60 |
fullPage.js — 回调函数演示
61 |
62 |
63 |
第二屏
64 |
滚动到第二屏后的回调函数执行的效果
65 |
66 |
67 |
第三屏
68 |
滚动到第三屏后的回调函数执行的效果
69 |
70 |
71 |
第四屏
72 |
滚动到第四屏后的回调函数执行的效果
73 |
74 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FrontCodeCollection(前端实用代码片段)
2 |
3 | ## [1.图片压缩上传](https://github.com/Mr-houzi/FrontCodeCollection/tree/master/uploadPic)
4 |
5 | ### 演示
6 |
7 | [演示Demo](https://mr-houzi.github.io/FrontCodeCollection/uploadPic/)
8 |
9 | ### 简介
10 |
11 | 之前图片上传用uploadify插件使用,分为两个版本flash免费版和H5收费版,目前手机端都不采用flash,并且H5版收费,个人感觉这个图片上传代码还是比较好的。虽然网上有大神根据uploadify插件H5版改写出了Huploadify并开源,但是这个图片压缩上传代码比较简洁,并且交互和界面也比较美观。(前端压缩未实现)
12 |
13 |
14 | ## [2.3D旋转焦点图](https://github.com/Mr-houzi/FrontCodeCollection/tree/master/3DRotateBanner)
15 |
16 | ### 演示
17 |
18 | [演示Demo](https://mr-houzi.github.io/FrontCodeCollection/3DRotateBanner/)
19 |
20 | ### 简介
21 |
22 | 简洁,轻便的3D旋转焦点图
23 |
24 | ### 用法
25 |
26 | 页面结构:
27 | ```
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 | ```
36 |
37 | jquery代码调用:
38 | ```
39 |
40 |
41 |
46 | ```
47 |
48 | ## [3.全屏滚动-fullPage.js](https://github.com/Mr-houzi/FrontCodeCollection/tree/master/fullPage.js)
49 |
50 | ### 演示
51 |
52 | [演示Demo](https://mr-houzi.github.io/FrontCodeCollection/fullPage.js/)
53 |
54 | ### 简介
55 |
56 | fullPage.js 是一个基于 jQuery 的插件,它能够很方便、很轻松的制作出全屏滚动网站。
57 |
58 | 主要功能有:
59 | - 支持鼠标滚动
60 | - 支持前进后退和键盘控制
61 | - 多个回调函数
62 | - 支持手机、平板触摸事件
63 | - 支持 CSS3 动画
64 | - 支持窗口缩放
65 | - 窗口缩放时自动调整
66 | - 可设置滚动宽度、背景颜色、滚动速度、循环选项、回调、文本对齐方式等等
67 |
68 | ### 用法
69 |
70 | 1、引入文件
71 |
72 | ```
73 |
74 |
75 |
76 | ```
77 |
78 | 如果使用高级功能还需要引入以下文件
79 |
80 | ```
81 |
82 |
83 |
84 |
85 |
86 | ```
87 |
88 | 2、HTML
89 |
90 | ```
91 |
92 |
93 |
第一屏
94 |
95 |
96 |
第二屏
97 |
98 |
99 |
第三屏
100 |
101 |
102 |
第四屏
103 |
104 |
105 | ```
106 |
107 | 每个 section 代表一屏,默认显示“第一屏”,如果要指定加载页面时显示的“屏幕”,可以在对应的 section 加上 class=”active”,如:
108 |
109 | ```
110 | 第三屏
111 | ```
112 |
113 | 同时,可以在 section 内加入 slide,如:
114 |
115 | ```
116 |
117 |
第一屏
118 |
第二屏
119 |
120 |
第三屏的第一屏
121 |
第三屏的第二屏
122 |
第三屏的第三屏
123 |
第三屏的第四屏
124 |
125 |
第四屏
126 |
127 | ```
128 |
129 | 3、JavaScript
130 |
131 | ```
132 | $(function(){
133 | $('#dowebok').fullpage();
134 | });
135 | ```
136 |
137 | 4、其他:配置、方法、回调函数
138 |
139 | 略 [更多请参考此页面](http://www.dowebok.com/77.html)
--------------------------------------------------------------------------------
/fullPage.js/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | jQuery全屏滚动插件fullPage.js演示
6 |
17 |
18 |
19 |
20 | jQuery全屏滚动插件fullPage.js演示
21 |
22 |
23 |
fullPage.js 是一个基于 jQuery 的插件,它能够很方便、很轻松的制作出全屏网站。
24 |
基本演示
25 |
36 |
37 |
综合演示
38 |
47 |
48 |
49 |
60 |
61 |
62 | 更多请参考 >>
63 | 说 明
64 | 下 载
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/fullPage.js/css/jquery.fullPage.css:
--------------------------------------------------------------------------------
1 | /**
2 | * fullPage 2.4.6
3 | * https://github.com/alvarotrigo/fullPage.js
4 | * MIT licensed
5 | *
6 | * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
7 | */
8 | html, body {
9 | margin: 0;
10 | padding: 0;
11 | overflow:hidden;
12 |
13 | /*Avoid flicker on slides transitions for mobile phones #336 */
14 | -webkit-tap-highlight-color: rgba(0,0,0,0);
15 | }
16 | #superContainer {
17 | height: 100%;
18 | position: relative;
19 |
20 | /* Touch detection for Windows 8 */
21 | -ms-touch-action: none;
22 |
23 | /* IE 11 on Windows Phone 8.1*/
24 | touch-action: none;
25 | }
26 | .fp-section {
27 | position: relative;
28 | -webkit-box-sizing: border-box; /* Safari<=5 Android<=3 */
29 | -moz-box-sizing: border-box; /* <=28 */
30 | box-sizing: border-box;
31 | }
32 | .fp-slide {
33 | float: left;
34 | }
35 | .fp-slide, .fp-slidesContainer {
36 | height: 100%;
37 | display: block;
38 | }
39 | .fp-slides {
40 | z-index:1;
41 | height: 100%;
42 | overflow: hidden;
43 | position: relative;
44 | -webkit-transition: all 0.3s ease-out; /* Safari<=6 Android<=4.3 */
45 | transition: all 0.3s ease-out;
46 | }
47 | .fp-section.fp-table, .fp-slide.fp-table {
48 | display: table;
49 | table-layout:fixed;
50 | width: 100%;
51 | }
52 | .fp-tableCell {
53 | display: table-cell;
54 | vertical-align: middle;
55 | width: 100%;
56 | height: 100%;
57 | }
58 | .fp-slidesContainer {
59 | float: left;
60 | position: relative;
61 | }
62 | .fp-controlArrow {
63 | position: absolute;
64 | z-index: 4;
65 | top: 50%;
66 | cursor: pointer;
67 | width: 0;
68 | height: 0;
69 | border-style: solid;
70 | margin-top: -38px;
71 | }
72 | .fp-controlArrow.fp-prev {
73 | left: 15px;
74 | width: 0;
75 | border-width: 38.5px 34px 38.5px 0;
76 | border-color: transparent #fff transparent transparent;
77 | }
78 | .fp-controlArrow.fp-next {
79 | right: 15px;
80 | border-width: 38.5px 0 38.5px 34px;
81 | border-color: transparent transparent transparent #fff;
82 | }
83 | .fp-scrollable {
84 | overflow: scroll;
85 |
86 | }
87 | .fp-notransition {
88 | -webkit-transition: none !important;
89 | transition: none !important;
90 | }
91 | #fp-nav {
92 | position: fixed;
93 | z-index: 100;
94 | margin-top: -32px;
95 | top: 50%;
96 | opacity: 1;
97 | }
98 | #fp-nav.right {
99 | right: 17px;
100 | }
101 | #fp-nav.left {
102 | left: 17px;
103 | }
104 | .fp-slidesNav{
105 | position: absolute;
106 | z-index: 4;
107 | left: 50%;
108 | opacity: 1;
109 | }
110 | .fp-slidesNav.bottom {
111 | bottom: 17px;
112 | }
113 | .fp-slidesNav.top {
114 | top: 17px;
115 | }
116 | #fp-nav ul,
117 | .fp-slidesNav ul {
118 | margin: 0;
119 | padding: 0;
120 | }
121 | #fp-nav ul li,
122 | .fp-slidesNav ul li {
123 | display: block;
124 | width: 14px;
125 | height: 13px;
126 | margin: 7px;
127 | position:relative;
128 | }
129 | .fp-slidesNav ul li {
130 | display: inline-block;
131 | }
132 | #fp-nav ul li a,
133 | .fp-slidesNav ul li a {
134 | display: block;
135 | position: relative;
136 | z-index: 1;
137 | width: 100%;
138 | height: 100%;
139 | cursor: pointer;
140 | text-decoration: none;
141 | }
142 | #fp-nav ul li a.active span,
143 | .fp-slidesNav ul li a.active span {
144 | background: #333;
145 | }
146 | #fp-nav ul li a span,
147 | .fp-slidesNav ul li a span {
148 | top: 2px;
149 | left: 2px;
150 | width: 8px;
151 | height: 8px;
152 | border: 1px solid #000;
153 | background: rgba(0, 0, 0, 0);
154 | border-radius: 50%;
155 | position: absolute;
156 | z-index: 1;
157 | }
158 | #fp-nav ul li .fp-tooltip {
159 | position: absolute;
160 | top: -2px;
161 | color: #fff;
162 | font-size: 14px;
163 | font-family: arial, helvetica, sans-serif;
164 | white-space: nowrap;
165 | max-width: 220px;
166 | overflow: hidden;
167 | display: block;
168 | opacity: 0;
169 | width: 0;
170 | }
171 | #fp-nav ul li:hover .fp-tooltip {
172 | -webkit-transition: opacity 0.2s ease-in;
173 | transition: opacity 0.2s ease-in;
174 | width: auto;
175 | opacity: 1;
176 | }
177 | #fp-nav ul li .fp-tooltip.right {
178 | right: 20px;
179 | }
180 | #fp-nav ul li .fp-tooltip.left {
181 | left: 20px;
182 | }
183 |
--------------------------------------------------------------------------------
/fullPage.js/index8.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | fullPage.js — iPhone 5C演示
6 |
7 |
54 |
55 |
56 |
57 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
fullPage.js — iPhone 5C演示
109 |
110 |
111 |
112 |
113 |
114 |
119 |
120 |
121 |
A powerful plugin
122 | fullPage.js callbacks allow you to create amazing dynamic sites with a bit of imagination. This example tries to reproduce the Apple iPhone-5c website animations as an example of what fullPage.js is capable of.
123 |
124 |
125 |
126 |
127 |
128 |
129 |
134 |
135 |
136 |
Amazing stuff
137 | Combining fullPage.js with your own CSS styles and animations, you will be able to create something remarkable.
138 |
139 |
140 |
141 |
142 |
143 |
144 |
Just a demo
145 | This is, of course, just a demo. I didn't want to spend much time on it.
146 | Don't expect it to work perfectly in all kind of screens.
147 | It has been designed to work on 1180px width or over on modern browsers with CSS3.
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
--------------------------------------------------------------------------------
/uploadPic/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 图片压缩上传
7 |
25 |
26 |
27 |
37 |
38 |
39 |
270 |
271 |
--------------------------------------------------------------------------------
/fullPage.js/js/jquery.fullPage.min.js:
--------------------------------------------------------------------------------
1 | /**
2 | * fullPage 2.5.4
3 | * https://github.com/alvarotrigo/fullPage.js
4 | * MIT licensed
5 | *
6 | * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
7 | */
8 | (function(b){b.fn.fullpage=function(c){function pa(a){a.find(".fp-slides").after('
');"#fff"!=c.controlArrowColor&&(a.find(".fp-controlArrow.fp-next").css("border-color","transparent transparent transparent "+c.controlArrowColor),a.find(".fp-controlArrow.fp-prev").css("border-color","transparent "+c.controlArrowColor+" transparent transparent"));c.loopHorizontal||a.find(".fp-controlArrow.fp-prev").hide()}function qa(){b("body").append('');
9 | k=b("#fp-nav");k.css("color",c.navigationColor);k.addClass(c.navigationPosition);for(var a=0;a ',e=c.navigationTooltips[a];void 0!=e&&""!=e&&(d+=''+e+"
");d+="";k.find("ul").append(d)}}function R(){b(".fp-section").each(function(){var a=b(this).find(".fp-slide");a.length?a.each(function(){y(b(this))}):y(b(this))});b.isFunction(c.afterRender)&&
10 | c.afterRender.call(this)}function S(){if(!c.autoScrolling||c.scrollBar){var a=b(window).scrollTop(),d=0,e=Math.abs(a-b(".fp-section").first().offset().top);b(".fp-section").each(function(c){var f=Math.abs(a-b(this).offset().top);f=d[0].scrollHeight:void 0,c)f();else return!0;else f()}}function sa(a){var d=a.originalEvent;if(!W(a.target)){c.autoScrolling&&!c.scrollBar&&a.preventDefault();a=b(".fp-section.active");var e=V(a);m||t||(d=X(d),u=d.y,A=d.x,a.find(".fp-slides").length&&Math.abs(B-A)>Math.abs(v-u)?Math.abs(B-A)>b(window).width()/100*c.touchSensitivity&&
13 | (B>A?l.right&&b.fn.fullpage.moveSlideRight():l.left&&b.fn.fullpage.moveSlideLeft()):c.autoScrolling&&!c.scrollBar&&Math.abs(v-u)>b(window).height()/100*c.touchSensitivity&&(v>u?z("down",e):u>v&&z("up",e)))}}function W(a,d){d=d||0;var e=b(a).parent();return dd?z("down",a):z("up",a));return!1}}function Y(a){var d=b(".fp-section.active").find(".fp-slides");if(d.length&&!t){var e=d.find(".fp-slide.active"),f=null,f="prev"===a?e.prev(".fp-slide"):e.next(".fp-slide");if(!f.length){if(!c.loopHorizontal)return;f="prev"===a?e.siblings(":last"):e.siblings(":first")}t=!0;w(d,f)}}function Z(){b(".fp-slide.active").each(function(){J(b(this))})}
15 | function q(a,d,e){var f=a.position();if("undefined"!==typeof f&&(d={element:a,callback:d,isMovementUp:e,dest:f,dtop:f.top,yMovement:G(a),anchorLink:a.data("anchor"),sectionIndex:a.index(".fp-section"),activeSlide:a.find(".fp-slide.active"),activeSection:b(".fp-section.active"),leavingSection:b(".fp-section.active").index(".fp-section")+1,localIsResizing:x},!(d.activeSection.is(a)&&!x||c.scrollBar&&b(window).scrollTop()===d.dtop))){if(d.activeSlide.length)var g=d.activeSlide.data("anchor"),h=d.activeSlide.index();
16 | c.autoScrolling&&c.continuousVertical&&"undefined"!==typeof d.isMovementUp&&(!d.isMovementUp&&"up"==d.yMovement||d.isMovementUp&&"down"==d.yMovement)&&(d.isMovementUp?b(".fp-section.active").before(d.activeSection.nextAll(".fp-section")):b(".fp-section.active").after(d.activeSection.prevAll(".fp-section").get().reverse()),n(b(".fp-section.active").position().top),Z(),d.wrapAroundElements=d.activeSection,d.dest=d.element.position(),d.dtop=d.dest.top,d.yMovement=G(d.element));a.addClass("active").siblings().removeClass("active");
17 | m=!0;I(h,g,d.anchorLink,d.sectionIndex);b.isFunction(c.onLeave)&&!d.localIsResizing&&c.onLeave.call(this,d.leavingSection,d.sectionIndex+1,d.yMovement);ua(d);p=d.anchorLink;c.autoScrolling&&H(d.anchorLink,d.sectionIndex)}}function ua(a){if(c.css3&&c.autoScrolling&&!c.scrollBar)aa("translate3d(0px, -"+a.dtop+"px, 0px)",!0),setTimeout(function(){ba(a)},c.scrollingSpeed);else{var d=va(a);b(d.element).animate(d.options,c.scrollingSpeed,c.easing).promise().done(function(){ba(a)})}}function va(a){var b=
18 | {};c.autoScrolling&&!c.scrollBar?(b.options={top:-a.dtop},b.element="."+ca):(b.options={scrollTop:a.dtop},b.element="html, body");return b}function wa(a){a.wrapAroundElements&&a.wrapAroundElements.length&&(a.isMovementUp?b(".fp-section:first").before(a.wrapAroundElements):b(".fp-section:last").after(a.wrapAroundElements),n(b(".fp-section.active").position().top),Z())}function ba(a){wa(a);b.isFunction(c.afterLoad)&&!a.localIsResizing&&c.afterLoad.call(this,a.anchorLink,a.sectionIndex+1);setTimeout(function(){m=
19 | !1;b.isFunction(a.callback)&&a.callback.call(this)},600)}function da(){if(!F){var a=window.location.hash.replace("#","").split("/"),b=a[0],a=a[1];if(b.length){var c="undefined"===typeof p,f="undefined"===typeof p&&"undefined"===typeof a&&!t;(b&&b!==p&&!c||f||!t&&K!=a)&&L(b,a)}}}function w(a,d){var e=d.position(),f=a.find(".fp-slidesContainer").parent(),g=d.index(),h=a.closest(".fp-section"),k=h.index(".fp-section"),l=h.data("anchor"),n=h.find(".fp-slidesNav"),m=d.data("anchor"),q=x;if(c.onSlideLeave){var p=
20 | h.find(".fp-slide.active").index(),r;r=p==g?"none":p>g?"left":"right";q||"none"===r||b.isFunction(c.onSlideLeave)&&c.onSlideLeave.call(this,l,k+1,p,r)}d.addClass("active").siblings().removeClass("active");"undefined"===typeof m&&(m=g);!c.loopHorizontal&&c.controlArrows&&(h.find(".fp-controlArrow.fp-prev").toggle(0!=g),h.find(".fp-controlArrow.fp-next").toggle(!d.is(":last-child")));h.hasClass("active")&&I(g,m,l,k);var u=function(){q||b.isFunction(c.afterSlideLoad)&&c.afterSlideLoad.call(this,l,k+
21 | 1,m,g);t=!1};c.css3?(e="translate3d(-"+e.left+"px, 0px, 0px)",ea(a.find(".fp-slidesContainer"),020*Math.max(M,a)/100&&(b.fn.fullpage.reBuild(!0),
22 | M=a)}}else clearTimeout(ia),ia=setTimeout(function(){b.fn.fullpage.reBuild(!0)},500)}function ha(){if(c.responsive){var a=g.hasClass("fp-responsive");b(window).width()a||900>d){var c=Math.min(100*a/825,100*d/900).toFixed(2);b("body").css("font-size",c+"%")}else b("body").css("font-size","100%")}function H(a,d){c.menu&&(b(c.menu).find(".active").removeClass("active"),b(c.menu).find('[data-menuanchor="'+a+'"]').addClass("active"));c.navigation&&(b("#fp-nav").find(".active").removeClass("active"),a?b("#fp-nav").find('a[href="#'+a+'"]').addClass("active"):b("#fp-nav").find("li").eq(d).find("a").addClass("active"))}
24 | function G(a){var d=b(".fp-section.active").index(".fp-section");a=a.index(".fp-section");return d==a?"none":d>a?"up":"down"}function y(a){a.css("overflow","hidden");var b=a.closest(".fp-section"),e=a.find(".fp-scrollable");if(e.length)var f=e.get(0).scrollHeight;else f=a.get(0).scrollHeight,c.verticalCentered&&(f=a.find(".fp-tableCell").get(0).scrollHeight);b=h-parseInt(b.css("padding-bottom"))-parseInt(b.css("padding-top"));f>b?e.length?e.css("height",b+"px").parent().css("height",b+"px"):(c.verticalCentered?
25 | a.find(".fp-tableCell").wrapInner('
'):a.wrapInner('
'),a.find(".fp-scrollable").slimScroll({allowPageScroll:!0,height:b+"px",size:"10px",alwaysVisible:!0})):ja(a);a.css("overflow","")}function ja(a){a.find(".fp-scrollable").children().first().unwrap().unwrap();a.find(".slimScrollBar").remove();a.find(".slimScrollRail").remove()}function ka(a){a.addClass("fp-table").wrapInner('
')}function la(a){var b=
26 | h;if(c.paddingTop||c.paddingBottom)b=a,b.hasClass("fp-section")||(b=a.closest(".fp-section")),a=parseInt(b.css("padding-top"))+parseInt(b.css("padding-bottom")),b=h-a;return b}function aa(a,b){b?ea(g):O(g);g.css(fa(a));setTimeout(function(){g.removeClass("fp-notransition")},10)}function L(a,d){"undefined"===typeof d&&(d=0);var c=isNaN(a)?b('[data-anchor="'+a+'"]'):b(".fp-section").eq(a-1);a===p||c.hasClass("active")?ma(c,d):q(c,function(){ma(c,d)})}function ma(a,b){if("undefined"!=typeof b){var c=
27 | a.find(".fp-slides"),f=c.find('[data-anchor="'+b+'"]');f.length||(f=c.find(".fp-slide").eq(b));f.length&&w(c,f)}}function ya(a,b){a.append('');var e=a.find(".fp-slidesNav");e.addClass(c.slidesNavPosition);for(var f=0;f ');e.css("margin-left","-"+e.width()/2+"px");e.find("li").first().find("a").addClass("active")}function I(a,b,e,f){var g="";c.anchors.length?(a?("undefined"!==typeof e&&(g=e),"undefined"===
28 | typeof b&&(b=a),K=b,na(g+"/"+b)):("undefined"!==typeof a&&(K=b),na(e)),D(location.hash)):"undefined"!==typeof a?D(f+"-"+a):D(String(f))}function na(a){if(c.recordHistory)location.hash=a;else if(C||P)history.replaceState(void 0,void 0,"#"+a);else{var b=window.location.href.split("#")[0];window.location.replace(b+"#"+a)}}function D(a){a=a.replace("/","-").replace("#","");b("body")[0].className=b("body")[0].className.replace(/\b\s?fp-viewing-[^\s]+\b/g,"");b("body").addClass("fp-viewing-"+a)}function za(){var a=
29 | document.createElement("p"),b,c={webkitTransform:"-webkit-transform",OTransform:"-o-transform",msTransform:"-ms-transform",MozTransform:"-moz-transform",transform:"transform"};document.body.insertBefore(a,null);for(var f in c)void 0!==a.style[f]&&(a.style[f]="translate3d(1px,1px,1px)",b=window.getComputedStyle(a).getPropertyValue(c[f]));document.body.removeChild(a);return void 0!==b&&0 ');e.parent().wrap('
');b(this).find(".fp-slidesContainer").css("width",a+"%");c.controlArrows&&pa(b(this));c.slidesNavigation&&ya(b(this),f);e.each(function(a){b(this).css("width",
44 | g+"%");c.verticalCentered&&ka(b(this))});d=d.find(".fp-slide.active");0==d.length?e.eq(0).addClass("active"):J(d)}else c.verticalCentered&&ka(b(this))}).promise().done(function(){b.fn.fullpage.setAutoScrolling(c.autoScrolling,"internal");var a=b(".fp-section.active").find(".fp-slide.active");a.length&&(0!=b(".fp-section.active").index(".fp-section")||0==b(".fp-section.active").index(".fp-section")&&0!=a.index())&&J(a);c.fixedElements&&c.css3&&b(c.fixedElements).appendTo("body");c.navigation&&(k.css("margin-top",
45 | "-"+k.height()/2+"px"),k.find("li").eq(b(".fp-section.active").index(".fp-section")).find("a").addClass("active"));c.menu&&c.css3&&b(c.menu).closest(".fullpage-wrapper").length&&b(c.menu).appendTo("body");c.scrollOverflow?("complete"===document.readyState&&R(),b(window).on("load",R)):b.isFunction(c.afterRender)&&c.afterRender.call(this);ha();a=window.location.hash.replace("#","").split("/")[0];if(a.length){var d=b('[data-anchor="'+a+'"]');!c.animateAnchor&&d.length&&(c.autoScrolling?n(d.position().top):
46 | (n(0),D(a),b("html, body").scrollTop(d.position().top)),H(a,null),b.isFunction(c.afterLoad)&&c.afterLoad.call(this,a,d.index(".fp-section")+1),d.addClass("active").siblings().removeClass("active"))}b(window).on("load",function(){var a=window.location.hash.replace("#","").split("/"),b=a[0],a=a[1];b&&L(b,a)})});var T,U,F=!1;b(window).on("scroll",S);var v=0,B=0,u=0,A=0;b(window).on("hashchange",da);b(document).keydown(function(a){if(c.keyboardScrolling&&c.autoScrolling&&(40!=a.which&&38!=a.which||a.preventDefault(),
47 | !m))switch(a.which){case 38:case 33:b.fn.fullpage.moveSectionUp();break;case 40:case 34:b.fn.fullpage.moveSectionDown();break;case 36:b.fn.fullpage.moveTo(1);break;case 35:b.fn.fullpage.moveTo(b(".fp-section").length);break;case 37:b.fn.fullpage.moveSlideLeft();break;case 39:b.fn.fullpage.moveSlideRight()}});b(document).on("click touchstart","#fp-nav a",function(a){a.preventDefault();a=b(this).parent().index();q(b(".fp-section").eq(a))});b(document).on("click touchstart",".fp-slidesNav a",function(a){a.preventDefault();
48 | a=b(this).closest(".fp-section").find(".fp-slides");var c=a.find(".fp-slide").eq(b(this).closest("li").index());w(a,c)});c.normalScrollElements&&(b(document).on("mouseenter",c.normalScrollElements,function(){b.fn.fullpage.setMouseWheelScrolling(!1)}),b(document).on("mouseleave",c.normalScrollElements,function(){b.fn.fullpage.setMouseWheelScrolling(!0)}));b(".fp-section").on("click touchstart",".fp-controlArrow",function(){b(this).hasClass("fp-prev")?b.fn.fullpage.moveSlideLeft():b.fn.fullpage.moveSlideRight()});
49 | b(window).resize(ga);var M=h,ia;b.fn.fullpage.destroy=function(a){b.fn.fullpage.setAutoScrolling(!1,"internal");b.fn.fullpage.setAllowScrolling(!1);b.fn.fullpage.setKeyboardScrolling(!1);b(window).off("scroll",S).off("hashchange",da).off("resize",ga);b(document).off("click","#fp-nav a").off("mouseenter","#fp-nav li").off("mouseleave","#fp-nav li").off("click",".fp-slidesNav a").off("mouseover",c.normalScrollElements).off("mouseout",c.normalScrollElements);b(".fp-section").off("click",".fp-controlArrow");
50 | a&&Aa()}}})(jQuery);
--------------------------------------------------------------------------------
/3DRotateBanner/js/jquery.roundabout.js:
--------------------------------------------------------------------------------
1 | /**
2 | * jQuery Roundabout - v2.4.2
3 | * http://fredhq.com/projects/roundabout
4 | *
5 | * Moves list-items of enabled ordered and unordered lists long
6 | * a chosen path. Includes the default "lazySusan" path, that
7 | * moves items long a spinning turntable.
8 | *
9 | * Terms of Use // jQuery Roundabout
10 | *
11 | * Open source under the BSD license
12 | *
13 | * Copyright (c) 2011-2012, Fred LeBlanc
14 | * All rights reserved.
15 | *
16 | * Redistribution and use in source and binary forms, with or without
17 | * modification, are permitted provided that the following conditions are met:
18 | *
19 | * - Redistributions of source code must retain the above copyright
20 | * notice, this list of conditions and the following disclaimer.
21 | * - Redistributions in binary form must reproduce the above
22 | * copyright notice, this list of conditions and the following
23 | * disclaimer in the documentation and/or other materials provided
24 | * with the distribution.
25 | * - Neither the name of the author nor the names of its contributors
26 | * may be used to endorse or promote products derived from this
27 | * software without specific prior written permission.
28 | *
29 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
30 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
33 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
34 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
35 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
36 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
37 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39 | * POSSIBILITY OF SUCH DAMAGE.
40 | */
41 | (function($) {
42 | "use strict";
43 |
44 | var defaults, internalData, methods;
45 |
46 | // add default shape
47 | $.extend({
48 | roundaboutShapes: {
49 | def: "lazySusan",
50 | lazySusan: function (r, a, t) {
51 | return {
52 | x: Math.sin(r + a),
53 | y: (Math.sin(r + 3 * Math.PI / 2 + a) / 8) * t,
54 | z: (Math.cos(r + a) + 1) / 2,
55 | scale: (Math.sin(r + Math.PI / 2 + a) / 2) + 0.5
56 | };
57 | }
58 | }
59 | });
60 |
61 | defaults = {
62 | bearing: 0.0,
63 | tilt: 0.0,
64 | minZ: 100,
65 | maxZ: 280,
66 | minOpacity: 0.4,
67 | maxOpacity: 1.0,
68 | minScale: 0.4,
69 | maxScale: 1.0,
70 | duration: 600,
71 | btnNext: null,
72 | btnNextCallback: function() {},
73 | btnPrev: null,
74 | btnPrevCallback: function() {},
75 | btnToggleAutoplay: null,
76 | btnStartAutoplay: null,
77 | btnStopAutoplay: null,
78 | easing: "swing",
79 | clickToFocus: true,
80 | clickToFocusCallback: function() {},
81 | focusBearing: 0.0,
82 | shape: "lazySusan",
83 | debug: false,
84 | childSelector: "li",
85 | startingChild: null,
86 | reflect: false,
87 | floatComparisonThreshold: 0.001,
88 | autoplay: false,
89 | autoplayDuration: 1000,
90 | autoplayPauseOnHover: false,
91 | autoplayCallback: function() {},
92 | autoplayInitialDelay: 0,
93 | enableDrag: false,
94 | dropDuration: 600,
95 | dropEasing: "swing",
96 | dropAnimateTo: "nearest",
97 | dropCallback: function() {},
98 | dragAxis: "x",
99 | dragFactor: 4,
100 | triggerFocusEvents: true,
101 | triggerBlurEvents: true,
102 | responsive: false
103 | };
104 |
105 | internalData = {
106 | autoplayInterval: null,
107 | autoplayIsRunning: false,
108 | autoplayStartTimeout: null,
109 | animating: false,
110 | childInFocus: -1,
111 | touchMoveStartPosition: null,
112 | stopAnimation: false,
113 | lastAnimationStep: false
114 | };
115 |
116 | methods = {
117 |
118 | // starters
119 | // -----------------------------------------------------------------------
120 |
121 | // init
122 | // starts up roundabout
123 | init: function(options, callback, relayout) {
124 | var settings,
125 | now = (new Date()).getTime();
126 |
127 | options = (typeof options === "object") ? options : {};
128 | callback = ($.isFunction(callback)) ? callback : function() {};
129 | callback = ($.isFunction(options)) ? options : callback;
130 | settings = $.extend({}, defaults, options, internalData);
131 |
132 | return this
133 | .each(function() {
134 | // make options
135 | var self = $(this),
136 | childCount = self.children(settings.childSelector).length,
137 | period = 360.0 / childCount,
138 | startingChild = (settings.startingChild && settings.startingChild > (childCount - 1)) ? (childCount - 1) : settings.startingChild,
139 | startBearing = (settings.startingChild === null) ? settings.bearing : 360 - (startingChild * period),
140 | holderCSSPosition = (self.css("position") !== "static") ? self.css("position") : "relative";
141 |
142 | self
143 | .css({ // starting styles
144 | padding: 0,
145 | position: holderCSSPosition
146 | })
147 | .addClass("roundabout-holder")
148 | .data( // starting options
149 | "roundabout",
150 | $.extend(
151 | {},
152 | settings,
153 | {
154 | startingChild: startingChild,
155 | bearing: startBearing,
156 | oppositeOfFocusBearing: methods.normalize.apply(null, [settings.focusBearing - 180]),
157 | dragBearing: startBearing,
158 | period: period
159 | }
160 | )
161 | );
162 |
163 | // unbind any events that we set if we're relaying out
164 | if (relayout) {
165 | self
166 | .unbind(".roundabout")
167 | .children(settings.childSelector)
168 | .unbind(".roundabout");
169 | } else {
170 | // bind responsive action
171 | if (settings.responsive) {
172 | $(window).bind("resize", function() {
173 | methods.stopAutoplay.apply(self);
174 | methods.relayoutChildren.apply(self);
175 | });
176 | }
177 | }
178 |
179 | // bind click-to-focus
180 | if (settings.clickToFocus) {
181 | self
182 | .children(settings.childSelector)
183 | .each(function(i) {
184 | $(this)
185 | .bind("click.roundabout", function() {
186 | var degrees = methods.getPlacement.apply(self, [i]);
187 |
188 | if (!methods.isInFocus.apply(self, [degrees])) {
189 | methods.stopAnimation.apply($(this));
190 | if (!self.data("roundabout").animating) {
191 | methods.animateBearingToFocus.apply(self, [degrees, self.data("roundabout").clickToFocusCallback]);
192 | }
193 | return false;
194 | }
195 | });
196 | });
197 | }
198 |
199 | // bind next buttons
200 | if (settings.btnNext) {
201 | $(settings.btnNext)
202 | .bind("click.roundabout", function() {
203 | if (!self.data("roundabout").animating) {
204 | methods.animateToNextChild.apply(self, [self.data("roundabout").btnNextCallback]);
205 | }
206 | return false;
207 | });
208 | }
209 |
210 | // bind previous buttons
211 | if (settings.btnPrev) {
212 | $(settings.btnPrev)
213 | .bind("click.roundabout", function() {
214 | methods.animateToPreviousChild.apply(self, [self.data("roundabout").btnPrevCallback]);
215 | return false;
216 | });
217 | }
218 |
219 | // bind toggle autoplay buttons
220 | if (settings.btnToggleAutoplay) {
221 | $(settings.btnToggleAutoplay)
222 | .bind("click.roundabout", function() {
223 | methods.toggleAutoplay.apply(self);
224 | return false;
225 | });
226 | }
227 |
228 | // bind start autoplay buttons
229 | if (settings.btnStartAutoplay) {
230 | $(settings.btnStartAutoplay)
231 | .bind("click.roundabout", function() {
232 | methods.startAutoplay.apply(self);
233 | return false;
234 | });
235 | }
236 |
237 | // bind stop autoplay buttons
238 | if (settings.btnStopAutoplay) {
239 | $(settings.btnStopAutoplay)
240 | .bind("click.roundabout", function() {
241 | methods.stopAutoplay.apply(self);
242 | return false;
243 | });
244 | }
245 |
246 | // autoplay pause on hover
247 | if (settings.autoplayPauseOnHover) {
248 | self
249 | .bind("mouseenter.roundabout.autoplay", function() {
250 | methods.stopAutoplay.apply(self, [true]);
251 | })
252 | .bind("mouseleave.roundabout.autoplay", function() {
253 | methods.startAutoplay.apply(self);
254 | });
255 | }
256 |
257 | // drag and drop
258 | if (settings.enableDrag) {
259 | // on screen
260 | if (!$.isFunction(self.drag)) {
261 | if (settings.debug) {
262 | alert("You do not have the drag plugin loaded.");
263 | }
264 | } else if (!$.isFunction(self.drop)) {
265 | if (settings.debug) {
266 | alert("You do not have the drop plugin loaded.");
267 | }
268 | } else {
269 | self
270 | .drag(function(e, properties) {
271 | var data = self.data("roundabout"),
272 | delta = (data.dragAxis.toLowerCase() === "x") ? "deltaX" : "deltaY";
273 | methods.stopAnimation.apply(self);
274 | methods.setBearing.apply(self, [data.dragBearing + properties[delta] / data.dragFactor]);
275 | })
276 | .drop(function(e) {
277 | var data = self.data("roundabout"),
278 | method = methods.getAnimateToMethod(data.dropAnimateTo);
279 | methods.allowAnimation.apply(self);
280 | methods[method].apply(self, [data.dropDuration, data.dropEasing, data.dropCallback]);
281 | data.dragBearing = data.period * methods.getNearestChild.apply(self);
282 | });
283 | }
284 |
285 | // on mobile
286 | self
287 | .each(function() {
288 | var element = $(this).get(0),
289 | data = $(this).data("roundabout"),
290 | page = (data.dragAxis.toLowerCase() === "x") ? "pageX" : "pageY",
291 | method = methods.getAnimateToMethod(data.dropAnimateTo);
292 |
293 | // some versions of IE don't like this
294 | if (element.addEventListener) {
295 | element.addEventListener("touchstart", function(e) {
296 | data.touchMoveStartPosition = e.touches[0][page];
297 | }, false);
298 |
299 | element.addEventListener("touchmove", function(e) {
300 | var delta = (e.touches[0][page] - data.touchMoveStartPosition) / data.dragFactor;
301 | e.preventDefault();
302 | methods.stopAnimation.apply($(this));
303 | methods.setBearing.apply($(this), [data.dragBearing + delta]);
304 | }, false);
305 |
306 | element.addEventListener("touchend", function(e) {
307 | e.preventDefault();
308 | methods.allowAnimation.apply($(this));
309 | method = methods.getAnimateToMethod(data.dropAnimateTo);
310 | methods[method].apply($(this), [data.dropDuration, data.dropEasing, data.dropCallback]);
311 | data.dragBearing = data.period * methods.getNearestChild.apply($(this));
312 | }, false);
313 | }
314 | });
315 | }
316 |
317 | // start children
318 | methods.initChildren.apply(self, [callback, relayout]);
319 | });
320 | },
321 |
322 |
323 | // initChildren
324 | // applys settings to child elements, starts roundabout
325 | initChildren: function(callback, relayout) {
326 | var self = $(this),
327 | data = self.data("roundabout");
328 |
329 | callback = callback || function() {};
330 |
331 | self.children(data.childSelector).each(function(i) {
332 | var startWidth, startHeight, startFontSize,
333 | degrees = methods.getPlacement.apply(self, [i]);
334 |
335 | // on relayout, grab these values from current data
336 | if (relayout && $(this).data("roundabout")) {
337 | startWidth = $(this).data("roundabout").startWidth;
338 | startHeight = $(this).data("roundabout").startHeight;
339 | startFontSize = $(this).data("roundabout").startFontSize;
340 | }
341 |
342 | // apply classes and css first
343 | $(this)
344 | .addClass("roundabout-moveable-item")
345 | .css("position", "absolute");
346 |
347 | // now measure
348 | $(this)
349 | .data(
350 | "roundabout",
351 | {
352 | startWidth: startWidth || $(this).width(),
353 | startHeight: startHeight || $(this).height(),
354 | startFontSize: startFontSize || parseInt($(this).css("font-size"), 10),
355 | degrees: degrees,
356 | backDegrees: methods.normalize.apply(null, [degrees - 180]),
357 | childNumber: i,
358 | currentScale: 1,
359 | parent: self
360 | }
361 | );
362 | });
363 |
364 | methods.updateChildren.apply(self);
365 |
366 | // start autoplay if necessary
367 | if (data.autoplay) {
368 | data.autoplayStartTimeout = setTimeout(function() {
369 | methods.startAutoplay.apply(self);
370 | }, data.autoplayInitialDelay);
371 | }
372 |
373 | self.trigger('ready');
374 | callback.apply(self);
375 | return self;
376 | },
377 |
378 |
379 |
380 | // positioning
381 | // -----------------------------------------------------------------------
382 |
383 | // updateChildren
384 | // move children elements into their proper locations
385 | updateChildren: function() {
386 | return this
387 | .each(function() {
388 | var self = $(this),
389 | data = self.data("roundabout"),
390 | inFocus = -1,
391 | info = {
392 | bearing: data.bearing,
393 | tilt: data.tilt,
394 | stage: {
395 | width: Math.floor($(this).width() * 0.9),
396 | height: Math.floor($(this).height() * 0.9)
397 | },
398 | animating: data.animating,
399 | inFocus: data.childInFocus,
400 | focusBearingRadian: methods.degToRad.apply(null, [data.focusBearing]),
401 | shape: $.roundaboutShapes[data.shape] || $.roundaboutShapes[$.roundaboutShapes.def]
402 | };
403 |
404 | // calculations
405 | info.midStage = {
406 | width: info.stage.width / 2,
407 | height: info.stage.height / 2
408 | };
409 |
410 | info.nudge = {
411 | width: info.midStage.width + (info.stage.width * 0.05),
412 | height: info.midStage.height + (info.stage.height * 0.05)
413 | };
414 |
415 | info.zValues = {
416 | min: data.minZ,
417 | max: data.maxZ,
418 | diff: data.maxZ - data.minZ
419 | };
420 |
421 | info.opacity = {
422 | min: data.minOpacity,
423 | max: data.maxOpacity,
424 | diff: data.maxOpacity - data.minOpacity
425 | };
426 |
427 | info.scale = {
428 | min: data.minScale,
429 | max: data.maxScale,
430 | diff: data.maxScale - data.minScale
431 | };
432 |
433 | // update child positions
434 | self.children(data.childSelector)
435 | .each(function(i) {
436 | if (methods.updateChild.apply(self, [$(this), info, i, function() { $(this).trigger('ready'); }]) && (!info.animating || data.lastAnimationStep)) {
437 | inFocus = i;
438 | $(this).addClass("roundabout-in-focus");
439 | } else {
440 | $(this).removeClass("roundabout-in-focus");
441 | }
442 | });
443 |
444 | if (inFocus !== info.inFocus) {
445 | // blur old child
446 | if (data.triggerBlurEvents) {
447 | self.children(data.childSelector)
448 | .eq(info.inFocus)
449 | .trigger("blur");
450 | }
451 |
452 | data.childInFocus = inFocus;
453 |
454 | if (data.triggerFocusEvents && inFocus !== -1) {
455 | // focus new child
456 | self.children(data.childSelector)
457 | .eq(inFocus)
458 | .trigger("focus");
459 | }
460 | }
461 |
462 | self.trigger("childrenUpdated");
463 | });
464 | },
465 |
466 |
467 | // updateChild
468 | // repositions a child element into its new position
469 | updateChild: function(childElement, info, childPos, callback) {
470 | var factors,
471 | self = this,
472 | child = $(childElement),
473 | data = child.data("roundabout"),
474 | out = [],
475 | rad = methods.degToRad.apply(null, [(360.0 - data.degrees) + info.bearing]);
476 |
477 | callback = callback || function() {};
478 |
479 | // adjust radians to be between 0 and Math.PI * 2
480 | rad = methods.normalizeRad.apply(null, [rad]);
481 |
482 | // get factors from shape
483 | factors = info.shape(rad, info.focusBearingRadian, info.tilt);
484 |
485 | // correct
486 | factors.scale = (factors.scale > 1) ? 1 : factors.scale;
487 | factors.adjustedScale = (info.scale.min + (info.scale.diff * factors.scale)).toFixed(4);
488 | factors.width = (factors.adjustedScale * data.startWidth).toFixed(4);
489 | factors.height = (factors.adjustedScale * data.startHeight).toFixed(4);
490 |
491 | // update item
492 | child
493 | .css({
494 | left: ((factors.x * info.midStage.width + info.nudge.width) - factors.width / 2.0).toFixed(0) + "px",
495 | top: ((factors.y * info.midStage.height + info.nudge.height) - factors.height / 2.0).toFixed(0) + "px",
496 | width: factors.width + "px",
497 | height: factors.height + "px",
498 | opacity: (info.opacity.min + (info.opacity.diff * factors.scale)).toFixed(2),
499 | zIndex: Math.round(info.zValues.min + (info.zValues.diff * factors.z)),
500 | fontSize: (factors.adjustedScale * data.startFontSize).toFixed(1) + "px"
501 | });
502 | data.currentScale = factors.adjustedScale;
503 |
504 | // for debugging purposes
505 | if (self.data("roundabout").debug) {
506 | out.push("");
507 | out.push("Child " + childPos + " ");
508 | out.push("left: " + child.css("left") + " ");
509 | out.push("top: " + child.css("top") + " ");
510 | out.push("width: " + child.css("width") + " ");
511 | out.push("opacity: " + child.css("opacity") + " ");
512 | out.push("height: " + child.css("height") + " ");
513 | out.push("z-index: " + child.css("z-index") + " ");
514 | out.push("font-size: " + child.css("font-size") + " ");
515 | out.push("scale: " + child.data("roundabout").currentScale);
516 | out.push("
");
517 |
518 | child.html(out.join(""));
519 | }
520 |
521 | // trigger event
522 | child.trigger("reposition");
523 |
524 | // callback
525 | callback.apply(self);
526 |
527 | return methods.isInFocus.apply(self, [data.degrees]);
528 | },
529 |
530 |
531 |
532 | // manipulation
533 | // -----------------------------------------------------------------------
534 |
535 | // setBearing
536 | // changes the bearing of the roundabout
537 | setBearing: function(bearing, callback) {
538 | callback = callback || function() {};
539 | bearing = methods.normalize.apply(null, [bearing]);
540 |
541 | this
542 | .each(function() {
543 | var diff, lowerValue, higherValue,
544 | self = $(this),
545 | data = self.data("roundabout"),
546 | oldBearing = data.bearing;
547 |
548 | // set bearing
549 | data.bearing = bearing;
550 | self.trigger("bearingSet");
551 | methods.updateChildren.apply(self);
552 |
553 | // not animating? we're done here
554 | diff = Math.abs(oldBearing - bearing);
555 | if (!data.animating || diff > 180) {
556 | return;
557 | }
558 |
559 | // check to see if any of the children went through the back
560 | diff = Math.abs(oldBearing - bearing);
561 | self.children(data.childSelector).each(function(i) {
562 | var eventType;
563 |
564 | if (methods.isChildBackDegreesBetween.apply($(this), [bearing, oldBearing])) {
565 | eventType = (oldBearing > bearing) ? "Clockwise" : "Counterclockwise";
566 | $(this).trigger("move" + eventType + "ThroughBack");
567 | }
568 | });
569 | });
570 |
571 | // call callback if one was given
572 | callback.apply(this);
573 | return this;
574 | },
575 |
576 |
577 | // adjustBearing
578 | // change the bearing of the roundabout by a given degree
579 | adjustBearing: function(delta, callback) {
580 | callback = callback || function() {};
581 | if (delta === 0) {
582 | return this;
583 | }
584 |
585 | this
586 | .each(function() {
587 | methods.setBearing.apply($(this), [$(this).data("roundabout").bearing + delta]);
588 | });
589 |
590 | callback.apply(this);
591 | return this;
592 | },
593 |
594 |
595 | // setTilt
596 | // changes the tilt of the roundabout
597 | setTilt: function(tilt, callback) {
598 | callback = callback || function() {};
599 |
600 | this
601 | .each(function() {
602 | $(this).data("roundabout").tilt = tilt;
603 | methods.updateChildren.apply($(this));
604 | });
605 |
606 | // call callback if one was given
607 | callback.apply(this);
608 | return this;
609 | },
610 |
611 |
612 | // adjustTilt
613 | // changes the tilt of the roundabout
614 | adjustTilt: function(delta, callback) {
615 | callback = callback || function() {};
616 |
617 | this
618 | .each(function() {
619 | methods.setTilt.apply($(this), [$(this).data("roundabout").tilt + delta]);
620 | });
621 |
622 | callback.apply(this);
623 | return this;
624 | },
625 |
626 |
627 |
628 | // animation
629 | // -----------------------------------------------------------------------
630 |
631 | // animateToBearing
632 | // animates the roundabout to a given bearing, all animations come through here
633 | animateToBearing: function(bearing, duration, easing, passedData, callback) {
634 | var now = (new Date()).getTime();
635 |
636 | callback = callback || function() {};
637 |
638 | // find callback function in arguments
639 | if ($.isFunction(passedData)) {
640 | callback = passedData;
641 | passedData = null;
642 | } else if ($.isFunction(easing)) {
643 | callback = easing;
644 | easing = null;
645 | } else if ($.isFunction(duration)) {
646 | callback = duration;
647 | duration = null;
648 | }
649 |
650 | this
651 | .each(function() {
652 | var timer, easingFn, newBearing,
653 | self = $(this),
654 | data = self.data("roundabout"),
655 | thisDuration = (!duration) ? data.duration : duration,
656 | thisEasingType = (easing) ? easing : data.easing || "swing";
657 |
658 | // is this your first time?
659 | if (!passedData) {
660 | passedData = {
661 | timerStart: now,
662 | start: data.bearing,
663 | totalTime: thisDuration
664 | };
665 | }
666 |
667 | // update the timer
668 | timer = now - passedData.timerStart;
669 |
670 | if (data.stopAnimation) {
671 | methods.allowAnimation.apply(self);
672 | data.animating = false;
673 | return;
674 | }
675 |
676 | // we need to animate more
677 | if (timer < thisDuration) {
678 | if (!data.animating) {
679 | self.trigger("animationStart");
680 | }
681 |
682 | data.animating = true;
683 |
684 | if (typeof $.easing.def === "string") {
685 | easingFn = $.easing[thisEasingType] || $.easing[$.easing.def];
686 | newBearing = easingFn(null, timer, passedData.start, bearing - passedData.start, passedData.totalTime);
687 | } else {
688 | newBearing = $.easing[thisEasingType]((timer / passedData.totalTime), timer, passedData.start, bearing - passedData.start, passedData.totalTime);
689 | }
690 |
691 | // fixes issue #24, animation changed as of jQuery 1.7.2
692 | // also addresses issue #29, using easing breaks "linear"
693 | if (methods.compareVersions.apply(null, [$().jquery, "1.7.2"]) >= 0 && !($.easing["easeOutBack"])) {
694 | newBearing = passedData.start + ((bearing - passedData.start) * newBearing);
695 | }
696 |
697 | newBearing = methods.normalize.apply(null, [newBearing]);
698 | data.dragBearing = newBearing;
699 |
700 | methods.setBearing.apply(self, [newBearing, function() {
701 | setTimeout(function() { // done with a timeout so that each step is displayed
702 | methods.animateToBearing.apply(self, [bearing, thisDuration, thisEasingType, passedData, callback]);
703 | }, 0);
704 | }]);
705 |
706 | // we're done animating
707 | } else {
708 | data.lastAnimationStep = true;
709 |
710 | bearing = methods.normalize.apply(null, [bearing]);
711 | methods.setBearing.apply(self, [bearing, function() {
712 | self.trigger("animationEnd");
713 | }]);
714 | data.animating = false;
715 | data.lastAnimationStep = false;
716 | data.dragBearing = bearing;
717 |
718 | callback.apply(self);
719 | }
720 | });
721 |
722 | return this;
723 | },
724 |
725 |
726 | // animateToNearbyChild
727 | // animates roundabout to a nearby child
728 | animateToNearbyChild: function(passedArgs, which) {
729 | var duration = passedArgs[0],
730 | easing = passedArgs[1],
731 | callback = passedArgs[2] || function() {};
732 |
733 | // find callback
734 | if ($.isFunction(easing)) {
735 | callback = easing;
736 | easing = null;
737 | } else if ($.isFunction(duration)) {
738 | callback = duration;
739 | duration = null;
740 | }
741 |
742 | return this
743 | .each(function() {
744 | var j, range,
745 | self = $(this),
746 | data = self.data("roundabout"),
747 | bearing = (!data.reflect) ? data.bearing % 360 : data.bearing,
748 | length = self.children(data.childSelector).length;
749 |
750 | if (!data.animating) {
751 | // reflecting, not moving to previous || not reflecting, moving to next
752 | if ((data.reflect && which === "previous") || (!data.reflect && which === "next")) {
753 | // slightly adjust for rounding issues
754 | bearing = (Math.abs(bearing) < data.floatComparisonThreshold) ? 360 : bearing;
755 |
756 | // clockwise
757 | for (j = 0; j < length; j += 1) {
758 | range = {
759 | lower: (data.period * j),
760 | upper: (data.period * (j + 1))
761 | };
762 | range.upper = (j === length - 1) ? 360 : range.upper;
763 |
764 | if (bearing <= Math.ceil(range.upper) && bearing >= Math.floor(range.lower)) {
765 | if (length === 2 && bearing === 360) {
766 | methods.animateToDelta.apply(self, [-180, duration, easing, callback]);
767 | } else {
768 | methods.animateBearingToFocus.apply(self, [range.lower, duration, easing, callback]);
769 | }
770 | break;
771 | }
772 | }
773 | } else {
774 | // slightly adjust for rounding issues
775 | bearing = (Math.abs(bearing) < data.floatComparisonThreshold || 360 - Math.abs(bearing) < data.floatComparisonThreshold) ? 0 : bearing;
776 |
777 | // counterclockwise
778 | for (j = length - 1; j >= 0; j -= 1) {
779 | range = {
780 | lower: data.period * j,
781 | upper: data.period * (j + 1)
782 | };
783 | range.upper = (j === length - 1) ? 360 : range.upper;
784 |
785 | if (bearing >= Math.floor(range.lower) && bearing < Math.ceil(range.upper)) {
786 | if (length === 2 && bearing === 360) {
787 | methods.animateToDelta.apply(self, [180, duration, easing, callback]);
788 | } else {
789 | methods.animateBearingToFocus.apply(self, [range.upper, duration, easing, callback]);
790 | }
791 | break;
792 | }
793 | }
794 | }
795 | }
796 | });
797 | },
798 |
799 |
800 | // animateToNearestChild
801 | // animates roundabout to the nearest child
802 | animateToNearestChild: function(duration, easing, callback) {
803 | callback = callback || function() {};
804 |
805 | // find callback
806 | if ($.isFunction(easing)) {
807 | callback = easing;
808 | easing = null;
809 | } else if ($.isFunction(duration)) {
810 | callback = duration;
811 | duration = null;
812 | }
813 |
814 | return this
815 | .each(function() {
816 | var nearest = methods.getNearestChild.apply($(this));
817 | methods.animateToChild.apply($(this), [nearest, duration, easing, callback]);
818 | });
819 | },
820 |
821 |
822 | // animateToChild
823 | // animates roundabout to a given child position
824 | animateToChild: function(childPosition, duration, easing, callback) {
825 | callback = callback || function() {};
826 |
827 | // find callback
828 | if ($.isFunction(easing)) {
829 | callback = easing;
830 | easing = null;
831 | } else if ($.isFunction(duration)) {
832 | callback = duration;
833 | duration = null;
834 | }
835 |
836 | return this
837 | .each(function() {
838 | var child,
839 | self = $(this),
840 | data = self.data("roundabout");
841 |
842 | if (data.childInFocus !== childPosition && !data.animating) {
843 | child = self.children(data.childSelector).eq(childPosition);
844 | methods.animateBearingToFocus.apply(self, [child.data("roundabout").degrees, duration, easing, callback]);
845 | }
846 | });
847 | },
848 |
849 |
850 | // animateToNextChild
851 | // animates roundabout to the next child
852 | animateToNextChild: function(duration, easing, callback) {
853 | return methods.animateToNearbyChild.apply(this, [arguments, "next"]);
854 | },
855 |
856 |
857 | // animateToPreviousChild
858 | // animates roundabout to the preious child
859 | animateToPreviousChild: function(duration, easing, callback) {
860 | return methods.animateToNearbyChild.apply(this, [arguments, "previous"]);
861 | },
862 |
863 |
864 | // animateToDelta
865 | // animates roundabout to a given delta (in degrees)
866 | animateToDelta: function(degrees, duration, easing, callback) {
867 | callback = callback || function() {};
868 |
869 | // find callback
870 | if ($.isFunction(easing)) {
871 | callback = easing;
872 | easing = null;
873 | } else if ($.isFunction(duration)) {
874 | callback = duration;
875 | duration = null;
876 | }
877 |
878 | return this
879 | .each(function() {
880 | var delta = $(this).data("roundabout").bearing + degrees;
881 | methods.animateToBearing.apply($(this), [delta, duration, easing, callback]);
882 | });
883 | },
884 |
885 |
886 | // animateBearingToFocus
887 | // animates roundabout to bring a given angle into focus
888 | animateBearingToFocus: function(degrees, duration, easing, callback) {
889 | callback = callback || function() {};
890 |
891 | // find callback
892 | if ($.isFunction(easing)) {
893 | callback = easing;
894 | easing = null;
895 | } else if ($.isFunction(duration)) {
896 | callback = duration;
897 | duration = null;
898 | }
899 |
900 | return this
901 | .each(function() {
902 | var delta = $(this).data("roundabout").bearing - degrees;
903 | delta = (Math.abs(360 - delta) < Math.abs(delta)) ? 360 - delta : -delta;
904 | delta = (delta > 180) ? -(360 - delta) : delta;
905 |
906 | if (delta !== 0) {
907 | methods.animateToDelta.apply($(this), [delta, duration, easing, callback]);
908 | }
909 | });
910 | },
911 |
912 |
913 | // stopAnimation
914 | // if an animation is currently in progress, stop it
915 | stopAnimation: function() {
916 | return this
917 | .each(function() {
918 | $(this).data("roundabout").stopAnimation = true;
919 | });
920 | },
921 |
922 |
923 | // allowAnimation
924 | // clears the stop-animation hold placed by stopAnimation
925 | allowAnimation: function() {
926 | return this
927 | .each(function() {
928 | $(this).data("roundabout").stopAnimation = false;
929 | });
930 | },
931 |
932 |
933 |
934 | // autoplay
935 | // -----------------------------------------------------------------------
936 |
937 | // startAutoplay
938 | // starts autoplaying this roundabout
939 | startAutoplay: function(callback) {
940 | return this
941 | .each(function() {
942 | var self = $(this),
943 | data = self.data("roundabout");
944 |
945 | callback = callback || data.autoplayCallback || function() {};
946 |
947 | clearInterval(data.autoplayInterval);
948 | data.autoplayInterval = setInterval(function() {
949 | methods.animateToNextChild.apply(self, [callback]);
950 | }, data.autoplayDuration);
951 | data.autoplayIsRunning = true;
952 |
953 | self.trigger("autoplayStart");
954 | });
955 | },
956 |
957 |
958 | // stopAutoplay
959 | // stops autoplaying this roundabout
960 | stopAutoplay: function(keepAutoplayBindings) {
961 | return this
962 | .each(function() {
963 | clearInterval($(this).data("roundabout").autoplayInterval);
964 | $(this).data("roundabout").autoplayInterval = null;
965 | $(this).data("roundabout").autoplayIsRunning = false;
966 |
967 | // this will prevent autoplayPauseOnHover from restarting autoplay
968 | if (!keepAutoplayBindings) {
969 | $(this).unbind(".autoplay");
970 | }
971 |
972 | $(this).trigger("autoplayStop");
973 | });
974 | },
975 |
976 |
977 | // toggleAutoplay
978 | // toggles autoplay pause/resume
979 | toggleAutoplay: function(callback) {
980 | return this
981 | .each(function() {
982 | var self = $(this),
983 | data = self.data("roundabout");
984 |
985 | callback = callback || data.autoplayCallback || function() {};
986 |
987 | if (!methods.isAutoplaying.apply($(this))) {
988 | methods.startAutoplay.apply($(this), [callback]);
989 | } else {
990 | methods.stopAutoplay.apply($(this), [callback]);
991 | }
992 | });
993 | },
994 |
995 |
996 | // isAutoplaying
997 | // is this roundabout currently autoplaying?
998 | isAutoplaying: function() {
999 | return (this.data("roundabout").autoplayIsRunning);
1000 | },
1001 |
1002 |
1003 | // changeAutoplayDuration
1004 | // stops the autoplay, changes the duration, restarts autoplay
1005 | changeAutoplayDuration: function(duration) {
1006 | return this
1007 | .each(function() {
1008 | var self = $(this),
1009 | data = self.data("roundabout");
1010 |
1011 | data.autoplayDuration = duration;
1012 |
1013 | if (methods.isAutoplaying.apply(self)) {
1014 | methods.stopAutoplay.apply(self);
1015 | setTimeout(function() {
1016 | methods.startAutoplay.apply(self);
1017 | }, 10);
1018 | }
1019 | });
1020 | },
1021 |
1022 |
1023 |
1024 | // helpers
1025 | // -----------------------------------------------------------------------
1026 |
1027 | // normalize
1028 | // regulates degrees to be >= 0.0 and < 360
1029 | normalize: function(degrees) {
1030 | var inRange = degrees % 360.0;
1031 | return (inRange < 0) ? 360 + inRange : inRange;
1032 | },
1033 |
1034 |
1035 | // normalizeRad
1036 | // regulates radians to be >= 0 and < Math.PI * 2
1037 | normalizeRad: function(radians) {
1038 | while (radians < 0) {
1039 | radians += (Math.PI * 2);
1040 | }
1041 |
1042 | while (radians > (Math.PI * 2)) {
1043 | radians -= (Math.PI * 2);
1044 | }
1045 |
1046 | return radians;
1047 | },
1048 |
1049 |
1050 | // isChildBackDegreesBetween
1051 | // checks that a given child's backDegrees is between two values
1052 | isChildBackDegreesBetween: function(value1, value2) {
1053 | var backDegrees = $(this).data("roundabout").backDegrees;
1054 |
1055 | if (value1 > value2) {
1056 | return (backDegrees >= value2 && backDegrees < value1);
1057 | } else {
1058 | return (backDegrees < value2 && backDegrees >= value1);
1059 | }
1060 | },
1061 |
1062 |
1063 | // getAnimateToMethod
1064 | // takes a user-entered option and maps it to an animation method
1065 | getAnimateToMethod: function(effect) {
1066 | effect = effect.toLowerCase();
1067 |
1068 | if (effect === "next") {
1069 | return "animateToNextChild";
1070 | } else if (effect === "previous") {
1071 | return "animateToPreviousChild";
1072 | }
1073 |
1074 | // default selection
1075 | return "animateToNearestChild";
1076 | },
1077 |
1078 |
1079 | // relayoutChildren
1080 | // lays out children again with new contextual information
1081 | relayoutChildren: function() {
1082 | return this
1083 | .each(function() {
1084 | var self = $(this),
1085 | settings = $.extend({}, self.data("roundabout"));
1086 |
1087 | settings.startingChild = self.data("roundabout").childInFocus;
1088 | methods.init.apply(self, [settings, null, true]);
1089 | });
1090 | },
1091 |
1092 |
1093 | // getNearestChild
1094 | // gets the nearest child from the current bearing
1095 | getNearestChild: function() {
1096 | var self = $(this),
1097 | data = self.data("roundabout"),
1098 | length = self.children(data.childSelector).length;
1099 |
1100 | if (!data.reflect) {
1101 | return ((length) - (Math.round(data.bearing / data.period) % length)) % length;
1102 | } else {
1103 | return (Math.round(data.bearing / data.period) % length);
1104 | }
1105 | },
1106 |
1107 |
1108 | // degToRad
1109 | // converts degrees to radians
1110 | degToRad: function(degrees) {
1111 | return methods.normalize.apply(null, [degrees]) * Math.PI / 180.0;
1112 | },
1113 |
1114 |
1115 | // getPlacement
1116 | // returns the starting degree for a given child
1117 | getPlacement: function(child) {
1118 | var data = this.data("roundabout");
1119 | return (!data.reflect) ? 360.0 - (data.period * child) : data.period * child;
1120 | },
1121 |
1122 |
1123 | // isInFocus
1124 | // is this roundabout currently in focus?
1125 | isInFocus: function(degrees) {
1126 | var diff,
1127 | self = this,
1128 | data = self.data("roundabout"),
1129 | bearing = methods.normalize.apply(null, [data.bearing]);
1130 |
1131 | degrees = methods.normalize.apply(null, [degrees]);
1132 | diff = Math.abs(bearing - degrees);
1133 |
1134 | // this calculation gives a bit of room for javascript float rounding
1135 | // errors, it looks on both 0deg and 360deg ends of the spectrum
1136 | return (diff <= data.floatComparisonThreshold || diff >= 360 - data.floatComparisonThreshold);
1137 | },
1138 |
1139 |
1140 | // getChildInFocus
1141 | // returns the current child in focus, or false if none are in focus
1142 | getChildInFocus: function() {
1143 | var data = $(this).data("roundabout");
1144 |
1145 | return (data.childInFocus > -1) ? data.childInFocus : false;
1146 | },
1147 |
1148 |
1149 | // compareVersions
1150 | // compares a given version string with another
1151 | compareVersions: function(baseVersion, compareVersion) {
1152 | var i,
1153 | base = baseVersion.split(/\./i),
1154 | compare = compareVersion.split(/\./i),
1155 | maxVersionSegmentLength = (base.length > compare.length) ? base.length : compare.length;
1156 |
1157 | for (i = 0; i <= maxVersionSegmentLength; i++) {
1158 | if (base[i] && !compare[i] && parseInt(base[i], 10) !== 0) {
1159 | // base is higher
1160 | return 1;
1161 | } else if (compare[i] && !base[i] && parseInt(compare[i], 10) !== 0) {
1162 | // compare is higher
1163 | return -1;
1164 | } else if (base[i] === compare[i]) {
1165 | // these are the same, next
1166 | continue;
1167 | }
1168 |
1169 | if (base[i] && compare[i]) {
1170 | if (parseInt(base[i], 10) > parseInt(compare[i], 10)) {
1171 | // base is higher
1172 | return 1;
1173 | } else {
1174 | // compare is higher
1175 | return -1;
1176 | }
1177 | }
1178 | }
1179 |
1180 | // nothing was triggered, versions are the same
1181 | return 0;
1182 | }
1183 | };
1184 |
1185 |
1186 | // start the plugin
1187 | $.fn.roundabout = function(method) {
1188 | if (methods[method]) {
1189 | return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
1190 | } else if (typeof method === "object" || $.isFunction(method) || !method) {
1191 | return methods.init.apply(this, arguments);
1192 | } else {
1193 | $.error("Method " + method + " does not exist for jQuery.roundabout.");
1194 | }
1195 | };
1196 | })(jQuery);
--------------------------------------------------------------------------------
/fullPage.js/js/jquery.fullPage.js:
--------------------------------------------------------------------------------
1 | /**
2 | * fullPage 2.5.4
3 | * https://github.com/alvarotrigo/fullPage.js
4 | * MIT licensed
5 | *
6 | * Copyright (C) 2013 alvarotrigo.com - A project by Alvaro Trigo
7 | */
8 |
9 | (function($) {
10 | $.fn.fullpage = function(options) {
11 | // Create some defaults, extending them with any options that were provided
12 | options = $.extend({
13 | //navigation
14 | 'menu': false,
15 | 'anchors':[],
16 | 'navigation': false,
17 | 'navigationPosition': 'right',
18 | 'navigationColor': '#000',
19 | 'navigationTooltips': [],
20 | 'slidesNavigation': false,
21 | 'slidesNavPosition': 'bottom',
22 | 'scrollBar': false,
23 |
24 | //scrolling
25 | 'css3': true,
26 | 'scrollingSpeed': 700,
27 | 'autoScrolling': true,
28 | 'easing': 'easeInQuart',
29 | 'easingcss3': 'ease',
30 | 'loopBottom': false,
31 | 'loopTop': false,
32 | 'loopHorizontal': true,
33 | 'continuousVertical': false,
34 | 'normalScrollElements': null,
35 | 'scrollOverflow': false,
36 | 'touchSensitivity': 5,
37 | 'normalScrollElementTouchThreshold': 5,
38 |
39 | //Accessibility
40 | 'keyboardScrolling': true,
41 | 'animateAnchor': true,
42 | 'recordHistory': true,
43 |
44 | //design
45 | 'controlArrows': true,
46 | 'controlArrowColor': '#fff',
47 | "verticalCentered": true,
48 | 'resize': true,
49 | 'sectionsColor' : [],
50 | 'paddingTop': 0,
51 | 'paddingBottom': 0,
52 | 'fixedElements': null,
53 | 'responsive': 0,
54 |
55 | //Custom selectors
56 | 'sectionSelector': '.section',
57 | 'slideSelector': '.slide',
58 |
59 |
60 | //events
61 | 'afterLoad': null,
62 | 'onLeave': null,
63 | 'afterRender': null,
64 | 'afterResize': null,
65 | 'afterReBuild': null,
66 | 'afterSlideLoad': null,
67 | 'onSlideLeave': null
68 | }, options);
69 |
70 | displayWarnings();
71 |
72 | //easeInQuart animation included in the plugin
73 | $.extend($.easing,{ easeInQuart: function (x, t, b, c, d) { return c*(t/=d)*t*t*t + b; }});
74 |
75 | //Defines the delay to take place before being able to scroll to the next section
76 | //BE CAREFUL! Not recommened to change it under 400 for a good behavior in laptops and
77 | //Apple devices (laptops, mouses...)
78 | var scrollDelay = 600;
79 |
80 | $.fn.fullpage.setAutoScrolling = function(value, type){
81 | setVariableState('autoScrolling', value, type);
82 |
83 | var element = $('.fp-section.active');
84 |
85 | if(options.autoScrolling && !options.scrollBar){
86 | $('html, body').css({
87 | 'overflow' : 'hidden',
88 | 'height' : '100%'
89 | });
90 |
91 | $.fn.fullpage.setRecordHistory(options.recordHistory, 'internal');
92 |
93 | //for IE touch devices
94 | container.css({
95 | '-ms-touch-action': 'none',
96 | 'touch-action': 'none'
97 | });
98 |
99 | if(element.length){
100 | //moving the container up
101 | silentScroll(element.position().top);
102 | }
103 |
104 | }else{
105 | $('html, body').css({
106 | 'overflow' : 'visible',
107 | 'height' : 'initial'
108 | });
109 |
110 | $.fn.fullpage.setRecordHistory(false, 'internal');
111 |
112 | //for IE touch devices
113 | container.css({
114 | '-ms-touch-action': '',
115 | 'touch-action': ''
116 | });
117 |
118 | silentScroll(0);
119 |
120 | //scrolling the page to the section with no animation
121 | $('html, body').scrollTop(element.position().top);
122 | }
123 |
124 | };
125 |
126 | /**
127 | * Defines wheter to record the history for each hash change in the URL.
128 | */
129 | $.fn.fullpage.setRecordHistory = function(value, type){
130 | setVariableState('recordHistory', value, type);
131 | };
132 |
133 | /**
134 | * Defines the scrolling speed
135 | */
136 | $.fn.fullpage.setScrollingSpeed = function(value, type){
137 | setVariableState('scrollingSpeed', value, type);
138 | };
139 |
140 | /**
141 | * Adds or remove the possiblity of scrolling through sections by using the mouse wheel or the trackpad.
142 | */
143 | $.fn.fullpage.setMouseWheelScrolling = function (value){
144 | if(value){
145 | addMouseWheelHandler();
146 | }else{
147 | removeMouseWheelHandler();
148 | }
149 | };
150 |
151 | /**
152 | * Adds or remove the possiblity of scrolling through sections by using the mouse wheel/trackpad or touch gestures.
153 | * Optionally a second parameter can be used to specify the direction for which the action will be applied.
154 | *
155 | * @param directions string containing the direction or directions separated by comma.
156 | */
157 | $.fn.fullpage.setAllowScrolling = function (value, directions){
158 | if(typeof directions != 'undefined'){
159 | directions = directions.replace(' ', '').split(',');
160 | $.each(directions, function (index, direction){
161 | setIsScrollable(value, direction);
162 | });
163 | }
164 | else if(value){
165 | $.fn.fullpage.setMouseWheelScrolling(true);
166 | addTouchHandler();
167 | }else{
168 | $.fn.fullpage.setMouseWheelScrolling(false);
169 | removeTouchHandler();
170 | }
171 | };
172 |
173 | /**
174 | * Adds or remove the possiblity of scrolling through sections by using the keyboard arrow keys
175 | */
176 | $.fn.fullpage.setKeyboardScrolling = function (value){
177 | options.keyboardScrolling = value;
178 | };
179 |
180 | $.fn.fullpage.moveSectionUp = function(){
181 | var prev = $('.fp-section.active').prev('.fp-section');
182 |
183 | //looping to the bottom if there's no more sections above
184 | if (!prev.length && (options.loopTop || options.continuousVertical)) {
185 | prev = $('.fp-section').last();
186 | }
187 |
188 | if (prev.length) {
189 | scrollPage(prev, null, true);
190 | }
191 | };
192 |
193 | $.fn.fullpage.moveSectionDown = function (){
194 | var next = $('.fp-section.active').next('.fp-section');
195 |
196 | //looping to the top if there's no more sections below
197 | if(!next.length &&
198 | (options.loopBottom || options.continuousVertical)){
199 | next = $('.fp-section').first();
200 | }
201 |
202 | if(next.length){
203 | scrollPage(next, null, false);
204 | }
205 | };
206 |
207 | $.fn.fullpage.moveTo = function (section, slide){
208 | var destiny = '';
209 |
210 | if(isNaN(section)){
211 | destiny = $('[data-anchor="'+section+'"]');
212 | }else{
213 | destiny = $('.fp-section').eq( (section -1) );
214 | }
215 |
216 | if (typeof slide !== 'undefined'){
217 | scrollPageAndSlide(section, slide);
218 | }else if(destiny.length > 0){
219 | scrollPage(destiny);
220 | }
221 | };
222 |
223 | $.fn.fullpage.moveSlideRight = function(){
224 | moveSlide('next');
225 | };
226 |
227 | $.fn.fullpage.moveSlideLeft = function(){
228 | moveSlide('prev');
229 | };
230 |
231 | /**
232 | * When resizing is finished, we adjust the slides sizes and positions
233 | */
234 | $.fn.fullpage.reBuild = function(resizing){
235 | isResizing = true;
236 |
237 | var windowsWidth = $(window).width();
238 | windowsHeight = $(window).height(); //updating global var
239 |
240 | //text and images resizing
241 | if (options.resize) {
242 | resizeMe(windowsHeight, windowsWidth);
243 | }
244 |
245 | $('.fp-section').each(function(){
246 | var scrollHeight = windowsHeight - parseInt($(this).css('padding-bottom')) - parseInt($(this).css('padding-top'));
247 |
248 | //adjusting the height of the table-cell for IE and Firefox
249 | if(options.verticalCentered){
250 | $(this).find('.fp-tableCell').css('height', getTableHeight($(this)) + 'px');
251 | }
252 |
253 | $(this).css('height', windowsHeight + 'px');
254 |
255 | //resizing the scrolling divs
256 | if(options.scrollOverflow){
257 | var slides = $(this).find('.fp-slide');
258 |
259 | if(slides.length){
260 | slides.each(function(){
261 | createSlimScrolling($(this));
262 | });
263 | }else{
264 | createSlimScrolling($(this));
265 | }
266 | }
267 |
268 | //adjusting the position fo the FULL WIDTH slides...
269 | var slides = $(this).find('.fp-slides');
270 | if (slides.length) {
271 | landscapeScroll(slides, slides.find('.fp-slide.active'));
272 | }
273 | });
274 |
275 | //adjusting the position for the current section
276 | var destinyPos = $('.fp-section.active').position();
277 |
278 | var activeSection = $('.fp-section.active');
279 |
280 | //isn't it the first section?
281 | if(activeSection.index('.fp-section')){
282 | scrollPage(activeSection);
283 | }
284 |
285 | isResizing = false;
286 | $.isFunction( options.afterResize ) && resizing && options.afterResize.call( this )
287 | $.isFunction( options.afterReBuild ) && !resizing && options.afterReBuild.call( this );
288 | }
289 |
290 | //flag to avoid very fast sliding for landscape sliders
291 | var slideMoving = false;
292 |
293 | var isTouchDevice = navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|Windows Phone|Tizen|Bada)/);
294 | var isTouch = (('ontouchstart' in window) || (navigator.msMaxTouchPoints > 0) || (navigator.maxTouchPoints));
295 | var container = $(this);
296 | var windowsHeight = $(window).height();
297 | var isMoving = false;
298 | var isResizing = false;
299 | var lastScrolledDestiny;
300 | var lastScrolledSlide;
301 | var nav;
302 | var wrapperSelector = 'fullpage-wrapper';
303 | var isScrollAllowed = { 'up':true, 'down':true, 'left':true, 'right':true };
304 | var originals = jQuery.extend(true, {}, options); //deep copy
305 |
306 | $.fn.fullpage.setAllowScrolling(true);
307 |
308 | //if css3 is not supported, it will use jQuery animations
309 | if(options.css3){
310 | options.css3 = support3d();
311 | }
312 |
313 | if($(this).length){
314 | container.css({
315 | 'height': '100%',
316 | 'position': 'relative'
317 | });
318 |
319 | //adding a class to recognize the container internally in the code
320 | container.addClass(wrapperSelector);
321 | }
322 |
323 | //trying to use fullpage without a selector?
324 | else{
325 | showError('error', "Error! Fullpage.js needs to be initialized with a selector. For example: $('#myContainer').fullpage();");
326 | }
327 |
328 | //adding internal class names to void problem with common ones
329 | $(options.sectionSelector).each(function(){
330 | $(this).addClass('fp-section');
331 | });
332 | $(options.slideSelector).each(function(){
333 | $(this).addClass('fp-slide');
334 | });
335 |
336 | //creating the navigation dots
337 | if (options.navigation) {
338 | addVerticalNavigation();
339 | }
340 |
341 | $('.fp-section').each(function(index){
342 | var that = $(this);
343 | var slides = $(this).find('.fp-slide');
344 | var numSlides = slides.length;
345 |
346 | //if no active section is defined, the 1st one will be the default one
347 | if(!index && $('.fp-section.active').length === 0) {
348 | $(this).addClass('active');
349 | }
350 |
351 | $(this).css('height', windowsHeight + 'px');
352 |
353 | if(options.paddingTop || options.paddingBottom){
354 | $(this).css('padding', options.paddingTop + ' 0 ' + options.paddingBottom + ' 0');
355 | }
356 |
357 | if (typeof options.sectionsColor[index] !== 'undefined') {
358 | $(this).css('background-color', options.sectionsColor[index]);
359 | }
360 |
361 | if (typeof options.anchors[index] !== 'undefined') {
362 | $(this).attr('data-anchor', options.anchors[index]);
363 | }
364 |
365 | // if there's any slide
366 | if (numSlides > 1) {
367 | var sliderWidth = numSlides * 100;
368 | var slideWidth = 100 / numSlides;
369 |
370 | slides.wrapAll('
');
371 | slides.parent().wrap('
');
372 |
373 | $(this).find('.fp-slidesContainer').css('width', sliderWidth + '%');
374 |
375 | if(options.controlArrows){
376 | createSlideArrows($(this));
377 | }
378 |
379 | if(options.slidesNavigation){
380 | addSlidesNavigation($(this), numSlides);
381 | }
382 |
383 | slides.each(function(index) {
384 | $(this).css('width', slideWidth + '%');
385 |
386 | if(options.verticalCentered){
387 | addTableClass($(this));
388 | }
389 | });
390 |
391 | var startingSlide = that.find('.fp-slide.active');
392 |
393 | //if the slide won#t be an starting point, the default will be the first one
394 | if(startingSlide.length == 0){
395 | slides.eq(0).addClass('active');
396 | }
397 |
398 | //is there a starting point for a non-starting section?
399 | else{
400 | silentLandscapeScroll(startingSlide);
401 | }
402 |
403 | }else{
404 | if(options.verticalCentered){
405 | addTableClass($(this));
406 | }
407 | }
408 |
409 | }).promise().done(function(){
410 | $.fn.fullpage.setAutoScrolling(options.autoScrolling, 'internal');
411 |
412 | //the starting point is a slide?
413 | var activeSlide = $('.fp-section.active').find('.fp-slide.active');
414 |
415 | //the active section isn't the first one? Is not the first slide of the first section? Then we load that section/slide by default.
416 | if( activeSlide.length && ($('.fp-section.active').index('.fp-section') != 0 || ($('.fp-section.active').index('.fp-section') == 0 && activeSlide.index() != 0))){
417 | silentLandscapeScroll(activeSlide);
418 | }
419 |
420 | //fixed elements need to be moved out of the plugin container due to problems with CSS3.
421 | if(options.fixedElements && options.css3){
422 | $(options.fixedElements).appendTo('body');
423 | }
424 |
425 | //vertical centered of the navigation + first bullet active
426 | if(options.navigation){
427 | nav.css('margin-top', '-' + (nav.height()/2) + 'px');
428 | nav.find('li').eq($('.fp-section.active').index('.fp-section')).find('a').addClass('active');
429 | }
430 |
431 | //moving the menu outside the main container if it is inside (avoid problems with fixed positions when using CSS3 tranforms)
432 | if(options.menu && options.css3 && $(options.menu).closest('.fullpage-wrapper').length){
433 | $(options.menu).appendTo('body');
434 | }
435 |
436 | if(options.scrollOverflow){
437 | if(document.readyState === "complete"){
438 | createSlimScrollingHandler();
439 | }
440 | //after DOM and images are loaded
441 | $(window).on('load', createSlimScrollingHandler);
442 | }else{
443 | $.isFunction( options.afterRender ) && options.afterRender.call( this);
444 | }
445 |
446 | responsive();
447 |
448 | //getting the anchor link in the URL and deleting the `#`
449 | var value = window.location.hash.replace('#', '').split('/');
450 | var destiny = value[0];
451 |
452 | if(destiny.length){
453 | var section = $('[data-anchor="'+destiny+'"]');
454 |
455 | if(!options.animateAnchor && section.length){
456 |
457 | if(options.autoScrolling){
458 | silentScroll(section.position().top);
459 | }
460 | else{
461 | silentScroll(0);
462 | setBodyClass(destiny);
463 |
464 | //scrolling the page to the section with no animation
465 | $('html, body').scrollTop(section.position().top);
466 | }
467 |
468 | activateMenuAndNav(destiny, null);
469 |
470 | $.isFunction( options.afterLoad ) && options.afterLoad.call( this, destiny, (section.index('.fp-section') + 1));
471 |
472 | //updating the active class
473 | section.addClass('active').siblings().removeClass('active');
474 | }
475 | }
476 |
477 |
478 | $(window).on('load', function() {
479 | scrollToAnchor();
480 | });
481 |
482 | });
483 |
484 |
485 | /**
486 | * Creates the control arrows for the given section
487 | */
488 | function createSlideArrows(section){
489 | section.find('.fp-slides').after('
');
490 |
491 | if(options.controlArrowColor!='#fff'){
492 | section.find('.fp-controlArrow.fp-next').css('border-color', 'transparent transparent transparent '+options.controlArrowColor);
493 | section.find('.fp-controlArrow.fp-prev').css('border-color', 'transparent '+ options.controlArrowColor + ' transparent transparent');
494 | }
495 |
496 | if(!options.loopHorizontal){
497 | section.find('.fp-controlArrow.fp-prev').hide();
498 | }
499 | }
500 |
501 | /**
502 | * Creates a vertical navigation bar.
503 | */
504 | function addVerticalNavigation(){
505 | $('body').append('');
506 | nav = $('#fp-nav');
507 |
508 | nav.css('color', options.navigationColor);
509 | nav.addClass(options.navigationPosition);
510 |
511 | for (var i = 0; i < $('.fp-section').length; i++) {
512 | var link = '';
513 | if (options.anchors.length) {
514 | link = options.anchors[i];
515 | }
516 |
517 | var li = ' ';
518 |
519 | // Only add tooltip if needed (defined by user)
520 | var tooltip = options.navigationTooltips[i];
521 | if (tooltip != undefined && tooltip != '') {
522 | li += '' + tooltip + '
';
523 | }
524 |
525 | li += ' ';
526 |
527 | nav.find('ul').append(li);
528 | }
529 | }
530 |
531 | function createSlimScrollingHandler(){
532 | $('.fp-section').each(function(){
533 | var slides = $(this).find('.fp-slide');
534 |
535 | if(slides.length){
536 | slides.each(function(){
537 | createSlimScrolling($(this));
538 | });
539 | }else{
540 | createSlimScrolling($(this));
541 | }
542 |
543 | });
544 | $.isFunction( options.afterRender ) && options.afterRender.call( this);
545 | }
546 |
547 | var scrollId;
548 | var scrollId2;
549 | var isScrolling = false;
550 |
551 | //when scrolling...
552 | $(window).on('scroll', scrollHandler);
553 |
554 | function scrollHandler(){
555 | if(!options.autoScrolling || options.scrollBar){
556 | var currentScroll = $(window).scrollTop();
557 | var visibleSectionIndex = 0;
558 | var initial = Math.abs(currentScroll - $('.fp-section').first().offset().top);
559 |
560 | //taking the section which is showing more content in the viewport
561 | $('.fp-section').each(function(index){
562 | var current = Math.abs(currentScroll - $(this).offset().top);
563 |
564 | if(current < initial){
565 | visibleSectionIndex = index;
566 | initial = current;
567 | }
568 | });
569 |
570 | //geting the last one, the current one on the screen
571 | var currentSection = $('.fp-section').eq(visibleSectionIndex);
572 | }
573 |
574 | if(!options.autoScrolling){
575 | //executing only once the first time we reach the section
576 | if(!currentSection.hasClass('active')){
577 | isScrolling = true;
578 |
579 | var leavingSection = $('.fp-section.active').index('.fp-section') + 1;
580 | var yMovement = getYmovement(currentSection);
581 | var anchorLink = currentSection.data('anchor');
582 | var sectionIndex = currentSection.index('.fp-section') + 1;
583 | var activeSlide = currentSection.find('.fp-slide.active');
584 |
585 | if(activeSlide.length){
586 | var slideAnchorLink = activeSlide.data('anchor');
587 | var slideIndex = activeSlide.index();
588 | }
589 |
590 | currentSection.addClass('active').siblings().removeClass('active');
591 |
592 | if(!isMoving){
593 | $.isFunction( options.onLeave ) && options.onLeave.call( this, leavingSection, sectionIndex, yMovement);
594 |
595 | $.isFunction( options.afterLoad ) && options.afterLoad.call( this, anchorLink, sectionIndex);
596 | }
597 |
598 | activateMenuAndNav(anchorLink, 0);
599 |
600 | if(options.anchors.length && !isMoving){
601 | //needed to enter in hashChange event when using the menu with anchor links
602 | lastScrolledDestiny = anchorLink;
603 |
604 | setState(slideIndex, slideAnchorLink, anchorLink, sectionIndex);
605 | }
606 |
607 | //small timeout in order to avoid entering in hashChange event when scrolling is not finished yet
608 | clearTimeout(scrollId);
609 | scrollId = setTimeout(function(){
610 | isScrolling = false;
611 | }, 100);
612 | }
613 | }
614 |
615 | if(options.scrollBar){
616 | //for the auto adjust of the viewport to fit a whole section
617 | clearTimeout(scrollId2);
618 | scrollId2 = setTimeout(function(){
619 | if(!isMoving){
620 | scrollPage(currentSection);
621 | }
622 | }, 1000);
623 | }
624 | }
625 |
626 |
627 | /**
628 | * Determines whether the active section or slide is scrollable through and scrolling bar
629 | */
630 | function isScrollable(activeSection){
631 | //if there are landscape slides, we check if the scrolling bar is in the current one or not
632 | if(activeSection.find('.fp-slides').length){
633 | scrollable= activeSection.find('.fp-slide.active').find('.fp-scrollable');
634 | }else{
635 | scrollable = activeSection.find('.fp-scrollable');
636 | }
637 |
638 | return scrollable;
639 | }
640 |
641 | /**
642 | * Determines the way of scrolling up or down:
643 | * by 'automatically' scrolling a section or by using the default and normal scrolling.
644 | */
645 | function scrolling(type, scrollable){
646 | if (!isScrollAllowed[type]){
647 | return;
648 | }
649 |
650 | if(type == 'down'){
651 | var check = 'bottom';
652 | var scrollSection = $.fn.fullpage.moveSectionDown;
653 | }else{
654 | var check = 'top';
655 | var scrollSection = $.fn.fullpage.moveSectionUp;
656 | }
657 |
658 | if(scrollable.length > 0 ){
659 | //is the scrollbar at the start/end of the scroll?
660 | if(isScrolled(check, scrollable)){
661 | scrollSection();
662 | }else{
663 | return true;
664 | }
665 | }else{
666 | // moved up/down
667 | scrollSection();
668 | }
669 | }
670 |
671 |
672 | var touchStartY = 0;
673 | var touchStartX = 0;
674 | var touchEndY = 0;
675 | var touchEndX = 0;
676 |
677 | /* Detecting touch events
678 |
679 | * As we are changing the top property of the page on scrolling, we can not use the traditional way to detect it.
680 | * This way, the touchstart and the touch moves shows an small difference between them which is the
681 | * used one to determine the direction.
682 | */
683 | function touchMoveHandler(event){
684 | var e = event.originalEvent;
685 |
686 | // additional: if one of the normalScrollElements isn't within options.normalScrollElementTouchThreshold hops up the DOM chain
687 | if (!checkParentForNormalScrollElement(event.target)) {
688 |
689 | if(options.autoScrolling && !options.scrollBar){
690 | //preventing the easing on iOS devices
691 | event.preventDefault();
692 | }
693 |
694 | var activeSection = $('.fp-section.active');
695 | var scrollable = isScrollable(activeSection);
696 |
697 | if (!isMoving && !slideMoving) { //if theres any #
698 | var touchEvents = getEventsPage(e);
699 |
700 | touchEndY = touchEvents['y'];
701 | touchEndX = touchEvents['x'];
702 |
703 | //if movement in the X axys is greater than in the Y and the currect section has slides...
704 | if (activeSection.find('.fp-slides').length && Math.abs(touchStartX - touchEndX) > (Math.abs(touchStartY - touchEndY))) {
705 |
706 | //is the movement greater than the minimum resistance to scroll?
707 | if (Math.abs(touchStartX - touchEndX) > ($(window).width() / 100 * options.touchSensitivity)) {
708 | if (touchStartX > touchEndX) {
709 | if(isScrollAllowed.right){
710 | $.fn.fullpage.moveSlideRight(); //next
711 | }
712 | } else {
713 | if(isScrollAllowed.left){
714 | $.fn.fullpage.moveSlideLeft(); //prev
715 | }
716 | }
717 | }
718 | }
719 |
720 | //vertical scrolling (only when autoScrolling is enabled)
721 | else if(options.autoScrolling && !options.scrollBar){
722 |
723 | //is the movement greater than the minimum resistance to scroll?
724 | if (Math.abs(touchStartY - touchEndY) > ($(window).height() / 100 * options.touchSensitivity)) {
725 | if (touchStartY > touchEndY) {
726 | scrolling('down', scrollable);
727 | } else if (touchEndY > touchStartY) {
728 | scrolling('up', scrollable);
729 | }
730 | }
731 | }
732 | }
733 | }
734 |
735 | }
736 |
737 | /**
738 | * recursive function to loop up the parent nodes to check if one of them exists in options.normalScrollElements
739 | * Currently works well for iOS - Android might need some testing
740 | * @param {Element} el target element / jquery selector (in subsequent nodes)
741 | * @param {int} hop current hop compared to options.normalScrollElementTouchThreshold
742 | * @return {boolean} true if there is a match to options.normalScrollElements
743 | */
744 | function checkParentForNormalScrollElement (el, hop) {
745 | hop = hop || 0;
746 | var parent = $(el).parent();
747 |
748 | if (hop < options.normalScrollElementTouchThreshold &&
749 | parent.is(options.normalScrollElements) ) {
750 | return true;
751 | } else if (hop == options.normalScrollElementTouchThreshold) {
752 | return false;
753 | } else {
754 | return checkParentForNormalScrollElement(parent, ++hop);
755 | }
756 | }
757 |
758 | function touchStartHandler(event){
759 | var e = event.originalEvent;
760 |
761 | var touchEvents = getEventsPage(e);
762 | touchStartY = touchEvents['y'];
763 | touchStartX = touchEvents['x'];
764 | }
765 |
766 |
767 | /**
768 | * Detecting mousewheel scrolling
769 | *
770 | * http://blogs.sitepointstatic.com/examples/tech/mouse-wheel/index.html
771 | * http://www.sitepoint.com/html5-javascript-mouse-wheel/
772 | */
773 | function MouseWheelHandler(e) {
774 | if(options.autoScrolling){
775 | // cross-browser wheel delta
776 | e = window.event || e;
777 | var delta = Math.max(-1, Math.min(1,
778 | (e.wheelDelta || -e.deltaY || -e.detail)));
779 |
780 | //preventing to scroll the site on mouse wheel when scrollbar is present
781 | if(options.scrollBar){
782 | e.preventDefault ? e.preventDefault() : e.returnValue = false;
783 |
784 | }
785 |
786 | var activeSection = $('.fp-section.active');
787 | var scrollable = isScrollable(activeSection);
788 |
789 | if (!isMoving) { //if theres any #
790 | //scrolling down?
791 | if (delta < 0) {
792 | scrolling('down', scrollable);
793 |
794 | //scrolling up?
795 | }else {
796 | scrolling('up', scrollable);
797 | }
798 | }
799 |
800 | return false;
801 | }
802 | }
803 |
804 | function moveSlide(direction){
805 | var activeSection = $('.fp-section.active');
806 | var slides = activeSection.find('.fp-slides');
807 |
808 | // more than one slide needed and nothing should be sliding
809 | if (!slides.length || slideMoving) {
810 | return;
811 | }
812 |
813 | var currentSlide = slides.find('.fp-slide.active');
814 | var destiny = null;
815 |
816 | if(direction === 'prev'){
817 | destiny = currentSlide.prev('.fp-slide');
818 | }else{
819 | destiny = currentSlide.next('.fp-slide');
820 | }
821 |
822 | //isn't there a next slide in the secuence?
823 | if(!destiny.length){
824 | //respect loopHorizontal settin
825 | if (!options.loopHorizontal) return;
826 |
827 | if(direction === 'prev'){
828 | destiny = currentSlide.siblings(':last');
829 | }else{
830 | destiny = currentSlide.siblings(':first');
831 | }
832 | }
833 |
834 | slideMoving = true;
835 |
836 | landscapeScroll(slides, destiny);
837 | }
838 |
839 | /**
840 | * Maintains the active slides in the viewport
841 | * (Because he `scroll` animation might get lost with some actions, such as when using continuousVertical)
842 | */
843 | function keepSlidesPosition(){
844 | $('.fp-slide.active').each(function(){
845 | silentLandscapeScroll($(this));
846 | });
847 | }
848 |
849 | /**
850 | * Scrolls the site to the given element and scrolls to the slide if a callback is given.
851 | */
852 | function scrollPage(element, callback, isMovementUp){
853 | var dest = element.position();
854 | if(typeof dest === "undefined"){ return; } //there's no element to scroll, leaving the function
855 |
856 | //local variables
857 | var v = {
858 | element: element,
859 | callback: callback,
860 | isMovementUp: isMovementUp,
861 | dest: dest,
862 | dtop: dest.top,
863 | yMovement: getYmovement(element),
864 | anchorLink: element.data('anchor'),
865 | sectionIndex: element.index('.fp-section'),
866 | activeSlide: element.find('.fp-slide.active'),
867 | activeSection: $('.fp-section.active'),
868 | leavingSection: $('.fp-section.active').index('.fp-section') + 1,
869 |
870 | //caching the value of isResizing at the momment the function is called
871 | //because it will be checked later inside a setTimeout and the value might change
872 | localIsResizing: isResizing
873 | };
874 |
875 | //quiting when destination scroll is the same as the current one
876 | if((v.activeSection.is(element) && !isResizing) || (options.scrollBar && $(window).scrollTop() === v.dtop)){ return; }
877 |
878 | if(v.activeSlide.length){
879 | var slideAnchorLink = v.activeSlide.data('anchor');
880 | var slideIndex = v.activeSlide.index();
881 | }
882 |
883 | // If continuousVertical && we need to wrap around
884 | if (options.autoScrolling && options.continuousVertical && typeof (v.isMovementUp) !== "undefined" &&
885 | ((!v.isMovementUp && v.yMovement == 'up') || // Intending to scroll down but about to go up or
886 | (v.isMovementUp && v.yMovement == 'down'))) { // intending to scroll up but about to go down
887 |
888 | v = createInfiniteSections(v);
889 | }
890 |
891 | element.addClass('active').siblings().removeClass('active');
892 |
893 | //preventing from activating the MouseWheelHandler event
894 | //more than once if the page is scrolling
895 | isMoving = true;
896 |
897 | setState(slideIndex, slideAnchorLink, v.anchorLink, v.sectionIndex);
898 |
899 | //callback (onLeave) if the site is not just resizing and readjusting the slides
900 | $.isFunction(options.onLeave) && !v.localIsResizing && options.onLeave.call(this, v.leavingSection, (v.sectionIndex + 1), v.yMovement);
901 |
902 | performMovement(v);
903 |
904 | //flag to avoid callingn `scrollPage()` twice in case of using anchor links
905 | lastScrolledDestiny = v.anchorLink;
906 |
907 | //avoid firing it twice (as it does also on scroll)
908 | if(options.autoScrolling){
909 | activateMenuAndNav(v.anchorLink, v.sectionIndex)
910 | }
911 | }
912 |
913 | /**
914 | * Performs the movement (by CSS3 or by jQuery)
915 | */
916 | function performMovement(v){
917 | // using CSS3 translate functionality
918 | if (options.css3 && options.autoScrolling && !options.scrollBar) {
919 |
920 | var translate3d = 'translate3d(0px, -' + v.dtop + 'px, 0px)';
921 | transformContainer(translate3d, true);
922 |
923 | setTimeout(function () {
924 | afterSectionLoads(v);
925 | }, options.scrollingSpeed);
926 | }
927 |
928 | // using jQuery animate
929 | else{
930 | var scrollSettings = getScrollSettings(v);
931 |
932 | $(scrollSettings.element).animate(
933 | scrollSettings.options
934 | , options.scrollingSpeed, options.easing).promise().done(function () { //only one single callback in case of animating `html, body`
935 | afterSectionLoads(v);
936 | });
937 | }
938 | }
939 |
940 | /**
941 | * Gets the scrolling settings depending on the plugin autoScrolling option
942 | */
943 | function getScrollSettings(v){
944 | var scroll = {};
945 |
946 | if(options.autoScrolling && !options.scrollBar){
947 | scroll.options = { 'top': -v.dtop};
948 | scroll.element = '.'+wrapperSelector;
949 | }else{
950 | scroll.options = { 'scrollTop': v.dtop};
951 | scroll.element = 'html, body';
952 | }
953 |
954 | return scroll;
955 | }
956 |
957 | /**
958 | * Adds sections before or after the current one to create the infinite effect.
959 | */
960 | function createInfiniteSections(v){
961 | // Scrolling down
962 | if (!v.isMovementUp) {
963 | // Move all previous sections to after the active section
964 | $(".fp-section.active").after(v.activeSection.prevAll(".fp-section").get().reverse());
965 | }
966 | else { // Scrolling up
967 | // Move all next sections to before the active section
968 | $(".fp-section.active").before(v.activeSection.nextAll(".fp-section"));
969 | }
970 |
971 | // Maintain the displayed position (now that we changed the element order)
972 | silentScroll($('.fp-section.active').position().top);
973 |
974 | // Maintain the active slides visible in the viewport
975 | keepSlidesPosition();
976 |
977 | // save for later the elements that still need to be reordered
978 | v.wrapAroundElements = v.activeSection;
979 |
980 | // Recalculate animation variables
981 | v.dest = v.element.position();
982 | v.dtop = v.dest.top;
983 | v.yMovement = getYmovement(v.element);
984 |
985 | return v;
986 | }
987 |
988 | /**
989 | * Fix section order after continuousVertical changes have been animated
990 | */
991 | function continuousVerticalFixSectionOrder (v) {
992 | // If continuousVertical is in effect (and autoScrolling would also be in effect then),
993 | // finish moving the elements around so the direct navigation will function more simply
994 | if (!v.wrapAroundElements || !v.wrapAroundElements.length) {
995 | return;
996 | }
997 |
998 | if (v.isMovementUp) {
999 | $('.fp-section:first').before(v.wrapAroundElements);
1000 | }
1001 | else {
1002 | $('.fp-section:last').after(v.wrapAroundElements);
1003 | }
1004 |
1005 | silentScroll($('.fp-section.active').position().top);
1006 |
1007 | // Maintain the active slides visible in the viewport
1008 | keepSlidesPosition();
1009 | };
1010 |
1011 |
1012 | /**
1013 | * Actions to do once the section is loaded
1014 | */
1015 | function afterSectionLoads (v){
1016 | continuousVerticalFixSectionOrder(v);
1017 | //callback (afterLoad) if the site is not just resizing and readjusting the slides
1018 | $.isFunction(options.afterLoad) && !v.localIsResizing && options.afterLoad.call(this, v.anchorLink, (v.sectionIndex + 1));
1019 |
1020 | setTimeout(function () {
1021 | isMoving = false;
1022 | $.isFunction(v.callback) && v.callback.call(this);
1023 | }, scrollDelay);
1024 | }
1025 |
1026 |
1027 | /**
1028 | * Scrolls to the anchor in the URL when loading the site
1029 | */
1030 | function scrollToAnchor(){
1031 | //getting the anchor link in the URL and deleting the `#`
1032 | var value = window.location.hash.replace('#', '').split('/');
1033 | var section = value[0];
1034 | var slide = value[1];
1035 |
1036 | if(section){ //if theres any #
1037 | scrollPageAndSlide(section, slide);
1038 | }
1039 | }
1040 |
1041 | //detecting any change on the URL to scroll to the given anchor link
1042 | //(a way to detect back history button as we play with the hashes on the URL)
1043 | $(window).on('hashchange', hashChangeHandler);
1044 |
1045 | function hashChangeHandler(){
1046 | if(!isScrolling){
1047 | var value = window.location.hash.replace('#', '').split('/');
1048 | var section = value[0];
1049 | var slide = value[1];
1050 |
1051 | if(section.length){
1052 | //when moving to a slide in the first section for the first time (first time to add an anchor to the URL)
1053 | var isFirstSlideMove = (typeof lastScrolledDestiny === 'undefined');
1054 | var isFirstScrollMove = (typeof lastScrolledDestiny === 'undefined' && typeof slide === 'undefined' && !slideMoving);
1055 |
1056 | /*in order to call scrollpage() only once for each destination at a time
1057 | It is called twice for each scroll otherwise, as in case of using anchorlinks `hashChange`
1058 | event is fired on every scroll too.*/
1059 | if ((section && section !== lastScrolledDestiny) && !isFirstSlideMove || isFirstScrollMove || (!slideMoving && lastScrolledSlide != slide )) {
1060 | scrollPageAndSlide(section, slide);
1061 | }
1062 | }
1063 | }
1064 | }
1065 |
1066 |
1067 | /**
1068 | * Sliding with arrow keys, both, vertical and horizontal
1069 | */
1070 | $(document).keydown(function(e) {
1071 | //Moving the main page with the keyboard arrows if keyboard scrolling is enabled
1072 | if (options.keyboardScrolling && options.autoScrolling) {
1073 |
1074 | //preventing the scroll with arrow keys
1075 | if(e.which == 40 || e.which == 38){
1076 | e.preventDefault();
1077 | }
1078 |
1079 | if(!isMoving){
1080 | switch (e.which) {
1081 | //up
1082 | case 38:
1083 | case 33:
1084 | $.fn.fullpage.moveSectionUp();
1085 | break;
1086 |
1087 | //down
1088 | case 40:
1089 | case 34:
1090 | $.fn.fullpage.moveSectionDown();
1091 | break;
1092 |
1093 | //Home
1094 | case 36:
1095 | $.fn.fullpage.moveTo(1);
1096 | break;
1097 |
1098 | //End
1099 | case 35:
1100 | $.fn.fullpage.moveTo( $('.fp-section').length );
1101 | break;
1102 |
1103 | //left
1104 | case 37:
1105 | $.fn.fullpage.moveSlideLeft();
1106 | break;
1107 |
1108 | //right
1109 | case 39:
1110 | $.fn.fullpage.moveSlideRight();
1111 | break;
1112 |
1113 | default:
1114 | return; // exit this handler for other keys
1115 | }
1116 | }
1117 | }
1118 | });
1119 |
1120 | /**
1121 | * Scrolls to the section when clicking the navigation bullet
1122 | */
1123 | $(document).on('click touchstart', '#fp-nav a', function(e){
1124 | e.preventDefault();
1125 | var index = $(this).parent().index();
1126 | scrollPage($('.fp-section').eq(index));
1127 | });
1128 |
1129 | /**
1130 | * Scrolls the slider to the given slide destination for the given section
1131 | */
1132 | $(document).on('click touchstart', '.fp-slidesNav a', function(e){
1133 | e.preventDefault();
1134 | var slides = $(this).closest('.fp-section').find('.fp-slides');
1135 | var destiny = slides.find('.fp-slide').eq($(this).closest('li').index());
1136 |
1137 | landscapeScroll(slides, destiny);
1138 | });
1139 |
1140 | if(options.normalScrollElements){
1141 | $(document).on('mouseenter', options.normalScrollElements, function () {
1142 | $.fn.fullpage.setMouseWheelScrolling(false);
1143 | });
1144 |
1145 | $(document).on('mouseleave', options.normalScrollElements, function(){
1146 | $.fn.fullpage.setMouseWheelScrolling(true);
1147 | });
1148 | }
1149 |
1150 | /**
1151 | * Scrolling horizontally when clicking on the slider controls.
1152 | */
1153 | $('.fp-section').on('click touchstart', '.fp-controlArrow', function() {
1154 | if ($(this).hasClass('fp-prev')) {
1155 | $.fn.fullpage.moveSlideLeft();
1156 | } else {
1157 | $.fn.fullpage.moveSlideRight();
1158 | }
1159 | });
1160 |
1161 | /**
1162 | * Scrolls horizontal sliders.
1163 | */
1164 | function landscapeScroll(slides, destiny){
1165 | var destinyPos = destiny.position();
1166 | var slidesContainer = slides.find('.fp-slidesContainer').parent();
1167 | var slideIndex = destiny.index();
1168 | var section = slides.closest('.fp-section');
1169 | var sectionIndex = section.index('.fp-section');
1170 | var anchorLink = section.data('anchor');
1171 | var slidesNav = section.find('.fp-slidesNav');
1172 | var slideAnchor = destiny.data('anchor');
1173 |
1174 | //caching the value of isResizing at the momment the function is called
1175 | //because it will be checked later inside a setTimeout and the value might change
1176 | var localIsResizing = isResizing;
1177 |
1178 | if(options.onSlideLeave){
1179 | var prevSlideIndex = section.find('.fp-slide.active').index();
1180 | var xMovement = getXmovement(prevSlideIndex, slideIndex);
1181 |
1182 | //if the site is not just resizing and readjusting the slides
1183 | if(!localIsResizing && xMovement!=='none'){
1184 | $.isFunction( options.onSlideLeave ) && options.onSlideLeave.call( this, anchorLink, (sectionIndex + 1), prevSlideIndex, xMovement);
1185 | }
1186 | }
1187 |
1188 | destiny.addClass('active').siblings().removeClass('active');
1189 |
1190 |
1191 | if(typeof slideAnchor === 'undefined'){
1192 | slideAnchor = slideIndex;
1193 | }
1194 |
1195 | if(!options.loopHorizontal && options.controlArrows){
1196 | //hidding it for the fist slide, showing for the rest
1197 | section.find('.fp-controlArrow.fp-prev').toggle(slideIndex!=0);
1198 |
1199 | //hidding it for the last slide, showing for the rest
1200 | section.find('.fp-controlArrow.fp-next').toggle(!destiny.is(':last-child'));
1201 | }
1202 |
1203 | //only changing the URL if the slides are in the current section (not for resize re-adjusting)
1204 | if(section.hasClass('active')){
1205 | setState(slideIndex, slideAnchor, anchorLink, sectionIndex);
1206 | }
1207 |
1208 | var afterSlideLoads = function(){
1209 | //if the site is not just resizing and readjusting the slides
1210 | if(!localIsResizing){
1211 | $.isFunction( options.afterSlideLoad ) && options.afterSlideLoad.call( this, anchorLink, (sectionIndex + 1), slideAnchor, slideIndex);
1212 | }
1213 | //letting them slide again
1214 | slideMoving = false;
1215 | };
1216 |
1217 | if(options.css3){
1218 | var translate3d = 'translate3d(-' + destinyPos.left + 'px, 0px, 0px)';
1219 |
1220 | addAnimation(slides.find('.fp-slidesContainer'), options.scrollingSpeed>0).css(getTransforms(translate3d));
1221 |
1222 | setTimeout(function(){
1223 | afterSlideLoads();
1224 | }, options.scrollingSpeed, options.easing);
1225 | }else{
1226 | slidesContainer.animate({
1227 | scrollLeft : destinyPos.left
1228 | }, options.scrollingSpeed, options.easing, function() {
1229 |
1230 | afterSlideLoads();
1231 | });
1232 | }
1233 |
1234 | slidesNav.find('.active').removeClass('active');
1235 | slidesNav.find('li').eq(slideIndex).find('a').addClass('active');
1236 | }
1237 |
1238 | //when resizing the site, we adjust the heights of the sections, slimScroll...
1239 | $(window).resize(resizeHandler);
1240 |
1241 | var previousHeight = windowsHeight;
1242 | var resizeId;
1243 | function resizeHandler(){
1244 | //checking if it needs to get responsive
1245 | responsive();
1246 |
1247 | // rebuild immediately on touch devices
1248 | if (isTouchDevice) {
1249 |
1250 | //if the keyboard is visible
1251 | if ($(document.activeElement).attr('type') !== 'text') {
1252 | var currentHeight = $(window).height();
1253 |
1254 | //making sure the change in the viewport size is enough to force a rebuild. (20 % of the window to avoid problems when hidding scroll bars)
1255 | if( Math.abs(currentHeight - previousHeight) > (20 * Math.max(previousHeight, currentHeight) / 100) ){
1256 | $.fn.fullpage.reBuild(true);
1257 | previousHeight = currentHeight;
1258 | }
1259 | }
1260 | }else{
1261 | //in order to call the functions only when the resize is finished
1262 | //http://stackoverflow.com/questions/4298612/jquery-how-to-call-resize-event-only-once-its-finished-resizing
1263 | clearTimeout(resizeId);
1264 |
1265 | resizeId = setTimeout(function(){
1266 | $.fn.fullpage.reBuild(true);
1267 | }, 500);
1268 | }
1269 | }
1270 |
1271 | /**
1272 | * Checks if the site needs to get responsive and disables autoScrolling if so.
1273 | * A class `fp-responsive` is added to the plugin's container in case the user wants to use it for his own responsive CSS.
1274 | */
1275 | function responsive(){
1276 | if(options.responsive){
1277 | var isResponsive = container.hasClass('fp-responsive');
1278 | if ($(window).width() < options.responsive ){
1279 | if(!isResponsive){
1280 | $.fn.fullpage.setAutoScrolling(false, 'internal');
1281 | $('#fp-nav').hide();
1282 | container.addClass('fp-responsive');
1283 | }
1284 | }else if(isResponsive){
1285 | $.fn.fullpage.setAutoScrolling(originals.autoScrolling, 'internal');
1286 | $('#fp-nav').show();
1287 | container.removeClass('fp-responsive');
1288 | }
1289 | }
1290 | }
1291 |
1292 | /**
1293 | * Adds transition animations for the given element
1294 | */
1295 | function addAnimation(element){
1296 | var transition = 'all ' + options.scrollingSpeed + 'ms ' + options.easingcss3;
1297 |
1298 | element.removeClass('fp-notransition');
1299 | return element.css({
1300 | '-webkit-transition': transition,
1301 | 'transition': transition
1302 | });
1303 | }
1304 |
1305 | /**
1306 | * Remove transition animations for the given element
1307 | */
1308 | function removeAnimation(element){
1309 | return element.addClass('fp-notransition');
1310 | }
1311 |
1312 | /**
1313 | * Resizing of the font size depending on the window size as well as some of the images on the site.
1314 | */
1315 | function resizeMe(displayHeight, displayWidth) {
1316 | //Standard dimensions, for which the body font size is correct
1317 | var preferredHeight = 825;
1318 | var preferredWidth = 900;
1319 |
1320 | if (displayHeight < preferredHeight || displayWidth < preferredWidth) {
1321 | var heightPercentage = (displayHeight * 100) / preferredHeight;
1322 | var widthPercentage = (displayWidth * 100) / preferredWidth;
1323 | var percentage = Math.min(heightPercentage, widthPercentage);
1324 | var newFontSize = percentage.toFixed(2);
1325 |
1326 | $("body").css("font-size", newFontSize + '%');
1327 | } else {
1328 | $("body").css("font-size", '100%');
1329 | }
1330 | }
1331 |
1332 | /**
1333 | * Activating the website navigation dots according to the given slide name.
1334 | */
1335 | function activateNavDots(name, sectionIndex){
1336 | if(options.navigation){
1337 | $('#fp-nav').find('.active').removeClass('active');
1338 | if(name){
1339 | $('#fp-nav').find('a[href="#' + name + '"]').addClass('active');
1340 | }else{
1341 | $('#fp-nav').find('li').eq(sectionIndex).find('a').addClass('active');
1342 | }
1343 | }
1344 | }
1345 |
1346 | /**
1347 | * Activating the website main menu elements according to the given slide name.
1348 | */
1349 | function activateMenuElement(name){
1350 | if(options.menu){
1351 | $(options.menu).find('.active').removeClass('active');
1352 | $(options.menu).find('[data-menuanchor="'+name+'"]').addClass('active');
1353 | }
1354 | }
1355 |
1356 | function activateMenuAndNav(anchor, index){
1357 | activateMenuElement(anchor);
1358 | activateNavDots(anchor, index);
1359 | }
1360 |
1361 | /**
1362 | * Return a boolean depending on whether the scrollable element is at the end or at the start of the scrolling
1363 | * depending on the given type.
1364 | */
1365 | function isScrolled(type, scrollable){
1366 | if(type === 'top'){
1367 | return !scrollable.scrollTop();
1368 | }else if(type === 'bottom'){
1369 | return scrollable.scrollTop() + 1 + scrollable.innerHeight() >= scrollable[0].scrollHeight;
1370 | }
1371 | }
1372 |
1373 | /**
1374 | * Retuns `up` or `down` depending on the scrolling movement to reach its destination
1375 | * from the current section.
1376 | */
1377 | function getYmovement(destiny){
1378 | var fromIndex = $('.fp-section.active').index('.fp-section');
1379 | var toIndex = destiny.index('.fp-section');
1380 | if( fromIndex == toIndex){
1381 | return 'none'
1382 | }
1383 | if(fromIndex > toIndex){
1384 | return 'up';
1385 | }
1386 | return 'down';
1387 | }
1388 |
1389 | /**
1390 | * Retuns `right` or `left` depending on the scrolling movement to reach its destination
1391 | * from the current slide.
1392 | */
1393 | function getXmovement(fromIndex, toIndex){
1394 | if( fromIndex == toIndex){
1395 | return 'none'
1396 | }
1397 | if(fromIndex > toIndex){
1398 | return 'left';
1399 | }
1400 | return 'right';
1401 | }
1402 |
1403 |
1404 | function createSlimScrolling(element){
1405 | //needed to make `scrollHeight` work under Opera 12
1406 | element.css('overflow', 'hidden');
1407 |
1408 | //in case element is a slide
1409 | var section = element.closest('.fp-section');
1410 | var scrollable = element.find('.fp-scrollable');
1411 |
1412 | //if there was scroll, the contentHeight will be the one in the scrollable section
1413 | if(scrollable.length){
1414 | var contentHeight = scrollable.get(0).scrollHeight;
1415 | }else{
1416 | var contentHeight = element.get(0).scrollHeight;
1417 | if(options.verticalCentered){
1418 | contentHeight = element.find('.fp-tableCell').get(0).scrollHeight;
1419 | }
1420 | }
1421 |
1422 | var scrollHeight = windowsHeight - parseInt(section.css('padding-bottom')) - parseInt(section.css('padding-top'));
1423 |
1424 | //needs scroll?
1425 | if ( contentHeight > scrollHeight) {
1426 | //was there already an scroll ? Updating it
1427 | if(scrollable.length){
1428 | scrollable.css('height', scrollHeight + 'px').parent().css('height', scrollHeight + 'px');
1429 | }
1430 | //creating the scrolling
1431 | else{
1432 | if(options.verticalCentered){
1433 | element.find('.fp-tableCell').wrapInner('
');
1434 | }else{
1435 | element.wrapInner('
');
1436 | }
1437 |
1438 | element.find('.fp-scrollable').slimScroll({
1439 | allowPageScroll: true,
1440 | height: scrollHeight + 'px',
1441 | size: '10px',
1442 | alwaysVisible: true
1443 | });
1444 | }
1445 | }
1446 |
1447 | //removing the scrolling when it is not necessary anymore
1448 | else{
1449 | removeSlimScroll(element);
1450 | }
1451 |
1452 | //undo
1453 | element.css('overflow', '');
1454 | }
1455 |
1456 | function removeSlimScroll(element){
1457 | element.find('.fp-scrollable').children().first().unwrap().unwrap();
1458 | element.find('.slimScrollBar').remove();
1459 | element.find('.slimScrollRail').remove();
1460 | }
1461 |
1462 | function addTableClass(element){
1463 | element.addClass('fp-table').wrapInner('
');
1464 | }
1465 |
1466 | function getTableHeight(element){
1467 | var sectionHeight = windowsHeight;
1468 |
1469 | if(options.paddingTop || options.paddingBottom){
1470 | var section = element;
1471 | if(!section.hasClass('fp-section')){
1472 | section = element.closest('.fp-section');
1473 | }
1474 |
1475 | var paddings = parseInt(section.css('padding-top')) + parseInt(section.css('padding-bottom'));
1476 | sectionHeight = (windowsHeight - paddings);
1477 | }
1478 |
1479 | return sectionHeight;
1480 | }
1481 |
1482 | /**
1483 | * Adds a css3 transform property to the container class with or without animation depending on the animated param.
1484 | */
1485 | function transformContainer(translate3d, animated){
1486 | if(animated){
1487 | addAnimation(container);
1488 | }else{
1489 | removeAnimation(container);
1490 | }
1491 |
1492 | container.css(getTransforms(translate3d));
1493 |
1494 | //syncronously removing the class after the animation has been applied.
1495 | setTimeout(function(){
1496 | container.removeClass('fp-notransition');
1497 | },10)
1498 | }
1499 |
1500 |
1501 | /**
1502 | * Scrolls to the given section and slide
1503 | */
1504 | function scrollPageAndSlide(destiny, slide){
1505 | if (typeof slide === 'undefined') {
1506 | slide = 0;
1507 | }
1508 |
1509 | if(isNaN(destiny)){
1510 | var section = $('[data-anchor="'+destiny+'"]');
1511 | }else{
1512 | var section = $('.fp-section').eq( (destiny -1) );
1513 | }
1514 |
1515 |
1516 | //we need to scroll to the section and then to the slide
1517 | if (destiny !== lastScrolledDestiny && !section.hasClass('active')){
1518 | scrollPage(section, function(){
1519 | scrollSlider(section, slide)
1520 | });
1521 | }
1522 | //if we were already in the section
1523 | else{
1524 | scrollSlider(section, slide);
1525 | }
1526 | }
1527 |
1528 | /**
1529 | * Scrolls the slider to the given slide destination for the given section
1530 | */
1531 | function scrollSlider(section, slide){
1532 | if(typeof slide != 'undefined'){
1533 | var slides = section.find('.fp-slides');
1534 | var destiny = slides.find('[data-anchor="'+slide+'"]');
1535 |
1536 | if(!destiny.length){
1537 | destiny = slides.find('.fp-slide').eq(slide);
1538 | }
1539 |
1540 | if(destiny.length){
1541 | landscapeScroll(slides, destiny);
1542 | }
1543 | }
1544 | }
1545 |
1546 | /**
1547 | * Creates a landscape navigation bar with dots for horizontal sliders.
1548 | */
1549 | function addSlidesNavigation(section, numSlides){
1550 | section.append('');
1551 | var nav = section.find('.fp-slidesNav');
1552 |
1553 | //top or bottom
1554 | nav.addClass(options.slidesNavPosition);
1555 |
1556 | for(var i=0; i< numSlides; i++){
1557 | nav.find('ul').append(' ');
1558 | }
1559 |
1560 | //centering it
1561 | nav.css('margin-left', '-' + (nav.width()/2) + 'px');
1562 |
1563 | nav.find('li').first().find('a').addClass('active');
1564 | }
1565 |
1566 |
1567 | /**
1568 | * Sets the state of the website depending on the active section/slide.
1569 | * It changes the URL hash when needed and updates the body class.
1570 | */
1571 | function setState(slideIndex, slideAnchor, anchorLink, sectionIndex){
1572 | var sectionHash = '';
1573 |
1574 | if(options.anchors.length){
1575 |
1576 | //isn't it the first slide?
1577 | if(slideIndex){
1578 | if(typeof anchorLink !== 'undefined'){
1579 | sectionHash = anchorLink;
1580 | }
1581 |
1582 | //slide without anchor link? We take the index instead.
1583 | if(typeof slideAnchor === 'undefined'){
1584 | slideAnchor = slideIndex;
1585 | }
1586 |
1587 | lastScrolledSlide = slideAnchor;
1588 | setUrlHash(sectionHash + '/' + slideAnchor);
1589 |
1590 | //first slide won't have slide anchor, just the section one
1591 | }else if(typeof slideIndex !== 'undefined'){
1592 | lastScrolledSlide = slideAnchor;
1593 | setUrlHash(anchorLink);
1594 | }
1595 |
1596 | //section without slides
1597 | else{
1598 | setUrlHash(anchorLink);
1599 | }
1600 |
1601 | setBodyClass(location.hash);
1602 | }
1603 | else if(typeof slideIndex !== 'undefined'){
1604 | setBodyClass(sectionIndex + '-' + slideIndex);
1605 | }
1606 | else{
1607 | setBodyClass(String(sectionIndex));
1608 | }
1609 | }
1610 |
1611 | /**
1612 | * Sets the URL hash.
1613 | */
1614 | function setUrlHash(url){
1615 | if(options.recordHistory){
1616 | location.hash = url;
1617 | }else{
1618 | //Mobile Chrome doesn't work the normal way, so... lets use HTML5 for phones :)
1619 | if(isTouchDevice || isTouch){
1620 | history.replaceState(undefined, undefined, "#" + url)
1621 | }else{
1622 | var baseUrl = window.location.href.split('#')[0];
1623 | window.location.replace( baseUrl + '#' + url );
1624 | }
1625 | }
1626 | }
1627 |
1628 | /**
1629 | * Sets a class for the body of the page depending on the active section / slide
1630 | */
1631 | function setBodyClass(text){
1632 | //changing slash for dash to make it a valid CSS style
1633 | text = text.replace('/', '-').replace('#','');
1634 |
1635 | //removing previous anchor classes
1636 | $("body")[0].className = $("body")[0].className.replace(/\b\s?fp-viewing-[^\s]+\b/g, '');
1637 |
1638 | //adding the current anchor
1639 | $("body").addClass("fp-viewing-" + text);
1640 | }
1641 |
1642 | /**
1643 | * Checks for translate3d support
1644 | * @return boolean
1645 | * http://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
1646 | */
1647 | function support3d() {
1648 | var el = document.createElement('p'),
1649 | has3d,
1650 | transforms = {
1651 | 'webkitTransform':'-webkit-transform',
1652 | 'OTransform':'-o-transform',
1653 | 'msTransform':'-ms-transform',
1654 | 'MozTransform':'-moz-transform',
1655 | 'transform':'transform'
1656 | };
1657 |
1658 | // Add it to the body to get the computed style.
1659 | document.body.insertBefore(el, null);
1660 |
1661 | for (var t in transforms) {
1662 | if (el.style[t] !== undefined) {
1663 | el.style[t] = "translate3d(1px,1px,1px)";
1664 | has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
1665 | }
1666 | }
1667 |
1668 | document.body.removeChild(el);
1669 |
1670 | return (has3d !== undefined && has3d.length > 0 && has3d !== "none");
1671 | }
1672 |
1673 |
1674 |
1675 | /**
1676 | * Removes the auto scrolling action fired by the mouse wheel and trackpad.
1677 | * After this function is called, the mousewheel and trackpad movements won't scroll through sections.
1678 | */
1679 | function removeMouseWheelHandler(){
1680 | if (document.addEventListener) {
1681 | document.removeEventListener('mousewheel', MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
1682 | document.removeEventListener('wheel', MouseWheelHandler, false); //Firefox
1683 | } else {
1684 | document.detachEvent("onmousewheel", MouseWheelHandler); //IE 6/7/8
1685 | }
1686 | }
1687 |
1688 |
1689 | /**
1690 | * Adds the auto scrolling action for the mouse wheel and trackpad.
1691 | * After this function is called, the mousewheel and trackpad movements will scroll through sections
1692 | */
1693 | function addMouseWheelHandler(){
1694 | if (document.addEventListener) {
1695 | document.addEventListener("mousewheel", MouseWheelHandler, false); //IE9, Chrome, Safari, Oper
1696 | document.addEventListener("wheel", MouseWheelHandler, false); //Firefox
1697 | } else {
1698 | document.attachEvent("onmousewheel", MouseWheelHandler); //IE 6/7/8
1699 | }
1700 | }
1701 |
1702 |
1703 | /**
1704 | * Adds the possibility to auto scroll through sections on touch devices.
1705 | */
1706 | function addTouchHandler(){
1707 | if(isTouchDevice || isTouch){
1708 | //Microsoft pointers
1709 | MSPointer = getMSPointer();
1710 |
1711 | $(document).off('touchstart ' + MSPointer.down).on('touchstart ' + MSPointer.down, touchStartHandler);
1712 | $(document).off('touchmove ' + MSPointer.move).on('touchmove ' + MSPointer.move, touchMoveHandler);
1713 | }
1714 | }
1715 |
1716 | /**
1717 | * Removes the auto scrolling for touch devices.
1718 | */
1719 | function removeTouchHandler(){
1720 | if(isTouchDevice || isTouch){
1721 | //Microsoft pointers
1722 | MSPointer = getMSPointer();
1723 |
1724 | $(document).off('touchstart ' + MSPointer.down);
1725 | $(document).off('touchmove ' + MSPointer.move);
1726 | }
1727 | }
1728 |
1729 |
1730 | /*
1731 | * Returns and object with Microsoft pointers (for IE<11 and for IE >= 11)
1732 | * http://msdn.microsoft.com/en-us/library/ie/dn304886(v=vs.85).aspx
1733 | */
1734 | function getMSPointer(){
1735 | var pointer;
1736 |
1737 | //IE >= 11 & rest of browsers
1738 | if(window.PointerEvent){
1739 | pointer = { down: "pointerdown", move: "pointermove"};
1740 | }
1741 |
1742 | //IE < 11
1743 | else{
1744 | pointer = { down: "MSPointerDown", move: "MSPointerMove"};
1745 | }
1746 |
1747 | return pointer;
1748 | }
1749 | /**
1750 | * Gets the pageX and pageY properties depending on the browser.
1751 | * https://github.com/alvarotrigo/fullPage.js/issues/194#issuecomment-34069854
1752 | */
1753 | function getEventsPage(e){
1754 | var events = new Array();
1755 |
1756 | events['y'] = (typeof e.pageY !== 'undefined' && (e.pageY || e.pageX) ? e.pageY : e.touches[0].pageY);
1757 | events['x'] = (typeof e.pageX !== 'undefined' && (e.pageY || e.pageX) ? e.pageX : e.touches[0].pageX);
1758 |
1759 | return events;
1760 | }
1761 |
1762 | function silentLandscapeScroll(activeSlide){
1763 | $.fn.fullpage.setScrollingSpeed (0, 'internal');
1764 | landscapeScroll(activeSlide.closest('.fp-slides'), activeSlide);
1765 | $.fn.fullpage.setScrollingSpeed(originals.scrollingSpeed, 'internal');
1766 | }
1767 |
1768 | function silentScroll(top){
1769 | if(options.scrollBar){
1770 | container.scrollTop(top);
1771 | }
1772 | else if (options.css3) {
1773 | var translate3d = 'translate3d(0px, -' + top + 'px, 0px)';
1774 | transformContainer(translate3d, false);
1775 | }
1776 | else {
1777 | container.css("top", -top);
1778 | }
1779 | }
1780 |
1781 | function getTransforms(translate3d){
1782 | return {
1783 | '-webkit-transform': translate3d,
1784 | '-moz-transform': translate3d,
1785 | '-ms-transform':translate3d,
1786 | 'transform': translate3d
1787 | };
1788 | }
1789 |
1790 | function setIsScrollable(value, direction){
1791 | switch (direction){
1792 | case 'up': isScrollAllowed.up = value; break;
1793 | case 'down': isScrollAllowed.down = value; break;
1794 | case 'left': isScrollAllowed.left = value; break;
1795 | case 'right': isScrollAllowed.right = value; break;
1796 | case 'all': $.fn.fullpage.setAllowScrolling(value);
1797 | }
1798 | }
1799 |
1800 |
1801 | /*
1802 | * Destroys fullpage.js plugin events and optinally its html markup and styles
1803 | */
1804 | $.fn.fullpage.destroy = function(all){
1805 | $.fn.fullpage.setAutoScrolling(false, 'internal');
1806 | $.fn.fullpage.setAllowScrolling(false);
1807 | $.fn.fullpage.setKeyboardScrolling(false);
1808 |
1809 |
1810 | $(window)
1811 | .off('scroll', scrollHandler)
1812 | .off('hashchange', hashChangeHandler)
1813 | .off('resize', resizeHandler);
1814 |
1815 | $(document)
1816 | .off('click', '#fp-nav a')
1817 | .off('mouseenter', '#fp-nav li')
1818 | .off('mouseleave', '#fp-nav li')
1819 | .off('click', '.fp-slidesNav a')
1820 | .off('mouseover', options.normalScrollElements)
1821 | .off('mouseout', options.normalScrollElements);
1822 |
1823 | $('.fp-section')
1824 | .off('click', '.fp-controlArrow');
1825 |
1826 | //lets make a mess!
1827 | if(all){
1828 | destroyStructure();
1829 | }
1830 | };
1831 |
1832 | /*
1833 | * Removes inline styles added by fullpage.js
1834 | */
1835 | function destroyStructure(){
1836 | //reseting the `top` or `translate` properties to 0
1837 | silentScroll(0);
1838 |
1839 | $('#fp-nav, .fp-slidesNav, .fp-controlArrow').remove();
1840 |
1841 | //removing inline styles
1842 | $('.fp-section').css( {
1843 | 'height': '',
1844 | 'background-color' : '',
1845 | 'padding': ''
1846 | });
1847 |
1848 | $('.fp-slide').css( {
1849 | 'width': ''
1850 | });
1851 |
1852 | container.css({
1853 | 'height': '',
1854 | 'position': '',
1855 | '-ms-touch-action': '',
1856 | 'touch-action': ''
1857 | });
1858 |
1859 | //removing added classes
1860 | $('.fp-section, .fp-slide').each(function(){
1861 | removeSlimScroll($(this));
1862 | $(this).removeClass('fp-table active');
1863 | });
1864 |
1865 | removeAnimation(container);
1866 | removeAnimation(container.find('.fp-easing'));
1867 |
1868 | //Unwrapping content
1869 | container.find('.fp-tableCell, .fp-slidesContainer, .fp-slides').each(function(){
1870 | //unwrap not being use in case there's no child element inside and its just text
1871 | $(this).replaceWith(this.childNodes);
1872 | });
1873 |
1874 | //scrolling the page to the top with no animation
1875 | $('html, body').scrollTop(0);
1876 | }
1877 |
1878 | /*
1879 | * Sets the state for a variable with multiple states (original, and temporal)
1880 | * Some variables such as `autoScrolling` or `recordHistory` might change automatically its state when using `responsive` or `autoScrolling:false`.
1881 | * This function is used to keep track of both states, the original and the temporal one.
1882 | * If type is not 'internal', then we assume the user is globally changing the variable.
1883 | */
1884 | function setVariableState(variable, value, type){
1885 | options[variable] = value;
1886 | if(type !== 'internal'){
1887 | originals[variable] = value;
1888 | }
1889 | }
1890 |
1891 | /**
1892 | * Displays warnings
1893 | */
1894 | function displayWarnings(){
1895 | // Disable mutually exclusive settings
1896 | if (options.continuousVertical &&
1897 | (options.loopTop || options.loopBottom)) {
1898 | options.continuousVertical = false;
1899 | showError('warn', "Option `loopTop/loopBottom` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled");
1900 | }
1901 | if(options.continuousVertical && options.scrollBar){
1902 | options.continuousVertical = false;
1903 | showError('warn', "Option `scrollBar` is mutually exclusive with `continuousVertical`; `continuousVertical` disabled");
1904 | }
1905 |
1906 | //anchors can not have the same value as any element ID or NAME
1907 | $.each(options.anchors, function(index, name){
1908 | if($('#' + name).length || $('[name="'+name+'"]').length ){
1909 | showError('error', "data-anchor tags can not have the same value as any `id` element on the site (or `name` element for IE).");
1910 | }
1911 | });
1912 | }
1913 |
1914 | function showError(type, text){
1915 | console && console[type] && console[type]('fullPage: ' + text);
1916 | }
1917 | };
1918 | })(jQuery);
1919 |
--------------------------------------------------------------------------------