If we load a webpage referencing office.js
outside Office client, we will get a warning: Office.js is loaded outside of Office client
.
This information is useful.
Does anyone know if there is an API to check that inside my code?
Edit 1:
I explain a little bit my scenario and why I ask this question. I am making an application with angularjs which can be loaded in a browser as a web page or in Office as an add-in. And I realise that we should not do <body ng-app="myApp">
and angular.bootstrap(document, ['myApp'])
together, otherwise controllers will execute twice. So I decided to not write <body ng-app="myApp">
and always use angular.bootstrap
in both cases (ie, web page & add-in).
So for a web page, I could write:
$(document).ready(function () {
angular.bootstrap(document, ['myApp'])
})
app = angular.module('myApp', ['ui.router', 'ui.bootstrap'])
...
So for a web page, I need to write angular.bootstrap
inside Office.initialize
, and share other code with the case of add-in:
Office.initialize = function (reason) {
$(document).ready(function () {
angular.bootstrap(document, ['myApp'])
});
}
app = angular.module('myApp', ['ui.router', 'ui.bootstrap'])
// share the same code
However, if I write these two cases together as follows, it works for a web page, whereas I gives Error: ng:btstrpd App Already Bootstrapped with this Element for add-in.
$(document).ready(function () {
angular.bootstrap(document, ['myApp'])
console.log("bootstrapped outside Office.initialize")
})
Office.initialize = function (reason) {
$(document).ready(function () {
angular.bootstrap(document, ['myApp'])
console.log("bootstrapped inside Office.initialize")
})
}
app = angular.module('myApp', ['ui.router', 'ui.bootstrap']).
If I set a flag, console will display bootstrapped outside Office.initialize
followed by isBootstrapped
, then running the code will show that Office.context
or Office.context.document
is undefined:
var isBootstrapped = false;
$(document).ready(function () {
angular.bootstrap(document, ['myApp'])
isBootstrapped = true
console.log("bootstrapped outside Office.initialize")
})
Office.initialize = function (reason) {
$(document).ready(function () {
if (isBootstrapped) console.log("isBootstrapped")
else {
angular.bootstrap(document, ['myApp'])
console.log("bootstrapped inside Office.initialize")
}
})
}
app = angular.module('myApp', ['ui.router', 'ui.bootstrap'])
So I really need an efficient way to check if Office.js is loaded outside of Office client (ie, whether it is a web page or an add-in), to decide which piece of angular.bootstrap
should be executed.
There is no such API at the moment, though we've internally talked about having an
Office.ready()
(similar in spirit to$(document).ready(...)
), that would fire whenever Office.js is done initializing (whether in the add-in or not).You are welcome to suggest it on https://github.com/OfficeDev/office-js, and post a link here. My thought on the API is that it would take in a callback (just like
$(document).ready(...)
that it would fire when ready, and would also be available in promise form (so you can doawait Office.ready()
). Do you think that works for your scenario?FWIW: As a workaround, for Script Lab, we wrap a Promise around Office.initialized (and make sure to do it early on in the loading of the application, else it won't fire if it's much later), wait for it, and if we don't receive anything in the first 3 seconds we show a set of buttons to let the user help disambiguate for us. See https://script-lab.azureedge.net/ for an example of what that looks like. Not perfect, but was OK-ish for our scenario. I do encourage you to file a suggestion bug on the office-js repo, though, adding your concrete scenario to back it.
One way is to use https://github.com/OfficeDev/office-js-helpers.
Both
OfficeHelpers.Utilities.host
andOfficeHelpers.Utilities.platform
provide useful information.