Stackedit/js/core.js

711 lines
28 KiB
JavaScript
Raw Normal View History

2013-05-26 22:59:03 +00:00
define([
"jquery",
2013-05-29 19:55:23 +00:00
"underscore",
2013-08-08 23:32:03 +00:00
"crel",
2013-05-26 22:59:03 +00:00
"utils",
2013-05-27 19:45:33 +00:00
"settings",
2013-07-30 08:46:36 +00:00
"eventMgr",
2013-06-10 21:22:32 +00:00
"mousetrap",
2013-08-04 15:49:14 +00:00
"text!html/bodyIndex.html",
"text!html/bodyViewer.html",
2013-06-10 21:22:32 +00:00
"text!html/settingsTemplateTooltip.html",
2013-07-07 20:07:11 +00:00
"text!html/settingsUserCustomExtensionTooltip.html",
2013-05-26 22:59:03 +00:00
"storage",
"config",
2013-06-02 00:38:23 +00:00
"libs/layout",
"libs/Markdown.Editor"
2013-08-08 23:32:03 +00:00
], function($, _, crel, utils, settings, eventMgr, mousetrap, bodyIndexHTML, bodyViewerHTML, settingsTemplateTooltipHTML, settingsUserCustomExtensionTooltipHTML) {
2013-04-02 18:42:47 +00:00
2013-05-29 19:55:23 +00:00
var core = {};
// Used for periodic tasks
var intervalId = undefined;
// Used to detect user activity
2013-08-04 00:53:46 +00:00
var isUserReal = false;
2013-05-29 19:55:23 +00:00
var userActive = false;
var windowUnique = true;
var userLastActivity = 0;
function setUserActive() {
2013-08-04 00:53:46 +00:00
isUserReal = true;
2013-05-29 19:55:23 +00:00
userActive = true;
2013-08-04 00:53:46 +00:00
var currentTime = utils.currentTime;
if(currentTime > userLastActivity + 1000) {
userLastActivity = currentTime;
eventMgr.onUserActive();
}
2013-05-29 19:55:23 +00:00
}
function isUserActive() {
if(userActive === true && utils.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
userActive = false;
}
return userActive && windowUnique;
}
// Used to only have 1 window of the application in the same browser
var windowId = undefined;
function checkWindowUnique() {
2013-08-04 00:53:46 +00:00
if(isUserReal === false || windowUnique === false) {
2013-05-29 19:55:23 +00:00
return;
}
if(windowId === undefined) {
windowId = utils.randomString();
localStorage["frontWindowId"] = windowId;
}
var frontWindowId = localStorage["frontWindowId"];
if(frontWindowId != windowId) {
windowUnique = false;
if(intervalId !== undefined) {
clearInterval(intervalId);
}
$(".modal").modal("hide");
2013-08-11 00:52:05 +00:00
$('.modal-non-unique').modal({
2013-05-29 19:55:23 +00:00
backdrop: "static",
keyboard: false
});
}
}
// Offline management
2013-08-04 00:53:46 +00:00
var isOffline = false;
2013-05-29 19:55:23 +00:00
var offlineTime = utils.currentTime;
core.setOffline = function() {
offlineTime = utils.currentTime;
2013-08-04 00:53:46 +00:00
if(isOffline === false) {
isOffline = true;
2013-07-30 08:46:36 +00:00
eventMgr.onOfflineChanged(true);
2013-05-29 19:55:23 +00:00
}
};
function setOnline() {
2013-08-04 00:53:46 +00:00
if(isOffline === true) {
isOffline = false;
2013-07-30 08:46:36 +00:00
eventMgr.onOfflineChanged(false);
2013-05-29 19:55:23 +00:00
}
}
function checkOnline() {
// Try to reconnect if we are offline but we have some network
2013-08-04 00:53:46 +00:00
if(isOffline === true && navigator.onLine === true && offlineTime + CHECK_ONLINE_PERIOD < utils.currentTime) {
2013-05-29 19:55:23 +00:00
offlineTime = utils.currentTime;
// Try to download anything to test the connection
$.ajax({
url: "//www.google.com/jsapi",
timeout: AJAX_TIMEOUT,
dataType: "script"
}).done(function() {
setOnline();
});
}
}
// Load settings in settings dialog
function loadSettings() {
// Layout orientation
utils.setInputRadio("radio-layout-orientation", settings.layoutOrientation);
// Theme
utils.setInputValue("#input-settings-theme", localStorage.theme);
// Lazy rendering
utils.setInputChecked("#input-settings-lazy-rendering", settings.lazyRendering);
2013-06-27 23:10:04 +00:00
// Editor font family
utils.setInputValue("#input-settings-editor-font-family", settings.editorFontFamily);
2013-05-29 19:55:23 +00:00
// Editor font size
utils.setInputValue("#input-settings-editor-font-size", settings.editorFontSize);
// Default content
utils.setInputValue("#textarea-settings-default-content", settings.defaultContent);
// Commit message
utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg);
// Template
utils.setInputValue("#textarea-settings-publish-template", settings.template);
// SSH proxy
utils.setInputValue("#input-settings-ssh-proxy", settings.sshProxy);
// Load extension settings
2013-07-30 08:46:36 +00:00
eventMgr.onLoadSettings();
2013-05-29 19:55:23 +00:00
}
// Save settings from settings dialog
function saveSettings(event) {
var newSettings = {};
// Layout orientation
newSettings.layoutOrientation = utils.getInputRadio("radio-layout-orientation");
// Theme
var theme = utils.getInputValue("#input-settings-theme");
// Lazy Rendering
newSettings.lazyRendering = utils.getInputChecked("#input-settings-lazy-rendering");
2013-06-27 23:10:04 +00:00
// Editor font family
newSettings.editorFontFamily = utils.getInputTextValue("#input-settings-editor-font-family", event);
2013-05-29 19:55:23 +00:00
// Editor font size
newSettings.editorFontSize = utils.getInputIntValue("#input-settings-editor-font-size", event, 1, 99);
// Default content
newSettings.defaultContent = utils.getInputValue("#textarea-settings-default-content");
// Commit message
newSettings.commitMsg = utils.getInputTextValue("#input-settings-publish-commit-msg", event);
// Template
newSettings.template = utils.getInputTextValue("#textarea-settings-publish-template", event);
// SSH proxy
newSettings.sshProxy = utils.checkUrl(utils.getInputTextValue("#input-settings-ssh-proxy", event), true);
// Save extension settings
newSettings.extensionSettings = {};
2013-07-30 08:46:36 +00:00
eventMgr.onSaveSettings(newSettings.extensionSettings, event);
2013-05-29 19:55:23 +00:00
if(!event.isPropagationStopped()) {
$.extend(settings, newSettings);
localStorage.settings = JSON.stringify(settings);
localStorage.theme = theme;
}
}
2013-08-10 11:34:30 +00:00
// Set the panels visibility
2013-08-10 00:28:48 +00:00
var layout = undefined;
2013-08-10 11:34:30 +00:00
var menuPanelElt = undefined;
var documentPanelElt = undefined;
function setPanelVisibility(forceHide) {
if(forceHide === true || layout.state.north.isClosed) {
menuPanelElt.hide();
documentPanelElt.hide();
}
else {
menuPanelElt.show();
documentPanelElt.show();
}
}
// Set the preview button visibility
2013-08-08 23:32:03 +00:00
var previewButtonsElt = undefined;
function setPreviewButtonsVisibility(forceHide) {
if(forceHide === true || layout.state.east.isClosed) {
previewButtonsElt.hide();
}
else {
previewButtonsElt.show();
}
}
2013-08-08 21:53:15 +00:00
2013-08-06 23:52:58 +00:00
// Create the layout
2013-06-19 20:33:46 +00:00
function createLayout() {
2013-05-29 19:55:23 +00:00
if(viewerMode === true) {
return;
}
var layoutGlobalConfig = {
2013-08-10 11:34:30 +00:00
closable: true,
2013-05-29 19:55:23 +00:00
resizable: false,
slidable: false,
livePaneResizing: true,
enableCursorHotkey: false,
2013-08-10 00:28:48 +00:00
north__spacing_open: 6,
2013-08-10 11:34:30 +00:00
north__spacing_closed: 6,
2013-08-10 00:28:48 +00:00
spacing_open: 35,
spacing_closed: 35,
togglerLength_open: 60,
togglerLength_closed: 60,
2013-05-29 19:55:23 +00:00
stateManagement__enabled: false,
center__minWidth: 200,
2013-08-10 11:34:30 +00:00
center__minHeight: 200,
2013-08-06 23:52:58 +00:00
onopen: function() {
2013-08-10 11:34:30 +00:00
setPanelVisibility();
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility();
2013-08-06 23:52:58 +00:00
},
onclose_start: function(paneName) {
2013-08-10 11:34:30 +00:00
if(paneName == 'north') {
setPanelVisibility(true);
}
else if(paneName == 'east') {
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility(true);
}
2013-08-06 23:52:58 +00:00
},
2013-05-29 19:55:23 +00:00
};
2013-07-30 08:46:36 +00:00
eventMgr.onLayoutConfigure(layoutGlobalConfig);
2013-05-29 19:55:23 +00:00
if(settings.layoutOrientation == "horizontal") {
$(".ui-layout-south").remove();
2013-08-08 23:32:03 +00:00
$(".preview-container").html('<div id="preview-contents"><div id="wmd-preview" class="preview-content"></div></div>');
2013-05-29 19:55:23 +00:00
layout = $('body').layout($.extend(layoutGlobalConfig, {
east__resizable: true,
east__size: .5,
2013-08-08 23:32:03 +00:00
east__minSize: 250
2013-05-29 19:55:23 +00:00
}));
}
else if(settings.layoutOrientation == "vertical") {
$(".ui-layout-east").remove();
2013-08-08 23:32:03 +00:00
$(".preview-container").html('<div id="preview-contents"><div id="wmd-preview" class="preview-content"></div></div>');
2013-05-29 19:55:23 +00:00
layout = $('body').layout($.extend(layoutGlobalConfig, {
south__resizable: true,
south__size: .5,
south__minSize: 200
}));
}
2013-07-20 01:08:17 +00:00
$(".navbar").click(function() {
2013-05-29 19:55:23 +00:00
layout.allowOverflow('north');
});
2013-08-10 00:28:48 +00:00
$(".ui-layout-toggler-south").addClass("btn btn-info").html('<i class="icon-none"></i>');
$(".ui-layout-toggler-east").addClass("btn btn-info").html('<i class="icon-none"></i>');
2013-08-10 11:34:30 +00:00
var northTogglerElt = $(".ui-layout-toggler-north").addClass("btn btn-info").html('<i class="icon-none"></i>');
2013-08-08 23:32:03 +00:00
// We attach the preview buttons to the UI layout resizer in order to have fixed position
2013-08-10 11:34:30 +00:00
// We also move the north toggler to the east or south resizer as the north resizer is very small
2013-08-08 23:32:03 +00:00
previewButtonsElt = $('<div class="extension-preview-buttons">');
if(settings.layoutOrientation == "horizontal") {
$('.ui-layout-resizer-north').append(previewButtonsElt);
2013-08-10 11:34:30 +00:00
$('.ui-layout-resizer-east').append(northTogglerElt);
2013-08-08 23:32:03 +00:00
}
else {
2013-08-10 11:34:30 +00:00
$('.ui-layout-resizer-south').append(previewButtonsElt).append(northTogglerElt);
2013-08-08 23:32:03 +00:00
}
2013-08-10 11:34:30 +00:00
setPanelVisibility();
2013-08-08 23:32:03 +00:00
setPreviewButtonsVisibility();
2013-05-29 19:55:23 +00:00
2013-07-30 08:46:36 +00:00
eventMgr.onLayoutCreated(layout);
2013-07-03 22:29:53 +00:00
}
2013-05-29 19:55:23 +00:00
// Create the PageDown editor
2013-06-02 00:38:23 +00:00
var editor = undefined;
2013-06-03 22:19:52 +00:00
var fileDesc = undefined;
2013-06-02 00:38:23 +00:00
var documentContent = undefined;
2013-06-19 20:33:46 +00:00
core.initEditor = function(fileDescParam) {
if(fileDesc !== undefined) {
2013-07-30 08:46:36 +00:00
eventMgr.onFileClosed(fileDesc);
}
2013-06-03 22:19:52 +00:00
fileDesc = fileDescParam;
2013-06-02 00:38:23 +00:00
documentContent = undefined;
2013-06-03 22:19:52 +00:00
var initDocumentContent = fileDesc.content;
2013-06-05 22:29:32 +00:00
var editorElt = $("#wmd-input");
editorElt.val(initDocumentContent);
2013-06-02 00:38:23 +00:00
if(editor !== undefined) {
2013-06-03 22:19:52 +00:00
// If the editor is already created
2013-07-20 01:08:17 +00:00
editor.undoManager.reinit(initDocumentContent, fileDesc.editorStart, fileDesc.editorEnd, fileDesc.editorScrollTop);
2013-07-30 08:46:36 +00:00
eventMgr.onFileOpen(fileDesc);
2013-07-28 10:35:04 +00:00
editor.refreshPreview();
2013-06-02 00:38:23 +00:00
return;
}
2013-06-05 22:29:32 +00:00
var previewContainerElt = $(".preview-container");
2013-06-10 21:22:32 +00:00
2013-06-05 22:29:32 +00:00
// Store editor scrollTop on scroll event
editorElt.scroll(function() {
2013-06-03 22:19:52 +00:00
if(documentContent !== undefined) {
fileDesc.editorScrollTop = $(this).scrollTop();
}
});
2013-06-05 22:29:32 +00:00
// Store editor selection on change
editorElt.bind("keyup mouseup", function() {
if(documentContent !== undefined) {
fileDesc.editorStart = this.selectionStart;
fileDesc.editorEnd = this.selectionEnd;
}
});
// Store preview scrollTop on scroll event
previewContainerElt.scroll(function() {
2013-06-03 22:19:52 +00:00
if(documentContent !== undefined) {
fileDesc.previewScrollTop = $(this).scrollTop();
}
});
2013-06-10 21:22:32 +00:00
// Create the converter and the editor
2013-05-29 19:55:23 +00:00
var converter = new Markdown.Converter();
2013-07-26 00:44:12 +00:00
// Create MD sections for extensions
converter.hooks.chain("preConversion", function(text) {
2013-08-04 00:53:46 +00:00
eventMgr.previewStartTime = new Date();
2013-07-26 00:44:12 +00:00
var tmpText = text + "\n\n";
var sectionList = [], offset = 0;
2013-07-28 10:35:04 +00:00
// Look for titles (excluding gfm blocs)
2013-07-26 00:44:12 +00:00
tmpText.replace(/^```.*\n[\s\S]*?\n```|(^.+[ \t]*\n=+[ \t]*\n+|^.+[ \t]*\n-+[ \t]*\n+|^\#{1,6}[ \t]*.+?[ \t]*\#*\n+)/gm, function(match, title, matchOffset) {
2013-07-28 10:35:04 +00:00
if(title) {
2013-08-04 00:53:46 +00:00
// We just found a title which means end of the previous
// section
2013-07-26 00:44:12 +00:00
// Exclude last \n of the section
2013-07-28 10:35:04 +00:00
sectionList.push(tmpText.substring(offset, matchOffset));
2013-07-26 00:44:12 +00:00
offset = matchOffset;
}
return "";
});
// Last section
sectionList.push(tmpText.substring(offset, text.length));
2013-07-30 08:46:36 +00:00
eventMgr.onSectionsCreated(sectionList);
2013-07-26 00:44:12 +00:00
return text;
});
2013-06-02 00:38:23 +00:00
editor = new Markdown.Editor(converter);
2013-05-29 19:55:23 +00:00
// Custom insert link dialog
editor.hooks.set("insertLinkDialog", function(callback) {
2013-06-02 00:38:23 +00:00
core.insertLinkCallback = callback;
2013-05-29 19:55:23 +00:00
utils.resetModalInputs();
2013-08-11 00:52:05 +00:00
$(".modal-insert-link").modal();
2013-05-29 19:55:23 +00:00
return true;
});
// Custom insert image dialog
editor.hooks.set("insertImageDialog", function(callback) {
2013-06-02 00:38:23 +00:00
core.insertLinkCallback = callback;
2013-07-16 23:54:56 +00:00
if(core.catchModal) {
return true;
}
2013-05-29 19:55:23 +00:00
utils.resetModalInputs();
2013-08-11 00:52:05 +00:00
$(".modal-insert-image").modal();
2013-05-29 19:55:23 +00:00
return true;
});
function checkDocumentChanges() {
2013-06-05 22:29:32 +00:00
var newDocumentContent = editorElt.val();
2013-05-29 19:55:23 +00:00
if(documentContent !== undefined && documentContent != newDocumentContent) {
2013-06-03 22:19:52 +00:00
fileDesc.content = newDocumentContent;
2013-07-30 08:46:36 +00:00
eventMgr.onContentChanged(fileDesc);
2013-05-29 19:55:23 +00:00
}
documentContent = newDocumentContent;
}
2013-06-02 00:38:23 +00:00
var previewWrapper;
2013-05-29 19:55:23 +00:00
if(settings.lazyRendering === true) {
previewWrapper = function(makePreview) {
var debouncedMakePreview = _.debounce(makePreview, 500);
return function() {
if(documentContent === undefined) {
makePreview();
2013-06-05 22:29:32 +00:00
editorElt.scrollTop(fileDesc.editorScrollTop);
previewContainerElt.scrollTop(fileDesc.previewScrollTop);
2013-05-29 19:55:23 +00:00
}
else {
debouncedMakePreview();
}
checkDocumentChanges();
};
};
}
else {
previewWrapper = function(makePreview) {
return function() {
makePreview();
2013-06-03 22:19:52 +00:00
if(documentContent === undefined) {
2013-06-05 22:29:32 +00:00
previewContainerElt.scrollTop(fileDesc.previewScrollTop);
2013-06-03 22:19:52 +00:00
}
checkDocumentChanges();
2013-05-29 19:55:23 +00:00
};
};
}
2013-07-30 08:46:36 +00:00
eventMgr.onEditorConfigure(editor);
editor.hooks.chain("onPreviewRefresh", eventMgr.onAsyncPreview);
2013-07-20 01:08:17 +00:00
editor.run(previewWrapper);
editor.undoManager.reinit(initDocumentContent, fileDesc.editorStart, fileDesc.editorEnd, fileDesc.editorScrollTop);
2013-05-29 19:55:23 +00:00
// Hide default buttons
2013-08-10 01:19:32 +00:00
$(".wmd-button-row li").addClass("btn btn-success").css("left", 0).find("span").hide();
2013-05-29 19:55:23 +00:00
// Add customized buttons
2013-08-10 01:19:32 +00:00
var btnGroupElt = $('.wmd-button-group1');
$("#wmd-bold-button").append($('<i class="icon-bold">')).appendTo(btnGroupElt);
$("#wmd-italic-button").append($('<i class="icon-italic">')).appendTo(btnGroupElt);
var btnGroupElt = $('.wmd-button-group2');
$("#wmd-link-button").append($('<i class="icon-globe">')).appendTo(btnGroupElt);
$("#wmd-quote-button").append($('<i class="icon-indent-right">')).appendTo(btnGroupElt);
$("#wmd-code-button").append($('<i class="icon-code">')).appendTo(btnGroupElt);
$("#wmd-image-button").append($('<i class="icon-picture">')).appendTo(btnGroupElt);
var btnGroupElt = $('.wmd-button-group3');
$("#wmd-olist-button").append($('<i class="icon-list-numbered">')).appendTo(btnGroupElt);
$("#wmd-ulist-button").append($('<i class="icon-list-bullet">')).appendTo(btnGroupElt);
$("#wmd-heading-button").append($('<i class="icon-text-height">')).appendTo(btnGroupElt);
$("#wmd-hr-button").append($('<i class="icon-ellipsis">')).appendTo(btnGroupElt);
var btnGroupElt = $('.wmd-button-group4');
$("#wmd-undo-button").append($('<i class="icon-reply">')).appendTo(btnGroupElt);
$("#wmd-redo-button").append($('<i class="icon-forward">')).appendTo(btnGroupElt);
2013-08-04 00:53:46 +00:00
2013-07-30 08:46:36 +00:00
eventMgr.onFileOpen(fileDesc);
2013-05-29 19:55:23 +00:00
};
2013-08-04 00:53:46 +00:00
// Used to lock the editor from the user interaction during asynchronous
// tasks
2013-07-18 23:30:28 +00:00
var uiLocked = false;
core.lockUI = function(param) {
uiLocked = param;
$("#wmd-input").prop("disabled", uiLocked);
2013-07-20 01:08:17 +00:00
$(".navbar-inner .btn").toggleClass("blocked", uiLocked);
2013-07-18 23:30:28 +00:00
if(uiLocked) {
$(".lock-ui").removeClass("hide");
}
else {
$(".lock-ui").addClass("hide");
}
};
2013-08-04 15:49:14 +00:00
// Initialize multiple things and then fire eventMgr.onReady
core.onReady = function() {
if(viewerMode === true) {
$('body').html(bodyViewerHTML);
}
else {
$('body').html(bodyIndexHTML);
}
2013-05-29 19:55:23 +00:00
// listen to online/offline events
$(window).on('offline', core.setOffline);
$(window).on('online', setOnline);
if(navigator.onLine === false) {
core.setOffline();
}
// Detect user activity
$(document).mousemove(setUserActive).keypress(setUserActive);
// Avoid dropdown to close when clicking on submenu
$(".dropdown-submenu > a").click(function(e) {
e.stopPropagation();
});
2013-08-08 21:53:15 +00:00
2013-08-06 23:52:58 +00:00
menuPanelElt = $('.menu-panel');
2013-08-06 00:28:21 +00:00
var isMenuPanelShown = false;
2013-08-12 22:08:22 +00:00
var menuPanelBackdropElt = undefined;
menuPanelElt.on('shown.bs.collapse', function(e) {
if(e.target === menuPanelElt[0]) {
isMenuPanelShown = true;
menuPanelBackdropElt = utils.createBackdrop();
menuPanelElt.addClass('move-to-front');
// Register a click listener when menu panel is open
var closePanelElt = menuPanelElt.find('.action-close-panel').add(menuPanelBackdropElt);
closePanelElt.on('click.hide-menu-panel', function(e) {
// Unregister the listener
2013-08-10 00:28:48 +00:00
$('body').off('click.hide-menu-panel');
2013-08-12 22:08:22 +00:00
menuPanelElt.collapse('hide');
2013-08-10 00:28:48 +00:00
isMenuPanelShown = false;
2013-08-12 22:08:22 +00:00
});
}
2013-08-11 00:52:05 +00:00
}).on('show.bs.collapse', function(){
// Close all open sub-menus when one submenu opens
menuPanelElt.find('.in').collapse('hide');
2013-08-12 22:08:22 +00:00
}).on('hidden.bs.collapse', function(e) {
2013-08-11 00:52:05 +00:00
// Close all open sub-menus when menu panel is closed
2013-08-12 22:08:22 +00:00
if(e.target === menuPanelElt[0]) {
menuPanelElt.find('.in').collapse('hide');
}
2013-08-06 00:28:21 +00:00
});
2013-08-08 21:53:15 +00:00
2013-08-06 23:52:58 +00:00
documentPanelElt = $('.document-panel');
2013-08-06 00:28:21 +00:00
var isDocumentPanelShown = false;
2013-08-12 22:08:22 +00:00
documentPanelElt.on('shown.bs.collapse', function(e) {
if(e.target === documentPanelElt[0]) {
isDocumentPanelShown = true;
// Register a click listener when document panel is open
$('body').on('click.hide-document-panel', function(e) {
// If click outside the panel, close the panel and unregister
// the listener
if($(e.target).is('.action-close-panel, .action-close-panel *, :not(.document-panel, .document-panel *)')) {
documentPanelElt.collapse('hide');
$('body').off('click.hide-document-panel');
isDocumentPanelShown = false;
}
});
}
2013-08-11 00:52:05 +00:00
}).on('show.bs.collapse', function(){
// Close all open sub-menus when one submenu opens
documentPanelElt.find('.in').collapse('hide');
2013-08-12 22:08:22 +00:00
}).on('hidden.bs.collapse', function(e) {
if(e.target === documentPanelElt[0]) {
// Close all open sub-menus when menu panel is closed
documentPanelElt.find('.in').collapse('hide');
}
2013-08-06 00:28:21 +00:00
});
2013-08-08 21:53:15 +00:00
2013-08-06 00:28:21 +00:00
var isModalShown = false;
$('.modal').on('shown.bs.modal', function() {
2013-06-02 00:38:23 +00:00
// Focus on the first input when modal opens
2013-08-06 00:28:21 +00:00
isModalShown = true;
_.defer(function(elt) {
elt.find("input:enabled:visible:first").focus();
}, $(this));
}).on('hidden.bs.modal', function() {
2013-06-02 00:38:23 +00:00
// Focus on the editor when modal is gone
2013-08-06 00:28:21 +00:00
isModalShown = false;
$("#wmd-input").focus();
2013-06-02 00:38:23 +00:00
}).keyup(function(e) {
// Handle enter key in modals
if(e.which == 13 && !$(e.target).is("textarea")) {
$(this).find(".modal-footer a:last").click();
}
});
2013-06-10 21:22:32 +00:00
// Configure Mousetrap
mousetrap.stopCallback = function(e, element, combo) {
2013-08-06 00:28:21 +00:00
return uiLocked || isMenuPanelShown || isDocumentPanelShown || isModalShown || $(element).is("input, select, textarea:not(#wmd-input)");
2013-06-10 21:22:32 +00:00
};
2013-08-04 00:53:46 +00:00
// UI layout
createLayout();
// Editor's textarea
$("#wmd-input, #md-section-helper").css({
// Apply editor font
"font-family": settings.editorFontFamily,
"font-size": settings.editorFontSize + "px",
"line-height": Math.round(settings.editorFontSize * (20 / 14)) + "px"
});
// Handle tab key
$("#wmd-input").keydown(function(e) {
if(e.keyCode === 9) {
var value = $(this).val();
var start = this.selectionStart;
var end = this.selectionEnd;
// IE8 does not support selection attributes
if(start === undefined || end === undefined) {
return;
}
$(this).val(value.substring(0, start) + "\t" + value.substring(end));
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
}
});
// Do periodic tasks
intervalId = window.setInterval(function() {
utils.updateCurrentTime();
checkWindowUnique();
if(isUserActive() === true || viewerMode === true) {
eventMgr.onPeriodicRun();
checkOnline();
}
}, 1000);
eventMgr.onReady();
};
// Other initialization that are not prioritary
eventMgr.addListener("onReady", function() {
// Load theme list
var themeOptions = _.reduce(THEME_LIST, function(themeOptions, name, value) {
return themeOptions + '<option value="' + value + '">' + name + '</option>';
}, "");
$("#input-settings-theme").html(themeOptions);
2013-05-29 19:55:23 +00:00
// Click events on "insert link" and "insert image" dialog buttons
$(".action-insert-link").click(function(e) {
var value = utils.getInputTextValue($("#input-insert-link"), e);
if(value !== undefined) {
2013-06-02 00:38:23 +00:00
core.insertLinkCallback(value);
2013-06-02 19:35:44 +00:00
core.insertLinkCallback = undefined;
2013-05-29 19:55:23 +00:00
}
});
$(".action-insert-image").click(function(e) {
var value = utils.getInputTextValue($("#input-insert-image"), e);
if(value !== undefined) {
2013-06-02 00:38:23 +00:00
core.insertLinkCallback(value);
2013-06-02 19:35:44 +00:00
core.insertLinkCallback = undefined;
2013-05-29 19:55:23 +00:00
}
});
2013-06-10 21:22:32 +00:00
2013-06-02 00:38:23 +00:00
// Hide events on "insert link" and "insert image" dialogs
2013-08-11 00:52:05 +00:00
$(".modal-insert-link, .modal-insert-image").on('hidden.bs.modal', function() {
2013-06-02 00:38:23 +00:00
if(core.insertLinkCallback !== undefined) {
core.insertLinkCallback(null);
2013-06-02 19:35:44 +00:00
core.insertLinkCallback = undefined;
2013-06-02 00:38:23 +00:00
}
2013-05-29 19:55:23 +00:00
});
// Settings loading/saving
$(".action-load-settings").click(function() {
loadSettings();
});
$(".action-apply-settings").click(function(e) {
saveSettings(e);
if(!e.isPropagationStopped()) {
window.location.reload();
}
});
2013-07-03 22:29:53 +00:00
// Import settings
$(".action-import-settings").click(function(e) {
$("#input-file-import-settings").click();
});
$("#input-file-import-settings").change(function(evt) {
var files = (evt.dataTransfer || evt.target).files;
2013-08-11 00:52:05 +00:00
$(".modal-settings").modal("hide");
2013-07-03 22:29:53 +00:00
_.each(files, function(file) {
var reader = new FileReader();
reader.onload = (function(importedFile) {
return function(e) {
var content = e.target.result;
try {
JSON.parse(content);
}
catch(e) {
2013-07-30 08:46:36 +00:00
eventMgr.onError(importedFile.name + " is not a valid JSON file.");
2013-07-03 22:29:53 +00:00
return;
}
localStorage.settings = content;
window.location.reload();
};
})(file);
var blob = file.slice(0, IMPORT_FILE_MAX_CONTENT_SIZE);
reader.readAsText(blob);
});
});
// Export settings
$(".action-export-settings").click(function(e) {
utils.saveAs(JSON.stringify(settings), "StackEdit Settings.json");
});
2013-05-29 19:55:23 +00:00
$(".action-default-settings").click(function() {
localStorage.removeItem("settings");
localStorage.removeItem("theme");
window.location.reload();
});
$(".action-app-reset").click(function() {
localStorage.clear();
window.location.reload();
});
2013-06-22 23:48:57 +00:00
// Reset inputs
$(".action-reset-input").click(function() {
utils.resetModalInputs();
});
2013-05-29 19:55:23 +00:00
// Tooltips
$(".tooltip-lazy-rendering").tooltip({
2013-08-11 00:52:05 +00:00
container: '.modal-settings',
2013-05-29 19:55:23 +00:00
placement: 'right',
2013-06-02 00:38:23 +00:00
trigger: 'hover',
2013-05-29 19:55:23 +00:00
title: 'Disable preview rendering while typing in order to offload CPU. Refresh preview after 500 ms of inactivity.'
});
$(".tooltip-default-content").tooltip({
html: true,
2013-08-11 00:52:05 +00:00
container: '.modal-settings',
2013-05-29 19:55:23 +00:00
placement: 'right',
2013-06-02 00:38:23 +00:00
trigger: 'hover',
2013-05-29 19:55:23 +00:00
title: 'Thanks for supporting StackEdit by adding a backlink in your documents!'
});
2013-07-07 20:07:11 +00:00
$(".tooltip-usercustom-extension").tooltip({
html: true,
2013-08-11 00:52:05 +00:00
container: '.modal-settings',
2013-07-07 20:07:11 +00:00
placement: 'right',
trigger: 'manual',
title: settingsUserCustomExtensionTooltipHTML
}).click(function(e) {
$(this).tooltip('show');
$(document).on("click.tooltip-usercustom-extension", function(e) {
$(".tooltip-usercustom-extension").tooltip('hide');
$(document).off("click.tooltip-usercustom-extension");
});
e.stopPropagation();
});
2013-05-29 19:55:23 +00:00
$(".tooltip-template").tooltip({
html: true,
2013-08-11 00:52:05 +00:00
container: '.modal-settings',
2013-05-29 19:55:23 +00:00
placement: 'right',
trigger: 'manual',
2013-06-10 21:22:32 +00:00
title: settingsTemplateTooltipHTML
2013-05-29 19:55:23 +00:00
}).click(function(e) {
$(this).tooltip('show');
2013-06-02 00:38:23 +00:00
$(document).on("click.tooltip-template", function(e) {
$(".tooltip-template").tooltip('hide');
$(document).off("click.tooltip-template");
});
2013-05-29 19:55:23 +00:00
e.stopPropagation();
});
2013-08-04 00:53:46 +00:00
// Avoid dropdown panels to close on click
$("div.dropdown-menu").click(function(e) {
e.stopPropagation();
});
2013-05-29 19:55:23 +00:00
});
return core;
});