<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="<% settings.charset %>">
  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
  <title><% title %></title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="<% request.uri_base %>/css/style.css">
  <link rel="stylesheet" href="<% request.uri_base %>/javascripts/jquery-ui-1.12.1.custom/jquery-ui.min.css">
  <script src="//code.jquery.com/jquery-2.1.4.min.js"></script>
  <script type="text/javascript">/* <![CDATA[ */
      !window.jQuery && document.write('<script type="text/javascript" src="<% request.uri_base %>/javascripts/jquery.js"><\/script>')
  /* ]]> */</script>
  <script src="/javascripts/jquery-ui-1.12.1.custom/jquery-ui.min.js"></script>
  <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js"></script>
</head>

<body>
    <% content %>
<div id="footer">
Powered by <a href="http://perldancer.org/">Dancer2</a> <% dancer_version %>
</div>

<script>

// set up some globals
var elems = $('.scrollspy');
var headers = {};
var headers_pos = [];
var current_active = $("#sidebar a:first");

// calc header element positions
function get_pos() {
  headers = {};
  headers_pos = [];
  elems.each(function(index){
    var pos = $(this).position().top - 100;

    var id = $(this).attr('id');
    pos_str = pos;
    headers[pos_str] = id;
    headers_pos.push(pos_str);
  });
  headers_pos.sort(function(a, b) {return a-b});
}


// Turn off autoscrolling when hovering over sidebar
var over;

// We sometimes want to force sidebar to seek current location
// when set to true
var seek = false;

// when true, used to suppress any unwanted activation of sidebar links when
// sliding sidebar in and out
var sidebar_change = false;

// toggle sidebar visibility
$('#sb-slider').click(function() {
  sidebar_change = true;
  speed = 400;
  $('#sidebar').toggle('slide', speed);
  $('#sb-slider').toggleClass('collapsed', speed);
  $('#sb-slider').toggleClass('expanded', speed);
  //if ($(window).width() > 599) {
    //$('#content').fadeTo(200, 0);
  //}

  // The width of the #content area will change when the sidebar is opened
  // and closed. This can create a drastic change the user sees in the viewport.
  // To compensate we do back of the envelope calculations to guess at where in the
  // content div to scroll to to minimize the change in content so the user
  // does not have to scroll to get back to where they were before closing or
  // opening the sidebar. This algorithm ususally gets us
  // with 10 pixels or so but there are layout factors that could throw it
  // further off. It works well enough.
  if ($(window).width() > 599) {
    var curr_height = $('#content').height();
		var distance_to_top_of_page = $(window).scrollTop(),
				content_div_distance_from_top_of_page = $('#content').offset().top ;
        content_div_scroll_distance = distance_to_top_of_page - content_div_distance_from_top_of_page;
    var href = current_active.attr('href');

    active_elem_distance_to_top_of_content_div = $('#content ' + href).position().top;
		distance_into_active_element = content_div_scroll_distance - active_elem_distance_to_top_of_content_div;
    over = false;
    $('#content').toggleClass('full', 1, 'linear', function() {
      get_pos();
      var new_curr_height = $('#content').height();
      var proportional_change = new_curr_height/curr_height;
		  var new_active_elem_distance_to_top_of_content_div = $('#content ' + href).position().top;
      var new_scroll_pos = new_active_elem_distance_to_top_of_content_div + (distance_into_active_element * proportional_change);
      var scroll_to = new_scroll_pos + content_div_distance_from_top_of_page;

      // add a 5 pixel fudge factor to try to ensure content near the top of
      // viewport remains in viewport
      if ($('#sb-slider').hasClass('collapsed')) {
        $(window).scrollTop( scroll_to + 5 );
      } else {
        $(window).scrollTop( scroll_to - 5 );
      }
    });
    //$('#content').fadeTo(500, 1);
  }
  sidebar_change = false;
  seek = true;
} );

$('#sidebar a').click(function() {
  $('#sidebar a').removeClass('active');
  $(this).addClass('active');
});

// set proper initial location of sidebar slider toggle
$(function() {
  if ($(window).width() < 599) {
    $('#sb-slider').addClass('collapsed');
  } else {
    $('#sb-slider').addClass('expanded');
  }
});

// needed to suppress autoscrolling when scrolling manually in sidebar.
// set to true when in sidebar except when we are actively sliding
// the sidebar in and out to prevent spurious link activation
$("#sidebar").hover(
  function() { if (!sidebar_change) { over = true } },
  function() { over = false; },
);

// init element positions
get_pos();

// recalc element positions when resized
$( window ).resize(function() {
  get_pos();

  // handle sidebar position when resizing window
  if ($(window).width() < 599) {
    if ($('#sb-slider').hasClass('expanded')) {
      $('#sidebar').css('display', 'inline-block');
      $('#sidebar-inner').css('display', 'block');
    }
  } else {
    if ($('#sb-slider').hasClass('collapsed')) {
      $('#content').addClass('full');
    }
  }

});

// call autoscroll feature very .030 seconds. Slower
// periodicity will increase menu snappiness but
// will degrade smoothness of menu animation effect.
window.setInterval(function(){
		autoscroll();
}, 30);

// scroll the table of contents automatically
// called periodically as set by window.setInterval function
function autoscroll() {
    // get out of here if we are hovering over the sidebar
    if (over == true) {
      return;
    }

    // figure out where we are
    var scrollTop = $(window).scrollTop(),
                    elementOffset = $('#content').offset().top,
		    distance = Math.abs(elementOffset - scrollTop);

    // get id of header section located near top of viewport
    var id;
    var last = $('#sidebar a:first').attr('href');
    headers_pos.forEach(function(index) {
      if (index > distance) {
        if (!id) {
          id = last;
          return;
        }
      } else {
        last = '#' + headers[index];
      }
    });
    if (!id) {
      id = last;
    }

    // get new jquery element and remove active class from last active element
    var navElem = $('a[href="' + id + '"]');
    navElem.addClass('active', 300);

    if (!current_active.is(navElem) || seek == true) {
      if (seek != true) {
        current_active.removeClass('active', 300);
      } else {
        $('#sidebar a').removeClass('active', 100);
        current_active.addClass('active', 300);
      }
      seek = false;
    } else {
      return;
    }
    current_active = navElem;

    // do the scrolling
    var dft = navElem[0].getBoundingClientRect().top; // distance from top of viewport
    var s = $('#sidebar');
    if (dft > s.innerHeight() * .5 || dft < s.scrollTop() ) {
      $('#sidebar').animate({ scrollTop: navElem.offset().top - s.offset().top + s.scrollTop() - s.innerHeight()/2 },
				100,
     );
   }
}

// cargo-culted code for smooth scrolling in content area
$(function() {
$('a[href*="#"]')
  // Remove links that don't actually link to anything
  .not('[href="#"]')
  .not('[href="#0"]')
  .click(function(event) {
    // On-page links
    if (
      location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '')
      &&
      location.hostname == this.hostname
    ) {
      // Figure out element to scroll to
      var target = $(this.hash);
      target = target.length ? target : $('[id=' + this.hash.slice(1) + ']');
      // Does a scroll target exist?
      if (target.length) {
        // Only prevent default if animation is actually gonna happen
        event.preventDefault();
        $('html, body').animate({
          scrollTop: target.offset().top
        }, 300, function() {
          // Callback after animation
          // Must change focus!
          var $target = $(target);
          $target.focus();
          if ($target.is(":focus")) { // Checking if the target was focused
            return false;
          } else {
            $target.attr('tabindex','-1'); // Adding tabindex for elements not focusable
            $target.focus(); // Set focus again
          };
        });
      }
    }
  });
});


</script>
</body>
</html>