blob: 327aedb9673f9fbdd91d913c77caee5c2e17a476 [file] [log] [blame]
Bri Prebilic Cole093739a2015-01-23 10:22:50 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/*
18 ONOS GUI -- Widget -- Table Service
19 */
20(function () {
21 'use strict';
22
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070023 // injected refs
Bri Prebilic Cole264c5ec2015-04-07 10:22:26 -070024 var $log, $window, fs, mast, is;
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070025
26 // constants
27 var tableIconTdSize = 33,
Bri Prebilic Cole9a5e0062015-05-11 17:20:57 -070028 pdg = 22,
Bri Prebilic Cole0e7a1bd2015-07-21 10:22:43 -070029 flashTime = 1500,
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070030 colWidth = 'col-width',
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -070031 tableIcon = 'table-icon',
32 asc = 'asc',
33 desc = 'desc',
34 none = 'none';
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070035
36 // internal state
37 var currCol = {},
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -070038 prevCol = {},
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070039 cstmWidths = {},
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -070040 sortIconAPI;
Bri Prebilic Cole093739a2015-01-23 10:22:50 -080041
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070042 // Functions for resizing a tabular view to the window
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -080043
Bri Prebilic Colee568ead2015-05-01 09:51:28 -070044 function _width(elem, width) {
45 elem.style('width', width);
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070046 }
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -080047
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070048 function findCstmWidths(table) {
49 var headers = table.select('.table-header').selectAll('td');
50
51 headers.each(function (d, i) {
52 var h = d3.select(this),
53 index = i.toString();
54 if (h.classed(tableIcon)) {
55 cstmWidths[index] = tableIconTdSize + 'px';
56 }
57 if (h.attr(colWidth)) {
58 cstmWidths[index] = h.attr(colWidth);
59 }
60 });
61 if (fs.debugOn('widget')) {
62 $log.debug('Headers with custom widths: ', cstmWidths);
63 }
Bri Prebilic Cole08d08d42015-04-01 14:37:02 -070064 }
Thomas Vachuska0fa583c2015-03-30 23:07:41 -070065
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070066 function setTdWidths(elem, width) {
67 var tds = elem.select('tr:first-child').selectAll('td');
68 _width(elem, width + 'px');
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -080069
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070070 tds.each(function (d, i) {
71 var td = d3.select(this),
72 index = i.toString();
73 if (cstmWidths.hasOwnProperty(index)) {
74 _width(td, cstmWidths[index]);
Simon Hunt4deb0e82015-06-10 16:18:25 -070075 }
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -070076 });
77 }
78
79 function setHeight(thead, body, height) {
80 var h = height - (mast.mastHeight() +
81 fs.noPxStyle(d3.select('.tabular-header'), 'height') +
82 fs.noPxStyle(thead, 'height') + pdg);
83 body.style('height', h + 'px');
84 }
85
86 function adjustTable(haveItems, tableElems, width, height) {
87 if (haveItems) {
88 setTdWidths(tableElems.thead, width);
89 setTdWidths(tableElems.tbody, width);
90 setHeight(tableElems.thead, tableElems.table.select('.table-body'), height);
91 } else {
92 setTdWidths(tableElems.thead, width);
93 _width(tableElems.tbody, width + 'px');
Bri Prebilic Colee568ead2015-05-01 09:51:28 -070094 }
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -080095 }
96
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -070097 // Functions for sorting table rows by header
Bri Prebilic Colee1bda3f2015-02-13 17:01:49 -080098
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -070099 function updateSortDirection(thElem) {
100 sortIconAPI.sortNone(thElem.select('div'));
101 currCol.div = thElem.append('div');
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800102 currCol.colId = thElem.attr('colId');
103
104 if (currCol.colId === prevCol.colId) {
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700105 (currCol.dir === desc) ? currCol.dir = asc : currCol.dir = desc;
106 prevCol.dir = currCol.dir;
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800107 } else {
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700108 currCol.dir = asc;
109 prevCol.dir = none;
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800110 }
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700111 (currCol.dir === asc) ?
112 sortIconAPI.sortAsc(currCol.div) : sortIconAPI.sortDesc(currCol.div);
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800113
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700114 if (prevCol.colId && prevCol.dir === none) {
115 sortIconAPI.sortNone(prevCol.div);
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800116 }
117
118 prevCol.colId = currCol.colId;
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700119 prevCol.div = currCol.div;
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800120 }
121
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -0700122 function sortRequestParams() {
123 return {
124 sortCol: currCol.colId,
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700125 sortDir: currCol.dir
Bri Prebilic Cole19a32dd2015-03-26 18:00:03 -0700126 };
Bri Prebilic Cole902cb042015-02-11 14:04:15 -0800127 }
128
Bri Prebilic Colec2449762015-05-29 14:30:51 -0700129 function resetSort() {
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700130 if (currCol.div) {
131 sortIconAPI.sortNone(currCol.div);
132 }
133 if (prevCol.div) {
134 sortIconAPI.sortNone(prevCol.div);
135 }
136 currCol = {};
137 prevCol = {};
138 }
139
Bri Prebilic Cole093739a2015-01-23 10:22:50 -0800140 angular.module('onosWidget')
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700141 .directive('onosTableResize', ['$log','$window',
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700142 'FnService', 'MastService',
143
144 function (_$log_, _$window_, _fs_, _mast_) {
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800145 return function (scope, element) {
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700146 $log = _$log_;
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800147 $window = _$window_;
148 fs = _fs_;
Bri Prebilic Cole264c5ec2015-04-07 10:22:26 -0700149 mast = _mast_;
150
Bri Prebilic Cole068814d2015-05-14 16:06:38 -0700151 var table = d3.select(element[0]),
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700152 tableElems = {
153 table: table,
154 thead: table.select('.table-header').select('table'),
155 tbody: table.select('.table-body').select('table')
156 },
157 wsz;
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -0800158
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700159 findCstmWidths(table);
160
161 // adjust table on window resize
Bri Prebilic Cole068814d2015-05-14 16:06:38 -0700162 scope.$watchCollection(function () {
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800163 return {
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700164 h: $window.innerHeight,
165 w: $window.innerWidth
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800166 };
Bri Prebilic Colee568ead2015-05-01 09:51:28 -0700167 }, function () {
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700168 wsz = fs.windowSize(0, 30);
169 adjustTable(
170 scope.tableData.length,
171 tableElems,
172 wsz.width, wsz.height
173 );
174 });
Bri Prebilic Cole9ca0f9c2015-01-29 15:44:20 -0800175
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700176 // adjust table when data changes
177 scope.$watchCollection('tableData', function () {
178 adjustTable(
179 scope.tableData.length,
180 tableElems,
181 wsz.width, wsz.height
182 );
183 });
Simon Hunt0c2c4c52015-04-02 17:42:45 -0700184
Bri Prebilic Coleb3a6afe2015-06-24 14:10:41 -0700185 scope.$on('$destroy', function () {
186 cstmWidths = {};
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800187 });
188 };
Bri Prebilic Cole1f93be22015-02-10 17:16:46 -0800189 }])
190
191 .directive('onosSortableHeader', ['$log', 'IconService',
192 function (_$log_, _is_) {
Bri Prebilic Cole0c41ba22015-07-06 15:09:48 -0700193 return function (scope, element) {
194 $log = _$log_;
195 is = _is_;
196 var header = d3.select(element[0]);
197 sortIconAPI = is.sortIcons();
Bri Prebilic Cole1f93be22015-02-10 17:16:46 -0800198
Bri Prebilic Cole0c41ba22015-07-06 15:09:48 -0700199 header.selectAll('td').on('click', function () {
200 var col = d3.select(this);
Bri Prebilic Cole1f93be22015-02-10 17:16:46 -0800201
Bri Prebilic Cole0c41ba22015-07-06 15:09:48 -0700202 if (col.attr('sortable') === '') {
203 updateSortDirection(col);
204 scope.sortParams = sortRequestParams();
205 scope.sortCallback(scope.sortParams);
206 }
207 });
Bri Prebilic Cole3d4d01c2015-04-30 13:48:36 -0700208
Bri Prebilic Cole0c41ba22015-07-06 15:09:48 -0700209 scope.$on('$destroy', function () {
210 resetSort();
211 });
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700212 };
213 }])
214
Bri Prebilic Cole0e7a1bd2015-07-21 10:22:43 -0700215 .directive('onosFlashChanges',
216 ['$log', '$parse', '$timeout', 'FnService',
217 function ($log, $parse, $timeout, fs) {
218
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700219 return function (scope, element, attrs) {
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700220 var idProp = attrs.idProp,
221 table = d3.select(element[0]),
222 trs, promise;
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700223
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700224 function highlightRows() {
225 var changedRows = [];
Bri Prebilic Cole0e7a1bd2015-07-21 10:22:43 -0700226 function classRows(b) {
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700227 if (changedRows.length) {
228 angular.forEach(changedRows, function (tr) {
229 tr.classed('data-change', b);
230 });
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700231 }
Bri Prebilic Cole0e7a1bd2015-07-21 10:22:43 -0700232 }
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700233 // timeout because 'row-id' was the un-interpolated value
234 // "{{link.one}}" for example, instead of link.one evaluated
235 // timeout executes on the next digest -- after evaluation
236 $timeout(function () {
237 if (scope.tableData.length) {
238 trs = table.selectAll('tr');
239 }
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700240
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700241 if (trs && !trs.empty()) {
242 trs.each(function () {
243 var tr = d3.select(this);
244 if (fs.find(tr.attr('row-id'),
245 scope.changedData,
246 idProp) > -1) {
247 changedRows.push(tr);
248 }
249 });
250 classRows(true);
251 promise = $timeout(function () {
252 classRows(false);
253 }, flashTime);
254 trs = undefined;
255 }
256 });
257 }
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700258
Bri Prebilic Cole70aacc42015-07-22 11:28:34 -0700259 // new items added:
260 scope.$on('ngRepeatComplete', highlightRows);
261 // items changed in existing set:
262 scope.$watchCollection('changedData', highlightRows);
Bri Prebilic Cole0e7a1bd2015-07-21 10:22:43 -0700263
Bri Prebilic Cole0bc4de22015-07-20 17:07:55 -0700264 scope.$on('$destroy', function () {
265 if (promise) {
266 $timeout.cancel(promise);
267 }
268 });
269 };
Bri Prebilic Colee4d5c6c2015-02-02 15:52:45 -0800270 }]);
Bri Prebilic Cole093739a2015-01-23 10:22:50 -0800271
272}());