Skip to content

Commit 6e68159

Browse files
committed
custom range for sliders
1 parent 59ce6e3 commit 6e68159

File tree

4 files changed

+99
-27
lines changed

4 files changed

+99
-27
lines changed

src/InputFieldMarkdownRenderChild.ts

Lines changed: 69 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -90,53 +90,96 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
9090

9191
inputFieldArguments = inputFieldArguments.map(x => x.trim());
9292
for (const inputFieldArgument of inputFieldArguments) {
93-
if (inputFieldArgument.startsWith('class')) {
94-
let classArgumentsString: string = inputFieldArgumentsRegExp.exec(inputFieldArgument)[0];
95-
if (!classArgumentsString && classArgumentsString.length >= 2) {
96-
throw new Error('class needs an argument');
97-
}
98-
classArgumentsString = classArgumentsString.substring(1, classArgumentsString.length - 1);
99-
if (!classArgumentsString) {
100-
throw new Error('class argument can not be empty');
101-
}
93+
const inputFieldArgumentName: string = this.extractInputFieldArgumentName(inputFieldArgument);
10294

103-
let inputFieldStyleArgument: { name: string, value: string } = {name: 'class', value: classArgumentsString};
95+
if (inputFieldArgumentName === 'class') {
96+
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
10497

105-
this.arguments.push(inputFieldStyleArgument);
98+
let inputFieldClassArgument: { name: string, value: string } = {name: inputFieldArgumentName, value: inputFieldArgumentValue};
99+
this.arguments.push(inputFieldClassArgument);
106100
}
107101

108-
if (inputFieldArgument.startsWith('addLabels')) {
102+
if (inputFieldArgumentName === 'addLabels') {
109103
this.arguments.push({name: 'labels', value: true});
110104
}
105+
106+
if (inputFieldArgumentName === 'minValue') {
107+
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
108+
const inputFieldArgumentValueAsNumber: number = Number.parseInt(inputFieldArgumentValue);
109+
110+
if (Number.isNaN(inputFieldArgumentValueAsNumber)) {
111+
throw new Error(`argument \'${inputFieldArgumentName}\' value must be of type number`);
112+
}
113+
114+
let inputFieldClassArgument: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
115+
this.arguments.push(inputFieldClassArgument);
116+
}
117+
118+
if (inputFieldArgumentName === 'maxValue') {
119+
const inputFieldArgumentValue: string = this.extractInputFieldArgumentValue(inputFieldArgument);
120+
const inputFieldArgumentValueAsNumber: number = Number.parseInt(inputFieldArgumentValue);
121+
122+
if (Number.isNaN(inputFieldArgumentValueAsNumber)) {
123+
throw new Error(`argument \'${inputFieldArgumentName}\' value must be of type number`);
124+
}
125+
126+
let inputFieldClassArgument: { name: string, value: number } = {name: inputFieldArgumentName, value: inputFieldArgumentValueAsNumber};
127+
this.arguments.push(inputFieldClassArgument);
128+
}
111129
}
112130
}
113131

132+
extractInputFieldArgumentName(argumentString: string): string {
133+
const argumentsRegExp: RegExp = new RegExp(/\(.*\)/);
134+
135+
return argumentString.replace(argumentsRegExp, '');
136+
}
137+
138+
extractInputFieldArgumentValue(argumentString: string): string {
139+
const argumentsRegExp: RegExp = new RegExp(/\(.*\)/);
140+
141+
let argumentName = this.extractInputFieldArgumentName(argumentString);
142+
143+
let argumentValueRegExpResult = argumentsRegExp.exec(argumentString);
144+
if (!argumentValueRegExpResult) {
145+
throw new Error(`argument \'${argumentName}\' requires a value`);
146+
}
147+
let argumentValue = argumentsRegExp.exec(argumentString)[0];
148+
if (!argumentValue && argumentValue.length >= 2) {
149+
throw new Error(`argument \'${argumentName}\' requires a value`);
150+
}
151+
argumentValue = argumentValue.substring(1, argumentValue.length - 1);
152+
if (!argumentValue) {
153+
throw new Error(`argument \'${argumentName}\' value can not be empty`);
154+
}
155+
156+
return argumentValue;
157+
}
158+
114159
parseBindTarget(bindTarget: string) {
115160
let bindTargetParts = bindTarget.split('#');
116161
if (bindTargetParts.length === 1) { // same file
117162
this.bindTargetMetadataField = bindTarget;
118163
const files = this.plugin.getFilesByName(this.filePath);
119164
if (files.length === 0) {
120-
this.error = 'file not fond.';
121-
return;
165+
throw new Error('file not found');
122166
} else if (files.length === 1) {
123167
this.file = files[0];
124168
} else {
125-
throw new Error('multiple files found. please specify the file path.');
169+
throw new Error('multiple files found. please specify the file path');
126170
}
127171
} else if (bindTargetParts.length === 2) {
128172
this.bindTargetMetadataField = bindTargetParts[1];
129173
const files = this.plugin.getFilesByName(bindTargetParts[0]);
130174
if (files.length === 0) {
131-
this.error = 'file not fond.';
132-
return;
175+
throw new Error('file not found');
133176
} else if (files.length === 1) {
134177
this.file = files[0];
135178
} else {
136-
throw new Error('multiple files found. please specify the file path.');
179+
throw new Error('multiple files found. please specify the file path');
137180
}
138181
} else {
139-
throw new Error('invalid binding.');
182+
throw new Error('invalid binding');
140183
}
141184
this.metaData = this.plugin.getMetaDataForFile(this.file);
142185
}
@@ -170,8 +213,12 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
170213
}
171214
}
172215

216+
getArguments(name: string) {
217+
return this.arguments.filter(x => x.name === name);
218+
}
219+
173220
getArgument(name: string) {
174-
return this.arguments.filter(x => x.name === name).first();
221+
return this.getArguments(name).first();
175222
}
176223

177224
async onload() {
@@ -193,9 +240,9 @@ export class InputFieldMarkdownRenderChild extends MarkdownRenderChild {
193240

194241
this.inputField.render(container);
195242

196-
const classArgument = this.getArgument('class');
243+
const classArgument = this.getArguments('class');
197244
if (classArgument) {
198-
this.inputField.getHtmlElement().addClass(classArgument.value);
245+
this.inputField.getHtmlElement().addClasses(classArgument.map(x => x.value));
199246
}
200247

201248
this.containerEl.empty();

src/inputFields/SliderInputField.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,30 @@
11
import {AbstractInputField} from './AbstractInputField';
22
import {SliderComponent} from 'obsidian';
33
import {Logger} from '../utils/Logger';
4+
import {InputFieldMarkdownRenderChild} from '../InputFieldMarkdownRenderChild';
5+
import {clamp} from '../utils/Utils';
46

57
export class SliderInputField extends AbstractInputField {
68
sliderComponent: SliderComponent;
7-
minValue: number = 0;
8-
maxValue: number = 100;
9+
minValue: number;
10+
maxValue: number;
11+
12+
13+
constructor(inputFieldMarkdownRenderChild: InputFieldMarkdownRenderChild, onValueChange: (value: any) => (void | Promise<void>)) {
14+
super(inputFieldMarkdownRenderChild, onValueChange);
15+
this.minValue = inputFieldMarkdownRenderChild.getArgument('minValue')?.value ?? 0;
16+
this.maxValue = inputFieldMarkdownRenderChild.getArgument('maxValue')?.value ?? 100;
17+
}
918

1019
getValue(): any {
1120
return this.sliderComponent.getValue();
1221
}
1322

1423
setValue(value: any): void {
1524
if (value != null && typeof value == 'number') {
16-
this.sliderComponent.setValue(value);
25+
if (value >= this.minValue && value <= this.maxValue) {
26+
this.sliderComponent.setValue(value);
27+
}
1728
} else {
1829
Logger.logWarning(`can not set value of slider to \'${value}\'`);
1930
this.sliderComponent.setValue(this.minValue);
@@ -27,7 +38,7 @@ export class SliderInputField extends AbstractInputField {
2738
render(container: HTMLDivElement): void {
2839
let labelArgument = this.inputFieldMarkdownRenderChild.getArgument('labels');
2940
if (labelArgument && labelArgument.value === true) {
30-
container.createSpan({text: this.minValue.toString()});
41+
container.createSpan({text: this.minValue.toString(), cls: 'meta-bind-slider-label'});
3142
}
3243

3344
const component = new SliderComponent(container);
@@ -37,7 +48,7 @@ export class SliderInputField extends AbstractInputField {
3748
component.setLimits(this.minValue, this.maxValue, 1);
3849

3950
if (labelArgument && labelArgument.value === true) {
40-
container.createSpan({text: this.maxValue.toString()});
51+
container.createSpan({text: this.maxValue.toString(), cls: 'meta-bind-slider-label'});
4152
}
4253

4354
this.sliderComponent = component;

src/utils/Utils.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,7 @@ export function removeFileEnding(fileName: string) {
1818
return newFileName;
1919
}
2020
}
21+
22+
export function clamp(num: number, min: number, max: number): number {
23+
return Math.min(Math.max(num, min), max);
24+
}

styles.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,16 @@
1010
color: red;
1111
}
1212

13+
.meta-bind-slider-label {
14+
color: var(--text-muted);
15+
}
16+
17+
18+
1319
.meta-bind-full-width {
1420
width: 100%;
1521
}
22+
23+
.meta-bind-high {
24+
height: 200px;
25+
}

0 commit comments

Comments
 (0)