V7 equivalent of CustomAnnotation.createFromClass(string, AnnotationCtor)

WebViewer Version: 7.x.x

I need to create a custom annotation that extends StampAnnotation which is serializable and deserializable from xfdf.

In v7 of webviewer, we must extend CustomAnnotation class and reimplement methods that matches StampAnnotation.

In v8 of webviewer, the following is provided

Annotations.CustomAnnotation.createFromClass(string, AnnotationCtor)

And our custom annotation is able to extend from StampAnnotation directly and passed to

CustomAnnotation.createFromClass

to create a serializable custom annotation.

How can we mimic what

Annotations.CustomAnnotation.createFromClass(string, AnnotationCtor)

does in v8, in v7 of webviewer?

Hello, I’m Ron, an automated tech support bot :robot:

While you wait for one of our customer support representatives to get back to you, please check out some of these documentation pages:

Guides:APIs:Forums:

Hi James,

It is possible to mimic that API by creating your class and calling the methods from the StampAnnotation class prototype:

class MyCustomAnnotation extends Annotations.CustomAnnotation {
  constructor(initializer) {
    super('myAnnotation', initializer);
    Annotations.StampAnnotation.apply(this, [initializer]);
  }
  serialize(el) {
    // Serialize custom annotation properties first
    el = Annotations.CustomAnnotation.prototype.serialize.apply(this, arguments);
    // Serialize stamp properties second
    el = Annotations.StampAnnotation.prototype.serialize.apply(this, arguments);

    // Remove duplicate child nodes since we are serializing twice
    for (let i = 0; i < el.childElementCount; i++) {
      const node = el.childNodes[i];
      const duplicateNodes = [...el.getElementsByTagName(node.tagName)];
      while (duplicateNodes.length > 1) {
        const duplicate = duplicateNodes.pop();
        if (!duplicate.parentElement || duplicate.parentElement !== el) {
          continue;
        }
        el.removeChild(duplicate);
      }
    }
    return el;
  }
  deserialize() {
    Annotations.CustomAnnotation.prototype.deserialize.apply(this, arguments);
    Annotations.StampAnnotation.prototype.deserialize.apply(this, arguments);
  }
}

MyCustomAnnotation.prototype.elementName = 'myAnnotation';
MyCustomAnnotation.prototype.draw = Annotations.StampAnnotation.prototype.draw;

MyCustomAnnotation.prototype = Object.assign(new Annotations.StampAnnotation(), Annotations.CustomAnnotation.prototype, MyCustomAnnotation.prototype);

I will also just leave the custom annotation guide here for reference: PDFTron Systems Inc. | Documentation

Let me know if this helps!

1 Like

So in your example, you are extending CustomAnnotation and calling methods from StampAnnotation. Can it be the other way around? In other words, “Can I extend StampAnnotation and call methods or add properties from CustomAnnotation?” so I can extend built-in annotations and create CustomAnnotation class definitions from them such that are serializable/deserializable to/from xfdf?

Annotations.CustomAnnotation.createFromClass(string, AnnotationCtor) allows me to do this

class MyCustomStampAnnotation extends Annotations.StampAnnotation {
 // ...
}


const CustomStamp = Annotations.CustomAnnotation.createFromClass('CustomStamp', MyCustomStampAnnotation);

Sure. With JavaScript prototypes, you can call any method from another class as long as you provide the this context. However, I cannot guarantee that everything will work as expected due to the differences in type.