<commit_before>/* Buttons that go to the next/previous post or backwards and forwards.
 * Copyright (C) 2014 <NAME> (born 1979)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/// <reference path="../../typedefs/react/react.d.ts" />
/// <reference path="../../typedefs/keymaster/keymaster.d.ts" />

//------------------------------------------------------------------------------
   module debiki2.postnavigation {
//------------------------------------------------------------------------------

var d = { i: debiki.internal, u: debiki.v0.util };
var r = React.DOM;

var visitedPostIds = [];
var currentVisitedPostIndex = -1;


var PostNavigation = React.createClass({
  canGoBack: function() {
    return this.props.currentVisitedPostIndex >= 1;
  },
  canGoForward: function() {
    return this.props.currentVisitedPostIndex >= 0 &&
        this.props.currentVisitedPostIndex < this.props.visitedPostIds.length - 1;
  },
  componentDidMount: function() {
    key('b', this.goBack);
    key('f', this.goForward);
  },
  componentWillUnmount: function() {
    key.unbind('b', this.goBack);
    key.unbind('f', this.goForward);
  },
  goBack: function() {
    if (!this.canGoBack()) return;
    var backPostId = this.props.visitedPostIds[this.props.currentVisitedPostIndex - 1];
    this.props.decreaseCurrentPostIndex();
    d.i.showAndHighlightPost($('#post-' + backPostId));
  },
  goForward: function() {
    if (!this.canGoForward()) return;
    var forwPostId = this.props.visitedPostIds[this.props.currentVisitedPostIndex + 1];
    this.props.increaseCurrentPostIndex();
    d.i.showAndHighlightPost($('#post-' + forwPostId));
  },
  render: function() {
    var buttons = [];
    buttons.push(
        r.button({
            id: 'dw-post-nav-back-btn', onClick: this.goBack, className: 'btn btn-default',
                disabled: !this.canGoBack() },
            r.span({}, 'B'), 'ack'));
    buttons.push(
        r.button({
            id: 'dw-post-nav-forw-btn', onClick: this.goForward, className: 'btn btn-default',
                disabled: !this.canGoForward() },
            r.span({}, 'F'), 'orward'));
    return this.props.visitedPostIds.length === 0 ? null : r.div({ id: 'dw-post-nav-panel'}, buttons);
  }
});


export function renderPostNavigationPanel() {
  React.renderComponent(
      PostNavigation({
        decreaseCurrentPostIndex: () => {
          currentVisitedPostIndex -= 1;
          renderPostNavigationPanel();
        },
        increaseCurrentPostIndex: () => {
          currentVisitedPostIndex += 1;
          renderPostNavigationPanel();
        },
        visitedPostIds: visitedPostIds,
        currentVisitedPostIndex: currentVisitedPostIndex
      }),
      document.getElementById('dw-posts-navigation'));
}


export function addVisitedPosts(currentPostId: number, nextPostId: number) {
  visitedPostIds.splice(currentVisitedPostIndex + 1, 999999);
  if (visitedPostIds.length && visitedPostIds[visitedPostIds.length - 1] === currentPostId) {
    // Don't duplicate postId
  }
  else {
    visitedPostIds.push(currentPostId);
  }
  visitedPostIds.push(nextPostId);
  currentVisitedPostIndex = visitedPostIds.length - 1;
  renderPostNavigationPanel();
}


//------------------------------------------------------------------------------
   }
//------------------------------------------------------------------------------
// vim: fdm=marker et ts=2 sw=2 tw=0 fo=tcqwn list<commit_msg>Remember scroll position when going back to last post.<commit_after>/* Buttons that go to the next/previous post or backwards and forwards.
 * Copyright (C) 2014 <NAME> (born 1979)
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

/// <reference path="../../typedefs/react/react.d.ts" />
/// <reference path="../../typedefs/keymaster/keymaster.d.ts" />

//------------------------------------------------------------------------------
   module debiki2.postnavigation {
//------------------------------------------------------------------------------

var d = { i: debiki.internal, u: debiki.v0.util };
var r = React.DOM;

var visitedPosts = [];
var currentVisitedPostIndex = -1;


var PostNavigation = React.createClass({
  canGoBack: function() {
    return this.props.currentVisitedPostIndex >= 1;
  },
  canGoForward: function() {
    return this.props.currentVisitedPostIndex >= 0 &&
        this.props.currentVisitedPostIndex < this.props.visitedPosts.length - 1;
  },
  componentDidMount: function() {
    key('b', this.goBack);
    key('f', this.goForward);
  },
  componentWillUnmount: function() {
    key.unbind('b', this.goBack);
    key.unbind('f', this.goForward);
  },
  goBack: function() {
    if (!this.canGoBack()) return;
    var backPost = this.props.visitedPosts[this.props.currentVisitedPostIndex - 1];
    this.props.decreaseCurrentPostIndex();
    if (typeof backPost.windowLeft !== 'undefined' && (
        backPost.windowLeft !== $(window).scrollLeft() ||
        backPost.windowTop !== $(window).scrollTop())) {
      // Restore the original window top and left coordinates, so the Back button
      // really moves back to the original position.
      $('html, body').animate({
        'scrollTop': backPost.windowTop,
        'scrollLeft': backPost.windowLeft
      }, 'slow', 'swing').queue(function(next) {
        d.i.showAndHighlightPost($('#post-' + backPost.postId));
        next();
      });
    }
    else {
      d.i.showAndHighlightPost($('#post-' + backPost.postId));
    }
  },
  goForward: function() {
    if (!this.canGoForward()) return;
    var forwPost = this.props.visitedPosts[this.props.currentVisitedPostIndex + 1];
    this.props.increaseCurrentPostIndex();
    d.i.showAndHighlightPost($('#post-' + forwPost.postId));
  },
  render: function() {
    var buttons = [];
    buttons.push(
        r.button({
            id: 'dw-post-nav-back-btn', onClick: this.goBack, className: 'btn btn-default',
                disabled: !this.canGoBack() },
            r.span({}, 'B'), 'ack'));
    buttons.push(
        r.button({
            id: 'dw-post-nav-forw-btn', onClick: this.goForward, className: 'btn btn-default',
                disabled: !this.canGoForward() },
            r.span({}, 'F'), 'orward'));
    return this.props.visitedPosts.length === 0 ? null : r.div({ id: 'dw-post-nav-panel'}, buttons);
  }
});


export function renderPostNavigationPanel() {
  React.renderComponent(
      PostNavigation({
        decreaseCurrentPostIndex: () => {
          currentVisitedPostIndex -= 1;
          renderPostNavigationPanel();
        },
        increaseCurrentPostIndex: () => {
          currentVisitedPostIndex += 1;
          renderPostNavigationPanel();
        },
        visitedPosts: visitedPosts,
        currentVisitedPostIndex: currentVisitedPostIndex
      }),
      document.getElementById('dw-posts-navigation'));
}


export function addVisitedPosts(currentPostId: number, nextPostId: number) {
  visitedPosts.splice(currentVisitedPostIndex + 1, 999999);
  if (visitedPosts.length && visitedPosts[visitedPosts.length - 1].postId === currentPostId) {
    // Don't duplicate postId.
    visitedPosts.splice(visitedPosts.length - 1, 1);
  }
  visitedPosts.push({
    windowLeft: $(window).scrollLeft(),
    windowTop: $(window).scrollTop(),
    postId: currentPostId
  });
  visitedPosts.push({ postId: nextPostId });
  currentVisitedPostIndex = visitedPosts.length - 1;
  renderPostNavigationPanel();
}


//------------------------------------------------------------------------------
   }
//------------------------------------------------------------------------------
// vim: fdm=marker et ts=2 sw=2 tw=0 fo=tcqwn list
{'fraction_non_alphanumeric': 0.19747662498591867, 'fraction_numerical': 0.007434944237918215, 'mean_word_length': 2.4080614203454895, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2637489', 'n_tokens_mistral': 2559, 'n_tokens_neox': 2464, 'n_words': 620}