diff options
Diffstat (limited to 'tools/droiddoc/templates-sdk/assets/js/docs.js')
-rw-r--r-- | tools/droiddoc/templates-sdk/assets/js/docs.js | 486 |
1 files changed, 368 insertions, 118 deletions
diff --git a/tools/droiddoc/templates-sdk/assets/js/docs.js b/tools/droiddoc/templates-sdk/assets/js/docs.js index 8baf3f4..60bbaf9 100644 --- a/tools/droiddoc/templates-sdk/assets/js/docs.js +++ b/tools/droiddoc/templates-sdk/assets/js/docs.js @@ -56,7 +56,7 @@ $(document).ready(function() { // setup keyboard listener for search shortcut $('body').keyup(function(event) { - if (event.which == 191) { + if (event.which == 191 && $(event.target).is(':not(:input)')) { $('#search_autocomplete').focus(); } }); @@ -71,15 +71,9 @@ $(document).ready(function() { }); // initialize the divs with custom scrollbars - $('.scroll-pane').jScrollPane( {verticalGutter:0} ); - - // add HRs below all H2s (except for a few other h2 variants) - $('h2').not('#qv h2') - .not('#tb h2') - .not('.sidebox h2') - .not('#devdoc-nav h2') - .not('h2.norule').css({marginBottom:0}) - .after('<hr/>'); + if (window.innerWidth >= 720) { + $('.scroll-pane').jScrollPane({verticalGutter: 0}); + } // set up the search close button $('#search-close').click(function() { @@ -192,8 +186,6 @@ $(document).ready(function() { subNavEl.find("li.google > a").addClass("selected"); } else if ($("body").hasClass("samples")) { subNavEl.find("li.samples > a").addClass("selected"); - } else if ($("body").hasClass("preview")) { - subNavEl.find("li.preview > a").addClass("selected"); } else { parentNavEl.removeClass('has-subnav').addClass("selected"); } @@ -372,7 +364,7 @@ false; // navigate across topic boundaries only in design docs var $liLesson; $classLinks.each(function(index) { $liClass = $('<li class="clearfix"></li>'); - $h2Title = $('<a class="title" href="'+$(this).attr('href')+'"><h2>' + $(this).html()+'</h2><span></span></a>'); + $h2Title = $('<a class="title" href="'+$(this).attr('href')+'"><h2 class="norule">' + $(this).html()+'</h2><span></span></a>'); $pSummary = $('<p class="description">' + $classDescriptions[index] + '</p>'); $olLessons = $('<ol class="lesson-list"></ol>'); @@ -405,23 +397,15 @@ false; // navigate across topic boundaries only in design docs /* Resize nav height when window height changes */ $(window).resize(function() { if ($('#side-nav').length == 0) return; - var stylesheet = $('link[rel="stylesheet"][class="fullscreen"]'); - setNavBarLeftPos(); // do this even if sidenav isn't fixed because it could become fixed + setNavBarDimensions(); // do this even if sidenav isn't fixed because it could become fixed // make sidenav behave when resizing the window and side-scolling is a concern - if (sticky) { - if ((stylesheet.attr("disabled") == "disabled") || stylesheet.length == 0) { - updateSideNavPosition(); - } else { - updateSidenavFullscreenWidth(); - } - } - resizeNav(); + updateSideNavDimensions(); + checkSticky(); + resizeNav(250); }); - - var navBarLeftPos; if ($('#devdoc-nav').length) { - setNavBarLeftPos(); + setNavBarDimensions(); } @@ -464,7 +448,12 @@ false; // navigate across topic boundaries only in design docs $('h2').click(function() { var id = $(this).attr('id'); if (id) { - document.location.hash = id; + if (history && history.replaceState) { + // Change url without scrolling. + history.replaceState({}, '', '#' + id); + } else { + document.location.hash = id; + } } }); @@ -546,15 +535,6 @@ false; // navigate across topic boundaries only in design docs }); }); } - - // Responsive testing - var responsiveParam = location.href.match(/[?&]responsive=?(|true|false)/); - if (responsiveParam) { - localStorage['test-responsive'] = ['', 'true'].indexOf(responsiveParam) > -1; - } - if (localStorage['test-responsive']) { - $(document.body).addClass('responsive'); - } }); // END of the onload event @@ -785,21 +765,24 @@ function toggleFullscreen(enable) { enabled = false; } writeCookie("fullscreen", enabled, null); - setNavBarLeftPos(); + setNavBarDimensions(); resizeNav(delay); - updateSideNavPosition(); + updateSideNavDimensions(); setTimeout(initSidenavHeightResize,delay); } - -function setNavBarLeftPos() { +// TODO: Refactor into a closure. +var navBarLeftPos; +var navBarWidth; +function setNavBarDimensions() { navBarLeftPos = $('#body-content').offset().left; + navBarWidth = $('#side-nav').width(); } -function updateSideNavPosition() { +function updateSideNavDimensions() { var newLeft = $(window).scrollLeft() - navBarLeftPos; - $('#devdoc-nav').css({left: -newLeft}); + $('#devdoc-nav').css({left: -newLeft, width: navBarWidth}); $('#devdoc-nav .totop').css({left: -(newLeft - parseInt($('#side-nav').css('padding-left')))}); } @@ -834,7 +817,7 @@ $(document).ready(function() { -/* ######### RESIZE THE SIDENAV HEIGHT ########## */ +/* ######### RESIZE THE SIDENAV ########## */ function resizeNav(delay) { var $nav = $("#devdoc-nav"); @@ -850,7 +833,7 @@ function resizeNav(delay) { // get the height of space between nav and top of window. // Could be either margin or top position, depending on whether the nav is fixed. - var topMargin = (parseInt($nav.css('margin-top')) || parseInt($nav.css('top'))) + 1; + var topMargin = (parseInt($nav.css('top')) || 20) + 1; // add 1 for the #side-nav bottom margin // Depending on whether the header is visible, set the side nav's height. @@ -865,7 +848,9 @@ function resizeNav(delay) { $scrollPanes = $(".scroll-pane"); - if ($scrollPanes.length > 1) { + if ($window.width() < 720) { + $nav.css('height', ''); + } else if ($scrollPanes.length > 1) { // subtract the height of the api level widget and nav swapper from the available nav height navHeight -= ($('#api-nav-header').outerHeight(true) + $('#nav-swap').outerHeight(true)); @@ -933,7 +918,7 @@ function delayedReInitScrollbars(delay) { function reInitScrollbars() { var pane = $(".scroll-pane").each(function(){ var api = $(this).data('jsp'); - if (!api) { setTimeout(reInitScrollbars,300); return;} + if (!api) {return;} api.reinitialise( {verticalGutter:0} ); }); $(".scroll-pane").removeAttr("tabindex"); // get rid of tabindex added by jscroller @@ -969,6 +954,7 @@ function restoreHeight(packageHeight) { /** Scroll the jScrollPane to make the currently selected item visible This is called when the page finished loading. */ function scrollIntoView(nav) { + return; var $nav = $("#"+nav); var element = $nav.jScrollPane({/* ...settings... */}); var api = element.data('jsp'); @@ -1051,18 +1037,21 @@ function setStickyTop() { * Displays sticky nav bar on pages when dac header scrolls out of view */ $(window).scroll(function(event) { - - setStickyTop(); - var hiding = false; - var $headerEl = $('#header'); - // Exit if there's no sidenav - if ($('#side-nav').length == 0) return; // Exit if the mouse target is a DIV, because that means the event is coming // from a scrollable div and so there's no need to make adjustments to our layout if ($(event.target).nodeName == "DIV") { return; } + checkSticky(); +}); + +function checkSticky() { + setStickyTop(); + var $headerEl = $('#header'); + // Exit if there's no sidenav + if ($('#side-nav').length == 0) return; + var top = $(window).scrollTop(); // we set the navbar fixed when the scroll position is beyond the height of the site header... var shouldBeSticky = top >= stickyTop; @@ -1071,11 +1060,15 @@ $(window).scroll(function(event) { if ($("#doc-col").height() < $("#side-nav").height()) { shouldBeSticky = false; } + // Nor on mobile + if (window.innerWidth < 720) { + shouldBeSticky = false; + } // Account for horizontal scroll var scrollLeft = $(window).scrollLeft(); // When the sidenav is fixed and user scrolls horizontally, reposition the sidenav to match if (sticky && (scrollLeft != prevScrollLeft)) { - updateSideNavPosition(); + updateSideNavDimensions(); prevScrollLeft = scrollLeft; } @@ -1088,38 +1081,29 @@ $(window).scroll(function(event) { // If sticky header visible and position is now near top, hide sticky if (sticky && !shouldBeSticky) { sticky = false; - hiding = true; // make the sidenav static again $('#devdoc-nav') - .removeClass('fixed') - .css({'width':'auto','margin':''}) - .prependTo('#side-nav'); + .removeClass('fixed') + .css({'width':'auto','margin':''}); // delay hide the sticky $headerEl.removeClass('is-sticky'); - hiding = false; // update the sidenaav position for side scrolling - updateSideNavPosition(); + updateSideNavDimensions(); } else if (!sticky && shouldBeSticky) { sticky = true; $headerEl.addClass('is-sticky'); // make the sidenav fixed - var width = $('#devdoc-nav').width(); $('#devdoc-nav') - .addClass('fixed') - .css({'width':width+'px'}) - .prependTo('#body-content'); + .addClass('fixed'); // update the sidenaav position for side scrolling - updateSideNavPosition(); + updateSideNavDimensions(); - } else if (hiding && top < 15) { - $headerEl.removeClass('is-sticky'); - hiding = false; } resizeNav(250); // pass true in order to delay the scrollbar re-initialization for performance -}); +} /* * Manages secion card states and nav resize to conclude loading @@ -1324,13 +1308,13 @@ function requestAppendHL(uri) { function changeNavLang(lang) { - var $links = $("#devdoc-nav,#header,#nav-x,.training-nav-top,.content-footer").find("a["+lang+"-lang]"); - $links.each(function(i){ // for each link with a translation + if (lang === 'en') { return; } + + var $links = $('a[' + lang + '-lang]'); + $links.each(function(){ // for each link with a translation var $link = $(this); - if (lang != "en") { // No need to worry about English, because a language change invokes new request - // put the desired language from the attribute as the text - $link.text($link.attr(lang+"-lang")) - } + // put the desired language from the attribute as the text + $link.text($link.attr(lang + '-lang')) }); } @@ -3147,6 +3131,10 @@ function init_google_navtree(navtree_id, toroot, root_nodes) me.node = new Object(); me.node.li = document.getElementById(navtree_id); + if (!me.node.li) { + return; + } + me.node.children_data = root_nodes; me.node.children = new Array(); me.node.children_ul = document.createElement("ul"); @@ -3740,7 +3728,7 @@ function showSamples() { return $el; } - + function createResponsiveFlowColumn(cardSize) { var cardWidth = parseInt(cardSize.match(/(\d+)/)[1], 10); var column = $('<div>').addClass('col-' + (cardWidth / 3) + 'of6'); @@ -3765,7 +3753,7 @@ function showSamples() { while (i < resources.length) { var cardSize = cardSizes[j++ % cardSizes.length]; cardSize = cardSize.replace(/^\s+|\s+$/,''); - + var column = createResponsiveFlowColumn(cardSize).appendTo($widget); // A stack has a third dimension which is the number of stacked items @@ -4374,6 +4362,88 @@ function showSamples() { } })(); +/** + * Auto TOC + * + * Upgrades h2s on the page to have a rule and be toggle-able on mobile. + */ +(function($) { + var upgraded = false; + var h2Titles; + + function initWidget() { + // add HRs below all H2s (except for a few other h2 variants) + // Consider doing this with css instead. + h2Titles = $('h2').not('#qv h2, #tb h2, .sidebox h2, #devdoc-nav h2, h2.norule'); + h2Titles.css({marginBottom:0}).after('<hr/>'); + + // Exit early if on older browser. + if (!window.matchMedia) { + return; + } + + // Only run logic in mobile layout. + var query = window.matchMedia('(max-width: 719px)'); + if (query.matches) { + makeTogglable(); + } else { + query.addListener(makeTogglable); + } + } + + function makeTogglable() { + // Only run this logic once. + if (upgraded) { return; } + upgraded = true; + + // Only make content h2s togglable. + var contentTitles = h2Titles.filter('#jd-content *'); + + // If there are more than 1 + if (contentTitles.size() < 2) { + return; + } + + contentTitles.each(function() { + // Find all the relevant nodes. + var $title = $(this); + var $hr = $title.next(); + var $contents = $hr.nextUntil('h2, .next-docs'); + var $section = $($title) + .add($hr) + .add($title.prev('a[name]')) + .add($contents); + var $anchor = $section.first().prev(); + var anchorMethod = 'after'; + if ($anchor.length === 0) { + $anchor = $title.parent(); + anchorMethod = 'prepend'; + } + + // Remove from DOM before messing with it. DOM is slow! + $section.detach(); + + // Add mobile-only expand arrows. + $title.prepend('<span class="dac-visible-mobile-inline-block">' + + '<i class="dac-toggle-expand dac-sprite dac-expand-more-black"></i>' + + '<i class="dac-toggle-collapse dac-sprite dac-expand-less-black"></i>' + + '</span>') + .attr('data-toggle', 'section'); + + // Wrap in magic markup. + $section = $section.wrapAll('<div class="dac-toggle dac-mobile">').parent(); + $contents.wrapAll('<div class="dac-toggle-content"><div>'); // extra div used for max-height calculation. + + // Add it back to the dom. + $anchor[anchorMethod].call($anchor, $section); + }); + } + + $(function() { + initWidget(); + }); +})(jQuery); + (function($) { 'use strict'; @@ -4642,27 +4712,26 @@ function showSamples() { this.frames.eq(next).removeClass('out'); // Recalculate styles before starting slide transition. - var that = this; - resolveStyles(this.el[0], function() { - // Update pagination - that.pagination.removeClass('active').eq(next).addClass('active'); + this.el.resolveStyles(); + // Update pagination + this.pagination.removeClass('active').eq(next).addClass('active'); - // Transition out current frame - that.frames.eq(that.current).toggleClass('active out'); + // Transition out current frame + this.frames.eq(this.current).toggleClass('active out'); - // Transition in a new frame - that.frames.eq(next).toggleClass('active'); + // Transition in a new frame + this.frames.eq(next).toggleClass('active'); - that.current = next; - }); + this.current = next; }; - // Helper - function resolveStyles(el, callback) { + // Helper which resolves new styles for an element, so it can start transitioning + // from the new values. + $.fn.resolveStyles = function() { /*jshint expr:true*/ - el.offsetTop; - callback(); - } + this[0] && this[0].offsetTop; + return this; + }; // jQuery plugin $.fn.dacCarousel = function() { @@ -4682,39 +4751,66 @@ function showSamples() { (function($) { 'use strict'; - /** - * Toggle the visabilty of the mobile navigation. - * @param {HTMLElement} el - The DOM element. - * @param options - * @constructor - */ - function ToggleModal(el, options) { + function Modal(el, options) { this.el = $(el); this.options = $.extend({}, ToggleModal.DEFAULTS_, options); - this.el.on('click', this.clickHandler_.bind(this)); + this.isOpen = false; + + this.el.on('click', function(event) { + if (!$.contains($('.dac-modal-window')[0], event.target)) { + return this.close_(); + } + }.bind(this)); + + this.el.on('open', this.open_.bind(this)); + this.el.on('close', this.close_.bind(this)); + this.el.on('toggle', this.toggle_.bind(this)); } - ToggleModal.DEFAULTS_ = { - toggleClass: 'dac-modal-open' + Modal.prototype.toggle_ = function() { + if (this.isOpen) { + this.close_(); + } else { + this.open_(); + } }; - /** - * The actual toggle logic. - * @param event - * @private - */ + Modal.prototype.close_ = function() { + this.el.removeClass('dac-active'); + $('body').removeClass('dac-modal-open'); + this.isOpen = false; + }; + + Modal.prototype.open_ = function() { + this.el.addClass('dac-active'); + $('body').addClass('dac-modal-open'); + this.isOpen = true; + }; + + function ToggleModal(el, options) { + this.el = $(el); + this.options = $.extend({}, ToggleModal.DEFAULTS_, options); + this.modal = this.options.modalToggle ? $('[data-modal="' + this.options.modalToggle + '"]') : + this.el.closest('[data-modal]'); + + this.el.on('click', this.clickHandler_.bind(this)); + } + ToggleModal.prototype.clickHandler_ = function(event) { event.preventDefault(); - //TODO: Toggle a class on the modal itself - $('body').toggleClass(this.options.toggleClass); - $('.dac-modal-dimmer').toggleClass('dac-active'); - $('.dac-modal-window').toggleClass('dac-active'); + this.modal.trigger('toggle'); }; /** * jQuery plugin * @param {object} options - Override default options. */ + $.fn.dacModal = function(options) { + return this.each(function() { + new Modal(this, options); + }); + }; + $.fn.dacToggleModal = function(options) { return this.each(function() { new ToggleModal(this, options); @@ -4725,7 +4821,11 @@ function showSamples() { * Data Attribute API */ $(document).on('ready.aranja', function() { - $('[data-modal-toogle]').each(function() { + $('[data-modal]').each(function() { + $(this).dacModal($(this).data()); + }); + + $('[data-modal-toggle]').each(function() { $(this).dacToggleModal($(this).data()); }); }); @@ -4803,8 +4903,12 @@ function showSamples() { */ function NewsletterForm(el) { this.el = $(el); - this.url = this.el.attr('action'); - this.el.on('submit', this.submitHandler_.bind(this)); + this.form = this.el.find('form'); + $('<iframe/>').hide() + .attr('name', 'dac-newsletter-iframe') + .attr('src', '') + .insertBefore(this.form); + this.form.on('submit', this.submitHandler_.bind(this)); } /** @@ -4812,10 +4916,8 @@ function showSamples() { * @private */ NewsletterForm.prototype.submitHandler_ = function() { - //TODO: Close the modal with an event and let modal.js handle this - $('body').removeClass('dac-modal-open'); - $('.dac-modal-dimmer').removeClass('dac-active'); - $('.dac-modal-window').removeClass('dac-active'); + this.form.trigger('reset'); + this.el.trigger('close'); }; /** @@ -4832,8 +4934,156 @@ function showSamples() { * Data Attribute API */ $(document).on('ready.aranja', function() { - $('[data-newsletter-form]').each(function() { + $('[data-newsletter]').each(function() { $(this).dacNewsletterForm(); }); }); })(jQuery); + +(function($) { + 'use strict'; + + /** + * Smoothly scroll to location on current page. + * @param el + * @param options + * @constructor + */ + function ScrollButton(el, options) { + this.el = $(el); + this.target = $(this.el.attr('href')); + this.options = $.extend({}, ScrollButton.DEFAULTS_, options); + + if (typeof this.options.offset === 'string') { + this.options.offset = $(this.options.offset).height(); + } + + this.el.on('click', this.clickHandler_.bind(this)); + } + + /** + * Default options + * @type {{duration: number, easing: string, offset: number, scrollContainer: string}} + * @private + */ + ScrollButton.DEFAULTS_ = { + duration: 300, + easing: 'swing', + offset: 0, + scrollContainer: 'html, body' + }; + + /** + * Scroll logic + * @param event + * @private + */ + ScrollButton.prototype.clickHandler_ = function(event) { + if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) { + return; + } + + event.preventDefault(); + + $(this.options.scrollContainer).animate({ + scrollTop: this.target.offset().top - this.options.offset + }, this.options); + }; + + /** + * jQuery plugin + * @param {object} options - Override default options. + */ + $.fn.dacScrollButton = function(options) { + return this.each(function() { + new ScrollButton(this, options); + }); + }; + + /** + * Data Attribute API + */ + $(document).on('ready.aranja', function() { + $('[data-scroll-button]').each(function() { + $(this).dacScrollButton($(this).data()); + }); + }); +})(jQuery); + +(function($) { + function Toggle(el) { + $(el).on('click.dac.togglesection', this.toggle); + } + + Toggle.prototype.toggle = function() { + var $this = $(this); + + var $parent = getParent($this); + var isExpanded = $parent.hasClass('is-expanded'); + + transitionMaxHeight($parent.find('.dac-toggle-content'), !isExpanded); + $parent.toggleClass('is-expanded'); + + return false; + }; + + function getParent($this) { + var selector = $this.attr('data-target'); + + if (!selector) { + selector = $this.attr('href'); + selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, ''); + } + + var $parent = selector && $(selector); + + return $parent && $parent.length ? $parent : $this.parent(); + } + + /** + * Runs a transition of max-height along with responsive styles which hide or expand the element. + * @param $el + * @param visible + */ + function transitionMaxHeight($el, visible) { + // Only supports 1 child + var contentHeight = $el.children().outerHeight(); + var targetHeight = visible ? contentHeight : 0; + var duration = $el.transitionDuration(); + + // If we're hiding, first set the maxHeight we're transitioning from. + if (!visible) { + $el.css('maxHeight', contentHeight + 'px') + .resolveStyles(); + } + + // Transition to new state + $el.css('maxHeight', targetHeight); + + // Reset maxHeight to css value after transition. + setTimeout(function() { + $el.css('maxHeight', ''); + }, duration); + } + + // Utility to get the transition duration for the element. + $.fn.transitionDuration = function() { + var d = $(this).css('transitionDuration') || '0s'; + + return +(parseFloat(d) * (/ms/.test(d) ? 1 : 1000)).toFixed(0); + }; + + // jQuery plugin + $.fn.toggleSection = function(option) { + return this.each(function() { + var $this = $(this); + var data = $this.data('dac.togglesection'); + if (!data) {$this.data('dac.togglesection', (data = new Toggle(this)));} + if (typeof option === 'string') {data[option].call($this);} + }); + }; + + // Data api + $(document) + .on('click.toggle', '[data-toggle="section"]', Toggle.prototype.toggle); +})(jQuery); |