New extension pattern
This commit is contained in:
parent
56fa0c5873
commit
d636e80646
@ -6,7 +6,7 @@ index.html
|
|||||||
viewer.html
|
viewer.html
|
||||||
css/main-min.css
|
css/main-min.css
|
||||||
js/main-min.js
|
js/main-min.js
|
||||||
js/require.js
|
js/lib/require.js
|
||||||
img/ajax-loader.gif
|
img/ajax-loader.gif
|
||||||
img/glyphicons-halflings.png
|
img/glyphicons-halflings.png
|
||||||
img/glyphicons-halflings-white.png
|
img/glyphicons-halflings-white.png
|
||||||
|
47
css/main-min.css
vendored
47
css/main-min.css
vendored
@ -5513,6 +5513,12 @@ code {
|
|||||||
h1 {
|
h1 {
|
||||||
margin: 30px 0 30px;
|
margin: 30px 0 30px;
|
||||||
}
|
}
|
||||||
|
h4, h5, h6 {
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
.toc ul {
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
p, pre, blockquote {
|
p, pre, blockquote {
|
||||||
margin: 0 0 20px;
|
margin: 0 0 20px;
|
||||||
}
|
}
|
||||||
@ -5727,9 +5733,48 @@ div.dropdown-menu i {
|
|||||||
height: 80px;
|
height: 80px;
|
||||||
max-width: 206px;
|
max-width: 206px;
|
||||||
}
|
}
|
||||||
.tooltip-inner {
|
#modal-settings .accordion-group {
|
||||||
|
border: 0;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
-webkit-border-radius: inherit;
|
||||||
|
-moz-border-radius: inherit;
|
||||||
|
border-radius: inherit;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
#modal-settings .accordion-heading .checkbox {
|
||||||
|
padding: 8px 15px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
#modal-settings .accordion-inner {
|
||||||
|
border: 0;
|
||||||
|
padding: 10px 40px;
|
||||||
|
}
|
||||||
|
#modal-settings .accordion-inner .form-horizontal .control-group {
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
#modal-settings .accordion-inner .form-horizontal .control-label {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
.accordion-toggle {
|
||||||
|
cursor: help;
|
||||||
|
}
|
||||||
|
.nav-tabs > .active > a, .nav-tabs > .active > a:hover, .nav-tabs > .active > a:focus {
|
||||||
|
color: #fff;
|
||||||
|
background-color: #777;
|
||||||
|
border-color: #777;
|
||||||
|
border-bottom-color: transparent;
|
||||||
|
}
|
||||||
|
.nav-tabs {
|
||||||
|
border-bottom-color: #eee;
|
||||||
|
}
|
||||||
|
.nav > li > a:hover,
|
||||||
|
.nav > li > a:focus {
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
.nav-tabs > li > a:hover,
|
||||||
|
.nav-tabs > li > a:focus {
|
||||||
|
border-color: #eee;
|
||||||
|
}
|
||||||
table {
|
table {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
@ -19,13 +19,12 @@
|
|||||||
document.write('<link href="css/main' + suffix + '.css" rel="stylesheet">');
|
document.write('<link href="css/main' + suffix + '.css" rel="stylesheet">');
|
||||||
var theme = localStorage.theme;
|
var theme = localStorage.theme;
|
||||||
if (theme) {
|
if (theme) {
|
||||||
document
|
document.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">');
|
||||||
.write('<link href="themes/' + theme + '/' + theme + '.css" rel="stylesheet">');
|
|
||||||
}
|
}
|
||||||
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
|
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
|
||||||
var viewerMode = false;
|
var viewerMode = false;
|
||||||
</script>
|
</script>
|
||||||
<script src="js/require.js"></script>
|
<script src="js/lib/require.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">
|
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">
|
||||||
|
@ -2,7 +2,12 @@
|
|||||||
* Used to run asynchronous tasks sequentially (ajax mainly). An asynchronous
|
* Used to run asynchronous tasks sequentially (ajax mainly). An asynchronous
|
||||||
* task is composed of different callback types: onRun, onSuccess, onError
|
* task is composed of different callback types: onRun, onSuccess, onError
|
||||||
*/
|
*/
|
||||||
define([ "core", "underscore" ], function(core) {
|
define([
|
||||||
|
"underscore",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager"
|
||||||
|
], function(_, core, utils, extensionMgr) {
|
||||||
|
|
||||||
var asyncRunner = {};
|
var asyncRunner = {};
|
||||||
|
|
||||||
@ -81,7 +86,7 @@ define([ "core", "underscore" ], function(core) {
|
|||||||
}
|
}
|
||||||
error = error || new Error("Unknown error");
|
error = error || new Error("Unknown error");
|
||||||
if(error.message) {
|
if(error.message) {
|
||||||
core.showError(error);
|
extensionMgr.onError(error);
|
||||||
}
|
}
|
||||||
runSafe(task, task.errorCallbacks, error);
|
runSafe(task, task.errorCallbacks, error);
|
||||||
// Exit the current call stack
|
// Exit the current call stack
|
||||||
@ -102,7 +107,7 @@ define([ "core", "underscore" ], function(core) {
|
|||||||
}
|
}
|
||||||
// Implement an exponential backoff
|
// Implement an exponential backoff
|
||||||
var delay = Math.pow(2, task.retryCounter++) * 1000;
|
var delay = Math.pow(2, task.retryCounter++) * 1000;
|
||||||
currentTaskStartTime = core.currentTime + delay;
|
currentTaskStartTime = utils.currentTime + delay;
|
||||||
currentTaskRunning = false;
|
currentTaskRunning = false;
|
||||||
asyncRunner.runTask();
|
asyncRunner.runTask();
|
||||||
};
|
};
|
||||||
@ -117,7 +122,7 @@ define([ "core", "underscore" ], function(core) {
|
|||||||
// If there is a task currently running
|
// If there is a task currently running
|
||||||
if (currentTaskRunning === true) {
|
if (currentTaskRunning === true) {
|
||||||
// If the current task takes too long
|
// If the current task takes too long
|
||||||
if (currentTaskStartTime + currentTask.timeout < core.currentTime) {
|
if (currentTaskStartTime + currentTask.timeout < utils.currentTime) {
|
||||||
currentTask.error(new Error("A timeout occurred."));
|
currentTask.error(new Error("A timeout occurred."));
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -131,12 +136,12 @@ define([ "core", "underscore" ], function(core) {
|
|||||||
|
|
||||||
// Dequeue an enqueued task
|
// Dequeue an enqueued task
|
||||||
currentTask = taskQueue.shift();
|
currentTask = taskQueue.shift();
|
||||||
currentTaskStartTime = core.currentTime;
|
currentTaskStartTime = utils.currentTime;
|
||||||
core.showWorkingIndicator(true);
|
extensionMgr.onAsyncRunning(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the task
|
// Run the task
|
||||||
if (currentTaskStartTime <= core.currentTime) {
|
if (currentTaskStartTime <= utils.currentTime) {
|
||||||
currentTaskRunning = true;
|
currentTaskRunning = true;
|
||||||
currentTask.chain();
|
currentTask.chain();
|
||||||
}
|
}
|
||||||
@ -157,7 +162,7 @@ define([ "core", "underscore" ], function(core) {
|
|||||||
currentTaskRunning = false;
|
currentTaskRunning = false;
|
||||||
}
|
}
|
||||||
if (taskQueue.length === 0) {
|
if (taskQueue.length === 0) {
|
||||||
core.showWorkingIndicator(false);
|
extensionMgr.onAsyncRunning(false);
|
||||||
} else {
|
} else {
|
||||||
asyncRunner.runTask();
|
asyncRunner.runTask();
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define(["utils", "google-helper"], function(utils, googleHelper) {
|
define([
|
||||||
|
"underscore",
|
||||||
|
"utils",
|
||||||
|
"google-helper"
|
||||||
|
], function(_, utils, googleHelper) {
|
||||||
|
|
||||||
var PROVIDER_BLOGGER = "blogger";
|
var PROVIDER_BLOGGER = "blogger";
|
||||||
|
|
||||||
@ -39,10 +43,11 @@ define(["utils", "google-helper"], function(utils, googleHelper) {
|
|||||||
publishAttributes.labelList = [];
|
publishAttributes.labelList = [];
|
||||||
var labels = utils.getInputTextValue("#input-publish-labels");
|
var labels = utils.getInputTextValue("#input-publish-labels");
|
||||||
if(labels !== undefined) {
|
if(labels !== undefined) {
|
||||||
publishAttributes.labelList = _.chain(labels.split(","))
|
publishAttributes.labelList = _.chain(
|
||||||
.map(function(label) {
|
labels.split(",")
|
||||||
return utils.trim(label);
|
).map(function(label) {
|
||||||
}).compact().value();
|
return utils.trim(label);
|
||||||
|
}).compact().value();
|
||||||
}
|
}
|
||||||
if(event.isPropagationStopped()) {
|
if(event.isPropagationStopped()) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
219
js/core.js
219
js/core.js
@ -1,28 +1,18 @@
|
|||||||
define([
|
define([
|
||||||
"jquery",
|
"jquery",
|
||||||
|
"underscore",
|
||||||
"utils",
|
"utils",
|
||||||
|
"settings",
|
||||||
"extension-manager",
|
"extension-manager",
|
||||||
"bootstrap",
|
|
||||||
"layout",
|
|
||||||
"Markdown.Editor",
|
|
||||||
"storage",
|
"storage",
|
||||||
"config",
|
"config",
|
||||||
"underscore",
|
"lib/bootstrap",
|
||||||
"FileSaver",
|
"lib/layout",
|
||||||
"css_browser_selector"
|
"lib/Markdown.Editor"
|
||||||
], function($, utils, extensionManager) {
|
], function($, _, utils, settings, extensionMgr) {
|
||||||
|
|
||||||
var core = {};
|
var core = {};
|
||||||
|
|
||||||
// For convenience
|
|
||||||
core.doNothing = function() {};
|
|
||||||
|
|
||||||
// Time shared by others modules
|
|
||||||
function updateCurrentTime() {
|
|
||||||
core.currentTime = new Date().getTime();
|
|
||||||
}
|
|
||||||
updateCurrentTime();
|
|
||||||
|
|
||||||
// Used for periodic tasks
|
// Used for periodic tasks
|
||||||
var intervalId = undefined;
|
var intervalId = undefined;
|
||||||
var periodicCallbacks = [];
|
var periodicCallbacks = [];
|
||||||
@ -38,11 +28,11 @@ define([
|
|||||||
function setUserActive() {
|
function setUserActive() {
|
||||||
userReal = true;
|
userReal = true;
|
||||||
userActive = true;
|
userActive = true;
|
||||||
userLastActivity = core.currentTime;
|
userLastActivity = utils.currentTime;
|
||||||
};
|
};
|
||||||
function isUserActive() {
|
function isUserActive() {
|
||||||
if(userActive === true
|
if(userActive === true
|
||||||
&& core.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
|
&& utils.currentTime - userLastActivity > USER_IDLE_THRESHOLD) {
|
||||||
userActive = false;
|
userActive = false;
|
||||||
}
|
}
|
||||||
return userActive && windowUnique;
|
return userActive && windowUnique;
|
||||||
@ -50,7 +40,7 @@ define([
|
|||||||
|
|
||||||
// Used to only have 1 window of the application in the same browser
|
// Used to only have 1 window of the application in the same browser
|
||||||
var windowId = undefined;
|
var windowId = undefined;
|
||||||
core.checkWindowUnique = function() {
|
function checkWindowUnique() {
|
||||||
if(userReal === false || windowUnique === false) {
|
if(userReal === false || windowUnique === false) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -70,136 +60,65 @@ define([
|
|||||||
keyboard: false
|
keyboard: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Export data on disk
|
|
||||||
core.saveFile = function(content, filename) {
|
|
||||||
if(saveAs !== undefined) {
|
|
||||||
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
|
|
||||||
saveAs(blob, filename);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
var uriContent = "data:application/octet-stream;base64,"
|
|
||||||
+ utils.encodeBase64(content);
|
|
||||||
window.open(uriContent, 'file');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Used by asyncRunner
|
|
||||||
core.showWorkingIndicator = function(show) {
|
|
||||||
if (show === false) {
|
|
||||||
$(".working-indicator").removeClass("show");
|
|
||||||
$("body").removeClass("working");
|
|
||||||
} else {
|
|
||||||
$(".working-indicator").addClass("show");
|
|
||||||
$("body").addClass("working");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log a message
|
|
||||||
core.showMessage = function(message) {
|
|
||||||
console.log(message);
|
|
||||||
extensionManager.onMessage(message);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Log an error
|
|
||||||
core.showError = function(error) {
|
|
||||||
console.error(error);
|
|
||||||
if(_.isString(error)) {
|
|
||||||
extensionManager.onMessage(error);
|
|
||||||
}
|
|
||||||
else if(_.isObject(error)) {
|
|
||||||
extensionManager.onMessage(error.message);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Offline management
|
// Offline management
|
||||||
core.isOffline = false;
|
core.isOffline = false;
|
||||||
var offlineTime = core.currentTime;
|
var offlineTime = utils.currentTime;
|
||||||
var offlineListeners = [];
|
|
||||||
core.addOfflineListener = function(callback) {
|
|
||||||
offlineListeners.push(callback);
|
|
||||||
};
|
|
||||||
core.setOffline = function() {
|
core.setOffline = function() {
|
||||||
offlineTime = core.currentTime;
|
offlineTime = utils.currentTime;
|
||||||
if(core.isOffline === false) {
|
if(core.isOffline === false) {
|
||||||
core.isOffline = true;
|
core.isOffline = true;
|
||||||
extensionManager.onOfflineChanged(true);
|
extensionMgr.onOfflineChanged(true);
|
||||||
_.each(offlineListeners, function(listener) {
|
|
||||||
listener();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
core.setOnline = function() {
|
function setOnline() {
|
||||||
if(core.isOffline === true) {
|
if(core.isOffline === true) {
|
||||||
core.isOffline = false;
|
core.isOffline = false;
|
||||||
extensionManager.onOfflineChanged(false);
|
extensionMgr.onOfflineChanged(false);
|
||||||
_.each(offlineListeners, function(listener) {
|
|
||||||
listener();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
function checkOnline() {
|
function checkOnline() {
|
||||||
// Try to reconnect if we are offline but we have some network
|
// Try to reconnect if we are offline but we have some network
|
||||||
if (core.isOffline === true && navigator.onLine === true
|
if (core.isOffline === true && navigator.onLine === true
|
||||||
&& offlineTime + CHECK_ONLINE_PERIOD < core.currentTime) {
|
&& offlineTime + CHECK_ONLINE_PERIOD < utils.currentTime) {
|
||||||
offlineTime = core.currentTime;
|
offlineTime = utils.currentTime;
|
||||||
// Try to download anything to test the connection
|
// Try to download anything to test the connection
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url : "//www.google.com/jsapi",
|
url : "//www.google.com/jsapi",
|
||||||
timeout : AJAX_TIMEOUT, dataType : "script"
|
timeout : AJAX_TIMEOUT, dataType : "script"
|
||||||
}).done(function() {
|
}).done(function() {
|
||||||
core.setOnline();
|
setOnline();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setting management
|
// Load settings in settings dialog
|
||||||
core.settings = {
|
function loadSettings() {
|
||||||
layoutOrientation : "horizontal",
|
|
||||||
lazyRendering : true,
|
|
||||||
editorFontSize : 14,
|
|
||||||
defaultContent: "\n\n\n> Written with [StackEdit](http://benweet.github.io/stackedit/).",
|
|
||||||
commitMsg : "Published by http://benweet.github.io/stackedit",
|
|
||||||
template : ['<!DOCTYPE html>\n',
|
|
||||||
'<html>\n',
|
|
||||||
'<head>\n',
|
|
||||||
'<title><%= documentTitle %></title>\n',
|
|
||||||
'</head>\n',
|
|
||||||
'<body><%= documentHTML %></body>\n',
|
|
||||||
'</html>'].join(""),
|
|
||||||
sshProxy : SSH_PROXY_URL,
|
|
||||||
extensionSettings: {}
|
|
||||||
};
|
|
||||||
if (_.has(localStorage, "settings")) {
|
|
||||||
_.extend(core.settings, JSON.parse(localStorage.settings));
|
|
||||||
}
|
|
||||||
extensionManager.init(core.settings.extensionSettings);
|
|
||||||
|
|
||||||
core.loadSettings = function() {
|
|
||||||
|
|
||||||
// Layout orientation
|
// Layout orientation
|
||||||
utils.setInputRadio("radio-layout-orientation", core.settings.layoutOrientation);
|
utils.setInputRadio("radio-layout-orientation", settings.layoutOrientation);
|
||||||
// Theme
|
// Theme
|
||||||
utils.setInputValue("#input-settings-theme", localStorage.theme);
|
utils.setInputValue("#input-settings-theme", localStorage.theme);
|
||||||
// Lazy rendering
|
// Lazy rendering
|
||||||
utils.setInputChecked("#input-settings-lazy-rendering", core.settings.lazyRendering);
|
utils.setInputChecked("#input-settings-lazy-rendering", settings.lazyRendering);
|
||||||
// Editor font size
|
// Editor font size
|
||||||
utils.setInputValue("#input-settings-editor-font-size", core.settings.editorFontSize);
|
utils.setInputValue("#input-settings-editor-font-size", settings.editorFontSize);
|
||||||
// Default content
|
// Default content
|
||||||
utils.setInputValue("#textarea-settings-default-content", core.settings.defaultContent);
|
utils.setInputValue("#textarea-settings-default-content", settings.defaultContent);
|
||||||
// Commit message
|
// Commit message
|
||||||
utils.setInputValue("#input-settings-publish-commit-msg", core.settings.commitMsg);
|
utils.setInputValue("#input-settings-publish-commit-msg", settings.commitMsg);
|
||||||
// Template
|
// Template
|
||||||
utils.setInputValue("#textarea-settings-publish-template", core.settings.template);
|
utils.setInputValue("#textarea-settings-publish-template", settings.template);
|
||||||
// SSH proxy
|
// SSH proxy
|
||||||
utils.setInputValue("#input-settings-ssh-proxy", core.settings.sshProxy);
|
utils.setInputValue("#input-settings-ssh-proxy", settings.sshProxy);
|
||||||
|
|
||||||
// Load extension settings
|
// Load extension settings
|
||||||
extensionManager.onLoadSettings();
|
extensionMgr.onLoadSettings();
|
||||||
};
|
}
|
||||||
|
|
||||||
core.saveSettings = function(event) {
|
// Save settings from settings dialog
|
||||||
|
function saveSettings(event) {
|
||||||
var newSettings = {};
|
var newSettings = {};
|
||||||
|
|
||||||
// Layout orientation
|
// Layout orientation
|
||||||
@ -221,14 +140,14 @@ define([
|
|||||||
|
|
||||||
// Save extension settings
|
// Save extension settings
|
||||||
newSettings.extensionSettings = {};
|
newSettings.extensionSettings = {};
|
||||||
extensionManager.onSaveSettings(newSettings.extensionSettings, event);
|
extensionMgr.onSaveSettings(newSettings.extensionSettings, event);
|
||||||
|
|
||||||
if(!event.isPropagationStopped()) {
|
if(!event.isPropagationStopped()) {
|
||||||
$.extend(core.settings, newSettings);
|
$.extend(settings, newSettings);
|
||||||
localStorage.settings = JSON.stringify(newSettings);
|
localStorage.settings = JSON.stringify(settings);
|
||||||
localStorage.theme = theme;
|
localStorage.theme = theme;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
// Create the layout
|
// Create the layout
|
||||||
var layout = undefined;
|
var layout = undefined;
|
||||||
@ -250,8 +169,8 @@ define([
|
|||||||
center__minWidth : 200,
|
center__minWidth : 200,
|
||||||
center__minHeight : 200
|
center__minHeight : 200
|
||||||
};
|
};
|
||||||
extensionManager.onLayoutConfigure(layoutGlobalConfig);
|
extensionMgr.onLayoutConfigure(layoutGlobalConfig);
|
||||||
if (core.settings.layoutOrientation == "horizontal") {
|
if (settings.layoutOrientation == "horizontal") {
|
||||||
$(".ui-layout-south").remove();
|
$(".ui-layout-south").remove();
|
||||||
$(".ui-layout-east").addClass("well").prop("id", "wmd-preview");
|
$(".ui-layout-east").addClass("well").prop("id", "wmd-preview");
|
||||||
layout = $('body').layout(
|
layout = $('body').layout(
|
||||||
@ -261,7 +180,7 @@ define([
|
|||||||
east__minSize : 200
|
east__minSize : 200
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (core.settings.layoutOrientation == "vertical") {
|
} else if (settings.layoutOrientation == "vertical") {
|
||||||
$(".ui-layout-east").remove();
|
$(".ui-layout-east").remove();
|
||||||
$(".ui-layout-south").addClass("well").prop("id", "wmd-preview");
|
$(".ui-layout-south").addClass("well").prop("id", "wmd-preview");
|
||||||
layout = $('body').layout(
|
layout = $('body').layout(
|
||||||
@ -282,7 +201,7 @@ define([
|
|||||||
layout.allowOverflow('north');
|
layout.allowOverflow('north');
|
||||||
});
|
});
|
||||||
|
|
||||||
extensionManager.onLayoutCreated(layout);
|
extensionMgr.onLayoutCreated(layout);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the PageDown editor
|
// Create the PageDown editor
|
||||||
@ -320,7 +239,7 @@ define([
|
|||||||
makePreview();
|
makePreview();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
if(core.settings.lazyRendering === true) {
|
if(settings.lazyRendering === true) {
|
||||||
var lastRefresh = 0;
|
var lastRefresh = 0;
|
||||||
previewWrapper = function(makePreview) {
|
previewWrapper = function(makePreview) {
|
||||||
//var debouncedMakePreview = _.debounce(makePreview, 500);
|
//var debouncedMakePreview = _.debounce(makePreview, 500);
|
||||||
@ -340,8 +259,8 @@ define([
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
extensionManager.onEditorConfigure(editor);
|
extensionMgr.onEditorConfigure(editor);
|
||||||
editor.hooks.chain("onPreviewRefresh", extensionManager.onAsyncPreview);
|
editor.hooks.chain("onPreviewRefresh", extensionMgr.onAsyncPreview);
|
||||||
|
|
||||||
// Convert email addresses (not managed by pagedown)
|
// Convert email addresses (not managed by pagedown)
|
||||||
converter.hooks.chain("postConversion", function(text) {
|
converter.hooks.chain("postConversion", function(text) {
|
||||||
@ -374,53 +293,29 @@ define([
|
|||||||
$("#wmd-redo-button").append($("<i>").addClass("icon-share-alt"));
|
$("#wmd-redo-button").append($("<i>").addClass("icon-share-alt"));
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create an centered popup window
|
|
||||||
core.popupWindow = function(url, title, w, h) {
|
|
||||||
var left = (screen.width / 2) - (w / 2);
|
|
||||||
var top = (screen.height / 2) - (h / 2);
|
|
||||||
return window
|
|
||||||
.open(
|
|
||||||
url,
|
|
||||||
title,
|
|
||||||
'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='
|
|
||||||
+ w
|
|
||||||
+ ', height='
|
|
||||||
+ h
|
|
||||||
+ ', top='
|
|
||||||
+ top
|
|
||||||
+ ', left='
|
|
||||||
+ left);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Keep a reference to the fileManager
|
|
||||||
core.setFileManager = function(fileManager) {
|
|
||||||
core.fileManager = fileManager;
|
|
||||||
runReadyCallbacks();
|
|
||||||
};
|
|
||||||
|
|
||||||
// onReady event callbacks
|
// onReady event callbacks
|
||||||
var readyCallbacks = [];
|
var readyCallbacks = [];
|
||||||
core.onReady = function(callback) {
|
core.onReady = function(callback) {
|
||||||
readyCallbacks.push(callback);
|
readyCallbacks.push(callback);
|
||||||
runReadyCallbacks();
|
runReadyCallbacks();
|
||||||
};
|
};
|
||||||
var documentLoaded = false;
|
var ready = false;
|
||||||
|
core.setReady = function() {
|
||||||
|
ready = true;
|
||||||
|
runReadyCallbacks();
|
||||||
|
};
|
||||||
function runReadyCallbacks() {
|
function runReadyCallbacks() {
|
||||||
if(documentLoaded === true && core.fileManager !== undefined) {
|
if(ready === true) {
|
||||||
_.each(readyCallbacks, function(callback) {
|
_.each(readyCallbacks, function(callback) {
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
readyCallbacks = [];
|
readyCallbacks = [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$(function() {
|
|
||||||
documentLoaded = true;
|
|
||||||
runReadyCallbacks();
|
|
||||||
});
|
|
||||||
|
|
||||||
core.onReady(extensionManager.onReady);
|
core.onReady(extensionManager.onReady);
|
||||||
core.onReady(function() {
|
core.onReady(function() {
|
||||||
|
|
||||||
// Load theme list
|
// Load theme list
|
||||||
_.each(THEME_LIST, function(name, value) {
|
_.each(THEME_LIST, function(name, value) {
|
||||||
$("#input-settings-theme").append($('<option value="' + value + '">' + name + '</option>'));
|
$("#input-settings-theme").append($('<option value="' + value + '">' + name + '</option>'));
|
||||||
@ -428,7 +323,7 @@ define([
|
|||||||
|
|
||||||
// listen to online/offline events
|
// listen to online/offline events
|
||||||
$(window).on('offline', core.setOffline);
|
$(window).on('offline', core.setOffline);
|
||||||
$(window).on('online', core.setOnline);
|
$(window).on('online', setOnline);
|
||||||
if (navigator.onLine === false) {
|
if (navigator.onLine === false) {
|
||||||
core.setOffline();
|
core.setOffline();
|
||||||
}
|
}
|
||||||
@ -460,10 +355,10 @@ define([
|
|||||||
|
|
||||||
// Settings loading/saving
|
// Settings loading/saving
|
||||||
$(".action-load-settings").click(function() {
|
$(".action-load-settings").click(function() {
|
||||||
core.loadSettings();
|
loadSettings();
|
||||||
});
|
});
|
||||||
$(".action-apply-settings").click(function(e) {
|
$(".action-apply-settings").click(function(e) {
|
||||||
core.saveSettings(e);
|
saveSettings(e);
|
||||||
if(!e.isPropagationStopped()) {
|
if(!e.isPropagationStopped()) {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
}
|
}
|
||||||
@ -487,8 +382,8 @@ define([
|
|||||||
// Editor's textarea
|
// Editor's textarea
|
||||||
$("#wmd-input, #md-section-helper").css({
|
$("#wmd-input, #md-section-helper").css({
|
||||||
// Apply editor font size
|
// Apply editor font size
|
||||||
"font-size": core.settings.editorFontSize + "px",
|
"font-size": settings.editorFontSize + "px",
|
||||||
"line-height": Math.round(core.settings.editorFontSize * (20/14)) + "px"
|
"line-height": Math.round(settings.editorFontSize * (20/14)) + "px"
|
||||||
});
|
});
|
||||||
|
|
||||||
// Manage tab key
|
// Manage tab key
|
||||||
@ -564,8 +459,8 @@ define([
|
|||||||
|
|
||||||
// Do periodic tasks
|
// Do periodic tasks
|
||||||
intervalId = window.setInterval(function() {
|
intervalId = window.setInterval(function() {
|
||||||
updateCurrentTime();
|
utils.updateCurrentTime();
|
||||||
core.checkWindowUnique();
|
checkWindowUnique();
|
||||||
if(isUserActive() === true || viewerMode === true) {
|
if(isUserActive() === true || viewerMode === true) {
|
||||||
_.each(periodicCallbacks, function(callback) {
|
_.each(periodicCallbacks, function(callback) {
|
||||||
callback();
|
callback();
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, asyncRunner) {
|
||||||
|
|
||||||
var PROVIDER_DOWNLOAD = "download";
|
var PROVIDER_DOWNLOAD = "download";
|
||||||
|
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"core",
|
||||||
|
"extension-manager",
|
||||||
|
"async-runner"
|
||||||
|
], function($, _, core, extensionMgr, asyncRunner) {
|
||||||
|
|
||||||
var client = undefined;
|
var client = undefined;
|
||||||
var authenticated = false;
|
var authenticated = false;
|
||||||
@ -50,7 +56,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
var immediate = true;
|
var immediate = true;
|
||||||
function localAuthenticate() {
|
function localAuthenticate() {
|
||||||
if (immediate === false) {
|
if (immediate === false) {
|
||||||
core.showMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Dropbox authorization popup is not blocked by your browser.");
|
||||||
// If not immediate we add time for user to enter his credentials
|
// If not immediate we add time for user to enter his credentials
|
||||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||||
}
|
}
|
||||||
@ -77,7 +83,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dropboxHelper.upload = function(path, content, callback) {
|
dropboxHelper.upload = function(path, content, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = undefined;
|
var result = undefined;
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
@ -106,7 +111,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dropboxHelper.checkChanges = function(lastChangeId, callback) {
|
dropboxHelper.checkChanges = function(lastChangeId, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var changes = [];
|
var changes = [];
|
||||||
var newChangeId = lastChangeId || 0;
|
var newChangeId = lastChangeId || 0;
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
@ -143,7 +147,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dropboxHelper.downloadMetadata = function(paths, callback) {
|
dropboxHelper.downloadMetadata = function(paths, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = [];
|
var result = [];
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
@ -177,7 +180,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
dropboxHelper.downloadContent = function(objects, callback) {
|
dropboxHelper.downloadContent = function(objects, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = [];
|
var result = [];
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
@ -289,7 +291,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dropboxHelper.picker = function(callback) {
|
dropboxHelper.picker = function(callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var paths = [];
|
var paths = [];
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
// Add some time for user to choose his files
|
// Add some time for user to choose his files
|
||||||
@ -312,7 +313,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
task.chain();
|
task.chain();
|
||||||
};
|
};
|
||||||
Dropbox.choose(options);
|
Dropbox.choose(options);
|
||||||
core.showMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Dropbox chooser popup is not blocked by your browser.");
|
||||||
});
|
});
|
||||||
task.onSuccess(function() {
|
task.onSuccess(function() {
|
||||||
callback(undefined, paths);
|
callback(undefined, paths);
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["core", "utils", "extension-manager", "dropbox-helper"], function(core, utils, extensionManager, dropboxHelper) {
|
define([
|
||||||
|
"underscore",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"file-manager",
|
||||||
|
"dropbox-helper"
|
||||||
|
], function(_, utils, extensionMgr, fileMgr, dropboxHelper) {
|
||||||
|
|
||||||
var PROVIDER_DROPBOX = "dropbox";
|
var PROVIDER_DROPBOX = "dropbox";
|
||||||
|
|
||||||
@ -13,7 +19,7 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if(!path.match(/^[^\\<>:"\|?\*]+$/)) {
|
if(!path.match(/^[^\\<>:"\|?\*]+$/)) {
|
||||||
core.showError('"' + path + '" contains invalid characters.');
|
extensionMgr.onError('"' + path + '" contains invalid characters.');
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
if(path.indexOf("/") !== 0) {
|
if(path.indexOf("/") !== 0) {
|
||||||
@ -51,11 +57,11 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
||||||
var syncLocations = {};
|
var syncLocations = {};
|
||||||
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||||
var fileDesc = core.fileManager.createFile(file.name, file.content, syncLocations);
|
var fileDesc = fileMgr.createFile(file.name, file.content, syncLocations);
|
||||||
core.fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
fileDescList.push(fileDesc);
|
fileDescList.push(fileDesc);
|
||||||
});
|
});
|
||||||
extensionManager.onSyncImportSuccess(fileDescList, dropboxProvider);
|
extensionMgr.onSyncImportSuccess(fileDescList, dropboxProvider);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -68,9 +74,9 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
var importPaths = [];
|
var importPaths = [];
|
||||||
_.each(paths, function(path) {
|
_.each(paths, function(path) {
|
||||||
var syncIndex = createSyncIndex(path);
|
var syncIndex = createSyncIndex(path);
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
core.showError('"' + fileDesc.title + '" was already imported');
|
extensionMgr.onError('"' + fileDesc.title + '" was already imported');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
importPaths.push(path);
|
importPaths.push(path);
|
||||||
@ -87,10 +93,10 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
}
|
}
|
||||||
// Check that file is not synchronized with an other one
|
// Check that file is not synchronized with an other one
|
||||||
var syncIndex = createSyncIndex(path);
|
var syncIndex = createSyncIndex(path);
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
var existingTitle = fileDesc.title;
|
var existingTitle = fileDesc.title;
|
||||||
core.showError('File path is already synchronized with "' + existingTitle + '"');
|
extensionMgr.onError('File path is already synchronized with "' + existingTitle + '"');
|
||||||
callback(true);
|
callback(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -143,7 +149,7 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
var interestingChanges = [];
|
var interestingChanges = [];
|
||||||
_.each(changes, function(change) {
|
_.each(changes, function(change) {
|
||||||
var syncIndex = createSyncIndex(change.path);
|
var syncIndex = createSyncIndex(change.path);
|
||||||
var syncAttributes = core.fileManager.getSyncAttributes(syncIndex);
|
var syncAttributes = fileMgr.getSyncAttributes(syncIndex);
|
||||||
if(syncAttributes === undefined) {
|
if(syncAttributes === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -164,11 +170,10 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var updateFileTitles = false;
|
|
||||||
_.each(changes, function(change) {
|
_.each(changes, function(change) {
|
||||||
var syncAttributes = change.syncAttributes;
|
var syncAttributes = change.syncAttributes;
|
||||||
var syncIndex = syncAttributes.syncIndex;
|
var syncIndex = syncAttributes.syncIndex;
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
// No file corresponding (file may have been deleted locally)
|
// No file corresponding (file may have been deleted locally)
|
||||||
if(fileDesc === undefined) {
|
if(fileDesc === undefined) {
|
||||||
return;
|
return;
|
||||||
@ -176,8 +181,8 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
var localTitle = fileDesc.title;
|
var localTitle = fileDesc.title;
|
||||||
// File deleted
|
// File deleted
|
||||||
if (change.wasRemoved === true) {
|
if (change.wasRemoved === true) {
|
||||||
core.showError('"' + localTitle + '" has been removed from Dropbox.');
|
extensionMgr.onError('"' + localTitle + '" has been removed from Dropbox.');
|
||||||
core.fileManager.removeSync(syncAttributes);
|
fileMgr.removeSync(syncAttributes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var localContent = localStorage[fileDesc.fileIndex + ".content"];
|
var localContent = localStorage[fileDesc.fileIndex + ".content"];
|
||||||
@ -188,17 +193,16 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
var fileContentChanged = localContent != file.content;
|
var fileContentChanged = localContent != file.content;
|
||||||
// Conflict detection
|
// Conflict detection
|
||||||
if (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
|
if (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true) {
|
||||||
core.fileManager.createFile(localTitle + " (backup)", localContent);
|
var backupFileDesc = fileMgr.createFile(localTitle + " (backup)", localContent);
|
||||||
updateFileTitles = true;
|
extensionMgr.onTitleChanged(backupFileDesc);
|
||||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||||
}
|
}
|
||||||
// If file content changed
|
// If file content changed
|
||||||
if(fileContentChanged && remoteContentChanged === true) {
|
if(fileContentChanged && remoteContentChanged === true) {
|
||||||
localStorage[fileDesc.fileIndex + ".content"] = file.content;
|
localStorage[fileDesc.fileIndex + ".content"] = file.content;
|
||||||
core.showMessage('"' + localTitle + '" has been updated from Dropbox.');
|
extensionMgr.onMessage('"' + localTitle + '" has been updated from Dropbox.');
|
||||||
if(core.fileManager.isCurrentFile(fileDesc)) {
|
if(fileMgr.isCurrentFile(fileDesc)) {
|
||||||
updateFileTitles = false; // Done by next function
|
fileMgr.selectFile(); // Refresh editor
|
||||||
core.fileManager.selectFile(); // Refresh editor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update syncAttributes
|
// Update syncAttributes
|
||||||
@ -206,9 +210,6 @@ define(["core", "utils", "extension-manager", "dropbox-helper"], function(core,
|
|||||||
syncAttributes.contentCRC = remoteContentCRC;
|
syncAttributes.contentCRC = remoteContentCRC;
|
||||||
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
|
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
|
||||||
});
|
});
|
||||||
if(updateFileTitles) {
|
|
||||||
extensionManager.onTitleChanged();
|
|
||||||
}
|
|
||||||
localStorage[PROVIDER_DROPBOX + ".lastChangeId"] = newChangeId;
|
localStorage[PROVIDER_DROPBOX + ".lastChangeId"] = newChangeId;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
@ -1,29 +1,40 @@
|
|||||||
define( [
|
define( [
|
||||||
"jquery",
|
"jquery",
|
||||||
"utils",
|
|
||||||
"underscore",
|
"underscore",
|
||||||
"bootstrap",
|
"utils",
|
||||||
|
"settings",
|
||||||
|
"extensions/button-publish",
|
||||||
|
"extensions/button-share",
|
||||||
|
"extensions/button-sync",
|
||||||
|
"extensions/document-selector",
|
||||||
|
"extensions/document-title",
|
||||||
|
"extensions/manage-publication",
|
||||||
|
"extensions/manage-synchronization",
|
||||||
|
"extensions/working-indicator",
|
||||||
"extensions/notifications",
|
"extensions/notifications",
|
||||||
"extensions/markdown-extra",
|
"extensions/markdown-extra",
|
||||||
"extensions/toc",
|
"extensions/toc",
|
||||||
"extensions/math-jax",
|
"extensions/math-jax",
|
||||||
"extensions/scroll-link"
|
"extensions/scroll-link",
|
||||||
], function($, utils) {
|
"lib/bootstrap"
|
||||||
|
], function($, _, utils, settings) {
|
||||||
|
|
||||||
var extensionManager = {};
|
var extensionMgr = {};
|
||||||
|
|
||||||
// Create a list of extensions
|
// Create a list of extensions
|
||||||
var extensionList = _.chain(arguments)
|
var extensionList = _.chain(
|
||||||
.map(function(argument) {
|
arguments
|
||||||
return _.isObject(argument) && argument.extensionId && argument;
|
).map(function(argument) {
|
||||||
}).compact().value();
|
return _.isObject(argument) && argument.extensionId && argument;
|
||||||
|
}).compact().value();
|
||||||
|
|
||||||
// Return every named callbacks implemented in extensions
|
// Return every named callbacks implemented in extensions
|
||||||
function getExtensionCallbackList(hookName) {
|
function getExtensionCallbackList(hookName) {
|
||||||
return _.chain(extensionList)
|
return _.chain(
|
||||||
.map(function(extension) {
|
extensionList
|
||||||
return extension.config.enabled && extension[hookName];
|
).map(function(extension) {
|
||||||
}).compact().value();
|
return extension.config.enabled && extension[hookName];
|
||||||
|
}).compact().value();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return a function that calls every callbacks from extensions
|
// Return a function that calls every callbacks from extensions
|
||||||
@ -38,9 +49,9 @@ define( [
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a Hook to the extensionManager
|
// Add a Hook to the extensionMgr
|
||||||
function addHook(hookName) {
|
function addHook(hookName) {
|
||||||
extensionManager[hookName] = createHook(hookName);
|
extensionMgr[hookName] = createHook(hookName);
|
||||||
}
|
}
|
||||||
|
|
||||||
var accordionTmpl = [
|
var accordionTmpl = [
|
||||||
@ -66,96 +77,97 @@ define( [
|
|||||||
settingsBloc: extension.settingsBloc
|
settingsBloc: extension.settingsBloc
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
||||||
extensionManager.init = function(extensionSettings) {
|
|
||||||
|
|
||||||
// Set extension config
|
|
||||||
extensionSettings = extensionSettings || {};
|
|
||||||
_.each(extensionList, function(extension) {
|
|
||||||
extension.config = _.extend({}, extension.defaultConfig, extensionSettings[extension.extensionId]);
|
|
||||||
extension.config.enabled = !extension.optional || extension.config.enabled === undefined || extension.config.enabled === true;
|
|
||||||
});
|
|
||||||
|
|
||||||
// Load/Save extension config from/to settings
|
|
||||||
extensionManager["onLoadSettings"] = function() {
|
|
||||||
console.debug("onLoadSettings");
|
|
||||||
_.each(extensionList, function(extension) {
|
|
||||||
utils.setInputChecked("#input-enable-extension-" + extension.extensionId, extension.config.enabled);
|
|
||||||
var onLoadSettingsCallback = extension.onLoadSettings;
|
|
||||||
onLoadSettingsCallback && onLoadSettingsCallback();
|
|
||||||
});
|
|
||||||
};
|
|
||||||
extensionManager["onSaveSettings"] = function(newExtensionSettings, event) {
|
|
||||||
console.debug("onSaveSettings");
|
|
||||||
_.each(extensionList, function(extension) {
|
|
||||||
var newExtensionConfig = extension.defaultConfig || {};
|
|
||||||
newExtensionConfig.enabled = utils.getInputChecked("#input-enable-extension-" + extension.extensionId);
|
|
||||||
var onSaveSettingsCallback = extension.onSaveSettings;
|
|
||||||
onSaveSettingsCallback && onSaveSettingsCallback(newExtensionConfig, event);
|
|
||||||
newExtensionSettings[extension.extensionId] = newExtensionConfig;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
addHook("onMessage");
|
|
||||||
addHook("onError");
|
|
||||||
addHook("onOfflineChanged");
|
|
||||||
|
|
||||||
// To store reference to modules that are accessible from extensions
|
|
||||||
addHook("onFileManagerCreated");
|
|
||||||
addHook("onSynchronizerCreated");
|
|
||||||
addHook("onPublisherCreated");
|
|
||||||
|
|
||||||
// Operations on files
|
|
||||||
addHook("onFileSystemLoaded");
|
|
||||||
addHook("onFileCreated");
|
|
||||||
addHook("onFileDeleted");
|
|
||||||
addHook("onFileChanged");
|
|
||||||
addHook("onFileSelected");
|
|
||||||
addHook("onTitleChanged");
|
|
||||||
addHook("onSyncImportSuccess");
|
|
||||||
addHook("onSyncExportSuccess");
|
|
||||||
addHook("onSyncRemoved");
|
|
||||||
addHook("onPublishSuccess");
|
|
||||||
addHook("onNewPublishSuccess");
|
|
||||||
addHook("onPublishRemoved");
|
|
||||||
|
|
||||||
// Operations on Layout
|
|
||||||
addHook("onLayoutConfigure");
|
|
||||||
addHook("onLayoutCreated");
|
|
||||||
|
|
||||||
// Operations on PageDown
|
|
||||||
addHook("onEditorConfigure");
|
|
||||||
|
|
||||||
var onPreviewFinished = createHook("onPreviewFinished");
|
|
||||||
var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview");
|
|
||||||
extensionManager["onAsyncPreview"] = function() {
|
|
||||||
console.debug("onAsyncPreview");
|
|
||||||
// Call onPreviewFinished callbacks when all async preview are finished
|
|
||||||
var counter = 0;
|
|
||||||
function tryFinished() {
|
|
||||||
if(counter === onAsyncPreviewCallbackList.length) {
|
|
||||||
onPreviewFinished();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_.each(onAsyncPreviewCallbackList, function(asyncPreviewCallback) {
|
|
||||||
asyncPreviewCallback(function() {
|
|
||||||
counter++;
|
|
||||||
tryFinished();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
tryFinished();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call onReady callbacks
|
|
||||||
var onReady = createHook("onReady");
|
|
||||||
extensionManager["onReady"] = function() {
|
|
||||||
|
|
||||||
// Create accordion in settings dialog
|
|
||||||
_.each(extensionList, createSettings);
|
|
||||||
|
|
||||||
onReady();
|
// Set extension config
|
||||||
};
|
extensionSettings = settings.extensionSettings || {};
|
||||||
|
_.each(extensionList, function(extension) {
|
||||||
|
extension.config = _.extend({}, extension.defaultConfig, extensionSettings[extension.extensionId]);
|
||||||
|
extension.config.enabled = !extension.optional || extension.config.enabled === undefined || extension.config.enabled === true;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Load/Save extension config from/to settings
|
||||||
|
extensionMgr["onLoadSettings"] = function() {
|
||||||
|
console.debug("onLoadSettings");
|
||||||
|
_.each(extensionList, function(extension) {
|
||||||
|
utils.setInputChecked("#input-enable-extension-" + extension.extensionId, extension.config.enabled);
|
||||||
|
var onLoadSettingsCallback = extension.onLoadSettings;
|
||||||
|
onLoadSettingsCallback && onLoadSettingsCallback();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
extensionMgr["onSaveSettings"] = function(newExtensionSettings, event) {
|
||||||
|
console.debug("onSaveSettings");
|
||||||
|
_.each(extensionList, function(extension) {
|
||||||
|
var newExtensionConfig = extension.defaultConfig || {};
|
||||||
|
newExtensionConfig.enabled = utils.getInputChecked("#input-enable-extension-" + extension.extensionId);
|
||||||
|
var onSaveSettingsCallback = extension.onSaveSettings;
|
||||||
|
onSaveSettingsCallback && onSaveSettingsCallback(newExtensionConfig, event);
|
||||||
|
newExtensionSettings[extension.extensionId] = newExtensionConfig;
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
return extensionManager;
|
addHook("onReady");
|
||||||
|
addHook("onMessage");
|
||||||
|
addHook("onError");
|
||||||
|
addHook("onOfflineChanged");
|
||||||
|
addHook("onAsyncRunning");
|
||||||
|
|
||||||
|
// To store reference to modules that are accessible from extensions
|
||||||
|
addHook("onFileMgrCreated");
|
||||||
|
addHook("onSynchronizerCreated");
|
||||||
|
addHook("onPublisherCreated");
|
||||||
|
|
||||||
|
// Operations on files
|
||||||
|
addHook("onFileSystemCreated");
|
||||||
|
addHook("onFileCreated");
|
||||||
|
addHook("onFileDeleted");
|
||||||
|
addHook("onFileChanged");
|
||||||
|
addHook("onFileSelected");
|
||||||
|
addHook("onTitleChanged");
|
||||||
|
|
||||||
|
// Sync events
|
||||||
|
addHook("onSyncRunning");
|
||||||
|
addHook("onSyncSuccess");
|
||||||
|
addHook("onSyncImportSuccess");
|
||||||
|
addHook("onSyncExportSuccess");
|
||||||
|
addHook("onSyncRemoved");
|
||||||
|
|
||||||
|
// Publish events
|
||||||
|
addHook("onPublishRunning");
|
||||||
|
addHook("onPublishSuccess");
|
||||||
|
addHook("onNewPublishSuccess");
|
||||||
|
addHook("onPublishRemoved");
|
||||||
|
|
||||||
|
// Operations on Layout
|
||||||
|
addHook("onLayoutConfigure");
|
||||||
|
addHook("onLayoutCreated");
|
||||||
|
|
||||||
|
// Operations on PageDown
|
||||||
|
addHook("onEditorConfigure");
|
||||||
|
|
||||||
|
var onPreviewFinished = createHook("onPreviewFinished");
|
||||||
|
var onAsyncPreviewCallbackList = getExtensionCallbackList("onAsyncPreview");
|
||||||
|
extensionMgr["onAsyncPreview"] = function() {
|
||||||
|
console.debug("onAsyncPreview");
|
||||||
|
// Call onPreviewFinished callbacks when all async preview are finished
|
||||||
|
var counter = 0;
|
||||||
|
function tryFinished() {
|
||||||
|
if(counter === onAsyncPreviewCallbackList.length) {
|
||||||
|
onPreviewFinished();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_.each(onAsyncPreviewCallbackList, function(asyncPreviewCallback) {
|
||||||
|
asyncPreviewCallback(function() {
|
||||||
|
counter++;
|
||||||
|
tryFinished();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
tryFinished();
|
||||||
|
};
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
// Create accordion in settings dialog
|
||||||
|
_.each(extensionList, createSettings);
|
||||||
|
});
|
||||||
|
|
||||||
|
return extensionMgr;
|
||||||
});
|
});
|
58
js/extensions/button-publish.js
Normal file
58
js/extensions/button-publish.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
|
var buttonPublish = {
|
||||||
|
extensionId: "buttonPublish",
|
||||||
|
extensionName: 'Button "Publish"',
|
||||||
|
optional: true,
|
||||||
|
settingsBloc: '<p>Adds a "Publish document" button in the navigation bar.</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
var currentFileDesc = undefined;
|
||||||
|
var publishRunning = false;
|
||||||
|
var hasPublications = false;
|
||||||
|
var isOffline = false;
|
||||||
|
// Enable/disable the button
|
||||||
|
function updateButtonState() {
|
||||||
|
if(publishRunning === true || hasPublications === false || isOffline === true) {
|
||||||
|
$(".action-force-publish").addClass("disabled");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(".action-force-publish").removeClass("disabled");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonPublish.onPublishRunning = function(isRunning) {
|
||||||
|
publishRunning = isRunning;
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonPublish.onOfflineChanged = function(isOfflineParameter) {
|
||||||
|
isOffline = isOfflineParameter;
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check that current file has publications
|
||||||
|
var checkPublication = function() {
|
||||||
|
if(_.size(currentFileDesc.publishLocations) === 0) {
|
||||||
|
hasPublications = false;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
hasPublications = true;
|
||||||
|
}
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonPublish.onFileSelected = function(fileDesc) {
|
||||||
|
currentFileDesc = fileDesc;
|
||||||
|
checkPublication();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonPublish.onPublishRemoved = checkPublication;
|
||||||
|
buttonPublish.onNewPublishSuccess = checkPublication;
|
||||||
|
|
||||||
|
return buttonPublish;
|
||||||
|
|
||||||
|
});
|
@ -1,12 +1,13 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var sharingButton = {
|
var buttonShare = {
|
||||||
extensionId: "sharingButton",
|
extensionId: "buttonShare",
|
||||||
extensionName: "Sharing button",
|
extensionName: 'Button "Share"',
|
||||||
optional: true,
|
optional: true,
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Adds a "Share document" button in the navigation bar.</p>'
|
||||||
'<p>Adds a "Share document" button in the navigation bar.</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileDesc = undefined;
|
var fileDesc = undefined;
|
||||||
@ -14,8 +15,7 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
'<div class="input-prepend">',
|
'<div class="input-prepend">',
|
||||||
'<a href="<%= link %>" class="add-on" title="Sharing location"><i class="icon-link"></i></a>',
|
'<a href="<%= link %>" class="add-on" title="Sharing location"><i class="icon-link"></i></a>',
|
||||||
'<input class="span2" type="text" value="<%= link %>" readonly />',
|
'<input class="span2" type="text" value="<%= link %>" readonly />',
|
||||||
'</div>'
|
'</div>'].join("");
|
||||||
].join("");
|
|
||||||
var refreshDocumentSharing = function(fileDescParameter) {
|
var refreshDocumentSharing = function(fileDescParameter) {
|
||||||
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
|
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
|
||||||
return;
|
return;
|
||||||
@ -39,14 +39,14 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
sharingButton.onFileSelected = function(fileDescParameter) {
|
buttonShare.onFileSelected = function(fileDescParameter) {
|
||||||
fileDesc = fileDescParameter;
|
fileDesc = fileDescParameter;
|
||||||
refreshDocumentSharing(fileDescParameter);
|
refreshDocumentSharing(fileDescParameter);
|
||||||
};
|
};
|
||||||
|
|
||||||
sharingButton.onNewPublishSuccess = refreshDocumentSharing;
|
buttonShare.onNewPublishSuccess = refreshDocumentSharing;
|
||||||
sharingButton.onPublishRemoved = refreshDocumentSharing;
|
buttonShare.onPublishRemoved = refreshDocumentSharing;
|
||||||
|
|
||||||
return sharingButton;
|
return buttonShare;
|
||||||
|
|
||||||
});
|
});
|
55
js/extensions/button-sync.js
Normal file
55
js/extensions/button-sync.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
|
var buttonSync = {
|
||||||
|
extensionId: "buttonSync",
|
||||||
|
extensionName: 'Button "Synchronize"',
|
||||||
|
optional: true,
|
||||||
|
settingsBloc: '<p>Adds a "Synchronize documents" button in the navigation bar.</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
var syncRunning = false;
|
||||||
|
var uploadPending = false;
|
||||||
|
var isOffline = false;
|
||||||
|
// Enable/disable the button
|
||||||
|
function updateButtonState() {
|
||||||
|
if(syncRunning === true || uploadPending === false || isOffline) {
|
||||||
|
$(".action-force-sync").addClass("disabled");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$(".action-force-sync").removeClass("disabled");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonSync.onSyncRunning = function(isRunning) {
|
||||||
|
syncRunning = isRunning;
|
||||||
|
uploadPending = true;
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonSync.onSyncSuccess = function() {
|
||||||
|
uploadPending = false;
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonSync.onOfflineChanged = function(isOfflineParameter) {
|
||||||
|
isOffline = isOfflineParameter;
|
||||||
|
updateButtonState();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check that a file has synchronized locations
|
||||||
|
var checkSynchronization = function(fileDesc) {
|
||||||
|
if(_.size(fileDesc.syncLocations) !== 0) {
|
||||||
|
uploadPending = true;
|
||||||
|
updateButtonState();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
buttonSync.onFileChanged = checkSynchronization;
|
||||||
|
buttonSync.onTitleChanged = checkSynchronization;
|
||||||
|
|
||||||
|
return buttonSync;
|
||||||
|
|
||||||
|
});
|
@ -1,64 +1,75 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var documentSelector = {
|
var documentSelector = {
|
||||||
extensionId: "documentSelector",
|
extensionId: "documentSelector",
|
||||||
extensionName: "Document selector",
|
extensionName: "Document selector",
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Builds the "Open document" dropdown menu.</p>'
|
||||||
'<p>Builds the "Open document" dropdown menu.</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileSystemDescriptor = undefined;
|
var fileSystem = undefined;
|
||||||
documentSelector.onFileSystemLoaded = function(fileSystemDescriptorParameter) {
|
documentSelector.onFileSystemCreated = function(fileSystemParameter) {
|
||||||
fileSystemDescriptor = fileSystemDescriptorParameter;
|
fileSystem = fileSystemParameter;
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileDesc = undefined;
|
var fileMgr = undefined;
|
||||||
var updateSelector = function() {
|
documentSelector.onFileMgrCreated = function(fileMgrParameter) {
|
||||||
var sortedDescriptor = _.sortBy(fileSystemDescriptor, function(fileDesc) {
|
fileMgr = fileMgrParameter;
|
||||||
return fileDesc.title.toLowerCase();
|
};
|
||||||
});
|
|
||||||
|
var liMap = undefined;
|
||||||
|
var buildSelector = function() {
|
||||||
|
|
||||||
function composeTitle(fileDesc) {
|
function composeTitle(fileDesc) {
|
||||||
var result = [];
|
var result = [];
|
||||||
var syncAttributesList = _.values(fileDesc.syncLocations);
|
var syncAttributesList = _.values(fileDesc.syncLocations);
|
||||||
var publishAttributesList = _.values(fileDesc.publishLocations);
|
var publishAttributesList = _.values(fileDesc.publishLocations);
|
||||||
var attributesList = syncAttributesList.concat(publishAttributesList);
|
var attributesList = syncAttributesList.concat(publishAttributesList);
|
||||||
_.chain(attributesList).sortBy(function(attributes) {
|
_.chain(attributesList).sortBy(function(attributes) {
|
||||||
return attributes.provider;
|
return attributes.provider.providerId;
|
||||||
}).each(function(attributes) {
|
}).each(function(attributes) {
|
||||||
result.push('<i class="icon-' + attributes.provider + '"></i>');
|
result.push('<i class="icon-' + attributes.provider.providerId + '"></i>');
|
||||||
});
|
});
|
||||||
result.push(" ");
|
result.push(" ");
|
||||||
result.push(fileDesc.title);
|
result.push(fileDesc.title);
|
||||||
return result.join("");
|
return result.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
liMap = {};
|
||||||
$("#file-selector li:not(.stick)").empty();
|
$("#file-selector li:not(.stick)").empty();
|
||||||
_.each(sortedDescriptor, function(fileDescToPrint) {
|
_.chain(
|
||||||
var a = $("<a>").html(composeTitle(fileDescToPrint.fileIndex));
|
fileSystem
|
||||||
|
).sortBy(function(fileDesc) {
|
||||||
|
return fileDesc.title.toLowerCase();
|
||||||
|
}).each(function(fileDesc) {
|
||||||
|
var a = $('<a href="#">').html(composeTitle(fileDesc)).click(function() {
|
||||||
|
if(liMap[fileDesc.fileIndex].is(".disabled")) {
|
||||||
|
fileMgr.selectFile(fileDesc);
|
||||||
|
}
|
||||||
|
});
|
||||||
var li = $("<li>").append(a);
|
var li = $("<li>").append(a);
|
||||||
if (fileDescToPrint === fileDesc) {
|
liMap[fileDesc.fileIndex] = li;
|
||||||
li.addClass("disabled");
|
|
||||||
} else {
|
|
||||||
a.prop("href", "#").click(function() {
|
|
||||||
fileManager.selectFile(fileDescToPrint);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
$("#file-selector").append(li);
|
$("#file-selector").append(li);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
documentSelector.onFileSelected = function(fileDescParameter) {
|
documentSelector.onFileSelected = function(fileDesc) {
|
||||||
fileDesc = fileDescParameter;
|
if(liMap === undefined) {
|
||||||
updateSelector();
|
buildSelector();
|
||||||
|
}
|
||||||
|
$("#file-selector li:not(.stick)").removeClass("disabled");
|
||||||
|
liMap[fileDesc.fileIndex].addClass("disabled");
|
||||||
};
|
};
|
||||||
|
|
||||||
documentSelector.onTitleChanged = updateSelector;
|
documentSelector.onFileCreated = buildSelector;
|
||||||
documentSelector.onSyncExportSuccess = updateSelector;
|
documentSelector.onFileDeleted = buildSelector;
|
||||||
documentSelector.onSyncRemoved = updateSelector;
|
documentSelector.onTitleChanged = buildSelector;
|
||||||
documentSelector.onNewPublishSuccess = updateSelector;
|
documentSelector.onSyncExportSuccess = buildSelector;
|
||||||
documentSelector.onPublishRemoved = updateSelector;
|
documentSelector.onSyncRemoved = buildSelector;
|
||||||
|
documentSelector.onNewPublishSuccess = buildSelector;
|
||||||
|
documentSelector.onPublishRemoved = buildSelector;
|
||||||
|
|
||||||
return documentSelector;
|
return documentSelector;
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var documentTitle = {
|
var documentTitle = {
|
||||||
extensionId: "documentTitle",
|
extensionId: "documentTitle",
|
||||||
extensionName: "Document title",
|
extensionName: "Document title",
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Responsible for showing the document title in the navigation bar.</p>'
|
||||||
'<p>Responsible for showing the document title in the navigation bar.</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var layout = undefined;
|
var layout = undefined;
|
||||||
@ -15,7 +16,7 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
|
|
||||||
var fileDesc = undefined;
|
var fileDesc = undefined;
|
||||||
var updateTitle = function(fileDescParameter) {
|
var updateTitle = function(fileDescParameter) {
|
||||||
if(fileDescParameter !== undefined && fileDescParameter !== fileDesc) {
|
if(fileDescParameter !== fileDesc) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,9 +26,9 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
var publishAttributesList = _.values(fileDesc.publishLocations);
|
var publishAttributesList = _.values(fileDesc.publishLocations);
|
||||||
var attributesList = syncAttributesList.concat(publishAttributesList);
|
var attributesList = syncAttributesList.concat(publishAttributesList);
|
||||||
_.chain(attributesList).sortBy(function(attributes) {
|
_.chain(attributesList).sortBy(function(attributes) {
|
||||||
return attributes.provider;
|
return attributes.provider.providerId;
|
||||||
}).each(function(attributes) {
|
}).each(function(attributes) {
|
||||||
result.push('<i class="icon-' + attributes.provider + '"></i>');
|
result.push('<i class="icon-' + attributes.provider.providerId + '"></i>');
|
||||||
});
|
});
|
||||||
result.push(" ");
|
result.push(" ");
|
||||||
result.push(fileDesc.title);
|
result.push(fileDesc.title);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var managePublication = {
|
var managePublication = {
|
||||||
extensionId: "managePublication",
|
extensionId: "managePublication",
|
||||||
extensionName: "Manage Publication",
|
extensionName: "Manage Publication",
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Populates the "Manage publication" dialog box.</p>'
|
||||||
'<p>Populates the "Manage publication" dialog box.</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileManager = undefined;
|
var fileMgr = undefined;
|
||||||
manageSynchronization.onFileManagerCreated = function(fileManagerParameter) {
|
managePublication.onFileMgrCreated = function(fileMgrParameter) {
|
||||||
fileManager = fileManagerParameter;
|
fileMgr = fileMgrParameter;
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileDesc = undefined;
|
var fileDesc = undefined;
|
||||||
@ -46,7 +47,7 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
publishDesc: publishDesc
|
publishDesc: publishDesc
|
||||||
}));
|
}));
|
||||||
lineElement.append($(removeButtonTemplate).click(function() {
|
lineElement.append($(removeButtonTemplate).click(function() {
|
||||||
fileManager.removePublish(publishAttributes);
|
fileMgr.removePublish(publishAttributes);
|
||||||
}));
|
}));
|
||||||
publishList.append(lineElement);
|
publishList.append(lineElement);
|
||||||
});
|
});
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var manageSynchronization = {
|
var manageSynchronization = {
|
||||||
extensionId: "manageSynchronization",
|
extensionId: "manageSynchronization",
|
||||||
extensionName: "Manage Synchronization",
|
extensionName: "Manage Synchronization",
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Populates the "Manage synchronization" dialog box.</p>'
|
||||||
'<p>Populates the "Manage synchronization" dialog box.</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileManager = undefined;
|
var fileMgr = undefined;
|
||||||
manageSynchronization.onFileManagerCreated = function(fileManagerParameter) {
|
manageSynchronization.onFileMgrCreated = function(fileMgrParameter) {
|
||||||
fileManager = fileManagerParameter;
|
fileMgr = fileMgrParameter;
|
||||||
};
|
};
|
||||||
|
|
||||||
var fileDesc = undefined;
|
var fileDesc = undefined;
|
||||||
@ -42,7 +43,7 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
syncDesc: syncDesc
|
syncDesc: syncDesc
|
||||||
}));
|
}));
|
||||||
lineElement.append($(removeButtonTemplate).click(function() {
|
lineElement.append($(removeButtonTemplate).click(function() {
|
||||||
fileManager.removeSync(syncAttributes);
|
fileMgr.removeSync(syncAttributes);
|
||||||
}));
|
}));
|
||||||
syncList.append(lineElement);
|
syncList.append(lineElement);
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
define( [ "utils", "Markdown.Extra" ], function(utils) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"lib/Markdown.Extra"
|
||||||
|
], function(utils) {
|
||||||
|
|
||||||
var markdownExtra = {
|
var markdownExtra = {
|
||||||
extensionId: "markdownExtra",
|
extensionId: "markdownExtra",
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
define( [ "MathJax" ], function($) {
|
define([
|
||||||
|
"lib/MathJax"
|
||||||
|
], function() {
|
||||||
|
|
||||||
var mathJax = {
|
var mathJax = {
|
||||||
extensionId: "mathJax",
|
extensionId: "mathJax",
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define( [ "jquery", "jgrowl", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"jgrowl"
|
||||||
|
], function($, _, jGrowl) {
|
||||||
|
|
||||||
var notifications = {
|
var notifications = {
|
||||||
extensionId: "notifications",
|
extensionId: "notifications",
|
||||||
@ -6,15 +10,15 @@ define( [ "jquery", "jgrowl", "underscore" ], function($) {
|
|||||||
defaultConfig: {
|
defaultConfig: {
|
||||||
showingTime: 5000
|
showingTime: 5000
|
||||||
},
|
},
|
||||||
settingsBloc: "<p>Shows notification messages in the bottom-right corner of the screen.</p>"
|
settingsBloc: '<p>Shows notification messages in the bottom-right corner of the screen.</p>'
|
||||||
};
|
};
|
||||||
|
|
||||||
notifications.onReady = function() {
|
notifications.onReady = function() {
|
||||||
// jGrowl configuration
|
// jGrowl configuration
|
||||||
$.jGrowl.defaults.life = notifications.config.showingTime;
|
jGrowl.defaults.life = notifications.config.showingTime;
|
||||||
$.jGrowl.defaults.closer = false;
|
jGrowl.defaults.closer = false;
|
||||||
$.jGrowl.defaults.closeTemplate = '';
|
jGrowl.defaults.closeTemplate = '';
|
||||||
$.jGrowl.defaults.position = 'bottom-right';
|
jGrowl.defaults.position = 'bottom-right';
|
||||||
};
|
};
|
||||||
|
|
||||||
function showMessage(msg, iconClass, options) {
|
function showMessage(msg, iconClass, options) {
|
||||||
@ -30,15 +34,22 @@ define( [ "jquery", "jgrowl", "underscore" ], function($) {
|
|||||||
}
|
}
|
||||||
options = options || {};
|
options = options || {};
|
||||||
iconClass = iconClass || "icon-info-sign";
|
iconClass = iconClass || "icon-info-sign";
|
||||||
$.jGrowl("<i class='icon-white " + iconClass + "'></i> " + _.escape(msg), options);
|
jGrowl("<i class='icon-white " + iconClass + "'></i> " + _.escape(msg), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifications.onMessage = function(message) {
|
notifications.onMessage = function(message) {
|
||||||
|
console.log(message);
|
||||||
showMessage(message);
|
showMessage(message);
|
||||||
};
|
};
|
||||||
|
|
||||||
notifications.onError = function(error) {
|
notifications.onError = function(error) {
|
||||||
showMessage(error, "icon-warning-sign");
|
console.error(error);
|
||||||
|
if(_.isString(error)) {
|
||||||
|
showMessage(error, "icon-warning-sign");
|
||||||
|
}
|
||||||
|
else if(_.isObject(error)) {
|
||||||
|
showMessage(error.message, "icon-warning-sign");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
notifications.onOfflineChanged = function(isOffline) {
|
notifications.onOfflineChanged = function(isOffline) {
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"lib/css_browser_selector"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var scrollLink = {
|
var scrollLink = {
|
||||||
extensionId: "scrollLink",
|
extensionId: "scrollLink",
|
||||||
@ -7,8 +11,8 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
settingsBloc: [
|
settingsBloc: [
|
||||||
'<p>Binds together editor and preview scrollbars.</p>',
|
'<p>Binds together editor and preview scrollbars.</p>',
|
||||||
'<blockquote class="muted"><b>NOTE:</b> ',
|
'<blockquote class="muted"><b>NOTE:</b> ',
|
||||||
'The mapping between Markdown and HTML is based on the position of the title elements (h1, h2, ...) in the page. ',
|
'The mapping between Markdown and HTML is based on the position of the title elements (h1, h2, ...) in the page. ',
|
||||||
'Therefore, if your document does not contain any title, the mapping will be linear and consequently less accurate.',
|
'Therefore, if your document does not contain any title, the mapping will be linear and consequently less accurate.',
|
||||||
'</bloquote>'
|
'</bloquote>'
|
||||||
].join("")
|
].join("")
|
||||||
};
|
};
|
||||||
|
@ -1,25 +1,16 @@
|
|||||||
define( [ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"utils"
|
||||||
|
], function($, _, utils) {
|
||||||
|
|
||||||
var toc = {
|
var toc = {
|
||||||
extensionId: "toc",
|
extensionId: "toc",
|
||||||
extensionName: "Table Of Content",
|
extensionName: "Table Of Content",
|
||||||
optional: true,
|
optional: true,
|
||||||
settingsBloc: [
|
settingsBloc: '<p>Generates tables of content using the marker [TOC].</p>'
|
||||||
'<p>Generates tables of content using the marker [TOC].</p>'
|
|
||||||
].join("")
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used to generate an anchor
|
|
||||||
function slugify(text)
|
|
||||||
{
|
|
||||||
return text.toLowerCase()
|
|
||||||
.replace(/\s+/g, '-') // Replace spaces with -
|
|
||||||
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
|
|
||||||
.replace(/\-\-+/g, '-') // Replace multiple - with single -
|
|
||||||
.replace(/^-+/, '') // Trim - from start of text
|
|
||||||
.replace(/-+$/, ''); // Trim - from end of text
|
|
||||||
}
|
|
||||||
|
|
||||||
// TOC element description
|
// TOC element description
|
||||||
function TocElement(tagName, anchor, text) {
|
function TocElement(tagName, anchor, text) {
|
||||||
this.tagName = tagName;
|
this.tagName = tagName;
|
||||||
@ -83,7 +74,7 @@ define( [ "jquery", "underscore" ], function($) {
|
|||||||
function buildToc() {
|
function buildToc() {
|
||||||
var anchorList = {};
|
var anchorList = {};
|
||||||
function createAnchor(element) {
|
function createAnchor(element) {
|
||||||
var id = element.prop("id") || slugify(element.text());
|
var id = element.prop("id") || utils.slugify(element.text());
|
||||||
var anchor = id;
|
var anchor = id;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
while(_.has(anchorList, anchor)) {
|
while(_.has(anchorList, anchor)) {
|
||||||
|
24
js/extensions/working-indicator.js
Normal file
24
js/extensions/working-indicator.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
|
var workingIndicator = {
|
||||||
|
extensionId: "workingIndicator",
|
||||||
|
extensionName: "Working indicator",
|
||||||
|
settingsBloc: '<p>Displays an animated image when a network operation is running.</p>'
|
||||||
|
};
|
||||||
|
|
||||||
|
workingIndicator.onAsyncRunning = function(isRunning) {
|
||||||
|
if (isRunning === false) {
|
||||||
|
$(".working-indicator").removeClass("show");
|
||||||
|
$("body").removeClass("working");
|
||||||
|
} else {
|
||||||
|
$(".working-indicator").addClass("show");
|
||||||
|
$("body").addClass("working");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return workingIndicator;
|
||||||
|
|
||||||
|
});
|
@ -1,53 +1,30 @@
|
|||||||
define([
|
define([
|
||||||
"jquery",
|
"jquery",
|
||||||
|
"underscore",
|
||||||
"core",
|
"core",
|
||||||
"utils",
|
"utils",
|
||||||
|
"settings",
|
||||||
"extension-manager",
|
"extension-manager",
|
||||||
"synchronizer",
|
"file-system",
|
||||||
"publisher",
|
"lib/text!../WELCOME.md"
|
||||||
"sharing",
|
], function($, _, core, utils, settings, extensionMgr, fileSystem, welcomeContent) {
|
||||||
"text!../WELCOME.md",
|
|
||||||
"underscore"
|
|
||||||
], function($, core, utils, extensionManager, synchronizer, publisher, sharing, welcomeContent) {
|
|
||||||
|
|
||||||
var fileManager = {};
|
var fileMgr = {};
|
||||||
|
|
||||||
// Load file descriptors from localStorage and store in a map
|
|
||||||
var fileSystemDescriptor = _.chain(localStorage["file.list"].split(";"))
|
|
||||||
.compact()
|
|
||||||
.reduce(function(fileSystemDescriptor, fileIndex) {
|
|
||||||
var title = localStorage[fileIndex + ".title"];
|
|
||||||
var fileDesc = {
|
|
||||||
fileIndex : fileIndex,
|
|
||||||
title : title,
|
|
||||||
syncLocations: {},
|
|
||||||
publishLocations: {}
|
|
||||||
};
|
|
||||||
synchronizer.populateSyncLocations(fileDesc),
|
|
||||||
publisher.populatePublishLocations(fileDesc),
|
|
||||||
fileSystemDescriptor[fileIndex] = fileDesc;
|
|
||||||
return fileSystemDescriptor;
|
|
||||||
}, {})
|
|
||||||
.value();
|
|
||||||
extensionManager.onFileSystemLoaded(fileSystemDescriptor);
|
|
||||||
fileManager.getFileList = function() {
|
|
||||||
return _.values(fileSystemDescriptor);
|
|
||||||
};
|
|
||||||
|
|
||||||
// Defines the current file
|
// Defines the current file
|
||||||
var currentFile = (function() {
|
var currentFile = (function() {
|
||||||
var currentFileIndex = localStorage["file.current"];
|
var fileIndex = localStorage["file.current"];
|
||||||
if(currentFileIndex !== undefined) {
|
if(fileIndex !== undefined) {
|
||||||
return fileSystemDescriptor[currentFileIndex];
|
return fileSystem[fileIndex];
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
fileManager.getCurrentFile = function() {
|
fileMgr.getCurrentFile = function() {
|
||||||
return currentFile;
|
return currentFile;
|
||||||
};
|
};
|
||||||
fileManager.isCurrentFile = function(fileDesc) {
|
fileMgr.isCurrentFile = function(fileDesc) {
|
||||||
return fileDesc === currentFile;
|
return fileDesc === currentFile;
|
||||||
};
|
};
|
||||||
fileManager.setCurrentFile = function(fileDesc) {
|
fileMgr.setCurrentFile = function(fileDesc) {
|
||||||
currentFile = fileDesc;
|
currentFile = fileDesc;
|
||||||
if(fileDesc === undefined) {
|
if(fileDesc === undefined) {
|
||||||
localStorage.removeItem("file.current");
|
localStorage.removeItem("file.current");
|
||||||
@ -58,24 +35,21 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Caution: this function recreate the editor (reset undo operations)
|
// Caution: this function recreate the editor (reset undo operations)
|
||||||
fileManager.selectFile = function(fileDesc) {
|
fileMgr.selectFile = function(fileDesc) {
|
||||||
|
var fileSystemSize = _.size(fileSystem);
|
||||||
// If no file create one
|
// If no file create one
|
||||||
if (_.size(fileSystemDescriptor) === 0) {
|
if (_.size(fileSystem) === 0) {
|
||||||
fileDesc = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
|
fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fileDesc === undefined) {
|
if(fileDesc === undefined) {
|
||||||
// If no file is selected take the last created
|
// If no file is selected take the last created
|
||||||
fileDesc = fileSystemDescriptor[_.keys(fileSystemDescriptor)[fileSystemDescriptor.length - 1]];
|
fileDesc = fileSystem[_.keys(fileSystem)[fileSystemSize - 1]];
|
||||||
}
|
}
|
||||||
fileManager.setCurrentFile(fileDesc);
|
fileMgr.setCurrentFile(fileDesc);
|
||||||
|
|
||||||
// Update the file titles
|
|
||||||
fileManager.updateFileTitles();
|
|
||||||
publisher.notifyPublish();
|
|
||||||
|
|
||||||
// Notify extensions
|
// Notify extensions
|
||||||
extensionManager.onFileSelected(fileDesc);
|
extensionMgr.onFileSelected(fileDesc);
|
||||||
|
|
||||||
// Hide the viewer pencil button
|
// Hide the viewer pencil button
|
||||||
if(fileDesc.fileIndex == TEMPORARY_FILE_INDEX) {
|
if(fileDesc.fileIndex == TEMPORARY_FILE_INDEX) {
|
||||||
@ -89,18 +63,18 @@ define([
|
|||||||
$("#wmd-input").val(localStorage[fileDesc.fileIndex + ".content"]);
|
$("#wmd-input").val(localStorage[fileDesc.fileIndex + ".content"]);
|
||||||
core.createEditor(function() {
|
core.createEditor(function() {
|
||||||
// Callback to save content when textarea changes
|
// Callback to save content when textarea changes
|
||||||
fileManager.saveFile();
|
fileMgr.saveFile();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
fileManager.createFile = function(title, content, syncLocations, isTemporary) {
|
fileMgr.createFile = function(title, content, syncLocations, isTemporary) {
|
||||||
content = content !== undefined ? content : core.settings.defaultContent;
|
content = content !== undefined ? content : settings.defaultContent;
|
||||||
syncLocations = syncLocations || {};
|
syncLocations = syncLocations || {};
|
||||||
if (!title) {
|
if (!title) {
|
||||||
// Create a file title
|
// Create a file title
|
||||||
title = DEFAULT_FILE_TITLE;
|
title = DEFAULT_FILE_TITLE;
|
||||||
var indicator = 2;
|
var indicator = 2;
|
||||||
while(_.some(fileSystemDescriptor, function(fileDesc) {
|
while(_.some(fileSystem, function(fileDesc) {
|
||||||
return fileDesc.title == title;
|
return fileDesc.title == title;
|
||||||
})) {
|
})) {
|
||||||
title = DEFAULT_FILE_TITLE + indicator++;
|
title = DEFAULT_FILE_TITLE + indicator++;
|
||||||
@ -112,7 +86,7 @@ define([
|
|||||||
if(!isTemporary) {
|
if(!isTemporary) {
|
||||||
do {
|
do {
|
||||||
fileIndex = "file." + utils.randomString();
|
fileIndex = "file." + utils.randomString();
|
||||||
} while(_.has(fileSystemDescriptor, fileIndex));
|
} while(_.has(fileSystem, fileIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the file in the localStorage
|
// Create the file in the localStorage
|
||||||
@ -137,27 +111,27 @@ define([
|
|||||||
// Add the index to the file list
|
// Add the index to the file list
|
||||||
if(!isTemporary) {
|
if(!isTemporary) {
|
||||||
localStorage["file.list"] += fileIndex + ";";
|
localStorage["file.list"] += fileIndex + ";";
|
||||||
fileSystemDescriptor[fileIndex] = fileDesc;
|
fileSystem[fileIndex] = fileDesc;
|
||||||
extensionManager.onFileCreated(fileDesc);
|
extensionMgr.onFileCreated(fileDesc);
|
||||||
}
|
}
|
||||||
return fileDesc;
|
return fileDesc;
|
||||||
};
|
};
|
||||||
|
|
||||||
fileManager.deleteFile = function(fileDesc) {
|
fileMgr.deleteFile = function(fileDesc) {
|
||||||
fileDesc = fileDesc || fileManager.getCurrentFile();
|
fileDesc = fileDesc || fileMgr.getCurrentFile();
|
||||||
if(fileManager.isCurrentFile(fileDesc)) {
|
if(fileMgr.isCurrentFile(fileDesc)) {
|
||||||
// Unset the current fileDesc
|
// Unset the current fileDesc
|
||||||
fileManager.setCurrentFile();
|
fileMgr.setCurrentFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove synchronized locations
|
// Remove synchronized locations
|
||||||
_.each(fileDesc.syncLocations, function(syncAttributes) {
|
_.each(fileDesc.syncLocations, function(syncAttributes) {
|
||||||
fileManager.removeSync(syncAttributes, true);
|
fileMgr.removeSync(syncAttributes, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove publish locations
|
// Remove publish locations
|
||||||
_.each(fileDesc.publishLocations, function(publishAttributes) {
|
_.each(fileDesc.publishLocations, function(publishAttributes) {
|
||||||
fileManager.removePublish(publishAttributes, true);
|
fileMgr.removePublish(publishAttributes, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Remove the index from the file list
|
// Remove the index from the file list
|
||||||
@ -168,30 +142,29 @@ define([
|
|||||||
localStorage.removeItem(fileIndex + ".content");
|
localStorage.removeItem(fileIndex + ".content");
|
||||||
localStorage.removeItem(fileIndex + ".sync");
|
localStorage.removeItem(fileIndex + ".sync");
|
||||||
localStorage.removeItem(fileIndex + ".publish");
|
localStorage.removeItem(fileIndex + ".publish");
|
||||||
fileSystemDescriptor.removeItem(fileIndex);
|
fileSystem.removeItem(fileIndex);
|
||||||
extensionManager.onFileDeleted(fileDesc);
|
extensionMgr.onFileDeleted(fileDesc);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Save current file in localStorage
|
// Save current file in localStorage
|
||||||
fileManager.saveFile = function() {
|
fileMgr.saveFile = function() {
|
||||||
var content = $("#wmd-input").val();
|
var content = $("#wmd-input").val();
|
||||||
var fileDesc = fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
localStorage[fileDesc.fileIndex + ".content"] = content;
|
localStorage[fileDesc.fileIndex + ".content"] = content;
|
||||||
extensionManager.onFileChanged(fileDesc);
|
extensionMgr.onFileChanged(fileDesc);
|
||||||
synchronizer.notifyChange(fileDesc);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add a synchronized location to a file
|
// Add a synchronized location to a file
|
||||||
fileManager.addSync = function(fileDesc, syncAttributes) {
|
fileMgr.addSync = function(fileDesc, syncAttributes) {
|
||||||
localStorage[fileDesc.fileIndex + ".sync"] += syncAttributes.syncIndex + ";";
|
localStorage[fileDesc.fileIndex + ".sync"] += syncAttributes.syncIndex + ";";
|
||||||
fileDesc.syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
fileDesc.syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||||
// addSync is only used for export, not for import
|
// addSync is only used for export, not for import
|
||||||
extensionManager.onSyncExportSuccess(fileDesc, syncAttributes);
|
extensionMgr.onSyncExportSuccess(fileDesc, syncAttributes);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove a synchronized location
|
// Remove a synchronized location
|
||||||
fileManager.removeSync = function(syncAttributes, skipExtensions) {
|
fileMgr.removeSync = function(syncAttributes, skipExtensions) {
|
||||||
var fileDesc = fileManager.getFileFromSyncIndex(syncAttributes.syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncAttributes.syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
localStorage[fileDesc.fileIndex + ".sync"] = localStorage[fileDesc.fileIndex + ".sync"].replace(";"
|
localStorage[fileDesc.fileIndex + ".sync"] = localStorage[fileDesc.fileIndex + ".sync"].replace(";"
|
||||||
+ syncAttributes.syncIndex + ";", ";");
|
+ syncAttributes.syncIndex + ";", ";");
|
||||||
@ -200,26 +173,26 @@ define([
|
|||||||
localStorage.removeItem(syncAttributes.syncIndex);
|
localStorage.removeItem(syncAttributes.syncIndex);
|
||||||
fileDesc.syncLocations.removeItem(syncIndex);
|
fileDesc.syncLocations.removeItem(syncIndex);
|
||||||
if(!skipExtensions) {
|
if(!skipExtensions) {
|
||||||
extensionManager.onSyncRemoved(fileDesc, syncAttributes);
|
extensionMgr.onSyncRemoved(fileDesc, syncAttributes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the file descriptor associated to a syncIndex
|
// Get the file descriptor associated to a syncIndex
|
||||||
fileManager.getFileFromSyncIndex = function(syncIndex) {
|
fileMgr.getFileFromSyncIndex = function(syncIndex) {
|
||||||
return _.find(fileSystemDescriptor, function(fileDesc) {
|
return _.find(fileSystem, function(fileDesc) {
|
||||||
return _.has(fileDesc.syncLocations, syncIndex);
|
return _.has(fileDesc.syncLocations, syncIndex);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get syncAttributes from syncIndex
|
// Get syncAttributes from syncIndex
|
||||||
fileManager.getSyncAttributes = function(syncIndex) {
|
fileMgr.getSyncAttributes = function(syncIndex) {
|
||||||
var fileDesc = fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
return fileDesc && fileDesc.syncLocations[syncIndex];
|
return fileDesc && fileDesc.syncLocations[syncIndex];
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true if provider has locations to synchronize
|
// Returns true if provider has locations to synchronize
|
||||||
fileManager.hasSync = function(provider) {
|
fileMgr.hasSync = function(provider) {
|
||||||
return _.some(fileSystemDescriptor, function(fileDesc) {
|
return _.some(fileSystem, function(fileDesc) {
|
||||||
return _.some(fileDesc.syncLocations, function(syncAttributes) {
|
return _.some(fileDesc.syncLocations, function(syncAttributes) {
|
||||||
syncAttributes.provider == provider.providerId;
|
syncAttributes.provider == provider.providerId;
|
||||||
});
|
});
|
||||||
@ -227,33 +200,30 @@ define([
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Add a publishIndex (publish location) to a file
|
// Add a publishIndex (publish location) to a file
|
||||||
fileManager.addPublish = function(fileDesc, publishAttributes) {
|
fileMgr.addPublish = function(fileDesc, publishAttributes) {
|
||||||
localStorage[fileDesc.fileIndex + ".publish"] += publishAttributes.publishIndex + ";";
|
localStorage[fileDesc.fileIndex + ".publish"] += publishAttributes.publishIndex + ";";
|
||||||
fileDesc.publishLocations[publishAttributes.publishIndex] = publishAttributes;
|
fileDesc.publishLocations[publishAttributes.publishIndex] = publishAttributes;
|
||||||
extensionManager.onNewPublishSuccess(fileDesc, publishAttributes);
|
extensionMgr.onNewPublishSuccess(fileDesc, publishAttributes);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove a publishIndex (publish location)
|
// Remove a publishIndex (publish location)
|
||||||
fileManager.removePublish = function(publishAttributes, skipExtensions) {
|
fileMgr.removePublish = function(publishAttributes, skipExtensions) {
|
||||||
var fileDesc = fileManager.getFileFromPublish(publishAttributes.publishIndex);
|
var fileDesc = fileMgr.getFileFromPublish(publishAttributes.publishIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
localStorage[fileDesc.fileIndex + ".publish"] = localStorage[fileDesc.fileIndex + ".publish"].replace(";"
|
localStorage[fileDesc.fileIndex + ".publish"] = localStorage[fileDesc.fileIndex + ".publish"].replace(";"
|
||||||
+ publishAttributes.publishIndex + ";", ";");
|
+ publishAttributes.publishIndex + ";", ";");
|
||||||
if(fileManager.isCurrentFile(fileDesc)) {
|
|
||||||
publisher.notifyPublish();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// Remove publish attributes
|
// Remove publish attributes
|
||||||
localStorage.removeItem(publishAttributes.publishIndex);
|
localStorage.removeItem(publishAttributes.publishIndex);
|
||||||
fileDesc.publishLocations.removeItem(publishIndex);
|
fileDesc.publishLocations.removeItem(publishIndex);
|
||||||
if(!skipExtensions) {
|
if(!skipExtensions) {
|
||||||
extensionManager.onPublishRemoved(fileDesc, publishAttributes);
|
extensionMgr.onPublishRemoved(fileDesc, publishAttributes);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get the file descriptor associated to a publishIndex
|
// Get the file descriptor associated to a publishIndex
|
||||||
fileManager.getFileFromPublish = function(publishIndex) {
|
fileMgr.getFileFromPublish = function(publishIndex) {
|
||||||
return _.find(fileSystemDescriptor, function(fileDesc) {
|
return _.find(fileSystem, function(fileDesc) {
|
||||||
return _.has(fileDesc.publishLocations, publishIndex);
|
return _.has(fileDesc.publishLocations, publishIndex);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -276,11 +246,12 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
core.onReady(function() {
|
core.onReady(function() {
|
||||||
fileManager.selectFile();
|
|
||||||
|
fileMgr.selectFile();
|
||||||
|
|
||||||
$(".action-create-file").click(function() {
|
$(".action-create-file").click(function() {
|
||||||
var fileDesc = fileManager.createFile();
|
var fileDesc = fileMgr.createFile();
|
||||||
fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
var wmdInput = $("#wmd-input").focus().get(0);
|
var wmdInput = $("#wmd-input").focus().get(0);
|
||||||
if(wmdInput.setSelectionRange) {
|
if(wmdInput.setSelectionRange) {
|
||||||
wmdInput.setSelectionRange(0, 0);
|
wmdInput.setSelectionRange(0, 0);
|
||||||
@ -288,8 +259,8 @@ define([
|
|||||||
$("#file-title").click();
|
$("#file-title").click();
|
||||||
});
|
});
|
||||||
$(".action-remove-file").click(function() {
|
$(".action-remove-file").click(function() {
|
||||||
fileManager.deleteFile();
|
fileMgr.deleteFile();
|
||||||
fileManager.selectFile();
|
fileMgr.selectFile();
|
||||||
});
|
});
|
||||||
$("#file-title").click(function() {
|
$("#file-title").click(function() {
|
||||||
if(viewerMode === true) {
|
if(viewerMode === true) {
|
||||||
@ -305,15 +276,13 @@ define([
|
|||||||
input.hide();
|
input.hide();
|
||||||
$("#file-title").show();
|
$("#file-title").show();
|
||||||
var title = $.trim(input.val());
|
var title = $.trim(input.val());
|
||||||
var fileDesc = fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
var fileIndexTitle = fileDesc.fileIndex + ".title";
|
var fileIndexTitle = fileDesc.fileIndex + ".title";
|
||||||
if (title) {
|
if (title) {
|
||||||
if (title != localStorage[fileIndexTitle]) {
|
if (title != localStorage[fileIndexTitle]) {
|
||||||
localStorage[fileIndexTitle] = title;
|
localStorage[fileIndexTitle] = title;
|
||||||
fileDesc.title = title;
|
fileDesc.title = title;
|
||||||
fileManager.updateFileTitles();
|
extensionMgr.onTitleChanged(fileDesc);
|
||||||
synchronizer.notifyChange(fileDesc);
|
|
||||||
extensionManager.onTitleChanged(fileDesc);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
input.val(localStorage[fileIndexTitle]);
|
input.val(localStorage[fileIndexTitle]);
|
||||||
@ -346,33 +315,17 @@ define([
|
|||||||
});
|
});
|
||||||
$(".action-edit-document").click(function() {
|
$(".action-edit-document").click(function() {
|
||||||
var content = $("#wmd-input").val();
|
var content = $("#wmd-input").val();
|
||||||
var title = fileManager.getCurrentFile().title;
|
var title = fileMgr.getCurrentFile().title;
|
||||||
var fileDesc = fileManager.createFile(title, content);
|
var fileDesc = fileMgr.createFile(title, content);
|
||||||
fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
window.location.href = ".";
|
window.location.href = ".";
|
||||||
});
|
});
|
||||||
$(".action-download-md").click(function() {
|
|
||||||
var content = $("#wmd-input").val();
|
|
||||||
var title = fileManager.getCurrentFile().title;
|
|
||||||
core.saveFile(content, title + ".md");
|
|
||||||
});
|
|
||||||
$(".action-download-html").click(function() {
|
|
||||||
var content = $("#wmd-preview").html();
|
|
||||||
var title = fileManager.getCurrentFile().title;
|
|
||||||
core.saveFile(content, title + ".html");
|
|
||||||
});
|
|
||||||
$(".action-download-template").click(function() {
|
|
||||||
var content = publisher.applyTemplate();
|
|
||||||
var title = fileManager.getCurrentFile().title;
|
|
||||||
core.saveFile(content, title + ".txt");
|
|
||||||
});
|
|
||||||
$(".action-welcome-file").click(function() {
|
$(".action-welcome-file").click(function() {
|
||||||
var fileDesc = fileManager.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
|
var fileDesc = fileMgr.createFile(WELCOME_DOCUMENT_TITLE, welcomeContent);
|
||||||
fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
core.setFileManager(fileManager);
|
extensionMgr.onFileMgrCreated(fileMgr);
|
||||||
extensionManager.onFileManagerCreated(fileManager);
|
return fileMgr;
|
||||||
return fileManager;
|
|
||||||
});
|
});
|
||||||
|
22
js/file-system.js
Normal file
22
js/file-system.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
define([
|
||||||
|
"underscore",
|
||||||
|
"extension-manager"
|
||||||
|
], function(_, extensionMgr) {
|
||||||
|
|
||||||
|
var fileSystem = {};
|
||||||
|
|
||||||
|
// Load file descriptors from localStorage
|
||||||
|
_.chain(
|
||||||
|
localStorage["file.list"].split(";")
|
||||||
|
).compact().each(function(fileIndex) {
|
||||||
|
fileSystem[fileIndex] = {
|
||||||
|
fileIndex : fileIndex,
|
||||||
|
title : localStorage[fileIndex + ".title"],
|
||||||
|
syncLocations: {},
|
||||||
|
publishLocations: {}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
extensionMgr.onFileSystemCreated(fileSystem);
|
||||||
|
|
||||||
|
return fileSystem;
|
||||||
|
});
|
@ -1,4 +1,11 @@
|
|||||||
define(["core", "utils", "extension-manager", "google-helper", "underscore"], function(core, utils, extensionManager, googleHelper) {
|
define([
|
||||||
|
"underscore",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"file-manager",
|
||||||
|
"google-helper"
|
||||||
|
], function(_, core, utils, extensionMgr, fileMgr, googleHelper) {
|
||||||
|
|
||||||
var PROVIDER_GDRIVE = "gdrive";
|
var PROVIDER_GDRIVE = "gdrive";
|
||||||
|
|
||||||
@ -39,11 +46,11 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
||||||
var syncLocations = {};
|
var syncLocations = {};
|
||||||
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||||
var fileDesc = core.fileManager.createFile(file.title, file.content, syncLocations);
|
var fileDesc = fileMgr.createFile(file.title, file.content, syncLocations);
|
||||||
core.fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
fileDescList.push(fileDesc);
|
fileDescList.push(fileDesc);
|
||||||
});
|
});
|
||||||
extensionManager.onSyncImportSuccess(fileDescList, gdriveProvider);
|
extensionMgr.onSyncImportSuccess(fileDescList, gdriveProvider);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -56,9 +63,9 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
var importIds = [];
|
var importIds = [];
|
||||||
_.each(ids, function(id) {
|
_.each(ids, function(id) {
|
||||||
var syncIndex = createSyncIndex(id);
|
var syncIndex = createSyncIndex(id);
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
core.showError('"' + fileDesc.title + '" was already imported');
|
extensionMgr.onError('"' + fileDesc.title + '" was already imported');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
importIds.push(id);
|
importIds.push(id);
|
||||||
@ -87,9 +94,9 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
}
|
}
|
||||||
// Check that file is not synchronized with an other one
|
// Check that file is not synchronized with an other one
|
||||||
var syncIndex = createSyncIndex(id);
|
var syncIndex = createSyncIndex(id);
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
core.showError('File ID is already synchronized with "' + fileDesc.title + '"');
|
extensionMgr.onError('File ID is already synchronized with "' + fileDesc.title + '"');
|
||||||
callback(true);
|
callback(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -134,7 +141,7 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
var interestingChanges = [];
|
var interestingChanges = [];
|
||||||
_.each(changes, function(change) {
|
_.each(changes, function(change) {
|
||||||
var syncIndex = createSyncIndex(change.fileId);
|
var syncIndex = createSyncIndex(change.fileId);
|
||||||
var syncAttributes = core.fileManager.getSyncAttributes(syncIndex);
|
var syncAttributes = fileMgr.getSyncAttributes(syncIndex);
|
||||||
if(syncAttributes === undefined) {
|
if(syncAttributes === undefined) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -155,11 +162,10 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
callback(error);
|
callback(error);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var updateFileTitles = false;
|
|
||||||
_.each(changes, function(change) {
|
_.each(changes, function(change) {
|
||||||
var syncAttributes = change.syncAttributes;
|
var syncAttributes = change.syncAttributes;
|
||||||
var syncIndex = syncAttributes.syncIndex;
|
var syncIndex = syncAttributes.syncIndex;
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
// No file corresponding (file may have been deleted locally)
|
// No file corresponding (file may have been deleted locally)
|
||||||
if(fileDesc === undefined) {
|
if(fileDesc === undefined) {
|
||||||
return;
|
return;
|
||||||
@ -167,8 +173,8 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
var localTitle = fileDesc.title;
|
var localTitle = fileDesc.title;
|
||||||
// File deleted
|
// File deleted
|
||||||
if (change.deleted === true) {
|
if (change.deleted === true) {
|
||||||
core.showError('"' + localTitle + '" has been removed from Google Drive.');
|
extensionMgr.onError('"' + localTitle + '" has been removed from Google Drive.');
|
||||||
core.fileManager.removeSync(syncAttributes);
|
fileMgr.removeSync(syncAttributes);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle);
|
var localTitleChanged = syncAttributes.titleCRC != utils.crc32(localTitle);
|
||||||
@ -184,24 +190,23 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
// Conflict detection
|
// Conflict detection
|
||||||
if ((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true)
|
if ((fileTitleChanged === true && localTitleChanged === true && remoteTitleChanged === true)
|
||||||
|| (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) {
|
|| (fileContentChanged === true && localContentChanged === true && remoteContentChanged === true)) {
|
||||||
core.fileManager.createFile(localTitle + " (backup)", localContent);
|
var backupFileDesc = fileMgr.createFile(localTitle + " (backup)", localContent);
|
||||||
updateFileTitles = true;
|
extensionMgr.onTitleChanged(backupFileDesc);
|
||||||
core.showMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
extensionMgr.onMessage('Conflict detected on "' + localTitle + '". A backup has been created locally.');
|
||||||
}
|
}
|
||||||
// If file title changed
|
// If file title changed
|
||||||
if(fileTitleChanged && remoteTitleChanged === true) {
|
if(fileTitleChanged && remoteTitleChanged === true) {
|
||||||
localStorage[fileDesc.fileIndex + ".title"] = file.title;
|
localStorage[fileDesc.fileIndex + ".title"] = file.title;
|
||||||
fileDesc.title = file.title;
|
fileDesc.title = file.title;
|
||||||
updateFileTitles = true;
|
extensionMgr.onTitleChanged(fileDesc);
|
||||||
core.showMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
|
extensionMgr.onMessage('"' + localTitle + '" has been renamed to "' + file.title + '" on Google Drive.');
|
||||||
}
|
}
|
||||||
// If file content changed
|
// If file content changed
|
||||||
if(fileContentChanged && remoteContentChanged === true) {
|
if(fileContentChanged && remoteContentChanged === true) {
|
||||||
localStorage[fileDesc.fileIndex + ".content"] = file.content;
|
localStorage[fileDesc.fileIndex + ".content"] = file.content;
|
||||||
core.showMessage('"' + file.title + '" has been updated from Google Drive.');
|
extensionMgr.onMessage('"' + file.title + '" has been updated from Google Drive.');
|
||||||
if(core.fileManager.isCurrentFile(fileDesc)) {
|
if(fileMgr.isCurrentFile(fileDesc)) {
|
||||||
updateFileTitles = false; // Done by next function
|
fileMgr.selectFile(); // Refresh editor
|
||||||
core.fileManager.selectFile(); // Refresh editor
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Update syncAttributes
|
// Update syncAttributes
|
||||||
@ -210,9 +215,6 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
syncAttributes.titleCRC = remoteTitleCRC;
|
syncAttributes.titleCRC = remoteTitleCRC;
|
||||||
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
|
localStorage[syncIndex] = utils.serializeAttributes(syncAttributes);
|
||||||
});
|
});
|
||||||
if(updateFileTitles) {
|
|
||||||
extensionManager.onTitleChanged();
|
|
||||||
}
|
|
||||||
localStorage[PROVIDER_GDRIVE + ".lastChangeId"] = newChangeId;
|
localStorage[PROVIDER_GDRIVE + ".lastChangeId"] = newChangeId;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
@ -264,18 +266,18 @@ define(["core", "utils", "extension-manager", "google-helper", "underscore"], fu
|
|||||||
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
localStorage[syncAttributes.syncIndex] = utils.serializeAttributes(syncAttributes);
|
||||||
var syncLocations = {};
|
var syncLocations = {};
|
||||||
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
syncLocations[syncAttributes.syncIndex] = syncAttributes;
|
||||||
var fileDesc = core.fileManager.createFile(file.title, file.content, syncAttributes);
|
var fileDesc = fileMgr.createFile(file.title, file.content, syncAttributes);
|
||||||
core.fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
core.showMessage('"' + file.title + '" created successfully on Google Drive.');
|
extensionMgr.onMessage('"' + file.title + '" created successfully on Google Drive.');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else if (state.action == "open") {
|
else if (state.action == "open") {
|
||||||
var importIds = [];
|
var importIds = [];
|
||||||
_.each(state.ids, function(id) {
|
_.each(state.ids, function(id) {
|
||||||
var syncIndex = createSyncIndex(id);
|
var syncIndex = createSyncIndex(id);
|
||||||
var fileDesc = core.fileManager.getFileFromSyncIndex(syncIndex);
|
var fileDesc = fileMgr.getFileFromSyncIndex(syncIndex);
|
||||||
if(fileDesc !== undefined) {
|
if(fileDesc !== undefined) {
|
||||||
core.fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
importIds.push(id);
|
importIds.push(id);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
define(["utils", "github-helper"], function(utils, githubHelper) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"github-helper"
|
||||||
|
], function(utils, githubHelper) {
|
||||||
|
|
||||||
var PROVIDER_GIST = "gist";
|
var PROVIDER_GIST = "gist";
|
||||||
|
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, utils, extensionMgr, asyncRunner) {
|
||||||
|
|
||||||
var connected = undefined;
|
var connected = undefined;
|
||||||
var github = undefined;
|
var github = undefined;
|
||||||
@ -51,14 +57,14 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
task.chain();
|
task.chain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.showMessage("Please make sure the Github authorization popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Github authorization popup is not blocked by your browser.");
|
||||||
var errorMsg = "Failed to retrieve a token from GitHub.";
|
var errorMsg = "Failed to retrieve a token from GitHub.";
|
||||||
// We add time for user to enter his credentials
|
// We add time for user to enter his credentials
|
||||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||||
var code = undefined;
|
var code = undefined;
|
||||||
function getCode() {
|
function getCode() {
|
||||||
localStorage.removeItem("githubCode");
|
localStorage.removeItem("githubCode");
|
||||||
authWindow = core.popupWindow(
|
authWindow = utils.popupWindow(
|
||||||
'github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID,
|
'github-oauth-client.html?client_id=' + GITHUB_CLIENT_ID,
|
||||||
'stackedit-github-oauth', 960, 600);
|
'stackedit-github-oauth', 960, 600);
|
||||||
authWindow.focus();
|
authWindow.focus();
|
||||||
@ -106,7 +112,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
githubHelper.upload = function(reponame, branch, path, content, commitMsg, callback) {
|
githubHelper.upload = function(reponame, branch, path, content, commitMsg, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
authenticate(task);
|
authenticate(task);
|
||||||
@ -145,7 +150,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
githubHelper.uploadGist = function(gistId, filename, isPublic, title, content, callback) {
|
githubHelper.uploadGist = function(gistId, filename, isPublic, title, content, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
authenticate(task);
|
authenticate(task);
|
||||||
@ -184,7 +188,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
githubHelper.downloadGist = function(gistId, filename, callback) {
|
githubHelper.downloadGist = function(gistId, filename, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
// No need for authentication
|
// No need for authentication
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define(["core", "utils", "github-helper"], function(core, utils, githubHelper) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"settings",
|
||||||
|
"github-helper"
|
||||||
|
], function(utils, settings, githubHelper) {
|
||||||
|
|
||||||
var PROVIDER_GITHUB = "github";
|
var PROVIDER_GITHUB = "github";
|
||||||
|
|
||||||
@ -9,7 +13,7 @@ define(["core", "utils", "github-helper"], function(core, utils, githubHelper) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
githubProvider.publish = function(publishAttributes, title, content, callback) {
|
githubProvider.publish = function(publishAttributes, title, content, callback) {
|
||||||
var commitMsg = core.settings.commitMsg;
|
var commitMsg = settings.commitMsg;
|
||||||
githubHelper.upload(publishAttributes.repository, publishAttributes.branch,
|
githubHelper.upload(publishAttributes.repository, publishAttributes.branch,
|
||||||
publishAttributes.path, content, commitMsg, callback);
|
publishAttributes.path, content, commitMsg, callback);
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, utils, extensionMgr, asyncRunner) {
|
||||||
|
|
||||||
var connected = false;
|
var connected = false;
|
||||||
var authenticated = false;
|
var authenticated = false;
|
||||||
@ -44,7 +50,7 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
var immediate = true;
|
var immediate = true;
|
||||||
function localAuthenticate() {
|
function localAuthenticate() {
|
||||||
if (immediate === false) {
|
if (immediate === false) {
|
||||||
core.showMessage("Please make sure the Google authorization popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Google authorization popup is not blocked by your browser.");
|
||||||
// If not immediate we add time for user to enter his credentials
|
// If not immediate we add time for user to enter his credentials
|
||||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||||
}
|
}
|
||||||
@ -74,7 +80,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
}
|
}
|
||||||
|
|
||||||
googleHelper.upload = function(fileId, parentId, title, content, etag, callback) {
|
googleHelper.upload = function(fileId, parentId, title, content, etag, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = undefined;
|
var result = undefined;
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
@ -151,7 +156,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
};
|
};
|
||||||
|
|
||||||
googleHelper.checkChanges = function(lastChangeId, callback) {
|
googleHelper.checkChanges = function(lastChangeId, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var changes = [];
|
var changes = [];
|
||||||
var newChangeId = lastChangeId || 0;
|
var newChangeId = lastChangeId || 0;
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
@ -202,7 +206,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
};
|
};
|
||||||
|
|
||||||
googleHelper.downloadMetadata = function(ids, callback, skipAuth) {
|
googleHelper.downloadMetadata = function(ids, callback, skipAuth) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = [];
|
var result = [];
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
@ -255,7 +258,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
};
|
};
|
||||||
|
|
||||||
googleHelper.downloadContent = function(objects, callback, skipAuth) {
|
googleHelper.downloadContent = function(objects, callback, skipAuth) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var result = [];
|
var result = [];
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
// Add some time for user to choose his files
|
// Add some time for user to choose his files
|
||||||
@ -378,7 +380,6 @@ define(["jquery", "core", "utils", "async-runner"], function($, core, utils, asy
|
|||||||
}
|
}
|
||||||
|
|
||||||
googleHelper.picker = function(callback) {
|
googleHelper.picker = function(callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var ids = [];
|
var ids = [];
|
||||||
var picker = undefined;
|
var picker = undefined;
|
||||||
function hidePicker() {
|
function hidePicker() {
|
||||||
|
0
js/bootstrap.js → js/lib/bootstrap.js
vendored
0
js/bootstrap.js → js/lib/bootstrap.js
vendored
0
js/jquery-ui.js → js/lib/jquery-ui.js
vendored
0
js/jquery-ui.js → js/lib/jquery-ui.js
vendored
0
js/jquery.js → js/lib/jquery.js
vendored
0
js/jquery.js → js/lib/jquery.js
vendored
@ -1,5 +1,5 @@
|
|||||||
/** vim: et:ts=4:sw=4:sts=4
|
/** vim: et:ts=4:sw=4:sts=4
|
||||||
* @license RequireJS 2.1.5 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
* @license RequireJS 2.1.6 Copyright (c) 2010-2012, The Dojo Foundation All Rights Reserved.
|
||||||
* Available via the MIT or new BSD license.
|
* Available via the MIT or new BSD license.
|
||||||
* see: http://github.com/jrburke/requirejs for details
|
* see: http://github.com/jrburke/requirejs for details
|
||||||
*/
|
*/
|
||||||
@ -12,7 +12,7 @@ var requirejs, require, define;
|
|||||||
(function (global) {
|
(function (global) {
|
||||||
var req, s, head, baseElement, dataMain, src,
|
var req, s, head, baseElement, dataMain, src,
|
||||||
interactiveScript, currentlyAddingScript, mainScript, subPath,
|
interactiveScript, currentlyAddingScript, mainScript, subPath,
|
||||||
version = '2.1.5',
|
version = '2.1.6',
|
||||||
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
|
commentRegExp = /(\/\*([\s\S]*?)\*\/|([^:]|^)\/\/(.*)$)/mg,
|
||||||
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
cjsRequireRegExp = /[^.]\s*require\s*\(\s*["']([^'"\s]+)["']\s*\)/g,
|
||||||
jsSuffixRegExp = /\.js$/,
|
jsSuffixRegExp = /\.js$/,
|
||||||
@ -22,7 +22,7 @@ var requirejs, require, define;
|
|||||||
hasOwn = op.hasOwnProperty,
|
hasOwn = op.hasOwnProperty,
|
||||||
ap = Array.prototype,
|
ap = Array.prototype,
|
||||||
apsp = ap.splice,
|
apsp = ap.splice,
|
||||||
isBrowser = !!(typeof window !== 'undefined' && navigator && document),
|
isBrowser = !!(typeof window !== 'undefined' && navigator && window.document),
|
||||||
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
|
isWebWorker = !isBrowser && typeof importScripts !== 'undefined',
|
||||||
//PS3 indicates loaded and complete, but need to wait for complete
|
//PS3 indicates loaded and complete, but need to wait for complete
|
||||||
//specifically. Sequence is 'loading', 'loaded', execution,
|
//specifically. Sequence is 'loading', 'loaded', execution,
|
||||||
@ -134,6 +134,10 @@ var requirejs, require, define;
|
|||||||
return document.getElementsByTagName('script');
|
return document.getElementsByTagName('script');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function defaultOnError(err) {
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
|
||||||
//Allow getting a global that expressed in
|
//Allow getting a global that expressed in
|
||||||
//dot notation, like 'a.b.c'.
|
//dot notation, like 'a.b.c'.
|
||||||
function getGlobal(value) {
|
function getGlobal(value) {
|
||||||
@ -500,7 +504,12 @@ var requirejs, require, define;
|
|||||||
fn(defined[id]);
|
fn(defined[id]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
getModule(depMap).on(name, fn);
|
mod = getModule(depMap);
|
||||||
|
if (mod.error && name === 'error') {
|
||||||
|
fn(mod.error);
|
||||||
|
} else {
|
||||||
|
mod.on(name, fn);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -571,7 +580,13 @@ var requirejs, require, define;
|
|||||||
id: mod.map.id,
|
id: mod.map.id,
|
||||||
uri: mod.map.url,
|
uri: mod.map.url,
|
||||||
config: function () {
|
config: function () {
|
||||||
return (config.config && getOwn(config.config, mod.map.id)) || {};
|
var c,
|
||||||
|
pkg = getOwn(config.pkgs, mod.map.id);
|
||||||
|
// For packages, only support config targeted
|
||||||
|
// at the main module.
|
||||||
|
c = pkg ? getOwn(config.config, mod.map.id + '/' + pkg.main) :
|
||||||
|
getOwn(config.config, mod.map.id);
|
||||||
|
return c || {};
|
||||||
},
|
},
|
||||||
exports: defined[mod.map.id]
|
exports: defined[mod.map.id]
|
||||||
});
|
});
|
||||||
@ -840,8 +855,13 @@ var requirejs, require, define;
|
|||||||
if (this.depCount < 1 && !this.defined) {
|
if (this.depCount < 1 && !this.defined) {
|
||||||
if (isFunction(factory)) {
|
if (isFunction(factory)) {
|
||||||
//If there is an error listener, favor passing
|
//If there is an error listener, favor passing
|
||||||
//to that instead of throwing an error.
|
//to that instead of throwing an error. However,
|
||||||
if (this.events.error) {
|
//only do it for define()'d modules. require
|
||||||
|
//errbacks should not be called for failures in
|
||||||
|
//their callbacks (#699). However if a global
|
||||||
|
//onError is set, use that.
|
||||||
|
if ((this.events.error && this.map.isDefine) ||
|
||||||
|
req.onError !== defaultOnError) {
|
||||||
try {
|
try {
|
||||||
exports = context.execCb(id, factory, depExports, exports);
|
exports = context.execCb(id, factory, depExports, exports);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@ -869,8 +889,8 @@ var requirejs, require, define;
|
|||||||
|
|
||||||
if (err) {
|
if (err) {
|
||||||
err.requireMap = this.map;
|
err.requireMap = this.map;
|
||||||
err.requireModules = [this.map.id];
|
err.requireModules = this.map.isDefine ? [this.map.id] : null;
|
||||||
err.requireType = 'define';
|
err.requireType = this.map.isDefine ? 'define' : 'require';
|
||||||
return onError((this.error = err));
|
return onError((this.error = err));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1093,7 +1113,7 @@ var requirejs, require, define;
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
if (this.errback) {
|
if (this.errback) {
|
||||||
on(depMap, 'error', this.errback);
|
on(depMap, 'error', bind(this, this.errback));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1605,7 +1625,7 @@ var requirejs, require, define;
|
|||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Executes a module callack function. Broken out as a separate function
|
* Executes a module callback function. Broken out as a separate function
|
||||||
* solely to allow the build system to sequence the files in the built
|
* solely to allow the build system to sequence the files in the built
|
||||||
* layer in the right sequence.
|
* layer in the right sequence.
|
||||||
*
|
*
|
||||||
@ -1643,7 +1663,7 @@ var requirejs, require, define;
|
|||||||
onScriptError: function (evt) {
|
onScriptError: function (evt) {
|
||||||
var data = getScriptData(evt);
|
var data = getScriptData(evt);
|
||||||
if (!hasPathFallback(data.id)) {
|
if (!hasPathFallback(data.id)) {
|
||||||
return onError(makeError('scripterror', 'Script error', evt, [data.id]));
|
return onError(makeError('scripterror', 'Script error for: ' + data.id, evt, [data.id]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -1772,9 +1792,7 @@ var requirejs, require, define;
|
|||||||
* function. Intercept/override it if you want custom error handling.
|
* function. Intercept/override it if you want custom error handling.
|
||||||
* @param {Error} err the error object.
|
* @param {Error} err the error object.
|
||||||
*/
|
*/
|
||||||
req.onError = function (err) {
|
req.onError = defaultOnError;
|
||||||
throw err;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does the request to load a module for the browser case.
|
* Does the request to load a module for the browser case.
|
||||||
@ -1906,24 +1924,31 @@ var requirejs, require, define;
|
|||||||
//baseUrl, if it is not already set.
|
//baseUrl, if it is not already set.
|
||||||
dataMain = script.getAttribute('data-main');
|
dataMain = script.getAttribute('data-main');
|
||||||
if (dataMain) {
|
if (dataMain) {
|
||||||
|
//Preserve dataMain in case it is a path (i.e. contains '?')
|
||||||
|
mainScript = dataMain;
|
||||||
|
|
||||||
//Set final baseUrl if there is not already an explicit one.
|
//Set final baseUrl if there is not already an explicit one.
|
||||||
if (!cfg.baseUrl) {
|
if (!cfg.baseUrl) {
|
||||||
//Pull off the directory of data-main for use as the
|
//Pull off the directory of data-main for use as the
|
||||||
//baseUrl.
|
//baseUrl.
|
||||||
src = dataMain.split('/');
|
src = mainScript.split('/');
|
||||||
mainScript = src.pop();
|
mainScript = src.pop();
|
||||||
subPath = src.length ? src.join('/') + '/' : './';
|
subPath = src.length ? src.join('/') + '/' : './';
|
||||||
|
|
||||||
cfg.baseUrl = subPath;
|
cfg.baseUrl = subPath;
|
||||||
dataMain = mainScript;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Strip off any trailing .js since dataMain is now
|
//Strip off any trailing .js since mainScript is now
|
||||||
//like a module name.
|
//like a module name.
|
||||||
dataMain = dataMain.replace(jsSuffixRegExp, '');
|
mainScript = mainScript.replace(jsSuffixRegExp, '');
|
||||||
|
|
||||||
|
//If mainScript is still a path, fall back to dataMain
|
||||||
|
if (req.jsExtRegExp.test(mainScript)) {
|
||||||
|
mainScript = dataMain;
|
||||||
|
}
|
||||||
|
|
||||||
//Put the data-main script in the files to load.
|
//Put the data-main script in the files to load.
|
||||||
cfg.deps = cfg.deps ? cfg.deps.concat(dataMain) : [dataMain];
|
cfg.deps = cfg.deps ? cfg.deps.concat(mainScript) : [mainScript];
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -1951,12 +1976,13 @@ var requirejs, require, define;
|
|||||||
//This module may not have dependencies
|
//This module may not have dependencies
|
||||||
if (!isArray(deps)) {
|
if (!isArray(deps)) {
|
||||||
callback = deps;
|
callback = deps;
|
||||||
deps = [];
|
deps = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If no name, and callback is a function, then figure out if it a
|
//If no name, and callback is a function, then figure out if it a
|
||||||
//CommonJS thing with dependencies.
|
//CommonJS thing with dependencies.
|
||||||
if (!deps.length && isFunction(callback)) {
|
if (!deps && isFunction(callback)) {
|
||||||
|
deps = [];
|
||||||
//Remove comments from the callback string,
|
//Remove comments from the callback string,
|
||||||
//look for require calls, and pull them into the dependencies,
|
//look for require calls, and pull them into the dependencies,
|
||||||
//but only if there are function args.
|
//but only if there are function args.
|
286
js/main-min.js
vendored
286
js/main-min.js
vendored
File diff suppressed because one or more lines are too long
34
js/main.js
34
js/main.js
@ -2,19 +2,34 @@
|
|||||||
requirejs.config({
|
requirejs.config({
|
||||||
waitSeconds: 0,
|
waitSeconds: 0,
|
||||||
paths: {
|
paths: {
|
||||||
MathJax: '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML'
|
"jquery": "lib/jquery",
|
||||||
|
"underscore": "lib/underscore",
|
||||||
|
"jgrowl": "lib/jgrowl",
|
||||||
|
"lib/MathJax": '../lib/MathJax/MathJax.js?config=TeX-AMS_HTML'
|
||||||
},
|
},
|
||||||
shim: {
|
shim: {
|
||||||
'jquery-ui': ['jquery'],
|
'lib/underscore': {
|
||||||
'bootstrap': ['jquery'],
|
exports: '_'
|
||||||
'jgrowl': ['jquery'],
|
},
|
||||||
'layout': ['jquery-ui'],
|
'lib/jgrowl': {
|
||||||
'Markdown.Extra': ['Markdown.Converter', 'prettify'],
|
deps: ['lib/jquery'],
|
||||||
'Markdown.Editor': ['Markdown.Converter']
|
exports: 'jQuery.jGrowl'
|
||||||
|
},
|
||||||
|
'lib/jquery-ui': ['lib/jquery'],
|
||||||
|
'lib/bootstrap': ['lib/jquery'],
|
||||||
|
'lib/layout': ['lib/jquery-ui'],
|
||||||
|
'lib/Markdown.Extra': ['lib/Markdown.Converter', 'lib/prettify'],
|
||||||
|
'lib/Markdown.Editor': ['lib/Markdown.Converter']
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
require(["jquery", "file-manager", "synchronizer", "publisher"], function($) {
|
require([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"synchronizer",
|
||||||
|
"publisher"
|
||||||
|
], function($, core) {
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
// If browser has detected a new application cache.
|
// If browser has detected a new application cache.
|
||||||
if (window.applicationCache) {
|
if (window.applicationCache) {
|
||||||
@ -25,5 +40,8 @@ require(["jquery", "file-manager", "synchronizer", "publisher"], function($) {
|
|||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core.setReady();
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
124
js/publisher.js
124
js/publisher.js
@ -1,8 +1,12 @@
|
|||||||
define([
|
define([
|
||||||
"jquery",
|
"jquery",
|
||||||
|
"underscore",
|
||||||
"core",
|
"core",
|
||||||
"utils",
|
"utils",
|
||||||
|
"settings",
|
||||||
"extension-manager",
|
"extension-manager",
|
||||||
|
"file-system",
|
||||||
|
"file-manager",
|
||||||
"sharing",
|
"sharing",
|
||||||
"blogger-provider",
|
"blogger-provider",
|
||||||
"dropbox-provider",
|
"dropbox-provider",
|
||||||
@ -11,59 +15,44 @@ define([
|
|||||||
"gdrive-provider",
|
"gdrive-provider",
|
||||||
"ssh-provider",
|
"ssh-provider",
|
||||||
"tumblr-provider",
|
"tumblr-provider",
|
||||||
"wordpress-provider",
|
"wordpress-provider"
|
||||||
"underscore"
|
], function($, _, core, utils, settings, extensionMgr, fileSystem, fileMgr, sharing) {
|
||||||
], function($, core, utils, extensionManager, sharing) {
|
|
||||||
|
|
||||||
var publisher = {};
|
var publisher = {};
|
||||||
|
|
||||||
// Create a map with providerId: providerObject
|
// Create a map with providerId: providerModule
|
||||||
var providerMap = _.chain(arguments)
|
var providerMap = _.chain(
|
||||||
.map(function(argument) {
|
arguments
|
||||||
return argument && argument.providerId && [argument.providerId, argument];
|
).map(function(argument) {
|
||||||
}).compact().object().value();
|
return argument && argument.providerId && [argument.providerId, argument];
|
||||||
|
}).compact().object().value();
|
||||||
// Used to know if the current file has publications
|
|
||||||
var hasPublications = false;
|
|
||||||
|
|
||||||
// Allows external modules to update hasPublications flag
|
// Retrieve publish locations from localStorage
|
||||||
publisher.notifyPublish = function() {
|
_.each(fileSystem, function(fileDesc) {
|
||||||
var fileDesc = core.fileManager.getCurrentFile();
|
_.chain(
|
||||||
|
localStorage[fileDesc.fileIndex + ".publish"].split(";")
|
||||||
// Check that file has publications
|
).compact().each(function(publishIndex) {
|
||||||
if(_.size(fileDesc.publishLocations) === 0) {
|
var publishAttributes = JSON.parse(localStorage[publishIndex]);
|
||||||
hasPublications = false;
|
// Store publishIndex
|
||||||
}
|
publishAttributes.publishIndex = publishIndex;
|
||||||
else {
|
// Replace provider ID by provider module in attributes
|
||||||
hasPublications = true;
|
publishAttributes.provider = providerMap[publishAttributes.provider];
|
||||||
}
|
fileDesc.publishLocations[publishIndex] = publishAttributes;
|
||||||
publisher.updatePublishButton();
|
});
|
||||||
};
|
});
|
||||||
|
|
||||||
// Used to enable/disable the publish button
|
|
||||||
publisher.updatePublishButton = function() {
|
|
||||||
if(publishRunning === true || hasPublications === false || core.isOffline) {
|
|
||||||
$(".action-force-publish").addClass("disabled");
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$(".action-force-publish").removeClass("disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Run updatePublishButton function on online/offline event
|
|
||||||
core.addOfflineListener(publisher.updatePublishButton);
|
|
||||||
|
|
||||||
// Apply template to the current document
|
// Apply template to the current document
|
||||||
publisher.applyTemplate = function(publishAttributes) {
|
publisher.applyTemplate = function(publishAttributes) {
|
||||||
var fileDesc = core.fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
try {
|
try {
|
||||||
return _.template(core.settings.template, {
|
return _.template(settings.template, {
|
||||||
documentTitle: fileDesc.title,
|
documentTitle: fileDesc.title,
|
||||||
documentMarkdown: $("#wmd-input").val(),
|
documentMarkdown: $("#wmd-input").val(),
|
||||||
documentHTML: $("#wmd-preview").html(),
|
documentHTML: $("#wmd-preview").html(),
|
||||||
publishAttributes: publishAttributes
|
publishAttributes: publishAttributes
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
core.showError(e);
|
extensionMgr.onError(e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -105,7 +94,7 @@ define([
|
|||||||
if(error !== undefined) {
|
if(error !== undefined) {
|
||||||
var errorMsg = error.toString();
|
var errorMsg = error.toString();
|
||||||
if(errorMsg.indexOf("|removePublish") !== -1) {
|
if(errorMsg.indexOf("|removePublish") !== -1) {
|
||||||
core.fileManager.removePublish(publishAttributes);
|
fileMgr.removePublish(publishAttributes);
|
||||||
}
|
}
|
||||||
if(errorMsg.indexOf("|stopPublish") !== -1) {
|
if(errorMsg.indexOf("|stopPublish") !== -1) {
|
||||||
callback(error);
|
callback(error);
|
||||||
@ -124,15 +113,15 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
publishRunning = true;
|
publishRunning = true;
|
||||||
publisher.updatePublishButton();
|
extensionMgr.onPublishRunning(true);
|
||||||
var fileDesc = fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
publishTitle = fileDesc.title;
|
publishTitle = fileDesc.title;
|
||||||
publishAttributesList = _.values(fileDesc.publishLocations);
|
publishAttributesList = _.values(fileDesc.publishLocations);
|
||||||
publishLocation(function(errorFlag) {
|
publishLocation(function(errorFlag) {
|
||||||
publishRunning = false;
|
publishRunning = false;
|
||||||
publisher.updatePublishButton();
|
extensionMgr.onPublishRunning(false);
|
||||||
if(errorFlag === undefined) {
|
if(errorFlag === undefined) {
|
||||||
extensionManager.onPublishSuccess(fileDesc);
|
extensionMgr.onPublishSuccess(fileDesc);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -144,8 +133,8 @@ define([
|
|||||||
publishIndex = "publish." + utils.randomString();
|
publishIndex = "publish." + utils.randomString();
|
||||||
} while(_.has(localStorage, publishIndex));
|
} while(_.has(localStorage, publishIndex));
|
||||||
publishAttributes.publishIndex = publishIndex;
|
publishAttributes.publishIndex = publishIndex;
|
||||||
localStorage[publishIndex] = JSON.stringify(publishAttributes);
|
localStorage[publishIndex] = utils.serializeAttributes(publishAttributes);
|
||||||
core.fileManager.addPublish(fileDesc, publishAttributes);
|
fileMgr.addPublish(fileDesc, publishAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the "New publication" dialog
|
// Initialize the "New publication" dialog
|
||||||
@ -185,7 +174,7 @@ define([
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform provider's publishing
|
// Perform provider's publishing
|
||||||
var fileDesc = core.fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
var title = fileDesc.title;
|
var title = fileDesc.title;
|
||||||
var content = getPublishContent(publishAttributes);
|
var content = getPublishContent(publishAttributes);
|
||||||
provider.publish(publishAttributes, title, content, function(error) {
|
provider.publish(publishAttributes, title, content, function(error) {
|
||||||
@ -193,8 +182,6 @@ define([
|
|||||||
publishAttributes.provider = provider.providerId;
|
publishAttributes.provider = provider.providerId;
|
||||||
sharing.createLink(publishAttributes, function() {
|
sharing.createLink(publishAttributes, function() {
|
||||||
createPublishIndex(fileDesc, publishAttributes);
|
createPublishIndex(fileDesc, publishAttributes);
|
||||||
publisher.notifyPublish();
|
|
||||||
core.fileManager.updateFileTitles();
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -210,16 +197,16 @@ define([
|
|||||||
|
|
||||||
// Retrieve file's publish locations from localStorage
|
// Retrieve file's publish locations from localStorage
|
||||||
publisher.populatePublishLocations = function(fileDesc) {
|
publisher.populatePublishLocations = function(fileDesc) {
|
||||||
_.chain(localStorage[fileDesc.fileIndex + ".publish"].split(";"))
|
_.chain(
|
||||||
.compact()
|
localStorage[fileDesc.fileIndex + ".publish"].split(";")
|
||||||
.each(function(publishIndex) {
|
).compact().each(function(publishIndex) {
|
||||||
var publishAttributes = JSON.parse(localStorage[publishIndex]);
|
var publishAttributes = JSON.parse(localStorage[publishIndex]);
|
||||||
// Store publishIndex
|
// Store publishIndex
|
||||||
publishAttributes.publishIndex = publishIndex;
|
publishAttributes.publishIndex = publishIndex;
|
||||||
// Replace provider ID by provider module in attributes
|
// Replace provider ID by provider module in attributes
|
||||||
publishAttributes.provider = providerMap[publishAttributes.provider];
|
publishAttributes.provider = providerMap[publishAttributes.provider];
|
||||||
fileDesc.publishLocations[publishIndex] = publishAttributes;
|
fileDesc.publishLocations[publishIndex] = publishAttributes;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
core.onReady(function() {
|
core.onReady(function() {
|
||||||
@ -249,8 +236,25 @@ define([
|
|||||||
publisher.publish();
|
publisher.publish();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Save As menu items
|
||||||
|
$(".action-download-md").click(function() {
|
||||||
|
var content = $("#wmd-input").val();
|
||||||
|
var title = fileMgr.getCurrentFile().title;
|
||||||
|
utils.saveAs(content, title + ".md");
|
||||||
|
});
|
||||||
|
$(".action-download-html").click(function() {
|
||||||
|
var content = $("#wmd-preview").html();
|
||||||
|
var title = fileMgr.getCurrentFile().title;
|
||||||
|
utils.saveAs(content, title + ".html");
|
||||||
|
});
|
||||||
|
$(".action-download-template").click(function() {
|
||||||
|
var content = publisher.applyTemplate();
|
||||||
|
var title = fileMgr.getCurrentFile().title;
|
||||||
|
utils.saveAs(content, title + ".txt");
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
extensionManager.onPublisherCreated(publisher);
|
extensionMgr.onPublisherCreated(publisher);
|
||||||
return publisher;
|
return publisher;
|
||||||
});
|
});
|
28
js/settings.js
Normal file
28
js/settings.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
define([
|
||||||
|
"underscore"
|
||||||
|
], function(_) {
|
||||||
|
|
||||||
|
var settings = {
|
||||||
|
layoutOrientation : "horizontal",
|
||||||
|
lazyRendering : true,
|
||||||
|
editorFontSize : 14,
|
||||||
|
defaultContent: "\n\n\n> Written with [StackEdit](http://benweet.github.io/stackedit/).",
|
||||||
|
commitMsg : "Published by http://benweet.github.io/stackedit",
|
||||||
|
template : [
|
||||||
|
'<!DOCTYPE html>\n',
|
||||||
|
'<html>\n',
|
||||||
|
'<head>\n',
|
||||||
|
'<title><%= documentTitle %></title>\n',
|
||||||
|
'</head>\n',
|
||||||
|
'<body><%= documentHTML %></body>\n',
|
||||||
|
'</html>'].join(""),
|
||||||
|
sshProxy : SSH_PROXY_URL,
|
||||||
|
extensionSettings: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (_.has(localStorage, "settings")) {
|
||||||
|
_.extend(settings, JSON.parse(localStorage.settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
});
|
@ -1,11 +1,24 @@
|
|||||||
define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-provider", "underscore"], function($, core, utils, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"file-system",
|
||||||
|
"file-manager",
|
||||||
|
"async-runner",
|
||||||
|
"download-provider",
|
||||||
|
"gist-provider"
|
||||||
|
], function($, _, core, utils, extensionMgr, fileMgr, asyncRunner) {
|
||||||
|
|
||||||
var sharing = {};
|
var sharing = {};
|
||||||
|
|
||||||
// Create a map with providerId: providerObject
|
// Create a map with providerId: providerModule
|
||||||
var providerMap = _.chain(arguments)
|
var providerMap = _.chain(
|
||||||
.map(function(argument) {
|
arguments
|
||||||
return argument && argument.providerId && [argument.providerId, argument];
|
).map(function(argument) {
|
||||||
}).compact().object().value();
|
return argument && argument.providerId && [argument.providerId, argument];
|
||||||
|
}).compact().object().value();
|
||||||
|
|
||||||
// Used to populate the "Sharing" dropdown box
|
// Used to populate the "Sharing" dropdown box
|
||||||
var lineTemplate = ['<div class="input-prepend">',
|
var lineTemplate = ['<div class="input-prepend">',
|
||||||
@ -52,11 +65,12 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
|
|||||||
url.push('=');
|
url.push('=');
|
||||||
url.push(encodeURIComponent(attributes[attributeName]));
|
url.push(encodeURIComponent(attributes[attributeName]));
|
||||||
});
|
});
|
||||||
|
url = url.join("");
|
||||||
$.getJSON(
|
$.getJSON(
|
||||||
"https://api-ssl.bitly.com/v3/shorten",
|
"https://api-ssl.bitly.com/v3/shorten",
|
||||||
{
|
{
|
||||||
"access_token": BITLY_ACCESS_TOKEN,
|
"access_token": BITLY_ACCESS_TOKEN,
|
||||||
"longUrl": url.join("")
|
"longUrl": url
|
||||||
},
|
},
|
||||||
function(response)
|
function(response)
|
||||||
{
|
{
|
||||||
@ -64,46 +78,22 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
|
|||||||
shortUrl = response.data.url;
|
shortUrl = response.data.url;
|
||||||
attributes.sharingLink = shortUrl;
|
attributes.sharingLink = shortUrl;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
extensionMgr.onError("An error occured while creating sharing link.");
|
||||||
|
attributes.sharingLink = url;
|
||||||
|
}
|
||||||
task.chain();
|
task.chain();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
function onFinish() {
|
function onFinish() {
|
||||||
if(shortUrl === undefined) {
|
callback();
|
||||||
localStorage["missingSharingLink"] = true;
|
|
||||||
}
|
|
||||||
callback(shortUrl);
|
|
||||||
}
|
}
|
||||||
task.onSuccess(onFinish);
|
task.onSuccess(onFinish);
|
||||||
task.onError(onFinish);
|
task.onError(onFinish);
|
||||||
asyncRunner.addTask(task);
|
asyncRunner.addTask(task);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create the possible missing links
|
|
||||||
function checkMissingLinks() {
|
|
||||||
if(core.isOffline === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!_.has(localStorage, "missingSharingLink")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
localStorage.removeItem("missingSharingLink");
|
|
||||||
var fileDescList = core.fileManager.getFileList();
|
|
||||||
_.each(fileDescList, function(fileDesc) {
|
|
||||||
_.each(fileDescList.publishLocations, function(publishAttributes, publishIndex) {
|
|
||||||
sharing.createLink(publishAttributes, function(shortUrl) {
|
|
||||||
if(shortUrl !== undefined) {
|
|
||||||
localStorage[publishIndex] = utils.serializeAttributes(attributes);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// Periodically check that links are not missing
|
|
||||||
if(viewerMode === false) {
|
|
||||||
core.addPeriodicCallback(checkMissingLinks);
|
|
||||||
}
|
|
||||||
|
|
||||||
core.onReady(function() {
|
core.onReady(function() {
|
||||||
if(viewerMode === false) {
|
if(viewerMode === false) {
|
||||||
return;
|
return;
|
||||||
@ -135,8 +125,8 @@ define(["jquery", "core", "utils", "async-runner", "download-provider", "gist-pr
|
|||||||
if(error) {
|
if(error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var fileDesc = core.fileManager.createFile(title, content, undefined, true);
|
var fileDesc = fileMgr.createFile(title, content, undefined, true);
|
||||||
core.fileManager.selectFile(fileDesc);
|
fileMgr.selectFile(fileDesc);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, asyncRunner) {
|
||||||
|
|
||||||
var sshHelper = {};
|
var sshHelper = {};
|
||||||
|
|
||||||
@ -14,7 +18,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
|
sshHelper.upload = function(host, port, username, password, path, title, content, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
task.onRun(function() {
|
task.onRun(function() {
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
define([ "utils", "ssh-helper" ], function(utils, sshHelper) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"ssh-helper"
|
||||||
|
], function(utils, sshHelper) {
|
||||||
|
|
||||||
var PROVIDER_SSH = "ssh";
|
var PROVIDER_SSH = "ssh";
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
// Setup an empty localStorage or upgrade an existing one
|
// Setup an empty localStorage or upgrade an existing one
|
||||||
define( [ "underscore" ], function() {
|
define([
|
||||||
|
"underscore"
|
||||||
|
], function(_) {
|
||||||
|
|
||||||
// Create the file system if not exist
|
// Create the file system if not exist
|
||||||
if (localStorage["file.list"] === undefined) {
|
if (localStorage["file.list"] === undefined) {
|
||||||
@ -122,8 +124,6 @@ define( [ "underscore" ], function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
// Force creation of sharing links
|
|
||||||
localStorage["missingSharingLink"] = true;
|
|
||||||
version = "v6";
|
version = "v6";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,44 +1,37 @@
|
|||||||
define([
|
define([
|
||||||
"jquery",
|
"jquery",
|
||||||
|
"underscore",
|
||||||
"core",
|
"core",
|
||||||
"utils",
|
"utils",
|
||||||
"extension-manager",
|
"extension-manager",
|
||||||
|
"file-system",
|
||||||
|
"file-manager",
|
||||||
"dropbox-provider",
|
"dropbox-provider",
|
||||||
"gdrive-provider",
|
"gdrive-provider"
|
||||||
"underscore"
|
], function($, _, core, utils, extensionMgr, fileSystem, fileMgr) {
|
||||||
], function($, core, utils, extensionManager) {
|
|
||||||
|
|
||||||
var synchronizer = {};
|
var synchronizer = {};
|
||||||
|
|
||||||
// Create a map with providerId: providerObject
|
// Create a map with providerId: providerModule
|
||||||
var providerMap = _.chain(arguments)
|
var providerMap = _.chain(
|
||||||
.map(function(argument) {
|
arguments
|
||||||
return argument && argument.providerId && [argument.providerId, argument];
|
).map(function(argument) {
|
||||||
}).compact().object().value();
|
return argument && argument.providerId && [argument.providerId, argument];
|
||||||
|
}).compact().object().value();
|
||||||
// Used to know if user can force synchronization
|
|
||||||
var uploadPending = false;
|
|
||||||
|
|
||||||
// Allows external modules to update uploadPending flag
|
// Retrieve sync locations from localStorage
|
||||||
synchronizer.notifyChange = function(fileDesc) {
|
_.each(fileSystem, function(fileDesc) {
|
||||||
// Check that file has synchronized locations
|
_.chain(
|
||||||
if(_.size(fileDesc.syncLocations) !== 0) {
|
localStorage[fileDesc.fileIndex + ".sync"].split(";")
|
||||||
uploadPending = true;
|
).compact().each(function(syncIndex) {
|
||||||
synchronizer.updateSyncButton();
|
var syncAttributes = JSON.parse(localStorage[syncIndex]);
|
||||||
}
|
// Store syncIndex
|
||||||
};
|
syncAttributes.syncIndex = syncIndex;
|
||||||
|
// Replace provider ID by provider module in attributes
|
||||||
// Used to enable/disable the synchronization button
|
syncAttributes.provider = providerMap[syncAttributes.provider];
|
||||||
synchronizer.updateSyncButton = function() {
|
fileDesc.syncLocations[syncIndex] = syncAttributes;
|
||||||
if(syncRunning === true || uploadPending === false || core.isOffline) {
|
});
|
||||||
$(".action-force-sync").addClass("disabled");
|
});
|
||||||
}
|
|
||||||
else {
|
|
||||||
$(".action-force-sync").removeClass("disabled");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
// Run updateSyncButton on online/offline event
|
|
||||||
core.addOfflineListener(synchronizer.updateSyncButton);
|
|
||||||
|
|
||||||
// Force the synchronization
|
// Force the synchronization
|
||||||
synchronizer.forceSync = function() {
|
synchronizer.forceSync = function() {
|
||||||
@ -73,8 +66,6 @@ define([
|
|||||||
if(uploadFlag === true) {
|
if(uploadFlag === true) {
|
||||||
// If uploadFlag is true, request another upload cycle
|
// If uploadFlag is true, request another upload cycle
|
||||||
uploadCycle = true;
|
uploadCycle = true;
|
||||||
// When page is refreshed, this flag is false but should be true here
|
|
||||||
uploadPending = true;
|
|
||||||
}
|
}
|
||||||
if(error) {
|
if(error) {
|
||||||
callback(error);
|
callback(error);
|
||||||
@ -121,7 +112,7 @@ define([
|
|||||||
if(uploadCycle === true) {
|
if(uploadCycle === true) {
|
||||||
// New upload cycle
|
// New upload cycle
|
||||||
uploadCycle = false;
|
uploadCycle = false;
|
||||||
uploadFileList = core.fileManager.getFileList();
|
uploadFileList = fileMgr.getFileList();
|
||||||
fileUp(callback);
|
fileUp(callback);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -139,7 +130,7 @@ define([
|
|||||||
var provider = providerList.pop();
|
var provider = providerList.pop();
|
||||||
|
|
||||||
// Check that provider has files to sync
|
// Check that provider has files to sync
|
||||||
if(!core.fileManager.hasSync(provider)) {
|
if(!fileMgr.hasSync(provider)) {
|
||||||
providerDown(callback);
|
providerDown(callback);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -165,18 +156,18 @@ define([
|
|||||||
var lastSync = 0;
|
var lastSync = 0;
|
||||||
synchronizer.sync = function() {
|
synchronizer.sync = function() {
|
||||||
// If sync is already running or timeout is not reached or offline
|
// If sync is already running or timeout is not reached or offline
|
||||||
if (syncRunning || lastSync + SYNC_PERIOD > core.currentTime || core.isOffline) {
|
if (syncRunning || lastSync + SYNC_PERIOD > utils.currentTime || core.isOffline) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
syncRunning = true;
|
syncRunning = true;
|
||||||
|
extensionMgr.onSyncRunning(true);
|
||||||
uploadCycle = true;
|
uploadCycle = true;
|
||||||
lastSync = core.currentTime;
|
lastSync = utils.currentTime;
|
||||||
synchronizer.updateSyncButton();
|
|
||||||
|
|
||||||
function isError(error) {
|
function isError(error) {
|
||||||
if(error !== undefined) {
|
if(error !== undefined) {
|
||||||
syncRunning = false;
|
syncRunning = false;
|
||||||
synchronizer.updateSyncButton();
|
extensionMgr.onSyncRunning(false);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -191,7 +182,8 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
syncRunning = false;
|
syncRunning = false;
|
||||||
uploadPending = false;
|
extensionMgr.onSyncRunning(false);
|
||||||
|
extensionMgr.onSyncSuccess();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@ -200,20 +192,6 @@ define([
|
|||||||
core.addPeriodicCallback(synchronizer.sync);
|
core.addPeriodicCallback(synchronizer.sync);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve file's sync locations from localStorage
|
|
||||||
publisher.populateSyncLocations = function(fileDesc) {
|
|
||||||
_.chain(localStorage[fileDesc.fileIndex + ".sync"].split(";"))
|
|
||||||
.compact()
|
|
||||||
.each(function(syncIndex) {
|
|
||||||
var syncAttributes = JSON.parse(localStorage[syncIndex]);
|
|
||||||
// Store syncIndex
|
|
||||||
syncAttributes.syncIndex = syncIndex;
|
|
||||||
// Replace provider ID by provider module in attributes
|
|
||||||
syncAttributes.provider = providerMap[syncAttributes.provider];
|
|
||||||
fileDesc.syncLocations[syncIndex] = syncAttributes;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// Initialize the export dialog
|
// Initialize the export dialog
|
||||||
function initExportDialog(provider) {
|
function initExportDialog(provider) {
|
||||||
|
|
||||||
@ -247,14 +225,14 @@ define([
|
|||||||
$(".action-sync-export-" + provider.providerId).click(function(event) {
|
$(".action-sync-export-" + provider.providerId).click(function(event) {
|
||||||
|
|
||||||
// Perform the provider's export
|
// Perform the provider's export
|
||||||
var fileDesc = core.fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
var title = fileDesc.title;
|
var title = fileDesc.title;
|
||||||
var content = localStorage[fileDesc.fileIndex + ".content"];
|
var content = localStorage[fileDesc.fileIndex + ".content"];
|
||||||
provider.exportFile(event, title, content, function(error, syncAttributes) {
|
provider.exportFile(event, title, content, function(error, syncAttributes) {
|
||||||
if(error) {
|
if(error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.fileManager.addSync(fileDesc, syncAttributes);
|
fileMgr.addSync(fileDesc, syncAttributes);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store input values as preferences for next time we open the export dialog
|
// Store input values as preferences for next time we open the export dialog
|
||||||
@ -266,19 +244,18 @@ define([
|
|||||||
});
|
});
|
||||||
// Provider's manual export button
|
// Provider's manual export button
|
||||||
$(".action-sync-manual-" + provider.providerId).click(function(event) {
|
$(".action-sync-manual-" + provider.providerId).click(function(event) {
|
||||||
var fileDesc = core.fileManager.getCurrentFile();
|
var fileDesc = fileMgr.getCurrentFile();
|
||||||
var title = fileDesc.title;
|
var title = fileDesc.title;
|
||||||
var content = localStorage[fileDesc.fileIndex + ".content"];
|
var content = localStorage[fileDesc.fileIndex + ".content"];
|
||||||
provider.exportManual(event, title, content, function(error, syncAttributes) {
|
provider.exportManual(event, title, content, function(error, syncAttributes) {
|
||||||
if(error) {
|
if(error) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.fileManager.addSync(fileDesc, syncAttributes);
|
fileMgr.addSync(fileDesc, syncAttributes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
synchronizer.updateSyncButton();
|
|
||||||
$(".action-force-sync").click(function() {
|
$(".action-force-sync").click(function() {
|
||||||
if(!$(this).hasClass("disabled")) {
|
if(!$(this).hasClass("disabled")) {
|
||||||
synchronizer.forceSync();
|
synchronizer.forceSync();
|
||||||
@ -286,6 +263,6 @@ define([
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
extensionManager.onSynchronizerCreated(synchronizer);
|
extensionMgr.onSynchronizerCreated(synchronizer);
|
||||||
return synchronizer;
|
return synchronizer;
|
||||||
});
|
});
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, utils, extensionMgr, asyncRunner) {
|
||||||
|
|
||||||
var oauthParams = undefined;
|
var oauthParams = undefined;
|
||||||
|
|
||||||
@ -30,7 +36,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
task.chain();
|
task.chain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.showMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Tumblr authorization popup is not blocked by your browser.");
|
||||||
var errorMsg = "Failed to retrieve a token from Tumblr.";
|
var errorMsg = "Failed to retrieve a token from Tumblr.";
|
||||||
// We add time for user to enter his credentials
|
// We add time for user to enter his credentials
|
||||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||||
@ -48,7 +54,7 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
function getVerifier() {
|
function getVerifier() {
|
||||||
localStorage.removeItem("tumblrVerifier");
|
localStorage.removeItem("tumblrVerifier");
|
||||||
authWindow = core.popupWindow(
|
authWindow = utils.popupWindow(
|
||||||
'tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token,
|
'tumblr-oauth-client.html?oauth_token=' + oauth_object.oauth_token,
|
||||||
'stackedit-tumblr-oauth', 800, 600);
|
'stackedit-tumblr-oauth', 800, 600);
|
||||||
authWindow.focus();
|
authWindow.focus();
|
||||||
@ -92,7 +98,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) {
|
tumblrHelper.upload = function(blogHostname, postId, tags, format, title, content, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
authenticate(task);
|
authenticate(task);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
define(["utils", "tumblr-helper"], function(utils, tumblrHelper) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"tumblr-helper"
|
||||||
|
], function(utils, tumblrHelper) {
|
||||||
|
|
||||||
var PROVIDER_TUMBLR = "tumblr";
|
var PROVIDER_TUMBLR = "tumblr";
|
||||||
|
|
||||||
|
53
js/utils.js
53
js/utils.js
@ -1,4 +1,8 @@
|
|||||||
define([ "jquery", "underscore" ], function($) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"underscore",
|
||||||
|
"lib/FileSaver"
|
||||||
|
], function($, _) {
|
||||||
|
|
||||||
var utils = {};
|
var utils = {};
|
||||||
|
|
||||||
@ -107,6 +111,16 @@ define([ "jquery", "underscore" ], function($) {
|
|||||||
return $.trim(str);
|
return $.trim(str);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Slug function
|
||||||
|
utils.slugify = function(text) {
|
||||||
|
return text.toLowerCase()
|
||||||
|
.replace(/\s+/g, '-') // Replace spaces with -
|
||||||
|
.replace(/[^\w\-]+/g, '') // Remove all non-word chars
|
||||||
|
.replace(/\-\-+/g, '-') // Replace multiple - with single -
|
||||||
|
.replace(/^-+/, '') // Trim - from start of text
|
||||||
|
.replace(/-+$/, ''); // Trim - from end of text
|
||||||
|
};
|
||||||
|
|
||||||
// Check an URL
|
// Check an URL
|
||||||
utils.checkUrl = function(url, addSlash) {
|
utils.checkUrl = function(url, addSlash) {
|
||||||
if(!url) {
|
if(!url) {
|
||||||
@ -242,11 +256,48 @@ define([ "jquery", "underscore" ], function($) {
|
|||||||
return crc.toString(16);
|
return crc.toString(16);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Create an centered popup window
|
||||||
|
utils.popupWindow = function(url, title, width, height) {
|
||||||
|
var left = (screen.width / 2) - (width / 2);
|
||||||
|
var top = (screen.height / 2) - (height / 2);
|
||||||
|
return window.open(
|
||||||
|
url,
|
||||||
|
title,
|
||||||
|
'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='
|
||||||
|
+ width
|
||||||
|
+ ', height='
|
||||||
|
+ height
|
||||||
|
+ ', top='
|
||||||
|
+ top
|
||||||
|
+ ', left='
|
||||||
|
+ left);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Export data on disk
|
||||||
|
utils.saveAs = function(content, filename) {
|
||||||
|
if(saveAs !== undefined) {
|
||||||
|
var blob = new Blob([content], {type: "text/plain;charset=utf-8"});
|
||||||
|
saveAs(blob, filename);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var uriContent = "data:application/octet-stream;base64,"
|
||||||
|
+ utils.encodeBase64(content);
|
||||||
|
window.open(uriContent, 'file');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Generates a random string
|
// Generates a random string
|
||||||
utils.randomString = function() {
|
utils.randomString = function() {
|
||||||
return _.random(4294967296).toString(36);
|
return _.random(4294967296).toString(36);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Time shared by others modules
|
||||||
|
utils.updateCurrentTime = function() {
|
||||||
|
utils.currentTime = new Date().getTime();
|
||||||
|
};
|
||||||
|
utils.updateCurrentTime();
|
||||||
|
|
||||||
|
|
||||||
// Serialize sync/publish attributes
|
// Serialize sync/publish attributes
|
||||||
utils.serializeAttributes = function(attributes) {
|
utils.serializeAttributes = function(attributes) {
|
||||||
// Don't store sync/publish index
|
// Don't store sync/publish index
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
define([
|
||||||
|
"jquery",
|
||||||
|
"core",
|
||||||
|
"utils",
|
||||||
|
"extension-manager",
|
||||||
|
"async-runner"
|
||||||
|
], function($, core, utils, extensionMgr, asyncRunner) {
|
||||||
|
|
||||||
var token = undefined;
|
var token = undefined;
|
||||||
|
|
||||||
@ -25,14 +31,14 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
task.chain();
|
task.chain();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
core.showMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
|
extensionMgr.onMessage("Please make sure the Wordpress authorization popup is not blocked by your browser.");
|
||||||
var errorMsg = "Failed to retrieve a token from Wordpress.";
|
var errorMsg = "Failed to retrieve a token from Wordpress.";
|
||||||
// We add time for user to enter his credentials
|
// We add time for user to enter his credentials
|
||||||
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
task.timeout = ASYNC_TASK_LONG_TIMEOUT;
|
||||||
var code = undefined;
|
var code = undefined;
|
||||||
function getCode() {
|
function getCode() {
|
||||||
localStorage.removeItem("wordpressCode");
|
localStorage.removeItem("wordpressCode");
|
||||||
authWindow = core.popupWindow(
|
authWindow = utils.popupWindow(
|
||||||
'wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID,
|
'wordpress-oauth-client.html?client_id=' + WORDPRESS_CLIENT_ID,
|
||||||
'stackedit-wordpress-oauth', 960, 600);
|
'stackedit-wordpress-oauth', 960, 600);
|
||||||
authWindow.focus();
|
authWindow.focus();
|
||||||
@ -76,7 +82,6 @@ define(["jquery", "core", "async-runner"], function($, core, asyncRunner) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
wordpressHelper.upload = function(site, postId, tags, title, content, callback) {
|
wordpressHelper.upload = function(site, postId, tags, title, content, callback) {
|
||||||
callback = callback || core.doNothing;
|
|
||||||
var task = asyncRunner.createTask();
|
var task = asyncRunner.createTask();
|
||||||
connect(task);
|
connect(task);
|
||||||
authenticate(task);
|
authenticate(task);
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
define(["utils", "wordpress-helper"], function(utils, wordpressHelper) {
|
define([
|
||||||
|
"utils",
|
||||||
|
"wordpress-helper"
|
||||||
|
], function(utils, wordpressHelper) {
|
||||||
|
|
||||||
var PROVIDER_WORDPRESS = "wordpress";
|
var PROVIDER_WORDPRESS = "wordpress";
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@
|
|||||||
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
|
var require = { baseUrl : "js", deps : [ "main" + suffix ] };
|
||||||
var viewerMode = true;
|
var viewerMode = true;
|
||||||
</script>
|
</script>
|
||||||
<script src="js/require.js"></script>
|
<script src="js/lib/require.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body class="viewer">
|
<body class="viewer">
|
||||||
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">
|
<div id="navbar" class="navbar navbar-fixed-top ui-layout-north">
|
||||||
|
Loading…
Reference in New Issue
Block a user