1*1789df15SXin Li/* 2*1789df15SXin Li * Copyright 2012 The Android Open Source Project 3*1789df15SXin Li * 4*1789df15SXin Li * Licensed under the Apache License, Version 2.0 (the "License"); 5*1789df15SXin Li * you may not use this file except in compliance with the License. 6*1789df15SXin Li * You may obtain a copy of the License at 7*1789df15SXin Li * 8*1789df15SXin Li * http://www.apache.org/licenses/LICENSE-2.0 9*1789df15SXin Li * 10*1789df15SXin Li * Unless required by applicable law or agreed to in writing, software 11*1789df15SXin Li * distributed under the License is distributed on an "AS IS" BASIS, 12*1789df15SXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13*1789df15SXin Li * See the License for the specific language governing permissions and 14*1789df15SXin Li * limitations under the License. 15*1789df15SXin Li */ 16*1789df15SXin Li 17*1789df15SXin Li$(document).ready(function() { 18*1789df15SXin Li prettyPrint(); 19*1789df15SXin Li preventParentScrolls('nav'); 20*1789df15SXin Li 21*1789df15SXin Li var sluggify_ = function(s) { 22*1789df15SXin Li return (s || '').replace(/ /g, '-').replace(/[^\w-]/g, '').toLowerCase(); 23*1789df15SXin Li }; 24*1789df15SXin Li 25*1789df15SXin Li $('h2, h3, h4.includetoc').each(function() { 26*1789df15SXin Li $(this).attr('id', 'toc_' + sluggify_($(this).data('tocid') || $(this).data('toctitle') || $(this).text())); 27*1789df15SXin Li $(this).click(function() { 28*1789df15SXin Li smoothScrollToId($(this).attr('id')); 29*1789df15SXin Li }); 30*1789df15SXin Li }); 31*1789df15SXin Li 32*1789df15SXin Li var buildNav_ = function(queries, $contentRoot, $navRoot) { 33*1789df15SXin Li if (!queries || !queries.length) { 34*1789df15SXin Li return; 35*1789df15SXin Li } 36*1789df15SXin Li 37*1789df15SXin Li $contentRoot.find(queries[0]).each(function() { 38*1789df15SXin Li var $navNode = $('<div>') 39*1789df15SXin Li .text($(this).html()) 40*1789df15SXin Li .appendTo($navRoot); 41*1789df15SXin Li buildNav_(queries.splice(1), $(this), $navNode); 42*1789df15SXin Li }); 43*1789df15SXin Li }; 44*1789df15SXin Li 45*1789df15SXin Li buildNav(); 46*1789df15SXin Li}); 47*1789df15SXin Li 48*1789df15SXin Lifunction buildNav() { 49*1789df15SXin Li var currentLevel = 2; 50*1789df15SXin Li var $currentParent = $('nav'); 51*1789df15SXin Li var $currentNode = null; 52*1789df15SXin Li 53*1789df15SXin Li $('#page-content').find('h2, h3, h4.includetoc').each(function() { 54*1789df15SXin Li var level = $(this).get(0).tagName.substring(1); 55*1789df15SXin Li 56*1789df15SXin Li if (level < currentLevel) { 57*1789df15SXin Li // ascend 58*1789df15SXin Li for (var i = 0; i < (currentLevel - level); i++) { 59*1789df15SXin Li $currentParent = $currentParent.parents('div.children, nav').first(); 60*1789df15SXin Li } 61*1789df15SXin Li 62*1789df15SXin Li } else if (level > currentLevel) { 63*1789df15SXin Li // descend 64*1789df15SXin Li $currentParent = $('<div>') 65*1789df15SXin Li .addClass('children') 66*1789df15SXin Li .appendTo($currentNode); 67*1789df15SXin Li } 68*1789df15SXin Li 69*1789df15SXin Li var tocId = $(this).attr('id'); 70*1789df15SXin Li var navId = tocId.replace(/toc_/, 'nav_'); 71*1789df15SXin Li 72*1789df15SXin Li $interactionNode = $('<span>') 73*1789df15SXin Li .html($(this).data('toctitle') || $(this).html()) 74*1789df15SXin Li .data('target', tocId) 75*1789df15SXin Li .click(function() { 76*1789df15SXin Li smoothScrollToId($(this).data('target')); 77*1789df15SXin Li }); 78*1789df15SXin Li 79*1789df15SXin Li $currentNode = $('<div>') 80*1789df15SXin Li .attr('id', navId) 81*1789df15SXin Li .addClass('item') 82*1789df15SXin Li .append($interactionNode) 83*1789df15SXin Li .appendTo($currentParent); 84*1789df15SXin Li 85*1789df15SXin Li currentLevel = level; 86*1789df15SXin Li }); 87*1789df15SXin Li 88*1789df15SXin Li var headerPositionCache = []; 89*1789df15SXin Li var rebuildHeaderPositionCache_ = function() { 90*1789df15SXin Li headerPositionCache = []; 91*1789df15SXin Li $('#page-content').find('h2, h3, h4.includetoc').each(function() { 92*1789df15SXin Li headerPositionCache.push({ 93*1789df15SXin Li id: $(this).attr('id').replace(/toc_/, 'nav_'), 94*1789df15SXin Li top: $(this).offset().top 95*1789df15SXin Li }); 96*1789df15SXin Li }); 97*1789df15SXin Li }; 98*1789df15SXin Li 99*1789df15SXin Li var updateSelectedNavPosition_ = function() { 100*1789df15SXin Li $('nav .item').removeClass('selected'); 101*1789df15SXin Li var scrollTop = $(window).scrollTop(); 102*1789df15SXin Li for (var i = headerPositionCache.length - 1; i >= 0; i--) { 103*1789df15SXin Li if (scrollTop >= headerPositionCache[i].top) { 104*1789df15SXin Li $('#' + headerPositionCache[i].id).addClass('selected'); 105*1789df15SXin Li break; 106*1789df15SXin Li } 107*1789df15SXin Li } 108*1789df15SXin Li }; 109*1789df15SXin Li 110*1789df15SXin Li rebuildHeaderPositionCache_(); 111*1789df15SXin Li $(window).resize(function() { 112*1789df15SXin Li rebuildHeaderPositionCache_(); 113*1789df15SXin Li updateSelectedNavPosition_(); 114*1789df15SXin Li }); 115*1789df15SXin Li 116*1789df15SXin Li $(window).scroll(function() { 117*1789df15SXin Li updateSelectedNavPosition_(); 118*1789df15SXin Li }); 119*1789df15SXin Li} 120*1789df15SXin Li 121*1789df15SXin Lifunction smoothScrollToId(id) { 122*1789df15SXin Li var $target = $('#' + id); 123*1789df15SXin Li $('body').animate({ scrollTop: $target.offset().top }, 200, 'swing', function() { 124*1789df15SXin Li document.location.hash = id; 125*1789df15SXin Li }); 126*1789df15SXin Li} 127*1789df15SXin Li 128*1789df15SXin Li// Based on http://stackoverflow.com/questions/5802467/prevent-scrolling-of-parent-element 129*1789df15SXin Lifunction preventParentScrolls($el) { 130*1789df15SXin Li $($el).on('DOMMouseScroll mousewheel', function(ev) { 131*1789df15SXin Li var $this = $(this), 132*1789df15SXin Li scrollTop = this.scrollTop, 133*1789df15SXin Li scrollHeight = this.scrollHeight, 134*1789df15SXin Li height = $this.height(), 135*1789df15SXin Li delta = (ev.type == 'DOMMouseScroll' ? 136*1789df15SXin Li ev.originalEvent.detail * -40 : 137*1789df15SXin Li ev.originalEvent.wheelDelta), 138*1789df15SXin Li up = delta > 0; 139*1789df15SXin Li 140*1789df15SXin Li if (!up && -delta > scrollHeight - height - scrollTop) { 141*1789df15SXin Li // Scrolling down, but this will take us past the bottom. 142*1789df15SXin Li $this.scrollTop(scrollHeight); 143*1789df15SXin Li } else if (up && delta > scrollTop) { 144*1789df15SXin Li // Scrolling up, but this will take us past the top. 145*1789df15SXin Li $this.scrollTop(0); 146*1789df15SXin Li } else { 147*1789df15SXin Li $this.scrollTop(scrollTop - delta); 148*1789df15SXin Li } 149*1789df15SXin Li 150*1789df15SXin Li ev.stopPropagation(); 151*1789df15SXin Li ev.preventDefault(); 152*1789df15SXin Li ev.returnValue = false; 153*1789df15SXin Li return false; 154*1789df15SXin Li }); 155*1789df15SXin Li}