farling42 / fvtt-pdf-pager

PDF Pager for Foundry
MIT License
6 stars 4 forks source link

Support Form Fillable PDFs which have automatic field calculations in them #11

Closed farling42 closed 1 year ago

farling42 commented 1 year ago

The CoC7 PDF has some fields which are automatically populated from other fields.

When an Actor sheet is first opened, this automatic calculation is not happening.

farling42 commented 1 year ago

Various attempts have failed:

In setFormFromActor:

        /*pdfpageview.eventBus.dispatch("dispatcheventinsandbox", {
            source: elem,   // AnnotationElement
            detail: {  // same as in "change" or "input" event
                id: elem.id,
                name: "Action",
                value: elem.value,
                target: elem,
            }
        })*/

        /*if (pdfpageview.annotationLayerFactory._scripting)
            await pdfpageview.annotationLayerFactory._scripting.dispatchEventInSandbox({
                id: elem.id,
                name: "Action"
            })
            */

        // pdfpageview.annotationLayerFactory._scriptingManager._scripting<Factory>

        /*
        elem.dispatchEvent(new CustomEvent("updatefromsandbox", {
            detail: { value: (elem.type === 'checkbox') ? (elem.checked ? "On ": "Off") : value },
        }))*/
        // Try to trigger the Sandbox calculateNow() function for the field
        /*pdfpageview.eventBus.dispatch("updatefromsandbox", {
            source: elem,
            detail: {  // same as in "change" or "input" event
                id: elem.id,
                name: "Action",
                value: elem.value,
                target: elem,
                bubbles: true
            }
        })*/

Or at the end of that function:

    /*
    // Process calculated fields
    const objects = await pdfpageview.annotationLayerFactory.pdfDocument.getFieldObjects();
    for (const [key,value] of Object.entries(objects)) {
        let entry = value[0];
        if (entry?.actions?.Calculate) {
            console.log(`Need to calculate value for ${key}`)
        }
    }*/
farling42 commented 1 year ago

Trying to catch when derived fields change and saving them works, and we can repopulate the fields, but the values are not stored for access by the PDF internal javascript.

At startup, in the "annotationlayerrendered handler I tried:

            // DISABLED: Listen for modifications to the fields (only catch the "derived" fields, which will be marked as disabled)
            const inputs = event.source.div.querySelectorAll('input,textarea');
            for (let elem of inputs) {
                elem.addEventListener("change" , event => {
                    if (elem.disabled) {
                        if (event.detail.formattedValue) {
                            console.log(`change: id = '${elem.id}', field = '${elem.name}', value = '${event.detail.formattedValue}'`);
                            modifyActor(actor, elem.id, elem.name, event.detail.formattedValue);
                        }
                    }
                })
            }
CePeU commented 1 year ago

I am sadly no expert so excuse me if I talk rubish, but as the PDF allows for different events for fields maybe the calculation is done after leaving a field or another event?

farling42 commented 1 year ago

The PDF viewer has an internal script engine which works with scripts embedded inside PDF documents (nothing to do with Foundry). The embedded script engine seems to run when a field value is changed, and these scripts can automatically update other fields in the PDF. I can capture most of these field values, but trying to set them again when the PDF is re-opened doesn't seem to work properly.

CePeU commented 1 year ago

Ok I see. Can you trigger them (the functions) again on reload (after filling the non calculated fields)? After all all fields necessary to calculate should be filled.

farling42 commented 1 year ago

I'm not that familiar with PdfView to know how to trigger any scripts which might be attached to fields unfortunately.

CePeU commented 1 year ago

Is that PDF.js which is used as a module? I have been researching a bit - it mainly seems a problem to access those functions as far as I understand the reading (security context and such). But generally speaking it should be possible to trigger those embedded calculation functions.

farling42 commented 1 year ago

Yes, it is pdf.js It will take some more investigation to see how to get the data into the annotation layer in a way that the scripting will see the value.

farling42 commented 1 year ago

It's all very simple really.

Version 0.25.0 adds support for this - it requires a slight delay between the PDF opening and the field data being loaded into the window.