-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathEditable.ts
117 lines (89 loc) · 2.87 KB
/
Editable.ts
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
import { Dict } from './util.js'
export type Range = 'int' | 'real' | Array<string> | RegExp;
export type Editable = {
id?: number;
edit: ( varname: string, value: any ) => void; // usually rangeEdit, but can be another function
editFields: Array<string>; // show editable value in panel
showFields?: Array<string>; // show value in panel but don't edit
ranges: { [key: string]: Range };
// these are related to specs and not used very much
overrideFields?: Array<string>; // list of fields that have been overridden
onUserEdit?: ( varname: string ) => void;
userReq?: Dict<any>;
}
export function rangeEdit( this: Editable, varname: string, value: any ) {
let range = this.ranges[varname];
extRangeEdit.apply( this, [varname, value, range] );
}
export function extRangeEdit( this: any, varname: string, value: any, range?: Range, ) {
if ( value === undefined ) return;
let ok = true;
let oldVal = ( this )[varname];
/*if ( typeof oldVal != typeof value ) {
throw new Error( 'rangeEdit: type mismatch for field ' + varname +
' (' + typeof oldVal + '!=' + typeof value + ')' );
}*/
// number
if ( typeof oldVal == 'number' ) {
let raw = value;
value = parseFloat( value );
if ( isNaN( value ) || value == Infinity || value == -Infinity ) {
throw new Error( 'rangeEdit: invalid value for field ' + varname + ' (' + raw + ')' );
}
if ( range !== undefined ) {
if ( range == 'real' ) {
// pass
} else if ( range == 'int' ) {
value = Math.floor( value );
}
// default number range is nonnegative integer
} else {
value = Math.floor( value );
if ( value < 0 ) {
ok = false;
}
}
// string
} else if ( typeof oldVal == 'string' ) {
if ( range !== undefined ) {
if ( range instanceof Array ) {
if ( !range.includes( value ) ) {
ok = false;
}
} else if ( range instanceof RegExp ) {
let match = value.match( range );
if ( !match ) {
ok = false;
}
}
} else {
// no default string range
}
}
if ( ok ) {
edit( this, varname, value ); // used to pass a function that assigned the value for some reason
}
}
export function edit( obj: any, varname: string, func: ( () => void ) | string | number | boolean | object ): boolean {
let oldVal = obj[varname];
if ( typeof func == 'string' ||
typeof func == 'number' ||
typeof func == 'boolean' ||
typeof func == 'object' ) {
if ( typeof oldVal != typeof func ) {
throw new Error( 'edit: type mismatch for field ' + varname + ' (' + typeof oldVal + '!=' + typeof func + ')' );
}
obj[varname] = func;
} else if ( typeof func == 'function' ) {
func();
} else {
throw new Error( 'Unhandled value type ' + ( typeof func ) );
}
if ( obj[varname] != oldVal ) {
if ( typeof document !== 'undefined' ) {
document.dispatchEvent( new CustomEvent( 'editObject', { detail: obj } ) );
}
return true;
}
return false;
}