Searching with Universal Web Viewer

197 views
Skip to first unread message

Keith Kaminski

unread,
Feb 25, 2014, 11:42:47 AM2/25/14
to pdfnet-w...@googlegroups.com
Hello,

I'm having a little bit of trouble understanding the relationship between the Universal Web Viewer and the Reader Controls. I've got a Universal Reader set up and I'm trying to execute a search and iterate across the results. I can't seem to figure out a way to do this with the Universal, though I do see how to do it by going to Reader Control.

Does the Universal only expose a subset of functionality? If so, what's the recommended approach to mixing Universal and the Reader together in one code base?


Keith Kaminski

unread,
Feb 25, 2014, 12:55:08 PM2/25/14
to pdfnet-w...@googlegroups.com
As a followup question, I'm having a lot of trouble getting searching + highlighting to work correctly. What I'm trying to do is have all instances of the word "New" highlighted in the PDF with the color of my choice. I've looked at a number of different posts on the forums here (https://groups.google.com/forum/#!topic/pdfnet-webviewer/4XvtnIemEws, https://groups.google.com/forum/#!searchin/pdfnet-webviewer/TextHighlightAnnotation|sort:relevance|spell:false/pdfnet-webviewer/5vxI5R4lV50/Qd_ZQQowBckJ) and it hasn't helped. Here's the code I have right now:

$('#testButton').click(function () {
                var docViewer = window.WebViewerUniversalInstance.webViewer.getInstance().docViewer;
                var am = docViewer.GetAnnotationManager();
                docViewer.TextSearchInit('New', docViewer.SearchMode.e_page_stop | docViewer.SearchMode.e_highlight, true,
                    function (result) {
                        var firstChar = result.quads[0];
                        var lastChar = result.quads[result.quads.length - 1];

                        /* point locations
                        x1 ---- x2
                        |       |
                        |       |
                        x4 ---- x3
                        */

                        // center the selection coordinates to make it more precise
                        var firstx = (firstChar.x1 + firstChar.x2) / 2;
                        var finalx = (lastChar.x3 + lastChar.x4) / 2;
                        var y = (firstChar.y1 + firstChar.y4) / 2;

                        // assume that all the characters are aligned vertically
                        // select from the top left of the first char to the bottom right of the last char
                        var topLeft = { x: firstx, y: y, pageIndex: result.page_num };
                        var bottomRight = { x: finalx, y: y, pageIndex: result.page_num };

                        var annot = new Annotations.TextHighlightAnnotation();
                        annot.SetPageNumber(result.page_num + 1);
                        annot.StrokeColor = new Annotations.Color(0, 255, 255);
                        am.AddAnnotation(annot);

                        var textHighlightTool = new Tools.TextHighlightCreateTool(docViewer);
                        textHighlightTool.annotation = annot;
                        textHighlightTool.pageCoordinates[0] = topLeft;
                        textHighlightTool.select(topLeft, bottomRight);
                    }
                );
            });

There's a bunch of problems. First, there's no Annotations object. It's undefined. I manually went into the WebViewer.js file and added this: outerWindow.Annotations = this.contentWindow.Annotations; right below where it current just sets this: outerWindow.Tools = this.contentWindow.Tools; That seemed to do the trick, but I feel like I probably shouldn't have to do that.

The next problem is that a "quad" has different properties. Mine has the properties "H", "Qa", "Ta", "k", "o", "qb", "v", and "yb". I can't find anything in the online documentation about quads are how to work with them.

Also, I'm just having trouble figuring out if the code above really is the right way to do this. Some posts mention setting a "quads" object directly or using a setQuads method? I'm not sure what to do. Any help would be appreciated.
 

Matt Parizeau

unread,
Feb 25, 2014, 2:58:55 PM2/25/14
to pdfnet-w...@googlegroups.com
The universal viewer is a higher level wrapper for the individual viewing technologies (HTML5, Silverlight and Flash) and exposes things that are common to all of them.  If you want to make more advanced customizations or customizations specifically for the HTML5 viewer then you may have to drop down to the lower level ReaderControl.js and ReaderControl.html files.

For your followup question there are a few things to be clarified and changed.  First is that it depends where your button that is triggering this is.  If the button will be inside ReaderControl.html then it's simpler as you can add that code to a config file and just change var docViewer = window.WebViewerUniversalInstance.webViewer.getInstance().docViewer; to var docViewer = readerControl.docViewer.  This is because the Tools and Annotations namespaces are on the window of the ReaderControl window which is inside an iframe.  When you use a config file the code is executed inside this window's context so you can use them just like above.

However from your code it seems like the button is outside the viewer iframe.  That code with outerWindow and contentWindow is a bit of a hack that allows the outer window to reference those namespaces on the inner window.  Basically we need to get a reference to the window object of the iframe.  So from universal.js one way we can get a reference to the iframe's window is like: $("#documentContainer iframe")[0].contentWindow.

So inside your click handler you could have something like: var iframeWindow = $("#documentContainer iframe")[0].contentWindow;
And then later have: new iframeWindow.Annotations.TextHighlightAnnotation() and new iframeWindow.Tools.TextHighlightCreateTool(docViewer)

The next issue with the quads is something we need to improve.  The code you took is from the text position sample which uses Document.GetTextPosition() which passes a quads parameter that has x1, y1, etc properties.  Internally this exposes these properties and so instead you can use the GetPoints function to do that here.  You would change the two lines with quads to the following and they would have the properties you expect:
var firstChar = result.quads[0].GetPoints();
var lastChar = result.quads[result.quads.length - 1].GetPoints();

What should ideally happen is that the text search should return quads with those properties already and there should be better documentation on the quads in general which we'll work on improving.

The last issue has to do with something that is also a bit specific to the GetTextPosition sample.  In that sample one quad will be returned for each character specified.  In this case the first and last quads aren't going to be the same so when it centers the firstx and finalx variables this is fine since it's just centering over different individual characters.  However in your searching case there is one quad being returned for the entire word.  This means the first and last quad will be the same and if you center x1 and x2 it will be the same as centering x3 and x4 so the width will be 0!

So in this case you could probably just have something like the following just shifting over the quads by one pixel:
var firstx = firstChar.x1 + 1;
var finalx = lastChar.x3 - 1;

Once I did this I was able to get it to work.  If you don't do the shifting then I've found that if your search term is in the middle of a larger word then sometimes the selection will select an extra character.  

Let me know if you have any issues with this or if you need some further clarification.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Keith Kaminski

unread,
Feb 25, 2014, 3:48:09 PM2/25/14
to pdfnet-w...@googlegroups.com
Thanks, Matt. I think I got it working! Thanks for the updates. I have a few follow-up questions though:

1) Is there any way to set the background AND the font of a text highlight? For example, I want the word "New" to be highlighted with with a red background and green text. I tried mixing StrokeColor and FillColor but only the background seems to get updated.
2) I'm a little confused about the relationship between a TextHighlightAnnotation and a TextHighlightCreateTool. Can you explain the differences between the two? Also - why does the TextHighlightAnnotation have the page number, but the TextHighlightCreateTool has coordinates? And why are the coordinates an array?
3) The "select" method of the TextHighlightCreateTool doesn't seem to be a part of the documentation anywhere. Is this by design?
4) The functionality I'm eventually going to implement is to have a set of terms I want to pre-highlight when a document loads. I won't always know what they are ahead of time - our users can define them on the fly. Is the most efficient way to do this going to be to call TextSearchInit for each term and then highlight the terms like I've done above?

Thanks!

Matt Parizeau

unread,
Feb 25, 2014, 6:11:01 PM2/25/14
to pdfnet-w...@googlegroups.com
1) There is no way to change properties of the text itself as that is part of the document and can't be changed.

2) The TextHighlightAnnotation is the actual annotation object and the TextHighlightCreateTool is a tool used for creating highlight annotations.  When you select that tool in the UI from the annotations tab then there is a highlight create tool listening for events and creating the annotation.  Internally how the tool is used is that it creates an annotation on mouseDown and adds it to the annotation manager on mouse up.  To be honest the code used above is exposing too many implementation details and is mostly a workaround for not having a simpler way to create text annotations.  We'll work on adding a simpler way to create them for the next version.

3) I'll add some documentation for this.

4) Yes, I think this is probably the most efficient way.

Matt Parizeau
Software Developer
PDFTron Systems Inc.
Reply all
Reply to author
Forward
0 new messages