GUI -- Implemented loadIcon() in the IconService.
Change-Id: Ib19e9ee01d0c015a2ba6f0431bc0d84adf530efd
Showing
3 changed files
with
98 additions
and
6 deletions
... | @@ -72,7 +72,7 @@ | ... | @@ -72,7 +72,7 @@ |
72 | 72 | ||
73 | <div> | 73 | <div> |
74 | <table class="summary-list"> | 74 | <table class="summary-list"> |
75 | - <tr> <th>One</th> <th>Two</th> <th>Three</th> </tr> | 75 | + <tr> <th></th> <th>Two</th> <th>Three</th> </tr> |
76 | <tr> | 76 | <tr> |
77 | <td> | 77 | <td> |
78 | <div icon icon-id="deviceOnline"> | 78 | <div icon icon-id="deviceOnline"> | ... | ... |
... | @@ -22,14 +22,53 @@ | ... | @@ -22,14 +22,53 @@ |
22 | (function () { | 22 | (function () { |
23 | 'use strict'; | 23 | 'use strict'; |
24 | 24 | ||
25 | - var $log; | 25 | + var $log, fs; |
26 | + | ||
27 | + var viewBoxDim = 50, | ||
28 | + viewBox = '0 0 ' + viewBoxDim + ' ' + viewBoxDim; | ||
29 | + | ||
30 | + // maps icon id to the glyph id it uses. | ||
31 | + // note: icon id maps to a CSS class for styling that icon | ||
32 | + var glyphMapping = { | ||
33 | + deviceOnline: 'checkMark', | ||
34 | + deviceOffline: 'xMark' | ||
35 | + }; | ||
26 | 36 | ||
27 | angular.module('onosSvg') | 37 | angular.module('onosSvg') |
28 | - .factory('IconService', ['$log', function (_$log_) { | 38 | + .factory('IconService', ['$log', 'FnService', function (_$log_, _fs_) { |
29 | $log = _$log_; | 39 | $log = _$log_; |
40 | + fs = _fs_; | ||
41 | + | ||
42 | + // div is a D3 selection of the <DIV> element into which icon should load | ||
43 | + // iconCls is the CSS class used to identify the icon | ||
44 | + // size is dimension of icon in pixels. Defaults to 20. | ||
45 | + function loadIcon(div, iconCls, size) { | ||
46 | + var dim = size || 20, | ||
47 | + gid = glyphMapping[iconCls] || 'unknown'; | ||
48 | + | ||
49 | + var svg = div.append('svg').attr({ | ||
50 | + width: dim, | ||
51 | + height: dim, | ||
52 | + viewBox: viewBox | ||
53 | + }); | ||
54 | + var g = svg.append('g').attr({ | ||
55 | + 'class': 'icon ' + iconCls | ||
56 | + }); | ||
57 | + g.append('rect').attr({ | ||
58 | + width: viewBoxDim, | ||
59 | + height: viewBoxDim, | ||
60 | + rx: 4 | ||
61 | + }); | ||
62 | + g.append('use').attr({ | ||
63 | + width: viewBoxDim, | ||
64 | + height: viewBoxDim, | ||
65 | + 'class': 'glyph', | ||
66 | + 'xlink:href': '#' + gid | ||
67 | + }); | ||
68 | + } | ||
30 | 69 | ||
31 | return { | 70 | return { |
32 | - tbd: function () {} | 71 | + loadIcon: loadIcon |
33 | }; | 72 | }; |
34 | }]); | 73 | }]); |
35 | 74 | ... | ... |
... | @@ -20,17 +20,70 @@ | ... | @@ -20,17 +20,70 @@ |
20 | @author Simon Hunt | 20 | @author Simon Hunt |
21 | */ | 21 | */ |
22 | describe('factory: fw/svg/icon.js', function() { | 22 | describe('factory: fw/svg/icon.js', function() { |
23 | - var is; | 23 | + var is, d3Elem; |
24 | + | ||
25 | + var viewBox = '0 0 50 50', | ||
26 | + glyphSize = '50', | ||
27 | + iconSize = '20'; | ||
28 | + | ||
24 | 29 | ||
25 | beforeEach(module('onosSvg')); | 30 | beforeEach(module('onosSvg')); |
26 | 31 | ||
27 | beforeEach(inject(function (IconService) { | 32 | beforeEach(inject(function (IconService) { |
28 | is = IconService; | 33 | is = IconService; |
34 | + d3Elem = d3.select('body').append('div').attr('id', 'myDiv'); | ||
29 | })); | 35 | })); |
30 | 36 | ||
37 | + afterEach(function () { | ||
38 | + d3.select('#myDiv').remove(); | ||
39 | + }); | ||
40 | + | ||
31 | it('should define IconService', function () { | 41 | it('should define IconService', function () { |
32 | expect(is).toBeDefined(); | 42 | expect(is).toBeDefined(); |
33 | }); | 43 | }); |
34 | 44 | ||
35 | - // TODO: unit tests for icon functions | 45 | + function checkElemSize(elem, dim) { |
46 | + expect(elem.attr('width')).toEqual(dim); | ||
47 | + expect(elem.attr('height')).toEqual(dim); | ||
48 | + } | ||
49 | + | ||
50 | + function verifyIconStructure(iconClass, useHref, iSize, vBox, gSize) { | ||
51 | + var isz = iSize || iconSize, | ||
52 | + vbx = vBox || viewBox, | ||
53 | + gsz = gSize || glyphSize; | ||
54 | + | ||
55 | + var svg = d3Elem.selectAll('svg'); | ||
56 | + expect(svg.size()).toBe(1); | ||
57 | + checkElemSize(svg, isz); | ||
58 | + expect(svg.attr('viewBox')).toEqual(vbx); | ||
59 | + | ||
60 | + var g = svg.selectAll('g'); | ||
61 | + expect(g.size()).toBe(1); | ||
62 | + expect(g.classed('icon')).toBeTruthy(); | ||
63 | + expect(g.classed(iconClass)).toBeTruthy(); | ||
64 | + | ||
65 | + var rect = g.select('rect'); | ||
66 | + expect(rect.size()).toBe(1); | ||
67 | + checkElemSize(rect, gsz); | ||
68 | + expect(rect.attr('rx')).toEqual('4'); | ||
69 | + | ||
70 | + var use = g.select('use'); | ||
71 | + expect(use.classed('glyph')).toBeTruthy(); | ||
72 | + expect(use.attr('xlink:href')).toEqual(useHref); | ||
73 | + checkElemSize(use, gsz); | ||
74 | + } | ||
75 | + | ||
76 | + | ||
77 | + it('should load an icon into a div', function () { | ||
78 | + expect(d3Elem.html()).toEqual(''); | ||
79 | + is.loadIcon(d3Elem, 'deviceOnline'); | ||
80 | + verifyIconStructure('deviceOnline', '#checkMark'); | ||
81 | + }); | ||
82 | + | ||
83 | + it('should allow us to specify the icon size', function () { | ||
84 | + expect(d3Elem.html()).toEqual(''); | ||
85 | + is.loadIcon(d3Elem, 'deviceOffline', 32); | ||
86 | + verifyIconStructure('deviceOffline', '#xMark', '32'); | ||
87 | + }); | ||
88 | + | ||
36 | }); | 89 | }); | ... | ... |
-
Please register or login to post a comment