-
StackEdit has stopped because another instance was running on
+
StackEdit has stopped because another instance was running in
the same browser.
If you want to reopen StackEdit, click on
"Reload".
diff --git a/js/core.js b/js/core.js
index be9261f2..8214c377 100644
--- a/js/core.js
+++ b/js/core.js
@@ -1,9 +1,9 @@
define(
[ "jquery", "file-manager", "google-helper", "dropbox-helper",
- "synchronizer", "publisher", "async-runner", "bootstrap", "jgrowl",
- "layout", "Markdown.Editor", "config", "custo" ],
- function($, fileManager, googleHelper, dropboxHelper, synchronizer,
- publisher, asyncTaskRunner) {
+ "github-helper", "synchronizer", "publisher", "async-runner",
+ "bootstrap", "jgrowl", "layout", "Markdown.Editor", "config", "custo" ],
+ function($, fileManager, googleHelper, dropboxHelper, githubHelper,
+ synchronizer, publisher, asyncTaskRunner) {
var core = {};
@@ -47,6 +47,7 @@ define(
var frontWindowId = localStorage["frontWindowId"];
if(frontWindowId != windowId) {
windowUnique = false;
+ $(".modal").modal("hide");
$('#modal-non-unique').modal({
backdrop: "static",
keyboard: false
@@ -54,23 +55,45 @@ define(
}
};
- // Useful function
- core.getInputValue = function(element, event) {
- var value = element.val();
- if (value !== undefined) {
- value = value.replace(/^\s+|\s+$/g, '');
- element.val(undefined);
+ // Useful function for input control
+ function inputError(element, event) {
+ element.stop(true, true).addClass("error").delay(400).switchClass("error");
+ if(event !== undefined) {
+ event.stopPropagation();
}
- if (value === undefined || value.length === 0) {
- element.stop(true, true).addClass("error").delay(400)
- .switchClass("error");
- if(event !== undefined) {
- event.stopPropagation();
- }
+ }
+ core.getInputValue = function(element, event, validationRegex) {
+ var value = element.val();
+ if (value === undefined) {
+ inputError(element, event);
+ return undefined;
+ }
+ // trim
+ value = value.replace(/^\s+|\s+$/g, '');
+ if((value.length === 0)
+ || (validationRegex !== undefined && !value.match(validationRegex))) {
+ inputError(element, event);
return undefined;
}
return value;
};
+ core.getInputIntValue = function(element, event, min, max) {
+ var value = core.getInputValue(element, event);
+ if(value === undefined) {
+ return undefined;
+ }
+ value = parseInt(value);
+ if((value === NaN)
+ || (min !== undefined && value < min)
+ || (max !== undefined && value > max)) {
+ inputError(element, event);
+ return undefined;
+ }
+ return value;
+ };
+ core.resetModalInputs = function() {
+ $(".modal input[type=text]:not([disabled])").val("");
+ };
// Used by asyncTaskRunner
core.showWorkingIndicator = function(show) {
@@ -143,7 +166,11 @@ define(
}
// Setting management
- var settings = { layoutOrientation : "horizontal" };
+ var settings = {
+ layoutOrientation : "horizontal",
+ editorFontSize : 14
+ };
+
core.loadSettings = function() {
if (localStorage.settings) {
$.extend(settings, JSON.parse(localStorage.settings));
@@ -152,15 +179,25 @@ define(
// Layout orientation
$("input:radio[name=radio-layout-orientation][value="
+ settings.layoutOrientation + "]").prop("checked", true);
+
+ // Editor font size
+ $("#input-editor-font-size").val(settings.editorFontSize);
};
- core.saveSettings = function() {
-
+ core.saveSettings = function(event) {
+ var newSettings = {};
+
// Layout orientation
- settings.layoutOrientation = $(
+ newSettings.layoutOrientation = $(
"input:radio[name=radio-layout-orientation]:checked").prop("value");
+
+ // Editor font size
+ newSettings.editorFontSize = core.getInputIntValue($("#input-editor-font-size"), event, 1, 99);
- localStorage.settings = JSON.stringify(settings);
+ if(!event.isPropagationStopped()) {
+ settings = newSettings;
+ localStorage.settings = JSON.stringify(newSettings);
+ }
};
// Create the layout
@@ -225,12 +262,14 @@ define(
var editor = new Markdown.Editor(converter);
editor.hooks.set("insertLinkDialog", function (callback) {
insertLinkCallback = callback;
- $("#modal-insert-link").modal('show');
+ core.resetModalInputs();
+ $("#modal-insert-link").modal();
return true;
});
editor.hooks.set("insertImageDialog", function (callback) {
insertLinkCallback = callback;
- $("#modal-insert-image").modal('show');
+ core.resetModalInputs();
+ $("#modal-insert-image").modal();
return true;
});
@@ -412,6 +451,24 @@ define(
}
localStorage["version"] = version;
}
+
+
+ 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);
+ };
core.init = function() {
setupLocalStorage();
@@ -458,14 +515,26 @@ define(
$("#menu-bar, .ui-layout-center, .ui-layout-east, .ui-layout-south").removeClass("hide");
this.loadSettings();
this.createLayout();
+
+ // Apply editor font size
+ $("#wmd-input").css({
+ "font-size": settings.editorFontSize + "px",
+ "line-height": Math.round(settings.editorFontSize * (20/14)) + "px"
+ });
$(".action-load-settings").click(function() {
core.loadSettings();
});
- $(".action-apply-settings").click(function() {
- core.saveSettings();
- window.location.reload();
+ $(".action-apply-settings").click(function(e) {
+ core.saveSettings(e);
+ if(!e.isPropagationStopped()) {
+ window.location.reload();
+ }
+ });
+
+ $(".action-reset-input").click(function() {
+ core.resetModalInputs();
});
// Init asyncTaskRunner
@@ -474,13 +543,16 @@ define(
// Init helpers
googleHelper.init(core, fileManager);
dropboxHelper.init(core, fileManager);
+ githubHelper.init(core, fileManager);
+
+ // Init synchronizer
+ synchronizer.init(core, fileManager);
// Init publisher
publisher.init(core, fileManager);
- // Init synchronizer
- synchronizer.init(core, fileManager);
offlineListeners.push(synchronizer.updateSyncButton);
+ offlineListeners.push(publisher.updatePublishButton);
// Init file manager
fileManager.init(core);
diff --git a/js/file-manager.js b/js/file-manager.js
index 4fe9307c..9768c058 100644
--- a/js/file-manager.js
+++ b/js/file-manager.js
@@ -21,8 +21,9 @@ define(["jquery", "google-helper", "dropbox-helper", "synchronizer", "publisher"
}
// Update the file titles
- this.updateFileTitles();
+ fileManager.updateFileTitles();
refreshManageSync();
+ publisher.notifyCurrentFile(localStorage["file.current"]);
// Recreate the editor
fileIndex = localStorage["file.current"];
@@ -347,6 +348,37 @@ define(["jquery", "google-helper", "dropbox-helper", "synchronizer", "publisher"
})(fileSyncIndex);
}
}
+
+
+ // Initialize the "New publication" dialog
+ var newPublishProvider = undefined;
+ function initNewPublish(provider, defaultPublishFormat) {
+ defaultPublishFormat = defaultPublishFormat || "markdown";
+ newPublishProvider = provider;
+
+ // Show/hide controls depending on provider
+ $('div[class*=" control-publish-"]').hide().filter(".control-publish-" + provider).show();
+
+ // Reset fields
+ core.resetModalInputs();
+ $("input:radio[name=radio-publish-format][value=" + defaultPublishFormat + "]").prop("checked", true);
+
+ // Open dialog box
+ $("#modal-publish").modal();
+ }
+
+ // Create a new publication
+ function newPublishBlogger(event) {
+ var blogUrl = core.getInputValue($("#input-publish-blogger-url"), event);
+ if(event.isPropagationStopped()) {
+ return;
+ }
+
+ googleHelper.getBlogByUrl(blogUrl, function(blog) {
+ console.log(blog);
+ });
+
+ }
fileManager.init = function(coreModule) {
core = coreModule;
@@ -393,6 +425,8 @@ define(["jquery", "google-helper", "dropbox-helper", "synchronizer", "publisher"
+ core.encodeBase64(content);
window.open(uriContent, 'file');
});
+
+ // Synchronize actions
$(".action-upload-gdrive-root").click(function() {
uploadGdrive();
});
@@ -423,6 +457,19 @@ define(["jquery", "google-helper", "dropbox-helper", "synchronizer", "publisher"
var path = core.getInputValue($("#manual-dropbox-path"), event);
manualDropbox(path);
});
+
+ // Publish actions
+ $(".action-publish-github").click(function() {
+ initNewPublish("github");
+ });
+ $(".action-publish-blogger").click(function() {
+ initNewPublish("blogger", "html");
+ });
+ $(".action-process-publish").click(function(e) {
+ if(newPublishProvider == "blogger") {
+ newPublishBlogger(e);
+ }
+ });
};
return fileManager;
diff --git a/js/github-helper.js b/js/github-helper.js
new file mode 100644
index 00000000..6c0a4586
--- /dev/null
+++ b/js/github-helper.js
@@ -0,0 +1,283 @@
+define(["jquery", "async-runner"], function($, asyncTaskRunner) {
+
+ // Dependencies
+ var core = undefined;
+ var fileManager = undefined;
+
+ var connected = undefined;
+ var client = undefined;
+
+ var githubHelper = {};
+
+ // Try to connect github by downloading js file
+ function connect(callback) {
+ callback = callback || core.doNothing;
+ var asyncTask = {};
+ asyncTask.run = function() {
+ if(core.isOffline === true) {
+ connected = false;
+ core.showMessage("Operation not available in offline mode.");
+ asyncTask.error();
+ return;
+ }
+ if (connected === true) {
+ asyncTask.success();
+ return;
+ }
+ $.ajax({
+ url : "lib/github.js",
+ dataType : "script", timeout : AJAX_TIMEOUT
+ }).done(function() {
+ connected = true;
+ asyncTask.success();
+ }).fail(function() {
+ asyncTask.error();
+ });
+ };
+ asyncTask.onSuccess = function() {
+ callback();
+ };
+ asyncTask.onError = function() {
+ core.setOffline();
+ callback();
+ };
+ asyncTaskRunner.addTask(asyncTask);
+ }
+
+ // Try to authenticate with Oauth
+ function authenticate(callback, immediate) {
+ callback = callback || core.doNothing;
+ if (immediate === undefined) {
+ immediate = true;
+ }
+ connect(function() {
+ if (connected === false) {
+ callback();
+ return;
+ }
+
+ var asyncTask = {};
+ asyncTask.run = function() {
+ if (client !== undefined) {
+ asyncTask.success();
+ return;
+ }
+ if (immediate !== false) {
+ }
+ core.showMessage("Please make sure the Github authorization popup is not blocked by your browser.");
+ myWindow=core.popupWindow('github-oauth-client.html?client_id=test','stackedit-github-oauth',500,400);
+ myWindow.focus();
+ };
+ asyncTask.onSuccess = function() {
+ callback();
+ };
+ asyncTask.onError = function() {
+ // If immediate did not work retry without immediate flag
+ if (connected === true && immediate === true) {
+ authenticate(callback, false);
+ return;
+ }
+ callback();
+ };
+ asyncTaskRunner.addTask(asyncTask);
+ });
+ }
+
+ githubHelper.upload = function(path, content, callback) {
+ callback = callback || core.doNothing;
+ authenticate(function() {
+ if (client === undefined) {
+ callback();
+ return;
+ }
+
+ var fileSyncIndex = undefined;
+ var asyncTask = {};
+ asyncTask.run = function() {
+ client.writeFile(path, content, function(error, stat) {
+ if (!error) {
+ fileSyncIndex = SYNC_PROVIDER_GITHUB + encodeURIComponent(stat.path.toLowerCase());
+ localStorage[fileSyncIndex + ".version"] = stat.versionTag;
+ asyncTask.success();
+ return;
+ }
+ // Handle error
+ if(error.status === Github.ApiError.INVALID_PARAM) {
+ error = 'Could not upload document into path "' + path + '".';
+ }
+ handleError(error, asyncTask, callback);
+ });
+ };
+ asyncTask.onSuccess = function() {
+ callback(fileSyncIndex);
+ };
+ asyncTaskRunner.addTask(asyncTask);
+ });
+ };
+
+ githubHelper.checkUpdates = function(lastChangeId, callback) {
+ callback = callback || core.doNothing;
+ authenticate(function() {
+ if (client === undefined) {
+ callback();
+ return;
+ }
+
+ var changes = [];
+ var newChangeId = lastChangeId || 0;
+ function retrievePageOfChanges(changeId) {
+ var shouldPullAgain = false;
+ var asyncTask = {};
+ asyncTask.run = function() {
+ client.pullChanges(changeId, function(error, pullChanges) {
+ if (pullChanges && pullChanges.cursorTag) {
+ // Retrieve success
+ newChangeId = pullChanges.cursor();
+ shouldPullAgain = pullChanges.shouldPullAgain;
+ if(pullChanges.changes !== undefined) {
+ for(var i=0; i