From bb80cdf5a6157ca1f3a276e12e9faae9a4739cb7 Mon Sep 17 00:00:00 2001
From: dh_ackergaul <dh_ackergaul@dh-software.de>
Date: Di, 23 Jun 2026 11:16:18 +0200
Subject: [PATCH] Update emvheya - 23.6.2026, 11:16:10 [JD]

---
 manufacturer/_furnview/_global/html/h/generic-katatree/js/modules/mod-standard.js |  703 ++++++++++++++++++++++++++--------------------------------
 1 files changed, 312 insertions(+), 391 deletions(-)

diff --git a/manufacturer/_furnview/_global/html/h/generic-katatree/js/modules/mod-standard.js b/manufacturer/_furnview/_global/html/h/generic-katatree/js/modules/mod-standard.js
index 030083c..5b608f4 100644
--- a/manufacturer/_furnview/_global/html/h/generic-katatree/js/modules/mod-standard.js
+++ b/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) {

--
Gitblit v1.9.3