@@ -225,6 +225,94 @@ jQuery(document).ready(function() {
225225 $ ( '.progress' ) . hover ( function ( ) {
226226 $ ( '.progress' ) . stop ( true , false , true ) . fadeToggle ( 100 ) ;
227227 } ) ;
228+
229+ /**
230+ * Fix anchor scrolling that hides behind top nav bar
231+ * Courtesy of https://stackoverflow.com/a/13067009/28106
232+ *
233+ * We could use pure css for this if only heading anchors were
234+ * involved, but this works for any anchor, including footnotes
235+ **/
236+ ( function ( document , history , location ) {
237+ var HISTORY_SUPPORT = ! ! ( history && history . pushState ) ;
238+
239+ var anchorScrolls = {
240+ ANCHOR_REGEX : / ^ # [ ^ ] + $ / ,
241+ OFFSET_HEIGHT_PX : 50 ,
242+
243+ /**
244+ * Establish events, and fix initial scroll position if a hash is provided.
245+ */
246+ init : function ( ) {
247+ this . scrollToCurrent ( ) ;
248+ window . addEventListener ( 'hashchange' , this . scrollToCurrent . bind ( this ) ) ;
249+ document . body . addEventListener ( 'click' , this . delegateAnchors . bind ( this ) ) ;
250+ } ,
251+
252+ /**
253+ * Return the offset amount to deduct from the normal scroll position.
254+ * Modify as appropriate to allow for dynamic calculations
255+ */
256+ getFixedOffset : function ( ) {
257+ return this . OFFSET_HEIGHT_PX ;
258+ } ,
259+
260+ /**
261+ * If the provided href is an anchor which resolves to an element on the
262+ * page, scroll to it.
263+ * @param {String } href
264+ * @return {Boolean } - Was the href an anchor.
265+ */
266+ scrollIfAnchor : function ( href , pushToHistory ) {
267+ var match , rect , anchorOffset ;
268+
269+ if ( ! this . ANCHOR_REGEX . test ( href ) ) {
270+ return false ;
271+ }
272+
273+ match = document . getElementById ( href . slice ( 1 ) ) ;
274+
275+ if ( match ) {
276+ rect = match . getBoundingClientRect ( ) ;
277+ anchorOffset = window . pageYOffset + rect . top - this . getFixedOffset ( ) ;
278+ window . scrollTo ( window . pageXOffset , anchorOffset ) ;
279+
280+ // Add the state to history as-per normal anchor links
281+ if ( HISTORY_SUPPORT && pushToHistory ) {
282+ history . pushState ( { } , document . title , location . pathname + href ) ;
283+ }
284+ }
285+
286+ return ! ! match ;
287+ } ,
288+
289+ /**
290+ * Attempt to scroll to the current location's hash.
291+ */
292+ scrollToCurrent : function ( ) {
293+ this . scrollIfAnchor ( window . location . hash ) ;
294+ } ,
295+
296+ /**
297+ * If the click event's target was an anchor, fix the scroll position.
298+ */
299+ delegateAnchors : function ( e ) {
300+ var elem = e . target ;
301+
302+ if (
303+ elem . nodeName === 'A' &&
304+ this . scrollIfAnchor ( elem . getAttribute ( 'href' ) , true )
305+ ) {
306+ e . preventDefault ( ) ;
307+ }
308+ }
309+ } ;
310+
311+ window . addEventListener (
312+ 'DOMContentLoaded' , anchorScrolls . init . bind ( anchorScrolls )
313+ ) ;
314+ } ) ( window . document , window . history , window . location ) ;
315+
228316} ) ;
229317
230318jQuery ( window ) . on ( 'load' , function ( ) {
0 commit comments