2013-07-30 08:46:36 +00:00
|
|
|
define([
|
|
|
|
"jquery",
|
|
|
|
"underscore",
|
|
|
|
"crel",
|
|
|
|
"utils",
|
|
|
|
"classes/Extension",
|
|
|
|
"settings",
|
|
|
|
"text!html/settingsExtensionsAccordion.html",
|
|
|
|
"extensions/partialRendering",
|
|
|
|
"extensions/userCustom",
|
2013-08-22 00:19:59 +00:00
|
|
|
"extensions/buttonMarkdownSyntax",
|
2013-07-30 08:46:36 +00:00
|
|
|
"extensions/googleAnalytics",
|
|
|
|
"extensions/dialogAbout",
|
|
|
|
"extensions/dialogManagePublication",
|
|
|
|
"extensions/dialogManageSynchronization",
|
|
|
|
"extensions/dialogOpenHarddrive",
|
2013-08-12 00:10:26 +00:00
|
|
|
"extensions/documentTitle",
|
2013-07-30 08:46:36 +00:00
|
|
|
"extensions/documentSelector",
|
2013-08-12 00:10:26 +00:00
|
|
|
"extensions/documentPanel",
|
2013-08-11 00:52:05 +00:00
|
|
|
"extensions/documentManager",
|
2013-07-30 08:46:36 +00:00
|
|
|
"extensions/workingIndicator",
|
|
|
|
"extensions/notifications",
|
|
|
|
"extensions/markdownExtra",
|
|
|
|
"extensions/toc",
|
|
|
|
"extensions/mathJax",
|
|
|
|
"extensions/emailConverter",
|
|
|
|
"extensions/scrollLink",
|
2013-09-11 23:26:47 +00:00
|
|
|
"extensions/focusMode",
|
2013-07-30 08:46:36 +00:00
|
|
|
"extensions/buttonSync",
|
|
|
|
"extensions/buttonPublish",
|
|
|
|
"extensions/buttonShare",
|
|
|
|
"extensions/buttonStat",
|
|
|
|
"extensions/buttonHtmlCode",
|
|
|
|
"extensions/buttonViewer",
|
2013-09-03 10:37:59 +00:00
|
|
|
"extensions/welcomeTour",
|
2013-08-30 22:45:29 +00:00
|
|
|
"bootstrap",
|
|
|
|
"jquery-waitforimages"
|
2013-07-30 08:46:36 +00:00
|
|
|
], function($, _, crel, utils, Extension, settings, settingsExtensionsAccordionHTML) {
|
|
|
|
|
|
|
|
var eventMgr = {};
|
|
|
|
|
|
|
|
// Create a list of extensions from module arguments
|
|
|
|
var extensionList = _.chain(arguments).map(function(argument) {
|
|
|
|
return argument instanceof Extension && argument;
|
|
|
|
}).compact().value();
|
|
|
|
|
|
|
|
// Configure extensions
|
|
|
|
extensionSettings = settings.extensionSettings || {};
|
|
|
|
_.each(extensionList, function(extension) {
|
2013-08-21 00:16:10 +00:00
|
|
|
// Set the extension.config attribute from settings or default
|
|
|
|
// configuration
|
2013-07-30 08:46:36 +00:00
|
|
|
extension.config = _.extend({}, extension.defaultConfig, extensionSettings[extension.extensionId]);
|
2013-07-31 12:49:05 +00:00
|
|
|
if(viewerMode === true && extension.disableInViewer === true) {
|
2013-08-21 00:16:10 +00:00
|
|
|
// Skip enabling the extension if we are in the viewer and extension
|
|
|
|
// doesn't support it
|
2013-07-31 12:49:05 +00:00
|
|
|
extension.enabled = false;
|
|
|
|
}
|
|
|
|
else {
|
2013-08-21 00:16:10 +00:00
|
|
|
// Enable the extension if it's not optional or it has not been
|
|
|
|
// disabled by the user
|
|
|
|
extension.enabled = !extension.isOptional || extension.config.enabled === undefined || extension.config.enabled === true;
|
2013-07-30 08:46:36 +00:00
|
|
|
}
|
|
|
|
});
|
2013-08-21 00:16:10 +00:00
|
|
|
|
|
|
|
// Returns all listeners with the specified name that are implemented in the
|
|
|
|
// enabled extensions
|
2013-07-30 08:46:36 +00:00
|
|
|
function getExtensionListenerList(eventName) {
|
|
|
|
return _.chain(extensionList).map(function(extension) {
|
2013-07-31 12:49:05 +00:00
|
|
|
return extension.enabled && extension[eventName];
|
2013-07-30 08:46:36 +00:00
|
|
|
}).compact().value();
|
|
|
|
}
|
|
|
|
|
2013-08-21 00:16:10 +00:00
|
|
|
// Returns a function that calls every listeners with the specified name
|
|
|
|
// from all enabled extensions
|
2013-07-30 08:46:36 +00:00
|
|
|
var eventListenerListMap = {};
|
|
|
|
function createEventHook(eventName) {
|
|
|
|
eventListenerListMap[eventName] = getExtensionListenerList(eventName);
|
|
|
|
return function() {
|
|
|
|
logger.log(eventName, arguments);
|
|
|
|
var eventArguments = arguments;
|
|
|
|
_.each(eventListenerListMap[eventName], function(listener) {
|
|
|
|
// Use try/catch in case userCustom listener contains error
|
|
|
|
try {
|
|
|
|
listener.apply(null, eventArguments);
|
|
|
|
}
|
|
|
|
catch(e) {
|
2013-08-21 00:16:10 +00:00
|
|
|
console.error(_.isObject(e) ? e.stack : e);
|
2013-07-30 08:46:36 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
}
|
2013-08-21 00:16:10 +00:00
|
|
|
|
2013-07-30 08:46:36 +00:00
|
|
|
// Add a Hook to the eventMgr that we can fire using eventMgr.eventName()
|
|
|
|
function addEventHook(eventName) {
|
|
|
|
eventMgr[eventName] = createEventHook(eventName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Used by external modules (not extensions) to listen to events
|
|
|
|
eventMgr.addListener = function(eventName, listener) {
|
|
|
|
try {
|
|
|
|
eventListenerListMap[eventName].push(listener);
|
2013-08-21 00:16:10 +00:00
|
|
|
}
|
|
|
|
catch(e) {
|
2013-07-30 08:46:36 +00:00
|
|
|
console.error('No event listener called ' + eventName);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// Call every onInit listeners (extensions only)
|
|
|
|
createEventHook("onInit")();
|
|
|
|
|
|
|
|
// Load/Save extension config from/to settings
|
|
|
|
eventMgr["onLoadSettings"] = function() {
|
|
|
|
logger.log("onLoadSettings");
|
|
|
|
_.each(extensionList, function(extension) {
|
2013-08-04 17:47:32 +00:00
|
|
|
utils.setInputChecked("#input-enable-extension-" + extension.extensionId, extension.enabled === true);
|
2013-07-30 08:46:36 +00:00
|
|
|
var onLoadSettingsListener = extension.onLoadSettings;
|
|
|
|
onLoadSettingsListener && onLoadSettingsListener();
|
|
|
|
});
|
|
|
|
};
|
|
|
|
eventMgr["onSaveSettings"] = function(newExtensionSettings, event) {
|
|
|
|
logger.log("onSaveSettings");
|
|
|
|
_.each(extensionList, function(extension) {
|
|
|
|
var newExtensionConfig = _.extend({}, extension.defaultConfig);
|
|
|
|
newExtensionConfig.enabled = utils.getInputChecked("#input-enable-extension-" + extension.extensionId);
|
|
|
|
var onSaveSettingsListener = extension.onSaveSettings;
|
|
|
|
onSaveSettingsListener && onSaveSettingsListener(newExtensionConfig, event);
|
|
|
|
newExtensionSettings[extension.extensionId] = newExtensionConfig;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
addEventHook("onMessage");
|
|
|
|
addEventHook("onError");
|
|
|
|
addEventHook("onOfflineChanged");
|
2013-08-04 00:53:46 +00:00
|
|
|
addEventHook("onUserActive");
|
2013-07-30 08:46:36 +00:00
|
|
|
addEventHook("onAsyncRunning", true);
|
|
|
|
addEventHook("onPeriodicRun", true);
|
|
|
|
|
|
|
|
// To access modules that are loaded after extensions
|
|
|
|
addEventHook("onFileMgrCreated");
|
|
|
|
addEventHook("onSynchronizerCreated");
|
|
|
|
addEventHook("onPublisherCreated");
|
|
|
|
addEventHook("onEventMgrCreated");
|
|
|
|
|
|
|
|
// Operations on files
|
|
|
|
addEventHook("onFileCreated");
|
|
|
|
addEventHook("onFileDeleted");
|
|
|
|
addEventHook("onFileSelected");
|
|
|
|
addEventHook("onFileOpen");
|
|
|
|
addEventHook("onFileClosed");
|
|
|
|
addEventHook("onContentChanged");
|
|
|
|
addEventHook("onTitleChanged");
|
2013-08-21 00:16:10 +00:00
|
|
|
|
2013-08-12 00:10:26 +00:00
|
|
|
// Operations on folders
|
|
|
|
addEventHook("onFoldersChanged");
|
2013-07-30 08:46:36 +00:00
|
|
|
|
|
|
|
// Sync events
|
|
|
|
addEventHook("onSyncRunning");
|
|
|
|
addEventHook("onSyncSuccess");
|
|
|
|
addEventHook("onSyncImportSuccess");
|
|
|
|
addEventHook("onSyncExportSuccess");
|
|
|
|
addEventHook("onSyncRemoved");
|
|
|
|
|
|
|
|
// Publish events
|
|
|
|
addEventHook("onPublishRunning");
|
|
|
|
addEventHook("onPublishSuccess");
|
|
|
|
addEventHook("onNewPublishSuccess");
|
|
|
|
addEventHook("onPublishRemoved");
|
|
|
|
|
|
|
|
// Operations on Layout
|
|
|
|
addEventHook("onLayoutConfigure");
|
|
|
|
addEventHook("onLayoutCreated");
|
2013-09-09 00:08:55 +00:00
|
|
|
addEventHook("onLayoutResize");
|
2013-07-30 08:46:36 +00:00
|
|
|
|
|
|
|
// Operations on PageDown
|
2013-09-09 23:32:24 +00:00
|
|
|
addEventHook("onPagedownConfigure");
|
2013-07-30 08:46:36 +00:00
|
|
|
addEventHook("onSectionsCreated");
|
2013-09-09 23:32:24 +00:00
|
|
|
|
|
|
|
// Operation on ACE
|
|
|
|
addEventHook("onAceCreated");
|
2013-07-30 08:46:36 +00:00
|
|
|
|
|
|
|
var onPreviewFinished = createEventHook("onPreviewFinished");
|
|
|
|
var onAsyncPreviewListenerList = getExtensionListenerList("onAsyncPreview");
|
|
|
|
// The number of times we expect tryFinished to be called
|
|
|
|
var nbAsyncPreviewListener = onAsyncPreviewListenerList.length + 1;
|
|
|
|
var previewContentsElt = undefined;
|
2013-08-22 00:19:59 +00:00
|
|
|
var $previewContentsElt = undefined;
|
2013-07-30 08:46:36 +00:00
|
|
|
eventMgr["onAsyncPreview"] = function() {
|
|
|
|
logger.log("onAsyncPreview");
|
|
|
|
logger.log("Conversion time: " + (new Date() - eventMgr.previewStartTime));
|
|
|
|
// Call onPreviewFinished listeners when all async preview are finished
|
|
|
|
var counter = 0;
|
|
|
|
function tryFinished() {
|
|
|
|
if(++counter === nbAsyncPreviewListener) {
|
|
|
|
logger.log("Preview time: " + (new Date() - eventMgr.previewStartTime));
|
|
|
|
_.defer(function() {
|
|
|
|
var html = "";
|
|
|
|
_.each(previewContentsElt.children, function(elt) {
|
|
|
|
html += elt.innerHTML;
|
|
|
|
});
|
|
|
|
onPreviewFinished(utils.trim(html));
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// We assume images are loading in the preview
|
2013-08-22 00:19:59 +00:00
|
|
|
$previewContentsElt.waitForImages(tryFinished);
|
2013-07-30 08:46:36 +00:00
|
|
|
_.each(onAsyncPreviewListenerList, function(asyncPreviewListener) {
|
|
|
|
asyncPreviewListener(tryFinished);
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
var onReady = createEventHook("onReady");
|
|
|
|
eventMgr["onReady"] = function() {
|
|
|
|
previewContentsElt = document.getElementById('preview-contents');
|
2013-08-22 00:19:59 +00:00
|
|
|
$previewContentsElt = $(previewContentsElt);
|
2013-08-21 00:16:10 +00:00
|
|
|
|
2013-07-30 08:46:36 +00:00
|
|
|
if(viewerMode === false) {
|
|
|
|
// Create accordion in settings dialog
|
|
|
|
var accordionHtml = _.chain(extensionList).sortBy(function(extension) {
|
|
|
|
return extension.extensionName.toLowerCase();
|
|
|
|
}).reduce(function(html, extension) {
|
2013-08-04 17:42:22 +00:00
|
|
|
return html + (extension.settingsBlock ? _.template(settingsExtensionsAccordionHTML, {
|
2013-07-30 08:46:36 +00:00
|
|
|
extensionId: extension.extensionId,
|
|
|
|
extensionName: extension.extensionName,
|
|
|
|
isOptional: extension.isOptional,
|
|
|
|
settingsBlock: extension.settingsBlock
|
2013-08-21 00:16:10 +00:00
|
|
|
}) : "");
|
2013-07-30 08:46:36 +00:00
|
|
|
}, "").value();
|
2013-08-15 23:17:16 +00:00
|
|
|
document.querySelector('.accordion-extensions').innerHTML = accordionHtml;
|
2013-08-21 00:16:10 +00:00
|
|
|
|
2013-07-30 08:46:36 +00:00
|
|
|
// Create a button from an extension listener
|
|
|
|
function createBtn(listener) {
|
|
|
|
var buttonGrpElt = crel('div', {
|
|
|
|
class: 'btn-group'
|
|
|
|
});
|
|
|
|
var btnElt = listener();
|
|
|
|
if(_.isString(btnElt)) {
|
|
|
|
buttonGrpElt.innerHTML = btnElt;
|
|
|
|
}
|
|
|
|
else if(_.isElement(btnElt)) {
|
|
|
|
buttonGrpElt.appendChild(btnElt);
|
|
|
|
}
|
|
|
|
return buttonGrpElt;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create extension buttons
|
|
|
|
logger.log("onCreateButton");
|
|
|
|
var onCreateButtonListenerList = getExtensionListenerList("onCreateButton");
|
|
|
|
var extensionButtonsFragment = document.createDocumentFragment();
|
|
|
|
_.each(onCreateButtonListenerList, function(listener) {
|
|
|
|
extensionButtonsFragment.appendChild(createBtn(listener));
|
|
|
|
});
|
|
|
|
document.getElementById('extension-buttons').appendChild(extensionButtonsFragment);
|
|
|
|
|
|
|
|
// Create extension preview buttons
|
|
|
|
logger.log("onCreatePreviewButton");
|
|
|
|
var onCreatePreviewButtonListenerList = getExtensionListenerList("onCreatePreviewButton");
|
|
|
|
var extensionPreviewButtonsFragment = document.createDocumentFragment();
|
|
|
|
_.each(onCreatePreviewButtonListenerList, function(listener) {
|
2013-08-08 23:32:03 +00:00
|
|
|
extensionPreviewButtonsFragment.appendChild(createBtn(listener));
|
2013-07-30 08:46:36 +00:00
|
|
|
});
|
2013-08-08 23:32:03 +00:00
|
|
|
var previewButtonsElt = document.querySelector('.extension-preview-buttons');
|
|
|
|
previewButtonsElt.appendChild(extensionPreviewButtonsFragment);
|
2013-08-21 00:16:10 +00:00
|
|
|
|
2013-08-08 23:32:03 +00:00
|
|
|
// A bit of jQuery...
|
2013-08-22 00:19:59 +00:00
|
|
|
var $previewButtonsElt = $(previewButtonsElt);
|
|
|
|
var previewButtonsWidth = $previewButtonsElt.width();
|
|
|
|
$previewButtonsElt.find('.btn-group').each(function() {
|
|
|
|
var $btnGroupElt = $(this);
|
2013-08-08 23:32:03 +00:00
|
|
|
// Align dropdown to the left of the screen
|
2013-08-22 00:19:59 +00:00
|
|
|
$btnGroupElt.find('.dropdown-menu').css({
|
|
|
|
right: -previewButtonsWidth + $btnGroupElt.width() + $btnGroupElt.position().left
|
2013-08-08 23:32:03 +00:00
|
|
|
});
|
|
|
|
});
|
2013-09-11 23:26:47 +00:00
|
|
|
|
|
|
|
// Create extension editor buttons
|
|
|
|
logger.log("onCreateEditorButton");
|
|
|
|
var onCreateEditorButtonListenerList = getExtensionListenerList("onCreateEditorButton");
|
|
|
|
var extensionEditorButtonsFragment = document.createDocumentFragment();
|
|
|
|
_.each(onCreateEditorButtonListenerList, function(listener) {
|
|
|
|
extensionEditorButtonsFragment.appendChild(createBtn(listener));
|
|
|
|
});
|
|
|
|
var editorButtonsElt = document.querySelector('.extension-editor-buttons');
|
|
|
|
editorButtonsElt.appendChild(extensionEditorButtonsFragment);
|
2013-07-30 08:46:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Call onReady listeners
|
|
|
|
onReady();
|
|
|
|
};
|
|
|
|
|
|
|
|
// For extensions that need to call other extensions
|
|
|
|
eventMgr.onEventMgrCreated(eventMgr);
|
|
|
|
return eventMgr;
|
|
|
|
});
|