dh_ackergaul
vor 3 Tagen 5bbf43c1b146439ab882815c12ed6292f1d7b4df
manufacturer/_furnview/_global/html/h/generic-katatree/js/modules/mod-standard.js
@@ -8,6 +8,39 @@
    this.constructionTypeListDistinctDimensions = {};
    this.defaultConfiguratorArt = undefined;
    this.pdfFile = undefined;
    this.manuCat = dh_TempGetJSONData("currentManuCat", "");
    this.modProg = "";
    this.modManu = "";
    /* GS [2026|06|09] Performance: Session-Cache fuer die statischen Katalog-Lookups.
    GetDynEquipment (Kategorie/Sortierung je ArtNr) und GetArtPropByArt (Vars je ArtNr)
    liefern fuer ein gegebenes (manu, prog, artNr[, progGroup]) immer dasselbe Ergebnis -
    das sind Katalog-Metadaten, die sich innerhalb einer Sitzung nicht aendern.
    Jeder dieser Aufrufe ist ein teurer synchroner FPS/COM-Roundtrip (JSON-Serialisierung
    hin und zurueck). buildEquipment ruft sie einmal PRO Zubehoer-Element auf und laeuft
    ueber onEquipmentChangeListeners bei JEDER Equipment-Aenderung komplett neu - das Cachen
    eliminiert die Roundtrips bei Wiederholung und bei doppelten ArtNrn vollstaendig.
    Die Ergebnisse werden nur gelesen, nie mutiert -> ein gemeinsam genutztes Objekt ist sicher. */
    this.dynEquipmentCache = {};
    this.artPropByArtCache = {};
    this.equipmentArtNumbersOnPage = [];
}
ModuleStandard.prototype.setEquipmentCache = function () {
    var self = this;
    var sqlResult = FurnplanCommunicationService.GetDynEquipment(this.modManu, this.modProg, this.equipmentArtNumbersOnPage, this.manuCat);
    if (sqlResult && sqlResult.rows && sqlResult.rows.length > 0) {
        sqlResult.rows.forEach(function (row) {
            var key = "KEY" + row.ArtNr;
            if (!self.dynEquipmentCache.hasOwnProperty(key)) {
                self.dynEquipmentCache[key] = [];
            }
            self.dynEquipmentCache[key].push(row);
        })
    }
    this.artPropByArtCache = FurnplanCommunicationService.GetArtPropByArt(this.modManu, this.modProg, this.equipmentArtNumbersOnPage);
}
ModuleStandard.prototype.getConstructionTypeListDistinctDimensionsFromArticles = function (articles) {
@@ -380,403 +413,291 @@
};
ModuleStandard.prototype.preFilter = function (clickEle) {
    var self = this;
    var selectedValues = {};
    var selectedCategories = {};
    var distinctValueList = {};
    var distinctCategoryList = {};
    distinctValueList.xMax = [];
    distinctValueList.yMax = [];
    distinctValueList.zMax = [];
    var clickedElement = $(clickEle);
    var clickedIsWildCard = clickedElement.attr("data-value") === "*";
    var clickedGroupIdent = clickedElement.attr("data-groupIdent");
    var clickedIsChecked = clickedElement.hasClass("checked");
    var clickedDimension = clickedElement.attr("data-dimension");
    var clickedPriority = clickedElement.attr("data-priority");
    // Wird im Original IMMER zurückgesetzt -- auch bei Klicks auf disabled/Wildcard.
    $(".hiddenByHideDimValuesByCategories").removeClass("hiddenByHideDimValuesByCategories");
    if (!clickedElement.hasClass("disabled")) {
        //Nur dann reagieren wenn Element nicht deaktiviert ist.
        if (clickedIsWildCard && clickedIsChecked) {
            //Wenn es ein WildCard-Element ist und eh schon gecheckt ist dann aus Funktion springen und nichts machen
            return;
        }
        if (clickedIsWildCard) {
            //Wenn WildCard und nicht ausgewählt, alle Elemente in der Gruppen unchecken und Wildcard checken
            // Deaktivierte nicht verändern das das durch postFiler passiert
            clickedElement.parent().parent().find(".checked").each(function () {
                var ele = $(this);
                if (ele.attr("data-groupIdent") === clickedGroupIdent) {
                    ele.removeClass("checked");
                }
            });
            clickedElement.toggleClass("checked");
        } else {
            //Wenn geklicktes Element kein Wildcard
            clickedElement.toggleClass("checked");
            var selectWildCard = true;
            //Wildcard in der Gruppe suchen und falls ausgewählt Auswahl entfernen
            clickedElement.parent().parent().find(".checked").each(function () {
                var ele = $(this);
                if (ele.attr("data-groupIdent") === clickedGroupIdent) {
                    if (ele.attr("data-value") === "*") {
                        ele.removeClass("checked");
                    }
                }
            });
            //Wenn durch klick kein ausgewähltes Element mehr in Gruppe dann Wildcard auswählen
            clickedElement.parent().parent().find(".checked").each(function () {
                var ele = $(this);
                if (ele.attr("data-groupIdent") === clickedGroupIdent) {
                    selectWildCard = false;
                }
            });
            if (selectWildCard) {
                clickedElement.parent().parent().find(".wildCard[data-groupIdent='" + clickedGroupIdent + "']").addClass("checked");
            }
        }
        var onlyCatWildCards = true;
        //Ausgewählte Kategorien
        self.distinctPriorities.forEach(function (prio) {
            if (prio >= 1000) {
                selectedCategories[prio] = [];
                distinctCategoryList[prio] = [];
                if (self.categoryValueButton[prio]) {
                    self.categoryValueButton[prio].forEach(function (jEle, index) {
                        if (jEle.attr("data-value") !== "*" && jEle.hasClass("checked")) {
                            selectedCategories[prio].push(jEle.attr("data-value"));
                            onlyCatWildCards = false;
                        }
                    });
                }
            }
        });
        //Ausgewählte Maße
        Object.keys(self.dimensionValueButton).forEach(function (key, index) {
            selectedValues[key] = [];
            self.dimensionValueButton[key].forEach(function (jEle, index) {
                if (jEle.hasClass("checked") && jEle.attr("data-value") !== "*") {
                    selectedValues[jEle.attr("data-dimension")].push(jEle.attr("data-value"));
                }
            });
        });
        var selectedGroupCount = 0;
        var selectedGroup = { "Prio": "", "Dim": "" };
        Object.keys(selectedCategories).forEach(function (prio, index) {
            if (selectedCategories[prio].length > 0) {
                selectedGroupCount += 1;
                selectedGroup.Prio = prio;
            }
        })
        Object.keys(selectedValues).forEach(function (dimension, index) {
            if (selectedValues[dimension].length > 0) {
                selectedGroupCount += 1;
                selectedGroup.Dim = dimension;
            }
        });
        self.filteredArticles = self.articles.filter(function (art) {
            var remove = false;
            //Prüfen ob der aktuelle Artikel die Abmessungen besitzt die gerade ausgewählt sind
            Object.keys(selectedValues).forEach(function (dimension) {
                if (selectedValues[dimension].length > 0 && selectedValues[dimension].indexOf(art[dimension]) === -1) {
                    remove = true;
                }
            });
            if (remove) {
                return false;
            }
            var prioChecked = {};
            Object.keys(selectedCategories).forEach(function (prio, index) {
                selectedCategories[prio].forEach(function (value, index) {
                    prioChecked[value] = false;
                })
            });
            //Prüfen ob alle Artikelkategorien in den selektierten Kategorien zu finde ist
            if (!onlyCatWildCards) {
                remove = true;
                art.artCategories.forEach(function (cat) {
                    if (selectedCategories[cat.priority] && selectedCategories[cat.priority].length > 0) {
                        if (!prioChecked[cat.priority]) {
                            if (selectedCategories[cat.priority].indexOf(cat.id) > -1) {
                                prioChecked[cat.priority] = true;
                                remove = false;
                            }
                        }
                    }
                });
            }
            if (remove) {
                return false;
            }
            //Erstellt eine Liste nach der Dimension gruppierte Liste aller Maße die in der aktuelll gefilterten Artikelmenge vorhanden sind
            Object.keys(distinctValueList).forEach(function (dimension) {
                if (distinctValueList[dimension].indexOf(art[dimension]) === -1) {
                    distinctValueList[dimension].push(art[dimension]);
                }
            });
            //Erstellt eine Liste nach der Priorität gruppierte Liste aller Kategorien die in der aktuelll gefilterten Artikelmenge vorhanden sind
            art.artCategories.forEach(function (cat) {
                if (cat.priority >= 1000 && distinctCategoryList[cat.priority] && distinctCategoryList[cat.priority].indexOf(cat.id) === -1) {
                    distinctCategoryList[cat.priority].push(cat.id);
                }
            });
            return true;
        });
        if (clickedDimension) {
            Object.keys(self.dimensionValueButton).forEach(function (key, index) {
                self.dimensionValueButton[key].forEach(function (jEle, index) {
                    if (key !== clickedDimension) {
                        if (jEle.attr("data-value") !== "*" && !jEle.hasClass("checked")) {
                            if (distinctValueList[jEle.attr("data-dimension")].indexOf(jEle.attr("data-value")) === -1) {
                                jEle.addClass("disabled");
                            } else {
                                jEle.removeClass("disabled");
                            }
                        }
                    } else {
                        if (jEle.attr("data-value") !== "*" && jEle.hasClass("disabled")) {
                            if (distinctValueList[jEle.attr("data-dimension")].indexOf(jEle.attr("data-value")) === -1) {
                                jEle.addClass("disabled");
                            } else {
                                jEle.removeClass("disabled");
                            }
                        }
                    }
                });
            });
        } else {
            Object.keys(self.dimensionValueButton).forEach(function (key, index) {
                self.dimensionValueButton[key].forEach(function (jEle, index) {
                    if (jEle.attr("data-value") !== "*") {
                        if (distinctValueList[jEle.attr("data-dimension")].indexOf(jEle.attr("data-value")) === -1) {
                            jEle.addClass("disabled");
                        } else {
                            jEle.removeClass("disabled");
                        }
                    }
                });
            });
        }
        if (clickedPriority) {
            Object.keys(self.categoryValueButton).forEach(function (prio) {
                if (self.categoryValueButton[prio]) {
                    self.categoryValueButton[prio].forEach(function (jEle, index) {
                        if (prio !== clickedPriority) {
                            if (jEle.attr("data-value") !== "*" && !jEle.hasClass("checked")) {
                                if (distinctCategoryList[prio].indexOf(jEle.attr("data-value")) === -1) {
                                    jEle.addClass("disabled");
                                    //Allle deaktivierten Kategorien ausblenden
                                    if (self.cfg["hideDisabledCategoriesInHigherPrio"] && (prio > clickedPriority)) {
                                        // if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
                                        jEle.hide();
                                    }
                                } else {
                                    jEle.removeClass("disabled");
                                    //Allle verfügbaren Kategorien einblenden
                                    if (self.cfg["hideDisabledCategoriesInHigherPrio"] && (prio > clickedPriority)) {
                                        // if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
                                        jEle.show();
                                    }
                                }
                            }
                        } else {
                            // if (jEle.attr("data-value") !== "*" && jEle.hasClass("disabled")) {
                            //     if (distinctCategoryList[prio].indexOf(jEle.attr("data-value")) === -1) {
                            //         jEle.addClass("disabled");
                            //     } else {
                            //         jEle.removeClass("disabled");
                            //     }
                            // }
                        }
                    })
                }
            });
        } else {
            Object.keys(self.categoryValueButton).forEach(function (prio) {
                if (self.categoryValueButton[prio]) {
                    self.categoryValueButton[prio].forEach(function (jEle, index) {
                        if (jEle.attr("data-value") !== "*") {
                            if (distinctCategoryList[prio].indexOf(jEle.attr("data-value")) === -1) {
                                jEle.addClass("disabled");
                                // if (self.cfg["hideDisabledCategoriesInHigherPrio"] && (prio > clickedPriority)) {
                                if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
                                    jEle.hide();
                                }
                            } else {
                                jEle.removeClass("disabled");
                                if (self.cfg["hideDisabledCategoriesInHigherPrio"] && (prio > clickedPriority)) {
                                    // if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
                                    jEle.show();
                                }
                            }
                        }
                    })
                }
            });
        }
        if (self.cfg["hideDimValuesByCategories"].length > 0) {
            //Erst wieder alle Buttons sichtbar machen
            Object.keys(self.dimensionValueButton).forEach(function (key, index) {
                self.dimensionValueButton[key].forEach(function (jEle, index) {
                    //jEle.show();
                });
            });
            //Alle Kategorien in ein Array packen
            var tmpSelectedCategories = [];
            Object.keys(selectedCategories).forEach(function (prio, index) {
                selectedCategories[prio].forEach(function (cat, index) {
                    tmpSelectedCategories.push(cat);
                })
            })
            //Alle Objekte in "hideDimValuesByCategories" durchlaufen
            self.cfg["hideDimValuesByCategories"].forEach(function (obj, index) {
                if (isStrArrayEqual(tmpSelectedCategories, obj.categories)) {
                    Object.keys(self.dimensionValueButton).forEach(function (key, index) {
                        self.dimensionValueButton[key].forEach(function (jEle, index) {
                            if (obj.values[key] && obj.values[key].indexOf(jEle.attr("data-value")) > -1) {
                                jEle.addClass("hiddenByHideDimValuesByCategories");
                            }
                        })
                    })
                }
            })
        }
        if (selectedGroupCount === 1) {
            if (selectedGroup.Dim !== "") {
                self.dimensionValueButton[selectedGroup.Dim].forEach(function (jEle, index) {
                    jEle.removeClass("disabled");
                })
            }
            if (selectedGroup.Prio !== "") {
                self.categoryValueButton[selectedGroup.Prio].forEach(function (jEle, index) {
                    jEle.removeClass("disabled");
                    if (self.cfg["hideDisabledCategoriesInHigherPrio"] && (selectedGroup.Prio > clickedPriority)) {
                        // if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
                        jEle.show();
                    }
                })
            }
        }
        // Wenn der Schalter "hideDisabledCategoriesInHigherPrio" aktiviert ist dann müssen die Wildcard
        // in einer Prio-Ebene ausgeblendet werden wenn alle Buttons in dieser Ebene ausgeblendet sinf
        if (self.cfg["hideDisabledCategoriesInHigherPrio"]) {
            Object.keys(self.categoryValueButton).forEach(function (prio) {
                if (self.categoryValueButton[prio]) {
                    var hideWildcard = false;
                    var btnCountHiddenNoneWildcard = 0;
                    self.categoryValueButton[prio].forEach(function (jEle, index) {
                        if (jEle.attr("data-value") !== "*" && jEle.css("display") === "none") {
                            btnCountHiddenNoneWildcard += 1;
                        }
                    })
                    if (btnCountHiddenNoneWildcard === self.categoryValueButton[prio].length - 1) {
                        self.categoryValueButton[prio].forEach(function (jEle, index) {
                            if (jEle.attr("data-value") === "*") {
                                jEle.hide();
                            }
                        })
                    } else {
                        self.categoryValueButton[prio].forEach(function (jEle, index) {
                            if (jEle.attr("data-value") === "*") {
                                jEle.show();
                            }
                        })
                    }
                }
            });
        }
        var flatSelectedCategories = [];
        Object.keys(selectedCategories).forEach(function (prio, index) {
            selectedCategories[prio].forEach(function (cat, index) {
                flatSelectedCategories.push(cat);
            })
        })
        var filterArticlesAllCats = [];
        var filterArticlesSomeCats = [];
        self.filteredArticles.forEach(function (art) {
            art.isCategorySpacer = false;
            //Prüfen ob alle selektieren Kategorie beim Artikel hinterlegt sind
            var hasAll = true;
            flatSelectedCategories.forEach(function (selectedCat) {
                var found = art.artCategories.find(function (cat) {
                    return cat.id === selectedCat;
                })
                if (!found) {
                    hasAll = false;
                }
            });
            if (hasAll) {
                filterArticlesAllCats.push(art);
            } else {
                filterArticlesSomeCats.push(art);
            }
        });
        var newAllArticles = [];
        // Wenn es gefilterte Artikel gibt, diese wieder zu newArticles hinzufügen
        filterArticlesAllCats.forEach(function (art) {
            newAllArticles.push(art);
        });
        // Wenn es alternative gefilterte Artikel gibt, diese wieder zu newArticles hinzufügen
        filterArticlesSomeCats.forEach(function (art, index) {
            if (index === 0) {
                //Vor erstem Artikel dann den Spacer anzeigen
                art.isCategorySpacer = true;
            }
            newAllArticles.push(art);
        });
        //Beim letzten Artikel dann Spacer zur Sicherheit deaktivieren
        // newAllArticles.forEach(function (art, index) {
        //     if (index === newAllArticles.length - 1) {
        //         art.isCategorySpacer = false;
        //     }
        // })
        var artContainer = $("." + self.id + ".articles");
        artContainer.empty();
        self.constructionTypeListDistinctDimensions = self.getConstructionTypeListDistinctDimensionsFromArticles(newAllArticles);
        artContainer.append(self.buildArticles(newAllArticles));
    // Deaktivierte Buttons ignorieren
    if (clickedElement.hasClass("disabled")) {
        return;
    }
    // --- Click-Metadaten einmalig auslesen ---
    var clickedValue = clickedElement.attr("data-value");
    var clickedGroupIdent = clickedElement.attr("data-groupIdent");
    var clickedDimension = clickedElement.attr("data-dimension");
    var clickedPriority = clickedElement.attr("data-priority");
    var clickedIsWildCard = clickedValue === "*";
    var clickedIsChecked = clickedElement.hasClass("checked");
    var hideHigherPrio = !!self.cfg["hideDisabledCategoriesInHigherPrio"];
    // Bereits aktive Wildcard erneut geklickt -> nichts zu tun
    if (clickedIsWildCard && clickedIsChecked) {
        return;
    }
    // --- Selektion in der Gruppe aktualisieren ---
    var groupContainer = clickedElement.parent().parent();
    var groupAttr = "[data-groupIdent='" + clickedGroupIdent + "']";
    if (clickedIsWildCard) {
        // Wildcard auswählen: alle Geschwister abwählen, Wildcard markieren
        groupContainer.find(".checked" + groupAttr).removeClass("checked");
        clickedElement.addClass("checked");
    } else {
        // Status togglen, Wildcard der Gruppe abwählen
        clickedElement.toggleClass("checked");
        groupContainer.find(".checked.wildCard" + groupAttr).removeClass("checked");
        // Wenn nach dem Klick nichts mehr in der Gruppe gewählt ist -> Wildcard aktivieren
        if (groupContainer.find(".checked" + groupAttr).length === 0) {
            groupContainer.find(".wildCard" + groupAttr).addClass("checked");
        }
    }
    // --- Selektierte Kategorien einsammeln ---
    var selectedCategories = {};
    var distinctCategoryList = {};
    var onlyCatWildCards = true;
    self.distinctPriorities.forEach(function (prio) {
        if (prio < 1000) return;
        selectedCategories[prio] = [];
        distinctCategoryList[prio] = [];
        var buttons = self.categoryValueButton[prio];
        if (!buttons) return;
        buttons.forEach(function (jEle) {
            if (jEle.attr("data-value") !== "*" && jEle.hasClass("checked")) {
                selectedCategories[prio].push(jEle.attr("data-value"));
                onlyCatWildCards = false;
            }
        });
    });
    // --- Selektierte Maße einsammeln ---
    var selectedValues = {};
    var distinctValueList = { xMax: [], yMax: [], zMax: [] };
    Object.keys(self.dimensionValueButton).forEach(function (key) {
        selectedValues[key] = [];
        self.dimensionValueButton[key].forEach(function (jEle) {
            if (jEle.hasClass("checked") && jEle.attr("data-value") !== "*") {
                selectedValues[jEle.attr("data-dimension")].push(jEle.attr("data-value"));
            }
        });
    });
    // --- Anzahl gefüllter Filtergruppen + Merken der letzten Gruppe ---
    var selectedGroupCount = 0;
    var selectedGroup = { Prio: "", Dim: "" };
    Object.keys(selectedCategories).forEach(function (prio) {
        if (selectedCategories[prio].length > 0) {
            selectedGroupCount += 1;
            selectedGroup.Prio = prio;
        }
    });
    Object.keys(selectedValues).forEach(function (dimension) {
        if (selectedValues[dimension].length > 0) {
            selectedGroupCount += 1;
            selectedGroup.Dim = dimension;
        }
    });
    var selectedValueKeys = Object.keys(selectedValues);
    var distinctValueKeys = Object.keys(distinctValueList);
    // --- Artikelliste filtern und distinkte Maße/Kategorien aufbauen ---
    self.filteredArticles = self.articles.filter(function (art) {
        // Maße prüfen
        for (var d = 0; d < selectedValueKeys.length; d++) {
            var dim = selectedValueKeys[d];
            if (selectedValues[dim].length > 0 && selectedValues[dim].indexOf(art[dim]) === -1) {
                return false;
            }
        }
        // Kategorien prüfen: mindestens ein Treffer in einer der gewählten Prioritäten
        if (!onlyCatWildCards) {
            var matched = false;
            for (var c = 0; c < art.artCategories.length; c++) {
                var cat = art.artCategories[c];
                var sel = selectedCategories[cat.priority];
                if (sel && sel.length > 0 && sel.indexOf(cat.id) > -1) {
                    matched = true;
                    break;
                }
            }
            if (!matched) {
                return false;
            }
        }
        // Distinkte Maßlisten aufbauen
        distinctValueKeys.forEach(function (dimension) {
            if (distinctValueList[dimension].indexOf(art[dimension]) === -1) {
                distinctValueList[dimension].push(art[dimension]);
            }
        });
        // Distinkte Kategorielisten aufbauen
        art.artCategories.forEach(function (cat) {
            if (cat.priority >= 1000 && distinctCategoryList[cat.priority] && distinctCategoryList[cat.priority].indexOf(cat.id) === -1) {
                distinctCategoryList[cat.priority].push(cat.id);
            }
        });
        return true;
    });
    // --- Maß-Buttons disable-/enable-Zustand aktualisieren ---
    var dimensionShouldDisable = function (jEle) {
        return distinctValueList[jEle.attr("data-dimension")].indexOf(jEle.attr("data-value")) === -1;
    };
    Object.keys(self.dimensionValueButton).forEach(function (key) {
        self.dimensionValueButton[key].forEach(function (jEle) {
            if (jEle.attr("data-value") === "*") return;
            if (clickedDimension) {
                // Auf der geklickten Achse nur deaktivierte Buttons anfassen,
                // auf den anderen Achsen nur nicht-gecheckte.
                var actOnThis = (key === clickedDimension)
                    ? jEle.hasClass("disabled")
                    : !jEle.hasClass("checked");
                if (!actOnThis) return;
            }
            jEle.toggleClass("disabled", dimensionShouldDisable(jEle));
        });
    });
    // --- Kategorie-Buttons disable-/enable-Zustand aktualisieren ---
    Object.keys(self.categoryValueButton).forEach(function (prio) {
        var buttons = self.categoryValueButton[prio];
        if (!buttons) return;
        var prioHidesHigher = hideHigherPrio && (prio > clickedPriority);
        buttons.forEach(function (jEle) {
            if (jEle.attr("data-value") === "*") return;
            // Auf der geklickten Priorität wurde original *nichts* getan (siehe alter Code).
            if (clickedPriority && prio === clickedPriority) return;
            // Auf anderen Prioritäten nur die nicht-gecheckten Buttons anfassen
            if (clickedPriority && jEle.hasClass("checked")) return;
            var shouldDisable = distinctCategoryList[prio].indexOf(jEle.attr("data-value")) === -1;
            jEle.toggleClass("disabled", shouldDisable);
            if (prioHidesHigher) {
                if (shouldDisable) jEle.hide();
                else jEle.show();
            } else if (!clickedPriority && hideHigherPrio && shouldDisable) {
                // Fallback ohne Click-Priorität: deaktivierte Buttons ausblenden
                jEle.hide();
            }
        });
    });
    // --- hideDimValuesByCategories: Maße ausblenden, deren Kategorie-Set passt ---
    if (self.cfg["hideDimValuesByCategories"].length > 0) {
        var flatCats = [];
        Object.keys(selectedCategories).forEach(function (prio) {
            flatCats = flatCats.concat(selectedCategories[prio]);
        });
        self.cfg["hideDimValuesByCategories"].forEach(function (obj) {
            if (!isStrArrayEqual(flatCats, obj.categories)) return;
            Object.keys(self.dimensionValueButton).forEach(function (key) {
                var rule = obj.values[key];
                if (!rule) return;
                self.dimensionValueButton[key].forEach(function (jEle) {
                    if (rule.indexOf(jEle.attr("data-value")) > -1) {
                        jEle.addClass("hiddenByHideDimValuesByCategories");
                    }
                });
            });
        });
    }
    // --- Bei genau einer aktiven Filtergruppe alles in dieser Gruppe aktivieren ---
    if (selectedGroupCount === 1) {
        if (selectedGroup.Dim !== "") {
            self.dimensionValueButton[selectedGroup.Dim].forEach(function (jEle) {
                jEle.removeClass("disabled");
            });
        }
        if (selectedGroup.Prio !== "") {
            var showHigher = hideHigherPrio && (selectedGroup.Prio > clickedPriority);
            self.categoryValueButton[selectedGroup.Prio].forEach(function (jEle) {
                jEle.removeClass("disabled");
                if (showHigher) jEle.show();
            });
        }
    }
    // --- Wildcard ausblenden, wenn in der Prio-Ebene keine echten Buttons mehr sichtbar sind ---
    if (hideHigherPrio) {
        Object.keys(self.categoryValueButton).forEach(function (prio) {
            var buttons = self.categoryValueButton[prio];
            if (!buttons) return;
            var hiddenNonWild = 0;
            var wildcardBtn = null;
            buttons.forEach(function (jEle) {
                if (jEle.attr("data-value") === "*") {
                    wildcardBtn = jEle;
                } else if (jEle.css("display") === "none") {
                    hiddenNonWild += 1;
                }
            });
            if (!wildcardBtn) return;
            if (hiddenNonWild === buttons.length - 1) {
                wildcardBtn.hide();
            } else {
                wildcardBtn.show();
            }
        });
    }
    // --- Artikel in "alle Kategorien getroffen" / "nur einige getroffen" sortieren ---
    var flatSelectedCategories = [];
    Object.keys(selectedCategories).forEach(function (prio) {
        flatSelectedCategories = flatSelectedCategories.concat(selectedCategories[prio]);
    });
    var filterArticlesAllCats = [];
    var filterArticlesSomeCats = [];
    self.filteredArticles.forEach(function (art) {
        art.isCategorySpacer = false;
        var hasAll = flatSelectedCategories.every(function (selectedCat) {
            return !!art.artCategories.find(function (cat) {
                return cat.id === selectedCat;
            });
        });
        if (hasAll) {
            filterArticlesAllCats.push(art);
        } else {
            filterArticlesSomeCats.push(art);
        }
    });
    // Spacer vor dem ersten "nur teilweise getroffenen" Artikel setzen
    if (filterArticlesSomeCats.length > 0) {
        filterArticlesSomeCats[0].isCategorySpacer = true;
    }
    var newAllArticles = filterArticlesAllCats.concat(filterArticlesSomeCats);
    var artContainer = $("." + self.id + ".articles");
    artContainer.empty();
    self.constructionTypeListDistinctDimensions = self.getConstructionTypeListDistinctDimensionsFromArticles(newAllArticles);
    artContainer.append(self.buildArticles(newAllArticles));
};
ModuleStandard.prototype.showDimension = function (dimension, articles) {