Skip to content

Commit 3130a45

Browse files
authored
Merge pull request #20 from zorkow/slider_widget
Slider widget
2 parents 21c3b8e + 9a6baed commit 3130a45

File tree

9 files changed

+271
-7
lines changed

9 files changed

+271
-7
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mj-context-menu",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "A generic context menu",
55
"main": "dist/ContextMenu.js",
66
"scripts": {

samples/mathjax2_test.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,6 @@ <h1 id="header">MathJax 2 with context menu</h1>
7474
<hr>
7575
<address></address>
7676
<!-- hhmts start -->
77-
Last modified: Wed May 20 11:53:28 BST 2020
77+
Last modified: Thu May 21 10:53:54 BST 2020
7878
<!-- hhmts end -->
7979
</body> </html>

samples/mathjaxmenu.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,8 @@ MathJax.Hub.Register.StartupHook("MathEvents Ready", function () {
133133

134134
var MENU = {};
135135
var SETTINGS = MathJax.Hub.config.menuSettings;
136+
MathJax.testCombo = 'hello';
137+
MathJax.testSlider = 50;
136138
MENU.id = function(value) { };
137139
MENU.About = function() {
138140
about.post(0, 0);
@@ -230,6 +232,18 @@ MathJax.Hub.Register.StartupHook("MathEvents Ready", function () {
230232
// always get "Auto".
231233
MathJax.Menu.Font();
232234
};
235+
MENU.getCombo = function() {
236+
return MathJax.testCombo;
237+
};
238+
MENU.setCombo = function(value) {
239+
MathJax.testCombo = value;
240+
};
241+
MENU.getSlider = function() {
242+
return MathJax.testSlider;
243+
};
244+
MENU.setSlider = function(value) {
245+
MathJax.testSlider = value;
246+
};
233247

234248
var cm_json =
235249
{"menu":
@@ -293,6 +307,14 @@ MathJax.Hub.Register.StartupHook("MathEvents Ready", function () {
293307
{ "name": "font",
294308
"getter": MENU.getFont,
295309
"setter": MENU.setFont
310+
},
311+
{ "name": "comboTest",
312+
"getter": MENU.getCombo,
313+
"setter": MENU.setCombo
314+
},
315+
{ "name": "sliderTest",
316+
"getter": MENU.getSlider,
317+
"setter": MENU.setSlider
296318
}
297319
],
298320
"items":
@@ -574,6 +596,10 @@ MathJax.Hub.Register.StartupHook("MathEvents Ready", function () {
574596
}
575597
},
576598
{"type": "rule"},
599+
{"type": "slider",
600+
"variable": "sliderTest",
601+
"content": "Slider: "
602+
},
577603
{"type": "command",
578604
"id": "About",
579605
"content": "About MathJax",
@@ -583,7 +609,12 @@ MathJax.Hub.Register.StartupHook("MathEvents Ready", function () {
583609
"id": "Help",
584610
"content": "MathJax Help",
585611
"action": MENU.Help
612+
},
613+
{"type": "combo",
614+
"variable": "comboTest",
615+
"content": "Combo: "
586616
}
617+
587618
]
588619
}
589620
};

ts/css_util.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ export namespace CssStyles {
125125
MENU_STYLES[makeClass_('MENUCOMBOBOX')] = '{' +
126126
' left:.1em; padding-bottom:.5em;' +
127127
'}',
128+
MENU_STYLES[makeClass_('MENUSLIDER')] = '{' +
129+
' left: .1em;' +
130+
'}',
131+
MENU_STYLES[makeClass_('SLIDERVALUE')] = '{' +
132+
' position:absolute; right:.1em; padding-top:.25em; color:#333333;' +
133+
' font-size: .75em' +
134+
'}',
135+
MENU_STYLES[makeClass_('SLIDERBAR')] = '{' +
136+
' outline: none; background: #d3d3d3' +
137+
'}',
128138
MENU_STYLES[makeClass_('MENULABEL')] = '{' +
129139
' padding: 1px 2em 3px 1.33em;' +
130140
' font-style:italic' +

ts/html_classes.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,13 +77,16 @@ export const HtmlClasses: {[id: string]: HtmlClass} = {
7777
MENURADIOCHECK: prefixClass_('MenuRadioCheck'),
7878
MENUINPUTBOX: prefixClass_('MenuInputBox'),
7979
MENURULE: prefixClass_('MenuRule'),
80+
MENUSLIDER: prefixClass_('MenuSlider'),
8081
MOUSEPOST: prefixClass_('MousePost'),
8182
RTL: prefixClass_('RTL'),
8283
INFO: prefixClass_('Info'),
8384
INFOCLOSE: prefixClass_('InfoClose'),
8485
INFOCONTENT: prefixClass_('InfoContent'),
8586
INFOSIGNATURE: prefixClass_('InfoSignature'),
86-
INFOTITLE: prefixClass_('InfoTitle')
87+
INFOTITLE: prefixClass_('InfoTitle'),
88+
SLIDERVALUE: prefixClass_('SliderValue'),
89+
SLIDERBAR: prefixClass_('SliderBar'),
8790
};
8891

8992
// This is an awkward type construction!
@@ -94,7 +97,7 @@ export type HtmlClass = 'CtxtMenu_ContextMenu' | 'CtxtMenu_Menu' |
9497
'CtxtMenu_MousePost' | 'CtxtMenu_RTL' | 'CtxtMenu_Attached' |
9598
'CtxtMenu_Info' | 'CtxtMenu_InfoClose' | 'CtxtMenu_InfoContent' |
9699
'CtxtMenu_InfoSignature' | 'CtxtMenu_InfoTitle' | 'CtxtMenu_MenuFrame' |
97-
'CtxtMenu_MenuInputBox' ;
100+
'CtxtMenu_MenuInputBox' | 'CtxtMenu_MenuSlider' ;
98101

99102
/**
100103
* HTML attributes.

ts/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ export let CssStyles = obj1;
99
export let Info = obj2;
1010
export let Popup = obj3;
1111
export let parse = Parse;
12-
export let version = '0.3.0';
12+
export let version = '0.4.0';

ts/item_combo.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export class Combo extends AbstractVariableItem<string> {
5151
* @param {string=} id Optionally the id of the menu item.
5252
*/
5353
constructor(menu: Menu, content: string, variable: string, id?: string) {
54-
super(menu, 'radio', content, id);
54+
super(menu, 'combobox', content, id);
5555
this.variable = menu.pool.lookup(variable) as Variable<string>;
5656
this.register();
5757
}
@@ -69,7 +69,7 @@ export class Combo extends AbstractVariableItem<string> {
6969
*/
7070
public space(event: KeyboardEvent) {
7171
super.space(event);
72-
this.down(null);
72+
MenuUtil.close(this);
7373
}
7474

7575
/**
@@ -80,6 +80,14 @@ export class Combo extends AbstractVariableItem<string> {
8080
this.input.focus();
8181
}
8282

83+
/**
84+
* @override
85+
*/
86+
public unfocus() {
87+
super.unfocus();
88+
this.updateSpan();
89+
}
90+
8391
/**
8492
* @override
8593
*/

ts/item_slider.ts

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/*************************************************************
2+
*
3+
* Copyright (c) 2015-2016 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+
/**
20+
* @fileoverview Class of slider.
21+
*
22+
* @author volker.sorge@gmail.com (Volker Sorge)
23+
*/
24+
25+
26+
import {AbstractVariableItem} from './abstract_variable_item';
27+
import {Menu} from './menu';
28+
import {MenuUtil} from './menu_util';
29+
import {Variable} from './variable';
30+
import {HtmlClasses} from './html_classes';
31+
import {KEY} from './key_navigatable';
32+
33+
34+
export class Slider extends AbstractVariableItem<string> {
35+
36+
/**
37+
* @override
38+
*/
39+
protected role = 'slider';
40+
private labelSpan: HTMLElement;
41+
private valueSpan: HTMLElement;
42+
private labelId = 'ctx_slideLabel' + MenuUtil.counter();
43+
private valueId = 'ctx_slideValue' + MenuUtil.counter();
44+
45+
private input: HTMLInputElement;
46+
47+
private inputEvent: boolean = false;
48+
49+
/**
50+
* @constructor
51+
* @extends {AbstractItem}
52+
* @param {Menu} menu The context menu or sub-menu the item belongs to.
53+
* @param {string} content The content of the menu item.
54+
* @param {string} variable The variable that is changed.
55+
* @param {string=} id Optionally the id of the menu item.
56+
*/
57+
constructor(menu: Menu, content: string, variable: string, id?: string) {
58+
super(menu, 'slider', content, id);
59+
this.variable = menu.pool.lookup(variable) as Variable<string>;
60+
this.register();
61+
}
62+
63+
/**
64+
* @override
65+
*/
66+
public executeAction() {
67+
this.variable.setValue(
68+
this.input.value, MenuUtil.getActiveElement(this));
69+
this.update();
70+
}
71+
72+
/**
73+
* @override
74+
*/
75+
public space(event: KeyboardEvent) {
76+
super.space(event);
77+
MenuUtil.close(this);
78+
}
79+
80+
/**
81+
* @override
82+
*/
83+
public focus() {
84+
super.focus();
85+
this.input.focus();
86+
}
87+
88+
/**
89+
* @override
90+
*/
91+
public unfocus() {
92+
super.unfocus();
93+
this.updateSpan();
94+
}
95+
96+
/**
97+
* @override
98+
*/
99+
public generateHtml() {
100+
super.generateHtml();
101+
let html = this.html;
102+
html.classList.add(HtmlClasses['MENUSLIDER']); // ???
103+
console.log(html.childNodes.length);
104+
this.valueSpan = document.createElement('span');
105+
this.valueSpan.setAttribute('id', this.valueId);
106+
// this.span.appendChild(this.valueSpan);
107+
this.valueSpan.classList.add(HtmlClasses['SLIDERVALUE']);
108+
this.html.appendChild(this.valueSpan);
109+
}
110+
111+
/**
112+
* @override
113+
*/
114+
public generateSpan() {
115+
this.span = document.createElement('span');
116+
this.labelSpan = document.createElement('span');
117+
this.labelSpan.setAttribute('id', this.labelId);
118+
this.labelSpan.appendChild(this.html.childNodes[0]);
119+
this.html.appendChild(this.labelSpan);
120+
// this.span.classList.add(HtmlClasses['MENUINPUTBOX']); // ???
121+
this.input = document.createElement('input');
122+
this.input.addEventListener('keydown', this.inputKey.bind(this));
123+
this.input.addEventListener('mousedown', this.inputKey.bind(this));
124+
this.input.setAttribute('type', 'range');
125+
this.input.setAttribute('min', '0');
126+
this.input.setAttribute('max', '100');
127+
this.input.setAttribute('aria-valuemin', '0');
128+
this.input.setAttribute('aria-valuemax', '100');
129+
this.input.setAttribute('aria-labelledby', this.labelId);
130+
// this.input.setAttribute('value', '50');
131+
this.input.oninput = this.executeAction.bind(this);
132+
this.input.classList.add(HtmlClasses['SLIDERBAR']);
133+
// this.input.setAttribute('style', 'width:50%;margin-top:.5em;appearance:slider-horizontal;');
134+
// this.input.setAttribute('', '');
135+
// this.input.setAttribute('size', '10em');
136+
// this.input.setAttribute('type', 'text');
137+
// this.input.setAttribute('tabindex', '-1');
138+
this.span.appendChild(this.input);
139+
}
140+
141+
142+
/**
143+
* Executes the key event of the sliderbox.
144+
* @param {KeyboardEvent} event The input event.
145+
*/
146+
public inputKey(_event: InputEvent) {
147+
this.inputEvent = true;
148+
}
149+
150+
151+
/**
152+
* @override
153+
*/
154+
public mousedown(event: MouseEvent) {
155+
event.stopPropagation();
156+
}
157+
158+
159+
/**
160+
* Specification of the keydown event.
161+
* @param {KeyboardEvent} event The input event.
162+
*/
163+
public keydown(event: KeyboardEvent) {
164+
if (this.inputEvent &&
165+
event.keyCode !== KEY.ESCAPE &&
166+
event.keyCode !== KEY.RETURN) {
167+
this.inputEvent = false;
168+
event.stopPropagation();
169+
return;
170+
}
171+
super.keydown(event);
172+
event.stopPropagation();
173+
}
174+
175+
/**
176+
* Toggles the aria checked attribute.
177+
*/
178+
protected updateAria() {
179+
let value = this.variable.getValue();
180+
this.input.setAttribute('aria-valuenow', value);
181+
this.input.setAttribute('aria-valuetext', value + '%');
182+
}
183+
184+
/**
185+
* Toggles the checked tick.
186+
*/
187+
protected updateSpan() {
188+
let initValue;
189+
try {
190+
initValue = this.variable.getValue(MenuUtil.getActiveElement(this));
191+
this.valueSpan.innerHTML = initValue + '%';
192+
} catch (e) {
193+
initValue = '';
194+
}
195+
this.input.value = initValue;
196+
}
197+
198+
}

ts/parser.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import {Radio} from './item_radio';
3535
import {Submenu} from './item_submenu';
3636
import {Rule} from './item_rule';
3737
import {Item} from './item';
38+
import {Slider} from './item_slider';
3839
import {SubMenu} from './sub_menu';
3940

4041

@@ -76,6 +77,18 @@ namespace Parser {
7677
return new Combo(menu, content, variable, id);
7778
};
7879

80+
/**
81+
* Parses a JSON respresentation of a combo item.
82+
* @param {JSON} json The JSON object to parse.
83+
* @param {Menu} menu The menu the item is attached to.
84+
* @return {Slider} The new combo object.
85+
*/
86+
const parseSlider = function(
87+
{content: content, variable: variable, id: id}:
88+
{content: string, variable: string, id: string}, menu: Menu): Slider {
89+
return new Slider(menu, content, variable, id);
90+
};
91+
7992
/**
8093
* Parses a JSON respresentation of a label item.
8194
* @param {JSON} json The JSON object to parse.
@@ -215,6 +228,7 @@ namespace Parser {
215228
'label': parseLabel,
216229
'radio': parseRadio,
217230
'rule': parseRule,
231+
'slider': parseSlider,
218232
'submenu': parseSubmenu
219233
};
220234
}

0 commit comments

Comments
 (0)