aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/web/gui/src/main/webapp/app/fw/widget/table.js
diff options
context:
space:
mode:
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.js272
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);
+ }
+ });
+ };
+ }]);
+
+}());