From 87b98e28625fbafc0916df9f17d00ec6a5a468ac Mon Sep 17 00:00:00 2001 From: David Taylor Date: Mon, 21 Feb 2022 09:42:39 +0000 Subject: [PATCH] FIX: Ensure category/tag classes are added and removed correctly (#16003) The use of a `/g` regex was causing some surprising, seemingly random, behavior. (https://stackoverflow.com/a/1520853/5913559) There was also a known issue which would cause inconsistent class behavior when running the 'loading slider' theme component. This commit takes the opportunity to refactor the component to remove the use of observers and remove the regex-based class parsing. --- .../components/add-category-tag-classes.js | 67 ++++++++----------- .../app/templates/navigation/category.hbs | 2 +- 2 files changed, 28 insertions(+), 41 deletions(-) diff --git a/app/assets/javascripts/discourse/app/components/add-category-tag-classes.js b/app/assets/javascripts/discourse/app/components/add-category-tag-classes.js index 8cb6081fe8..ec4e54baf2 100644 --- a/app/assets/javascripts/discourse/app/components/add-category-tag-classes.js +++ b/app/assets/javascripts/discourse/app/components/add-category-tag-classes.js @@ -1,57 +1,44 @@ import Component from "@ember/component"; -import { observes } from "discourse-common/utils/decorators"; import { scheduleOnce } from "@ember/runloop"; -export default Component.extend({ - _slug: null, +export default class extends Component { + tagName = ""; + currentClasses = new Set(); - didInsertElement() { - this._super(...arguments); - this.refreshClass(); - }, + didReceiveAttrs() { + scheduleOnce("afterRender", this, this._updateClasses); + } - _updateClass() { + willDestroyElement() { + scheduleOnce("afterRender", this, this._removeClasses); + } + + _updateClasses() { if (this.isDestroying || this.isDestroyed) { return; } - const slug = this.get("category.fullSlug"); - this._removeClass(); - - const classes = []; + const desiredClasses = new Set(); + const slug = this.category?.fullSlug; if (slug) { - classes.push("category"); - classes.push(`category-${slug}`); + desiredClasses.add("category"); + desiredClasses.add(`category-${slug}`); } + this.tags?.forEach((t) => desiredClasses.add(`tag-${t}`)); - this.tags?.forEach((t) => classes.push(`tag-${t}`)); + document.body.classList.add(...desiredClasses); - document.body.classList.add(...classes); - }, + const removeClasses = [...this.currentClasses].filter( + (c) => !desiredClasses.has(c) + ); - @observes("category.fullSlug", "tags") - refreshClass() { - scheduleOnce("afterRender", this, this._updateClass); - }, + document.body.classList.remove(...removeClasses); - willDestroyElement() { - this._super(...arguments); - this._removeClass(); - }, + this.currentClasses = desiredClasses; + } - _removeClass() { - const invalidClasses = []; - const regex = /\b(?:category|tag)-\S+|( category )/g; - - document.body.classList.forEach((name) => { - if (regex.test(name)) { - invalidClasses.push(name); - } - }); - - if (invalidClasses.length) { - document.body.classList.remove(...invalidClasses); - } - }, -}); + _removeClasses() { + document.body.classList.remove(...this.currentClasses); + } +} diff --git a/app/assets/javascripts/discourse/app/templates/navigation/category.hbs b/app/assets/javascripts/discourse/app/templates/navigation/category.hbs index b2aa1dd413..de4d5d2d4b 100644 --- a/app/assets/javascripts/discourse/app/templates/navigation/category.hbs +++ b/app/assets/javascripts/discourse/app/templates/navigation/category.hbs @@ -1,4 +1,4 @@ -{{add-category-tag-classes category=category tagName=""}} +{{add-category-tag-classes category=category}}
{{#if category.uploaded_logo.url}}