<commit_before>'use strict';

class Reader {

    constructor (data) {
        this.viewerEl = document.querySelector('.viewer');
        this.viewBox = document.querySelector('.view-box');
        this.panel = document.querySelector('.viewer .panel');
        this.page = document.querySelector('.viewer .page');

        this.debug = false;
        this.fitScreen = false;

        this.pageDimensions = null;
        this.pageOffsetY = 0;
        this.screenWidth = window.innerWidth;
        this.screenHeight = window.innerHeight;

        this.currentPageIndex = 0;
        this.currentPanelIndex = 0;
        this._setPageHash();

        this.pages = data;

        this._addEventListeners();

        this._loadImage(this.pages[this.currentPageIndex].image).then(_ => {
          if (this.fitScreen) {
            this.viewerEl.classList.add('fitscreen');
          }

          this._calculatePageDimensions();

          if (this.fitScreen) {
            this.viewerEl.style.width = this.pageDimensions.width + 'px';
          }

          this._drawPanel(this.currentPanelIndex);
          this._positionPageIfNeeded();

          if (this.debug) {
            this._drawDebugPanels();
          }

          // Display the panels after initial setup is complete
          this.page.classList.remove('hidden');
          this.panel.classList.remove('hidden');
        });
    }

    _loadImage(url) {
      return new Promise((resolve, reject) => {
        this.panel.src = url;
        this.page.src = url;

        this.panel.onload = function() {
          resolve();
        }
      });
    }

    _addEventListeners() {
      window.addEventListener('resize', this._recalc.bind(this));
      window.addEventListener('keydown', event => {
        if (event.keyCode === 39) { // right
          this._nextPanel();
        }
        if (event.keyCode === 37) { // left
          this._previousPanel();
        }
      });
    }

    _recalc() {
      this._calculatePageDimensions();
      if (this.fitScreen) {
        this.viewerEl.style.width = this.pageDimensions.width + 'px';
      }

      this.screenWidth = window.innerWidth;
      this.screenHeight = window.innerHeight;
      this._positionPageIfNeeded();
      if (this.debug) {
        this._drawDebugPanels();
      }
    }

    _calculatePageDimensions() {
      this.pageDimensions = this.page.getBoundingClientRect();
    }

    _drawPanel(index) {
      const panel = this.pages[this.currentPageIndex].panels[index];

      const path = panel.path;

      this.panel.setAttribute('style',
        `-webkit-clip-path: polygon(${path}); clip-path: polygon(${path});
        clip-path: polygon(${path}); clip-path: polygon(${path});`
      );
    }

    _drawDebugPanels() {
      document.querySelectorAll('.debug-box').forEach(node => node.remove());

      const box = document.createElement('div');
      box.classList.add('debug-box');

      const panels = this.pages[this.currentPageIndex].panels;
      for (var i = 0; i < panels.length; i++) {
        const clone = box.cloneNode();

        // 15 = page margin
        clone.style.left = (panels[i].x * this.pageDimensions.width / 100) + 15 + 'px';
        clone.style.top = (panels[i].y * this.pageDimensions.height / 100) + this.pageDimensions.top + 'px';
        clone.style.width = panels[i].width * this.pageDimensions.width / 100 + 'px';
        clone.style.height = panels[i].height * this.pageDimensions.height / 100 + 'px';

        this.viewerEl.appendChild(clone);
      }
    }

    _positionPageIfNeeded() {
      const panel = this.pages[this.currentPageIndex].panels[this.currentPanelIndex];

      // Figure out the Panel position on the page in pixels.
      const panelY = panel.y * this.pageDimensions.height / 100;
      const panelX = panel.x * this.pageDimensions.width / 100;
      const panelWidth = panel.width * this.pageDimensions.width / 100;
      const panelHeight = panel.height * this.pageDimensions.height / 100;

      // Check if panel is off screen.
      if ((panelHeight + panelY) - this.pageOffsetY > this.screenHeight - this.pageDimensions.top) {
        // calculate where to scoll
        console.log('offscreen');
        this.pageOffsetY = panelY;
      }

      if (panelY < this.pageOffsetY) {
        // reset scroll to panel
        this.pageOffsetY = panelY;
      }

      this.viewerEl.scrollTop = this.pageOffsetY;
    }

    _setPageHash() {
      let currentPage = this.currentPageIndex + 1;
      let currentPanel = this.currentPanelIndex + 1;

      if (currentPage < 10)
        currentPage = '0' + currentPage;

      if (currentPanel < 10)
        currentPanel = '0' + currentPanel;

      window.location.hash = currentPage + '-' + currentPanel;
    }

    _nextPanel() {
      let index = this.currentPanelIndex + 1;

      if (index !== this.pages[this.currentPageIndex].panels.length) {
        const clone = this.panel.cloneNode();
        this.viewBox.appendChild(clone);
      }

      if (index > this.pages[this.currentPageIndex].panels.length - 1) {
        // last slide

        if (this.currentPageIndex < this.pages.length - 1) {
          console.log('goToNextPage');
          this._nextPage();
          return;
        }

        console.log('last slide');<commit_msg>draw previous panels if loaded via a hash; refactor<commit_after>'use strict';

class Reader {

    constructor (data) {
        this.viewerEl = document.querySelector('.viewer');
        this.viewBox = document.querySelector('.view-box');
        this.panel = document.querySelector('.viewer .panel');
        this.page = document.querySelector('.viewer .page');

        this.debug = false;
        this.fitScreen = false;

        this.pageDimensions = null;
        this.pageOffsetY = 0;
        this.screenWidth = window.innerWidth;
        this.screenHeight = window.innerHeight;

        this.pages = data;

        this._setInitialIndexes();

        if (!window.location.hash)
          this._setPageHash();

        this._addEventListeners();

        this._loadImage(this.pages[this.currentPageIndex].image).then(_ => {
          if (this.fitScreen) {
            this.viewerEl.classList.add('fitscreen');
          }

          this._calculatePageDimensions();

          if (this.fitScreen) {
            this.viewerEl.style.width = this.pageDimensions.width + 'px';
          }

          // If the panel index is higher than 0 it means
          // we loaded into the page on a specific panel.
          // therefor draw all panels up and to the current index.
          if (this.currentPanelIndex > 0) {
            this._drawUpToPanel(this.currentPanelIndex);
          } else {
            this._drawPanel(this.currentPanelIndex);
          }

          this._positionPageIfNeeded();

          if (this.debug) {
            this._drawDebugPanels();
          }

          // Display the panels after initial setup is complete
          this.page.classList.remove('hidden');
          document.querySelectorAll('.panel').forEach(panel => panel.classList.remove('hidden'));
        });
    }

    _setInitialIndexes() {
      if (window.location.hash) {
        let match = window.location.hash.match(/(\d+)-(\d+)/);

        if (!match)
          return;

        this.currentPageIndex = Math.min(
          Math.max(parseInt(parseInt(match[1]) - 1), 0), this.pages.length - 1);

        const maxPanels = this.pages[this.currentPageIndex].panels.length - 1;
        this.currentPanelIndex = Math.min(
          Math.max(parseInt(parseInt(match[2]) - 1), 0), maxPanels);

        return;
      }

      this.currentPageIndex = 0;
      this.currentPanelIndex = 0;
    }

    _loadImage(url) {
      return new Promise((resolve, reject) => {
        this.panel.src = url;
        this.page.src = url;

        this.panel.onload = function() {
          resolve();
        }
      });
    }

    _addEventListeners() {
      window.addEventListener('resize', this._recalc.bind(this));
      window.addEventListener('keydown', event => {
        if (event.keyCode === 39) { // right
          this._nextPanel();
        }
        if (event.keyCode === 37) { // left
          this._previousPanel();
        }
      });
    }

    _recalc() {
      this._calculatePageDimensions();
      if (this.fitScreen) {
        this.viewerEl.style.width = this.pageDimensions.width + 'px';
      }

      this.screenWidth = window.innerWidth;
      this.screenHeight = window.innerHeight;
      this._positionPageIfNeeded();
      if (this.debug) {
        this._drawDebugPanels();
      }
    }

    _calculatePageDimensions() {
      this.pageDimensions = this.page.getBoundingClientRect();
    }

    _drawPanel(index) {
      const panel = this.pages[this.currentPageIndex].panels[index];

      const path = panel.path;

      this.panel.setAttribute('style',
        `-webkit-clip-path: polygon(${path}); clip-path: polygon(${path});
        clip-path: polygon(${path}); clip-path: polygon(${path});`
      );
      this.panel.setAttribute('data-index', index);
    }

    _drawDebugPanels() {
      document.querySelectorAll('.debug-box').forEach(node => node.remove());

      const box = document.createElement('div');
      box.classList.add('debug-box');

      const panels = this.pages[this.currentPageIndex].panels;
      for (var i = 0; i < panels.length; i++) {
        const clone = box.cloneNode();

        // 15 = page margin
        clone.style.left = (panels[i].x * this.pageDimensions.width / 100) + 15 + 'px';
        clone.style.top = (panels[i].y * this.pageDimensions.height / 100) + this.pageDimensions.top + 'px';
        clone.style.width = panels[i].width * this.pageDimensions.width / 100 + 'px';
        clone.style.height = panels[i].height * this.pageDimensions.height / 100 + 'px';

        this.viewerEl.appendChild(clone);
      }
    }

    _positionPageIfNeeded() {
      const panel = this.pages[this.currentPageIndex].panels[this.currentPanelIndex];

      // Figure out the Panel position on the page in pixels.
      const panelY = panel.y * this.pageDimensions.height / 100;
      const panelX = panel.x * this.pageDimensions.width / 100;
      const panelWidth = panel.width * this.pageDimensions.width / 100;
      const panelHeight = panel.height * this.pageDimensions.height / 100;

      // Check if panel is off screen.
      if ((panelHeight + panelY) - this.pageOffsetY > this.screenHeight - this.pageDimensions.top) {
        // calculate where to scoll
        console.log('offscreen');
        this.pageOffsetY = panelY;
      }

      if (panelY < this.pageOffsetY) {
        // reset scroll to panel
        this.pageOffsetY = panelY;
      }

      this.viewerEl.scrollTop = this.pageOffsetY;
    }

    _setPageHash() {
      let currentPage = this.currentPageIndex + 1;
      let currentPanel = this.currentPanelIndex + 1;

      if (currentPage < 10)
        currentPage = '0' + currentPage;

      if (currentPanel < 10)
        currentPanel = '0' + currentPanel;

      window.location.hash = currentPage + '-' + currentPanel;
    }

    _drawUpToPanel(index) {
      const max = this.pages[this.currentPageIndex].panels.length;
      const drawUpTo =
        Math.min(Math.max(parseInt(index + 1), 0), max);

      for (var i = 0; i < drawUpTo; i++) {
        this._drawPanel(i);

        if (i !== max) {
          const clone = this.panel.cloneNode();
          this.viewBox.appendChild(clone);
        }
      }
    }

    _nextPanel() {
      let index = this.currentPanelIndex + 1;

      if (index !== this.pages[this.currentPageIndex].panels.length) {
        const clone = this.panel.cloneNode();
        this.viewBox.appendChild(clone);
      }

      if (index > this.pages[this.currentPageIndex].panels.length - 1) {
        // last slide

        if (this.currentPageIndex < this.pages.length - 1) {
          console.log('goToNextPage');
          this._nextPage();
          return;
        }

        console.log('last slide');
{'fraction_non_alphanumeric': 0.13205502292621926, 'fraction_numerical': 0.008920383493122134, 'mean_word_length': 2.163502109704641, 'pattern_counts': {'":': 0, '<': 14, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '279389', 'n_tokens_mistral': 3654, 'n_tokens_neox': 3480, 'n_words': 665}