Skip to content

Commit 6e75e94

Browse files
Support language independent keyboard shortcuts (T1027453) (#30)
1 parent a20c2c3 commit 6e75e94

File tree

4 files changed

+100
-10
lines changed

4 files changed

+100
-10
lines changed

modules/keyboard.js

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,12 @@ class Keyboard extends Module {
178178
if (typeof handler === 'function') {
179179
handler = { handler };
180180
}
181-
const keys = Array.isArray(binding.key) ? binding.key : [binding.key];
181+
182+
const keyPropery = binding.which ? 'which' : 'key';
183+
const keys = Array.isArray(binding[keyPropery])
184+
? binding[keyPropery]
185+
: [binding[keyPropery]];
186+
182187
keys.forEach(key => {
183188
const singleBinding = {
184189
...binding,
@@ -225,7 +230,10 @@ class Keyboard extends Module {
225230
suffix: suffixText,
226231
event: evt,
227232
};
228-
const prevented = matches.some(binding => {
233+
234+
let prevented = false;
235+
236+
matches.some(binding => {
229237
if (
230238
binding.collapsed != null &&
231239
binding.collapsed !== curContext.collapsed
@@ -263,8 +271,20 @@ class Keyboard extends Module {
263271
if (binding.suffix != null && !binding.suffix.test(curContext.suffix)) {
264272
return false;
265273
}
266-
return binding.handler.call(this, range, curContext, binding) !== true;
274+
275+
const handlerResult = binding.handler.call(
276+
this,
277+
range,
278+
curContext,
279+
binding,
280+
);
281+
const preventAfterAllMatches = handlerResult?.preventAfterAllMatches;
282+
283+
prevented = handlerResult !== true || preventAfterAllMatches;
284+
285+
return prevented && !preventAfterAllMatches;
267286
});
287+
268288
if (prevented) {
269289
evt.preventDefault();
270290
}
@@ -375,9 +395,9 @@ class Keyboard extends Module {
375395

376396
Keyboard.DEFAULTS = {
377397
bindings: {
378-
bold: makeFormatHandler('bold'),
379-
italic: makeFormatHandler('italic'),
380-
underline: makeFormatHandler('underline'),
398+
bold: makeFormatHandler('bold', 66),
399+
italic: makeFormatHandler('italic', 73),
400+
underline: makeFormatHandler('underline', 85),
381401
indent: {
382402
// highlight tab or tab at beginning of list, indent or blockquote
383403
key: 'tab',
@@ -665,12 +685,14 @@ function makeEmbedArrowHandler(key, shiftKey) {
665685
};
666686
}
667687

668-
function makeFormatHandler(format) {
688+
function makeFormatHandler(format, which) {
669689
return {
670690
key: format[0],
691+
which,
671692
shortKey: true,
672693
handler(range, context) {
673694
this.quill.format(format, !context.format[format], Quill.sources.USER);
695+
return { preventAfterAllMatches: true };
674696
},
675697
};
676698
}

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "devextreme-quill",
3-
"version": "1.5.10",
3+
"version": "1.5.11",
44
"description": "Core of the DevExtreme HtmlEditor",
55
"author": "Developer Express Inc.",
66
"main": "dist/dx-quill.js",

test/unit/modules/keyboard.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,4 +189,72 @@ describe('Keyboard', function() {
189189
});
190190
});
191191
});
192+
193+
describe('bindings', function() {
194+
it('which modifier', function() {
195+
const quillMock = {
196+
root: document.createElement('div'),
197+
once: (eventName, handler) => {
198+
handler();
199+
},
200+
hasFocus: () => true,
201+
getSelection: () => {
202+
return { index: 0, length: 0 };
203+
},
204+
getFormat: () => {
205+
return {};
206+
},
207+
getLine: () => {
208+
return [{ length: () => 0 }, 0];
209+
},
210+
getLeaf: () => {
211+
return [0, 0];
212+
},
213+
};
214+
const fakeEvent = {
215+
key: 'b',
216+
which: 66,
217+
code: 'KeyB',
218+
shiftKey: false,
219+
metaKey: false,
220+
ctrlKey: true,
221+
altKey: false,
222+
};
223+
let counter = 0;
224+
225+
const nativeAddEventListener = quillMock.root.addEventListener;
226+
227+
quillMock.root.addEventListener = function(type, handler) {
228+
const modifiedHandler = () => {
229+
handler(fakeEvent);
230+
};
231+
232+
nativeAddEventListener.call(this, type, modifiedHandler);
233+
};
234+
235+
// eslint-disable-next-line no-new
236+
new Keyboard(quillMock, {
237+
bindings: {
238+
66: {
239+
key: 'b',
240+
which: 66,
241+
ctrlKey: true,
242+
handler() {
243+
counter += 1;
244+
},
245+
},
246+
},
247+
});
248+
249+
const keydownEvent = new KeyboardEvent('keydown', {
250+
key: 'n',
251+
});
252+
253+
quillMock.root.dispatchEvent(keydownEvent);
254+
255+
expect(counter).toBe(1);
256+
257+
quillMock.root.addEventListener = nativeAddEventListener;
258+
});
259+
});
192260
});

0 commit comments

Comments
 (0)