How can support multi-user annotation collaboration on my server and integrate it with WebViewer?

339 views
Skip to first unread message

Kevin Kuo

unread,
Dec 19, 2014, 6:14:40 PM12/19/14
to
Q: How can support multi-user annotation collaboration on my server and integrate it with WebViewer?


=========================================

A:  WebViewer has been implemented with annotation collaboration in mind.
We have implemented annot commands as a way to serialize annotations as xml to communicate with a server.
The method is is AnnotationManager, called GetAnnotCommand()

It is accompanied by ImportAnnotCommand, which takes the XFDF xml as a string. This loads and renders the annotations.

To integrate annotations with your server, the steps are as followed:
  • use a simple javascript polling mechanism (let's say using setInterval)
  • on each tick
    • call AnnotationManager.GetAnnotCommand() to get all the "dirty" annotations
    • make a POST request to your server, with the annot command string as the body
    • now your server should process this these annot commands. This is where extra logic may be needed regarding permissions and how you persist the annotation data. It is up to your implementation.
      • an example, is that your server temporarily saves the annot commands (to database or file). And returns any new annot commands it has received (from other users).
      • in a simple scenario, you can keep track of annot commands by using timestamps on when it was sent to the server.
    • your server will respond with any new annot commands created from other clients
    • you can call AnnotationManager,ImportAnnotCommand(data) to load the annotations
    • so effectively, on every tick, a client sends to the server any changes it has made. The server will respond with changes that any other users have made since the last "tick".
For on your client side, it will look something like this. Note that this code should be placed in the documentLoaded event block to ensure a document was loaded first.
            setInterval(function(){
               
var am = readerControl.docViewer.GetAnnotationManager();
               
var clientAnnotData= am.GetAnnotCommand();
                $
.ajax({
                    url
: serverurl
                    cache
: false,
                    data
: clientAnnotData,
                    success
: function(data) {
                       
//server returned some annotation commands
                       
if (data !== null) {
                            am
.ImportAnnotCommand(data);
                       
}
                   
},
                    error
: function() {
                       
//server gave an error
                   
},
                    dataType
: 'xml'
               
});
           
},3000); //execute this code every 3 seconds



An alternative way to sync with servers is through WebSockets, which opens a two-way communication channel between server and client. This requires specific servers that support it. In this case, you would not use polling, but instead you would listen to events.

Mike Ruthven

unread,
Apr 16, 2014, 2:22:23 PM4/16/14
to pdfnet-w...@googlegroups.com
Would it be possible to post a sample of the output of GetAnnotCommand() somewhere? I like this command structure, since PDFNet can use it also, but unfortunately all of my current implementations are using PDFNet, which can't generate this command.

Thanks,

Mike


On Wednesday, January 29, 2014 8:51:56 PM UTC-5, Kevin Kuo wrote:
> Q: How can support multi-user annotation collaboration on my server and integrate it with WebViewer?
>
>
>
>
> =========================================
>
>
> A:  WebViewer has been implemented with annotation collaboration in mind.
>
>
> We have implemented annot commands as a way to serialize annotations as xml to communicate with a server.
> The method is is AnnotationManager, called GetAnnotCommand()
>
>
> It is accompanied by ImportAnnotCommand, which takes the XFDF xml as a string. This loads and renders the annotations.
>
>
> To integrate annotations with your server, the steps are as followed:
> use a simple javascript polling mechanism (let's say using setInterval)on each tickcall AnnotationManager.GetAnnotCommand() to get all the "dirty" annotationsmake a POST request to your server, with the annot command string as the bodynow your server should process this these annot commands. This is where extra logic may be needed regarding permissions and how you persist the annotation data. It is up to your implementation.an example, is that your server temporarily saves the annot commands (to database or file). And returns any new annot commands it has received (from other users).in a simple scenario, you can keep track of annot commands by using timestamps on when it was sent to the server.your server will respond with any new annot commands created from other clientsyou can call AnnotationManager,ImportAnnotCommand(data) to load the annotationsso effectively, on every tick, a client sends to the server any changes it has made. The server will respond with changes that any other users have made since the last "tick".
> For on your client side, it will look something like this. Note that this code should be placed in the documentLoaded event block to ensure a document was loaded first.
>
>
>             setInterval(function(){
>                 var am = me.docViewer.GetAnnotationManager();

Matt Parizeau

unread,
Apr 17, 2014, 1:53:02 PM4/17/14
to pdfnet-w...@googlegroups.com
Hi Mike,

Here's an example output:
<?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf" xml:space="preserve">
<doc_id>doc_id</doc_id>
<fields />
<add><text subject="Sticky" page="0" rect="524.1,686.84,547.35,663.59" name="ed838d13-fb6c-5f41-64bb-226a8c40edd8" title="Guest" date="D:20140417104711-07'00'" color="#FFFF00" creationdate="D:20140417104711-07'00'" icon="Comment"><popup flags="print,nozoom,norotate" page="0" rect="471.37,739.56,621.37,664.56" open="yes"></popup></text></add>
<modify>
<circle subject="Ellipse" page="0" rect="329.71,694.22,417.24,655.55" name="2ac76be6-b813-2248-289b-694a765c7a37" title="Guest" date="D:20140417104725-07'00'" color="#000000" interior-color="#FFFF00" width="1" creationdate="D:20140417104618-07'00'"><popup flags="print,nozoom,norotate" page="0" rect="276.99,746.94,426.99,671.94" open="no"></popup></circle>
<ink subject="Free Hand" page="0" rect="398.61,618.99,552.21,563.1" name="2b34d76f-761a-31eb-37f9-5244175f4aef" title="Guest" date="D:20140417104725-07'00'" color="#000000" width="5" creationdate="D:20140417104621-07'00'"><popup flags="print,nozoom,norotate" page="0" rect="39.72,719.88,189.72,644.88" open="no"></popup><inklist><gesture>498.79,582.44;498.79,579.62;497.38,576.46;495.97,573.3;491.05,568.02;488.24,565.91;475.59,563.1;463.28,564.16;445.01,569.08;427.08,576.46;409.15,587.36;399.66,595.09;398.61,601.77;405.64,607.39;422.86,613.37;450.63,617.94;475.23,615.83;491.4,609.15;500.54,593.33;499.84,581.03;496.33,572.95;492.81,570.13;489.3,569.78;485.43,570.84;477.7,578.92;472.42,591.22;473.83,597.9;481.21,602.82;506.52,607.04;522.69,605.99;533.94,601.42;538.86,598.61;539.56,598.25;539.91,598.25;540.97,599.31;544.83,606.69;548.7,614.77;551.16,618.29;552.21,618.99</gesture></inklist></ink>
</modify>
<delete>
<id>a5066124-f8a7-a35c-af30-debcba144bae</id>
</delete>
</xfdf>

This shows there was a text annotation added, circle and ink modified and an annotation with a specific id that was deleted. The add element will have the XFDF representation of zero or more annotations that were added. Modify will be the same except it will have annotations that existed at the last time GetAnnotCommand was called and have been modified since then. Delete will have 0 or more annotation ids for annotations that were deleted. The id corresponds to the name attribute in XFDF.

Matt Parizeau
Software Developer
PDFTron Systems Inc.

Mike Ruthven

unread,
Apr 17, 2014, 2:54:27 PM4/17/14
to pdfnet-w...@googlegroups.com
That's excellent, Matt, thanks a lot. One last thing here, where does doc_id come from? Is that something that I "make up myself", i.e. use it externally, or is that something from the PDF itself?

Thanks,

Mike

Matt Parizeau

unread,
Apr 21, 2014, 6:07:38 PM4/21/14
to
Hi Mike,

I've looked into it and it appears doc_id isn't necessary for the output and we'll be removing it in the next version so you shouldn't have to worry about it. You'll probably want to have something that you make up yourself to identify which document this annotation command belongs to and maybe pass it as a query parameter to your server.

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