src/assets/js/main.js (1,026 lines of code) (raw):

/*! * Glance Digital Custom JavaScript Programing * lance@glance.ca * * */ window.is_touch_device = 'ontouchstart' in document.documentElement; jQuery(document).ready(function ($) { // SETTINGS // ------------------ // Velocty Easing // ------ $.Velocity.defaults.easing = 'easeInOutQuart'; // Device // ------ if (is_touch_device) { $('body').addClass('touch-device'); } $('body').on('mousedown', function () { $('body').addClass('using-mouse'); }); $('body').on('keydown', function () { $('body').removeClass('using-mouse'); }); // PLUGINS // ------------------ // 1. Site Nav if ($('.full-width .site-header, .sidebar .site-header').length) { $('.site-header').switchNav(); } $('.has-children').each(function () { if ($(this).find('.is-active').length) { $(this).addClass('has-active-children'); } }); if ($('.sidenav').length) { $('.sidenav').sideNav(); } if ($('#sidenav-status-pagename').length) { $('#sidenav-status-pagename').sideNavStatus(); } if ($('.sidenav-top .primary > .has-subfolder.has-active-children').length) { $( '.sidenav-top .primary > .has-subfolder.has-active-children' ).sideNavTop(); } // Secondary Dropdown should not be tabbed through since it repeats functionality above: if ($('.sidenav-top a').length) { $('.sidenav-top a').each(function () { $(this).attr('tabindex', '-1'); }); } if ($('.sidenav-detail').length) { $('.sidenav-detail').sideNavDetail(); } // 2. Anchor Link Scroll // ------ $('a[href^="#"]').scrollto({ offset_lg: 38, offset_sm: 38 }); // 3. Show in View // ------ if ($('.showOnView').length) { $('.showOnView').showOnView(); } // 4. Banner Image Parallax // ------ // ****** ****** // ** the plugin code is found in parallax.js ** // ***** ****** if (!is_touch_device) { console.debug('Parallax effects enabled'); if ($('.parallax').length) { $('.parallax').parallax({ offsetIntertia: -0.15 }); } if ($('.parallaxFG').length) { $('.parallaxFG').parallaxFG({ offsetIntertia: 0.15 }); } if ($('.parallaxFG-right').length) { $('.parallaxFG-right').parallaxFG({ offsetIntertia: 0.075, axis: 'x' }); } if ($('.parallaxFG-left').length) { $('.parallaxFG-left').parallaxFG({ offsetIntertia: -0.075, axis: 'x' }); } } // 5. Video Popup // ------ // ****** ****** // ** the plugin code is found in youtubeplayer.js ** // ***** ****** // 6. Slick slider // ------ // ****** ****** // ** external plugin ** // ***** ****** if ($('.mobile-slider .grid-container').length) { $('.mobile-slider .grid-container').slick({ mobileFirst: true, dots: true, arrows: false, centerMode: true, centerPadding: '16px', slidesToShow: 1, responsive: [ { breakpoint: 640, settings: 'unslick', }, ], }); } // 7. RSS Feed // ------ if ($('#rss-feed').length) { $('#rss-feed').rss_feed(); } // 8. Anatomy of an extension // ------ if ($('#anatomy-of-an-extension-graphic').length) { $('#anatomy-of-an-extension-graphic').extenstionAnatomy(); } // 9. Popups // ------ if ($('.popup-action').length) { $('.popup-action').popups(); } // 10. Site (Content Guidelines) Nav // ------ if ($('.content-guidelines .site-nav-container').length) { $('.content-guidelines .site-nav-container').switchContentGuidelinesNav(); } // 11. Site Search Header // ------ if ($('.search-input').length) { $('.search-input').searchHeader(); } // 12. Site Search Results // ------ if ($('#result-list').length) { $('#result-list').searchResults(); } if ($('#tag-list').length) { $('#tag-list').searchResults({ input: null, default: '.popular-searches', search_fields: [ { title: 'tags', }, ], }); } // 13. Sidebar Nav Page Section Highlighting // ------ if ($('.is-active > .section').length) { $('.is-active > .section').highlightPageSection(); } // 14. Expandable List // ------ if ($('.expandable-list').length) { $('.expandable-list').expandableList(); } // 15. Up Next: hide if empty // ------ if ($('.up-next').length && !$('.up-next a').length) { $('.up-next').hide(0); } // 16. Scroll sidebar to active page position // ------ if ($('.sidenav-detail .is-active').length) { $('.sidenav').sidenavScrollToActive(); } // Init Breakpoint Listeners // ------------------ $(this).breakpoints(); }); // ------------------------------------------------------------------------------------------------------------------------------------------------ // PLUGINS (function ($) { // 1. Top Navigation : toggle mobile and desktop // ------ $.fn.switchNav = function (options) { var settings = $.extend( { breakpoint: 'atleast_large', }, options ); var $top = this; var nav_all = $top.persistantMenu(); var nav_desk = null; var nav_mobile = null; function switchNav(obj, media) { // Set Desktop Nav if (media[settings.breakpoint] || media.fallback) { if (nav_mobile != null) { nav_mobile.kill(); nav_mobile = null; } if (nav_desk == null) { nav_desk = $top.desktopMenu(); } // Set Mobile Nav } else { if (nav_desk != null) { nav_desk.kill(); nav_desk = null; } if (nav_mobile == null) { nav_mobile = $top.mobileMenu(); } } } $.subscribe('breakpoints', switchNav); }; // 1.a Mobile Menu $.fn.mobileMenu = function () { var $body = $('body'); var $container = this; var $nav = $container.find('.top-nav'); var $primaryDropdown = this.find('.hamburger'); $nav.velocity('transition.slideUpOut', { duration: 0, display: 'none' }); $primaryDropdown.on('click', function (e) { e.preventDefault(); if ($body.hasClass('nav-open')) { $primaryDropdown .removeClass('is-active') .attr('aria-expanded', 'false'); $body.removeClass('nav-open'); $nav.velocity('transition.slideUpOut', { duration: 600, display: 'none', }); } else { $primaryDropdown.addClass('is-active').attr('aria-expanded', 'true'); $body.addClass('nav-open'); $nav.velocity('transition.slideDownIn', { duration: 600, display: 'flex', }); } }); return { kill: function () { $primaryDropdown.off('click').removeClass('is-active'); $nav.velocity('transition.slideDownIn', { duration: 0, display: 'flex', complete: function () { $nav.attr('style', ''); $body.removeClass('nav-open'); }, }); }, }; }; // 1.b Desktop Menu $.fn.desktopMenu = function () { var $container = this; var $subnav = $container.find('.subfolder'); $subnav .on('focus', 'a', function () { $(this).closest('.has-subfolder').addClass('over'); }) .on('blur', 'a', function () { $(this).closest('.has-subfolder').removeClass('over'); }); return { kill: function () { $subnav.off('focus').off('blur'); }, }; }; // 1.c Persistant Menu $.fn.persistantMenu = function () { // Don't enable the scroll hidden menu for touch devices. if (is_touch_device) { console.debug('No-op persistantMenu for touch enabled devices'); return { kill: function () { console.debug('No-op persistantMenu.kill()'); }, }; } var $container = this; var $window = $(window); var scrollTop = $window.scrollTop(); var stateMinimized = false; var lastScrollTop = 0; var sensitivity = 5; var trigger = 30; function scrollState() { scrollTop = $window.scrollTop(); // downscroll if (scrollTop > trigger && scrollTop > lastScrollTop && !stateMinimized) { stateMinimized = true; $container.addClass('minimize').removeClass('minimize-down'); // upscroll } else if ( scrollTop > trigger && scrollTop < lastScrollTop - sensitivity && stateMinimized ) { stateMinimized = false; $container.removeClass('minimize').addClass('minimize-down'); // top of page } else if (scrollTop < trigger) { stateMinimized = false; $container.removeClass('minimize minimize-down'); } lastScrollTop = scrollTop; } $window.on('scroll', scrollState); scrollState(); return { kill: function () { $container.removeClass('minimize'); $window.off('scroll'); }, }; }; // 1.d Sidebar Nav $.fn.sideNav = function (options) { var settings = $.extend( { breakpoint: 'atleast_large', }, options ); var $top = this; var nav_mobile = null; function switchNav(obj, media) { // Set Desktop Nav if (media[settings.breakpoint] || media.fallback) { if (nav_mobile != null) { nav_mobile.kill(); nav_mobile = null; } // Set Mobile Nav } else { if (nav_mobile == null) { nav_mobile = $top.mobileSideNav(); } } } $.subscribe('breakpoints', switchNav); }; // 1.e Mobile Side Menu $.fn.mobileSideNav = function () { var $body = $('body'); var $container = this; var $nav = $container.find('.sidenav-top, .sidenav-detail'); var $primaryDropdown = this.find('.sidenav-status'); $nav.velocity('transition.slideUpOut', { duration: 0, display: 'none' }); $primaryDropdown.on('click', function (e) { e.preventDefault(); if ($body.hasClass('subnav-open')) { $primaryDropdown.removeClass('is-active'); $body.removeClass('subnav-open'); $nav.velocity('transition.slideUpOut', { duration: 600, display: 'none', }); } else { $primaryDropdown.addClass('is-active'); $body.addClass('subnav-open'); $nav.velocity('transition.slideDownIn', { duration: 600, display: 'block', }); } }); return { kill: function () { $primaryDropdown.off('click').removeClass('is-active'); $nav.velocity('transition.slideDownIn', { duration: 0, display: 'block', complete: function () { $nav.attr('style', ''); $body.removeClass('subnav-open'); }, }); }, }; }; // 1.f Sidebar Nav Top // ------ $.fn.sideNavTop = function () { var $label = this.find('> a, > .label'); var $active_parent = this.find( '.subfolder > .has-active-children > a, .subfolder > .is-active > a' ); var url = $active_parent.attr('href'); var title = $active_parent.text(); $label.attr('href', url); $label.text(title); }; $.fn.sideNavDetail = function () { this.find('a[data-overviewtitle]').each(function () { var $this = $(this); var attr = $this.data('overviewtitle'); $this.text(attr); }); }; // 1.g Sidebar Status // ------ $.fn.sideNavStatus = function (options) { var settings = $.extend( { active_el: '.sidenav-detail .is-active > a', }, options ); this.text($(settings.active_el).text()); }; // 2. Anchor scroll // ------ $.fn.scrollto = function (options) { var settings = $.extend( { offset_lg: 0, offset_sm: 0, exclude: 'tabbed-link', }, options ); var offset = settings.offset_lg; $.subscribe('breakpoints', function (obj, media) { offset = media.small ? settings.offset_sm : settings.offset_lg; }); this.on('click.scrollto', function (event) { var $anchor = $(this); var id = $anchor.attr('href').split('#')[1]; if ($('#' + id).length && !$anchor.hasClass(settings.exclude)) { event.preventDefault(); $.publish('scrollto', [$anchor]); var $el = $('#' + id); var top = id == 'top' ? $el.offset().top : $el.offset().top - offset; $('html').velocity('scroll', { duration: 900, offset: top }); var url_state = window.location.protocol + '//' + window.location.host + window.location.pathname + '#' + id; window.history.pushState({ href: url_state }, '', url_state); } }); return this; }; // 3. Show On Inview // ------ $.fn.showOnView = function (options) { if (is_touch_device) { console.debug('showOnView disabled for touch device'); return; } var settings = $.extend( { count: 'once', transitionDelay: 0, transitionIn: 'transition.slideUpIn', transitionOut: 'transition.slideDownOut', transitionSpeed: 500, transitionEasing: 'easeOutSine', display: null, staggerGroup: false, staggerIncrement: 100, breakpoint: 'atleast_medium', }, options ); var $window = $(window); var onLoad = true; var first = true; var active = false; var $elements = this; if (settings.staggerGroup && $(settings.staggerGroup).length) { var ar = settings.staggerGroup.split(' '); var $groups = $(ar[0]); $groups.each(function () { var increment = settings.staggerIncrement; var $els = $(this).find(ar[1]); $els.each(function () { $(this).data('onscrolldelay', increment); increment += settings.staggerIncrement; }); }); } $window.on('scroll.onLoad', function () { onLoad = false; $window.off('scroll.onLoad'); }); function activate() { $elements.each(function () { var $el = $(this); var delay = $el.data('onscrolldelay') !== undefined ? $el.data('onscrolldelay') : settings.transitionDelay; var onLoadDelay = $el.data('onloaddelay'); var thisDelay; var thisDisplay = $el.data('display') !== undefined ? $el.data('display') : settings.display; if (settings.count == 'once') { $el.one('inview', function (event, isInView) { if (isInView) { thisDelay = onLoad && onLoadDelay != undefined ? onLoadDelay : delay; $el.velocity(settings.transitionIn, { delay: thisDelay, duration: settings.transitionSpeed, easing: settings.transitionEasing, display: thisDisplay, }); } }); } else if (settings.count == 'everytime') { $el.on('inview', function (event, isInView) { if (isInView) { thisDelay = onLoad && onLoadDelay != undefined ? onLoadDelay : delay; $el.velocity(settings.transitionIn, { delay: thisDelay, duration: settings.transitionSpeed, easing: settings.transitionEasing, }); } else { $el.velocity(settings.transitionOut, { duration: settings.transitionSpeed, easing: settings.transitionEasing, }); } }); } }); } $.subscribe('breakpoints', function (obj, media) { active = settings.breakpoint == null || media[settings.breakpoint] || media.fallback; if (active && first) { first = false; activate(); } }); }; // 7. RSS Feed // ------ $.fn.rss_feed = function (options) { var settings = $.extend( { container: '<a href="" class="cell small-12 large-4 tile illustrated-tile tile-block-link no-img"><div class="block-link"></div></a>', breakpoint: 'atleast_large', num: 3, }, options ); var $container = this; function handleFeedXml(doc) { var $xml = $(doc); var i = settings.num; $xml.find('item').each(function () { if (i--) { var $this = $(this), item = { title: $this.find('title').text(), description: $this.find('description').text(), pubDate: $this.find('pubDate').text(), }; var newDate = new Date(item.pubDate); var d = newDate.getDate(); var m = newDate.getMonth(); m += 1; // JavaScript months are 0-11 var y = newDate.getFullYear(); var formattedDate = y + '/' + pad(m, 2) + '/' + pad(d, 2); var $cell = $(settings.container); var $cell_content = $cell.find('.block-link'); $cell_content .append($('<h4>').text(item.title)) .append($('<p class="meta-date">').text(formattedDate)) .append(DOMPurify.sanitize(item.description)); var $link = $cell.find('p a:last-child'); var link_label = $link.html(); var link_url = $link.attr('href'); $link.remove(); $cell_content.append( $( '<p><span class="block-link-inline">' + link_label + '</span></p>' ) ); $cell.attr('href', link_url); $container.append($cell); } else { return false; } }); $container.slick({ mobileFirst: true, dots: true, arrows: false, centerMode: true, centerPadding: '16px', slidesToShow: 1, responsive: [ { breakpoint: 640, settings: 'unslick', }, ], }); } // The third parameter (dataType) is set to 'xml' to make sure that the // response is always a parsed document regardless of the server's MIME // type. Without this, handleFeedXml could receive a string instead of a // document (when the server replies with a non-XML MIME type). That would // result in a XSS vulnerability. $.get('https://blog.mozilla.org/addons/feed/', handleFeedXml, 'xml'); return this; }; // 8. Anatomy of an extenstion // ------ $.fn.extenstionAnatomy = function (options) { var settings = $.extend( { control: $('#anatomy-control'), }, options ); var $this = this; var first = true; var timer1 = null; var timer2 = null; var $tile_interface = $('#interface'); var $tile_content = $('#content'); var $tile_background = $('#background'); $tile_interface .on('mouseenter', function () { $tile_interface.addClass('hover'); }) .on('mouseleave', function () { $tile_interface.removeClass('hover'); }); $tile_content .on('mouseenter', function () { $tile_content.addClass('hover'); }) .on('mouseleave', function () { $tile_content.removeClass('hover'); }); $tile_background .on('mouseenter', function () { $tile_background.addClass('hover'); }) .on('mouseleave', function () { $tile_background.removeClass('hover'); }); $this.on('inview', function (event, isInView) { clearTimeout(timer1); clearTimeout(timer2); if (isInView) { var delay = first ? 700 : 100; timer1 = setTimeout(function () { $this.addClass('step-one'); settings.control.addClass('step-one'); }, delay); timer2 = setTimeout(function () { $this.addClass('step-two'); settings.control.addClass('step-two'); }, delay + 200); first = false; } else { $this.removeClass('step-one step-two'); settings.control.removeClass('step-one step-two'); } }); settings.control .on('mouseenter', 'button', function () { var panel = $(this).data('panel'); if (panel == 'anatomy-ui') { $tile_interface.addClass('hover'); } else if (panel == 'anatomy-content') { $tile_content.addClass('hover'); } else if (panel == 'anatomy-background') { $tile_background.addClass('hover'); } }) .on('mouseleave', 'button', function () { $tile_interface.removeClass('hover'); $tile_content.removeClass('hover'); $tile_background.removeClass('hover'); }); // Fallback for touch devices using full-width layout. if (is_touch_device) { $('#anatomy-of-an-extension-graphic, #anatomy-control').addClass( 'step-one step-two' ); } }; // 9. Popups // ------ $.fn.popups = function (options) { var settings = $.extend( { panels: '.popup-panel', offset_x: -220, offset_y: -55, padding_x: 0, padding_y: 80, }, options ); var $window = $(window); var $body = $('body'); var $links = this; var $panels = $(settings.panels); $links.on('click', function () { var $link = $(this); var panel = '#' + $link.data('panel'); if ($panels.filter(':visible').length) { $panels.velocity('transition.slideDownOut', { duration: 300, complete: function () { openPanel($link, panel); }, }); } else { openPanel($link, panel); } }); function openPanel($link, panel) { if ($(panel).length) { var $panel = $(panel); positionPanel($panel); $panel.velocity('transition.slideUpIn', { duration: 300, complete: function () { if (!$body.hasClass('using-mouse')) { $panel.find('button.close').focus(); } }, }); $panel .find('button.close') .off('click') .on('click', function () { closePanel($link, $panel); }); $(document) .off('click.openpanel') .off('keyup.openpanel') .on('click.openpanel', function (e) { var $target = $(e.target); if (!$target.closest(panel).length && $panel.is(':visible')) { closePanel($link, $panel); } }) .on('keyup.openpanel', function (e) { if (e.key == 'Escape' && $panel.is(':visible')) { closePanel($link, $panel); } }); } } function closePanel($link, $panel) { $panel.velocity('transition.slideDownOut', { duration: 300, complete: function () { if (!$body.hasClass('using-mouse')) { $link.focus(); } }, }); } function positionPanel($panel) { var x = $window.width() / 2; var y = $window.height() / 2; var w = $panel.outerWidth() / 2; var h = $panel.outerHeight() / 2; $panel.css({ top: y - h, left: x - w }); } function updatePanelPosition() { $panels.filter(':visible').each(function () { positionPanel($(this)); }); } $window.on('resize', updatePanelPosition); updatePanelPosition(); }; // 10. Content Guidelines Navigation // ------ $.fn.switchContentGuidelinesNav = function (options) { var settings = $.extend( { breakpoint: 'atleast_medium', }, options ); var $container = this; var nav_desk = null; var nav_mobile = null; function switchContentGuidelinesNav(obj, media) { // Set Desktop Nav if (media[settings.breakpoint] || media.fallback) { if (nav_mobile != null) { nav_mobile.kill(); nav_mobile = null; } if (nav_desk == null) { nav_desk = $container.desktopContentGuidelinesMenu(); } // Set Mobile Nav } else { if (nav_desk != null) { nav_desk.kill(); nav_desk = null; } if (nav_mobile == null) { nav_mobile = $container.mobileContentGuidelinesMenu(); } } } $.subscribe('breakpoints', switchContentGuidelinesNav); }; // 10.a Mobile Menu $.fn.mobileContentGuidelinesMenu = function () { var $container = this; var $nav = $container.find('nav'); var $links = $container.find('p, li:not(.current)'); var open = $nav.hasClass('open'); var $window = $(window); $window.on('scroll.mobile', function () { if ($window.scrollTop() >= $container.offset().top) { $container.addClass('sticky'); } else { $container.removeClass('sticky'); } }); if (!open) { $links.velocity('slideUp', { duration: 0 }); } $nav.on('click', function () { if (open) { $nav.removeClass('open'); $links.velocity('slideUp'); } else { $nav.addClass('open'); $links.velocity('slideDown', { complete: function () { // if ($nav.outerHeight() + $nav.offset().top > $window.height() + $window.scrollTop()) { // $nav.velocity('scroll', {duration: 900, offset: -($nav.outerHeight() - 16)}); // } }, }); } open = !open; }); return { kill: function () { $nav.off('click'); $nav.removeClass('open'); $links.attr('style', ''); $window.off('scroll.mobile'); }, }; }; // 10.b Desktop Menu $.fn.desktopContentGuidelinesMenu = function () { return { kill: function () {}, }; }; // 11. Search Header // ------ $.fn.searchHeader = function (options) { var settings = $.extend( { open: '.search-input-open', close: '.search-input-close', input: '#lunrsearch', }, options ); var $container = this; var $open = $(settings.open); var $close = $(settings.close); var $input = $(settings.input); $open.on('click', function () { $input.val(''); $container.velocity('transition.slideRightIn', { duration: 450, display: 'flex', complete: function () { $input.focus(); }, }); }); $close.on('click', function () { $container.velocity('transition.slideRightOut', { duration: 450 }); }); $(document).on('keyup.searchheader', function (e) { if (e.key == 'Escape') { $container.velocity('transition.slideRightOut', { duration: 450 }); } }); }; // 12. Search Results // ------ $.fn.searchResults = function (options) { var settings = $.extend( { input: '.search-cta #lunrsearch', default: '.popular-searches', search_fields: [ { title: 'tags', boost: 5, }, { title: 'title', boost: 25, }, { title: 'body', boost: 1, }, ], }, options ); var $container = this; var $local_input = settings.input ? $(settings.input) : false; var $default = $(settings.default); var urlParams = new URLSearchParams(window.location.search); var myParam = urlParams.get('q'); var idx = null; var data = $.getJSON('/api/v1/pages.json'); // Lunr Search function lunr_search(query) { var result = []; try { result = idx.search(query); } catch (e) { console.error('Search Error: ' + e.message); } var num = result.length && query != '' ? result.length : 0; var query_output = num + ' ' + $container.data('message') + ' "' + query + '"'; var $title = $('<h2 class="no-underline"></h2>'); data.then(function (loaded_data) { // Show results $container.empty(); // Add status $title.text(query_output); $container.prepend($title); if (num != 0) { var $list = $('<ol></ol>'); // Loop through, match, and add results for (var item in result) { var ref = result[item].ref; var item = loaded_data.entries[ref]; var topic = item.meta && item.meta.topic ? '<p class="post-meta"><small>' + item.meta.topic + '</small></p>' : ''; var excerpt = $.trim(item.body) .substring(0, 300) .split(' ') .slice(0, -1) .join(' ') + '...'; var searchitem = '<li class="result"><a href="' + item.url + '">' + topic + '<h3>' + item.title + '</h3><p>' + excerpt + '</p><p><small>' + item.url + '</small></p></a></li>'; $list.append(searchitem); } $default.hide(0); $container.append($list); } else { $default.show(0); } }); } // Build Lunr data.then(function (loaded_data) { idx = lunr(function () { var l = this; $.each(settings.search_fields, function (i, obj) { l.field(obj.title, { boost: obj.boost ? obj.boost : 1 }); }); l.ref('id'); $.each(loaded_data.entries, function (index, value) { if (!value.skip_index) { l.add($.extend({ id: index }, value)); } }); }); if ($local_input) { $local_input.on('keyup', function () { var searchVal = $(this).val(); if (searchVal && searchVal.length && searchVal.length > 3) { lunr_search(searchVal); } }); } lunr_search(myParam); }); if ($local_input) { $local_input.val(myParam); } }; // 13. Sidebar Nav Page Section Highlighting $.fn.highlightPageSection = function (options) { var settings = $.extend( { offset: 38, }, options ); var $window = $(window); var $this = this; var $anchors = this.find('a'); $window.on('scroll', function () { updateAnchorActive(); }); updateAnchorActive(); function updateAnchorActive() { $anchors.removeClass('is-in-view'); $anchors.each(function () { var $self = $(this); var $el = $($self.attr('href')); if ($el.length && isInFocus($el, 0.75)) { $anchors.removeClass('is-in-view'); $self.addClass('is-in-view'); } }); } return this; }; // 14. Expandable List // ------ $.fn.expandableList = function (options) { var settings = $.extend( { title: 'dt', title_button: 'dt button', description: 'dd', }, options ); this.find(settings.title).addClass('closed'); this.find(settings.title_button).attr('aria-expanded', 'false'); this.find(settings.description).attr('aria-hidden', 'true'); this.on('click', settings.title_button, function () { var $this = $(this); if ($this.attr('aria-expanded') == 'true') { $this.attr('aria-expanded', 'false'); $this .closest(settings.title) .next(settings.description) .attr('aria-hidden', 'true'); } else { $this.attr('aria-expanded', 'true'); $this .closest(settings.title) .next(settings.description) .attr('aria-hidden', 'false'); } $this.closest(settings.title).toggleClass('closed'); }); }; // 16. Scroll sidebar to active page position // ------ $.fn.sidenavScrollToActive = function (options) { var settings = $.extend( { active: $('.sidenav-detail .is-active'), }, options ); var $container = this; /* Don't scroll for overview pages, * as they are already the first page element * and we want to see the section above them. */ if (!settings.active.find('a[data-overviewtitle]').length) { settings.active.velocity('scroll', { container: $container, duration: 0, delay: 0, }); } }; // Utilities // ------ function pad(n, width, z) { z = z || '0'; n = n + ''; return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n; } function decodeUrlParameter(str) { return decodeURIComponent((str + '').replace(/\+/g, '%20')); } function getUrlVars() { var vars = [], hash; var hashes = window.location.href .slice(window.location.href.indexOf('?') + 1) .split('&'); for (var i = 0; i < hashes.length; i++) { hash = hashes[i].split('='); vars.push(hash[0]); vars[hash[0]] = hash[1]; } return vars; } var aboveView = function (element) { return ( $(window).scrollTop() >= element.offset().top + element.outerHeight() ); }; var belowFocus = function (element, focusMultipliers) { return ( $(window).height() + $(window).scrollTop() < element.offset().top + $(window).height() * focusMultipliers ); }; var isInFocus = function (element, focusMultipliers) { return ( aboveView(element) != true && belowFocus(element, focusMultipliers) != true ); }; })(jQuery);