Как мне подождать, пока все области будут зарегистрированы с помощью CustomizableUI в bootstrap.js::startup()?
Я создаю беспомощное дополнение, которое является CustomizableUI
виджет.
Когда я звоню CustomizableUI.createWidget()
в течение startup()
, Я хочу defaultArea
свойство быть одним из выбора предпочтительных областей. В настоящее время я достигаю этого примерно так:
// ordered from most to least preferred
let preferredAreas = [
'ctraddon_addon-bar',
'ctraddon_extra-bar',
CustomizableUI.AREA_BOOKMARKS,
CustomizableUI.AREA_NAVBAR,
// null basically translates to 'PanelUI-contents'
// but this makes it easy to test later on
null
];
let registeredAreas = CustomizableUI.areas;
let preferredArea;
for( let i = 0, l = preferredAreas.length; i < l; i++ ) {
preferredArea = preferredAreas[ i ];
if( registeredAreas.indexOf( preferredArea ) > -1 ) {
break;
}
}
if( !preferredArea ) { // i.e. null
/* on first run: notify user that we were unable to find a preferred area */
}
CustomizableUI.createWidget( {
id: 'myAddon',
type: 'custom',
defaultArea: preferredArea,
/* etc */
} );
Другими словами: я проверяю, присутствует ли предпочтительная область. Это работает в значительной степени, как ожидалось, в startup()
сразу после установки, потому что в основном все области интереса (из других расширений, таких как Classic Theme Restorer) уже зарегистрированы. Однако, когда мое дополнение уже установлено и Firefox запускается, CustomizableUI.areas
еще не заполнен всеми интересующими областями (возможно, потому что мое расширение загружается раньше, чем расширение, которое регистрирует интересующие области).
Я пытался использовать mostRecentWindow.addEventListener( 'load', /* etc */ )
, где mostRecentWindow
это возвращаемое значение nsIWindowMediator.getMostRecentWindow( 'navigator:browser' )
, но:
- при запуске приложения
mostRecentWindow
будетnull
- при установке дополнения
mostRecentWindow
не уволитload
событие больше
Итак, мой вопрос: каков простой и эффективный способ ожидания звонка CustomizableUI.createWidget()
пока весь соответствующий код не загружен?
В конечном итоге я сделал следующее (что также предложил Noitidart), что, похоже, работает:
let createWidget = function() {
/* all the preferredArea and CustomizableUI.createWidget() stuff from above */
}
let mostRecentBrowserWindow = windowMediator.getMostRecentWindow( 'navigator:browser' );
if( null == mostRecentBrowserWindow ) {
let windowListenerWidget = {
onOpenWindow: function( wrappedWindow ) {
windowMediator.removeListener( windowListenerWidget );
let domWindow = wrappedWindow.QueryInterface( Ci.nsIInterfaceRequestor )
.getInterface( Ci.nsIDOMWindow );
domWindow.addEventListener( 'load', function onWindowLoad( event ) {
this.removeEventListener( 'load', onWindowLoad );
createWidget();
} );
}
}
windowMediator.addListener( windowListenerWidget );
}
else {
createWidget();
}
1 ответ
Что вам нужно сделать, это добавить слушателя для onAreaNodeRegistered
, В обратном вызове создайте свой виджет.
Смотрите MDN:: CustomizableUI.jsm - addListener()
onAreaNodeRegistered и onAreaNodeUnregsitered не находятся на mdn, так что вот определения: http://mxr.mozilla.org/mozilla-release/source/browser/components/customizableui/src/CustomizableUI.jsm#2704
2704 * - onAreaNodeRegistered(aArea, aContainer)
2705 * Fired after an area node is first built when it is registered. This
2706 * is often when the window has opened, but in the case of add-ons,
2707 * could fire when the node has just been registered with CustomizableUI
2708 * after an add-on update or disable/enable sequence.
2709 * - onAreaNodeUnregistered(aArea, aContainer, aReason)
2710 * Fired when an area node is explicitly unregistered by an API caller,
2711 * or by a window closing. The aReason parameter indicates which of
2712 * these is the case.
2713 */
Так что для реализации сделайте это:
Сначала проверьте, существует ли область, которую вы хотите. Если это не так, добавьте слушателя. И в слушателе сделать виджет создания:
var targetAreaId = 'blah'; //the id of area you want test for, meaning the area you want to add your widget too, targetAreaId can be CustomizableUI.AREA_NAVBAR, basically its the id (first arg) argument of CustomizableUI.registerArea('blahIdHere'..
function createMyWidget() {
CustomizableUI.addWidget({
id: "edit-controls",
type: "custom",
defaultArea: targetAreaId,
onBuild: function(aDocument) {}
//........ blah blah balh
})
}
if (CustomizableUI.areas.indexOf(targetAreaId) > -1) { // customizableUI.areas is an array for example for me it is:`Array [ "PanelUI-contents", "nav-bar", "toolbar-menubar", "TabsToolbar", "PersonalToolbar", "addon-bar", "thePuzzlePiece-addon-bar" ]`
createMyWidget();
} else {
var myCustUiListener = {
'onAreaNodeRegistered': function(aArea, aContainer) {
//create your widget here
if (aArea.id == targetAreaId) { //im not sure of the properties on aArea do a console.log('aArea properties:', aArea) to see what all properties are there
createMyWidget();
}
}
};
CustomizableUI.addListener(myCustUiListener);
}