Neue Funktion einfügen: Icons? Toolbars? Warnung?

Liebe Community,

ich habe folgenden Interceptor entworfen, um eine Funktion zum „Einbrennen“ der Annotations anzubieten:

class EDAnnotationFlattener {

// code fragements taken from https://docs.apryse.com/documentation/web/guides/annotation/flatten-annotations/

async flattenAllAnnotations(instance) {

    const confirmation = confirm("Alle Anmerkungen werden unwiederruflich in das PDF integriert. Sind Sie sicher, dass sie dies tun möchten?");
    if (!confirmation) {
      return;
    }
    
    const { documentViewer, PDFNet, annotationManager } = instance.Core;

    await PDFNet.initialize();
    const theDocument = await documentViewer.getDocument().getPDFDoc();

    // export annotations from the document
    const allAnnotations = await annotationManager.exportAnnotations();

    // Run PDFNet methods with memory management
    await PDFNet.runWithCleanup(async () => {

      // lock the document before a write operation
      // runWithCleanup will auto unlock when complete
      theDocument.lock(); 

      // import annotations to PDFNet
      const fdfDocument = await PDFNet.FDFDoc.createFromXFDF(allAnnotations);
      await theDocument.fdfUpdate(fdfDocument);

      // flatten all annotations in the document 
      // see https://docs.apryse.com/api/web/Core.PDFNet.PDFDoc.html#flattenAnnotations__anchor
      await theDocument.flattenAnnotations();

      // clear the original annotations
      annotationManager.deleteAnnotations(annotationManager.getAnnotationsList());
    });

    // clear the cache (rendered) data with the newly updated document
    documentViewer.refreshAll();

    // Update viewer to render with the new document
    documentViewer.updateView();

    // Refresh searchable and selectable text data with the new document
    documentViewer.getDocument().refreshTextData();

}

initEditorConfiguration(instance) {
    // Create a new action button
    const aButton = {
        type: 'actionButton',
        img: 'paint-roller-solid.svg',
        title: 'Alle Anmerkungen fixieren',
        onClick: () => this.flattenAllAnnotations(instance)
    };

    // Add the new button to the header
    instance.UI.setHeaderItems(header => {
        header.push(aButton);
    });
  };
}

window.ed.registerInterceptor(new EDAnnotationFlattener);

Wobei ich nicht sicher bin: Wie baue ich ein neues Icon ein, wie platziere ich es in der Edit-Toolbar und wie baue ich einen „besser integrierten“ Confirmation-Dialog?
Hat da jemand von Euch ein paar Hinweise für mich?

2 „Gefällt mir“

Hallo @hajoh,

das ist ein sehr gutes Beispiel, vielen Dank.

Das ein und ausblenden der Buttons mache ich üblicherweise über das DataElements Feature.

    const aButton = {
      dataElement: 'custom_annotation_flattener',
      type: 'actionButton',
      img: 'svg...',
      title: 'Alle Anmerkungen fixieren',
      onClick: () => this.flattenAllAnnotations(instance),
    };

Dieses kann man dann zum Beispiel so ein und ausblenden:

  async updateEditorConfiguration(instance, info, config) {
    if (info.mode != 'edit') {
      instance.UI.disableElements([this.buttonDataElement]);
    } else {
      instance.UI.enableElements([this.buttonDataElement]);
    }
  }

Als SVG kannst du auch direkt ein SVG XML angeben. Hier gebit es zum Beispiel die Icons von Bootstrap welche unter MIT Lizenz stehen:

Schönere Dialoge kann man über die Custom Modals realisieren.

Ich habe mal dein Beispiel mal etwas erweitert:

class EDAnnotationFlattener {
  // code fragements taken from https://docs.apryse.com/documentation/web/guides/annotation/flatten-annotations/
  buttonDataElement = 'custom_annotation_flattener_button';
  dialogDataElement = 'custom_annotation_flattener_dialog';

  async flattenAllAnnotations(instance) {
    const { documentViewer, PDFNet, annotationManager } = instance.Core;

    await PDFNet.initialize();
    const theDocument = await documentViewer.getDocument().getPDFDoc();

    // export annotations from the document
    const allAnnotations = await annotationManager.exportAnnotations();

    // Run PDFNet methods with memory management
    await PDFNet.runWithCleanup(async () => {
      // lock the document before a write operation
      // runWithCleanup will auto unlock when complete
      theDocument.lock();

      // import annotations to PDFNet
      const fdfDocument = await PDFNet.FDFDoc.createFromXFDF(allAnnotations);
      await theDocument.fdfUpdate(fdfDocument);

      // flatten all annotations in the document
      // see https://docs.apryse.com/api/web/Core.PDFNet.PDFDoc.html#flattenAnnotations__anchor
      await theDocument.flattenAnnotations();

      // clear the original annotations
      annotationManager.deleteAnnotations(annotationManager.getAnnotationsList());
    });

    // clear the cache (rendered) data with the newly updated document
    documentViewer.refreshAll();

    // Update viewer to render with the new document
    documentViewer.updateView();

    // Refresh searchable and selectable text data with the new document
    documentViewer.getDocument().refreshTextData();
  }

  initEditorConfiguration(instance) {
    // Create a new action button
    const aButton = {
      dataElement: this.buttonDataElement,
      type: 'actionButton',
      img: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-shield-fill-exclamation" viewBox="0 0 16 16"><path fill-rule="evenodd" d="M8 0c-.69 0-1.843.265-2.928.56-1.11.3-2.229.655-2.887.87a1.54 1.54 0 0 0-1.044 1.262c-.596 4.477.787 7.795 2.465 9.99a11.777 11.777 0 0 0 2.517 2.453c.386.273.744.482 1.048.625.28.132.581.24.829.24s.548-.108.829-.24a7.159 7.159 0 0 0 1.048-.625 11.775 11.775 0 0 0 2.517-2.453c1.678-2.195 3.061-5.513 2.465-9.99a1.541 1.541 0 0 0-1.044-1.263 62.467 62.467 0 0 0-2.887-.87C9.843.266 8.69 0 8 0zm-.55 8.502L7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0zM8.002 12a1 1 0 1 1 0-2 1 1 0 0 1 0 2z"/></svg>',
      title: 'Alle Anmerkungen fixieren',
      onClick: () => instance.UI.openElements([this.dialogDataElement]),
    };

    // Add the new button to the header
    instance.UI.setHeaderItems((header) => {
      header.push(aButton);
    });

    const body = document.createElement("div");
    body.innerHTML = "Alle Anmerkungen werden unwiederruflich in das PDF integriert. Sind Sie sicher, dass sie dies tun möchten?";

    const modal = {
        dataElement: this.dialogDataElement,
        header: {
          title: 'Annotationen einbrennen',
        },
        body: {
          className: 'myCustomModal-body',
          style: {textAlign: "center"}, // optional inline styles
          children: [body], // HTML dom elements
        },
        footer: {
          className: 'myCustomModal-footer footer',
          style: {}, // optional inline styles
          children: [
            {
              title: 'abbrechen',
              button: true,
              style: {},
              className: 'modal-button cancel-form-field-button',
              onClick: async (e) => {
                instance.UI.closeElements([this.dialogDataElement]);
              },
            },
            {
              title: 'einbrennen',
              button: true,
              style: {},
              className: 'modal-button confirm ok-btn',
              onClick: async (e) => {
                await this.flattenAllAnnotations(instance);
                instance.UI.closeElements([this.dialogDataElement]);
              },
            },
          ],
        },
      };
      instance.UI.addCustomModal(modal);
  }

  async updateEditorConfiguration(instance, info, config) {
    if (info.mode != 'edit') {
      instance.UI.disableElements([this.buttonDataElement]);
    } else {
      instance.UI.enableElements([this.buttonDataElement]);
    }
  }
}

window.ed.registerInterceptor(new EDAnnotationFlattener());

Ich hoffe diese Erweiterung hilft dir weiter.

3 „Gefällt mir“