lichen-annotate-pdf
Version:
Annotation layer for pdf.js in vue fork of Aaron Leong pdf-annotate-vue
311 lines (287 loc) • 8.52 kB
JavaScript
import PDFJSAnnotate from '../PDFJSAnnotate';
import { appendChild } from '../render/appendChild';
let MathLive = require('mathlive/dist/mathlive.mjs');
import { CUSTOM_KEYBOARD_LAYER } from '../UI/keyboardOptions.js';
// import { renderMathInDocument } from 'https://unpkg.com/mathlive/dist/mathlive.min.mjs';
// document.addEventListener("load", () => {
// renderMathInDocument();
// });
import {
BORDER_COLOR,
findSVGAtPoint,
getMetadata,
convertToSvgPoint
} from './utils';
let _enabled = false;
let input;
let mathField;
let _textSize;
let _textColor;
/**
* Handle document.mouseup event
*
* @param {Event} e The DOM event to handle
*/
function handleDocumentMouseup (e) {
if (!findSVGAtPoint(e.clientX, e.clientY)) {
console.log('deja un input || !findSVGAtPoint(e.clientX, e.clientY)')
return;
}
if (!e.srcElement.classList.contains('annotationLayer')) {
console.log('on a pas de annotationLayer')
return;
}
input = document.createElement('input');
input.setAttribute('id', 'pdf-annotate-text-input');
input.setAttribute('placeholder', 'Insérer du texte ici...');
input.style.border = `3px solid ${BORDER_COLOR}`;
input.style.borderRadius = '3px';
input.style.backgroundColor = 'rgba(255,255,255,0.85)';
input.style.position = 'absolute';
input.style.top = `${e.clientY}px`;
input.style.left = `${e.clientX}px`;
input.style.fontSize = `${_textSize}px`;
input.style.zIndex = '999999';
input.style.padding = '5px';
input.addEventListener('blur', handleInputBlur);
input.addEventListener('keyup', handleInputKeyup);
document.body.appendChild(input);
input.focus();
}
function handleDocumentMathMouseup (e) {
// on gère les maths
// console.log('on est ici', input)
if (!findSVGAtPoint(e.clientX, e.clientY)) {
console.log('not find svg')
return;
}
if (!e.srcElement.classList.contains('annotationLayer')) {
return;
}
// on va chercker si un truc est déjà là
const temp = window.document.getElementById('pdf-annotate-text-input')
if (temp) {
temp.remove();
}
input = document.createElement('div');
input.setAttribute('id', 'pdf-annotate-text-input');
input.setAttribute('placeholder', 'Insérer du texte ici...');
input.style.border = `3px solid ${BORDER_COLOR}`;
input.style.borderRadius = '3px';
input.style.backgroundColor = 'rgba(255,255,255,0.85)';
input.style.position = 'absolute';
input.style.top = `${e.clientY}px`;
input.style.left = `${e.clientX}px`;
input.style.fontSize = `${_textSize}px`;
input.style.zIndex = '999999';
input.style.padding = '5px';
document.body.appendChild(input);
mathField = MathLive.makeMathField('pdf-annotate-text-input', {
locale: 'fr',
customVirtualKeyboardLayers: CUSTOM_KEYBOARD_LAYER,
customVirtualKeyboards: { 'custom-keyboard': { label: '123', tooltip: 'Numérique', layer: 'custom-layer' } },
virtualKeyboards: 'custom-keyboard symbols',
virtualKeyboardMode: 'manual',
onBlur: (test) => {
handleMathBlur();
}
})
}
/**
* Handle input.blur event
*/
function handleInputBlur () {
saveText();
}
function handleMathBlur () {
saveMathText();
}
/**
* Handle input.keyup event
*
* @param {Event} e The DOM event to handle
*/
function handleInputKeyup (e) {
if (e.keyCode === 27) {
closeInput();
}
else if (e.keyCode === 13) {
saveText();
}
}
/**
* Save a text annotation from input
*/
function saveText () {
let value = (input.value) ? input.value.replace(/ +$/, '') : '';
if (value.length > 0) {
let clientX = parseInt(input.style.left, 10);
let clientY = parseInt(input.style.top, 10);
let svg = findSVGAtPoint(clientX, clientY);
if (!svg) {
return;
}
let height = _textSize;
let { documentId, pageNumber, viewport } = getMetadata(svg);
let scale = 1 / viewport.scale;
let rect = svg.getBoundingClientRect();
let pt = convertToSvgPoint([
clientX - rect.left,
clientY - rect.top + height], svg, viewport);
let annotation = {
type: 'textbox',
size: _textSize * scale,
color: _textColor,
content: value,
x: pt[0],
y: pt[1],
rotation: -viewport.rotation
};
PDFJSAnnotate.getStoreAdapter().addAnnotation(documentId, pageNumber, annotation)
.then((annotation) => {
appendChild(svg, annotation);
});
}
closeInput();
}
async function saveMathText () {
let value = (mathField.getValue()) ? mathField.getValue() : '';
// console.log('SAVE MATH TEXT', value)
if (value.length > 0) {
const SVGCODE = await mathToSvg(value)
// console.log('LE SCG CORE', SVGCODE)
let clientX = parseInt(input.style.left, 10);
let clientY = parseInt(input.style.top, 10);
let svg = findSVGAtPoint(clientX, clientY);
if (!svg) {
return;
}
let height = _textSize;
let { documentId, pageNumber, viewport } = getMetadata(svg);
let scale = 1 / viewport.scale;
let rect = svg.getBoundingClientRect();
let pt = convertToSvgPoint([
clientX - rect.left,
clientY - rect.top + height], svg, viewport);
let annotation = {
type: 'image',
size: _textSize * scale,
color: _textColor,
html: SVGCODE,
x: pt[0],
y: pt[1],
rotation: -viewport.rotation
};
PDFJSAnnotate.getStoreAdapter().addAnnotation(documentId, pageNumber, annotation)
.then((annotation) => {
appendChild(svg, annotation);
});
}
MathLive.renderMathInDocument();
closeMathInput();
}
function mathToSvg (formula) {
return new Promise((resolve, reject) => {
const fixedFormula = formula.replaceAll('\\mleft', '').replaceAll('\\mright?', '').replaceAll('\\mright', '')
let wrapper = window.MathJax.tex2svg(fixedFormula, { em: 10, ex: 5, display: true })
let output = { svg: "", img: "" }
let mjOut = wrapper.getElementsByTagName("svg")[0]
// mjOut.setAttribute("xmlns", "http://www.w3.org/2000/svg")
output.svg = mjOut.outerHTML
var image = new Image()
image.src = 'data:image/svg+xml;base64,' + window.btoa(unescape(encodeURIComponent(output.svg)));
image.onload = function () {
var canvas = document.createElement('canvas');
canvas.width = image.width;
canvas.height = image.height;
var context = canvas.getContext('2d');
context.drawImage(image, 0, 0);
output.img = canvas.toDataURL('image/png');
resolve(output.img)
}
image.onerror = function () {
reject()
}
})
}
/**
* Close the input
*/
function closeInput () {
if (input) {
input.removeEventListener('blur', handleInputBlur);
input.removeEventListener('keyup', handleInputKeyup);
document.body.removeChild(input);
input = null;
}
}
function closeMathInput () {
// console.log('on close')
if (input) {
document.body.removeChild(input);
let temp = document.getElementsByClassName('ML__virtual-keyboard-toggle');
if (temp[0]) {
temp[0].remove()
}
input = null;
mathField = null;
}
}
/**
* Set the text attributes
*
* @param {Number} textSize The size of the text
* @param {String} textColor The color of the text
*/
export function setText (textSize = 16, textColor = '000000') {
_textSize = parseInt(textSize, 10);
_textColor = textColor;
}
/**
* Enable text behavior
*/
export function enableText () {
if (_enabled) {
return;
}
_enabled = true;
document.addEventListener('mouseup', handleDocumentMouseup);
}
/**
* Disable text behavior
*/
export function disableText (val) {
if (val) {
_enabled = false;
document.removeEventListener('mouseup', handleDocumentMouseup);
} else {
if (!_enabled) { return; }
_enabled = false;
document.removeEventListener('mouseup', handleDocumentMouseup);
}
}
export function enableMathText () {
if (_enabled) {
return;
}
_enabled = true;
document.addEventListener('mouseup', handleDocumentMathMouseup);
}
export function disableMathText (val) {
if (val) {
_enabled = false;
document.removeEventListener('mouseup', handleDocumentMathMouseup);
const temp = window.document.getElementById('pdf-annotate-text-input');
if (temp) {
temp.remove();
}
} else {
if (!_enabled) { return; }
_enabled = false;
document.removeEventListener('mouseup', handleDocumentMathMouseup);
const temp = window.document.getElementById('pdf-annotate-text-input');
if (temp) {
temp.remove();
}
}
}