summaryrefslogtreecommitdiff
path: root/public/js/index.js
diff options
context:
space:
mode:
authorYukai Huang2017-03-13 21:32:50 +0800
committerYukai Huang2017-03-13 21:32:50 +0800
commit93e41f3a40394f061ca81c8ce119c85611173621 (patch)
tree20a81f7e77263e05b3d28304f72f4f224d931b0e /public/js/index.js
parent9b513f619fe74a579fadd807f86bd38f1049c56b (diff)
parentedb1b4aa0a72ac8b0215211c9dbc54156c3ff91f (diff)
Merge branch 'master' into cm-refactor
Diffstat (limited to '')
-rw-r--r--public/js/index.js6087
1 files changed, 2980 insertions, 3107 deletions
diff --git a/public/js/index.js b/public/js/index.js
index 0d4da4d0..7764fb58 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -1,26 +1,30 @@
-/* jquery and jquery plugins */
-require('../vendor/showup/showup');
+/* eslint-env browser, jquery */
+/* global CodeMirror, Cookies, moment, editor, ui, Spinner,
+ modeType, Idle, serverurl, key, gapi, Dropbox, FilePicker
+ ot, MediaUploader, hex2rgb, num_loaded, Visibility */
-require('../css/index.css');
-require('../css/extra.css');
-require('../css/slide-preview.css');
-require('../css/site.css');
+require('../vendor/showup/showup')
-require('highlight.js/styles/github-gist.css');
+require('../css/index.css')
+require('../css/extra.css')
+require('../css/slide-preview.css')
+require('../css/site.css')
-var toMarkdown = require('to-markdown');
+require('highlight.js/styles/github-gist.css')
-var saveAs = require('file-saver').saveAs;
-var randomColor = require('randomcolor');
+var toMarkdown = require('to-markdown')
-var _ = require("lodash");
+var saveAs = require('file-saver').saveAs
+var randomColor = require('randomcolor')
-var List = require('list.js');
+var _ = require('lodash')
+
+var List = require('list.js')
import {
checkLoginStateChanged,
setloginStateChangeEvent
-} from './lib/common/login';
+} from './lib/common/login'
import {
debug,
@@ -31,7 +35,7 @@ import {
noteurl,
urlpath,
version
-} from './lib/config';
+} from './lib/config'
import {
autoLinkify,
@@ -53,14 +57,14 @@ import {
updateLastChange,
updateLastChangeUser,
updateOwner
-} from './extra';
+} from './extra'
import {
clearMap,
setupSyncAreas,
syncScrollToEdit,
syncScrollToView
-} from './syncscroll';
+} from './syncscroll'
import {
writeHistory,
@@ -68,3469 +72,3338 @@ import {
getHistory,
saveHistory,
removeHistory
-} from './history';
+} from './history'
-var renderer = require('./render');
-var preventXSS = renderer.preventXSS;
+var renderer = require('./render')
+var preventXSS = renderer.preventXSS
-import Editor from './lib/editor';
+import Editor from './lib/editor'
-import getUIElements from './lib/editor/ui-elements';
+import getUIElements from './lib/editor/ui-elements'
-var defaultTextHeight = 20;
-var viewportMargin = 20;
+var defaultTextHeight = 20
+var viewportMargin = 20
-var idleTime = 300000; //5 mins
-var updateViewDebounce = 100;
-var cursorMenuThrottle = 50;
-var cursorActivityDebounce = 50;
-var cursorAnimatePeriod = 100;
-var supportContainers = ['success', 'info', 'warning', 'danger'];
-var supportCodeModes = ['javascript', 'typescript', 'jsx', 'htmlmixed', 'htmlembedded', 'css', 'xml', 'clike', 'clojure', 'ruby', 'python', 'shell', 'php', 'sql', 'haskell', 'coffeescript', 'yaml', 'pug', 'lua', 'cmake', 'nginx', 'perl', 'sass', 'r', 'dockerfile', 'tiddlywiki', 'mediawiki', 'go'];
-var supportCharts = ['sequence', 'flow', 'graphviz', 'mermaid'];
+var idleTime = 300000 // 5 mins
+var updateViewDebounce = 100
+var cursorMenuThrottle = 50
+var cursorActivityDebounce = 50
+var cursorAnimatePeriod = 100
+var supportContainers = ['success', 'info', 'warning', 'danger']
+var supportCodeModes = ['javascript', 'typescript', 'jsx', 'htmlmixed', 'htmlembedded', 'css', 'xml', 'clike', 'clojure', 'ruby', 'python', 'shell', 'php', 'sql', 'haskell', 'coffeescript', 'yaml', 'pug', 'lua', 'cmake', 'nginx', 'perl', 'sass', 'r', 'dockerfile', 'tiddlywiki', 'mediawiki', 'go']
+var supportCharts = ['sequence', 'flow', 'graphviz', 'mermaid']
var supportHeaders = [
- {
- text: '# h1',
- search: '#'
- },
- {
- text: '## h2',
- search: '##'
- },
- {
- text: '### h3',
- search: '###'
- },
- {
- text: '#### h4',
- search: '####'
- },
- {
- text: '##### h5',
- search: '#####'
- },
- {
- text: '###### h6',
- search: '######'
- },
- {
- text: '###### tags: `example`',
- search: '###### tags:'
- }
-];
+ {
+ text: '# h1',
+ search: '#'
+ },
+ {
+ text: '## h2',
+ search: '##'
+ },
+ {
+ text: '### h3',
+ search: '###'
+ },
+ {
+ text: '#### h4',
+ search: '####'
+ },
+ {
+ text: '##### h5',
+ search: '#####'
+ },
+ {
+ text: '###### h6',
+ search: '######'
+ },
+ {
+ text: '###### tags: `example`',
+ search: '###### tags:'
+ }
+]
var supportReferrals = [
- {
- text: '[reference link]',
- search: '[]'
- },
- {
- text: '[reference]: https:// "title"',
- search: '[]:'
- },
- {
- text: '[^footnote link]',
- search: '[^]'
- },
- {
- text: '[^footnote reference]: https:// "title"',
- search: '[^]:'
- },
- {
- text: '^[inline footnote]',
- search: '^[]'
- },
- {
- text: '[link text][reference]',
- search: '[][]'
- },
- {
- text: '[link text](https:// "title")',
- search: '[]()'
- },
- {
- text: '![image alt][reference]',
- search: '![][]'
- },
- {
- text: '![image alt](https:// "title")',
- search: '![]()'
- },
- {
- text: '![image alt](https:// "title" =WidthxHeight)',
- search: '![]()'
- },
- {
- text: '[TOC]',
- search: '[]'
- }
-];
+ {
+ text: '[reference link]',
+ search: '[]'
+ },
+ {
+ text: '[reference]: https:// "title"',
+ search: '[]:'
+ },
+ {
+ text: '[^footnote link]',
+ search: '[^]'
+ },
+ {
+ text: '[^footnote reference]: https:// "title"',
+ search: '[^]:'
+ },
+ {
+ text: '^[inline footnote]',
+ search: '^[]'
+ },
+ {
+ text: '[link text][reference]',
+ search: '[][]'
+ },
+ {
+ text: '[link text](https:// "title")',
+ search: '[]()'
+ },
+ {
+ text: '![image alt][reference]',
+ search: '![][]'
+ },
+ {
+ text: '![image alt](https:// "title")',
+ search: '![]()'
+ },
+ {
+ text: '![image alt](https:// "title" =WidthxHeight)',
+ search: '![]()'
+ },
+ {
+ text: '[TOC]',
+ search: '[]'
+ }
+]
var supportExternals = [
- {
- text: '{%youtube youtubeid %}',
- search: 'youtube'
- },
- {
- text: '{%vimeo vimeoid %}',
- search: 'vimeo'
- },
- {
- text: '{%gist gistid %}',
- search: 'gist'
- },
- {
- text: '{%slideshare slideshareid %}',
- search: 'slideshare'
- },
- {
- text: '{%speakerdeck speakerdeckid %}',
- search: 'speakerdeck'
- },
- {
- text: '{%pdf pdfurl %}',
- search: 'pdf'
- }
-];
+ {
+ text: '{%youtube youtubeid %}',
+ search: 'youtube'
+ },
+ {
+ text: '{%vimeo vimeoid %}',
+ search: 'vimeo'
+ },
+ {
+ text: '{%gist gistid %}',
+ search: 'gist'
+ },
+ {
+ text: '{%slideshare slideshareid %}',
+ search: 'slideshare'
+ },
+ {
+ text: '{%speakerdeck speakerdeckid %}',
+ search: 'speakerdeck'
+ },
+ {
+ text: '{%pdf pdfurl %}',
+ search: 'pdf'
+ }
+]
var supportExtraTags = [
- {
- text: '[name tag]',
- search: '[]',
- command: function () {
- return '[name=' + personalInfo.name + ']';
- },
- },
- {
- text: '[time tag]',
- search: '[]',
- command: function () {
- return '[time=' + moment().format('llll') + ']';
- },
- },
- {
- text: '[my color tag]',
- search: '[]',
- command: function () {
- return '[color=' + personalInfo.color + ']';
- }
- },
- {
- text: '[random color tag]',
- search: '[]',
- command: function () {
- var color = randomColor();
- return '[color=' + color + ']';
- }
- }
-];
+ {
+ text: '[name tag]',
+ search: '[]',
+ command: function () {
+ return '[name=' + window.personalInfo.name + ']'
+ }
+ },
+ {
+ text: '[time tag]',
+ search: '[]',
+ command: function () {
+ return '[time=' + moment().format('llll') + ']'
+ }
+ },
+ {
+ text: '[my color tag]',
+ search: '[]',
+ command: function () {
+ return '[color=' + window.personalInfo.color + ']'
+ }
+ },
+ {
+ text: '[random color tag]',
+ search: '[]',
+ command: function () {
+ var color = randomColor()
+ return '[color=' + color + ']'
+ }
+ }
+]
window.modeType = {
- edit: {
- name: "edit"
- },
- view: {
- name: "view"
- },
- both: {
- name: "both"
- }
-};
+ edit: {
+ name: 'edit'
+ },
+ view: {
+ name: 'view'
+ },
+ both: {
+ name: 'both'
+ }
+}
var statusType = {
- connected: {
- msg: "CONNECTED",
- label: "label-warning",
- fa: "fa-wifi"
- },
- online: {
- msg: "ONLINE",
- label: "label-primary",
- fa: "fa-users"
- },
- offline: {
- msg: "OFFLINE",
- label: "label-danger",
- fa: "fa-plug"
- }
-};
-var defaultMode = modeType.view;
-
-//global vars
-window.loaded = false;
-window.needRefresh = false;
-window.isDirty = false;
-window.editShown = false;
-window.visibleXS = false;
-window.visibleSM = false;
-window.visibleMD = false;
-window.visibleLG = false;
-window.isTouchDevice = 'ontouchstart' in document.documentElement;
-window.currentMode = defaultMode;
-window.currentStatus = statusType.offline;
+ connected: {
+ msg: 'CONNECTED',
+ label: 'label-warning',
+ fa: 'fa-wifi'
+ },
+ online: {
+ msg: 'ONLINE',
+ label: 'label-primary',
+ fa: 'fa-users'
+ },
+ offline: {
+ msg: 'OFFLINE',
+ label: 'label-danger',
+ fa: 'fa-plug'
+ }
+}
+var defaultMode = modeType.view
+
+// global vars
+window.loaded = false
+window.needRefresh = false
+window.isDirty = false
+window.editShown = false
+window.visibleXS = false
+window.visibleSM = false
+window.visibleMD = false
+window.visibleLG = false
+window.isTouchDevice = 'ontouchstart' in document.documentElement
+window.currentMode = defaultMode
+window.currentStatus = statusType.offline
window.lastInfo = {
- needRestore: false,
- cursor: null,
- scroll: null,
- edit: {
- scroll: {
- left: null,
- top: null
- },
- cursor: {
- line: null,
- ch: null
- },
- selections: null
+ needRestore: false,
+ cursor: null,
+ scroll: null,
+ edit: {
+ scroll: {
+ left: null,
+ top: null
},
- view: {
- scroll: {
- left: null,
- top: null
- }
+ cursor: {
+ line: null,
+ ch: null
},
- history: null
-};
-window.personalInfo = {};
-window.onlineUsers = [];
+ selections: null
+ },
+ view: {
+ scroll: {
+ left: null,
+ top: null
+ }
+ },
+ history: null
+}
+window.personalInfo = {}
+window.onlineUsers = []
window.fileTypes = {
- "pl": "perl",
- "cgi": "perl",
- "js": "javascript",
- "php": "php",
- "sh": "bash",
- "rb": "ruby",
- "html": "html",
- "py": "python"
-};
+ 'pl': 'perl',
+ 'cgi': 'perl',
+ 'js': 'javascript',
+ 'php': 'php',
+ 'sh': 'bash',
+ 'rb': 'ruby',
+ 'html': 'html',
+ 'py': 'python'
+}
// editor settings
-var textit = document.getElementById("textit");
+var textit = document.getElementById('textit')
if (!textit) {
- throw new Error("There was no textit area!");
+ throw new Error('There was no textit area!')
}
-const editorInstance = new Editor();
-var editor = editorInstance.init(textit);
+const editorInstance = new Editor()
+var editor = editorInstance.init(textit)
// TODO: global referncing in jquery-textcomplete patch
-window.editor = editor;
-
-var inlineAttach = inlineAttachment.editors.codemirror4.attach(editor);
-defaultTextHeight = parseInt($(".CodeMirror").css('line-height'));
-
-var selection = null;
-
-function updateStatusBar() {
- if (!editorInstance.statusBar) return;
- var cursor = editor.getCursor();
- var cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1);
- if (selection) {
- var anchor = selection.anchor;
- var head = selection.head;
- var start = head.line <= anchor.line ? head : anchor;
- var end = head.line >= anchor.line ? head : anchor;
- var selectionText = ' — Selected ';
- var selectionCharCount = Math.abs(head.ch - anchor.ch);
- // borrow from brackets EditorStatusBar.js
- if (start.line !== end.line) {
- var lines = end.line - start.line + 1;
- if (end.ch === 0) {
- lines--;
- }
- selectionText += lines + ' lines';
- } else if (selectionCharCount > 0)
- selectionText += selectionCharCount + ' columns';
- if (start.line !== end.line || selectionCharCount > 0)
- cursorText += selectionText;
- }
- editorInstance.statusCursor.text(cursorText);
- var fileText = ' — ' + editor.lineCount() + ' Lines';
- editorInstance.statusFile.text(fileText);
- var docLength = editor.getValue().length;
- editorInstance.statusLength.text('Length ' + docLength);
- if (docLength > (docmaxlength * 0.95)) {
- editorInstance.statusLength.css('color', 'red');
- editorInstance.statusLength.attr('title', 'Your almost reach note max length limit.');
- } else if (docLength > (docmaxlength * 0.8)) {
- editorInstance.statusLength.css('color', 'orange');
- editorInstance.statusLength.attr('title', 'You nearly fill the note, consider to make more pieces.');
- } else {
- editorInstance.statusLength.css('color', 'white');
- editorInstance.statusLength.attr('title', 'You could write up to ' + docmaxlength + ' characters in this note.');
- }
+window.editor = editor
+
+var inlineAttach = inlineAttachment.editors.codemirror4.attach(editor)
+defaultTextHeight = parseInt($('.CodeMirror').css('line-height'))
+
+var selection = null
+
+function updateStatusBar () {
+ if (!editorInstance.statusBar) return
+ var cursor = editor.getCursor()
+ var cursorText = 'Line ' + (cursor.line + 1) + ', Columns ' + (cursor.ch + 1)
+ if (selection) {
+ var anchor = selection.anchor
+ var head = selection.head
+ var start = head.line <= anchor.line ? head : anchor
+ var end = head.line >= anchor.line ? head : anchor
+ var selectionText = ' — Selected '
+ var selectionCharCount = Math.abs(head.ch - anchor.ch)
+ // borrow from brackets EditorStatusBar.js
+ if (start.line !== end.line) {
+ var lines = end.line - start.line + 1
+ if (end.ch === 0) {
+ lines--
+ }
+ selectionText += lines + ' lines'
+ } else if (selectionCharCount > 0) {
+ selectionText += selectionCharCount + ' columns'
+ }
+ if (start.line !== end.line || selectionCharCount > 0) {
+ cursorText += selectionText
+ }
+ }
+ editorInstance.statusCursor.text(cursorText)
+ var fileText = ' — ' + editor.lineCount() + ' Lines'
+ editorInstance.statusFile.text(fileText)
+ var docLength = editor.getValue().length
+ editorInstance.statusLength.text('Length ' + docLength)
+ if (docLength > (docmaxlength * 0.95)) {
+ editorInstance.statusLength.css('color', 'red')
+ editorInstance.statusLength.attr('title', 'Your almost reach note max length limit.')
+ } else if (docLength > (docmaxlength * 0.8)) {
+ editorInstance.statusLength.css('color', 'orange')
+ editorInstance.statusLength.attr('title', 'You nearly fill the note, consider to make more pieces.')
+ } else {
+ editorInstance.statusLength.css('color', 'white')
+ editorInstance.statusLength.attr('title', 'You could write up to ' + docmaxlength + ' characters in this note.')
+ }
}
// initalize ui reference
-const ui = getUIElements();
+const ui = getUIElements()
-//page actions
+// page actions
var opts = {
- lines: 11, // The number of lines to draw
- length: 20, // The length of each line
- width: 2, // The line thickness
- radius: 30, // The radius of the inner circle
- corners: 0, // Corner roundness (0..1)
- rotate: 0, // The rotation offset
- direction: 1, // 1: clockwise, -1: counterclockwise
- color: '#000', // #rgb or #rrggbb or array of colors
- speed: 1.1, // Rounds per second
- trail: 60, // Afterglow percentage
- shadow: false, // Whether to render a shadow
- hwaccel: true, // Whether to use hardware acceleration
- className: 'spinner', // The CSS class to assign to the spinner
- zIndex: 2e9, // The z-index (defaults to 2000000000)
- top: '50%', // Top position relative to parent
- left: '50%' // Left position relative to parent
-};
-var spinner = new Spinner(opts).spin(ui.spinner[0]);
-
-//idle
+ lines: 11, // The number of lines to draw
+ length: 20, // The length of each line
+ width: 2, // The line thickness
+ radius: 30, // The radius of the inner circle
+ corners: 0, // Corner roundness (0..1)
+ rotate: 0, // The rotation offset
+ direction: 1, // 1: clockwise, -1: counterclockwise
+ color: '#000', // #rgb or #rrggbb or array of colors
+ speed: 1.1, // Rounds per second
+ trail: 60, // Afterglow percentage
+ shadow: false, // Whether to render a shadow
+ hwaccel: true, // Whether to use hardware acceleration
+ className: 'spinner', // The CSS class to assign to the spinner
+ zIndex: 2e9, // The z-index (defaults to 2000000000)
+ top: '50%', // Top position relative to parent
+ left: '50%' // Left position relative to parent
+}
+
+/* eslint-disable no-unused-vars */
+var spinner = new Spinner(opts).spin(ui.spinner[0])
+/* eslint-enable no-unused-vars */
+
+// idle
var idle = new Idle({
- onAway: function () {
- idle.isAway = true;
- emitUserStatus();
- updateOnlineStatus();
- },
- onAwayBack: function () {
- idle.isAway = false;
- emitUserStatus();
- updateOnlineStatus();
- setHaveUnreadChanges(false);
- updateTitleReminder();
- },
- awayTimeout: idleTime
-});
+ onAway: function () {
+ idle.isAway = true
+ emitUserStatus()
+ updateOnlineStatus()
+ },
+ onAwayBack: function () {
+ idle.isAway = false
+ emitUserStatus()
+ updateOnlineStatus()
+ setHaveUnreadChanges(false)
+ updateTitleReminder()
+ },
+ awayTimeout: idleTime
+})
ui.area.codemirror.on('touchstart', function () {
- idle.onActive();
-});
+ idle.onActive()
+})
-var haveUnreadChanges = false;
+var haveUnreadChanges = false
-function setHaveUnreadChanges(bool) {
- if (!loaded) return;
- if (bool && (idle.isAway || Visibility.hidden())) {
- haveUnreadChanges = true;
- } else if (!bool && !idle.isAway && !Visibility.hidden()) {
- haveUnreadChanges = false;
- }
+function setHaveUnreadChanges (bool) {
+ if (!window.loaded) return
+ if (bool && (idle.isAway || Visibility.hidden())) {
+ haveUnreadChanges = true
+ } else if (!bool && !idle.isAway && !Visibility.hidden()) {
+ haveUnreadChanges = false
+ }
}
-function updateTitleReminder() {
- if (!loaded) return;
- if (haveUnreadChanges) {
- document.title = '• ' + renderTitle(ui.area.markdown);
- } else {
- document.title = renderTitle(ui.area.markdown);
- }
+function updateTitleReminder () {
+ if (!window.loaded) return
+ if (haveUnreadChanges) {
+ document.title = '• ' + renderTitle(ui.area.markdown)
+ } else {
+ document.title = renderTitle(ui.area.markdown)
+ }
}
-function setRefreshModal(status) {
- $('#refreshModal').modal('show');
- $('#refreshModal').find('.modal-body > div').hide();
- $('#refreshModal').find('.' + status).show();
+function setRefreshModal (status) {
+ $('#refreshModal').modal('show')
+ $('#refreshModal').find('.modal-body > div').hide()
+ $('#refreshModal').find('.' + status).show()
}
-function setNeedRefresh() {
- needRefresh = true;
- editor.setOption('readOnly', true);
- socket.disconnect();
- showStatus(statusType.offline);
+function setNeedRefresh () {
+ window.needRefresh = true
+ editor.setOption('readOnly', true)
+ socket.disconnect()
+ showStatus(statusType.offline)
}
setloginStateChangeEvent(function () {
- setRefreshModal('user-state-changed');
- setNeedRefresh();
-});
+ setRefreshModal('user-state-changed')
+ setNeedRefresh()
+})
-//visibility
-var wasFocus = false;
+// visibility
+var wasFocus = false
Visibility.change(function (e, state) {
- var hidden = Visibility.hidden();
- if (hidden) {
- if (editorHasFocus()) {
- wasFocus = true;
- editor.getInputField().blur();
- }
- } else {
- if (wasFocus) {
- if (!visibleXS) {
- editor.focus();
- editor.refresh();
- }
- wasFocus = false;
- }
- setHaveUnreadChanges(false);
- }
- updateTitleReminder();
-});
+ var hidden = Visibility.hidden()
+ if (hidden) {
+ if (editorHasFocus()) {
+ wasFocus = true
+ editor.getInputField().blur()
+ }
+ } else {
+ if (wasFocus) {
+ if (!window.visibleXS) {
+ editor.focus()
+ editor.refresh()
+ }
+ wasFocus = false
+ }
+ setHaveUnreadChanges(false)
+ }
+ updateTitleReminder()
+})
-//when page ready
+// when page ready
$(document).ready(function () {
- idle.checkAway();
- checkResponsive();
- //if in smaller screen, we don't need advanced scrollbar
- var scrollbarStyle;
- if (visibleXS) {
- scrollbarStyle = 'native';
- } else {
- scrollbarStyle = 'overlay';
- }
- if (scrollbarStyle != editor.getOption('scrollbarStyle')) {
- editor.setOption('scrollbarStyle', scrollbarStyle);
- clearMap();
- }
- checkEditorStyle();
+ idle.checkAway()
+ checkResponsive()
+ // if in smaller screen, we don't need advanced scrollbar
+ var scrollbarStyle
+ if (window.visibleXS) {
+ scrollbarStyle = 'native'
+ } else {
+ scrollbarStyle = 'overlay'
+ }
+ if (scrollbarStyle !== editor.getOption('scrollbarStyle')) {
+ editor.setOption('scrollbarStyle', scrollbarStyle)
+ clearMap()
+ }
+ checkEditorStyle()
/* we need this only on touch devices */
- if (isTouchDevice) {
+ if (window.isTouchDevice) {
/* cache dom references */
- var $body = jQuery('body');
+ var $body = jQuery('body')
/* bind events */
- $(document)
+ $(document)
.on('focus', 'textarea, input', function () {
- $body.addClass('fixfixed');
+ $body.addClass('fixfixed')
})
.on('blur', 'textarea, input', function () {
- $body.removeClass('fixfixed');
- });
- }
- //showup
- $().showUp('.navbar', {
- upClass: 'navbar-hide',
- downClass: 'navbar-show'
- });
- //tooltip
- $('[data-toggle="tooltip"]').tooltip();
+ $body.removeClass('fixfixed')
+ })
+ }
+ // showup
+ $().showUp('.navbar', {
+ upClass: 'navbar-hide',
+ downClass: 'navbar-show'
+ })
+ // tooltip
+ $('[data-toggle="tooltip"]').tooltip()
// shortcuts
// allow on all tags
- key.filter = function (e) { return true; };
- key('ctrl+alt+e', function (e) {
- changeMode(modeType.edit);
- });
- key('ctrl+alt+v', function (e) {
- changeMode(modeType.view);
- });
- key('ctrl+alt+b', function (e) {
- changeMode(modeType.both);
- });
+ key.filter = function (e) { return true }
+ key('ctrl+alt+e', function (e) {
+ changeMode(modeType.edit)
+ })
+ key('ctrl+alt+v', function (e) {
+ changeMode(modeType.view)
+ })
+ key('ctrl+alt+b', function (e) {
+ changeMode(modeType.both)
+ })
// toggle-dropdown
- $(document).on('click', '.toggle-dropdown .dropdown-menu', function (e) {
- e.stopPropagation();
- });
-});
-//when page resize
+ $(document).on('click', '.toggle-dropdown .dropdown-menu', function (e) {
+ e.stopPropagation()
+ })
+})
+// when page resize
$(window).resize(function () {
- checkLayout();
- checkEditorStyle();
- checkTocStyle();
- checkCursorMenu();
- windowResize();
-});
-//when page unload
+ checkLayout()
+ checkEditorStyle()
+ checkTocStyle()
+ checkCursorMenu()
+ windowResize()
+})
+// when page unload
$(window).on('unload', function () {
- //updateHistoryInner();
-});
+ // updateHistoryInner();
+})
$(window).on('error', function () {
- //setNeedRefresh();
-});
-
-setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown);
+ // setNeedRefresh();
+})
-function autoSyncscroll() {
- if (editorHasFocus()) {
- syncScrollToView();
+setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown)
+
+function autoSyncscroll () {
+ if (editorHasFocus()) {
+ syncScrollToView()
+ } else {
+ syncScrollToEdit()
+ }
+}
+
+var windowResizeDebounce = 200
+var windowResize = _.debounce(windowResizeInner, windowResizeDebounce)
+
+function windowResizeInner (callback) {
+ checkLayout()
+ checkResponsive()
+ checkEditorStyle()
+ checkTocStyle()
+ checkCursorMenu()
+ // refresh editor
+ if (window.loaded) {
+ if (editor.getOption('scrollbarStyle') === 'native') {
+ setTimeout(function () {
+ clearMap()
+ autoSyncscroll()
+ updateScrollspy()
+ if (callback && typeof callback === 'function') { callback() }
+ }, 1)
} else {
- syncScrollToEdit();
- }
-}
-
-var windowResizeDebounce = 200;
-var windowResize = _.debounce(windowResizeInner, windowResizeDebounce);
-
-function windowResizeInner(callback) {
- checkLayout();
- checkResponsive();
- checkEditorStyle();
- checkTocStyle();
- checkCursorMenu();
- //refresh editor
- if (loaded) {
- if (editor.getOption('scrollbarStyle') === 'native') {
- setTimeout(function () {
- clearMap();
- autoSyncscroll();
- updateScrollspy();
- if (callback && typeof callback === 'function')
- callback();
- }, 1);
- } else {
// force it load all docs at once to prevent scroll knob blink
- editor.setOption('viewportMargin', Infinity);
- setTimeout(function () {
- clearMap();
- autoSyncscroll();
- editor.setOption('viewportMargin', viewportMargin);
- //add or update user cursors
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id != personalInfo.id)
- buildCursor(onlineUsers[i]);
- }
- updateScrollspy();
- if (callback && typeof callback === 'function')
- callback();
- }, 1);
+ editor.setOption('viewportMargin', Infinity)
+ setTimeout(function () {
+ clearMap()
+ autoSyncscroll()
+ editor.setOption('viewportMargin', viewportMargin)
+ // add or update user cursors
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id !== window.personalInfo.id) { buildCursor(window.onlineUsers[i]) }
}
+ updateScrollspy()
+ if (callback && typeof callback === 'function') { callback() }
+ }, 1)
}
+ }
}
-function checkLayout() {
- var navbarHieght = $('.navbar').outerHeight();
- $('body').css('padding-top', navbarHieght + 'px');
+function checkLayout () {
+ var navbarHieght = $('.navbar').outerHeight()
+ $('body').css('padding-top', navbarHieght + 'px')
}
-function editorHasFocus() {
- return $(editor.getInputField()).is(":focus");
+function editorHasFocus () {
+ return $(editor.getInputField()).is(':focus')
}
-//768-792px have a gap
-function checkResponsive() {
- visibleXS = $(".visible-xs").is(":visible");
- visibleSM = $(".visible-sm").is(":visible");
- visibleMD = $(".visible-md").is(":visible");
- visibleLG = $(".visible-lg").is(":visible");
+// 768-792px have a gap
+function checkResponsive () {
+ window.visibleXS = $('.visible-xs').is(':visible')
+ window.visibleSM = $('.visible-sm').is(':visible')
+ window.visibleMD = $('.visible-md').is(':visible')
+ window.visibleLG = $('.visible-lg').is(':visible')
- if (visibleXS && currentMode == modeType.both)
- if (editorHasFocus())
- changeMode(modeType.edit);
- else
- changeMode(modeType.view);
+ if (window.visibleXS && window.currentMode === modeType.both) {
+ if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) }
+ }
- emitUserStatus();
+ emitUserStatus()
}
-var lastEditorWidth = 0;
-var previousFocusOnEditor = null;
+var lastEditorWidth = 0
+var previousFocusOnEditor = null
-function checkEditorStyle() {
- var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height();
+function checkEditorStyle () {
+ var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height()
// set editor height and min height based on scrollbar style and mode
- var scrollbarStyle = editor.getOption('scrollbarStyle');
- if (scrollbarStyle == 'overlay' || currentMode == modeType.both) {
- ui.area.codemirrorScroll.css('height', desireHeight + 'px');
- ui.area.codemirrorScroll.css('min-height', '');
- checkEditorScrollbar();
- } else if (scrollbarStyle == 'native') {
- ui.area.codemirrorScroll.css('height', '');
- ui.area.codemirrorScroll.css('min-height', desireHeight + 'px');
- }
+ var scrollbarStyle = editor.getOption('scrollbarStyle')
+ if (scrollbarStyle === 'overlay' || window.currentMode === modeType.both) {
+ ui.area.codemirrorScroll.css('height', desireHeight + 'px')
+ ui.area.codemirrorScroll.css('min-height', '')
+ checkEditorScrollbar()
+ } else if (scrollbarStyle === 'native') {
+ ui.area.codemirrorScroll.css('height', '')
+ ui.area.codemirrorScroll.css('min-height', desireHeight + 'px')
+ }
// workaround editor will have wrong doc height when editor height changed
- editor.setSize(null, ui.area.edit.height());
- //make editor resizable
- if (!ui.area.resize.handle.length) {
- ui.area.edit.resizable({
- handles: 'e',
- maxWidth: $(window).width() * 0.7,
- minWidth: $(window).width() * 0.2,
- create: function (e, ui) {
- $(this).parent().on('resize', function (e) {
- e.stopPropagation();
- });
- },
- start: function (e) {
- editor.setOption('viewportMargin', Infinity);
- },
- resize: function (e) {
- ui.area.resize.syncToggle.stop(true, true).show();
- checkTocStyle();
- },
- stop: function (e) {
- lastEditorWidth = ui.area.edit.width();
+ editor.setSize(null, ui.area.edit.height())
+ // make editor resizable
+ if (!ui.area.resize.handle.length) {
+ ui.area.edit.resizable({
+ handles: 'e',
+ maxWidth: $(window).width() * 0.7,
+ minWidth: $(window).width() * 0.2,
+ create: function (e, ui) {
+ $(this).parent().on('resize', function (e) {
+ e.stopPropagation()
+ })
+ },
+ start: function (e) {
+ editor.setOption('viewportMargin', Infinity)
+ },
+ resize: function (e) {
+ ui.area.resize.syncToggle.stop(true, true).show()
+ checkTocStyle()
+ },
+ stop: function (e) {
+ lastEditorWidth = ui.area.edit.width()
// workaround that scroll event bindings
- preventSyncScrollToView = 2;
- preventSyncScrollToEdit = true;
- editor.setOption('viewportMargin', viewportMargin);
- if (editorHasFocus()) {
- windowResizeInner(function () {
- ui.area.codemirrorScroll.scroll();
- });
- } else {
- windowResizeInner(function () {
- ui.area.view.scroll();
- });
- }
- checkEditorScrollbar();
- }
- });
- ui.area.resize.handle = $('.ui-resizable-handle');
- }
- if (!ui.area.resize.syncToggle.length) {
- ui.area.resize.syncToggle = $('<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>');
- ui.area.resize.syncToggle.hover(function () {
- previousFocusOnEditor = editorHasFocus();
- }, function () {
- previousFocusOnEditor = null;
- });
- ui.area.resize.syncToggle.click(function () {
- syncscroll = !syncscroll;
- checkSyncToggle();
- });
- ui.area.resize.handle.append(ui.area.resize.syncToggle);
- ui.area.resize.syncToggle.hide();
- ui.area.resize.handle.hover(function () {
- ui.area.resize.syncToggle.stop(true, true).delay(200).fadeIn(100);
- }, function () {
- ui.area.resize.syncToggle.stop(true, true).delay(300).fadeOut(300);
- });
- }
-}
-
-function checkSyncToggle() {
- if (syncscroll) {
- if (previousFocusOnEditor) {
- preventSyncScrollToView = false;
- syncScrollToView();
+ window.preventSyncScrollToView = 2
+ window.preventSyncScrollToEdit = true
+ editor.setOption('viewportMargin', viewportMargin)
+ if (editorHasFocus()) {
+ windowResizeInner(function () {
+ ui.area.codemirrorScroll.scroll()
+ })
} else {
- preventSyncScrollToEdit = false;
- syncScrollToEdit();
+ windowResizeInner(function () {
+ ui.area.view.scroll()
+ })
}
- ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link');
+ checkEditorScrollbar()
+ }
+ })
+ ui.area.resize.handle = $('.ui-resizable-handle')
+ }
+ if (!ui.area.resize.syncToggle.length) {
+ ui.area.resize.syncToggle = $('<button class="btn btn-lg btn-default ui-sync-toggle" title="Toggle sync scrolling"><i class="fa fa-link fa-fw"></i></button>')
+ ui.area.resize.syncToggle.hover(function () {
+ previousFocusOnEditor = editorHasFocus()
+ }, function () {
+ previousFocusOnEditor = null
+ })
+ ui.area.resize.syncToggle.click(function () {
+ window.syncscroll = !window.syncscroll
+ checkSyncToggle()
+ })
+ ui.area.resize.handle.append(ui.area.resize.syncToggle)
+ ui.area.resize.syncToggle.hide()
+ ui.area.resize.handle.hover(function () {
+ ui.area.resize.syncToggle.stop(true, true).delay(200).fadeIn(100)
+ }, function () {
+ ui.area.resize.syncToggle.stop(true, true).delay(300).fadeOut(300)
+ })
+ }
+}
+
+function checkSyncToggle () {
+ if (window.syncscroll) {
+ if (previousFocusOnEditor) {
+ window.preventSyncScrollToView = false
+ syncScrollToView()
} else {
- ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink');
+ window.preventSyncScrollToEdit = false
+ syncScrollToEdit()
}
+ ui.area.resize.syncToggle.find('i').removeClass('fa-unlink').addClass('fa-link')
+ } else {
+ ui.area.resize.syncToggle.find('i').removeClass('fa-link').addClass('fa-unlink')
+ }
}
var checkEditorScrollbar = _.debounce(function () {
- editor.operation(checkEditorScrollbarInner);
-}, 50);
+ editor.operation(checkEditorScrollbarInner)
+}, 50)
-function checkEditorScrollbarInner() {
+function checkEditorScrollbarInner () {
// workaround simple scroll bar knob
// will get wrong position when editor height changed
- var scrollInfo = editor.getScrollInfo();
- editor.scrollTo(null, scrollInfo.top - 1);
- editor.scrollTo(null, scrollInfo.top);
-}
-
-function checkTocStyle() {
- //toc right
- var paddingRight = parseFloat(ui.area.markdown.css('padding-right'));
- var right = ($(window).width() - (ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - paddingRight));
- ui.toc.toc.css('right', right + 'px');
- //affix toc left
- var newbool;
- var rightMargin = (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) / 2;
- //for ipad or wider device
- if (rightMargin >= 133) {
- newbool = true;
- var affixLeftMargin = (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2;
- var left = ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - affixLeftMargin;
- ui.toc.affix.css('left', left + 'px');
- ui.toc.affix.css('width', rightMargin + 'px');
- } else {
- newbool = false;
- }
- //toc scrollspy
- ui.toc.toc.removeClass('scrollspy-body, scrollspy-view');
- ui.toc.affix.removeClass('scrollspy-body, scrollspy-view');
- if (currentMode == modeType.both) {
- ui.toc.toc.addClass('scrollspy-view');
- ui.toc.affix.addClass('scrollspy-view');
- } else if (currentMode != modeType.both && !newbool) {
- ui.toc.toc.addClass('scrollspy-body');
- ui.toc.affix.addClass('scrollspy-body');
- } else {
- ui.toc.toc.addClass('scrollspy-view');
- ui.toc.affix.addClass('scrollspy-body');
- }
- if (newbool != enoughForAffixToc) {
- enoughForAffixToc = newbool;
- generateScrollspy();
- }
-}
-
-function showStatus(type, num) {
- currentStatus = type;
- var shortStatus = ui.toolbar.shortStatus;
- var status = ui.toolbar.status;
- var label = $('<span class="label"></span>');
- var fa = $('<i class="fa"></i>');
- var msg = "";
- var shortMsg = "";
-
- shortStatus.html("");
- status.html("");
-
- switch (currentStatus) {
- case statusType.connected:
- label.addClass(statusType.connected.label);
- fa.addClass(statusType.connected.fa);
- msg = statusType.connected.msg;
- break;
- case statusType.online:
- label.addClass(statusType.online.label);
- fa.addClass(statusType.online.fa);
- shortMsg = num;
- msg = num + " " + statusType.online.msg;
- break;
- case statusType.offline:
- label.addClass(statusType.offline.label);
- fa.addClass(statusType.offline.fa);
- msg = statusType.offline.msg;
- break;
- }
-
- label.append(fa);
- var shortLabel = label.clone();
-
- shortLabel.append(" " + shortMsg);
- shortStatus.append(shortLabel);
-
- label.append(" " + msg);
- status.append(label);
-}
-
-function toggleMode() {
- switch (currentMode) {
- case modeType.edit:
- changeMode(modeType.view);
- break;
- case modeType.view:
- changeMode(modeType.edit);
- break;
- case modeType.both:
- changeMode(modeType.view);
- break;
- }
-}
-
-var lastMode = null;
-
-function changeMode(type) {
+ var scrollInfo = editor.getScrollInfo()
+ editor.scrollTo(null, scrollInfo.top - 1)
+ editor.scrollTo(null, scrollInfo.top)
+}
+
+function checkTocStyle () {
+ // toc right
+ var paddingRight = parseFloat(ui.area.markdown.css('padding-right'))
+ var right = ($(window).width() - (ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - paddingRight))
+ ui.toc.toc.css('right', right + 'px')
+ // affix toc left
+ var newbool
+ var rightMargin = (ui.area.markdown.parent().outerWidth() - ui.area.markdown.outerWidth()) / 2
+ // for ipad or wider device
+ if (rightMargin >= 133) {
+ newbool = true
+ var affixLeftMargin = (ui.toc.affix.outerWidth() - ui.toc.affix.width()) / 2
+ var left = ui.area.markdown.offset().left + ui.area.markdown.outerWidth() - affixLeftMargin
+ ui.toc.affix.css('left', left + 'px')
+ ui.toc.affix.css('width', rightMargin + 'px')
+ } else {
+ newbool = false
+ }
+ // toc scrollspy
+ ui.toc.toc.removeClass('scrollspy-body, scrollspy-view')
+ ui.toc.affix.removeClass('scrollspy-body, scrollspy-view')
+ if (window.currentMode === modeType.both) {
+ ui.toc.toc.addClass('scrollspy-view')
+ ui.toc.affix.addClass('scrollspy-view')
+ } else if (window.currentMode !== modeType.both && !newbool) {
+ ui.toc.toc.addClass('scrollspy-body')
+ ui.toc.affix.addClass('scrollspy-body')
+ } else {
+ ui.toc.toc.addClass('scrollspy-view')
+ ui.toc.affix.addClass('scrollspy-body')
+ }
+ if (newbool !== enoughForAffixToc) {
+ enoughForAffixToc = newbool
+ generateScrollspy()
+ }
+}
+
+function showStatus (type, num) {
+ window.currentStatus = type
+ var shortStatus = ui.toolbar.shortStatus
+ var status = ui.toolbar.status
+ var label = $('<span class="label"></span>')
+ var fa = $('<i class="fa"></i>')
+ var msg = ''
+ var shortMsg = ''
+
+ shortStatus.html('')
+ status.html('')
+
+ switch (window.currentStatus) {
+ case statusType.connected:
+ label.addClass(statusType.connected.label)
+ fa.addClass(statusType.connected.fa)
+ msg = statusType.connected.msg
+ break
+ case statusType.online:
+ label.addClass(statusType.online.label)
+ fa.addClass(statusType.online.fa)
+ shortMsg = num
+ msg = num + ' ' + statusType.online.msg
+ break
+ case statusType.offline:
+ label.addClass(statusType.offline.label)
+ fa.addClass(statusType.offline.fa)
+ msg = statusType.offline.msg
+ break
+ }
+
+ label.append(fa)
+ var shortLabel = label.clone()
+
+ shortLabel.append(' ' + shortMsg)
+ shortStatus.append(shortLabel)
+
+ label.append(' ' + msg)
+ status.append(label)
+}
+
+function toggleMode () {
+ switch (window.currentMode) {
+ case modeType.edit:
+ changeMode(modeType.view)
+ break
+ case modeType.view:
+ changeMode(modeType.edit)
+ break
+ case modeType.both:
+ changeMode(modeType.view)
+ break
+ }
+}
+
+var lastMode = null
+
+function changeMode (type) {
// lock navbar to prevent it hide after changeMode
- lockNavbar();
- saveInfo();
- if (type) {
- lastMode = currentMode;
- currentMode = type;
- }
- var responsiveClass = "col-lg-6 col-md-6 col-sm-6";
- var scrollClass = "ui-scrollable";
- ui.area.codemirror.removeClass(scrollClass);
- ui.area.edit.removeClass(responsiveClass);
- ui.area.view.removeClass(scrollClass);
- ui.area.view.removeClass(responsiveClass);
- switch (currentMode) {
- case modeType.edit:
- ui.area.edit.show();
- ui.area.view.hide();
- if (!editShown) {
- editor.refresh();
- editShown = true;
- }
- break;
- case modeType.view:
- ui.area.edit.hide();
- ui.area.view.show();
- break;
- case modeType.both:
- ui.area.codemirror.addClass(scrollClass);
- ui.area.edit.addClass(responsiveClass).show();
- ui.area.view.addClass(scrollClass);
- ui.area.view.show();
- break;
- }
+ lockNavbar()
+ saveInfo()
+ if (type) {
+ lastMode = window.currentMode
+ window.currentMode = type
+ }
+ var responsiveClass = 'col-lg-6 col-md-6 col-sm-6'
+ var scrollClass = 'ui-scrollable'
+ ui.area.codemirror.removeClass(scrollClass)
+ ui.area.edit.removeClass(responsiveClass)
+ ui.area.view.removeClass(scrollClass)
+ ui.area.view.removeClass(responsiveClass)
+ switch (window.currentMode) {
+ case modeType.edit:
+ ui.area.edit.show()
+ ui.area.view.hide()
+ if (!window.editShown) {
+ editor.refresh()
+ window.editShown = true
+ }
+ break
+ case modeType.view:
+ ui.area.edit.hide()
+ ui.area.view.show()
+ break
+ case modeType.both:
+ ui.area.codemirror.addClass(scrollClass)
+ ui.area.edit.addClass(responsiveClass).show()
+ ui.area.view.addClass(scrollClass)
+ ui.area.view.show()
+ break
+ }
// save mode to url
- if (history.replaceState && loaded) history.replaceState(null, "", serverurl + '/' + noteid + '?' + currentMode.name);
- if (currentMode == modeType.view) {
- editor.getInputField().blur();
- }
- if (currentMode == modeType.edit || currentMode == modeType.both) {
- ui.toolbar.uploadImage.fadeIn();
- //add and update status bar
- if (!editorInstance.statusBar) {
- editorInstance.addStatusBar();
- updateStatusBar();
- }
- //work around foldGutter might not init properly
- editor.setOption('foldGutter', false);
- editor.setOption('foldGutter', true);
- } else {
- ui.toolbar.uploadImage.fadeOut();
- }
- if (currentMode != modeType.edit) {
- $(document.body).css('background-color', 'white');
- updateView();
+ if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + window.currentMode.name)
+ if (window.currentMode === modeType.view) {
+ editor.getInputField().blur()
+ }
+ if (window.currentMode === modeType.edit || window.currentMode === modeType.both) {
+ ui.toolbar.uploadImage.fadeIn()
+ // add and update status bar
+ if (!editorInstance.statusBar) {
+ editorInstance.addStatusBar()
+ updateStatusBar()
+ }
+ // work around foldGutter might not init properly
+ editor.setOption('foldGutter', false)
+ editor.setOption('foldGutter', true)
+ } else {
+ ui.toolbar.uploadImage.fadeOut()
+ }
+ if (window.currentMode !== modeType.edit) {
+ $(document.body).css('background-color', 'white')
+ updateView()
+ } else {
+ $(document.body).css('background-color', ui.area.codemirror.css('background-color'))
+ }
+ // check resizable editor style
+ if (window.currentMode === modeType.both) {
+ if (lastEditorWidth > 0) {
+ ui.area.edit.css('width', lastEditorWidth + 'px')
} else {
- $(document.body).css('background-color', ui.area.codemirror.css('background-color'));
- }
- //check resizable editor style
- if (currentMode == modeType.both) {
- if (lastEditorWidth > 0)
- ui.area.edit.css('width', lastEditorWidth + 'px');
- else
- ui.area.edit.css('width', '');
- ui.area.resize.handle.show();
- } else {
- ui.area.edit.css('width', '');
- ui.area.resize.handle.hide();
- }
-
- windowResizeInner();
-
- restoreInfo();
-
- if (lastMode == modeType.view && currentMode == modeType.both) {
- preventSyncScrollToView = 2;
- syncScrollToEdit(null, true);
- }
-
- if (lastMode == modeType.edit && currentMode == modeType.both) {
- preventSyncScrollToEdit = 2;
- syncScrollToView(null, true);
- }
-
- if (lastMode == modeType.both && currentMode != modeType.both) {
- preventSyncScrollToView = false;
- preventSyncScrollToEdit = false;
- }
-
- if (lastMode != modeType.edit && currentMode == modeType.edit) {
- editor.refresh();
- }
-
- $(document.body).scrollspy('refresh');
- ui.area.view.scrollspy('refresh');
-
- ui.toolbar.both.removeClass("active");
- ui.toolbar.edit.removeClass("active");
- ui.toolbar.view.removeClass("active");
- var modeIcon = ui.toolbar.mode.find('i');
- modeIcon.removeClass('fa-pencil').removeClass('fa-eye');
- if (ui.area.edit.is(":visible") && ui.area.view.is(":visible")) { //both
- ui.toolbar.both.addClass("active");
- modeIcon.addClass('fa-eye');
- } else if (ui.area.edit.is(":visible")) { //edit
- ui.toolbar.edit.addClass("active");
- modeIcon.addClass('fa-eye');
- } else if (ui.area.view.is(":visible")) { //view
- ui.toolbar.view.addClass("active");
- modeIcon.addClass('fa-pencil');
- }
- unlockNavbar();
-}
-
-function lockNavbar() {
- $('.navbar').addClass('locked');
+ ui.area.edit.css('width', '')
+ }
+ ui.area.resize.handle.show()
+ } else {
+ ui.area.edit.css('width', '')
+ ui.area.resize.handle.hide()
+ }
+
+ windowResizeInner()
+
+ restoreInfo()
+
+ if (lastMode === modeType.view && window.currentMode === modeType.both) {
+ window.preventSyncScrollToView = 2
+ syncScrollToEdit(null, true)
+ }
+
+ if (lastMode === modeType.edit && window.currentMode === modeType.both) {
+ window.preventSyncScrollToEdit = 2
+ syncScrollToView(null, true)
+ }
+
+ if (lastMode === modeType.both && window.currentMode !== modeType.both) {
+ window.preventSyncScrollToView = false
+ window.preventSyncScrollToEdit = false
+ }
+
+ if (lastMode !== modeType.edit && window.currentMode === modeType.edit) {
+ editor.refresh()
+ }
+
+ $(document.body).scrollspy('refresh')
+ ui.area.view.scrollspy('refresh')
+
+ ui.toolbar.both.removeClass('active')
+ ui.toolbar.edit.removeClass('active')
+ ui.toolbar.view.removeClass('active')
+ var modeIcon = ui.toolbar.mode.find('i')
+ modeIcon.removeClass('fa-pencil').removeClass('fa-eye')
+ if (ui.area.edit.is(':visible') && ui.area.view.is(':visible')) { // both
+ ui.toolbar.both.addClass('active')
+ modeIcon.addClass('fa-eye')
+ } else if (ui.area.edit.is(':visible')) { // edit
+ ui.toolbar.edit.addClass('active')
+ modeIcon.addClass('fa-eye')
+ } else if (ui.area.view.is(':visible')) { // view
+ ui.toolbar.view.addClass('active')
+ modeIcon.addClass('fa-pencil')
+ }
+ unlockNavbar()
+}
+
+function lockNavbar () {
+ $('.navbar').addClass('locked')
}
var unlockNavbar = _.debounce(function () {
- $('.navbar').removeClass('locked');
-}, 200);
-
-function closestIndex(arr, closestTo) {
- var closest = Math.max.apply(null, arr); //Get the highest number in arr in case it match nothing.
- var index = 0;
- for (var i = 0; i < arr.length; i++) { //Loop the array
- if (arr[i] >= closestTo && arr[i] < closest) {
- closest = arr[i]; //Check if it's higher than your number, but lower than your closest value
- index = i;
- }
- }
- return index; // return the value
-}
+ $('.navbar').removeClass('locked')
+}, 200)
-function showMessageModal(title, header, href, text, success) {
- var modal = $('.message-modal');
- modal.find('.modal-title').html(title);
- modal.find('.modal-body h5').html(header);
- if (href)
- modal.find('.modal-body a').attr('href', href).text(text);
- else
- modal.find('.modal-body a').removeAttr('href').text(text);
- modal.find('.modal-footer button').removeClass('btn-default btn-success btn-danger')
- if (success)
- modal.find('.modal-footer button').addClass('btn-success');
- else
- modal.find('.modal-footer button').addClass('btn-danger');
- modal.modal('show');
+function showMessageModal (title, header, href, text, success) {
+ var modal = $('.message-modal')
+ modal.find('.modal-title').html(title)
+ modal.find('.modal-body h5').html(header)
+ if (href) { modal.find('.modal-body a').attr('href', href).text(text) } else { modal.find('.modal-body a').removeAttr('href').text(text) }
+ modal.find('.modal-footer button').removeClass('btn-default btn-success btn-danger')
+ if (success) { modal.find('.modal-footer button').addClass('btn-success') } else { modal.find('.modal-footer button').addClass('btn-danger') }
+ modal.modal('show')
}
// check if dropbox app key is set and load scripts
if (DROPBOX_APP_KEY) {
- $('<script>')
+ $('<script>')
.attr('type', 'text/javascript')
.attr('src', 'https://www.dropbox.com/static/api/2/dropins.js')
.attr('id', 'dropboxjs')
.attr('data-app-key', DROPBOX_APP_KEY)
.prop('async', true)
.prop('defer', true)
- .appendTo('body');
+ .appendTo('body')
} else {
- ui.toolbar.import.dropbox.hide();
- ui.toolbar.export.dropbox.hide();
+ ui.toolbar.import.dropbox.hide()
+ ui.toolbar.export.dropbox.hide()
}
// check if google api key and client id are set and load scripts
if (GOOGLE_API_KEY && GOOGLE_CLIENT_ID) {
- $('<script>')
+ $('<script>')
.attr('type', 'text/javascript')
.attr('src', 'https://www.google.com/jsapi?callback=onGoogleAPILoaded')
.prop('async', true)
.prop('defer', true)
- .appendTo('body');
+ .appendTo('body')
} else {
- ui.toolbar.import.googleDrive.hide();
- ui.toolbar.export.googleDrive.hide();
+ ui.toolbar.import.googleDrive.hide()
+ ui.toolbar.export.googleDrive.hide()
}
-function onGoogleAPILoaded() {
- $('<script>')
+function onGoogleAPILoaded () {
+ $('<script>')
.attr('type', 'text/javascript')
.attr('src', 'https://apis.google.com/js/client:plusone.js?onload=onGoogleClientLoaded')
.prop('async', true)
.prop('defer', true)
- .appendTo('body');
+ .appendTo('body')
}
-window.onGoogleAPILoaded = onGoogleAPILoaded;
+window.onGoogleAPILoaded = onGoogleAPILoaded
-//button actions
-//share
-ui.toolbar.publish.attr("href", noteurl + "/publish");
+// button actions
+// share
+ui.toolbar.publish.attr('href', noteurl + '/publish')
// extra
-//slide
-ui.toolbar.extra.slide.attr("href", noteurl + "/slide");
-//download
-//markdown
+// slide
+ui.toolbar.extra.slide.attr('href', noteurl + '/slide')
+// download
+// markdown
ui.toolbar.download.markdown.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- var filename = renderFilename(ui.area.markdown) + '.md';
- var markdown = editor.getValue();
- var blob = new Blob([markdown], {
- type: "text/markdown;charset=utf-8"
- });
- saveAs(blob, filename, true);
-});
-//html
+ e.preventDefault()
+ e.stopPropagation()
+ var filename = renderFilename(ui.area.markdown) + '.md'
+ var markdown = editor.getValue()
+ var blob = new Blob([markdown], {
+ type: 'text/markdown;charset=utf-8'
+ })
+ saveAs(blob, filename, true)
+})
+// html
ui.toolbar.download.html.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- exportToHTML(ui.area.markdown);
-});
+ e.preventDefault()
+ e.stopPropagation()
+ exportToHTML(ui.area.markdown)
+})
// raw html
ui.toolbar.download.rawhtml.click(function (e) {
- e.preventDefault();
- e.stopPropagation();
- exportToRawHTML(ui.area.markdown);
-});
-//pdf
-ui.toolbar.download.pdf.attr("download", "").attr("href", noteurl + "/pdf");
-//export to dropbox
+ e.preventDefault()
+ e.stopPropagation()
+ exportToRawHTML(ui.area.markdown)
+})
+// pdf
+ui.toolbar.download.pdf.attr('download', '').attr('href', noteurl + '/pdf')
+// export to dropbox
ui.toolbar.export.dropbox.click(function () {
- var filename = renderFilename(ui.area.markdown) + '.md';
- var options = {
- files: [
- {
- 'url': noteurl + "/download",
- 'filename': filename
- }
- ],
- error: function (errorMessage) {
- console.error(errorMessage);
- }
- };
- Dropbox.save(options);
-});
-function uploadToGoogleDrive(accessToken) {
- ui.spinner.show();
- var filename = renderFilename(ui.area.markdown) + '.md';
- var markdown = editor.getValue();
- var blob = new Blob([markdown], {
- type: "text/markdown;charset=utf-8"
- });
- blob.name = filename;
- var uploader = new MediaUploader({
- file: blob,
- token: accessToken,
- onComplete: function (data) {
- data = JSON.parse(data);
- showMessageModal('<i class="fa fa-cloud-upload"></i> Export to Google Drive', 'Export Complete!', data.alternateLink, 'Click here to view your file', true);
- ui.spinner.hide();
- },
- onError: function (data) {
- var modal = $('.export-modal');
- showMessageModal('<i class="fa fa-cloud-upload"></i> Export to Google Drive', 'Export Error :(', '', data, false);
- ui.spinner.hide();
- }
- });
- uploader.upload();
-}
-function googleApiAuth(immediate, callback) {
- gapi.auth.authorize(
- {
- 'client_id': GOOGLE_CLIENT_ID,
- 'scope': 'https://www.googleapis.com/auth/drive.file',
- 'immediate': immediate
- }, callback ? callback : function () { });
-}
-function onGoogleClientLoaded() {
- googleApiAuth(true);
- buildImportFromGoogleDrive();
-}
-window.onGoogleClientLoaded = onGoogleClientLoaded;
+ var filename = renderFilename(ui.area.markdown) + '.md'
+ var options = {
+ files: [
+ {
+ 'url': noteurl + '/download',
+ 'filename': filename
+ }
+ ],
+ error: function (errorMessage) {
+ console.error(errorMessage)
+ }
+ }
+ Dropbox.save(options)
+})
+function uploadToGoogleDrive (accessToken) {
+ ui.spinner.show()
+ var filename = renderFilename(ui.area.markdown) + '.md'
+ var markdown = editor.getValue()
+ var blob = new Blob([markdown], {
+ type: 'text/markdown;charset=utf-8'
+ })
+ blob.name = filename
+ var uploader = new MediaUploader({
+ file: blob,
+ token: accessToken,
+ onComplete: function (data) {
+ data = JSON.parse(data)
+ showMessageModal('<i class="fa fa-cloud-upload"></i> Export to Google Drive', 'Export Complete!', data.alternateLink, 'Click here to view your file', true)
+ ui.spinner.hide()
+ },
+ onError: function (data) {
+ showMessageModal('<i class="fa fa-cloud-upload"></i> Export to Google Drive', 'Export Error :(', '', data, false)
+ ui.spinner.hide()
+ }
+ })
+ uploader.upload()
+}
+function googleApiAuth (immediate, callback) {
+ gapi.auth.authorize(
+ {
+ 'client_id': GOOGLE_CLIENT_ID,
+ 'scope': 'https://www.googleapis.com/auth/drive.file',
+ 'immediate': immediate
+ }, callback || function () { })
+}
+function onGoogleClientLoaded () {
+ googleApiAuth(true)
+ buildImportFromGoogleDrive()
+}
+window.onGoogleClientLoaded = onGoogleClientLoaded
// export to google drive
ui.toolbar.export.googleDrive.click(function (e) {
- var token = gapi.auth.getToken();
- if (token) {
- uploadToGoogleDrive(token.access_token);
- } else {
- googleApiAuth(false, function (result) {
- uploadToGoogleDrive(result.access_token);
- });
- }
-});
-//export to gist
-ui.toolbar.export.gist.attr("href", noteurl + "/gist");
-//export to snippet
-ui.toolbar.export.snippet.click(function() {
- ui.spinner.show();
- $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')
+ var token = gapi.auth.getToken()
+ if (token) {
+ uploadToGoogleDrive(token.access_token)
+ } else {
+ googleApiAuth(false, function (result) {
+ uploadToGoogleDrive(result.access_token)
+ })
+ }
+})
+// export to gist
+ui.toolbar.export.gist.attr('href', noteurl + '/gist')
+// export to snippet
+ui.toolbar.export.snippet.click(function () {
+ ui.spinner.show()
+ $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')
.done(function (data) {
- $("#snippetExportModalAccessToken").val(data.accesstoken);
- $("#snippetExportModalBaseURL").val(data.baseURL);
- $("#snippetExportModalLoading").hide();
- $("#snippetExportModal").modal('toggle');
- $("#snippetExportModalProjects").find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>');
- if (data.projects) {
- data.projects.sort(function(a,b) {
- return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0);
- });
- data.projects.forEach(function(project) {
- if (!project.snippets_enabled
- || (project.permissions.project_access === null && project.permissions.group_access === null)
- || (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20))
- {
- return;
- }
- $('<option>').val(project.id).text(project.path_with_namespace).appendTo("#snippetExportModalProjects");
- });
- $("#snippetExportModalProjects").prop('disabled', false);
- }
- $("#snippetExportModalLoading").hide();
+ $('#snippetExportModalAccessToken').val(data.accesstoken)
+ $('#snippetExportModalBaseURL').val(data.baseURL)
+ $('#snippetExportModalLoading').hide()
+ $('#snippetExportModal').modal('toggle')
+ $('#snippetExportModalProjects').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>')
+ if (data.projects) {
+ data.projects.sort(function (a, b) {
+ return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)
+ })
+ data.projects.forEach(function (project) {
+ if (!project.snippets_enabled ||
+ (project.permissions.project_access === null && project.permissions.group_access === null) ||
+ (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {
+ return
+ }
+ $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetExportModalProjects')
+ })
+ $('#snippetExportModalProjects').prop('disabled', false)
+ }
+ $('#snippetExportModalLoading').hide()
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false);
+ showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)
})
.always(function () {
- ui.spinner.hide();
- });
-});
-//import from dropbox
+ ui.spinner.hide()
+ })
+})
+// import from dropbox
ui.toolbar.import.dropbox.click(function () {
- var options = {
- success: function (files) {
- ui.spinner.show();
- var url = files[0].link;
- importFromUrl(url);
- },
- linkType: "direct",
- multiselect: false,
- extensions: ['.md', '.html']
- };
- Dropbox.choose(options);
-});
+ var options = {
+ success: function (files) {
+ ui.spinner.show()
+ var url = files[0].link
+ importFromUrl(url)
+ },
+ linkType: 'direct',
+ multiselect: false,
+ extensions: ['.md', '.html']
+ }
+ Dropbox.choose(options)
+})
// import from google drive
-var picker = null;
-function buildImportFromGoogleDrive() {
- picker = new FilePicker({
- apiKey: GOOGLE_API_KEY,
- clientId: GOOGLE_CLIENT_ID,
- buttonEl: ui.toolbar.import.googleDrive,
- onSelect: function (file) {
- if (file.downloadUrl) {
- ui.spinner.show();
- var accessToken = gapi.auth.getToken().access_token;
- $.ajax({
- type: 'GET',
- beforeSend: function (request) {
- request.setRequestHeader('Authorization', 'Bearer ' + accessToken);
- },
- url: file.downloadUrl,
- success: function (data) {
- if (file.fileExtension == 'html')
- parseToEditor(data);
- else
- replaceAll(data);
- },
- error: function (data) {
- showMessageModal('<i class="fa fa-cloud-download"></i> Import from Google Drive', 'Import failed :(', '', data, false);
- },
- complete: function () {
- ui.spinner.hide();
- }
- });
- }
- }
- });
+function buildImportFromGoogleDrive () {
+ FilePicker({
+ apiKey: GOOGLE_API_KEY,
+ clientId: GOOGLE_CLIENT_ID,
+ buttonEl: ui.toolbar.import.googleDrive,
+ onSelect: function (file) {
+ if (file.downloadUrl) {
+ ui.spinner.show()
+ var accessToken = gapi.auth.getToken().access_token
+ $.ajax({
+ type: 'GET',
+ beforeSend: function (request) {
+ request.setRequestHeader('Authorization', 'Bearer ' + accessToken)
+ },
+ url: file.downloadUrl,
+ success: function (data) {
+ if (file.fileExtension === 'html') { parseToEditor(data) } else { replaceAll(data) }
+ },
+ error: function (data) {
+ showMessageModal('<i class="fa fa-cloud-download"></i> Import from Google Drive', 'Import failed :(', '', data, false)
+ },
+ complete: function () {
+ ui.spinner.hide()
+ }
+ })
+ }
+ }
+ })
}
-//import from gist
+// import from gist
ui.toolbar.import.gist.click(function () {
- //na
-});
-//import from snippet
+ // na
+})
+// import from snippet
ui.toolbar.import.snippet.click(function () {
- ui.spinner.show();
- $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')
+ ui.spinner.show()
+ $.get(serverurl + '/auth/gitlab/callback/' + noteid + '/projects')
.done(function (data) {
- $("#snippetImportModalAccessToken").val(data.accesstoken);
- $("#snippetImportModalBaseURL").val(data.baseURL);
- $("#snippetImportModalContent").prop('disabled', false);
- $("#snippetImportModalConfirm").prop('disabled', false);
- $("#snippetImportModalLoading").hide();
- $("#snippetImportModal").modal('toggle');
- $("#snippetImportModalProjects").find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>');
- if (data.projects) {
- data.projects.sort(function(a,b) {
- return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0);
- });
- data.projects.forEach(function(project) {
- if (!project.snippets_enabled
- || (project.permissions.project_access === null && project.permissions.group_access === null)
- || (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20))
- {
- return;
- }
- $('<option>').val(project.id).text(project.path_with_namespace).appendTo("#snippetImportModalProjects");
- });
- $("#snippetImportModalProjects").prop('disabled', false);
- }
- $("#snippetImportModalLoading").hide();
+ $('#snippetImportModalAccessToken').val(data.accesstoken)
+ $('#snippetImportModalBaseURL').val(data.baseURL)
+ $('#snippetImportModalContent').prop('disabled', false)
+ $('#snippetImportModalConfirm').prop('disabled', false)
+ $('#snippetImportModalLoading').hide()
+ $('#snippetImportModal').modal('toggle')
+ $('#snippetImportModalProjects').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Projects</option>')
+ if (data.projects) {
+ data.projects.sort(function (a, b) {
+ return (a.path_with_namespace < b.path_with_namespace) ? -1 : ((a.path_with_namespace > b.path_with_namespace) ? 1 : 0)
+ })
+ data.projects.forEach(function (project) {
+ if (!project.snippets_enabled ||
+ (project.permissions.project_access === null && project.permissions.group_access === null) ||
+ (project.permissions.project_access !== null && project.permissions.project_access.access_level < 20)) {
+ return
+ }
+ $('<option>').val(project.id).text(project.path_with_namespace).appendTo('#snippetImportModalProjects')
+ })
+ $('#snippetImportModalProjects').prop('disabled', false)
+ }
+ $('#snippetImportModalLoading').hide()
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false);
+ showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Unable to fetch gitlab parameters :(', '', '', false)
})
.always(function () {
- ui.spinner.hide();
- });
-});
-//import from clipboard
+ ui.spinner.hide()
+ })
+})
+// import from clipboard
ui.toolbar.import.clipboard.click(function () {
- //na
-});
-//upload image
+ // na
+})
+// upload image
ui.toolbar.uploadImage.bind('change', function (e) {
- var files = e.target.files || e.dataTransfer.files;
- e.dataTransfer = {};
- e.dataTransfer.files = files;
- inlineAttach.onDrop(e);
-});
-//toc
+ var files = e.target.files || e.dataTransfer.files
+ e.dataTransfer = {}
+ e.dataTransfer.files = files
+ inlineAttach.onDrop(e)
+})
+// toc
ui.toc.dropdown.click(function (e) {
- e.stopPropagation();
-});
+ e.stopPropagation()
+})
// prevent empty link change hash
$('a[href="#"]').click(function (e) {
- e.preventDefault();
-});
-
-//modal actions
-var revisions = [];
-var revisionViewer = null;
-var revisionInsert = [];
-var revisionDelete = [];
-var revisionInsertAnnotation = null;
-var revisionDeleteAnnotation = null;
-var revisionList = ui.modal.revision.find('.ui-revision-list');
-var revision = null;
-var revisionTime = null;
+ e.preventDefault()
+})
+
+// modal actions
+var revisions = []
+var revisionViewer = null
+var revisionInsert = []
+var revisionDelete = []
+var revisionInsertAnnotation = null
+var revisionDeleteAnnotation = null
+var revisionList = ui.modal.revision.find('.ui-revision-list')
+var revision = null
+var revisionTime = null
ui.modal.revision.on('show.bs.modal', function (e) {
- $.get(noteurl + '/revision')
- .done(function(data) {
- parseRevisions(data.revision);
- initRevisionViewer();
+ $.get(noteurl + '/revision')
+ .done(function (data) {
+ parseRevisions(data.revision)
+ initRevisionViewer()
})
- .fail(function(err) {
-
+ .fail(function (err) {
+ if (debug) {
+ console.log(err)
+ }
})
- .always(function() {
- //na
- });
-});
-function checkRevisionViewer() {
- if (revisionViewer) {
- var container = $(revisionViewer.display.wrapper).parent();
- $(revisionViewer.display.scroller).css('height', container.height() + 'px');
- revisionViewer.refresh();
- }
-}
-ui.modal.revision.on('shown.bs.modal', checkRevisionViewer);
-$(window).resize(checkRevisionViewer);
-function parseRevisions(_revisions) {
- if (_revisions.length != revisions) {
- revisions = _revisions;
- var lastRevision = null;
- if (revisionList.children().length > 0) {
- lastRevision = revisionList.find('.active').attr('data-revision-time');
- }
- revisionList.html('');
- for (var i = 0; i < revisions.length; i++) {
- var revision = revisions[i];
- var item = $('<a href="#" class="list-group-item"></a>');
- item.attr('data-revision-time', revision.time);
- if (lastRevision == revision.time) item.addClass('active');
- var itemHeading = $('<h5 class="list-group-item-heading"></h5>');
- itemHeading.html('<i class="fa fa-clock-o"></i> ' + moment(revision.time).format('llll'));
- var itemText = $('<p class="list-group-item-text"></p>');
- itemText.html('<i class="fa fa-file-text"></i> Length: ' + revision.length);
- item.append(itemHeading).append(itemText);
- item.click(function (e) {
- var time = $(this).attr('data-revision-time');
- selectRevision(time);
- });
- revisionList.append(item);
- }
- if (!lastRevision) {
- selectRevision(revisions[0].time);
- }
- }
-}
-function selectRevision(time) {
- if (time == revisionTime) return;
- $.get(noteurl + '/revision/' + time)
- .done(function(data) {
- revision = data;
- revisionTime = time;
- var lastScrollInfo = revisionViewer.getScrollInfo();
- revisionList.children().removeClass('active');
- revisionList.find('[data-revision-time="' + time + '"]').addClass('active');
- var content = revision.content;
- revisionViewer.setValue(content);
- revisionViewer.scrollTo(null, lastScrollInfo.top);
- revisionInsert = [];
- revisionDelete = [];
+ .always(function () {
+ // na
+ })
+})
+function checkRevisionViewer () {
+ if (revisionViewer) {
+ var container = $(revisionViewer.display.wrapper).parent()
+ $(revisionViewer.display.scroller).css('height', container.height() + 'px')
+ revisionViewer.refresh()
+ }
+}
+ui.modal.revision.on('shown.bs.modal', checkRevisionViewer)
+$(window).resize(checkRevisionViewer)
+function parseRevisions (_revisions) {
+ if (_revisions.length !== revisions) {
+ revisions = _revisions
+ var lastRevision = null
+ if (revisionList.children().length > 0) {
+ lastRevision = revisionList.find('.active').attr('data-revision-time')
+ }
+ revisionList.html('')
+ for (var i = 0; i < revisions.length; i++) {
+ var revision = revisions[i]
+ var item = $('<a href="#" class="list-group-item"></a>')
+ item.attr('data-revision-time', revision.time)
+ if (lastRevision === revision.time) item.addClass('active')
+ var itemHeading = $('<h5 class="list-group-item-heading"></h5>')
+ itemHeading.html('<i class="fa fa-clock-o"></i> ' + moment(revision.time).format('llll'))
+ var itemText = $('<p class="list-group-item-text"></p>')
+ itemText.html('<i class="fa fa-file-text"></i> Length: ' + revision.length)
+ item.append(itemHeading).append(itemText)
+ item.click(function (e) {
+ var time = $(this).attr('data-revision-time')
+ selectRevision(time)
+ })
+ revisionList.append(item)
+ }
+ if (!lastRevision) {
+ selectRevision(revisions[0].time)
+ }
+ }
+}
+function selectRevision (time) {
+ if (time === revisionTime) return
+ $.get(noteurl + '/revision/' + time)
+ .done(function (data) {
+ revision = data
+ revisionTime = time
+ var lastScrollInfo = revisionViewer.getScrollInfo()
+ revisionList.children().removeClass('active')
+ revisionList.find('[data-revision-time="' + time + '"]').addClass('active')
+ var content = revision.content
+ revisionViewer.setValue(content)
+ revisionViewer.scrollTo(null, lastScrollInfo.top)
+ revisionInsert = []
+ revisionDelete = []
// mark the text which have been insert or delete
- if (revision.patch.length > 0) {
- var bias = 0;
- for (var j = 0; j < revision.patch.length; j++) {
- var patch = revision.patch[j];
- var currIndex = patch.start1 + bias;
- for (var i = 0; i < patch.diffs.length; i++) {
- var diff = patch.diffs[i];
+ if (revision.patch.length > 0) {
+ var bias = 0
+ for (var j = 0; j < revision.patch.length; j++) {
+ var patch = revision.patch[j]
+ var currIndex = patch.start1 + bias
+ for (var i = 0; i < patch.diffs.length; i++) {
+ var diff = patch.diffs[i]
// ignore if diff only contains line breaks
- if ((diff[1].match(new RegExp("\n", "g")) || []).length == diff[1].length) continue;
- switch(diff[0]) {
- case 0: // retain
- currIndex += diff[1].length;
- break;
- case 1: // insert
- var prePos = revisionViewer.posFromIndex(currIndex);
- var postPos = revisionViewer.posFromIndex(currIndex + diff[1].length);
- revisionInsert.push({
- from: prePos,
- to: postPos
- });
- revisionViewer.markText(prePos, postPos, {
- css: 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'
- });
- currIndex += diff[1].length;
- break;
- case -1: // delete
- var prePos = revisionViewer.posFromIndex(currIndex);
- revisionViewer.replaceRange(diff[1], prePos);
- var postPos = revisionViewer.posFromIndex(currIndex + diff[1].length);
- revisionDelete.push({
- from: prePos,
- to: postPos
- });
- revisionViewer.markText(prePos, postPos, {
- css: 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'
- });
- bias += diff[1].length;
- currIndex += diff[1].length;
- break;
- }
- }
+ if ((diff[1].match(/\n/g) || []).length === diff[1].length) continue
+ var prePos
+ var postPos
+ switch (diff[0]) {
+ case 0: // retain
+ currIndex += diff[1].length
+ break
+ case 1: // insert
+ prePos = revisionViewer.posFromIndex(currIndex)
+ postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)
+ revisionInsert.push({
+ from: prePos,
+ to: postPos
+ })
+ revisionViewer.markText(prePos, postPos, {
+ css: 'background-color: rgba(230,255,230,0.7); text-decoration: underline;'
+ })
+ currIndex += diff[1].length
+ break
+ case -1: // delete
+ prePos = revisionViewer.posFromIndex(currIndex)
+ revisionViewer.replaceRange(diff[1], prePos)
+ postPos = revisionViewer.posFromIndex(currIndex + diff[1].length)
+ revisionDelete.push({
+ from: prePos,
+ to: postPos
+ })
+ revisionViewer.markText(prePos, postPos, {
+ css: 'background-color: rgba(255,230,230,0.7); text-decoration: line-through;'
+ })
+ bias += diff[1].length
+ currIndex += diff[1].length
+ break
}
+ }
}
- revisionInsertAnnotation.update(revisionInsert);
- revisionDeleteAnnotation.update(revisionDelete);
+ }
+ revisionInsertAnnotation.update(revisionInsert)
+ revisionDeleteAnnotation.update(revisionDelete)
})
- .fail(function(err) {
-
+ .fail(function (err) {
+ if (debug) {
+ console.log(err)
+ }
+ })
+ .always(function () {
+ // na
})
- .always(function() {
- //na
- });
-}
-function initRevisionViewer() {
- if (revisionViewer) return;
- var revisionViewerTextArea = document.getElementById("revisionViewer");
- revisionViewer = CodeMirror.fromTextArea(revisionViewerTextArea, {
- mode: defaultEditorMode,
- viewportMargin: viewportMargin,
- lineNumbers: true,
- lineWrapping: true,
- showCursorWhenSelecting: true,
- inputStyle: "textarea",
- gutters: ["CodeMirror-linenumbers"],
- flattenSpans: true,
- addModeClass: true,
- readOnly: true,
- autoRefresh: true,
- scrollbarStyle: 'overlay'
- });
- revisionInsertAnnotation = revisionViewer.annotateScrollbar({ className:"CodeMirror-insert-match" });
- revisionDeleteAnnotation = revisionViewer.annotateScrollbar({ className:"CodeMirror-delete-match" });
- checkRevisionViewer();
+}
+function initRevisionViewer () {
+ if (revisionViewer) return
+ var revisionViewerTextArea = document.getElementById('revisionViewer')
+ revisionViewer = CodeMirror.fromTextArea(revisionViewerTextArea, {
+ mode: defaultEditorMode,
+ viewportMargin: viewportMargin,
+ lineNumbers: true,
+ lineWrapping: true,
+ showCursorWhenSelecting: true,
+ inputStyle: 'textarea',
+ gutters: ['CodeMirror-linenumbers'],
+ flattenSpans: true,
+ addModeClass: true,
+ readOnly: true,
+ autoRefresh: true,
+ scrollbarStyle: 'overlay'
+ })
+ revisionInsertAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-insert-match' })
+ revisionDeleteAnnotation = revisionViewer.annotateScrollbar({ className: 'CodeMirror-delete-match' })
+ checkRevisionViewer()
}
$('#revisionModalDownload').click(function () {
- if (!revision) return;
- var filename = renderFilename(ui.area.markdown) + '_' + revisionTime + '.md';
- var blob = new Blob([revision.content], {
- type: "text/markdown;charset=utf-8"
- });
- saveAs(blob, filename, true);
-});
+ if (!revision) return
+ var filename = renderFilename(ui.area.markdown) + '_' + revisionTime + '.md'
+ var blob = new Blob([revision.content], {
+ type: 'text/markdown;charset=utf-8'
+ })
+ saveAs(blob, filename, true)
+})
$('#revisionModalRevert').click(function () {
- if (!revision) return;
- editor.setValue(revision.content);
- ui.modal.revision.modal('hide');
-});
-//snippet projects
-ui.modal.snippetImportProjects.change(function() {
- var accesstoken = $("#snippetImportModalAccessToken").val(),
- baseURL = $("#snippetImportModalBaseURL").val(),
- project = $("#snippetImportModalProjects").val();
-
- $("#snippetImportModalLoading").show();
- $("#snippetImportModalContent").val('/projects/' + project);
- $.get(baseURL + '/api/v3/projects/' + project + '/snippets?access_token=' + accesstoken)
- .done(function(data) {
- $("#snippetImportModalSnippets").find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Snippets</option>');
- data.forEach(function(snippet) {
- $('<option>').val(snippet.id).text(snippet.title).appendTo($("#snippetImportModalSnippets"));
- });
- $("#snippetImportModalLoading").hide();
- $("#snippetImportModalSnippets").prop('disabled', false);
+ if (!revision) return
+ editor.setValue(revision.content)
+ ui.modal.revision.modal('hide')
+})
+// snippet projects
+ui.modal.snippetImportProjects.change(function () {
+ var accesstoken = $('#snippetImportModalAccessToken').val()
+ var baseURL = $('#snippetImportModalBaseURL').val()
+ var project = $('#snippetImportModalProjects').val()
+
+ $('#snippetImportModalLoading').show()
+ $('#snippetImportModalContent').val('/projects/' + project)
+ $.get(baseURL + '/api/v3/projects/' + project + '/snippets?access_token=' + accesstoken)
+ .done(function (data) {
+ $('#snippetImportModalSnippets').find('option').remove().end().append('<option value="init" selected="selected" disabled="disabled">Select From Available Snippets</option>')
+ data.forEach(function (snippet) {
+ $('<option>').val(snippet.id).text(snippet.title).appendTo($('#snippetImportModalSnippets'))
+ })
+ $('#snippetImportModalLoading').hide()
+ $('#snippetImportModalSnippets').prop('disabled', false)
})
- .fail(function(err) {
-
+ .fail(function (err) {
+ if (debug) {
+ console.log(err)
+ }
})
- .always(function() {
- //na
- });
-});
-//snippet snippets
-ui.modal.snippetImportSnippets.change(function() {
- var project = $("#snippetImportModalProjects").val(),
- snippet = $("#snippetImportModalSnippets").val();
-
- $("#snippetImportModalContent").val($("#snippetImportModalContent").val() + '/snippets/' + snippet);
-})
-
-function scrollToTop() {
- if (currentMode == modeType.both) {
- if (editor.getScrollInfo().top != 0)
- editor.scrollTo(0, 0);
- else
- ui.area.view.animate({
- scrollTop: 0
- }, 100, "linear");
- } else {
- $('body, html').stop(true, true).animate({
- scrollTop: 0
- }, 100, "linear");
- }
-}
-
-function scrollToBottom() {
- if (currentMode == modeType.both) {
- var scrollInfo = editor.getScrollInfo();
- var scrollHeight = scrollInfo.height;
- if (scrollInfo.top != scrollHeight)
- editor.scrollTo(0, scrollHeight * 2);
- else
- ui.area.view.animate({
- scrollTop: ui.area.view[0].scrollHeight
- }, 100, "linear");
- } else {
- $('body, html').stop(true, true).animate({
- scrollTop: $(document.body)[0].scrollHeight
- }, 100, "linear");
- }
-}
-
-window.scrollToTop = scrollToTop;
-window.scrollToBottom = scrollToBottom;
-
-var enoughForAffixToc = true;
-
-//scrollspy
-function generateScrollspy() {
- $(document.body).scrollspy({
- target: '.scrollspy-body'
- });
- ui.area.view.scrollspy({
- target: '.scrollspy-view'
- });
- $(document.body).scrollspy('refresh');
- ui.area.view.scrollspy('refresh');
- if (enoughForAffixToc) {
- ui.toc.toc.hide();
- ui.toc.affix.show();
- } else {
- ui.toc.affix.hide();
- ui.toc.toc.show();
- }
- //$(document.body).scroll();
- //ui.area.view.scroll();
-}
-
-function updateScrollspy() {
- var headers = ui.area.markdown.find('h1, h2, h3').toArray();
- var headerMap = [];
- for (var i = 0; i < headers.length; i++) {
- headerMap.push($(headers[i]).offset().top - parseInt($(headers[i]).css('margin-top')));
- }
- applyScrollspyActive($(window).scrollTop(), headerMap, headers,
- $('.scrollspy-body'), 0);
- var offset = ui.area.view.scrollTop() - ui.area.view.offset().top;
- applyScrollspyActive(ui.area.view.scrollTop(), headerMap, headers,
- $('.scrollspy-view'), offset - 10);
-}
+ .always(function () {
+ // na
+ })
+})
+// snippet snippets
+ui.modal.snippetImportSnippets.change(function () {
+ var snippet = $('#snippetImportModalSnippets').val()
+ $('#snippetImportModalContent').val($('#snippetImportModalContent').val() + '/snippets/' + snippet)
+})
-function applyScrollspyActive(top, headerMap, headers, target, offset) {
- var index = 0;
- for (var i = headerMap.length - 1; i >= 0; i--) {
- if (top >= (headerMap[i] + offset) && headerMap[i + 1] && top < (headerMap[i + 1] + offset)) {
- index = i;
- break;
- }
- }
- var header = $(headers[index]);
- var active = target.find('a[href="#' + header.attr('id') + '"]');
- active.closest('li').addClass('active').parent().closest('li').addClass('active').parent().closest('li').addClass('active');
+function scrollToTop () {
+ if (window.currentMode === modeType.both) {
+ if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else {
+ ui.area.view.animate({
+ scrollTop: 0
+ }, 100, 'linear')
+ }
+ } else {
+ $('body, html').stop(true, true).animate({
+ scrollTop: 0
+ }, 100, 'linear')
+ }
+}
+
+function scrollToBottom () {
+ if (window.currentMode === modeType.both) {
+ var scrollInfo = editor.getScrollInfo()
+ var scrollHeight = scrollInfo.height
+ if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else {
+ ui.area.view.animate({
+ scrollTop: ui.area.view[0].scrollHeight
+ }, 100, 'linear')
+ }
+ } else {
+ $('body, html').stop(true, true).animate({
+ scrollTop: $(document.body)[0].scrollHeight
+ }, 100, 'linear')
+ }
+}
+
+window.scrollToTop = scrollToTop
+window.scrollToBottom = scrollToBottom
+
+var enoughForAffixToc = true
+
+// scrollspy
+function generateScrollspy () {
+ $(document.body).scrollspy({
+ target: '.scrollspy-body'
+ })
+ ui.area.view.scrollspy({
+ target: '.scrollspy-view'
+ })
+ $(document.body).scrollspy('refresh')
+ ui.area.view.scrollspy('refresh')
+ if (enoughForAffixToc) {
+ ui.toc.toc.hide()
+ ui.toc.affix.show()
+ } else {
+ ui.toc.affix.hide()
+ ui.toc.toc.show()
+ }
+ // $(document.body).scroll();
+ // ui.area.view.scroll();
+}
+
+function updateScrollspy () {
+ var headers = ui.area.markdown.find('h1, h2, h3').toArray()
+ var headerMap = []
+ for (var i = 0; i < headers.length; i++) {
+ headerMap.push($(headers[i]).offset().top - parseInt($(headers[i]).css('margin-top')))
+ }
+ applyScrollspyActive($(window).scrollTop(), headerMap, headers,
+ $('.scrollspy-body'), 0)
+ var offset = ui.area.view.scrollTop() - ui.area.view.offset().top
+ applyScrollspyActive(ui.area.view.scrollTop(), headerMap, headers,
+ $('.scrollspy-view'), offset - 10)
+}
+
+function applyScrollspyActive (top, headerMap, headers, target, offset) {
+ var index = 0
+ for (var i = headerMap.length - 1; i >= 0; i--) {
+ if (top >= (headerMap[i] + offset) && headerMap[i + 1] && top < (headerMap[i + 1] + offset)) {
+ index = i
+ break
+ }
+ }
+ var header = $(headers[index])
+ var active = target.find('a[href="#' + header.attr('id') + '"]')
+ active.closest('li').addClass('active').parent().closest('li').addClass('active').parent().closest('li').addClass('active')
}
// clipboard modal
-//fix for wrong autofocus
+// fix for wrong autofocus
$('#clipboardModal').on('shown.bs.modal', function () {
- $('#clipboardModal').blur();
-});
-$("#clipboardModalClear").click(function () {
- $("#clipboardModalContent").html('');
-});
-$("#clipboardModalConfirm").click(function () {
- var data = $("#clipboardModalContent").html();
- if (data) {
- parseToEditor(data);
- $('#clipboardModal').modal('hide');
- $("#clipboardModalContent").html('');
- }
-});
+ $('#clipboardModal').blur()
+})
+$('#clipboardModalClear').click(function () {
+ $('#clipboardModalContent').html('')
+})
+$('#clipboardModalConfirm').click(function () {
+ var data = $('#clipboardModalContent').html()
+ if (data) {
+ parseToEditor(data)
+ $('#clipboardModal').modal('hide')
+ $('#clipboardModalContent').html('')
+ }
+})
// refresh modal
$('#refreshModalRefresh').click(function () {
- location.reload(true);
-});
+ location.reload(true)
+})
// gist import modal
-$("#gistImportModalClear").click(function () {
- $("#gistImportModalContent").val('');
-});
-$("#gistImportModalConfirm").click(function () {
- var gisturl = $("#gistImportModalContent").val();
- if (!gisturl) return;
- $('#gistImportModal').modal('hide');
- $("#gistImportModalContent").val('');
- if (!isValidURL(gisturl)) {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid URL :(', '', '', false);
- return;
+$('#gistImportModalClear').click(function () {
+ $('#gistImportModalContent').val('')
+})
+$('#gistImportModalConfirm').click(function () {
+ var gisturl = $('#gistImportModalContent').val()
+ if (!gisturl) return
+ $('#gistImportModal').modal('hide')
+ $('#gistImportModalContent').val('')
+ if (!isValidURL(gisturl)) {
+ showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid URL :(', '', '', false)
+ } else {
+ var hostname = window.url('hostname', gisturl)
+ if (hostname !== 'gist.github.com') {
+ showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', '', false)
} else {
- var hostname = url('hostname', gisturl)
- if (hostname !== 'gist.github.com') {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', '', false);
- } else {
- ui.spinner.show();
- $.get('https://api.github.com/gists/' + url('-1', gisturl))
+ ui.spinner.show()
+ $.get('https://api.github.com/gists/' + window.url('-1', gisturl))
.done(function (data) {
- if (data.files) {
- var contents = "";
- Object.keys(data.files).forEach(function (key) {
- contents += key;
- contents += '\n---\n';
- contents += data.files[key].content;
- contents += '\n\n';
- });
- replaceAll(contents);
- } else {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Unable to fetch gist files :(', '', '', false);
- }
+ if (data.files) {
+ var contents = ''
+ Object.keys(data.files).forEach(function (key) {
+ contents += key
+ contents += '\n---\n'
+ contents += data.files[key].content
+ contents += '\n\n'
+ })
+ replaceAll(contents)
+ } else {
+ showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Unable to fetch gist files :(', '', '', false)
+ }
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', JSON.stringify(data), false);
+ showMessageModal('<i class="fa fa-github"></i> Import from Gist', 'Not a valid Gist URL :(', '', JSON.stringify(data), false)
})
.always(function () {
- ui.spinner.hide();
- });
- }
+ ui.spinner.hide()
+ })
}
-});
+ }
+})
// snippet import modal
-$("#snippetImportModalClear").click(function () {
- $("#snippetImportModalContent").val('');
- $("#snippetImportModalProjects").val('init');
- $("#snippetImportModalSnippets").val('init');
- $("#snippetImportModalSnippets").prop('disabled', true);
-});
-$("#snippetImportModalConfirm").click(function () {
- var snippeturl = $("#snippetImportModalContent").val();
- if (!snippeturl) return;
- $('#snippetImportModal').modal('hide');
- $("#snippetImportModalContent").val('');
- if (!/^.+\/snippets\/.+$/.test(snippeturl)) {
- showMessageModal('<i class="fa fa-github"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', '', false);
- } else {
- ui.spinner.show();
- var accessToken = '?access_token=' + $("#snippetImportModalAccessToken").val();
- var fullURL = $("#snippetImportModalBaseURL").val() + '/api/v3' + snippeturl;
- $.get(fullURL + accessToken)
- .done(function(data) {
- var content = '# ' + (data.title || "Snippet Import");
- var fileInfo = data.file_name.split('.');
- fileInfo[1] = (fileInfo[1]) ? fileInfo[1] : "md";
- $.get(fullURL + '/raw' + accessToken)
+$('#snippetImportModalClear').click(function () {
+ $('#snippetImportModalContent').val('')
+ $('#snippetImportModalProjects').val('init')
+ $('#snippetImportModalSnippets').val('init')
+ $('#snippetImportModalSnippets').prop('disabled', true)
+})
+$('#snippetImportModalConfirm').click(function () {
+ var snippeturl = $('#snippetImportModalContent').val()
+ if (!snippeturl) return
+ $('#snippetImportModal').modal('hide')
+ $('#snippetImportModalContent').val('')
+ if (!/^.+\/snippets\/.+$/.test(snippeturl)) {
+ showMessageModal('<i class="fa fa-github"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', '', false)
+ } else {
+ ui.spinner.show()
+ var accessToken = '?access_token=' + $('#snippetImportModalAccessToken').val()
+ var fullURL = $('#snippetImportModalBaseURL').val() + '/api/v3' + snippeturl
+ $.get(fullURL + accessToken)
+ .done(function (data) {
+ var content = '# ' + (data.title || 'Snippet Import')
+ var fileInfo = data.file_name.split('.')
+ fileInfo[1] = (fileInfo[1]) ? fileInfo[1] : 'md'
+ $.get(fullURL + '/raw' + accessToken)
.done(function (raw) {
- if (raw) {
- content += "\n\n";
- if (fileInfo[1] != "md") {
- content += "```" + fileTypes[fileInfo[1]] + "\n";
- }
- content += raw;
- if (fileInfo[1] != "md") {
- content += "\n```";
- }
- replaceAll(content);
+ if (raw) {
+ content += '\n\n'
+ if (fileInfo[1] !== 'md') {
+ content += '```' + window.fileTypes[fileInfo[1]] + '\n'
}
+ content += raw
+ if (fileInfo[1] !== 'md') {
+ content += '\n```'
+ }
+ replaceAll(content)
+ }
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false);
+ showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)
})
.always(function () {
- ui.spinner.hide();
- });
+ ui.spinner.hide()
+ })
})
.fail(function (data) {
- showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false);
- });
- }
-});
-
-//snippet export modal
-$("#snippetExportModalConfirm").click(function() {
- var accesstoken = $("#snippetExportModalAccessToken").val(),
- baseURL = $("#snippetExportModalBaseURL").val(),
- data = {
- title: $("#snippetExportModalTitle").val(),
- file_name: $("#snippetExportModalFileName").val(),
- code: editor.getValue(),
- visibility_level: $("#snippetExportModalVisibility").val()
- };
- if (!data.title || !data.file_name || !data.code || !data.visibility_level || !$("#snippetExportModalProjects").val()) return;
- $("#snippetExportModalLoading").show();
- var fullURL = baseURL + '/api/v3/projects/' + $("#snippetExportModalProjects").val() + '/snippets?access_token=' + accesstoken;
- $.post(fullURL
+ showMessageModal('<i class="fa fa-gitlab"></i> Import from Snippet', 'Not a valid Snippet URL :(', '', JSON.stringify(data), false)
+ })
+ }
+})
+
+// snippet export modal
+$('#snippetExportModalConfirm').click(function () {
+ var accesstoken = $('#snippetExportModalAccessToken').val()
+ var baseURL = $('#snippetExportModalBaseURL').val()
+ var data = {
+ title: $('#snippetExportModalTitle').val(),
+ file_name: $('#snippetExportModalFileName').val(),
+ code: editor.getValue(),
+ visibility_level: $('#snippetExportModalVisibility').val()
+ }
+ if (!data.title || !data.file_name || !data.code || !data.visibility_level || !$('#snippetExportModalProjects').val()) return
+ $('#snippetExportModalLoading').show()
+ var fullURL = baseURL + '/api/v3/projects/' + $('#snippetExportModalProjects').val() + '/snippets?access_token=' + accesstoken
+ $.post(fullURL
, data
- , function(ret) {
- $("#snippetExportModalLoading").hide();
- $('#snippetExportModal').modal('hide');
- var redirect = baseURL + '/' + $("#snippetExportModalProjects option[value='" + $("#snippetExportModalProjects").val() + "']").text() + '/snippets/' + ret.id;
- showMessageModal('<i class="fa fa-gitlab"></i> Export to Snippet', 'Export Successful!', redirect, 'View Snippet Here', true);
+ , function (ret) {
+ $('#snippetExportModalLoading').hide()
+ $('#snippetExportModal').modal('hide')
+ var redirect = baseURL + '/' + $("#snippetExportModalProjects option[value='" + $('#snippetExportModalProjects').val() + "']").text() + '/snippets/' + ret.id
+ showMessageModal('<i class="fa fa-gitlab"></i> Export to Snippet', 'Export Successful!', redirect, 'View Snippet Here', true)
}
, 'json'
- );
-});
-
-function parseToEditor(data) {
- var parsed = toMarkdown(data);
- if (parsed)
- replaceAll(parsed);
-}
-
-function replaceAll(data) {
- editor.replaceRange(data, {
- line: 0,
- ch: 0
- }, {
- line: editor.lastLine(),
- ch: editor.lastLine().length
- }, '+input');
-}
-
-function importFromUrl(url) {
- //console.log(url);
- if (!url) return;
- if (!isValidURL(url)) {
- showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Not a valid URL :(', '', '', false);
- return;
- }
- $.ajax({
- method: "GET",
- url: url,
- success: function (data) {
- var extension = url.split('.').pop();
- if (extension == 'html')
- parseToEditor(data);
- else
- replaceAll(data);
- },
- error: function (data) {
- showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Import failed :(', '', JSON.stringify(data), false);
- },
- complete: function () {
- ui.spinner.hide();
- }
- });
+ )
+})
+
+function parseToEditor (data) {
+ var parsed = toMarkdown(data)
+ if (parsed) { replaceAll(parsed) }
+}
+
+function replaceAll (data) {
+ editor.replaceRange(data, {
+ line: 0,
+ ch: 0
+ }, {
+ line: editor.lastLine(),
+ ch: editor.lastLine().length
+ }, '+input')
+}
+
+function importFromUrl (url) {
+ // console.log(url);
+ if (!url) return
+ if (!isValidURL(url)) {
+ showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Not a valid URL :(', '', '', false)
+ return
+ }
+ $.ajax({
+ method: 'GET',
+ url: url,
+ success: function (data) {
+ var extension = url.split('.').pop()
+ if (extension === 'html') { parseToEditor(data) } else { replaceAll(data) }
+ },
+ error: function (data) {
+ showMessageModal('<i class="fa fa-cloud-download"></i> Import from URL', 'Import failed :(', '', JSON.stringify(data), false)
+ },
+ complete: function () {
+ ui.spinner.hide()
+ }
+ })
}
-//mode
+// mode
ui.toolbar.mode.click(function () {
- toggleMode();
-});
-//edit
+ toggleMode()
+})
+// edit
ui.toolbar.edit.click(function () {
- changeMode(modeType.edit);
-});
-//view
+ changeMode(modeType.edit)
+})
+// view
ui.toolbar.view.click(function () {
- changeMode(modeType.view);
-});
-//both
+ changeMode(modeType.view)
+})
+// both
ui.toolbar.both.click(function () {
- changeMode(modeType.both);
-});
-//permission
-//freely
+ changeMode(modeType.both)
+})
+// permission
+// freely
ui.infobar.permission.freely.click(function () {
- emitPermission("freely");
-});
-//editable
+ emitPermission('freely')
+})
+// editable
ui.infobar.permission.editable.click(function () {
- emitPermission("editable");
-});
-//locked
+ emitPermission('editable')
+})
+// locked
ui.infobar.permission.locked.click(function () {
- emitPermission("locked");
-});
-//private
+ emitPermission('locked')
+})
+// private
ui.infobar.permission.private.click(function () {
- emitPermission("private");
-});
-//limited
-ui.infobar.permission.limited.click(function() {
- emitPermission("limited");
-});
-//protected
-ui.infobar.permission.protected.click(function() {
- emitPermission("protected");
-});
+ emitPermission('private')
+})
+// limited
+ui.infobar.permission.limited.click(function () {
+ emitPermission('limited')
+})
+// protected
+ui.infobar.permission.protected.click(function () {
+ emitPermission('protected')
+})
// delete note
ui.infobar.delete.click(function () {
- $('.delete-modal').modal('show');
-});
+ $('.delete-modal').modal('show')
+})
$('.ui-delete-modal-confirm').click(function () {
- socket.emit('delete');
-});
-
-function emitPermission(_permission) {
- if (_permission != permission) {
- socket.emit('permission', _permission);
- }
-}
-
-function updatePermission(newPermission) {
- if (permission != newPermission) {
- permission = newPermission;
- if (loaded) refreshView();
- }
- var label = null;
- var title = null;
- switch (permission) {
- case "freely":
- label = '<i class="fa fa-leaf"></i> Freely';
- title = "Anyone can edit";
- break;
- case "editable":
- label = '<i class="fa fa-shield"></i> Editable';
- title = "Signed people can edit";
- break;
- case "limited":
- label = '<i class="fa fa-id-card"></i> Limited';
- title = "Signed people can edit (forbid guest)"
- break;
- case "locked":
- label = '<i class="fa fa-lock"></i> Locked';
- title = "Only owner can edit";
- break;
- case "protected":
- label = '<i class="fa fa-umbrella"></i> Protected';
- title = "Only owner can edit (forbid guest)";
- break;
- case "private":
- label = '<i class="fa fa-hand-stop-o"></i> Private';
- title = "Only owner can view & edit";
- break;
- }
- if (personalInfo.userid && owner && personalInfo.userid == owner) {
- label += ' <i class="fa fa-caret-down"></i>';
- ui.infobar.permission.label.removeClass('disabled');
- } else {
- ui.infobar.permission.label.addClass('disabled');
- }
- ui.infobar.permission.label.html(label).attr('title', title);
-}
-
-function havePermission() {
- var bool = false;
- switch (permission) {
- case "freely":
- bool = true;
- break;
- case "editable":
- case "limited":
- if (!personalInfo.login) {
- bool = false;
- } else {
- bool = true;
- }
- break;
- case "locked":
- case "private":
- case "protected":
- if (!owner || personalInfo.userid != owner) {
- bool = false;
- } else {
- bool = true;
- }
- break;
- }
- return bool;
+ socket.emit('delete')
+})
+
+function emitPermission (_permission) {
+ if (_permission !== permission) {
+ socket.emit('permission', _permission)
+ }
+}
+
+function updatePermission (newPermission) {
+ if (permission !== newPermission) {
+ permission = newPermission
+ if (window.loaded) refreshView()
+ }
+ var label = null
+ var title = null
+ switch (permission) {
+ case 'freely':
+ label = '<i class="fa fa-leaf"></i> Freely'
+ title = 'Anyone can edit'
+ break
+ case 'editable':
+ label = '<i class="fa fa-shield"></i> Editable'
+ title = 'Signed people can edit'
+ break
+ case 'limited':
+ label = '<i class="fa fa-id-card"></i> Limited'
+ title = 'Signed people can edit (forbid guest)'
+ break
+ case 'locked':
+ label = '<i class="fa fa-lock"></i> Locked'
+ title = 'Only owner can edit'
+ break
+ case 'protected':
+ label = '<i class="fa fa-umbrella"></i> Protected'
+ title = 'Only owner can edit (forbid guest)'
+ break
+ case 'private':
+ label = '<i class="fa fa-hand-stop-o"></i> Private'
+ title = 'Only owner can view & edit'
+ break
+ }
+ if (window.personalInfo.userid && window.owner && window.personalInfo.userid === window.owner) {
+ label += ' <i class="fa fa-caret-down"></i>'
+ ui.infobar.permission.label.removeClass('disabled')
+ } else {
+ ui.infobar.permission.label.addClass('disabled')
+ }
+ ui.infobar.permission.label.html(label).attr('title', title)
+}
+
+function havePermission () {
+ var bool = false
+ switch (permission) {
+ case 'freely':
+ bool = true
+ break
+ case 'editable':
+ case 'limited':
+ if (!window.personalInfo.login) {
+ bool = false
+ } else {
+ bool = true
+ }
+ break
+ case 'locked':
+ case 'private':
+ case 'protected':
+ if (!window.owner || window.personalInfo.userid !== window.owner) {
+ bool = false
+ } else {
+ bool = true
+ }
+ break
+ }
+ return bool
}
// global module workaround
-window.havePermission = havePermission;
+window.havePermission = havePermission
-//socket.io actions
-var io = require("socket.io-client");
+// socket.io actions
+var io = require('socket.io-client')
var socket = io.connect({
- path: urlpath ? '/' + urlpath + '/socket.io/' : '',
- timeout: 5000, //5 secs to timeout,
- reconnectionAttempts: 20 // retry 20 times on connect failed
-});
-//overwrite original event for checking login state
-var on = socket.on;
+ path: urlpath ? '/' + urlpath + '/socket.io/' : '',
+ timeout: 5000, // 5 secs to timeout,
+ reconnectionAttempts: 20 // retry 20 times on connect failed
+})
+// overwrite original event for checking login state
+var on = socket.on
socket.on = function () {
- if (!checkLoginStateChanged() && !needRefresh)
- return on.apply(socket, arguments);
-};
-var emit = socket.emit;
+ if (!checkLoginStateChanged() && !window.needRefresh) { return on.apply(socket, arguments) }
+}
+var emit = socket.emit
socket.emit = function () {
- if (!checkLoginStateChanged() && !needRefresh)
- emit.apply(socket, arguments);
-};
+ if (!checkLoginStateChanged() && !window.needRefresh) { emit.apply(socket, arguments) }
+}
socket.on('info', function (data) {
- console.error(data);
- switch (data.code) {
- case 403:
- location.href = serverurl + "/403";
- break;
- case 404:
- location.href = serverurl + "/404";
- break;
- case 500:
- location.href = serverurl + "/500";
- break;
- }
-});
+ console.error(data)
+ switch (data.code) {
+ case 403:
+ location.href = serverurl + '/403'
+ break
+ case 404:
+ location.href = serverurl + '/404'
+ break
+ case 500:
+ location.href = serverurl + '/500'
+ break
+ }
+})
socket.on('error', function (data) {
- console.error(data);
- if (data.message && data.message.indexOf('AUTH failed') === 0)
- location.href = serverurl + "/403";
-});
+ console.error(data)
+ if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' }
+})
socket.on('delete', function () {
- if (personalInfo.login) {
- deleteServerHistory(noteid, function (err, data) {
- if (!err) location.href = serverurl;
- });
- } else {
- getHistory(function (notehistory) {
- var newnotehistory = removeHistory(noteid, notehistory);
- saveHistory(newnotehistory);
- location.href = serverurl;
- });
- }
-});
-var retryTimer = null;
+ if (window.personalInfo.login) {
+ deleteServerHistory(noteid, function (err, data) {
+ if (!err) location.href = serverurl
+ })
+ } else {
+ getHistory(function (notehistory) {
+ var newnotehistory = removeHistory(noteid, notehistory)
+ saveHistory(newnotehistory)
+ location.href = serverurl
+ })
+ }
+})
+var retryTimer = null
socket.on('maintenance', function () {
- cmClient.revision = -1;
-});
+ cmClient.revision = -1
+})
socket.on('disconnect', function (data) {
- showStatus(statusType.offline);
- if (loaded) {
- saveInfo();
- lastInfo.history = editor.getHistory();
- }
- if (!editor.getOption('readOnly'))
- editor.setOption('readOnly', true);
- if (!retryTimer) {
- retryTimer = setInterval(function () {
- if (!needRefresh) socket.connect();
- }, 1000);
- }
-});
+ showStatus(statusType.offline)
+ if (window.loaded) {
+ saveInfo()
+ window.lastInfo.history = editor.getHistory()
+ }
+ if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) }
+ if (!retryTimer) {
+ retryTimer = setInterval(function () {
+ if (!window.needRefresh) socket.connect()
+ }, 1000)
+ }
+})
socket.on('reconnect', function (data) {
- //sync back any change in offline
- emitUserStatus(true);
- cursorActivity();
- socket.emit('online users');
-});
+ // sync back any change in offline
+ emitUserStatus(true)
+ cursorActivity()
+ socket.emit('online users')
+})
socket.on('connect', function (data) {
- clearInterval(retryTimer);
- retryTimer = null;
- personalInfo['id'] = socket.id;
- showStatus(statusType.connected);
- socket.emit('version');
-});
+ clearInterval(retryTimer)
+ retryTimer = null
+ window.personalInfo['id'] = socket.id
+ showStatus(statusType.connected)
+ socket.emit('version')
+})
socket.on('version', function (data) {
- if (version != data.version) {
- if (version < data.minimumCompatibleVersion) {
- setRefreshModal('incompatible-version');
- setNeedRefresh();
- } else {
- setRefreshModal('new-version');
- }
- }
-});
-var authors = [];
-var authorship = [];
-var authorshipMarks = {};
-var authorMarks = {}; // temp variable
-var addTextMarkers = []; // temp variable
-function updateInfo(data) {
- //console.log(data);
- if (data.hasOwnProperty('createtime') && createtime !== data.createtime) {
- createtime = data.createtime;
- updateLastChange();
- }
- if (data.hasOwnProperty('updatetime') && lastchangetime !== data.updatetime) {
- lastchangetime = data.updatetime;
- updateLastChange();
- }
- if (data.hasOwnProperty('owner') && owner !== data.owner) {
- owner = data.owner;
- ownerprofile = data.ownerprofile;
- updateOwner();
- }
- if (data.hasOwnProperty('lastchangeuser') && lastchangeuser !== data.lastchangeuser) {
- lastchangeuser = data.lastchangeuser;
- lastchangeuserprofile = data.lastchangeuserprofile;
- updateLastChangeUser();
- updateOwner();
- }
- if (data.hasOwnProperty('authors') && authors !== data.authors) {
- authors = data.authors;
- }
- if (data.hasOwnProperty('authorship') && authorship !== data.authorship) {
- authorship = data.authorship;
- updateAuthorship();
+ if (version !== data.version) {
+ if (version < data.minimumCompatibleVersion) {
+ setRefreshModal('incompatible-version')
+ setNeedRefresh()
+ } else {
+ setRefreshModal('new-version')
}
+ }
+})
+var authors = []
+var authorship = []
+var authorMarks = {} // temp variable
+var addTextMarkers = [] // temp variable
+function updateInfo (data) {
+ // console.log(data);
+ if (data.hasOwnProperty('createtime') && window.createtime !== data.createtime) {
+ window.createtime = data.createtime
+ updateLastChange()
+ }
+ if (data.hasOwnProperty('updatetime') && window.lastchangetime !== data.updatetime) {
+ window.lastchangetime = data.updatetime
+ updateLastChange()
+ }
+ if (data.hasOwnProperty('owner') && window.owner !== data.owner) {
+ window.owner = data.owner
+ window.ownerprofile = data.ownerprofile
+ updateOwner()
+ }
+ if (data.hasOwnProperty('lastchangeuser') && window.lastchangeuser !== data.lastchangeuser) {
+ window.lastchangeuser = data.lastchangeuser
+ window.lastchangeuserprofile = data.lastchangeuserprofile
+ updateLastChangeUser()
+ updateOwner()
+ }
+ if (data.hasOwnProperty('authors') && authors !== data.authors) {
+ authors = data.authors
+ }
+ if (data.hasOwnProperty('authorship') && authorship !== data.authorship) {
+ authorship = data.authorship
+ updateAuthorship()
+ }
}
var updateAuthorship = _.debounce(function () {
- editor.operation(updateAuthorshipInner);
-}, 50);
-function initMark() {
- return {
- gutter: {
- userid: null,
- timestamp: null
- },
- textmarkers: []
- };
-}
-function initMarkAndCheckGutter(mark, author, timestamp) {
- if (!mark) mark = initMark();
- if (!mark.gutter.userid || mark.gutter.timestamp > timestamp) {
- mark.gutter.userid = author.userid;
- mark.gutter.timestamp = timestamp;
- }
- return mark;
-}
-var gutterStylePrefix = "border-left: 3px solid ";
-var gutterStylePostfix = "; height: " + defaultTextHeight + "px; margin-left: 3px;";
-var textMarkderStylePrefix = "background-image: linear-gradient(to top, ";
-var textMarkderStylePostfix = " 1px, transparent 1px);";
+ editor.operation(updateAuthorshipInner)
+}, 50)
+function initMark () {
+ return {
+ gutter: {
+ userid: null,
+ timestamp: null
+ },
+ textmarkers: []
+ }
+}
+function initMarkAndCheckGutter (mark, author, timestamp) {
+ if (!mark) mark = initMark()
+ if (!mark.gutter.userid || mark.gutter.timestamp > timestamp) {
+ mark.gutter.userid = author.userid
+ mark.gutter.timestamp = timestamp
+ }
+ return mark
+}
+var gutterStylePrefix = 'border-left: 3px solid '
+var gutterStylePostfix = '; height: ' + defaultTextHeight + 'px; margin-left: 3px;'
+var textMarkderStylePrefix = 'background-image: linear-gradient(to top, '
+var textMarkderStylePostfix = ' 1px, transparent 1px);'
var addStyleRule = (function () {
- var added = {};
- var styleElement = document.createElement('style');
- document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
- var styleSheet = styleElement.sheet;
-
- return function (css) {
- if (added[css]) {
- return;
- }
- added[css] = true;
- styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length);
- };
-}());
-function updateAuthorshipInner() {
+ var added = {}
+ var styleElement = document.createElement('style')
+ document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement)
+ var styleSheet = styleElement.sheet
+
+ return function (css) {
+ if (added[css]) {
+ return
+ }
+ added[css] = true
+ styleSheet.insertRule(css, (styleSheet.cssRules || styleSheet.rules).length)
+ }
+}())
+function updateAuthorshipInner () {
// ignore when ot not synced yet
- if (havePendingOperation()) return;
- authorMarks = {};
- for (var i = 0; i < authorship.length; i++) {
- var atom = authorship[i];
- var author = authors[atom[0]];
- if (author) {
- var prePos = editor.posFromIndex(atom[1]);
- var preLine = editor.getLine(prePos.line);
- var postPos = editor.posFromIndex(atom[2]);
- var postLine = editor.getLine(postPos.line);
- if (prePos.ch == 0 && postPos.ch == postLine.length) {
- for (var j = prePos.line; j <= postPos.line; j++) {
- if (editor.getLine(j)) {
- authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3]);
- }
- }
- } else if (postPos.line - prePos.line >= 1) {
- var startLine = prePos.line;
- var endLine = postPos.line;
- if (prePos.ch == preLine.length) {
- startLine++;
- } else if (prePos.ch != 0) {
- var mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3]);
- var _postPos = {
- line: prePos.line,
- ch: preLine.length
- };
- if (JSON.stringify(prePos) != JSON.stringify(_postPos)) {
- mark.textmarkers.push({
- userid: author.userid,
- pos: [prePos, _postPos]
- });
- startLine++;
- }
- authorMarks[prePos.line] = mark;
- }
- if (postPos.ch == 0) {
- endLine--;
- } else if (postPos.ch != postLine.length) {
- var mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3]);
- var _prePos = {
- line: postPos.line,
- ch: 0
- };
- if (JSON.stringify(_prePos) != JSON.stringify(postPos)) {
- mark.textmarkers.push({
- userid: author.userid,
- pos: [_prePos, postPos]
- });
- endLine--;
- }
- authorMarks[postPos.line] = mark;
- }
- for (var j = startLine; j <= endLine; j++) {
- if (editor.getLine(j)) {
- authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3]);
- }
- }
- } else {
- var mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3]);
- if (JSON.stringify(prePos) != JSON.stringify(postPos)) {
- mark.textmarkers.push({
- userid: author.userid,
- pos: [prePos, postPos]
- });
- }
- authorMarks[prePos.line] = mark;
- }
- }
- }
- addTextMarkers = [];
- editor.eachLine(iterateLine);
- var allTextMarks = editor.getAllMarks();
- for (var i = 0; i < allTextMarks.length; i++) {
- var _textMarker = allTextMarks[i];
- var pos = _textMarker.find();
- var found = false;
- for (var j = 0; j < addTextMarkers.length; j++) {
- var textMarker = addTextMarkers[j];
- var author = authors[textMarker.userid];
- var className = 'authorship-inline-' + author.color.substr(1);
- var obj = {
- from: textMarker.pos[0],
- to: textMarker.pos[1]
- };
- if (JSON.stringify(pos) == JSON.stringify(obj) && _textMarker.className &&
+ if (havePendingOperation()) return
+ authorMarks = {}
+ for (let i = 0; i < authorship.length; i++) {
+ var atom = authorship[i]
+ let author = authors[atom[0]]
+ if (author) {
+ var prePos = editor.posFromIndex(atom[1])
+ var preLine = editor.getLine(prePos.line)
+ var postPos = editor.posFromIndex(atom[2])
+ var postLine = editor.getLine(postPos.line)
+ if (prePos.ch === 0 && postPos.ch === postLine.length) {
+ for (let j = prePos.line; j <= postPos.line; j++) {
+ if (editor.getLine(j)) {
+ authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])
+ }
+ }
+ } else if (postPos.line - prePos.line >= 1) {
+ var startLine = prePos.line
+ var endLine = postPos.line
+ if (prePos.ch === preLine.length) {
+ startLine++
+ } else if (prePos.ch !== 0) {
+ let mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
+ var _postPos = {
+ line: prePos.line,
+ ch: preLine.length
+ }
+ if (JSON.stringify(prePos) !== JSON.stringify(_postPos)) {
+ mark.textmarkers.push({ userid: author.userid, pos: [prePos, _postPos] })
+ startLine++
+ }
+ authorMarks[prePos.line] = mark
+ }
+ if (postPos.ch === 0) {
+ endLine--
+ } else if (postPos.ch !== postLine.length) {
+ let mark = initMarkAndCheckGutter(authorMarks[postPos.line], author, atom[3])
+ var _prePos = {
+ line: postPos.line,
+ ch: 0
+ }
+ if (JSON.stringify(_prePos) !== JSON.stringify(postPos)) {
+ mark.textmarkers.push({ userid: author.userid, pos: [_prePos, postPos] })
+ endLine--
+ }
+ authorMarks[postPos.line] = mark
+ }
+ for (let j = startLine; j <= endLine; j++) {
+ if (editor.getLine(j)) {
+ authorMarks[j] = initMarkAndCheckGutter(authorMarks[j], author, atom[3])
+ }
+ }
+ } else {
+ let mark = initMarkAndCheckGutter(authorMarks[prePos.line], author, atom[3])
+ if (JSON.stringify(prePos) !== JSON.stringify(postPos)) {
+ mark.textmarkers.push({
+ userid: author.userid,
+ pos: [prePos, postPos]
+ })
+ }
+ authorMarks[prePos.line] = mark
+ }
+ }
+ }
+ addTextMarkers = []
+ editor.eachLine(iterateLine)
+ var allTextMarks = editor.getAllMarks()
+ for (let i = 0; i < allTextMarks.length; i++) {
+ let _textMarker = allTextMarks[i]
+ var pos = _textMarker.find()
+ var found = false
+ for (let j = 0; j < addTextMarkers.length; j++) {
+ let textMarker = addTextMarkers[j]
+ let author = authors[textMarker.userid]
+ let className = 'authorship-inline-' + author.color.substr(1)
+ var obj = {
+ from: textMarker.pos[0],
+ to: textMarker.pos[1]
+ }
+ if (JSON.stringify(pos) === JSON.stringify(obj) && _textMarker.className &&
_textMarker.className.indexOf(className) > -1) {
- addTextMarkers.splice(j, 1);
- j--;
- found = true;
- break;
- }
- }
- if (!found && _textMarker.className && _textMarker.className.indexOf('authorship-inline') > -1) {
- _textMarker.clear();
- }
- }
- for (var i = 0; i < addTextMarkers.length; i++) {
- var textMarker = addTextMarkers[i];
- var author = authors[textMarker.userid];
- var rgbcolor = hex2rgb(author.color);
- var colorString = "rgba(" + rgbcolor.red + "," + rgbcolor.green + "," + rgbcolor.blue + ",0.7)";
- var styleString = textMarkderStylePrefix + colorString + textMarkderStylePostfix;
- var className = 'authorship-inline-' + author.color.substr(1);
- var rule = "." + className + "{" + styleString + "}";
- addStyleRule(rule);
- var _textMarker = editor.markText(textMarker.pos[0], textMarker.pos[1], {
- className: 'authorship-inline ' + className,
- title: author.name
- });
- }
- authorshipMarks = authorMarks;
-}
-function iterateLine(line) {
- var lineNumber = line.lineNo();
- var currMark = authorMarks[lineNumber];
- var author = currMark ? authors[currMark.gutter.userid] : null;
- if (currMark && author) {
- var className = 'authorship-gutter-' + author.color.substr(1);
- var gutters = line.gutterMarkers;
- if (!gutters || !gutters['authorship-gutters'] ||
+ addTextMarkers.splice(j, 1)
+ j--
+ found = true
+ break
+ }
+ }
+ if (!found && _textMarker.className && _textMarker.className.indexOf('authorship-inline') > -1) {
+ _textMarker.clear()
+ }
+ }
+ for (let i = 0; i < addTextMarkers.length; i++) {
+ let textMarker = addTextMarkers[i]
+ let author = authors[textMarker.userid]
+ var rgbcolor = hex2rgb(author.color)
+ var colorString = 'rgba(' + rgbcolor.red + ',' + rgbcolor.green + ',' + rgbcolor.blue + ',0.7)'
+ var styleString = textMarkderStylePrefix + colorString + textMarkderStylePostfix
+ let className = 'authorship-inline-' + author.color.substr(1)
+ var rule = '.' + className + '{' + styleString + '}'
+ addStyleRule(rule)
+ editor.markText(textMarker.pos[0], textMarker.pos[1], {
+ className: 'authorship-inline ' + className,
+ title: author.name
+ })
+ }
+}
+function iterateLine (line) {
+ var lineNumber = line.lineNo()
+ var currMark = authorMarks[lineNumber]
+ var author = currMark ? authors[currMark.gutter.userid] : null
+ if (currMark && author) {
+ let className = 'authorship-gutter-' + author.color.substr(1)
+ var gutters = line.gutterMarkers
+ if (!gutters || !gutters['authorship-gutters'] ||
!gutters['authorship-gutters'].className ||
!gutters['authorship-gutters'].className.indexOf(className) < 0) {
- var styleString = gutterStylePrefix + author.color + gutterStylePostfix;
- var rule = "." + className + "{" + styleString + "}";
- addStyleRule(rule);
- var gutter = $('<div>', {
- class: 'authorship-gutter ' + className,
- title: author.name
- });
- editor.setGutterMarker(line, "authorship-gutters", gutter[0]);
- }
- } else {
- editor.setGutterMarker(line, "authorship-gutters", null);
- }
- if (currMark && currMark.textmarkers.length > 0) {
- for (var i = 0; i < currMark.textmarkers.length; i++) {
- var textMarker = currMark.textmarkers[i];
- if (textMarker.userid != currMark.gutter.userid) {
- addTextMarkers.push(textMarker);
- }
- }
- }
+ var styleString = gutterStylePrefix + author.color + gutterStylePostfix
+ var rule = '.' + className + '{' + styleString + '}'
+ addStyleRule(rule)
+ var gutter = $('<div>', {
+ class: 'authorship-gutter ' + className,
+ title: author.name
+ })
+ editor.setGutterMarker(line, 'authorship-gutters', gutter[0])
+ }
+ } else {
+ editor.setGutterMarker(line, 'authorship-gutters', null)
+ }
+ if (currMark && currMark.textmarkers.length > 0) {
+ for (var i = 0; i < currMark.textmarkers.length; i++) {
+ let textMarker = currMark.textmarkers[i]
+ if (textMarker.userid !== currMark.gutter.userid) {
+ addTextMarkers.push(textMarker)
+ }
+ }
+ }
}
editor.on('update', function () {
- $('.authorship-gutter:not([data-original-title])').tooltip({
- container: '.CodeMirror-lines',
- placement: 'right',
- delay: { "show": 500, "hide": 100 }
- });
- $('.authorship-inline:not([data-original-title])').tooltip({
- container: '.CodeMirror-lines',
- placement: 'bottom',
- delay: { "show": 500, "hide": 100 }
- });
+ $('.authorship-gutter:not([data-original-title])').tooltip({
+ container: '.CodeMirror-lines',
+ placement: 'right',
+ delay: { 'show': 500, 'hide': 100 }
+ })
+ $('.authorship-inline:not([data-original-title])').tooltip({
+ container: '.CodeMirror-lines',
+ placement: 'bottom',
+ delay: { 'show': 500, 'hide': 100 }
+ })
// clear tooltip which described element has been removed
- $('[id^="tooltip"]').each(function (index, element) {
- var $ele = $(element);
- if ($('[aria-describedby="' + $ele.attr('id') + '"]').length <= 0) $ele.remove();
- });
-});
+ $('[id^="tooltip"]').each(function (index, element) {
+ var $ele = $(element)
+ if ($('[aria-describedby="' + $ele.attr('id') + '"]').length <= 0) $ele.remove()
+ })
+})
socket.on('check', function (data) {
- //console.log(data);
- updateInfo(data);
-});
+ // console.log(data);
+ updateInfo(data)
+})
socket.on('permission', function (data) {
- updatePermission(data.permission);
-});
-var docmaxlength = null;
-var permission = null;
+ updatePermission(data.permission)
+})
+var docmaxlength = null
+var permission = null
socket.on('refresh', function (data) {
- //console.log(data);
- docmaxlength = data.docmaxlength;
- editor.setOption("maxLength", docmaxlength);
- updateInfo(data);
- updatePermission(data.permission);
- if (!loaded) {
+ // console.log(data);
+ docmaxlength = data.docmaxlength
+ editor.setOption('maxLength', docmaxlength)
+ updateInfo(data)
+ updatePermission(data.permission)
+ if (!window.loaded) {
// auto change mode if no content detected
- var nocontent = editor.getValue().length <= 0;
- if (nocontent) {
- if (visibleXS)
- currentMode = modeType.edit;
- else
- currentMode = modeType.both;
- }
+ var nocontent = editor.getValue().length <= 0
+ if (nocontent) {
+ if (window.visibleXS) { window.currentMode = modeType.edit } else { window.currentMode = modeType.both }
+ }
// parse mode from url
- if (window.location.search.length > 0) {
- var urlMode = modeType[window.location.search.substr(1)];
- if (urlMode) currentMode = urlMode;
- }
- changeMode(currentMode);
- if (nocontent && !visibleXS) {
- editor.focus();
- editor.refresh();
- }
- updateViewInner(); // bring up view rendering earlier
- updateHistory(); //update history whether have content or not
- loaded = true;
- emitUserStatus(); //send first user status
- updateOnlineStatus(); //update first online status
- setTimeout(function () {
- //work around editor not refresh or doc not fully loaded
- windowResizeInner();
- //work around might not scroll to hash
- scrollToHash();
- }, 1);
- }
- if (editor.getOption('readOnly'))
- editor.setOption('readOnly', false);
-});
-
-var EditorClient = ot.EditorClient;
-var SocketIOAdapter = ot.SocketIOAdapter;
-var CodeMirrorAdapter = ot.CodeMirrorAdapter;
-var cmClient = null;
-var synchronized_ = null;
-
-function havePendingOperation() {
- return (cmClient && cmClient.state && cmClient.state.hasOwnProperty('outstanding')) ? true : false;
-}
-
-socket.on('doc', function (obj) {
- var body = obj.str;
- var bodyMismatch = editor.getValue() !== body;
- var setDoc = !cmClient || (cmClient && (cmClient.revision === -1 || (cmClient.revision !== obj.revision && !havePendingOperation()))) || obj.force;
+ if (window.location.search.length > 0) {
+ var urlMode = modeType[window.location.search.substr(1)]
+ if (urlMode) window.currentMode = urlMode
+ }
+ changeMode(window.currentMode)
+ if (nocontent && !window.visibleXS) {
+ editor.focus()
+ editor.refresh()
+ }
+ updateViewInner() // bring up view rendering earlier
+ updateHistory() // update history whether have content or not
+ window.loaded = true
+ emitUserStatus() // send first user status
+ updateOnlineStatus() // update first online status
+ setTimeout(function () {
+ // work around editor not refresh or doc not fully loaded
+ windowResizeInner()
+ // work around might not scroll to hash
+ scrollToHash()
+ }, 1)
+ }
+ if (editor.getOption('readOnly')) { editor.setOption('readOnly', false) }
+})
- saveInfo();
- if (setDoc && bodyMismatch) {
- if (cmClient) cmClient.editorAdapter.ignoreNextChange = true;
- if (body) editor.setValue(body);
- else editor.setValue("");
- }
+var EditorClient = ot.EditorClient
+var SocketIOAdapter = ot.SocketIOAdapter
+var CodeMirrorAdapter = ot.CodeMirrorAdapter
+var cmClient = null
+var synchronized_ = null
- if (!loaded) {
- editor.clearHistory();
- ui.spinner.hide();
- ui.content.fadeIn();
- } else {
- //if current doc is equal to the doc before disconnect
- if (setDoc && bodyMismatch) editor.clearHistory();
- else if (lastInfo.history) editor.setHistory(lastInfo.history);
- lastInfo.history = null;
- }
+function havePendingOperation () {
+ return !!((cmClient && cmClient.state && cmClient.state.hasOwnProperty('outstanding')))
+}
- if (!cmClient) {
- cmClient = window.cmClient = new EditorClient(
+socket.on('doc', function (obj) {
+ var body = obj.str
+ var bodyMismatch = editor.getValue() !== body
+ var setDoc = !cmClient || (cmClient && (cmClient.revision === -1 || (cmClient.revision !== obj.revision && !havePendingOperation()))) || obj.force
+
+ saveInfo()
+ if (setDoc && bodyMismatch) {
+ if (cmClient) cmClient.editorAdapter.ignoreNextChange = true
+ if (body) editor.setValue(body)
+ else editor.setValue('')
+ }
+
+ if (!window.loaded) {
+ editor.clearHistory()
+ ui.spinner.hide()
+ ui.content.fadeIn()
+ } else {
+ // if current doc is equal to the doc before disconnect
+ if (setDoc && bodyMismatch) editor.clearHistory()
+ else if (window.lastInfo.history) editor.setHistory(window.lastInfo.history)
+ window.lastInfo.history = null
+ }
+
+ if (!cmClient) {
+ cmClient = window.cmClient = new EditorClient(
obj.revision, obj.clients,
new SocketIOAdapter(socket), new CodeMirrorAdapter(editor)
- );
- synchronized_ = cmClient.state;
- } else if (setDoc) {
- if (bodyMismatch) {
- cmClient.undoManager.undoStack.length = 0;
- cmClient.undoManager.redoStack.length = 0;
- }
- cmClient.revision = obj.revision;
- cmClient.setState(synchronized_);
- cmClient.initializeClientList();
- cmClient.initializeClients(obj.clients);
- } else if (havePendingOperation()) {
- cmClient.serverReconnect();
- }
-
- if (setDoc && bodyMismatch) {
- isDirty = true;
- updateView();
- }
-
- restoreInfo();
-});
+ )
+ synchronized_ = cmClient.state
+ } else if (setDoc) {
+ if (bodyMismatch) {
+ cmClient.undoManager.undoStack.length = 0
+ cmClient.undoManager.redoStack.length = 0
+ }
+ cmClient.revision = obj.revision
+ cmClient.setState(synchronized_)
+ cmClient.initializeClientList()
+ cmClient.initializeClients(obj.clients)
+ } else if (havePendingOperation()) {
+ cmClient.serverReconnect()
+ }
+
+ if (setDoc && bodyMismatch) {
+ window.isDirty = true
+ updateView()
+ }
+
+ restoreInfo()
+})
socket.on('ack', function () {
- isDirty = true;
- updateView();
-});
+ window.isDirty = true
+ updateView()
+})
socket.on('operation', function () {
- isDirty = true;
- updateView();
-});
+ window.isDirty = true
+ updateView()
+})
socket.on('online users', function (data) {
- if (debug)
- console.debug(data);
- onlineUsers = data.users;
- updateOnlineStatus();
- $('.CodeMirror-other-cursors').children().each(function (key, value) {
- var found = false;
- for (var i = 0; i < data.users.length; i++) {
- var user = data.users[i];
- if ($(this).attr('id') == user.id)
- found = true;
- }
- if (!found)
- $(this).stop(true).fadeOut("normal", function () {
- $(this).remove();
- });
- });
+ if (debug) { console.debug(data) }
+ window.onlineUsers = data.users
+ updateOnlineStatus()
+ $('.CodeMirror-other-cursors').children().each(function (key, value) {
+ var found = false
for (var i = 0; i < data.users.length; i++) {
- var user = data.users[i];
- if (user.id != socket.id)
- buildCursor(user);
- else
- personalInfo = user;
- }
-});
+ var user = data.users[i]
+ if ($(this).attr('id') === user.id) { found = true }
+ }
+ if (!found) {
+ $(this).stop(true).fadeOut('normal', function () {
+ $(this).remove()
+ })
+ }
+ })
+ for (var i = 0; i < data.users.length; i++) {
+ var user = data.users[i]
+ if (user.id !== socket.id) { buildCursor(user) } else { window.personalInfo = user }
+ }
+})
socket.on('user status', function (data) {
- if (debug)
- console.debug(data);
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == data.id) {
- onlineUsers[i] = data;
- }
- }
- updateOnlineStatus();
- if (data.id != socket.id)
- buildCursor(data);
-});
+ if (debug) { console.debug(data) }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === data.id) {
+ window.onlineUsers[i] = data
+ }
+ }
+ updateOnlineStatus()
+ if (data.id !== socket.id) { buildCursor(data) }
+})
socket.on('cursor focus', function (data) {
- if (debug)
- console.debug(data);
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == data.id) {
- onlineUsers[i].cursor = data.cursor;
- }
- }
- if (data.id != socket.id)
- buildCursor(data);
- //force show
- var cursor = $('div[data-clientid="' + data.id + '"]');
- if (cursor.length > 0) {
- cursor.stop(true).fadeIn();
- }
-});
+ if (debug) { console.debug(data) }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === data.id) {
+ window.onlineUsers[i].cursor = data.cursor
+ }
+ }
+ if (data.id !== socket.id) { buildCursor(data) }
+ // force show
+ var cursor = $('div[data-clientid="' + data.id + '"]')
+ if (cursor.length > 0) {
+ cursor.stop(true).fadeIn()
+ }
+})
socket.on('cursor activity', function (data) {
- if (debug)
- console.debug(data);
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == data.id) {
- onlineUsers[i].cursor = data.cursor;
- }
+ if (debug) { console.debug(data) }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === data.id) {
+ window.onlineUsers[i].cursor = data.cursor
}
- if (data.id != socket.id)
- buildCursor(data);
-});
+ }
+ if (data.id !== socket.id) { buildCursor(data) }
+})
socket.on('cursor blur', function (data) {
- if (debug)
- console.debug(data);
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == data.id) {
- onlineUsers[i].cursor = null;
- }
- }
- if (data.id != socket.id)
- buildCursor(data);
- //force hide
- var cursor = $('div[data-clientid="' + data.id + '"]');
- if (cursor.length > 0) {
- cursor.stop(true).fadeOut();
- }
-});
+ if (debug) { console.debug(data) }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === data.id) {
+ window.onlineUsers[i].cursor = null
+ }
+ }
+ if (data.id !== socket.id) { buildCursor(data) }
+ // force hide
+ var cursor = $('div[data-clientid="' + data.id + '"]')
+ if (cursor.length > 0) {
+ cursor.stop(true).fadeOut()
+ }
+})
var options = {
- valueNames: ['id', 'name'],
- item: '<li class="ui-user-item">\
- <span class="id" style="display:none;"></span>\
- <a href="#">\
- <span class="pull-left"><i class="ui-user-icon"></i></span><span class="ui-user-name name"></span><span class="pull-right"><i class="fa fa-circle ui-user-status"></i></span>\
- </a>\
- </li>'
-};
-var onlineUserList = new List('online-user-list', options);
-var shortOnlineUserList = new List('short-online-user-list', options);
-
-function updateOnlineStatus() {
- if (!loaded || !socket.connected) return;
- var _onlineUsers = deduplicateOnlineUsers(onlineUsers);
- showStatus(statusType.online, _onlineUsers.length);
- var items = onlineUserList.items;
- //update or remove current list items
- for (var i = 0; i < items.length; i++) {
- var found = false;
- var foundindex = null;
- for (var j = 0; j < _onlineUsers.length; j++) {
- if (items[i].values().id == _onlineUsers[j].id) {
- foundindex = j;
- found = true;
- break;
- }
- }
- var id = items[i].values().id;
- if (found) {
- onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex]);
- shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex]);
- } else {
- onlineUserList.remove('id', id);
- shortOnlineUserList.remove('id', id);
- }
- }
- //add not in list items
- for (var i = 0; i < _onlineUsers.length; i++) {
- var found = false;
- for (var j = 0; j < items.length; j++) {
- if (items[j].values().id == _onlineUsers[i].id) {
- found = true;
- break;
- }
- }
- if (!found) {
- onlineUserList.add(_onlineUsers[i]);
- shortOnlineUserList.add(_onlineUsers[i]);
- }
+ valueNames: ['id', 'name'],
+ item: '<li class="ui-user-item">' +
+ '<span class="id" style="display:none;"></span>' +
+ '<a href="#">' +
+ '<span class="pull-left"><i class="ui-user-icon"></i></span><span class="ui-user-name name"></span><span class="pull-right"><i class="fa fa-circle ui-user-status"></i></span>' +
+ '</a>' +
+ '</li>'
+}
+var onlineUserList = new List('online-user-list', options)
+var shortOnlineUserList = new List('short-online-user-list', options)
+
+function updateOnlineStatus () {
+ if (!window.loaded || !socket.connected) return
+ var _onlineUsers = deduplicateOnlineUsers(window.onlineUsers)
+ showStatus(statusType.online, _onlineUsers.length)
+ var items = onlineUserList.items
+ // update or remove current list items
+ for (let i = 0; i < items.length; i++) {
+ let found = false
+ let foundindex = null
+ for (let j = 0; j < _onlineUsers.length; j++) {
+ if (items[i].values().id === _onlineUsers[j].id) {
+ foundindex = j
+ found = true
+ break
+ }
+ }
+ let id = items[i].values().id
+ if (found) {
+ onlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
+ shortOnlineUserList.get('id', id)[0].values(_onlineUsers[foundindex])
+ } else {
+ onlineUserList.remove('id', id)
+ shortOnlineUserList.remove('id', id)
+ }
+ }
+ // add not in list items
+ for (let i = 0; i < _onlineUsers.length; i++) {
+ let found = false
+ for (let j = 0; j < items.length; j++) {
+ if (items[j].values().id === _onlineUsers[i].id) {
+ found = true
+ break
+ }
+ }
+ if (!found) {
+ onlineUserList.add(_onlineUsers[i])
+ shortOnlineUserList.add(_onlineUsers[i])
+ }
+ }
+ // sorting
+ sortOnlineUserList(onlineUserList)
+ sortOnlineUserList(shortOnlineUserList)
+ // render list items
+ renderUserStatusList(onlineUserList)
+ renderUserStatusList(shortOnlineUserList)
+}
+
+function sortOnlineUserList (list) {
+ // sort order by isSelf, login state, idle state, alphabet name, color brightness
+ list.sort('', {
+ sortFunction: function (a, b) {
+ var usera = a.values()
+ var userb = b.values()
+ var useraIsSelf = (usera.id === window.personalInfo.id || (usera.login && usera.userid === window.personalInfo.userid))
+ var userbIsSelf = (userb.id === window.personalInfo.id || (userb.login && userb.userid === window.personalInfo.userid))
+ if (useraIsSelf && !userbIsSelf) {
+ return -1
+ } else if (!useraIsSelf && userbIsSelf) {
+ return 1
+ } else {
+ if (usera.login && !userb.login) { return -1 } else if (!usera.login && userb.login) { return 1 } else {
+ if (!usera.idle && userb.idle) { return -1 } else if (usera.idle && !userb.idle) { return 1 } else {
+ if (usera.name && userb.name && usera.name.toLowerCase() < userb.name.toLowerCase()) {
+ return -1
+ } else if (usera.name && userb.name && usera.name.toLowerCase() > userb.name.toLowerCase()) { return 1 } else { if (usera.color && userb.color && usera.color.toLowerCase() < userb.color.toLowerCase()) { return -1 } else if (usera.color && userb.color && usera.color.toLowerCase() > userb.color.toLowerCase()) { return 1 } else { return 0 } }
+ }
+ }
+ }
+ }
+ })
+}
+
+function renderUserStatusList (list) {
+ var items = list.items
+ for (var j = 0; j < items.length; j++) {
+ var item = items[j]
+ var userstatus = $(item.elm).find('.ui-user-status')
+ var usericon = $(item.elm).find('.ui-user-icon')
+ if (item.values().login && item.values().photo) {
+ usericon.css('background-image', 'url(' + item.values().photo + ')')
+ // add 1px more to right, make it feel aligned
+ usericon.css('margin-right', '6px')
+ $(item.elm).css('border-left', '4px solid ' + item.values().color)
+ usericon.css('margin-left', '-4px')
+ } else {
+ usericon.css('background-color', item.values().color)
}
- //sorting
- sortOnlineUserList(onlineUserList);
- sortOnlineUserList(shortOnlineUserList);
- //render list items
- renderUserStatusList(onlineUserList);
- renderUserStatusList(shortOnlineUserList);
-}
-
-function sortOnlineUserList(list) {
- //sort order by isSelf, login state, idle state, alphabet name, color brightness
- list.sort('', {
- sortFunction: function (a, b) {
- var usera = a.values();
- var userb = b.values();
- var useraIsSelf = (usera.id == personalInfo.id || (usera.login && usera.userid == personalInfo.userid));
- var userbIsSelf = (userb.id == personalInfo.id || (userb.login && userb.userid == personalInfo.userid));
- if (useraIsSelf && !userbIsSelf) {
- return -1;
- } else if (!useraIsSelf && userbIsSelf) {
- return 1;
- } else {
- if (usera.login && !userb.login)
- return -1;
- else if (!usera.login && userb.login)
- return 1;
- else {
- if (!usera.idle && userb.idle)
- return -1;
- else if (usera.idle && !userb.idle)
- return 1;
- else {
- if (usera.name && userb.name && usera.name.toLowerCase() < userb.name.toLowerCase()) {
- return -1;
- } else if (usera.name && userb.name && usera.name.toLowerCase() > userb.name.toLowerCase()) {
- return 1;
- } else {
- if (usera.color && userb.color && usera.color.toLowerCase() < userb.color.toLowerCase())
- return -1;
- else if (usera.color && userb.color && usera.color.toLowerCase() > userb.color.toLowerCase())
- return 1;
- else
- return 0;
- }
- }
- }
- }
- }
- });
-}
-
-function renderUserStatusList(list) {
- var items = list.items;
- for (var j = 0; j < items.length; j++) {
- var item = items[j];
- var userstatus = $(item.elm).find('.ui-user-status');
- var usericon = $(item.elm).find('.ui-user-icon');
- if (item.values().login && item.values().photo) {
- usericon.css('background-image', 'url(' + item.values().photo + ')');
- //add 1px more to right, make it feel aligned
- usericon.css('margin-right', '6px');
- $(item.elm).css('border-left', '4px solid ' + item.values().color);
- usericon.css('margin-left', '-4px');
- } else {
- usericon.css('background-color', item.values().color);
- }
- userstatus.removeClass('ui-user-status-offline ui-user-status-online ui-user-status-idle');
- if (item.values().idle)
- userstatus.addClass('ui-user-status-idle');
- else
- userstatus.addClass('ui-user-status-online');
- }
-}
-
-function deduplicateOnlineUsers(list) {
- var _onlineUsers = [];
- for (var i = 0; i < list.length; i++) {
- var user = $.extend({}, list[i]);
- if (!user.userid)
- _onlineUsers.push(user);
- else {
- var found = false;
- for (var j = 0; j < _onlineUsers.length; j++) {
- if (_onlineUsers[j].userid == user.userid) {
- //keep self color when login
- if (user.id == personalInfo.id) {
- _onlineUsers[j].color = user.color;
- }
- //keep idle state if any of self client not idle
- if (!user.idle) {
- _onlineUsers[j].idle = user.idle;
- _onlineUsers[j].color = user.color;
- }
- found = true;
- break;
- }
- }
- if (!found)
- _onlineUsers.push(user);
+ userstatus.removeClass('ui-user-status-offline ui-user-status-online ui-user-status-idle')
+ if (item.values().idle) { userstatus.addClass('ui-user-status-idle') } else { userstatus.addClass('ui-user-status-online') }
+ }
+}
+
+function deduplicateOnlineUsers (list) {
+ var _onlineUsers = []
+ for (var i = 0; i < list.length; i++) {
+ var user = $.extend({}, list[i])
+ if (!user.userid) { _onlineUsers.push(user) } else {
+ var found = false
+ for (var j = 0; j < _onlineUsers.length; j++) {
+ if (_onlineUsers[j].userid === user.userid) {
+ // keep self color when login
+ if (user.id === window.personalInfo.id) {
+ _onlineUsers[j].color = user.color
+ }
+ // keep idle state if any of self client not idle
+ if (!user.idle) {
+ _onlineUsers[j].idle = user.idle
+ _onlineUsers[j].color = user.color
+ }
+ found = true
+ break
}
+ }
+ if (!found) { _onlineUsers.push(user) }
}
- return _onlineUsers;
+ }
+ return _onlineUsers
}
-var userStatusCache = null;
+var userStatusCache = null
-function emitUserStatus(force) {
- if (!loaded) return;
- var type = null;
- if (visibleXS)
- type = 'xs';
- else if (visibleSM)
- type = 'sm';
- else if (visibleMD)
- type = 'md';
- else if (visibleLG)
- type = 'lg';
+function emitUserStatus (force) {
+ if (!window.loaded) return
+ var type = null
+ if (window.visibleXS) { type = 'xs' } else if (window.visibleSM) { type = 'sm' } else if (window.visibleMD) { type = 'md' } else if (window.visibleLG) { type = 'lg' }
- personalInfo['idle'] = idle.isAway;
- personalInfo['type'] = type;
+ window.personalInfo['idle'] = idle.isAway
+ window.personalInfo['type'] = type
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == personalInfo.id) {
- onlineUsers[i] = personalInfo;
- }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === window.personalInfo.id) {
+ window.onlineUsers[i] = window.personalInfo
}
+ }
- var userStatus = {
- idle: idle.isAway,
- type: type
- };
+ var userStatus = {
+ idle: idle.isAway,
+ type: type
+ }
- if (force || JSON.stringify(userStatus) != JSON.stringify(userStatusCache)) {
- socket.emit('user status', userStatus);
- userStatusCache = userStatus;
- }
+ if (force || JSON.stringify(userStatus) !== JSON.stringify(userStatusCache)) {
+ socket.emit('user status', userStatus)
+ userStatusCache = userStatus
+ }
}
-function checkCursorTag(coord, ele) {
- if (!ele) return; // return if element not exists
+function checkCursorTag (coord, ele) {
+ if (!ele) return // return if element not exists
// set margin
- var tagRightMargin = 0;
- var tagBottomMargin = 2;
+ var tagRightMargin = 0
+ var tagBottomMargin = 2
// use sizer to get the real doc size (won't count status bar and gutters)
- var docWidth = ui.area.codemirrorSizer.width();
- var docHeight = ui.area.codemirrorSizer.height();
+ var docWidth = ui.area.codemirrorSizer.width()
// get editor size (status bar not count in)
- var editorWidth = ui.area.codemirror.width();
- var editorHeight = ui.area.codemirror.height();
+ var editorHeight = ui.area.codemirror.height()
// get element size
- var width = ele.outerWidth();
- var height = ele.outerHeight();
- var padding = (ele.outerWidth() - ele.width()) / 2;
+ var width = ele.outerWidth()
+ var height = ele.outerHeight()
+ var padding = (ele.outerWidth() - ele.width()) / 2
// get coord position
- var left = coord.left;
- var top = coord.top;
+ var left = coord.left
+ var top = coord.top
// get doc top offset (to workaround with viewport)
- var docTopOffset = ui.area.codemirrorSizerInner.position().top;
+ var docTopOffset = ui.area.codemirrorSizerInner.position().top
// set offset
- var offsetLeft = -3;
- var offsetTop = defaultTextHeight;
+ var offsetLeft = -3
+ var offsetTop = defaultTextHeight
// only do when have width and height
- if (width > 0 && height > 0) {
+ if (width > 0 && height > 0) {
// flip x when element right bound larger than doc width
- if (left + width + offsetLeft + tagRightMargin > docWidth) {
- offsetLeft = -(width + tagRightMargin) + padding + offsetLeft;
- }
+ if (left + width + offsetLeft + tagRightMargin > docWidth) {
+ offsetLeft = -(width + tagRightMargin) + padding + offsetLeft
+ }
// flip y when element bottom bound larger than doc height
// and element top position is larger than element height
- if (top + docTopOffset + height + offsetTop + tagBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + tagBottomMargin) {
- offsetTop = -(height);
- }
+ if (top + docTopOffset + height + offsetTop + tagBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + tagBottomMargin) {
+ offsetTop = -(height)
}
+ }
// set position
- ele[0].style.left = offsetLeft + 'px';
- ele[0].style.top = offsetTop + 'px';
-}
-
-function buildCursor(user) {
- if (currentMode == modeType.view) return;
- if (!user.cursor) return;
- var coord = editor.charCoords(user.cursor, 'windows');
- coord.left = coord.left < 4 ? 4 : coord.left;
- coord.top = coord.top < 0 ? 0 : coord.top;
- var iconClass = 'fa-user';
- switch (user.type) {
- case 'xs':
- iconClass = 'fa-mobile';
- break;
- case 'sm':
- iconClass = 'fa-tablet';
- break;
- case 'md':
- iconClass = 'fa-desktop';
- break;
- case 'lg':
- iconClass = 'fa-desktop';
- break;
- }
- if ($('.CodeMirror-other-cursors').length <= 0) {
- $("<div class='CodeMirror-other-cursors'>").insertAfter('.CodeMirror-cursors');
- }
- if ($('div[data-clientid="' + user.id + '"]').length <= 0) {
- var cursor = $('<div data-clientid="' + user.id + '" class="CodeMirror-other-cursor" style="display:none;"></div>');
- cursor.attr('data-line', user.cursor.line);
- cursor.attr('data-ch', user.cursor.ch);
- cursor.attr('data-offset-left', 0);
- cursor.attr('data-offset-top', 0);
-
- var cursorbar = $('<div class="cursorbar">&nbsp;</div>');
- cursorbar[0].style.height = defaultTextHeight + 'px';
- cursorbar[0].style.borderLeft = '2px solid ' + user.color;
-
- var icon = '<i class="fa ' + iconClass + '"></i>';
-
- var cursortag = $('<div class="cursortag">' + icon + '&nbsp;<span class="name">' + user.name + '</span></div>');
- //cursortag[0].style.background = color;
- cursortag[0].style.color = user.color;
-
- cursor.attr('data-mode', 'hover');
- cursortag.delay(2000).fadeOut("fast");
- cursor.hover(
+ ele[0].style.left = offsetLeft + 'px'
+ ele[0].style.top = offsetTop + 'px'
+}
+
+function buildCursor (user) {
+ if (window.currentMode === modeType.view) return
+ if (!user.cursor) return
+ var coord = editor.charCoords(user.cursor, 'windows')
+ coord.left = coord.left < 4 ? 4 : coord.left
+ coord.top = coord.top < 0 ? 0 : coord.top
+ var iconClass = 'fa-user'
+ switch (user.type) {
+ case 'xs':
+ iconClass = 'fa-mobile'
+ break
+ case 'sm':
+ iconClass = 'fa-tablet'
+ break
+ case 'md':
+ iconClass = 'fa-desktop'
+ break
+ case 'lg':
+ iconClass = 'fa-desktop'
+ break
+ }
+ if ($('.CodeMirror-other-cursors').length <= 0) {
+ $("<div class='CodeMirror-other-cursors'>").insertAfter('.CodeMirror-cursors')
+ }
+ if ($('div[data-clientid="' + user.id + '"]').length <= 0) {
+ let cursor = $('<div data-clientid="' + user.id + '" class="CodeMirror-other-cursor" style="display:none;"></div>')
+ cursor.attr('data-line', user.cursor.line)
+ cursor.attr('data-ch', user.cursor.ch)
+ cursor.attr('data-offset-left', 0)
+ cursor.attr('data-offset-top', 0)
+
+ let cursorbar = $('<div class="cursorbar">&nbsp;</div>')
+ cursorbar[0].style.height = defaultTextHeight + 'px'
+ cursorbar[0].style.borderLeft = '2px solid ' + user.color
+
+ var icon = '<i class="fa ' + iconClass + '"></i>'
+
+ let cursortag = $('<div class="cursortag">' + icon + '&nbsp;<span class="name">' + user.name + '</span></div>')
+ // cursortag[0].style.background = color;
+ cursortag[0].style.color = user.color
+
+ cursor.attr('data-mode', 'hover')
+ cursortag.delay(2000).fadeOut('fast')
+ cursor.hover(
function () {
- if (cursor.attr('data-mode') == 'hover')
- cursortag.stop(true).fadeIn("fast");
+ if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeIn('fast') }
},
function () {
- if (cursor.attr('data-mode') == 'hover')
- cursortag.stop(true).fadeOut("fast");
- });
-
- function switchMode(ele) {
- if (ele.attr('data-mode') == 'state')
- ele.attr('data-mode', 'hover');
- else if (ele.attr('data-mode') == 'hover')
- ele.attr('data-mode', 'state');
- }
-
- function switchTag(ele) {
- if (ele.css('display') === 'none')
- ele.stop(true).fadeIn("fast");
- else
- ele.stop(true).fadeOut("fast");
- }
- var hideCursorTagDelay = 2000;
- var hideCursorTagTimer = null;
-
- function hideCursorTag() {
- if (cursor.attr('data-mode') == 'hover')
- cursortag.fadeOut("fast");
- }
- cursor.on('touchstart', function (e) {
- var display = cursortag.css('display');
- cursortag.stop(true).fadeIn("fast");
- clearTimeout(hideCursorTagTimer);
- hideCursorTagTimer = setTimeout(hideCursorTag, hideCursorTagDelay);
- if (display === 'none') {
- e.preventDefault();
- e.stopPropagation();
- }
- });
- cursortag.on('mousedown touchstart', function (e) {
- if (cursor.attr('data-mode') == 'state')
- switchTag(cursortag);
- switchMode(cursor);
- e.preventDefault();
- e.stopPropagation();
- });
-
- cursor.append(cursorbar);
- cursor.append(cursortag);
-
- cursor[0].style.left = coord.left + 'px';
- cursor[0].style.top = coord.top + 'px';
- $('.CodeMirror-other-cursors').append(cursor);
-
- if (!user.idle)
- cursor.stop(true).fadeIn();
-
- checkCursorTag(coord, cursortag);
- } else {
- var cursor = $('div[data-clientid="' + user.id + '"]');
- var lineDiff = Math.abs(cursor.attr('data-line') - user.cursor.line);
- cursor.attr('data-line', user.cursor.line);
- cursor.attr('data-ch', user.cursor.ch);
-
- var cursorbar = cursor.find('.cursorbar');
- cursorbar[0].style.height = defaultTextHeight + 'px';
- cursorbar[0].style.borderLeft = '2px solid ' + user.color;
-
- var cursortag = cursor.find('.cursortag');
- cursortag.find('i').removeClass().addClass('fa').addClass(iconClass);
- cursortag.find(".name").text(user.name);
-
- if (cursor.css('display') === 'none') {
- cursor[0].style.left = coord.left + 'px';
- cursor[0].style.top = coord.top + 'px';
- } else {
- cursor.animate({
- "left": coord.left,
- "top": coord.top
- }, {
- duration: cursorAnimatePeriod,
- queue: false
- });
- }
+ if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeOut('fast') }
+ })
- if (user.idle && cursor.css('display') !== 'none')
- cursor.stop(true).fadeOut();
- else if (!user.idle && cursor.css('display') === 'none')
- cursor.stop(true).fadeIn();
+ var hideCursorTagDelay = 2000
+ var hideCursorTagTimer = null
- checkCursorTag(coord, cursortag);
+ var switchMode = function (ele) {
+ if (ele.attr('data-mode') === 'state') { ele.attr('data-mode', 'hover') } else if (ele.attr('data-mode') === 'hover') { ele.attr('data-mode', 'state') }
}
-}
-//editor actions
-function removeNullByte(cm, change) {
- var str = change.text.join("\n");
- if (/\u0000/g.test(str) && change.update) {
- change.update(change.from, change.to, str.replace(/\u0000/g, "").split("\n"));
+ var switchTag = function (ele) {
+ if (ele.css('display') === 'none') { ele.stop(true).fadeIn('fast') } else { ele.stop(true).fadeOut('fast') }
}
-}
-function enforceMaxLength(cm, change) {
- var maxLength = cm.getOption("maxLength");
- if (maxLength && change.update) {
- var str = change.text.join("\n");
- var delta = str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from));
- if (delta <= 0) {
- return false;
- }
- delta = cm.getValue().length + delta - maxLength;
- if (delta > 0) {
- str = str.substr(0, str.length - delta);
- change.update(change.from, change.to, str.split("\n"));
- return true;
- }
+
+ var hideCursorTag = function () {
+ if (cursor.attr('data-mode') === 'hover') { cursortag.fadeOut('fast') }
}
- return false;
-}
-var ignoreEmitEvents = ['setValue', 'ignoreHistory'];
-editor.on('beforeChange', function (cm, change) {
- if (debug)
- console.debug(change);
- removeNullByte(cm, change);
- if (enforceMaxLength(cm, change)) {
- $('.limit-modal').modal('show');
- }
- var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(change.origin) != -1);
- if (!isIgnoreEmitEvent) {
- if (!havePermission()) {
- change.canceled = true;
- switch (permission) {
- case "editable":
- $('.signin-modal').modal('show');
- break;
- case "locked":
- case "private":
- $('.locked-modal').modal('show');
- break;
- }
- }
+ cursor.on('touchstart', function (e) {
+ var display = cursortag.css('display')
+ cursortag.stop(true).fadeIn('fast')
+ clearTimeout(hideCursorTagTimer)
+ hideCursorTagTimer = setTimeout(hideCursorTag, hideCursorTagDelay)
+ if (display === 'none') {
+ e.preventDefault()
+ e.stopPropagation()
+ }
+ })
+ cursortag.on('mousedown touchstart', function (e) {
+ if (cursor.attr('data-mode') === 'state') { switchTag(cursortag) }
+ switchMode(cursor)
+ e.preventDefault()
+ e.stopPropagation()
+ })
+
+ cursor.append(cursorbar)
+ cursor.append(cursortag)
+
+ cursor[0].style.left = coord.left + 'px'
+ cursor[0].style.top = coord.top + 'px'
+ $('.CodeMirror-other-cursors').append(cursor)
+
+ if (!user.idle) { cursor.stop(true).fadeIn() }
+
+ checkCursorTag(coord, cursortag)
+ } else {
+ let cursor = $('div[data-clientid="' + user.id + '"]')
+ cursor.attr('data-line', user.cursor.line)
+ cursor.attr('data-ch', user.cursor.ch)
+
+ let cursorbar = cursor.find('.cursorbar')
+ cursorbar[0].style.height = defaultTextHeight + 'px'
+ cursorbar[0].style.borderLeft = '2px solid ' + user.color
+
+ let cursortag = cursor.find('.cursortag')
+ cursortag.find('i').removeClass().addClass('fa').addClass(iconClass)
+ cursortag.find('.name').text(user.name)
+
+ if (cursor.css('display') === 'none') {
+ cursor[0].style.left = coord.left + 'px'
+ cursor[0].style.top = coord.top + 'px'
} else {
- if (change.origin == 'ignoreHistory') {
- setHaveUnreadChanges(true);
- updateTitleReminder();
- }
- }
- if (cmClient && !socket.connected)
- cmClient.editorAdapter.ignoreNextChange = true;
-});
+ cursor.animate({
+ 'left': coord.left,
+ 'top': coord.top
+ }, {
+ duration: cursorAnimatePeriod,
+ queue: false
+ })
+ }
+
+ if (user.idle && cursor.css('display') !== 'none') { cursor.stop(true).fadeOut() } else if (!user.idle && cursor.css('display') === 'none') { cursor.stop(true).fadeIn() }
+
+ checkCursorTag(coord, cursortag)
+ }
+}
+
+// editor actions
+function removeNullByte (cm, change) {
+ var str = change.text.join('\n')
+ if (/\u0000/g.test(str) && change.update) {
+ change.update(change.from, change.to, str.replace(/\u0000/g, '').split('\n'))
+ }
+}
+function enforceMaxLength (cm, change) {
+ var maxLength = cm.getOption('maxLength')
+ if (maxLength && change.update) {
+ var str = change.text.join('\n')
+ var delta = str.length - (cm.indexFromPos(change.to) - cm.indexFromPos(change.from))
+ if (delta <= 0) {
+ return false
+ }
+ delta = cm.getValue().length + delta - maxLength
+ if (delta > 0) {
+ str = str.substr(0, str.length - delta)
+ change.update(change.from, change.to, str.split('\n'))
+ return true
+ }
+ }
+ return false
+}
+var ignoreEmitEvents = ['setValue', 'ignoreHistory']
+editor.on('beforeChange', function (cm, change) {
+ if (debug) { console.debug(change) }
+ removeNullByte(cm, change)
+ if (enforceMaxLength(cm, change)) {
+ $('.limit-modal').modal('show')
+ }
+ var isIgnoreEmitEvent = (ignoreEmitEvents.indexOf(change.origin) !== -1)
+ if (!isIgnoreEmitEvent) {
+ if (!havePermission()) {
+ change.canceled = true
+ switch (permission) {
+ case 'editable':
+ $('.signin-modal').modal('show')
+ break
+ case 'locked':
+ case 'private':
+ $('.locked-modal').modal('show')
+ break
+ }
+ }
+ } else {
+ if (change.origin === 'ignoreHistory') {
+ setHaveUnreadChanges(true)
+ updateTitleReminder()
+ }
+ }
+ if (cmClient && !socket.connected) { cmClient.editorAdapter.ignoreNextChange = true }
+})
editor.on('cut', function () {
- //na
-});
+ // na
+})
editor.on('paste', function () {
- //na
-});
+ // na
+})
editor.on('changes', function (cm, changes) {
- updateHistory();
- var docLength = editor.getValue().length;
- //workaround for big documents
- var newViewportMargin = 20;
- if (docLength > 20000) {
- newViewportMargin = 1;
- } else if (docLength > 10000) {
- newViewportMargin = 10;
- } else if (docLength > 5000) {
- newViewportMargin = 15;
- }
- if (newViewportMargin != viewportMargin) {
- viewportMargin = newViewportMargin;
- windowResize();
- }
- checkEditorScrollbar();
- if (ui.area.codemirrorScroll[0].scrollHeight > ui.area.view[0].scrollHeight && editorHasFocus()) {
- postUpdateEvent = function () {
- syncScrollToView();
- postUpdateEvent = null;
- };
- }
-});
+ updateHistory()
+ var docLength = editor.getValue().length
+ // workaround for big documents
+ var newViewportMargin = 20
+ if (docLength > 20000) {
+ newViewportMargin = 1
+ } else if (docLength > 10000) {
+ newViewportMargin = 10
+ } else if (docLength > 5000) {
+ newViewportMargin = 15
+ }
+ if (newViewportMargin !== viewportMargin) {
+ viewportMargin = newViewportMargin
+ windowResize()
+ }
+ checkEditorScrollbar()
+ if (ui.area.codemirrorScroll[0].scrollHeight > ui.area.view[0].scrollHeight && editorHasFocus()) {
+ postUpdateEvent = function () {
+ syncScrollToView()
+ postUpdateEvent = null
+ }
+ }
+})
editor.on('focus', function (cm) {
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == personalInfo.id) {
- onlineUsers[i].cursor = editor.getCursor();
- }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === window.personalInfo.id) {
+ window.onlineUsers[i].cursor = editor.getCursor()
}
- personalInfo['cursor'] = editor.getCursor();
- socket.emit('cursor focus', editor.getCursor());
-});
+ }
+ window.personalInfo['cursor'] = editor.getCursor()
+ socket.emit('cursor focus', editor.getCursor())
+})
editor.on('cursorActivity', function (cm) {
- updateStatusBar();
- cursorActivity();
-});
+ updateStatusBar()
+ cursorActivity()
+})
editor.on('beforeSelectionChange', function (doc, selections) {
- if (selections)
- selection = selections.ranges[0];
- else
- selection = null;
- updateStatusBar();
-});
-
-var cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce);
-
-function cursorActivityInner() {
- if (editorHasFocus() && !Visibility.hidden()) {
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == personalInfo.id) {
- onlineUsers[i].cursor = editor.getCursor();
- }
- }
- personalInfo['cursor'] = editor.getCursor();
- socket.emit('cursor activity', editor.getCursor());
+ if (selections) { selection = selections.ranges[0] } else { selection = null }
+ updateStatusBar()
+})
+
+var cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce)
+
+function cursorActivityInner () {
+ if (editorHasFocus() && !Visibility.hidden()) {
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === window.personalInfo.id) {
+ window.onlineUsers[i].cursor = editor.getCursor()
+ }
}
+ window.personalInfo['cursor'] = editor.getCursor()
+ socket.emit('cursor activity', editor.getCursor())
+ }
}
editor.on('blur', function (cm) {
- for (var i = 0; i < onlineUsers.length; i++) {
- if (onlineUsers[i].id == personalInfo.id) {
- onlineUsers[i].cursor = null;
- }
+ for (var i = 0; i < window.onlineUsers.length; i++) {
+ if (window.onlineUsers[i].id === window.personalInfo.id) {
+ window.onlineUsers[i].cursor = null
}
- personalInfo['cursor'] = null;
- socket.emit('cursor blur');
-});
-
-function saveInfo() {
- var scrollbarStyle = editor.getOption('scrollbarStyle');
- var left = $(window).scrollLeft();
- var top = $(window).scrollTop();
- switch (currentMode) {
- case modeType.edit:
- if (scrollbarStyle == 'native') {
- lastInfo.edit.scroll.left = left;
- lastInfo.edit.scroll.top = top;
- } else {
- lastInfo.edit.scroll = editor.getScrollInfo();
- }
- break;
- case modeType.view:
- lastInfo.view.scroll.left = left;
- lastInfo.view.scroll.top = top;
- break;
- case modeType.both:
- lastInfo.edit.scroll = editor.getScrollInfo();
- lastInfo.view.scroll.left = ui.area.view.scrollLeft();
- lastInfo.view.scroll.top = ui.area.view.scrollTop();
- break;
- }
- lastInfo.edit.cursor = editor.getCursor();
- lastInfo.edit.selections = editor.listSelections();
- lastInfo.needRestore = true;
-}
-
-function restoreInfo() {
- var scrollbarStyle = editor.getOption('scrollbarStyle');
- if (lastInfo.needRestore) {
- var line = lastInfo.edit.cursor.line;
- var ch = lastInfo.edit.cursor.ch;
- editor.setCursor(line, ch);
- editor.setSelections(lastInfo.edit.selections);
- switch (currentMode) {
- case modeType.edit:
- if (scrollbarStyle == 'native') {
- $(window).scrollLeft(lastInfo.edit.scroll.left);
- $(window).scrollTop(lastInfo.edit.scroll.top);
- } else {
- var left = lastInfo.edit.scroll.left;
- var top = lastInfo.edit.scroll.top;
- editor.scrollIntoView();
- editor.scrollTo(left, top);
- }
- break;
- case modeType.view:
- $(window).scrollLeft(lastInfo.view.scroll.left);
- $(window).scrollTop(lastInfo.view.scroll.top);
- break;
- case modeType.both:
- var left = lastInfo.edit.scroll.left;
- var top = lastInfo.edit.scroll.top;
- editor.scrollIntoView();
- editor.scrollTo(left, top);
- ui.area.view.scrollLeft(lastInfo.view.scroll.left);
- ui.area.view.scrollTop(lastInfo.view.scroll.top);
- break;
- }
+ }
+ window.personalInfo['cursor'] = null
+ socket.emit('cursor blur')
+})
- lastInfo.needRestore = false;
+function saveInfo () {
+ var scrollbarStyle = editor.getOption('scrollbarStyle')
+ var left = $(window).scrollLeft()
+ var top = $(window).scrollTop()
+ switch (window.currentMode) {
+ case modeType.edit:
+ if (scrollbarStyle === 'native') {
+ window.lastInfo.edit.scroll.left = left
+ window.lastInfo.edit.scroll.top = top
+ } else {
+ window.lastInfo.edit.scroll = editor.getScrollInfo()
+ }
+ break
+ case modeType.view:
+ window.lastInfo.view.scroll.left = left
+ window.lastInfo.view.scroll.top = top
+ break
+ case modeType.both:
+ window.lastInfo.edit.scroll = editor.getScrollInfo()
+ window.lastInfo.view.scroll.left = ui.area.view.scrollLeft()
+ window.lastInfo.view.scroll.top = ui.area.view.scrollTop()
+ break
+ }
+ window.lastInfo.edit.cursor = editor.getCursor()
+ window.lastInfo.edit.selections = editor.listSelections()
+ window.lastInfo.needRestore = true
+}
+
+function restoreInfo () {
+ var scrollbarStyle = editor.getOption('scrollbarStyle')
+ if (window.lastInfo.needRestore) {
+ var line = window.lastInfo.edit.cursor.line
+ var ch = window.lastInfo.edit.cursor.ch
+ editor.setCursor(line, ch)
+ editor.setSelections(window.lastInfo.edit.selections)
+ switch (window.currentMode) {
+ case modeType.edit:
+ if (scrollbarStyle === 'native') {
+ $(window).scrollLeft(window.lastInfo.edit.scroll.left)
+ $(window).scrollTop(window.lastInfo.edit.scroll.top)
+ } else {
+ let left = window.lastInfo.edit.scroll.left
+ let top = window.lastInfo.edit.scroll.top
+ editor.scrollIntoView()
+ editor.scrollTo(left, top)
+ }
+ break
+ case modeType.view:
+ $(window).scrollLeft(window.lastInfo.view.scroll.left)
+ $(window).scrollTop(window.lastInfo.view.scroll.top)
+ break
+ case modeType.both:
+ let left = window.lastInfo.edit.scroll.left
+ let top = window.lastInfo.edit.scroll.top
+ editor.scrollIntoView()
+ editor.scrollTo(left, top)
+ ui.area.view.scrollLeft(window.lastInfo.view.scroll.left)
+ ui.area.view.scrollTop(window.lastInfo.view.scroll.top)
+ break
}
+
+ window.lastInfo.needRestore = false
+ }
}
-//view actions
-function refreshView() {
- ui.area.markdown.html('');
- isDirty = true;
- updateViewInner();
+// view actions
+function refreshView () {
+ ui.area.markdown.html('')
+ window.isDirty = true
+ updateViewInner()
}
var updateView = _.debounce(function () {
- editor.operation(updateViewInner);
-}, updateViewDebounce);
-
-var lastResult = null;
-var postUpdateEvent = null;
-
-function updateViewInner() {
- if (currentMode == modeType.edit || !isDirty) return;
- var value = editor.getValue();
- var lastMeta = md.meta;
- md.meta = {};
- delete md.metaError;
- var rendered = md.render(value);
- if (md.meta.type && md.meta.type === 'slide') {
- var slideOptions = {
- separator: '^(\r\n?|\n)---(\r\n?|\n)$',
- verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$'
- };
- var slides = RevealMarkdown.slidify(editor.getValue(), slideOptions);
- ui.area.markdown.html(slides);
- RevealMarkdown.initialize();
+ editor.operation(updateViewInner)
+}, updateViewDebounce)
+
+var lastResult = null
+var postUpdateEvent = null
+
+function updateViewInner () {
+ if (window.currentMode === modeType.edit || !window.isDirty) return
+ var value = editor.getValue()
+ var lastMeta = md.meta
+ md.meta = {}
+ delete md.metaError
+ var rendered = md.render(value)
+ if (md.meta.type && md.meta.type === 'slide') {
+ var slideOptions = {
+ separator: '^(\r\n?|\n)---(\r\n?|\n)$',
+ verticalSeparator: '^(\r\n?|\n)----(\r\n?|\n)$'
+ }
+ var slides = window.RevealMarkdown.slidify(editor.getValue(), slideOptions)
+ ui.area.markdown.html(slides)
+ window.RevealMarkdown.initialize()
// prevent XSS
- ui.area.markdown.html(preventXSS(ui.area.markdown.html()));
- ui.area.markdown.addClass('slides');
- syncscroll = false;
- checkSyncToggle();
- } else {
- if (lastMeta.type && lastMeta.type === 'slide') {
- refreshView();
- ui.area.markdown.removeClass('slides');
- syncscroll = true;
- checkSyncToggle();
- }
+ ui.area.markdown.html(preventXSS(ui.area.markdown.html()))
+ ui.area.markdown.addClass('slides')
+ window.syncscroll = false
+ checkSyncToggle()
+ } else {
+ if (lastMeta.type && lastMeta.type === 'slide') {
+ refreshView()
+ ui.area.markdown.removeClass('slides')
+ window.syncscroll = true
+ checkSyncToggle()
+ }
// only render again when meta changed
- if (JSON.stringify(md.meta) != JSON.stringify(lastMeta)) {
- parseMeta(md, ui.area.codemirror, ui.area.markdown, $('#ui-toc'), $('#ui-toc-affix'));
- rendered = md.render(value);
- }
+ if (JSON.stringify(md.meta) !== JSON.stringify(lastMeta)) {
+ parseMeta(md, ui.area.codemirror, ui.area.markdown, $('#ui-toc'), $('#ui-toc-affix'))
+ rendered = md.render(value)
+ }
// prevent XSS
- rendered = preventXSS(rendered);
- var result = postProcess(rendered).children().toArray();
- partialUpdate(result, lastResult, ui.area.markdown.children().toArray());
- if (result && lastResult && result.length != lastResult.length)
- updateDataAttrs(result, ui.area.markdown.children().toArray());
- lastResult = $(result).clone();
- }
- finishView(ui.area.markdown);
- autoLinkify(ui.area.markdown);
- deduplicatedHeaderId(ui.area.markdown);
- renderTOC(ui.area.markdown);
- generateToc('ui-toc');
- generateToc('ui-toc-affix');
- generateScrollspy();
- updateScrollspy();
- smoothHashScroll();
- isDirty = false;
- clearMap();
- //buildMap();
- updateTitleReminder();
- if (postUpdateEvent && typeof postUpdateEvent === 'function')
- postUpdateEvent();
-}
-
-var updateHistoryDebounce = 600;
+ rendered = preventXSS(rendered)
+ var result = postProcess(rendered).children().toArray()
+ partialUpdate(result, lastResult, ui.area.markdown.children().toArray())
+ if (result && lastResult && result.length !== lastResult.length) { updateDataAttrs(result, ui.area.markdown.children().toArray()) }
+ lastResult = $(result).clone()
+ }
+ finishView(ui.area.markdown)
+ autoLinkify(ui.area.markdown)
+ deduplicatedHeaderId(ui.area.markdown)
+ renderTOC(ui.area.markdown)
+ generateToc('ui-toc')
+ generateToc('ui-toc-affix')
+ generateScrollspy()
+ updateScrollspy()
+ smoothHashScroll()
+ window.isDirty = false
+ clearMap()
+ // buildMap();
+ updateTitleReminder()
+ if (postUpdateEvent && typeof postUpdateEvent === 'function') { postUpdateEvent() }
+}
+
+var updateHistoryDebounce = 600
var updateHistory = _.debounce(updateHistoryInner, updateHistoryDebounce)
-function updateHistoryInner() {
- writeHistory(renderFilename(ui.area.markdown), renderTags(ui.area.markdown));
-}
-
-function updateDataAttrs(src, des) {
- //sync data attr startline and endline
- for (var i = 0; i < src.length; i++) {
- copyAttribute(src[i], des[i], 'data-startline');
- copyAttribute(src[i], des[i], 'data-endline');
- }
-}
-
-function partialUpdate(src, tar, des) {
- if (!src || src.length == 0 || !tar || tar.length == 0 || !des || des.length == 0) {
- ui.area.markdown.html(src);
- return;
- }
- if (src.length == tar.length) { //same length
- for (var i = 0; i < src.length; i++) {
- copyAttribute(src[i], des[i], 'data-startline');
- copyAttribute(src[i], des[i], 'data-endline');
- var rawSrc = cloneAndRemoveDataAttr(src[i]);
- var rawTar = cloneAndRemoveDataAttr(tar[i]);
- if (rawSrc.outerHTML != rawTar.outerHTML) {
- //console.log(rawSrc);
- //console.log(rawTar);
- $(des[i]).replaceWith(src[i]);
- }
- }
- } else { //diff length
- var start = 0;
- var end = 0;
- //find diff start position
- for (var i = 0; i < tar.length; i++) {
- //copyAttribute(src[i], des[i], 'data-startline');
- //copyAttribute(src[i], des[i], 'data-endline');
- var rawSrc = cloneAndRemoveDataAttr(src[i]);
- var rawTar = cloneAndRemoveDataAttr(tar[i]);
- if (!rawSrc || !rawTar || rawSrc.outerHTML != rawTar.outerHTML) {
- start = i;
- break;
- }
- }
- //find diff end position
- var srcEnd = 0;
- var tarEnd = 0;
- for (var i = 0; i < src.length; i++) {
- //copyAttribute(src[i], des[i], 'data-startline');
- //copyAttribute(src[i], des[i], 'data-endline');
- var rawSrc = cloneAndRemoveDataAttr(src[i]);
- var rawTar = cloneAndRemoveDataAttr(tar[i]);
- if (!rawSrc || !rawTar || rawSrc.outerHTML != rawTar.outerHTML) {
- start = i;
- break;
- }
- }
- //tar end
- for (var i = 1; i <= tar.length + 1; i++) {
- var srcLength = src.length;
- var tarLength = tar.length;
- //copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
- //copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
- var rawSrc = cloneAndRemoveDataAttr(src[srcLength - i]);
- var rawTar = cloneAndRemoveDataAttr(tar[tarLength - i]);
- if (!rawSrc || !rawTar || rawSrc.outerHTML != rawTar.outerHTML) {
- tarEnd = tar.length - i;
- break;
- }
- }
- //src end
- for (var i = 1; i <= src.length + 1; i++) {
- var srcLength = src.length;
- var tarLength = tar.length;
- //copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
- //copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
- var rawSrc = cloneAndRemoveDataAttr(src[srcLength - i]);
- var rawTar = cloneAndRemoveDataAttr(tar[tarLength - i]);
- if (!rawSrc || !rawTar || rawSrc.outerHTML != rawTar.outerHTML) {
- srcEnd = src.length - i;
- break;
- }
- }
- //check if tar end overlap tar start
- var overlap = 0;
- for (var i = start; i >= 0; i--) {
- var rawTarStart = cloneAndRemoveDataAttr(tar[i - 1]);
- var rawTarEnd = cloneAndRemoveDataAttr(tar[tarEnd + 1 + start - i]);
- if (rawTarStart && rawTarEnd && rawTarStart.outerHTML == rawTarEnd.outerHTML)
- overlap++;
- else
- break;
- }
- if (debug)
- console.log('overlap:' + overlap);
- //show diff content
- if (debug) {
- console.log('start:' + start);
- console.log('tarEnd:' + tarEnd);
- console.log('srcEnd:' + srcEnd);
- }
- tarEnd += overlap;
- srcEnd += overlap;
- var repeatAdd = (start - srcEnd) < (start - tarEnd);
- var repeatDiff = Math.abs(srcEnd - tarEnd) - 1;
- //push new elements
- var newElements = [];
- if (srcEnd >= start) {
- for (var j = start; j <= srcEnd; j++) {
- if (!src[j]) continue;
- newElements.push(src[j].outerHTML);
- }
- } else if (repeatAdd) {
- for (var j = srcEnd - repeatDiff; j <= srcEnd; j++) {
- if (!des[j]) continue;
- newElements.push(des[j].outerHTML);
- }
- }
- //push remove elements
- var removeElements = [];
- if (tarEnd >= start) {
- for (var j = start; j <= tarEnd; j++) {
- if (!des[j]) continue;
- removeElements.push(des[j]);
- }
- } else if (!repeatAdd) {
- for (var j = start; j <= start + repeatDiff; j++) {
- if (!des[j]) continue;
- removeElements.push(des[j]);
- }
- }
- //add elements
- if (debug) {
- console.log('ADD ELEMENTS');
- console.log(newElements.join('\n'));
- }
- if (des[start])
- $(newElements.join('')).insertBefore(des[start]);
- else
- $(newElements.join('')).insertAfter(des[start - 1]);
- //remove elements
- if (debug)
- console.log('REMOVE ELEMENTS');
- for (var j = 0; j < removeElements.length; j++) {
- if (debug) {
- console.log(removeElements[j].outerHTML);
- }
- if (removeElements[j])
- $(removeElements[j]).remove();
- }
- }
-}
-
-function cloneAndRemoveDataAttr(el) {
- if (!el) return;
- var rawEl = $(el).clone();
- rawEl.removeAttr('data-startline data-endline');
- rawEl.find('[data-startline]').removeAttr('data-startline data-endline');
- return rawEl[0];
-}
-
-function copyAttribute(src, des, attr) {
- if (src && src.getAttribute(attr) && des)
- des.setAttribute(attr, src.getAttribute(attr));
+function updateHistoryInner () {
+ writeHistory(renderFilename(ui.area.markdown), renderTags(ui.area.markdown))
+}
+
+function updateDataAttrs (src, des) {
+ // sync data attr startline and endline
+ for (var i = 0; i < src.length; i++) {
+ copyAttribute(src[i], des[i], 'data-startline')
+ copyAttribute(src[i], des[i], 'data-endline')
+ }
+}
+
+function partialUpdate (src, tar, des) {
+ if (!src || src.length === 0 || !tar || tar.length === 0 || !des || des.length === 0) {
+ ui.area.markdown.html(src)
+ return
+ }
+ if (src.length === tar.length) { // same length
+ for (let i = 0; i < src.length; i++) {
+ copyAttribute(src[i], des[i], 'data-startline')
+ copyAttribute(src[i], des[i], 'data-endline')
+ var rawSrc = cloneAndRemoveDataAttr(src[i])
+ var rawTar = cloneAndRemoveDataAttr(tar[i])
+ if (rawSrc.outerHTML !== rawTar.outerHTML) {
+ // console.log(rawSrc);
+ // console.log(rawTar);
+ $(des[i]).replaceWith(src[i])
+ }
+ }
+ } else { // diff length
+ var start = 0
+ // find diff start position
+ for (let i = 0; i < tar.length; i++) {
+ // copyAttribute(src[i], des[i], 'data-startline');
+ // copyAttribute(src[i], des[i], 'data-endline');
+ let rawSrc = cloneAndRemoveDataAttr(src[i])
+ let rawTar = cloneAndRemoveDataAttr(tar[i])
+ if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
+ start = i
+ break
+ }
+ }
+ // find diff end position
+ var srcEnd = 0
+ var tarEnd = 0
+ for (let i = 0; i < src.length; i++) {
+ // copyAttribute(src[i], des[i], 'data-startline');
+ // copyAttribute(src[i], des[i], 'data-endline');
+ let rawSrc = cloneAndRemoveDataAttr(src[i])
+ let rawTar = cloneAndRemoveDataAttr(tar[i])
+ if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
+ start = i
+ break
+ }
+ }
+ // tar end
+ for (let i = 1; i <= tar.length + 1; i++) {
+ let srcLength = src.length
+ let tarLength = tar.length
+ // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
+ // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
+ let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
+ let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
+ if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
+ tarEnd = tar.length - i
+ break
+ }
+ }
+ // src end
+ for (let i = 1; i <= src.length + 1; i++) {
+ let srcLength = src.length
+ let tarLength = tar.length
+ // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-startline');
+ // copyAttribute(src[srcLength - i], des[srcLength - i], 'data-endline');
+ let rawSrc = cloneAndRemoveDataAttr(src[srcLength - i])
+ let rawTar = cloneAndRemoveDataAttr(tar[tarLength - i])
+ if (!rawSrc || !rawTar || rawSrc.outerHTML !== rawTar.outerHTML) {
+ srcEnd = src.length - i
+ break
+ }
+ }
+ // check if tar end overlap tar start
+ var overlap = 0
+ for (var i = start; i >= 0; i--) {
+ var rawTarStart = cloneAndRemoveDataAttr(tar[i - 1])
+ var rawTarEnd = cloneAndRemoveDataAttr(tar[tarEnd + 1 + start - i])
+ if (rawTarStart && rawTarEnd && rawTarStart.outerHTML === rawTarEnd.outerHTML) { overlap++ } else { break }
+ }
+ if (debug) { console.log('overlap:' + overlap) }
+ // show diff content
+ if (debug) {
+ console.log('start:' + start)
+ console.log('tarEnd:' + tarEnd)
+ console.log('srcEnd:' + srcEnd)
+ }
+ tarEnd += overlap
+ srcEnd += overlap
+ var repeatAdd = (start - srcEnd) < (start - tarEnd)
+ var repeatDiff = Math.abs(srcEnd - tarEnd) - 1
+ // push new elements
+ var newElements = []
+ if (srcEnd >= start) {
+ for (let j = start; j <= srcEnd; j++) {
+ if (!src[j]) continue
+ newElements.push(src[j].outerHTML)
+ }
+ } else if (repeatAdd) {
+ for (let j = srcEnd - repeatDiff; j <= srcEnd; j++) {
+ if (!des[j]) continue
+ newElements.push(des[j].outerHTML)
+ }
+ }
+ // push remove elements
+ var removeElements = []
+ if (tarEnd >= start) {
+ for (let j = start; j <= tarEnd; j++) {
+ if (!des[j]) continue
+ removeElements.push(des[j])
+ }
+ } else if (!repeatAdd) {
+ for (let j = start; j <= start + repeatDiff; j++) {
+ if (!des[j]) continue
+ removeElements.push(des[j])
+ }
+ }
+ // add elements
+ if (debug) {
+ console.log('ADD ELEMENTS')
+ console.log(newElements.join('\n'))
+ }
+ if (des[start]) { $(newElements.join('')).insertBefore(des[start]) } else { $(newElements.join('')).insertAfter(des[start - 1]) }
+ // remove elements
+ if (debug) { console.log('REMOVE ELEMENTS') }
+ for (let j = 0; j < removeElements.length; j++) {
+ if (debug) {
+ console.log(removeElements[j].outerHTML)
+ }
+ if (removeElements[j]) { $(removeElements[j]).remove() }
+ }
+ }
+}
+
+function cloneAndRemoveDataAttr (el) {
+ if (!el) return
+ var rawEl = $(el).clone()
+ rawEl.removeAttr('data-startline data-endline')
+ rawEl.find('[data-startline]').removeAttr('data-startline data-endline')
+ return rawEl[0]
+}
+
+function copyAttribute (src, des, attr) {
+ if (src && src.getAttribute(attr) && des) { des.setAttribute(attr, src.getAttribute(attr)) }
}
if ($('.cursor-menu').length <= 0) {
- $("<div class='cursor-menu'>").insertAfter('.CodeMirror-cursors');
+ $("<div class='cursor-menu'>").insertAfter('.CodeMirror-cursors')
}
-function reverseSortCursorMenu(dropdown) {
- var items = dropdown.find('.textcomplete-item');
- items.sort(function (a, b) {
- return $(b).attr('data-index') - $(a).attr('data-index');
- });
- return items;
+function reverseSortCursorMenu (dropdown) {
+ var items = dropdown.find('.textcomplete-item')
+ items.sort(function (a, b) {
+ return $(b).attr('data-index') - $(a).attr('data-index')
+ })
+ return items
}
-var checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle);
+var checkCursorMenu = _.throttle(checkCursorMenuInner, cursorMenuThrottle)
-function checkCursorMenuInner() {
+function checkCursorMenuInner () {
// get element
- var dropdown = $('.cursor-menu > .dropdown-menu');
+ var dropdown = $('.cursor-menu > .dropdown-menu')
// return if not exists
- if (dropdown.length <= 0) return;
+ if (dropdown.length <= 0) return
// set margin
- var menuRightMargin = 10;
- var menuBottomMargin = 4;
+ var menuRightMargin = 10
+ var menuBottomMargin = 4
// use sizer to get the real doc size (won't count status bar and gutters)
- var docWidth = ui.area.codemirrorSizer.width();
- var docHeight = ui.area.codemirrorSizer.height();
+ var docWidth = ui.area.codemirrorSizer.width()
// get editor size (status bar not count in)
- var editorWidth = ui.area.codemirror.width();
- var editorHeight = ui.area.codemirror.height();
+ var editorHeight = ui.area.codemirror.height()
// get element size
- var width = dropdown.outerWidth();
- var height = dropdown.outerHeight();
+ var width = dropdown.outerWidth()
+ var height = dropdown.outerHeight()
// get cursor
- var cursor = editor.getCursor();
+ var cursor = editor.getCursor()
// set element cursor data
- if (!dropdown.hasClass('CodeMirror-other-cursor'))
- dropdown.addClass('CodeMirror-other-cursor');
- dropdown.attr('data-line', cursor.line);
- dropdown.attr('data-ch', cursor.ch);
+ if (!dropdown.hasClass('CodeMirror-other-cursor')) { dropdown.addClass('CodeMirror-other-cursor') }
+ dropdown.attr('data-line', cursor.line)
+ dropdown.attr('data-ch', cursor.ch)
// get coord position
- var coord = editor.charCoords({
- line: cursor.line,
- ch: cursor.ch
- }, 'windows');
- var left = coord.left;
- var top = coord.top;
+ var coord = editor.charCoords({
+ line: cursor.line,
+ ch: cursor.ch
+ }, 'windows')
+ var left = coord.left
+ var top = coord.top
// get doc top offset (to workaround with viewport)
- var docTopOffset = ui.area.codemirrorSizerInner.position().top;
+ var docTopOffset = ui.area.codemirrorSizerInner.position().top
// set offset
- var offsetLeft = 0;
- var offsetTop = defaultTextHeight;
+ var offsetLeft = 0
+ var offsetTop = defaultTextHeight
// set up side down
- window.upSideDown = false;
- var lastUpSideDown = upSideDown = false;
+ window.upSideDown = false
+ var lastUpSideDown = window.upSideDown = false
// only do when have width and height
- if (width > 0 && height > 0) {
+ if (width > 0 && height > 0) {
// make element right bound not larger than doc width
- if (left + width + offsetLeft + menuRightMargin > docWidth)
- offsetLeft = -(left + width - docWidth + menuRightMargin);
+ if (left + width + offsetLeft + menuRightMargin > docWidth) { offsetLeft = -(left + width - docWidth + menuRightMargin) }
// flip y when element bottom bound larger than doc height
// and element top position is larger than element height
- if (top + docTopOffset + height + offsetTop + menuBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + menuBottomMargin) {
- offsetTop = -(height + menuBottomMargin);
+ if (top + docTopOffset + height + offsetTop + menuBottomMargin > Math.max(editor.doc.height, editorHeight) && top + docTopOffset > height + menuBottomMargin) {
+ offsetTop = -(height + menuBottomMargin)
// reverse sort menu because upSideDown
- dropdown.html(reverseSortCursorMenu(dropdown));
- upSideDown = true;
- }
- var textCompleteDropdown = $(editor.getInputField()).data('textComplete').dropdown;
- lastUpSideDown = textCompleteDropdown.upSideDown;
- textCompleteDropdown.upSideDown = upSideDown;
+ dropdown.html(reverseSortCursorMenu(dropdown))
+ window.upSideDown = true
}
+ var textCompleteDropdown = $(editor.getInputField()).data('textComplete').dropdown
+ lastUpSideDown = textCompleteDropdown.upSideDown
+ textCompleteDropdown.upSideDown = window.upSideDown
+ }
// make menu scroll top only if upSideDown changed
- if (upSideDown !== lastUpSideDown)
- dropdown.scrollTop(dropdown[0].scrollHeight);
+ if (window.upSideDown !== lastUpSideDown) { dropdown.scrollTop(dropdown[0].scrollHeight) }
// set element offset data
- dropdown.attr('data-offset-left', offsetLeft);
- dropdown.attr('data-offset-top', offsetTop);
+ dropdown.attr('data-offset-left', offsetLeft)
+ dropdown.attr('data-offset-top', offsetTop)
// set position
- dropdown[0].style.left = left + offsetLeft + 'px';
- dropdown[0].style.top = top + offsetTop + 'px';
+ dropdown[0].style.left = left + offsetLeft + 'px'
+ dropdown[0].style.top = top + offsetTop + 'px'
}
-function checkInIndentCode() {
+function checkInIndentCode () {
// if line starts with tab or four spaces is a code block
- var line = editor.getLine(editor.getCursor().line);
- var isIndentCode = ((line.substr(0, 4) === ' ') || (line.substr(0, 1) === '\t'));
- return isIndentCode;
-}
-
-var isInCode = false;
-
-function checkInCode() {
- isInCode = checkAbove(matchInCode) || checkInIndentCode();
-}
-
-function checkAbove(method) {
- var cursor = editor.getCursor();
- var text = [];
- for (var i = 0; i < cursor.line; i++) //contain current line
- text.push(editor.getLine(i));
- text = text.join('\n') + '\n' + editor.getLine(cursor.line).slice(0, cursor.ch);
- //console.log(text);
- return method(text);
-}
-
-function checkBelow(method) {
- var cursor = editor.getCursor();
- var count = editor.lineCount();
- var text = [];
- for (var i = cursor.line + 1; i < count; i++) //contain current line
- text.push(editor.getLine(i));
- text = editor.getLine(cursor.line).slice(cursor.ch) + '\n' + text.join('\n');
- //console.log(text);
- return method(text);
-}
-
-function matchInCode(text) {
- var match;
- match = text.match(/`{3,}/g);
+ var line = editor.getLine(editor.getCursor().line)
+ var isIndentCode = ((line.substr(0, 4) === ' ') || (line.substr(0, 1) === '\t'))
+ return isIndentCode
+}
+
+var isInCode = false
+
+function checkInCode () {
+ isInCode = checkAbove(matchInCode) || checkInIndentCode()
+}
+
+function checkAbove (method) {
+ var cursor = editor.getCursor()
+ var text = []
+ for (var i = 0; i < cursor.line; i++) { // contain current line
+ text.push(editor.getLine(i))
+ }
+ text = text.join('\n') + '\n' + editor.getLine(cursor.line).slice(0, cursor.ch)
+ // console.log(text);
+ return method(text)
+}
+
+function checkBelow (method) {
+ var cursor = editor.getCursor()
+ var count = editor.lineCount()
+ var text = []
+ for (var i = cursor.line + 1; i < count; i++) { // contain current line
+ text.push(editor.getLine(i))
+ }
+ text = editor.getLine(cursor.line).slice(cursor.ch) + '\n' + text.join('\n')
+ // console.log(text);
+ return method(text)
+}
+
+function matchInCode (text) {
+ var match
+ match = text.match(/`{3,}/g)
+ if (match && match.length % 2) {
+ return true
+ } else {
+ match = text.match(/`/g)
if (match && match.length % 2) {
- return true;
+ return true
} else {
- match = text.match(/`/g);
- if (match && match.length % 2) {
- return true;
- } else {
- return false;
- }
+ return false
}
+ }
}
-var isInContainer = false;
-var isInContainerSyntax = false;
+var isInContainer = false
+var isInContainerSyntax = false
-function checkInContainer() {
- isInContainer = checkAbove(matchInContainer) && !checkInIndentCode();
+function checkInContainer () {
+ isInContainer = checkAbove(matchInContainer) && !checkInIndentCode()
}
-function checkInContainerSyntax() {
+function checkInContainerSyntax () {
// if line starts with :::, it's in container syntax
- var line = editor.getLine(editor.getCursor().line);
- isInContainerSyntax = (line.substr(0, 3) === ':::');
+ var line = editor.getLine(editor.getCursor().line)
+ isInContainerSyntax = (line.substr(0, 3) === ':::')
}
-function matchInContainer(text) {
- var match;
- match = text.match(/:{3,}/g);
- if (match && match.length % 2) {
- return true;
- } else {
- return false;
- }
+function matchInContainer (text) {
+ var match
+ match = text.match(/:{3,}/g)
+ if (match && match.length % 2) {
+ return true
+ } else {
+ return false
+ }
}
$(editor.getInputField())
.textcomplete([
- { // emoji strategy
- match: /(^|\n|\s)\B:([\-+\w]*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line);
- term = line.match(this.match)[2];
- var list = [];
- $.map(emojify.emojiNames, function (emoji) {
- if (emoji.indexOf(term) === 0) //match at first character
- list.push(emoji);
- });
- $.map(emojify.emojiNames, function (emoji) {
- if (emoji.indexOf(term) !== -1) //match inside the word
- list.push(emoji);
- });
- callback(list);
- },
- template: function (value) {
- return '<img class="emoji" src="' + serverurl + '/build/emojify.js/dist/images/basic/' + value + '.png"></img> ' + value;
- },
- replace: function (value) {
- return '$1:' + value + ': ';
- },
- index: 1,
- context: function (text) {
- checkInCode();
- checkInContainer();
- checkInContainerSyntax();
- return !isInCode && !isInContainerSyntax;
+ { // emoji strategy
+ match: /(^|\n|\s)\B:([-+\w]*)$/,
+ search: function (term, callback) {
+ var line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[2]
+ var list = []
+ $.map(window.emojify.emojiNames, function (emoji) {
+ if (emoji.indexOf(term) === 0) { // match at first character
+ list.push(emoji)
}
- },
- { // Code block language strategy
- langs: supportCodeModes,
- charts: supportCharts,
- match: /(^|\n)```(\w+)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line);
- term = line.match(this.match)[2];
- var list = [];
- $.map(this.langs, function (lang) {
- if (lang.indexOf(term) === 0 && lang !== term)
- list.push(lang);
- });
- $.map(this.charts, function (chart) {
- if (chart.indexOf(term) === 0 && chart !== term)
- list.push(chart);
- });
- callback(list);
- },
- replace: function (lang) {
- var ending = '';
- if (!checkBelow(matchInCode)) {
- ending = '\n\n```';
- }
- if (this.langs.indexOf(lang) !== -1)
- return '$1```' + lang + '=' + ending;
- else if (this.charts.indexOf(lang) !== -1)
- return '$1```' + lang + ending;
- },
- done: function () {
- var cursor = editor.getCursor();
- var text = [];
- text.push(editor.getLine(cursor.line - 1));
- text.push(editor.getLine(cursor.line));
- text = text.join('\n');
- //console.log(text);
- if (text == '\n```')
- editor.doc.cm.execCommand("goLineUp");
- },
- context: function (text) {
- return isInCode;
+ })
+ $.map(window.emojify.emojiNames, function (emoji) {
+ if (emoji.indexOf(term) !== -1) { // match inside the word
+ list.push(emoji)
}
+ })
+ callback(list)
},
- { // Container strategy
- containers: supportContainers,
- match: /(^|\n):::(\s*)(\w*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line);
- term = line.match(this.match)[3].trim();
- var list = [];
- $.map(this.containers, function (container) {
- if (container.indexOf(term) === 0 && container !== term)
- list.push(container);
- });
- callback(list);
- },
- replace: function (lang) {
- var ending = '';
- if (!checkBelow(matchInContainer)) {
- ending = '\n\n:::';
- }
- if (this.containers.indexOf(lang) !== -1)
- return '$1:::$2' + lang + ending;
- },
- done: function () {
- var cursor = editor.getCursor();
- var text = [];
- text.push(editor.getLine(cursor.line - 1));
- text.push(editor.getLine(cursor.line));
- text = text.join('\n');
- //console.log(text);
- if (text == '\n:::')
- editor.doc.cm.execCommand("goLineUp");
- },
- context: function (text) {
- return !isInCode && isInContainer;
- }
+ template: function (value) {
+ return '<img class="emoji" src="' + serverurl + '/build/emojify.js/dist/images/basic/' + value + '.png"></img> ' + value
},
- { //header
- match: /(?:^|\n)(\s{0,3})(#{1,6}\w*)$/,
- search: function (term, callback) {
- callback($.map(supportHeaders, function (header) {
- return header.search.indexOf(term) === 0 ? header.text : null;
- }));
- },
- replace: function (value) {
- return '$1' + value;
- },
- context: function (text) {
- return !isInCode;
- }
+ replace: function (value) {
+ return '$1:' + value + ': '
},
- { //extra tags for blockquote
- match: /(?:^|\n|\s)(\>.*|\s|)((\^|)\[(\^|)\](\[\]|\(\)|\:|)\s*\w*)$/,
- search: function (term, callback) {
- var line = editor.getLine(editor.getCursor().line);
- var quote = line.match(this.match)[1].trim();
- var list = [];
- if (quote.indexOf('>') == 0) {
- $.map(supportExtraTags, function (extratag) {
- if (extratag.search.indexOf(term) === 0)
- list.push(extratag.command());
- });
- }
- $.map(supportReferrals, function (referral) {
- if (referral.search.indexOf(term) === 0)
- list.push(referral.text);
- })
- callback(list);
- },
- replace: function (value) {
- return '$1' + value;
- },
- context: function (text) {
- return !isInCode;
- }
+ index: 1,
+ context: function (text) {
+ checkInCode()
+ checkInContainer()
+ checkInContainerSyntax()
+ return !isInCode && !isInContainerSyntax
+ }
+ },
+ { // Code block language strategy
+ langs: supportCodeModes,
+ charts: supportCharts,
+ match: /(^|\n)```(\w+)$/,
+ search: function (term, callback) {
+ var line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[2]
+ var list = []
+ $.map(this.langs, function (lang) {
+ if (lang.indexOf(term) === 0 && lang !== term) { list.push(lang) }
+ })
+ $.map(this.charts, function (chart) {
+ if (chart.indexOf(term) === 0 && chart !== term) { list.push(chart) }
+ })
+ callback(list)
},
- { //extra tags for list
- match: /(^[>\s]*[\-\+\*]\s(?:\[[x ]\]|.*))(\[\])(\w*)$/,
- search: function (term, callback) {
- var list = [];
- $.map(supportExtraTags, function (extratag) {
- if (extratag.search.indexOf(term) === 0)
- list.push(extratag.command());
- });
- $.map(supportReferrals, function (referral) {
- if (referral.search.indexOf(term) === 0)
- list.push(referral.text);
- })
- callback(list);
- },
- replace: function (value) {
- return '$1' + value;
- },
- context: function (text) {
- return !isInCode;
- }
+ replace: function (lang) {
+ var ending = ''
+ if (!checkBelow(matchInCode)) {
+ ending = '\n\n```'
+ }
+ if (this.langs.indexOf(lang) !== -1) { return '$1```' + lang + '=' + ending } else if (this.charts.indexOf(lang) !== -1) { return '$1```' + lang + ending }
},
- { //referral
- match: /(^\s*|\n|\s{2})((\[\]|\[\]\[\]|\[\]\(\)|\!|\!\[\]|\!\[\]\[\]|\!\[\]\(\))\s*\w*)$/,
- search: function (term, callback) {
- callback($.map(supportReferrals, function (referral) {
- return referral.search.indexOf(term) === 0 ? referral.text : null;
- }));
- },
- replace: function (value) {
- return '$1' + value;
- },
- context: function (text) {
- return !isInCode;
- }
+ done: function () {
+ var cursor = editor.getCursor()
+ var text = []
+ text.push(editor.getLine(cursor.line - 1))
+ text.push(editor.getLine(cursor.line))
+ text = text.join('\n')
+ // console.log(text);
+ if (text === '\n```') { editor.doc.cm.execCommand('goLineUp') }
},
- { //externals
- match: /(^|\n|\s)\{\}(\w*)$/,
- search: function (term, callback) {
- callback($.map(supportExternals, function (external) {
- return external.search.indexOf(term) === 0 ? external.text : null;
- }));
- },
- replace: function (value) {
- return '$1' + value;
- },
- context: function (text) {
- return !isInCode;
- }
- }
- ], {
- appendTo: $('.cursor-menu')
- })
- .on({
- 'textComplete:beforeSearch': function (e) {
- //NA
+ context: function (text) {
+ return isInCode
+ }
+ },
+ { // Container strategy
+ containers: supportContainers,
+ match: /(^|\n):::(\s*)(\w*)$/,
+ search: function (term, callback) {
+ var line = editor.getLine(editor.getCursor().line)
+ term = line.match(this.match)[3].trim()
+ var list = []
+ $.map(this.containers, function (container) {
+ if (container.indexOf(term) === 0 && container !== term) { list.push(container) }
+ })
+ callback(list)
},
- 'textComplete:afterSearch': function (e) {
- checkCursorMenu();
+ replace: function (lang) {
+ var ending = ''
+ if (!checkBelow(matchInContainer)) {
+ ending = '\n\n:::'
+ }
+ if (this.containers.indexOf(lang) !== -1) { return '$1:::$2' + lang + ending }
},
- 'textComplete:select': function (e, value, strategy) {
- //NA
+ done: function () {
+ var cursor = editor.getCursor()
+ var text = []
+ text.push(editor.getLine(cursor.line - 1))
+ text.push(editor.getLine(cursor.line))
+ text = text.join('\n')
+ // console.log(text);
+ if (text === '\n:::') { editor.doc.cm.execCommand('goLineUp') }
},
- 'textComplete:show': function (e) {
- $(this).data('autocompleting', true);
- editor.setOption("extraKeys", {
- "Up": function () {
- return false;
- },
- "Right": function () {
- editor.doc.cm.execCommand("goCharRight");
- },
- "Down": function () {
- return false;
- },
- "Left": function () {
- editor.doc.cm.execCommand("goCharLeft");
- },
- "Enter": function () {
- return false;
- },
- "Backspace": function () {
- editor.doc.cm.execCommand("delCharBefore");
- }
- });
+ context: function (text) {
+ return !isInCode && isInContainer
+ }
+ },
+ { // header
+ match: /(?:^|\n)(\s{0,3})(#{1,6}\w*)$/,
+ search: function (term, callback) {
+ callback($.map(supportHeaders, function (header) {
+ return header.search.indexOf(term) === 0 ? header.text : null
+ }))
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
+ },
+ { // extra tags for blockquote
+ match: /(?:^|\n|\s)(>.*|\s|)((\^|)\[(\^|)\](\[\]|\(\)|:|)\s*\w*)$/,
+ search: function (term, callback) {
+ var line = editor.getLine(editor.getCursor().line)
+ var quote = line.match(this.match)[1].trim()
+ var list = []
+ if (quote.indexOf('>') === 0) {
+ $.map(supportExtraTags, function (extratag) {
+ if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }
+ })
+ }
+ $.map(supportReferrals, function (referral) {
+ if (referral.search.indexOf(term) === 0) { list.push(referral.text) }
+ })
+ callback(list)
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
+ },
+ { // extra tags for list
+ match: /(^[>\s]*[-+*]\s(?:\[[x ]\]|.*))(\[\])(\w*)$/,
+ search: function (term, callback) {
+ var list = []
+ $.map(supportExtraTags, function (extratag) {
+ if (extratag.search.indexOf(term) === 0) { list.push(extratag.command()) }
+ })
+ $.map(supportReferrals, function (referral) {
+ if (referral.search.indexOf(term) === 0) { list.push(referral.text) }
+ })
+ callback(list)
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
+ },
+ { // referral
+ match: /(^\s*|\n|\s{2})((\[\]|\[\]\[\]|\[\]\(\)|!|!\[\]|!\[\]\[\]|!\[\]\(\))\s*\w*)$/,
+ search: function (term, callback) {
+ callback($.map(supportReferrals, function (referral) {
+ return referral.search.indexOf(term) === 0 ? referral.text : null
+ }))
},
- 'textComplete:hide': function (e) {
- $(this).data('autocompleting', false);
- editor.setOption("extraKeys", editorInstance.defaultExtraKeys);
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
+ }
+ },
+ { // externals
+ match: /(^|\n|\s)\{\}(\w*)$/,
+ search: function (term, callback) {
+ callback($.map(supportExternals, function (external) {
+ return external.search.indexOf(term) === 0 ? external.text : null
+ }))
+ },
+ replace: function (value) {
+ return '$1' + value
+ },
+ context: function (text) {
+ return !isInCode
}
- });
+ }
+ ], {
+ appendTo: $('.cursor-menu')
+ })
+ .on({
+ 'textComplete:beforeSearch': function (e) {
+ // NA
+ },
+ 'textComplete:afterSearch': function (e) {
+ checkCursorMenu()
+ },
+ 'textComplete:select': function (e, value, strategy) {
+ // NA
+ },
+ 'textComplete:show': function (e) {
+ $(this).data('autocompleting', true)
+ editor.setOption('extraKeys', {
+ 'Up': function () {
+ return false
+ },
+ 'Right': function () {
+ editor.doc.cm.execCommand('goCharRight')
+ },
+ 'Down': function () {
+ return false
+ },
+ 'Left': function () {
+ editor.doc.cm.execCommand('goCharLeft')
+ },
+ 'Enter': function () {
+ return false
+ },
+ 'Backspace': function () {
+ editor.doc.cm.execCommand('delCharBefore')
+ }
+ })
+ },
+ 'textComplete:hide': function (e) {
+ $(this).data('autocompleting', false)
+ editor.setOption('extraKeys', editorInstance.defaultExtraKeys)
+ }
+ })