GUI -- Working towards embedding icons in tables. WIP.
- Skeleton of icon directive added. - icons embedded in table - test HTML file. - Augmented GlyphService.loadDefs() to allow subset of glyph ids to be specified. Change-Id: I775a958ef9dc35b0b89a126d5c0497f72a721b71
Showing
5 changed files
with
227 additions
and
43 deletions
1 | +<!DOCTYPE html> | ||
2 | +<!-- | ||
3 | + ~ Copyright 2015 Open Networking Laboratory | ||
4 | + ~ | ||
5 | + ~ Licensed under the Apache License, Version 2.0 (the "License"); | ||
6 | + ~ you may not use this file except in compliance with the License. | ||
7 | + ~ You may obtain a copy of the License at | ||
8 | + ~ | ||
9 | + ~ http://www.apache.org/licenses/LICENSE-2.0 | ||
10 | + ~ | ||
11 | + ~ Unless required by applicable law or agreed to in writing, software | ||
12 | + ~ distributed under the License is distributed on an "AS IS" BASIS, | ||
13 | + ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
14 | + ~ See the License for the specific language governing permissions and | ||
15 | + ~ limitations under the License. | ||
16 | + --> | ||
17 | + | ||
18 | +<!-- | ||
19 | + ONOS -- Embedded icon test page | ||
20 | + | ||
21 | + @author Simon Hunt | ||
22 | + @author Bri Prebilic Cole | ||
23 | + --> | ||
24 | +<html> | ||
25 | +<head> | ||
26 | + <meta charset="utf-8"> | ||
27 | + <title>Embedded Icons</title> | ||
28 | + | ||
29 | + <script src="../tp/d3.js"></script> | ||
30 | + | ||
31 | + <link rel="stylesheet" href="../app/common.css"> | ||
32 | + | ||
33 | + <style> | ||
34 | + html, | ||
35 | + body { | ||
36 | + background-color: #fff; | ||
37 | + font-family: Arial, Helvetica, sans-serif; | ||
38 | + font-size: 9pt; | ||
39 | + } | ||
40 | + | ||
41 | + svg .icon .glyph { | ||
42 | + stroke: none; | ||
43 | + fill: white; | ||
44 | + fill-rule: evenodd; | ||
45 | + } | ||
46 | + | ||
47 | + svg .icon.deviceOnline { | ||
48 | + fill: green; | ||
49 | + } | ||
50 | + | ||
51 | + svg .icon.deviceOffline { | ||
52 | + fill: darkred; | ||
53 | + } | ||
54 | + | ||
55 | + svg .icon rect { | ||
56 | + stroke: black; | ||
57 | + stroke-width: 1px; | ||
58 | + } | ||
59 | + | ||
60 | + </style> | ||
61 | +</head> | ||
62 | +<body class="light"> | ||
63 | +<!-- minimal framework to access glyphs library module --> | ||
64 | +<script> | ||
65 | + var libs = {}; | ||
66 | + var ONOS = { ui: { addLib: function (id, things) { libs[id] = things; }}}; | ||
67 | + | ||
68 | + | ||
69 | +</script> | ||
70 | + | ||
71 | +<!-- Test HTML --> | ||
72 | + | ||
73 | +<div> | ||
74 | + <table class="summary-list"> | ||
75 | + <tr> <th>One</th> <th>Two</th> <th>Three</th> </tr> | ||
76 | + <tr> | ||
77 | + <td> | ||
78 | + <div icon icon-id="deviceOnline"> | ||
79 | + | ||
80 | + <!-- icon directive needs to inject the following structure --> | ||
81 | + <!-- ------------------------------------------------ --> | ||
82 | + <svg width="20" height="20" viewBox="0 0 50 50"> | ||
83 | + <g class="icon deviceOnline"> | ||
84 | + <rect width="50" height="50" rx="4"></rect> | ||
85 | + <use class="glyph" xlink:href="#ui" width="50" height="50"></use> | ||
86 | + </g> | ||
87 | + </svg> | ||
88 | + <!-- ------------------------------------------------ --> | ||
89 | + | ||
90 | + </div> | ||
91 | + </td> | ||
92 | + <td>Some text</td> | ||
93 | + <td>Some text</td> | ||
94 | + </tr> | ||
95 | + <tr> | ||
96 | + <td> | ||
97 | + <div icon icon-id="deviceOffline"> | ||
98 | + | ||
99 | + <!-- icon directive needs to inject the following structure --> | ||
100 | + <!-- ------------------------------------------------ --> | ||
101 | + <svg width="20" height="20" viewBox="0 0 50 50"> | ||
102 | + <g class="icon deviceOffline"> | ||
103 | + <rect width="50" height="50" rx="4"></rect> | ||
104 | + <use class="glyph" xlink:href="#ui" width="50" height="50"></use> | ||
105 | + </g> | ||
106 | + </svg> | ||
107 | + <!-- ------------------------------------------------ --> | ||
108 | + | ||
109 | + | ||
110 | + </div> | ||
111 | + </td> | ||
112 | + <td>Some text</td> | ||
113 | + <td>Some Other text</td> | ||
114 | + </tr> | ||
115 | + </table> | ||
116 | +</div> | ||
117 | + | ||
118 | +<!-- common definitions for other SVG elements to use --> | ||
119 | +<svg width="0" height="0"> | ||
120 | + <defs> | ||
121 | + <symbol id="ui" viewBox="0 0 10 10"> | ||
122 | + <path d="M2,2.5a.5,.5,0,0,1,.5-.5h5 | ||
123 | + a.5,.5,0,0,1,.5,.5v3a.5,.5,0,0,1-.5,.5h-5a.5, | ||
124 | + .5,0,0,1-.5-.5zM2.5,2.8a.3,.3,0,0,1,.3-.3 | ||
125 | + h4.4a.3,.3,0,0,1,.3,.3v2.4a.3,.3,0,0,1-.3, | ||
126 | + .3h-4.4a.3,.3,0,0,1-.3-.3zM2,6.55h6l1,1.45h-8z"> | ||
127 | + </path> | ||
128 | + </symbol> | ||
129 | + </defs> | ||
130 | +</svg> | ||
131 | + | ||
132 | +</body> | ||
133 | +</html> |
... | @@ -56,4 +56,23 @@ | ... | @@ -56,4 +56,23 @@ |
56 | }; | 56 | }; |
57 | }]) | 57 | }]) |
58 | 58 | ||
59 | + | ||
60 | + // create icon directive, so that we can inject icons into | ||
61 | + // HTML tables etc. | ||
62 | + .directive('icon', ['GlyphService', function (gs) { | ||
63 | + return { | ||
64 | + templateUrl: 'toBeDecided-iconContext.html', | ||
65 | + restrict: 'A', | ||
66 | + link: function (scope, element, attrs) { | ||
67 | + // TODO: implement this | ||
68 | + // needs to pull out the parameters for the icon | ||
69 | + // from the attributes of the element, and use those | ||
70 | + // as arguments to the IconService.addIcon(...) call. | ||
71 | + | ||
72 | + | ||
73 | + } | ||
74 | + }; | ||
75 | + | ||
76 | + | ||
77 | + }]); | ||
59 | }()); | 78 | }()); | ... | ... |
... | @@ -23,6 +23,7 @@ | ... | @@ -23,6 +23,7 @@ |
23 | 'use strict'; | 23 | 'use strict'; |
24 | 24 | ||
25 | var $log, | 25 | var $log, |
26 | + fs, | ||
26 | glyphs = d3.map(), | 27 | glyphs = d3.map(), |
27 | msgGS = 'GlyphService.'; | 28 | msgGS = 'GlyphService.'; |
28 | 29 | ||
... | @@ -121,8 +122,9 @@ | ... | @@ -121,8 +122,9 @@ |
121 | // ---------------------------------------------------------------------- | 122 | // ---------------------------------------------------------------------- |
122 | 123 | ||
123 | angular.module('onosSvg') | 124 | angular.module('onosSvg') |
124 | - .factory('GlyphService', ['$log', function (_$log_) { | 125 | + .factory('GlyphService', ['$log', 'FnService', function (_$log_, _fs_) { |
125 | $log = _$log_; | 126 | $log = _$log_; |
127 | + fs = _fs_; | ||
126 | 128 | ||
127 | function clear() { | 129 | function clear() { |
128 | // start with a fresh map | 130 | // start with a fresh map |
... | @@ -166,15 +168,20 @@ | ... | @@ -166,15 +168,20 @@ |
166 | } | 168 | } |
167 | 169 | ||
168 | // Note: defs should be a D3 selection of a single <defs> element | 170 | // Note: defs should be a D3 selection of a single <defs> element |
169 | - function loadDefs(defs) { | 171 | + function loadDefs(defs, glyphIds) { |
172 | + var list = fs.isA(glyphIds) || ids(); | ||
173 | + | ||
170 | // remove all existing content | 174 | // remove all existing content |
171 | defs.html(null); | 175 | defs.html(null); |
172 | 176 | ||
173 | - // load up the currently registered glyphs | 177 | + // load up the requested glyphs |
174 | - glyphs.values().forEach(function (g) { | 178 | + list.forEach(function (id) { |
175 | - defs.append('symbol') | 179 | + var g = glyph(id); |
176 | - .attr({ id: g.id, viewBox: g.vb }) | 180 | + if (g) { |
177 | - .append('path').attr('d', g.d); | 181 | + defs.append('symbol') |
182 | + .attr({ id: g.id, viewBox: g.vb }) | ||
183 | + .append('path').attr('d', g.d); | ||
184 | + } | ||
178 | }); | 185 | }); |
179 | } | 186 | } |
180 | 187 | ... | ... |
... | @@ -25,7 +25,24 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -25,7 +25,24 @@ describe('factory: fw/svg/glyph.js', function() { |
25 | var numBaseGlyphs = 11, | 25 | var numBaseGlyphs = 11, |
26 | vbBird = '352 224 113 112', | 26 | vbBird = '352 224 113 112', |
27 | vbGlyph = '0 0 110 110', | 27 | vbGlyph = '0 0 110 110', |
28 | - vbBadge = '0 0 10 10'; | 28 | + vbBadge = '0 0 10 10', |
29 | + prefixLookup = { | ||
30 | + bird: 'M427.7,300.4', | ||
31 | + unknown: 'M35,40a5', | ||
32 | + node: 'M15,100a5', | ||
33 | + switch: 'M10,20a10', | ||
34 | + roadm: 'M10,35l25-', | ||
35 | + endstation: 'M10,15a5,5', | ||
36 | + router: 'M10,55A45,45', | ||
37 | + bgpSpeaker: 'M10,40a45,35', | ||
38 | + chain: 'M60.4,77.6c-', | ||
39 | + crown: 'M99.5,21.6c0,', | ||
40 | + uiAttached: 'M2,2.5a.5,.5', | ||
41 | + | ||
42 | + // our test ones.. | ||
43 | + triangle: 'M.5,.2', | ||
44 | + diamond: 'M.2,.5' | ||
45 | + }; | ||
29 | 46 | ||
30 | beforeEach(module('onosUtil', 'onosSvg')); | 47 | beforeEach(module('onosUtil', 'onosSvg')); |
31 | 48 | ||
... | @@ -47,7 +64,7 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -47,7 +64,7 @@ describe('factory: fw/svg/glyph.js', function() { |
47 | 64 | ||
48 | it('should define api functions', function () { | 65 | it('should define api functions', function () { |
49 | expect(fs.areFunctions(gs, [ | 66 | expect(fs.areFunctions(gs, [ |
50 | - 'init', 'register', 'ids', 'glyph', 'loadDefs' | 67 | + 'clear', 'init', 'register', 'ids', 'glyph', 'loadDefs' |
51 | ])).toBeTruthy(); | 68 | ])).toBeTruthy(); |
52 | }); | 69 | }); |
53 | 70 | ||
... | @@ -55,20 +72,22 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -55,20 +72,22 @@ describe('factory: fw/svg/glyph.js', function() { |
55 | expect(gs.ids()).toEqual([]); | 72 | expect(gs.ids()).toEqual([]); |
56 | }); | 73 | }); |
57 | 74 | ||
58 | - it('should load the base set of glyphs', function () { | 75 | + it('should load the base set of glyphs into the cache', function () { |
59 | gs.init(); | 76 | gs.init(); |
60 | expect(gs.ids().length).toEqual(numBaseGlyphs); | 77 | expect(gs.ids().length).toEqual(numBaseGlyphs); |
61 | }); | 78 | }); |
62 | 79 | ||
63 | - it('should remove glyphs on clear', function () { | 80 | + it('should remove glyphs from the cache on clear', function () { |
64 | gs.init(); | 81 | gs.init(); |
65 | expect(gs.ids().length).toEqual(numBaseGlyphs); | 82 | expect(gs.ids().length).toEqual(numBaseGlyphs); |
66 | gs.clear(); | 83 | gs.clear(); |
67 | expect(gs.ids().length).toEqual(0); | 84 | expect(gs.ids().length).toEqual(0); |
68 | }); | 85 | }); |
69 | 86 | ||
70 | - function verifyGlyphLoaded(id, vbox, prefix) { | 87 | + function verifyGlyphLoadedInCache(id, vbox, expPfxId) { |
71 | - var glyph = gs.glyph(id), | 88 | + var pfxId = expPfxId || id, |
89 | + glyph = gs.glyph(id), | ||
90 | + prefix = prefixLookup[pfxId], | ||
72 | plen = prefix.length; | 91 | plen = prefix.length; |
73 | expect(fs.contains(gs.ids(), id)).toBeTruthy(); | 92 | expect(fs.contains(gs.ids(), id)).toBeTruthy(); |
74 | expect(glyph).toBeDefined(); | 93 | expect(glyph).toBeDefined(); |
... | @@ -79,47 +98,47 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -79,47 +98,47 @@ describe('factory: fw/svg/glyph.js', function() { |
79 | 98 | ||
80 | it('should load the bird glyph', function() { | 99 | it('should load the bird glyph', function() { |
81 | gs.init(); | 100 | gs.init(); |
82 | - verifyGlyphLoaded('bird', vbBird, 'M427.7,300.4'); | 101 | + verifyGlyphLoadedInCache('bird', vbBird); |
83 | }); | 102 | }); |
84 | it('should load the unknown glyph', function() { | 103 | it('should load the unknown glyph', function() { |
85 | gs.init(); | 104 | gs.init(); |
86 | - verifyGlyphLoaded('unknown', vbGlyph, 'M35,40a5'); | 105 | + verifyGlyphLoadedInCache('unknown', vbGlyph); |
87 | }); | 106 | }); |
88 | it('should load the node glyph', function() { | 107 | it('should load the node glyph', function() { |
89 | gs.init(); | 108 | gs.init(); |
90 | - verifyGlyphLoaded('node', vbGlyph, 'M15,100a5'); | 109 | + verifyGlyphLoadedInCache('node', vbGlyph); |
91 | }); | 110 | }); |
92 | it('should load the switch glyph', function() { | 111 | it('should load the switch glyph', function() { |
93 | gs.init(); | 112 | gs.init(); |
94 | - verifyGlyphLoaded('switch', vbGlyph, 'M10,20a10'); | 113 | + verifyGlyphLoadedInCache('switch', vbGlyph); |
95 | }); | 114 | }); |
96 | it('should load the roadm glyph', function() { | 115 | it('should load the roadm glyph', function() { |
97 | gs.init(); | 116 | gs.init(); |
98 | - verifyGlyphLoaded('roadm', vbGlyph, 'M10,35l25-'); | 117 | + verifyGlyphLoadedInCache('roadm', vbGlyph); |
99 | }); | 118 | }); |
100 | it('should load the endstation glyph', function() { | 119 | it('should load the endstation glyph', function() { |
101 | gs.init(); | 120 | gs.init(); |
102 | - verifyGlyphLoaded('endstation', vbGlyph, 'M10,15a5,5'); | 121 | + verifyGlyphLoadedInCache('endstation', vbGlyph); |
103 | }); | 122 | }); |
104 | it('should load the router glyph', function() { | 123 | it('should load the router glyph', function() { |
105 | gs.init(); | 124 | gs.init(); |
106 | - verifyGlyphLoaded('router', vbGlyph, 'M10,55A45,45'); | 125 | + verifyGlyphLoadedInCache('router', vbGlyph); |
107 | }); | 126 | }); |
108 | it('should load the bgpSpeaker glyph', function() { | 127 | it('should load the bgpSpeaker glyph', function() { |
109 | gs.init(); | 128 | gs.init(); |
110 | - verifyGlyphLoaded('bgpSpeaker', vbGlyph, 'M10,40a45,35'); | 129 | + verifyGlyphLoadedInCache('bgpSpeaker', vbGlyph); |
111 | }); | 130 | }); |
112 | it('should load the chain glyph', function() { | 131 | it('should load the chain glyph', function() { |
113 | gs.init(); | 132 | gs.init(); |
114 | - verifyGlyphLoaded('chain', vbGlyph, 'M60.4,77.6c-'); | 133 | + verifyGlyphLoadedInCache('chain', vbGlyph); |
115 | }); | 134 | }); |
116 | it('should load the crown glyph', function() { | 135 | it('should load the crown glyph', function() { |
117 | gs.init(); | 136 | gs.init(); |
118 | - verifyGlyphLoaded('crown', vbGlyph, 'M99.5,21.6c0'); | 137 | + verifyGlyphLoadedInCache('crown', vbGlyph); |
119 | }); | 138 | }); |
120 | it('should load the uiAttached glyph', function() { | 139 | it('should load the uiAttached glyph', function() { |
121 | gs.init(); | 140 | gs.init(); |
122 | - verifyGlyphLoaded('uiAttached', vbBadge, 'M2,2.5a.5,.5'); | 141 | + verifyGlyphLoadedInCache('uiAttached', vbBadge); |
123 | }); | 142 | }); |
124 | 143 | ||
125 | // define some glyphs that we want to install | 144 | // define some glyphs that we want to install |
... | @@ -147,8 +166,8 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -147,8 +166,8 @@ describe('factory: fw/svg/glyph.js', function() { |
147 | expect($log.warn).not.toHaveBeenCalled(); | 166 | expect($log.warn).not.toHaveBeenCalled(); |
148 | 167 | ||
149 | expect(gs.ids().length).toEqual(numBaseGlyphs + 2); | 168 | expect(gs.ids().length).toEqual(numBaseGlyphs + 2); |
150 | - verifyGlyphLoaded('triangle', testVbox, 'M.5,.2'); | 169 | + verifyGlyphLoadedInCache('triangle', testVbox); |
151 | - verifyGlyphLoaded('diamond', testVbox, 'M.2,.5'); | 170 | + verifyGlyphLoadedInCache('diamond', testVbox); |
152 | }); | 171 | }); |
153 | 172 | ||
154 | it('should not overwrite glyphs with dup IDs', function () { | 173 | it('should not overwrite glyphs with dup IDs', function () { |
... | @@ -163,8 +182,8 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -163,8 +182,8 @@ describe('factory: fw/svg/glyph.js', function() { |
163 | 182 | ||
164 | expect(gs.ids().length).toEqual(numBaseGlyphs); | 183 | expect(gs.ids().length).toEqual(numBaseGlyphs); |
165 | // verify original glyphs still exist... | 184 | // verify original glyphs still exist... |
166 | - verifyGlyphLoaded('router', vbGlyph, 'M10,55A45,45'); | 185 | + verifyGlyphLoadedInCache('router', vbGlyph); |
167 | - verifyGlyphLoaded('switch', vbGlyph, 'M10,20a10'); | 186 | + verifyGlyphLoadedInCache('switch', vbGlyph); |
168 | }); | 187 | }); |
169 | 188 | ||
170 | it('should replace glyphs if asked nicely', function () { | 189 | it('should replace glyphs if asked nicely', function () { |
... | @@ -178,8 +197,8 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -178,8 +197,8 @@ describe('factory: fw/svg/glyph.js', function() { |
178 | 197 | ||
179 | expect(gs.ids().length).toEqual(numBaseGlyphs); | 198 | expect(gs.ids().length).toEqual(numBaseGlyphs); |
180 | // verify glyphs have been overwritten... | 199 | // verify glyphs have been overwritten... |
181 | - verifyGlyphLoaded('router', testVbox, 'M.5,.2'); | 200 | + verifyGlyphLoadedInCache('router', testVbox, 'triangle'); |
182 | - verifyGlyphLoaded('switch', testVbox, 'M.2,.5'); | 201 | + verifyGlyphLoadedInCache('switch', testVbox, 'diamond'); |
183 | }); | 202 | }); |
184 | 203 | ||
185 | function verifyPathPrefix(elem, prefix) { | 204 | function verifyPathPrefix(elem, prefix) { |
... | @@ -188,16 +207,19 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -188,16 +207,19 @@ describe('factory: fw/svg/glyph.js', function() { |
188 | expect(d.slice(0, plen)).toEqual(prefix); | 207 | expect(d.slice(0, plen)).toEqual(prefix); |
189 | } | 208 | } |
190 | 209 | ||
210 | + function verifyLoadedInDom(id, vb, expPfxId) { | ||
211 | + var pfxId = expPfxId || id, | ||
212 | + symbol = d3Elem.select('#' + id); | ||
213 | + expect(symbol.size()).toEqual(1); | ||
214 | + expect(symbol.attr('viewBox')).toEqual(vb); | ||
215 | + verifyPathPrefix(symbol, prefixLookup[pfxId]); | ||
216 | + } | ||
217 | + | ||
191 | it('should load base glyphs into the DOM', function () { | 218 | it('should load base glyphs into the DOM', function () { |
192 | gs.init(); | 219 | gs.init(); |
193 | gs.loadDefs(d3Elem); | 220 | gs.loadDefs(d3Elem); |
194 | expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs); | 221 | expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs); |
195 | - | 222 | + verifyLoadedInDom('bgpSpeaker', vbGlyph); |
196 | - // verify bgpSpeaker | ||
197 | - var bs = d3Elem.select('#bgpSpeaker'); | ||
198 | - expect(bs.size()).toEqual(1); | ||
199 | - expect(bs.attr('viewBox')).toEqual(vbGlyph); | ||
200 | - verifyPathPrefix(bs, 'M10,40a45,35'); | ||
201 | }); | 223 | }); |
202 | 224 | ||
203 | it('should load custom glyphs into the DOM', function () { | 225 | it('should load custom glyphs into the DOM', function () { |
... | @@ -205,11 +227,15 @@ describe('factory: fw/svg/glyph.js', function() { | ... | @@ -205,11 +227,15 @@ describe('factory: fw/svg/glyph.js', function() { |
205 | gs.register(testVbox, newGlyphs); | 227 | gs.register(testVbox, newGlyphs); |
206 | gs.loadDefs(d3Elem); | 228 | gs.loadDefs(d3Elem); |
207 | expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs + 2); | 229 | expect(d3Elem.selectAll('symbol').size()).toEqual(numBaseGlyphs + 2); |
230 | + verifyLoadedInDom('diamond', testVbox); | ||
231 | + }); | ||
208 | 232 | ||
209 | - // verify diamond | 233 | + it('should load only specified glyphs into the DOM', function () { |
210 | - var dia = d3Elem.select('#diamond'); | 234 | + gs.init(); |
211 | - expect(dia.size()).toEqual(1); | 235 | + gs.loadDefs(d3Elem, ['crown', 'chain', 'node']); |
212 | - expect(dia.attr('viewBox')).toEqual(testVbox); | 236 | + expect(d3Elem.selectAll('symbol').size()).toEqual(3); |
213 | - verifyPathPrefix(dia, 'M.2,.5l.3,-.3'); | 237 | + verifyLoadedInDom('crown', vbGlyph); |
238 | + verifyLoadedInDom('chain', vbGlyph); | ||
239 | + verifyLoadedInDom('node', vbGlyph); | ||
214 | }); | 240 | }); |
215 | }); | 241 | }); | ... | ... |
-
Please register or login to post a comment