OfficeDev / office-js

A repo and NPM package for Office.js, corresponding to a copy of what gets published to the official "evergreen" Office.js CDN, at https://appsforoffice.microsoft.com/lib/1/hosted/office.js.
https://learn.microsoft.com/javascript/api/overview
Other
690 stars 95 forks source link

Cannot insert multiple footnotes using Footnote API #2216

Closed sureshjoshi closed 8 months ago

sureshjoshi commented 3 years ago

Message from office-js bot: We’re closing this issue because it has been inactive for a long time. We’re doing this to keep the issues list manageable and useful for everyone. If this issue is still relevant for you, please create a new issue. Thank you for your understanding and continued feedback.

While using the footnote API, I'm unable to insert more than 1 footnote. I've attached an example where I create 2 paragraphs, and add a footnote to the end of each with every permutation (no footnotes, one on the first, one on the second, both).

The "both" use case fails with the attached error. However, the paragraphs are always inserted correctly.

Maybe I'm not using the API in the correct way? Or perhaps that functionality is not implemented yet.

Your Environment

Expected behavior

Footnotes can be created in the same fashion as paragraphs, meaning multiple can be created together.

Current behavior

One can be created without any problems, however, the second causes a RichAPI error

Script Lab example

name: Insert multiple footnotes
description: ''
host: WORD
api_set: {}
script:
  content: |
    $("#nofootnotes").click(() => tryCatch(noFootnotes));
    $("#firstfootnote").click(() => tryCatch(firstFootnote));
    $("#secondfootnote").click(() => tryCatch(secondFootnote));
    $("#bothfootnotes").click(() => tryCatch(bothFootnotes));

    async function noFootnotes() {
      await Word.run(async (context) => {
        context.document.body.clear();
        await context.sync();

        const p1 = context.document.body
          .insertParagraph("Placeholder text for the first footnote.", "Start")
          .getRange("End");
        await context.sync();

        const p2 = context.document.body
          .insertParagraph("Placeholder text for the second footnote.", "End")
          .getRange("End");
        await context.sync();
      });
    }

    async function firstFootnote() {
      await Word.run(async (context) => {
        context.document.body.clear();
        await context.sync();
        const p1 = context.document.body
          .insertParagraph("Placeholder text for the first footnote.", "Start")
          .getRange("End");
        p1.insertFootnote("First footnote content");
        await context.sync();

        const p2 = context.document.body
          .insertParagraph("Placeholder text for the second footnote.", "End")
          .getRange("End");
        await context.sync();
      });
    }

    async function secondFootnote() {
      await Word.run(async (context) => {
        context.document.body.clear();
        await context.sync();

        const p1 = context.document.body
          .insertParagraph("Placeholder text for the first footnote.", "Start")
          .getRange("End");
        await context.sync();

        const p2 = context.document.body
          .insertParagraph("Placeholder text for the second footnote.", "End")
          .getRange("End");
        p2.insertFootnote("Second footnote content");
        await context.sync();
      });
    }

    async function bothFootnotes() {
      await Word.run(async (context) => {
        context.document.body.clear();
        await context.sync();

        const p1 = context.document.body
          .insertParagraph("Placeholder text for the first footnote.", "Start")
          .getRange("End");
        p1.insertFootnote("First footnote content");
        await context.sync();

        const p2 = context.document.body
          .insertParagraph("Placeholder text for the second footnote.", "End")
          .getRange("End");
        p2.insertFootnote("Second footnote content");
        await context.sync();
      });
    }

    /** Default helper for invoking an action and handling errors. */
    async function tryCatch(callback) {
      try {
        await callback();
      } catch (error) {
        // Note: In a production add-in, you'd want to notify the user through your add-in's UI.
        console.error(error);
      }
    }
  language: typescript
template:
  content: |-
    <button id="nofootnotes" class="ms-Button">
        <span class="ms-Button-label">No Notes</span>
    </button>
    <button id="firstfootnote" class="ms-Button">
        <span class="ms-Button-label">First Footnote</span>
    </button>
    <button id="secondfootnote" class="ms-Button">
        <span class="ms-Button-label">Second Footnote</span>
    </button>
    <button id="bothfootnotes" class="ms-Button">
        <span class="ms-Button-label">Both Footnotes</span>
    </button>
  language: html
style:
  content: |-
    section.samples {
        margin-top: 20px;
    }

    section.samples .ms-Button, section.setup .ms-Button {
        display: block;
        margin-bottom: 5px;
        margin-left: 20px;
        min-width: 80px;
    }
  language: css
libraries: |
  https://appsforoffice.microsoft.com/lib/beta/hosted/office.js
  @types/office-js

  office-ui-fabric-js@1.4.0/dist/css/fabric.min.css
  office-ui-fabric-js@1.4.0/dist/css/fabric.components.min.css

  core-js@2.4.1/client/core.min.js
  @types/core-js

  jquery@3.1.1
  @types/jquery@3.3.1

Context

Just testing out the new API for an application being developed (in order to replace a lot of nasty insertOOXML).

Useful logs

[ERROR]: Error:
{
    "stack": "RichApi.Error: The action isn’t supported by Word in a browser. Check the OfficeExtension.Error.debugInfo for more information.\n    at new n (https://appsforoffice.microsoft.com/lib/beta/hosted/word-web-16.00.js:26:308248)\n    at n.o.processRequestExecutorResponseMessage (https://appsforoffice.microsoft.com/lib/beta/hosted/word-web-16.00.js:26:371544)\n    at https://appsforoffice.microsoft.com/lib/beta/hosted/word-web-16.00.js:26:369649",
    "message": "The action isn’t supported by Word in a browser. Check the OfficeExtension.Error.debugInfo for more information.",
    "name": "RichApi.Error",
    "code": "NotAllowed",
    "traceMessages": [],
    "innerError": null,
    "debugInfo": {
        "code": "NotAllowed",
        "message": "The action isn’t supported by Word in a browser. Check the OfficeExtension.Error.debugInfo for more information.",
        "errorLocation": "Range.insertFootnote",
        "statement": "var insertFootnote = range.insertFootnote(...);",
        "surroundingStatements": [
            "var v = context.root._getObjectByReferenceId(\"{54127e92-8c9a-46ee-8b6c-b65947b3f636}{202}\");",
            "var insertParagraph = v.insertParagraph(...);",
            "// Instantiate {insertParagraph}",
            "var range = insertParagraph.getRange(...);",
            "// Instantiate {range}",
            "// >>>>>",
            "var insertFootnote = range.insertFootnote(...);",
            "// <<<<<",
            "// Instantiate {insertFootnote}"
        ],
        "fullStatements": [
            "Please enable config.extendedErrorLogging to see full statements."
        ]
    },
    "httpStatusCode": 500
}
chiz-ms commented 3 years ago

Thank you for reporting this issue regarding Range.insertFootnote API. The issue is confirmed and tracked as ADO#5539077 in our backlog.

RuoyingLiang commented 3 years ago

@sureshjoshi Thanks for reaching us. The focus will be in the footnote body so the second footnote cannot be inserted. We will take a look at this behavior. Currently, you may consider to set focus to the next footnote's range and insert.

sureshjoshi commented 3 years ago

Thanks @RuoyingLiang !

But question, isn't that what should happen when I select the context.document.body.insertParagraph? Wouldn't that re-focus my range back to the doc?

What you've described is what I assumed was happening, but I guess I assumed that my code automatically re-shifted focus. How would I do this explicitly?

chiz-ms commented 2 years ago

The team has reported that the issue has been fixed in code and the fix is currently in the release process. We'll come back to this thread when it is publicly available.

sureshjoshi commented 2 years ago

Thanks @chiz-ms !

xiaoyuMS commented 2 years ago

Some information about this fix for @sureshjoshi .

The focus won't be shifted when you call getRange().

For insertfootnote(), we added an optional parameter called "keepCurrentFocus: boolean" to decide whether to keep the current focus. The default value is false which indicates that the footnote editor will be opened and the focus will be shifted to the editor.

You can set it true which indicates the editor won't be opened and the focus won't be changed, then you can insert the next footnote. It is same for endnote.

sureshjoshi commented 2 years ago

Thanks @xiaoyuMS - I'll test it out when it reaches production

sureshjoshi commented 2 years ago

Hi @xiaoyuMS and @chiz-ms

Has this fixed reached production? Or is it still in the works?

xiaoyuMS commented 2 years ago

It is still in the works of CDN deployment. I will come back for any update.

xiaoyuMS commented 2 years ago

Hi @sureshjoshi The fix is expected to reach production ring by the end of February.

xiaoyu03 commented 2 years ago

Hi @sureshjoshi Sorry for those poor experiences with these APIs and also thank you for your valuable feedback. Good news is that the fix has reached the production ring, please have a try.

We change the default behavior of insertFootnote/Endnote() to make sure that it can be called multiple times in a row. Before: The footnote/endnote editor will be opened and the focus will be switched to the editor after a footnote/endnote is inserted. Now: There is no UI action invoked after a footnote/endnote is inserted. image

No parameter change for insertFootnote/Endnote().

sureshjoshi commented 2 years ago

@xiaoyu03 Thanks! I'll take a look at them later this week to test!

ghost commented 2 years ago

This issue has been automatically marked as stale because it is marked as needing author feedback but has not had any activity for 4 days. It will be closed if no further activity occurs within 3 days of this comment. Thank you for your interest in Office Add-ins!

sureshjoshi commented 2 years ago

Bumping to avoid auto-close