Added mechanism for apps to easily add their own custom link/node/host highlighting wihout having to create a new UI extensions

Change-Id: Iefa21d76190c60db79a4b07a8b22e301d29fe58e
diff --git a/web/gui/src/main/webapp/app/view/topo/topoForce.js b/web/gui/src/main/webapp/app/view/topo/topoForce.js
index 8819107..912e851 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoForce.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoForce.js
@@ -1023,6 +1023,7 @@
 
     function clearLinkTrafficStyle() {
         link.style('stroke-width', null)
+            .style('stroke', null)
             .classed(allTrafficClasses, false);
     }
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
index 4e9133a..7cf47ff 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoOverlay.js
@@ -398,6 +398,8 @@
             }
         });
 
+        const stylePattern = /style=\"[^\"]*\"/g;
+
         data.links.forEach(function (link) {
             var ldata = api.findLinkById(link.id);
 
@@ -405,6 +407,14 @@
                 if (!link.subdue) {
                     api.unsupLink(ldata.key, less);
                 }
+                var styleFound = link.css.match(stylePattern);
+                if (styleFound) {
+                    link.css = link.css.replace(stylePattern, '');
+                    var style = styleFound[0].replace('style="', '').replace('"$', '')
+                    ldata.el.attr('style', style);
+                } else {
+                    ldata.el.attr('style', '');
+                }
                 ldata.el.classed(link.css, true);
                 ldata.label = link.label;
 
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
index 640a233..c643494 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTraffic.js
@@ -47,7 +47,8 @@
     // internal state
     var trafficMode = null,
         hoverMode = null,
-        allTrafficIndex = 0;
+        allTrafficIndex = 0,
+        customTrafficIndex = 0;
 
 
     // === -----------------------------------------------------
@@ -137,6 +138,16 @@
         allTrafficIndex = (allTrafficIndex + 1) % 3;
     }
 
+    function showCustomTraffic() {
+        trafficMode = 'allCustom';
+        hoverMode = null;
+        wss.sendEvent('requestCustomTraffic', {
+            index: customTrafficIndex,
+        });
+        flash.flash('Custom Traffic');
+        customTrafficIndex = customTrafficIndex + 1;
+    }
+
     function showDeviceLinkFlows() {
         trafficMode = hoverMode = 'flows';
         requestDeviceLinkFlows();
@@ -270,6 +281,7 @@
                 showNextIntent: showNextIntent,
                 showSelectedIntentTraffic: showSelectedIntentTraffic,
                 selectIntent: selectIntent,
+                showCustomTraffic: showCustomTraffic,
 
                 // invoked from mouseover/mouseout and selection change
                 requestTrafficForMode: requestTrafficForMode,
diff --git a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
index 143aa30..2057f7b 100644
--- a/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
+++ b/web/gui/src/main/webapp/app/view/topo/topoTrafficNew.js
@@ -109,9 +109,14 @@
                 tt: function () { return topoLion('tr_btn_monitor_sel_intent'); },
                 gid: 'm_intentTraffic',
             },
+            C: {
+                cb: function () { tts.showCustomTraffic(); },
+                tt: function () { return topoLion('tr_btn_monitor_custom_all'); },
+                gid: 'm_allTraffic',
+            },
 
             _keyOrder: [
-                '0', 'A', 'F', 'V', 'leftArrow', 'rightArrow', 'W',
+                '0', 'A', 'F', 'V', 'leftArrow', 'rightArrow', 'W', 'C'
             ],
         },