officedev / office-js-helpers Goto Github PK
View Code? Open in Web Editor NEW[ARCHIVED] A collection of helpers to simplify development of Office Add-ins & Microsoft Teams Tabs
License: MIT License
[ARCHIVED] A collection of helpers to simplify development of Office Add-ins & Microsoft Teams Tabs
License: MIT License
I get two different IDs in the same client.
And it was with different domains.
With one domain, I got one ID.
I wonder is there something to do with the server when generating IDs?
And how it effects.
I'm having issues trying to use this library in an Outlook web add-in with Azure AD. I can get the auth dialog to popup and have the user login and then authorize the application. However after that step (and subsequent retries) the auth page displays the "Sorry, but we're having trouble signing you in" page with this error:
AADSTS50011: The reply address 'https://mywebapp.azurewebsites.net' does not match the reply addresses configured for the application
The full issue is documented here: https://stackoverflow.com/questions/47276315/problems-with-azure-application-manifest-trying-to-authenticate-with-office-js-h.
What exactly is the relationship between the add-in's url and the Reply URL for the application manifest (I have the same for both)? That seems to be the core of the problem but I can't figure out what else it should be.
A secondary issue is that the auth popup doesn't appear when the add-in is hosted in a browser (it only works with Outlook desktop). I see a DOM error about blocking a cross-origin frame. Can the helpers be used at all from the browser?
I seem to be having the same problems as described in #5, but I'm using the latest version of this package (0.7.4
). I've made sure that all domains are in my manifest, and all the self-signed certs are installed correctly. I don't see any error messages, so it's difficult to troubleshoot, but after authentication succeeds, the redirect url is loaded into the existing auth popup instead of closing and sending the token back to the add-in. Is there anything else I can try to troubleshoot this?
I'm using a Mac - behavior is as expected if opened via Chrome itself (opens a pop-up), but when opened as an add-in within excel, it instead opens a new tab in Chrome preventing the user from completing the sign-in process.
Perhaps related to firebase/firebase-js-sdk#63 (though I'm using Chrome 64, which should be fixed)
Also is there any documentation on how to debug an add-in when it's opened within an Office product?
I'm trying to use the Office Helpers to authenticate against a private OAuth2 endpoint with implicit flow in a React based Add-In for Excel.
When I run the following code in the add-in within the Office.initialize
callback and my add-in is side loaded in Excel 365 :
const authenticator = new Authenticator();
authenticator.endpoints.add('MyID', {
...config options...
});
I always get the following error from chrome in the debug console:
Uncaught DOMException: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.
at EndpointStorage.Storage.switchStorage (eval at ../node_modules/@microsoft/office-js-helpers/dist/helpers/storage.js (https://localhost:3100/app.d84d4783b7237d4a074c.js:871:1), <anonymous>:121:61)
at EndpointStorage.Storage [as constructor] (eval at ../node_modules/@microsoft/office-js-helpers/dist/helpers/storage.js (https://localhost:3100/app.d84d4783b7237d4a074c.js:871:1), <anonymous>:104:15)
at new EndpointStorage (eval at ../node_modules/@microsoft/office-js-helpers/dist/authentication/endpoint.manager.js (https://localhost:3100/app.d84d4783b7237d4a074c.js:815:1), <anonymous>:38:23)
at new Authenticator (eval at ../node_modules/@microsoft/office-js-helpers/dist/authentication/authenticator.js (https://localhost:3100/app.d84d4783b7237d4a074c.js:807:1), <anonymous>:87:30)
at Object.eval (eval at ./main.tsx (https://localhost:3100/app.d84d4783b7237d4a074c.js:6972:1), <anonymous>:18:21)
at Object.eval (eval at ./main.tsx (https://localhost:3100/app.d84d4783b7237d4a074c.js:6972:1), <anonymous>:50:27)
at eval (eval at ./main.tsx (https://localhost:3100/app.d84d4783b7237d4a074c.js:6972:1), <anonymous>:51:30)
at Object../main.tsx (https://localhost:3100/app.d84d4783b7237d4a074c.js:6972:1)
at __webpack_require__ (https://localhost:3100/app.d84d4783b7237d4a074c.js:693:30)
at fn (https://localhost:3100/app.d84d4783b7237d4a074c.js:112:20)
Is there a way to prevent the EndpointManager from using the localStorage ?
I tried both version 0.7.4 and 0.8.0-beta.4 without success.
There are 4 occurrences where the config object is extended using the Lodash 'extend' method.
In each of these, the initial empty object is extended first with the overrides, then with the defaults. Doesn't this mean that any custom setting defined in the overrides will be actually overridden by an existing default value ?
OfficeHelpers.Utilities.host will return "WEB" while running in Office 2013 on Windows 7.
I believe (but haven't verified) that it's catching an error as below.
catch (error) {
return { host: 'WEB', platform: null };
}
Hi, I'm new to office-js. Want to create an outlook addin to talk to sharepoint online. Do you have an example of this?
The doc says:
Add the location of the provider in your AppDomains, example:
https://login.windows.net
https://login.microsoftonline.com
Where do i do that?
I found that this library is not working when I try to use it in Outlook 2013, and it seems to be due to the use of displayDialogAsync. Is this a known limitation? If so, perhaps it is something good to list in the readme?
@WrathOfZombies thanks for the beta to address #35. I tried using it, and after yarn add @microsoft/[email protected]
, I'm getting the following error when I try to build my extension:
Module not found: Error: Can't resolve './message-banner.html' in 'node_modules/@microsoft/office-js-helpers/dist/ui'
I believe you need to use file-loader
in addition to html-loader
to get the contents of the html file. (But that's just a guess).
Authenticator opens up popup window where user can put credentials but it is not returning any token as specified.
It's more an information than an issue.
If you are using angularjs router or stateprovider with redirecting, the popup url will immediately redirected to the default url you set.
The result of that is, that the token couldn't read out of the URL from the popup. Additionally the popup doesn't close automatically.
Sometimes it works because in this case the read out was faster than the redirection of angularjs.
Is it possible to use it for Azure Active Directory B2C ? When i try to use the library with following code:
this.authenticator = new OfficeHelpers.Authenticator();
this.authenticator.endpoints.registerAzureADAuth('myClientId', 'myTenant');
...
this.authenticator.authenticate(OfficeHelpers.DefaultEndpoints.AzureAD)
It's opening the "general" microsoft login page instead of my tenant's login page.
Hi,
There should be samples to implement OfficeJSHelper.
Samples Like : Javascript Samples - SPA, C# .NET and NodeJS implementation.
*** Sorry in advance if this is not the right forum for this question! ***
I would like to detect whether a user has hit the URL of my add-in from a browser, outside of Office and Office online.
I've looked at the utility functions OfficeHelpers.Utilities.host
and OfficeHelpers.Utilities.isAddin
but the docs say these will only work after Office.initialize is called. If the URL has been navigated to from outside of an Office client then this won't be the case (?).
So I need to perform the same check as whatever is being done when you get the warning:
A simple use of this, would be to direct users to a page that displays explains they cannot access this without loading it as an add-in, and instructions on how to load the add-in etc.
The actual result I am trying to get is to handle both cases as:
Is there anything wrong with doing this? And how should it be done?
Today's readme says the following:
Inside of your Office.initialize function add the following check:
if (OfficeHelpers.Authenticator.isAuthDialog()) return;
This to inform the Authenticator to automatically close the authentication dialog once the
authentication is complete.
This works great for an Office Add-in. But what about the web scenario? There the function returns "false" because host is web, and so the dialog flow -- including messaging back to the parent -- fails to complete.
You can actually see this in Script Lab itself, when using it on the web. Just try signing in to https://script-lab.azureedge.net/
Note that the issue only manifests itself on Internet Explorer (IE 11), not Chrome.
Suggestion: Rather (or in addition) to having the isAuthDialog
method (which is actually a bit weird anyway, having it be an is
but having sideffects), can we have a closeAuthDialog
method? Ideally the authenticate
method would just add some query string parameter (e.g., ?isAuthDialog=true
to the return URI, and read it off from there). I am also ok with that method requiring a parameter, I can do the query string myself. But in any case, I need to be able to close the dialog even when running in IE11 in a web-only context.
Thanks!
Hi, I see that you've pinned to rxjs version 5.2.0
instead of following semver with something like ^5.2.0
. I am also using rxjs in my add-in, but at a different (more recent) version. Because of this, I now have two versions of the same package being bundled. Is it possible to use a more generous range for rxjs
in this package?
Thanks!
How do you run your tests? I did not find npm run test
.
On a related note, typings
is required for npm run build
. I see you install it for travis... I suspect it was an oversight to not including installing typings with npm install
. I can see why you wouldn't put it in definition for npm run build
because you don't need to keep installing typings. I suspect you want to add:
"postinstall": "npm run typings install"
to the scripts section of your package.json?
How do you logoff and forcefully expire\delete the cached token ?
Using adal.js with implicit flow it is possible to refresh the obtained access token (without a refresh token) and thus prolong the user session without requiring user login. This is possible until the Azure AD session cookies expire.
Is this possible with office-js-helpers? I would like to keep the user logged in as long as possible.
When I trying to authenticate using registerMicrosoftAuth I notice that the token expire by default in 3600 seconds.
I was reviewing the library and I'm seeing a method setExpiry inside TokenStorage class
office-js-helpers/src/authentication/token.manager.ts
Lines 42 to 47 in 4687cc5
Is there any easy way to set the desired expiration date before request the authenticate method?
This is how I'm requesting the token:
OutlookAuthenticate() {
const authenticator = new Authenticator();
authenticator.endpoints.registerMicrosoftAuth(microsoftApplicationClientId, {
scope: 'User.Read User.ReadBasic.All Contacts.Read Contacts.ReadWrite',
});
return authenticator.authenticate(DefaultEndpoints.Microsoft)
.then(this.parseResponse);
}
I noticed that my bundle for my add-in has 74kb (gzipped) of lodash in it, even though I don't use lodash in my project. It seems that it's being pulled in because of office-js-helpers
and the way that it imports from lodash
.
I did a little investigating, and it seems that as of today, it's not super simple to tree-shake lodash with typescript. https://medium.com/@martin_hotell/tree-shake-lodash-with-webpack-jest-and-typescript-2734fa13b5cd has a good rundown of the challenges and various approaches that can be taken. It seems that there's upcoming support for a pure-modules
flag that lodash can/will use, but it doesn't seem to be released in webpack yet:
https://twitter.com/jdalton/status/893109185264500737, and it also seems this project uses browserify. Also, I think you'd need to compile down to ES2015 modules, which I'm not sure all your consumers would be able to handle, so you'd need to perhaps have multiple different builds.
One sure-fire way of ensuring that you do not ship extra code to consumers is to depend on individual lodash modules like lodash.iserror
. Then, no matter what kind of build process the consuming add-ins use, they are guaranteed not to get too much code.
I attempted various approaches like importing from lodash-es
instead of lodash
, more focused imports like import debounce from 'lodash/debounce';
, etc. But I ran into trouble with either typescript or browserify, neither of which I have much experience with.
So, I guess I would ask if you could find some way to avoid consumers from pulling in all of lodash because of office-js-helpers
.
Hi,
Running over IE or Edge has different behavior than running on Firefox or Chrome. While Chrome and Firefox authentication popup window closes once authentication is done, and data is retrieved back in the original window, this is not the case within Internet Explorer or Edge.
IE and Edge popup window won't close which causes retrieved token to remain in new popup window rather than return to original caller window. Once authentication is done, the new popup window is redirected to the "redirection URL" assigned in endpoint.
I'm receiving an error when calling authenticator.authenticate to authenticate to AAD. If I debug into line 257 of officehelpers.js, I see that the error code is a 12007, which according to the office docs corresponds to multiple dialog boxes opened, but no dialog has been opened. Do I have something wrong with the configuration? I've also added login.windows.net as an app domain to my manifest. My code making the call is below.
let authenticator = new OfficeHelpers.Authenticator();
authenticator.endpoints.registerAzureADAuth("<clientId>", "<tenantName>")
console.log(authenticator)
authenticator
.authenticate(OfficeHelpers.DefaultEndpoints.AzureAD)
.then(function (token) { console.log("Successfully authenticated", token) })
.catch(function(error) { console.log("Failed to authenticate", error) })
Is there a working sample of using authenticator with Office addin?
See:
If you set up an OAuth endpoint via:
const authenticator = new Authenticator();
authenticator.endpoints.add(OAUTH_CLIENT.clientName, {
clientId: OAUTH_CLIENT.clientId,
baseUrl: OAUTH_CLIENT.baseUrl,
authorizeUrl: OAUTH_CLIENT.authorizeUrl,
responseType: 'token'
});
And try to print out a token (should be null
), via:
console.log(authenticator.tokens.get(OAUTH_CLIENT.clientName));
You get the endpoint configuration back.
Suggested fix:
Change line 36 in token.manager.ts
to super('OAuth2Tokens', storageType);
Following advice from #41 on logout, I implemented logout of Azure AD using this code:
function Logout() {
window.location.replace("https://login.microsoftonline.com/" + Tenant + "/oauth2/logout?post_logout_redirect_uri=" + encodeURIComponent(location.origin + location.pathname));
}
This takes me to the Azure AD logout page and seems to be doing logoff...
Then I'm redirected to the post_logout_redirect_uri, which is my main page from SPA office web addins, and the following calls are made again:
authenticator.endpoints.registerAzureADAuth(...)
authenticator.authenticate(OfficeHelpers.DefaultEndpoints.AzureAD)
This brings up the Azure AD login dialog, which immediately closes and reauthenticates with same user... So I'm unable to login with a different user, and entering a loop of login/logout...
Am I missing something here? Do I need to also clear cookies or localstorage or sessionstorage or else?
Where are the tokens saved? Can I delete them from my code?
Thanks
In the case that host
is undefined
it would be helpful if there was a default value here: https://github.com/lemniscate-labs/office-js-helpers/blob/master/src/helpers/utilities.ts#L102
Can it fallback to the following:
return officeJsToHelperEnumMapping[host] || host || HostType.WEB;
Does this framework support the implementation of consent framework - https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-integrating-applications#overview-of-the-consent-framework?
I'm experiencing some issues atm, where the consent is not being requested for users from another tenant.
Thanks
Hi,
I am building an OfficeJS add-in for Word that is using Angular 4.
I installed @microsoft/office-js-helpers from NPM:
npm install @microsoft/office-js-helpers --save
Then, as soon as I reference it:
import { Utilities } from '@microsoft/office-js-helpers';
and then ng build
I get the following:
webpack: Compiling...
Hash: cdde99e2c228a80bddc3
Time: 385ms
chunk {0} polyfills.bundle.js, polyfills.bundle.js.map (polyfills) 232 kB {4} [initial]
chunk {1} styles.bundle.js, styles.bundle.js.map (styles) 65.2 kB {4} [initial]
chunk {2} main.bundle.js, main.bundle.js.map (main) 5.09 kB {3} [initial] [rendered]
chunk {3} vendor.bundle.js, vendor.bundle.js.map (vendor) 2.73 MB [initial]
chunk {4} inline.bundle.js, inline.bundle.js.map (inline) 0 bytes [entry]
ERROR in [PATH]/node_modules/@microsoft/office-js-helpers/dist/office.helpers.d.ts (303,41): Cannot find namespace 'Excel'.
ERROR in [PATH]/node_modules/@microsoft/office-js-helpers/dist/office.helpers.d.ts (303,106): Cannot find namespace 'Excel'.
webpack: Failed to compile.
What am I doing wrong?
this repo contains "demo" folder, in this url http://dev.office.com/docs/add-ins/develop/auth-external-add-ins.
"The \demo folder of the repo contains a sample add-in that uses the library to access some popular services including Google, Facebook, and Office 365."
But I can't find it. Where is demo folder??
I have been trying to implement a custom app in Teams. As part of the app i am making a call to an external web API. I am trying to use the office-js-helpers library to obtain a id_token, but I am seeing that the _handleTokenResult does not handle the id_token responsetype result, even though the library allows for providing a responseType. Am I missing something obvious? Or is not supporting this auth pattern intentional within the library. Also, i am using this library to handle the team situation with the popup as opposed to hidden IFRAME that the adal.js library uses.
I started new office JS project , the default Word sample, removed all code in Office.initialize, to the point where I only get the following code in Home.js:
`(function () {
"use strict";
// The initialize function must be run each time a new page is loaded.
Office.initialize = function (reason) {
$(document).ready(function () {
if (OfficeHelpers.Authenticator.isAuthDialog())
return;
var authenticator = new OfficeHelpers.Authenticator();
authenticator.endpoints.registerAzureADAuth('##MYAPPID##', '##MYTENANT##');
authenticator
.authenticate(OfficeHelpers.DefaultEndpoints.AzureAD, true)
.then(function(token) {
console.log(token);
})
.catch(OfficeHelpers.Utilities.log);
});
};
})();`
I know this appId and tenant work fine since I can get the same code to work with ADAL outside office JS, and already ironed out all reply urls and other issues,
The call to _openAuthDialog inside authenticator.authenticate never returns to the promise, and I experience the following error in JS console:
The Auth popup does appear on top of Web Add-ins, but closes immediately after echoing this error,
Any ideas what is going wrong?
Second question: Am I correct to assume I can use this library for something else than MS Graph, such as Microsoft Dynamics 365 OData endpoint which supports OAuth 2.0 as well, or is this just for Office365 and MSGraph?
Thanks
Hi office-js-helpers,
Great tool, I just can't figure out where to get the username after receiving the token?
I know ADAL.js gives us the username, but can't find it in this lib.
Any advice?
We are using this library to handle authentication, but when clicking our Log in
button, users are shown a App wants to display a new window.
dialog which they can choose to Allow
or Ignore.
Is there any way to avoid this clunky interaction? I am concerned that it will cause confusion and abandonment among our users.
If there's currently no way (it seems there isn't), is there a chance that any changes could be made so that it can be avoided/eliminated?
I am right now trying to get an id_token through Office-js-helpers, because this seems compatible with ADAL.js behaviour for my app:
me.Authenticator = new OfficeHelpers.Authenticator();
me.Authenticator.endpoints.registerAzureADAuth(settings.clientId, settings.tenant, {
responseType: 'id_token',
redirectUrl: window.location.origin + window.location.pathname
});
me.Authenticator
.authenticate(OfficeHelpers.DefaultEndpoints.AzureAD)
.then(function (token) {
me.successCallback(token.id_token);
})
.catch(OfficeHelpers.Utilities.log);
This fails in Office-js-helpers because authenticator._handleTokenResult does not handle the "id_token" case.
When I use OfficeHelpers.Authenticator.isAuthDialog() throw this error and IE doesn't close de dialog
Example:
Office.initialize = function (){
if (OfficeHelpers.Authenticator.isAuthDialog()) return;
var authenticator = new OfficeHelpers.Authenticator();
authenticator.endpoints.add("endpoint", {
baseUrl: "BASE_URL",
authorizeUrl: "Authorize_URL",
clientId: "Client_id",
responseType: "token",
scope: "user",
redirectUrl: "redirect",
});
var t = authenticator.authenticate("endpoint");
t.then(function(token){
console.log("logged");
})
.catch(function(error){
console.log(error);
})
}
I am using the AzureAD SAML2 for My WebApp which we are soon going to integrate with Office 365.
We have SAML2 in office-js-helpers
I got the SSO login working in Chrome with popup, and now I am trying the Outlook plugin against Outlook 2016 (EXE version 16.0.8431.2107). When I open F12 Developer Tools and call
Authenticator.authenticate("AzureAD")
I get
Script 5022: Die Domäne der URL ist nicht im "AppDomains"-Element im Manifest enthalten.
but the endpoint's baseUrl is
https://login.windows.net/09265c06-...-1c39
and my AddIn's AppDomains are (copied from a Microsoft list):
``
api.login.microsoftonline.com
clientconfig.microsoftonline-p.net
device.login.microsoftonline.com
hip.microsoftonline-p.net
hipservice.microsoftonline.com
login.microsoft.com
login.microsoftonline.com
logincert.microsoftonline.com
loginex.microsoftonline.com
login-us.microsoftonline.com
login.microsoftonline-p.com
nexus.microsoftonline-p.com
stamp2.login.microsoftonline.com
login.windows.net
I now found this comment by a Microsoft employee:
The page, controller method, or other resource that is passed to the displayDialogAsync method must be in the same domain as the host page.
It seems that you call displayDialogAsync with the remote URL; is that correct, and did that work for anyone at all?
Hello,
I just discovered OfficeJSHelpers. I added console.log("OfficeHelpers.Utilities.host: " + OfficeHelpers.Utilities.host)
and console.log("OfficeHelpers.Utilities.platform: " + OfficeHelpers.Utilities.platform)
to my website. It works fine, but when I load in a browser https://localhost:3000/try?_host_Info=excel|web|16.00|en-us|7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc|isDialog#%2Ftry%3F_host_Info=excel%7Cweb%7C16.00%7Cen-us%7C7fe9b4e9-d51e-bea5-d194-c817bc5ed4bc%7CisDialog
(see why I have this url here), it considers EXCEL
as host
and OFFICE_ONLINE
as platform
, and raised an error Uncaught TypeError: Cannot read property '_appName' of null
in excel-web-16.00.js
.
What is worse is that, it disturbs the loading of other pages. Now, all the pages like https://localhost:3000/home
or https://localhost:3000/try
in a browser returns EXCEL
as host
and OFFICE_ONLINE
as platform
, and raised an error Uncaught Error: Sys.ArgumentNullException: Value cannot be null. Parameter name: conversationId
in excel-web-16.00.js
. The only solution is to clearing browser history data.
I think it is a bug...
Thank you
Do you have samples of unit tests for this framework, where we can supply test user credentials
and more generally how do we test any office js addins?
Ta
The state was undefined because in "params" the "state" got saved like this: "result./state"
`Authenticator.extractParams = function (segment) {
if (segment == null || segment.trim() === '') {
return null;
}
var params = {}, regex = /([^&=]+)=([^&]*)/g, matchParts;
while ((matchParts = regex.exec(segment)) !== null) {
// NEXT LINE GOT ADDED
if (matchParts[1] === "/state") matchParts[1] = matchParts[1].replace("/", "");
params[decodeURIComponent(matchParts[1])] = decodeURIComponent(matchParts[2]);
}
return params;
};`
Using adal.js with implicit flow after user login (Azure AD in my case) it is possible acquire tokens for multiple services without user interaction. Is this possible with office-js-helpers?
Hi,
So far I followed all the steps on how to setup this. Like adding the IDP/SSO in app domain list in the manifest file. Setting the Requirement set MinVersion to 1.4 of Mailbox. Using https and trusted cert.
The authentication popup is working and redirecting to our SSO eg google and custom SSO (Identity Server 4). The user can login but when it comes to close or send a message from popup dialog to the parent windows it always says :
Failed to execute 'postMessage' on 'DOMWindow': The target origin provided ('https://outlook.office.com') does not match the recipient window's origin ('https://localhost:3000').
invoke @ outlook-web-16.01.js:9
Btw, the popup or the invoke of authenticate was fired from the web outlook addin.
Any idea or tips on how to solve this?
Thanks
Mike
Under Application Registration Portal, there are 2 types of applications, converaged app and Azure AD only app.
I followed the steps and successfully get the token from the app in "converaged app" type.
However the same code same settings, it does not work when the app in "Azure AD only applications" type. The returned error when calling the authenticator.authenticate
method is,
AADSTS90130 : Application'[My App ID]' ([My App Name]) is not supported over the /common or /consumers endpoints. Please use the /organizations or tenant-specific endpoint.
I also tried to use the Azure AD by adding the following to authenticator.endpoints.registerMicrosoftAuth
, but it does not work too and the new error is
baseUrl: "https://login.microsoftonline.com/[My Tenant ID]/oauth2"
Error Message is:
AADSTS50001 : Resource identifier is not provided.
Hi,
I have done following code in Home.js. It returns following exception.
Unhandled exception at line 1, column 1149 in https://localhost:44365/office.helpers.min.js
0x800a1391 - JavaScript runtime error: 'Promise' is undefined occurred
Solution : Add following code before OfficeJSHelper.js
<!-- IE support: add promises polyfill before msal.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bluebird/3.3.4/bluebird.min.js" class="pre"></script>
Is there a way to catch or handle this error (thrown if the user clicks "Ignore" when prompted to open a new window for oauth)?
I've got a .catch
in place which is reached if the user closes the opened dialog prematurely, but there doesn't seem to be any higher level with which to wrap the call to authenticate
.
authenticator
.authenticate(`${subdomain}.${domain}`, force)
.then(function(token) {
console.log("got token", token)
return token
})
.catch(function(err) {
console.log("error authenticating (user closed dialog)", err)
})
Hello,
I load the following page as an Excel add-in in Excel (Office 365 Version 1706) for Windows 7. It shows EXCEL
as host
, but null
as platform
. I cleared my browser history before the tests...
It seems that for the same code, it showed PC
yesterday...
Shouldn't it be always PC
in Excel for Windows?
Thank you
<html>
<head>
<script src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
<script src="https://unpkg.com/@microsoft/[email protected]/dist/office.helpers.min.js"></script>
</head>
<body>
<div id="console"></div>
<script>
debug("OfficeHelpers.Utilities.host: " + OfficeHelpers.Utilities.host + "<br/>");
debug("OfficeHelpers.Utilities.platform: " + OfficeHelpers.Utilities.platform);
function debug(msg) {
if (document.getElementById("console") !== null)
document.getElementById("console").innerHTML += msg;
}
</script>
</body>
</html>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.