Topo2: Improved node scaling performance

Originally the scale was being applied to all the child elements
of the node SVG. By grouping all the elements (label, icon, text, etc..)
into 1 group we can reduce the amount of 'redraw' events fired by 75%

- Label elements are grouped
- Icon elements are group

Change-Id: I7f7033174d70431ba9beb26dfe86d022a24cf048
diff --git a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
index 8e39922..7498696 100644
--- a/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
+++ b/web/gui/src/main/webapp/app/view/topo2/topo2NodeModel.js
@@ -151,28 +151,6 @@
                     return o ? sus.cat7().getColor(id, 0, ts.theme()) :
                         dColTheme[ts.theme()][otag];
                 },
-                addLabelElements: function (label) {
-                    var rect = this.el.append('rect')
-                        .attr('class', 'node-container');
-                    var glythRect = this.el.append('rect')
-                        .attr('class', 'icon-rect')
-                        .attr('y', -halfDevIcon)
-                        .attr('x', -halfDevIcon)
-                        .attr('width', devIconDim)
-                        .attr('height', devIconDim)
-                        .style('fill', this.devGlyphColor.bind(this));
-
-                    var text = this.el.append('text').text(label)
-                        .attr('text-anchor', 'left')
-                        .attr('y', '0.3em')
-                        .attr('x', halfDevIcon + labelPad + textPad);
-
-                    return {
-                        rect: rect,
-                        glythRect: glythRect,
-                        text: text
-                    };
-                },
                 labelBox: function (dim, labelWidth) {
                     var _textPad = (textPad * 2) - labelPad;
 
@@ -250,14 +228,56 @@
                         multipler = devIconDimMax / (dim * zoomService.scale());
                     }
 
-                    this.el.selectAll('*')
+                    this.el.select('.node-content')
                         .style('transform', 'scale(' + multipler + ')');
                 },
+                addLabelElements: function (label) {
+
+                    var labelG = this.el.select('.node-content')
+                        .append('g')
+                        .attr('class', 'label');
+
+                    var rect = labelG.append('rect')
+                        .attr('class', 'node-container');
+
+                    var text = labelG.append('text').text(label)
+                        .attr('text-anchor', 'left')
+                        .attr('y', '0.3em')
+                        .attr('x', halfDevIcon + labelPad + textPad);
+
+                    return {
+                        rect: rect,
+                        text: text
+                    };
+                },
+                addIconElements: function (el) {
+
+                    var glyphId = this.icon(this.get('type')),
+                        glyph;
+
+                    var iconG = el.append('g')
+                        .attr('class', 'icon')
+
+                    iconG.append('rect')
+                        .attr('class', 'icon-rect')
+                        .attr('y', -halfDevIcon)
+                        .attr('x', -halfDevIcon)
+                        .attr('width', devIconDim)
+                        .attr('height', devIconDim)
+                        .style('fill', this.devGlyphColor.bind(this));
+
+                    // Icon
+                    glyph = is.addDeviceIcon(iconG, glyphId, devIconDim);
+                    glyph.attr(this.iconBox(devIconDim, 0));
+                    glyph.style('fill', dUseTheme[ts.theme()]);
+                },
                 render: function () {
                     var node = this.el,
-                        glyphId = this.icon(this.get('type')),
                         label = this.trimLabel(this.label()),
-                        glyph, labelWidth;
+                        labelWidth;
+
+                    var nodeG = node.append('g')
+                        .attr('class', 'node-content');
 
                     // Label
                     var labelElements = this.addLabelElements(label);
@@ -265,10 +285,7 @@
                     labelElements.rect
                         .attr(this.labelBox(devIconDim, labelWidth));
 
-                    // Icon
-                    glyph = is.addDeviceIcon(node, glyphId, devIconDim);
-                    glyph.attr(this.iconBox(devIconDim, 0));
-                    glyph.style('fill', dUseTheme[ts.theme()]);
+                    this.addIconElements(nodeG);
 
                     node.attr('transform',
                         sus.translate(-halfDevIcon, -halfDevIcon));