iobroker.alias-workbench 0.9.11 → 0.10.0

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.
package/admin/js/werte.js CHANGED
@@ -42,7 +42,7 @@ export function jsonVon(id) {
42
42
  }
43
43
 
44
44
  export function feldWert(obj, pfad) {
45
- var t = pfad.split('.');
45
+ var t = pfadTeile(pfad);
46
46
  var x = obj;
47
47
  for (var i = 0; i < t.length; i++) {
48
48
  if (x === null || x === undefined || typeof x !== 'object') { return undefined; }
@@ -171,7 +171,11 @@ export function zeileAusAlias(o, zeilenname) {
171
171
  aber als Lesequelle gilt sie nicht: sonst zeigte „Alias bearbeiten"
172
172
  eine Quelle, die „Alias anlegen" nie eingetragen hat, und beim
173
173
  naechsten Aktualisieren kippte `read` still auf `true` zurueck. */
174
- srcR: (c.read === false && q.einfach) ? '' : (q.read || ''),
174
+ /* Seit 19.09.2026 auch beim Taster: `read: false` am Alias haengt an
175
+ der Rolle, nicht an einer fehlenden Lesequelle (`knopfZeile`). Ein
176
+ alter Taster-Alias mit einfacher `alias.id` liest also aus seinem
177
+ Schreibziel - genau das, was ioBroker mit ihm ohnehin tut. */
178
+ srcR: q.read || '',
175
179
  srcW: schreibQuelle(o),
176
180
  f: (typeof a.read === 'string') ? a.read : '',
177
181
  fw: (typeof a.write === 'string') ? a.write : '',
@@ -285,7 +289,7 @@ export function auswerten(formel, roh) {
285
289
  var gedauert = performance.now() - t0;
286
290
  if (gedauert > GEDULD_MS) {
287
291
  formelGesperrt[formel] = Math.round(gedauert);
288
- console.warn('[alias-workbench] Formel gesperrt nach ' + Math.round(gedauert) + ' ms: ' + formel);
292
+ console.warn('[alias-workbench] Formula blocked after ' + Math.round(gedauert) + ' ms: ' + formel);
289
293
  return { ok: false, txt: tr('detail.formulaTooSlow', Math.round(gedauert)), fehler: true };
290
294
  }
291
295
  if (sch !== null) {
@@ -375,6 +379,49 @@ var FELDTEIL = "\\??\\.(?:[A-Za-z_$][\\w$]*|\\[(?:'(?:[^'\\\\]|\\\\.)*'|\"(?:[^\
375
379
  var FELDPFAD = new RegExp('^JSON\\.parse\\(val\\)((?:' + FELDTEIL + ')+)(?:\\s*\\?\\?\\s*null)?$');
376
380
  var FELDSTUECK = new RegExp(FELDTEIL, 'g');
377
381
 
382
+ /* Der Feldpfad als Text und zurueck (X12, 19.09.2026).
383
+
384
+ Gewoehnlich sind die Stuecke durch Punkte getrennt: `ENERGY.Power`,
385
+ `service.storage./dev/shm.free`. Das bleibt zeichengleich - so stehen
386
+ die Pfade in gespeicherten Vorlagen, und die sollen weiter gelten.
387
+ Nur ein Schluessel, der SELBST einen Punkt enthaelt, steht in Klammern
388
+ ohne Punkt davor: `cpu_usages['frigate.full_system'].cpu`. Vorher
389
+ wurde er an jedem Punkt zerteilt, die Formel suchte
390
+ `?.frigate?.full_system` und ergab null. Frigate hat so einen
391
+ Schluessel in `stats`. Ein Stueck, das mit `[` anfaengt, kommt aus
392
+ demselben Grund in Klammern. */
393
+ export function pfadAus(teile) {
394
+ var raus = '';
395
+ teile.forEach(function (t, n) {
396
+ t = String(t);
397
+ if (t.indexOf('.') > -1 || t.charAt(0) === '[') {
398
+ raus += "['" + t.replace(/\\/g, '\\\\').replace(/'/g, "\\'") + "']";
399
+ } else {
400
+ raus += (n ? '.' : '') + t;
401
+ }
402
+ });
403
+ return raus;
404
+ }
405
+
406
+ export function pfadTeile(pfad) {
407
+ var s = String(pfad || ''), teile = [], i = 0;
408
+ while (i < s.length) {
409
+ if (s.charAt(i) === '.') { i++; continue; }
410
+ if (s.slice(i, i + 2) === "['") {
411
+ var j = i + 2, t = '';
412
+ while (j < s.length && !(s.charAt(j) === "'" && s.charAt(j + 1) === ']')) {
413
+ if (s.charAt(j) === '\\' && j + 1 < s.length) { j++; }
414
+ t += s.charAt(j); j++;
415
+ }
416
+ teile.push(t); i = j + 2; continue;
417
+ }
418
+ var k = i;
419
+ while (k < s.length && s.charAt(k) !== '.' && s.slice(k, k + 2) !== "['") { k++; }
420
+ teile.push(s.slice(i, k)); i = k;
421
+ }
422
+ return teile;
423
+ }
424
+
378
425
  export function feldAusFormel(f) {
379
426
  var m = FELDPFAD.exec(f || '');
380
427
  if (!m) { return ''; }
@@ -386,21 +433,19 @@ export function feldAusFormel(f) {
386
433
  if (s.charAt(0) === '[') {
387
434
  /* Nur die Fluchtzeichen zurueckdrehen, die feldSegment setzt. */
388
435
  s = s.slice(2, -2).replace(/\\(.)/g, '$1');
389
- /* Ein Punkt im Schluessel selbst laesst sich im Pfadformat von
390
- `jsonFelder` nicht wieder auseinanderhalten — dann lieber
391
- „eigene Formel" zeigen als einen Pfad, der nicht zurueckfuehrt. */
392
- if (s.indexOf('.') > -1) { return ''; }
393
436
  }
394
437
  teile.push(s);
395
438
  }
396
- return teile.join('.');
439
+ /* Ein Punkt im Schluessel selbst kommt seit X12 in Klammern zurueck
440
+ (`pfadAus`); vorher hiess das hier „eigene Formel". */
441
+ return pfadAus(teile);
397
442
  }
398
443
 
399
444
  /* Der abgesicherte Zugriff auf ein JSON-Feld. An einer Stelle, damit die
400
445
  Vorlagen-Abkuerzung und die Feldauswahl im Detail dasselbe bauen. */
401
446
  export function feldFormel(feld) {
402
447
  if (!feld) { return ''; }
403
- return 'JSON.parse(val)' + String(feld).split('.').map(feldSegment).join('') + ' ?? null';
448
+ return 'JSON.parse(val)' + pfadTeile(feld).map(feldSegment).join('') + ' ?? null';
404
449
  }
405
450
 
406
451
  /* ---- Feldpfade: Ende ---- */
@@ -412,18 +457,49 @@ export function jsonFelder(id) {
412
457
  try { o = JSON.parse(st.val); } catch { return null; }
413
458
  if (!o || typeof o !== 'object') { return null; }
414
459
  var raus = [];
415
- (function geh(x, pfad, tiefe) {
460
+ (function geh(x, weg, tiefe) {
416
461
  if (tiefe > 3) { return; }
417
462
  Object.keys(x).forEach(function (k) {
418
- var p = pfad ? pfad + '.' + k : k;
419
- if (x[k] && typeof x[k] === 'object' && !Array.isArray(x[k])) { geh(x[k], p, tiefe + 1); }
420
- else { raus.push(p); }
463
+ var w = weg.concat([k]);
464
+ if (x[k] && typeof x[k] === 'object' && !Array.isArray(x[k])) { geh(x[k], w, tiefe + 1); }
465
+ else { raus.push(pfadAus(w)); }
421
466
  });
422
- })(o, '', 0);
467
+ })(o, [], 0);
423
468
  return raus;
424
469
  }
425
470
 
426
471
 
472
+ /* Ist das Objekt ein Taster - ein Punkt ohne Zustand?
473
+
474
+ `read: false` allein reicht nicht (siehe `zielKann`). Dazu muss er
475
+ schreibbar sein und sich als Tastendruck ausweisen: Homematic ueber
476
+ `native.TYPE: ACTION`, alle anderen ueber eine Rolle `button…`. Die
477
+ eine Stelle fuer diese Frage - der Entwurf fragt sie auch. */
478
+ export function istTaster(o) {
479
+ var c = (o && o.common) || {};
480
+ var nat = (o && o.native) || {};
481
+ return c.read === false && !!c.write &&
482
+ (nat.TYPE === 'ACTION' || /^button/.test(String(c.role || '')));
483
+ }
484
+
485
+ /* Wird der Alias-Datenpunkt ein Knopf?
486
+
487
+ Die eine Regel fuer `common.read` am Alias (Ricardo, 19.09.2026): Rolle
488
+ `button…` UND ein Schreibziel -> Knopf, `read: false`. Alles andere
489
+ `read: true`. So steht es in der Rollenliste von ioBroker: „Buttons
490
+ (booleans, write-only) … common.write=true, common.read=false"; der
491
+ Tastensensor (`button.press`, `button.long` ohne Schreiben) liest.
492
+
493
+ Nicht aus der Quelle abgeleitet: deren `read` setzt jeder Adapter
494
+ anders. hm-rpc schreibt `read: false` an `BOOST_MODE`, einen Schalter,
495
+ der seinen Zustand meldet - uebernommen, zeichneten vis, Alexa und
496
+ matter den Boost als Knopf. Und nicht aus einer fehlenden Lesequelle:
497
+ gemessen am Testsystem liest ein Alias mit `read: false` trotzdem aus
498
+ seiner Lesequelle, jeder Druck kommt an. */
499
+ export function knopfZeile(s) {
500
+ return !!(s && s.srcW && /^button/.test(String(s.role || '')));
501
+ }
502
+
427
503
  /* ---- Was das Ziel kann ---------------------------------------------
428
504
 
429
505
  Die Werkbank schreibt auf fremde Punkte und liest aus fremden Punkten.
@@ -440,8 +516,15 @@ export function jsonFelder(id) {
440
516
  Schreibvorgang trotzdem durch — gemessen —, der Adapter
441
517
  dahinter reicht ihn aber nicht ans Geraet weiter.
442
518
  Ein stiller Blindgaenger.
443
- `meldetNichts` Die Lesequelle traegt `read: false`. Ein Tastendruck
444
- hat keinen Zustand; gelesen wird dort nie etwas.
519
+ Bis 19.09.2026 stand an dritter Stelle `meldetNichts`: jede Lesequelle
520
+ mit `read: false` bekam die Marke „aendert sich nie". Gemessen am
521
+ Produktivsystem traf das 1371 Punkte, 620 davon keine Taster, und 76
522
+ dieser 620 hatten ihren Wert in den letzten 30 Tagen geaendert -
523
+ `BOOST_MODE` an den Heizungen etwa. hm-rpc setzt `read: false`, sobald
524
+ der Wert nicht *abfragbar* ist (OPERATIONS ohne Bit 1); gemeldet wird er
525
+ trotzdem. Aus dem Feld allein laesst sich nicht ablesen, ob ein Punkt
526
+ lebt, und wer der Marke folgte, nahm eine funktionierende Lesequelle
527
+ heraus (Ricardo).
445
528
 
446
529
  Gibt eine Liste zurueck, nicht ein Urteil — wer sie anzeigt, entscheidet
447
530
  ueber die Schaerfe. */
@@ -463,10 +546,5 @@ export function zielKann(s) {
463
546
  }
464
547
  }
465
548
 
466
- if (s.srcR) {
467
- var r = S.objects[s.srcR];
468
- var rc = (r && r.common) || null;
469
- if (rc && rc.read === false) { raus.push({ art: 'meldetNichts', punkt: s.srcR }); }
470
- }
471
549
  return raus;
472
550
  }
@@ -11,7 +11,7 @@ import { el } from './basis.js';
11
11
  import { tr } from './sprache.js';
12
12
  import { enumListe } from './aufzaehlungen.js';
13
13
  import { enumZeile, setzeZiel } from './zuordnung.js';
14
- import { aliasFuer, ordnerUnterAlias, kennungtauglich, knotenDa } from './entwurf.js';
14
+ import { aliasFuer, ausgangsQuellen, ordnerUnterAlias, kennungtauglich, knotenDa } from './entwurf.js';
15
15
  import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
16
16
  import { zeigeVerlegen } from './schreiben.js';
17
17
 
@@ -381,7 +381,13 @@ export function baueZielleiste(host, e) {
381
381
  irrt sie hier, irrt sie dort ebenso. Und der Hinweis haelt
382
382
  niemanden auf. */
383
383
  var zwilling = null;
384
- var vorhAlias = aliasFuer(e.kanal);
384
+ /* Dieselbe Frage wie die Vorbelegung, also auch dieselbe Antwort:
385
+ am Mehrfachgeraet der Alias DIESES Ausgangs. Sonst nennt der
386
+ Hinweis einen anderen Alias als den, dessen Stand oben in der
387
+ Liste steht - zwei Aussagen auf einem Bildschirm, die sich
388
+ widersprechen (C13). */
389
+ var vorhAlias = aliasFuer(e.kanal, ausgangsQuellen(e)) ||
390
+ ((e.instanz === null || e.instanz === undefined) ? aliasFuer(e.kanal) : null);
385
391
  if (vorhAlias && S.objects[vorhAlias] && vorhAlias !== e.ziel) {
386
392
  var zw = el('div', 'uebernahme zwilling');
387
393
  zw.appendChild(el('span', 'zq', tr('target.twinExists', vorhAlias)));
@@ -4,7 +4,7 @@
4
4
  import { S } from './zustand.js';
5
5
  import { el } from './basis.js';
6
6
  import { tr, txt } from './sprache.js';
7
- import { enums, enumsUnbekannt } from './enums.js';
7
+ import { enums, enumsUnbekannt, beiEnumsGeladen } from './enums.js';
8
8
  import {
9
9
  enumListe,
10
10
  enumsVon,
@@ -16,7 +16,8 @@ import { enumVorlagen, katalogFehlt, ikonCache, ikonErlaubt, ikonNachtrag,
16
16
  ikonTaugt, vorlageZu, holeIkon } from './katalog.js';
17
17
  import { kindZustaende, aliasQuellen, holeEinzelne,
18
18
  zeileAusAlias } from './werte.js';
19
- import { aliasFuer, zielId, knotenDa } from './entwurf.js';
19
+ import { aliasFuer, ausgangsQuellen, zielId, knotenDa,
20
+ aboErgaenzen, quellenVonEntwurf } from './entwurf.js';
20
21
  import { zeichneErgebnis, entwurfAngefasst, angebotFrisch } from './ergebnis.js';
21
22
 
22
23
 
@@ -237,6 +238,15 @@ export function enumZeile(host, e) {
237
238
  ex.title = tr('enums.clear');
238
239
  ex.setAttribute('aria-label', tr('enums.clear'));
239
240
  ex.hidden = !ei.value;
241
+ /* Aufzaehlungen nicht geladen: dann wird Raum und Funktion nicht
242
+ geschrieben, also laesst sich hier auch nichts waehlen. Vorher
243
+ stand das nur im Trockenlauf, und die Felder sahen aus wie immer
244
+ (P8, 19.09.2026). */
245
+ if (enumsUnbekannt()) {
246
+ ei.disabled = true;
247
+ ex.disabled = true;
248
+ ei.title = tr('enums.unknown');
249
+ }
240
250
  ex.addEventListener('mousedown', function (ev) {
241
251
  ev.preventDefault();
242
252
  e[spec.feld] = '';
@@ -269,7 +279,7 @@ export function enumZeile(host, e) {
269
279
  if (spec.art === 'rooms' && e.zuletzt === 'raum' && e.ziel && !aliasFuer(e.kanal)) {
270
280
  var ro2 = enumAlsOrdner(e.raum);
271
281
  if (ro2 && e.zielOrdner !== 'alias.0.' + ro2) {
272
- var oz = el('div', 'uebernahme' +
282
+ var oz = el('div', 'uebernahme raumangebot' +
273
283
  (angebotFrisch('raum:' + ro2) ? ' frisch' : ''));
274
284
  oz.appendChild(el('span', 'zq', tr('enums.alsoFolder', ro2)));
275
285
  var ob = el('button', 'btn mini wichtig', tr('target.yes'));
@@ -340,15 +350,7 @@ export function enumZeile(host, e) {
340
350
  : (x.anzahl ? tr('enums.members', x.anzahl) : tr('enums.unused'))));
341
351
  z.addEventListener('mousedown', function (ev) {
342
352
  ev.preventDefault();
343
- e[spec.feld] = x.id;
344
- e[spec.her] = 'hand';
345
- if (spec.art === 'rooms') { e.zuletzt = 'raum'; }
346
- /* Das Icon jetzt holen, nicht erst beim Schreiben: dort ist
347
- kein Warten mehr moeglich, der Objektbau laeuft synchron. */
348
- if (x.vorlage && x.vorlage.icon) { holeIkon(spec.art, x.vorlage.icon); }
349
- entwurfAngefasst();
350
- zu();
351
- zeichneErgebnis();
353
+ nimm(x);
352
354
  });
353
355
  el2.appendChild(z);
354
356
  });
@@ -365,6 +367,23 @@ export function enumZeile(host, e) {
365
367
  el2.hidden = false;
366
368
  };
367
369
 
370
+ /* Einen Eintrag der Liste uebernehmen — fuer Mausklick und Enter
371
+ dieselbe Stelle. Bis 19.09.2026 waren es zwei, und der Enter-Weg
372
+ vergass zweierlei: `e.zuletzt`, an dem das Angebot „Den Alias auch
373
+ unter … ablegen?“ haengt, und das Bild einer neuen Aufzaehlung aus
374
+ den Vorlagen des Admin (Lauf vom 19.09.2026, S3). */
375
+ function nimm(x) {
376
+ e[spec.feld] = x.id;
377
+ e[spec.her] = 'hand';
378
+ if (spec.art === 'rooms') { e.zuletzt = 'raum'; }
379
+ /* Das Icon jetzt holen, nicht erst beim Schreiben: dort ist
380
+ kein Warten mehr moeglich, der Objektbau laeuft synchron. */
381
+ if (x.vorlage && x.vorlage.icon) { holeIkon(spec.art, x.vorlage.icon); }
382
+ entwurfAngefasst();
383
+ zu();
384
+ zeichneErgebnis();
385
+ }
386
+
368
387
  ei.addEventListener('focus', function () { ei.value = ''; mMark = -1; malen(); });
369
388
  ei.addEventListener('input', function () { mMark = -1; malen(); });
370
389
  ei.addEventListener('blur', function () {
@@ -386,18 +405,23 @@ export function enumZeile(host, e) {
386
405
  }
387
406
  if (ev.key === 'Enter' && !el2.hidden && mListe.length) {
388
407
  ev.preventDefault();
389
- e[spec.feld] = mListe[mMark >= 0 ? mMark : 0].id;
390
- e[spec.her] = 'hand';
391
- entwurfAngefasst();
392
- zu();
393
- zeichneErgebnis();
408
+ nimm(mListe[mMark >= 0 ? mMark : 0]);
394
409
  }
395
410
  });
396
411
  });
397
412
  if (enumAngebot) { ebar.appendChild(enumAngebot); }
398
413
  host.appendChild(ebar);
414
+ if (enumsUnbekannt()) {
415
+ var eh = el('div', 'aside w', tr('enums.notLoadedField'));
416
+ eh.style.margin = '4px 0 8px';
417
+ host.appendChild(eh);
418
+ }
399
419
  }
400
420
 
421
+ /* Klappt ein Nachversuch, verschwindet der Hinweis von selbst - sonst
422
+ stuende er bis zum naechsten Klick da, obwohl alles wieder geht. */
423
+ beiEnumsGeladen(function () { if (S.current) { zeichneErgebnis(); } });
424
+
401
425
  /* Welcher Raum, welche Funktion - und woher.
402
426
 
403
427
  Gibt es den Alias schon, gilt, was dort steht: seine Zuordnung ist eine
@@ -475,18 +499,35 @@ export function setzeZiel(e) {
475
499
  /* Mehrere Ausgaenge: das Geraet wird zum Ordner, jeder Ausgang
476
500
  ein Kanal darin. Ein folder darueber, kein device — sonst
477
501
  rutscht die Erkennung hoch und macht aus dreien wieder eins. */
478
- if (vorhanden) {
479
- /* Der gefundene Kanal ist einer der Ausgaenge; der Ordner liegt
480
- darueber. Wie der einzelne Ausgang heisst, kann die Werkbank
481
- nicht wissen — wer sie umbenannt hat, sieht den Vorschlag in
482
- der Zielzeile und kann ihn anpassen. */
483
- var tm = vorhanden.split('.');
484
- tm.pop();
485
- e.zielOrdner = tm.join('.');
502
+ /* Gibt es den Alias fuer GENAU DIESEN Ausgang, ist er das Ziel —
503
+ mit seinem eigenen Namen, nicht mit dem der Ausgangsnummer.
504
+
505
+ Hier stand: „Wie der einzelne Ausgang heisst, kann die Werkbank
506
+ nicht wissen." Das galt, solange sie nur nach dem GERAET fragen
507
+ konnte. Seit `ausgangsQuellen` weiss sie es: Ricardos `RF1000`
508
+ liest aus `stat.POWER1` und ist damit Ausgang 1. Vorher schlug
509
+ die Zielzeile `…Steckdosenleiste.POWER1` vor — eine Kennung, die
510
+ es gar nicht gibt —, meldete „wird neu angelegt" und haette beim
511
+ Klick einen zweiten Alias neben `RF1000` gesetzt (C13,
512
+ 16.09.2026). */
513
+ var vorhAus = aliasFuer(S.current, ausgangsQuellen(e));
514
+ if (vorhAus) {
515
+ var ta = vorhAus.split('.');
516
+ e.zielName = ta.pop();
517
+ e.zielOrdner = ta.join('.');
486
518
  } else {
487
- e.zielOrdner = zt0.join('.') + '.' + geraet;
519
+ if (vorhanden) {
520
+ /* Kein Alias fuer diesen Ausgang, aber einer am Geraet: der gibt
521
+ wenigstens den Ordner vor. Der Name kommt aus der
522
+ Ausgangsnummer — hier entsteht wirklich etwas Neues. */
523
+ var tm = vorhanden.split('.');
524
+ tm.pop();
525
+ e.zielOrdner = tm.join('.');
526
+ } else {
527
+ e.zielOrdner = zt0.join('.') + '.' + geraet;
528
+ }
529
+ e.zielName = ausgangName(e, e.instanz);
488
530
  }
489
- e.zielName = ausgangName(e, e.instanz);
490
531
  } else if (vorhanden) {
491
532
  var te = vorhanden.split('.');
492
533
  e.zielName = te.pop();
@@ -583,7 +624,10 @@ export function uebernehmeBestand(e) {
583
624
  function vomAliasUebernehmen(z, o) {
584
625
  var c = o.common || {}, q2 = aliasQuellen(o);
585
626
  var ist = zeileAusAlias(o, z.n);
586
- if (!z.vorlagenWert) {
627
+ /* Dieselbe Frage wie in `bestandVorrang`: ohne Vorlage gibt es keinen
628
+ Vorlagenwert. Sonst verglich die Zeile gegen den Rohentwurf und
629
+ nannte das „weicht von der Vorlage ab" (17.09.2026). */
630
+ if (!z.vorlagenWert && e.vorschlag && e.vorlage) {
587
631
  z.vorlagenWert = {
588
632
  on: z.on, role: z.role, typ: z.typ, unit: z.unit, caption: z.caption,
589
633
  f: z.f, fw: z.fw, srcR: z.srcR, srcW: z.srcW, states: z.states
@@ -768,6 +812,13 @@ export function uebernehmeBestand(e) {
768
812
  });
769
813
  }
770
814
  }
815
+ /* Geholt ist nur der erste Wert - mitlaufen tut er erst mit einem Abo.
816
+ Die Zeilen aus dem Alias lesen oft aus einem anderen Knoten als dem
817
+ angeklickten (J9, 18.09.2026: `Stromzaehler` zeigte drei Zeilen „aus
818
+ Solar.Netz" stundenlang auf dem Stand vom Anklicken). Ergaenzt wird
819
+ nur, was noch nicht laeuft; bei jedem Zeichnen zu rufen kostet also
820
+ nichts. */
821
+ if (S.entwurf === e && e.kanal === S.current) { aboErgaenzen(quellenVonEntwurf(e)); }
771
822
  }
772
823
 
773
824
  export function unterschiede(e) {
@@ -14,6 +14,11 @@ export var S = {
14
14
  objects: {},
15
15
  keysSorted: [],
16
16
  kleinIndex: {},
17
+ /* Zaehlt jede Aenderung an S.objects. Wer sich etwas aus den Objekten
18
+ merkt (die Karte Quelle -> Alias in entwurf.js), vergleicht hiermit
19
+ statt mit der Zahl der Schluessel — beim Verlegen verschwinden genau
20
+ so viele, wie dazukommen (T22). */
21
+ objektStand: 0,
17
22
  /* Alias-Kanal -> Zahl der Punkte, deren Quelle es nicht (mehr) gibt.
18
23
  Einmal beim Laden gerechnet; der Baum schlaegt nur nach. */
19
24
  aliasKaputt: {},
@@ -44,7 +49,6 @@ export var S = {
44
49
  loeschListe: [],
45
50
  loeschZiel: null,
46
51
  loeschAlleAusgaenge: false,
47
- verlegeZiel: null,
48
52
  /* Einmal registrierter Schliesser fuer die Quellenauswahl am
49
53
  Sprungknopf - siehe ergebnis.js. */
50
54
  sprungZuhoerer: false,