forked from desandro/sticky-titles
-
Notifications
You must be signed in to change notification settings - Fork 0
/
sticky-titles.js
122 lines (101 loc) · 2.81 KB
/
sticky-titles.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*!
* StickTitles
* iOS-like titles that sticky, but scroll
* http://github.com/desandro/sticky-titles
**/
( function( window ) {
'use strict';
var StickyTitle = window.StickyTitles.Title;
// turn element or nodeList into an array
function makeArray( obj ) {
var ary = [];
if ( typeof obj.length === 'number' ) {
// convert nodeList to array
for ( var i=0, len = obj.length; i < len; i++ ) {
ary.push( obj[i] );
}
} else {
// array of single index
ary.push( obj );
}
return ary;
}
// -------------------------- StickyTitles -------------------------- //
// class for titles collection
function StickyTitles( elems ) {
this.titles = [];
this.add( elems );
this._create();
}
StickyTitles.prototype.handleEvent = function( event ) {
var method = 'on' + event.type;
if ( this[ method ] ) {
this[ method ]( event );
}
};
StickyTitles.prototype._create = function() {
this.measure();
window.addEventListener( 'scroll', this, false );
};
StickyTitles.prototype.add = function( elems ) {
if ( !elems ) {
return;
}
elems = makeArray( elems );
var titles = [];
for ( var i=0, len = elems.length; i < len; i++ ) {
var elem = elems[i];
var title = new StickyTitle( elem );
titles.push( title );
}
this.titles.push.apply( this.titles, titles );
};
StickyTitles.prototype.measure = function() {
for ( var i=0, len = this.titles.length; i < len; i++ ) {
var title = this.titles[i];
title.measure();
}
};
StickyTitles.prototype.stickTitle = function( title ) {
// don't stick if the same
if ( title === this.stuckTitle ) {
return;
}
this.unstickTitle();
title.stick();
this.stuckTitle = title;
};
StickyTitles.prototype.unstickTitle = function() {
if ( !this.stuckTitle ) {
return;
}
this.stuckTitle.unstick();
delete this.stuckTitle;
};
// -------------------------- events -------------------------- //
StickyTitles.prototype.onscroll = function() {
// console.log( window.scrollY );
var scrollY = window.scrollY;
var firstTitle = this.titles[0];
var isFirstTitleStuck = firstTitle && this.stuckTitle === firstTitle;
if ( isFirstTitleStuck && scrollY < firstTitle.top ) {
this.unstickTitle( firstTitle );
return;
}
for ( var i=0, len = this.titles.length; i < len; i++ ) {
var title = this.titles[i];
// var previousTitle = i && this.titles[ i - 1 ];
var nextTitle = i < len - 1 && this.titles[ i + 1 ];
if ( scrollY >= title.top && scrollY <= nextTitle.top ) {
this.stickTitle( title );
title.offset( nextTitle );
// var gap = nextTitle.top - scrollY;
// title.offset( nextTitle.top - scrollY );
break;
}
}
};
// -------------------------- transport -------------------------- //
window.StickyTitles = StickyTitles;
StickyTitles.Title = StickyTitle;
})( window );