From db06a51299e0888b07062cefd780d514d09ebd37 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sun, 9 Apr 2017 20:05:48 +0800 Subject: Load statusbar template by string-loader --- public/js/lib/editor/index.js | 54 ++++++++++++++----------------------- public/js/lib/editor/statusbar.html | 41 ++++++++++++++++++++++++++++ public/views/statusbar.html | 41 ---------------------------- 3 files changed, 61 insertions(+), 75 deletions(-) create mode 100644 public/js/lib/editor/statusbar.html delete mode 100644 public/views/statusbar.html (limited to 'public') diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js index c807a17f..8cab486c 100644 --- a/public/js/lib/editor/index.js +++ b/public/js/lib/editor/index.js @@ -1,5 +1,6 @@ import * as utils from './utils' import config from './config' +import statusBarTemplate from './statusbar.html' /* config section */ const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault @@ -132,40 +133,27 @@ export default class Editor { }) } - getStatusBarTemplate () { - return new Promise((resolve, reject) => { - $.get(window.serverurl + '/views/statusbar.html').done(template => { - this.statusBarTemplate = template - resolve() - }).fail(reject) - }) - } - addStatusBar () { - if (!this.statusBarTemplate) { - this.getStatusBarTemplate.then(this.addStatusBar) - } else { - this.statusBar = $(this.statusBarTemplate) - this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column') - this.statusSelection = this.statusBar.find('.status-cursor > .status-selection') - this.statusFile = this.statusBar.find('.status-file') - this.statusIndicators = this.statusBar.find('.status-indicators') - this.statusIndent = this.statusBar.find('.status-indent') - this.statusKeymap = this.statusBar.find('.status-keymap') - this.statusLength = this.statusBar.find('.status-length') - this.statusTheme = this.statusBar.find('.status-theme') - this.statusSpellcheck = this.statusBar.find('.status-spellcheck') - this.statusPreferences = this.statusBar.find('.status-preferences') - this.statusPanel = this.editor.addPanel(this.statusBar[0], { - position: 'bottom' - }) + this.statusBar = $(statusBarTemplate) + this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column') + this.statusSelection = this.statusBar.find('.status-cursor > .status-selection') + this.statusFile = this.statusBar.find('.status-file') + this.statusIndicators = this.statusBar.find('.status-indicators') + this.statusIndent = this.statusBar.find('.status-indent') + this.statusKeymap = this.statusBar.find('.status-keymap') + this.statusLength = this.statusBar.find('.status-length') + this.statusTheme = this.statusBar.find('.status-theme') + this.statusSpellcheck = this.statusBar.find('.status-spellcheck') + this.statusPreferences = this.statusBar.find('.status-preferences') + this.statusPanel = this.editor.addPanel(this.statusBar[0], { + position: 'bottom' + }) - this.setIndent() - this.setKeymap() - this.setTheme() - this.setSpellcheck() - this.setPreferences() - } + this.setIndent() + this.setKeymap() + this.setTheme() + this.setSpellcheck() + this.setPreferences() } updateStatusBar () { @@ -508,8 +496,6 @@ export default class Editor { placeholder: "← Start by entering a title here\n===\nVisit /features if you don't know what to do.\nHappy hacking :)" }) - this.getStatusBarTemplate() - return this.editor } diff --git a/public/js/lib/editor/statusbar.html b/public/js/lib/editor/statusbar.html new file mode 100644 index 00000000..24cbf6c2 --- /dev/null +++ b/public/js/lib/editor/statusbar.html @@ -0,0 +1,41 @@ +
diff --git a/public/views/statusbar.html b/public/views/statusbar.html deleted file mode 100644 index 24cbf6c2..00000000 --- a/public/views/statusbar.html +++ /dev/null @@ -1,41 +0,0 @@ - -- cgit v1.2.3 From c6c11c54ef62ed5c87dc7eb8139805a2889cbcc8 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Sun, 9 Apr 2017 21:14:23 +0800 Subject: Expose internal editor config variable --- public/js/index.js | 7 +++---- public/js/lib/editor/index.js | 1 + 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index 9a8ee11f..d34bfa93 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -78,7 +78,6 @@ import { import { preventXSS } from './render' import Editor from './lib/editor' -import EditorConfig from './lib/editor/config' import getUIElements from './lib/editor/ui-elements' @@ -446,7 +445,7 @@ $(document).ready(function () { /* we need this only on touch devices */ if (window.isTouchDevice) { /* cache dom references */ - var $body = jQuery('body') + var $body = $('body') /* bind events */ $(document) @@ -2082,8 +2081,8 @@ socket.on('permission', function (data) { var permission = null socket.on('refresh', function (data) { // console.log(data); - EditorConfig.docmaxlength = data.docmaxlength - editor.setOption('maxLength', EditorConfig.docmaxlength) + editorInstance.config.docmaxlength = data.docmaxlength + editor.setOption('maxLength', editorInstance.config.docmaxlength) updateInfo(data) updatePermission(data.permission) if (!window.loaded) { diff --git a/public/js/lib/editor/index.js b/public/js/lib/editor/index.js index 8cab486c..2991998b 100644 --- a/public/js/lib/editor/index.js +++ b/public/js/lib/editor/index.js @@ -119,6 +119,7 @@ export default class Editor { } } this.eventListeners = {} + this.config = config } on (event, cb) { -- cgit v1.2.3 From 432f215a456071d166d05ae3f51bf91e454a46e0 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 11 Apr 2017 11:37:41 +0800 Subject: Fix indentation --- public/js/index.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index d34bfa93..66e3da28 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -2499,12 +2499,12 @@ function buildCursor (user) { cursor.attr('data-mode', 'hover') cursortag.delay(2000).fadeOut('fast') cursor.hover( - function () { - if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeIn('fast') } - }, - function () { - if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeOut('fast') } - }) + function () { + if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeIn('fast') } + }, + function () { + if (cursor.attr('data-mode') === 'hover') { cursortag.stop(true).fadeOut('fast') } + }) var hideCursorTagDelay = 2000 var hideCursorTagTimer = null -- cgit v1.2.3 From 18a6f9063ebab9913883f8bef78ad95736e7627d Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 11 Apr 2017 11:48:39 +0800 Subject: Change some global variables to local --- public/js/index.js | 62 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index 66e3da28..d28f4d6c 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -258,14 +258,14 @@ 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 +let needRefresh = false +let isDirty = false +let editShown = false +let visibleXS = false +let visibleSM = false +let visibleMD = false +let visibleLG = false +const isTouchDevice = 'ontouchstart' in document.documentElement window.currentMode = defaultMode window.currentStatus = statusType.offline window.lastInfo = { @@ -393,7 +393,7 @@ function setRefreshModal (status) { } function setNeedRefresh () { - window.needRefresh = true + needRefresh = true editor.setOption('readOnly', true) socket.disconnect() showStatus(statusType.offline) @@ -415,7 +415,7 @@ Visibility.change(function (e, state) { } } else { if (wasFocus) { - if (!window.visibleXS) { + if (!visibleXS) { editor.focus() editor.refresh() } @@ -432,7 +432,7 @@ $(document).ready(function () { checkResponsive() // if in smaller screen, we don't need advanced scrollbar var scrollbarStyle - if (window.visibleXS) { + if (visibleXS) { scrollbarStyle = 'native' } else { scrollbarStyle = 'overlay' @@ -443,7 +443,7 @@ $(document).ready(function () { } checkEditorStyle() /* we need this only on touch devices */ - if (window.isTouchDevice) { + if (isTouchDevice) { /* cache dom references */ var $body = $('body') @@ -553,12 +553,12 @@ function editorHasFocus () { // 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') + visibleXS = $('.visible-xs').is(':visible') + visibleSM = $('.visible-sm').is(':visible') + visibleMD = $('.visible-md').is(':visible') + visibleLG = $('.visible-lg').is(':visible') - if (window.visibleXS && window.currentMode === modeType.both) { + if (visibleXS && window.currentMode === modeType.both) { if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) } } @@ -780,9 +780,9 @@ function changeMode (type) { case modeType.edit: ui.area.edit.show() ui.area.view.hide() - if (!window.editShown) { + if (!editShown) { editor.refresh() - window.editShown = true + editShown = true } break case modeType.view: @@ -1764,11 +1764,11 @@ var socket = io.connect({ // overwrite original event for checking login state var on = socket.on socket.on = function () { - if (!checkLoginStateChanged() && !window.needRefresh) { return on.apply(socket, arguments) } + if (!checkLoginStateChanged() && !needRefresh) { return on.apply(socket, arguments) } } var emit = socket.emit socket.emit = function () { - if (!checkLoginStateChanged() && !window.needRefresh) { emit.apply(socket, arguments) } + if (!checkLoginStateChanged() && !needRefresh) { emit.apply(socket, arguments) } } socket.on('info', function (data) { console.error(data) @@ -1814,7 +1814,7 @@ socket.on('disconnect', function (data) { if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) } if (!retryTimer) { retryTimer = setInterval(function () { - if (!window.needRefresh) socket.connect() + if (!needRefresh) socket.connect() }, 1000) } }) @@ -2089,7 +2089,7 @@ socket.on('refresh', function (data) { // auto change mode if no content detected var nocontent = editor.getValue().length <= 0 if (nocontent) { - if (window.visibleXS) { window.currentMode = modeType.edit } else { window.currentMode = modeType.both } + if (visibleXS) { window.currentMode = modeType.edit } else { window.currentMode = modeType.both } } // parse mode from url if (window.location.search.length > 0) { @@ -2097,7 +2097,7 @@ socket.on('refresh', function (data) { if (urlMode) window.currentMode = urlMode } changeMode(window.currentMode) - if (nocontent && !window.visibleXS) { + if (nocontent && !visibleXS) { editor.focus() editor.refresh() } @@ -2169,7 +2169,7 @@ socket.on('doc', function (obj) { } if (setDoc && bodyMismatch) { - window.isDirty = true + isDirty = true updateView() } @@ -2177,12 +2177,12 @@ socket.on('doc', function (obj) { }) socket.on('ack', function () { - window.isDirty = true + isDirty = true updateView() }) socket.on('operation', function () { - window.isDirty = true + isDirty = true updateView() }) @@ -2395,7 +2395,7 @@ var userStatusCache = null 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' } + if (visibleXS) { type = 'xs' } else if (visibleSM) { type = 'sm' } else if (visibleMD) { type = 'md' } else if (visibleLG) { type = 'lg' } window.personalInfo['idle'] = idle.isAway window.personalInfo['type'] = type @@ -2800,7 +2800,7 @@ function restoreInfo () { // view actions function refreshView () { ui.area.markdown.html('') - window.isDirty = true + isDirty = true updateViewInner() } @@ -2812,7 +2812,7 @@ var lastResult = null var postUpdateEvent = null function updateViewInner () { - if (window.currentMode === modeType.edit || !window.isDirty) return + if (window.currentMode === modeType.edit || !isDirty) return var value = editor.getValue() var lastMeta = md.meta md.meta = {} @@ -2860,7 +2860,7 @@ function updateViewInner () { generateScrollspy() updateScrollspy() smoothHashScroll() - window.isDirty = false + isDirty = false clearMap() // buildMap(); updateTitleReminder() -- cgit v1.2.3 From 68ccee20b3709b9a0499d659c74ac0a298a9ffeb Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 11 Apr 2017 11:48:59 +0800 Subject: Extract modeType --- public/js/index.js | 12 +----------- public/js/lib/editor/modeType.js | 11 +++++++++++ public/js/syncscroll.js | 5 +++-- 3 files changed, 15 insertions(+), 13 deletions(-) create mode 100644 public/js/lib/editor/modeType.js (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index d28f4d6c..27b0295d 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -80,6 +80,7 @@ import { preventXSS } from './render' import Editor from './lib/editor' import getUIElements from './lib/editor/ui-elements' +import modeType from './lib/editor/modeType' var defaultTextHeight = 20 var viewportMargin = 20 @@ -226,17 +227,6 @@ var supportExtraTags = [ } } ] -window.modeType = { - edit: { - name: 'edit' - }, - view: { - name: 'view' - }, - both: { - name: 'both' - } -} var statusType = { connected: { msg: 'CONNECTED', diff --git a/public/js/lib/editor/modeType.js b/public/js/lib/editor/modeType.js new file mode 100644 index 00000000..f3212105 --- /dev/null +++ b/public/js/lib/editor/modeType.js @@ -0,0 +1,11 @@ +export default { + edit: { + name: 'edit' + }, + view: { + name: 'view' + }, + both: { + name: 'both' + } +} diff --git a/public/js/syncscroll.js b/public/js/syncscroll.js index c227f83f..ad21e57b 100644 --- a/public/js/syncscroll.js +++ b/public/js/syncscroll.js @@ -5,6 +5,7 @@ import markdownitContainer from 'markdown-it-container' import { md } from './extra' +import modeType from './lib/editor/modeType' function addPart (tokens, idx) { if (tokens[idx].map && tokens[idx].level === 0) { @@ -228,7 +229,7 @@ function buildMapInner (callback) { let viewScrollingTimer = null export function syncScrollToEdit (event, preventAnimate) { - if (window.currentMode !== window.modeType.both || !window.syncscroll || !editArea) return + if (window.currentMode !== modeType.both || !window.syncscroll || !editArea) return if (window.preventSyncScrollToEdit) { if (typeof window.preventSyncScrollToEdit === 'number') { window.preventSyncScrollToEdit-- @@ -310,7 +311,7 @@ function viewScrollingTimeoutInner () { let editScrollingTimer = null export function syncScrollToView (event, preventAnimate) { - if (window.currentMode !== window.modeType.both || !window.syncscroll || !viewArea) return + if (window.currentMode !== modeType.both || !window.syncscroll || !viewArea) return if (window.preventSyncScrollToView) { if (typeof preventSyncScrollToView === 'number') { window.preventSyncScrollToView-- -- cgit v1.2.3 From 88c0c688561e8656763391699c385cc89461d776 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 11 Apr 2017 12:07:04 +0800 Subject: Change more global var to global --- public/js/index.js | 174 ++++++++++++++++++++++++++--------------------------- 1 file changed, 87 insertions(+), 87 deletions(-) (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index 27b0295d..81c24ebc 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -124,7 +124,7 @@ var supportHeaders = [ search: '###### tags:' } ] -var supportReferrals = [ +const supportReferrals = [ { text: '[reference link]', search: '[]' @@ -170,7 +170,7 @@ var supportReferrals = [ search: '[]' } ] -var supportExternals = [ +const supportExternals = [ { text: '{%youtube youtubeid %}', search: 'youtube' @@ -196,12 +196,12 @@ var supportExternals = [ search: 'pdf' } ] -var supportExtraTags = [ +const supportExtraTags = [ { text: '[name tag]', search: '[]', command: function () { - return '[name=' + window.personalInfo.name + ']' + return '[name=' + personalInfo.name + ']' } }, { @@ -215,7 +215,7 @@ var supportExtraTags = [ text: '[my color tag]', search: '[]', command: function () { - return '[color=' + window.personalInfo.color + ']' + return '[color=' + personalInfo.color + ']' } }, { @@ -227,7 +227,7 @@ var supportExtraTags = [ } } ] -var statusType = { +const statusType = { connected: { msg: 'CONNECTED', label: 'label-warning', @@ -244,7 +244,7 @@ var statusType = { fa: 'fa-plug' } } -var defaultMode = modeType.view +const defaultMode = modeType.view // global vars window.loaded = false @@ -257,8 +257,8 @@ let visibleMD = false let visibleLG = false const isTouchDevice = 'ontouchstart' in document.documentElement window.currentMode = defaultMode -window.currentStatus = statusType.offline -window.lastInfo = { +let currentStatus = statusType.offline +let lastInfo = { needRestore: false, cursor: null, scroll: null, @@ -281,9 +281,9 @@ window.lastInfo = { }, history: null } -window.personalInfo = {} -window.onlineUsers = [] -window.fileTypes = { +let personalInfo = {} +let onlineUsers = [] +const fileTypes = { 'pl': 'perl', 'cgi': 'perl', 'js': 'javascript', @@ -295,7 +295,7 @@ window.fileTypes = { } // editor settings -var textit = document.getElementById('textit') +const textit = document.getElementById('textit') if (!textit) { throw new Error('There was no textit area!') } @@ -522,8 +522,8 @@ function windowResizeInner (callback) { 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]) } + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id !== personalInfo.id) { buildCursor(onlineUsers[i]) } } updateScrollspy() if (callback && typeof callback === 'function') { callback() } @@ -696,7 +696,7 @@ function checkTocStyle () { } function showStatus (type, num) { - window.currentStatus = type + currentStatus = type var shortStatus = ui.toolbar.shortStatus var status = ui.toolbar.status var label = $('') @@ -707,7 +707,7 @@ function showStatus (type, num) { shortStatus.html('') status.html('') - switch (window.currentStatus) { + switch (currentStatus) { case statusType.connected: label.addClass(statusType.connected.label) fa.addClass(statusType.connected.fa) @@ -1533,7 +1533,7 @@ $('#snippetImportModalConfirm').click(function () { if (raw) { content += '\n\n' if (fileInfo[1] !== 'md') { - content += '```' + window.fileTypes[fileInfo[1]] + '\n' + content += '```' + fileTypes[fileInfo[1]] + '\n' } content += raw if (fileInfo[1] !== 'md') { @@ -1706,7 +1706,7 @@ function updatePermission (newPermission) { title = 'Only owner can view & edit' break } - if (window.personalInfo.userid && window.owner && window.personalInfo.userid === window.owner) { + if (personalInfo.userid && window.owner && personalInfo.userid === window.owner) { label += ' ' ui.infobar.permission.label.removeClass('disabled') } else { @@ -1723,7 +1723,7 @@ function havePermission () { break case 'editable': case 'limited': - if (!window.personalInfo.login) { + if (!personalInfo.login) { bool = false } else { bool = true @@ -1732,7 +1732,7 @@ function havePermission () { case 'locked': case 'private': case 'protected': - if (!window.owner || window.personalInfo.userid !== window.owner) { + if (!window.owner || personalInfo.userid !== window.owner) { bool = false } else { bool = true @@ -1779,7 +1779,7 @@ socket.on('error', function (data) { if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' } }) socket.on('delete', function () { - if (window.personalInfo.login) { + if (personalInfo.login) { deleteServerHistory(noteid, function (err, data) { if (!err) location.href = serverurl }) @@ -1799,7 +1799,7 @@ socket.on('disconnect', function (data) { showStatus(statusType.offline) if (window.loaded) { saveInfo() - window.lastInfo.history = editor.getHistory() + lastInfo.history = editor.getHistory() } if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) } if (!retryTimer) { @@ -1817,7 +1817,7 @@ socket.on('reconnect', function (data) { socket.on('connect', function (data) { clearInterval(retryTimer) retryTimer = null - window.personalInfo['id'] = socket.id + personalInfo['id'] = socket.id showStatus(statusType.connected) socket.emit('version') }) @@ -2135,8 +2135,8 @@ socket.on('doc', function (obj) { } 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 + else if (lastInfo.history) editor.setHistory(lastInfo.history) + lastInfo.history = null } if (!cmClient) { @@ -2178,7 +2178,7 @@ socket.on('operation', function () { socket.on('online users', function (data) { if (debug) { console.debug(data) } - window.onlineUsers = data.users + onlineUsers = data.users updateOnlineStatus() $('.CodeMirror-other-cursors').children().each(function (key, value) { var found = false @@ -2194,14 +2194,14 @@ socket.on('online users', function (data) { }) 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 } + if (user.id !== socket.id) { buildCursor(user) } else { personalInfo = user } } }) socket.on('user status', function (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 + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id === data.id) { + onlineUsers[i] = data } } updateOnlineStatus() @@ -2209,9 +2209,9 @@ socket.on('user status', function (data) { }) socket.on('cursor focus', function (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].cursor = data.cursor + 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) } @@ -2223,18 +2223,18 @@ socket.on('cursor focus', function (data) { }) socket.on('cursor activity', function (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].cursor = data.cursor + 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) } }) socket.on('cursor blur', function (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].cursor = null + 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) } @@ -2259,7 +2259,7 @@ var shortOnlineUserList = new List('short-online-user-list', options) function updateOnlineStatus () { if (!window.loaded || !socket.connected) return - var _onlineUsers = deduplicateOnlineUsers(window.onlineUsers) + var _onlineUsers = deduplicateOnlineUsers(onlineUsers) showStatus(statusType.online, _onlineUsers.length) var items = onlineUserList.items // update or remove current list items @@ -2310,8 +2310,8 @@ function sortOnlineUserList (list) { 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)) + 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) { @@ -2362,7 +2362,7 @@ function deduplicateOnlineUsers (list) { 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) { + if (user.id === personalInfo.id) { _onlineUsers[j].color = user.color } // keep idle state if any of self client not idle @@ -2387,12 +2387,12 @@ function emitUserStatus (force) { var type = null if (visibleXS) { type = 'xs' } else if (visibleSM) { type = 'sm' } else if (visibleMD) { type = 'md' } else if (visibleLG) { type = 'lg' } - window.personalInfo['idle'] = idle.isAway - window.personalInfo['type'] = type + personalInfo['idle'] = idle.isAway + personalInfo['type'] = type - for (var i = 0; i < window.onlineUsers.length; i++) { - if (window.onlineUsers[i].id === window.personalInfo.id) { - window.onlineUsers[i] = window.personalInfo + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id === personalInfo.id) { + onlineUsers[i] = personalInfo } } @@ -2653,12 +2653,12 @@ editorInstance.on('changes', function (editor, changes) { } }) editorInstance.on('focus', function (editor) { - for (var i = 0; i < window.onlineUsers.length; i++) { - if (window.onlineUsers[i].id === window.personalInfo.id) { - window.onlineUsers[i].cursor = editor.getCursor() + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id === personalInfo.id) { + onlineUsers[i].cursor = editor.getCursor() } } - window.personalInfo['cursor'] = editor.getCursor() + personalInfo['cursor'] = editor.getCursor() socket.emit('cursor focus', editor.getCursor()) }) @@ -2666,12 +2666,12 @@ const cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce) function cursorActivityInner (editor) { 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() + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id === personalInfo.id) { + onlineUsers[i].cursor = editor.getCursor() } } - window.personalInfo['cursor'] = editor.getCursor() + personalInfo['cursor'] = editor.getCursor() socket.emit('cursor activity', editor.getCursor()) } } @@ -2713,12 +2713,12 @@ editorInstance.on('beforeSelectionChange', function (doc, selections) { }) editorInstance.on('blur', function (cm) { - for (var i = 0; i < window.onlineUsers.length; i++) { - if (window.onlineUsers[i].id === window.personalInfo.id) { - window.onlineUsers[i].cursor = null + for (var i = 0; i < onlineUsers.length; i++) { + if (onlineUsers[i].id === personalInfo.id) { + onlineUsers[i].cursor = null } } - window.personalInfo['cursor'] = null + personalInfo['cursor'] = null socket.emit('cursor blur') }) @@ -2729,61 +2729,61 @@ function saveInfo () { switch (window.currentMode) { case modeType.edit: if (scrollbarStyle === 'native') { - window.lastInfo.edit.scroll.left = left - window.lastInfo.edit.scroll.top = top + lastInfo.edit.scroll.left = left + lastInfo.edit.scroll.top = top } else { - window.lastInfo.edit.scroll = editor.getScrollInfo() + lastInfo.edit.scroll = editor.getScrollInfo() } break case modeType.view: - window.lastInfo.view.scroll.left = left - window.lastInfo.view.scroll.top = top + lastInfo.view.scroll.left = left + 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() + lastInfo.edit.scroll = editor.getScrollInfo() + lastInfo.view.scroll.left = ui.area.view.scrollLeft() + 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 + lastInfo.edit.cursor = editor.getCursor() + lastInfo.edit.selections = editor.listSelections() + 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 + if (lastInfo.needRestore) { + var line = lastInfo.edit.cursor.line + var ch = lastInfo.edit.cursor.ch editor.setCursor(line, ch) - editor.setSelections(window.lastInfo.edit.selections) + editor.setSelections(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) + $(window).scrollLeft(lastInfo.edit.scroll.left) + $(window).scrollTop(lastInfo.edit.scroll.top) } else { - let left = window.lastInfo.edit.scroll.left - let top = window.lastInfo.edit.scroll.top + let left = lastInfo.edit.scroll.left + let top = 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) + $(window).scrollLeft(lastInfo.view.scroll.left) + $(window).scrollTop(lastInfo.view.scroll.top) break case modeType.both: - let left = window.lastInfo.edit.scroll.left - let top = window.lastInfo.edit.scroll.top + let left = lastInfo.edit.scroll.left + let top = 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) + ui.area.view.scrollLeft(lastInfo.view.scroll.left) + ui.area.view.scrollTop(lastInfo.view.scroll.top) break } - window.lastInfo.needRestore = false + lastInfo.needRestore = false } } -- cgit v1.2.3 From d9221f6011aab9355f842b6e001df75b71120960 Mon Sep 17 00:00:00 2001 From: Yukai Huang Date: Tue, 11 Apr 2017 14:17:14 +0800 Subject: Remove CodeMirror-other-cursors dom creation Since it’s done via hackmdio/CodeMirror#1 --- public/js/index.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'public') diff --git a/public/js/index.js b/public/js/index.js index 81c24ebc..0ca6827b 100644 --- a/public/js/index.js +++ b/public/js/index.js @@ -2466,9 +2466,6 @@ function buildCursor (user) { iconClass = 'fa-desktop' break } - if ($('.CodeMirror-other-cursors').length <= 0) { - $("${highlighted}
\n`
+ }
+
+ return `${highlighted}
\n`
+}
+md.renderer.rules.code_block = (tokens, idx, options, env, self) => {
+ if (tokens[idx].map && tokens[idx].level === 0) {
+ const startline = tokens[idx].map[0] + 1
+ const endline = tokens[idx].map[1]
+ return `${md.utils.escapeHtml(tokens[idx].content)}
\n`
+ }
+ return `${md.utils.escapeHtml(tokens[idx].content)}
\n`
+}
+function renderContainer (tokens, idx, options, env, self) {
+ tokens[idx].attrJoin('role', 'alert')
+ tokens[idx].attrJoin('class', 'alert')
+ tokens[idx].attrJoin('class', `alert-${tokens[idx].info.trim()}`)
+ addPart(tokens, idx)
+ return self.renderToken(...arguments)
+}
+
+md.use(markdownitContainer, 'success', { render: renderContainer })
+md.use(markdownitContainer, 'info', { render: renderContainer })
+md.use(markdownitContainer, 'warning', { render: renderContainer })
+md.use(markdownitContainer, 'danger', { render: renderContainer })
+
+// FIXME: expose syncscroll to window
+window.syncscroll = true
+
+window.preventSyncScrollToEdit = false
+window.preventSyncScrollToView = false
+
+const editScrollThrottle = 5
+const viewScrollThrottle = 5
+const buildMapThrottle = 100
+
+let viewScrolling = false
+let editScrolling = false
+
+let editArea = null
+let viewArea = null
+let markdownArea = null
+
+export function setupSyncAreas (edit, view, markdown) {
+ editArea = edit
+ viewArea = view
+ markdownArea = markdown
+ editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle))
+ viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle))
+}
+
+let scrollMap, lineHeightMap, viewTop, viewBottom
+
+export function clearMap () {
+ scrollMap = null
+ lineHeightMap = null
+ viewTop = null
+ viewBottom = null
+}
+window.viewAjaxCallback = clearMap
+
+const buildMap = _.throttle(buildMapInner, buildMapThrottle)
+
+// Build offsets for each line (lines can be wrapped)
+// That's a bit dirty to process each line everytime, but ok for demo.
+// Optimizations are required only for big texts.
+function buildMapInner (callback) {
+ if (!viewArea || !markdownArea) return
+ let i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, acc, _scrollMap
+
+ offset = viewArea.scrollTop() - viewArea.offset().top
+ _scrollMap = []
+ nonEmptyList = []
+ _lineHeightMap = []
+ viewTop = 0
+ viewBottom = viewArea[0].scrollHeight - viewArea.height()
+
+ acc = 0
+ const lines = window.editor.getValue().split('\n')
+ const lineHeight = window.editor.defaultTextHeight()
+ for (i = 0; i < lines.length; i++) {
+ const str = lines[i]
+
+ _lineHeightMap.push(acc)
+
+ if (str.length === 0) {
+ acc++
+ continue
+ }
+
+ const h = window.editor.heightAtLine(i + 1) - window.editor.heightAtLine(i)
+ acc += Math.round(h / lineHeight)
+ }
+ _lineHeightMap.push(acc)
+ linesCount = acc
+
+ for (i = 0; i < linesCount; i++) {
+ _scrollMap.push(-1)
+ }
+
+ nonEmptyList.push(0)
+ // make the first line go top
+ _scrollMap[0] = viewTop
+
+ const parts = markdownArea.find('.part').toArray()
+ for (i = 0; i < parts.length; i++) {
+ const $el = $(parts[i])
+ let t = $el.attr('data-startline') - 1
+ if (t === '') {
+ return
+ }
+ t = _lineHeightMap[t]
+ if (t !== 0 && t !== nonEmptyList[nonEmptyList.length - 1]) {
+ nonEmptyList.push(t)
+ }
+ _scrollMap[t] = Math.round($el.offset().top + offset - 10)
+ }
+
+ nonEmptyList.push(linesCount)
+ _scrollMap[linesCount] = viewArea[0].scrollHeight
+
+ pos = 0
+ for (i = 1; i < linesCount; i++) {
+ if (_scrollMap[i] !== -1) {
+ pos++
+ continue
+ }
+
+ a = nonEmptyList[pos]
+ b = nonEmptyList[pos + 1]
+ _scrollMap[i] = Math.round((_scrollMap[b] * (i - a) + _scrollMap[a] * (b - i)) / (b - a))
+ }
+
+ _scrollMap[0] = 0
+
+ scrollMap = _scrollMap
+ lineHeightMap = _lineHeightMap
+
+ if (window.loaded && callback) callback()
+}
+
+// sync view scroll progress to edit
+let viewScrollingTimer = null
+
+export function syncScrollToEdit (event, preventAnimate) {
+ if (window.currentMode !== modeType.both || !window.syncscroll || !editArea) return
+ if (window.preventSyncScrollToEdit) {
+ if (typeof window.preventSyncScrollToEdit === 'number') {
+ window.preventSyncScrollToEdit--
+ } else {
+ window.preventSyncScrollToEdit = false
+ }
+ return
+ }
+ if (!scrollMap || !lineHeightMap) {
+ buildMap(() => {
+ syncScrollToEdit(event, preventAnimate)
+ })
+ return
+ }
+ if (editScrolling) return
+
+ const scrollTop = viewArea[0].scrollTop
+ let lineIndex = 0
+ for (let i = 0, l = scrollMap.length; i < l; i++) {
+ if (scrollMap[i] > scrollTop) {
+ break
+ } else {
+ lineIndex = i
+ }
+ }
+ let lineNo = 0
+ let lineDiff = 0
+ for (let i = 0, l = lineHeightMap.length; i < l; i++) {
+ if (lineHeightMap[i] > lineIndex) {
+ break
+ } else {
+ lineNo = lineHeightMap[i]
+ lineDiff = lineHeightMap[i + 1] - lineNo
+ }
+ }
+
+ let posTo = 0
+ let topDiffPercent = 0
+ let posToNextDiff = 0
+ const scrollInfo = window.editor.getScrollInfo()
+ const textHeight = window.editor.defaultTextHeight()
+ const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight
+ const preLastLineNo = Math.round(preLastLineHeight / textHeight)
+ const preLastLinePos = scrollMap[preLastLineNo]
+
+ if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {
+ posTo = preLastLineHeight
+ topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos)
+ posToNextDiff = textHeight * topDiffPercent
+ posTo += Math.ceil(posToNextDiff)
+ } else {
+ posTo = lineNo * textHeight
+ topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo])
+ posToNextDiff = textHeight * lineDiff * topDiffPercent
+ posTo += Math.ceil(posToNextDiff)
+ }
+
+ if (preventAnimate) {
+ editArea.scrollTop(posTo)
+ } else {
+ const posDiff = Math.abs(scrollInfo.top - posTo)
+ var duration = posDiff / 50
+ duration = duration >= 100 ? duration : 100
+ editArea.stop(true, true).animate({
+ scrollTop: posTo
+ }, duration, 'linear')
+ }
+
+ viewScrolling = true
+ clearTimeout(viewScrollingTimer)
+ viewScrollingTimer = setTimeout(viewScrollingTimeoutInner, duration * 1.5)
+}
+
+function viewScrollingTimeoutInner () {
+ viewScrolling = false
+}
+
+// sync edit scroll progress to view
+let editScrollingTimer = null
+
+export function syncScrollToView (event, preventAnimate) {
+ if (window.currentMode !== modeType.both || !window.syncscroll || !viewArea) return
+ if (window.preventSyncScrollToView) {
+ if (typeof preventSyncScrollToView === 'number') {
+ window.preventSyncScrollToView--
+ } else {
+ window.preventSyncScrollToView = false
+ }
+ return
+ }
+ if (!scrollMap || !lineHeightMap) {
+ buildMap(() => {
+ syncScrollToView(event, preventAnimate)
+ })
+ return
+ }
+ if (viewScrolling) return
+
+ let lineNo, posTo
+ let topDiffPercent, posToNextDiff
+ const scrollInfo = window.editor.getScrollInfo()
+ const textHeight = window.editor.defaultTextHeight()
+ lineNo = Math.floor(scrollInfo.top / textHeight)
+ // if reach the last line, will start lerp to the bottom
+ const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
+ if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
+ topDiffPercent = diffToBottom / textHeight
+ posTo = scrollMap[lineNo + 1]
+ posToNextDiff = (viewBottom - posTo) * topDiffPercent
+ posTo += Math.floor(posToNextDiff)
+ } else {
+ topDiffPercent = (scrollInfo.top % textHeight) / textHeight
+ posTo = scrollMap[lineNo]
+ posToNextDiff = (scrollMap[lineNo + 1] - posTo) * topDiffPercent
+ posTo += Math.floor(posToNextDiff)
+ }
+
+ if (preventAnimate) {
+ viewArea.scrollTop(posTo)
+ } else {
+ const posDiff = Math.abs(viewArea.scrollTop() - posTo)
+ var duration = posDiff / 50
+ duration = duration >= 100 ? duration : 100
+ viewArea.stop(true, true).animate({
+ scrollTop: posTo
+ }, duration, 'linear')
+ }
+
+ editScrolling = true
+ clearTimeout(editScrollingTimer)
+ editScrollingTimer = setTimeout(editScrollingTimeoutInner, duration * 1.5)
+}
+
+function editScrollingTimeoutInner () {
+ editScrolling = false
+}
diff --git a/public/js/syncscroll.js b/public/js/syncscroll.js
deleted file mode 100644
index ad21e57b..00000000
--- a/public/js/syncscroll.js
+++ /dev/null
@@ -1,368 +0,0 @@
-/* eslint-env browser, jquery */
-/* global _ */
-// Inject line numbers for sync scroll.
-
-import markdownitContainer from 'markdown-it-container'
-
-import { md } from './extra'
-import modeType from './lib/editor/modeType'
-
-function addPart (tokens, idx) {
- if (tokens[idx].map && tokens[idx].level === 0) {
- const startline = tokens[idx].map[0] + 1
- const endline = tokens[idx].map[1]
- tokens[idx].attrJoin('class', 'part')
- tokens[idx].attrJoin('data-startline', startline)
- tokens[idx].attrJoin('data-endline', endline)
- }
-}
-
-md.renderer.rules.blockquote_open = function (tokens, idx, options, env, self) {
- tokens[idx].attrJoin('class', 'raw')
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.table_open = function (tokens, idx, options, env, self) {
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.bullet_list_open = function (tokens, idx, options, env, self) {
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.list_item_open = function (tokens, idx, options, env, self) {
- tokens[idx].attrJoin('class', 'raw')
- if (tokens[idx].map) {
- const startline = tokens[idx].map[0] + 1
- const endline = tokens[idx].map[1]
- tokens[idx].attrJoin('data-startline', startline)
- tokens[idx].attrJoin('data-endline', endline)
- }
- return self.renderToken(...arguments)
-}
-md.renderer.rules.ordered_list_open = function (tokens, idx, options, env, self) {
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.paragraph_open = function (tokens, idx, options, env, self) {
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.heading_open = function (tokens, idx, options, env, self) {
- tokens[idx].attrJoin('class', 'raw')
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-md.renderer.rules.fence = (tokens, idx, options, env, self) => {
- const token = tokens[idx]
- const info = token.info ? md.utils.unescapeAll(token.info).trim() : ''
- let langName = ''
- let highlighted
-
- if (info) {
- langName = info.split(/\s+/g)[0]
- if (/!$/.test(info)) token.attrJoin('class', 'wrap')
- token.attrJoin('class', options.langPrefix + langName.replace(/=$|=\d+$|=\+$|!$|=!/, ''))
- token.attrJoin('class', 'hljs')
- token.attrJoin('class', 'raw')
- }
-
- if (options.highlight) {
- highlighted = options.highlight(token.content, langName) || md.utils.escapeHtml(token.content)
- } else {
- highlighted = md.utils.escapeHtml(token.content)
- }
-
- if (highlighted.indexOf('${highlighted}
\n`
- }
-
- return `${highlighted}
\n`
-}
-md.renderer.rules.code_block = (tokens, idx, options, env, self) => {
- if (tokens[idx].map && tokens[idx].level === 0) {
- const startline = tokens[idx].map[0] + 1
- const endline = tokens[idx].map[1]
- return `${md.utils.escapeHtml(tokens[idx].content)}
\n`
- }
- return `${md.utils.escapeHtml(tokens[idx].content)}
\n`
-}
-function renderContainer (tokens, idx, options, env, self) {
- tokens[idx].attrJoin('role', 'alert')
- tokens[idx].attrJoin('class', 'alert')
- tokens[idx].attrJoin('class', `alert-${tokens[idx].info.trim()}`)
- addPart(tokens, idx)
- return self.renderToken(...arguments)
-}
-
-md.use(markdownitContainer, 'success', { render: renderContainer })
-md.use(markdownitContainer, 'info', { render: renderContainer })
-md.use(markdownitContainer, 'warning', { render: renderContainer })
-md.use(markdownitContainer, 'danger', { render: renderContainer })
-
-// FIXME: expose syncscroll to window
-window.syncscroll = true
-
-window.preventSyncScrollToEdit = false
-window.preventSyncScrollToView = false
-
-const editScrollThrottle = 5
-const viewScrollThrottle = 5
-const buildMapThrottle = 100
-
-let viewScrolling = false
-let editScrolling = false
-
-let editArea = null
-let viewArea = null
-let markdownArea = null
-
-export function setupSyncAreas (edit, view, markdown) {
- editArea = edit
- viewArea = view
- markdownArea = markdown
- editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle))
- viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle))
-}
-
-let scrollMap, lineHeightMap, viewTop, viewBottom
-
-export function clearMap () {
- scrollMap = null
- lineHeightMap = null
- viewTop = null
- viewBottom = null
-}
-window.viewAjaxCallback = clearMap
-
-const buildMap = _.throttle(buildMapInner, buildMapThrottle)
-
-// Build offsets for each line (lines can be wrapped)
-// That's a bit dirty to process each line everytime, but ok for demo.
-// Optimizations are required only for big texts.
-function buildMapInner (callback) {
- if (!viewArea || !markdownArea) return
- let i, offset, nonEmptyList, pos, a, b, _lineHeightMap, linesCount, acc, _scrollMap
-
- offset = viewArea.scrollTop() - viewArea.offset().top
- _scrollMap = []
- nonEmptyList = []
- _lineHeightMap = []
- viewTop = 0
- viewBottom = viewArea[0].scrollHeight - viewArea.height()
-
- acc = 0
- const lines = window.editor.getValue().split('\n')
- const lineHeight = window.editor.defaultTextHeight()
- for (i = 0; i < lines.length; i++) {
- const str = lines[i]
-
- _lineHeightMap.push(acc)
-
- if (str.length === 0) {
- acc++
- continue
- }
-
- const h = window.editor.heightAtLine(i + 1) - window.editor.heightAtLine(i)
- acc += Math.round(h / lineHeight)
- }
- _lineHeightMap.push(acc)
- linesCount = acc
-
- for (i = 0; i < linesCount; i++) {
- _scrollMap.push(-1)
- }
-
- nonEmptyList.push(0)
- // make the first line go top
- _scrollMap[0] = viewTop
-
- const parts = markdownArea.find('.part').toArray()
- for (i = 0; i < parts.length; i++) {
- const $el = $(parts[i])
- let t = $el.attr('data-startline') - 1
- if (t === '') {
- return
- }
- t = _lineHeightMap[t]
- if (t !== 0 && t !== nonEmptyList[nonEmptyList.length - 1]) {
- nonEmptyList.push(t)
- }
- _scrollMap[t] = Math.round($el.offset().top + offset - 10)
- }
-
- nonEmptyList.push(linesCount)
- _scrollMap[linesCount] = viewArea[0].scrollHeight
-
- pos = 0
- for (i = 1; i < linesCount; i++) {
- if (_scrollMap[i] !== -1) {
- pos++
- continue
- }
-
- a = nonEmptyList[pos]
- b = nonEmptyList[pos + 1]
- _scrollMap[i] = Math.round((_scrollMap[b] * (i - a) + _scrollMap[a] * (b - i)) / (b - a))
- }
-
- _scrollMap[0] = 0
-
- scrollMap = _scrollMap
- lineHeightMap = _lineHeightMap
-
- if (window.loaded && callback) callback()
-}
-
-// sync view scroll progress to edit
-let viewScrollingTimer = null
-
-export function syncScrollToEdit (event, preventAnimate) {
- if (window.currentMode !== modeType.both || !window.syncscroll || !editArea) return
- if (window.preventSyncScrollToEdit) {
- if (typeof window.preventSyncScrollToEdit === 'number') {
- window.preventSyncScrollToEdit--
- } else {
- window.preventSyncScrollToEdit = false
- }
- return
- }
- if (!scrollMap || !lineHeightMap) {
- buildMap(() => {
- syncScrollToEdit(event, preventAnimate)
- })
- return
- }
- if (editScrolling) return
-
- const scrollTop = viewArea[0].scrollTop
- let lineIndex = 0
- for (let i = 0, l = scrollMap.length; i < l; i++) {
- if (scrollMap[i] > scrollTop) {
- break
- } else {
- lineIndex = i
- }
- }
- let lineNo = 0
- let lineDiff = 0
- for (let i = 0, l = lineHeightMap.length; i < l; i++) {
- if (lineHeightMap[i] > lineIndex) {
- break
- } else {
- lineNo = lineHeightMap[i]
- lineDiff = lineHeightMap[i + 1] - lineNo
- }
- }
-
- let posTo = 0
- let topDiffPercent = 0
- let posToNextDiff = 0
- const scrollInfo = window.editor.getScrollInfo()
- const textHeight = window.editor.defaultTextHeight()
- const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight
- const preLastLineNo = Math.round(preLastLineHeight / textHeight)
- const preLastLinePos = scrollMap[preLastLineNo]
-
- if (scrollInfo.height > scrollInfo.clientHeight && scrollTop >= preLastLinePos) {
- posTo = preLastLineHeight
- topDiffPercent = (scrollTop - preLastLinePos) / (viewBottom - preLastLinePos)
- posToNextDiff = textHeight * topDiffPercent
- posTo += Math.ceil(posToNextDiff)
- } else {
- posTo = lineNo * textHeight
- topDiffPercent = (scrollTop - scrollMap[lineNo]) / (scrollMap[lineNo + lineDiff] - scrollMap[lineNo])
- posToNextDiff = textHeight * lineDiff * topDiffPercent
- posTo += Math.ceil(posToNextDiff)
- }
-
- if (preventAnimate) {
- editArea.scrollTop(posTo)
- } else {
- const posDiff = Math.abs(scrollInfo.top - posTo)
- var duration = posDiff / 50
- duration = duration >= 100 ? duration : 100
- editArea.stop(true, true).animate({
- scrollTop: posTo
- }, duration, 'linear')
- }
-
- viewScrolling = true
- clearTimeout(viewScrollingTimer)
- viewScrollingTimer = setTimeout(viewScrollingTimeoutInner, duration * 1.5)
-}
-
-function viewScrollingTimeoutInner () {
- viewScrolling = false
-}
-
-// sync edit scroll progress to view
-let editScrollingTimer = null
-
-export function syncScrollToView (event, preventAnimate) {
- if (window.currentMode !== modeType.both || !window.syncscroll || !viewArea) return
- if (window.preventSyncScrollToView) {
- if (typeof preventSyncScrollToView === 'number') {
- window.preventSyncScrollToView--
- } else {
- window.preventSyncScrollToView = false
- }
- return
- }
- if (!scrollMap || !lineHeightMap) {
- buildMap(() => {
- syncScrollToView(event, preventAnimate)
- })
- return
- }
- if (viewScrolling) return
-
- let lineNo, posTo
- let topDiffPercent, posToNextDiff
- const scrollInfo = window.editor.getScrollInfo()
- const textHeight = window.editor.defaultTextHeight()
- lineNo = Math.floor(scrollInfo.top / textHeight)
- // if reach the last line, will start lerp to the bottom
- const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
- if (scrollInfo.height > scrollInfo.clientHeight && diffToBottom > 0) {
- topDiffPercent = diffToBottom / textHeight
- posTo = scrollMap[lineNo + 1]
- posToNextDiff = (viewBottom - posTo) * topDiffPercent
- posTo += Math.floor(posToNextDiff)
- } else {
- topDiffPercent = (scrollInfo.top % textHeight) / textHeight
- posTo = scrollMap[lineNo]
- posToNextDiff = (scrollMap[lineNo + 1] - posTo) * topDiffPercent
- posTo += Math.floor(posToNextDiff)
- }
-
- if (preventAnimate) {
- viewArea.scrollTop(posTo)
- } else {
- const posDiff = Math.abs(viewArea.scrollTop() - posTo)
- var duration = posDiff / 50
- duration = duration >= 100 ? duration : 100
- viewArea.stop(true, true).animate({
- scrollTop: posTo
- }, duration, 'linear')
- }
-
- editScrolling = true
- clearTimeout(editScrollingTimer)
- editScrollingTimer = setTimeout(editScrollingTimeoutInner, duration * 1.5)
-}
-
-function editScrollingTimeoutInner () {
- editScrolling = false
-}
--
cgit v1.2.3
From 4839838d0cdfca29a9e87fcf966ec026ee99a14f Mon Sep 17 00:00:00 2001
From: Yukai Huang
Date: Wed, 12 Apr 2017 09:21:13 +0800
Subject: Manage syncscroll / currentMode in appState
---
public/js/index.js | 67 ++++++++++++++++++++--------------------
public/js/lib/appState.js | 8 +++++
public/js/lib/editor/modeType.js | 11 -------
public/js/lib/modeType.js | 11 +++++++
public/js/lib/syncscroll.js | 31 ++++++++++---------
5 files changed, 69 insertions(+), 59 deletions(-)
create mode 100644 public/js/lib/appState.js
delete mode 100644 public/js/lib/editor/modeType.js
create mode 100644 public/js/lib/modeType.js
(limited to 'public')
diff --git a/public/js/index.js b/public/js/index.js
index 245cf299..b336af90 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -80,7 +80,8 @@ import { preventXSS } from './render'
import Editor from './lib/editor'
import getUIElements from './lib/editor/ui-elements'
-import modeType from './lib/editor/modeType'
+import modeType from './lib/modeType'
+import appState from './lib/appState'
var defaultTextHeight = 20
var viewportMargin = 20
@@ -244,7 +245,6 @@ const statusType = {
fa: 'fa-plug'
}
}
-const defaultMode = modeType.view
// global vars
window.loaded = false
@@ -256,7 +256,6 @@ let visibleSM = false
let visibleMD = false
let visibleLG = false
const isTouchDevice = 'ontouchstart' in document.documentElement
-window.currentMode = defaultMode
let currentStatus = statusType.offline
let lastInfo = {
needRestore: false,
@@ -486,7 +485,7 @@ $(window).on('error', function () {
// setNeedRefresh();
})
-setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown)
+setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown, editor)
function autoSyncscroll () {
if (editorHasFocus()) {
@@ -548,7 +547,7 @@ function checkResponsive () {
visibleMD = $('.visible-md').is(':visible')
visibleLG = $('.visible-lg').is(':visible')
- if (visibleXS && window.currentMode === modeType.both) {
+ if (visibleXS && appState.currentMode === modeType.both) {
if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) }
}
@@ -562,7 +561,7 @@ 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' || window.currentMode === modeType.both) {
+ if (scrollbarStyle === 'overlay' || appState.currentMode === modeType.both) {
ui.area.codemirrorScroll.css('height', desireHeight + 'px')
ui.area.codemirrorScroll.css('min-height', '')
checkEditorScrollbar()
@@ -618,7 +617,7 @@ function checkEditorStyle () {
previousFocusOnEditor = null
})
ui.area.resize.syncToggle.click(function () {
- window.syncscroll = !window.syncscroll
+ appState.syncscroll = !appState.syncscroll
checkSyncToggle()
})
ui.area.resize.handle.append(ui.area.resize.syncToggle)
@@ -632,7 +631,7 @@ function checkEditorStyle () {
}
function checkSyncToggle () {
- if (window.syncscroll) {
+ if (appState.syncscroll) {
if (previousFocusOnEditor) {
window.preventSyncScrollToView = false
syncScrollToView()
@@ -679,10 +678,10 @@ function checkTocStyle () {
// toc scrollspy
ui.toc.toc.removeClass('scrollspy-body, scrollspy-view')
ui.toc.affix.removeClass('scrollspy-body, scrollspy-view')
- if (window.currentMode === modeType.both) {
+ if (appState.currentMode === modeType.both) {
ui.toc.toc.addClass('scrollspy-view')
ui.toc.affix.addClass('scrollspy-view')
- } else if (window.currentMode !== modeType.both && !newbool) {
+ } else if (appState.currentMode !== modeType.both && !newbool) {
ui.toc.toc.addClass('scrollspy-body')
ui.toc.affix.addClass('scrollspy-body')
} else {
@@ -737,7 +736,7 @@ function showStatus (type, num) {
}
function toggleMode () {
- switch (window.currentMode) {
+ switch (appState.currentMode) {
case modeType.edit:
changeMode(modeType.view)
break
@@ -757,8 +756,8 @@ function changeMode (type) {
lockNavbar()
saveInfo()
if (type) {
- lastMode = window.currentMode
- window.currentMode = type
+ lastMode = appState.currentMode
+ appState.currentMode = type
}
var responsiveClass = 'col-lg-6 col-md-6 col-sm-6'
var scrollClass = 'ui-scrollable'
@@ -766,7 +765,7 @@ function changeMode (type) {
ui.area.edit.removeClass(responsiveClass)
ui.area.view.removeClass(scrollClass)
ui.area.view.removeClass(responsiveClass)
- switch (window.currentMode) {
+ switch (appState.currentMode) {
case modeType.edit:
ui.area.edit.show()
ui.area.view.hide()
@@ -787,11 +786,11 @@ function changeMode (type) {
break
}
// save mode to url
- if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + window.currentMode.name)
- if (window.currentMode === modeType.view) {
+ if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + appState.currentMode.name)
+ if (appState.currentMode === modeType.view) {
editor.getInputField().blur()
}
- if (window.currentMode === modeType.edit || window.currentMode === modeType.both) {
+ if (appState.currentMode === modeType.edit || appState.currentMode === modeType.both) {
ui.toolbar.uploadImage.fadeIn()
// add and update status bar
if (!editorInstance.statusBar) {
@@ -804,14 +803,14 @@ function changeMode (type) {
} else {
ui.toolbar.uploadImage.fadeOut()
}
- if (window.currentMode !== modeType.edit) {
+ if (appState.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 (appState.currentMode === modeType.both) {
if (lastEditorWidth > 0) {
ui.area.edit.css('width', lastEditorWidth + 'px')
} else {
@@ -827,22 +826,22 @@ function changeMode (type) {
restoreInfo()
- if (lastMode === modeType.view && window.currentMode === modeType.both) {
+ if (lastMode === modeType.view && appState.currentMode === modeType.both) {
window.preventSyncScrollToView = 2
syncScrollToEdit(null, true)
}
- if (lastMode === modeType.edit && window.currentMode === modeType.both) {
+ if (lastMode === modeType.edit && appState.currentMode === modeType.both) {
window.preventSyncScrollToEdit = 2
syncScrollToView(null, true)
}
- if (lastMode === modeType.both && window.currentMode !== modeType.both) {
+ if (lastMode === modeType.both && appState.currentMode !== modeType.both) {
window.preventSyncScrollToView = false
window.preventSyncScrollToEdit = false
}
- if (lastMode !== modeType.edit && window.currentMode === modeType.edit) {
+ if (lastMode !== modeType.edit && appState.currentMode === modeType.edit) {
editor.refresh()
}
@@ -1360,7 +1359,7 @@ ui.modal.snippetImportSnippets.change(function () {
})
function scrollToTop () {
- if (window.currentMode === modeType.both) {
+ if (appState.currentMode === modeType.both) {
if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else {
ui.area.view.animate({
scrollTop: 0
@@ -1374,7 +1373,7 @@ function scrollToTop () {
}
function scrollToBottom () {
- if (window.currentMode === modeType.both) {
+ if (appState.currentMode === modeType.both) {
var scrollInfo = editor.getScrollInfo()
var scrollHeight = scrollInfo.height
if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else {
@@ -2079,14 +2078,14 @@ socket.on('refresh', function (data) {
// auto change mode if no content detected
var nocontent = editor.getValue().length <= 0
if (nocontent) {
- if (visibleXS) { window.currentMode = modeType.edit } else { window.currentMode = modeType.both }
+ if (visibleXS) { appState.currentMode = modeType.edit } else { appState.currentMode = modeType.both }
}
// parse mode from url
if (window.location.search.length > 0) {
var urlMode = modeType[window.location.search.substr(1)]
- if (urlMode) window.currentMode = urlMode
+ if (urlMode) appState.currentMode = urlMode
}
- changeMode(window.currentMode)
+ changeMode(appState.currentMode)
if (nocontent && !visibleXS) {
editor.focus()
editor.refresh()
@@ -2446,7 +2445,7 @@ function checkCursorTag (coord, ele) {
}
function buildCursor (user) {
- if (window.currentMode === modeType.view) return
+ if (appState.currentMode === modeType.view) return
if (!user.cursor) return
var coord = editor.charCoords(user.cursor, 'windows')
coord.left = coord.left < 4 ? 4 : coord.left
@@ -2723,7 +2722,7 @@ function saveInfo () {
var scrollbarStyle = editor.getOption('scrollbarStyle')
var left = $(window).scrollLeft()
var top = $(window).scrollTop()
- switch (window.currentMode) {
+ switch (appState.currentMode) {
case modeType.edit:
if (scrollbarStyle === 'native') {
lastInfo.edit.scroll.left = left
@@ -2754,7 +2753,7 @@ function restoreInfo () {
var ch = lastInfo.edit.cursor.ch
editor.setCursor(line, ch)
editor.setSelections(lastInfo.edit.selections)
- switch (window.currentMode) {
+ switch (appState.currentMode) {
case modeType.edit:
if (scrollbarStyle === 'native') {
$(window).scrollLeft(lastInfo.edit.scroll.left)
@@ -2799,7 +2798,7 @@ var lastResult = null
var postUpdateEvent = null
function updateViewInner () {
- if (window.currentMode === modeType.edit || !isDirty) return
+ if (appState.currentMode === modeType.edit || !isDirty) return
var value = editor.getValue()
var lastMeta = md.meta
md.meta = {}
@@ -2816,13 +2815,13 @@ function updateViewInner () {
// prevent XSS
ui.area.markdown.html(preventXSS(ui.area.markdown.html()))
ui.area.markdown.addClass('slides')
- window.syncscroll = false
+ appState.syncscroll = false
checkSyncToggle()
} else {
if (lastMeta.type && lastMeta.type === 'slide') {
refreshView()
ui.area.markdown.removeClass('slides')
- window.syncscroll = true
+ appState.syncscroll = true
checkSyncToggle()
}
// only render again when meta changed
diff --git a/public/js/lib/appState.js b/public/js/lib/appState.js
new file mode 100644
index 00000000..fb8030e1
--- /dev/null
+++ b/public/js/lib/appState.js
@@ -0,0 +1,8 @@
+import modeType from './modeType'
+
+let state = {
+ syncscroll: true,
+ currentMode: modeType.view
+}
+
+export default state
diff --git a/public/js/lib/editor/modeType.js b/public/js/lib/editor/modeType.js
deleted file mode 100644
index f3212105..00000000
--- a/public/js/lib/editor/modeType.js
+++ /dev/null
@@ -1,11 +0,0 @@
-export default {
- edit: {
- name: 'edit'
- },
- view: {
- name: 'view'
- },
- both: {
- name: 'both'
- }
-}
diff --git a/public/js/lib/modeType.js b/public/js/lib/modeType.js
new file mode 100644
index 00000000..f3212105
--- /dev/null
+++ b/public/js/lib/modeType.js
@@ -0,0 +1,11 @@
+export default {
+ edit: {
+ name: 'edit'
+ },
+ view: {
+ name: 'view'
+ },
+ both: {
+ name: 'both'
+ }
+}
diff --git a/public/js/lib/syncscroll.js b/public/js/lib/syncscroll.js
index 6b07e79c..cee317ea 100644
--- a/public/js/lib/syncscroll.js
+++ b/public/js/lib/syncscroll.js
@@ -5,7 +5,8 @@
import markdownitContainer from 'markdown-it-container'
import { md } from '../extra'
-import modeType from '../lib/editor/modeType'
+import modeType from './modeType'
+import appState from './appState'
function addPart (tokens, idx) {
if (tokens[idx].map && tokens[idx].level === 0) {
@@ -110,9 +111,6 @@ md.use(markdownitContainer, 'info', { render: renderContainer })
md.use(markdownitContainer, 'warning', { render: renderContainer })
md.use(markdownitContainer, 'danger', { render: renderContainer })
-// FIXME: expose syncscroll to window
-window.syncscroll = true
-
window.preventSyncScrollToEdit = false
window.preventSyncScrollToView = false
@@ -127,10 +125,15 @@ let editArea = null
let viewArea = null
let markdownArea = null
-export function setupSyncAreas (edit, view, markdown) {
+let editor
+
+export function setupSyncAreas (edit, view, markdown, _editor) {
editArea = edit
viewArea = view
markdownArea = markdown
+
+ editor = _editor
+
editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle))
viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle))
}
@@ -162,8 +165,8 @@ function buildMapInner (callback) {
viewBottom = viewArea[0].scrollHeight - viewArea.height()
acc = 0
- const lines = window.editor.getValue().split('\n')
- const lineHeight = window.editor.defaultTextHeight()
+ const lines = editor.getValue().split('\n')
+ const lineHeight = editor.defaultTextHeight()
for (i = 0; i < lines.length; i++) {
const str = lines[i]
@@ -174,7 +177,7 @@ function buildMapInner (callback) {
continue
}
- const h = window.editor.heightAtLine(i + 1) - window.editor.heightAtLine(i)
+ const h = editor.heightAtLine(i + 1) - editor.heightAtLine(i)
acc += Math.round(h / lineHeight)
}
_lineHeightMap.push(acc)
@@ -229,7 +232,7 @@ function buildMapInner (callback) {
let viewScrollingTimer = null
export function syncScrollToEdit (event, preventAnimate) {
- if (window.currentMode !== modeType.both || !window.syncscroll || !editArea) return
+ if (appState.currentMode !== modeType.both || !appState.syncscroll || !editArea) return
if (window.preventSyncScrollToEdit) {
if (typeof window.preventSyncScrollToEdit === 'number') {
window.preventSyncScrollToEdit--
@@ -269,8 +272,8 @@ export function syncScrollToEdit (event, preventAnimate) {
let posTo = 0
let topDiffPercent = 0
let posToNextDiff = 0
- const scrollInfo = window.editor.getScrollInfo()
- const textHeight = window.editor.defaultTextHeight()
+ const scrollInfo = editor.getScrollInfo()
+ const textHeight = editor.defaultTextHeight()
const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight
const preLastLineNo = Math.round(preLastLineHeight / textHeight)
const preLastLinePos = scrollMap[preLastLineNo]
@@ -311,7 +314,7 @@ function viewScrollingTimeoutInner () {
let editScrollingTimer = null
export function syncScrollToView (event, preventAnimate) {
- if (window.currentMode !== modeType.both || !window.syncscroll || !viewArea) return
+ if (appState.currentMode !== modeType.both || !appState.syncscroll || !viewArea) return
if (window.preventSyncScrollToView) {
if (typeof preventSyncScrollToView === 'number') {
window.preventSyncScrollToView--
@@ -330,8 +333,8 @@ export function syncScrollToView (event, preventAnimate) {
let lineNo, posTo
let topDiffPercent, posToNextDiff
- const scrollInfo = window.editor.getScrollInfo()
- const textHeight = window.editor.defaultTextHeight()
+ const scrollInfo = editor.getScrollInfo()
+ const textHeight = editor.defaultTextHeight()
lineNo = Math.floor(scrollInfo.top / textHeight)
// if reach the last line, will start lerp to the bottom
const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight)
--
cgit v1.2.3
From be99350655ca33aaa14b99d7b44b529aba0c8773 Mon Sep 17 00:00:00 2001
From: Wu Cheng-Han
Date: Tue, 9 May 2017 22:11:57 +0800
Subject: Fix to implement toggle of TOC in HTML template
---
public/views/html.hbs | 23 +++++++++++++++++++++++
1 file changed, 23 insertions(+)
(limited to 'public')
diff --git a/public/views/html.hbs b/public/views/html.hbs
index 5ef51920..a300ddd5 100644
--- a/public/views/html.hbs
+++ b/public/views/html.hbs
@@ -160,6 +160,29 @@
removeHash();
});
+ var toggle = $('.expand-toggle');
+ var tocExpand = false;
+
+ checkExpandToggle();
+ toggle.click(function (e) {
+ e.preventDefault();
+ e.stopPropagation();
+ tocExpand = !tocExpand;
+ checkExpandToggle();
+ })
+
+ function checkExpandToggle () {
+ var toc = $('.ui-toc-dropdown .toc');
+ var toggle = $('.expand-toggle');
+ if (!tocExpand) {
+ toc.removeClass('expand');
+ toggle.text('Expand all');
+ } else {
+ toc.addClass('expand');
+ toggle.text('Collapse all');
+ }
+ }
+
function scrollToTop() {
$('body, html').stop(true, true).animate({
scrollTop: 0
--
cgit v1.2.3