GUI: Javascript cleanup and additional utility functions.
Change-Id: Ia16dd7eecedfd116e9d0a65d60d724657e87b8d3
diff --git a/web/gui/src/main/webapp/app/fw/layer/flash.js b/web/gui/src/main/webapp/app/fw/layer/flash.js
index 0d95b77..3139f2c 100644
--- a/web/gui/src/main/webapp/app/fw/layer/flash.js
+++ b/web/gui/src/main/webapp/app/fw/layer/flash.js
@@ -143,6 +143,13 @@
enabled = !!b;
}
+ function tempDiv(ms) {
+ var div = d3.select('body').append('div').classed('centered', true),
+ delay = (ms === undefined || ms < 100) ? 3000 : ms;
+ $timeout(function () { div.remove(); }, delay);
+ return div;
+ }
+
angular.module('onosLayer')
.factory('FlashService', ['$log', '$timeout',
function (_$log_, _$timeout_) {
@@ -158,7 +165,8 @@
return {
initFlash: initFlash,
flash: flash,
- enable: enable
+ enable: enable,
+ tempDiv: tempDiv
};
}]);
diff --git a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
index cb67ae8..5132587 100644
--- a/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
+++ b/web/gui/src/main/webapp/app/fw/svg/svgUtil.js
@@ -28,267 +28,275 @@
// injected references
var $log, fs;
+ // TODO: change 'force' ref to be 'force.alpha' ref.
+ function createDragBehavior(force, selectCb, atDragEnd,
+ dragEnabled, clickEnabled) {
+ var draggedThreshold = d3.scale.linear()
+ .domain([0, 0.1])
+ .range([5, 20])
+ .clamp(true),
+ drag,
+ fSel = fs.isF(selectCb),
+ fEnd = fs.isF(atDragEnd),
+ fDEn = fs.isF(dragEnabled),
+ fCEn = fs.isF(clickEnabled),
+ bad = [];
+
+ function naf(what) {
+ return 'SvgUtilService: createDragBehavior(): ' + what +
+ ' is not a function';
+ }
+
+ if (!force) {
+ bad.push('SvgUtilService: createDragBehavior(): ' +
+ 'Bad force reference');
+ }
+ if (!fSel) {
+ bad.push(naf('selectCb'));
+ }
+ if (!fEnd) {
+ bad.push(naf('atDragEnd'));
+ }
+ if (!fDEn) {
+ bad.push(naf('dragEnabled'));
+ }
+ if (!fCEn) {
+ bad.push(naf('clickEnabled'));
+ }
+
+ if (bad.length) {
+ $log.error(bad.join('\n'));
+ return null;
+ }
+
+ function dragged(d) {
+ var threshold = draggedThreshold(force.alpha()),
+ dx = d.oldX - d.px,
+ dy = d.oldY - d.py;
+ if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
+ d.dragged = true;
+ }
+ return d.dragged;
+ }
+
+ drag = d3.behavior.drag()
+ .origin(function(d) { return d; })
+ .on('dragstart', function(d) {
+ if (clickEnabled() || dragEnabled()) {
+ d3.event.sourceEvent.stopPropagation();
+
+ d.oldX = d.x;
+ d.oldY = d.y;
+ d.dragged = false;
+ d.fixed |= 2;
+ d.dragStarted = true;
+ }
+ })
+ .on('drag', function(d) {
+ if (dragEnabled()) {
+ d.px = d3.event.x;
+ d.py = d3.event.y;
+ if (dragged(d)) {
+ if (!force.alpha()) {
+ force.alpha(.025);
+ }
+ }
+ }
+ })
+ .on('dragend', function(d) {
+ if (d.dragStarted) {
+ d.dragStarted = false;
+ if (!dragged(d)) {
+ // consider this the same as a 'click'
+ // (selection of a node)
+ if (clickEnabled()) {
+ selectCb.call(this, d);
+ }
+ }
+ d.fixed &= ~6;
+
+ // hook at the end of a drag gesture
+ if (dragEnabled()) {
+ atDragEnd.call(this, d);
+ }
+ }
+ });
+
+ return drag;
+ }
+
+
+ function loadGlow(defs, r, g, b, id) {
+ var glow = defs.append('filter')
+ .attr('x', '-50%')
+ .attr('y', '-50%')
+ .attr('width', '200%')
+ .attr('height', '200%')
+ .attr('id', id);
+
+ glow.append('feColorMatrix')
+ .attr('type', 'matrix')
+ .attr('values',
+ '0 0 0 0 ' + r + ' ' +
+ '0 0 0 0 ' + g + ' ' +
+ '0 0 0 0 ' + b + ' ' +
+ '0 0 0 1 0 ');
+
+ glow.append('feGaussianBlur')
+ .attr('stdDeviation', 3)
+ .attr('result', 'coloredBlur');
+
+ glow.append('feMerge').selectAll('feMergeNode')
+ .data(['coloredBlur', 'SourceGraphic'])
+ .enter().append('feMergeNode')
+ .attr('in', String);
+ }
+
+ function loadGlowDefs(defs) {
+ loadGlow(defs, 0.0, 0.0, 0.7, 'blue-glow');
+ loadGlow(defs, 1.0, 1.0, 0.3, 'yellow-glow');
+ }
+
+ // --- Ordinal scales for 7 values.
+
+ // blue brown brick red sea green purple dark teal lime
+ var lightNorm = ['#3E5780', '#78533B', '#CB4D28', '#018D61', '#8A2979', '#006D73', '#56AF00'],
+ lightMute = ['#A8B8CC', '#CCB3A8', '#FFC2BD', '#96D6BF', '#D19FCE', '#8FCCCA', '#CAEAA4'],
+
+ darkNorm = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'],
+ darkMute = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'];
+
+ var colors= {
+ light: {
+ norm: d3.scale.ordinal().range(lightNorm),
+ mute: d3.scale.ordinal().range(lightMute)
+ },
+ dark: {
+ norm: d3.scale.ordinal().range(darkNorm),
+ mute: d3.scale.ordinal().range(darkMute)
+ }
+ };
+
+ function cat7() {
+ var tcid = 'd3utilTestCard';
+
+ function getColor(id, muted, theme) {
+ // NOTE: since we are lazily assigning domain ids, we need to
+ // get the color from all 4 scales, to keep the domains
+ // in sync.
+ var ln = colors.light.norm(id),
+ lm = colors.light.mute(id),
+ dn = colors.dark.norm(id),
+ dm = colors.dark.mute(id);
+ if (theme === 'dark') {
+ return muted ? dm : dn;
+ } else {
+ return muted ? lm : ln;
+ }
+ }
+
+ function testCard(svg) {
+ var g = svg.select('g#' + tcid),
+ dom = d3.range(7),
+ k, muted, theme, what;
+
+ if (!g.empty()) {
+ g.remove();
+
+ } else {
+ g = svg.append('g')
+ .attr('id', tcid)
+ .attr('transform', 'scale(4)translate(20,20)');
+
+ for (k=0; k<4; k++) {
+ muted = k%2;
+ what = muted ? ' muted' : ' normal';
+ theme = k < 2 ? 'light' : 'dark';
+ dom.forEach(function (id, i) {
+ var x = i * 20,
+ y = k * 20,
+ f = get(id, muted, theme);
+ g.append('circle').attr({
+ cx: x,
+ cy: y,
+ r: 5,
+ fill: f
+ });
+ });
+ g.append('rect').attr({
+ x: 140,
+ y: k * 20 - 5,
+ width: 32,
+ height: 10,
+ rx: 2,
+ fill: '#888'
+ });
+ g.append('text').text(theme + what)
+ .attr({
+ x: 142,
+ y: k * 20 + 2,
+ fill: 'white'
+ })
+ .style('font-size', '4pt');
+ }
+ }
+ }
+
+ return {
+ testCard: testCard,
+ getColor: getColor
+ };
+ }
+
+ function translate(x, y) {
+ if (fs.isA(x) && x.length === 2 && !y) {
+ return 'translate(' + x[0] + ',' + x[1] + ')';
+ }
+ return 'translate(' + x + ',' + y + ')';
+ }
+
+ function scale(x, y) {
+ return 'scale(' + x + ',' + y + ')';
+ }
+
+ function skewX(x) {
+ return 'skewX(' + x + ')';
+ }
+
+ function rotate(deg) {
+ return 'rotate(' + deg + ')';
+ }
+
+ function stripPx(s) {
+ return s.replace(/px$/,'');
+ }
+
+ function safeId(s) {
+ return s.replace(/[^a-z0-9]/gi, '-');
+ }
+
+ function makeVisible(el, b) {
+ el.style('visibility', (b ? 'visible' : 'hidden'));
+ }
+
+ function isVisible(el) {
+ return el.style('visibility') === 'visible';
+ }
+
+ function visible(el, x) {
+ if (x === undefined) {
+ return isVisible(el);
+ } else {
+ makeVisible(el, x);
+ }
+ }
+
angular.module('onosSvg')
- .factory('SvgUtilService', ['$log', 'FnService',
+ .factory('SvgUtilService', ['$log', 'FnService',
function (_$log_, _fs_) {
$log = _$log_;
fs = _fs_;
- // TODO: change 'force' ref to be 'force.alpha' ref.
- function createDragBehavior(force, selectCb, atDragEnd,
- dragEnabled, clickEnabled) {
- var draggedThreshold = d3.scale.linear()
- .domain([0, 0.1])
- .range([5, 20])
- .clamp(true),
- drag,
- fSel = fs.isF(selectCb),
- fEnd = fs.isF(atDragEnd),
- fDEn = fs.isF(dragEnabled),
- fCEn = fs.isF(clickEnabled),
- bad = [];
-
- function naf(what) {
- return 'SvgUtilService: createDragBehavior(): ' + what +
- ' is not a function';
- }
-
- if (!force) {
- bad.push('SvgUtilService: createDragBehavior(): ' +
- 'Bad force reference');
- }
- if (!fSel) {
- bad.push(naf('selectCb'));
- }
- if (!fEnd) {
- bad.push(naf('atDragEnd'));
- }
- if (!fDEn) {
- bad.push(naf('dragEnabled'));
- }
- if (!fCEn) {
- bad.push(naf('clickEnabled'));
- }
-
- if (bad.length) {
- $log.error(bad.join('\n'));
- return null;
- }
-
- function dragged(d) {
- var threshold = draggedThreshold(force.alpha()),
- dx = d.oldX - d.px,
- dy = d.oldY - d.py;
- if (Math.abs(dx) >= threshold || Math.abs(dy) >= threshold) {
- d.dragged = true;
- }
- return d.dragged;
- }
-
- drag = d3.behavior.drag()
- .origin(function(d) { return d; })
- .on('dragstart', function(d) {
- if (clickEnabled() || dragEnabled()) {
- d3.event.sourceEvent.stopPropagation();
-
- d.oldX = d.x;
- d.oldY = d.y;
- d.dragged = false;
- d.fixed |= 2;
- d.dragStarted = true;
- }
- })
- .on('drag', function(d) {
- if (dragEnabled()) {
- d.px = d3.event.x;
- d.py = d3.event.y;
- if (dragged(d)) {
- if (!force.alpha()) {
- force.alpha(.025);
- }
- }
- }
- })
- .on('dragend', function(d) {
- if (d.dragStarted) {
- d.dragStarted = false;
- if (!dragged(d)) {
- // consider this the same as a 'click'
- // (selection of a node)
- if (clickEnabled()) {
- selectCb.call(this, d);
- }
- }
- d.fixed &= ~6;
-
- // hook at the end of a drag gesture
- if (dragEnabled()) {
- atDragEnd.call(this, d);
- }
- }
- });
-
- return drag;
- }
-
-
- function loadGlow(defs, r, g, b, id) {
- var glow = defs.append('filter')
- .attr('x', '-50%')
- .attr('y', '-50%')
- .attr('width', '200%')
- .attr('height', '200%')
- .attr('id', id);
-
- glow.append('feColorMatrix')
- .attr('type', 'matrix')
- .attr('values',
- '0 0 0 0 ' + r + ' ' +
- '0 0 0 0 ' + g + ' ' +
- '0 0 0 0 ' + b + ' ' +
- '0 0 0 1 0 ');
-
- glow.append('feGaussianBlur')
- .attr('stdDeviation', 3)
- .attr('result', 'coloredBlur');
-
- glow.append('feMerge').selectAll('feMergeNode')
- .data(['coloredBlur', 'SourceGraphic'])
- .enter().append('feMergeNode')
- .attr('in', String);
- }
-
- function loadGlowDefs(defs) {
- loadGlow(defs, 0.0, 0.0, 0.7, 'blue-glow');
- loadGlow(defs, 1.0, 1.0, 0.3, 'yellow-glow');
- }
-
- // --- Ordinal scales for 7 values.
-
- // blue brown brick red sea green purple dark teal lime
- var lightNorm = ['#3E5780', '#78533B', '#CB4D28', '#018D61', '#8A2979', '#006D73', '#56AF00'],
- lightMute = ['#A8B8CC', '#CCB3A8', '#FFC2BD', '#96D6BF', '#D19FCE', '#8FCCCA', '#CAEAA4'],
-
- darkNorm = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'],
- darkMute = ['#304860', '#664631', '#A8391B', '#00754B', '#77206D', '#005959', '#428700'];
-
- var colors= {
- light: {
- norm: d3.scale.ordinal().range(lightNorm),
- mute: d3.scale.ordinal().range(lightMute)
- },
- dark: {
- norm: d3.scale.ordinal().range(darkNorm),
- mute: d3.scale.ordinal().range(darkMute)
- }
- };
-
- function cat7() {
- var tcid = 'd3utilTestCard';
-
- function getColor(id, muted, theme) {
- // NOTE: since we are lazily assigning domain ids, we need to
- // get the color from all 4 scales, to keep the domains
- // in sync.
- var ln = colors.light.norm(id),
- lm = colors.light.mute(id),
- dn = colors.dark.norm(id),
- dm = colors.dark.mute(id);
- if (theme === 'dark') {
- return muted ? dm : dn;
- } else {
- return muted ? lm : ln;
- }
- }
-
- function testCard(svg) {
- var g = svg.select('g#' + tcid),
- dom = d3.range(7),
- k, muted, theme, what;
-
- if (!g.empty()) {
- g.remove();
-
- } else {
- g = svg.append('g')
- .attr('id', tcid)
- .attr('transform', 'scale(4)translate(20,20)');
-
- for (k=0; k<4; k++) {
- muted = k%2;
- what = muted ? ' muted' : ' normal';
- theme = k < 2 ? 'light' : 'dark';
- dom.forEach(function (id, i) {
- var x = i * 20,
- y = k * 20,
- f = get(id, muted, theme);
- g.append('circle').attr({
- cx: x,
- cy: y,
- r: 5,
- fill: f
- });
- });
- g.append('rect').attr({
- x: 140,
- y: k * 20 - 5,
- width: 32,
- height: 10,
- rx: 2,
- fill: '#888'
- });
- g.append('text').text(theme + what)
- .attr({
- x: 142,
- y: k * 20 + 2,
- fill: 'white'
- })
- .style('font-size', '4pt');
- }
- }
- }
-
- return {
- testCard: testCard,
- getColor: getColor
- };
- }
-
- function translate(x, y) {
- if (fs.isA(x) && x.length === 2 && !y) {
- return 'translate(' + x[0] + ',' + x[1] + ')';
- }
- return 'translate(' + x + ',' + y + ')';
- }
-
- function scale(x, y) {
- return 'scale(' + x + ',' + y + ')';
- }
-
- function skewX(x) {
- return 'skewX(' + x + ')';
- }
-
- function rotate(deg) {
- return 'rotate(' + deg + ')';
- }
-
- function stripPx(s) {
- return s.replace(/px$/,'');
- }
-
- function safeId(s) {
- return s.replace(/[^a-z0-9]/gi, '-');
- }
-
- function makeVisible(el, b) {
- el.style('visibility', (b ? 'visible' : 'hidden'));
- }
-
- function isVisible(el) {
- return el.style('visibility') === 'visible';
- }
-
return {
createDragBehavior: createDragBehavior,
loadGlowDefs: loadGlowDefs,
@@ -299,13 +307,7 @@
rotate: rotate,
stripPx: stripPx,
safeId: safeId,
- visible: function (el, x) {
- if (x === undefined) {
- return isVisible(el);
- } else {
- makeVisible(el, x);
- }
- }
+ visible: visible
};
}]);
}());
diff --git a/web/gui/src/main/webapp/app/fw/util/ee.js b/web/gui/src/main/webapp/app/fw/util/ee.js
index 43455c2..78f6a9e 100644
--- a/web/gui/src/main/webapp/app/fw/util/ee.js
+++ b/web/gui/src/main/webapp/app/fw/util/ee.js
@@ -21,11 +21,26 @@
'use strict';
// injected services
- var fs;
+ var $log, fs, flash;
// function references
var fcc = String.fromCharCode;
+ // magic beans
+ var beans = [
+ //'umpxwnwcw'
+ //'eufdvexoc',
+ //'egpdytgv',
+ //'xcjvte',
+ //'bgvest',
+ //'sevlr',
+ 'ias'
+ ];
+
+ function pickBean() {
+ return beans[Math.floor(Math.random() * beans.length)] + '.foo';
+ }
+
function computeTransform(x) {
var m = x.split(':'),
h = Number(m[0]),
@@ -45,18 +60,39 @@
data.forEach(function (x) {
var r = computeTransform(x);
- map['shift' + r.e] = r.o.toLowerCase() + '.bin';
+ map[r.e] = r.o.toLowerCase() + '.foo';
});
return map;
}
- angular.module('onosUtil')
- .factory('EeService',
- ['FnService', function (_fs_) {
- fs = _fs_;
+ function cluck(foo) {
+ var f = fs.isF(foo),
+ s = fs.isS(foo);
- return {
- genMap: genMap
+ $log.debug('>>> CLUCK! <<<', foo);
+
+ if (s === 'fgfb.foo') {
+ s = pickBean();
+ $log.debug('bean picked:', s);
}
- }]);
+
+ if (s && fs.endsWith(s, '.foo')) {
+ flash.tempDiv().append('img').attr('src', 'raw/'+s);
+ }
+
+ f && f();
+ }
+
+ angular.module('onosUtil')
+ .factory('EeService', ['$log', 'FnService', 'FlashService',
+ function (_$log_, _fs_, _flash_) {
+ $log = _$log_;
+ fs = _fs_;
+ flash = _flash_;
+
+ return {
+ genMap: genMap,
+ cluck: cluck
+ }
+ }]);
}());
diff --git a/web/gui/src/main/webapp/app/fw/util/keys.js b/web/gui/src/main/webapp/app/fw/util/keys.js
index 393f660..9c60e83 100644
--- a/web/gui/src/main/webapp/app/fw/util/keys.js
+++ b/web/gui/src/main/webapp/app/fw/util/keys.js
@@ -21,11 +21,7 @@
'use strict';
// references to injected services
- var $log, $timeout, fs, ts, ns, qhs;
-
- // constants
- var eeggMin = 'shiftO',
- eeggMax = 'shiftONOS';
+ var $log, $timeout, fs, ts, ns, ee, qhs;
// internal state
var enabled = true,
@@ -37,23 +33,30 @@
viewFn: null,
viewGestures: []
},
- eegg = '';
+ seq = {},
+ matching = false,
+ matched = '',
+ lookup;
- function layEgg(key) {
- eegg += key;
- if (eeggMax.indexOf(eegg) === 0) {
- if (eegg === eeggMax) {
- d3.select('body').append('div').attr('id', 'eegg')
- .append('img').attr('src', 'raw/ewo.foo');
- $timeout(function () { d3.select('#eegg').remove(); }, 3000);
- eegg = '';
- }
+ function matchSeq(key) {
+ if (!matching && key === 'shift') {
+ matching = true;
return true;
}
- if (eegg !== eeggMin) {
- eegg = '';
+ if (matching) {
+ matched += key;
+ lookup = fs.trieLookup(seq, matched);
+ if (lookup === -1) {
+ return true;
+ }
+ matching = false;
+ matched = '';
+ if (!lookup) {
+ return;
+ }
+ ee.cluck(lookup);
+ return true;
}
- return false;
}
function whatKey(code) {
@@ -109,7 +112,7 @@
d3.event.stopPropagation();
if (enabled) {
- if (layEgg(key)) return;
+ if (matchSeq(key)) return;
// global callback?
if (gcb && gcb(token, key, keyCode, event)) {
@@ -230,13 +233,15 @@
angular.module('onosUtil')
.factory('KeyService',
['$log', '$timeout', 'FnService', 'ThemeService', 'NavService',
+ 'EeService',
- function (_$log_, _$timeout_, _fs_, _ts_, _ns_) {
+ function (_$log_, _$timeout_, _fs_, _ts_, _ns_, _ee_) {
$log = _$log_;
$timeout = _$timeout_;
fs = _fs_;
ts = _ts_;
ns = _ns_;
+ ee = _ee_;
return {
bindQhs: function (_qhs_) {
@@ -254,6 +259,12 @@
}
},
unbindKeys: unbindKeys,
+ addSeq: function (word, data) {
+ fs.addToTrie(seq, word, data);
+ },
+ remSeq: function (word) {
+ fs.removeFromTrie(seq, word);
+ },
gestureNotes: function (g) {
if (g === undefined) {
return keyHandler.viewGestures;
diff --git a/web/gui/src/main/webapp/app/onos.css b/web/gui/src/main/webapp/app/onos.css
index b82a6e5..0a6cd90 100644
--- a/web/gui/src/main/webapp/app/onos.css
+++ b/web/gui/src/main/webapp/app/onos.css
@@ -59,7 +59,7 @@
color: #CE5650;
}
-#eegg {
+.centered {
position: fixed;
top: 50%;
left: 50%;
diff --git a/web/gui/src/main/webapp/onos.js b/web/gui/src/main/webapp/onos.js
index 2fffb24..9d34433 100644
--- a/web/gui/src/main/webapp/onos.js
+++ b/web/gui/src/main/webapp/onos.js
@@ -21,6 +21,9 @@
(function () {
'use strict';
+ // injected refs
+ var $log;
+
// define core module dependencies here...
var coreDependencies = [
'ngRoute',
@@ -41,6 +44,18 @@
''
];
+ // secret sauce
+ var sauce = [
+ '20:70717066',
+ '24:886774868469',
+ '6:698570688669887967',
+ '7:6971806889847186',
+ '22:8369867682',
+ '13:736583',
+ '7:667186698384',
+ '1:857780888778876787'
+ ];
+
var defaultView = 'topo',
viewDependencies = [];
@@ -52,6 +67,13 @@
var moduleDependencies = coreDependencies.concat(viewDependencies);
+ function saucy(ee, ks) {
+ var map = ee.genMap(sauce);
+ Object.keys(map).forEach(function (k) {
+ ks.addSeq(k, map[k]);
+ });
+ }
+
function cap(s) {
return s ? s[0].toUpperCase() + s.slice(1) : s;
}
@@ -61,17 +83,18 @@
.controller('OnosCtrl', [
'$log', '$scope', '$route', '$routeParams', '$location',
'KeyService', 'ThemeService', 'GlyphService', 'VeilService',
- 'PanelService', 'FlashService', 'QuickHelpService',
+ 'PanelService', 'FlashService', 'QuickHelpService', 'EeService',
'WebSocketService',
- function ($log, $scope, $route, $routeParams, $location,
- ks, ts, gs, vs, ps, flash, qhs, wss) {
+ function (_$log_, $scope, $route, $routeParams, $location,
+ ks, ts, gs, vs, ps, flash, qhs, ee, wss) {
var self = this;
+ $log = _$log_;
self.$route = $route;
self.$routeParams = $routeParams;
self.$location = $location;
- self.version = '1.3.0';
+ self.version = '1.5.0';
// shared object inherited by all views:
$scope.onos = {};
@@ -83,6 +106,7 @@
gs.init();
vs.init();
ps.init();
+ saucy(ee, ks);
flash.initFlash();
qhs.initQuickHelp();
diff --git a/web/gui/src/main/webapp/raw/ewo.foo b/web/gui/src/main/webapp/raw/ias.foo
similarity index 100%
rename from web/gui/src/main/webapp/raw/ewo.foo
rename to web/gui/src/main/webapp/raw/ias.foo
Binary files differ