x4js 2.3.24 → 2.3.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -90,6 +90,9 @@ export class PropertyGrid extends VBox {
90
90
  private root: Component;
91
91
  private groups: PropertyGroup[];
92
92
 
93
+ // the editor of each property, by its name: no id, a name is not unique in a page
94
+ private editors = new Map<string, Component>( );
95
+
93
96
  constructor(props: PropertyProps) {
94
97
  super(props);
95
98
 
@@ -118,6 +121,8 @@ export class PropertyGrid extends VBox {
118
121
 
119
122
  setItems( _grps: PropertyGroup[] ) {
120
123
 
124
+ this.editors.clear( );
125
+
121
126
  if( !_grps || _grps.length==0 ) {
122
127
  this.root.clearContent( );
123
128
  return;
@@ -218,7 +223,6 @@ export class PropertyGrid extends VBox {
218
223
  if (item.type === 'boolean') {
219
224
  editor = new Input({
220
225
  type: "checkbox",
221
- id: item.name,
222
226
  //name: item.name,
223
227
  checked: value as boolean,
224
228
  dom_events: {
@@ -232,7 +236,6 @@ export class PropertyGrid extends VBox {
232
236
  else if (item.type === 'options') {
233
237
  editor = new Select( {
234
238
  value: value as ListboxID,
235
- id: item.name,
236
239
  items: item.options,
237
240
  //name: item.name,
238
241
  change: ( e: EvChange ) => {
@@ -243,20 +246,23 @@ export class PropertyGrid extends VBox {
243
246
  else if (item.type === 'password') {
244
247
  editor = new Input({
245
248
  type: 'password',
246
- id: item.name,
247
- //name: item.name,
248
- value: String(value),
249
+ //name: item.name,
250
+ value: String(value),
249
251
  focus: ( e: EvFocus ) => {
250
252
  if( e.focus_out ) {
251
253
  item.callback?.( item.name, (editor as Input).getValue() );
252
254
  }
255
+ },
256
+ change: ( ) => {
257
+ if( item.live ) {
258
+ item.callback?.( item.name, (editor as Input).getValue() );
259
+ }
253
260
  }
254
261
  });
255
262
  }
256
263
  else if (item.type === 'number') {
257
264
  editor = new Input({
258
265
  type: 'number',
259
- id: item.name,
260
266
  //name: item.name,
261
267
  value: String(value),
262
268
  step: item.step,
@@ -276,7 +282,6 @@ export class PropertyGrid extends VBox {
276
282
  }
277
283
  else if (item.type === 'color') {
278
284
  editor = new ColorInput({
279
- id: item.name,
280
285
  color: value as string,
281
286
  format: "hex",
282
287
  picker: true,
@@ -289,14 +294,12 @@ export class PropertyGrid extends VBox {
289
294
  }
290
295
  else if (item.type === 'label') {
291
296
  editor = new Label({
292
- id: item.name,
293
297
  text: value as string,
294
298
  });
295
299
  }
296
300
  else if (item.type === 'button') {
297
301
  use_hdr = false;
298
302
  editor = new Button({
299
- id: item.name,
300
303
  cls: "button",
301
304
  label: value as string,
302
305
  click: ( ) => {
@@ -307,7 +310,6 @@ export class PropertyGrid extends VBox {
307
310
  else {
308
311
  editor = new Input({
309
312
  type: 'text',
310
- id: item.name,
311
313
  //name: item.name,
312
314
  value: value as string,
313
315
  focus: ( e: EvFocus ) => {
@@ -315,8 +317,17 @@ export class PropertyGrid extends VBox {
315
317
  item.callback?.( item.name, (editor as Input).getValue() );
316
318
  }
317
319
  },
320
+ change: ( ) => {
321
+ if( item.live ) {
322
+ item.callback?.( item.name, (editor as Input).getValue() );
323
+ }
324
+ }
318
325
  })
319
326
  }
327
+
328
+ if( item.name ) {
329
+ this.editors.set( item.name, editor );
330
+ }
320
331
 
321
332
  let cls = 'row';
322
333
  if( item.cls ) {
@@ -340,7 +351,7 @@ export class PropertyGrid extends VBox {
340
351
  cls,
341
352
  content: [
342
353
  use_hdr ? new Component({ cls: 'cell hdr', content: item.title ?? item.name, tooltip: item.desc }) : null,
343
- new HBox({ cls: 'cell', tag: "label", attrs: { "labelFor": item.name }, content }),
354
+ new HBox({ cls: 'cell', tag: "label", content }),
344
355
  ]
345
356
  });
346
357
  }
@@ -352,45 +363,28 @@ export class PropertyGrid extends VBox {
352
363
  setPropValue( name: string, value: any ) {
353
364
  const all = this.groups.flatMap( x => [ ...x.items ] ) ;
354
365
  const item = all.find( x => x.name==name );
355
- if( !item ) {
366
+ const editor = this.editors.get( name );
367
+ if( !item || !editor ) {
356
368
  return;
357
369
  }
358
370
 
359
371
  if (item.type === 'boolean') {
360
- const editor = this.root.query<Input>( '#'+item.name );
361
- if( editor ) {
362
- editor.setCheck( value as boolean );
363
- }
372
+ (editor as Input).setCheck( value as boolean );
364
373
  }
365
374
  else if (item.type === 'options') {
366
- const editor = this.root.query<Select>( '#'+item.name );
367
- if( editor ) {
368
- editor.setValue( value as string );
369
- }
375
+ (editor as Select).setValue( value as string );
370
376
  }
371
377
  else if (item.type === 'number') {
372
- const editor = this.root.query<Input>( '#'+item.name );
373
- if( editor ) {
374
- editor.setNumValue( value as number, -2 );
375
- }
378
+ (editor as Input).setNumValue( value as number, -2 );
376
379
  }
377
380
  else if (item.type === 'color') {
378
- const editor = this.root.query<ColorInput>( '#'+item.name );
379
- if( editor ) {
380
- editor.setColor( value as string );
381
- }
381
+ (editor as ColorInput).setColor( value as string );
382
382
  }
383
383
  else if (item.type === 'label') {
384
- const label = this.root.query<Label>( '#'+item.name );
385
- if( label ) {
386
- label.setText( value );
387
- }
384
+ (editor as Label).setText( value );
388
385
  }
389
386
  else {
390
- const editor = this.root.query<Input>( '#'+item.name );
391
- if( editor ) {
392
- editor.setValue( value as string );
393
- }
387
+ (editor as Input).setValue( value as string );
394
388
  }
395
389
  }
396
390
 
@@ -32,6 +32,15 @@ let mouse_pos: Point = {x:0, y:0 };
32
32
 
33
33
  const timer = new Timer( );
34
34
 
35
+ /**
36
+ * the tooltips are shown once this is called: the text of the attribute "tooltip" (the prop
37
+ * tooltip of a component), or the one getTip( ) of a "tip-handler" gives.
38
+ * This text is shown as html: a text that comes from a user is escaped by the application,
39
+ * with sanitizeHtml( text ).
40
+ * @example
41
+ * new Button( { label: "Open", tooltip: `Open <b>${sanitizeHtml( file.name )}</b>` } );
42
+ */
43
+
35
44
  export function initTooltips( ) {
36
45
 
37
46
  document.addEventListener( "mouseenter", ( ev: MouseEvent ) => {
@@ -255,7 +255,11 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
255
255
  private _setupKeyboard( ) {
256
256
 
257
257
  document.addEventListener( "keydown", (ev) => {
258
- if( ev.key=="Tab" || ev.key=="Enter" ) {
258
+ // Enter in a text of several lines is a new line, not the next field
259
+ const target = ev.target as HTMLElement;
260
+ const multiline = target.tagName==="TEXTAREA" || target.isContentEditable;
261
+
262
+ if( ev.key=="Tab" || ( ev.key=="Enter" && !multiline ) ) {
259
263
  if( this.focusNext( !ev.shiftKey ) ) {
260
264
  ev.preventDefault( );
261
265
  }
@@ -263,7 +267,8 @@ export class Application<E extends ApplicationEvents = ApplicationEvents> extend
263
267
 
264
268
  // The focus is nowhere: the shortcuts of the view the user worked in last.
265
269
  // (when it is in a view, the view has seen the key before us)
266
- if( ev.target===document.body && this._active?.owner.dom.isConnected && this._active.shortcuts.handle( ev ) ) {
270
+ // (a view hidden, in a tab not shown: its shortcuts sleep)
271
+ if( ev.target===document.body && this._active?.owner.isVisible( ) && this._active.shortcuts.handle( ev ) ) {
267
272
  return;
268
273
  }
269
274
 
@@ -159,6 +159,8 @@ export class EventSource<E extends EventMap = EventMap > {
159
159
 
160
160
  /**
161
161
  * Dispatches an event with a given name and payload to all registered listeners.
162
+ * A listener that throws: its error goes to console.error, the next listeners are
163
+ * called, and fire returns normally.
162
164
  * @param name - The name of the event to fire (must be a key in `E`).
163
165
  * @param evx - The event payload (event object) to pass to the listeners.
164
166
  */
@@ -192,14 +194,24 @@ export class EventSource<E extends EventMap = EventMap > {
192
194
  ev.stopPropagation = stopPropagation;
193
195
  }
194
196
 
197
+ // a listener that throws stops neither the others nor the one that fires
198
+ const call = ( listener: EventCallback ) => {
199
+ try {
200
+ listener( ev );
201
+ }
202
+ catch( e ) {
203
+ console.error( e );
204
+ }
205
+ };
206
+
195
207
  // small optimisation
196
208
  if (listeners.length == 1) {
197
- listeners[0](ev);
209
+ call( listeners[0] );
198
210
  }
199
211
  else {
200
212
  const temp = listeners.slice();
201
213
  for (let i = 0, n = temp.length; i < n; i++) {
202
- temp[i](ev);
214
+ call( temp[i] );
203
215
  if (ev.propagationStopped) {
204
216
  break;
205
217
  }
@@ -336,6 +336,13 @@ let fr = {
336
336
  search: 'Rechercher un paramètre',
337
337
  nomatch: 'Aucun paramètre trouvé',
338
338
  },
339
+
340
+ progression: {
341
+ error: '{0} erreur',
342
+ errors: '{0} erreurs',
343
+ warning: '{0} avertissement',
344
+ warnings: '{0} avertissements',
345
+ },
339
346
  }
340
347
  };
341
348
 
@@ -406,6 +413,13 @@ let en = {
406
413
  search: 'Search settings',
407
414
  nomatch: 'No setting found',
408
415
  },
416
+
417
+ progression: {
418
+ error: '{0} error',
419
+ errors: '{0} errors',
420
+ warning: '{0} warning',
421
+ warnings: '{0} warnings',
422
+ },
409
423
  }
410
424
  };
411
425
 
@@ -476,6 +490,13 @@ let es = {
476
490
  search: 'Buscar un ajuste',
477
491
  nomatch: 'Ningún ajuste encontrado',
478
492
  },
493
+
494
+ progression: {
495
+ error: '{0} error',
496
+ errors: '{0} errores',
497
+ warning: '{0} advertencia',
498
+ warnings: '{0} advertencias',
499
+ },
479
500
  }
480
501
  };
481
502
 
@@ -546,6 +567,13 @@ let de = {
546
567
  search: 'Einstellungen durchsuchen',
547
568
  nomatch: 'Keine Einstellung gefunden',
548
569
  },
570
+
571
+ progression: {
572
+ error: '{0} Fehler',
573
+ errors: '{0} Fehler',
574
+ warning: '{0} Warnung',
575
+ warnings: '{0} Warnungen',
576
+ },
549
577
  }
550
578
  };
551
579