From 8ab2d31bfe3540f510a6f2e48c7ffdfdee066cac Mon Sep 17 00:00:00 2001
From: Cherrg <michael@gnehr.de>
Date: Sun, 30 Jun 2019 13:55:48 +0200
Subject: [PATCH] fix topic bar to allow prefixes (#7325)

* - do not select if escape is pressed
- allow prefixes by adding current request content to result list
- remove html-tags before insert on page

fix #7126

Signed-off-by: Michael Gnehr <michael@gnehr.de>

* sort current query to top

Signed-off-by: Michael Gnehr <michael@gnehr.de>

* remove already added topics from dropdown list

Signed-off-by: Michael Gnehr <michael@gnehr.de>

* protoct against xss

thanks to @silverwind

Signed-off-by: Michael Gnehr <michael@gnehr.de>
---
 public/js/index.js | 41 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 37 insertions(+), 4 deletions(-)

diff --git a/public/js/index.js b/public/js/index.js
index 53fcaa8ba..b932ef959 100644
--- a/public/js/index.js
+++ b/public/js/index.js
@@ -2847,6 +2847,7 @@ function initTopicbar() {
 
     topicDropdown.dropdown({
         allowAdditions: true,
+        forceSelection: false,
         fields: { name: "description", value: "data-value" },
         saveRemoteData: false,
         label: {
@@ -2864,18 +2865,50 @@ function initTopicbar() {
             throttle: 500,
             cache: false,
             onResponse: function(res) {
-                var formattedResponse = {
+                let formattedResponse = {
                     success: false,
                     results: [],
                 };
+                const stripTags = function (text) {
+                    return text.replace(/<[^>]*>?/gm, "");
+                };
+
+                let query = stripTags(this.urlData.query.trim());
+                let found_query = false;
+                let current_topics = [];
+                topicDropdown.find('div.label.visible.topic,a.label.visible').each(function(_,e){ current_topics.push(e.dataset.value); });
 
                 if (res.topics) {
-                    formattedResponse.success = true;
-                    for (var i=0;i < res.topics.length;i++) {
-                        formattedResponse.results.push({"description": res.topics[i].Name, "data-value": res.topics[i].Name})
+                    let found = false;
+                    for (let i=0;i < res.topics.length;i++) {
+                        // skip currently added tags
+                        if (current_topics.indexOf(res.topics[i].Name) != -1){
+                            continue;
+                        }
+
+                        if (res.topics[i].Name.toLowerCase() === query.toLowerCase()){
+                            found_query = true;
+                        }
+                        formattedResponse.results.push({"description": res.topics[i].Name, "data-value": res.topics[i].Name});
+                        found = true;
                     }
+                    formattedResponse.success = found;
                 }
 
+                if (query.length > 0 && !found_query){
+                    formattedResponse.success = true;
+                    formattedResponse.results.unshift({"description": query, "data-value": query});
+                } else if (query.length > 0 && found_query) {
+                    formattedResponse.results.sort(function(a, b){
+                        if (a.description.toLowerCase() === query.toLowerCase()) return -1;
+                        if (b.description.toLowerCase() === query.toLowerCase()) return 1;
+                        if (a.description > b.description) return -1;
+                        if (a.description < b.description) return 1;
+                        return 0;
+                    });
+                }
+
+
                 return formattedResponse;
             },
         },