ratchet_design 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +21 -0
  3. data/README.md +41 -0
  4. data/app/assets/images/ratchet/favicon.ico +0 -0
  5. data/app/assets/javascripts/ratchet/_svg.js +55 -0
  6. data/app/assets/javascripts/ratchet/base/form.js +220 -0
  7. data/app/assets/javascripts/ratchet/base/mobilemenu.js +62 -0
  8. data/app/assets/javascripts/ratchet/base/validation.js +230 -0
  9. data/app/assets/javascripts/ratchet/core.js +92 -0
  10. data/app/assets/javascripts/ratchet/enhancement/_collapse.js +96 -0
  11. data/app/assets/javascripts/ratchet/enhancement/_lightbox.js +93 -0
  12. data/app/assets/javascripts/ratchet/enhancement/_swap.js +120 -0
  13. data/app/assets/javascripts/ratchet/enhancement/_switcheroo.js +28 -0
  14. data/app/assets/javascripts/ratchet/enhancement/_textcounter.js +92 -0
  15. data/app/assets/javascripts/ratchet/enhancement/loader.js +77 -0
  16. data/app/assets/javascripts/ratchet/enhancement/notice.js +70 -0
  17. data/app/assets/javascripts/ratchet/enhancement/sticky.js +128 -0
  18. data/app/assets/javascripts/ratchet/enhancement/waypoints.js +328 -0
  19. data/app/assets/javascripts/ratchet/shim/classlist.js +234 -0
  20. data/app/assets/javascripts/ratchet/shim/object.assign.js +30 -0
  21. data/app/assets/javascripts/ratchet/utility/compile_data.js +32 -0
  22. data/app/assets/javascripts/ratchet/utility/from_top.js +14 -0
  23. data/app/assets/javascripts/ratchet/utility/full_stop.js +55 -0
  24. data/app/assets/javascripts/ratchet/utility/get_closest.js +20 -0
  25. data/app/assets/javascripts/ratchet/utility/get_next.js +17 -0
  26. data/app/assets/javascripts/ratchet/utility/load_font.js +72 -0
  27. data/app/assets/javascripts/ratchet/utility/load_script.js +34 -0
  28. data/app/assets/javascripts/ratchet/utility/matches.js +15 -0
  29. data/app/assets/javascripts/ratchet/utility/scroll_to.js +74 -0
  30. data/app/assets/javascripts/ratchet/utility/throttle.js +25 -0
  31. data/app/assets/javascripts/ratchet/utility/timeout.js +45 -0
  32. data/app/assets/javascripts/ratchet/utility/unhover.js +56 -0
  33. data/app/assets/javascripts/ratchet/utility/word_count.js +15 -0
  34. data/app/assets/stylesheets/ratchet/_core.scss +20 -0
  35. data/app/assets/stylesheets/ratchet/base/_button.scss +101 -0
  36. data/app/assets/stylesheets/ratchet/base/_document.scss +306 -0
  37. data/app/assets/stylesheets/ratchet/base/_form.scss +614 -0
  38. data/app/assets/stylesheets/ratchet/base/_list.scss +114 -0
  39. data/app/assets/stylesheets/ratchet/base/_media.scss +41 -0
  40. data/app/assets/stylesheets/ratchet/base/_table.scss +81 -0
  41. data/app/assets/stylesheets/ratchet/base/_text.scss +411 -0
  42. data/app/assets/stylesheets/ratchet/enhancement/_contrast-section.scss +22 -0
  43. data/app/assets/stylesheets/ratchet/enhancement/_feature.scss +49 -0
  44. data/app/assets/stylesheets/ratchet/enhancement/_hero.scss +44 -0
  45. data/app/assets/stylesheets/ratchet/enhancement/_loader.scss +109 -0
  46. data/app/assets/stylesheets/ratchet/enhancement/_notice.scss +74 -0
  47. data/app/assets/stylesheets/ratchet/enhancement/_signup.scss +206 -0
  48. data/app/assets/stylesheets/ratchet/enhancement/_sticky-sidebar.scss +36 -0
  49. data/app/assets/stylesheets/ratchet/fonts-woff.css +55 -0
  50. data/app/assets/stylesheets/ratchet/fonts-woff2.css +55 -0
  51. data/app/assets/stylesheets/ratchet/utility/_global.scss +255 -0
  52. data/app/assets/stylesheets/ratchet/utility/_grid.scss +102 -0
  53. data/app/assets/svgs/ratchet/facebook.svg +1 -0
  54. data/app/assets/svgs/ratchet/github.svg +1 -0
  55. data/app/assets/svgs/ratchet/google-plus.svg +1 -0
  56. data/app/assets/svgs/ratchet/ibm.svg +1 -0
  57. data/app/assets/svgs/ratchet/inbox.svg +1 -0
  58. data/app/assets/svgs/ratchet/linkedin.svg +1 -0
  59. data/app/assets/svgs/ratchet/ratchet.svg +1 -0
  60. data/app/assets/svgs/ratchet/search.svg +1 -0
  61. data/app/assets/svgs/ratchet/subscribe.svg +1 -0
  62. data/app/assets/svgs/ratchet/twitter.svg +1 -0
  63. data/app/assets/svgs/ratchet/y-combinator.svg +1 -0
  64. data/app/helpers/ratchet/application_helper.rb +51 -0
  65. data/app/views/layouts/ratchet/default.html.slim +61 -0
  66. data/app/views/shared/ratchet/_footer.html.slim +2 -0
  67. data/app/views/shared/ratchet/_header.html.slim +17 -0
  68. data/app/views/shared/ratchet/_icons.html.slim +89 -0
  69. data/lib/ratchet_design.rb +12 -0
  70. data/lib/ratchet_design/version.rb +3 -0
  71. data/public/assets/ratchet/core-0.1.0.js +103 -0
  72. data/public/assets/ratchet/core-0.1.0.js.gz +0 -0
  73. data/public/assets/ratchet/core-0.1.0.map.json +1 -0
  74. data/public/assets/ratchet/fonts-woff-0.1.0.css +55 -0
  75. data/public/assets/ratchet/fonts-woff-0.1.0.css.gz +0 -0
  76. data/public/assets/ratchet/fonts-woff2-0.1.0.css +55 -0
  77. data/public/assets/ratchet/fonts-woff2-0.1.0.css.gz +0 -0
  78. metadata +177 -0
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Loader 0.0.1
3
+ * Compose loader module
4
+ * @author Kyle Foster (@hkfoster)
5
+ * @license MIT
6
+ **/
7
+
8
+ // Public API function
9
+ var loader = function( settings ) {
10
+
11
+ // Overridable defaults
12
+ var defaults = {
13
+ selector : document.body,
14
+ loaderClass : 'loader',
15
+ loadingMessage : 'Hang tight…',
16
+ loadingClass : 'loading',
17
+ successMessage : 'Got it!',
18
+ successClass : 'success',
19
+ failureMessage : 'Hold up!',
20
+ failureClass : 'failure'
21
+ };
22
+
23
+ // Extend defaults
24
+ var options = Object.assign( {}, defaults, settings );
25
+
26
+ // Create and prepend loader element
27
+ options.selector.insertAdjacentHTML( 'afterbegin', '<div class="' + options.loaderClass + '"></div>' );
28
+
29
+ // Cache loader element
30
+ var element = document.querySelector( 'div.' + options.loaderClass );
31
+
32
+ // Show loader icon function
33
+ var show = function( state ) {
34
+
35
+ // Loader pending state
36
+ if ( state === 'pending' ) {
37
+
38
+ element.textContent = options.loadingMessage;
39
+ element.classList.remove( options.successClass, options.failureClass );
40
+ element.classList.add( options.loadingClass );
41
+
42
+ // Loader failure state
43
+ } else if ( state === 'failure' ) {
44
+
45
+ element.textContent = options.failureMessage;
46
+ element.classList.remove( options.loadingClass );
47
+ element.classList.add( options.failureClass );
48
+
49
+ // Loader success state
50
+ } else if ( state === 'success' ) {
51
+
52
+ element.textContent = options.successMessage;
53
+ element.classList.remove( options.loadingClass );
54
+ element.classList.add( options.successClass );
55
+
56
+ }
57
+
58
+ };
59
+
60
+ // Hide loader icon function
61
+ var hide = function() {
62
+
63
+ // Remove state classes altogether
64
+ element.classList.remove( options.loadingClass, options.successClass, options.failureClass );
65
+
66
+ };
67
+
68
+ // Public functions
69
+ return {
70
+ show : show,
71
+ hide : hide
72
+ };
73
+
74
+ };
75
+
76
+ // Public API
77
+ module.exports = loader;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Notice 0.0.1
3
+ * Compose notice module
4
+ * @author Kyle Foster (@hkfoster)
5
+ * @license MIT
6
+ **/
7
+
8
+ // Public API function
9
+ var notice = function( element, settings ) {
10
+
11
+ // Overridable defaults
12
+ var defaults = {
13
+ noticeName : 'notice',
14
+ noticeClass : 'notice',
15
+ noticeMessage : '[your notice message here]'
16
+ };
17
+
18
+ // Scoped variables
19
+ var options = Object.assign( {}, defaults, settings ),
20
+ selector = document.querySelector( element ),
21
+ cookieName = 'dismiss-' + options.noticeName;
22
+
23
+ // Only run if selector exists & no dismiss cookie is found
24
+ if ( !selector || getCookie( cookieName ) ) return false;
25
+
26
+ // Uncomment for development
27
+ // deleteCookie( cookieName );
28
+
29
+ // Create and append notice
30
+ var html = '<aside class="' + options.noticeClass + '">' + options.noticeMessage + '<a href="#?" class="close-btn"></a></aside>'
31
+ document.querySelector( 'main' ).insertAdjacentHTML( 'afterbegin', html );
32
+
33
+ // Listen for close button click
34
+ selector.querySelector( '.' + options.noticeClass + ' > .close-btn' ).addEventListener( 'click', dismissNotice, false );
35
+
36
+ // Dismiss notice on close
37
+ function dismissNotice( event ) {
38
+
39
+ // Prevent default behavior
40
+ event.preventDefault();
41
+
42
+ // Cache notice element
43
+ var noticeElem = selector.querySelector( '.' + options.noticeClass );
44
+
45
+ // Remove notice from page
46
+ selector.removeChild( noticeElem );
47
+
48
+ // Set cookie to prevent it from returning
49
+ document.cookie = cookieName + '=true; expires=Fri, 31 Dec 9999 23:59:59 GMT; path=/';
50
+
51
+ }
52
+
53
+ // Check for cookie by name
54
+ function getCookie( name ) {
55
+ var value = '; ' + document.cookie;
56
+ var parts = value.split( '; ' + name + '=' );
57
+ if ( parts.length == 2 ) return parts.pop().split( ';' ).shift();
58
+ }
59
+
60
+ // Delete a cookie by setting the date of expiry to yesterday
61
+ function deleteCookie( name ) {
62
+ var date = new Date();
63
+ date.setDate( date.getDate() -1 );
64
+ document.cookie = escape( name ) + '=;expires=' + date;
65
+ }
66
+
67
+ };
68
+
69
+ // Public API
70
+ module.exports = notice;
@@ -0,0 +1,128 @@
1
+ /**
2
+ * Sticky 0.0.3
3
+ * Compose sticky elements module
4
+ * @author Kyle Foster (@hkfoster)
5
+ * @license MIT
6
+ **/
7
+
8
+ // Dependencies
9
+ var throttle = require( '../utility/throttle' ),
10
+ fromTop = require( '../utility/from_top' );
11
+
12
+ // Public API function
13
+ var sticky = function( element, settings ) {
14
+
15
+ // Overridable defaults
16
+ var defaults = {
17
+ topPadding : false,
18
+ initWidth : '700px',
19
+ stickyClass : 'sticky',
20
+ anchorPoint : null
21
+ };
22
+
23
+ // Scoped variables
24
+ var options = Object.assign( {}, defaults, settings ),
25
+ selector = document.querySelector( element );
26
+
27
+ // If selector is not present
28
+ if ( !selector ) {
29
+
30
+ // Abort
31
+ return false;
32
+
33
+ // Otherwise attach listeners
34
+ } else {
35
+
36
+ // Scoped variables
37
+ var topPadding = ( options.topPadding === true ) ? parseInt( window.getComputedStyle( selector, null ).getPropertyValue( 'padding-top' ) ) : 0,
38
+ widthQuery = window.matchMedia( '(min-width: ' + options.initWidth + ')' ),
39
+ topOffset = fromTop( selector ) + topPadding,
40
+ elemHeight = selector.offsetHeight,
41
+ anchorInit = options.anchorPoint,
42
+ docBody = document.body,
43
+ docHeight,
44
+ winHeight;
45
+
46
+ // Resize throttle function init
47
+ throttle( 'resize', 'optimizedResize' );
48
+
49
+ // Scroll throttle function init
50
+ throttle( 'scroll', 'optimizedScroll' );
51
+
52
+ // Call listener function explicitly at run time
53
+ queryHandler( widthQuery );
54
+
55
+ // Attach listener function to listen in on state changes
56
+ widthQuery.addListener( queryHandler );
57
+
58
+ }
59
+
60
+ // Media query handler function
61
+ function queryHandler( condition ) {
62
+
63
+ // If media query matches
64
+ if ( condition.matches ) {
65
+
66
+ // Call resize listener function explicitly at run time
67
+ resizeHandler();
68
+
69
+ // Resize function listener
70
+ window.addEventListener( 'optimizedResize', resizeHandler, false );
71
+
72
+ // Call scroll listener function explicitly at run time
73
+ scrollHandler();
74
+
75
+ // Scroll function listener
76
+ window.addEventListener( 'optimizedScroll', scrollHandler, false );
77
+
78
+ } else {
79
+
80
+ // Reset styles
81
+ docBody.classList.remove( 'sticky' );
82
+
83
+ // Remove resize listener
84
+ window.removeEventListener( 'optimizedResize', resizeHandler, false );
85
+
86
+ // Remove scroll listener
87
+ window.removeEventListener( 'optimizedScroll', scrollHandler, false );
88
+
89
+ }
90
+
91
+ }
92
+
93
+ // Resize handler function
94
+ function resizeHandler() {
95
+
96
+ // Update document height variable
97
+ docHeight = document.body.scrollHeight;
98
+
99
+ // Update window height variable
100
+ winHeight = window.innerHeight;
101
+
102
+ }
103
+
104
+ // Scroll handler function
105
+ function scrollHandler() {
106
+
107
+ // Scoped variables
108
+ var newScrollY = window.pageYOffset,
109
+ pastOffset = newScrollY > topOffset,
110
+ anchored = ( anchorInit ) ? newScrollY >= docHeight - elemHeight - anchorInit + topPadding : null;
111
+
112
+ // Where the magic happens
113
+ if ( pastOffset && !anchored ) {
114
+ docBody.classList.remove( 'anchored' );
115
+ docBody.classList.add( 'sticky' );
116
+ } else if ( pastOffset && anchored ) {
117
+ docBody.classList.remove( 'sticky' );
118
+ docBody.classList.add( 'anchored' );
119
+ } else {
120
+ docBody.classList.remove( 'sticky' );
121
+ }
122
+
123
+ }
124
+
125
+ };
126
+
127
+ // Public API
128
+ module.exports = sticky;
@@ -0,0 +1,328 @@
1
+ /**
2
+ * Waypoints 0.0.4
3
+ * Compose waypoint navigation module
4
+ * @author Kyle Foster (@hkfoster)
5
+ * @license MIT
6
+ **/
7
+
8
+ // Dependencies
9
+ var matches = require( '../utility/matches' ),
10
+ fromTop = require( '../utility/from_top' ),
11
+ scrollTo = require( '../utility/scroll_to' ),
12
+ getClosest = require( '../utility/get_closest' ),
13
+ throttle = require( '../utility/throttle' );
14
+
15
+ // Public API function
16
+ var waypoints = function( elements, settings ) {
17
+
18
+ // Overridable defaults
19
+ var defaults = {
20
+ initWidth : '700px',
21
+ navigation : '.secondary',
22
+ activeAnchor : 'active',
23
+ elemOffset : 0,
24
+ showLandmarks : false,
25
+ landmarkSelector : '.landmark',
26
+ activeLandmark : 'pinned',
27
+ };
28
+
29
+ // Scoped variables
30
+ var options = Object.assign( {}, defaults, settings ),
31
+ selectors = document.querySelectorAll( elements );
32
+
33
+ // If selectors are not present
34
+ if ( !selectors.length ) {
35
+
36
+ // Abort
37
+ return false;
38
+
39
+ // Otherwise attach listeners
40
+ } else {
41
+
42
+ // Scoped variables
43
+ var navigation = document.querySelector( options.navigation ),
44
+ widthQuery = window.matchMedia( '(min-width: ' + options.initWidth + ')' ),
45
+ coordinates = [],
46
+ oldActiveItem,
47
+ windowHash,
48
+ docHeight,
49
+ winHeight;
50
+
51
+ // If hash is present
52
+ if ( window.location.hash ) {
53
+
54
+ // Cache it
55
+ windowHash = window.location.hash.replace( '#', '' );
56
+
57
+ // Then delete it to prevent default page scroll
58
+ window.location.hash = '';
59
+
60
+ // And replace it
61
+ history.replaceState( null, '', '#' + windowHash );
62
+
63
+ }
64
+
65
+ // Resize throttle function init
66
+ throttle( 'resize', 'optimizedResize' );
67
+
68
+ // Scroll throttle function init
69
+ throttle( 'scroll', 'optimizedScroll' );
70
+
71
+ // Only run once the window is loaded
72
+ window.addEventListener( 'load', function() {
73
+
74
+ // Call listener function explicitly at run time
75
+ queryHandler( widthQuery );
76
+
77
+ // Attach listener function to listen in on state changes
78
+ widthQuery.addListener( queryHandler );
79
+
80
+ }, false );
81
+
82
+ }
83
+
84
+ // Media query handler function
85
+ function queryHandler( condition ) {
86
+
87
+ // If media query matches
88
+ if ( condition.matches ) {
89
+
90
+ // Call resize listener function explicitly at run time
91
+ resizeHandler();
92
+
93
+ // Resize throttle function init
94
+ window.addEventListener( 'optimizedResize', resizeHandler, false );
95
+
96
+ // Call scroll listener function explicitly at run time
97
+ scrollHandler();
98
+
99
+ // Scroll function listener
100
+ window.addEventListener( 'optimizedScroll', scrollHandler, false );
101
+
102
+ // Click function listener
103
+ navigation.addEventListener( 'click', clickHandler, false );
104
+
105
+ // Call hash change listener function explicitly at run time
106
+ hashHandler();
107
+
108
+ // Hash change function listener
109
+ window.addEventListener( 'hashchange', hashHandler, false );
110
+
111
+ // Otherwise…
112
+ } else {
113
+
114
+ // Remove resize listener
115
+ window.removeEventListener( 'optimizedResize', resizeHandler, false );
116
+
117
+ // Remove scroll listener
118
+ window.removeEventListener( 'optimizedScroll', scrollHandler, false );
119
+
120
+ // Remove click listener
121
+ navigation.removeEventListener( 'click', clickHandler, false );
122
+
123
+ // Remove hash change listener
124
+ window.removeEventListener( 'hashchange', hashHandler, false );
125
+
126
+ }
127
+
128
+ }
129
+
130
+ // Resize handler function
131
+ function resizeHandler() {
132
+
133
+ // Update document height variable
134
+ docHeight = document.body.scrollHeight;
135
+
136
+ // Update window height variable
137
+ winHeight = window.innerHeight;
138
+
139
+ // Loop through waypoints
140
+ for ( var i = 0; i < selectors.length; i++ ) {
141
+
142
+ // Construct coordinate object
143
+ var coordinate = {
144
+ elem : selectors[ i ],
145
+ offset : fromTop( selectors[ i ] )
146
+ };
147
+
148
+ // And update coordinates array
149
+ coordinates[ i ] = coordinate;
150
+
151
+ }
152
+
153
+ }
154
+
155
+ // Scroll handler function
156
+ function scrollHandler() {
157
+
158
+ // Scoped variables
159
+ var newScrollY = window.pageYOffset,
160
+ rockBottom = newScrollY < 0 || newScrollY + winHeight >= docHeight,
161
+ newActiveItem,
162
+ activeLink,
163
+ landmark;
164
+
165
+ // Loop through coordinates
166
+ for ( var i = 0; i < coordinates.length; i++ ) {
167
+
168
+ // Scoped variables
169
+ var firstWaypoint = coordinates[ 0 ],
170
+ currWaypoint = coordinates[ i ],
171
+ nextWaypoint = coordinates[ i + 1 ],
172
+ lastWaypoint = coordinates[ coordinates.length - 1 ];
173
+
174
+ // If scrolled to last waypoint
175
+ if ( newScrollY < firstWaypoint.offset ) {
176
+
177
+ // Set active item to first waypoint
178
+ newActiveItem = firstWaypoint.elem.id;
179
+
180
+ // If scrolled to bottom of page or on past the last waypoint
181
+ } else if ( rockBottom || newScrollY > lastWaypoint.offset - options.elemOffset ) {
182
+
183
+ // Set active item to last waypoint
184
+ newActiveItem = lastWaypoint.elem.id;
185
+
186
+ // Otherwise if a waypoint is in the viewport
187
+ } else if ( newScrollY > currWaypoint.offset - options.elemOffset && newScrollY < nextWaypoint.offset - options.elemOffset ) {
188
+
189
+ // Update active item to match
190
+ newActiveItem = currWaypoint.elem.id;
191
+
192
+ }
193
+
194
+ }
195
+
196
+ // If active item exists
197
+ if ( newActiveItem ) {
198
+
199
+ // Only run when new active item is triggered
200
+ if ( newActiveItem === oldActiveItem ) return false;
201
+
202
+ // Update active link
203
+ activeLink = navigation.querySelector( 'a[href="#' + newActiveItem + '"]' );
204
+
205
+ // If no active link is found, abort
206
+ if ( !activeLink ) return false;
207
+
208
+ // And enable navigation item
209
+ activate( navigation, activeLink, options.activeAnchor );
210
+
211
+ // If landmarks are turned on
212
+ if ( options.showLandmarks === true ) {
213
+
214
+ // Set active landmark to active link’s parent
215
+ landmark = getClosest( activeLink, options.landmarkSelector );
216
+
217
+ // Enable active landmark
218
+ activate( navigation, landmark, options.activeLandmark );
219
+
220
+ }
221
+
222
+ // Update old active item variable
223
+ oldActiveItem = newActiveItem;
224
+
225
+ }
226
+
227
+ }
228
+
229
+ // Click handler function
230
+ function clickHandler( event ) {
231
+
232
+ // Prevent default behavior
233
+ event.preventDefault();
234
+
235
+ // Matches selector function init
236
+ if ( matches( event.target, 'a[href^="#"]' ) ) {
237
+
238
+ // Travel to clicked target
239
+ travel( event.target, 'click' );
240
+
241
+ }
242
+ }
243
+
244
+ // Hash change handler function
245
+ function hashHandler() {
246
+
247
+ // Only run when a hash is present
248
+ if ( !window.location.hash ) return false;
249
+
250
+ // Find the hash’s relevant navigation item
251
+ var hashAnchor = document.querySelector( 'a[href="' + window.location.hash + '"]' );
252
+
253
+ // And travel to its target
254
+ travel( hashAnchor, 'hash' );
255
+
256
+ }
257
+
258
+ // Window scroll travel function
259
+ function travel( destination, trigger ) {
260
+
261
+ // Define scoped variable(s)
262
+ var targetAnchor = destination.href.split( '#' )[ 1 ],
263
+ targetElement = document.querySelector( '#' + targetAnchor ),
264
+ targetOffset,
265
+ travelTime;
266
+
267
+ // If a target element exists
268
+ if ( targetElement ) {
269
+
270
+ // Enable new active navigation item
271
+ activate( navigation, destination, options.activeAnchor );
272
+
273
+ // Loop through coordinates
274
+ for ( var i = 0; i < coordinates.length; i++ ) {
275
+
276
+ // If coordinate element matches target element
277
+ if ( coordinates[ i ].elem === targetElement ) {
278
+
279
+ // Assign its coordinates to target offset variable
280
+ targetOffset = coordinates[ i ].offset;
281
+ }
282
+ }
283
+
284
+ // If trigger was a click
285
+ if ( trigger === 'click' ) {
286
+
287
+ // Temporarily remove scroll listener function
288
+ window.removeEventListener( 'optimizedScroll', scrollHandler, false );
289
+
290
+ // Update the hash
291
+ history.pushState( null, '', '#' + targetAnchor );
292
+
293
+ // Animate scroll to appropriate element
294
+ scrollTo( targetOffset - options.elemOffset + 1, function() {
295
+
296
+ // Once scroll is complete, enable scroll listener
297
+ window.addEventListener( 'optimizedScroll', scrollHandler, false );
298
+
299
+ });
300
+
301
+ // Otherwise if trigger was a hash
302
+ } else if ( trigger === 'hash' ) {
303
+
304
+ // Skip the scroll animation
305
+ window.scrollTo( 0, targetOffset - options.elemOffset + 1 );
306
+
307
+ }
308
+ }
309
+ }
310
+
311
+ // Link activation function
312
+ function activate( container, selector, cls ) {
313
+
314
+ // Find currently active link
315
+ var activeLink = container.querySelector( '.' + cls );
316
+
317
+ // And if it exists, disable it
318
+ if ( activeLink ) activeLink.classList.remove( cls );
319
+
320
+ // Then enable the passed selector
321
+ selector.classList.add( cls );
322
+
323
+ }
324
+
325
+ };
326
+
327
+ // Public API
328
+ module.exports = waypoints;