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
670 stars 96 forks source link

History API's pushState & replaceState are nullified by Office.js #429

Open shirbr510 opened 5 years ago

shirbr510 commented 5 years ago

I'm currently writing an outlook add-in that can also act as a web application. Office.js's code consists of some history API nullifying logic that turns history.pushState & history.replaceState into null. this behaviour will break all Add-ins that try to use modern routing solutions like react-router, etc...

Expected Behavior

history API will remain unharmed.

Current Behavior

history.pushState & history.replaceState become null

Steps to Reproduce, or Live Example

Your Environment

I assume that these are the relevant piece of code:

https://github.com/OfficeDev/office-js/blob/b357f8e44939c9bd92fe6c04edb8a8eb541b30e6/dist/office.debug.js#L1587 https://github.com/OfficeDev/office-js/blob/b357f8e44939c9bd92fe6c04edb8a8eb541b30e6/dist/office.debug.js#L1588

Zlatkovsky commented 5 years ago

FYI, there appears to be a related question (and explanation/workaround) here: https://stackoverflow.com/questions/42642863/office-js-nullifies-browser-history-functions-breaking-history-usage

exextoc commented 5 years ago

The internal Outlook browser has does not support the History API. The history.replaceState and history.pushState are visible but just throw “unspecified error” when used. Due to this behavior, the history objects are set to null in Office.js by-design.

shirbr510 commented 5 years ago

@exextoc any plans on supporting the history API anytime soon? Also, on which specific environment is it not supported? Ios native browser? Android? Cause locally on my mac with the native outlook it appears to be working properly

shirbr510 commented 5 years ago

@Zlatkovsky I actually posted a similar solution on stack overflow to a different variation of this question (that might be a duplicate to the one you posted) https://stackoverflow.com/questions/33954663/unable-to-use-window-history-replacestate-function-in-mail-addin/55202524#55202524

vyazadji commented 5 years ago

I faced an issue in Windows Outlook after restore history.replaceState and history.pushState

//save "replaceState" and "pushState"
window._historyCache = {
        replaceState: window.history.replaceState,
        pushState: window.history.pushState
   };

//LOADING Office.js
...

//restore "replaceState" and "pushState"
window.history.replaceState = window._historyCache.replaceState;
window.history.pushState = window._historyCache.pushState;

They throw some unexpected error :( (Looks like due of this these methods were disabled in Office.js) So react router didn't work. But I found one interesting thing. If suppress the error they do their work.

So my final result is:

    function isIE10 () {
      return !!document.documentMode
    }

    // Office js deletes window.history.pushState and window.history.replaceState. Cache them and restore them
    // Also there is an issue in Windows Outlook with `pushState` and `replaceState`. They throw an error but in the same time do their expected work
    // So I suppress errors for IE10 (we use it inside Window Outlook)
    window._historyCache = {
      replaceState: function (originalReplaceState) {
        return function () {
          try {
            return originalReplaceState.apply(window.history, arguments)
          } catch (e) {
            if (isIE10()) {
              console.warn("Unexpected error in 'window.history.replaceState', but we can continue to work :)");
              return false;
            }
            throw(e);
          }
        }
      }(window.history.replaceState),
      pushState: function (originalFunction) {
        return function () {
          try {
            return originalFunction.apply(window.history, arguments)
          } catch (e) {
            if (isIE10()) {
              console.warn("Unexpected error in 'window.history.pushState', but we can continue to work :)");
              return false;
            }
            throw(e);
          }
        }
      }(window.history.pushState)
    };

      // In Window Outlook we have issue with 'replaceState' and 'pushState. So replaced it by wrapped version.
      window.history.replaceState = window._historyCache.replaceState;
      window.history.pushState = window._historyCache.pushState;

//include the main code with react-router
//include Office.js

   Office.initialize = function () {

    // Office js deletes window.history.pushState and window.history.replaceState. Restore them
    window.history.replaceState = window._historyCache.replaceState;
    window.history.pushState = window._historyCache.pushState;

    // Now you can start initialize&&run your application
        ....
   }
shirbr510 commented 5 years ago

@vyazadji correct me if I'm wrong, IE10 has reached EOL about 2 years ago and all the rest of the browsers should have full history API support

vyazadji commented 5 years ago

@shirbr510 I say about IE10 because it runs inside Outlook under Windows. My Windows version is 10 Pro, default browser is Edge 42.17134.1.0 . But the right side bar where Outlook runs add-in uses this old browser (IE10 as a browser also is in Windows). I don't know this is true for all Windows or it's some specific case for my version. So I must adapt my add-in (and part of my application which I use in this add-in) for IE10 ;(

PS. IE10 supports history.replaceState and history.pushState, but inside Outlook I have problems with these methods, so simple restore doesn't work for me.

exextoc commented 5 years ago

Navigation is not available in mshtml, but available in WebKit (hence Mac), which is why it works on MAC but not on win32. We are actively working on enabling a new WebView Control based off of Edge where history will be supported.

exextoc commented 5 years ago

https://developer.microsoft.com/en-us/office/blogs/microsoft-edge-webview-for-office-add-ins/

shirbr510 commented 5 years ago

@exextoc so from now on, history API is supported everywhere?

cause as far as the post explains, only new Office365 based versions will support history API

exextoc commented 5 years ago

Only on new versions.

sundariragavan commented 3 years ago

@vyazadji @exextoc i'm getting this error Uncaught TypeError: Cannot read property 'apply' of null . How to solve this error.

vyazadji commented 3 years ago

@sundariragavan I resolved it as described here https://github.com/OfficeDev/office-js/issues/429#issuecomment-479982199. It was more than a year ago. I no longer work on a project, where I used it, so I can't confirm that it's still actual.

jcbdev commented 2 years ago

this works for me fix in angular which manifests as a routing loop which crashes the browser eventually

<body>
    <app-root></app-root>
  </body>
  <script>
    // this late load is required due to bug in office-js causing a routing loop
    // https://github.com/OfficeDev/office-js/issues/1198
    // https://github.com/OfficeDev/office-js/issues/1344
    // https://github.com/OfficeDev/office-js/issues/429
    let replaceState = window.history.replaceState;
    let pushState = window.history.pushState;
    var head = document.getElementsByTagName("head")[0];
    var script = document.createElement("script");
    script.type = "text/javascript";
    script.onload = function () {
      Office.onReady().then(() => {
        console.log("Office is ready!");
        window.history.replaceState = replaceState;
        window.history.pushState = pushState;
      });
    };
    script.src = "/assets/office-js/office.js";
    head.appendChild(script);
  </script>
chenxizhang commented 2 years ago

echo this issue, I faced this problem too.

remain use the react-router-dom (5.2.1) can solve this problem, but why office.js set "pushState" to "null"?

geneLavender commented 1 year ago

I'm seeing this issue appear again for react-router-dom 5.3.4 latest

KaiyuanMa commented 1 year ago

got Uncaught TypeError: history.replaceState is not a function

lsmith77 commented 10 months ago

since the bug is still not fixed (https://appsforoffice.microsoft.com/lib/1/hosted/office.js), could someone reopen the issue and look into fixing it?

frank-hoffman commented 8 months ago

since the bug is still not fixed (https://appsforoffice.microsoft.com/lib/1/hosted/office.js), could someone reopen the issue and look into fixing it?

I concur. The issue persists.

montella1507 commented 8 months ago

I cannot believe Microsoft is deleting basic HTML5 api of the browser... How is that even possible in 2023? It destroys React/Angular/ any SPA framework..

O365/Exchange is really garbage software on every line of code.... No wonder EHchange / O365 can handle upmost 20 mailbox requests at the same time DOMAIN_WIDE.

Just let that software die.

frank-hoffman commented 8 months ago

I've come to the conclusion that Microsoft really doesn't want you to navigate between pages this way in an Office add-in. What I've done instead is just map links to actions in the ribbon through the manifest.

montella1507 commented 8 months ago

Yeah Microsoft wants us to use 20 years deprecated Hash strategy.. Legacy, thats the way Microsoft likes it.

jimbarrett33 commented 7 months ago

What is closed/completed about this issue?

If this is an Outlook only problem then do fix testing for only outlook before replaceState and pushState are nulled out. Don't break all other add-in hosts.

janbensch commented 6 months ago

@exextoc This issue still persists as @gergzk describes in https://github.com/OfficeDev/office-js/pull/2808#issuecomment-1813034595. Please reopen this issue for transparency reasons as it is clearly not solved.

gergzk commented 6 months ago

Good news! We've recently made the fix discussed above (just removed the overrides). Expect to see it roll out in the newest office.js versions in about a week or two.

tqmp commented 6 months ago

Hey @gergzk - I wonder if the update has been rolled out. The issue still persists when I load my Outlook add-in using Nextjs webapp. What do you recommend I should do? Thanks a lot!

Uncaught TypeError: window.history.replaceState is not a function

nikhilatsap commented 5 months ago

Hey @gergzk this error is still there in the office.js hosted at /lib/1 CDN url

gergzk commented 5 months ago

@nikhilatsap - yes, we had to roll back the fix because it had other unwanted side effects. We'll look into adding it as an opt-in.

nikhilatsap commented 5 months ago

Ok Thanks for clarifying that @gergzk , My code suddenly stopped working in production because of this change after I had got it tested and deployed, Can you please let me know if you guys have a fixed timeline for it to provided as an opt-in?

RudyCo commented 5 months ago

I cannot believe Microsoft is deleting basic HTML5 api of the browser... How is that even possible in 2023? It destroys React/Angular/ any SPA framework..

O365/Exchange is really garbage software on every line of code.... No wonder EHchange / O365 can handle upmost 20 mailbox requests at the same time DOMAIN_WIDE.

Just let that software die.

It also breaks Blazor Web App, which is a 100% Microsoft product!

andrew-at-acta commented 4 months ago

I cannot believe Microsoft is deleting basic HTML5 api of the browser... How is that even possible in 2023? It destroys React/Angular/ any SPA framework.. O365/Exchange is really garbage software on every line of code.... No wonder EHchange / O365 can handle upmost 20 mailbox requests at the same time DOMAIN_WIDE. Just let that software die.

It also breaks Blazor Web App, which is a 100% Microsoft product!

Currently experiencing this issue while migrating a angular-based Outlook add-in to angular V16.

ovdixon commented 1 month ago

Any update on a new fix?

@nikhilatsap - yes, we had to roll back the fix because it had other unwanted side effects. We'll look into adding it as an opt-in.