API Usage
Tips
To highlight key points, not all functions and parameters in every file are listed or explained. For more details, please refer to the corresponding files. If the file contents do not meet your workflow requirements, you can consult our technical team for assistance.
1. Initializing ElasticPDF
The initialization for a pure HTML + JavaScript project is as follows:
var elasticpdf_viewer = null;
function initialPDFEditor() {
// Listen for callbacks from PDF editor
listenPDFEditorMessage();
elasticpdf_viewer = document.getElementById('elasticpdf-iframe').contentWindow;
// PDF file URL, or you can use PDF base64 data
// Example of PDF base64: pdf_url ='data:application/pdf;base64,JVB...'
var pdf_url = 'https://app.elasticpdf.com/web/tutorial-607.pdf';
elasticpdf_viewer.postMessage({
"source": "elasticpdf",
"function_name": "initialApp",
"content": {
'language': 'zh-cn', // Interaction language, supports Chinese and English
'pdf_url': pdf_url,
'display_annotation_list': true, // Whether to expand annotation list by default
'read_only_model': false, // Whether read-only mode is activated by default
'member_info': { // User information
'id': 'elasticpdf_id',
'name': 'elasticpdf',
},
'show_reply_panel': true, // Whether clicking annotations shows the reply/edit panel
'modify_others_annotation': true, // Whether editing others' annotations is allowed
'path_merge_interval': 2000, // Interval in ms to auto-merge pen paths
'show_message': true, // Whether to display tips during operations
}
}, '*');
}2. Data Communication
The following functions demonstrate how to communicate with the ElasticPDF app component, i.e., sending and receiving data/commands. Example uses pure HTML + JavaScript.
// Listen for messages sent from the elasticpdf app
function listenPDFEditorMessage() {
window.addEventListener('message', (e) => {
if (e.data.source != 'elasticpdf') {
return;
}
// Listen for local file opening; optionally upload the file to the server
if (e.data.function_name == 'openLocalFile') {
// console.log('Local PDF loaded successfully');
uploadLocalFile(e.data.content);
reloadData();
}
// PDF loaded callback; you can import annotation files
// or add and generate new annotations here
if (e.data.function_name == 'pdfLoaded') {
// console.log('PDF loaded successfully');
// Example: add new annotation
// var page_number = 7;
// var anno_id = '1743689572423_1';
// highlightAnnotationWithArrowMark(page_number, anno_id);
reloadData();
}
// Receive edited PDF data; all annotations are written in standard format
if (e.data.function_name == 'downloadPDF') {
// Corresponding PDF file data
let file_name = e.data.content['file_name'];
let pdf_blob = e.data.content['pdf_blob'];
let pdf_base64 = e.data.content['pdf_base64'];
// console.log('PDF info', pdf_base64);
// If the document was not edited, pdf_base64 is still the filename
// pdf_base64 can be quickly uploaded to a server
postService('upload-pdf-data', {
'file_name': file_name,
'file_id': '123ddasfsdffads',
'file_data': pdf_base64,
});
}
// PDF annotation edit callback; annotations can be exported and sent to the server
// Every modification, including any add/update/delete, will trigger this data
if (e.data.function_name == 'annotationsModified') {
// Get standalone PDF annotation data without the PDF itself; very small size, suitable for cloud collaboration
let this_data = elasticpdf_viewer.pdfAnnotation.outputAnnotations();
let annotation_content = JSON.stringify(this_data['file_annotation']);
let file_name = this_data['file_name'];
// console.log('Annotation info', annotation_content);
postService('upload-annotation-data', {
'file_name': file_name,
'file_id': '123ddasfsdffads',
'file_annotation': annotation_content,
});
}
});
}3. Calling Internal Functions
Internal class functions allow you to easily call ElasticPDF app functions. Due to space limitations, the following content is only an example; more functions are available in the code package.
// Get PDF file data; results will be returned via the 'downloadPDF' callback
function getPDFData() {
elasticpdf_viewer.getPDFData();
}
// Open or close the annotation list
function openOrCloseAnnotationList() {
elasticpdf_viewer.editAnnotation();
}
// Export pure annotation objects for saving; saves network and bandwidth
function outputAnnotation() {
var this_data = elasticpdf_viewer.pdfAnnotation.outputAnnotations();
var content = JSON.stringify(this_data['file_annotation']);
// console.log('Export annotations', content);
}
// Clear all annotations in the current file
function clearAnnotation() {
elasticpdf_viewer.confirmToClearFileAnnotations();
elasticpdf_viewer.addOperationTips("Annotations cleared");
}
// Switch and open another document
function changeFile() {
var test_pdf = 'https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf';
elasticpdf_viewer.pdfAnnotation.refreshFabricState(1);
elasticpdf_viewer.pdfAnnotation.openFile(test_pdf);
elasticpdf_viewer.addOperationTips("File changed");
}
// Set or update the current user; easily match system user info
function setMember() {
var this_member = {
'id': 'test_id',
'name': 'test_name',
};
elasticpdf_viewer.setCurrentMemberId(this_member);
elasticpdf_viewer.addOperationTips("User set successfully");
}
// Load existing annotations into the current file
function reloadOldAnnotationData() {
var old_annotation = getOldAnnotation();
elasticpdf_viewer.setPureFileAnnotation({
'file_annotation': old_annotation
});
}
// Placeholder for reloading annotation business logic
async function reloadData() {
return;
}
// Function to communicate with backend server
async function postService(url, data) {
// Write logic for uploading annotations to server here
return;
}
// Generate mock old annotation data
function getOldAnnotation() {
var old_annotation = {
"annos-for-page-1": {
"page_id": "annos-for-page-1",
"page_canvas_container": {},
"page_annotations": [],
"page_canvas": {
"fabric_canvas": {
"version": "5.2.0",
"objects": [{
"type": "rect",
"version": "5.2.0",
"left": 64.38,
"top": 159.99,
"width": 608.27,
"height": 290.3,
"fill": "rgba(255,237,0,0.3)",
"stroke": "rgba(17,153,158,1)",
"erasable": true
}],
"background": "rgba(255, 255, 255, 0)"
},
"width": 994,
"height": 1407,
"fabric_canvas_json": {
"version": "5.2.0",
"objects": [{
"type": "rect",
"version": "5.2.0",
"left": 64.38,
"top": 159.99,
"width": 608.27,
"height": 290.3,
"fill": "rgba(255,237,0,0.3)",
"stroke": "rgba(17,153,158,1)",
"erasable": true,
"id": "1742436474916_1",
"hasControls": true,
"hasBorders": true,
"selectable": true,
"lockMovementX": false,
"lockMovementY": false,
"member_id": "elasticpdf_id",
"member_name": "elasticpdf",
"my_type": "rectangle",
"comment": "Add annotation",
"backup_opacity": 1,
"lockRotation": false
}],
"background": "rgba(255, 255, 255, 0)"
}
}
}
}
return JSON.stringify(old_annotation);
}4. Custom UI Buttons
Annotation Features Buttons
Annotation function buttons are generated via JavaScript code. You can easily control their visibility and modify their styles.
// Create the top annotation toolbar
function setAnnotationButtons() {
var annotation_buttons_node = document.getElementById('firefly-annotation-buttons');
annotation_buttons_node.innerHTML = ''; // Clear all child elements
var buttons_text = {
'zh-cn': [
'<div>',
'<button title="Download annotated file (annotations will be marked in the downloaded file)" id="ff-download-btn" onclick="myDownLoad()" type="button"><i class="fa fa-folder" aria-hidden="true"><span></span></i></button>',
'<button title="Extract part of PDF pages" id="ff-extract-pdf" onclick="extractPDF()" type="button"><i class="fa fa-map" aria-hidden="true"><span></span></i></button>',
'<button title="Export annotations (JSON format)" id="ff-output-btn" onclick="outputAnnotations()" type="button"><i class="fa fa-download" aria-hidden="true"><span></span></i></button>',
'<button title="Import annotations (JSON format)" id="ff-import-btn" onclick="openAnnotationFile()" type="button"><i class="fa fa-upload" aria-hidden="true"><span></span></i></button>',
'<button title="Switch to English" id="ff-language-btn" onclick="setLanguage(1)" type="button"><i class="fa fa-language" aria-hidden="true"><span></span></i></button>',
'</div>',
'<div>',
'<button title="Select object" id="ff-pointer-obj" onclick="setFabricTop(this)" type="button"><i class="fa fa-mouse-pointer" aria-hidden="true"><span></span></i></button>',
'<button title="Edit annotation" id="ff-edit-btn" onclick="editAnnotation()" type="button"><i class="fa fa-list-ul" aria-hidden="true"><span></span></i></button>',
'<button title="Text highlight (click again to cancel selection)" id="ff-highlight-btn" onclick="clickTab(this)" type="button"><i class="fa fa-paint-brush" aria-hidden="true"><span></span></i></button>',
'<button title="Text underline (click again to cancel selection)" id="ff-underline-btn" onclick="clickTab(this)" type="button"><i class="fa fa-underline" aria-hidden="true"><span></span></i></button>',
'<button title="Text strikethrough (click again to cancel selection)" id="ff-strikethrough-btn" onclick="clickTab(this)" type="button"><i class="fa fa-strikethrough" aria-hidden="true"><span></span></i></button>',
'<button title="Insert signature" id="ff-import-signature" onclick="openSignaturePanel()" type="button"><i class="fa fa-signature" aria-hidden="true"><span></span></i></button>',
'<button title="Insert image" id="ff-import-img" onclick="chooseImage()" type="button"><i class="fa fa-picture-o" aria-hidden="true"><span></span></i></button>',
'<button title="Page screenshot" id="ff-screen-shot" onclick="addFabricObj(this,6)" type="button"><i class="fa fa-camera"><span></span></i></button>',
'<button title="Brush tool" id="ff-free-draw" onclick="fabricDraw(this)" type="button"><i class="fa fa-pencil" aria-hidden="true"><span></span></i></button>',
'<button title="Text tool" id="ff-add-text" onclick="addFabricObj(this,2)" type="button"><i class="fa fa-font" aria-hidden="true"><span></span></i></button>',
'<button title="Arrow tool" id="ff-add-arrow" onclick="addFabricObj(this,3)" type="button"><i class="fa fa-external-link-square" aria-hidden="true"><span></span></i></button>',
'<button title="Rectangle tool" id="ff-add-rect" onclick="addFabricObj(this,4)" type="button"><i class="fa fa-window-maximize" aria-hidden="true"><span></span></i></button>',
'<button title="Circle tool" id="ff-add-circle" onclick="addFabricObj(this,5)" type="button"><i class="fa fa-circle" aria-hidden="true"><span></span></i></button>',
'<button title="Line tool" id="ff-add-line" onclick="addFabricObj(this,7)" type="button"><i class="fa fa-minus" aria-hidden="true"><span></span></i></button>',
'<button title="Hyperlink tool" id="ff-add-hyperlink" onclick="addFabricObj(this,10)" type="button"><i class="fa fa-link" aria-hidden="true"><span></span></i></button>',
'<button title="Stamp tool" id="ff-add-stamp" onclick="addFabricObj(this,8)" type="button"><i class="fa fa-id-card" aria-hidden="true"><span></span></i></button>',
'<button title="Insert checkmark" id="ff-add-check" onclick="addFabricObj(this,9)" type="button"><i class="fa fa-check" aria-hidden="true"><span></span></i></button>',
'</div>',
'<div>',
'<div class="read-only-model-div" id="hide-anno-div"></div>',
'<button title="AI Chat" id="ff-ai-btn" onclick="chatToPDF()" type="button"><i class="fa fa-comments" aria-hidden="true"><span></span></i></button>',
'<button title="Eraser" id="ff-eraser-btn" onclick="clickTab(this)" type="button"><i class="fa fa-eraser" aria-hidden="true"><span></span></i></button>',
'<button title="Undo annotation" id="ff-undo-btn" onclick="undoAnnotation()" type="button"><i class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
'<button title="Redo annotation" id="ff-redo-btn" onclick="redoAnnotation()" type="button"><i style="transform: rotateY(180deg);" class="fa fa-undo" aria-hidden="true"><span></span></i></button>',
'<button title="Clear all annotations" id="ff-clear-file-annotation-btn" onclick="clearFileAnnotations()" type="button"><i class="fa fa-trash" aria-hidden="true"><span></span></i></button>',
'<button title="Help document" style="' + help_button_style +
'" id="ff-help-btn" onclick="openHelpDoc()" type="button"><i class="fa fa-question-circle" aria-hidden="true"><span></span></i></button>',
'</div>',
]} [tips_language];
var new_html = '';
for (var i = 0; i < buttons_text.length; i++) {
var btn_html = buttons_text[i];
if (!btnInHiddenBtns(btn_html)) {
new_html += buttons_text[i];
}
}
annotation_buttons_node.innerHTML = new_html;
// Create div for preview mode selection
}Preview Buttons
Preview styles are all defined in the HTML and can be easily modified. Below are some example codes that can be used to adjust the zoom controls:
<div id="toolbarViewerMiddle">
<div class="splitToolbarButton">
<button id="zoomOut" class="toolbarButton" title="Zoom Out" tabindex="21"
data-l10n-id="zoom_out">
<span data-l10n-id="zoom_out_label">Zoom Out</span>
</button>
<div class="splitToolbarButtonSeparator"></div>
<button id="zoomIn" class="toolbarButton" title="Zoom In" tabindex="22"
data-l10n-id="zoom_in">
<span data-l10n-id="zoom_in_label">Zoom In</span>
</button>
</div>
<span id="scaleSelectContainer" class="dropdownToolbarButton">
<select id="scaleSelect" title="Zoom" tabindex="23" data-l10n-id="zoom">
<option id="pageAutoOption" title="" value="auto" selected="selected"
data-l10n-id="page_scale_auto">Auto Scale</option>
<option id="pageActualOption" title="" value="page-actual"
data-l10n-id="page_scale_actual">Actual Size</option>
<option id="pageFitOption" title="" value="page-fit"
data-l10n-id="page_scale_fit">Fit to Page</option>
<option id="pageWidthOption" title="" value="page-width"
data-l10n-id="page_scale_width">Page Width</option>
<option id="customScaleOption" title="" value="custom" disabled="disabled"
hidden="true"></option>
<option title="" value="0.5" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 50 }'>50%</option>
<option title="" value="0.75" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 75 }'>75%</option>
<option title="" value="1" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 100 }'>100%</option>
<option title="" value="1.25" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 125 }'>125%</option>
<option title="" value="1.5" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 150 }'>150%</option>
<option title="" value="2" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 200 }'>200%</option>
<option title="" value="3" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 300 }'>300%</option>
<option title="" value="4" data-l10n-id="page_scale_percent"
data-l10n-args='{ "scale": 400 }'>400%</option>
</select>
</span>
</div>
</div>
<div class='op-buttons-container' id='op-buttons-container'>
<div id='firefly-annotation-buttons' class='annotation-buttons'>
</div>
</div>
<div id="loadingBar">
<div class="progress">
<div class="glimmer">
</div>
</div>
</div>
</div>
</div>More APIs
In ElasticPDF, all buttons and parameter functions can be deeply accessed and invoked. Due to space limitations, not all related content is shown here. Please feel free to contact our technical team for more information.
