0

I have a requirement for a webapp to implement the following behavior:

After a webform is opened with an embedded PDF object is shown in the browser the user needs to be able to select a text in the document with a ctrl + mouse click after which the selected text is copied to an inputfield in the same webform that the embedded PDF object is shown.

Are there API's out there (preferably open source) that implement this behavior? Can I meet this requirement using techniques like JSP, JSF, PrimeFaces, Javascript or HTML5 and how would I do that?

mtb
  • 1,350
  • 16
  • 32
Martijn Burger
  • 7,315
  • 8
  • 54
  • 94
  • Checking for the control key during a click should be easy -> **http://stackoverflow.com/questions/21778621/how-to-check-if-control-key-is-pressed-while-mouse-click** – adeneo Jun 23 '14 at 15:33
  • Sure. But how to copy the data from an embedded object in the onCtrlClick method? – Martijn Burger Jun 23 '14 at 15:38
  • I don't think adeneo's answer would work because you need it inside the PDF versus text on the page. @Martijn, can you make the assumption that every user would use Adobe Reader, or something? – Ryan B Jun 23 '14 at 15:40
  • 1
    [Missed the edit window] You can write javascript inside of acrobat, but I am not an expert in PDF JS, so you can browse [some tutorials](http://acrobatusers.com/tutorials/filter/search&keywords=form&channel=tutorials&category=+13&tut_type=Video+OnDemand+Infographic+HTML/) maybe? – Ryan B Jun 23 '14 at 15:49
  • 1
    @RyanB Yes, that assumption could work, I am going to look in the tutorials. – Martijn Burger Jun 23 '14 at 16:22
  • 1
    pdf-js could be an option too. http://mozilla.github.io/pdf.js/ – Martijn Burger Jun 23 '14 at 21:56

1 Answers1

3

In the example I'll use

  • PDF.js
  • JSF 2.2 (doesn't really matter what version, but it's better to be 2.x)
  • PrimeFaces (for the inputField or textArea) * optional

Steps:

  • Downloading and Integrating PDF.js
  • Register Event on CTRL

Downloading and Integrating PDF.js

Download PDF.js, after the download is complete unzip it, you would see the following folder hierarchy

.
 ├── LICENSE
 ├── build
 │   ├── pdf.js
 │   └── pdf.worker.js
 └── web
     ├── cmaps/
     ├── compatibility.js
     ├── compressed.tracemonkey-pldi-09.pdf
     ├── debugger.js
     ├── images/
     ├── l10n.js
     ├── locale/
     ├── viewer.css
     ├── viewer.html
     └── viewer.js

Assuming you have a JSF project with a resources folder inside webapp, copy the following files from web folder (from the unziped file) into resources in which they would look like this :

webapp/resources folder

├── css
│   └── viewer.css (web/viewer.css)
├── images
│   └── pdfjs
│       ├── ** All the images inside (web/images)
└── js
   └── pdfjs
       ├── compatibility.js (web/compatibility.js)
       ├── l10n.js (web/l10n.js)
       ├── pdf.js (web/pdf.js)
       ├── pdf.worker.js (web/pdf.worker.js)
       └── viewer.js (web/viewer.js)

Edit viewer.css to resolve all the required images, replace each url with

"#{resource['images/pdfjs/correspondingImageName']}"

here's a full resolved viewer.css

Create xhtml file with the content of viewer.html (web/viewer.html from zip), which would represent the viewer markup, the reason that I'de use the viewer with all the html 5 markup is the ability to select text, not like the canvas only example

Here's a full copied example of viewer.html into viewer.xhml

Notice in the end I've included the libraries in the following order:

<h:outputScript name="js/pdfjs/compatibility.js" target="head" /> 
<h:outputScript name="js/pdfjs/l10n.js" target="head" />
<h:outputScript name="js/pdfjs/pdf.js" target="head" />  
<h:outputScript name="js/pdfjs/viewer.js" target="head" />

To get PDF.js running you need to specify two things, the pdf.worder.js location and the pdfURL (see in viewer.xhml)

 <script>
     var DEFAULT_URL = "#{pdfURL}"; //pdf should be hosted on your domain name (ajaxly loaded) 
     PDFJS.workerSrc = "#{resource['js/pdfjs/pdf.worker.js']}";
 </script>

Register Event on CTRL

Define an inputText or inputTextArea

<p:inputTextarea id="inputTextArea" />

Now register an event of keydown or whatever that fit, example:

 $('.pdfZone').keydown(function(event) {
    if (event.which == "17"){ // CTRL key
       $('#inputTextArea').text(window.getSelection().toString())
     }                 
 });

.pdfZone is a div container of the pdf viewer

You can find a full example on github [1] [2], and an online Demo.

Note: I didn't use CTRL + Click because in my Mac OSX would trigger the Right Click, anyhow you could change the event handling.

Suggestion to use CTRL + Click (but the demo would use only CTRL)

 $('.pdfZone').on('mouseup',function(e) {                       
    if (e.ctrlKey) {
       $('#inputTextArea').text(window.getSelection().toString());
     }
 });
Hatem Alimam
  • 9,968
  • 4
  • 44
  • 56