├── README.md
├── assets
├── jquery.alton.js
└── jquery.alton.min.js
├── bower.json
└── package.json
/README.md:
--------------------------------------------------------------------------------
1 | # README #
2 |
3 | ## What is Alton? ##
4 | Alton is a jQuery-powered scrolling plugin that utilizes custom vertical scrolling effects in order to present and navigate through web content in a unique manner. It utilizes the whole scrolljacking idea, but greatly improves upon the often-poorly-implemented scrolljacking experiences you might be used to.
5 |
6 | ## What makes Alton unique? ##
7 | Good question. Here's why Alton rules:
8 |
9 | 1. The **Standard** functionality. Standard brings you the full page scrolling you're used to by making the "featured area of projects" in the middle section 100% height, and each scroll directs you to the next one (scroll down) or previous (scroll up). [Here's a demo of Standard.](http://demo.paper-leaf.com/alton/standard)
10 |
11 | 2. The **Bookend** functionality. This allows you to create a bookend experience which allows you to seamlessly introduce your full height section, and summarize or even conclude it. [Here's a demo of Bookend.](http://demo.paper-leaf.com/alton/bookend)
12 |
13 | 3. The **Hero Scroll** functionality. This allows you to scrolljack *only* the "Hero Section", wherein the page will scoll to the top of the section that immediately follows the Hero Section, then re-enable native scrolling for the rest of the page. [Here's a demo of Hero Scroll.](http://demo.paper-leaf.com/alton/heroscroll)
14 |
15 | 4. The plugin uses **100% height** containers for full-screen presentation; it's great for impactful presentation.
16 |
17 | 5. You have options for a **couple of different layouts** right out of the box.
18 |
19 | 6. It's **lightweight, easy to implement,** and **not CPU intensive.**
20 |
21 | ## What is "ScrollJacking"? ##
22 | Scrolljacking basically means we replace native scrolling (what you're used to) with targeted scrolling: when the user initiates a scroll, either with their mouse or keyboard, scrolljacking takes them to an exact vertical point on the screen (for example, the top of the next content container). When done properly, scrolljacking can be a part of a unique, enjoyable online experience.
23 |
24 | ## Compatibility ##
25 | This plugin has been tested on IE9+ and with jQuery 1.7+. Anything less and you're on your own for now – sorry!
26 |
27 | ## Demos ##
28 | In case you missed the links above, here are a few demos showing the different ways Alton can be used. You can also take a quick peek under the hood there to see exactly how we're implementing it.
29 |
30 | [Demo 1 (Standard Implementation)](http://demo.paper-leaf.com/alton/standard)
31 |
32 | [Demo 2 (with Bookend functionality)](http://demo.paper-leaf.com/alton/bookend)
33 |
34 | [Demo 3 (with Hero Scroll functionality)](http://demo.paper-leaf.com/alton/heroscroll)
35 |
36 | ## Quick start ##
37 | ### Standard Functionality ###
38 | *Standard* functionality brings you the full page scrolling you're used to. The "featured area of projects" in the middle section are all 100% height, and each scroll directs you to the next one (scroll down) or previous (scroll up). [Here's a demo of Standard.](http://demo.paper-leaf.com/alton/standard)
39 |
40 | Here is an example for all the options needed for *Standard*:
41 |
42 | First ensure you have the proper HTML structure:
43 | ```html
44 |
45 |
50 |
51 | ```
52 |
53 | Next add the following JavaScript where you want to call it. Note: **If you don't want errors to occur, only run the script on the page where scrolling occurs**
54 |
55 | ```js
56 | $(document).alton({
57 | fullSlideContainer: 'full', // Tell Alton the full height container
58 | singleSlideClass: 'slide', // Tell Alton the full height slide class
59 | useSlideNumbers: true, // Set to false if you don't want to use pagination
60 | slideNumbersBorderColor: '#fff', // Set the outside color of the pagination items (also used for active)
61 | slideNumbersColor: 'transparent', // Set the inner color of the pagination items (not active)
62 | bodyContainer: 'pageWrapper', // Tell Alton the body class
63 | });
64 | ```
65 |
66 | ### Bookend Functionality ###
67 | The Idea behind *Bookend* functionality is that you have a header and footer sections ("bookends"), with a featured area of projects or something in the middle. The "featured area of projects" in the middle section are all 100% height, whereas the bookends can be whatever height you'd like them to be. [Here's a demo of Bookend.](http://demo.paper-leaf.com/alton/bookend)
68 |
69 | Here is an example for all the options needed for *Bookend*:
70 |
71 | First ensure you have the proper HTML structure:
72 |
73 | ```html
74 |
75 |
76 |
77 |
82 |
83 |
84 | ```
85 |
86 | Next add the following JavaScript where you want to call it. Note: **If you don't want errors to occur, only run the script on the page where scrolling occurs**
87 |
88 | ```js
89 | $(document).alton({
90 | fullSlideContainer: 'full', // Tell Alton the full height container
91 | singleSlideClass: 'slide', // Tell Alton the full height slide class
92 | useSlideNumbers: true, // Set to false if you don't want to use pagination
93 | slideNumbersBorderColor: '#fff', // Set the outside color of the pagination items (also used for active)
94 | slideNumbersColor: 'transparent', // Set the inner color of the pagination items (not active)
95 | bodyContainer: 'pageWrapper', // Tell Alton the body class
96 | });
97 | ```
98 |
99 | ### Hero Scroll ###
100 | The Idea behind *Hero Scroll* is that we only apply scrolljacking to the topmost "Hero" container; one scroll movement takes the user to the top of the next section of content and native scrolling is enabled. [Here's a demo of Hero Scroll.](http://demo.paper-leaf.com/alton/heroscroll)
101 |
102 | Here is an example for all the options needed for *Hero Scroll*:
103 |
104 | First ensure you have the proper HTML structure:
105 |
106 | ```html
107 |
110 |
113 | ```
114 |
115 | Next add the following JavaScript where you want to call it. Note: **If you don't want errors to occur, only run the script on the page where scrolling occurs**
116 |
117 | ```js
118 | $(document).alton({
119 | firstClass : 'header', // Set the first container class
120 | bodyContainer: 'pageWrapper', // Set the body container
121 | scrollMode: 'headerScroll', // Set the scroll mode
122 | });
123 | ```
124 |
125 | ### All Available Options ###
126 |
127 | Here's a list of all the options that come built in to Alton, along with their default values.
128 |
129 | ```js
130 | firstClass : 'header', // classname of the first element in your page content
131 | fullSlideContainer : 'full', // full page elements container for
132 | singleSlideClass : 'slide', // class for each individual slide
133 | nextElement : 'div', // set the first element in the first page series.
134 | previousClass : null, // null when starting at the top. Will be updated based on current postion
135 | lastClass: 'footer', // last block to scroll to
136 | slideNumbersContainer: 'slide-numbers', // ID of Slide Numbers
137 | bodyContainer: 'pageWrapper', // ID of content container
138 | scrollMode: 'featuredScroll', // Choose scroll mode
139 | useSlideNumbers: false, // Enable or disable slider
140 | slideNumbersBorderColor: '#fff', // outside color for slide numbers
141 | slideNumbersColor: '#000', // interior color when slide numbers inactive
142 | ```
143 | ## What's included ##
144 |
145 | ## Bugs and feature requests ##
146 |
147 | Have a bug or a feature request? Please first read the issue guidelines and search for existing and closed issues. If your problem or idea is not addressed yet, please open a new issue.
148 |
149 | ### Currently Working On ###
150 | * Custom Animations
151 | * More Customization for slide number indicators (pagination)
152 |
153 | ## Keep track of our progress. ##
154 |
155 | Follow [@paper_leaf](https://twitter.com/paper_leaf) on Twitter.
156 |
157 | ## Copyright and License ##
158 | *Copyright 2014 Paper Leaf Design*
159 |
160 | License: GPL v3
161 |
162 | ## Frequently Asked Questions ##
163 | #### Does this work on touchscreens? ####
164 | No.
165 | #### Why not? ####
166 | Touch events are a different beast, and considering the amount of people on cheaper, less powerful devices, or even the majority still stuck in contracts, the usability is usually non-existent. That being said, we are continuing to explore ways of implementing this for mobile devices.
167 | #### So you are looking at adding mobile functionality? ####
168 | Possibly!
169 | #### What currently happens on mobile devices, then, if Alton doesn't work? ####
170 | It falls back to regular scrolling on mobile. It's the best of both worlds, like pizza made out of candy.
171 | #### Scrolling appears unresponsive at times. What's going on? ####
172 | After every scroll there's a delay in effect to help get rid of Inertia Scroll on Macs. If you try to scroll within this delay it will prevent you from scrolling, until the barrage of mousewheel events has ended.
173 | #### Why did you name this plugin Alton? ####
174 | We're playing off the idea of height, in that this plugin uses 100% height containers. That led us to the discovery of [Robert Wadlow](http://en.wikipedia.org/wiki/Robert_Wadlow), the world's tallest man – also known as the Alton Giant. *mic drop*
175 |
--------------------------------------------------------------------------------
/assets/jquery.alton.js:
--------------------------------------------------------------------------------
1 | /* ===============================================================================
2 | * alton.js v1.2.1
3 | * ===============================================================================
4 | * Copyright 2014 Paper Leaf Design
5 | * http://www.paper-leaf.com
6 | *
7 | * Author: Paper Leaf
8 | *
9 | * A full featured scrolling plugin for creating
10 | * immersive featured sections or headers.
11 | *
12 | * Credit:
13 | * is_mobile() based off these helpful posts
14 | * - http://stackoverflow.com/questions/3514784/what-is-the-best-way-to-detect-a-handheld-device-in-jquery
15 | *
16 | * Getting stable scroll events was helped hugely by Huge Inc's insights
17 | * - http://www.hugeinc.com/ideas/perspective/scroll-jacking-on-hugeinc
18 | *
19 | * Stabilizing keypress events was helped in large part by jQuery OnePage Scroll
20 | * - https://github.com/peachananr/onepage-scroll
21 | *
22 | * License: GPL v3
23 | * =============================================================================== */
24 |
25 | (function($) {
26 | /* ===============================================================================
27 | * Table of Contents
28 | * -------------------
29 | *
30 | * 1. Default Options
31 | * 2. Global Variables
32 | * 3. Initiate Layout
33 | * 4. Mobile Device Check
34 | * 5. Click to Navigate
35 | * 6. Update Position
36 | * 7. Move Up
37 | * 8. Move Down
38 | * 9. Prevent Default Animations
39 | * 10. Scroll To
40 | * 11. Featured Scroll
41 | * 12. Header Scroll
42 | *
43 | * =============================================================================== */
44 |
45 | /* =============================================================================
46 | * Default Options
47 | * -------------------
48 | * Creating defaults in case the user doesn't feel like adding their own
49 | * ============================================================================= */
50 | "use strict";
51 | var defaults = {
52 | firstClass: 'header', // classname of the first element in your page content
53 | fullSlideContainer: 'full', // full page elements container for
54 | singleSlideClass: 'slide', // class for each individual slide
55 | nextElement: 'div', // set the first element in the first page series.
56 | previousClass: null, // null when starting at the top. Will be updated based on current postion
57 | lastClass: 'footer', // last block to scroll to
58 | slideNumbersContainer: 'slide-numbers', // ID of Slide Numbers
59 | bodyContainer: 'pageWrapper', // ID of content container
60 | scrollMode: 'featuredScroll', // Choose scroll mode
61 | useSlideNumbers: false, // Enable or disable slider
62 | slideNumbersBorderColor: '#fff', // outside color for slide numbers
63 | slideNumbersColor: '#000', // interior color when slide numbers inactive
64 | animationType: 'slow', // animation type: currently doesn't do anything
65 | callback: false, // default is no callback
66 | };
67 |
68 | $.fn.alton = function(options) {
69 | /* =============================================================================
70 | * User Settings
71 | * -------------------
72 | * Update the default settings with user selected options
73 | * ============================================================================= */
74 | var settings = $.extend(true, {}, defaults, options),
75 |
76 | /* =============================================================================
77 | * Global Variables
78 | * -------------------
79 | * Setting up variables that will be used throught the plugin
80 | * ============================================================================= */
81 | singleSlideClass = settings.singleSlideClass,
82 | singleSlide,
83 | bodyScroll,
84 | down = false,
85 | up = false,
86 | current = $('.' + settings.firstClass),
87 | next = $('.' + singleSlideClass + ':first'),
88 | previous = null,
89 | last = $('.' + settings.lastClass),
90 | projectCount = $('.' + settings.fullSlideContainer).children().length,
91 | slideNumbers,
92 | top = true,
93 | upCount = 0,
94 | downCount = 0,
95 | windowHeight = $(window).outerHeight(),
96 | animating = false,
97 | docElem = window.document.documentElement,
98 | scrollOffset,
99 | offsetTest,
100 | i;
101 |
102 | // IE8 Support for getElementsByClassname
103 | if ('getElementsByClassName' in document) {
104 | singleSlide = document.getElementsByClassName(singleSlideClass);
105 | } else {
106 | singleSlide = document.querySelectorAll('.' + singleSlideClass);
107 | }
108 |
109 | if (!current.length) {
110 | current = next;
111 | next = current.next();
112 | }
113 | if (!last.length) {
114 | last = $('.' + singleSlideClass + ':last');
115 | }
116 | last = last[0];
117 |
118 | /* =============================================================================
119 | * Position Variables
120 | * -------------------
121 | * Update postion variable if headerScroll
122 | * ============================================================================= */
123 | if (settings.scrollMode === 'headerScroll') {
124 | current = $('.' + settings.firstClass); // current element is the topmost element
125 | next = $('.' + settings.bodyContainer + ':first');
126 | }
127 |
128 | /* ============================================================================
129 | * Initiate Layout
130 | * -------------------
131 | * Get the slides to 100% height, and add pagination
132 | * ============================================================================ */
133 | function initiateLayout(style) {
134 | if (style === 'featuredScroll') {
135 | for (i = singleSlide.length - 1; i >= 0; i -= 1) {
136 | if (is_mobile()) {
137 | if ($(singleSlide[i]).height() > windowHeight) {
138 | $(singleSlide[i]).css('height', $(singleSlide[i]).height());
139 | } else {
140 | $(singleSlide[i]).css('height', windowHeight);
141 | $(singleSlide[i]).outerHeight(windowHeight);
142 | }
143 | } else {
144 | $(singleSlide[i]).css('height', windowHeight);
145 | $(singleSlide[i]).outerHeight(windowHeight);
146 |
147 | }
148 | }
149 | if (settings.useSlideNumbers && !is_mobile()) {
150 | // Create Slider Buttons
151 | $('.' + settings.bodyContainer).append('');
152 | $('#' + settings.slideNumbersContainer).css({
153 | 'height': '100%',
154 | 'position': 'fixed',
155 | 'top': 0,
156 | 'right': '0px',
157 | 'bottom': '0px',
158 | 'width': '86px',
159 | 'z-index': 999
160 | });
161 | if (is_mobile()) {
162 | $('#' + settings.slideNumbersContainer).css({
163 | 'height': 'auto',
164 | 'min-height': '100%'
165 | });
166 | }
167 | $('.' + settings.bodyContainer + ' #' + settings.slideNumbersContainer).append('');
168 | $('.' + settings.bodyContainer + ' #' + settings.slideNumbersContainer + ' ul').css({
169 | 'transform': 'translateY(-50%)',
170 | '-moz-transform': 'translateY(-50%)',
171 | '-ms-transform': 'translateY(-50%)',
172 | '-o-transform': 'translateY(-50%)',
173 | '-webkit-transform': 'translateY(-50%)',
174 | 'top': '50%',
175 | 'position': 'fixed'
176 | });
177 |
178 | var testCount = 0;
179 |
180 | while (testCount < projectCount) {
181 | $('.' + settings.bodyContainer + ' #' + settings.slideNumbersContainer + ' ul').append('');
182 | if (msieversion()) {
183 | $('.paginate').css({
184 | 'cursor': 'pointer',
185 | 'border-radius': '50%',
186 | 'list-style': 'none',
187 | 'background': settings.slideNumbersBorderColor,
188 | 'border-color': settings.slideNumbersBorderColor,
189 | 'border-width': '2px',
190 | 'border-style': 'solid',
191 | 'height': '11px',
192 | 'width': '11px',
193 | 'margin': '5px 0'
194 | });
195 | } else {
196 | $('.paginate').css({
197 | 'cursor': 'pointer',
198 | 'border-radius': '50%',
199 | 'list-style': 'none',
200 | 'background': settings.slideNumbersBorderColor,
201 | 'border-color': settings.slideNumbersBorderColor,
202 | 'border-width': '2px',
203 | 'border-style': 'solid',
204 | 'height': '10px',
205 | 'width': '10px',
206 | 'margin': '5px 0'
207 | });
208 | }
209 |
210 | testCount += 1;
211 | }
212 | // Store the slidenumbers
213 | // IE8 Support for getElementsByClassname
214 | if (('getElementsByClassName' in document)) {
215 | slideNumbers = document.getElementsByClassName('paginate');
216 | } else {
217 | slideNumbers = document.querySelectorAll('.paginate');
218 | }
219 | }
220 | } else {
221 | $('.' + settings.firstClass).css('height', windowHeight + 10);
222 | if (!$('.' + settings.firstClass).hasClass('active')) {
223 | $('.' + settings.firstClass).toggleClass('active');
224 | if (msieversion()) {
225 | $('.paginate.active').css({
226 | 'margin-left': '-1px',
227 | 'border-color': '#' + settings.slideNumbersBorderColor,
228 | 'border-style': 'solid',
229 | 'border-width': '2px',
230 | 'height': '8px',
231 | 'width': '8px'
232 | });
233 | }
234 | }
235 | }
236 | }
237 |
238 | function msieversion() {
239 | var ua = window.navigator.userAgent;
240 | var msie = ua.indexOf("MSIE ");
241 |
242 | if (msie > 0 || navigator.userAgent.match(/Trident.*rv\:11\./)) { // If Internet Explorer, return version number
243 | return true;
244 | } else {
245 | return false;
246 | }
247 | }
248 |
249 | /* ============================================================================
250 | * Mobile device check
251 | * -------------------
252 | * Check if mobile device
253 | * ============================================================================ */
254 | function is_mobile() {
255 | return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|Windows Phone|Tizen|Bada)/);
256 | }
257 |
258 | /* ============================================================================
259 | * Update pagination
260 | * -------------------
261 | * Updates pagination on scroll down or up when called etc.
262 | * ============================================================================ */
263 | function slideIndex(element, toggle) {
264 | if (toggle && $(slideNumbers[$(element).parent().children().index(element)]).hasClass('active')) {
265 | $(slideNumbers[$(element).parent().children().index(element)]).toggleClass('active');
266 | $(slideNumbers[$(element).parent().children().index(element)]).css('background', settings.slideNumbersBorderColor);
267 | } else if (!$(slideNumbers[$(element).parent().children().index(element)]).hasClass('active')) {
268 | $(slideNumbers[$(element).parent().children().index(element)]).toggleClass('active');
269 | $(slideNumbers[$(element).parent().children().index(element)]).css('background', settings.slideNumbersColor);
270 | }
271 | }
272 |
273 | /* ============================================================================
274 | * Slide Numbers Fade
275 | * -------------------
276 | * Fades out the slide numbers
277 | * ============================================================================ */
278 | function slideNumbersFade(fadeInOut) {
279 | if (settings.useSlideNumbers) {
280 | if (fadeInOut) {
281 | $('#' + settings.slideNumbersContainer).fadeIn();
282 | } else {
283 | $('#' + settings.slideNumbersContainer).fadeOut();
284 | }
285 | }
286 | }
287 |
288 | /* ============================================================================
289 | * Click to Navigate
290 | * -------------------
291 | * Adds click to navigate functionality to pagination
292 | * ============================================================================ */
293 | function clickToNavigate(elementIndex) {
294 | var elementContainer = document.getElementsByClassName(singleSlideClass);
295 | $(document).scrollTo($(elementContainer[elementIndex]));
296 | current = elementContainer[elementIndex];
297 | if ($(current).prev().hasClass(singleSlideClass)) {
298 | previous = $(current).prev();
299 | } else {
300 | previous = $('.' + settings.firstClass);
301 | }
302 | if ($(current).next().hasClass(singleSlideClass)) {
303 | next = $(current).next();
304 | } else {
305 | next = $('.' + settings.lastClass);
306 | }
307 |
308 | slideIndex($('#' + settings.slideNumbersContainer + ' li.active'), true);
309 | slideIndex(elementContainer[elementIndex], false);
310 |
311 | // Callback function
312 | if ( typeof settings.callback == 'function' ) {
313 | settings.callback();
314 | }
315 | }
316 |
317 | /* ============================================================================
318 | * Update Position
319 | * -------------------
320 | * Update current, previous and next, based on window position on load.
321 | * ============================================================================ */
322 | function getCurrentPosition() {
323 | if ($(next).length > 0 || $(previous).length > 0) {
324 | if ($(window).scrollTop() >= $('.' + singleSlideClass + ':first').offset().top && $(window).scrollTop() + $(window).outerHeight() !== $(document).outerHeight()) {
325 | if (settings.useSlideNumbers) {
326 | slideIndex(current, true);
327 | }
328 | $('.' + singleSlideClass).each(function() {
329 | offsetTest = $(this).offset().top;
330 | if (offsetTest <= $(window).scrollTop()) {
331 | if ($(this).prev().hasClass(singleSlideClass)) {
332 | previous = $(this).prev();
333 | } else {
334 | previous = $('.' + settings.firstClass);
335 | }
336 | current = $(this);
337 | if (current.next().hasClass(singleSlideClass)) {
338 | next = $(this).next();
339 | } else {
340 | next = $('.' + settings.lastClass);
341 | }
342 | top = false;
343 | }
344 | });
345 | if (settings.useSlideNumbers) {
346 | slideIndex(current, false);
347 | }
348 | $(document).scrollTo(current);
349 | } else {
350 | if (settings.useSlideNumbers) {
351 | if (last !== $('.' + singleSlideClass + ':last-child')[0]) {
352 | slideNumbersFade(false);
353 | } else {
354 | slideNumbersFade(true);
355 | slideIndex(current, false);
356 | }
357 | }
358 | $(document).scrollTo(current);
359 | }
360 | }
361 | }
362 |
363 | /* ============================================================================
364 | * Prevent Default Animations
365 | * -------------------
366 | * Stops default scroll animations when called
367 | * ============================================================================ */
368 | function preventDefault(e) {
369 | if(e !== undefined) {
370 | e = e || window.event;
371 | if (e.preventDefault) {
372 | e.stopPropagation();
373 | e.returnValue = false;
374 | }
375 | }
376 | }
377 |
378 | function stopDefaultAnimate(event) {
379 | return preventDefault(event);
380 | }
381 |
382 | /* ============================================================================
383 | * Move Down
384 | * -------------------
385 | * All the code to move the page down
386 | * ============================================================================ */
387 | $.fn.moveDown = function() {
388 | scrollOffset = scrollY();
389 | if (scrollOffset >= 0 && (scrollOffset <= $(current).scrollTop()) && top === true) {
390 | // Check if top of page
391 | // Update the selectors
392 | previous = current;
393 | current = next;
394 | next = current.next();
395 |
396 | // Set Slide Indexes and Fade Slide Numbers
397 | if (settings.useSlideNumbers) {
398 | if (last === $('.' + singleSlideClass + ':last-child')[0]) {
399 | slideIndex(previous, true);
400 | slideIndex(current, false);
401 | } else {
402 | slideIndex(current, false);
403 | slideNumbersFade(true);
404 | }
405 | }
406 |
407 | // Update top variable
408 | top = false;
409 | $(document).scrollTo(current); // Scroll to selected element
410 | } else if (!bodyScroll && next && $(current).offset().top < scrollOffset + 1) {
411 | // Check if slide
412 | if (next.hasClass(singleSlideClass)) {
413 | // Update the selectors
414 | previous = current;
415 | current = next;
416 | next = $(current).next();
417 | // Set Slide Indexes and Fade Slide Numbers
418 | if (settings.useSlideNumbers) {
419 | slideIndex(previous, true);
420 | slideIndex(current, false);
421 | }
422 | $(document).scrollTo(current); // Scroll to selected element
423 | } else if (last !== $('.' + singleSlideClass + ':last-child')[0]) {
424 | // Update the selectors
425 | previous = $('.' + singleSlideClass + ':last-child')[0];
426 | current = last;
427 | next = null;
428 | if ($(window).scrollTop() + windowHeight + 10 >= $(document).outerHeight() - $(last).outerHeight()) {
429 | // Check for bottom
430 | // Set Slide Indexes and Fade Slide Numbers
431 | if (settings.useSlideNumbers) {
432 | slideIndex(previous, false);
433 | slideNumbersFade(false);
434 | }
435 | }
436 | $(document).scrollTo(current); // Scroll to selected element
437 | $.event.trigger({
438 | type: "lastSlide",
439 | slide: last,
440 | time: new Date()
441 | });
442 | }
443 | }
444 |
445 | // Callback function
446 | if ( typeof settings.callback == 'function' ) {
447 | settings.callback();
448 | }
449 | };
450 |
451 | /* ============================================================================
452 | * Move Up
453 | * -------------------
454 | * All the code to move the page up
455 | * ============================================================================ */
456 | $.fn.moveUp = function() {
457 | scrollOffset = scrollY();
458 | if ($('.' + settings.fullSlideContainer).offset().top + 1 > scrollOffset && previous && scrollOffset > 0) {
459 | // Check if not scrolling to top of page
460 | if ($(current).offset().top >= scrollOffset) {
461 | // Update the selectors
462 | current = $('.' + settings.firstClass);
463 | previous = null;
464 | next = $('.' + singleSlideClass);
465 |
466 | // Update and fade slideNumbers
467 | if (settings.useSlideNumbers) {
468 | slideNumbersFade(false);
469 | slideIndex(next, false);
470 | }
471 | // Update top variable as we are at the top of the page
472 | top = true;
473 | } else {
474 | // Update the selectors
475 | current = previous;
476 | previous = null;
477 | next = $('.' + singleSlideClass);
478 |
479 | // Update and fade slideNumbers
480 | if (settings.useSlideNumbers) {
481 | slideIndex(current, true);
482 | slideIndex(previous, true);
483 | }
484 | }
485 | $(document).scrollTo(current); // Scroll to proper element
486 | } else if (!bodyScroll && $('.' + settings.fullSlideContainer).offset().top < scrollOffset) {
487 | // Update the selectors
488 | current = previous;
489 | previous = $(current).prev();
490 | next = $(current).next();
491 |
492 | // Update and fade slideNumbers
493 | if (settings.useSlideNumbers) {
494 | slideIndex(current, false);
495 | slideIndex(next, true);
496 | slideNumbersFade(true);
497 | }
498 |
499 | // Scroll to proper element
500 | $(document).scrollTo(current);
501 |
502 | // Stop default scrolling
503 | }
504 |
505 | // Update movement variables
506 | up = true;
507 | down = false;
508 |
509 | // Callback function
510 | if ( typeof settings.callback == 'function' ) {
511 | settings.callback();
512 | }
513 |
514 | // Stop default scrolling animations
515 | };
516 |
517 | /* ============================================================================
518 | * Scroll To
519 | * -------------------
520 | * Scroll to element. This is a public function and can be used in an JS file
521 | * ============================================================================ */
522 | $.fn.scrollTo = function(element) {
523 | if (element !== last) {
524 | $("body,html").stop(true, true).animate({
525 | scrollTop: $(element).offset().top
526 | }, {
527 | duration: 375
528 | });
529 | } else {
530 | $("body,html").stop(true, true).animate({
531 | scrollTop: $(document).outerHeight() - windowHeight
532 | }, {
533 | duration: 375
534 | });
535 | }
536 | };
537 |
538 | /* ============================================================================
539 | * ScrollY
540 | * -------------------
541 | * Replacing default scrollY with IE8 Compat
542 | * ============================================================================ */
543 | function scrollY() {
544 | return window.pageYOffset || docElem.scrollTop;
545 | }
546 |
547 | /* ============================================================================
548 | * Featured Scroll
549 | * -------------------
550 | * Scroll based on the idea of having a header, a full screen featured projects
551 | * area, and then a footer after
552 | * ============================================================================ */
553 | function featuredScroll(e) {
554 | bodyScroll = $('body,html').is(':animated') || $('body').is(':animated') || $('html').is(':animated'); // Check if body is currently animated
555 |
556 | if (e.type == 'mousewheel' || e.type == "DOMMouseScroll") { // <-- fix for firefox
557 | clearTimeout($.data(this, 'scrollTimer')); // jshint ignore:line
558 | $(document).unbind({
559 | 'scroll' : featuredScroll
560 | });
561 | $.data(this, 'scrollTimer', setTimeout(function() { // jshint ignore:line
562 | animating = false;
563 | $(document).bind({
564 | 'scroll' : featuredScroll
565 | });
566 | }, 35));
567 |
568 | if (e.originalEvent.detail > 1 && !animating || e.originalEvent.wheelDelta < -1 && !animating) {
569 | // Check if scrolling down
570 | downCount += 1;
571 | $(document).moveDown();
572 | animating = true;
573 | preventDefault();
574 | } else if (e.originalEvent.detail < -1 && !animating || e.originalEvent.wheelDelta > 1 && !animating) {
575 | // Check if not scrolling up
576 | upCount += 1;
577 | $(document).moveUp();
578 | animating = true;
579 | preventDefault();
580 | }
581 | } else if (e.type == 'scroll') {
582 | preventDefault();
583 | animating = false;
584 | clearTimeout($.data(this, 'scrollTimer')); // jshint ignore:line
585 | $.data(this, 'scrollTimer', setTimeout(function() { // jshint ignore:line
586 | getCurrentPosition();
587 | }, 500));
588 | }
589 | return false;
590 | }
591 |
592 | /* ============================================================================
593 | * Header Scroll
594 | * -------------------
595 | * Scroll jacking for full size header image, then re-enables native scrolling
596 | *
597 | * ============================================================================ */
598 | function headerScroll(e) {
599 | scrollOffset = scrollY();
600 | if (e.originalEvent.detail > 0 || e.originalEvent.wheelDelta < 0) {
601 | if ($(next).offset().top > 0 && scrollOffset < $('.' + settings.firstClass).outerHeight()) {
602 | if ($('.' + settings.firstClass).hasClass('active')) {
603 | $('.' + settings.firstClass).toggleClass('active');
604 | $(document).scrollTo(next);
605 | previous = current;
606 | current = next;
607 | return stopDefaultAnimate(e);
608 | } else if (!$('html, body').is(':animated')) {
609 | return true;
610 | }
611 | } else {
612 | return true;
613 | }
614 | } else {
615 | if (!$('.' + settings.firstClass).hasClass('active') && $(window).scrollTop() <= $('.' + settings.firstClass).outerHeight()) {
616 | $('.' + settings.firstClass).toggleClass('active');
617 | $(document).scrollTo(previous);
618 | next = current;
619 | current = previous;
620 | } else if (!$('html, body').is(':animated')) {
621 | return true;
622 | }
623 | }
624 | return false;
625 | }
626 |
627 | /* ============================================================================
628 | * Function Calls and Ordering
629 | * -------------------
630 | * Calling all the functions on document load to make sure nothing breaks
631 | * ============================================================================ */
632 | $(document).ready(function() {
633 | initiateLayout(settings.scrollMode);
634 | if (settings.scrollMode === 'featuredScroll' && !is_mobile()) {
635 | getCurrentPosition();
636 | }
637 | if (settings.scrollMode === 'featuredScroll' && !is_mobile()) {
638 | $('#' + settings.slideNumbersContainer + ' li').on("click", function() {
639 | clickToNavigate($(this).parent().children().index(this));
640 | });
641 |
642 | var map = [];
643 | onkeydown = onkeyup = function(e) {
644 | e = e || event; // to deal with IE
645 | map[e.which] = e.type == 'keyup';
646 | switch (e.which) {
647 | case 40: // arrowDown
648 | e.preventDefault();
649 | $(document).moveDown(e);
650 | break;
651 | case 32: // pageUp
652 | e.preventDefault();
653 | if (map['16'] === true) {
654 | $(document).moveUp(e);
655 | } else {
656 | $(document).moveDown(e);
657 | }
658 | break;
659 | case 33: // pageUp
660 | $(document).moveDown(e);
661 | e.preventDefault();
662 | break;
663 | case 34: // pageUp
664 | e.preventDefault();
665 | $(document).moveUp(e);
666 | break;
667 | case 38: // arrowUp
668 | e.preventDefault();
669 | $(document).moveUp(e);
670 | break;
671 | case 36: // home
672 | e.preventDefault();
673 | if ($('.' + settings.firstClass).length !== 0) {
674 | if (settings.useSlideNumbers) {
675 | slideIndex(current, true);
676 | }
677 | previous = null;
678 | current = '.' + settings.firstClass;
679 | next = $('.' + singleSlideClass + ':first');
680 |
681 | if (settings.useSlideNumbers) {
682 | slideIndex(current, false);
683 | }
684 | $(document).scrollTo('.' + settings.firstClass);
685 | } else {
686 | if (settings.useSlideNumbers) {
687 | slideIndex(current, true);
688 | }
689 | previous = null;
690 | current = $('.pane:first');
691 | next = current.next();
692 | $(document).scrollTo($('.pane')[0]);
693 | if (settings.useSlideNumbers) {
694 | slideIndex(current, false);
695 | }
696 | }
697 | break;
698 | case 35: // end
699 | if ($('.' + settings.firstClass).length !== 0) {
700 | if (settings.useSlideNumbers) {
701 | slideIndex($(current), true);
702 | slideIndex($('.pane:last'), false);
703 | }
704 | previous = $('.pane:last');
705 | } else {
706 | if (settings.useSlideNumbers) {
707 | slideIndex($(current), true);
708 | slideIndex($(last), false);
709 | }
710 | previous = $(last).prev();
711 | }
712 | current = $(last);
713 | next = null;
714 | e.preventDefault();
715 | $(document).scrollTo(last);
716 | }
717 | };
718 | }
719 |
720 | if (!is_mobile()) {
721 | if (settings.scrollMode === 'featuredScroll') {
722 | $(document).bind({
723 | 'DOMMouseScroll mousewheel scroll': featuredScroll
724 | });
725 | } else if (settings.scrollMode === 'headerScroll') {
726 | $(document).bind({
727 | 'DOMMouseScroll mousewheel': headerScroll
728 | });
729 | }
730 | $(window).resize(function() {
731 | $(singleSlide).each(function() {
732 | $(this).css('height', $(window).outerHeight());
733 | $(this).outerHeight($(window).outerHeight());
734 | });
735 | });
736 | }
737 | });
738 | };
739 | })(jQuery);
--------------------------------------------------------------------------------
/assets/jquery.alton.min.js:
--------------------------------------------------------------------------------
1 | !function(e){"use strict";var t={firstClass:"header",fullSlideContainer:"full",singleSlideClass:"slide",nextElement:"div",previousClass:null,lastClass:"footer",slideNumbersContainer:"slide-numbers",bodyContainer:"pageWrapper",scrollMode:"featuredScroll",useSlideNumbers:!1,slideNumbersBorderColor:"#fff",slideNumbersColor:"#000",animationType:"slow",callback:!1};e.fn.alton=function(s){function l(t){if("featuredScroll"===t){for(w=p.length-1;w>=0;w-=1)r()&&e(p[w]).height()>O?e(p[w]).css("height",e(p[w]).height()):(e(p[w]).css("height",O),e(p[w]).outerHeight(O));if(N.useSlideNumbers&&!r()){e("."+N.bodyContainer).append(''),e("#"+N.slideNumbersContainer).css({height:"100%",position:"fixed",top:0,right:"0px",bottom:"0px",width:"86px","z-index":999}),r()&&e("#"+N.slideNumbersContainer).css({height:"auto","min-height":"100%"}),e("."+N.bodyContainer+" #"+N.slideNumbersContainer).append(""),e("."+N.bodyContainer+" #"+N.slideNumbersContainer+" ul").css({transform:"translateY(-50%)","-moz-transform":"translateY(-50%)","-ms-transform":"translateY(-50%)","-o-transform":"translateY(-50%)","-webkit-transform":"translateY(-50%)",top:"50%",position:"fixed"});for(var s=0;E>s;)e("."+N.bodyContainer+" #"+N.slideNumbersContainer+" ul").append(''),o()?e(".paginate").css({cursor:"pointer","border-radius":"50%","list-style":"none",background:N.slideNumbersBorderColor,"border-color":N.slideNumbersBorderColor,"border-width":"2px","border-style":"solid",height:"11px",width:"11px",margin:"5px 0"}):e(".paginate").css({cursor:"pointer","border-radius":"50%","list-style":"none",background:N.slideNumbersBorderColor,"border-color":N.slideNumbersBorderColor,"border-width":"2px","border-style":"solid",height:"10px",width:"10px",margin:"5px 0"}),s+=1;g="getElementsByClassName"in document?document.getElementsByClassName("paginate"):document.querySelectorAll(".paginate")}}else e("."+N.firstClass).css("height",O+10),e("."+N.firstClass).hasClass("active")||(e("."+N.firstClass).toggleClass("active"),o()&&e(".paginate.active").css({"margin-left":"-1px","border-color":"#"+N.slideNumbersBorderColor,"border-style":"solid","border-width":"2px",height:"8px",width:"8px"}))}function o(){var e=window.navigator.userAgent,t=e.indexOf("MSIE ");return t>0||navigator.userAgent.match(/Trident.*rv\:11\./)?!0:!1}function r(){return navigator.userAgent.match(/(iPhone|iPod|iPad|Android|BlackBerry|BB10|Windows Phone|Tizen|Bada)/)}function n(t,s){s&&e(g[e(t).parent().children().index(t)]).hasClass("active")?(e(g[e(t).parent().children().index(t)]).toggleClass("active"),e(g[e(t).parent().children().index(t)]).css("background",N.slideNumbersBorderColor)):e(g[e(t).parent().children().index(t)]).hasClass("active")||(e(g[e(t).parent().children().index(t)]).toggleClass("active"),e(g[e(t).parent().children().index(t)]).css("background",N.slideNumbersColor))}function i(t){N.useSlideNumbers&&(t?e("#"+N.slideNumbersContainer).fadeIn():e("#"+N.slideNumbersContainer).fadeOut())}function a(t){var s=document.getElementsByClassName(y);e(document).scrollTo(e(s[t])),T=s[t],D=e(T).prev().hasClass(y)?e(T).prev():e("."+N.firstClass),k=e(T).next().hasClass(y)?e(T).next():e("."+N.lastClass),n(e("#"+N.slideNumbersContainer+" li.active"),!0),n(s[t],!1),"function"==typeof N.callback&&N.callback()}function d(){(e(k).length>0||e(D).length>0)&&(e(window).scrollTop()>=e("."+y+":first").offset().top&&e(window).scrollTop()+e(window).outerHeight()!==e(document).outerHeight()?(N.useSlideNumbers&&n(T,!0),e("."+y).each(function(){v=e(this).offset().top,v<=e(window).scrollTop()&&(D=e(this).prev().hasClass(y)?e(this).prev():e("."+N.firstClass),T=e(this),k=T.next().hasClass(y)?e(this).next():e("."+N.lastClass),M=!1)}),N.useSlideNumbers&&n(T,!1),e(document).scrollTo(T)):(N.useSlideNumbers&&(B!==e("."+y+":last-child")[0]?i(!1):(i(!0),n(T,!1))),e(document).scrollTo(T)))}function u(e){void 0!==e&&(e=e||window.event,e.preventDefault&&(e.stopPropagation(),e.returnValue=!1))}function c(e){return u(e)}function m(){return window.pageYOffset||P.scrollTop}function f(t){return b=e("body,html").is(":animated")||e("body").is(":animated")||e("html").is(":animated"),"mousewheel"==t.type||"DOMMouseScroll"==t.type?(clearTimeout(e.data(this,"scrollTimer")),e(document).unbind({scroll:f}),e.data(this,"scrollTimer",setTimeout(function(){Y=!1,e(document).bind({scroll:f})},35)),t.originalEvent.detail>1&&!Y||t.originalEvent.wheelDelta<-1&&!Y?(A+=1,e(document).moveDown(),Y=!0,u()):(t.originalEvent.detail<-1&&!Y||t.originalEvent.wheelDelta>1&&!Y)&&(H+=1,e(document).moveUp(),Y=!0,u())):"scroll"==t.type&&(u(),Y=!1,clearTimeout(e.data(this,"scrollTimer")),e.data(this,"scrollTimer",setTimeout(function(){d()},500))),!1}function h(t){if(C=m(),t.originalEvent.detail>0||t.originalEvent.wheelDelta<0){if(!(e(k).offset().top>0&&C=0&&C<=e(T).scrollTop()&&M===!0?(D=T,T=k,k=T.next(),N.useSlideNumbers&&(B===e("."+y+":last-child")[0]?(n(D,!0),n(T,!1)):(n(T,!1),i(!0))),M=!1,e(document).scrollTo(T)):!b&&k&&e(T).offset().top=e(document).outerHeight()-e(B).outerHeight()&&N.useSlideNumbers&&(n(D,!1),i(!1)),e(document).scrollTo(T),e.event.trigger({type:"lastSlide",slide:B,time:new Date}))),"function"==typeof N.callback&&N.callback()},e.fn.moveUp=function(){C=m(),e("."+N.fullSlideContainer).offset().top+1>C&&D&&C>0?(e(T).offset().top>=C?(T=e("."+N.firstClass),D=null,k=e("."+y),N.useSlideNumbers&&(i(!1),n(k,!1)),M=!0):(T=D,D=null,k=e("."+y),N.useSlideNumbers&&(n(T,!0),n(D,!0))),e(document).scrollTo(T)):!b&&e("."+N.fullSlideContainer).offset().top"
17 | ],
18 | "license": "GPL-3.0",
19 | "ignore": [
20 | "package.json"
21 | ],
22 | "private": false
23 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "alton",
3 | "version": "1.2.1",
4 | "description": "Alton is a jQuery-powered scrolling plugin, with a twist.",
5 | "main": "jquery.alton.min.js",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/paper-leaf/alton.git"
9 | },
10 | "keywords": [
11 | "jQuery",
12 | "scroll",
13 | "twist"
14 | ],
15 | "author": "Paper Leaf Design",
16 | "license": "GPL-3.0",
17 | "bugs": {
18 | "url": "https://github.com/paper-leaf/alton/issues"
19 | },
20 | "homepage": "https://github.com/paper-leaf/alton#readme"
21 |
22 | }
23 |
--------------------------------------------------------------------------------