Merge pull request #429 from hackmdio/refactor-part-3
Refactor frontend part 3
This commit is contained in:
		
						commit
						f85d1d8801
					
				| @ -162,8 +162,9 @@ | |||||||
|     "less-loader": "^2.2.3", |     "less-loader": "^2.2.3", | ||||||
|     "optimize-css-assets-webpack-plugin": "^1.3.0", |     "optimize-css-assets-webpack-plugin": "^1.3.0", | ||||||
|     "script-loader": "^0.7.0", |     "script-loader": "^0.7.0", | ||||||
|     "style-loader": "^0.13.1", |  | ||||||
|     "standard": "^9.0.1", |     "standard": "^9.0.1", | ||||||
|  |     "string-loader": "^0.0.1", | ||||||
|  |     "style-loader": "^0.13.1", | ||||||
|     "url-loader": "^0.5.7", |     "url-loader": "^0.5.7", | ||||||
|     "webpack": "^1.14.0", |     "webpack": "^1.14.0", | ||||||
|     "webpack-parallel-uglify-plugin": "^0.2.0" |     "webpack-parallel-uglify-plugin": "^0.2.0" | ||||||
|  | |||||||
| @ -65,7 +65,7 @@ import { | |||||||
|     setupSyncAreas, |     setupSyncAreas, | ||||||
|     syncScrollToEdit, |     syncScrollToEdit, | ||||||
|     syncScrollToView |     syncScrollToView | ||||||
| } from './syncscroll' | } from './lib/syncscroll' | ||||||
| 
 | 
 | ||||||
| import { | import { | ||||||
|     writeHistory, |     writeHistory, | ||||||
| @ -78,9 +78,10 @@ import { | |||||||
| import { preventXSS } from './render' | import { preventXSS } from './render' | ||||||
| 
 | 
 | ||||||
| import Editor from './lib/editor' | import Editor from './lib/editor' | ||||||
| import EditorConfig from './lib/editor/config' |  | ||||||
| 
 | 
 | ||||||
| import getUIElements from './lib/editor/ui-elements' | import getUIElements from './lib/editor/ui-elements' | ||||||
|  | import modeType from './lib/modeType' | ||||||
|  | import appState from './lib/appState' | ||||||
| 
 | 
 | ||||||
| var defaultTextHeight = 20 | var defaultTextHeight = 20 | ||||||
| var viewportMargin = 20 | var viewportMargin = 20 | ||||||
| @ -124,7 +125,7 @@ var supportHeaders = [ | |||||||
|     search: '###### tags:' |     search: '###### tags:' | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
| var supportReferrals = [ | const supportReferrals = [ | ||||||
|   { |   { | ||||||
|     text: '[reference link]', |     text: '[reference link]', | ||||||
|     search: '[]' |     search: '[]' | ||||||
| @ -170,7 +171,7 @@ var supportReferrals = [ | |||||||
|     search: '[]' |     search: '[]' | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
| var supportExternals = [ | const supportExternals = [ | ||||||
|   { |   { | ||||||
|     text: '{%youtube youtubeid %}', |     text: '{%youtube youtubeid %}', | ||||||
|     search: 'youtube' |     search: 'youtube' | ||||||
| @ -196,12 +197,12 @@ var supportExternals = [ | |||||||
|     search: 'pdf' |     search: 'pdf' | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
| var supportExtraTags = [ | const supportExtraTags = [ | ||||||
|   { |   { | ||||||
|     text: '[name tag]', |     text: '[name tag]', | ||||||
|     search: '[]', |     search: '[]', | ||||||
|     command: function () { |     command: function () { | ||||||
|       return '[name=' + window.personalInfo.name + ']' |       return '[name=' + personalInfo.name + ']' | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
| @ -215,7 +216,7 @@ var supportExtraTags = [ | |||||||
|     text: '[my color tag]', |     text: '[my color tag]', | ||||||
|     search: '[]', |     search: '[]', | ||||||
|     command: function () { |     command: function () { | ||||||
|       return '[color=' + window.personalInfo.color + ']' |       return '[color=' + personalInfo.color + ']' | ||||||
|     } |     } | ||||||
|   }, |   }, | ||||||
|   { |   { | ||||||
| @ -227,18 +228,7 @@ var supportExtraTags = [ | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| ] | ] | ||||||
| window.modeType = { | const statusType = { | ||||||
|   edit: { |  | ||||||
|     name: 'edit' |  | ||||||
|   }, |  | ||||||
|   view: { |  | ||||||
|     name: 'view' |  | ||||||
|   }, |  | ||||||
|   both: { |  | ||||||
|     name: 'both' |  | ||||||
|   } |  | ||||||
| } |  | ||||||
| var statusType = { |  | ||||||
|   connected: { |   connected: { | ||||||
|     msg: 'CONNECTED', |     msg: 'CONNECTED', | ||||||
|     label: 'label-warning', |     label: 'label-warning', | ||||||
| @ -255,21 +245,19 @@ var statusType = { | |||||||
|     fa: 'fa-plug' |     fa: 'fa-plug' | ||||||
|   } |   } | ||||||
| } | } | ||||||
| var defaultMode = modeType.view |  | ||||||
| 
 | 
 | ||||||
| // global vars
 | // global vars
 | ||||||
| window.loaded = false | window.loaded = false | ||||||
| window.needRefresh = false | let needRefresh = false | ||||||
| window.isDirty = false | let isDirty = false | ||||||
| window.editShown = false | let editShown = false | ||||||
| window.visibleXS = false | let visibleXS = false | ||||||
| window.visibleSM = false | let visibleSM = false | ||||||
| window.visibleMD = false | let visibleMD = false | ||||||
| window.visibleLG = false | let visibleLG = false | ||||||
| window.isTouchDevice = 'ontouchstart' in document.documentElement | const isTouchDevice = 'ontouchstart' in document.documentElement | ||||||
| window.currentMode = defaultMode | let currentStatus = statusType.offline | ||||||
| window.currentStatus = statusType.offline | let lastInfo = { | ||||||
| window.lastInfo = { |  | ||||||
|   needRestore: false, |   needRestore: false, | ||||||
|   cursor: null, |   cursor: null, | ||||||
|   scroll: null, |   scroll: null, | ||||||
| @ -292,9 +280,9 @@ window.lastInfo = { | |||||||
|   }, |   }, | ||||||
|   history: null |   history: null | ||||||
| } | } | ||||||
| window.personalInfo = {} | let personalInfo = {} | ||||||
| window.onlineUsers = [] | let onlineUsers = [] | ||||||
| window.fileTypes = { | const fileTypes = { | ||||||
|   'pl': 'perl', |   'pl': 'perl', | ||||||
|   'cgi': 'perl', |   'cgi': 'perl', | ||||||
|   'js': 'javascript', |   'js': 'javascript', | ||||||
| @ -306,7 +294,7 @@ window.fileTypes = { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // editor settings
 | // editor settings
 | ||||||
| var textit = document.getElementById('textit') | const textit = document.getElementById('textit') | ||||||
| if (!textit) { | if (!textit) { | ||||||
|   throw new Error('There was no textit area!') |   throw new Error('There was no textit area!') | ||||||
| } | } | ||||||
| @ -394,7 +382,7 @@ function setRefreshModal (status) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function setNeedRefresh () { | function setNeedRefresh () { | ||||||
|   window.needRefresh = true |   needRefresh = true | ||||||
|   editor.setOption('readOnly', true) |   editor.setOption('readOnly', true) | ||||||
|   socket.disconnect() |   socket.disconnect() | ||||||
|   showStatus(statusType.offline) |   showStatus(statusType.offline) | ||||||
| @ -416,7 +404,7 @@ Visibility.change(function (e, state) { | |||||||
|     } |     } | ||||||
|   } else { |   } else { | ||||||
|     if (wasFocus) { |     if (wasFocus) { | ||||||
|       if (!window.visibleXS) { |       if (!visibleXS) { | ||||||
|         editor.focus() |         editor.focus() | ||||||
|         editor.refresh() |         editor.refresh() | ||||||
|       } |       } | ||||||
| @ -433,7 +421,7 @@ $(document).ready(function () { | |||||||
|   checkResponsive() |   checkResponsive() | ||||||
|     // if in smaller screen, we don't need advanced scrollbar
 |     // if in smaller screen, we don't need advanced scrollbar
 | ||||||
|   var scrollbarStyle |   var scrollbarStyle | ||||||
|   if (window.visibleXS) { |   if (visibleXS) { | ||||||
|     scrollbarStyle = 'native' |     scrollbarStyle = 'native' | ||||||
|   } else { |   } else { | ||||||
|     scrollbarStyle = 'overlay' |     scrollbarStyle = 'overlay' | ||||||
| @ -444,9 +432,9 @@ $(document).ready(function () { | |||||||
|   } |   } | ||||||
|   checkEditorStyle() |   checkEditorStyle() | ||||||
|   /* we need this only on touch devices */ |   /* we need this only on touch devices */ | ||||||
|   if (window.isTouchDevice) { |   if (isTouchDevice) { | ||||||
|     /* cache dom references */ |     /* cache dom references */ | ||||||
|     var $body = jQuery('body') |     var $body = $('body') | ||||||
| 
 | 
 | ||||||
|     /* bind events */ |     /* bind events */ | ||||||
|     $(document) |     $(document) | ||||||
| @ -497,7 +485,7 @@ $(window).on('error', function () { | |||||||
|   // setNeedRefresh();
 |   // setNeedRefresh();
 | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown) | setupSyncAreas(ui.area.codemirrorScroll, ui.area.view, ui.area.markdown, editor) | ||||||
| 
 | 
 | ||||||
| function autoSyncscroll () { | function autoSyncscroll () { | ||||||
|   if (editorHasFocus()) { |   if (editorHasFocus()) { | ||||||
| @ -533,8 +521,8 @@ function windowResizeInner (callback) { | |||||||
|         autoSyncscroll() |         autoSyncscroll() | ||||||
|         editor.setOption('viewportMargin', viewportMargin) |         editor.setOption('viewportMargin', viewportMargin) | ||||||
|         // add or update user cursors
 |         // add or update user cursors
 | ||||||
|         for (var i = 0; i < window.onlineUsers.length; i++) { |         for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|           if (window.onlineUsers[i].id !== window.personalInfo.id) { buildCursor(window.onlineUsers[i]) } |           if (onlineUsers[i].id !== personalInfo.id) { buildCursor(onlineUsers[i]) } | ||||||
|         } |         } | ||||||
|         updateScrollspy() |         updateScrollspy() | ||||||
|         if (callback && typeof callback === 'function') { callback() } |         if (callback && typeof callback === 'function') { callback() } | ||||||
| @ -554,12 +542,12 @@ function editorHasFocus () { | |||||||
| 
 | 
 | ||||||
| // 768-792px have a gap
 | // 768-792px have a gap
 | ||||||
| function checkResponsive () { | function checkResponsive () { | ||||||
|   window.visibleXS = $('.visible-xs').is(':visible') |   visibleXS = $('.visible-xs').is(':visible') | ||||||
|   window.visibleSM = $('.visible-sm').is(':visible') |   visibleSM = $('.visible-sm').is(':visible') | ||||||
|   window.visibleMD = $('.visible-md').is(':visible') |   visibleMD = $('.visible-md').is(':visible') | ||||||
|   window.visibleLG = $('.visible-lg').is(':visible') |   visibleLG = $('.visible-lg').is(':visible') | ||||||
| 
 | 
 | ||||||
|   if (window.visibleXS && window.currentMode === modeType.both) { |   if (visibleXS && appState.currentMode === modeType.both) { | ||||||
|     if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) } |     if (editorHasFocus()) { changeMode(modeType.edit) } else { changeMode(modeType.view) } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -573,7 +561,7 @@ function checkEditorStyle () { | |||||||
|   var desireHeight = editorInstance.statusBar ? (ui.area.edit.height() - editorInstance.statusBar.outerHeight()) : ui.area.edit.height() |   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
 |     // set editor height and min height based on scrollbar style and mode
 | ||||||
|   var scrollbarStyle = editor.getOption('scrollbarStyle') |   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('height', desireHeight + 'px') | ||||||
|     ui.area.codemirrorScroll.css('min-height', '') |     ui.area.codemirrorScroll.css('min-height', '') | ||||||
|     checkEditorScrollbar() |     checkEditorScrollbar() | ||||||
| @ -629,7 +617,7 @@ function checkEditorStyle () { | |||||||
|       previousFocusOnEditor = null |       previousFocusOnEditor = null | ||||||
|     }) |     }) | ||||||
|     ui.area.resize.syncToggle.click(function () { |     ui.area.resize.syncToggle.click(function () { | ||||||
|       window.syncscroll = !window.syncscroll |       appState.syncscroll = !appState.syncscroll | ||||||
|       checkSyncToggle() |       checkSyncToggle() | ||||||
|     }) |     }) | ||||||
|     ui.area.resize.handle.append(ui.area.resize.syncToggle) |     ui.area.resize.handle.append(ui.area.resize.syncToggle) | ||||||
| @ -643,7 +631,7 @@ function checkEditorStyle () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function checkSyncToggle () { | function checkSyncToggle () { | ||||||
|   if (window.syncscroll) { |   if (appState.syncscroll) { | ||||||
|     if (previousFocusOnEditor) { |     if (previousFocusOnEditor) { | ||||||
|       window.preventSyncScrollToView = false |       window.preventSyncScrollToView = false | ||||||
|       syncScrollToView() |       syncScrollToView() | ||||||
| @ -690,10 +678,10 @@ function checkTocStyle () { | |||||||
|   // toc scrollspy
 |   // toc scrollspy
 | ||||||
|   ui.toc.toc.removeClass('scrollspy-body, scrollspy-view') |   ui.toc.toc.removeClass('scrollspy-body, scrollspy-view') | ||||||
|   ui.toc.affix.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.toc.addClass('scrollspy-view') | ||||||
|     ui.toc.affix.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.toc.addClass('scrollspy-body') | ||||||
|     ui.toc.affix.addClass('scrollspy-body') |     ui.toc.affix.addClass('scrollspy-body') | ||||||
|   } else { |   } else { | ||||||
| @ -707,7 +695,7 @@ function checkTocStyle () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function showStatus (type, num) { | function showStatus (type, num) { | ||||||
|   window.currentStatus = type |   currentStatus = type | ||||||
|   var shortStatus = ui.toolbar.shortStatus |   var shortStatus = ui.toolbar.shortStatus | ||||||
|   var status = ui.toolbar.status |   var status = ui.toolbar.status | ||||||
|   var label = $('<span class="label"></span>') |   var label = $('<span class="label"></span>') | ||||||
| @ -718,7 +706,7 @@ function showStatus (type, num) { | |||||||
|   shortStatus.html('') |   shortStatus.html('') | ||||||
|   status.html('') |   status.html('') | ||||||
| 
 | 
 | ||||||
|   switch (window.currentStatus) { |   switch (currentStatus) { | ||||||
|     case statusType.connected: |     case statusType.connected: | ||||||
|       label.addClass(statusType.connected.label) |       label.addClass(statusType.connected.label) | ||||||
|       fa.addClass(statusType.connected.fa) |       fa.addClass(statusType.connected.fa) | ||||||
| @ -748,7 +736,7 @@ function showStatus (type, num) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function toggleMode () { | function toggleMode () { | ||||||
|   switch (window.currentMode) { |   switch (appState.currentMode) { | ||||||
|     case modeType.edit: |     case modeType.edit: | ||||||
|       changeMode(modeType.view) |       changeMode(modeType.view) | ||||||
|       break |       break | ||||||
| @ -768,8 +756,8 @@ function changeMode (type) { | |||||||
|   lockNavbar() |   lockNavbar() | ||||||
|   saveInfo() |   saveInfo() | ||||||
|   if (type) { |   if (type) { | ||||||
|     lastMode = window.currentMode |     lastMode = appState.currentMode | ||||||
|     window.currentMode = type |     appState.currentMode = type | ||||||
|   } |   } | ||||||
|   var responsiveClass = 'col-lg-6 col-md-6 col-sm-6' |   var responsiveClass = 'col-lg-6 col-md-6 col-sm-6' | ||||||
|   var scrollClass = 'ui-scrollable' |   var scrollClass = 'ui-scrollable' | ||||||
| @ -777,13 +765,13 @@ function changeMode (type) { | |||||||
|   ui.area.edit.removeClass(responsiveClass) |   ui.area.edit.removeClass(responsiveClass) | ||||||
|   ui.area.view.removeClass(scrollClass) |   ui.area.view.removeClass(scrollClass) | ||||||
|   ui.area.view.removeClass(responsiveClass) |   ui.area.view.removeClass(responsiveClass) | ||||||
|   switch (window.currentMode) { |   switch (appState.currentMode) { | ||||||
|     case modeType.edit: |     case modeType.edit: | ||||||
|       ui.area.edit.show() |       ui.area.edit.show() | ||||||
|       ui.area.view.hide() |       ui.area.view.hide() | ||||||
|       if (!window.editShown) { |       if (!editShown) { | ||||||
|         editor.refresh() |         editor.refresh() | ||||||
|         window.editShown = true |         editShown = true | ||||||
|       } |       } | ||||||
|       break |       break | ||||||
|     case modeType.view: |     case modeType.view: | ||||||
| @ -798,11 +786,11 @@ function changeMode (type) { | |||||||
|       break |       break | ||||||
|   } |   } | ||||||
|   // save mode to url
 |   // save mode to url
 | ||||||
|   if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + window.currentMode.name) |   if (history.replaceState && window.loaded) history.replaceState(null, '', serverurl + '/' + noteid + '?' + appState.currentMode.name) | ||||||
|   if (window.currentMode === modeType.view) { |   if (appState.currentMode === modeType.view) { | ||||||
|     editor.getInputField().blur() |     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() |     ui.toolbar.uploadImage.fadeIn() | ||||||
|     // add and update status bar
 |     // add and update status bar
 | ||||||
|     if (!editorInstance.statusBar) { |     if (!editorInstance.statusBar) { | ||||||
| @ -815,14 +803,14 @@ function changeMode (type) { | |||||||
|   } else { |   } else { | ||||||
|     ui.toolbar.uploadImage.fadeOut() |     ui.toolbar.uploadImage.fadeOut() | ||||||
|   } |   } | ||||||
|   if (window.currentMode !== modeType.edit) { |   if (appState.currentMode !== modeType.edit) { | ||||||
|     $(document.body).css('background-color', 'white') |     $(document.body).css('background-color', 'white') | ||||||
|     updateView() |     updateView() | ||||||
|   } else { |   } else { | ||||||
|     $(document.body).css('background-color', ui.area.codemirror.css('background-color')) |     $(document.body).css('background-color', ui.area.codemirror.css('background-color')) | ||||||
|   } |   } | ||||||
|     // check resizable editor style
 |     // check resizable editor style
 | ||||||
|   if (window.currentMode === modeType.both) { |   if (appState.currentMode === modeType.both) { | ||||||
|     if (lastEditorWidth > 0) { |     if (lastEditorWidth > 0) { | ||||||
|       ui.area.edit.css('width', lastEditorWidth + 'px') |       ui.area.edit.css('width', lastEditorWidth + 'px') | ||||||
|     } else { |     } else { | ||||||
| @ -838,22 +826,22 @@ function changeMode (type) { | |||||||
| 
 | 
 | ||||||
|   restoreInfo() |   restoreInfo() | ||||||
| 
 | 
 | ||||||
|   if (lastMode === modeType.view && window.currentMode === modeType.both) { |   if (lastMode === modeType.view && appState.currentMode === modeType.both) { | ||||||
|     window.preventSyncScrollToView = 2 |     window.preventSyncScrollToView = 2 | ||||||
|     syncScrollToEdit(null, true) |     syncScrollToEdit(null, true) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (lastMode === modeType.edit && window.currentMode === modeType.both) { |   if (lastMode === modeType.edit && appState.currentMode === modeType.both) { | ||||||
|     window.preventSyncScrollToEdit = 2 |     window.preventSyncScrollToEdit = 2 | ||||||
|     syncScrollToView(null, true) |     syncScrollToView(null, true) | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (lastMode === modeType.both && window.currentMode !== modeType.both) { |   if (lastMode === modeType.both && appState.currentMode !== modeType.both) { | ||||||
|     window.preventSyncScrollToView = false |     window.preventSyncScrollToView = false | ||||||
|     window.preventSyncScrollToEdit = false |     window.preventSyncScrollToEdit = false | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (lastMode !== modeType.edit && window.currentMode === modeType.edit) { |   if (lastMode !== modeType.edit && appState.currentMode === modeType.edit) { | ||||||
|     editor.refresh() |     editor.refresh() | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -1371,7 +1359,7 @@ ui.modal.snippetImportSnippets.change(function () { | |||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| function scrollToTop () { | function scrollToTop () { | ||||||
|   if (window.currentMode === modeType.both) { |   if (appState.currentMode === modeType.both) { | ||||||
|     if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else { |     if (editor.getScrollInfo().top !== 0) { editor.scrollTo(0, 0) } else { | ||||||
|       ui.area.view.animate({ |       ui.area.view.animate({ | ||||||
|         scrollTop: 0 |         scrollTop: 0 | ||||||
| @ -1385,7 +1373,7 @@ function scrollToTop () { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function scrollToBottom () { | function scrollToBottom () { | ||||||
|   if (window.currentMode === modeType.both) { |   if (appState.currentMode === modeType.both) { | ||||||
|     var scrollInfo = editor.getScrollInfo() |     var scrollInfo = editor.getScrollInfo() | ||||||
|     var scrollHeight = scrollInfo.height |     var scrollHeight = scrollInfo.height | ||||||
|     if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else { |     if (scrollInfo.top !== scrollHeight) { editor.scrollTo(0, scrollHeight * 2) } else { | ||||||
| @ -1544,7 +1532,7 @@ $('#snippetImportModalConfirm').click(function () { | |||||||
|                       if (raw) { |                       if (raw) { | ||||||
|                         content += '\n\n' |                         content += '\n\n' | ||||||
|                         if (fileInfo[1] !== 'md') { |                         if (fileInfo[1] !== 'md') { | ||||||
|                           content += '```' + window.fileTypes[fileInfo[1]] + '\n' |                           content += '```' + fileTypes[fileInfo[1]] + '\n' | ||||||
|                         } |                         } | ||||||
|                         content += raw |                         content += raw | ||||||
|                         if (fileInfo[1] !== 'md') { |                         if (fileInfo[1] !== 'md') { | ||||||
| @ -1717,7 +1705,7 @@ function updatePermission (newPermission) { | |||||||
|       title = 'Only owner can view & edit' |       title = 'Only owner can view & edit' | ||||||
|       break |       break | ||||||
|   } |   } | ||||||
|   if (window.personalInfo.userid && window.owner && window.personalInfo.userid === window.owner) { |   if (personalInfo.userid && window.owner && personalInfo.userid === window.owner) { | ||||||
|     label += ' <i class="fa fa-caret-down"></i>' |     label += ' <i class="fa fa-caret-down"></i>' | ||||||
|     ui.infobar.permission.label.removeClass('disabled') |     ui.infobar.permission.label.removeClass('disabled') | ||||||
|   } else { |   } else { | ||||||
| @ -1734,7 +1722,7 @@ function havePermission () { | |||||||
|       break |       break | ||||||
|     case 'editable': |     case 'editable': | ||||||
|     case 'limited': |     case 'limited': | ||||||
|       if (!window.personalInfo.login) { |       if (!personalInfo.login) { | ||||||
|         bool = false |         bool = false | ||||||
|       } else { |       } else { | ||||||
|         bool = true |         bool = true | ||||||
| @ -1743,7 +1731,7 @@ function havePermission () { | |||||||
|     case 'locked': |     case 'locked': | ||||||
|     case 'private': |     case 'private': | ||||||
|     case 'protected': |     case 'protected': | ||||||
|       if (!window.owner || window.personalInfo.userid !== window.owner) { |       if (!window.owner || personalInfo.userid !== window.owner) { | ||||||
|         bool = false |         bool = false | ||||||
|       } else { |       } else { | ||||||
|         bool = true |         bool = true | ||||||
| @ -1765,11 +1753,11 @@ var socket = io.connect({ | |||||||
| // overwrite original event for checking login state
 | // overwrite original event for checking login state
 | ||||||
| var on = socket.on | var on = socket.on | ||||||
| socket.on = function () { | socket.on = function () { | ||||||
|   if (!checkLoginStateChanged() && !window.needRefresh) { return on.apply(socket, arguments) } |   if (!checkLoginStateChanged() && !needRefresh) { return on.apply(socket, arguments) } | ||||||
| } | } | ||||||
| var emit = socket.emit | var emit = socket.emit | ||||||
| socket.emit = function () { | socket.emit = function () { | ||||||
|   if (!checkLoginStateChanged() && !window.needRefresh) { emit.apply(socket, arguments) } |   if (!checkLoginStateChanged() && !needRefresh) { emit.apply(socket, arguments) } | ||||||
| } | } | ||||||
| socket.on('info', function (data) { | socket.on('info', function (data) { | ||||||
|   console.error(data) |   console.error(data) | ||||||
| @ -1790,7 +1778,7 @@ socket.on('error', function (data) { | |||||||
|   if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' } |   if (data.message && data.message.indexOf('AUTH failed') === 0) { location.href = serverurl + '/403' } | ||||||
| }) | }) | ||||||
| socket.on('delete', function () { | socket.on('delete', function () { | ||||||
|   if (window.personalInfo.login) { |   if (personalInfo.login) { | ||||||
|     deleteServerHistory(noteid, function (err, data) { |     deleteServerHistory(noteid, function (err, data) { | ||||||
|       if (!err) location.href = serverurl |       if (!err) location.href = serverurl | ||||||
|     }) |     }) | ||||||
| @ -1810,12 +1798,12 @@ socket.on('disconnect', function (data) { | |||||||
|   showStatus(statusType.offline) |   showStatus(statusType.offline) | ||||||
|   if (window.loaded) { |   if (window.loaded) { | ||||||
|     saveInfo() |     saveInfo() | ||||||
|     window.lastInfo.history = editor.getHistory() |     lastInfo.history = editor.getHistory() | ||||||
|   } |   } | ||||||
|   if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) } |   if (!editor.getOption('readOnly')) { editor.setOption('readOnly', true) } | ||||||
|   if (!retryTimer) { |   if (!retryTimer) { | ||||||
|     retryTimer = setInterval(function () { |     retryTimer = setInterval(function () { | ||||||
|       if (!window.needRefresh) socket.connect() |       if (!needRefresh) socket.connect() | ||||||
|     }, 1000) |     }, 1000) | ||||||
|   } |   } | ||||||
| }) | }) | ||||||
| @ -1828,7 +1816,7 @@ socket.on('reconnect', function (data) { | |||||||
| socket.on('connect', function (data) { | socket.on('connect', function (data) { | ||||||
|   clearInterval(retryTimer) |   clearInterval(retryTimer) | ||||||
|   retryTimer = null |   retryTimer = null | ||||||
|   window.personalInfo['id'] = socket.id |   personalInfo['id'] = socket.id | ||||||
|   showStatus(statusType.connected) |   showStatus(statusType.connected) | ||||||
|   socket.emit('version') |   socket.emit('version') | ||||||
| }) | }) | ||||||
| @ -2082,23 +2070,23 @@ socket.on('permission', function (data) { | |||||||
| var permission = null | var permission = null | ||||||
| socket.on('refresh', function (data) { | socket.on('refresh', function (data) { | ||||||
|     // console.log(data);
 |     // console.log(data);
 | ||||||
|   EditorConfig.docmaxlength = data.docmaxlength |   editorInstance.config.docmaxlength = data.docmaxlength | ||||||
|   editor.setOption('maxLength', EditorConfig.docmaxlength) |   editor.setOption('maxLength', editorInstance.config.docmaxlength) | ||||||
|   updateInfo(data) |   updateInfo(data) | ||||||
|   updatePermission(data.permission) |   updatePermission(data.permission) | ||||||
|   if (!window.loaded) { |   if (!window.loaded) { | ||||||
|         // auto change mode if no content detected
 |         // auto change mode if no content detected
 | ||||||
|     var nocontent = editor.getValue().length <= 0 |     var nocontent = editor.getValue().length <= 0 | ||||||
|     if (nocontent) { |     if (nocontent) { | ||||||
|       if (window.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
 |     // parse mode from url
 | ||||||
|     if (window.location.search.length > 0) { |     if (window.location.search.length > 0) { | ||||||
|       var urlMode = modeType[window.location.search.substr(1)] |       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 && !window.visibleXS) { |     if (nocontent && !visibleXS) { | ||||||
|       editor.focus() |       editor.focus() | ||||||
|       editor.refresh() |       editor.refresh() | ||||||
|     } |     } | ||||||
| @ -2146,8 +2134,8 @@ socket.on('doc', function (obj) { | |||||||
|   } else { |   } else { | ||||||
|     // if current doc is equal to the doc before disconnect
 |     // if current doc is equal to the doc before disconnect
 | ||||||
|     if (setDoc && bodyMismatch) editor.clearHistory() |     if (setDoc && bodyMismatch) editor.clearHistory() | ||||||
|     else if (window.lastInfo.history) editor.setHistory(window.lastInfo.history) |     else if (lastInfo.history) editor.setHistory(lastInfo.history) | ||||||
|     window.lastInfo.history = null |     lastInfo.history = null | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (!cmClient) { |   if (!cmClient) { | ||||||
| @ -2170,7 +2158,7 @@ socket.on('doc', function (obj) { | |||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (setDoc && bodyMismatch) { |   if (setDoc && bodyMismatch) { | ||||||
|     window.isDirty = true |     isDirty = true | ||||||
|     updateView() |     updateView() | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -2178,18 +2166,18 @@ socket.on('doc', function (obj) { | |||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| socket.on('ack', function () { | socket.on('ack', function () { | ||||||
|   window.isDirty = true |   isDirty = true | ||||||
|   updateView() |   updateView() | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| socket.on('operation', function () { | socket.on('operation', function () { | ||||||
|   window.isDirty = true |   isDirty = true | ||||||
|   updateView() |   updateView() | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| socket.on('online users', function (data) { | socket.on('online users', function (data) { | ||||||
|   if (debug) { console.debug(data) } |   if (debug) { console.debug(data) } | ||||||
|   window.onlineUsers = data.users |   onlineUsers = data.users | ||||||
|   updateOnlineStatus() |   updateOnlineStatus() | ||||||
|   $('.CodeMirror-other-cursors').children().each(function (key, value) { |   $('.CodeMirror-other-cursors').children().each(function (key, value) { | ||||||
|     var found = false |     var found = false | ||||||
| @ -2205,14 +2193,14 @@ socket.on('online users', function (data) { | |||||||
|   }) |   }) | ||||||
|   for (var i = 0; i < data.users.length; i++) { |   for (var i = 0; i < data.users.length; i++) { | ||||||
|     var user = data.users[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) { | socket.on('user status', function (data) { | ||||||
|   if (debug) { console.debug(data) } |   if (debug) { console.debug(data) } | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === data.id) { |     if (onlineUsers[i].id === data.id) { | ||||||
|       window.onlineUsers[i] = data |       onlineUsers[i] = data | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   updateOnlineStatus() |   updateOnlineStatus() | ||||||
| @ -2220,9 +2208,9 @@ socket.on('user status', function (data) { | |||||||
| }) | }) | ||||||
| socket.on('cursor focus', function (data) { | socket.on('cursor focus', function (data) { | ||||||
|   if (debug) { console.debug(data) } |   if (debug) { console.debug(data) } | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === data.id) { |     if (onlineUsers[i].id === data.id) { | ||||||
|       window.onlineUsers[i].cursor = data.cursor |       onlineUsers[i].cursor = data.cursor | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (data.id !== socket.id) { buildCursor(data) } |   if (data.id !== socket.id) { buildCursor(data) } | ||||||
| @ -2234,18 +2222,18 @@ socket.on('cursor focus', function (data) { | |||||||
| }) | }) | ||||||
| socket.on('cursor activity', function (data) { | socket.on('cursor activity', function (data) { | ||||||
|   if (debug) { console.debug(data) } |   if (debug) { console.debug(data) } | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === data.id) { |     if (onlineUsers[i].id === data.id) { | ||||||
|       window.onlineUsers[i].cursor = data.cursor |       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) { | socket.on('cursor blur', function (data) { | ||||||
|   if (debug) { console.debug(data) } |   if (debug) { console.debug(data) } | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === data.id) { |     if (onlineUsers[i].id === data.id) { | ||||||
|       window.onlineUsers[i].cursor = null |       onlineUsers[i].cursor = null | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   if (data.id !== socket.id) { buildCursor(data) } |   if (data.id !== socket.id) { buildCursor(data) } | ||||||
| @ -2270,7 +2258,7 @@ var shortOnlineUserList = new List('short-online-user-list', options) | |||||||
| 
 | 
 | ||||||
| function updateOnlineStatus () { | function updateOnlineStatus () { | ||||||
|   if (!window.loaded || !socket.connected) return |   if (!window.loaded || !socket.connected) return | ||||||
|   var _onlineUsers = deduplicateOnlineUsers(window.onlineUsers) |   var _onlineUsers = deduplicateOnlineUsers(onlineUsers) | ||||||
|   showStatus(statusType.online, _onlineUsers.length) |   showStatus(statusType.online, _onlineUsers.length) | ||||||
|   var items = onlineUserList.items |   var items = onlineUserList.items | ||||||
|     // update or remove current list items
 |     // update or remove current list items
 | ||||||
| @ -2321,8 +2309,8 @@ function sortOnlineUserList (list) { | |||||||
|     sortFunction: function (a, b) { |     sortFunction: function (a, b) { | ||||||
|       var usera = a.values() |       var usera = a.values() | ||||||
|       var userb = b.values() |       var userb = b.values() | ||||||
|       var useraIsSelf = (usera.id === window.personalInfo.id || (usera.login && usera.userid === window.personalInfo.userid)) |       var useraIsSelf = (usera.id === personalInfo.id || (usera.login && usera.userid === personalInfo.userid)) | ||||||
|       var userbIsSelf = (userb.id === window.personalInfo.id || (userb.login && userb.userid === window.personalInfo.userid)) |       var userbIsSelf = (userb.id === personalInfo.id || (userb.login && userb.userid === personalInfo.userid)) | ||||||
|       if (useraIsSelf && !userbIsSelf) { |       if (useraIsSelf && !userbIsSelf) { | ||||||
|         return -1 |         return -1 | ||||||
|       } else if (!useraIsSelf && userbIsSelf) { |       } else if (!useraIsSelf && userbIsSelf) { | ||||||
| @ -2373,7 +2361,7 @@ function deduplicateOnlineUsers (list) { | |||||||
|       for (var j = 0; j < _onlineUsers.length; j++) { |       for (var j = 0; j < _onlineUsers.length; j++) { | ||||||
|         if (_onlineUsers[j].userid === user.userid) { |         if (_onlineUsers[j].userid === user.userid) { | ||||||
|           // keep self color when login
 |           // keep self color when login
 | ||||||
|           if (user.id === window.personalInfo.id) { |           if (user.id === personalInfo.id) { | ||||||
|             _onlineUsers[j].color = user.color |             _onlineUsers[j].color = user.color | ||||||
|           } |           } | ||||||
|           // keep idle state if any of self client not idle
 |           // keep idle state if any of self client not idle
 | ||||||
| @ -2396,14 +2384,14 @@ var userStatusCache = null | |||||||
| function emitUserStatus (force) { | function emitUserStatus (force) { | ||||||
|   if (!window.loaded) return |   if (!window.loaded) return | ||||||
|   var type = null |   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 |   personalInfo['idle'] = idle.isAway | ||||||
|   window.personalInfo['type'] = type |   personalInfo['type'] = type | ||||||
| 
 | 
 | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === window.personalInfo.id) { |     if (onlineUsers[i].id === personalInfo.id) { | ||||||
|       window.onlineUsers[i] = window.personalInfo |       onlineUsers[i] = personalInfo | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
| @ -2457,7 +2445,7 @@ function checkCursorTag (coord, ele) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function buildCursor (user) { | function buildCursor (user) { | ||||||
|   if (window.currentMode === modeType.view) return |   if (appState.currentMode === modeType.view) return | ||||||
|   if (!user.cursor) return |   if (!user.cursor) return | ||||||
|   var coord = editor.charCoords(user.cursor, 'windows') |   var coord = editor.charCoords(user.cursor, 'windows') | ||||||
|   coord.left = coord.left < 4 ? 4 : coord.left |   coord.left = coord.left < 4 ? 4 : coord.left | ||||||
| @ -2477,9 +2465,6 @@ function buildCursor (user) { | |||||||
|       iconClass = 'fa-desktop' |       iconClass = 'fa-desktop' | ||||||
|       break |       break | ||||||
|   } |   } | ||||||
|   if ($('.CodeMirror-other-cursors').length <= 0) { |  | ||||||
|     $("<div class='CodeMirror-other-cursors'>").insertAfter('.CodeMirror-cursors') |  | ||||||
|   } |  | ||||||
|   if ($('div[data-clientid="' + user.id + '"]').length <= 0) { |   if ($('div[data-clientid="' + user.id + '"]').length <= 0) { | ||||||
|     let cursor = $('<div data-clientid="' + user.id + '" class="CodeMirror-other-cursor" style="display:none;"></div>') |     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-line', user.cursor.line) | ||||||
| @ -2664,12 +2649,12 @@ editorInstance.on('changes', function (editor, changes) { | |||||||
|   } |   } | ||||||
| }) | }) | ||||||
| editorInstance.on('focus', function (editor) { | editorInstance.on('focus', function (editor) { | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === window.personalInfo.id) { |     if (onlineUsers[i].id === personalInfo.id) { | ||||||
|       window.onlineUsers[i].cursor = editor.getCursor() |       onlineUsers[i].cursor = editor.getCursor() | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   window.personalInfo['cursor'] = editor.getCursor() |   personalInfo['cursor'] = editor.getCursor() | ||||||
|   socket.emit('cursor focus', editor.getCursor()) |   socket.emit('cursor focus', editor.getCursor()) | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| @ -2677,12 +2662,12 @@ const cursorActivity = _.debounce(cursorActivityInner, cursorActivityDebounce) | |||||||
| 
 | 
 | ||||||
| function cursorActivityInner (editor) { | function cursorActivityInner (editor) { | ||||||
|   if (editorHasFocus() && !Visibility.hidden()) { |   if (editorHasFocus() && !Visibility.hidden()) { | ||||||
|     for (var i = 0; i < window.onlineUsers.length; i++) { |     for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|       if (window.onlineUsers[i].id === window.personalInfo.id) { |       if (onlineUsers[i].id === personalInfo.id) { | ||||||
|         window.onlineUsers[i].cursor = editor.getCursor() |         onlineUsers[i].cursor = editor.getCursor() | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     window.personalInfo['cursor'] = editor.getCursor() |     personalInfo['cursor'] = editor.getCursor() | ||||||
|     socket.emit('cursor activity', editor.getCursor()) |     socket.emit('cursor activity', editor.getCursor()) | ||||||
|   } |   } | ||||||
| } | } | ||||||
| @ -2724,12 +2709,12 @@ editorInstance.on('beforeSelectionChange', function (doc, selections) { | |||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| editorInstance.on('blur', function (cm) { | editorInstance.on('blur', function (cm) { | ||||||
|   for (var i = 0; i < window.onlineUsers.length; i++) { |   for (var i = 0; i < onlineUsers.length; i++) { | ||||||
|     if (window.onlineUsers[i].id === window.personalInfo.id) { |     if (onlineUsers[i].id === personalInfo.id) { | ||||||
|       window.onlineUsers[i].cursor = null |       onlineUsers[i].cursor = null | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   window.personalInfo['cursor'] = null |   personalInfo['cursor'] = null | ||||||
|   socket.emit('cursor blur') |   socket.emit('cursor blur') | ||||||
| }) | }) | ||||||
| 
 | 
 | ||||||
| @ -2737,71 +2722,71 @@ function saveInfo () { | |||||||
|   var scrollbarStyle = editor.getOption('scrollbarStyle') |   var scrollbarStyle = editor.getOption('scrollbarStyle') | ||||||
|   var left = $(window).scrollLeft() |   var left = $(window).scrollLeft() | ||||||
|   var top = $(window).scrollTop() |   var top = $(window).scrollTop() | ||||||
|   switch (window.currentMode) { |   switch (appState.currentMode) { | ||||||
|     case modeType.edit: |     case modeType.edit: | ||||||
|       if (scrollbarStyle === 'native') { |       if (scrollbarStyle === 'native') { | ||||||
|         window.lastInfo.edit.scroll.left = left |         lastInfo.edit.scroll.left = left | ||||||
|         window.lastInfo.edit.scroll.top = top |         lastInfo.edit.scroll.top = top | ||||||
|       } else { |       } else { | ||||||
|         window.lastInfo.edit.scroll = editor.getScrollInfo() |         lastInfo.edit.scroll = editor.getScrollInfo() | ||||||
|       } |       } | ||||||
|       break |       break | ||||||
|     case modeType.view: |     case modeType.view: | ||||||
|       window.lastInfo.view.scroll.left = left |       lastInfo.view.scroll.left = left | ||||||
|       window.lastInfo.view.scroll.top = top |       lastInfo.view.scroll.top = top | ||||||
|       break |       break | ||||||
|     case modeType.both: |     case modeType.both: | ||||||
|       window.lastInfo.edit.scroll = editor.getScrollInfo() |       lastInfo.edit.scroll = editor.getScrollInfo() | ||||||
|       window.lastInfo.view.scroll.left = ui.area.view.scrollLeft() |       lastInfo.view.scroll.left = ui.area.view.scrollLeft() | ||||||
|       window.lastInfo.view.scroll.top = ui.area.view.scrollTop() |       lastInfo.view.scroll.top = ui.area.view.scrollTop() | ||||||
|       break |       break | ||||||
|   } |   } | ||||||
|   window.lastInfo.edit.cursor = editor.getCursor() |   lastInfo.edit.cursor = editor.getCursor() | ||||||
|   window.lastInfo.edit.selections = editor.listSelections() |   lastInfo.edit.selections = editor.listSelections() | ||||||
|   window.lastInfo.needRestore = true |   lastInfo.needRestore = true | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| function restoreInfo () { | function restoreInfo () { | ||||||
|   var scrollbarStyle = editor.getOption('scrollbarStyle') |   var scrollbarStyle = editor.getOption('scrollbarStyle') | ||||||
|   if (window.lastInfo.needRestore) { |   if (lastInfo.needRestore) { | ||||||
|     var line = window.lastInfo.edit.cursor.line |     var line = lastInfo.edit.cursor.line | ||||||
|     var ch = window.lastInfo.edit.cursor.ch |     var ch = lastInfo.edit.cursor.ch | ||||||
|     editor.setCursor(line, ch) |     editor.setCursor(line, ch) | ||||||
|     editor.setSelections(window.lastInfo.edit.selections) |     editor.setSelections(lastInfo.edit.selections) | ||||||
|     switch (window.currentMode) { |     switch (appState.currentMode) { | ||||||
|       case modeType.edit: |       case modeType.edit: | ||||||
|         if (scrollbarStyle === 'native') { |         if (scrollbarStyle === 'native') { | ||||||
|           $(window).scrollLeft(window.lastInfo.edit.scroll.left) |           $(window).scrollLeft(lastInfo.edit.scroll.left) | ||||||
|           $(window).scrollTop(window.lastInfo.edit.scroll.top) |           $(window).scrollTop(lastInfo.edit.scroll.top) | ||||||
|         } else { |         } else { | ||||||
|           let left = window.lastInfo.edit.scroll.left |           let left = lastInfo.edit.scroll.left | ||||||
|           let top = window.lastInfo.edit.scroll.top |           let top = lastInfo.edit.scroll.top | ||||||
|           editor.scrollIntoView() |           editor.scrollIntoView() | ||||||
|           editor.scrollTo(left, top) |           editor.scrollTo(left, top) | ||||||
|         } |         } | ||||||
|         break |         break | ||||||
|       case modeType.view: |       case modeType.view: | ||||||
|         $(window).scrollLeft(window.lastInfo.view.scroll.left) |         $(window).scrollLeft(lastInfo.view.scroll.left) | ||||||
|         $(window).scrollTop(window.lastInfo.view.scroll.top) |         $(window).scrollTop(lastInfo.view.scroll.top) | ||||||
|         break |         break | ||||||
|       case modeType.both: |       case modeType.both: | ||||||
|         let left = window.lastInfo.edit.scroll.left |         let left = lastInfo.edit.scroll.left | ||||||
|         let top = window.lastInfo.edit.scroll.top |         let top = lastInfo.edit.scroll.top | ||||||
|         editor.scrollIntoView() |         editor.scrollIntoView() | ||||||
|         editor.scrollTo(left, top) |         editor.scrollTo(left, top) | ||||||
|         ui.area.view.scrollLeft(window.lastInfo.view.scroll.left) |         ui.area.view.scrollLeft(lastInfo.view.scroll.left) | ||||||
|         ui.area.view.scrollTop(window.lastInfo.view.scroll.top) |         ui.area.view.scrollTop(lastInfo.view.scroll.top) | ||||||
|         break |         break | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     window.lastInfo.needRestore = false |     lastInfo.needRestore = false | ||||||
|   } |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // view actions
 | // view actions
 | ||||||
| function refreshView () { | function refreshView () { | ||||||
|   ui.area.markdown.html('') |   ui.area.markdown.html('') | ||||||
|   window.isDirty = true |   isDirty = true | ||||||
|   updateViewInner() |   updateViewInner() | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -2813,7 +2798,7 @@ var lastResult = null | |||||||
| var postUpdateEvent = null | var postUpdateEvent = null | ||||||
| 
 | 
 | ||||||
| function updateViewInner () { | function updateViewInner () { | ||||||
|   if (window.currentMode === modeType.edit || !window.isDirty) return |   if (appState.currentMode === modeType.edit || !isDirty) return | ||||||
|   var value = editor.getValue() |   var value = editor.getValue() | ||||||
|   var lastMeta = md.meta |   var lastMeta = md.meta | ||||||
|   md.meta = {} |   md.meta = {} | ||||||
| @ -2830,13 +2815,13 @@ function updateViewInner () { | |||||||
|         // prevent XSS
 |         // prevent XSS
 | ||||||
|     ui.area.markdown.html(preventXSS(ui.area.markdown.html())) |     ui.area.markdown.html(preventXSS(ui.area.markdown.html())) | ||||||
|     ui.area.markdown.addClass('slides') |     ui.area.markdown.addClass('slides') | ||||||
|     window.syncscroll = false |     appState.syncscroll = false | ||||||
|     checkSyncToggle() |     checkSyncToggle() | ||||||
|   } else { |   } else { | ||||||
|     if (lastMeta.type && lastMeta.type === 'slide') { |     if (lastMeta.type && lastMeta.type === 'slide') { | ||||||
|       refreshView() |       refreshView() | ||||||
|       ui.area.markdown.removeClass('slides') |       ui.area.markdown.removeClass('slides') | ||||||
|       window.syncscroll = true |       appState.syncscroll = true | ||||||
|       checkSyncToggle() |       checkSyncToggle() | ||||||
|     } |     } | ||||||
|         // only render again when meta changed
 |         // only render again when meta changed
 | ||||||
| @ -2861,7 +2846,7 @@ function updateViewInner () { | |||||||
|   generateScrollspy() |   generateScrollspy() | ||||||
|   updateScrollspy() |   updateScrollspy() | ||||||
|   smoothHashScroll() |   smoothHashScroll() | ||||||
|   window.isDirty = false |   isDirty = false | ||||||
|   clearMap() |   clearMap() | ||||||
|     // buildMap();
 |     // buildMap();
 | ||||||
|   updateTitleReminder() |   updateTitleReminder() | ||||||
|  | |||||||
							
								
								
									
										8
									
								
								public/js/lib/appState.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								public/js/lib/appState.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,8 @@ | |||||||
|  | import modeType from './modeType' | ||||||
|  | 
 | ||||||
|  | let state = { | ||||||
|  |   syncscroll: true, | ||||||
|  |   currentMode: modeType.view | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | export default state | ||||||
| @ -1,5 +1,6 @@ | |||||||
| import * as utils from './utils' | import * as utils from './utils' | ||||||
| import config from './config' | import config from './config' | ||||||
|  | import statusBarTemplate from './statusbar.html' | ||||||
| 
 | 
 | ||||||
| /* config section */ | /* config section */ | ||||||
| const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault | const isMac = CodeMirror.keyMap.default === CodeMirror.keyMap.macDefault | ||||||
| @ -118,6 +119,7 @@ export default class Editor { | |||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     this.eventListeners = {} |     this.eventListeners = {} | ||||||
|  |     this.config = config | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   on (event, cb) { |   on (event, cb) { | ||||||
| @ -132,20 +134,8 @@ 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 () { |   addStatusBar () { | ||||||
|     if (!this.statusBarTemplate) { |     this.statusBar = $(statusBarTemplate) | ||||||
|       this.getStatusBarTemplate.then(this.addStatusBar) |  | ||||||
|     } else { |  | ||||||
|       this.statusBar = $(this.statusBarTemplate) |  | ||||||
|     this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column') |     this.statusCursor = this.statusBar.find('.status-cursor > .status-line-column') | ||||||
|     this.statusSelection = this.statusBar.find('.status-cursor > .status-selection') |     this.statusSelection = this.statusBar.find('.status-cursor > .status-selection') | ||||||
|     this.statusFile = this.statusBar.find('.status-file') |     this.statusFile = this.statusBar.find('.status-file') | ||||||
| @ -166,7 +156,6 @@ export default class Editor { | |||||||
|     this.setSpellcheck() |     this.setSpellcheck() | ||||||
|     this.setPreferences() |     this.setPreferences() | ||||||
|   } |   } | ||||||
|   } |  | ||||||
| 
 | 
 | ||||||
|   updateStatusBar () { |   updateStatusBar () { | ||||||
|     if (!this.statusBar) return |     if (!this.statusBar) return | ||||||
| @ -508,8 +497,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 :)" |       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 |     return this.editor | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										11
									
								
								public/js/lib/modeType.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								public/js/lib/modeType.js
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | |||||||
|  | export default { | ||||||
|  |   edit: { | ||||||
|  |     name: 'edit' | ||||||
|  |   }, | ||||||
|  |   view: { | ||||||
|  |     name: 'view' | ||||||
|  |   }, | ||||||
|  |   both: { | ||||||
|  |     name: 'both' | ||||||
|  |   } | ||||||
|  | } | ||||||
| @ -4,7 +4,9 @@ | |||||||
| 
 | 
 | ||||||
| import markdownitContainer from 'markdown-it-container' | import markdownitContainer from 'markdown-it-container' | ||||||
| 
 | 
 | ||||||
| import { md } from './extra' | import { md } from '../extra' | ||||||
|  | import modeType from './modeType' | ||||||
|  | import appState from './appState' | ||||||
| 
 | 
 | ||||||
| function addPart (tokens, idx) { | function addPart (tokens, idx) { | ||||||
|   if (tokens[idx].map && tokens[idx].level === 0) { |   if (tokens[idx].map && tokens[idx].level === 0) { | ||||||
| @ -109,9 +111,6 @@ md.use(markdownitContainer, 'info', { render: renderContainer }) | |||||||
| md.use(markdownitContainer, 'warning', { render: renderContainer }) | md.use(markdownitContainer, 'warning', { render: renderContainer }) | ||||||
| md.use(markdownitContainer, 'danger', { render: renderContainer }) | md.use(markdownitContainer, 'danger', { render: renderContainer }) | ||||||
| 
 | 
 | ||||||
| // FIXME: expose syncscroll to window
 |  | ||||||
| window.syncscroll = true |  | ||||||
| 
 |  | ||||||
| window.preventSyncScrollToEdit = false | window.preventSyncScrollToEdit = false | ||||||
| window.preventSyncScrollToView = false | window.preventSyncScrollToView = false | ||||||
| 
 | 
 | ||||||
| @ -126,10 +125,15 @@ let editArea = null | |||||||
| let viewArea = null | let viewArea = null | ||||||
| let markdownArea = null | let markdownArea = null | ||||||
| 
 | 
 | ||||||
| export function setupSyncAreas (edit, view, markdown) { | let editor | ||||||
|  | 
 | ||||||
|  | export function setupSyncAreas (edit, view, markdown, _editor) { | ||||||
|   editArea = edit |   editArea = edit | ||||||
|   viewArea = view |   viewArea = view | ||||||
|   markdownArea = markdown |   markdownArea = markdown | ||||||
|  | 
 | ||||||
|  |   editor = _editor | ||||||
|  | 
 | ||||||
|   editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle)) |   editArea.on('scroll', _.throttle(syncScrollToView, editScrollThrottle)) | ||||||
|   viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle)) |   viewArea.on('scroll', _.throttle(syncScrollToEdit, viewScrollThrottle)) | ||||||
| } | } | ||||||
| @ -161,8 +165,8 @@ function buildMapInner (callback) { | |||||||
|   viewBottom = viewArea[0].scrollHeight - viewArea.height() |   viewBottom = viewArea[0].scrollHeight - viewArea.height() | ||||||
| 
 | 
 | ||||||
|   acc = 0 |   acc = 0 | ||||||
|   const lines = window.editor.getValue().split('\n') |   const lines = editor.getValue().split('\n') | ||||||
|   const lineHeight = window.editor.defaultTextHeight() |   const lineHeight = editor.defaultTextHeight() | ||||||
|   for (i = 0; i < lines.length; i++) { |   for (i = 0; i < lines.length; i++) { | ||||||
|     const str = lines[i] |     const str = lines[i] | ||||||
| 
 | 
 | ||||||
| @ -173,7 +177,7 @@ function buildMapInner (callback) { | |||||||
|       continue |       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) |     acc += Math.round(h / lineHeight) | ||||||
|   } |   } | ||||||
|   _lineHeightMap.push(acc) |   _lineHeightMap.push(acc) | ||||||
| @ -228,7 +232,7 @@ function buildMapInner (callback) { | |||||||
| let viewScrollingTimer = null | let viewScrollingTimer = null | ||||||
| 
 | 
 | ||||||
| export function syncScrollToEdit (event, preventAnimate) { | export function syncScrollToEdit (event, preventAnimate) { | ||||||
|   if (window.currentMode !== window.modeType.both || !window.syncscroll || !editArea) return |   if (appState.currentMode !== modeType.both || !appState.syncscroll || !editArea) return | ||||||
|   if (window.preventSyncScrollToEdit) { |   if (window.preventSyncScrollToEdit) { | ||||||
|     if (typeof window.preventSyncScrollToEdit === 'number') { |     if (typeof window.preventSyncScrollToEdit === 'number') { | ||||||
|       window.preventSyncScrollToEdit-- |       window.preventSyncScrollToEdit-- | ||||||
| @ -268,8 +272,8 @@ export function syncScrollToEdit (event, preventAnimate) { | |||||||
|   let posTo = 0 |   let posTo = 0 | ||||||
|   let topDiffPercent = 0 |   let topDiffPercent = 0 | ||||||
|   let posToNextDiff = 0 |   let posToNextDiff = 0 | ||||||
|   const scrollInfo = window.editor.getScrollInfo() |   const scrollInfo = editor.getScrollInfo() | ||||||
|   const textHeight = window.editor.defaultTextHeight() |   const textHeight = editor.defaultTextHeight() | ||||||
|   const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight |   const preLastLineHeight = scrollInfo.height - scrollInfo.clientHeight - textHeight | ||||||
|   const preLastLineNo = Math.round(preLastLineHeight / textHeight) |   const preLastLineNo = Math.round(preLastLineHeight / textHeight) | ||||||
|   const preLastLinePos = scrollMap[preLastLineNo] |   const preLastLinePos = scrollMap[preLastLineNo] | ||||||
| @ -310,7 +314,7 @@ function viewScrollingTimeoutInner () { | |||||||
| let editScrollingTimer = null | let editScrollingTimer = null | ||||||
| 
 | 
 | ||||||
| export function syncScrollToView (event, preventAnimate) { | export function syncScrollToView (event, preventAnimate) { | ||||||
|   if (window.currentMode !== window.modeType.both || !window.syncscroll || !viewArea) return |   if (appState.currentMode !== modeType.both || !appState.syncscroll || !viewArea) return | ||||||
|   if (window.preventSyncScrollToView) { |   if (window.preventSyncScrollToView) { | ||||||
|     if (typeof preventSyncScrollToView === 'number') { |     if (typeof preventSyncScrollToView === 'number') { | ||||||
|       window.preventSyncScrollToView-- |       window.preventSyncScrollToView-- | ||||||
| @ -329,8 +333,8 @@ export function syncScrollToView (event, preventAnimate) { | |||||||
| 
 | 
 | ||||||
|   let lineNo, posTo |   let lineNo, posTo | ||||||
|   let topDiffPercent, posToNextDiff |   let topDiffPercent, posToNextDiff | ||||||
|   const scrollInfo = window.editor.getScrollInfo() |   const scrollInfo = editor.getScrollInfo() | ||||||
|   const textHeight = window.editor.defaultTextHeight() |   const textHeight = editor.defaultTextHeight() | ||||||
|   lineNo = Math.floor(scrollInfo.top / textHeight) |   lineNo = Math.floor(scrollInfo.top / textHeight) | ||||||
|     // if reach the last line, will start lerp to the bottom
 |     // if reach the last line, will start lerp to the bottom
 | ||||||
|   const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight) |   const diffToBottom = (scrollInfo.top + scrollInfo.clientHeight) - (scrollInfo.height - textHeight) | ||||||
| @ -412,6 +412,9 @@ module.exports = { | |||||||
|     }, { |     }, { | ||||||
|       test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, |       test: /\.eot(\?v=\d+\.\d+\.\d+)?$/, | ||||||
|       loader: 'file' |       loader: 'file' | ||||||
|  |     }, { | ||||||
|  |       test: /\.html$/, | ||||||
|  |       loader: 'string' | ||||||
|     }, { |     }, { | ||||||
|       test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, |       test: /\.(woff|woff2)(\?v=\d+\.\d+\.\d+)?$/, | ||||||
|       loader: 'url?prefix=font/&limit=5000' |       loader: 'url?prefix=font/&limit=5000' | ||||||
|  | |||||||
| @ -6529,6 +6529,10 @@ strict-uri-encode@^1.0.0: | |||||||
|   version "1.1.0" |   version "1.1.0" | ||||||
|   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" |   resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" | ||||||
| 
 | 
 | ||||||
|  | string-loader@^0.0.1: | ||||||
|  |   version "0.0.1" | ||||||
|  |   resolved "https://registry.yarnpkg.com/string-loader/-/string-loader-0.0.1.tgz#496f3cccc990213e0dd5411499f9ac6a6a6f2ff8" | ||||||
|  | 
 | ||||||
| string-natural-compare@^2.0.2: | string-natural-compare@^2.0.2: | ||||||
|   version "2.0.2" |   version "2.0.2" | ||||||
|   resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-2.0.2.tgz#c5ce4e278ab5d1265ae6fc55435aeb7b76fcb001" |   resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-2.0.2.tgz#c5ce4e278ab5d1265ae6fc55435aeb7b76fcb001" | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user