Skip to content

Commit 379a731

Browse files
authored
Merge pull request #1534 from mathjax/fix/menu-sliders
Fix problem with sliders and add keyboard controls.
2 parents 6c2be35 + 7b052ae commit 379a731

3 files changed

Lines changed: 113 additions & 2 deletions

File tree

ts/ui/menu/Menu.ts

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { SVG } from '../../output/svg.js';
4343
import * as AnnotationMenu from './AnnotationMenu.js';
4444
import { MJContextMenu } from './MJContextMenu.js';
4545
import { RadioCompare } from './RadioCompare.js';
46+
import { mjSlider } from './Slider.js';
4647
import { MmlVisitor } from './MmlVisitor.js';
4748
import { MenuMathDocument } from './MenuHandler.js';
4849
import * as MenuUtil from './MenuUtil.js';
@@ -586,6 +587,7 @@ export class Menu {
586587
const parser = new Parser([
587588
['contextMenu', MJContextMenu.fromJson.bind(MJContextMenu)],
588589
['radioCompare', RadioCompare.fromJson.bind(RadioCompare)],
590+
['slider', mjSlider.fromJson.bind(mjSlider)],
589591
]);
590592
this.menu = parser.parse({
591593
type: 'contextMenu',
@@ -810,7 +812,7 @@ export class Menu {
810812
'Black',
811813
])
812814
),
813-
{ type: 'slider', variable: 'backgroundOpacity', content: ' ' },
815+
this.slider('backgroundOpacity'),
814816
this.submenu(
815817
'Highlight/Foreground',
816818
this.radioGroup('foregroundColor', 'Highlight', [
@@ -824,7 +826,7 @@ export class Menu {
824826
'Blue',
825827
])
826828
),
827-
{ type: 'slider', variable: 'foregroundOpacity', content: ' ' },
829+
this.slider('foregroundOpacity'),
828830
this.rule(),
829831
this.radioGroup('highlight', 'Highlight', [
830832
'None',
@@ -2038,5 +2040,15 @@ export class Menu {
20382040
return { type: 'rule' };
20392041
}
20402042

2043+
/**
2044+
* Create JSON for a slider
2045+
*
2046+
* @param {string} variable The (pool) variable to attach to this slider
2047+
* @returns {object} The JSON for the slider item
2048+
*/
2049+
public slider(variable: string): object {
2050+
return {type: 'slider', variable, content: ' '};
2051+
}
2052+
20412053
/*======================================================================*/
20422054
}

ts/ui/menu/Slider.ts

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
/*************************************************************
2+
*
3+
* Copyright (c) 2022-2026 The MathJax Consortium
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
/**
19+
* @file Implements a radio button with customizable comparator.
20+
*
21+
* @author dpvc@mathjax.org (Davide Cervone)
22+
*/
23+
24+
import {Slider} from './mj-context-menu.js';
25+
26+
//
27+
// Fix slider actions (FIXME: remove when mj-context-menu is merged into MathJax-src repo)
28+
//
29+
export class mjSlider extends Slider {
30+
/**
31+
* @override
32+
*/
33+
focus() {
34+
super.focus();
35+
this.html.focus(); // needed since super.focus uses setTimout for this
36+
(this as any).input.focus();
37+
}
38+
39+
/**
40+
* @override
41+
*/
42+
mouseup(event: MouseEvent) {
43+
super.mouseup(event);
44+
this.stop(event); // needs to prevent default action
45+
}
46+
47+
/**
48+
* @override
49+
*/
50+
keydown(event: KeyboardEvent) {
51+
let value = parseInt(((this as any).input as HTMLInputElement).value);
52+
switch (event.key) {
53+
case 'ArrowLeft':
54+
case 'ArrowDown':
55+
if (!event.shiftKey) {
56+
super.keydown(event);
57+
return;
58+
}
59+
/* @eslint-ignore: no-fallthrough */
60+
case '-':
61+
value = Math.max(0, value - (event.ctrlKey ? 5 : 1));
62+
break;
63+
64+
case 'ArrowRight':
65+
case 'ArrowUp':
66+
if (!event.shiftKey) {
67+
super.keydown(event);
68+
return;
69+
}
70+
/* @eslint-ignore: no-fallthrough */
71+
case '+':
72+
value = Math.min(100, value + (event.ctrlKey ? 5 : 1));
73+
break
74+
75+
case 'PageDown':
76+
value = Math.max(0, value - 5);
77+
break;
78+
79+
case 'PageUp':
80+
value= Math.max(0, value + 5);
81+
break;
82+
83+
case 'Home':
84+
value = 0;
85+
break;
86+
87+
case 'End':
88+
value = 100;
89+
break;
90+
91+
default:
92+
super.keydown(event);
93+
return;
94+
}
95+
this.variable.setValue(String(value));
96+
this.stop(event);
97+
}
98+
}

ts/ui/menu/mj-context-menu.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export { SubMenu } from '#menu/sub_menu.js';
2727
export { Submenu } from '#menu/item_submenu.js';
2828
export { Radio } from '#menu/item_radio.js';
2929
export { Rule } from '#menu/item_rule.js';
30+
export { Slider } from '#menu/item_slider.js';
3031
export { ParserFactory } from '#menu/parser_factory.js';
3132
export { Parser } from '#menu/parse.js';
3233
export * as CssStyles from '#menu/css_util.js';

0 commit comments

Comments
 (0)