Skip to content
wiki.fftac.org

Book Shell - Source Excerpt 16

Back to Book Shell

Summary

This source excerpt preserves a bounded section of Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js so readers can inspect the evidence without opening the full source file.

**Source path:** Spiralist/wp-content/plugins/ns12-manuscript/assets/js/book-shell.js

viewport.addEventListener('dblclick', (event) => {
      if (zoom.hidden) {
        return;
      }

      event.preventDefault();
      if (state.scale <= state.minScale + 0.01) {
        zoomTo(2, event.clientX, event.clientY);
      } else {
        fitToViewport();
      }
    });

    viewport.addEventListener(
      'touchstart',
      (event) => {
        if (zoom.hidden || event.touches.length !== 2) {
          if (event.touches.length < 2) {
            stopPinching();
          }
          return;
        }

        const distance = getTouchDistance(event.touches);
        if (!distance) {
          return;
        }

        state.dragging = false;
        state.pinching = true;
        state.pinchDistance = distance;
        state.pinchScale = state.scale;
      },
      { passive: true }
    );

    viewport.addEventListener(
      'touchmove',
      (event) => {
        if (zoom.hidden || !state.pinching || event.touches.length !== 2) {
          return;
        }

        const distance = getTouchDistance(event.touches);
        if (!distance) {
          return;
        }

        const midpoint = getTouchMidpoint(event.touches);
        zoomTo(state.pinchScale * (distance / state.pinchDistance), midpoint.clientX, midpoint.clientY);
        event.preventDefault();
      },
      { passive: false }
    );

    viewport.addEventListener('touchend', (event) => {
      if (event.touches.length < 2) {
        stopPinching();
      }
    });

    viewport.addEventListener('touchcancel', () => {
      stopPinching();
    });

    viewport.addEventListener('pointerdown', (event) => {
      if (zoom.hidden || state.scale <= state.minScale + 0.01) {
        return;
      }

      if (state.pinching) {
        return;
      }

      if (event.pointerType === 'mouse' && event.button !== 0) {
        return;
      }

      state.dragging = true;
      state.lastPointerX = event.clientX;
      state.lastPointerY = event.clientY;
      setPointerCapture(viewport, event.pointerId);
      render();
      event.preventDefault();
    });

    viewport.addEventListener('pointermove', (event) => {
      if (!state.dragging) {
        return;
      }

      state.x += event.clientX - state.lastPointerX;
      state.y += event.clientY - state.lastPointerY;
      state.lastPointerX = event.clientX;
      state.lastPointerY = event.clientY;
      render();
    });

    viewport.addEventListener('pointerup', (event) => {
      stopDragging(event);
    });

    viewport.addEventListener('pointercancel', (event) => {
      stopDragging(event);
    });

    window.addEventListener('resize', () => {
      if (zoom.hidden) {
        return;
      }

      render();
    });

    document.addEventListener('keydown', (event) => {
      if (zoom.hidden) {
        return;
      }

      if (event.key === 'Escape') {
        event.preventDefault();
        closeZoom();
        return;
      }

      if (event.altKey || event.ctrlKey || event.metaKey) {
        return;
      }

      if (event.key === '+' || event.key === '=') {
        event.preventDefault();
        zoomTo(state.scale + 0.25);
        return;
      }

      if (event.key === '-' || event.key === '_') {
        event.preventDefault();
        zoomTo(state.scale - 0.25);
        return;
      }

      if (event.key === '0') {
        event.preventDefault();
        fitToViewport();
        return;
      }

      const step = event.shiftKey ? 120 : 60;

      if (event.key === 'ArrowLeft') {
        event.preventDefault();
        state.x += step;
        render();
      }

      if (event.key === 'ArrowRight') {
        event.preventDefault();
        state.x -= step;
        render();
      }

      if (event.key === 'ArrowUp') {
        event.preventDefault();
        state.y += step;
        render();
      }

      if (event.key === 'ArrowDown') {
        event.preventDefault();
        state.y -= step;
        render();
      }
    });

    render();
  });
  renderWorkbenchExamples();
  refreshParticipantState();

});