Customization done for version 2.0:
1 - File extensions changes:
Due to the IIS default configurations and the inability to change it in Personal Environments, some file extensions were changed in the resources module.
1.1 - All files that had the extension mjs were changed to js:
And all the references to these files inside the original files were also changed.
(Each file was opened and search for the mjs extension in order to replace it to js)
1.2 - All files that had the extension ftl were changed to txt:
All the references to these files inside the locale.json file were also changed to point to the new .txt files.
2 - Code changes and Event customizations:
The file viewer.js was changed to trigger an event before the viewer initialization:
This follows the same pattern used on the version 1.0.
Check the previous documentation for more details.
The OnBeforeInit() action is define on the OnReady of the PDF_JS web block:
However, differently than the version 1.0, now all the events can be defined in the web block as well, inside the action PDFJS_OnInit:
Currently we have a Page Rendered and Document Loaded event.
Besides the Init event.
It is also possible to include specific preferences to initialize PDF.JS inside the PDFJS_OnBeforeInit action:
A list of possible options that could be implemented can be found here:
https://github.com/mozilla/pdf.js/blob/master/web/app_options.js
3 - Integration with PDF Annotate
To be able to support custom annotations that can be added programatically, I have integrated another JS library called PDF Annotate: https://github.com/highkite/pdfAnnotate
This Library has methods to add annotations to a PDF FIle, that can be opened later with PDF JS.
It is important to understand that PDFAnnotate and PDF.JS are 2 different libraries, and the annotations added to a file using PDFAnnotate are not applied to the document loaded in the PDF.JS viewer.
Instead it always creates a new document and if you require to add annotations live you will always need to reload the document.
There are some functions already ready for these use cases. You will find them under the PDF_Annotate Library:
You will also note that there are 2 actions to get Annotations.
The Get_CustomAnnotations action will return all the annotations created programmatically with the PDFAnnotate library. It will not include annotations created by PDF.JS using the default editors.
The PDFJS_GetAnnotationsData action will return the annotations created by PDF.JS using the default editors
You can also check this topic for different options to get the annotation data from PDF JS: https://stackoverflow.com/questions/63278540/how-to-use-annotation-layer-in-pdf-js
______________
As for the next steps, maybe we can try to find a way to use PDF.JS directly without using PDFAnnotate to add annotations.
This topic is promising in terms of how to do it: https://github.com/mozilla/pdf.js/discussions/17649
2 new client actions are now available.
This action will return the loaded document in a Base64 format, including all the annotations.
This action will return all the annotations present in the document as a List.This includes the position coordinates in the page, the page number, the text content, styling and etc.Here is an example of an annotation item:
Object:
{
"annotationFlags": 24,
"borderStyle": {
"width": 1,
"style": 1,
"dashArray": [3]
},
"color": {},
"contentsObj": {
"str": "Test Content",
"dir": "ltr"
"id": "998R",
"modificationDate": "D:20230309185452",
"rect": [136.52307692307693, 705.9538461538463, 158.52307692307693, 727.9538461538463],
"subtype": "Text",
"titleObj": {
"str": "Test Author",
"annotationType": 1,
"name": "Note",
"page": 1,
"quadPoints": []
}
In this new version, was added the option to customize the secondary toolbar:
They correspond to the elements from the menu on the right corner:
I also added a new option called OnlyHide, which is true by default:
When using it as False, it will completely remove the elements instead of hiding them.However, I noticed that it can create problems if you are toggling the elements on or off.So, if you have this requirement maybe is better to use OnlyHide as true.
Bug Fixing.Sometimes when changing documents too fast you could receive a javascript error saying 'cannot read properties of null' or ''cannot read appconfig from undefined'
This problem is fixed.
To fix the issue before trying to change the configurations we validate to see if the object is already initialized and exists.
The documentation from version 1.0.0 is still applicable.The only addition is that now we have support for Binary files as well.Simply use the Binary Attribute from the webblock.
Keep in mind that using a Binary will override the FileURL so it doesn't matter if you provide something in the URL if you are using a Binary file
Introduction:This component is custom implementation for the PDF JS Viewer that supports annotations and events.
The version implemented for the PDF JS Library is pdfjs-3.4.120-dist
Gotten from: https://mozilla.github.io/pdf.js/getting_started/#download
This is the GitHub: https://github.com/mozilla/pdf.js
PDF JS is a Library provided by Mozilla that allows us to handle PDFs in the browser.
By default they provide a sample "Viewer" that is separated from the PDF JS Library.
This component is a custom implementantion of this Viewer not the Library.
On the last version of this Library and Viewer they provide support to see Annotations on the PDF File but not to create them.
Next steps for the future on this component is to try to allow creating annotations as well.
using a different library: https://github.com/highkite/pdfAnnotate
However, this is for the future, currently we don't support creation just vieweing of annotation.
________________________________
Events customizations:
The events implemented so far are just 'OnInitialized' and 'OnPageRendered'.
However, it is possible to implement any other supported event by the library using the same behavior.To be able to implement those 2 events wecustomized the file '\pdfjs-3.4.120-dist\web\viewer.js'.If you open it and search by the keyword 'OutSystems' you should find the following:
The way this component works is that it renders the viewer inside an iFrame.What we did to enable events is that after the initialization we call actions that are stored in the window frame object defined by the outsystems code.
For example:
Getting the OnInitialized event as a sample.
On the OutSystems Module 'PDF_JS_CW' in the 'PDF_JS' webblock inside the 'OnReady' action we define in the Javascript node the follwing:
We are saying that the 'OnInit' attribute of our frame will hold a reference to the 'PDF_OnInit' Client Action of our webblock.
This way when we call the OnInit action from the frame on our custom code we are triggering the 'PDF_OnInit' cleint action, and thus triggering the event:
The same is true for the OnPageRendered.You should be able to use the same pattern for any other events such as:
__________________________________
Attributes customization:
The same way we customized the events, we also did a similar thing for showing and hidding UI elements.
It uses the DefineAppConfig action that is called before the initialization and overrides the JS object for the Library.If you goto your console on the sample app and type 'PDFViewerApplication.appConfig' (Make sure you are on the frame contect on the dropdown, see the image where we have b6-Frame), you should be able to access the appConfig object that we are overriding:
to hide the download button for instance we use the variable 'toolbar.download.hidden' of the appConfig:
In theory you could try to overwrite any other attribute as well.But le me know using the forums if you have any problems