14f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen// Copyright 2010 The Go Authors. All rights reserved.
24f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen// Use of this source code is governed by a BSD-style
34f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen// license that can be found in the LICENSE file.
44f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
54f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
64f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * A class to hold information about the Codewalk Viewer.
74f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {jQuery} context The top element in whose context the viewer should
84f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen *     operate.  It will not touch any elements above this one.
94f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @constructor
104f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
114f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen var CodewalkViewer = function(context) {
124f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context = context;
134f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
144f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
154f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The div that contains all of the comments and their controls.
164f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
174f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.commentColumn = this.context.find('#comment-column');
184f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
194f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
204f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The div that contains the comments proper.
214f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
224f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.commentArea = this.context.find('#comment-area');
234f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
244f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
254f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The div that wraps the iframe with the code, as well as the drop down menu
264f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * listing the different files.
274f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
284f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
294f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeColumn = this.context.find('#code-column');
304f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
314f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
324f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The div that contains the code but excludes the options strip.
334f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
344f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
354f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeArea = this.context.find('#code-area');
364f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
374f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
384f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The iframe that holds the code (from Sourcerer).
394f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
404f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
414f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeDisplay = this.context.find('#code-display');
424f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
434f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
444f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The overlaid div used as a grab handle for sizing the code/comment panes.
454f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
464f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
474f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.sizer = this.context.find('#sizer');
484f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
494f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
504f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The full-screen overlay that ensures we don't lose track of the mouse
514f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * while dragging.
524f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
534f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
544f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.overlay = this.context.find('#overlay');
554f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
564f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
574f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The hidden input field that we use to hold the focus so that we can detect
584f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * shortcut keypresses.
594f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
604f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
614f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.shortcutInput = this.context.find('#shortcut-input');
624f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
634f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  /**
644f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * The last comment that was selected.
654f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   * @type {jQuery}
664f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen   */
674f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.lastSelected = null;
684f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
694f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
704f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
714f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Minimum width of the comments or code pane, in pixels.
724f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @type {number}
734f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
744f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.MIN_PANE_WIDTH = 200;
754f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
764f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
774f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Navigate the code iframe to the given url and update the code popout link.
784f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {string} url The target URL.
794f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {Object} opt_window Window dependency injection for testing only.
804f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
814f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.navigateToCode = function(url, opt_window) {
824f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (!opt_window) opt_window = window;
834f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // Each iframe is represented by two distinct objects in the DOM:  an iframe
844f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // object and a window object.  These do not expose the same capabilities.
854f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // Here we need to get the window representation to get the location member,
864f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // so we access it directly through window[] since jQuery returns the iframe
874f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // representation.
884f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // We replace location rather than set so as not to create a history for code
894f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // navigation.
904f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  opt_window['code-display'].location.replace(url);
914f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var k = url.indexOf('&');
924f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (k != -1) url = url.slice(0, k);
934f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  k = url.indexOf('fileprint=');
944f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (k != -1) url = url.slice(k+10, url.length);
954f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#code-popout-link').attr('href', url);
964f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
974f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
984f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
994f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Selects the first comment from the list and forces a refresh of the code
1004f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * view.
1014f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
1024f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.selectFirstComment = function() {
1034f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // TODO(rsc): handle case where there are no comments
1044f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var firstSourcererLink = this.context.find('.comment:first');
1054f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.changeSelectedComment(firstSourcererLink);
1064f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
1074f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1084f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
1094f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Sets the target on all links nested inside comments to be _blank.
1104f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
1114f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.targetCommentLinksAtBlank = function() {
1124f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('.comment a[href], #description a[href]').each(function() {
1134f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    if (!this.target) this.target = '_blank';
1144f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  });
1154f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
1164f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1174f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
1184f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Installs event handlers for all the events we care about.
1194f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
1204f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.installEventHandlers = function() {
1214f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var self = this;
1224f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1234f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('.comment')
1244f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .click(function(event) {
1254f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        if (jQuery(event.target).is('a[href]')) return true;
1264f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        self.changeSelectedComment(jQuery(this));
1274f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        return false;
1284f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      });
1294f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1304f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#code-selector')
1314f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .change(function() {self.navigateToCode(jQuery(this).val());});
1324f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1334f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#description-table .quote-feet.setting')
1344f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .click(function() {self.toggleDescription(jQuery(this)); return false;});
1354f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1364f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.sizer
1374f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .mousedown(function(ev) {self.startSizerDrag(ev); return false;});
1384f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.overlay
1394f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .mouseup(function(ev) {self.endSizerDrag(ev); return false;})
1404f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .mousemove(function(ev) {self.handleSizerDrag(ev); return false;});
1414f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1424f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#prev-comment')
1434f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .click(function() {
1444f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          self.changeSelectedComment(self.lastSelected.prev()); return false;
1454f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      });
1464f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1474f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#next-comment')
1484f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .click(function() {
1494f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          self.changeSelectedComment(self.lastSelected.next()); return false;
1504f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      });
1514f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1524f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // Workaround for Firefox 2 and 3, which steal focus from the main document
1534f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // whenever the iframe content is (re)loaded.  The input field is not shown,
1544f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // but is a way for us to bring focus back to a place where we can detect
1554f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // keypresses.
1564f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#code-display')
1574f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      .load(function(ev) {self.shortcutInput.focus();});
1584f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1594f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  jQuery(document).keypress(function(ev) {
1604f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    switch(ev.which) {
1614f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      case 110:  // 'n'
1624f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          self.changeSelectedComment(self.lastSelected.next());
1634f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          return false;
1644f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      case 112:  // 'p'
1654f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          self.changeSelectedComment(self.lastSelected.prev());
1664f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          return false;
1674f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      default:  // ignore
1684f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    }
1694f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  });
1704f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1714f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  window.onresize = function() {self.updateHeight();};
1724f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
1734f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1744f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
1754f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Starts dragging the pane sizer.
1764f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {Object} ev The mousedown event that started us dragging.
1774f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
1784f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.startSizerDrag = function(ev) {
1794f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.initialCodeWidth = this.codeColumn.width();
1804f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.initialCommentsWidth = this.commentColumn.width();
1814f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.initialMouseX = ev.pageX;
1824f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.overlay.show();
1834f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
1844f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
1854f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
1864f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Handles dragging the pane sizer.
1874f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {Object} ev The mousemove event updating dragging position.
1884f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
1894f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.handleSizerDrag = function(ev) {
1904f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var delta = ev.pageX - this.initialMouseX;
1914f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (this.codeColumn.is('.right')) delta = -delta;
1924f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var proposedCodeWidth = this.initialCodeWidth + delta;
1934f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var proposedCommentWidth = this.initialCommentsWidth - delta;
1944f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var mw = CodewalkViewer.MIN_PANE_WIDTH;
1954f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (proposedCodeWidth < mw) delta = mw - this.initialCodeWidth;
1964f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (proposedCommentWidth < mw) delta = this.initialCommentsWidth - mw;
1974f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  proposedCodeWidth = this.initialCodeWidth + delta;
1984f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  proposedCommentWidth = this.initialCommentsWidth - delta;
1994f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // If window is too small, don't even try to resize.
2004f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (proposedCodeWidth < mw || proposedCommentWidth < mw) return;
2014f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeColumn.width(proposedCodeWidth);
2024f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.commentColumn.width(proposedCommentWidth);
2034f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.options.codeWidth = parseInt(
2044f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      this.codeColumn.width() /
2054f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      (this.codeColumn.width() + this.commentColumn.width()) * 100);
2064f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#code-column-width').text(this.options.codeWidth + '%');
2074f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2084f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2094f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
2104f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Ends dragging the pane sizer.
2114f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {Object} ev The mouseup event that caused us to stop dragging.
2124f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
2134f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.endSizerDrag = function(ev) {
2144f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.overlay.hide();
2154f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.updateHeight();
2164f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2174f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2184f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
2194f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Toggles the Codewalk description between being shown and hidden.
2204f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {jQuery} target The target that was clicked to trigger this function.
2214f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
2224f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.toggleDescription = function(target) {
2234f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var description = this.context.find('#description');
2244f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  description.toggle();
2254f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  target.find('span').text(description.is(':hidden') ? 'show' : 'hide');
2264f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.updateHeight();
2274f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2284f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2294f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
2304f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Changes the side of the window on which the code is shown and saves the
2314f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * setting in a cookie.
2324f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {string?} codeSide The side on which the code should be, either
2334f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen *     'left' or 'right'.
2344f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
2354f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.changeCodeSide = function(codeSide) {
2364f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var commentSide = codeSide == 'left' ? 'right' : 'left';
2374f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#set-code-' + codeSide).addClass('selected');
2384f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.context.find('#set-code-' + commentSide).removeClass('selected');
2394f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // Remove previous side class and add new one.
2404f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeColumn.addClass(codeSide).removeClass(commentSide);
2414f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.commentColumn.addClass(commentSide).removeClass(codeSide);
2424f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.sizer.css(codeSide, 'auto').css(commentSide, 0);
2434f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.options.codeSide = codeSide;
2444f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2454f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2464f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
2474f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Adds selected class to newly selected comment, removes selected style from
2484f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * previously selected comment, changes drop down options so that the correct
2494f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * file is selected, and updates the code popout link.
2504f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * @param {jQuery} target The target that was clicked to trigger this function.
2514f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
2524f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.changeSelectedComment = function(target) {
2534f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var currentFile = target.find('.comment-link').attr('href');
2544f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (!currentFile) return;
2554f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2564f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  if (!(this.lastSelected && this.lastSelected.get(0) === target.get(0))) {
2574f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    if (this.lastSelected) this.lastSelected.removeClass('selected');
2584f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    target.addClass('selected');
2594f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    this.lastSelected = target;
2604f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    var targetTop = target.position().top;
2614f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    var parentTop = target.parent().position().top;
2624f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    if (targetTop + target.height() > parentTop + target.parent().height() ||
2634f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        targetTop < parentTop) {
2644f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      var delta = targetTop - parentTop;
2654f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen      target.parent().animate(
2664f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          {'scrollTop': target.parent().scrollTop() + delta},
2674f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen          Math.max(delta / 2, 200), 'swing');
2684f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    }
2694f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    var fname = currentFile.match(/(?:select=|fileprint=)\/[^&]+/)[0];
2704f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    fname = fname.slice(fname.indexOf('=')+2, fname.length);
2714f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    this.context.find('#code-selector').val(fname);
2724f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    this.context.find('#prev-comment').toggleClass(
2734f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        'disabled', !target.prev().length);
2744f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen    this.context.find('#next-comment').toggleClass(
2754f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen        'disabled', !target.next().length);
2764f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  }
2774f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2784f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // Force original file even if user hasn't changed comments since they may
2794f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  // have nagivated away from it within the iframe without us knowing.
2804f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.navigateToCode(currentFile);
2814f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2824f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2834f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen/**
2844f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * Updates the viewer by changing the height of the comments and code so that
2854f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * they fit within the height of the window.  The function is typically called
2864f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen * after the user changes the window size.
2874f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen */
2884f7f559a4b744258a796dd591b11bd88e4a6dc7Dan WillemsenCodewalkViewer.prototype.updateHeight = function() {
2894f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var windowHeight = jQuery(window).height() - 5  // GOK
2904f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var areaHeight = windowHeight - this.codeArea.offset().top
2914f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var footerHeight = this.context.find('#footer').outerHeight(true)
2924f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.commentArea.height(areaHeight - footerHeight - this.context.find('#comment-options').outerHeight(true))
2934f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var codeHeight = areaHeight - footerHeight - 15  // GOK
2944f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeArea.height(codeHeight)
2954f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.codeDisplay.height(codeHeight - this.codeDisplay.offset().top + this.codeArea.offset().top);
2964f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  this.sizer.height(codeHeight);
2974f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen};
2984f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen
2994f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsenwindow.initFuncs.push(function() {
3004f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  var viewer = new CodewalkViewer(jQuery('#codewalk-main'));
3014f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  viewer.selectFirstComment();
3024f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  viewer.targetCommentLinksAtBlank();
3034f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  viewer.installEventHandlers();
3044f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen  viewer.updateHeight();
3054f7f559a4b744258a796dd591b11bd88e4a6dc7Dan Willemsen});
306