-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathcodemirror-composition-mod.js.coffee
More file actions
144 lines (105 loc) · 4.82 KB
/
codemirror-composition-mod.js.coffee
File metadata and controls
144 lines (105 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
###
# Composition Mod for CodeMirror
# v2.0.2
# Zhusee <zhusee2@gmail.com>
#
# Additional instance properties added to CodeMirror:
# - cm.display.inCompositionMode (Boolen)
# - cm.display.compositionHead (Pos)
# - cm.display.textMarkerInComposition (TextMarker)
###
modInitialized = false
TEXT_MARKER_CLASS_NAME = "CodeMirror-text-in-composition"
TEXT_MARKER_OPTIONS = {
inclusiveLeft: true,
inclusiveRight: true,
className: TEXT_MARKER_CLASS_NAME
}
PREFIX_LIST = ['webkit', 'moz', 'o']
capitalizeString = (string) ->
return string.charAt(0).toUpperCase() + string.slice(1)
getPrefixedPropertyName = (propertyName) ->
tempElem = document.createElement('div')
return propertyName if tempElem.style[propertyName]?
for prefix in PREFIX_LIST
prefixedPropertyName = prefix + capitalizeString(propertyName)
return prefixedPropertyName if tempElem.style[prefixedPropertyName]?
return false
CodeMirror.defineOption 'enableCompositionMod', false, (cm, newVal, oldVal) ->
if newVal and !modInitialized
if window.CompositionEvent?
initCompositionMode(cm)
else
console.warn("Your browser doesn't support CompositionEvent.")
cm.setOption('enableCompositionMod', false)
CodeMirror.defineOption 'debugCompositionMod', false, (cm, newVal, oldVal) ->
inputField = cm.display.input
return if !jQuery?
if newVal
$(inputField).on 'input.composition-debug keypress.composition-debug compositionupdate.composition-debug', (e) ->
console.log "[#{e.type}]", e.originalEvent.data, inputField.value, e.timeStamp
$(inputField).on 'compositionstart.composition-debug compositionend.composition-debug', (e) ->
console.warn "[#{e.type}]", e.originalEvent.data, inputField.value, cm.getCursor(), e.timeStamp
else
$(inputField).off('.composition-debug')
setInputTranslate = (cm, translateValue) ->
transformProperty = getPrefixedPropertyName("transform")
cm.display.input.style[transformProperty] = translateValue
resetInputTranslate = (cm) ->
setInputTranslate("")
clearCompositionTextMarkers = (cm)->
# Clear previous text markers
textMarkersArray = cm.getAllMarks()
for textMarker in textMarkersArray
if textMarker? and textMarker.className is TEXT_MARKER_CLASS_NAME
textMarker.clear()
console.log "[TextMarker] Cleared" if cm.options.debugCompositionMod
return true
initCompositionMode = (cm) ->
inputField = cm.display.input
inputWrapper = cm.display.inputDiv
inputWrapper.classList.add('CodeMirror-input-wrapper')
CodeMirror.on inputField, 'compositionstart', (event) ->
return if !cm.options.enableCompositionMod
cm.display.inCompositionMode = true
cm.setOption('readOnly', true)
cm.replaceSelection("") if cm.somethingSelected() # Clear the selected text first
cm.display.compositionHead = cm.getCursor()
console.log "[compositionstart] Update Composition Head", cm.display.compositionHead if cm.options.debugCompositionMod
inputField.value = ""
console.log "[compositionstart] Clear cm.display.input", cm.display.compositionHead if cm.options.debugCompositionMod
inputWrapper.classList.add('in-composition')
CodeMirror.on inputField, 'compositionupdate', (event) ->
return if !cm.options.enableCompositionMod
headPos = cm.display.compositionHead
if cm.display.textMarkerInComposition
markerRange = cm.display.textMarkerInComposition.find()
cm.replaceRange(event.data, headPos, markerRange.to)
cm.display.textMarkerInComposition.clear()
cm.display.textMarkerInComposition = undefined
else
cm.replaceRange(event.data, headPos, headPos)
endPos = cm.getCursor()
cm.display.textMarkerInComposition = cm.markText(headPos, endPos, TEXT_MARKER_OPTIONS)
pixelToTranslate = cm.charCoords(endPos).left - cm.charCoords(headPos).left
setInputTranslate(cm, "translateX(-#{pixelToTranslate}px)")
CodeMirror.on inputField, 'compositionend', (event) ->
return if !cm.options.enableCompositionMod
textLeftComposition = event.data
headPos = cm.display.compositionHead
endPos = cm.getCursor()
cm.replaceRange(textLeftComposition, headPos, endPos)
cm.display.inCompositionMode = false
cm.display.compositionHead = undefined
cm.display.textMarkerInComposition?.clear()
cm.display.textMarkerInComposition = undefined
cm.setOption('readOnly', false)
inputWrapper.classList.remove('in-composition')
clearCompositionTextMarkers(cm)
postCompositionEnd = ->
return false if cm.display.inCompositionMode
inputField.value = ""
console.warn "[postCompositionEnd] Input Cleared" if cm.options.debugCompositionMod
CodeMirror.off(inputField, 'input', postCompositionEnd)
console.log "[postCompositionEnd] Handler unregistered for future input events" if cm.options.debugCompositionMod
CodeMirror.on(inputField, 'input', postCompositionEnd)