Skip to content

Commit 8820763

Browse files
committed
Select and multi select
1 parent 5c8088e commit 8820763

14 files changed

+457
-19
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ INPUT[input_type(argument_name(argument_value), argument_name_2, ...):file_name_
1818
```
1919

2020
#### Input field types
21-
- `slider` a slider from 0 to 100 (custom ranges are on the road map)
21+
- `slider` a slider from 0 to 100 (custom ranges can be set using `minValue` and `maxValue`, see below)
2222
- `toggle` a toggle element
2323
- `text` a text field
2424
- `text_area` a bigger text field

src/InputFieldMarkdownRenderChild.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@ import {Logger} from './utils/Logger';
44
import {AbstractInputField} from './inputFields/AbstractInputField';
55
import {InputFieldFactory, InputFieldType} from './inputFields/InputFieldFactory';
66

7+
export enum InputFieldMarkdownRenderChildType {
8+
INLINE_CODE_BLOCK,
9+
CODE_BLOCK,
10+
}
11+
712
export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
813
plugin: MetaBindPlugin;
914
metaData: any;
@@ -24,7 +29,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
2429

2530
arguments: { name: string, value: any }[];
2631

27-
constructor(containerEl: HTMLElement, fullDeclaration: string, plugin: MetaBindPlugin, filePath: string, uid: number) {
32+
constructor(containerEl: HTMLElement, type: InputFieldMarkdownRenderChildType, fullDeclaration: string, plugin: MetaBindPlugin, filePath: string, uid: number) {
2833
super(containerEl);
2934

3035
//console.log(this, 2)
@@ -43,6 +48,7 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
4348
this.parseDeclaration();
4449

4550
this.inputField = InputFieldFactory.createInputField(this.inputFieldType, {
51+
type: type,
4652
inputFieldMarkdownRenderChild: this,
4753
onValueChanged: this.updateMetaData.bind(this),
4854
});
@@ -100,31 +106,54 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
100106
}
101107

102108
if (inputFieldArgumentName === 'addLabels') {
109+
if (this.inputFieldType !== InputFieldType.SLIDER) {
110+
throw new Error(`argument \'${inputFieldArgumentName}\' is only applicable to slider input fields`);
111+
}
112+
103113
this.arguments.push({name: 'labels', value: true});
104114
}
105115

106116
if (inputFieldArgumentName === 'minValue') {
117+
if (this.inputFieldType !== InputFieldType.SLIDER) {
118+
throw new Error(`argument \'${inputFieldArgumentName}\' is only applicable to slider input fields`);
119+
}
120+
107121
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
108122
const inputFieldArgumentValueAsNumber: number = Number.parseInt(inputFieldArgumentValue);
109123

110124
if (Number.isNaN(inputFieldArgumentValueAsNumber)) {
111125
throw new Error(`argument \'${inputFieldArgumentName}\' value must be of type number`);
112126
}
113127

114-
let inputFieldClassArgument: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
115-
this.arguments.push(inputFieldClassArgument);
128+
let inputFieldArgumentObject: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
129+
this.arguments.push(inputFieldArgumentObject);
116130
}
117131

118132
if (inputFieldArgumentName === 'maxValue') {
133+
if (this.inputFieldType !== InputFieldType.SLIDER) {
134+
throw new Error(`argument \'${inputFieldArgumentName}\' is only applicable to slider input fields`);
135+
}
136+
119137
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
120138
const inputFieldArgumentValueAsNumber: number = Number.parseInt(inputFieldArgumentValue);
121139

122140
if (Number.isNaN(inputFieldArgumentValueAsNumber)) {
123141
throw new Error(`argument \'${inputFieldArgumentName}\' value must be of type number`);
124142
}
125143

126-
let inputFieldClassArgument: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
127-
this.arguments.push(inputFieldClassArgument);
144+
let inputFieldArgumentObject: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
145+
this.arguments.push(inputFieldArgumentObject);
146+
}
147+
148+
if (inputFieldArgumentName === 'option') {
149+
if (this.inputFieldType !== InputFieldType.SELECT && this.inputFieldType !== InputFieldType.MULTI_SELECT) {
150+
throw new Error(`argument \'${inputFieldArgumentName}\' is only applicable to select and multi-select input fields`);
151+
}
152+
153+
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
154+
155+
let inputFieldArgumentObject: { name: string, value: string } = {name: inputFieldArgumentName, value: inputFieldArgumentValue};
156+
this.arguments.push(inputFieldArgumentObject);
128157
}
129158
}
130159
}
@@ -200,16 +229,20 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
200229
}
201230

202231
updateValue(value: any) {
203-
if (value != null && this.inputField.getValue() !== value && this.valueQueue.length === 0) {
204-
Logger.logDebug(`updating input field ${this.uid} to '${value.toString()}'`);
232+
if (value == null) {
233+
value = this.inputField.getDefaultValue();
234+
}
235+
236+
if (!this.inputField.isEqualValue(value) && this.valueQueue.length === 0) {
237+
Logger.logDebug(`updating input field ${this.uid} to`, value);
205238
this.inputField.setValue(value);
206239
}
207240
}
208241

209242
getInitialValue() {
210243
// console.log(this);
211244
if (this.isBound) {
212-
return this.metaData[this.bindTargetMetadataField];
245+
return this.metaData[this.bindTargetMetadataField] ?? this.inputField.getDefaultValue();
213246
}
214247
}
215248

src/inputFields/AbstractInputField.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import {InputFieldMarkdownRenderChild} from '../InputFieldMarkdownRenderChild';
22

33
export abstract class AbstractInputField {
4+
static allowCodeBlock: boolean = true;
5+
static allowInlineCodeBlock: boolean = true;
46
inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild;
57
onValueChange: (value: any) => void | Promise<void>;
68

@@ -21,6 +23,10 @@ export abstract class AbstractInputField {
2123
*/
2224
abstract setValue(value: any): void;
2325

26+
abstract isEqualValue(value: any): boolean;
27+
28+
abstract getDefaultValue(): any;
29+
2430
abstract getHtmlElement(): HTMLElement;
2531

2632
abstract render(container: HTMLDivElement): void;

src/inputFields/InputFieldFactory.ts

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,72 @@
11
import {AbstractInputField} from './AbstractInputField';
22
import {ToggleInputField} from './ToggleInputField';
3-
import {InputFieldMarkdownRenderChild} from '../InputFieldMarkdownRenderChild';
3+
import {InputFieldMarkdownRenderChild, InputFieldMarkdownRenderChildType} from '../InputFieldMarkdownRenderChild';
44
import {TextInputField} from './TextInputField';
55
import {SliderInputField} from './SliderInputField';
66
import {TextAreaInputField} from './TextAreaInputField';
7+
import {SelectInputField} from './SelectInputField';
8+
import {MultiSelectInputField} from './MultiSelectInputField';
79

810
export enum InputFieldType {
911
TOGGLE = 'toggle',
1012
SLIDER = 'slider',
1113
TEXT = 'text',
1214
TEXT_AREA = 'text_area',
15+
SELECT = 'select',
16+
MULTI_SELECT = 'multi_select',
1317
INVALID = 'invalid',
1418
}
1519

1620
export class InputFieldFactory {
17-
static createInputField(inputFieldType: InputFieldType, args: { inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild, onValueChanged: (value: any) => void | Promise<void> }): AbstractInputField {
21+
static createInputField(inputFieldType: InputFieldType, args: { type: InputFieldMarkdownRenderChildType, inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild, onValueChanged: (value: any) => void | Promise<void> }): AbstractInputField {
1822
if (inputFieldType === InputFieldType.TOGGLE) {
23+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !ToggleInputField.allowCodeBlock) {
24+
throw new Error(`can not create ${inputFieldType} as code block`);
25+
}
26+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !ToggleInputField.allowInlineCodeBlock) {
27+
throw new Error(`can not create ${inputFieldType} as inline code block`);
28+
}
1929
return new ToggleInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
2030
} else if (inputFieldType === InputFieldType.SLIDER) {
31+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !SliderInputField.allowCodeBlock) {
32+
throw new Error(`can not create ${inputFieldType} as code block`);
33+
}
34+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !SliderInputField.allowInlineCodeBlock) {
35+
throw new Error(`can not create ${inputFieldType} as inline code block`);
36+
}
2137
return new SliderInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
2238
} else if (inputFieldType === InputFieldType.TEXT) {
39+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !TextInputField.allowCodeBlock) {
40+
throw new Error(`can not create ${inputFieldType} as code block`);
41+
}
42+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !TextInputField.allowInlineCodeBlock) {
43+
throw new Error(`can not create ${inputFieldType} as inline code block`);
44+
}
2345
return new TextInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
2446
} else if (inputFieldType === InputFieldType.TEXT_AREA) {
47+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !TextAreaInputField.allowCodeBlock) {
48+
throw new Error(`can not create ${inputFieldType} as code block`);
49+
}
50+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !TextAreaInputField.allowInlineCodeBlock) {
51+
throw new Error(`can not create ${inputFieldType} as inline code block`);
52+
}
2553
return new TextAreaInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
54+
} else if (inputFieldType === InputFieldType.SELECT) {
55+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !SelectInputField.allowCodeBlock) {
56+
throw new Error(`can not create ${inputFieldType} as code block`);
57+
}
58+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !SelectInputField.allowInlineCodeBlock) {
59+
throw new Error(`can not create ${inputFieldType} as inline code block`);
60+
}
61+
return new SelectInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
62+
} else if (inputFieldType === InputFieldType.MULTI_SELECT) {
63+
if (args.type === InputFieldMarkdownRenderChildType.CODE_BLOCK && !MultiSelectInputField.allowCodeBlock) {
64+
throw new Error(`can not create ${inputFieldType} as code block`);
65+
}
66+
if (args.type === InputFieldMarkdownRenderChildType.INLINE_CODE_BLOCK && !MultiSelectInputField.allowInlineCodeBlock) {
67+
throw new Error(`can not create ${inputFieldType} as inline code block`);
68+
}
69+
return new MultiSelectInputField(args.inputFieldMarkdownRenderChild, args.onValueChanged);
2670
}
2771

2872
return null;
@@ -37,4 +81,5 @@ export class InputFieldFactory {
3781

3882
return InputFieldType.INVALID;
3983
}
84+
4085
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import {SelectInputField} from './SelectInputField';
2+
import {InputFieldMarkdownRenderChild} from '../InputFieldMarkdownRenderChild';
3+
import {arrayEquals} from '../utils/Utils';
4+
5+
export class MultiSelectInputField extends SelectInputField {
6+
7+
constructor(inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild, onValueChange: (value: any) => (void | Promise<void>)) {
8+
super(inputFieldMarkdownRenderChild, onValueChange);
9+
this.allowMultiSelect = true;
10+
}
11+
12+
getValue(): any {
13+
return this.elements.filter(x => x.isActive()).map(x => x.value);
14+
}
15+
16+
setValue(value: string[]): void {
17+
if (value.length === 0) {
18+
return;
19+
}
20+
21+
elementLoop : for (const element of this.elements) {
22+
for (const valueElement of value) {
23+
if (valueElement === element.value) {
24+
element.setActive(true, false);
25+
continue elementLoop;
26+
}
27+
}
28+
element.setActive(false, false);
29+
}
30+
}
31+
32+
isEqualValue(value: any): boolean {
33+
if (!Array.isArray(value)) {
34+
return false;
35+
}
36+
37+
return arrayEquals(this.getValue(), value);
38+
}
39+
40+
getDefaultValue(): string[] {
41+
return [];
42+
}
43+
}

0 commit comments

Comments
 (0)