<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require bootstrap-sprockets
//= require jquery_ujs
//= require turbolinks
//= require_tree .

$(function() {
  $('.hero').animate({ height: '450px', opacity: '1'  }, 1000, 'linear');
});

$(document).ready(function(){
  $(window).scroll(function(){
    $(".taller-container").each( function(i){
      var bottom_of_object = $(this).offset().top + $(this).outerHeight();
      var bottom_of_window = $(window).scrollTop() + $(window).height();

      if (bottom_of_window > bottom_of_object){
        $(this).animate({'opacity': '1'}, 700);
      }
    });
  });
});
<commit_msg>further tweaked jquery animations<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require bootstrap-sprockets
//= require jquery_ujs
//= require turbolinks
//= require_tree .

$(function() {
  $('.hero').animate({ height: '450px', opacity: '1'  }, { duration: 1200, easing: 'linear'});
});

$(document).ready(function(){
  $(window).scroll(function(){
    $(".taller-container").each( function(i){
      var bottom_of_object = $(this).offset().top + $(this).outerHeight();
      var bottom_of_window = $(window).scrollTop() + $(window).height();

      if (bottom_of_window > bottom_of_object){
        $(this).animate({'opacity': '1'}, 700);
      }
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Application entry point.
 */
require([
  'jquery',
  'underscore',
  'Class',
  'backbone',
  '_string',
  'home/views/sliderView',
  'home/views/launchCounter',
  'views/SourceWindowView',
  'views/SidebarNavView'
], function($, _, Class, Backbone, _string, sliderView, LaunchCounterView, SourceWindowView, SidebarNavView) {

  'use strict';

  var HomePage = Class.extend({

    $el: $('body'),

    init: function() {
      this._initViews();
    },

    /**
     * Initialize the map by starting the history.
     */
    _initApp: function() {
      if (!Backbone.History.started) {
        Backbone.history.start({pushState: true});
      }
    },

    /**
     * Initialize Application Views.
     * CAUTION: Don't change the order of initanciations if
     * you are not completely sure.
     */
    _initViews: function() {
      new SourceWindowView();
      new LaunchCounterView();
      new sliderView();
      new SidebarNavView();
    }

  });

  new HomePage();

});
<commit_msg>and removed all calls to that view. The launcScreen one<commit_after>/**
 * Application entry point.
 */
require([
  'jquery',
  'underscore',
  'Class',
  'backbone',
  '_string',
  'home/views/sliderView',
  'views/SourceWindowView',
  'views/SidebarNavView'
], function($, _, Class, Backbone, _string, sliderView, SourceWindowView, SidebarNavView) {

  'use strict';

  var HomePage = Class.extend({

    $el: $('body'),

    init: function() {
      this._initViews();
    },

    /**
     * Initialize the map by starting the history.
     */
    _initApp: function() {
      if (!Backbone.History.started) {
        Backbone.history.start({pushState: true});
      }
    },

    /**
     * Initialize Application Views.
     * CAUTION: Don't change the order of initanciations if
     * you are not completely sure.
     */
    _initViews: function() {
      new SourceWindowView();
      new sliderView();
      new SidebarNavView();
    }

  });

  new HomePage();

});
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
$(document).ready( function(){

	$('#form_nav').hide();

	$('#browse').on("click", function(){
		event.preventDefault();
		$('#form_nav').show();
		$('#browse').hide();
	});

	$('.appendTrack').on("click",function(){
		$('.track_divs').append("
English

<button class='timeButton'>Get timestamps</button>
");

	// 	$('#play').on("click", function(){
	// 	$('#play').replaceWith( "

 ");
	// 	$('#pause').on("click", function(){
	// 	$('#pause').replaceWith( "

");
	// 	});
	// });
	});

	$('.track_divs').on("click", ".timeButton", function(){
		$(this).parent().children('.post-it').each(function(){
			console.log(this.style.left);
			console.log($(this).children(".content").text());
		});
	});

	$('#totalDuration').hide();
	console.log("hello");
	$('#play').on('click', function(){
	$('li #totalDuration').show();
	});

	$('.track_divs').on('dblclick', ".tracks_box", function(event){
	  if (event.target.className == "tracks_box") {
	    $(this).append( buildPostIt(event) );
	  }
	  $('.post-it').draggable({ handle: ".header", containment: "parent" });
	  $('.remove_note').on('click', function(){
	    $(this).parent().parent().remove();
	  });
	});
});

function getStamps() {
  var stamps = {};
  console.log(this);
  $($(this).parent().children()).each(function() {
  	console.log(this);
    // var leftVal = $(this).css('left');
    // var sentence = $(this).html();
    // stamps["time"] = leftVal;
    // stamps["sentence"] = sentence;

    // console.log(stamps['time']);
    // console.log(stamps['sentence']);
  });
}

<commit_msg>resizable working<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
$(document).ready( function(){

	$('#form_nav').hide();

	$('#browse').on("click", function(){
		event.preventDefault();
		$('#form_nav').show();
		$('#browse').hide();
	});

	$('.appendTrack').on("click",function(){
		$('.track_divs').append("
English

<button class='timeButton'>Get timestamps</button>
");

	// 	$('#play').on("click", function(){
	// 	$('#play').replaceWith( "

 ");
	// 	$('#pause').on("click", function(){
	// 	$('#pause').replaceWith( "

");
	// 	});
	// });
	});

	$('.track_divs').on("click", ".timeButton", function(){
		$(this).parent().children('.post-it').each(function(){
			console.log(this.style.left);
			console.log($(this).children(".content").text());
		});
	});

	$('#totalDuration').hide();
	console.log("hello");
	$('#play').on('click', function(){
	$('li #totalDuration').show();
	});

	$('.track_divs').on('dblclick', ".tracks_box", function(event){
	  if (event.target.className == "tracks_box") {
	    $(this).append( buildPostIt(event) );
	  }
	  $('.post-it').draggable({ handle: ".header", containment: "parent" }).resizable({containment:"parent"});
	  $('.remove_note').on('click', function(){
	    $(this).parent().parent().remove();
	  });
	});
});

function getStamps() {
  var stamps = {};
  console.log(this);
  $($(this).parent().children()).each(function() {
  	console.log(this);
    // var leftVal = $(this).css('left');
    // var sentence = $(this).html();
    // stamps["time"] = leftVal;
    // stamps["sentence"] = sentence;

    // console.log(stamps['time']);
    // console.log(stamps['sentence']);
  });
}

<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
// http://getbootstrap.com/customize/ with only Affix and Scrollspy.
//
//= require bootstrap.min.js
//= require jed.js

var i18n = new Jed({});

/**
 * Translates strings.
 *
 * @param {String} msgid A string
 * @param {Object} options Replacement fields
 * @return {String} Returns the translated string
 */
function _(msgid, options) {
  var message = i18n.gettext(msgid);
  if (options == null) {
    return message;
  }
  else {
    return Jed.sprintf(message, options);
  }
}

/**
 * Formats a number with a specified number of significant digits.
 *
 * @param {Float} number A number
 * @param {Float} precision The number of significant digits
 * @return {String} Returns the number with a specified number of significant digits
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
 */
function number_to_rounded(number, precision) {
  var digits = number ? Math.floor(Math.log(Math.abs(number) / Math.log(10)) + 1) : 1
    , multiplier = Math.pow(10, digits - precision);
  return Math.round(number / multiplier) * multiplier;
}

/**
 * Formats a number a currency string.
 *
 * @param {Float} number A number
 * @param {Float} precision The number of significant digits
 * @return {String} Returns the number as a currency string
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb
 */
function number_to_currency(number, precision) {
  var parts = number_to_rounded(number, precision).toString().split('.');
  parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + _('number.currency.format.delimiter'));
  return _('number.currency.format.format').replace('%n', parts.join(_('number.currency.format.separator'))).replace('%u', _('number.currency.format.unit'));
}

/**
 * Formats a number a percentage string.
 *
 * @param {Float} number A number
 * @return {String} Returns the number as a percentage string
 */
function number_to_percentage(number) {
  var parts = number.toString().split('.');
  parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + _('number.percentage.format.delimiter'));
  return _('number.percentage.format.format').replace('%n', parts.join(_('number.format.separator')));
}

/**
 * Collects variable values to pass to `solution()`.
 *
 * @return {Object} Returns each variable's value
 */
function variables() {
  var variables = {};
  $('input[type="range"]').each(function () {
    var $this = $(this);
    variables[$this.attr('id')] = parseFloat($this.val());
  });
  return variables;
}

$.getJSON('/admin/translations/export/?locale=' + $('html').attr('lang')).done(function (messages) {
  // Load the translations via AJAX.
  i18n = new Jed({locale_data: {messages: messages}});
}).always(function () {
  $(function () {
    // Scrollspy
    $(document.body).scrollspy({
      target: '#sidebar'
    });
    $(window).on('load', function () {
      $(document.body).scrollspy('refresh');
    });

    // Affix
    setTimeout(function () {
      $('#sidebar').affix({
        offset: {
          top: function () {
            return (this.top = $('#sidebar').offset().top);
          }
        , bottom: function () {
            return (this.bottom = $('footer').outerHeight(true) + 75);
          }
        }
      });
    }, 100);

    // Popover
    $('a[data-toggle="popover"]').popover().click(function (event) {
      event.preventDefault();
    });

    $('input[type="range"]').change(function () {
      // Display a message.
      var message = ''
        , css_class = ''
        , number = solution(variables())
        , options = {
            number: number_to_currency(Math.round(Math.abs(number / 1000000)), 2)
          , percentage: number_to_percentage(Math.abs(number / total_revenue * 100).toFixed(2))
          };

      if (number > 0) {
        message = _('Your changes would increase revenues by %(number)s million, or %(percentage)s of total revenues.', options);
        css_class = 'alert-info';
      }
      else if (number < 0) {
        message = _('Your changes would decrease revenues by %(number)s million, or %(percentage)s of total revenues.', options);
        css_class = 'alert-warning';
      }

      if (message) {
        $('#impacts-summary,#impacts-sidebar').html($('
' + message + '
'));
        // Pulsate the alert to draw attention.
        $('#impacts-sidebar').animate({opacity: 0}, 'fast').animate({opacity: 1}, 'fast');
      }
      else {
        $('#impacts-summary,#impacts-sidebar').empty();
      }
    }).each(function () {
      // Reset the simulator on refresh.
      var $this = $(this);
      $this.val($this.attr('value'));
    });
  });
});
<commit_msg>fix parentheses<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
// about supported directives.
//
// http://getbootstrap.com/customize/ with only Affix and Scrollspy.
//
//= require bootstrap.min.js
//= require jed.js

var i18n = new Jed({});

/**
 * Translates strings.
 *
 * @param {String} msgid A string
 * @param {Object} options Replacement fields
 * @return {String} Returns the translated string
 */
function _(msgid, options) {
  var message = i18n.gettext(msgid);
  if (options == null) {
    return message;
  }
  else {
    return Jed.sprintf(message, options);
  }
}

/**
 * Formats a number with a specified number of significant digits.
 *
 * @param {Float} number A number
 * @param {Float} precision The number of significant digits
 * @return {String} Returns the number with a specified number of significant digits
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_rounded_converter.rb
 */
function number_to_rounded(number, precision) {
  var digits = number ? Math.floor(Math.log(Math.abs(number)) / Math.log(10) + 1) : 1
    , multiplier = Math.pow(10, digits - precision);
  return Math.round(number / multiplier) * multiplier;
}

/**
 * Formats a number a currency string.
 *
 * @param {Float} number A number
 * @param {Float} precision The number of significant digits
 * @return {String} Returns the number as a currency string
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_currency_converter.rb
 * @see https://github.com/rails/rails/blob/master/activesupport/lib/active_support/number_helper/number_to_delimited_converter.rb
 */
function number_to_currency(number, precision) {
  var parts = number_to_rounded(number, precision).toString().split('.');
  parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + _('number.currency.format.delimiter'));
  return _('number.currency.format.format').replace('%n', parts.join(_('number.currency.format.separator'))).replace('%u', _('number.currency.format.unit'));
}

/**
 * Formats a number a percentage string.
 *
 * @param {Float} number A number
 * @return {String} Returns the number as a percentage string
 */
function number_to_percentage(number) {
  var parts = number.toString().split('.');
  parts[0] = parts[0].replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1' + _('number.percentage.format.delimiter'));
  return _('number.percentage.format.format').replace('%n', parts.join(_('number.format.separator')));
}

/**
 * Collects variable values to pass to `solution()`.
 *
 * @return {Object} Returns each variable's value
 */
function variables() {
  var variables = {};
  $('input[type="range"]').each(function () {
    var $this = $(this);
    variables[$this.attr('id')] = parseFloat($this.val());
  });
  return variables;
}

$.getJSON('/admin/translations/export/?locale=' + $('html').attr('lang')).done(function (messages) {
  // Load the translations via AJAX.
  i18n = new Jed({locale_data: {messages: messages}});
}).always(function () {
  $(function () {
    // Scrollspy
    $(document.body).scrollspy({
      target: '#sidebar'
    });
    $(window).on('load', function () {
      $(document.body).scrollspy('refresh');
    });

    // Affix
    setTimeout(function () {
      $('#sidebar').affix({
        offset: {
          top: function () {
            return (this.top = $('#sidebar').offset().top);
          }
        , bottom: function () {
            return (this.bottom = $('footer').outerHeight(true) + 75);
          }
        }
      });
    }, 100);

    // Popover
    $('a[data-toggle="popover"]').popover().click(function (event) {
      event.preventDefault();
    });

    $('input[type="range"]').change(function () {
      // Display a message.
      var message = ''
        , css_class = ''
        , number = solution(variables())
        , options = {
            number: number_to_currency(Math.round(Math.abs(number / 1000000)), 2)
          , percentage: number_to_percentage(Math.abs(number / total_revenue * 100).toFixed(2))
          };

      if (number > 0) {
        message = _('Your changes would increase revenues by %(number)s million, or %(percentage)s of total revenues.', options);
        css_class = 'alert-info';
      }
      else if (number < 0) {
        message = _('Your changes would decrease revenues by %(number)s million, or %(percentage)s of total revenues.', options);
        css_class = 'alert-warning';
      }

      if (message) {
        $('#impacts-summary,#impacts-sidebar').html($('
' + message + '
'));
        // Pulsate the alert to draw attention.
        $('#impacts-sidebar').animate({opacity: 0}, 'fast').animate({opacity: 1}, 'fast');
      }
      else {
        $('#impacts-summary,#impacts-sidebar').empty();
      }
    }).each(function () {
      // Reset the simulator on refresh.
      var $this = $(this);
      $this.val($this.attr('value'));
    });
  });
});
<|endoftext|>


<commit_before>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require turbolinks
//= require_tree .
<commit_msg>remove turbolinks from app.js<commit_after>// This is a manifest file that'll be compiled into application.js, which will include all the files
// listed below.
//
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
//
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
// compiled file.
//
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
// about supported directives.
//
//= require jquery
//= require jquery_ujs
//= require_tree .
<|endoftext|>


<commit_before>(function() {
  function renderComments(lineComments) {
    $(".file-pane").each(function(index) {
      var theseComments = lineComments[index] || {};
      if (theseComments["noCommentsFor"]) return;
      // Standard text-files get line comments
      $(this).find(".CodeMirror").each(function(_, cm) {
        renderLineComments(cm.CodeMirror, theseComments);
      });
      // Nonstandard files (jars, overly-large files) get page comments
      $(this).find(".pageContainer").each(function(pageNum, pageContainer) {
        renderPageComments(pageNum + 1, pageContainer, theseComments);
      });
      // Pdfs get page and region comments
      $(this).find("div[id^='pdf_']").each(function(_, pdfDiv) {
        var pageRendered = [];
        $(pdfDiv).pdfViewer({
          pageContainerReady: function(_, details) {
            renderPageComments(details.pageNum, details.pageContainer, theseComments);
          },
          pageReady: function(_, details) {
            if (pageRendered[details.pageNum]) return;
            pageRendered[details.pageNum] = true;
            renderRegionComments(details.pageNum, details.container.regionComments, theseComments);
          }
        });
      });
    });
  }
  window.renderComments = renderComments;
  function renderLineComments(cm, theseComments) {
    cm.operation(function() {
      Object.keys(theseComments).forEach(function(gradeId, _) {
        var commentsByGrade = theseComments[gradeId] || {};
        var type = commentsByGrade.type;
        Object.keys(commentsByGrade).forEach(function(line, _) {
          if (line === "type") return;
          var commentsOnLine = commentsByGrade[line] || {};
          commentsOnLine.forEach(function(comment, _) {
            renderLineComment(cm, gradeId, type, line, comment);
          });
        });
      });
    });
  }
  function renderPageComments(pageNum, pageContainer, theseComments) {
    var pageComments = $(pageContainer).find(".pageComments");
    Object.keys(theseComments).forEach(function(gradeId, _) {
      var commentsByGrade = theseComments[gradeId] || {};
      var type = commentsByGrade.type;
      var commentsForPage = commentsByGrade[pageNum] || [];
      commentsForPage.forEach(function(comment, _) {
        if (!comment.info) {
          renderPageComment(pageComments[0], gradeId, type, pageNum, comment);
        }
      });
    });
  }
  function renderRegionComments(pageNum, regionComments, theseComments) {
    Object.keys(theseComments).forEach(function(gradeId, _) {
      var commentsByGrade = theseComments[gradeId] || {};
      var type = commentsByGrade.type;
      var commentsForPage = commentsByGrade[pageNum] || [];
      commentsForPage.forEach(function(comment, _) {
        if (comment.info) {
          renderRegionComment(regionComments[0], gradeId, type, pageNum, comment);
        }
      });
    });
  }

  function renderPageComment(pc, gradeId, type, line, comment) {
    var widget = $("<div>").lineCommentView({
      gradeId,
      type,
      line,
      severity: comment.severity,
      label: comment.label,
      author: comment.author,
      deduction: comment.deduction,
      title: comment.title,
      comment: comment.comment,
      suppressed: comment.suppressed
    });
    $(pc).append(widget);
  }
  window.renderPageComment = renderPageComment;
  function renderRegionComment(rc, gradeId, type, line, comment) {
    var pdfViewer = $(rc).closest(".pdfDisplay").pdfViewer("instance");
    var $page = $(rc).find(".page");
    var infoJson;
    if (comment.info) {
      try {
        infoJson = JSON.parse(comment.info);
      } catch(e) {
        infoJson = undefined;
      }
    }
    if (infoJson && infoJson.type === "area") {
      pdfViewer.createAreaComment($page, false, {
        gradeId,
        left: infoJson.left,
        top: infoJson.top,
        width: infoJson.width,
        height: infoJson.height,
        dimensions: infoJson.dimensions,
        type,
        line,
        label: comment.label,
        id: comment.id,
        severity: comment.severity,
        label: comment.label,
        author: comment.author,
        deduction: comment.deduction,
        title: comment.title,
        comment: comment.comment,
        suppressed: comment.suppressed
      });
    }
  }
  window.renderRegionComment = renderRegionComment;

  function renderLineComment(cm, gradeId, type, line, comment) {
    var widget = $("<div>").lineCommentView({
      gradeId,
      type,
      line,
      severity: comment.severity,
      label: comment.label,
      author: comment.author,
      deduction: comment.deduction,
      title: comment.title,
      comment: comment.comment,
      suppressed: comment.suppressed
    });
    cm.addLineWidget(parseInt(line) - 1, widget[0], {coverGutter: false, noHScroll: true});
  }
  window.renderLineComment = renderLineComment;

  function init_datetime() {
    $('.datetime-picker').datetimepicker({
      sideBySide: true,
      format: "YYYY/MM/DD h:mm A",
      defaultDate: undefined
    });
  }

  var max_grader_order;
  const extraCreditWarning = "This assignment is already marked as extra-credit.  Only mark this grader as extra credit if you truly mean to have extra credit on top of extra credit.";
  function on_add_grader(evt, el) {
    el.find(".spinner").each(function(_ii, div) {
      activateSpinner(div);
    });
    var newToggles = el.find("input[data-toggle='toggle']");
    newToggles.bootstrapToggle();
    newToggles = newToggles.parent("div[data-toggle='toggle']");
    newToggles.attr('title', extraCreditWarning);
    newToggles.tooltip();
    if ($("input[data-toggle='toggle'][name='assignment[extra_credit]']").prop('checked')) {
      newToggles.tooltip('enable');
    } else {
      newToggles.tooltip('disable');
    }
    el.find("input[name$='[order]']").val(++max_grader_order);
    el.find(".file-picker").each(function(index) { activate_file_picker($(this)); });
    form_tabs_init_all(el);
  }

  function on_add_interlock(evt, el) {
    var relAssignment = el.find("select[name$='[related_assignment_id]']");
    el.find("select[name$='[constraint]']").change(function(){
      if (this.value == "check_section_toggles") {
        $(relAssignment).hide();
      } else {
        $(relAssignment).show();
      }
    });
  }

  function activate_file_picker($e) {
    $e.find(".custom-file").change(function() {
      var label = $(this).val().replace(/\\/g, '/').replace(/.*\//, '');
      $e.find(".current_file").text("New file: " + label);
      $e.find(".remove-custom-file").prop('disabled', false).removeClass("btn-default").addClass("btn-warning");
      $e.find("input.remove-custom-file").val('');
    });
    $e.find(".remove-custom-file").click(function() {
      $e.find("input.custom-file").replaceWith(
        $e.find("input.custom-file").clone(true));
      $(this).prop('disabled', true).addClass("btn-default").removeClass("btn-warning");
      $e.find(".current_file").text("New file: <nothing>");
      $e.find("input.remove-custom-file").val('remove');
    });
  }

  function form_init() {
    init_datetime();

    max_grader_order =
      Math.max(0,
               Math.max.apply(null,
                              $("input[name$='[order]']").map(function() { return $(this).val() }).toArray()));

    $('.graders-list').on('cocoon:after-insert', on_add_grader);
    $('.interlocks-list').on('cocoon:after-insert', on_add_interlock);

    $('.spinner').each(function (_ii, div) {
      activateSpinner(div);
      if ($(div).find("input").prop("disabled")) {
        disableSpinner(div);
      }
    });

    $("#files-graders").sortable({
      placeholder: "ui-state-highlight",
      update: function(e, ui) {
        var orders = $("#files-graders input[name$='[order]']");
        orders.each(function(index, item) {
          $(item).val(++max_grader_order);
        });
      }
    });

    $("input[name='assignment[extra_credit]']").change(function() {
      var newToggles = $(".graders-list .tab-pane").map(function(_, e) { return $(e).data("bn.detached-tab"); });
      newToggles = $.map(newToggles, function(kids) { return $.map(kids, function(k) { return k; }); });
      newToggles = $(newToggles).find("div[data-toggle='toggle']");
      debugger
      if ($(this).prop('checked')) {
        newToggles.tooltip('enable');
        newToggles.find("input[data-toggle='toggle']").bootstrapToggle('off');
      } else {
        newToggles.tooltip('disable');
      }
    });

    $("form").submit(function(e) {
      var graderTypeInputs =
          $("li.grader").filter(function(index) {
            return $(this).find("input[id^='assignment_graders_'][id$='_destroy'][value='1']").length == 0;
          }).find("input[id$='_type']");
      debugger
      var graderTypes = graderTypeInputs.map(function() { return $(this).val().replace(/^.*_/, ""); });
      var asHash = Object.create(null);
      graderTypes.map(function() { asHash[this] = (asHash[this] || 0) + 1; });
      var prompt = "";
      for (var type in asHash) {
        if (asHash[type] > 1) {
          prompt += "\t" + asHash[type] + " of " + type + "\n";
        }
      }
      if (prompt !== "") {
        if (!confirm("Are you sure you intended to have multiple graders of the same type?\n" + prompt)) {
          e.preventDefault();
          return false;
        }
      }
      return true;
    });

    $(".file-picker").each(function(index) { activate_file_picker($(this)); });
  }

  function toggles_init() {
    $.each($('.toggle-wrapper'), function(index, toggleWrapper) {
      $(toggleWrapper).click(function(e) {
        e.stopPropagation(); // calling bootstrapToggle on the toggle itself fires the 'change' event, so the wrapper is necessary to change the toggle's value without firing the event
        var toggle = $(toggleWrapper).find('.submission-enabled-toggle')[0];
        var toggleId = toggle.id.split('-')[1];
        var data = {state: !toggle.checked}; // attemp to flip
        function complete(xhr, status) {
          if (xhr.status == 409) {
            alert("That section was toggled by another user. Toggles have been updated to match the current state.");
            $.each(xhr.responseJSON, function(index, newState) {
              var sel = '.submission-enabled-toggle#allow-' + newState.id;
              $(sel).bootstrapToggle(newState.state);
            });
          } else if (xhr.status == 200) {
            // successfully changed the state
            $(toggle).bootstrapToggle('toggle'); // display success to user
          } else {
            alert("Error (" + xhr.status + ") while trying to change section toggle.");
            toggle.bootstrapToggle('toggle'); // set it back because of the error
          }
        }
        var url = 'submission_enabled_toggles/' + toggleId + '/update';
        $.ajax({url: url, data: data, type: 'PATCH', complete: complete});
      });
    });
  }

  run_on_page("assignments/new", form_init);
  run_on_page("assignments/create", form_init);
  run_on_page("assignments/edit", form_init);
  run_on_page("assignments/update", form_init);
  run_on_page("assignments/show", toggles_init);
})();

/*
run_on_page "assignments/show", () ->
  inputs  = []
  by_user = {}

  find_inputs = () ->
    inputs = $(".grade-entry-box")

    by_user = {}
    inputs.each (ii, box) ->
      user_id = $(box).data("user-id")
      by_user[user_id] = ii

  focus_row = (row_number) ->
    next = inputs[row_number]
    if next
      $(next).focus()

  handle_arrow_keys = (event) ->
    user_id    = $(event.target).data("user-id")
    row_number = by_user[user_id]

    switch $.keyDecoder.parse(event)
      when "Up"
        focus_row(row_number - 1)

      when "Down"
        focus_row(row_number + 1)

  handle_form_send = (event) ->
    box = $(event.target).find(".grade-entry-box")[0]
    user_id = $(box).data("user-id")

    row_number = by_user[user_id]
    focus_row(row_number + 1)

  setup_handlers = () ->
    find_inputs()

    $(".grade-entry-box").off "keyup", handle_arrow_keys
    $(".grade-entry-box").on "keyup", handle_arrow_keys

    $(".sub-form").off "ajax:send", handle_form_send
    $(".sub-form").on "ajax:send", handle_form_send

  $(document).ajaxComplete () ->
    $('#ajax-status').text("ajax-status: done")
    setup_handlers()

  setup_handlers()
*/
<commit_msg>Fixes functioning of toggles<commit_after>(function() {
  function renderComments(lineComments) {
    $(".file-pane").each(function(index) {
      var theseComments = lineComments[index] || {};
      if (theseComments["noCommentsFor"]) return;
      // Standard text-files get line comments
      $(this).find(".CodeMirror").each(function(_, cm) {
        renderLineComments(cm.CodeMirror, theseComments);
      });
      // Nonstandard files (jars, overly-large files) get page comments
      $(this).find(".pageContainer").each(function(pageNum, pageContainer) {
        renderPageComments(pageNum + 1, pageContainer, theseComments);
      });
      // Pdfs get page and region comments
      $(this).find("div[id^='pdf_']").each(function(_, pdfDiv) {
        var pageRendered = [];
        $(pdfDiv).pdfViewer({
          pageContainerReady: function(_, details) {
            renderPageComments(details.pageNum, details.pageContainer, theseComments);
          },
          pageReady: function(_, details) {
            if (pageRendered[details.pageNum]) return;
            pageRendered[details.pageNum] = true;
            renderRegionComments(details.pageNum, details.container.regionComments, theseComments);
          }
        });
      });
    });
  }
  window.renderComments = renderComments;
  function renderLineComments(cm, theseComments) {
    cm.operation(function() {
      Object.keys(theseComments).forEach(function(gradeId, _) {
        var commentsByGrade = theseComments[gradeId] || {};
        var type = commentsByGrade.type;
        Object.keys(commentsByGrade).forEach(function(line, _) {
          if (line === "type") return;
          var commentsOnLine = commentsByGrade[line] || {};
          commentsOnLine.forEach(function(comment, _) {
            renderLineComment(cm, gradeId, type, line, comment);
          });
        });
      });
    });
  }
  function renderPageComments(pageNum, pageContainer, theseComments) {
    var pageComments = $(pageContainer).find(".pageComments");
    Object.keys(theseComments).forEach(function(gradeId, _) {
      var commentsByGrade = theseComments[gradeId] || {};
      var type = commentsByGrade.type;
      var commentsForPage = commentsByGrade[pageNum] || [];
      commentsForPage.forEach(function(comment, _) {
        if (!comment.info) {
          renderPageComment(pageComments[0], gradeId, type, pageNum, comment);
        }
      });
    });
  }
  function renderRegionComments(pageNum, regionComments, theseComments) {
    Object.keys(theseComments).forEach(function(gradeId, _) {
      var commentsByGrade = theseComments[gradeId] || {};
      var type = commentsByGrade.type;
      var commentsForPage = commentsByGrade[pageNum] || [];
      commentsForPage.forEach(function(comment, _) {
        if (comment.info) {
          renderRegionComment(regionComments[0], gradeId, type, pageNum, comment);
        }
      });
    });
  }

  function renderPageComment(pc, gradeId, type, line, comment) {
    var widget = $("<div>").lineCommentView({
      gradeId,
      type,
      line,
      severity: comment.severity,
      label: comment.label,
      author: comment.author,
      deduction: comment.deduction,
      title: comment.title,
      comment: comment.comment,
      suppressed: comment.suppressed
    });
    $(pc).append(widget);
  }
  window.renderPageComment = renderPageComment;
  function renderRegionComment(rc, gradeId, type, line, comment) {
    var pdfViewer = $(rc).closest(".pdfDisplay").pdfViewer("instance");
    var $page = $(rc).find(".page");
    var infoJson;
    if (comment.info) {
      try {
        infoJson = JSON.parse(comment.info);
      } catch(e) {
        infoJson = undefined;
      }
    }
    if (infoJson && infoJson.type === "area") {
      pdfViewer.createAreaComment($page, false, {
        gradeId,
        left: infoJson.left,
        top: infoJson.top,
        width: infoJson.width,
        height: infoJson.height,
        dimensions: infoJson.dimensions,
        type,
        line,
        label: comment.label,
        id: comment.id,
        severity: comment.severity,
        label: comment.label,
        author: comment.author,
        deduction: comment.deduction,
        title: comment.title,
        comment: comment.comment,
        suppressed: comment.suppressed
      });
    }
  }
  window.renderRegionComment = renderRegionComment;

  function renderLineComment(cm, gradeId, type, line, comment) {
    var widget = $("<div>").lineCommentView({
      gradeId,
      type,
      line,
      severity: comment.severity,
      label: comment.label,
      author: comment.author,
      deduction: comment.deduction,
      title: comment.title,
      comment: comment.comment,
      suppressed: comment.suppressed
    });
    cm.addLineWidget(parseInt(line) - 1, widget[0], {coverGutter: false, noHScroll: true});
  }
  window.renderLineComment = renderLineComment;

  function init_datetime() {
    $('.datetime-picker').datetimepicker({
      sideBySide: true,
      format: "YYYY/MM/DD h:mm A",
      defaultDate: undefined
    });
  }

  var max_grader_order;
  const extraCreditWarning = "This assignment is already marked as extra-credit.  Only mark this grader as extra credit if you truly mean to have extra credit on top of extra credit.";
  function on_add_grader(evt, el) {
    el.find(".spinner").each(function(_ii, div) {
      activateSpinner(div);
    });
    var newToggles = el.find("input[data-toggle='toggle']");
    newToggles.bootstrapToggle();
    newToggles = newToggles.parent("div[data-toggle='toggle']");
    newToggles.attr('title', extraCreditWarning);
    newToggles.tooltip();
    if ($("input[data-toggle='toggle'][name='assignment[extra_credit]']").prop('checked')) {
      newToggles.tooltip('enable');
    } else {
      newToggles.tooltip('disable');
    }
    el.find("input[name$='[order]']").val(++max_grader_order);
    el.find(".file-picker").each(function(index) { activate_file_picker($(this)); });
    form_tabs_init_all(el);
  }

  function on_add_interlock(evt, el) {
    var relAssignment = el.find("select[name$='[related_assignment_id]']");
    el.find("select[name$='[constraint]']").change(function(){
      if (this.value == "check_section_toggles") {
        $(relAssignment).hide();
      } else {
        $(relAssignment).show();
      }
    });
  }

  function activate_file_picker($e) {
    $e.find(".custom-file").change(function() {
      var label = $(this).val().replace(/\\/g, '/').replace(/.*\//, '');
      $e.find(".current_file").text("New file: " + label);
      $e.find(".remove-custom-file").prop('disabled', false).removeClass("btn-default").addClass("btn-warning");
      $e.find("input.remove-custom-file").val('');
    });
    $e.find(".remove-custom-file").click(function() {
      $e.find("input.custom-file").replaceWith(
        $e.find("input.custom-file").clone(true));
      $(this).prop('disabled', true).addClass("btn-default").removeClass("btn-warning");
      $e.find(".current_file").text("New file: <nothing>");
      $e.find("input.remove-custom-file").val('remove');
    });
  }

  function form_init() {
    init_datetime();

    max_grader_order =
      Math.max(0,
               Math.max.apply(null,
                              $("input[name$='[order]']").map(function() { return $(this).val() }).toArray()));

    $('.graders-list').on('cocoon:after-insert', on_add_grader);
    $('.interlocks-list').on('cocoon:after-insert', on_add_interlock);

    $('.spinner').each(function (_ii, div) {
      activateSpinner(div);
      if ($(div).find("input").prop("disabled")) {
        disableSpinner(div);
      }
    });

    $("#files-graders").sortable({
      placeholder: "ui-state-highlight",
      update: function(e, ui) {
        var orders = $("#files-graders input[name$='[order]']");
        orders.each(function(index, item) {
          $(item).val(++max_grader_order);
        });
      }
    });

    $("input[name='assignment[extra_credit]']").change(function() {
      var newToggles = $(".graders-list .tab-pane").map(function(_, e) { return $(e).data("bn.detached-tab"); });
      newToggles = $.map(newToggles, function(kids) { return $.map(kids, function(k) { return k; }); });
      newToggles = $(newToggles).find("div[data-toggle='toggle']");
      debugger
      if ($(this).prop('checked')) {
        newToggles.tooltip('enable');
        newToggles.find("input[data-toggle='toggle']").bootstrapToggle('off');
      } else {
        newToggles.tooltip('disable');
      }
    });

    $("form").submit(function(e) {
      var graderTypeInputs =
          $("li.grader").filter(function(index) {
            return $(this).find("input[id^='assignment_graders_'][id$='_destroy'][value='1']").length == 0;
          }).find("input[id$='_type']");
      debugger
      var graderTypes = graderTypeInputs.map(function() { return $(this).val().replace(/^.*_/, ""); });
      var asHash = Object.create(null);
      graderTypes.map(function() { asHash[this] = (asHash[this] || 0) + 1; });
      var prompt = "";
      for (var type in asHash) {
        if (asHash[type] > 1) {
          prompt += "\t" + asHash[type] + " of " + type + "\n";
        }
      }
      if (prompt !== "") {
        if (!confirm("Are you sure you intended to have multiple graders of the same type?\n" + prompt)) {
          e.preventDefault();
          return false;
        }
      }
      return true;
    });

    $(".file-picker").each(function(index) { activate_file_picker($(this)); });
  }

  function toggles_init() {
    $.each($('.toggle-wrapper'), function(index, toggleWrapper) {
      $(toggleWrapper).click(function(e) {
        e.stopPropagation(); // calling bootstrapToggle on the toggle itself fires the 'change' event, so the wrapper is necessary to change the toggle's value without firing the event
        var toggle = $(toggleWrapper).find('.submission-enabled-toggle')[0];
        var toggleId = toggle.id.split('-')[1];
        var data = {state: !toggle.checked}; // attemp to flip
        function complete(xhr, status) {
          if (xhr.status == 409) {
            alert("That section was toggled by another user. Toggles have been updated to match the current state.");
            $.each(xhr.responseJSON, function(index, newState) {
              var sel = '.submission-enabled-toggle#allow-' + newState.id;
              $(sel).bootstrapToggle(newState.state);
            });
          } else if (xhr.status == 200) {
            // successfully changed the state
            $(toggle).bootstrapToggle('toggle'); // display success to user
          } else {
            alert("Error (" + xhr.status + ") while trying to change section toggle.");
            toggle.bootstrapToggle('toggle'); // set it back because of the error
          }
        }
        var url = window.location.href + '/submission_enabled_toggles/' + toggleId + '/update';
        $.ajax({url: url, data: data, type: 'PATCH', complete: complete});
      });
    });
  }

  run_on_page("assignments/new", form_init);
  run_on_page("assignments/create", form_init);
  run_on_page("assignments/edit", form_init);
  run_on_page("assignments/update", form_init);
  run_on_page("assignments/show", toggles_init);
})();

/*
run_on_page "assignments/show", () ->
  inputs  = []
  by_user = {}

  find_inputs = () ->
    inputs = $(".grade-entry-box")

    by_user = {}
    inputs.each (ii, box) ->
      user_id = $(box).data("user-id")
      by_user[user_id] = ii

  focus_row = (row_number) ->
    next = inputs[row_number]
    if next
      $(next).focus()

  handle_arrow_keys = (event) ->
    user_id    = $(event.target).data("user-id")
    row_number = by_user[user_id]

    switch $.keyDecoder.parse(event)
      when "Up"
        focus_row(row_number - 1)

      when "Down"
        focus_row(row_number + 1)

  handle_form_send = (event) ->
    box = $(event.target).find(".grade-entry-box")[0]
    user_id = $(box).data("user-id")

    row_number = by_user[user_id]
    focus_row(row_number + 1)

  setup_handlers = () ->
    find_inputs()

    $(".grade-entry-box").off "keyup", handle_arrow_keys
    $(".grade-entry-box").on "keyup", handle_arrow_keys

    $(".sub-form").off "ajax:send", handle_form_send
    $(".sub-form").on "ajax:send", handle_form_send

  $(document).ajaxComplete () ->
    $('#ajax-status').text("ajax-status: done")
    setup_handlers()

  setup_handlers()
*/
<|endoftext|>


<commit_before>$(document).ready(function() {

  var sidebar = $('.sidebar');
  if (sidebar.length > 0) {

    var sidebar_top = sidebar.position().top,
        document_height = $(document).height(),
        nav_height = $('.top-bar').outerHeight() + $('.sub-navi').outerHeight() + $('.breadcrumbs').outerHeight();

    function set_height(height) {
      sidebar.height(height);
      $('.image img', '.sidebar').css({
        'max-height': (height / 100) * 80
      }).fadeIn();
    };

    $(document).scroll(function() {
      var scroll_top = $(document).scrollTop() + $('.top-bar').outerHeight();
      if (scroll_top >= sidebar_top) {
        $('.sidebar').css('position', 'fixed');
        $('.sidebar').css('right', '0px');
        $('.sidebar').css('top', $('.top-bar').outerHeight());
        set_height(document_height);
      } else if (scroll_top < sidebar_top){
        $('.sidebar').css('position', 'static');
        set_height(document_height - nav_height);
      }
    });

    set_height(document_height - nav_height);

  }

});
<commit_msg>correct resize of content image<commit_after>$(document).ready(function() {

  var sidebar = $('.sidebar');
  if (sidebar.length > 0) {

    var sidebar_top = sidebar.position().top,
        document_height = $(document).height(),
        nav_height = $('.top-bar').outerHeight() + $('.sub-navi').outerHeight() + $('.breadcrumbs').outerHeight();

    function set_height(height) {
      sidebar.height(height);
    };

    function set_image_width(width) {
      $('.image img', '.sidebar').css({
        'max-width': width
      }).fadeIn();
    };

    $(document).scroll(function() {
      var scroll_top = $(document).scrollTop() + $('.top-bar').outerHeight();
      if (scroll_top >= sidebar_top) {
        $('.sidebar').css('position', 'fixed');
        $('.sidebar').css('right', '0px');
        $('.sidebar').css('top', $('.top-bar').outerHeight());
        set_height(document_height);
      } else if (scroll_top < sidebar_top){
        $('.sidebar').css('position', 'static');
        set_height(document_height - nav_height);
      }
    });

    set_height(document_height - nav_height);
    set_image_width($('.sidebar').width());

    $(window).resize(function() {
      set_image_width($('.sidebar').width());
    });

  }

});
<|endoftext|>


<commit_before>/** Component for showing the queried index data as a set of graphs */

modulejs.define( "graphs-view", [
  "lib/lodash",
  "lib/jquery",
  "lib/d3",
  "lib/util",
  "preferences",
  "aspects"
], function(
  _,
  $,
  D3,
  Util,
  Preferences,
  Aspects
) {
  "use strict";

  var GraphView = function() {
    this.preferences = new Preferences();
    this.graphConf = {};
  };

  var SERIES_MARKER = {
    "":               "circle",
    "Detached":       "diamond",
    "SemiDetached":   "square",
    "Terraced":       "triangle-down",
    "FlatMaisonette": "triangle-up"
  };

  var GRAPHS_OPTIONS = {
    averagePrice: {
      cssClass: "average-price",
      ticksCount: 5,
      yDomain: "",
      graphType: "lineAndPoints"
    },
    housePriceIndex: {
      cssClass: "house-price-index",
      ticksCount: 5,
      yDomain: "",
      graphType: "lineAndPoints"
    },
    percentageMonthlyChange: {
      cssClass: "percentage-monthly-change",
      ticksCount: 5,
      yDomain: "",
      graphType: "bars",
      symmetricalYAxis: true
    }
  };

  var GRAPH_PADDING = {
    top: 30,
    right: 20,
    bottom: 20,
    left: 80
  };
  GRAPH_PADDING.horizontal = GRAPH_PADDING.left + GRAPH_PADDING.right;
  GRAPH_PADDING.vertical = GRAPH_PADDING.top + GRAPH_PADDING.bottom;

  /** Width of graph bars, in pixels */
  var HALF_BAR_WIDTH = 1;
  var BAR_WIDTH = HALF_BAR_WIDTH * 2;

  /** Minimum height of graph bars (so that zero values are still visible) */
  var MIN_BAR_HEIGHT = 2;

  /* Methods */

  _.extend( GraphView.prototype, {
    prefs: function() {
      return this.preferences;
    },

    showQueryResults: function( qr ) {
      var gv = this;
      var dateRange = qr.dateRange();

      _.each( this.prefs().indicators(), function( indicator ) {
        var options = GRAPHS_OPTIONS[indicator];
        if (options) {
          gv.graphConf[indicator] = {};
          var graphConf = gv.graphConf[indicator];

          graphConf.elem = revealGraphElem( options );
          graphConf.root = drawGraphRoot( graphConf );

          var valueRange = calculateValueRange( indicator, gv.prefs(), qr, options );
          _.merge( graphConf, configureAxes( graphConf, dateRange, valueRange, options ) );
          drawAxes( graphConf );
          drawGraph( indicator, gv.prefs(), qr, graphConf, options );
        }
      } );
    }
  } );

  /* Helper functions */

  var revealGraphElem = function( options ) {
    var selector = ".js-graph." + options.cssClass;
    $( selector )
      .removeClass( "hidden" )
      .find( "svg" )
      .empty();
    return D3.select( selector + " svg" );
  };

  var configureAxes = function( graphConf, dateRange, valueRange, options ) {
    var scales = createScales( graphConf.elem );
    var axes = createAxes( scales, options );

    setScaleDomain( scales, dateRange, valueRange );

    return {
      scales: scales,
      axes: axes
    };
  };

  var createScales = function( graphElem ) {
    var xScale = D3.time.scale().nice(D3.time.month);
    var yScale = D3.scale.linear();
    return setScaleViewDimensions( xScale, yScale, graphElem );
  };

  var setScaleViewDimensions = function( xScale, yScale, elem ) {
    var width = parseInt( elem.style("width") ) - GRAPH_PADDING.horizontal;
    var height = parseInt( elem.style("height") ) - GRAPH_PADDING.vertical;

    xScale.range( [0, width] );
    yScale.range( [height, 0] );

    return {x: xScale, y: yScale, width: width, height: height};
  };

  var createAxes = function( scales, options ) {
    var xAxis = D3.svg.axis()
      .scale( scales.x )
      .orient("bottom")
      .tickFormat(D3.time.format("%b %Y"));

    var yAxis = D3.svg.axis()
      .scale( scales.y )
      .orient("left")
      .ticks( options.ticksCount );

    return {x: xAxis, y: yAxis};
  };

  var setScaleDomain = function( scales, dateRange, valueRange ) {
    scales.x.domain( dateRange );
    scales.y.domain( valueRange ).nice();
  };

  var calculateValueRange = function( indicator, prefs, qr, options ) {
    var aspects = aspectNames( indicator, prefs );
    var extents = _.map( aspects, function( aspect ) {
      return D3.extent( qr.results(), function( result ) {
        return result.value( aspect );
      } );
    } );

    var overallRange = D3.extent( _.flatten( extents ) );

    if (options.symmetricalYAxis) {
      var largest = _.max( _.map( overallRange, Math.abs ) );
      return [largest * -1.0, largest];
    }
    else {
      return [0, overallRange[1]];
    }
  };

  var aspectNames = function( indicator, prefs ) {
    var aspects = prefs.aspects( {indicators: [indicator]} );
    return _.map( aspects, function( a ) {return "ukhpi:" + a;} );
  };

  var drawGraphRoot = function( graphConf ) {
    return graphConf
      .elem
      .append("g")
      .attr("transform", "translate(" + GRAPH_PADDING.left + "," + GRAPH_PADDING.top + ")");
  };

  var drawAxes = function( graphConf ) {
    graphConf.root
      .append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + graphConf.scales.height + ")")
      .call( graphConf.axes.x );
    graphConf.root
      .append("g")
      .attr("class", "y axis")
      .call( graphConf.axes.y );
  };

  var categoryCssClass = function( categoryName ) {
    return Util.Text.unCamelCase( categoryName, "-" ).toLocaleLowerCase();
  };

  var drawGraph = function( indicator, prefs, qr, graphConf, options ) {
    switch (options.graphType) {
    case "lineAndPoints":
      drawPoints( indicator, prefs, qr, graphConf, options );
      drawLine( indicator, prefs, qr, graphConf );
      break;
    case "bars":
      drawBars( indicator, prefs, qr, graphConf );
      break;
    default:
      console.log( "Unknown graph type" );
    }
  };

  var collectedSeries = function( indicator, prefs, qr ) {
    var s = _.map( prefs.categories(), function( c, i ) {
      var series = qr.series( indicator, c );
      _.each( series, function( d ) {d.categoryIndex = i;} );

      return series;
    } );

    return _.flatten( s );
  };

  var drawPoints = function( indicator, prefs, qr, graphConf, options ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;
    var data = collectedSeries( indicator, prefs, qr );

    graphConf.root
      .selectAll(".point")
      .data( data )
      .enter()
      .append("path")
      .attr("class", function( d ) {return "point " + categoryCssClass( d.cat );} )
      .attr("d", function( d, i ) {return D3.svg.symbol().type( SERIES_MARKER[d.cat] )( d, i );} )
      .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

  };

  var drawLine = function( indicator, prefs, qr, graphConf ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;

    var line = D3.svg
      .line()
      .x( function(d) { return x( d.x ); } )
      .y( function(d) { return y( d.y ); } );

    _.each( prefs.categories(), function( c ) {
      var s = qr.series( indicator, c );
      graphConf.root
        .append( "path" )
        .datum( s )
        .attr( "class", "line " + categoryCssClass( c ) )
        .attr( "d", line );
    } );
  };

  var drawBars = function( indicator, prefs, qr, graphConf ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;
    var y0 = y( 0 );

    var offsets = barOffsets( prefs.categories().length );
    var data = collectedSeries( indicator, prefs, qr );

    graphConf.root
      .selectAll( ".bar" )
      .data( data )
      .enter()
      .append( "rect" )
      .attr( "class", function( d ) {return "bar " + categoryCssClass( d.cat );} )
      .attr( "x", function( d ) { return x( d.x ) + offsets[d.categoryIndex]; })
      .attr( "y", function( d ) { return y( Math.max( 0, d.y ) ); })
      .attr( "width", BAR_WIDTH )
      .attr( "height", function( d ) {return Math.max( MIN_BAR_HEIGHT, Math.abs( y( d.y ) - y0 ) );} );
  };

  /** @return An array of the offsets around 0 for n category bars */
  var barOffsets = function( nPrefs ) {
    var lower = (nPrefs - 1) * HALF_BAR_WIDTH * -1.0;
    var upper = nPrefs * HALF_BAR_WIDTH;
    return _.range( lower, upper, BAR_WIDTH );
  };

  return GraphView;
} );
<commit_msg>Add a small bar margin<commit_after>/** Component for showing the queried index data as a set of graphs */

modulejs.define( "graphs-view", [
  "lib/lodash",
  "lib/jquery",
  "lib/d3",
  "lib/util",
  "preferences",
  "aspects"
], function(
  _,
  $,
  D3,
  Util,
  Preferences,
  Aspects
) {
  "use strict";

  var GraphView = function() {
    this.preferences = new Preferences();
    this.graphConf = {};
  };

  var SERIES_MARKER = {
    "":               "circle",
    "Detached":       "diamond",
    "SemiDetached":   "square",
    "Terraced":       "triangle-down",
    "FlatMaisonette": "triangle-up"
  };

  var GRAPHS_OPTIONS = {
    averagePrice: {
      cssClass: "average-price",
      ticksCount: 5,
      yDomain: "",
      graphType: "lineAndPoints"
    },
    housePriceIndex: {
      cssClass: "house-price-index",
      ticksCount: 5,
      yDomain: "",
      graphType: "lineAndPoints"
    },
    percentageMonthlyChange: {
      cssClass: "percentage-monthly-change",
      ticksCount: 5,
      yDomain: "",
      graphType: "bars",
      symmetricalYAxis: true
    }
  };

  var GRAPH_PADDING = {
    top: 30,
    right: 20,
    bottom: 20,
    left: 80
  };
  GRAPH_PADDING.horizontal = GRAPH_PADDING.left + GRAPH_PADDING.right;
  GRAPH_PADDING.vertical = GRAPH_PADDING.top + GRAPH_PADDING.bottom;

  /** Width of graph bars, in pixels */
  var BAR_MARGIN = 1;
  var VISIBLE_BAR_WIDTH = 3;;
  var BAR_WIDTH = VISIBLE_BAR_WIDTH + BAR_MARGIN;
  var HALF_BAR_WIDTH = BAR_WIDTH / 2;

  /** Minimum height of graph bars (so that zero values are still visible) */
  var MIN_BAR_HEIGHT = 2;

  /* Methods */

  _.extend( GraphView.prototype, {
    prefs: function() {
      return this.preferences;
    },

    showQueryResults: function( qr ) {
      var gv = this;
      var dateRange = qr.dateRange();

      _.each( this.prefs().indicators(), function( indicator ) {
        var options = GRAPHS_OPTIONS[indicator];
        if (options) {
          gv.graphConf[indicator] = {};
          var graphConf = gv.graphConf[indicator];

          graphConf.elem = revealGraphElem( options );
          graphConf.root = drawGraphRoot( graphConf );

          var valueRange = calculateValueRange( indicator, gv.prefs(), qr, options );
          _.merge( graphConf, configureAxes( graphConf, dateRange, valueRange, options ) );
          drawAxes( graphConf );
          drawGraph( indicator, gv.prefs(), qr, graphConf, options );
        }
      } );
    }
  } );

  /* Helper functions */

  var revealGraphElem = function( options ) {
    var selector = ".js-graph." + options.cssClass;
    $( selector )
      .removeClass( "hidden" )
      .find( "svg" )
      .empty();
    return D3.select( selector + " svg" );
  };

  var configureAxes = function( graphConf, dateRange, valueRange, options ) {
    var scales = createScales( graphConf.elem );
    var axes = createAxes( scales, options );

    setScaleDomain( scales, dateRange, valueRange );

    return {
      scales: scales,
      axes: axes
    };
  };

  var createScales = function( graphElem ) {
    var xScale = D3.time.scale().nice(D3.time.month);
    var yScale = D3.scale.linear();
    return setScaleViewDimensions( xScale, yScale, graphElem );
  };

  var setScaleViewDimensions = function( xScale, yScale, elem ) {
    var width = parseInt( elem.style("width") ) - GRAPH_PADDING.horizontal;
    var height = parseInt( elem.style("height") ) - GRAPH_PADDING.vertical;

    xScale.range( [0, width] );
    yScale.range( [height, 0] );

    return {x: xScale, y: yScale, width: width, height: height};
  };

  var createAxes = function( scales, options ) {
    var xAxis = D3.svg.axis()
      .scale( scales.x )
      .orient("bottom")
      .tickFormat(D3.time.format("%b %Y"));

    var yAxis = D3.svg.axis()
      .scale( scales.y )
      .orient("left")
      .ticks( options.ticksCount );

    return {x: xAxis, y: yAxis};
  };

  var setScaleDomain = function( scales, dateRange, valueRange ) {
    scales.x.domain( dateRange );
    scales.y.domain( valueRange ).nice();
  };

  var calculateValueRange = function( indicator, prefs, qr, options ) {
    var aspects = aspectNames( indicator, prefs );
    var extents = _.map( aspects, function( aspect ) {
      return D3.extent( qr.results(), function( result ) {
        return result.value( aspect );
      } );
    } );

    var overallRange = D3.extent( _.flatten( extents ) );

    if (options.symmetricalYAxis) {
      var largest = _.max( _.map( overallRange, Math.abs ) );
      return [largest * -1.0, largest];
    }
    else {
      return [0, overallRange[1]];
    }
  };

  var aspectNames = function( indicator, prefs ) {
    var aspects = prefs.aspects( {indicators: [indicator]} );
    return _.map( aspects, function( a ) {return "ukhpi:" + a;} );
  };

  var drawGraphRoot = function( graphConf ) {
    return graphConf
      .elem
      .append("g")
      .attr("transform", "translate(" + GRAPH_PADDING.left + "," + GRAPH_PADDING.top + ")");
  };

  var drawAxes = function( graphConf ) {
    graphConf.root
      .append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + graphConf.scales.height + ")")
      .call( graphConf.axes.x );
    graphConf.root
      .append("g")
      .attr("class", "y axis")
      .call( graphConf.axes.y );
  };

  var categoryCssClass = function( categoryName ) {
    return Util.Text.unCamelCase( categoryName, "-" ).toLocaleLowerCase();
  };

  var drawGraph = function( indicator, prefs, qr, graphConf, options ) {
    switch (options.graphType) {
    case "lineAndPoints":
      drawPoints( indicator, prefs, qr, graphConf, options );
      drawLine( indicator, prefs, qr, graphConf );
      break;
    case "bars":
      drawBars( indicator, prefs, qr, graphConf );
      break;
    default:
      console.log( "Unknown graph type" );
    }
  };

  var collectedSeries = function( indicator, prefs, qr ) {
    var s = _.map( prefs.categories(), function( c, i ) {
      var series = qr.series( indicator, c );
      _.each( series, function( d ) {d.categoryIndex = i;} );

      return series;
    } );

    return _.flatten( s );
  };

  var drawPoints = function( indicator, prefs, qr, graphConf, options ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;
    var data = collectedSeries( indicator, prefs, qr );

    graphConf.root
      .selectAll(".point")
      .data( data )
      .enter()
      .append("path")
      .attr("class", function( d ) {return "point " + categoryCssClass( d.cat );} )
      .attr("d", function( d, i ) {return D3.svg.symbol().type( SERIES_MARKER[d.cat] )( d, i );} )
      .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; });

  };

  var drawLine = function( indicator, prefs, qr, graphConf ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;

    var line = D3.svg
      .line()
      .x( function(d) { return x( d.x ); } )
      .y( function(d) { return y( d.y ); } );

    _.each( prefs.categories(), function( c ) {
      var s = qr.series( indicator, c );
      graphConf.root
        .append( "path" )
        .datum( s )
        .attr( "class", "line " + categoryCssClass( c ) )
        .attr( "d", line );
    } );
  };

  var drawBars = function( indicator, prefs, qr, graphConf ) {
    var x = graphConf.scales.x;
    var y = graphConf.scales.y;
    var y0 = y( 0 );

    var offsets = barOffsets( prefs.categories().length );
    var data = collectedSeries( indicator, prefs, qr );

    graphConf.root
      .selectAll( ".bar" )
      .data( data )
      .enter()
      .append( "rect" )
      .attr( "class", function( d ) {return "bar " + categoryCssClass( d.cat );} )
      .attr( "x", function( d ) { return x( d.x ) + offsets[d.categoryIndex]; })
      .attr( "y", function( d ) { return y( Math.max( 0, d.y ) ); })
      .attr( "width", VISIBLE_BAR_WIDTH )
      .attr( "height", function( d ) {return Math.max( MIN_BAR_HEIGHT, Math.abs( y( d.y ) - y0 ) );} );
  };

  /** @return An array of the offsets around 0 for n category bars */
  var barOffsets = function( nPrefs ) {
    var lower = (nPrefs - 1) * HALF_BAR_WIDTH * -1.0;
    var upper = nPrefs * HALF_BAR_WIDTH;
    return _.range( lower, upper, BAR_WIDTH );
  };

  return GraphView;
} );
<|endoftext|>


<commit_before>/**
 * --------------------------------------------------------------------
 * jQuery tabs plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */

/*
 * Edited to support GOV.UK markup and add acccessibility features
*/

jQuery.fn.tabs = function(settings){
	//configurable options
	var o = $.extend({
		trackState: true, //track tabs in history, url hash, back button, page load
		srcPath: 'jQuery.history.blank.html',
		autoRotate: false,
		alwaysScrollToTop: true,
		selected: null
	},settings);

	return $(this).each(function(){
		//reference to tabs container
		var tabs = $(this);

		//set app mode
		//if( !$('body').is('[role]') ){ $('body').attr('role','application'); }

		//nav is first ul or ol
		var tabsNav = tabs.find('.js-tabs ul, .js-tabs ol');

		//body is nav's next sibling
		var tabsBody = $(".js-tab-content");

		var tabIDprefix = 'tab-';

		var tabIDsuffix = '-enhanced';

		//add class to nav, tab body
		tabsNav
			.addClass('tabs-nav')
			.attr('role','tablist');

		tabsBody
			.addClass('tabs-body')
			.attr('aria-live', 'polite');

		//find tab panels, add class and aria
		tabsBody.find('.js-tab-pane').each(function(){
			$(this)
				.addClass('tabs-panel')
				.attr('role','tabpanel')
				.attr('aria-hidden', true)
				.attr('aria-expanded', false)
				.attr('aria-labelledby', tabIDprefix + $(this).attr('id'))
				.attr('id', $(this).attr('id') + tabIDsuffix)
				.hide();
		});

		//set role of each tab
		tabsNav.find('li').find('a').each(function(){
			var id = $(this).attr('href').split('#')[1];

			$(this)
				.attr('role','tab')
				.attr('id', tabIDprefix+id)
				.attr('aria-controls', id)
				.attr('aria-flowto', id);
		});

		//switch selected on click
    // tabsNav.find('a').attr('tabindex','-1');

		//generic select tab function
		function selectTab(tab,fromHashChange){
			if(o.trackState && !fromHashChange){
				var anchor = tab.attr('href').split("#")[1];
				$.historyLoad(anchor);
			} else {
				//unselect tabs
				tabsNav.find('li').find('a')
					.attr('aria-selected', false)
					.attr('tabindex', -1)
					.parent().filter('.active').removeClass('active');
				//set selected tab item
				tab
					.attr('aria-selected', true)
					.attr('tabindex', 0)
					.parent().addClass('active');
				//unselect panels
				tabsBody.find('.tabs-panel-selected')
					.attr('aria-hidden',true)
					.attr('aria-expanded', false)
					.removeClass('tabs-panel-selected')
					.hide();

				//select active panel
				var anchor = tab.attr('href').split("#")[1];
				$( "#" + anchor + tabIDsuffix )
					.addClass('tabs-panel-selected')
					.attr('aria-hidden',false)
					.attr('aria-expanded', true)
					.show();

				// set selected index
				o.selected = tab.parent().index();
			}
		}

		tabsNav.on('click', 'a', function(){
			selectTab($(this));
			$(this).focus();
			return false;
		}).on('focus', 'a', function() {
			o.selected = $(this).parent().index();
		});

		// keyboard navigation
		tabs.on('keydown', function(event) {
			if (event.keyCode < $.ui.keyCode.PAGE_UP || event.keyCode > $.ui.keyCode.DOWN)
				return;

			var selectedIndex;
			switch (event.keyCode) {
				case $.ui.keyCode.RIGHT:
				event.preventDefault();
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.DOWN:
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.UP:
				selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.LEFT:
				selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.END:
				selectedIndex = that.anchors.length - 1;
				break;
				case $.ui.keyCode.HOME:
				selectedIndex = 0;
				break;
				case $.ui.keyCode.PAGE_UP:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.PAGE_DOWN:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected - 1;
				break;
			}
			event.preventDefault();
			event.stopPropagation();

			if (selectedIndex !== undefined) {
				selectedIndex = selectedIndex >= tabsNav.find('a').length ? 0 : selectedIndex < 0 ? tabsNav.find('a').length - 1 : selectedIndex;

				selectTab(tabsNav.find('a').eq(selectedIndex).focus());
			}
			return false;
		});

		//if tabs are rotating, stop them upon user events
		tabs.bind('click keydown focus',function(){
			if(o.autoRotate){ clearInterval(tabRotator); }
		});

		//function to select a tab from the url hash
		function selectTabFromHash(hash){
			var currHash = hash || window.location.hash;
			if(currHash.indexOf("#") == 0){
        currHash = currHash.split("#")[1];
      }
			var hashedTab = tabsNav.find('a[href$=#'+ currHash +']');
				if( hashedTab.size() > 0){
					selectTab(hashedTab,true);
				}
				else {
					selectTab( tabsNav.find('a:first'),true);
				}
				//return true/false
				return !!hashedTab.size();
		}

		//if state tracking is enabled, set up the callback
		if(o.trackState){ $.historyInit(selectTabFromHash, o.srcPath); }

		//set tab from hash at page load, if no tab hash, select first tab
		selectTabFromHash(null,true);

		if(o.alwaysScrollToTop){
			$(window)[0].scrollTo(0,0);
		}
	});
};
<commit_msg>Corrections to tab conversion (for mobile version)<commit_after>/**
 * --------------------------------------------------------------------
 * jQuery tabs plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */

/*
 * Edited to support GOV.UK markup and add acccessibility features
*/

jQuery.fn.tabs = function(settings){
	//configurable options
	var o = $.extend({
		trackState: true, //track tabs in history, url hash, back button, page load
		srcPath: 'jQuery.history.blank.html',
		autoRotate: false,
		alwaysScrollToTop: true,
		selected: null,
		mobileHeadingTag: 'h2'
	},settings);

	var isMobile = false,
	    checkMobile = function ($tabsNav) {
            var $navContainer = $tabsNav.closest('nav');

            if ($navContainer.hasClass('programme-progression')) {
                if ($tabsNav.closest('nav').css('float') === 'none') {
                    return true;
                }
            } else { // is transaction start page tabs
                if ($tabsNav.find('li').css('float') === 'none') {
                    return true;
                }
            }

            return false;
        };

    var setTabItems = function ($tabsBody, $tabsNav) {
        if (isMobile) {
            return $tabsBody.find(o.mobileHeadingTag + '.js-heading-tab');
        }

        return $tabsNav.find('li');
    };

	var adapt = function ($tabs, $tabsNav, $tabItems) {
        var $tabItems = $tabsNav.find('li'),
            $container = $tabsNav.closest('nav').parent(),
            $relatedArticle,
            $tmpHeading;

        $.each($tabItems, function (idx) {
            $tmpHeading = $('<' + o.mobileHeadingTag + ' />').addClass('js-heading-tab');
            $relatedArticle = $container.find('#' + $(this).find('a').attr('href').split('#')[1]);
            $tmpHeading.append($(this).find('a'));
            $tmpHeading.insertBefore($relatedArticle);
        })

        $tabsNav.closest('nav').remove();
    };

	return $(this).each(function(){
		//reference to tabs container
		var tabs = $(this);

		//set app mode
		//if( !$('body').is('[role]') ){ $('body').attr('role','application'); }

		//nav is first ul or ol
		var tabsNav = tabs.find('.js-tabs ul, .js-tabs ol');

		//body is nav's next sibling
		var tabsBody = $(".js-tab-content");

		var tabIDprefix = 'tab-';

		var tabIDsuffix = '-enhanced';

        // check for mobile and adapt DOM if required
        isMobile = checkMobile(tabsNav);
        if (isMobile) {
            adapt(tabs, tabsNav);
        } else {
            //add class to nav, tab body
            tabsNav
                .addClass('tabs-nav')
                .attr('role','tablist');
	    }

		tabsBody
			.addClass('tabs-body')
			.attr('aria-live', 'polite');

		//find tab panels, add class and aria
		tabsBody.find('.js-tab-pane').each(function(){
			$(this)
				.addClass('tabs-panel')
				.attr('role','tabpanel')
				.attr('aria-hidden', true)
				.attr('aria-expanded', false)
				.attr('aria-labelledby', tabIDprefix + $(this).attr('id'))
				.attr('id', $(this).attr('id') + tabIDsuffix)
				.hide();
		});

        var tabItems = setTabItems(tabsBody, tabsNav);

		//set role of each tab
		tabItems.find('a').each(function(){
			var id = $(this).attr('href').split('#')[1];
			$(this)
				.attr('role','tab')
				.attr('id', tabIDprefix+id)
				.attr('aria-controls', id)
				.attr('aria-flowto', id);
		});

		//switch selected on click
        // tabItems.find('a').attr('tabindex','-1');

		//generic select tab function
		function selectTab(tab,fromHashChange){
			if(o.trackState && !fromHashChange){
				var anchor = tab.attr('href').split("#")[1];
				$.historyLoad(anchor);
			} else {
				//unselect tabs
				tabItems
					.attr('aria-selected', false)
					.attr('tabindex', -1)
					.parent().filter('.active').removeClass('active');
				//set selected tab item
				tab
					.attr('aria-selected', true)
					.attr('tabindex', 0)
					.parent().addClass('active');
				//unselect panels
				tabsBody.find('.tabs-panel-selected')
					.attr('aria-hidden',true)
					.attr('aria-expanded', false)
					.removeClass('tabs-panel-selected')
					.hide();

				//select active panel
				var anchor = tab.attr('href').split("#")[1];
				$( "#" + anchor + tabIDsuffix )
					.addClass('tabs-panel-selected')
					.attr('aria-hidden',false)
					.attr('aria-expanded', true)
					.show();

				// set selected index
				o.selected = tab.parent().index();
			}
		}

		// keyboard navigation
		tabs.on('keydown', function(event) {
			if (event.keyCode < $.ui.keyCode.PAGE_UP || event.keyCode > $.ui.keyCode.DOWN)
				return;

			var selectedIndex;
			switch (event.keyCode) {
				case $.ui.keyCode.RIGHT:
				event.preventDefault();
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.DOWN:
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.UP:
				selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.LEFT:
				selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.END:
				selectedIndex = that.anchors.length - 1;
				break;
				case $.ui.keyCode.HOME:
				selectedIndex = 0;
				break;
				case $.ui.keyCode.PAGE_UP:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.PAGE_DOWN:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected - 1;
				break;
			}
			event.preventDefault();
			event.stopPropagation();

			if (selectedIndex !== undefined) {
				selectedIndex = selectedIndex >= tabItems.find('a').length ? 0 : selectedIndex < 0 ? tabItems.find('a').length - 1 : selectedIndex;

				selectTab(tabItems.find('a').eq(selectedIndex).focus());
			}
			return false;
		});

		//if tabs are rotating, stop them upon user events
		tabs.bind('click keydown focus',function(){
			if(o.autoRotate){ clearInterval(tabRotator); }
		});

		//function to select a tab from the url hash
		function selectTabFromHash(hash){
			var currHash = hash || window.location.hash;
			if(currHash.indexOf("#") == 0){
              currHash = currHash.split("#")[1];
            }
			var hashedTab = tabItems.find('a[href$=#'+ currHash +']');
				if( hashedTab.size() > 0){
					selectTab(hashedTab,true);
				}
				else {
					selectTab( tabItems.find('a:first'),true);
				}
				//return true/false
				return !!hashedTab.size();
		}

		//if state tracking is enabled, set up the callback
		if(o.trackState){ $.historyInit(selectTabFromHash, o.srcPath); }

		//set tab from hash at page load, if no tab hash, select first tab
		selectTabFromHash(null,true);

		tabItems.on('click', 'a', function(){
			selectTab($(this));
			$(this).focus();
			return false;
		}).on('focus', 'a', function() {
			o.selected = $(this).parent().index();
		});

		if(o.alwaysScrollToTop){
			$(window)[0].scrollTo(0,0);
		}
	});
};
<|endoftext|>


<commit_before>/**
 * --------------------------------------------------------------------
 * jQuery tabs plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */

/*
 * Edited to support GOV.UK markup and add acccessibility features
*/

jQuery.fn.tabs = function(settings){
	//configurable options
	var o = $.extend({
		trackState: true, //track tabs in history, url hash, back button, page load
		srcPath: 'jQuery.history.blank.html',
		autoRotate: false,
		alwaysScrollToTop: true,
		selected: null,
		wrapperTag : 'section',
		defaultTab : null,
		scrollOnload : false
	},settings);

	var tabFormat = 'tabset',
    checkFormat = function ($tabsNav) {
      var format = tabFormat,
          $navContainer = $tabsNav.closest('nav');

          if ($navContainer.hasClass('programme-progression')) {
            if ($tabsNav.closest('nav').css('float') === 'none') {
              format = 'accordion';
            }
          } else { // is transaction start page tabs
            if ($tabsNav.find('li').css('float') === 'none') {
              format = 'accordion';
            }
          }

          // accordions default to all tabs closed, tabsets to open at the 1st
          if (format === 'accordion') {
            if (o.defaultTab === null) {
              o.defaultTab = -1;
            }
          } else {
            if (o.defaultTab === null) {
              o.defaultTab = 0;
            }
          }

          return format;
        };

  var setTabItems = function ($tabsBody, $tabsNav) {
    if (tabFormat === 'accordion') {
      return $tabsBody.find('header.js-heading-tab');
    }

    return $tabsNav.find('li');
  };

	var adapt = function ($tabs, $tabsNav, $tabsBody) {
    var $tabItems = $tabsNav.find('li'),
        $container = $tabsNav.closest('nav').parent(),
        $relatedArticle,
        $articleHeading,
        $articleInner;

    $.each($tabItems, function (idx) {
      var $tabAnchor = $(this).find('a'),
          tabId = $tabAnchor.attr('href').split('#')[1],
          $shiftLink = $('Return to top of section ↑');

      $relatedArticle = $container.find('#' + tabId);

      // get heading & store
      $articleHeading = $relatedArticle.find('header');

      if (!$articleHeading.length) {
        $articleHeading = $('
');
      } else {
        $articleHeading = $articleHeading.remove();
      }

      $articleHeading
        .addClass('js-heading-tab')
        .removeClass('visuallyhidden')

      $articleHeading.children().html('').append($tabAnchor);

      // get div.inner
      $articleInner = $relatedArticle.find('.inner');

      // if article has no inner div, add one & move the content into it
      if (!$articleInner.length) {
        $articleInner = $('
').html($relatedArticle.html());
      } else {
        $articleInner.addClass('js-tab-pane');
      }

      $articleInner.attr('id', tabId);

      // create a new blank article with the original's inner div
      $relatedArticle.replaceWith($('<' + o.wrapperTag  + ' />').append($articleInner));
      $relatedArticle = $articleInner.parent();
      $relatedArticle.prepend($articleHeading)
        .attr('id', tabId);
      $relatedArticle.addClass('js-tab-container');
      $articleInner.append($shiftLink);
    });

    $tabsNav.closest('nav').remove();
  };

	return $(this).each(function(){
		//reference to tabs container
		var tabs = $(this);

		//nav is first ul or ol
		var tabsNav = tabs.find('.js-tabs ul, .js-tabs ol');

    // exit early if there isn't anything to click
    if (tabsNav.length === 0) {
      return tabs;
    }

		//body is nav's next sibling
		var tabsBody = $(".js-tab-content");

		var tabIDprefix = 'tab-';

		var tabIDsuffix = '-enhanced';

		tabsBody
			.addClass('tabs-body')
			.attr('aria-live', 'polite');

        // check for mobile and adapt DOM if required
        tabFormat = checkFormat(tabsNav);
        if (tabFormat === 'accordion') {
          adapt(tabs, tabsNav);
        } else {
          //add class to nav, tab body
          tabsNav
            .addClass('tabs-nav')
            .attr('role','tablist');
	    }

		//find tab panels, add class and aria
		tabsBody.find('.js-tab-pane').each(function(){
			$(this)
				.addClass('tabs-panel')
				.attr('role','tabpanel')
				.attr('aria-hidden', true)
				.attr('aria-expanded', false)
				.attr('aria-labelledby', tabIDprefix + $(this).attr('id'))
				.attr('id', $(this).attr('id') + tabIDsuffix)
				.hide();
		});

    var tabItems = setTabItems(tabsBody, tabsNav);

		//set role of each tab
		tabItems.find('a').each(function(idx){
      var id = $(this).attr('href').split('#')[1];

			$(this)
				.attr('role','tab')
				.attr('id', tabIDprefix + id)
				.attr('aria-controls', id)
				.attr('aria-flowto', id);
		});

		//generic select tab function
		function selectTab(tab,fromHashChange){
			if(o.trackState && !fromHashChange){
				var anchor = tab.attr('href').split('#')[1];
				$.historyLoad(anchor);
			} else {
				//unselect tabs
				tabItems.find('a')
					.attr('aria-selected', false)
					.attr('tabindex', -1);
            if (tabFormat === 'accordion') {
              tabItems.find('a').closest('.js-heading-tab').removeClass('active');
            } else {
              tabItems.find('a').parent().filter('.active').removeClass('active');
            }
				//set selected tab item
				tab
					.attr('aria-selected', true)
					.attr('tabindex', 0);
        if (tabFormat === 'accordion') {
          tab.closest('.js-heading-tab').addClass('active');
        } else {
					tab.parent().addClass('active');
        }
				//unselect panels
				tabsBody.find('.tabs-panel-selected')
					.attr('aria-hidden',true)
					.attr('aria-expanded', false)
					.removeClass('tabs-panel-selected')
					.hide();

				//select active panel
				var anchor = tab.attr('href').split('#')[1];

				$( "#" + anchor + tabIDsuffix )
					.addClass('tabs-panel-selected')
					.attr('aria-hidden',false)
					.attr('aria-expanded', true)
					.show();

				// set selected index
				o.selected = tabItems.find('a').index(tab);

				// fire tab changed event
				tabs.trigger('tabChanged', anchor);

			}
		}

		//deselect tab function
		function deselectTab(tab){
      tabItems.find('a')
        .attr('aria-selected', false)
        .attr('tabindex', -1);

      tabItems.find('a').closest('.js-heading-tab').removeClass('active');

      //unselect panels
      tabsBody.find('.tabs-panel-selected')
        .attr('aria-hidden',true)
        .attr('aria-expanded', false)
        .removeClass('tabs-panel-selected')
        .hide();
		}

		// keyboard navigation
		tabs.on('keydown', function(event) {
			if (event.keyCode < $.ui.keyCode.PAGE_UP || event.keyCode > $.ui.keyCode.DOWN)
				return;

			var selectedIndex,
			    selectedTabItem;

			switch (event.keyCode) {
				case $.ui.keyCode.RIGHT:
          event.preventDefault();
          selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.DOWN:
          selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.UP:
          selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.LEFT:
          selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.END:
          selectedIndex = tabItems.length - 1;
				break;
				case $.ui.keyCode.HOME:
          selectedIndex = 0;
				break;
				case $.ui.keyCode.PAGE_UP:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.PAGE_DOWN:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected - 1;
				break;
			}
			event.preventDefault();
			event.stopPropagation();

			if (selectedIndex !== undefined) {
				selectedIndex = selectedIndex >= tabItems.length ? 0 : selectedIndex < 0 ? tabItems.length - 1 : selectedIndex;

        selectedTabItem = tabItems.find('a').eq(selectedIndex);
        selectedTabItem.focus();
        o.selected = selectedIndex;
			}

			return false;
		});

		//if tabs are rotating, stop them upon user events
		tabs.bind('click keydown focus',function(){
      if(o.autoRotate){ clearInterval(tabRotator); }
		});

		//function to select a tab from the url hash
		function selectTabFromHash(hash, pageLoad){
			var currHash = hash || window.location.hash;
			if(currHash.indexOf("#") == 0){
        currHash = currHash.split("#")[1];
      }
			var hashedTab = tabItems.find('a[href$=#' +  currHash + ']');

      if(hashedTab.size() > 0){
        selectTab(hashedTab,true);
        if(o.scrollOnload && pageLoad){
          window.setTimeout(function(){ $(document).scrollTop(hashedTab.offset().top) }, 0);
        }
      }
      else {
        if (o.defaultTab > -1) {
          selectTab( tabItems.find('a').eq(o.defaultTab), true);
        }
      }
      //return true/false
      return !!hashedTab.size();
		}

		//if state tracking is enabled, set up the callback
		if(o.trackState){ $.historyInit(selectTabFromHash, o.srcPath); }

		//set tab from hash at page load, if no tab hash, select first tab
		selectTabFromHash(null, true);

		tabItems.on('click', 'a', function(){
      if ($(this).closest('.js-heading-tab').hasClass('active')) {
        deselectTab($(this));
      } else {
        selectTab($(this));
      }
			$(this).focus();
			return false;
		});

		if(o.alwaysScrollToTop){
			$(window)[0].scrollTo(0,0);
		}

    // related content box needs to know the top position of the footer
    // this changes when content is split into tabs
    if (typeof GOVUK.stopScrollingAtFooter !== 'undefined') {
      GOVUK.stopScrollingAtFooter.updateFooterTop();
    }
	});
};
<commit_msg>Make container tag a variable & change to div<commit_after>/**
 * --------------------------------------------------------------------
 * jQuery tabs plugin
 * Author: Scott Jehl, scott@filamentgroup.com
 * Copyright (c) 2009 Filament Group
 * licensed under MIT (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */

/*
 * Edited to support GOV.UK markup and add acccessibility features
*/

jQuery.fn.tabs = function(settings){
	//configurable options
	var o = $.extend({
    trackState: true, //track tabs in history, url hash, back button, page load
    srcPath: 'jQuery.history.blank.html',
    autoRotate: false,
    alwaysScrollToTop: true,
    selected: null,
    wrapperTag : 'section',
    defaultTab : null,
    containerTag : 'div'
		scrollOnload : false
	},settings);

	var tabFormat = 'tabset',
    checkFormat = function ($tabsNav) {
      var format = tabFormat,
          $navContainer = $tabsNav.closest(o.containerTag);

          if ($navContainer.hasClass('programme-progression')) {
            if ($tabsNav.closest(o.containerTag).css('float') === 'none') {
              format = 'accordion';
            }
          } else { // is transaction start page tabs
            if ($tabsNav.find('li').css('float') === 'none') {
              format = 'accordion';
            }
          }

          // accordions default to all tabs closed, tabsets to open at the 1st
          if (format === 'accordion') {
            if (o.defaultTab === null) {
              o.defaultTab = -1;
            }
          } else {
            if (o.defaultTab === null) {
              o.defaultTab = 0;
            }
          }

          return format;
        };

  var setTabItems = function ($tabsBody, $tabsNav) {
    if (tabFormat === 'accordion') {
      return $tabsBody.find('header.js-heading-tab');
    }

    return $tabsNav.find('li');
  };

	var adapt = function ($tabs, $tabsNav, $tabsBody) {
    var $tabItems = $tabsNav.find('li'),
        $container = $tabsNav.closest(o.containerTag).parent(),
        $relatedArticle,
        $articleHeading,
        $articleInner;

    $.each($tabItems, function (idx) {
      var $tabAnchor = $(this).find('a'),
          tabId = $tabAnchor.attr('href').split('#')[1],
          $shiftLink = $('Return to top of section ↑');

      $relatedArticle = $container.find('#' + tabId);

      // get heading & store
      $articleHeading = $relatedArticle.find('header');

      if (!$articleHeading.length) {
        $articleHeading = $('
');
      } else {
        $articleHeading = $articleHeading.remove();
      }

      $articleHeading
        .addClass('js-heading-tab')
        .removeClass('visuallyhidden')

      $articleHeading.children().html('').append($tabAnchor);

      // get div.inner
      $articleInner = $relatedArticle.find('.inner');

      // if article has no inner div, add one & move the content into it
      if (!$articleInner.length) {
        $articleInner = $('
').html($relatedArticle.html());
      } else {
        $articleInner.addClass('js-tab-pane');
      }

      $articleInner.attr('id', tabId);

      // create a new blank article with the original's inner div
      $relatedArticle.replaceWith($('<' + o.wrapperTag  + ' />').append($articleInner));
      $relatedArticle = $articleInner.parent();
      $relatedArticle.prepend($articleHeading)
        .attr('id', tabId);
      $relatedArticle.addClass('js-tab-container');
      $articleInner.append($shiftLink);
    });

    $tabsNav.closest(o.containerTag).remove();
  };

	return $(this).each(function(){
		//reference to tabs container
		var tabs = $(this);

		//nav is first ul or ol
		var tabsNav = tabs.find('.js-tabs ul, .js-tabs ol');

    // exit early if there isn't anything to click
    if (tabsNav.length === 0) {
      return tabs;
    }

		//body is nav's next sibling
		var tabsBody = $(".js-tab-content");

		var tabIDprefix = 'tab-';

		var tabIDsuffix = '-enhanced';

		tabsBody
			.addClass('tabs-body')
			.attr('aria-live', 'polite');

    // check for mobile and adapt DOM if required
    tabFormat = checkFormat(tabsNav);
    if (tabFormat === 'accordion') {
      adapt(tabs, tabsNav);
    } else {
      //add class to nav, tab body
      tabsNav
        .addClass('tabs-nav')
        .attr('role','tablist');
    }

		//find tab panels, add class and aria
		tabsBody.find('.js-tab-pane').each(function(){
			$(this)
				.addClass('tabs-panel')
				.attr('role','tabpanel')
				.attr('aria-hidden', true)
				.attr('aria-expanded', false)
				.attr('aria-labelledby', tabIDprefix + $(this).attr('id'))
				.attr('id', $(this).attr('id') + tabIDsuffix)
				.hide();
		});

    var tabItems = setTabItems(tabsBody, tabsNav);

		//set role of each tab
		tabItems.find('a').each(function(idx){
      var id = $(this).attr('href').split('#')[1];

			$(this)
				.attr('role','tab')
				.attr('id', tabIDprefix + id)
				.attr('aria-controls', id)
				.attr('aria-flowto', id);
		});

		//generic select tab function
		function selectTab(tab,fromHashChange){
			if(o.trackState && !fromHashChange){
				var anchor = tab.attr('href').split('#')[1];
				$.historyLoad(anchor);
			} else {
				//unselect tabs
				tabItems.find('a')
					.attr('aria-selected', false)
					.attr('tabindex', -1);
            if (tabFormat === 'accordion') {
              tabItems.find('a').closest('.js-heading-tab').removeClass('active');
            } else {
              tabItems.find('a').parent().filter('.active').removeClass('active');
            }
				//set selected tab item
				tab
					.attr('aria-selected', true)
					.attr('tabindex', 0);
        if (tabFormat === 'accordion') {
          tab.closest('.js-heading-tab').addClass('active');
        } else {
					tab.parent().addClass('active');
        }
				//unselect panels
				tabsBody.find('.tabs-panel-selected')
					.attr('aria-hidden',true)
					.attr('aria-expanded', false)
					.removeClass('tabs-panel-selected')
					.hide();

				//select active panel
				var anchor = tab.attr('href').split('#')[1];

				$( "#" + anchor + tabIDsuffix )
					.addClass('tabs-panel-selected')
					.attr('aria-hidden',false)
					.attr('aria-expanded', true)
					.show();

				// set selected index
				o.selected = tabItems.find('a').index(tab);

				// fire tab changed event
				tabs.trigger('tabChanged', anchor);

			}
		}

		//deselect tab function
		function deselectTab(tab){
      tabItems.find('a')
        .attr('aria-selected', false)
        .attr('tabindex', -1);

      tabItems.find('a').closest('.js-heading-tab').removeClass('active');

      //unselect panels
      tabsBody.find('.tabs-panel-selected')
        .attr('aria-hidden',true)
        .attr('aria-expanded', false)
        .removeClass('tabs-panel-selected')
        .hide();
		}

		// keyboard navigation
		tabs.on('keydown', function(event) {
			if (event.keyCode < $.ui.keyCode.PAGE_UP || event.keyCode > $.ui.keyCode.DOWN)
				return;

			var selectedIndex,
			    selectedTabItem;

			switch (event.keyCode) {
				case $.ui.keyCode.RIGHT:
          event.preventDefault();
          selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.DOWN:
          selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.UP:
          selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.LEFT:
          selectedIndex = o.selected - 1;
				break;
				case $.ui.keyCode.END:
          selectedIndex = tabItems.length - 1;
				break;
				case $.ui.keyCode.HOME:
          selectedIndex = 0;
				break;
				case $.ui.keyCode.PAGE_UP:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				break;
				case $.ui.keyCode.PAGE_DOWN:
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected + 1;
				if (!event.ctrlKey)
					return;
				selectedIndex = o.selected - 1;
				break;
			}
			event.preventDefault();
			event.stopPropagation();

			if (selectedIndex !== undefined) {
				selectedIndex = selectedIndex >= tabItems.length ? 0 : selectedIndex < 0 ? tabItems.length - 1 : selectedIndex;

        selectedTabItem = tabItems.find('a').eq(selectedIndex);
        selectedTabItem.focus();
        o.selected = selectedIndex;
			}

			return false;
		});

		//if tabs are rotating, stop them upon user events
		tabs.bind('click keydown focus',function(){
      if(o.autoRotate){ clearInterval(tabRotator); }
		});

		//function to select a tab from the url hash
		function selectTabFromHash(hash, pageLoad){
			var currHash = hash || window.location.hash;
			if(currHash.indexOf("#") == 0){
        currHash = currHash.split("#")[1];
      }
			var hashedTab = tabItems.find('a[href$=#' +  currHash + ']');

      if(hashedTab.size() > 0){
        selectTab(hashedTab,true);
        if(o.scrollOnload && pageLoad){
          window.setTimeout(function(){ $(document).scrollTop(hashedTab.offset().top) }, 0);
        }
      }
      else {
        if (o.defaultTab > -1) {
          selectTab( tabItems.find('a').eq(o.defaultTab), true);
        }
      }
      //return true/false
      return !!hashedTab.size();
		}

		//if state tracking is enabled, set up the callback
		if(o.trackState){ $.historyInit(selectTabFromHash, o.srcPath); }

		//set tab from hash at page load, if no tab hash, select first tab
		selectTabFromHash(null, true);

		tabItems.on('click', 'a', function(){
      if ($(this).closest('.js-heading-tab').hasClass('active')) {
        deselectTab($(this));
      } else {
        selectTab($(this));
      }
			$(this).focus();
			return false;
		});

		if(o.alwaysScrollToTop){
			$(window)[0].scrollTo(0,0);
		}

    // related content box needs to know the top position of the footer
    // this changes when content is split into tabs
    if (typeof GOVUK.stopScrollingAtFooter !== 'undefined') {
      GOVUK.stopScrollingAtFooter.updateFooterTop();
    }
	});
};
<|endoftext|>