Handle contextmenu for spelling

This commit is contained in:
Alasdair Smith 2018-05-03 17:28:36 +01:00
parent abcc2cc11b
commit e6ffaaa489
3 changed files with 91 additions and 8 deletions

View file

@ -20,6 +20,7 @@ define [
EditSession = ace.require('ace/edit_session').EditSession
ModeList = ace.require('ace/ext/modelist')
Vim = ace.require('ace/keyboard/vim').Vim
Range = ace.require('ace/range').Range
# set the path for ace workers if using a CDN (from editor.pug)
if window.aceWorkerPath != ""
@ -363,18 +364,22 @@ define [
session.setScrollTop(session.getScrollTop() + 1)
session.setScrollTop(session.getScrollTop() - 1)
onSessionChange = (e) ->
onSessionChangeForSpellCheck = (e) ->
spellCheckManager.onSessionChange()
e.oldSession?.getDocument().off "change", spellCheckManager.onChange
e.session.getDocument().on "change", spellCheckManager.onChange
e.oldSession?.off "changeScrollTop", spellCheckManager.onScroll
e.session.on "changeScrollTop", spellCheckManager.onScroll
attachToSpellCheck = () ->
initSpellCheck = () ->
spellCheckManager.init()
editor.on 'changeSession', onSessionChange
onSessionChange({ session: editor.getSession() }) # Force initial setup
editor.on 'changeSession', onSessionChangeForSpellCheck
onSessionChangeForSpellCheck({ session: editor.getSession() }) # Force initial setup
editor.on 'nativecontextmenu', spellCheckManager.onContextMenu
detachFromSpellCheck = () ->
editor.off 'changeSession', onSessionChange
tearDownSpellCheck = () ->
editor.off 'changeSession', onSessionChangeForSpellCheck
editor.off 'nativecontextmenu', spellCheckManager.onContextMenu
attachToAce = (sharejs_doc) ->
lines = sharejs_doc.getSnapshot().split("\n")
@ -421,7 +426,7 @@ define [
editor.initing = false
# now ready to edit document
editor.setReadOnly(scope.readOnly) # respect the readOnly setting, normally false
attachToSpellCheck()
initSpellCheck()
resetScrollMargins()
@ -483,7 +488,7 @@ define [
scope.$on '$destroy', () ->
if scope.sharejsDoc?
detachFromSpellCheck()
tearDownSpellCheck()
detachFromAce(scope.sharejsDoc)
session = editor.getSession()
session?.destroy()
@ -608,3 +613,24 @@ define [
@wordManager = new HighlightedWordManager(@editor)
getLines: () -> @editor.getValue().split('\n')
normalizeChangeEvent: (e) -> e
getCoordsFromContextMenuEvent: (e) ->
e.domEvent.stopPropagation()
return {
x: e.domEvent.clientX,
y: e.domEvent.clientY
}
preventContextMenuEventDefault: (e) ->
e.domEvent.preventDefault()
getHighlightFromCoords: (coords) ->
position = @editor.renderer.screenToTextCoordinates(coords.x, coords.y)
@wordManager.findHighlightWithinRange({
start: position
end: position
})
selectHighlightedWord: (highlight) ->
@editor.getSession().getSelection().setSelectionRange(
new Range(
highlight.row, highlight.column,
highlight.row, highlight.column + highlight.word.length
)
)

View file

@ -51,3 +51,20 @@ define [
row = @highlights.rows[row]
for highlight in (row || []).slice()
@removeHighlight highlight
findHighlightWithinRange: (range) ->
rows = @highlights.rows.slice(range.start.row, range.end.row + 1)
for row in rows
for highlight in (row || [])
if @_doesHighlightOverlapRange(highlight, range.start, range.end)
return highlight
return null
_doesHighlightOverlapRange: (highlight, start, end) ->
highlightIsAllBeforeRange =
highlight.row < start.row or
(highlight.row == start.row and highlight.column + highlight.word.length <= start.column)
highlightIsAllAfterRange =
highlight.row > end.row or
(highlight.row == end.row and highlight.column >= end.column)
!(highlightIsAllBeforeRange or highlightIsAllAfterRange)

View file

@ -1,6 +1,12 @@
define [], () ->
class SpellCheckManager
constructor: (@$scope, @cache, @$http, @$q, @adapter) ->
@$scope.spellMenu = {
open: false
top: '0px'
left: '0px'
suggestions: []
}
@inProgressRequest = null
@updatedLines = []
@ -30,6 +36,40 @@ define [], () ->
@runSpellCheckSoon(200) if @isSpellCheckEnabled()
onContextMenu: (e) =>
@closeContextMenu()
@openContextMenu(e)
onScroll: () => @closeContextMenu()
openContextMenu: (e) ->
coords = @adapter.getCoordsFromContextMenuEvent(e)
highlight = @adapter.getHighlightFromCoords(coords)
if highlight
@adapter.preventContextMenuEventDefault(e)
@adapter.selectHighlightedWord(highlight)
@$scope.$apply () =>
@$scope.spellMenu = {
open: true
top: coords.y + 'px'
left: coords.x + 'px'
suggestions: highlight.suggestions
}
@setUpClickOffContextMenuListener()
return false
setUpClickOffContextMenuListener: () ->
$(document).one 'click', (e) =>
@closeContextMenu() if e.which != 3 # Ignore if right click
return true
closeContextMenu: () ->
# This is triggered on scroll, so for performance only apply setting when
# it changes
if @$scope?.spellMenu and @$scope.spellMenu.open != false
@$scope.$apply () =>
@$scope.spellMenu.open = false
runFullCheck: () ->
@adapter.wordManager.reset()
@runSpellCheck() if @isSpellCheckEnabled()