-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implementing web/pdf_find_bar.js #10120
Comments
Just a day ago we merged a pull request, #10099, that dropped the dependency of the find bar on the find controller, which makes integration a bit easier. The find bar is created and controlled in Line 1326 in ec10cae
Line 1943 in ec10cae
The find bar in https://github.com/mozilla/pdf.js/blob/master/web/pdf_find_bar.js is a simple component (class) that you can import and use as long as you provide the required options. However, since the find bar class is not exposed in the web bundle by default (see https://github.com/mozilla/pdf.js/blob/66ffdc4c5b63a135f201508264761fce17c08059/web/pdf_viewer.component.js), you'll most likely need to add it to your project yourself. I think we're open for ideas on how to improve this to make third-party usage of our components easier. Perhaps we should integrate the |
Thank you for the thorough reply. In other words, I could simply pass all of those elements into findbar as an object instead of using the logic at https://github.com/mozilla/pdf.js/blob/master/web/app.js#L353 that generates findBarConfig? |
To add to this... Is it possible to use this find bar / find functionality if I am not using PDF.JS as my viewer? What I mean by this, is that I currently need full control over the implementation of each pdf page in my viewer, so I am using PDF.JS to convert the pdf, page by page, into png's which I then attach to my viewer canvas's. I was able to implement the text layer with this method, however, I can not determine how heavily this find feature depends on the document being set via the PDFJS.pdfViewer() object. |
Yes, in fact the
Yes, that should be possible. If you have the text layer working, then the find bar and find controller should work just fine, especially since the pull request I mentioned above since that removes the need to pass in a Hopefully this answers the questions; if not, feel free to ask! We're working more towards decoupling our components, for both internal and third-party usage. The pull request above is an example of that to reduce the number of direct dependencies, but there is also another PR open at the moment that aims to simplify the find functionality a bit more. If you see more things that can be improved to make third-party usage easier, do not hesitate to open a ticket. Edit: The commit 3f3ddaf is just merged which makes the find bar slightly easier to use since you can provide the event bus directly and don't have to put it in the configuration object anymore. |
I believe I am following along with what you are saying, however, I might still be slightly confused on the exact implementation. From my understanding here are the steps needed to implement the find bar:
Are these steps correct? Is anything else required to be done to the findBar object, or is it fully functional from that point? Does PDFFindBar rely strictly on our text layer (if so, how does it locate it)? Does PDFFindBar assume that the entire text layer has already been rendered? For example, if part of the text layer has not been rendered because a page has not been accessed yet, will PDFFindBar still be able to find the text? |
This sounds correct to me, but note that I did not test this myself.
The find bar dispatches an event that you can catch in your custom text layer to render the matches, so it doesn't need to locate it at all. However, the find controller does need access to the
The |
Given the info above I was able to get the findBar implemented and catching events. The code below is functioning and the webViewerFind() method is triggering correctly. At this point, I am still unsure how to verify that the textLayer is catching this event. After this event fires, I do not see any visual updates on my page. Is there anything else that I could be missing?
Something I still am not certain about... It seems that the pdfLinkService object needs to be attached to both the viewer and controller to allow text highlighting (as removing it from the components/simpleviewer.js demo breaks the highlighting feature). If this is correct, and I am not using the PDFViewer, how would I use the pdfLinkService? |
First of all, are you using the latest code from the Aside from that, I think there are a few problems in this code:
Finally, to answer your question about the link service: As far as I can tell, it should work after you make these changes. You should start seeing the I just want to conclude this post by saying that this is also a valuable thread for us because your feedback inspired some of the most recent commits for the find bar/find controller, since we saw that not everything is as intuitive as one would like for third-party usage. Therefore, thank you for the feedback! |
I have made the updates mentioned to the getGlobalEventBus() call and the setDocument() call, but still seem to be having issues. Below is a rough outline as to how I am implementing the text layer. Could it be possible that since I am using "renderText" instead of creating a "custom text layer" that there is nothing listening for the updateTextLayerMatches event being fired? If this should be done differently, how? I am also not understanding what must be done to create the link service in the case that I am not using the PDFViewer (like below), nor am I 100% understanding how it should be implemented. In the case where we do use the PDFViewer (/components/simpleviewer.js), should I be using the same link service object for the creation of both the viewer/find controller?
I would also like to note that as I have been implementing these changes, I have also been attempting to implement the changes into /components/simpleviewer.js to see how this could be done while using the PDFViewer as to gain a better understanding, however, I have not had luck there either. As always, thank you for your help! Edit: After inspecting further, I am more certain that the issue is with how I am implementing my text layer. How could/should I be implementing the text_layer_builder.js mentioned above? The only examples that I was able to find made use of a PDF.JS viewer object. In the meantime, I proceeded to work on the components/simpleviewer.js example. I determined that in this example, PDFViewer controlled the text layer. I created an eventBus that could be accessed globally, which I then attached to the PDFFindBar and PDFFindController. I then made this find controller accessible before attaching it to the PDFViewer object. With that done, I am now able to make calls to the PDFFindController on event triggers in the components/simpleviewer.js example! Edit2: Are the pdf_find_controller.js and pdfjsViewer.PDFFindController different objects, or are they interchangeable? I think this could have lead to some confusion with the simpleviewer.js implementation. |
It's becoming hard to tell from just code snippets alone since it doesn't show all context and we can't run it. Would it be possible to set up a minimal project somewhere (JSFiddle, JSBin or your own server) with your find bar/controller and custom text layer so we can take a look (you can strip out any irrelevant information to make it a minimal example to reproduce the issue)? You can test if
It sound like there is some progress there then, so I think you're indeed narrowing the problem down to
|
Instead of using the PDFJS.renderText method to generate my text layer, I figured out how to use the text_layer_builder.js class discussed earlier. Below is my implementation.
Luckily, this seems to work quite nicely and generate the text layer in a similar manner as before, however, now we have access to all of the listener functions that come with text_layer_builder.js I believe the only missing piece here is that I can not seem to determine the correct way of implementing the PDFLinkService object used when creating the PDFFindController, nor do I fully understand what PDFLinkService does. Without this linkService object, my PDFFindController does not seem to fire the correct events, as the text_layer_builder.js never catches any of them. In the components/simpleviewer.js example, I was able to get the PDFLinkService object via Would importing
It appears to me that without setting a pdfViewer object for PDFLinkService, PDFFindController will throw errors. This happens because when it attempts to find search results, it accesses [1] Is the only solution here to modify pdf_link_service.js to access the respective values from my viewer instead of the PDFViewer object? |
Yes, it does look like a much better solution to me!
Indeed, I think there is not really a way around it if you're not using the However, implementing a custom link service is not hard because it's a simple class for which you can provide a custom one that implements the interface. Notice how we have https://github.com/mozilla/pdf.js/blob/master/web/pdf_link_service.js#L411 and https://github.com/mozilla/pdf.js/blob/master/test/unit/pdf_find_controller_spec.js#L22 for example, for exactly the same reason that sometimes it's not useful to have an actual The link service is a simple layer between components and the underlying |
Closing since this should be answered now. |
I have been attempting to implement a find bar into my pdf viewer, which uses pdf.js. I have noticed that the demo viewer makes use of pdf_find_bar.js for this functionality, however, it is not very clear how it is exactly implemented.
Are there any examples/documentation on how to implement this feature into my viewer? For a starter, how would such a feature be implemented into the examples/components/simpleviewer?
The text was updated successfully, but these errors were encountered: