| <div class="list-group side-menu" id="side-menu"> |
| {% comment %} |
| |
| Case 1) If we're the landing page show nothing. |
| Case 2) If we're contained in the top (landing page) menu, show our menu if we have one. |
| Case 3a) Otherwise if we're contained in a menu, show that menu. |
| Case 3b) And if we have a menu, show our menu nested. |
| |
| Note the breadcrumbs are offset:1. This is because usually breadcrumbs include the root; |
| but also if we're overriding breadcrumbs it gives us a way to set a topmenu item (making it breadcrumb[0]) |
| while customizing the side menu (make self breadcrumb[1]). |
| {% endcomment %} |
| |
| {% if page.layout != "website-landing" %} |
| {% if page.menu_parent %} |
| {% if page.menu_parent.layout == "website-landing" %} {% comment %} case 2 {% endcomment %} |
| {% for item in page.breadcrumb_pages offset:1 %} |
| <h4 class="{% if forloop.index0 > 0 %} with_preceding{% endif %}{% if forloop.rindex0 > 0 %} with_following{% endif %}"> |
| <a href="{{item.url}}" class="list-group-item{% if item.path == page.menu_path %} active{% endif %} breadcrumb breadcrumb{{ forloop.index0 }}"> |
| {{ item.title_in_menu }}</a></h4> |
| {% endfor %} |
| |
| {% for item in page.menu %} |
| <a href="{{item.url}}" class="list-group-item{% if page.breadcrumbs contains item %} active{% endif %}">{{ item.title_in_menu }} |
| {% if item.external %} <span class="octicon octicon-link-external"></span>{% endif %}</a> |
| {% endfor %} |
| |
| {% else %} {% comment %} case 3a {% endcomment %} |
| {% for item in page.menu_parent.breadcrumb_pages offset:1 %} |
| <h4 class="{% if forloop.index0 > 0 %} with_preceding{% endif %}{% if forloop.rindex0 > 0 %} with_following{% endif %}"> |
| <a href="{{item.url}}" class="list-group-item{% if item.path == page.menu_path %}{% unless item.menu_customization.force_inactive %} active{% endunless %}{% endif %} breadcrumb breadcrumb{{ forloop.index0 }}"> |
| {{ item.title_in_menu }} |
| {% if item.external %} <span class="octicon octicon-link-external"></span>{% endif %}</a></h4> |
| {% endfor %} |
| {% for item in page.menu_parent.menu %} |
| {% if page.breadcrumb_paths contains item.menu_path %}{% assign in_menu = true %}{% else %}{% assign in_menu = false %}{% endif %} |
| {% if in_menu and page.menu %} |
| {% comment %} case 3b {% endcomment %} |
| <a href="{{item.url}}" class="list-group-item active with-sub-item">{{ item.title_in_menu }} |
| {% if item.external %} <span class="octicon octicon-link-external"></span>{% endif %}</a> |
| <div class="sub-item"> |
| {% for item2 in page.menu %} |
| {% capture item_section_classes %}{% if item2.section %} section{% endif %}{% endcapture %} |
| <a href="{{item2.url | relative_url}}" class="list-group-item sub-item {{ item_section_classes }}" {% if item2.section %}section-target="#{{ item2.section }}"{% endif %}> |
| {{ item2.title_in_menu }} |
| {% if item2.external %} <span class="octicon octicon-link-external"></span>{% endif %}</a> |
| {% endfor %} |
| </div> |
| {% else %} |
| {% comment %} case 3a side menu item {% endcomment %} |
| <a href="{{item.url}}" class="list-group-item{% if page.breadcrumb_paths contains item.menu_path %}{% unless item.menu_customization.force_inactive %} active{% endunless %}{% endif %}">{{ item.title_in_menu }} |
| {% if item.external %} <span class="octicon octicon-link-external"></span>{% endif %}</a> |
| {% endif %} |
| {% endfor %} |
| |
| {% endif %} |
| {% elsif page.menu %} |
| <!-- no pages have a menu without being in the top menu, won't come here --> |
| {% endif %} |
| {% endif %} |
| |
| </div> |
| <div id="width_reference"></div> |
| |
| |
| <script language="JavaScript" type="application/javascript"> |
| (function($){ |
| {% comment %} |
| the menu is css position:fixed so won't scroll; |
| but also it will not obey its parents width. |
| set the width on load and on resize. |
| {% endcomment %} |
| sidemenu_x_sizer=function(){ $('#side-menu').width($('#side-menu').parent().find('#width_reference').outerWidth()); }; |
| $(sidemenu_x_sizer); |
| $(window).resize(sidemenu_x_sizer); |
| |
| {% comment %} |
| also ensure the screen is big enough, else revert to non-floating menu: |
| check y-height, and check widths (in case it was moved to after the other column) |
| {% endcomment %} |
| sidemenu_y_nonfloater=function(){ |
| if ($('#side-menu').outerHeight(true) + $('#header').outerHeight(true) + $('#footer').outerHeight(true) > window.innerHeight || |
| $('#side-menu').width() >= $('#content_container').width()/2) { |
| $('#side-menu').css('position', 'inherit'); |
| } else { |
| // restore if screen has grown |
| $('#side-menu').css('position', 'fixed'); |
| } |
| }; |
| $(sidemenu_y_nonfloater); |
| $(window).resize(sidemenu_y_nonfloater); |
| |
| {% comment %} |
| auto-advance "sections" in menu on scroll |
| {% endcomment %} |
| |
| var sideMenu = $("#side-menu"), |
| sideItems = sideMenu.find("a"), |
| // Anchors corresponding to menu items |
| scrollItems = sideItems.map(function(){ |
| var item = $(this).attr("section-target"); |
| if (item && item.length) { return item; } |
| }); |
| |
| var highlight_section_last_top = -1; |
| var highlight_section_completed = false; |
| |
| var highlight_section = function() { |
| // Get container scroll position |
| var highlight_section_new_top = $(this).scrollTop(); |
| if (highlight_section_new_top == highlight_section_last_top) return; |
| var highlight_section_new_bottom = highlight_section_new_top + $(window).height(); |
| var scroll_advancing = (highlight_section_new_top > highlight_section_last_top); |
| |
| var last_item = null, active_item = $("#side-menu a.section#active"); |
| |
| var found_top = false; |
| var displayable_items = scrollItems.map(function(itemI){ |
| item = $(scrollItems[itemI]); |
| if (item && item.length) { |
| if (highlight_section_last_top == -1 || !highlight_section_completed) { |
| // just opening page - take item matching hash, or otherwise the first item visible |
| if (item.selector === window.location.hash || (item.offset().top > highlight_section_new_top - 20 && !found_top)) { |
| found_top = true; |
| if (item.selector === window.location.hash && item.offset().top < highlight_section_new_top + 60) { |
| // because of our top header, we need to scroll 64px down from any link |
| $('html, body').animate({scrollTop: item.offset().top - 64}, 0); |
| } |
| return item; |
| } |
| } else if (scroll_advancing) { |
| // if scrolling advance, pick up a section when title starts before 1/3 height |
| if (item.offset().top < highlight_section_new_top + $(window).height()/3) |
| return item; |
| |
| // or if containing div is finished (usu the whole main content) |
| div_containing_item = item.closest("div"); |
| if (div_containing_item.offset().top + div_containing_item.height() < highlight_section_new_bottom + 15) |
| return item; |
| // or when next title is visible |
| if (last_item && item.offset().top < highlight_section_new_bottom + 15) |
| return last_item; |
| } else { |
| // if scrolling back, pick up a section as soon as the title is visible, |
| if (item.offset().top < highlight_section_new_top) |
| return item; |
| // or if title is before the 2/3 point |
| // (not sure about this, probably want also to have |
| // "AND the id.top is <= displayable_itemsrent_active_it.top" so we don't jump FORWARD a section |
| // when scrolling BACK, with lots of tiny sections) |
| if ((item.offset().top < highlight_section_new_top + 2*$(window).height()/3) |
| && (!active_item || !active_item.offset() || active_item.offset().top >= item.offset().top)) |
| return item; |
| |
| } |
| last_item = item; |
| } |
| }); |
| if (!highlight_section_completed && document.readyState === "complete") { |
| highlight_section_completed = true; |
| } |
| if (!displayable_items.length) { |
| $("#side-menu a.section").removeClass("active"); |
| } else { |
| displayable_items = displayable_items[displayable_items.length-1]; |
| var id = displayable_items && displayable_items.length ? displayable_items[0].id : ""; |
| // Set/remove active class |
| new_active = $("#side-menu a.section").filter("[section-target='#"+id+"']"); |
| if (new_active.hasClass("active")) { |
| // nothing needed |
| } else { |
| $("#side-menu a.section").removeClass("active"); |
| $("#side-menu a.section").filter("[section-target='#"+id+"']").addClass("active"); |
| } |
| } |
| |
| highlight_section_last_top = highlight_section_new_top; |
| }; |
| var highlight_new_section = function() { |
| highlight_section_completed = false; |
| highlight_section_last_top = -1; |
| highlight_section(); |
| } |
| |
| $(window).scroll(highlight_section); |
| $(highlight_new_section); |
| |
| // detect link change - courtesy http://www.bennadel.com/blog/1520-binding-events-to-non-dom-objects-with-jquery.htm |
| |
| // Default to the current location. |
| var strLocation = window.location.href; |
| var strHash = window.location.hash; |
| var strPrevLocation = ""; |
| var strPrevHash = ""; |
| |
| // This is how often we will be checkint for |
| // changes on the location. |
| var intIntervalTime = 100; |
| |
| // This method removes the pound from the hash. |
| var fnCleanHash = function( strHash ){ |
| return( |
| strHash.substring( 1, strHash.length ) |
| ); |
| } |
| |
| // This will be the method that we use to check |
| // changes in the window location. |
| var fnCheckLocation = function(){ |
| // Check to see if the location has changed. |
| if (strLocation != window.location.href){ |
| |
| // Store the new and previous locations. |
| strPrevLocation = strLocation; |
| strPrevHash = strHash; |
| strLocation = window.location.href; |
| strHash = window.location.hash; |
| |
| // The location has changed. Trigger a |
| // change event on the location object, |
| // passing in the current and previous |
| // location values. |
| $( window.location ).trigger( |
| "change", |
| { |
| currentHref: strLocation, |
| currentHash: fnCleanHash( strHash ), |
| previousHref: strPrevLocation, |
| previousHash: fnCleanHash( strPrevHash ) |
| } |
| ); |
| |
| } |
| } |
| |
| // Set an interval to check the location changes. |
| setInterval( fnCheckLocation, intIntervalTime ); |
| |
| // and trigger highlight section on link change |
| $(window.location).bind("change", highlight_new_section); |
| })(jQuery); |
| |
| </script> |