Skip to content

Commit 8567558

Browse files
committed
fix: Remove backwards compatibility for missing input events
The logic causes issues as it loses the first change event.
1 parent ca44307 commit 8567558

File tree

2 files changed

+36
-82
lines changed

2 files changed

+36
-82
lines changed

spec/dispatcher.spec.js

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {Editable} from '../src/core.js'
77
import Selection from '../src/selection.js'
88
const {key} = Keyboard
99

10-
describe('Dispatcher', function () {
10+
describe('Dispatcher:', function () {
1111
let editable, elem
1212

1313
// create a Cursor object and set the selection to it
@@ -55,7 +55,7 @@ describe('Dispatcher', function () {
5555
return obj
5656
}
5757

58-
describe('for editable', function () {
58+
describe('for editable:', function () {
5959

6060
beforeEach(function () {
6161
elem = document.createElement('div')
@@ -71,7 +71,7 @@ describe('Dispatcher', function () {
7171
editable.unload()
7272
})
7373

74-
describe('on focus', function () {
74+
describe('on focus:', function () {
7575
it('should trigger the focus event', function () {
7676
elem.blur()
7777
const focus = on('focus', function (element) {
@@ -103,7 +103,7 @@ describe('Dispatcher', function () {
103103
})
104104
})
105105

106-
describe('on enter', function () {
106+
describe('on enter:', function () {
107107

108108
it('fires insert "after" if cursor is at the end', function () {
109109
// <div>foo\</div>
@@ -162,7 +162,7 @@ describe('Dispatcher', function () {
162162
})
163163
})
164164

165-
describe('on backspace', function () {
165+
describe('on backspace:', function () {
166166

167167
it('fires "merge" if cursor is at the beginning', function (done) {
168168
elem.innerHTML = 'foo'
@@ -175,21 +175,9 @@ describe('Dispatcher', function () {
175175

176176
elem.dispatchEvent(new KeyboardEvent('keydown', {keyCode: key.backspace}))
177177
})
178-
179-
it('fires "change" if cursor is not at the beginning', (done) => {
180-
elem.innerHTML = 'foo'
181-
createCursor(createRangeAtEnd(elem))
182-
183-
on('change', (element) => {
184-
expect(element).to.equal(elem)
185-
done()
186-
})
187-
188-
elem.dispatchEvent(new KeyboardEvent('keydown', {keyCode: key.backspace}))
189-
})
190178
})
191179

192-
describe('on delete', function () {
180+
describe('on delete:', function () {
193181

194182
it('fires "merge" if cursor is at the end', (done) => {
195183
elem.innerHTML = 'foo'
@@ -202,25 +190,9 @@ describe('Dispatcher', function () {
202190

203191
elem.dispatchEvent(new KeyboardEvent('keydown', {keyCode: key.delete}))
204192
})
205-
206-
it('fires "change" if cursor is at the beginning', (done) => {
207-
elem.innerHTML = 'foo'
208-
createCursor(createRangeAtBeginning(elem))
209-
on('change', () => done())
210-
elem.dispatchEvent(new KeyboardEvent('keydown', {keyCode: key.delete}))
211-
})
212193
})
213194

214-
describe('on keydown', function () {
215-
216-
it('fires change when a character is pressed', (done) => {
217-
const evt = new KeyboardEvent('keydown', {keyCode: 'e'.charCodeAt(0)})
218-
on('change', () => done())
219-
elem.dispatchEvent(evt)
220-
})
221-
})
222-
223-
describe('on newline', function () {
195+
describe('on newline:', function () {
224196

225197
function typeKeys (element, chars) {
226198
const selection = window.getSelection()
@@ -245,25 +217,28 @@ describe('Dispatcher', function () {
245217
expect(elem.innerHTML).to.equal('<br>\uFEFF')
246218
})
247219

248-
it('appends a zero-width space after the br tag to force a line break', () => {
220+
it('appends a zero-width space after the br tag to force a line break', async () => {
249221
typeKeys(elem, 'foobar')
250222
shiftReturn(elem)
223+
elem.addEventListener('input', function (e) { console.log('input event', e) })
224+
await 1
251225
expect(elem.innerHTML).to.equal(
252226
`\uFEFFfoobar<br>\uFEFF`
253227
)
254228
})
255229

256-
it('does not append another zero-width space when one is present already', () => {
230+
it('does not append another zero-width space when one is present already', async () => {
257231
typeKeys(elem, 'foobar')
258232
shiftReturn(elem)
259233
shiftReturn(elem)
234+
await 1
260235
expect(elem.innerHTML).to.equal(
261236
`\uFEFFfoobar<br><br>\uFEFF`
262237
)
263238
})
264239
})
265240

266-
describe('on bold', function () {
241+
describe('on bold:', function () {
267242

268243
it('fires toggleBold when ctrl + b is pressed', (done) => {
269244
elem.innerHTML = 'foo'
@@ -280,7 +255,7 @@ describe('Dispatcher', function () {
280255
})
281256
})
282257

283-
describe('on italic', function () {
258+
describe('on italic:', function () {
284259

285260
it('fires toggleEmphasis when ctrl + i is pressed', (done) => {
286261
elem.innerHTML = 'foo'
@@ -297,7 +272,7 @@ describe('Dispatcher', function () {
297272
})
298273
})
299274

300-
describe('selectToBoundary event:', function () {
275+
describe('selectToBoundary event::', function () {
301276

302277
it('fires "both" if all is selected', function () {
303278
elem.innerHTML = 'People Make The World Go Round'
@@ -353,7 +328,7 @@ describe('Dispatcher', function () {
353328
})
354329
})
355330

356-
describe('on paste', function () {
331+
describe('on paste:', function () {
357332

358333
it('inserts plain text clipboard content', (done) => {
359334
on('paste', (block, blocks) => {
@@ -408,5 +383,19 @@ describe('Dispatcher', function () {
408383
elem.dispatchEvent(evt)
409384
})
410385
})
386+
387+
describe('input event:', function () {
388+
it('fires "change" event', (done) => {
389+
elem.innerHTML = 'foo'
390+
createCursor(createRangeAtEnd(elem))
391+
392+
on('change', (element) => {
393+
expect(element).to.equal(elem)
394+
done()
395+
})
396+
397+
elem.dispatchEvent(new Event('input', {bubbles: true}))
398+
})
399+
})
411400
})
412401
})

src/dispatcher.js

Lines changed: 6 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,6 @@ import Keyboard from './keyboard.js'
77
import {closest} from './util/dom.js'
88
import {replaceLast, endsWithSingleSpace} from './util/string.js'
99

10-
// This will be set to true once we detect the input event is working.
11-
// Input event description on MDN:
12-
// https://developer.mozilla.org/en-US/docs/Web/Reference/Events/input
13-
let isInputEventSupported = false
14-
1510
/**
1611
* The Dispatcher module is responsible for dealing with events and their handlers.
1712
*
@@ -23,7 +18,6 @@ export default class Dispatcher {
2318
constructor (editable) {
2419
const win = editable.win
2520
eventable(this, editable)
26-
this.supportsInputEvent = false
2721
this.document = win.document
2822
this.config = editable.config
2923
this.editable = editable
@@ -122,7 +116,6 @@ export default class Dispatcher {
122116
const selection = this.selectionWatcher.getFreshSelection()
123117
if (selection && selection.isSelection) {
124118
this.notify('clipboard', block, 'cut', selection)
125-
this.triggerChangeEvent(block)
126119
}
127120
})
128121
.setupDocumentListener('paste', function pasteListener (evt) {
@@ -151,14 +144,7 @@ export default class Dispatcher {
151144
.setupDocumentListener('input', function inputListener (evt) {
152145
const block = this.getEditableBlockByEvent(evt)
153146
if (!block) return
154-
if (isInputEventSupported) {
155-
this.notify('change', block)
156-
} else {
157-
// Most likely the event was already handled manually by
158-
// triggerChangeEvent so the first time we just switch the
159-
// isInputEventSupported flag without notifying the change event.
160-
isInputEventSupported = true
161-
}
147+
this.notify('change', block)
162148
})
163149

164150
.setupDocumentListener('formatEditable', function formatEditableListener (evt) {
@@ -168,26 +154,6 @@ export default class Dispatcher {
168154
})
169155
}
170156

171-
/**
172-
* Trigger a change event
173-
*
174-
* This should be done in these cases:
175-
* - typing a letter
176-
* - delete (backspace and delete keys)
177-
* - cut
178-
* - paste
179-
* - copy and paste (not easily possible manually as far as I know)
180-
*
181-
* Preferably this is done using the input event. But the input event is not
182-
* supported on all browsers for contenteditable elements.
183-
* To make things worse it is not detectable either. So instead of detecting
184-
* we set 'isInputEventSupported' when the input event fires the first time.
185-
*/
186-
triggerChangeEvent (target) {
187-
if (isInputEventSupported) return
188-
this.notify('change', target)
189-
}
190-
191157
dispatchSwitchEvent (event, element, direction) {
192158
if (event.altKey || event.ctrlKey || event.metaKey || event.shiftKey) return
193159
const cursor = this.selectionWatcher.getFreshSelection()
@@ -228,8 +194,7 @@ export default class Dispatcher {
228194
this.setupDocumentListener('keydown', function (evt) {
229195
const block = this.getEditableBlockByEvent(evt)
230196
if (!block) return
231-
const notifyCharacterEvent = !isInputEventSupported
232-
this.keyboard.dispatchKeyEvent(evt, block, notifyCharacterEvent)
197+
this.keyboard.dispatchKeyEvent(evt, block, false)
233198
}, true)
234199
}
235200

@@ -253,10 +218,10 @@ export default class Dispatcher {
253218

254219
.on('backspace', function (event) {
255220
const rangeContainer = self.selectionWatcher.getFreshRange()
256-
if (!rangeContainer.isCursor) return self.triggerChangeEvent(this)
221+
if (!rangeContainer.isCursor) return
257222

258223
const cursor = rangeContainer.getCursor()
259-
if (!cursor.isAtBeginning()) return self.triggerChangeEvent(this)
224+
if (!cursor.isAtBeginning()) return
260225

261226
event.preventDefault()
262227
event.stopPropagation()
@@ -265,10 +230,10 @@ export default class Dispatcher {
265230

266231
.on('delete', function (event) {
267232
const rangeContainer = self.selectionWatcher.getFreshRange()
268-
if (!rangeContainer.isCursor) return self.triggerChangeEvent(this)
233+
if (!rangeContainer.isCursor) return
269234

270235
const cursor = rangeContainer.getCursor()
271-
if (!cursor.isAtTextEnd()) return self.triggerChangeEvent(this)
236+
if (!cursor.isAtTextEnd()) return
272237

273238
event.preventDefault()
274239
event.stopPropagation()

0 commit comments

Comments
 (0)