Bearbeiten von „OS2.spielplan

Zur Navigation springen Zur Suche springen
Warnung: Du bist nicht angemeldet. Deine IP-Adresse wird bei Bearbeitungen öffentlich sichtbar. Melde dich an oder erstelle ein Benutzerkonto, damit Bearbeitungen deinem Benutzernamen zugeordnet werden. Ein eigenes Benutzerkonto hat eine ganze Reihe von Vorteilen.

Die Bearbeitung kann rückgängig gemacht werden. Bitte prüfe den Vergleich unten, um sicherzustellen, dass du dies tun möchtest, und veröffentliche dann unten deine Änderungen, um die Bearbeitung rückgängig zu machen.

Aktuelle Version Dein Text
Zeile 1: Zeile 1:
[[Kategorie:Greasemonkey]]
[[Kategorie:Greasemonkey]]
[[Kategorie:Greasemonkey WE]]
{| style="background-color:white; font-size:11px; float: right; margin:3px 3px 3px 10px; border:1px solid #999; border-color: #9C1818; border-collapse:collapse;" width=500 cellpadding=3 cellspacing=0
{| style="background-color:white; font-size:11px; float: right; margin:3px 3px 3px 10px; border:1px solid #999; border-color: #9C1818; border-collapse:collapse;" width=500 cellpadding=3 cellspacing=0
| colspan="2" style="padding:0.3em; background-color:#9C1818; font-size: 18px; color:#FFFFFF" align=center| '''OS2.spielplan'''
| colspan="2" style="padding:0.3em; background-color:#9C1818; font-size: 18px; color:#FFFFFF" align=center| '''OS2.spielplan'''
Zeile 8: Zeile 7:
|- bgcolor="#FFCC00"
|- bgcolor="#FFCC00"
| '''Version'''
| '''Version'''
| '''0.73 (WebExtensions)'''  
| '''0.71'''  
|- bgcolor="#FFCC00"
|- bgcolor="#FFCC00"
| '''Autor'''
| '''Autor'''
Zeile 20: Zeile 19:
|- bgcolor="#FFCC00"
|- bgcolor="#FFCC00"
| '''Funktionalität'''
| '''Funktionalität'''
| '''Trennstriche zwischen den Abrechnungsmonaten'''<br> '''Verkürzung von "Vorbericht(e)" und "Kommentar(e)"'''<br> '''Details zu den Spielen'''<br> '''Ergebnisse aufaddieren'''<br> '''Nachträgliche Vorschau: Bilanz'''<br> '''Benutzermenü für Optionen'''<br> '''Erweiterte Optionen auch auf der Seite'''<br> '''Link auf den jeweiligen Spieltag bzw. die jeweilige Runde'''<br> '''Interaktive Menü-Optionen'''<br> '''Gemeinsame Code- und Datenbasis'''<br> '''Gezielte "hl"-Links auf die eigenen Spiele'''
| '''Trennstriche zwischen den Abrechnungsmonaten'''<br> '''Verkürzung von "Vorbericht(e)" und "Kommentar(e)"'''<br> '''Details zu den Spielen'''<br> '''Ergebnisse aufaddieren'''<br> '''Nachträgliche Vorschau: Bilanz'''<br> '''Benutzermenü für Optionen'''<br> '''Erweiterte Optionen auch auf der Seite'''<br> '''Link auf den jeweiligen Spieltag bzw. die jeweilige Runde'''<br> '''Interaktive Menü-Optionen'''<br> '''Gemeinsame Code- und Datenbasis'''
|- bgcolor="#FFCC00"
|- bgcolor="#FFCC00"
| '''Letzte Änderung'''
| '''Letzte Änderung'''
Zeile 32: Zeile 31:
// @name        OS2.spielplan
// @name        OS2.spielplan
// @namespace    http://os.ongapo.com/
// @namespace    http://os.ongapo.com/
// @version      0.73
// @version      0.70
// @copyright    2013+
// @copyright    2013+
// @author      Sven Loges (SLC)
// @author      Sven Loges (SLC)
// @description  Spielplan-Abschnitt aus dem Master-Script fuer Online Soccer 2.0
// @description  Spielplan-Abschnitt aus dem Master-Script fuer Online Soccer 2.0
// @include      /^https?://(www\.)?(os\.ongapo\.com|online-soccer\.eu|os-zeitungen\.com)/(st|showteam)\.php\?s=6(&\w+=?[+\w]+)*(#\w+)?$/
// @include      /^https?://(www\.)?(os\.ongapo\.com|online-soccer\.eu|os-zeitungen\.com)/(st|showteam)\.php\?s=6(&\S+)*$/
// @grant        GM.getValue
// @grant        GM.setValue
// @grant        GM.deleteValue
// @grant        GM.registerMenuCommand
// @grant        GM.info
// @require      https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant        GM_getValue
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_setValue
Zeile 50: Zeile 43:
// ==/UserScript==
// ==/UserScript==


// ECMAScript 6:
// ECMAScript 6: Erlaubt 'const', 'let', ...
/* jshint esnext: true */
/* jshint esnext: true */
/* jshint moz: true */
/* jshint moz: true */
Zeile 144: Zeile 137:
                   'Name'      : "sepStyle",
                   'Name'      : "sepStyle",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'String',
                   'ValType'  : "String",
                   'Choice'    : [ 'solid', 'hidden', 'dotted', 'dashed', 'double', 'groove', 'ridge',
                   'Choice'    : [ "solid", "hidden", "dotted", "dashed", "double", "groove", "ridge",
                                   'inset', 'outset', 'none' ],
                                   "inset", "outset", "none" ],
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
                   'Label'    : "Stil: $",
                   'Label'    : "Stil: $",
Zeile 155: Zeile 148:
                   'Name'      : "sepColor",
                   'Name'      : "sepColor",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'String',
                   'ValType'  : "String",
                   'FreeValue' : true,
                   'FreeValue' : true,
                   'Choice'    : [ 'white', 'yellow', 'black', 'blue', 'cyan', 'gold', 'grey', 'green',
                   'Choice'    : [ "white", "yellow", "black", "blue", "cyan", "gold", "grey", "green",
                                   'lime', 'magenta', 'maroon', 'navy', 'olive', 'orange', 'purple',
                                   "lime", "magenta", "maroon", "navy", "olive", "orange", "purple",
                                   'red', 'teal', 'transparent' ],
                                   "red", "teal", "transparent" ],
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
                   'Label'    : "Farbe: $",
                   'Label'    : "Farbe: $",
Zeile 168: Zeile 161:
                   'Name'      : "sepWidth",
                   'Name'      : "sepWidth",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'String',
                   'ValType'  : "String",
                   'FreeValue' : true,
                   'FreeValue' : true,
                   'Choice'    : [ 'thin', 'medium', 'thick' ],
                   'Choice'    : [ "thin", "medium", "thick" ],
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
                   'Label'    : "Dicke: $",
                   'Label'    : "Dicke: $",
Zeile 176: Zeile 169:
                   'FormLabel' : "Dicke:|$"
                   'FormLabel' : "Dicke:|$"
               },
               },
     'saison' : {          // Angezeigte Saison
     'saison' : {          // Laufende Saison
                   'Name'      : "saison",
                   'Name'      : "saison",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'Number',
                   'ValType'  : "Number",
                   'FreeValue' : true,
                   'FreeValue' : true,
                   'SelValue'  : false,
                   'SelValue'  : false,
                   'Choice'    : [ 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 ],
                   'Choice'    : [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 ],
                   'Default'  : 18,
                   'Default'  : 11,
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
                   'Label'    : "Saison: $",
                   'Label'    : "Saison: $",
                   'Hotkey'    : 's',
                   'Hotkey'    : 'a',
                   'FormLabel' : "Saison:|$"
                   'FormLabel' : "Saison:|$"
               },
               },
Zeile 192: Zeile 185:
                   'Name'      : "ligaSize",
                   'Name'      : "ligaSize",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'Number',
                   'ValType'  : "Number",
                   'AutoReset' : true,
                   'AutoReset' : true,
                   'Choice'    : [ 10, 18, 20 ],
                   'Choice'    : [ 10, 18, 20 ],
Zeile 206: Zeile 199:
                   'Serial'    : true,
                   'Serial'    : true,
                   'Permanent' : true,
                   'Permanent' : true,
                   'Default'  : undefined,  // new Team() // { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined, 'TmNr' : 0, 'LdNr' : 0, 'LgNr' : 0 }
                   'Default'  : undefined,  // new Team() // { 'Team' : undefined, 'Liga' : undefined, 'Land' : undefined, 'LdNr' : 0, 'LgNr' : 0 }
                   'Submit'    : undefined,
                   'Submit'    : undefined,
                   'Cols'      : 36,
                   'Cols'      : 36,
Zeile 215: Zeile 208:
               },
               },
     'reset' : {          // Optionen auf die "Werkseinstellungen" zuruecksetzen
     'reset' : {          // Optionen auf die "Werkseinstellungen" zuruecksetzen
                  'FormPrio'  : undefined,
                   'Name'      : "reset",
                   'Name'      : "reset",
                   'Type'      : __OPTTYPES.SI,
                   'Type'      : __OPTTYPES.SI,
Zeile 224: Zeile 216:
               },
               },
     'storage' : {        // Browserspeicher fuer die Klicks auf Optionen
     'storage' : {        // Browserspeicher fuer die Klicks auf Optionen
                  'FormPrio'  : undefined,
                   'Name'      : "storage",
                   'Name'      : "storage",
                   'Type'      : __OPTTYPES.MC,
                   'Type'      : __OPTTYPES.MC,
                   'ValType'  : 'String',
                   'ValType'  : "String",
                   'Choice'    : Object.keys(__OPTMEM),
                   'Choice'    : Object.keys(__OPTMEM),
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
Zeile 235: Zeile 226:
               },
               },
     'oldStorage' : {      // Vorheriger Browserspeicher fuer die Klicks auf Optionen
     'oldStorage' : {      // Vorheriger Browserspeicher fuer die Klicks auf Optionen
                  'FormPrio'  : undefined,
                   'Name'      : "oldStorage",
                   'Name'      : "oldStorage",
                   'Type'      : __OPTTYPES.SD,
                   'Type'      : __OPTTYPES.SD,
Zeile 243: Zeile 233:
               },
               },
     'showForm' : {        // Optionen auf der Webseite (true = anzeigen, false = nicht anzeigen)
     'showForm' : {        // Optionen auf der Webseite (true = anzeigen, false = nicht anzeigen)
                  'FormPrio'  : undefined,
                   'Name'      : "showForm",
                   'Name'      : "showForm",
                   'Type'      : __OPTTYPES.SW,
                   'Type'      : __OPTTYPES.SW,
Zeile 249: Zeile 238:
                   'Permanent' : true,
                   'Permanent' : true,
                   'Default'  : false,
                   'Default'  : false,
                  'Title'    : "$V Optionen",
                   'Action'    : __OPTACTION.NXT,
                   'Action'    : __OPTACTION.NXT,
                   'Label'    : "Optionen anzeigen",
                   'Label'    : "Optionen anzeigen",
                   'Hotkey'    : 'a',
                   'Hotkey'    : 'a',
                  'AltTitle'  : "$V schlie\xDFen",
                   'AltLabel'  : "Optionen verbergen",
                   'AltLabel'  : "Optionen verbergen",
                   'AltHotkey' : 'v',
                   'AltHotkey' : 'v',
Zeile 264: Zeile 251:
// Ein Satz von Logfunktionen, die je nach Loglevel zur Verfuegung stehen. Aufruf: __LOG[level](text)
// Ein Satz von Logfunktionen, die je nach Loglevel zur Verfuegung stehen. Aufruf: __LOG[level](text)
const __LOG = {
const __LOG = {
                   'logFun'   : [
                   'logFun'   : [
                                    console.error,  // [0] Alert
                                  console.error,  // [0] Alert
                                    console.error,  // [1] Error
                                  console.error,  // [1] Error
                                    console.log,    // [2] Log: Release
                                  console.log,    // [2] Log: Release
                                    console.log,    // [3] Log: Info
                                  console.log,    // [3] Log: Info
                                    console.log,    // [4] Log: Debug
                                  console.log,    // [4] Log: Debug
                                    console.log,    // [5] Log: Verbose
                                  console.log,    // [5] Log: Verbose
                                    console.log,    // [6] Log: Very verbose
                                  console.log     // [6] Log: Very verbose
                                    console.log    // [7] Log: Testing
                              ],
                                ],
                   'init'     : function(win, logLevel = 1) {
                   'init'     : function(win, logLevel = 1) {
                                  for (level = 0; level < this.logFun.length; level++) {
                                    for (let level = 0; level < this.logFun.length; level++) {
                                      this[level] = ((level > logLevel) ? function() { } : this.logFun[level]);
                                        this[level] = ((level > logLevel) ? function() { } : this.logFun[level]);
                                  }
                                    }
                              },
                                },
                   'changed' : function(oldVal, newVal) {
                  'stringify' : safeStringify,      // JSON.stringify
                                  const __OLDVAL = safeStringify(oldVal);
                   'changed'   : function(oldVal, newVal) {
                                  const __NEWVAL = safeStringify(newVal);
                                    const __OLDVAL = this.stringify(oldVal);
                                    const __NEWVAL = this.stringify(newVal);


                                    return ((__OLDVAL !== __NEWVAL) ? __OLDVAL + " => " : "") + __NEWVAL;
                                  return ((__OLDVAL !== __NEWVAL) ? __OLDVAL + " => " : "") + __NEWVAL;
                                }
                              }
               };
               };


Zeile 325: Zeile 310:
// message: Der Meldungs-Text
// message: Der Meldungs-Text
// data: Ein Wert. Ist er angegeben, wird er in der Console ausgegeben
// data: Ein Wert. Ist er angegeben, wird er in der Console ausgegeben
// return Liefert die Parameter zurueck
function showAlert(label, message, data = undefined) {
function showAlert(label, message, data = undefined) {
     __LOG[0](label + ": " + message);
     __LOG[1](label + ": " + message);


     if (data !== undefined) {
     if (data !== undefined) {
Zeile 334: Zeile 318:


     alert(label + "\n\n" + message);
     alert(label + "\n\n" + message);
    return arguments;
}
// Gibt eine Meldung in der Console aus und oeffnet ein Bestaetigungsfenster
// mit der Meldung zu einer Exception oder einer Fehlermeldung
// label: Eine Ueberschrift
// ex: Exception oder sonstiges Fehlerobjekt
// return Liefert die showAlert()-Parameter zurueck
function showException(label, ex) {
    if (ex && ex.message) {  // Exception
        showAlert(label, ex.message, ex);
    } else {  // sonstiger Fehler
        showAlert(label, ex);
    }
}
// Standard-Callback-Funktion fuer onRejected, also abgefangener Fehler
// in einer Promise bei Exceptions oder Fehler bzw. Rejections
// error: Parameter von reject() im Promise-Objekt, der von Promise.catch() erhalten wurde
// return Liefert die showAlert()-Parameter zurueck
function defaultCatch(error) {
    try {
        const __LABEL = `[${error.lineNumber}] ${__DBMOD.Name}`;
        if (error && error.message) {  // Exception
            return showException(__LABEL, error.message, error);
        } else {
            return showException(__LABEL, error);
        }
    } catch (ex) {
        return showException(`[${ex.lineNumber}] ${__DBMOD.Name}`, ex.message, ex);
    }
}
}


Zeile 472: Zeile 423:
                                         return this.className;
                                         return this.className;
                                     }
                                     }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Class ====================
// ==================== Ende Abschnitt fuer Klasse Class ====================
Zeile 519: Zeile 470:
                                     this.home = home;
                                     this.home = home;
                                 }
                                 }
           });
           } );


// ==================== Ende Abschnitt fuer Klasse Delims ====================
// ==================== Ende Abschnitt fuer Klasse Delims ====================
Zeile 598: Zeile 549:
                                     this.node = node;
                                     this.node = node;
                                 }
                                 }
           });
           } );


// ==================== Ende Abschnitt fuer Klasse UriDelims ====================
// ==================== Ende Abschnitt fuer Klasse UriDelims ====================
Zeile 697: Zeile 648:
                                         return __DIRS.slice(1);
                                         return __DIRS.slice(1);
                                     }
                                     }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Path ====================
// ==================== Ende Abschnitt fuer Klasse Path ====================
Zeile 855: Zeile 806:
                                             const __LOWER = (value ? value.toLowerCase() : undefined);
                                             const __LOWER = (value ? value.toLowerCase() : undefined);


                                             if ((__LOWER === 'true') || (__LOWER === 'false')) {
                                             if ((__LOWER === "true") || (__LOWER === "false")) {
                                                 return (value === 'true');
                                                 return (value === "true");
                                             }
                                             }
                                         }
                                         }
Zeile 908: Zeile 859:
                                         return Path.prototype.getDirs.call(this, __PATH);
                                         return Path.prototype.getDirs.call(this, __PATH);
                                     }
                                     }
           });
           } );


// ==================== Ende Abschnitt fuer Klasse URI ====================
// ==================== Ende Abschnitt fuer Klasse URI ====================
Zeile 948: Zeile 899:
                                   return this.getPath();
                                   return this.getPath();
                               }
                               }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Directory ====================
// ==================== Ende Abschnitt fuer Klasse Directory ====================
Zeile 976: Zeile 927:
                                     return ret;
                                     return ret;
                                 }
                                 }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse ObjRef ====================
// ==================== Ende Abschnitt fuer Klasse ObjRef ====================
Zeile 1.021: Zeile 972:


// Gibt ein Produkt zurueck. Ist einer der Multiplikanten nicht definiert, wird ein Alternativwert geliefert
// Gibt ein Produkt zurueck. Ist einer der Multiplikanten nicht definiert, wird ein Alternativwert geliefert
// valueA: Ein Multiplikant. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert
// valueA: Ein Multipliksnt. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert
// valueB: Ein Multiplikant. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert
// valueB: Ein Multipliksnt. Ist dieser undefined, wird als Produkt defValue zurueckgeliefert
// digits: Anzahl der Stellen nach dem Komma fuer das Produkt (Default: 0)
// digits: Anzahl der Stellen nach dem Komma fuer das Produkt (Default: 0)
// defValue: Default-Wert fuer den Fall, dass ein Multiplikant nicht gesetzt ist (Default: NaN)
// defValue: Default-Wert fuer den Fall, dass ein Multiplikant nicht gesetzt ist (Default: NaN)
Zeile 1.038: Zeile 989:


     return parseFloat(product.toFixed(digits));
     return parseFloat(product.toFixed(digits));
}
// Gibt eine Ordinalzahl zur uebergebenen Zahl zurueck
// value: Eine ganze Zahl
// defValue: Default-Wert fuer den Fall, dass der Wert nicht gesetzt ist (Default: '*')
// return Die Ordinalzahl als String der Form "n." oder defValue, falls nicht angegeben
function getOrdinal(value, defValue = '*') {
    return getValue(value, defValue, value + '.');
}
}


Zeile 1.062: Zeile 1.005:
function instanceOf(obj, base) {
function instanceOf(obj, base) {
     while (obj !== null) {
     while (obj !== null) {
         if (obj === base.prototype) {
         if (obj === base.prototype)
             return true;
             return true;
        }
         if ((typeof obj) === 'xml') {  // Sonderfall mit Selbstbezug
         if ((typeof obj) === 'xml') {  // Sonderfall mit Selbstbezug
             return (base.prototype === XML.prototype);
             return (base.prototype === XML.prototype);
Zeile 1.142: Zeile 1.084:
}
}


// Entfernt Properties in einem Objekt
// Entfernt Properties in einem Objekt.
// data: Objekt, deren Properties bearbeitet werden
// data: Objekt, deren Properties bearbeitet werden
// delList: Checkliste der zu loeschenden Items (true fuer loeschen), falls angegeben
// delList: Checkliste der zu loeschenden Items (true fuer loeschen), falls angegeben
Zeile 1.232: Zeile 1.174:
}
}


// Replacer fuer JSON.stringify() oder safeStringify(), der Arrays kompakter darstellt
// Replacer fuer JSON.stringify() oder safeStringify(), der Arrays kompakter darstellt.
// key: Der uebergebene Schluessel
// key: Der uebergebene Schluessel
// value: Der uebergebene Wert
// value: Der uebergebene Wert
Zeile 1.244: Zeile 1.186:
}
}


// Replacer fuer JSON.stringify() oder safeStringify(), der Arrays kompakter darstellt
// Replacer fuer JSON.stringify() oder safeStringify(), der Arrays kompakter darstellt.
// key: Der uebergebene Schluessel
// key: Der uebergebene Schluessel
// value: Der uebergebene Wert
// value: Der uebergebene Wert
Zeile 1.258: Zeile 1.200:


     return value;
     return value;
}
// Moegliche einfache Ersetzungen mit '$'...
let textSubst;
// Substituiert '$'-Parameter in einem Text
// text: Urspruenglicher Text mit '$'-Befehlen
// par1: Der (erste) uebergebene Parameter
// return Fuer Arrays eine kompakte Darstellung, sonst derselbe Wert
function substParam(text, par1) {
    let ret = getValue(text, "");
    if (! textSubst) {
        textSubst  = {
                'n' : __DBMOD.name,
                'v' : __DBMOD.version,
                'V' : __DBMOD.Name
            };
    }
    for (let ch in textSubst) {
        const __SUBST = textSubst[ch];
        ret = ret.replace('$' + ch, __SUBST);
    }
    return ret.replace('$', par1);
}
}


// Fuegt in die uebergebene Zahl Tausender-Trennpunkte ein
// Fuegt in die uebergebene Zahl Tausender-Trennpunkte ein
// Wandelt einen etwaig vorhandenen Dezimalpunkt in ein Komma um
// Wandelt einen etwaig vorhandenen Dezimalpunkt in ein Komma um
// numberString: Dezimalzahl als String
// return Diese Dezimalzahl als String mit Tausender-Trennpunkten und Komma statt Dezimalpunkt
function getNumberString(numberString) {
function getNumberString(numberString) {
     if (numberString.lastIndexOf('.') !== -1) {
     if (numberString.lastIndexOf(".") !== -1) {
         // Zahl enthaelt Dezimalpunkt
         // Zahl enthaelt Dezimalpunkt
         const __VORKOMMA = numberString.substring(0, numberString.lastIndexOf('.'));
         const __VORKOMMA = numberString.substring(0, numberString.lastIndexOf("."));
         const __NACHKOMMA = numberString.substring(numberString.lastIndexOf('.') + 1, numberString.length);
         const __NACHKOMMA = numberString.substring(numberString.lastIndexOf(".") + 1, numberString.length);


         return getNumberString(__VORKOMMA) + ',' + __NACHKOMMA;
         return getNumberString(__VORKOMMA) + "," + __NACHKOMMA;
     } else {
     } else {
         // Kein Dezimalpunkt, fuege Tausender-Trennpunkte ein:
         // Kein Dezimalpunkt, fuege Tausender-Trennpunkte ein:
Zeile 1.306: Zeile 1.219:
         for (let i = 0; i < __TEMP.length; i++) {
         for (let i = 0; i < __TEMP.length; i++) {
             if ((i > 0) && (i % 3 === 0)) {
             if ((i > 0) && (i % 3 === 0)) {
                 result += '.';
                 result += ".";
             }
             }
             result += __TEMP.substr(i, 1);
             result += __TEMP.substr(i, 1);
Zeile 1.316: Zeile 1.229:


// Dreht den uebergebenen String um
// Dreht den uebergebenen String um
// string: Eine Zeichenkette
// return Dieselbe Zeichenkette rueckwaerts
function reverseString(string) {
function reverseString(string) {
     let result = "";
     let result = "";
Zeile 1.328: Zeile 1.239:
}
}


// Speichert einen String/Integer/Boolean-Wert unter einem Namen ab
// Speichert einen beliebiegen (strukturierten) Wert unter einem Namen ab
// name: GM.setValue()-Name, unter dem die Daten gespeichert werden
// name: GM_setValue-Name, unter dem die Daten gespeichert werden
// value: Zu speichernder String/Integer/Boolean-Wert
// value: Beliebiger (strukturierter) Wert
// return Promise auf ein Objekt, das 'name' und 'value' der Operation enthaelt
// return String-Darstellung des Wertes
function storeValue(name, value) {
function serialize(name, value) {
     __LOG[4](name + " >> " + value);
     const __STREAM = ((value !== undefined) ? safeStringify(value) : value);


     return GM.setValue(name, value).then(voidValue => {
     __LOG[4](name + " >> " + __STREAM);
            __LOG[5]("OK " + name + " >> " + value);


            return Promise.resolve({
     GM_setValue(name, __STREAM);
                    'name'  : name,
 
                    'value' : value
     return __STREAM;
                });
        }, defaultCatch);
}
 
// Holt einen String/Integer/Boolean-Wert unter einem Namen zurueck
// name: GM.getValue()-Name, unter dem die Daten gespeichert wurden
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist
// return Promise fuer den String/Integer/Boolean-Wert, der unter dem Namen gespeichert war
function summonValue(name, defValue = undefined) {
     return GM.getValue(name, defValue).then(value => {
            __LOG[4](name + " << " + value);
 
            return Promise.resolve(value);
        }, ex => {
            __LOG[0](name + ": " + ex.message);
 
            return Promise.reject(ex);
        }, defaultCatch);
}
 
// Speichert einen beliebiegen (strukturierten) Wert unter einem Namen ab
// name: GM.setValue()-Name, unter dem die Daten gespeichert werden
// value: Beliebiger (strukturierter) Wert
// return Promise auf ein Objekt, das 'name' und 'value' in der String-Darstellung des Wertes enthaelt
function serialize(name, value) {
    const __STREAM = ((value !== undefined) ? safeStringify(value) : value);
 
     return storeValue(name, __STREAM);
}
}


// Holt einen beliebiegen (strukturierter) Wert unter einem Namen zurueck
// Holt einen beliebiegen (strukturierter) Wert unter einem Namen zurueck
// name: GM.getValue()-Name, unter dem die Daten gespeichert wurden
// name: GM_setValue-Name, unter dem die Daten gespeichert werden
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist
// defValue: Default-Wert fuer den Fall, dass nichts gespeichert ist
// return Promise fuer das Objekt, das unter dem Namen gespeichert war
// return Objekt, das unter dem Namen gespeichert war
function deserialize(name, defValue = undefined) {
function deserialize(name, defValue = undefined) {
     return summonValue(name).then(stream => {
     const __STREAM = GM_getValue(name);
            if (stream && stream.length) {
 
                return JSON.parse(stream);
    __LOG[4](name + " << " + __STREAM);
            } else {
                return defValue;
            }
        });
}


// Setzt die Seite gemaess der Aenderungen zurueck...
    if ((__STREAM !== undefined) && __STREAM.length) {
// reload: Seite wird ganz neu geladen
        try {
function refreshPage(reload = true) {
            return JSON.parse(__STREAM);
    if (reload) {
        } catch (ex) {
        __LOG[2]("Seite wird neu geladen...");
            __LOG[1](name + ": " + ex.message);
         window.location.reload();
         }
     }
     }
    return defValue;
}
}


Zeile 1.398: Zeile 1.277:
// value: Zu setzender Wert
// value: Zu setzender Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// serial: Serialization fuer komplexe Daten
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gespeicherter Wert fuer setOptValue()
// return Gespeicherter Wert fuer setOptValue()
function setStored(name, value, reload = false, serial = false, onFulfilled = undefined, onRejected = undefined) {
function setStored(name, value, reload = false, serial = false) {
     (serial ? serialize(name, value)
     if (serial) {
            : storeValue(name, value))
        serialize(name, value);
                .then(onFulfilled, onRejected)
    } else {
                .then(() => refreshPage(reload), defaultCatch); // Ende der Kette...
        GM_setValue(name, value);
    }
 
    if (reload) {
        window.location.reload();
    }


     return value;
     return value;
Zeile 1.416: Zeile 1.297:
// value: Vorher gesetzter Wert
// value: Vorher gesetzter Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// serial: Serialization fuer komplexe Daten
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gespeicherter Wert fuer setOptValue()
// return Gespeicherter Wert fuer setOptValue()
function setNextStored(arr, name, value, reload = false, serial = false, onFulfilled = undefined, onRejected = undefined) {
function setNextStored(arr, name, value, reload = false, serial = false) {
     return setStored(name, getNextValue(arr, value), reload, serial, onFulfilled, onRejected);
     return setStored(name, getNextValue(arr, value), reload, serial);
}
}


Zeile 1.449: Zeile 1.327:
                 value = JSON.parse(value);
                 value = JSON.parse(value);
             } catch (ex) {
             } catch (ex) {
                 __LOG[0]("getStoredCmds(): " + __CMD + " '" + __KEY + "' hat illegalen Wert '" + value + "'");
                 __LOG[1]("getStoredCmds(): " + __CMD + " '" + __KEY + "' hat illegalen Wert '" + value + "'");
                 // ... meist kann man den String selber aber speichern, daher kein "return"...
                 // ... meist kann man den String selber aber speichern, daher kein "return"...
             }
             }
Zeile 1.470: Zeile 1.348:
// Fuehrt die in einem Storage gespeicherte Operation aus
// Fuehrt die in einem Storage gespeicherte Operation aus
// storedCmds: Array von Objekten mit 'cmd' / 'key' / 'val' (siehe getStoredCmds())
// storedCmds: Array von Objekten mit 'cmd' / 'key' / 'val' (siehe getStoredCmds())
// optSet: Object mit den Optionen
// optSet: Set mit den Optionen
// beforeLoad: Angabe, ob nach der Speicherung noch loadOptions() aufgerufen wird
// beforeLoad: Angabe, ob nach der Speicherung noch loadOptions() aufgerufen wird
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// memory: __OPTMEM.normal = unbegrenzt gespeichert (localStorage), __OPTMEM.begrenzt = bis Browserende gespeichert (sessionStorage), __OPTMEM.inaktiv
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Array von Operationen (wie storedCmds), die fuer die naechste Phase uebrig bleiben
// return Promise auf ein Array von Operationen (wie storedCmds), die fuer die naechste Phase uebrig bleiben
function runStoredCmds(storedCmds, optSet = undefined, beforeLoad = undefined) {
async function runStoredCmds(storedCmds, optSet = undefined, beforeLoad = undefined, onFulfilled = undefined, onRejected = undefined) {
     const __BEFORELOAD = getValue(beforeLoad, true);
     const __BEFORELOAD = getValue(beforeLoad, true);
     const __STOREDCMDS = getValue(storedCmds, []);
     const __STOREDCMDS = getValue(storedCmds, []);
Zeile 1.489: Zeile 1.366:
         if (__BEFORELOAD) {
         if (__BEFORELOAD) {
             if (__STOREDCMDS.length) {
             if (__STOREDCMDS.length) {
                 await invalidateOpts(optSet);  // alle Optionen invalidieren
                 invalidateOpts(optSet);  // alle Optionen invalidieren
                 invalidated = true;
                 invalidated = true;
             }
             }
             switch (__OPTACTION[__CMD]) {
             switch (__OPTACTION[__CMD]) {
             case __OPTACTION.SET : __LOG[4]("SET '" + __KEY + "' " + __VAL);
             case __OPTACTION.SET : __LOG[4]("SET '" + __KEY + "' " + __VAL);
                                   setStored(__KEY, __VAL, false, false, onFulfilled, onRejected);
                                   setStored(__KEY, __VAL, false, false);
                                   break;
                                   break;
             case __OPTACTION.NXT : __LOG[4]("SETNEXT '" + __KEY + "' " + __VAL);
             case __OPTACTION.NXT : __LOG[4]("SETNEXT '" + __KEY + "' " + __VAL);
                                   //setNextStored(__CONFIG.Choice, __KEY, __VAL, false, false, onFulfilled, onRejected);
                                   //setNextStored(__CONFIG.Choice, __KEY, __VAL, false, false);
                                   setStored(__KEY, __VAL, false, false, onFulfilled, onRejected);
                                   setStored(__KEY, __VAL, false, false);
                                   break;
                                   break;
             case __OPTACTION.RST : __LOG[4]("RESET (delayed)");
             case __OPTACTION.RST : __LOG[4]("RESET (delayed)");
Zeile 1.511: Zeile 1.388:
                                   break;
                                   break;
             case __OPTACTION.RST : __LOG[4]("RESET");
             case __OPTACTION.RST : __LOG[4]("RESET");
                                   await resetOptions(optSet, false);
                                   resetOptions(optSet, false);
                                   await loadOptions(optSet);  // Reset auf umbenannte Optionen anwenden!
                                   loadOptions(optSet);  // Reset auf umbenannte Optionen anwenden!
                                   break;
                                   break;
             default :              break;
             default :              break;
Zeile 1.614: Zeile 1.491:
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// return Gesetzter Wert
// return Gesetzter Wert
function getOptValue(opt, defValue = undefined, load = true, asyncLoad = false, force = false) {
function getOptValue(opt, defValue = undefined, load = true, force = false) {
     let value;
     let value;


     if (opt !== undefined) {
     if (opt !== undefined) {
         if (load && ! opt.Loaded) {
         if (load && ! opt.Loaded) {
             if (! opt.Promise) {
             value = loadOption(opt, force);
                loadOption(opt, force);
            }
            if (! asyncLoad) {
                __LOG[0]("Warnung: getOptValue(" + getOptName(opt) + ") fordert zum Nachladen auf, daher nur Default-Wert!");
            }
         } else {
         } else {
             value = opt.Value;
             value = opt.Value;
Zeile 1.745: Zeile 1.617:
// Restauriert den vorherigen Speicher (der in einer Option definiert ist)
// Restauriert den vorherigen Speicher (der in einer Option definiert ist)
// opt: Option zur Wahl des Speichers
// opt: Option zur Wahl des Speichers
// return Promise auf gesuchten Speicher oder Null-Speicher ('inaktiv')
// return Gesuchter Speicher oder Null-Speicher ('inaktiv')
async function restoreMemoryByOpt(opt) {
function restoreMemoryByOpt(opt) {
     // Memory Storage fuer vorherige Speicherung...
     // Memory Storage fuer vorherige Speicherung...
     const __STORAGE = await getOptValue(opt, __MEMNORMAL, true, true, true);
     const __STORAGE = getOptValue(opt, __MEMNORMAL, true, true);


     return __OPTMEM[__STORAGE];
     return __OPTMEM[__STORAGE];
Zeile 1.756: Zeile 1.628:
// opt: Option zur Wahl des Speichers
// opt: Option zur Wahl des Speichers
// saveOpt: Option zur Speicherung der Wahl des Speichers (fuer restoreMemoryByOpt)
// saveOpt: Option zur Speicherung der Wahl des Speichers (fuer restoreMemoryByOpt)
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesuchter Speicher oder Null-Speicher ('inaktiv'), falls speichern nicht moeglich ist
// return Gesuchter Speicher oder Null-Speicher ('inaktiv'), falls speichern nicht moeglich ist
function startMemoryByOpt(opt, saveOpt = undefined, onFulfilled = undefined, onRejected = undefined) {
function startMemoryByOpt(opt, saveOpt = undefined) {
     // Memory Storage fuer naechste Speicherung...
     // Memory Storage fuer naechste Speicherung...
     let storage = getOptValue(opt, __MEMNORMAL);
     let storage = getOptValue(opt, __MEMNORMAL);
Zeile 1.772: Zeile 1.642:


     if (saveOpt !== undefined) {
     if (saveOpt !== undefined) {
         setOpt(saveOpt, storage, false, onFulfilled, onRejected);
         setOpt(saveOpt, storage, false);
     }
     }


Zeile 1.783: Zeile 1.653:


// Initialisiert das Script-Modul und ermittelt die beschreibenden Daten
// Initialisiert das Script-Modul und ermittelt die beschreibenden Daten
// meta: Metadaten des Scripts (Default: GM.info.script)
// meta: Metadaten des Scripts (Default: GM_info.script)
// return Beschreibende Daten fuer __DBMOD
// return Beschreibende Daten fuer __DBMOD
function ScriptModule(meta) {
function ScriptModule(meta) {
     'use strict';
     'use strict';


     const __META = getValue(meta, GM.info.script);
     const __META = getValue(meta, GM_info.script);
     const __PROPS = {
     const __PROPS = {
                 'name'        : true,
                 'name'        : true,
Zeile 1.894: Zeile 1.764:
// funOff: Funktion zum Ausschalten
// funOff: Funktion zum Ausschalten
// keyOff: Hotkey zum Ausschalten im Menu
// keyOff: Hotkey zum Ausschalten im Menu
// return Promise von GM.registerMenuCommand()
function registerMenuOption(val, menuOn, funOn, keyOn, menuOff, funOff, keyOff) {
function registerMenuOption(val, menuOn, funOn, keyOn, menuOff, funOff, keyOff) {
     const __ON  = (val ? '*' : "");
     const __ON  = (val ? '*' : "");
Zeile 1.902: Zeile 1.771:


     if (val) {
     if (val) {
         return GM.registerMenuCommand(menuOff, funOff, keyOff).then(result => menuOn);
         GM_registerMenuCommand(menuOff, funOff, keyOff);
     } else {
     } else {
         return GM.registerMenuCommand(menuOn, funOn, keyOn).then(result => menuOff);
         GM_registerMenuCommand(menuOn, funOn, keyOn);
     }
     }
}
}
Zeile 1.914: Zeile 1.783:
// fun: Funktion zum Setzen des naechsten Wertes
// fun: Funktion zum Setzen des naechsten Wertes
// key: Hotkey zum Setzen des naechsten Wertes im Menu
// key: Hotkey zum Setzen des naechsten Wertes im Menu
// return Promise von GM.registerMenuCommand()
function registerNextMenuOption(val, arr, menu, fun, key) {
function registerNextMenuOption(val, arr, menu, fun, key) {
     const __MENU = substParam(menu, val);
     const __MENU = menu.replace('$', val);
     let options = "OPTION " + __MENU;
     let options = "OPTION " + __MENU;


Zeile 1.928: Zeile 1.796:
     __LOG[3](options);
     __LOG[3](options);


     return GM.registerMenuCommand(__MENU, fun, key).then(result => __MENU);
     GM_registerMenuCommand(__MENU, fun, key);
}
}


Zeile 1.938: Zeile 1.806:
// hidden: Angabe, ob Menupunkt nicht sichtbar sein soll (Default: sichtbar)
// hidden: Angabe, ob Menupunkt nicht sichtbar sein soll (Default: sichtbar)
// serial: Serialization fuer komplexe Daten
// serial: Serialization fuer komplexe Daten
// return Promise von GM.registerMenuCommand() (oder String-Version des Wertes)
function registerDataOption(val, menu, fun, key, hidden = false, serial = true) {
function registerDataOption(val, menu, fun, key, hidden = false, serial = true) {
     const __VALUE = ((serial && (val !== undefined)) ? safeStringify(val) : val);
     const __VALUE = ((serial && (val !== undefined)) ? safeStringify(val) : val);
     const __MENU = substParam(menu, __VALUE);
     const __MENU = getValue(menu, "").replace('$', __VALUE);
     const __OPTIONS = (hidden ? "HIDDEN " : "") + "OPTION " + __MENU +
     const __OPTIONS = (hidden ? "HIDDEN " : "") + "OPTION " + __MENU +
                       getValue(__VALUE, "", " = " + __VALUE);
                       getValue(__VALUE, "", " = " + __VALUE);
Zeile 1.947: Zeile 1.814:
     __LOG[hidden ? 4 : 3](__OPTIONS);
     __LOG[hidden ? 4 : 3](__OPTIONS);


     if (hidden) {
     if (! hidden) {
         return Promise.resolve(__VALUE);
         GM_registerMenuCommand(__MENU, fun, key);
    } else {
        return GM.registerMenuCommand(__MENU, fun, key).then(result => __MENU);
     }
     }
}
}
Zeile 1.956: Zeile 1.821:
// Zeigt den Eintrag im Menu einer Option
// Zeigt den Eintrag im Menu einer Option
// opt: Config und Value der Option
// opt: Config und Value der Option
// return Promise von GM.registerMenuCommand() (oder String-Version des Wertes)
function registerOption(opt) {
function registerOption(opt) {
     const __CONFIG = getOptConfig(opt);
     const __CONFIG = getOptConfig(opt);
Zeile 1.968: Zeile 1.832:
     if (! __CONFIG.HiddenMenu) {
     if (! __CONFIG.HiddenMenu) {
         switch (__CONFIG.Type) {
         switch (__CONFIG.Type) {
         case __OPTTYPES.MC : return registerNextMenuOption(__VALUE, __CONFIG.Choice, __LABEL, __ACTION, __HOTKEY);
         case __OPTTYPES.MC : registerNextMenuOption(__VALUE, __CONFIG.Choice, __LABEL, __ACTION, __HOTKEY);
         case __OPTTYPES.SW : return registerMenuOption(__VALUE, __LABEL, __ACTION, __HOTKEY,
                            break;
                                                      __CONFIG.AltLabel, __ACTION, __CONFIG.AltHotkey);
         case __OPTTYPES.SW : registerMenuOption(__VALUE, __LABEL, __ACTION, __HOTKEY,
         case __OPTTYPES.TF : return registerMenuOption(__VALUE, __LABEL, __ACTION, __HOTKEY,
                                                __CONFIG.AltLabel, __ACTION, __CONFIG.AltHotkey);
                                                      __CONFIG.AltLabel, opt.AltAction, __CONFIG.AltHotkey);
                            break;
         case __OPTTYPES.SD : return registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
         case __OPTTYPES.TF : registerMenuOption(__VALUE, __LABEL, __ACTION, __HOTKEY,
         case __OPTTYPES.SI : return registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
                                                __CONFIG.AltLabel, opt.AltAction, __CONFIG.AltHotkey);
         default :            return Promise.resolve(__VALUE);
                            break;
         }
         case __OPTTYPES.SD : registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
                            break;
         case __OPTTYPES.SI : registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
                            break;
         default :            break;
         }
     } else {
     } else {
         // Nur Anzeige im Log...
         // Nur Anzeige im Log...
         return registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
         registerDataOption(__VALUE, __LABEL, __ACTION, __HOTKEY, __HIDDEN, __SERIAL);
     }
     }
}
}
Zeile 2.031: Zeile 1.900:
         switch (optAction) {
         switch (optAction) {
         case __OPTACTION.SET : fun = function() {
         case __OPTACTION.SET : fun = function() {
                                       return setOptByName(optSet, item, __CONFIG.SetValue, __RELOAD).catch(defaultCatch);
                                       return setOptByName(optSet, item, __CONFIG.SetValue, __RELOAD);
                                   };
                                   };
                               break;
                               break;
         case __OPTACTION.NXT : fun = function() {
         case __OPTACTION.NXT : fun = function() {
                                       return promptNextOptByName(optSet, item, __CONFIG.SetValue, __RELOAD,
                                       return promptNextOptByName(optSet, item, __CONFIG.SetValue, __RELOAD,
                                                   __CONFIG.FreeValue, __CONFIG.SelValue, __CONFIG.MinChoice).catch(defaultCatch);
                                                   __CONFIG.FreeValue, __CONFIG.SelValue, __CONFIG.MinChoice);
                                   };
                                   };
                               break;
                               break;
         case __OPTACTION.RST : fun = function() {
         case __OPTACTION.RST : fun = function() {
                                       return resetOptions(optSet, __RELOAD).then(
                                       return resetOptions(optSet, __RELOAD);
                                              result => __LOG[3]("RESETTING (" + result + ")..."),
                                              defaultCatch);
                                   };
                                   };
                               break;
                               break;
Zeile 2.097: Zeile 1.964:
             addProps(config, getOptConfig(__REF));
             addProps(config, getOptConfig(__REF));
             addProps(config, optConfig);
             addProps(config, optConfig);
             config.setConst('SharedData', getOptValue(__REF), false);   // Wert muss schon da sein, NICHT nachladen, sonst ggfs. Promise
             config.setConst('SharedData', getOptValue(__REF));
         } else {  // __OBJREF enthaelt die Daten selbst
         } else {  // __OBJREF enthaelt die Daten selbst
             if (! config.Name) {
             if (! config.Name) {
Zeile 2.131: Zeile 1.998:
             // Gab es vorher einen Aufruf, der einen Stub-Eintrag erzeugt hat, und wurden Daten geladen?
             // Gab es vorher einen Aufruf, der einen Stub-Eintrag erzeugt hat, und wurden Daten geladen?
             const __LOADED = ((preInit === false) && optSet[opt].Loaded);
             const __LOADED = ((preInit === false) && optSet[opt].Loaded);
            const __PROMISE = ((__LOADED || ! optSet[opt]) ? undefined : optSet[opt].Promise);
             const __VALUE = (__LOADED ? optSet[opt].Value : undefined);
             const __VALUE = (__LOADED ? optSet[opt].Value : undefined);


Zeile 2.138: Zeile 2.004:
                 'Config'    : __CONFIG,
                 'Config'    : __CONFIG,
                 'Loaded'    : (__ISSHARED || __LOADED),
                 'Loaded'    : (__ISSHARED || __LOADED),
                'Promise'  : __PROMISE,
                 'Value'    : initOptValue(__CONFIG, __VALUE),
                 'Value'    : initOptValue(__CONFIG, __VALUE),
                 'SetValue'  : __CONFIG.SetValue,
                 'SetValue'  : __CONFIG.SetValue,
Zeile 2.150: Zeile 2.015:
                 'Config'    : __OPTCONFIG,
                 'Config'    : __OPTCONFIG,
                 'Loaded'    : false,
                 'Loaded'    : false,
                'Promise'  : undefined,
                 'Value'    : initOptValue(__OPTCONFIG),
                 'Value'    : initOptValue(__OPTCONFIG),
                 'ReadOnly'  : (__ISSHARED || __OPTCONFIG.ReadOnly)
                 'ReadOnly'  : (__ISSHARED || __OPTCONFIG.ReadOnly)
Zeile 2.183: Zeile 2.047:
// optConfig: Konfiguration der Optionen
// optConfig: Konfiguration der Optionen
// optSet: Platz fuer die gesetzten Optionen
// optSet: Platz fuer die gesetzten Optionen
// return Promise auf gefuelltes Objekt mit den gesetzten Optionen
// return Gefuelltes Objekt mit den gesetzten Optionen
async function startOptions(optConfig, optSet = undefined, classification = undefined) {
function startOptions(optConfig, optSet = undefined, classification = undefined) {
     optSet = initOptions(optConfig, optSet, true);  // PreInit
     optSet = initOptions(optConfig, optSet, true);  // PreInit


     // Memory Storage fuer vorherige Speicherung...
     // Memory Storage fuer vorherige Speicherung...
     myOptMemSize = getMemSize(myOptMem = await restoreMemoryByOpt(optSet.oldStorage));
     myOptMemSize = getMemSize(myOptMem = restoreMemoryByOpt(optSet.oldStorage));


     // Zwischengespeicherte Befehle auslesen...
     // Zwischengespeicherte Befehle auslesen...
Zeile 2.194: Zeile 2.058:


     // ... ermittelte Befehle ausfuehren...
     // ... ermittelte Befehle ausfuehren...
     const __LOADEDCMDS = await runStoredCmds(__STOREDCMDS, optSet, true);  // BeforeLoad
     const __LOADEDCMDS = runStoredCmds(__STOREDCMDS, optSet, true);  // BeforeLoad


     // Bisher noch nicht geladenene Optionen laden...
     // Bisher noch nicht geladenene Optionen laden...
     await loadOptions(optSet);
     loadOptions(optSet);


     // Memory Storage fuer naechste Speicherung...
     // Memory Storage fuer naechste Speicherung...
Zeile 2.209: Zeile 2.073:
     if (classification !== undefined) {
     if (classification !== undefined) {
         // Umbenennungen durchfuehren...
         // Umbenennungen durchfuehren...
         await classification.renameOptions();
         classification.renameOptions();
     }
     }


     // ... ermittelte Befehle ausfuehren...
     // ... ermittelte Befehle ausfuehren...
     await runStoredCmds(__LOADEDCMDS, optSet, false);  // Rest
     runStoredCmds(__LOADEDCMDS, optSet, false);  // Rest


     // Als globale Daten speichern...
     // Als globale Daten speichern...
Zeile 2.230: Zeile 2.094:
// 'formWidth': Anzahl der Elemente pro Zeile
// 'formWidth': Anzahl der Elemente pro Zeile
// 'formBreak': Elementnummer des ersten Zeilenumbruchs
// 'formBreak': Elementnummer des ersten Zeilenumbruchs
// return Liefert die gesetzten Optionen zurueck
function showOptions(optSet = undefined, optParams = { 'hideMenu' : false }) {
function showOptions(optSet = undefined, optParams = { 'hideMenu' : false }) {
     if (! optParams.hideMenu) {
     if (! optParams.hideMenu) {
         buildMenu(optSet).then(() => __LOG[3]("Menu OK"));
         buildMenu(optSet);
     }
     }


Zeile 2.239: Zeile 2.102:
         buildForm(optParams.menuAnchor, optSet, optParams);
         buildForm(optParams.menuAnchor, optSet, optParams);
     }
     }
    return optSet;
}
}


Zeile 2.248: Zeile 2.109:
// value: (Bei allen Typen) Zu setzender Wert
// value: (Bei allen Typen) Zu setzender Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function setOpt(opt, value, reload = false, onFulfilled = undefined, onRejected = undefined) {
function setOpt(opt, value, reload = false) {
     return setOptValue(opt, setStored(getOptName(opt), value, reload, getOptConfig(opt).Serial, onFulfilled, onRejected));
     return setOptValue(opt, setStored(getOptName(opt), value, reload, getOptConfig(opt).Serial));
}
}


Zeile 2.279: Zeile 2.138:
// value: Default fuer ggfs. zu setzenden Wert
// value: Default fuer ggfs. zu setzenden Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function setNextOpt(opt, value = undefined, reload = false, onFulfilled = undefined, onRejected = undefined) {
function setNextOpt(opt, value = undefined, reload = false) {
     return setOpt(opt, getNextOpt(opt, value), reload, onFulfilled, onRejected);
     return setOpt(opt, getNextOpt(opt, value), reload);
}
}


Zeile 2.292: Zeile 2.149:
// freeValue: Angabe, ob Freitext zugelassen ist (Default: false)
// freeValue: Angabe, ob Freitext zugelassen ist (Default: false)
// minChoice: Ab wievielen Auswahlmoeglichkeiten soll abgefragt werden? (Default: 3)
// minChoice: Ab wievielen Auswahlmoeglichkeiten soll abgefragt werden? (Default: 3)
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function promptNextOpt(opt, value = undefined, reload = false, freeValue = false, selValue = true, minChoice = 3, onFulfilled = undefined, onRejected = undefined) {
function promptNextOpt(opt, value = undefined, reload = false, freeValue = false, selValue = true, minChoice = 3) {
     const __CONFIG = getOptConfig(opt);
     const __CONFIG = getOptConfig(opt);
     const __CHOICE = __CONFIG.Choice;
     const __CHOICE = __CONFIG.Choice;


     if (value || (! __CHOICE) || (__CHOICE.length < minChoice)) {
     if (value || (! __CHOICE) || (__CHOICE.length < minChoice)) {
         return setNextOpt(opt, value, reload, onFulfilled, onRejected);
         return setNextOpt(opt, value, reload);
     }
     }


Zeile 2.335: Zeile 2.190:
             if (nextVal !== __VALUE) {
             if (nextVal !== __VALUE) {
                 if (nextVal) {
                 if (nextVal) {
                     return setOpt(opt, nextVal, reload, onFulfilled, onRejected);
                     return setOpt(opt, nextVal, reload);
                 }
                 }


                 const __LABEL = substParam(__CONFIG.Label, __VALUE);
                 const __LABEL = __CONFIG.Label.replace('$', __VALUE);


                 showAlert(__LABEL, "Ung\xFCltige Eingabe: " + __ANSWER);
                 showAlert(__LABEL, "Ung\xFCltige Eingabe: " + __ANSWER);
Zeile 2.344: Zeile 2.199:
         }
         }
     } catch (ex) {
     } catch (ex) {
         __LOG[0]("promptNextOpt: " + ex.message);
         __LOG[1]("promptNextOpt: " + ex.message);
     }
     }


Zeile 2.356: Zeile 2.211:
// value: (Bei allen Typen) Zu setzender Wert
// value: (Bei allen Typen) Zu setzender Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function setOptByName(optSet, item, value, reload = false, onFulfilled = undefined, onRejected = undefined) {
function setOptByName(optSet, item, value, reload = false) {
     const __OPT = getOptByName(optSet, item);
     const __OPT = getOptByName(optSet, item);


     return setOpt(__OPT, value, reload, onFulfilled, onRejected);
     return setOpt(__OPT, value, reload);
}
}


Zeile 2.381: Zeile 2.234:
// value: Default fuer ggfs. zu setzenden Wert
// value: Default fuer ggfs. zu setzenden Wert
// reload: Seite mit neuem Wert neu laden
// reload: Seite mit neuem Wert neu laden
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function setNextOptByName(optSet, item, value = undefined, reload = false, onFulfilled = undefined, onRejected = undefined) {
function setNextOptByName(optSet, item, value = undefined, reload = false) {
     const __OPT = getOptByName(optSet, item);
     const __OPT = getOptByName(optSet, item);


     return setNextOpt(__OPT, value, reload, onFulfilled, onRejected);
     return setNextOpt(__OPT, value, reload);
}
}


Zeile 2.397: Zeile 2.248:
// freeValue: Angabe, ob Freitext zugelassen ist (Default: false)
// freeValue: Angabe, ob Freitext zugelassen ist (Default: false)
// minChoice: Ab wievielen Auswahlmoeglichkeiten soll abgefragt werden? (Default: 3)
// minChoice: Ab wievielen Auswahlmoeglichkeiten soll abgefragt werden? (Default: 3)
// onFulfilled: Reaktion auf Speicherung im resolve-Fall (1. Promise.then()-Parameter)
// onRejected: Reaktion auf Speicherung im reject-Fall (2. Promise.then()-Parameter)
// return Gesetzter Wert
// return Gesetzter Wert
function promptNextOptByName(optSet, item, value = undefined, reload = false, freeValue = false, selValue = true, minChoice = 3, onFulfilled = undefined, onRejected = undefined) {
function promptNextOptByName(optSet, item, value = undefined, reload = false, freeValue = false, selValue = true, minChoice = 3) {
     const __OPT = getOptByName(optSet, item);
     const __OPT = getOptByName(optSet, item);


     return promptNextOpt(__OPT, value, reload, freeValue, selValue, minChoice, onFulfilled, onRejected);
     return promptNextOpt(__OPT, value, reload, freeValue, selValue, minChoice);
}
}


// Baut das Benutzermenu auf (asynchron im Hintergrund)
// Baut das Benutzermenu auf
// optSet: Gesetzte Optionen
// optSet: Gesetzte Optionen
// return Promise auf void
function buildMenu(optSet) {
async function buildMenu(optSet) {
     __LOG[3]("buildMenu()");
     __LOG[3]("buildMenu()");


     for (let opt in optSet) {
     for (let opt in optSet) {
         await registerOption(optSet[opt]).then(
         registerOption(optSet[opt]);
                result => __LOG[6](`REGISTEROPTION[${opt}] = ${result}`),
                defaultCatch);
     }
     }
}
}
Zeile 2.422: Zeile 2.268:
// opt: Zu invalidierende Option
// opt: Zu invalidierende Option
// force: Invalidiert auch Optionen mit 'AutoReset'-Attribut
// force: Invalidiert auch Optionen mit 'AutoReset'-Attribut
// return Promise auf resultierenden Wert
function invalidateOpt(opt, force = false) {
function invalidateOpt(opt, force = false) {
     return Promise.resolve(opt.Promise).then(value => {
     if (opt.Loaded && ! opt.ReadOnly) {
            if (opt.Loaded && ! opt.ReadOnly) {
        const __CONFIG = getOptConfig(opt);
                const __CONFIG = getOptConfig(opt);


                // Wert "ungeladen"...
        // Wert "ungeladen"...
                opt.Loaded = (force || ! __CONFIG.AutoReset);
        opt.Loaded = (force || ! __CONFIG.AutoReset);


                if (opt.Loaded && __CONFIG.AutoReset) {
        if (opt.Loaded && __CONFIG.AutoReset) {
                    // Nur zuruecksetzen, gilt als geladen...
            // Nur zuruecksetzen, gilt als geladen...
                    setOptValue(opt, initOptValue(__CONFIG));
            setOptValue(opt, initOptValue(__CONFIG));
                }
        }
            }
    }
 
            return getOptValue(opt);
        }, defaultCatch);
}
}


// Invalidiert die (ueber Menu) gesetzten Optionen
// Invalidiert die (ueber Menu) gesetzten Optionen
// optSet: Object mit den Optionen
// optSet: Set mit den Optionen
// force: Invalidiert auch Optionen mit 'AutoReset'-Attribut
// force: Invalidiert auch Optionen mit 'AutoReset'-Attribut
// return Promise auf Object mit den geladenen Optionen
// return Set mit den geladenen Optionen
async function invalidateOpts(optSet, force = false) {
function invalidateOpts(optSet, force = false) {
     for (let opt in optSet) {
     for (let opt in optSet) {
         const __OPT = optSet[opt];
         const __OPT = optSet[opt];


         await invalidateOpt(__OPT, force);
         invalidateOpt(__OPT, force);
     }
     }


Zeile 2.458: Zeile 2.299:
// opt: Zu ladende Option
// opt: Zu ladende Option
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// return Promise auf gesetzten Wert der gelandenen Option
// return Gesetzter Wert der gelandenen Option
function loadOption(opt, force = false) {
function loadOption(opt, force = false) {
     if (! opt.Promise) {
     const __CONFIG = getOptConfig(opt);
        const __CONFIG = getOptConfig(opt);
    const __ISSHARED = getValue(__CONFIG.Shared, false, true);
        const __ISSHARED = getValue(__CONFIG.Shared, false, true);
    const __NAME = getOptName(opt);
        const __NAME = getOptName(opt);
    const __DEFAULT = getOptValue(opt, undefined, false, false);
        const __DEFAULT = getOptValue(opt, undefined, false, false, false);
    let value;
        let value;


        if (opt.Loaded && ! __ISSHARED) {
    if (opt.Loaded && ! __ISSHARED) {
            const __ERROR = "Error: Oprion '" + __NAME + "' bereits geladen!";
        __LOG[1]("Error: Oprion '" + __NAME + "' bereits geladen!");
    }


            __LOG[0](__MESSAGE);
    if (opt.ReadOnly || __ISSHARED) {
 
        value = __DEFAULT;
            return Promise.reject(__MESSAGE);
    } else if (! force && __CONFIG.AutoReset) {
        }
        value = initOptValue(__CONFIG);
 
    } else {
        if (opt.ReadOnly || __ISSHARED) {
        value = (__CONFIG.Serial ?
            value = __DEFAULT;
                        deserialize(__NAME, __DEFAULT) :
        } else if (! force && __CONFIG.AutoReset) {
                        GM_getValue(__NAME, __DEFAULT));
            value = initOptValue(__CONFIG);
    }
        } else {
            value = (__CONFIG.Serial ?
                            deserialize(__NAME, __DEFAULT) :
                            GM.getValue(__NAME, __DEFAULT));
        }


        opt.Promise = Promise.resolve(value).then(value => {
    __LOG[5]("LOAD " + __NAME + ": " + __LOG.changed(__DEFAULT, value));
                // Paranoide Sicherheitsabfrage (das sollte nie passieren!)...
                if (opt.Loaded || ! opt.Promise) {
                    showAlert("Error", "Unerwarteter Widerspruch zwischen opt.Loaded und opt.Promise", safeStringify(opt));
                }
                __LOG[5]("LOAD " + __NAME + ": " + __LOG.changed(__DEFAULT, value));


                // Wert intern setzen...
    // Wert als geladen markieren...
                const __VAL = setOptValue(opt, value);
    opt.Loaded = true;


                // Wert als geladen markieren...
    // Wert intern setzen...
                opt.Promise = undefined;
    return setOptValue(opt, value);
                opt.Loaded = true;
 
                return __VAL;
            }, defaultCatch);
    }
 
    return opt.Promise;
}
}


// Laedt die (ueber Menu) gesetzten Optionen
// Laedt die (ueber Menu) gesetzten Optionen
// optSet: Object mit den Optionen
// optSet: Set mit den Optionen
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// return Array mit Promises neuer Ladevorgaenge (fuer Objekte mit 'name' und 'value')
// return Set mit den geladenen Optionen
function loadOptions(optSet, force = false) {
function loadOptions(optSet, force = false) {
    const __PROMISES = [];
     for (let opt in optSet) {
     for (let opt in optSet) {
         const __OPT = optSet[opt];
         const __OPT = optSet[opt];


         if (! __OPT.Loaded) {
         if (! __OPT.Loaded) {
             const __PROMISE = loadOption(__OPT, force).then(value => {
             loadOption(__OPT, force);
                    __LOG[5]("LOADED " + opt + " << " + value);
 
                    return Promise.resolve({
                            'name'  : opt,
                            'value' : value
                        });
                }, defaultCatch);
 
            __PROMISES.push(__PROMISE);
         }
         }
     }
     }


     return Promise.all(__PROMISES);
     return optSet;
}
}


Zeile 2.537: Zeile 2.350:
// force: Entfernt auch Optionen mit 'Permanent'-Attribut
// force: Entfernt auch Optionen mit 'Permanent'-Attribut
// reset: Setzt bei Erfolg auf Initialwert der Option (auch fuer nicht 'AutoReset')
// reset: Setzt bei Erfolg auf Initialwert der Option (auch fuer nicht 'AutoReset')
// return Promise von GM.deleteValue() (oder void)
function deleteOption(opt, force = false, reset = true) {
function deleteOption(opt, force = false, reset = true) {
     const __CONFIG = getOptConfig(opt);
     const __CONFIG = getOptConfig(opt);
Zeile 2.546: Zeile 2.358:
         __LOG[4]("DELETE " + __NAME);
         __LOG[4]("DELETE " + __NAME);


         return GM.deleteValue(__NAME).then(voidValue => {
         GM_deleteValue(__NAME);
                if (reset || __CONFIG.AutoReset) {
 
                    setOptValue(opt, initOptValue(__CONFIG));
        if (reset || __CONFIG.AutoReset) {
                }
            setOptValue(opt, initOptValue(__CONFIG));
            }, defaultCatch);
        }
     }
     }
    return Promise.resolve();
}
}


Zeile 2.561: Zeile 2.371:
// force: Entfernt auch Optionen mit 'Permanent'-Attribut
// force: Entfernt auch Optionen mit 'Permanent'-Attribut
// reset: Setzt bei Erfolg auf Initialwert der Option
// reset: Setzt bei Erfolg auf Initialwert der Option
// return Promise auf diesen Vorgang
function deleteOptions(optSet, optSelect = undefined, force = false, reset = true) {
async function deleteOptions(optSet, optSelect = undefined, force = false, reset = true) {
     const __DELETEALL = ((optSelect === undefined) || (optSelect === true));
     const __DELETEALL = ((optSelect === undefined) || (optSelect === true));
     const __OPTSELECT = getValue(optSelect, { });
     const __OPTSELECT = getValue(optSelect, { });
Zeile 2.568: Zeile 2.377:
     for (let opt in optSet) {
     for (let opt in optSet) {
         if (getValue(__OPTSELECT[opt], __DELETEALL)) {
         if (getValue(__OPTSELECT[opt], __DELETEALL)) {
             await deleteOption(optSet[opt], force, reset);
             deleteOption(optSet[opt], force, reset);
         }
         }
     }
     }
    return Promise.resolve();
}
}


Zeile 2.580: Zeile 2.387:
// reload: Wert nachladen statt beizubehalten
// reload: Wert nachladen statt beizubehalten
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// force: Laedt auch Optionen mit 'AutoReset'-Attribut
// return Promise auf umbenannte Option
// return Umbenannte Option
async function renameOption(opt, name, reload = false, force = false) {
function renameOption(opt, name, reload = false, force = false) {
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);


     if (__NAME !== name) {
     if (__NAME !== name) {
         await deleteOption(opt, true, ! reload);
         deleteOption(opt, true, ! reload);


         setOptName(opt, name);
         setOptName(opt, name);


         await invalidateOpt(opt, opt.Loaded);
         invalidateOpt(opt, opt.Loaded);


         if (reload) {
         if (reload) {
             opt.Loaded = false;
             opt.Loaded = false;


             await loadOption(opt, force);
             loadOption(opt, force);
         }
         }
     }
     }


     return Promise.resolve(opt);
     return opt;
}
}


Zeile 2.626: Zeile 2.433:
// - name: Neu zu setzender Name (Speicheradresse)
// - name: Neu zu setzender Name (Speicheradresse)
// - param: Parameter "renameParam" von oben, z.B. Prefix oder Postfix
// - param: Parameter "renameParam" von oben, z.B. Prefix oder Postfix
// return Promise auf diesen Vorgang
function renameOptions(optSet, optSelect, renameParam = undefined, renameFun = prefixName) {
async function renameOptions(optSet, optSelect, renameParam = undefined, renameFun = prefixName) {
     if (renameFun === undefined) {
     if (renameFun === undefined) {
         __LOG[0]("RENAME: Illegale Funktion!");
         __LOG[1]("RENAME: Illegale Funktion!");
     }
     }
     for (let opt in optSelect) {
     for (let opt in optSelect) {
Zeile 2.636: Zeile 2.442:


         if (__OPT === undefined) {
         if (__OPT === undefined) {
             __LOG[0]("RENAME: Option '" + opt + "' nicht gefunden!");
             __LOG[1]("RENAME: Option '" + opt + "' nicht gefunden!");
         } else {
         } else {
             const __NAME = getOptName(__OPT);
             const __NAME = getOptName(__OPT);
Zeile 2.646: Zeile 2.452:
             const __FORCE = (__ISSCALAR ? true : __OPTPARAMS.force);
             const __FORCE = (__ISSCALAR ? true : __OPTPARAMS.force);


             await renameOption(__OPT, __NEWNAME, __RELOAD, __FORCE);
             renameOption(__OPT, __NEWNAME, __RELOAD, __FORCE);
         }
         }
     }
     }
Zeile 2.654: Zeile 2.460:
// optSet: Gesetzte Optionen
// optSet: Gesetzte Optionen
// reload: Seite mit "Werkseinstellungen" neu laden
// reload: Seite mit "Werkseinstellungen" neu laden
// return Promise auf diesen Vorgang
function resetOptions(optSet, reload = true) {
async function resetOptions(optSet, reload = true) {
     // Alle (nicht 'Permanent') gesetzten Optionen entfernen...
     // Alle (nicht 'Permanent') gesetzten Optionen entfernen...
     await deleteOptions(optSet, true, false, ! reload);
     deleteOptions(optSet, true, false, ! reload);


     // ... und ggfs. Seite neu laden (mit "Werkseinstellungen")...
     if (reload) {
    refreshPage(reload);
        // ... und Seite neu laden (mit "Werkseinstellungen")...
        window.location.reload();
    }
}
}


Zeile 2.670: Zeile 2.477:
// type: Typ der Input-Felder (Default: unsichtbare Daten)
// type: Typ der Input-Felder (Default: unsichtbare Daten)
// return Ergaenztes Form-Konstrukt
// return Ergaenztes Form-Konstrukt
function addInputField(form, props, type = 'hidden') {
function addInputField(form, props, type = "hidden") {
     for (let fieldName in props) {
     for (let fieldName in props) {
         let field = form[fieldName];
         let field = form[fieldName];
         if (! field) {
         if (! field) {
             field = document.createElement('input');
             field = document.createElement("input");
             field.type = type;
             field.type = type;
             field.name = fieldName;
             field.name = fieldName;
Zeile 2.690: Zeile 2.497:
// return Ergaenztes Form-Konstrukt
// return Ergaenztes Form-Konstrukt
function addHiddenField(form, props) {
function addHiddenField(form, props) {
     return addInputField(form, props, 'hidden');
     return addInputField(form, props, "hidden");
}
}


Zeile 2.703: Zeile 2.510:
         return obj.addEventListener(type, callback, capture);
         return obj.addEventListener(type, callback, capture);
     } else if (obj.attachEvent) {
     } else if (obj.attachEvent) {
         return obj.attachEvent('on' + type, callback);
         return obj.attachEvent("on" + type, callback);
     } else {
     } else {
         __LOG[0]("Could not add " + type + " event:");
         __LOG[1]("Could not add " + type + " event:");
         __LOG[2](callback);
         __LOG[2](callback);


Zeile 2.722: Zeile 2.529:
         return obj.removeEventListener(type, callback, capture);
         return obj.removeEventListener(type, callback, capture);
     } else if (obj.detachEvent) {
     } else if (obj.detachEvent) {
         return obj.detachEvent('on' + type, callback);
         return obj.detachEvent("on" + type, callback);
     } else {
     } else {
         __LOG[0]("Could not remove " + type + " event:");
         __LOG[1]("Could not remove " + type + " event:");
         __LOG[2](callback);
         __LOG[2](callback);


Zeile 2.772: Zeile 2.579:
// doc: Dokument (document)
// doc: Dokument (document)
// return Gesuchtes Element oder undefined (falls nicht gefunden)
// return Gesuchtes Element oder undefined (falls nicht gefunden)
function getTable(index, tag = 'table', doc = document) {
function getTable(index, tag = "table", doc = document) {
     const __TAGS = doc.getElementsByTagName(tag);
     const __TAGS = doc.getElementsByTagName(tag);
     const __TABLE = (__TAGS ? __TAGS[index] : undefined);
     const __TABLE = (__TAGS ? __TAGS[index] : undefined);
Zeile 2.796: Zeile 2.603:
// return Gesuchte Zeilen oder undefined (falls nicht gefunden)
// return Gesuchte Zeilen oder undefined (falls nicht gefunden)
function getRows(index, doc = document) {
function getRows(index, doc = document) {
     const __TABLE = getTable(index, 'table', doc);
     const __TABLE = getTable(index, "table", doc);
     const __ROWS = (__TABLE ? __TABLE.rows : undefined);
     const __ROWS = (__TABLE ? __TABLE.rows : undefined);


Zeile 2.839: Zeile 2.646:
         const __CONFIG = getOptConfig(opt);
         const __CONFIG = getOptConfig(opt);
         const __SERIAL = getValue(serial, getValue(__CONFIG.Serial, false));
         const __SERIAL = getValue(serial, getValue(__CONFIG.Serial, false));
         const __THISVAL = ((__CONFIG.ValType === 'String') ? "'\\x22' + this.value + '\\x22'" : "this.value");
         const __THISVAL = ((__CONFIG.ValType === "String") ? "'\\x22' + this.value + '\\x22'" : "this.value");
         const __TVALUE = getValue(__CONFIG.ValType, __THISVAL, "new " + __CONFIG.ValType + '(' + __THISVAL + ')');
         const __TVALUE = getValue(__CONFIG.ValType, __THISVAL, "new " + __CONFIG.ValType + '(' + __THISVAL + ')');
         const __VALSTR = ((value !== undefined) ? safeStringify(value) : __SERIAL ? "JSON.stringify(" + __TVALUE + ')' : __TVALUE);
         const __VALSTR = ((value !== undefined) ? safeStringify(value) : __SERIAL ? "JSON.stringify(" + __TVALUE + ')' : __TVALUE);
Zeile 2.868: Zeile 2.675:
// memory: __OPTMEM.normal = unbegrenzt gespeichert (localStorage), __OPTMEM.begrenzt = bis Browserende gespeichert (sessionStorage), __OPTMEM.inaktiv
// memory: __OPTMEM.normal = unbegrenzt gespeichert (localStorage), __OPTMEM.begrenzt = bis Browserende gespeichert (sessionStorage), __OPTMEM.inaktiv
// return String mit dem (reinen) Funktionsaufruf
// return String mit dem (reinen) Funktionsaufruf
function getFormActionEvent(opt, isAlt = false, value = undefined, type = 'click', serial = undefined, memory = undefined) {
function getFormActionEvent(opt, isAlt = false, value = undefined, type = "click", serial = undefined, memory = undefined) {
     const __ACTION = getFormAction(opt, isAlt, value, serial, memory);
     const __ACTION = getFormAction(opt, isAlt, value, serial, memory);


     return getValue(__ACTION, "", ' on' + type + '="' + __ACTION + '"');
     return getValue(__ACTION, "", ' on' + type + '="' + __ACTION + '"');
}
// Hilfsfunktion: Wendet eine Konvertierung auf jede "Zeile" innerhalb eines Textes an
// text: Urspruenglicher Text
// convFun: function(line, index, arr): Konvertiert line in "Zeile" line des Arrays arr
// separator: Zeilentrenner im Text (Default: '\n')
// thisArg: optionaler this-Parameter fuer die Konvertierung
// limit: optionale Begrenzung der Zeilen
// return String mit dem neuen Text
function eachLine(text, convFun, separator = '\n', thisArg = undefined, limit = undefined) {
    const __ARR = text.split(separator, limit);
    const __RES = __ARR.map(convFun, thisArg);
    return __RES.join(separator);
}
// Hilfsfunktion: Ergaenzt einen HTML-Code um einen Titel (ToolTip)
// html: Urspruenglicher HTML-Code (z.B. ein HTML-Element oder Text)
// title: Im ToolTip angezeigter Text
// separator: Zeilentrenner im Text (Default: '|')
// limit: optionale Begrenzung der Zeilen
// return String mit dem neuen HTML-Code
function withTitle(html, title, separator = '|', limit = undefined) {
    if (title && title.length) {
        return eachLine(html, line => '<abbr title="' + title + '">' + line + '</abbr>', separator, undefined, limit);
    } else {
        return html;
    }
}
// Hilfsfunktion: Ermittelt einen Label- oder FormLabel-Eintrag (Default)
// label: Config-Eintrag fuer Label oder FormLabel
// defLabel: Ersatzwert, falls label nicht angegeben
// isSelect: Angabe, ob ein Parameter angezeigt wird (Default: false)
// isForm: Angabe, ob ein FormLabel gesucht ist (Default: true)
// return Vollstaendiger Label- oder FormLabel-Eintrag
function formatLabel(label, defLabel = undefined, isSelect = false, isForm = true) {
    const __LABEL = getValue(label, defLabel);
    if (isSelect && __LABEL && (substParam(__LABEL, '_') === __LABEL)) {
        return __LABEL + (isForm ? "|$" : " $");
    } else {
        return __LABEL;
    }
}
}


Zeile 2.925: Zeile 2.688:
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);
     const __VALUE = getOptValue(opt);
     const __VALUE = getOptValue(opt);
     const __ACTION = getFormActionEvent(opt, false, undefined, 'change', undefined);
     const __ACTION = getFormActionEvent(opt, false, undefined, "change", undefined);
     const __FORMLABEL = formatLabel(__CONFIG.FormLabel, __CONFIG.Label, true);
     const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label);
    const __TITLE = substParam(getValue(__CONFIG.Title, __CONFIG.Label), __VALUE);
     const __LABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>';
     const __LABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>';
     let element = '<select name="' + __NAME + '" id="' + __NAME + '"' + __ACTION + '>';
     let element = '<select name="' + __NAME + '" id="' + __NAME + '"' + __ACTION + '>';
Zeile 2.941: Zeile 2.703:
     element += '\n</select>';
     element += '\n</select>';


     return withTitle(substParam(__LABEL, element), __TITLE);
     return __LABEL.replace('$', element);
}
}


Zeile 2.951: Zeile 2.713:
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);
     const __VALUE = getOptValue(opt, false);
     const __VALUE = getOptValue(opt, false);
     const __ACTION = getFormActionEvent(opt, false, true, 'click', false);
     const __ACTION = getFormActionEvent(opt, false, true, "click", false);
     const __ALTACTION = getFormActionEvent(opt, true, false, 'click', false);
     const __ALTACTION = getFormActionEvent(opt, true, false, "click", false);
    const __FORMLABEL = formatLabel(__CONFIG.FormLabel); // nur nutzen, falls angegeben
    const __TITLE = getValue(__CONFIG.Title, '$');
    const __TITLEON = substParam(__TITLE, __CONFIG.Label);
    const __TITLEOFF = substParam(getValue(__CONFIG.AltTitle, __TITLE), __CONFIG.AltLabel);
     const __ELEMENTON  = '<input type="radio" name="' + __NAME +
     const __ELEMENTON  = '<input type="radio" name="' + __NAME +
                         '" id="' + __NAME + 'ON" value="1"' +
                         '" id="' + __NAME + 'ON" value="1"' +
Zeile 2.967: Zeile 2.725:
                         ' /><label for="' + __NAME + 'OFF">' +
                         ' /><label for="' + __NAME + 'OFF">' +
                         __CONFIG.AltLabel + '</label>';
                         __CONFIG.AltLabel + '</label>';
    const __ELEMENT = [
                          withTitle(__FORMLABEL, __VALUE ? __TITLEON : __TITLEOFF),
                          withTitle(__ELEMENTON, __TITLEON),
                          withTitle(__ELEMENTOFF, __TITLEOFF)
                      ];


     return ((__FORMLABEL && __FORMLABEL.length) ? __ELEMENT : __ELEMENT.slice(1, 3));
     return [ __ELEMENTON, __ELEMENTOFF ];
}
}


Zeile 2.983: Zeile 2.736:
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);
     const __VALUE = getOptValue(opt, false);
     const __VALUE = getOptValue(opt, false);
     const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, 'click', false);
     const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, "click", false);
     const __VALUELABEL = (__VALUE ? __CONFIG.Label : getValue(__CONFIG.AltLabel, __CONFIG.Label));
     const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label);
    const __FORMLABEL = formatLabel(__CONFIG.FormLabel, __CONFIG.Label);
    const __TITLE = substParam(getValue(__VALUE ? __CONFIG.Title : getValue(__CONFIG.AltTitle, __CONFIG.Title), '$'), __VALUELABEL);


     return withTitle('<input type="checkbox" name="' + __NAME +
     return '<input type="checkbox" name="' + __NAME +
                    '" id="' + __NAME + '" value="' + __VALUE + '"' +
          '" id="' + __NAME + '" value="' + __VALUE + '"' +
                    (__VALUE ? ' CHECKED' : "") + __ACTION + ' /><label for="' +
          (__VALUE ? ' CHECKED' : "") + __ACTION + ' /><label for="' +
                    __NAME + '">' + __FORMLABEL + '</label>', __TITLE);
          __NAME + '">' + __FORMLABEL + '</label>';
}
}


Zeile 3.001: Zeile 2.752:
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);
     const __VALUE = getOptValue(opt);
     const __VALUE = getOptValue(opt);
     const __ACTION = getFormActionEvent(opt, false, undefined, 'submit', undefined);
     const __ACTION = getFormActionEvent(opt, false, undefined, "submit", undefined);
     const __SUBMIT = getValue(__CONFIG.Submit, "");
     const __SUBMIT = getValue(__CONFIG.Submit, "");
     //const __ONSUBMIT = (__SUBMIT.length ? ' onKeyDown="' + __SUBMIT + '"': "");
     //const __ONSUBMIT = (__SUBMIT.length ? ' onKeyDown="' + __SUBMIT + '"': "");
     const __ONSUBMIT = (__SUBMIT ? ' onKeyDown="' + __SUBMIT + '"': "");
     const __ONSUBMIT = (__SUBMIT ? ' onKeyDown="' + __SUBMIT + '"': "");
     const __FORMLABEL = formatLabel(__CONFIG.FormLabel, __CONFIG.Label);
     const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label);
    const __TITLE = substParam(getValue(__CONFIG.Title, '$'), __FORMLABEL);
     const __ELEMENTLABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>';
     const __ELEMENTLABEL = '<label for="' + __NAME + '">' + __FORMLABEL + '</label>';
     const __ELEMENTTEXT = '<textarea name="' + __NAME + '" id="' + __NAME + '" cols="' + __CONFIG.Cols +
     const __ELEMENTTEXT = '<textarea name="' + __NAME + '" id="' + __NAME + '" cols="' + __CONFIG.Cols +
Zeile 3.012: Zeile 2.762:
                           safeStringify(__VALUE, __CONFIG.Replace, __CONFIG.Space) + '</textarea>';
                           safeStringify(__VALUE, __CONFIG.Replace, __CONFIG.Space) + '</textarea>';


     return [ withTitle(__ELEMENTLABEL, __TITLE), __ELEMENTTEXT ];
     return [ __ELEMENTLABEL, __ELEMENTTEXT ];
}
}


Zeile 3.022: Zeile 2.772:
     const __NAME = getOptName(opt);
     const __NAME = getOptName(opt);
     const __VALUE = getOptValue(opt, false);
     const __VALUE = getOptValue(opt, false);
     const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, 'click', false);
     const __ACTION = getFormActionEvent(opt, __VALUE, ! __VALUE, "click", false);
     const __BUTTONLABEL = (__VALUE ? getValue(__CONFIG.AltLabel, __CONFIG.Label) : __CONFIG.Label);
     const __BUTTONLABEL = (__VALUE ? __CONFIG.AltLabel : __CONFIG.Label);
     const __FORMLABEL = formatLabel(__CONFIG.FormLabel, __BUTTONLABEL);
     const __FORMLABEL = getValue(__CONFIG.FormLabel, __CONFIG.Label);
    const __BUTTONTITLE = substParam(getValue(__VALUE ? getValue(__CONFIG.AltTitle, __CONFIG.Title) : __CONFIG.Title, '$'), __BUTTONLABEL);


     return '<label for="' + __NAME + '">' + __FORMLABEL + '</label>' +
     return '<label for="' + __NAME + '">' + __FORMLABEL +
          withTitle('<input type="button" name="" + ' + __NAME +
          '</label><input type="button" name="' + __NAME +
                    '" id="' + __NAME + '" value="' + __BUTTONLABEL +
          '" id="' + __NAME + '" value="' + __BUTTONLABEL + '"' +
                    '"' + __ACTION + '/>', __BUTTONTITLE);
          __ACTION + '/>';
}
}


Zeile 3.060: Zeile 2.809:
         }
         }


         if ((typeof element) !== 'string') {
         if (element.length === 2) {
             element = '<div>' + Array.from(element).join('<br />') + '</div>';
             element = '<div>' + element[0] + '<br />' + element[1] + '</div>';
         }
         }
     }
     }


     return element;
     return element;
}
// Gruppiert die Daten eines Objects nach einem Kriterium
// data: Object mit Daten
// byFun: function(val), die das Kriterium ermittelt. Default: value
// filterFun: function(key, index, arr), die das Kriterium key im Array arr an der Stelle index vergleicht. Default: Wert identisch
// sortFun: function(a, b), nach der die Kriterien sortiert werden. Default: Array.sort()
// return Neues Object mit Eintraegen der Form <Kriterium> : [ <alle Keys zu diesem Kriterium> ]
function groupData(data, byFun, filterFun, sortFun) {
    const __BYFUN = (byFun || (val => val));
    const __FILTERFUN = (filterFun || ((key, index, arr) => (arr[index] === key)));
    const __KEYS = Object.keys(data);
    const __VALS = Object.values(data);
    const __BYKEYS = __VALS.map(__BYFUN);
    const __BYKEYSET = new Set(__BYKEYS);
    const __BYKEYARRAY = [...__BYKEYSET];
    const __SORTEDKEYS = __BYKEYARRAY.sort(sortFun);
    const __GROUPEDKEYS = __SORTEDKEYS.map(byVal => __KEYS.filter((key, index, arr) => __FILTERFUN(byVal, index, __BYKEYS)));
    const __ASSIGN = ((keyArr, valArr) => Object.assign({ }, ...keyArr.map((key, index) => ({ [key] : valArr[index] }))));
    return __ASSIGN(__SORTEDKEYS, __GROUPEDKEYS);
}
}


Zeile 3.103: Zeile 2.831:
     const __FORMBREAK = getValue(optParams.formBreak, __FORMWIDTH);
     const __FORMBREAK = getValue(optParams.formBreak, __FORMWIDTH);
     const __SHOWFORM = getOptValue(optSet.showForm, true) ? optParams.showForm : { 'showForm' : true };
     const __SHOWFORM = getOptValue(optSet.showForm, true) ? optParams.showForm : { 'showForm' : true };
    const __PRIOOPTS = groupData(optSet, opt => getOptConfig(opt).FormPrio);
     let form = __FORM;
     let form = __FORM;
     let count = 0;  // Bisher angezeigte Optionen
     let count = 0;  // Bisher angezeigte Optionen
     let column = 0;  // Spalte der letzten Option (1-basierend)
     let column = 0;  // Spalte der letzten Option (1-basierend)


     for (let optKeys of Object.values(__PRIOOPTS)) {
     for (let opt in optSet) {
         for (let optKey of optKeys) {
         if (checkItem(opt, __SHOWFORM, optParams.hideForm)) {
            if (checkItem(optKey, __SHOWFORM, optParams.hideForm)) {
            const __ELEMENT = getOptionElement(optSet[opt]);
                const __ELEMENT = getOptionElement(optSet[optKey]);
            const __TDOPT = ((~ __ELEMENT.indexOf('|')) ? "" : ' colspan="2"');
                const __TDOPT = ((~ __ELEMENT.indexOf('|')) ? "" : ' colspan="2"');


                if (__ELEMENT) {
            if (__ELEMENT) {
                    if (++count > __FORMBREAK) {
                if (++count > __FORMBREAK) {
                        if (++column > __FORMWIDTH) {
                    if (++column > __FORMWIDTH) {
                            column = 1;
                        column = 1;
                        }
                     }
                     }
                    if (column === 1) {
                        form += '</tr><tr>';
                    }
                    form += '\n<td' + __TDOPT + '>' + __ELEMENT.replace('|', '</td><td>') + '</td>';
                 }
                 }
                if (column === 1) {
                    form += '</tr><tr>';
                }
                form += '\n<td' + __TDOPT + '>' + __ELEMENT.replace('|', '</td><td>') + '</td>';
             }
             }
         }
         }
Zeile 3.205: Zeile 2.930:
                                           if (__PARAM !== undefined) {
                                           if (__PARAM !== undefined) {
                                               // Klassifizierte Optionen umbenennen...
                                               // Klassifizierte Optionen umbenennen...
                                               return renameOptions(this.optSet, this.optSelect, __PARAM, this.renameFun);
                                               renameOptions(this.optSet, this.optSelect, __PARAM, this.renameFun);
                                          } else {
                                              return Promise.resolve();
                                           }
                                           }
                                       },
                                       },
Zeile 3.215: Zeile 2.938:
                                           return deleteOptions(this.optSet, __OPTSELECT, true, true);
                                           return deleteOptions(this.optSet, __OPTSELECT, true, true);
                                       }
                                       }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Classification ====================
// ==================== Ende Abschnitt fuer Klasse Classification ====================
Zeile 3.242: Zeile 2.965:
                                           }
                                           }
                                       }
                                       }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse TeamClassification ====================
// ==================== Ende Abschnitt fuer Klasse TeamClassification ====================
Zeile 3.249: Zeile 2.972:


// Klasse fuer Teamdaten
// Klasse fuer Teamdaten
function Team(team, land, liga) {
    'use strict';


/*class*/ function Team /*{
     this.Team = team;
     constructor*/(team, land, liga, teamId) {
    this.Land = land;
        'use strict';
    this.Liga = liga;
 
    this.LdNr = getLandNr(land);
        this.Team = team;
    this.LgNr = getLigaNr(liga);
        this.Land = land;
}
        this.Liga = liga;
        this.TmNr = (teamId || 0);
        this.LdNr = getLandNr(land);
        this.LgNr = getLigaNr(liga);
    }
//}


Class.define(Team, Object, {
Class.define(Team, Object, {
Zeile 3.268: Zeile 2.987:
                                         'Liga' : true,
                                         'Liga' : true,
                                         'Land' : true,
                                         'Land' : true,
                                        'TmNr' : true,
                                         'LdNr' : true,
                                         'LdNr' : true,
                                         'LgNr' : true
                                         'LgNr' : true
                                     }
                                     }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Team ====================
// ==================== Ende Abschnitt fuer Klasse Team ====================
Zeile 3.279: Zeile 2.997:


// Klasse fuer Vereinsdaten
// Klasse fuer Vereinsdaten
function Verein(team, land, liga, id, manager, flags) {
    'use strict';


/*class*/ function Verein /*extends Team {
    Team.call(this, team, land, liga);
    constructor*/(team, land, liga, teamId, manager, flags) {
        'use strict';


        Team.call(this, team, land, liga, teamId);
    this.ID = id;
 
    this.Manager = manager;
        this.Manager = manager;
    this.Flags = (flags || []);
        this.Flags = (flags || []);
}
    }
//}


Class.define(Verein, Team, {
Class.define(Verein, Team, {
Zeile 3.296: Zeile 3.012:
                                         'Liga'    : true,
                                         'Liga'    : true,
                                         'Land'    : true,
                                         'Land'    : true,
                                        'TmNr'    : true,
                                         'LdNr'    : true,
                                         'LdNr'    : true,
                                         'LgNr'    : true,
                                         'LgNr'    : true,
                                        'ID'      : true,
                                         'Manager' : true,
                                         'Manager' : true,
                                         'Flags'  : true
                                         'Flags'  : true
                                     }
                                     }
                 });
                 } );


// ==================== Ende Abschnitt fuer Klasse Verein ====================
// ==================== Ende Abschnitt fuer Klasse Verein ====================
Zeile 3.321: Zeile 3.037:
// Gibt die Teamdaten zurueck und aktualisiert sie ggfs. in der Option
// Gibt die Teamdaten zurueck und aktualisiert sie ggfs. in der Option
// optSet: Platz fuer die gesetzten Optionen
// optSet: Platz fuer die gesetzten Optionen
// teamParams: Dynamisch ermittelte Teamdaten ('Team', 'Liga', 'Land', 'TmNr', 'LdNr' und 'LgNr')
// teamParams: Dynamisch ermittelte Teamdaten ('Team', 'Liga', 'Land', 'LdNr' und 'LgNr')
// myTeam: Objekt fuer die Teamdaten
// myTeam: Objekt fuer die Teamdaten
// return Die Teamdaten oder undefined bei Fehler
// return Die Teamdaten oder undefined bei Fehler
Zeile 3.328: Zeile 3.044:
         addProps(myTeam, teamParams, myTeam.__TEAMITEMS);
         addProps(myTeam, teamParams, myTeam.__TEAMITEMS);
         __LOG[2]("Ermittelt: " + safeStringify(myTeam));
         __LOG[2]("Ermittelt: " + safeStringify(myTeam));
         // ... und abspeichern, falls erweunscht...
         // ... und abspeichern...
         if (optSet && optSet.team) {
         setOpt(optSet.team, myTeam, false);
            setOpt(optSet.team, myTeam, false);
        }
     } else {
     } else {
         const __TEAM = ((optSet && optSet.team) ? getOptValue(optSet.team) : undefined);  // Gespeicherte Parameter
         const __TEAM = getOptValue(optSet.team);  // Gespeicherte Parameter


         if ((__TEAM !== undefined) && (__TEAM.Land !== undefined)) {
         if ((__TEAM !== undefined) && (__TEAM.Land !== undefined)) {
Zeile 3.339: Zeile 3.053:
             __LOG[2]("Gespeichert: " + safeStringify(myTeam));
             __LOG[2]("Gespeichert: " + safeStringify(myTeam));
         } else {
         } else {
             __LOG[6]("Team nicht ermittelt: " + safeStringify(__TEAM));
             __LOG[1]("Unbekannt: " + safeStringify(__TEAM));
         }
         }
     }
     }


    //return ((myTeam.length > 0) ? myTeam : undefined);
     return myTeam;
     return myTeam;
}
}
Zeile 3.360: Zeile 3.075:
// 'formWidth': Anzahl der Elemente pro Zeile
// 'formWidth': Anzahl der Elemente pro Zeile
// 'formBreak': Elementnummer des ersten Zeilenumbruchs
// 'formBreak': Elementnummer des ersten Zeilenumbruchs
// return Promise auf gefuelltes Objekt mit den gesetzten Optionen
// return Gefuelltes Objekt mit den gesetzten Optionen
function buildOptions(optConfig, optSet = undefined, optParams = { 'hideMenu' : false }) {
function buildOptions(optConfig, optSet = undefined, optParams = { 'hideMenu' : false }) {
     // Klassifikation ueber Land und Liga des Teams...
     // Klassifikation ueber Land und Liga des Teams...
Zeile 3.366: Zeile 3.081:
     __TEAMCLASS.teamParams = optParams.teamParams;  // Ermittelte Parameter
     __TEAMCLASS.teamParams = optParams.teamParams;  // Ermittelte Parameter


     return startOptions(optConfig, optSet, __TEAMCLASS).then(optSet => {
     optSet = startOptions(optConfig, optSet, __TEAMCLASS);
                    // Werte aus der HTML-Seite ermitteln...
                    const __BOXSAISONS = document.getElementsByTagName('option');
                    const __SAISON = getSelectionFromComboBox(__BOXSAISONS, 0, 'Number');
                    const __LIGASIZE = (optParams.Tab ? getLigaSizeFromSpielplan(optParams.Tab.rows, optParams.Zei, optParams.Spa, getOptValue(optSet.saison)) : undefined);


                    // ... und abspeichern...
    // Werte aus der HTML-Seite ermitteln...
                    setOpt(optSet.saison, __SAISON, false);
    const __BOXSAISONS = document.getElementsByTagName('option');
                    setOpt(optSet.ligaSize, __LIGASIZE, false);
    const __SAISON = getSelectionFromComboBox(__BOXSAISONS, 0, 'Number');
    const __LIGASIZE = getLigaSizeFromSpielplan(optParams.Tab.rows, optParams.Zei, optParams.Spa, getOptValue(optSet.saison));


                    return showOptions(optSet, optParams);
    // ... und abspeichern...
                }, defaultCatch);
    setOpt(optSet.saison, __SAISON, false);
}
    setOpt(optSet.ligaSize, __LIGASIZE, false);
 
    showOptions(optSet, optParams);
 
    return optSet;
}


// ==================== Ende Abschnitt fuer Optionen ====================
// ==================== Ende Abschnitt fuer Optionen ====================
Zeile 3.416: Zeile 3.133:
                             this.uri.setQueryPar('landauswahl', team.LdNr);
                             this.uri.setQueryPar('landauswahl', team.LdNr);
                             this.uri.setQueryPar('ligaauswahl', team.LgNr);
                             this.uri.setQueryPar('ligaauswahl', team.LgNr);
                            this.uri.setQueryPar('hl',          team.TmNr);                        },
                        },
         'setPage'      : function(page, label) {
         'setPage'      : function(page, label) {
                             this.uri.home();
                             this.uri.home();
Zeile 3.478: Zeile 3.195:
         'saison'      : saison,
         'saison'      : saison,
         'ZAT'          : 0,
         'ZAT'          : 0,
         'gameType'    : 'spielfrei',
         'gameType'    : "spielfrei",
         'heim'        : true,
         'heim'        : true,
         'gegner'      : "",
         'gegner'      : "",
Zeile 3.575: Zeile 3.292:
     const __LINK = new RundenLink(currZAT.saison, __TEAMCLASS.team);
     const __LINK = new RundenLink(currZAT.saison, __TEAMCLASS.team);


     if (currZAT.gameType === 'Liga') {
     if (currZAT.gameType === "Liga") {
         if (currZAT.ZAT < 70) {
         if (currZAT.ZAT < 70) {
             __LINK.setRunde('stauswahl', currZAT.ligaSpieltag);
             __LINK.setRunde("stauswahl", currZAT.ligaSpieltag);
             __LINK.setPage('ls', __LINK.runde + ". Spieltag");
             __LINK.setPage("ls", __LINK.runde + ". Spieltag");
         } else {
         } else {
             __LINK.setLabel("Relegation");
             __LINK.setLabel("Relegation");
         }
         }
     } else if (currZAT.gameType === 'LP') {
     } else if (currZAT.gameType === "LP") {
         __LINK.setRunde('stauswahl', currZAT.pokalRunde);
         __LINK.setRunde("stauswahl", currZAT.pokalRunde);
         __LINK.setPage('lp', __POKALRUNDEN[__LINK.runde]);
         __LINK.setPage("lp", __POKALRUNDEN[__LINK.runde]);
     } else if ((currZAT.gameType === 'OSCQ') || (currZAT.gameType === 'OSEQ')) {
     } else if ((currZAT.gameType === "OSCQ") || (currZAT.gameType === "OSEQ")) {
         __LINK.setRunde('runde', currZAT.euroRunde);
         __LINK.setRunde("runde", currZAT.euroRunde);
         __LINK.setPage(((currZAT.gameType === 'OSCQ') ? 'oscq' : 'oseq'), __QUALIRUNDEN[__LINK.runde] + __HINRUECK[currZAT.hinRueck]);
         __LINK.setPage(((currZAT.gameType === "OSCQ") ? "oscq" : "oseq"), __QUALIRUNDEN[__LINK.runde] + __HINRUECK[currZAT.hinRueck]);
     } else if (currZAT.gameType === 'OSC') {
     } else if (currZAT.gameType === "OSC") {
         if (currZAT.euroRunde < 9) {
         if (currZAT.euroRunde < 9) {
             const __GRUPPENPHASE = ((currZAT.euroRunde < 6) ? "HR-Grp. " : "ZR-Grp. ");
             const __GRUPPENPHASE = ((currZAT.euroRunde < 6) ? "HR-Grp. " : "ZR-Grp. ");


             __LINK.setRunde("", (currZAT.euroRunde % 3) * 2 + 1 + currZAT.hinRueck);
             __LINK.setRunde("", (currZAT.euroRunde % 3) * 2 + 1 + currZAT.hinRueck);
             __LINK.setPage(((currZAT.euroRunde < 6) ? 'oschr' : 'osczr'), __GRUPPENPHASE + "Spiel " + __LINK.runde);
             __LINK.setPage(((currZAT.euroRunde < 6) ? "oschr" : "osczr"), __GRUPPENPHASE + "Spiel " + __LINK.runde);
         } else {
         } else {
             __LINK.setPage('oscfr', __OSCRUNDEN[currZAT.euroRunde - 8] + __HINRUECK[currZAT.hinRueck]);
             __LINK.setPage("oscfr", __OSCRUNDEN[currZAT.euroRunde - 8] + __HINRUECK[currZAT.hinRueck]);
         }
         }
     } else if (currZAT.gameType === 'OSE') {
     } else if (currZAT.gameType === "OSE") {
         __LINK.setRunde('runde', currZAT.euroRunde - 3);
         __LINK.setRunde("runde", currZAT.euroRunde - 3);
         __LINK.setPage('ose', __OSERUNDEN[__LINK.runde] + __HINRUECK[currZAT.hinRueck]);
         __LINK.setPage("ose", __OSERUNDEN[__LINK.runde] + __HINRUECK[currZAT.hinRueck]);
    } else if (currZAT.gameType === 'Supercup') {
        __LINK.setRunde("", 1);
        __LINK.setPage('supercup', currZAT.gameType);
     } else {
     } else {
         __LINK.setLabel();  // irgendwie besser lesbar! ("Friendly" bzw. "spielfrei"/"Frei"/"reserviert")
         __LINK.setLabel();  // irgendwie besser lesbar! ("Friendly" bzw. "spielfrei"/"Frei"/"reserviert")
Zeile 3.670: Zeile 3.384:
// ==================== Abschnitt fuer interne IDs auf den Seiten ====================
// ==================== Abschnitt fuer interne IDs auf den Seiten ====================


const __GAMETYPENRN = {    // "Blind FSS gesucht!"
const __GAMETYPES = {    // "Blind FSS gesucht!"
         'unbekannt'  : -1,
         'unbekannt'  : -1,
         'reserviert' :  0,
         "reserviert" :  0,
         'Frei'       :  0,
         "Frei"       :  0,
         'spielfrei' :  0,
         "spielfrei" :  0,
         'Friendly'   :  1,
         "Friendly"   :  1,
         'Liga'       :  2,
         "Liga"       :  2,
         'LP'         :  3,
         "LP"         :  3,
         'OSEQ'       :  4,
         "OSEQ"       :  4,
         'OSE'       :  5,
         "OSE"       :  5,
         'OSCQ'       :  6,
         "OSCQ"       :  6,
         'OSC'       :  7,
         "OSC"       :  7
        'Supercup'  : 10
    };
 
const __GAMETYPEALIASES = {
        'unbekannt'  :  "unbekannt",
        'reserviert' :  undefined,
        'Frei'      :  undefined,
        'spielfrei'  :  "",
        'Friendly'  :  "FSS",
        'Liga'      :  undefined,
        'LP'        :  "Pokal",
        'OSEQ'      :  undefined,
        'OSE'        :  undefined,
        'OSCQ'      :  undefined,
        'OSC'        :  undefined,
        'Supercup'  : "Super"
     };
     };
const __GAMETYPES = reverseMapping(__GAMETYPENRN);


const __LIGANRN = {
const __LIGANRN = {
Zeile 3.711: Zeile 3.408:
         '3. Liga D'  :  7
         '3. Liga D'  :  7
     };
     };
const __LIGATYPES = reverseMapping(__LIGANRN);


const __LANDNRN = {
const __LANDNRN = {
Zeile 3.768: Zeile 3.464:
         'Zypern'                :  38
         'Zypern'                :  38
     };
     };
const __LAENDER = reverseMapping(__LANDNRN);
const __TLALAND = {
        undefined : 'unbekannt',
        'ALB'    : 'Albanien',
        'AND'    : 'Andorra',
        'ARM'    : 'Armenien',
        'AZE'    : 'Aserbaidschan',
        'BEL'    : 'Belgien',
        'BIH'    : 'Bosnien-Herzegowina',
        'BUL'    : 'Bulgarien',
        'DEN'    : 'D\xE4nemark',
        'GER'    : 'Deutschland',
        'ENG'    : 'England',
        'EST'    : 'Estland',
        'FRO'    : 'Far\xF6er',
        'FIN'    : 'Finnland',
        'FRA'    : 'Frankreich',
        'GEO'    : 'Georgien',
        'GRE'    : 'Griechenland',
        'IRL'    : 'Irland',
        'ISL'    : 'Island',
        'ISR'    : 'Israel',
        'ITA'    : 'Italien',
        'KAZ'    : 'Kasachstan',
        'CRO'    : 'Kroatien',
        'LVA'    : 'Lettland',
        'LIE'    : 'Liechtenstein',
        'LTU'    : 'Litauen',
        'LUX'    : 'Luxemburg',
        'MLT'    : 'Malta',
        'MKD'    : 'Mazedonien',
        'MDA'    : 'Moldawien',
        'NED'    : 'Niederlande',
        'NIR'    : 'Nordirland',
        'NOR'    : 'Norwegen',
        'AUT'    : '\xD6sterreich',
        'POL'    : 'Polen',
        'POR'    : 'Portugal',
        'ROM'    : 'Rum\xE4nien',
        'RUS'    : 'Russland',
        'SMR'    : 'San Marino',
        'SCO'    : 'Schottland',
        'SWE'    : 'Schweden',
        'SUI'    : 'Schweiz',
        'SCG'    : 'Serbien und Montenegro',
        'SVK'    : 'Slowakei',
        'SVN'    : 'Slowenien',
        'ESP'    : 'Spanien',
        'CZE'    : 'Tschechien',
        'TUR'    : 'T\xFCrkei',
        'UKR'    : 'Ukraine',
        'HUN'    : 'Ungarn',
        'WAL'    : 'Wales',
        'BLR'    : 'Weissrussland',
        'CYP'    : 'Zypern'
    };
const __LANDTLAS = reverseMapping(__TLALAND);


// ==================== Abschnitt fuer Daten des Spielplans ====================
// ==================== Abschnitt fuer Daten des Spielplans ====================
Zeile 3.831: Zeile 3.469:
// Gibt die ID fuer den Namen eines Wettbewerbs zurueck
// Gibt die ID fuer den Namen eines Wettbewerbs zurueck
// gameType: Name des Wettbewerbs eines Spiels
// gameType: Name des Wettbewerbs eines Spiels
// defValue: Default-Wert
// return OS2-ID fuer den Spieltyp (1 bis 7), 0 fuer spielfrei/Frei/reserviert, -1 fuer ungueltig
// return OS2-ID fuer den Spieltyp (1 bis 7 oder 10), 0 fuer "spielfrei"/"Frei"/"reserviert", -1 fuer ungueltig
function getGameTypeID(gameType) {
function getGameTypeID(gameType, defValue = __GAMETYPENRN.unbekannt) {
     return getValue(__GAMETYPES[gameType], __GAMETYPES.unbekannt);
     return getValue(__GAMETYPENRN[gameType], defValue);
}
 
// Gibt den Namen eines Wettbewerbs zurueck
// id: OS2-ID des Wettbewerbs eines Spiels (1 bis 7 oder 10), 0 fuer "spielfrei"/"Frei"/"reserviert", -1 fuer ungueltig
// defValue: Default-Wert
// return Spieltyp fuer die uebergebene OS2-ID
function getGameType(id, defValue) {
    return getValue(__GAMETYPES[id], defValue);
}
 
// Gibt den alternativen (Kurznamen) fuer den Namen eines Wettbewerbs zurueck
// gameType: Name des Wettbewerbs eines Spiels
// return Normalerweise den uebergebenen Parameter, in Einzelfaellen eine Kurzversion
function getGameTypeAlias(gameType) {
    return getValue(__GAMETYPEALIASES[gameType], getValue(gameType, __GAMETYPEALIASES.unbekannt));
}
 
// Gibt den Namen des Landes mit dem uebergebenen Kuerzel (TLA) zurueck.
// tla: Kuerzel (TLA) des Landes
// defValue: Default-Wert
// return Name des Landes, 'unbekannt' fuer undefined
function getLandName(tla, defValue = __TLALAND[undefined]) {
    return getValue(__TLALAND[tla], defValue);
}
}


// Gibt die ID des Landes mit dem uebergebenen Namen zurueck.
// Gibt die ID des Landes mit dem uebergebenen Namen zurueck.
// land: Name des Landes
// land: Name des Landes
// defValue: Default-Wert
// return OS2-ID des Landes, 0 fuer ungueltig
// return OS2-ID des Landes, 0 fuer ungueltig
function getLandNr(land, defValue = __LANDNRN.unbekannt) {
function getLandNr(land) {
     return getValue(__LANDNRN[land], defValue);
     return getValue(__LANDNRN[land], __LANDNRN.unbekannt);
}
}


// Gibt die ID der Liga mit dem uebergebenen Namen zurueck.
// Gibt die ID der Liga mit dem uebergebenen Namen zurueck.
// land: Name der Liga
// land: Name der Liga
// defValue: Default-Wert
// return OS2-ID der Liga, 0 fuer ungueltig
// return OS2-ID der Liga, 0 fuer ungueltig
function getLigaNr(liga, defValue = __LIGANRN.unbekannt) {
function getLigaNr(liga) {
     return getValue(__LIGANRN[liga], defValue);
     return getValue(__LIGANRN[liga], __LIGANRN.unbekannt);
}
}


// Kehrt das Mapping eines Objekts um und liefert ein neues Objekt zurueck.
// Ermittelt den Spielgegner aus einer Tabellenzelle und liefert den Namen zurueck
// obj: Objekt mit key => value
// cell: Tabellenzelle mit dem Namen des Gegners
// convFun: Konvertierfunktion fuer die Werte
// return Der Name des Gegners
// return Neues Objekt mit value => key (doppelte value-Werte fallen heraus!)
function getGegnerFromCell(cell) {
function reverseMapping(obj, convFun) {
    const __GEGNER = cell.textContent;
    if (! obj) {
    const __POS = __GEGNER.indexOf(" (");
         return obj;
 
    if (~ __POS) {
        return __GEGNER.substr(0, __POS);
    } else {
         return __GEGNER;
     }
     }
}


     const __RET = { };
// Ermittelt das Spiel-Ergebnis aus einer Tabellenzelle, etwa "2 : 1", und liefert zwei Werte zurueck
// cell: Tabellenzelle mit Eintrag "2 : 1"
// return { '2', '1' } im Beispiel
function getErgebnisFromCell(cell) {
     const __ERGEBNIS = cell.textContent.split(" : ", 2);


    for (let key in obj) {
     return __ERGEBNIS;
        const __VALUE = obj[key];
 
        __RET[__VALUE] = (convFun ? convFun(key) : key);
    }
 
     return __RET;
}
}


// ==================== Abschnitt fuer sonstige Parameter ====================
// Ermittelt die Spielart aus einer Tabellenzelle, etwa "Liga : Heim", und liefert zwei Werte zurueck
 
// cell: Tabellenzelle mit Eintrag "Liga : Heim" (Spielplan) oder "Liga  Heim: " (Managerbuero)
// Formatiert eine Zelle um (mit einfachen Parametern)
// return { "Liga", "Heim" } im Beispiel
// cell: Zu formatierende Zelle
function getSpielArtFromCell(cell) {
// bold: Inhalt fett darstellen (true = ja, false = nein)
     const __TEXT = cell.textContent.replace('\xA0', "").replace(':', "").replace("  ", ' ');
// color: Falls angegeben, die Schriftfarbe
    const __SPIELART = __TEXT.split(' ', 2);
// bgColor: Falls angegeben, die Hintergrundfarbe
// return Die formatierte Zelle
function formatCell(cell, bold = true, color = undefined, bgColor = undefined) {
     if (cell) {
        if (bold) {
            cell.style.fontWeight = 'bold';
        }
        if (color) {
            cell.style.color = color;
        }
        if (bgColor) {
            cell.style.backgroundColor = bgColor;
        }
    }


     return cell;
     return __SPIELART;
}
}


// Ermittelt die auszugewaehlenden Werte eines Selects (Combo-Box) als Array zurueck
// Ermittelt den Namen des Spielgegners aus einer Tabellenzelle und setzt gegner im Spielplanzeiger
// element: 'select'-Element oder dessen Name auf der HTML-Seite mit 'option'-Eintraegen der Combo-Box
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// valType: Typ-Klasse der Optionswerte ('String', 'Number', ...)
// cell: Tabellenzelle mit dem Namen des Gegners
// valFun: Funktion zur Ermittlung des Wertes eines 'option'-Eintrags (getSelectedOptionText, getSelectedValue, ...)
function setGegnerFromCell(currZAT, cell) {
// defValue: Default-Wert, falls nichts selektiert ist
     const __GEGNER = getGegnerFromCell(cell);
// return Array mit den Options-Werten
function getSelectionArray(element, valType = 'String', valFun = getSelectedValue, defValue = undefined) {
     const __SELECT = ((typeof element) === 'string' ? getValue(document.getElementsByName(element), [])[0] : element);


     return (__SELECT ? [].map.call(__SELECT.options, function(option) {
     currZAT.gegner = __GEGNER;
                                                        return this[valType](getValue(valFun(option), defValue));
                                                    }) : undefined);
}
}


// Ermittelt den ausgewaehlten Wert eines Selects (Combo-Box) und gibt diesen zurueck
// Ermittelt das Spiel-Ergebnis aus einer Tabellenzelle und setzt tore/gtore im Spielplanzeiger
// element: 'select'-Element oder dessen Name auf der HTML-Seite mit 'option'-Eintraegen der Combo-Box
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// valType: Typ-Klasse der Optionswerte ('String', 'Number', ...)
// cell: Tabellenzelle mit Eintrag "2 : 1"
// valFun: Funktion zur Ermittlung des Wertes eines 'option'-Eintrags (getSelectedOptionText, getSelectedValue, ...)
// return Modifizierter Spielplanzeiger
// defValue: Default-Wert, falls nichts selektiert ist
function setErgebnisFromCell(currZAT, cell) {
// return Ausgewaehlter Wert
     const __ERGEBNIS = getErgebnisFromCell(cell);
function getSelection(element, valType = 'String', valFun = getSelectedOptionText, defValue = undefined) {
 
     const __SELECT = ((typeof element) === 'string' ? getValue(document.getElementsByName(element), [])[0] : element);
    if (__ERGEBNIS.length === 2) {
        currZAT.gFor = parseInt(__ERGEBNIS[0], 10);
        currZAT.gAga = parseInt(__ERGEBNIS[1], 10);
    } else {
        currZAT.gFor = -1;
        currZAT.gAga = -1;
    }


     return this[valType](getValue(valFun(__SELECT), defValue));
     return currZAT;
}
}


// Ermittelt den ausgewaehlten Wert einer Combo-Box und gibt diesen zurueck
// Ermittelt die Spielart aus einer Tabellenzelle und setzt gameType/heim im Spielplanzeiger
// comboBox: Alle 'option'-Eintraege der Combo-Box
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// defValue: Default-Wert, falls nichts selektiert ist
// cell: Tabellenzelle mit Eintrag "Liga : Heim" oder "Liga Heim"
// valType: Typ-Klasse der Optionswerte ('String', 'Number', ...)
function setSpielArtFromCell(currZAT, cell) {
// return Ausgewaehlter Wert
    const __SPIELART = getSpielArtFromCell(cell);
function getSelectionFromComboBox(comboBox, defValue = undefined, valType = 'String') {
 
     let selection;
    currZAT.gameType = __SPIELART[0];
    currZAT.heim    = (__SPIELART.length < 2) || (__SPIELART[1] === "Heim");
}
 
// Gibt die ID fuer den Namen eines Wettbewerbs zurueck
// cell: Tabellenzelle mit Link auf den Spielberichts-Link
// gameType: Name des Wettbewerbs eines Spiels
// label: Anzuklickender Text des neuen Links
// return HTML-Link auf die Preview-Seite fuer diesen Spielbericht
function getBilanzLinkFromCell(cell, gameType, label) {
    const __GAMETYPEID = getGameTypeID(gameType);
     let ret = "";


     for (let i = 0; i < comboBox.length; i++) {
     if (cell.textContent !== "Vorschau") {   // Nur falls Link nicht bereits vorhanden
         const __ENTRY = comboBox[i];
         if (__GAMETYPEID > 1) {              // nicht moeglich fuer "Friendly" bzw. "spielfrei"/"Frei"/"reserviert"
            const __SEARCHFUN = ":os_bericht(";
            let paarung = cell.innerHTML.substr(cell.innerHTML.indexOf(__SEARCHFUN) + __SEARCHFUN.length);


        if (__ENTRY.outerHTML.match(/selected/)) {
            paarung = paarung.substr(0, paarung.indexOf(')'));
             selection = __ENTRY.textContent;
            paarung = paarung.substr(0, paarung.lastIndexOf(','));
             paarung = paarung.substr(0, paarung.lastIndexOf(','));
            ret = ' <a href="javascript:spielpreview(' + paarung + ',' + __GAMETYPEID + ')">' + label + "</a>";
         }
         }
     }
     }


     return this[valType](getValue(selection, defValue));
     return ret;
}
}


// Liefert den Text (textContent) einer selektierten Option
// Addiert einen Link auf die Bilanz hinter den Spielberichts-Link
// element: 'select'-Element auf der HTML-Seite mit 'option'-Eintraegen der Combo-Box
// cell: Tabellenzelle mit Link auf den Spielberichts-Link
// return Wert der Selektion (textContent)
// gameType: Name des Wettbewerbs eines Spiels
function getSelectedOptionText(element) {
// label: Anzuklickender Text des neuen Links
     const __SELECTEDOPTIONS = getValue(element, { }).selectedOptions;
function addBilanzLinkToCell(cell, gameType, label) {
    const __OPTION = getValue(__SELECTEDOPTIONS, { })[0];
     const __BILANZLINK = getBilanzLinkFromCell(cell, gameType, label);


     return (__OPTION ? __OPTION.textContent : undefined);
     if (__BILANZLINK !== "") {
        cell.innerHTML += __BILANZLINK;
    }
}
}


// Liefert den 'value' einer selektierten Option
// ==================== Abschnitt fuer sonstige Parameter des Spielplans ====================
// element: 'select'-Element auf der HTML-Seite mit 'option'-Eintraegen der Combo-Box
// return Wert der Selektion ('value')
function getSelectedValue(element) {
    return getValue(element, { }).value;
}


// ==================== Ende Abschnitt fuer sonstige Parameter ====================
const __TEAMSEARCHHAUPT = {  // Parameter zum Team "<b>Willkommen im Managerb&uuml;ro von TEAM</b><br>LIGA LAND<a href=..."
        'Zeile'  : 0,
        'Spalte' : 1,
        'start'  : " von ",
        'middle' : "</b><br>",
        'liga'  : ". Liga",
        'land'  : ' ',
        'end'    : "<a href="
    };


// Ermittelt den Spielgegner aus einer Tabellenzelle und liefert den Namen zurueck
const __TEAMSEARCHTEAM = {  // Parameter zum Team "<b>TEAM - LIGA <a href=...>LAND</a></b>"
// cell: Tabellenzelle mit dem Namen des Gegners
        'Zeile'  : 0,
// return Der Name des Gegners
        'Spalte' : 0,
function getGegnerFromCell(cell) {
        'start'  : "<b>",
    const __GEGNER = cell.textContent;
        'middle' : " - ",
    const __POS = __GEGNER.indexOf(" (");
        'liga'  : ". Liga",
        'land'  : 'target="_blank">',
        'end'    : "</a></b>"
    };


    if (~ __POS) {
// Ermittelt, wie das eigene Team heisst und aus welchem Land bzw. Liga es kommt (zur Unterscheidung von Erst- und Zweitteam)
        return __GEGNER.substr(0, __POS);
// cell: Tabellenzelle mit den Parametern zum Team "startTEAMmiddleLIGA...landLANDend", LIGA = "#liga[ (A|B|C|D)]"
     } else {
// teamSeach: Muster fuer die Suche, die Eintraege fuer 'start', 'middle', 'liga', 'land' und 'end' enthaelt
        return __GEGNER;
// return Im Beispiel { 'Team' : "TEAM", 'Liga' : "LIGA", 'Land' : "LAND", 'LdNr' : LAND-NUMMER, 'LgNr' : LIGA-NUMMER },
     }
//        z.B. { 'Team' : "Choromonets Odessa", 'Liga' : "1. Liga", 'Land' : "Ukraine", 'LdNr' : 20, 'LgNr' : 1 }
}
function getTeamParamsFromTable(table, teamSearch = undefined) {
    const __TEAMSEARCH  = getValue(teamSearch, __TEAMSEARCHHAUPT);
    const __TEAMCELLROW  = getValue(__TEAMSEARCH.Zeile, 0);
    const __TEAMCELLCOL  = getValue(__TEAMSEARCH.Spalte, 0);
    const __TEAMCELLSTR  = (table === undefined) ? "" : table.rows[__TEAMCELLROW].cells[__TEAMCELLCOL].innerHTML;
    const __SEARCHSTART  = __TEAMSEARCH.start;
    const __SEARCHMIDDLE = __TEAMSEARCH.middle;
    const __SEARCHLIGA  = __TEAMSEARCH.liga;
     const __SEARCHLAND  = __TEAMSEARCH.land;
    const __SEARCHEND    = __TEAMSEARCH.end;
     const __INDEXSTART  = __TEAMCELLSTR.indexOf(__SEARCHSTART);
    const __INDEXEND    = __TEAMCELLSTR.indexOf(__SEARCHEND);


// Ermittelt das Spiel-Ergebnis aus einer Tabellenzelle, etwa "2 : 1", und liefert zwei Werte zurueck
    let teamParams = __TEAMCELLSTR.substring(__INDEXSTART + __SEARCHSTART.length, __INDEXEND);
// cell: Tabellenzelle mit Eintrag "2 : 1"
    const __INDEXLIGA = teamParams.indexOf(__SEARCHLIGA);
// return { '2', '1' } im Beispiel
     const __INDEXMIDDLE = teamParams.indexOf(__SEARCHMIDDLE);
function getErgebnisFromCell(cell) {
     const __ERGEBNIS = cell.textContent.split(" : ", 2);


     return __ERGEBNIS;
     let land = (~ __INDEXLIGA) ? teamParams.substring(__INDEXLIGA + __SEARCHLIGA.length) : undefined;
}
    const __TEAMNAME = (~ __INDEXMIDDLE) ? teamParams.substring(0, __INDEXMIDDLE) : undefined;
    let liga = ((~ __INDEXLIGA) && (~ __INDEXMIDDLE)) ? teamParams.substring(__INDEXMIDDLE + __SEARCHMIDDLE.length) : undefined;


// Ermittelt die Spielart aus einer Tabellenzelle, etwa "Liga : Heim", und liefert zwei Werte zurueck
    if (land !== undefined) {
// cell: Tabellenzelle mit Eintrag "Liga : Heim" (Spielplan) oder "Liga Heim: " (Managerbuero)
        if (land.charAt(2) === ' ') {    // Land z.B. hinter "2. Liga A " statt "1. Liga "
// return { "Liga", "Heim" } im Beispiel
            land = land.substr(2);
function getSpielArtFromCell(cell) {
        }
    const __TEXT = cell.textContent.replace('\xA0', "").replace(':', "").replace("  ", ' ');
        if (liga !== undefined) {
    const __SPIELART = __TEXT.split(' ', 2);
            liga = liga.substring(0, liga.length - land.length);
        }
        const __INDEXLAND = land.indexOf(__SEARCHLAND);
        if (~ __INDEXLAND) {
            land = land.substr(__INDEXLAND + __SEARCHLAND.length);
        }
    }


     return __SPIELART;
     const __TEAM = new Team(__TEAMNAME, land, liga);
}


// Ermittelt den Namen des Spielgegners aus einer Tabellenzelle und setzt gegner im Spielplanzeiger
     return __TEAM;
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// cell: Tabellenzelle mit dem Namen des Gegners
function setGegnerFromCell(currZAT, cell) {
     const __GEGNER = getGegnerFromCell(cell);
 
    currZAT.gegner = __GEGNER;
}
}


// Ermittelt das Spiel-Ergebnis aus einer Tabellenzelle und setzt tore/gtore im Spielplanzeiger
// Verarbeitet die URL der Seite und ermittelt die Nummer der gewuenschten Unterseite
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// url: Adresse der Seite
// cell: Tabellenzelle mit Eintrag "2 : 1"
// leafs: Liste von Filenamen mit der Default-Seitennummer (falls Query-Parameter nicht gefunden)
// return Modifizierter Spielplanzeiger
// item: Query-Parameter, der die Nummer der Unterseite angibt
function setErgebnisFromCell(currZAT, cell) {
// return Parameter aus der URL der Seite als Nummer
     const __ERGEBNIS = getErgebnisFromCell(cell);
function getPageIdFromURL(url, leafs, item = "page") {
     const __URI = new URI(url);
    const __LEAF = __URI.getLeaf();
 
    for (let leaf in leafs) {
        if (__LEAF === leaf) {
            const __DEFAULT = leafs[leaf];


    if (__ERGEBNIS.length === 2) {
            return getValue(__URI.getQueryPar(item), __DEFAULT);
        currZAT.gFor = parseInt(__ERGEBNIS[0], 10);
         }
         currZAT.gAga = parseInt(__ERGEBNIS[1], 10);
    } else {
        currZAT.gFor = -1;
        currZAT.gAga = -1;
     }
     }


     return currZAT;
     return -1;
}
}


// Ermittelt die Spielart aus einer Tabellenzelle und setzt gameType/heim im Spielplanzeiger
// Ermittelt den ausgewaehlten Wert eines Selects (Combo-Box) und gibt diesen zurueck
// currZAT: Enthaelt den Spielplanzeiger auf den aktuellen ZAT
// element: "select"-Element oder dessen Name auf der HTML-Seite mit 'option'-Eintraegen der Combo-Box
// cell: Tabellenzelle mit Eintrag "Liga : Heim" oder "Liga Heim"
// defValue: Default-Wert, falls nichts selektiert ist
function setSpielArtFromCell(currZAT, cell) {
// return Ausgewaehlter Wert
     const __SPIELART = getSpielArtFromCell(cell);
function getSelection(element, defValue = undefined, valType = 'String') {
     const __ELEMENT = ((typeof element) === 'string' ? document.getElementsByName(element) : element);
    const __ENTRY = (__ELEMENT ? __ELEMENT.selectedOptions[0] : undefined);


     currZAT.gameType = __SPIELART[0];
     return this[valType](getValue(__ENTRY, defValue, __ENTRY.textContent));
    currZAT.heim    = (__SPIELART.length < 2) || (__SPIELART[1] === 'Heim');
}
}


// Gibt die ID fuer den Namen eines Wettbewerbs zurueck
// Ermittelt den ausgewaehlten Wert einer Combo-Box und gibt diesen zurueck
// cell: Tabellenzelle mit Link auf den Spielberichts-Link
// comboBox: Alle 'option'-Eintraege der Combo-Box
// gameType: Name des Wettbewerbs eines Spiels
// defValue: Default-Wert, falls nichts selektiert ist
// label: Anzuklickender Text des neuen Links
// return Ausgewaehlter Wert
// return HTML-Link auf die Preview-Seite fuer diesen Spielbericht
function getSelectionFromComboBox(comboBox, defValue = undefined, valType = 'String') {
function getBilanzLinkFromCell(cell, gameType, label) {
     let selection;
    const __GAMETYPEID = getGameTypeID(gameType);
     let ret = "";


     if (cell.textContent !== 'Vorschau') {   // Nur falls Link nicht bereits vorhanden
     for (let i = 0; i < comboBox.length; i++) {
         if (__GAMETYPEID > 1) {              // nicht moeglich fuer "Friendly" bzw. "spielfrei"/"Frei"/"reserviert"
         const __ENTRY = comboBox[i];
            const __SEARCHFUN = ":os_bericht(";
            let paarung = cell.innerHTML.substr(cell.innerHTML.indexOf(__SEARCHFUN) + __SEARCHFUN.length);


            paarung = paarung.substr(0, paarung.indexOf(')'));
        if (__ENTRY.outerHTML.match(/selected/)) {
            paarung = paarung.substr(0, paarung.lastIndexOf(','));
             selection = __ENTRY.textContent;
             paarung = paarung.substr(0, paarung.lastIndexOf(','));
            ret = ' <a href="javascript:spielpreview(' + paarung + ',' + __GAMETYPEID + ')">' + label + "</a>";
         }
         }
     }
     }


     return ret;
     return this[valType](getValue(selection, defValue));
}
}


// Addiert einen Link auf die Bilanz hinter den Spielberichts-Link
// Ermittelt aus dem Spielplan die Ligengroesse ueber die Sonderspieltage
// cell: Tabellenzelle mit Link auf den Spielberichts-Link
// rows: Tabellenzeilen mit dem Spielplan
// gameType: Name des Wettbewerbs eines Spiels
// startIdx: Index der Zeile mit dem ersten ZAT
// label: Anzuklickender Text des neuen Links
// colArtIdx: Index der Spalte der Tabellenzelle mit der Spielart (z.B. "Liga : Heim")
function addBilanzLinkToCell(cell, gameType, label) {
// saison: Enthaelt die Nummer der laufenden Saison
     const __BILANZLINK = getBilanzLinkFromCell(cell, gameType, label);
// return 10 bei 36 Spielen, 18 bei 34 Spielen, 20 bei 38 Spielen
function getLigaSizeFromSpielplan(rows, startIdx, colArtIdx, saison) {
     const __LIGAEXTRA = getLigaExtra(saison);
    const __TEST10ER = getSpielArtFromCell(rows[startIdx + __LIGAEXTRA[0] - 1].cells[colArtIdx]);
    const __TEST20ER = getSpielArtFromCell(rows[startIdx + __LIGAEXTRA[2] - 1].cells[colArtIdx]);


     if (__BILANZLINK !== "") {
     if (__TEST20ER[0] === "Liga") {
         cell.innerHTML += __BILANZLINK;
         return 20;
    } else if (__TEST10ER[0] === "Liga") {
        return 10;
    } else {
        return 18;
     }
     }
}
}


// ==================== Abschnitt fuer sonstige Parameter des Spielplans ====================
// ==================== Ende Abschnitt fuer Spielplan und ZATs ====================


const __TEAMSEARCHHAUPT = // Parameter zum Team "<b>Willkommen im Managerb&uuml;ro von TEAM</b><br>LIGA LAND<a href=..."
// ==================== Hauptprogramm ====================
        'Tabelle'  : 1,
 
         'Zeile'     : 0,
// Verarbeitet Ansicht "Saisonplan"
         'Spalte'   : 1,
function procSpielplan() {
         'start'     : " von ",
    const __ROWOFFSETUPPER = 1;     // Header-Zeile
         'middle'   : "</b><br>",
    const __ROWOFFSETLOWER = 0;
         'liga'     : ". Liga",
 
         'land'     : ' ',
    const __COLUMNINDEX = {
         'end'       : "<a href="
         'ZAT' : 0,
         'Art' : 1,
         'Geg' : 2,
         'Erg' : 3,
         'Ber' : 4,
         'Zus' : 5,
         'Kom' : 6
     };
     };


const __TEAMSEARCHTEAM = { // Parameter zum Team "<b>TEAM - LIGA <a href=...>LAND</a></b>"
    const __TEAMPARAMS = getTeamParamsFromTable(getTable(1), __TEAMSEARCHTEAM); // Link mit Team, Liga, Land...
        'Tabelle'   : 1,
 
        'Zeile'     : 0,
    buildOptions(__OPTCONFIG, __OPTSET, {
        'Spalte'   : 0,
                    'Tab'       : getTable(2),
        'start'     : "<b>",
                    'Zei'       : __ROWOFFSETUPPER,
        'middle'   : " - ",
                    'Spa'       : __COLUMNINDEX.Art,
        'liga'     : ". Liga",
                    'teamParams' : __TEAMPARAMS,
        'land'     : 'target="_blank">',
                    'menuAnchor' : getTable(0, "div"),
        'end'       : "</a></b>"
                    'hideForm'   : {
     };
                                        'team'         : true
                                    },
                    'formWidth' : 3,
                    'formBreak' : 4
                });
 
     const __ZAT = firstZAT(getOptValue(__OPTSET.saison), getOptValue(__OPTSET.ligaSize));


const __TEAMIDSEARCHHAUPT = {  // Parameter zur Team-ID "<b>Deine Spiele in</b>...<a href="livegame/index.php?spiele=TEAMID,0">LIVEGAME</a>"
    const __ROWS = getRows(2);
        'Tabelle'  : 0,
        'Zeile'    : 6,
        'Spalte'    : 0,
        'start'    : '<a href="livegame/index.php?spiele=',
        'end'      : ',0">LIVEGAME</a>'
    };


const __TEAMIDSEARCHTEAM = {  // Parameter zur Team-ID "<b>Deine Spiele in</b>...<a href="livegame/index.php?spiele=TEAMID,0">LIVEGAME</a>"
    let ligaStats = emptyStats();
        'Tabelle'  : 0,
     let euroStats = emptyStats();
        'Zeile'     : 1,
        'Spalte'    : 1,
        'start'    : '<a hspace="20" href="javascript:tabellenplatz(',
        'end'      : ')">Tabellenpl\xE4tze</a>'
    };


// Ermittelt, wie das eigene Team heisst und aus welchem Land bzw. Liga es kommt (zur Unterscheidung von Erst- und Zweitteam)
     for (let i = __ROWOFFSETUPPER; i < __ROWS.length - __ROWOFFSETLOWER; i++) {
// teamSearch: Muster fuer die Suche nach Team, die Eintraege fuer 'start', 'middle', 'liga', 'land' und 'end' enthaelt, ausserdem die
        const __CELLS = __ROWS[i].cells;    // Aktuelle Eintraege
//              Adresse der Tabellenzelle mit den Parametern zum Team "startTEAMmiddleLIGA...landLANDend", LIGA = "#liga[ (A|B|C|D)]"
// teamIdSearch: Muster fuer die Suche nach Team-ID, die Eintraege fuer 'start' und 'end' enthaelt, ausserdem die
//              Adresse der Tabellenzelle mit den Parametern zur Team-ID "startTEAMIDend"
// doc: Optionale Angabe des Dokuments, in dem die Tabelle gesucht wird  (Default: document)
// return Im Beispiel { 'Team' : "TEAM", 'Liga' : "LIGA", 'Land' : "LAND", 'TmNr' : TEAMID, 'LdNr' : LAND-NUMMER, 'LgNr' : LIGA-NUMMER },
//        z.B. { 'Team' : "Choromonets Odessa", 'Liga' : "1. Liga", 'Land' : "Ukraine", 'TmNr' : 930, 'LdNr' : 20, 'LgNr' : 1 }
function getTeamParamsFromTable(teamSearch, teamIdSearch, doc = document) {
     // Ermittlung von Team, Liga und Land...
    const __TEAMSEARCH  = getValue(teamSearch, __TEAMSEARCHHAUPT);
    const __TEAMTABLE    = getTable(getValue(__TEAMSEARCH.Tabelle, 1), 'table', doc);
    const __TEAMCELLROW  = getValue(__TEAMSEARCH.Zeile, 0);
    const __TEAMCELLCOL  = getValue(__TEAMSEARCH.Spalte, 0);
    const __TEAMCELLSTR  = (__TEAMTABLE === undefined) ? "" : __TEAMTABLE.rows[__TEAMCELLROW].cells[__TEAMCELLCOL].innerHTML;
    const __SEARCHSTART  = __TEAMSEARCH.start;
    const __SEARCHMIDDLE = __TEAMSEARCH.middle;
    const __SEARCHLIGA  = __TEAMSEARCH.liga;
    const __SEARCHLAND  = __TEAMSEARCH.land;
    const __SEARCHEND   = __TEAMSEARCH.end;
    const __INDEXSTART  = __TEAMCELLSTR.indexOf(__SEARCHSTART);
    const __INDEXEND    = __TEAMCELLSTR.indexOf(__SEARCHEND);


    let teamParams = __TEAMCELLSTR.substring(__INDEXSTART + __SEARCHSTART.length, __INDEXEND);
        incZAT(__ZAT);
    const __INDEXLIGA = teamParams.indexOf(__SEARCHLIGA);
    const __INDEXMIDDLE = teamParams.indexOf(__SEARCHMIDDLE);


    let land = ((~ __INDEXLIGA) ? teamParams.substring(__INDEXLIGA + __SEARCHLIGA.length) : undefined);
        setGegnerFromCell(__ZAT, __CELLS[__COLUMNINDEX.Geg]);
    const __TEAMNAME = ((~ __INDEXMIDDLE) ? teamParams.substring(0, __INDEXMIDDLE) : undefined);
        setSpielArtFromCell(__ZAT, __CELLS[__COLUMNINDEX.Art]);
    let liga = (((~ __INDEXLIGA) && (~ __INDEXMIDDLE)) ? teamParams.substring(__INDEXMIDDLE + __SEARCHMIDDLE.length) : undefined);
        setErgebnisFromCell(__ZAT, __CELLS[__COLUMNINDEX.Erg]);


    if (land !== undefined) {
        if (getOptValue(__OPTSET.shortKom)) {
        if (land.charAt(2) === ' ') {    // Land z.B. hinter "2. Liga A " statt "1. Liga "
            const __CELLKOM = __CELLS[__COLUMNINDEX.Kom];
            land = land.substr(2);
            const __CELLART = __CELLS[__COLUMNINDEX.Art];
 
            __CELLKOM.innerHTML = __CELLKOM.innerHTML.replace("Vorbericht(e)", 'V').replace("Kommentar(e)", 'K').replace("&amp;", '/').replace('&', '/');
            __CELLART.innerHTML = __CELLART.innerHTML.replace(": Heim", "(H)").replace(": Ausw\xE4rts", "(A)").replace("Friendly", "FSS");
         }
         }
        if (liga !== undefined) {
            liga = liga.substring(0, liga.length - land.length);
        }
        const __INDEXLAND = land.indexOf(__SEARCHLAND);
        if (~ __INDEXLAND) {
            land = land.substr(__INDEXLAND + __SEARCHLAND.length);
        }
    }


    // Ermittlung der Team-ID (indirekt ueber den Livegame- bzw. Tabellenplatz-Link)...
        __CELLS[__COLUMNINDEX.Zus].className = __CELLS[__COLUMNINDEX.Art].className;
    const __TEAMIDSEARCH  = getValue(teamIdSearch, __TEAMIDSEARCHHAUPT);
 
    const __TEAMIDTABLE    = getTable(getValue(__TEAMIDSEARCH.Tabelle, 0), 'table', doc);
        if (__CELLS[__COLUMNINDEX.Zus].textContent === "") {
    const __TEAMIDCELLROW  = getValue(__TEAMIDSEARCH.Zeile, 6);
            const __CELLBER = __CELLS[__COLUMNINDEX.Ber];
    const __TEAMIDCELLCOL  = getValue(__TEAMIDSEARCH.Spalte, 0);
            let stats = "";
    const __TEAMIDCELLSTR  = (__TEAMIDTABLE === undefined) ? "" : __TEAMIDTABLE.rows[__TEAMIDCELLROW].cells[__TEAMIDCELLCOL].innerHTML;
 
    const __SEARCHIDSTART  = __TEAMIDSEARCH.start;
            addBilanzLinkToCell(__CELLBER, __ZAT.gameType, "Bilanz");
    const __SEARCHIDEND    = __TEAMIDSEARCH.end;
    const __INDEXIDSTART  = __TEAMIDCELLSTR.indexOf(__SEARCHIDSTART);
    const __INDEXIDEND    = __TEAMIDCELLSTR.indexOf(__SEARCHIDEND);
    const __TEAMIDSTR      = __TEAMIDCELLSTR.substring(__INDEXIDSTART + __SEARCHIDSTART.length, __INDEXIDEND);
    const __TEAMID        = Number.parseInt(__TEAMIDSTR, 10);


    const __TEAM = new Team(__TEAMNAME, land, liga, __TEAMID);
            if (getOptValue(__OPTSET.shortKom)) {
                __CELLBER.innerHTML = __CELLBER.innerHTML.replace("Klick", "(*)").replace("Bilanz", 'V').replace("Vorschau", 'V');
            }


    return __TEAM;
            if (__ZAT.gameType === "Liga") {
}
                if (__ZAT.ZAT < 70) {
                    stats = addResultToStats(ligaStats, getOptValue(__OPTSET.longStats), __ZAT);
                }
            } else if ((__ZAT.gameType === "OSCQ") || (__ZAT.gameType === "OSEQ") || (__ZAT.gameType === "OSE")) {
                if (__ZAT.hinRueck !== 1) {
                    euroStats = emptyStats();
                }
                stats = addResultToStats(euroStats, getOptValue(__OPTSET.longStats), __ZAT);
            } else if (__ZAT.gameType === "OSC") {
                if ((__ZAT.hinRueck !== 1) && ((__ZAT.euroRunde >= 9) || ((__ZAT.euroRunde % 3) === 0))) {
                    euroStats = emptyStats();
                }
                stats = addResultToStats(euroStats, getOptValue(__OPTSET.longStats), __ZAT);
            }


// Verarbeitet die URL der Seite und ermittelt die Nummer der gewuenschten Unterseite
            if (getOptValue(__OPTSET.showStats)) {
// url: Adresse der Seite
                if (stats !== "") {
// leafs: Liste von Filenamen mit der Default-Seitennummer (falls Query-Parameter nicht gefunden)
                    stats = ' ' + stats;
// item: Query-Parameter, der die Nummer der Unterseite angibt
                }
// return Parameter aus der URL der Seite als Nummer
            } else {
function getPageIdFromURL(url, leafs, item = 'page') {
                stats = "";
    const __URI = new URI(url);
            }
    const __LEAF = __URI.getLeaf();
            __CELLS[__COLUMNINDEX.Zus].innerHTML = getZusatz(__ZAT, true) + stats;
        }


    for (let leaf in leafs) {
        if (getOptValue(__OPTSET.sepMonths) && (__ZAT.ZAT % __ZAT.anzZATpMonth === 0) && (i < __ROWS.length - __ROWOFFSETLOWER - 1)) {
        if (__LEAF === leaf) {
            // Format der Trennlinie zwischen den Monaten...
             const __DEFAULT = leafs[leaf];
             const __BORDERSTRING = getOptValue(__OPTSET.sepStyle) + ' ' + getOptValue(__OPTSET.sepColor) + ' ' + getOptValue(__OPTSET.sepWidth);


             return getValue(__URI.getQueryPar(item), __DEFAULT);
/*
             for (let entry of __CELLS) {
                entry.style.borderBottom = __BORDERSTRING;
            }
*/
            for (let j = 0; j < __CELLS.length; j++) {
                __CELLS[j].style.borderBottom = __BORDERSTRING;
            }
         }
         }
     }
     }
    return -1;
}
}


// Ermittelt aus dem Spielplan die Ligengroesse ueber die Sonderspieltage
try {
// rows: Tabellenzeilen mit dem Spielplan
    // URL-Legende:
// startIdx: Index der Zeile mit dem ersten ZAT
    // s=0: Teamuebersicht
// colArtIdx: Index der Spalte der Tabellenzelle mit der Spielart (z.B. "Liga : Heim")
    // s=1: Vertragsdaten
// saison: Enthaelt die Nummer der laufenden Saison
    // s=2: Einzelwerte
// return 10 bei 36 Spielen, 18 bei 34 Spielen, 20 bei 38 Spielen
    // s=3: Statistik Saison
function getLigaSizeFromSpielplan(rows, startIdx, colArtIdx, saison) {
    // s=4: Statistik Gesamt
     const __LIGAEXTRA = getLigaExtra(saison);
    // s=5: Teaminfo
     const __TEST10ER = getSpielArtFromCell(rows[startIdx + __LIGAEXTRA[0] - 1].cells[colArtIdx]);
     // s=6: Saisonplan
     const __TEST20ER = getSpielArtFromCell(rows[startIdx + __LIGAEXTRA[2] - 1].cells[colArtIdx]);
     // s=7: Vereinshistorie
    // s=8: Transferhistorie
     // s=9: Leihhistorie


     if (__TEST20ER[0] === 'Liga') {
     // Verzweige in unterschiedliche Verarbeitungen je nach Wert von s:
        return 20;
    switch (getPageIdFromURL(window.location.href, {
    } else if (__TEST10ER[0] === 'Liga') {
                                                      'showteam.php' : 0,  // Teamansicht Hauptfenster
         return 10;
                                                      'st.php'       : 0  // Teamansicht Popupfenster
    } else {
                                                  }, 's')) {
         return 18;
         case 6  : procSpielplan(); break;
         default : break;
     }
     }
} catch (ex) {
    showAlert('[' + ex.lineNumber + "] " + __DBMOD.Name, ex.message, ex);
} finally {
    __LOG[2]("SCRIPT END");
}
}
// ==================== Ende Abschnitt fuer sonstige Parameter des Spielplans ====================
// ==================== Ende Abschnitt fuer Spielplan und ZATs ====================
// ==================== Hauptprogramm ====================
// Verarbeitet Ansicht "Saisonplan"
function procSpielplan() {
    const __ROWOFFSETUPPER = 1;    // Header-Zeile
    const __ROWOFFSETLOWER = 0;
    const __CLASSFREI = 'DMI';
    const __COLUMNINDEX = {
        'ZAT' : 0,
        'Art' : 1,
        'Geg' : 2,
        'Erg' : 3,
        'Ber' : 4,
        'Zus' : 5,
        'Kom' : 6
    };
    const __TEAMPARAMS = getTeamParamsFromTable(__TEAMSEARCHTEAM, __TEAMIDSEARCHTEAM);
    return buildOptions(__OPTCONFIG, __OPTSET, {
                            'Tab'        : getTable(2),
                            'Zei'        : __ROWOFFSETUPPER,
                            'Spa'        : __COLUMNINDEX.Art,
                            'teamParams' : __TEAMPARAMS,
                            'menuAnchor' : getTable(0, 'div'),
                            'hideForm'  : {
                                              'team'        : true
                                          },
                            'formWidth'  : 3,
                            'formBreak'  : 4
                        }).then(optSet => {
            const __ZAT = firstZAT(getOptValue(__OPTSET.saison), getOptValue(__OPTSET.ligaSize));
            const __ROWS = getRows(2);
            if (! __ROWS) {
                __LOG[0]("Kein Spielplan vorhanden!");
                return;
            }
            let ligaStats = emptyStats();
            let euroStats = emptyStats();
            for (let i = __ROWOFFSETUPPER; i < __ROWS.length - __ROWOFFSETLOWER; i++) {
                const __CELLS = __ROWS[i].cells;    // Aktuelle Eintraege
                const __ARTCLASS = __CELLS[__COLUMNINDEX.Art].className;
                incZAT(__ZAT);
                setGegnerFromCell(__ZAT, __CELLS[__COLUMNINDEX.Geg]);
                setSpielArtFromCell(__ZAT, __CELLS[__COLUMNINDEX.Art]);
                setErgebnisFromCell(__ZAT, __CELLS[__COLUMNINDEX.Erg]);
                if (getOptValue(__OPTSET.shortKom)) {
                    const __CELLKOM = __CELLS[__COLUMNINDEX.Kom];
                    const __CELLART = __CELLS[__COLUMNINDEX.Art];
                    __CELLKOM.innerHTML = __CELLKOM.innerHTML.replace("Vorbericht(e)", 'V').replace("Kommentar(e)", 'K').replace("&amp;", '/').replace('&', '/');
                    __CELLART.innerHTML = __CELLART.innerHTML.replace(": Heim", "(H)").replace(": Ausw\xE4rts", "(A)").replace(__ZAT.gameType, getGameTypeAlias(__ZAT.gameType));
                }
                __CELLS[__COLUMNINDEX.Erg].className = __ARTCLASS;
                __CELLS[__COLUMNINDEX.Zus].className = __ARTCLASS;
                if (__ZAT.gameType === 'spielfrei') {
                    __CELLS[__COLUMNINDEX.ZAT].className = __CLASSFREI;
                }
                if (__CELLS[__COLUMNINDEX.Zus].textContent === "") {
                    const __CELLBER = __CELLS[__COLUMNINDEX.Ber];
                    let stats = "";
                    addBilanzLinkToCell(__CELLBER, __ZAT.gameType, "Bilanz");
                    if (getOptValue(__OPTSET.shortKom)) {
                        __CELLBER.innerHTML = __CELLBER.innerHTML.replace("Klick", "(*)").replace("Bilanz", 'V').replace("Vorschau", 'V');
                    }
                    if (__ZAT.gameType === 'Liga') {
                        if (__ZAT.ZAT < 70) {
                            stats = addResultToStats(ligaStats, getOptValue(__OPTSET.longStats), __ZAT);
                        }
                    } else if ((__ZAT.gameType === 'OSCQ') || (__ZAT.gameType === 'OSEQ') || (__ZAT.gameType === 'OSE')) {
                        if (__ZAT.hinRueck !== 1) {
                            euroStats = emptyStats();
                        }
                        stats = addResultToStats(euroStats, getOptValue(__OPTSET.longStats), __ZAT);
                    } else if (__ZAT.gameType === 'OSC') {
                        if ((__ZAT.hinRueck !== 1) && ((__ZAT.euroRunde >= 9) || ((__ZAT.euroRunde % 3) === 0))) {
                            euroStats = emptyStats();
                        }
                        stats = addResultToStats(euroStats, getOptValue(__OPTSET.longStats), __ZAT);
                    }
                    if (getOptValue(__OPTSET.showStats)) {
                        if (stats !== "") {
                            stats = ' ' + stats;
                        }
                    } else {
                        stats = "";
                    }
                    __CELLS[__COLUMNINDEX.Zus].innerHTML = getZusatz(__ZAT, true) + stats;
                }
                if (getOptValue(__OPTSET.sepMonths) && (__ZAT.ZAT % __ZAT.anzZATpMonth === 0) && (i < __ROWS.length - __ROWOFFSETLOWER - 1)) {
                    // Format der Trennlinie zwischen den Monaten...
                    const __BORDERSTRING = getOptValue(__OPTSET.sepStyle) + ' ' + getOptValue(__OPTSET.sepColor) + ' ' + getOptValue(__OPTSET.sepWidth);
/*
                    for (let entry of __CELLS) {
                        entry.style.borderBottom = __BORDERSTRING;
                    }
*/
                    for (let j = 0; j < __CELLS.length; j++) {
                        __CELLS[j].style.borderBottom = __BORDERSTRING;
                    }
                }
            }
        });
}
(() => {
    (async () => {
        try {
            // URL-Legende:
            // s=0: Teamuebersicht
            // s=1: Vertragsdaten
            // s=2: Einzelwerte
            // s=3: Statistik Saison
            // s=4: Statistik Gesamt
            // s=5: Teaminfo
            // s=6: Saisonplan
            // s=7: Vereinshistorie
            // s=8: Transferhistorie
            // s=9: Leihhistorie
            // Verzweige in unterschiedliche Verarbeitungen je nach Wert von s:
            switch (getPageIdFromURL(window.location.href, {
                                                              'showteam.php' : 0,  // Teamansicht Hauptfenster
                                                              'st.php'      : 0  // Teamansicht Popupfenster
                                                          }, 's')) {
                case 6  : await procSpielplan().catch(defaultCatch); break;
                default : break;
            }
            return 'OK';
        } catch (ex) {
            return defaultCatch(ex);
        }
    })().then(rc => {
            __LOG[1]('SCRIPT END', __DBMOD.Name, '(' + rc + ')');
        })
})();


// *** EOF ***
// *** EOF ***
</pre>
</pre>

Bitte beachte, dass alle Beiträge zu Online-Soccer-Wiki von anderen Mitwirkenden bearbeitet, geändert oder gelöscht werden können. Reiche hier keine Texte ein, falls du nicht willst, dass diese ohne Einschränkung geändert werden können.

Du bestätigst hiermit auch, dass du diese Texte selbst geschrieben hast oder diese von einer gemeinfreien Quelle kopiert hast (weitere Einzelheiten unter Online-Soccer-Wiki:Urheberrechte). ÜBERTRAGE OHNE GENEHMIGUNG KEINE URHEBERRECHTLICH GESCHÜTZTEN INHALTE!

Abbrechen Bearbeitungshilfe (wird in einem neuen Fenster geöffnet)