diff --git a/web/gui/src/main/webapp/_sdh/embedded-icon.html b/web/gui/src/main/webapp/_sdh/embedded-icon.html index b4b8f341c4..44fd2601cd 100644 --- a/web/gui/src/main/webapp/_sdh/embedded-icon.html +++ b/web/gui/src/main/webapp/_sdh/embedded-icon.html @@ -72,7 +72,7 @@
- +
One Two Three
Two Three
diff --git a/web/gui/src/main/webapp/app/fw/svg/icon.js b/web/gui/src/main/webapp/app/fw/svg/icon.js index 4e1b2194a6..2013a632cb 100644 --- a/web/gui/src/main/webapp/app/fw/svg/icon.js +++ b/web/gui/src/main/webapp/app/fw/svg/icon.js @@ -22,14 +22,53 @@ (function () { 'use strict'; - var $log; + var $log, fs; + + var viewBoxDim = 50, + viewBox = '0 0 ' + viewBoxDim + ' ' + viewBoxDim; + + // maps icon id to the glyph id it uses. + // note: icon id maps to a CSS class for styling that icon + var glyphMapping = { + deviceOnline: 'checkMark', + deviceOffline: 'xMark' + }; angular.module('onosSvg') - .factory('IconService', ['$log', function (_$log_) { + .factory('IconService', ['$log', 'FnService', function (_$log_, _fs_) { $log = _$log_; + fs = _fs_; + + // div is a D3 selection of the
element into which icon should load + // iconCls is the CSS class used to identify the icon + // size is dimension of icon in pixels. Defaults to 20. + function loadIcon(div, iconCls, size) { + var dim = size || 20, + gid = glyphMapping[iconCls] || 'unknown'; + + var svg = div.append('svg').attr({ + width: dim, + height: dim, + viewBox: viewBox + }); + var g = svg.append('g').attr({ + 'class': 'icon ' + iconCls + }); + g.append('rect').attr({ + width: viewBoxDim, + height: viewBoxDim, + rx: 4 + }); + g.append('use').attr({ + width: viewBoxDim, + height: viewBoxDim, + 'class': 'glyph', + 'xlink:href': '#' + gid + }); + } return { - tbd: function () {} + loadIcon: loadIcon }; }]); diff --git a/web/gui/src/main/webapp/tests/app/fw/svg/icon-spec.js b/web/gui/src/main/webapp/tests/app/fw/svg/icon-spec.js index 8823df6678..3bb35ba9e5 100644 --- a/web/gui/src/main/webapp/tests/app/fw/svg/icon-spec.js +++ b/web/gui/src/main/webapp/tests/app/fw/svg/icon-spec.js @@ -20,17 +20,70 @@ @author Simon Hunt */ describe('factory: fw/svg/icon.js', function() { - var is; + var is, d3Elem; + + var viewBox = '0 0 50 50', + glyphSize = '50', + iconSize = '20'; + beforeEach(module('onosSvg')); beforeEach(inject(function (IconService) { is = IconService; + d3Elem = d3.select('body').append('div').attr('id', 'myDiv'); })); + afterEach(function () { + d3.select('#myDiv').remove(); + }); + it('should define IconService', function () { expect(is).toBeDefined(); }); - // TODO: unit tests for icon functions + function checkElemSize(elem, dim) { + expect(elem.attr('width')).toEqual(dim); + expect(elem.attr('height')).toEqual(dim); + } + + function verifyIconStructure(iconClass, useHref, iSize, vBox, gSize) { + var isz = iSize || iconSize, + vbx = vBox || viewBox, + gsz = gSize || glyphSize; + + var svg = d3Elem.selectAll('svg'); + expect(svg.size()).toBe(1); + checkElemSize(svg, isz); + expect(svg.attr('viewBox')).toEqual(vbx); + + var g = svg.selectAll('g'); + expect(g.size()).toBe(1); + expect(g.classed('icon')).toBeTruthy(); + expect(g.classed(iconClass)).toBeTruthy(); + + var rect = g.select('rect'); + expect(rect.size()).toBe(1); + checkElemSize(rect, gsz); + expect(rect.attr('rx')).toEqual('4'); + + var use = g.select('use'); + expect(use.classed('glyph')).toBeTruthy(); + expect(use.attr('xlink:href')).toEqual(useHref); + checkElemSize(use, gsz); + } + + + it('should load an icon into a div', function () { + expect(d3Elem.html()).toEqual(''); + is.loadIcon(d3Elem, 'deviceOnline'); + verifyIconStructure('deviceOnline', '#checkMark'); + }); + + it('should allow us to specify the icon size', function () { + expect(d3Elem.html()).toEqual(''); + is.loadIcon(d3Elem, 'deviceOffline', 32); + verifyIconStructure('deviceOffline', '#xMark', '32'); + }); + });