diff options
Diffstat (limited to 'framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js')
-rw-r--r-- | framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js new file mode 100644 index 00000000..327aedb9 --- /dev/null +++ b/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js @@ -0,0 +1,272 @@ +/* + * Copyright 2015 Open Networking Laboratory + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + ONOS GUI -- Widget -- Table Service + */ +(function () { + 'use strict'; + + // injected refs + var $log, $window, fs, mast, is; + + // constants + var tableIconTdSize = 33, + pdg = 22, + flashTime = 1500, + colWidth = 'col-width', + tableIcon = 'table-icon', + asc = 'asc', + desc = 'desc', + none = 'none'; + + // internal state + var currCol = {}, + prevCol = {}, + cstmWidths = {}, + sortIconAPI; + + // Functions for resizing a tabular view to the window + + function _width(elem, width) { + elem.style('width', width); + } + + function findCstmWidths(table) { + var headers = table.select('.table-header').selectAll('td'); + + headers.each(function (d, i) { + var h = d3.select(this), + index = i.toString(); + if (h.classed(tableIcon)) { + cstmWidths[index] = tableIconTdSize + 'px'; + } + if (h.attr(colWidth)) { + cstmWidths[index] = h.attr(colWidth); + } + }); + if (fs.debugOn('widget')) { + $log.debug('Headers with custom widths: ', cstmWidths); + } + } + + function setTdWidths(elem, width) { + var tds = elem.select('tr:first-child').selectAll('td'); + _width(elem, width + 'px'); + + tds.each(function (d, i) { + var td = d3.select(this), + index = i.toString(); + if (cstmWidths.hasOwnProperty(index)) { + _width(td, cstmWidths[index]); + } + }); + } + + function setHeight(thead, body, height) { + var h = height - (mast.mastHeight() + + fs.noPxStyle(d3.select('.tabular-header'), 'height') + + fs.noPxStyle(thead, 'height') + pdg); + body.style('height', h + 'px'); + } + + function adjustTable(haveItems, tableElems, width, height) { + if (haveItems) { + setTdWidths(tableElems.thead, width); + setTdWidths(tableElems.tbody, width); + setHeight(tableElems.thead, tableElems.table.select('.table-body'), height); + } else { + setTdWidths(tableElems.thead, width); + _width(tableElems.tbody, width + 'px'); + } + } + + // Functions for sorting table rows by header + + function updateSortDirection(thElem) { + sortIconAPI.sortNone(thElem.select('div')); + currCol.div = thElem.append('div'); + currCol.colId = thElem.attr('colId'); + + if (currCol.colId === prevCol.colId) { + (currCol.dir === desc) ? currCol.dir = asc : currCol.dir = desc; + prevCol.dir = currCol.dir; + } else { + currCol.dir = asc; + prevCol.dir = none; + } + (currCol.dir === asc) ? + sortIconAPI.sortAsc(currCol.div) : sortIconAPI.sortDesc(currCol.div); + + if (prevCol.colId && prevCol.dir === none) { + sortIconAPI.sortNone(prevCol.div); + } + + prevCol.colId = currCol.colId; + prevCol.div = currCol.div; + } + + function sortRequestParams() { + return { + sortCol: currCol.colId, + sortDir: currCol.dir + }; + } + + function resetSort() { + if (currCol.div) { + sortIconAPI.sortNone(currCol.div); + } + if (prevCol.div) { + sortIconAPI.sortNone(prevCol.div); + } + currCol = {}; + prevCol = {}; + } + + angular.module('onosWidget') + .directive('onosTableResize', ['$log','$window', + 'FnService', 'MastService', + + function (_$log_, _$window_, _fs_, _mast_) { + return function (scope, element) { + $log = _$log_; + $window = _$window_; + fs = _fs_; + mast = _mast_; + + var table = d3.select(element[0]), + tableElems = { + table: table, + thead: table.select('.table-header').select('table'), + tbody: table.select('.table-body').select('table') + }, + wsz; + + findCstmWidths(table); + + // adjust table on window resize + scope.$watchCollection(function () { + return { + h: $window.innerHeight, + w: $window.innerWidth + }; + }, function () { + wsz = fs.windowSize(0, 30); + adjustTable( + scope.tableData.length, + tableElems, + wsz.width, wsz.height + ); + }); + + // adjust table when data changes + scope.$watchCollection('tableData', function () { + adjustTable( + scope.tableData.length, + tableElems, + wsz.width, wsz.height + ); + }); + + scope.$on('$destroy', function () { + cstmWidths = {}; + }); + }; + }]) + + .directive('onosSortableHeader', ['$log', 'IconService', + function (_$log_, _is_) { + return function (scope, element) { + $log = _$log_; + is = _is_; + var header = d3.select(element[0]); + sortIconAPI = is.sortIcons(); + + header.selectAll('td').on('click', function () { + var col = d3.select(this); + + if (col.attr('sortable') === '') { + updateSortDirection(col); + scope.sortParams = sortRequestParams(); + scope.sortCallback(scope.sortParams); + } + }); + + scope.$on('$destroy', function () { + resetSort(); + }); + }; + }]) + + .directive('onosFlashChanges', + ['$log', '$parse', '$timeout', 'FnService', + function ($log, $parse, $timeout, fs) { + + return function (scope, element, attrs) { + var idProp = attrs.idProp, + table = d3.select(element[0]), + trs, promise; + + function highlightRows() { + var changedRows = []; + function classRows(b) { + if (changedRows.length) { + angular.forEach(changedRows, function (tr) { + tr.classed('data-change', b); + }); + } + } + // timeout because 'row-id' was the un-interpolated value + // "{{link.one}}" for example, instead of link.one evaluated + // timeout executes on the next digest -- after evaluation + $timeout(function () { + if (scope.tableData.length) { + trs = table.selectAll('tr'); + } + + if (trs && !trs.empty()) { + trs.each(function () { + var tr = d3.select(this); + if (fs.find(tr.attr('row-id'), + scope.changedData, + idProp) > -1) { + changedRows.push(tr); + } + }); + classRows(true); + promise = $timeout(function () { + classRows(false); + }, flashTime); + trs = undefined; + } + }); + } + + // new items added: + scope.$on('ngRepeatComplete', highlightRows); + // items changed in existing set: + scope.$watchCollection('changedData', highlightRows); + + scope.$on('$destroy', function () { + if (promise) { + $timeout.cancel(promise); + } + }); + }; + }]); + +}()); |