mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 09:48:58 -04:00
merge current master
This commit is contained in:
commit
7b27dfef14
66 changed files with 3293 additions and 1868 deletions
44
src/bower_components/K4D3/.bower.json
vendored
44
src/bower_components/K4D3/.bower.json
vendored
|
@ -1,44 +0,0 @@
|
|||
{
|
||||
"name": "K4D3",
|
||||
"main": "core.js",
|
||||
"scripts": [
|
||||
"k4.d3.js"
|
||||
],
|
||||
"homepage": "https://github.com/elasticsearch/K4D3",
|
||||
"authors": [
|
||||
"Shelby Sturgis",
|
||||
"Juan Thomassie"
|
||||
],
|
||||
"description": "D3 Charting Library for Kibana 4",
|
||||
"keywords": [
|
||||
"data",
|
||||
"visualization",
|
||||
"elasticsearch",
|
||||
"kibana"
|
||||
],
|
||||
"license": "MIT",
|
||||
"private": true,
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"node_modules",
|
||||
"bower_components",
|
||||
"test",
|
||||
"tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"d3": "~3.4.1",
|
||||
"requirejs": "~2.1.11",
|
||||
"queue-async": "~1.0.7",
|
||||
"topojson": "~1.4.6"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"_release": "482f0b6eaf",
|
||||
"_resolution": {
|
||||
"type": "branch",
|
||||
"branch": "master",
|
||||
"commit": "482f0b6eafa5996c835b45ba5df1d112c31ac071"
|
||||
},
|
||||
"_source": "git@github.com:elasticsearch/K4D3.git",
|
||||
"_target": "*",
|
||||
"_originalSource": "git@github.com:elasticsearch/K4D3.git"
|
||||
}
|
3
src/bower_components/K4D3/.bowerrc
vendored
Normal file
3
src/bower_components/K4D3/.bowerrc
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"directory" : "lib"
|
||||
}
|
3
src/bower_components/K4D3/.gitignore
vendored
Normal file
3
src/bower_components/K4D3/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
node_modules/
|
||||
test-results.xml
|
37
src/bower_components/K4D3/.jshintrc
vendored
Normal file
37
src/bower_components/K4D3/.jshintrc
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* For an explanation of the different configuration
|
||||
* options listed here, please visit:
|
||||
* http://www.jshint.com/docs/options/
|
||||
*/
|
||||
{
|
||||
"browser": true,
|
||||
"node": false,
|
||||
"undef": true,
|
||||
"unused": true,
|
||||
"globals": {
|
||||
"d3": true,
|
||||
"define": true,
|
||||
"k4": true,
|
||||
"window": true,
|
||||
"require": true,
|
||||
"console": true
|
||||
},
|
||||
"curly": true,
|
||||
"eqeqeq": true,
|
||||
"forin": true,
|
||||
"freeze": true,
|
||||
"indent": 4,
|
||||
"latedef": "nofunc",
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"nonbsp": true,
|
||||
"nonew": true,
|
||||
"plusplus": false,
|
||||
"quotmark": "single",
|
||||
"strict": true,
|
||||
"trailing": true,
|
||||
"maxparams": 3,
|
||||
"maxlen": 140,
|
||||
"devel": true,
|
||||
"maxerr": 10
|
||||
}
|
12
src/bower_components/K4D3/GruntFile.js
vendored
12
src/bower_components/K4D3/GruntFile.js
vendored
|
@ -14,12 +14,7 @@ module.exports = function(grunt) {
|
|||
},
|
||||
dist: {
|
||||
src: [
|
||||
'src/start.js',
|
||||
'src/core.js',
|
||||
'src/tooltip.js',
|
||||
'src/legend.js',
|
||||
'src/modules/histogram.js',
|
||||
'src/end.js'
|
||||
'src/index.js'
|
||||
],
|
||||
dest: 'k4.d3.js'
|
||||
}
|
||||
|
@ -37,7 +32,7 @@ module.exports = function(grunt) {
|
|||
},
|
||||
jshint: {
|
||||
foo: {
|
||||
src: "src/**/*.js"
|
||||
src: 'src/**/*.js'
|
||||
},
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
|
@ -45,7 +40,7 @@ module.exports = function(grunt) {
|
|||
},
|
||||
watch: {
|
||||
js: {
|
||||
files: ["src/**/*.js"],
|
||||
files: ['src/**/*.js'],
|
||||
tasks: ['concat']
|
||||
}
|
||||
},
|
||||
|
@ -67,6 +62,7 @@ module.exports = function(grunt) {
|
|||
|
||||
grunt.loadNpmTasks('grunt-karma');
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-contrib-requirejs');
|
||||
grunt.loadNpmTasks('grunt-contrib-concat');
|
||||
grunt.loadNpmTasks('grunt-contrib-jshint');
|
||||
grunt.loadNpmTasks('grunt-contrib-uglify');
|
||||
|
|
2
src/bower_components/K4D3/Makefile
vendored
2
src/bower_components/K4D3/Makefile
vendored
|
@ -1,5 +1,5 @@
|
|||
JS_FILES = \
|
||||
src/start.js \
|
||||
src/index.js \
|
||||
src/core.js \
|
||||
src/modules/area.js \
|
||||
src/modules/dendrogram.js \
|
||||
|
|
|
@ -17,11 +17,10 @@
|
|||
<div id="element" style="height: 100%"></div>
|
||||
|
||||
<!-- javascript files -->
|
||||
<script src="../lib/d3/d3.min.js"></script>
|
||||
<script src="../k4.d3.js"></script>
|
||||
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
|
||||
<script>
|
||||
<script src="../lib/requirejs/require.js"></script>
|
||||
<!-- <script src="../require.config.js"></script> -->
|
||||
<!--
|
||||
<script>require(['../src/index'], function(k4) {
|
||||
var data = {
|
||||
"rows": [
|
||||
{
|
||||
|
@ -500,14 +499,19 @@
|
|||
elem = $("#element")[0],
|
||||
myChart;
|
||||
|
||||
$("#element").width("100%");
|
||||
$("#element").height(0);
|
||||
$(elem).width("100%");
|
||||
$(elem).height(0);
|
||||
d3.select(elem).style("padding-bottom", "40%");
|
||||
|
||||
myChart = new k4.Chart(elem, { type: "histogram", stacktype: "expand", yGroup: true, color: ['#81dfe2','#0762b7'] });
|
||||
myChart.render(data);
|
||||
console.log(d3.select(elem).style("padding-bottom"));
|
||||
</script>
|
||||
myChart = new k4.Chart(elem, {
|
||||
type: "histogram",
|
||||
stacktype: "group",
|
||||
yGroup: true,
|
||||
color: ['#81dfe2','#0762b7']
|
||||
});
|
||||
|
||||
myChart.render(data);
|
||||
})</script>
|
||||
-->
|
||||
</body>
|
||||
</html>
|
681
src/bower_components/K4D3/k4.d3.js
vendored
681
src/bower_components/K4D3/k4.d3.js
vendored
|
@ -8,677 +8,14 @@
|
|||
} else {
|
||||
root.k4 = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
var k4 = { version: '0.0.0' };
|
||||
|
||||
/*
|
||||
* Main module
|
||||
* Accepts an html element and a config object.
|
||||
* Calls all other K4 modules.
|
||||
* Returns the charting function.
|
||||
*/
|
||||
|
||||
k4.Chart = function(elem, args) {
|
||||
'use strict';
|
||||
|
||||
if (typeof(k4[args.type]) !== 'function') { throw args.type + " is not a supported k4 function."; }
|
||||
|
||||
var type = args.type,
|
||||
chartFunc = k4[type](elem, args);
|
||||
|
||||
return chartFunc;
|
||||
};
|
||||
|
||||
|
||||
k4.tooltip = function() {
|
||||
'use strict';
|
||||
|
||||
// Based on Justin Palmer's d3.tip() function
|
||||
|
||||
var direction = d3_tip_direction,
|
||||
offset = d3_tip_offset,
|
||||
html = d3_tip_html,
|
||||
node = initNode(),
|
||||
svg = null,
|
||||
point = null,
|
||||
target = null;
|
||||
|
||||
function tip(vis) {
|
||||
svg = getSVGNode(vis);
|
||||
point = svg.createSVGPoint();
|
||||
document.body.appendChild(node);
|
||||
}
|
||||
|
||||
// Public - show the tooltip on the screen
|
||||
//
|
||||
// Returns a tip
|
||||
tip.show = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
if(args[args.length - 1] instanceof SVGElement) { target = args.pop(); }
|
||||
|
||||
var content = html.apply(this, args),
|
||||
poffset = offset.apply(this, args),
|
||||
dir = direction.apply(this, args),
|
||||
nodel = d3.select(node),
|
||||
i = directions.length,
|
||||
coords;
|
||||
|
||||
nodel.html(content)
|
||||
.style({ opacity: 1, 'pointer-events': 'all' });
|
||||
|
||||
while(i--) nodel.classed(directions[i], false);
|
||||
coords = direction_callbacks.get(dir).apply(this);
|
||||
nodel.classed(dir, true).style({
|
||||
top: (coords.top + poffset[0]) + 'px',
|
||||
left: (coords.left + poffset[1]) + 'px'
|
||||
});
|
||||
|
||||
return tip;
|
||||
}(this, function(require) {
|
||||
var k4 = {
|
||||
version: '0.0.0',
|
||||
tooltip: require('./bower_components/K4D3/src/tooltip'),
|
||||
legend: require('./bower_components/K4D3/src/legend'),
|
||||
Chart: require('./bower_components/K4D3/src/core'),
|
||||
histogram: require('./bower_components/K4D3/src/modules/histogram')
|
||||
};
|
||||
|
||||
// Public - hide the tooltip
|
||||
//
|
||||
// Returns a tip
|
||||
tip.hide = function() {
|
||||
var nodel = d3.select(node);
|
||||
nodel.style({ opacity: 0, 'pointer-events': 'none' });
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
|
||||
//
|
||||
// n - name of the attribute
|
||||
// v - value of the attribute
|
||||
//
|
||||
// Returns tip or attribute value
|
||||
tip.attr = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).attr(n);
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.attr.apply(d3.select(node), args);
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
|
||||
//
|
||||
// n - name of the property
|
||||
// v - value of the property
|
||||
//
|
||||
// Returns tip or style property value
|
||||
tip.style = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).style(n)
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.style.apply(d3.select(node), args);
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Set or get the direction of the tooltip
|
||||
//
|
||||
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
|
||||
// sw(southwest), ne(northeast) or se(southeast)
|
||||
//
|
||||
// Returns tip or direction
|
||||
tip.direction = function(v) {
|
||||
if (!arguments.length) { return direction; }
|
||||
direction = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Sets or gets the offset of the tip
|
||||
//
|
||||
// v - Array of [x, y] offset
|
||||
//
|
||||
// Returns offset or
|
||||
tip.offset = function(v) {
|
||||
if (!arguments.length) { return offset; }
|
||||
offset = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: sets or gets the html value of the tooltip
|
||||
//
|
||||
// v - String value of the tip
|
||||
//
|
||||
// Returns html value or tip
|
||||
tip.html = function(v) {
|
||||
if (!arguments.length) { return html; }
|
||||
html = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
function d3_tip_direction() { return 'n'; }
|
||||
function d3_tip_offset() { return [0, 0]; }
|
||||
function d3_tip_html() { return ' '; }
|
||||
|
||||
var direction_callbacks = d3.map({
|
||||
n: direction_n,
|
||||
s: direction_s,
|
||||
e: direction_e,
|
||||
w: direction_w,
|
||||
nw: direction_nw,
|
||||
ne: direction_ne,
|
||||
sw: direction_sw,
|
||||
se: direction_se
|
||||
}),
|
||||
|
||||
directions = direction_callbacks.keys();
|
||||
|
||||
function direction_n() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.n.y - node.offsetHeight,
|
||||
left: bbox.n.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_s() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.s.y,
|
||||
left: bbox.s.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_e() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.e.y - node.offsetHeight / 2,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_w() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.w.y - node.offsetHeight / 2,
|
||||
left: bbox.w.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_nw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.nw.y - node.offsetHeight,
|
||||
left: bbox.nw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_ne() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.ne.y - node.offsetHeight,
|
||||
left: bbox.ne.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_sw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.sw.y,
|
||||
left: bbox.sw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_se() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.se.y,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function initNode() {
|
||||
var node = d3.select(document.createElement('div'));
|
||||
node.style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
opacity: 0,
|
||||
'pointer-events': 'none',
|
||||
'box-sizing': 'border-box'
|
||||
});
|
||||
|
||||
return node.node();
|
||||
}
|
||||
|
||||
function getSVGNode(el) {
|
||||
el = el.node();
|
||||
if(el.tagName.toLowerCase() === 'svg') { return el; }
|
||||
|
||||
return el.ownerSVGElement
|
||||
}
|
||||
|
||||
// Private - gets the screen coordinates of a shape
|
||||
//
|
||||
// Given a shape on the screen, will return an SVGPoint for the directions
|
||||
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
|
||||
// sw(southwest).
|
||||
//
|
||||
// +-+-+
|
||||
// | |
|
||||
// + +
|
||||
// | |
|
||||
// +-+-+
|
||||
//
|
||||
// Returns an Object {n, s, e, w, nw, sw, ne, se}
|
||||
function getScreenBBox() {
|
||||
var targetel = target || d3.event.target,
|
||||
bbox = {},
|
||||
matrix = targetel.getScreenCTM(),
|
||||
tbbox = targetel.getBBox(),
|
||||
width = tbbox.width,
|
||||
height = tbbox.height,
|
||||
x = tbbox.x,
|
||||
y = tbbox.y,
|
||||
scrollEl = document.documentElement ? document.documentElement : document.body,
|
||||
scrollTop = scrollEl.scrollTop,
|
||||
scrollLeft = scrollEl.scrollLeft;
|
||||
|
||||
|
||||
point.x = x + scrollLeft;
|
||||
point.y = y + scrollTop;
|
||||
bbox.nw = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.ne = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.se = point.matrixTransform(matrix);
|
||||
point.x -= width;
|
||||
bbox.sw = point.matrixTransform(matrix);
|
||||
point.y -= height / 2;
|
||||
bbox.w = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.e = point.matrixTransform(matrix);
|
||||
point.x -= width / 2;
|
||||
point.y -= height / 2;
|
||||
bbox.n = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.s = point.matrixTransform(matrix);
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
return tip;
|
||||
};k4.legend = function(g) {
|
||||
'use strict';
|
||||
|
||||
g.each(function() {
|
||||
var g = d3.select(this),
|
||||
items = {},
|
||||
svg = d3.select(g.property("nearestViewportElement")),
|
||||
legendPadding = g.attr("data-style-padding") || 5,
|
||||
lb = g.selectAll(".legend-box").data([true]),
|
||||
li = g.selectAll(".legend-items").data([true]),
|
||||
lbbox;
|
||||
|
||||
lb.enter().append("rect").classed("legend-box",true);
|
||||
li.enter().append("g").classed("legend-items",true);
|
||||
|
||||
svg.selectAll("[data-legend]").each(function() {
|
||||
var self = d3.select(this);
|
||||
items[self.attr("data-legend")] = {
|
||||
pos : self.attr("data-legend-pos") || this.getBBox().y,
|
||||
color : self.attr("data-legend-color") !== null ? self.attr("data-legend-color") :
|
||||
self.style("fill") !== 'none' ? self.style("fill") : self.style("stroke")
|
||||
};
|
||||
});
|
||||
|
||||
items = d3.entries(items).sort(function(a, b) { return a.value.pos - b.value.pos; });
|
||||
|
||||
/*
|
||||
li.selectAll('div')
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("div"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-div");
|
||||
*/
|
||||
|
||||
li.selectAll("text")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("text"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-text")
|
||||
.attr("x", "0.7em")
|
||||
.attr("y", function(d, i) { return i + "em"; })
|
||||
.text(function(d) { return d.key; });
|
||||
|
||||
li.selectAll("circle")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("circle"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-circle")
|
||||
.attr("cx", 0)
|
||||
.attr("cy", function(d, i) { return i - 0.25 + "em"; })
|
||||
.attr("r", "0.4em")
|
||||
.style("fill", function(d) { return d.value.color; });
|
||||
|
||||
// Reposition and resize the box
|
||||
lbbox = li[0][0].getBBox();
|
||||
|
||||
lb.attr("x", (lbbox.x - legendPadding))
|
||||
.attr("y", (lbbox.y - legendPadding))
|
||||
.attr("height", (lbbox.height + 2 * legendPadding))
|
||||
.attr("width", (lbbox.width + 2 * legendPadding));
|
||||
});
|
||||
|
||||
return g;
|
||||
};
|
||||
k4.histogram = function(elem, args) {
|
||||
'use strict';
|
||||
|
||||
var chart = {},
|
||||
|
||||
/* ********** Sizing DOM Elements ************* */
|
||||
// accessing the element width/height
|
||||
elemWidth = parseInt(d3.select(elem).style("width"), 10),
|
||||
elemHeight = parseInt(d3.select(elem).style("padding-bottom"), 10),
|
||||
// number of rows
|
||||
numRows = data.rows.length,
|
||||
// number of charts
|
||||
n = data.rows[0].columns.length,
|
||||
// number of layers per chart
|
||||
m = data.rows[0].columns[0].layers.length,
|
||||
// row width
|
||||
outerWidth = elemWidth,
|
||||
// row height
|
||||
outerHeight = elemHeight / numRows,
|
||||
margin = {
|
||||
top: outerHeight * 0.05,
|
||||
right: outerWidth * 0.01,
|
||||
bottom: outerHeight * 0.15,
|
||||
left: outerWidth * 0.05
|
||||
},
|
||||
// svg width/height
|
||||
width = outerWidth/n - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom,
|
||||
/* ************************************************** */
|
||||
|
||||
/* ************* Data manipulation **************** */
|
||||
// pulls out the x-axis key values
|
||||
keys = data.rows[0].columns[0].layers[0].values.map(function(item) { return item.x; }),
|
||||
// defines the stack.offset()
|
||||
stacktype = args.stacktype || 'zero', // 'zero', 'expand', 'group'
|
||||
stack = d3.layout.stack().offset(stacktype).values(function(d) { return d.values; }),
|
||||
// calculates the y-axis max value for all charts, i.e. grouped and stacked
|
||||
yGroup = args.yGroup || false,
|
||||
yGroupMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y;
|
||||
});
|
||||
});
|
||||
});
|
||||
})),
|
||||
yStackMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y0 + d.y;
|
||||
});
|
||||
});
|
||||
});
|
||||
})),
|
||||
/* **************************************************** */
|
||||
|
||||
/* *************** D3 parameters ********************* */
|
||||
xScale = d3.scale.ordinal().domain(keys).rangeRoundBands([0, width], 0.1),
|
||||
yScale = d3.scale.linear().range([height, 0]).nice(),
|
||||
xAxis = d3.svg.axis().scale(xScale).ticks(6).tickSize(3, 0).tickPadding(6).orient('bottom'),
|
||||
yAxis = d3.svg.axis().scale(yScale).ticks(6).tickSize(-(width), 0).tickPadding(4).orient('left'),
|
||||
color = d3.scale.linear().domain([0, m - 1]).range(args.color) ||
|
||||
d3.scale.linear().domain([0, m - 1]).range(['#e24700', '#f9e593']),
|
||||
toolTip = k4.tooltip().attr('class', 'k4-tip').html(function(d) {
|
||||
if (d.y < 1) { return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y.toFixed(2) * 100 + '%</span>'; }
|
||||
return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y + '</span>';
|
||||
}).offset([-12, 0]),
|
||||
svg, g, layer;
|
||||
/* ******************************************************** */
|
||||
|
||||
chart.render = function(data) {
|
||||
|
||||
// append svg(s)
|
||||
svg = getSvg(elem, data);
|
||||
|
||||
// render each chart
|
||||
g = svg.append('g')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||
.each(function(d) {
|
||||
var g = d3.select(this);
|
||||
|
||||
var yMax = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y;
|
||||
});
|
||||
});
|
||||
console.log(yMax);
|
||||
console.log(yGroupMax);
|
||||
|
||||
var yStack = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y0 + e.y;
|
||||
});
|
||||
});
|
||||
|
||||
// Change y/xScale domain based on stacktype
|
||||
if (stacktype === 'expand') { yScale.domain([0, 1]); }
|
||||
|
||||
if (stacktype === 'group' && yGroup) {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yGroupMax]);
|
||||
} else {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yMax]);
|
||||
}
|
||||
|
||||
if (stacktype === 'zero' && yGroup) {
|
||||
yScale.domain([0, yStackMax]);
|
||||
} else {
|
||||
yScale.domain([0, yStack]);
|
||||
}
|
||||
|
||||
// background rect
|
||||
g.append('g')
|
||||
.append('rect')
|
||||
.attr('class', 'bkgd')
|
||||
.style('fill', '#fff')
|
||||
.style('opacity', 0.35)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
|
||||
// x axis
|
||||
g.append('g')
|
||||
.attr('class', 'x axis')
|
||||
.attr('transform', 'translate(0,' + height + ')')
|
||||
.style('stroke-width', 0.5)
|
||||
.call(xAxis);
|
||||
|
||||
// y axis
|
||||
g.append('g')
|
||||
.attr('class', 'y axis')
|
||||
.style('stroke-width', 0.5)
|
||||
.call(yAxis);
|
||||
|
||||
// layer of bars
|
||||
layer = g.selectAll('.layer')
|
||||
.data(function(d) { return stack(d.layers); })
|
||||
.enter().append('g')
|
||||
.attr('class', 'layer')
|
||||
.style('fill', function(d, i) { return color(i); });
|
||||
|
||||
//Enter
|
||||
// bars for stack, expand, group
|
||||
layer.selectAll('rect')
|
||||
.data(function(d) { return d.values; })
|
||||
.enter().append('rect');
|
||||
|
||||
// Update
|
||||
if (stacktype === 'group') {
|
||||
layer.selectAll('rect')
|
||||
.attr('x', function(d, i, j) { return xScale(d.x) + xScale.rangeBand() / m * j; })
|
||||
.attr('width', xScale.rangeBand() / m)
|
||||
.attr('y', function(d) { return yScale(d.y); })
|
||||
.attr('height', function(d) { return height - yScale(d.y); })
|
||||
.on('mouseover', toolTip.show)
|
||||
.on('mouseout', toolTip.hide);
|
||||
} else {
|
||||
layer.selectAll('rect')
|
||||
.attr('width', xScale.rangeBand())
|
||||
.attr('x', function(d) { return xScale(d.x); })
|
||||
.attr('y', function(d) { return yScale(d.y0 + d.y); })
|
||||
.attr('height', function(d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
|
||||
.on('mouseover', toolTip.show)
|
||||
.on('mouseout', toolTip.hide);
|
||||
}
|
||||
|
||||
//Exit
|
||||
layer.selectAll('rect').data(function(d) { return d.values; }).exit().remove();
|
||||
});
|
||||
|
||||
// Window resize
|
||||
d3.select(window).on('resize', resize);
|
||||
|
||||
// k4 tooltip function
|
||||
g.call(toolTip);
|
||||
|
||||
return svg;
|
||||
};
|
||||
|
||||
// append layout divs to elem and bind layout data
|
||||
function getSvg(elem, data) {
|
||||
var rows, cols, svg;
|
||||
|
||||
rows = d3.select(elem).selectAll('div')
|
||||
.data(data.rows)
|
||||
.enter().append('div')
|
||||
.attr('class', function(d, i) { return 'row r' + i; });
|
||||
|
||||
cols = rows.selectAll('div')
|
||||
.data(function(d) { return d.columns; })
|
||||
.enter().append('div')
|
||||
.attr('class', function(d,i){ return 'col c' + i; });
|
||||
|
||||
svg = cols.append('svg')
|
||||
.attr("width", outerWidth/n)
|
||||
.attr("height", outerHeight);
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
function resize() {
|
||||
/* Update graph using new width and height */
|
||||
var elemWidth = parseInt(d3.select(elem).style("width"), 10),
|
||||
elemHeight = parseInt(d3.select(elem).style("padding-bottom"), 10),
|
||||
outerWidth = elemWidth / n,
|
||||
outerHeight = elemHeight / numRows,
|
||||
width = outerWidth - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom;
|
||||
|
||||
d3.select(".row r").style("width", elemWidth).style("height", outerHeight);
|
||||
d3.select(".col c").style ("width", outerWidth).style("height", outerHeight);
|
||||
svg.attr("width", outerWidth).attr("height", outerHeight);
|
||||
|
||||
g.each(function(d) {
|
||||
var g = d3.select(this);
|
||||
|
||||
var yMax = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y; }); });
|
||||
var yStack = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y0 + e.y; }); });
|
||||
|
||||
// Change y/xScale domain based on stacktype
|
||||
// Change y/xScale domain based on stacktype
|
||||
if (stacktype === 'expand') { yScale.domain([0, 1]); }
|
||||
|
||||
if (stacktype === 'group' && yGroup) {
|
||||
yScale.domain([0, yGroupMax]);
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
} else {
|
||||
yScale.domain([0, yMax]);
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
}
|
||||
|
||||
if (stacktype === 'zero' && yGroup) {
|
||||
yScale.domain([0, yStackMax]);
|
||||
} else {
|
||||
yScale.domain([0, yStack]);
|
||||
}
|
||||
|
||||
/* Update the range of the scale with new width/height */
|
||||
if (stacktype === "group") { xScale.rangeRoundBands([0, width], 0.4); }
|
||||
else { xScale.rangeRoundBands([0, width], 0.1); }
|
||||
yScale.range([height, 0]).nice();
|
||||
xAxis.ticks(Math.max(width/50, 2));
|
||||
yAxis.ticks(Math.max(height/20, 2)).tickSize(-(width), 0);
|
||||
|
||||
if (width < 300 && height < 80) {
|
||||
g.select('.x.axis').style('display', 'none');
|
||||
} else {
|
||||
g.select('.x.axis').style('display', 'initial');
|
||||
g.select('.y.axis').style('display', 'initial');
|
||||
}
|
||||
|
||||
g.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
g.selectAll(".bkgd").attr("width", width).attr("height", height);
|
||||
|
||||
/* Update the axis with the new scale */
|
||||
g.select('.x.axis')
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
g.select('.y.axis')
|
||||
.call(yAxis);
|
||||
|
||||
/* Force D3 to recalculate and update the line */
|
||||
if (stacktype === "group") {
|
||||
layer.selectAll("rect")
|
||||
.attr( "x", function (d, i, j) { return xScale(d.x) + xScale.rangeBand() / n * j; })
|
||||
.attr("width", xScale.rangeBand() / n)
|
||||
.attr( "y", function (d) { return yScale(d.y); })
|
||||
.attr( "height", function (d) { return height - yScale(d.y); });
|
||||
}
|
||||
|
||||
g.selectAll('rect')
|
||||
.attr("width", xScale.rangeBand())
|
||||
.attr("x", function(d) { return xScale(d.x); })
|
||||
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
|
||||
.attr("y", function(d) { return yScale(d.y0 + d.y); });
|
||||
});
|
||||
}
|
||||
|
||||
chart.margin = function() {
|
||||
if (!args.margin) { return margin; }
|
||||
margin.top = typeof args.margin.top !== 'undefined' ? args.margin.top : margin.top;
|
||||
margin.right = typeof args.margin.right !== 'undefined' ? args.margin.right : margin.right;
|
||||
margin.bottom = typeof args.margin.bottom !== 'undefined' ? args.margin.bottom : margin.bottom;
|
||||
margin.left = typeof args.margin.left !== 'undefined' ? args.margin.left : margin.left;
|
||||
return margin;
|
||||
};
|
||||
|
||||
chart.width = function() {
|
||||
if (!args.width) { return width; }
|
||||
width = args.width;
|
||||
return width;
|
||||
};
|
||||
|
||||
chart.height = function() {
|
||||
if (!args.height) { return height; }
|
||||
height = args.height;
|
||||
return height;
|
||||
};
|
||||
|
||||
chart.color = function() {
|
||||
if (!args.color) { return color; }
|
||||
color = args.color;
|
||||
return color;
|
||||
};
|
||||
|
||||
return chart;
|
||||
}; return k4;
|
||||
}));
|
||||
return k4;
|
||||
}));
|
||||
|
|
2
src/bower_components/K4D3/k4.d3.min.js
vendored
2
src/bower_components/K4D3/k4.d3.min.js
vendored
File diff suppressed because one or more lines are too long
18
src/bower_components/K4D3/lib/angular-route/.bower.json
vendored
Normal file
18
src/bower_components/K4D3/lib/angular-route/.bower.json
vendored
Normal file
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"name": "angular-route",
|
||||
"version": "1.2.14-build.2338+sha.27873ac",
|
||||
"main": "./angular-route.js",
|
||||
"dependencies": {
|
||||
"angular": "1.2.14-build.2338+sha.27873ac"
|
||||
},
|
||||
"homepage": "https://github.com/angular/bower-angular-route",
|
||||
"_release": "1.2.14-build.2338+sha.27873ac",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.2.14-build.2338+sha.27873ac",
|
||||
"commit": "dc4057d931755391886975255bb4a52fd24f6634"
|
||||
},
|
||||
"_source": "git://github.com/angular/bower-angular-route.git",
|
||||
"_target": "~1.2.13",
|
||||
"_originalSource": "angular-route"
|
||||
}
|
16
src/bower_components/K4D3/lib/angular/.bower.json
vendored
Normal file
16
src/bower_components/K4D3/lib/angular/.bower.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "angular",
|
||||
"version": "1.2.14-build.2338+sha.27873ac",
|
||||
"main": "./angular.js",
|
||||
"dependencies": {},
|
||||
"homepage": "https://github.com/angular/bower-angular",
|
||||
"_release": "1.2.14-build.2338+sha.27873ac",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.2.14-build.2338+sha.27873ac",
|
||||
"commit": "75d2b41ae7da8231ebe2d10940166e249c1262c0"
|
||||
},
|
||||
"_source": "git://github.com/angular/bower-angular.git",
|
||||
"_target": "1.2.14-build.2338+sha.27873ac",
|
||||
"_originalSource": "angular"
|
||||
}
|
35
src/bower_components/K4D3/lib/bootstrap/.bower.json
vendored
Normal file
35
src/bower_components/K4D3/lib/bootstrap/.bower.json
vendored
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "bootstrap",
|
||||
"version": "3.1.1",
|
||||
"main": [
|
||||
"./dist/css/bootstrap.css",
|
||||
"./dist/js/bootstrap.js",
|
||||
"./dist/fonts/glyphicons-halflings-regular.eot",
|
||||
"./dist/fonts/glyphicons-halflings-regular.svg",
|
||||
"./dist/fonts/glyphicons-halflings-regular.ttf",
|
||||
"./dist/fonts/glyphicons-halflings-regular.woff"
|
||||
],
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"_config.yml",
|
||||
"CNAME",
|
||||
"composer.json",
|
||||
"CONTRIBUTING.md",
|
||||
"docs",
|
||||
"js/tests"
|
||||
],
|
||||
"dependencies": {
|
||||
"jquery": ">= 1.9.0"
|
||||
},
|
||||
"homepage": "https://github.com/twbs/bootstrap",
|
||||
"_release": "3.1.1",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v3.1.1",
|
||||
"commit": "a365d8689c3f3cee7f1acf86b61270ecca8e106d"
|
||||
},
|
||||
"_source": "git://github.com/twbs/bootstrap.git",
|
||||
"_target": "~3.1.1",
|
||||
"_originalSource": "bootstrap",
|
||||
"_direct": true
|
||||
}
|
34
src/bower_components/K4D3/lib/d3/.bower.json
vendored
Normal file
34
src/bower_components/K4D3/lib/d3/.bower.json
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "d3",
|
||||
"version": "3.4.3",
|
||||
"main": "d3.js",
|
||||
"scripts": [
|
||||
"d3.js"
|
||||
],
|
||||
"ignore": [
|
||||
".DS_Store",
|
||||
".git",
|
||||
".gitignore",
|
||||
".npmignore",
|
||||
".travis.yml",
|
||||
"Makefile",
|
||||
"bin",
|
||||
"component.json",
|
||||
"index.js",
|
||||
"lib",
|
||||
"node_modules",
|
||||
"package.json",
|
||||
"src",
|
||||
"test"
|
||||
],
|
||||
"homepage": "https://github.com/mbostock/d3",
|
||||
"_release": "3.4.3",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v3.4.3",
|
||||
"commit": "368a48205152483fb68e7423fefc87a90fbe9a9d"
|
||||
},
|
||||
"_source": "git://github.com/mbostock/d3.git",
|
||||
"_target": "~3.4.1",
|
||||
"_originalSource": "d3"
|
||||
}
|
24
src/bower_components/K4D3/lib/elasticsearch/.bower.json
vendored
Normal file
24
src/bower_components/K4D3/lib/elasticsearch/.bower.json
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "elasticsearch",
|
||||
"version": "1.5.9",
|
||||
"authors": [
|
||||
"Spencer Alger <spencer@spenceralger.com>"
|
||||
],
|
||||
"description": "The official low-level Elasticsearch client, for use in the browser.",
|
||||
"main": "elasticsearch.js",
|
||||
"keywords": [
|
||||
"elasticsearch",
|
||||
"client"
|
||||
],
|
||||
"license": "Apache 2.0",
|
||||
"homepage": "https://github.com/elasticsearch/bower-elasticsearch-js",
|
||||
"_release": "1.5.9",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.5.9",
|
||||
"commit": "02d4b405996c1be5e7adfb8922443a5e31db4a48"
|
||||
},
|
||||
"_source": "git://github.com/elasticsearch/bower-elasticsearch-js.git",
|
||||
"_target": "~1.5.8",
|
||||
"_originalSource": "elasticsearch"
|
||||
}
|
37
src/bower_components/K4D3/lib/jquery/.bower.json
vendored
Normal file
37
src/bower_components/K4D3/lib/jquery/.bower.json
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"name": "jquery",
|
||||
"version": "2.1.0",
|
||||
"main": "dist/jquery.js",
|
||||
"license": "MIT",
|
||||
"ignore": [
|
||||
"**/.*",
|
||||
"build",
|
||||
"speed",
|
||||
"test",
|
||||
"*.md",
|
||||
"AUTHORS.txt",
|
||||
"Gruntfile.js",
|
||||
"package.json"
|
||||
],
|
||||
"devDependencies": {
|
||||
"sizzle": "1.10.16",
|
||||
"requirejs": "~2.1.8",
|
||||
"qunit": "~1.12.0",
|
||||
"sinon": "~1.7.3"
|
||||
},
|
||||
"keywords": [
|
||||
"jquery",
|
||||
"javascript",
|
||||
"library"
|
||||
],
|
||||
"homepage": "https://github.com/jquery/jquery",
|
||||
"_release": "2.1.0",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "2.1.0",
|
||||
"commit": "9434e03193c45d51bbd063a0edd1a07a6178d33f"
|
||||
},
|
||||
"_source": "git://github.com/jquery/jquery.git",
|
||||
"_target": ">= 1.9.0",
|
||||
"_originalSource": "jquery"
|
||||
}
|
34
src/bower_components/K4D3/lib/lodash/.bower.json
vendored
Normal file
34
src/bower_components/K4D3/lib/lodash/.bower.json
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
{
|
||||
"name": "lodash",
|
||||
"version": "2.4.1",
|
||||
"main": "dist/lodash.compat.js",
|
||||
"ignore": [
|
||||
".*",
|
||||
"*.custom.*",
|
||||
"*.template.*",
|
||||
"*.map",
|
||||
"*.md",
|
||||
"/*.min.*",
|
||||
"/lodash.js",
|
||||
"index.js",
|
||||
"component.json",
|
||||
"package.json",
|
||||
"doc",
|
||||
"modularize",
|
||||
"node_modules",
|
||||
"perf",
|
||||
"test",
|
||||
"vendor"
|
||||
],
|
||||
"homepage": "https://github.com/lodash/lodash",
|
||||
"_release": "2.4.1",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "2.4.1",
|
||||
"commit": "c7aa842eded639d6d90a5714d3195a8802c86687"
|
||||
},
|
||||
"_source": "git://github.com/lodash/lodash.git",
|
||||
"_target": "~2.4.1",
|
||||
"_originalSource": "lodash",
|
||||
"_direct": true
|
||||
}
|
16
src/bower_components/K4D3/lib/queue-async/.bower.json
vendored
Normal file
16
src/bower_components/K4D3/lib/queue-async/.bower.json
vendored
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"name": "queue-async",
|
||||
"version": "1.0.7",
|
||||
"main": "./queue.js",
|
||||
"homepage": "https://github.com/mbostock/queue",
|
||||
"_release": "1.0.7",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.0.7",
|
||||
"commit": "ca293e8c2e3654807ead7597cad0188e6f5b4dfe"
|
||||
},
|
||||
"_source": "git://github.com/mbostock/queue.git",
|
||||
"_target": "~1.0.7",
|
||||
"_originalSource": "queue-async",
|
||||
"_direct": true
|
||||
}
|
2
src/bower_components/K4D3/lib/queue-async/.gitignore
vendored
Normal file
2
src/bower_components/K4D3/lib/queue-async/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
node_modules
|
1
src/bower_components/K4D3/lib/queue-async/.npmignore
vendored
Normal file
1
src/bower_components/K4D3/lib/queue-async/.npmignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
test/
|
404
src/bower_components/K4D3/lib/queue-async/test/queue-test.js
vendored
Normal file
404
src/bower_components/K4D3/lib/queue-async/test/queue-test.js
vendored
Normal file
|
@ -0,0 +1,404 @@
|
|||
var queue = require("../queue"),
|
||||
fs = require("fs"),
|
||||
vows = require("vows"),
|
||||
assert = require("assert");
|
||||
|
||||
var suite = vows.describe("queue");
|
||||
|
||||
suite.addBatch({
|
||||
|
||||
"version": {
|
||||
"is semantic": function() {
|
||||
assert.isTrue(/^([0-9]+)\.([0-9]+)\.([0-9]+)/.test(queue.version));
|
||||
}
|
||||
},
|
||||
|
||||
"example queue of fs.stat": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(fs.stat, __dirname + "/../Makefile")
|
||||
.defer(fs.stat, __dirname + "/../README.md")
|
||||
.defer(fs.stat, __dirname + "/../package.json")
|
||||
.await(this.callback);
|
||||
},
|
||||
"does not fail": function(error, one, two, three) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"successfully executes the three tasks": function(error, one, two, three) {
|
||||
assert.greater(one.size, 0);
|
||||
assert.greater(two.size, 0);
|
||||
assert.greater(three.size, 0);
|
||||
}
|
||||
},
|
||||
|
||||
"queue of single synchronous task that errors": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(function(callback) { callback(-1); })
|
||||
.await(this.callback);
|
||||
},
|
||||
"fails": function(error, result) {
|
||||
assert.equal(error, -1);
|
||||
assert.isUndefined(result);
|
||||
}
|
||||
},
|
||||
|
||||
"queue of single asynchronous task that errors": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(function(callback) { process.nextTick(function() { callback(-1); }); })
|
||||
.await(this.callback);
|
||||
},
|
||||
"fails": function(error, result) {
|
||||
assert.equal(error, -1);
|
||||
assert.isUndefined(result);
|
||||
}
|
||||
},
|
||||
|
||||
"queue with multiple tasks that error": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(function(callback) { setTimeout(function() { callback(-2); }, 100); })
|
||||
.defer(function(callback) { process.nextTick(function() { callback(-1); }); })
|
||||
.defer(function(callback) { setTimeout(function() { callback(-3); }, 200); })
|
||||
.await(this.callback);
|
||||
},
|
||||
"the first error is returned": function(error, one, two, three) {
|
||||
assert.equal(error, -1);
|
||||
assert.isUndefined(one);
|
||||
assert.isUndefined(two);
|
||||
assert.isUndefined(three);
|
||||
}
|
||||
},
|
||||
|
||||
"queue with multiple tasks where one errors": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(function(callback) { process.nextTick(function() { callback(-1); }); })
|
||||
.defer(function(callback) { process.nextTick(function() { callback(null, 'ok'); }); })
|
||||
.await(this.callback);
|
||||
},
|
||||
"the first error is returned": function(error, one, two) {
|
||||
assert.equal(error, -1);
|
||||
assert.isUndefined(one);
|
||||
assert.isUndefined(two);
|
||||
}
|
||||
},
|
||||
|
||||
"queue with multiple synchronous tasks that error": {
|
||||
topic: function() {
|
||||
queue()
|
||||
.defer(function(callback) { callback(-1); })
|
||||
.defer(function(callback) { callback(-2); })
|
||||
.defer(function(callback) { throw new Error(); })
|
||||
.await(this.callback);
|
||||
},
|
||||
"the first error prevents the other tasks from running": function(error, one, two, three) {
|
||||
assert.equal(error, -1);
|
||||
assert.isUndefined(one);
|
||||
assert.isUndefined(two);
|
||||
assert.isUndefined(three);
|
||||
}
|
||||
},
|
||||
|
||||
"queue of asynchronous closures, processed serially": {
|
||||
topic: function() {
|
||||
var tasks = [], task = asynchronousTask(), n = 10, q = queue(1);
|
||||
while (--n >= 0) tasks.push(task);
|
||||
tasks.forEach(function(t) { q.defer(t); });
|
||||
q.awaitAll(this.callback)
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in series": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 1, index: 0},
|
||||
{active: 1, index: 1},
|
||||
{active: 1, index: 2},
|
||||
{active: 1, index: 3},
|
||||
{active: 1, index: 4},
|
||||
{active: 1, index: 5},
|
||||
{active: 1, index: 6},
|
||||
{active: 1, index: 7},
|
||||
{active: 1, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"fully-parallel queue of ten asynchronous tasks": {
|
||||
topic: function() {
|
||||
var t = asynchronousTask();
|
||||
queue()
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in parallel": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 10, index: 0},
|
||||
{active: 9, index: 1},
|
||||
{active: 8, index: 2},
|
||||
{active: 7, index: 3},
|
||||
{active: 6, index: 4},
|
||||
{active: 5, index: 5},
|
||||
{active: 4, index: 6},
|
||||
{active: 3, index: 7},
|
||||
{active: 2, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"partly-parallel queue of ten asynchronous tasks": {
|
||||
topic: function() {
|
||||
var t = asynchronousTask();
|
||||
queue(3)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes at most three tasks in parallel": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 3, index: 0},
|
||||
{active: 3, index: 1},
|
||||
{active: 3, index: 2},
|
||||
{active: 3, index: 3},
|
||||
{active: 3, index: 4},
|
||||
{active: 3, index: 5},
|
||||
{active: 3, index: 6},
|
||||
{active: 3, index: 7},
|
||||
{active: 2, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"serialized queue of ten asynchronous tasks": {
|
||||
topic: function() {
|
||||
var t = asynchronousTask();
|
||||
queue(1)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in series": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 1, index: 0},
|
||||
{active: 1, index: 1},
|
||||
{active: 1, index: 2},
|
||||
{active: 1, index: 3},
|
||||
{active: 1, index: 4},
|
||||
{active: 1, index: 5},
|
||||
{active: 1, index: 6},
|
||||
{active: 1, index: 7},
|
||||
{active: 1, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"serialized queue of ten deferred synchronous tasks": {
|
||||
topic: function() {
|
||||
var t = deferredSynchronousTask();
|
||||
queue(1)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
t.finish();
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in series, within the callback of the first task": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 1, index: 0},
|
||||
{active: 2, index: 1},
|
||||
{active: 2, index: 2},
|
||||
{active: 2, index: 3},
|
||||
{active: 2, index: 4},
|
||||
{active: 2, index: 5},
|
||||
{active: 2, index: 6},
|
||||
{active: 2, index: 7},
|
||||
{active: 2, index: 8},
|
||||
{active: 2, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"partly-parallel queue of ten synchronous tasks": {
|
||||
topic: function() {
|
||||
var t = synchronousTask();
|
||||
queue(3)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in series": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 1, index: 0},
|
||||
{active: 1, index: 1},
|
||||
{active: 1, index: 2},
|
||||
{active: 1, index: 3},
|
||||
{active: 1, index: 4},
|
||||
{active: 1, index: 5},
|
||||
{active: 1, index: 6},
|
||||
{active: 1, index: 7},
|
||||
{active: 1, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
},
|
||||
|
||||
"serialized queue of ten synchronous tasks": {
|
||||
topic: function() {
|
||||
var t = synchronousTask();
|
||||
queue(1)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.defer(t)
|
||||
.awaitAll(this.callback);
|
||||
},
|
||||
"does not fail": function(error, results) {
|
||||
assert.isNull(error);
|
||||
},
|
||||
"executes all tasks in series": function(error, results) {
|
||||
assert.deepEqual(results, [
|
||||
{active: 1, index: 0},
|
||||
{active: 1, index: 1},
|
||||
{active: 1, index: 2},
|
||||
{active: 1, index: 3},
|
||||
{active: 1, index: 4},
|
||||
{active: 1, index: 5},
|
||||
{active: 1, index: 6},
|
||||
{active: 1, index: 7},
|
||||
{active: 1, index: 8},
|
||||
{active: 1, index: 9}
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
suite.export(module);
|
||||
|
||||
function asynchronousTask(counter) {
|
||||
var active = 0;
|
||||
|
||||
if (!counter) counter = {scheduled: 0};
|
||||
|
||||
return function(callback) {
|
||||
var index = counter.scheduled++;
|
||||
++active;
|
||||
process.nextTick(function() {
|
||||
try {
|
||||
callback(null, {active: active, index: index});
|
||||
} finally {
|
||||
--active;
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
function synchronousTask(counter) {
|
||||
var active = 0;
|
||||
|
||||
if (!counter) counter = {scheduled: 0};
|
||||
|
||||
return function(callback) {
|
||||
try {
|
||||
callback(null, {active: ++active, index: counter.scheduled++});
|
||||
} finally {
|
||||
--active;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function deferredSynchronousTask(counter) {
|
||||
var active = 0, deferrals = [];
|
||||
|
||||
if (!counter) counter = {scheduled: 0};
|
||||
|
||||
function task(callback) {
|
||||
if (deferrals) return deferrals.push({callback: callback, index: counter.scheduled++});
|
||||
try {
|
||||
callback(null, {active: ++active, index: counter.scheduled++});
|
||||
} finally {
|
||||
--active;
|
||||
}
|
||||
}
|
||||
|
||||
task.finish = function() {
|
||||
var deferrals_ = deferrals.slice();
|
||||
deferrals = null;
|
||||
deferrals_.forEach(function(deferral) {
|
||||
try {
|
||||
deferral.callback(null, {active: ++active, index: deferral.index});
|
||||
} finally {
|
||||
--active;
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return task;
|
||||
}
|
24
src/bower_components/K4D3/lib/requirejs/.bower.json
vendored
Normal file
24
src/bower_components/K4D3/lib/requirejs/.bower.json
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "requirejs",
|
||||
"version": "2.1.11",
|
||||
"homepage": "http://requirejs.org",
|
||||
"authors": [
|
||||
"jrburke.com"
|
||||
],
|
||||
"description": "A file and module loader for JavaScript",
|
||||
"main": "require.js",
|
||||
"keywords": [
|
||||
"AMD"
|
||||
],
|
||||
"license": "new BSD, and MIT",
|
||||
"_release": "2.1.11",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "2.1.11",
|
||||
"commit": "fc97e49f1ec9fb2f204bef2b60ed21a32d6a2e05"
|
||||
},
|
||||
"_source": "git://github.com/jrburke/requirejs-bower.git",
|
||||
"_target": "~2.1.11",
|
||||
"_originalSource": "requirejs",
|
||||
"_direct": true
|
||||
}
|
30
src/bower_components/K4D3/lib/topojson/.bower.json
vendored
Normal file
30
src/bower_components/K4D3/lib/topojson/.bower.json
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
{
|
||||
"name": "topojson",
|
||||
"version": "1.4.8",
|
||||
"main": "topojson.js",
|
||||
"scripts": [
|
||||
"topojson.js"
|
||||
],
|
||||
"ignore": [
|
||||
".DS_Store",
|
||||
".git",
|
||||
"Makefile",
|
||||
"bin",
|
||||
"examples",
|
||||
"index.js",
|
||||
"lib",
|
||||
"node_modules",
|
||||
"package.json",
|
||||
"test"
|
||||
],
|
||||
"homepage": "https://github.com/mbostock/topojson",
|
||||
"_release": "1.4.8",
|
||||
"_resolution": {
|
||||
"type": "version",
|
||||
"tag": "v1.4.8",
|
||||
"commit": "0148855246c1234765048ef91e52392d05115476"
|
||||
},
|
||||
"_source": "git://github.com/mbostock/topojson.git",
|
||||
"_target": "~1.4.6",
|
||||
"_originalSource": "topojson"
|
||||
}
|
3
src/bower_components/K4D3/lib/topojson/.gitignore
vendored
Normal file
3
src/bower_components/K4D3/lib/topojson/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
.DS_Store
|
||||
topojson.min.js
|
||||
node_modules
|
2
src/bower_components/K4D3/lib/topojson/.npmignore
vendored
Normal file
2
src/bower_components/K4D3/lib/topojson/.npmignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
.DS_Store
|
||||
node_modules
|
3
src/bower_components/K4D3/package.json
vendored
3
src/bower_components/K4D3/package.json
vendored
|
@ -51,7 +51,8 @@
|
|||
"grunt-karma": "~0.6.2",
|
||||
"karma-junit-reporter": "~0.2.1",
|
||||
"karma-commonjs": "0.0.6",
|
||||
"karma-safari-launcher": "~0.1.1"
|
||||
"karma-safari-launcher": "~0.1.1",
|
||||
"grunt-contrib-requirejs": "~0.4.3"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
|
|
20
src/bower_components/K4D3/src/core.js
vendored
20
src/bower_components/K4D3/src/core.js
vendored
|
@ -5,15 +5,21 @@
|
|||
* Returns the charting function.
|
||||
*/
|
||||
|
||||
k4.Chart = function(elem, args) {
|
||||
'use strict';
|
||||
define(function(require) {
|
||||
"use strict";
|
||||
|
||||
if (typeof(k4[args.type]) !== 'function') { throw args.type + " is not a supported k4 function."; }
|
||||
var histogram = require('bower_components/K4D3/src/modules/histogram');
|
||||
|
||||
var type = args.type,
|
||||
chartFunc = k4[type](elem, args);
|
||||
return function(elem, args) {
|
||||
var type = args.type,
|
||||
charts = {
|
||||
'histogram': histogram
|
||||
};
|
||||
|
||||
return chartFunc;
|
||||
};
|
||||
if (typeof(charts[type]) !== 'function') { throw type + " is not a supported k4 function."; }
|
||||
|
||||
var chartFunc = charts[type](elem, args);
|
||||
|
||||
return chartFunc;
|
||||
};
|
||||
});
|
||||
|
|
2
src/bower_components/K4D3/src/end.js
vendored
2
src/bower_components/K4D3/src/end.js
vendored
|
@ -1,2 +0,0 @@
|
|||
return k4;
|
||||
}));
|
21
src/bower_components/K4D3/src/index.js
vendored
Normal file
21
src/bower_components/K4D3/src/index.js
vendored
Normal file
|
@ -0,0 +1,21 @@
|
|||
(function(root, factory) {
|
||||
'use strict';
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.k4 = factory();
|
||||
}
|
||||
}(this, function(require) {
|
||||
var k4 = {
|
||||
version: '0.0.0',
|
||||
tooltip: require('./bower_components/K4D3/src/tooltip'),
|
||||
legend: require('./bower_components/K4D3/src/legend'),
|
||||
Chart: require('./bower_components/K4D3/src/core'),
|
||||
histogram: require('./bower_components/K4D3/src/modules/histogram')
|
||||
};
|
||||
|
||||
return k4;
|
||||
}));
|
123
src/bower_components/K4D3/src/legend.js
vendored
123
src/bower_components/K4D3/src/legend.js
vendored
|
@ -1,64 +1,71 @@
|
|||
k4.legend = function(g) {
|
||||
'use strict';
|
||||
define(function(require) {
|
||||
"use strict";
|
||||
|
||||
g.each(function() {
|
||||
var g = d3.select(this),
|
||||
items = {},
|
||||
svg = d3.select(g.property("nearestViewportElement")),
|
||||
legendPadding = g.attr("data-style-padding") || 5,
|
||||
lb = g.selectAll(".legend-box").data([true]),
|
||||
li = g.selectAll(".legend-items").data([true]),
|
||||
lbbox;
|
||||
var d3 = require('d3');
|
||||
|
||||
lb.enter().append("rect").classed("legend-box",true);
|
||||
li.enter().append("g").classed("legend-items",true);
|
||||
return function(g) {
|
||||
'use strict';
|
||||
|
||||
svg.selectAll("[data-legend]").each(function() {
|
||||
var self = d3.select(this);
|
||||
items[self.attr("data-legend")] = {
|
||||
pos : self.attr("data-legend-pos") || this.getBBox().y,
|
||||
color : self.attr("data-legend-color") !== null ? self.attr("data-legend-color") :
|
||||
self.style("fill") !== 'none' ? self.style("fill") : self.style("stroke")
|
||||
};
|
||||
g.each(function() {
|
||||
var g = d3.select(this),
|
||||
items = {},
|
||||
svg = d3.select(g.property("nearestViewportElement")),
|
||||
legendPadding = g.attr("data-style-padding") || 5,
|
||||
lb = g.selectAll(".legend-box").data([true]),
|
||||
li = g.selectAll(".legend-items").data([true]),
|
||||
lbbox;
|
||||
|
||||
lb.enter().append("rect").classed("legend-box",true);
|
||||
li.enter().append("g").classed("legend-items",true);
|
||||
|
||||
svg.selectAll("[data-legend]").each(function() {
|
||||
var self = d3.select(this);
|
||||
items[self.attr("data-legend")] = {
|
||||
pos : self.attr("data-legend-pos") || this.getBBox().y,
|
||||
color : self.attr("data-legend-color") !== null ? self.attr("data-legend-color") :
|
||||
self.style("fill") !== 'none' ? self.style("fill") : self.style("stroke")
|
||||
};
|
||||
});
|
||||
|
||||
items = d3.entries(items).sort(function(a, b) { return a.value.pos - b.value.pos; });
|
||||
|
||||
/*
|
||||
li.selectAll('div')
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("div"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-div");
|
||||
*/
|
||||
|
||||
li.selectAll("text")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("text"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-text")
|
||||
.attr("x", "0.7em")
|
||||
.attr("y", function(d, i) { return i + "em"; })
|
||||
.text(function(d) { return d.key; });
|
||||
|
||||
li.selectAll("circle")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("circle"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-circle")
|
||||
.attr("cx", 0)
|
||||
.attr("cy", function(d, i) { return i - 0.25 + "em"; })
|
||||
.attr("r", "0.4em")
|
||||
.style("fill", function(d) { return d.value.color; });
|
||||
|
||||
// Reposition and resize the box
|
||||
lbbox = li[0][0].getBBox();
|
||||
|
||||
lb.attr("x", (lbbox.x - legendPadding))
|
||||
.attr("y", (lbbox.y - legendPadding))
|
||||
.attr("height", (lbbox.height + 2 * legendPadding))
|
||||
.attr("width", (lbbox.width + 2 * legendPadding));
|
||||
});
|
||||
|
||||
items = d3.entries(items).sort(function(a, b) { return a.value.pos - b.value.pos; });
|
||||
return g;
|
||||
};
|
||||
|
||||
/*
|
||||
li.selectAll('div')
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("div"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-div");
|
||||
*/
|
||||
|
||||
li.selectAll("text")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("text"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-text")
|
||||
.attr("x", "0.7em")
|
||||
.attr("y", function(d, i) { return i + "em"; })
|
||||
.text(function(d) { return d.key; });
|
||||
|
||||
li.selectAll("circle")
|
||||
.data(items, function(d) { return d.key; })
|
||||
.call(function(d) { d.enter().append("circle"); })
|
||||
.call(function(d) { d.exit().remove(); })
|
||||
.attr("class", "legend-circle")
|
||||
.attr("cx", 0)
|
||||
.attr("cy", function(d, i) { return i - 0.25 + "em"; })
|
||||
.attr("r", "0.4em")
|
||||
.style("fill", function(d) { return d.value.color; });
|
||||
|
||||
// Reposition and resize the box
|
||||
lbbox = li[0][0].getBBox();
|
||||
|
||||
lb.attr("x", (lbbox.x - legendPadding))
|
||||
.attr("y", (lbbox.y - legendPadding))
|
||||
.attr("height", (lbbox.height + 2 * legendPadding))
|
||||
.attr("width", (lbbox.width + 2 * legendPadding));
|
||||
});
|
||||
|
||||
return g;
|
||||
};
|
||||
});
|
||||
|
|
566
src/bower_components/K4D3/src/modules/histogram.js
vendored
566
src/bower_components/K4D3/src/modules/histogram.js
vendored
|
@ -1,311 +1,337 @@
|
|||
|
||||
k4.histogram = function(elem, args) {
|
||||
define(function(require) {
|
||||
'use strict';
|
||||
var tooltip = require('bower_components/K4D3/src/tooltip'),
|
||||
d3 = require('d3');
|
||||
|
||||
var chart = {},
|
||||
return function(elem, args) {
|
||||
|
||||
/* ********** Sizing DOM Elements ************* */
|
||||
// accessing the element width/height
|
||||
elemWidth = parseInt(d3.select(elem).style("width"), 10),
|
||||
elemHeight = parseInt(d3.select(elem).style("padding-bottom"), 10),
|
||||
// number of rows
|
||||
numRows = data.rows.length,
|
||||
// number of charts
|
||||
n = data.rows[0].columns.length,
|
||||
// number of layers per chart
|
||||
m = data.rows[0].columns[0].layers.length,
|
||||
// row width
|
||||
outerWidth = elemWidth,
|
||||
// row height
|
||||
outerHeight = elemHeight / numRows,
|
||||
margin = {
|
||||
top: outerHeight * 0.05,
|
||||
right: outerWidth * 0.01,
|
||||
bottom: outerHeight * 0.15,
|
||||
left: outerWidth * 0.05
|
||||
},
|
||||
// svg width/height
|
||||
width = outerWidth/n - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom,
|
||||
/* ************************************************** */
|
||||
var chart = {},
|
||||
elemWidth = parseInt(d3.select(elem.parentNode).style('width'), 10),
|
||||
elemHeight = d3.select(elem).attr('height'), //.80 * window.innerHeight, //parseInt(d3.select(elem.parentNode).style('height'), 10) < 100 ? 400 : parseInt(d3.select(elem.parentNode).style('height'), 10),
|
||||
stacktype = args.stacktype || 'zero', // 'zero', 'expand', 'group'
|
||||
yGroup = args.yGroup || false,
|
||||
colors = args.color,
|
||||
//displayToolTip = args.displayToolTip || true,
|
||||
numRows, margin, svg, g, layer, n, m, width, height, outerWidth, outerHeight, keys, stack, toolTip,
|
||||
xScale, yScale, xAxis, yAxis, yStackMax, yGroupMax, color;
|
||||
|
||||
/* ************* Data manipulation **************** */
|
||||
// pulls out the x-axis key values
|
||||
keys = data.rows[0].columns[0].layers[0].values.map(function(item) { return item.x; }),
|
||||
// defines the stack.offset()
|
||||
stacktype = args.stacktype || 'zero', // 'zero', 'expand', 'group'
|
||||
stack = d3.layout.stack().offset(stacktype).values(function(d) { return d.values; }),
|
||||
// calculates the y-axis max value for all charts, i.e. grouped and stacked
|
||||
yGroup = args.yGroup || false,
|
||||
yGroupMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y;
|
||||
chart.render = function(data) {
|
||||
|
||||
/* ********** Sizing DOM Elements ************* */
|
||||
// number of rows
|
||||
numRows = data.rows.length,
|
||||
// number of charts
|
||||
n = data.rows[0].columns.length,
|
||||
// number of layers per chart
|
||||
m = data.rows[0].columns[0].layers.length,
|
||||
// row width
|
||||
outerWidth = elemWidth,
|
||||
// row height
|
||||
outerHeight = elemHeight / numRows,
|
||||
margin = {
|
||||
top: outerHeight * 0.05,
|
||||
right: outerWidth * 0.01,
|
||||
bottom: outerHeight * 0.15,
|
||||
left: outerWidth * 0.05
|
||||
},
|
||||
// svg width/height
|
||||
width = outerWidth/n - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom,
|
||||
/* ************************************************** */
|
||||
|
||||
/* ************* Data manipulation **************** */
|
||||
// pulls out the x-axis key values
|
||||
keys = data.rows[0].columns[0].layers[0].values.map(function(item) { return item.x; }),
|
||||
stack = d3.layout.stack().offset(stacktype).values(function(d) { return d.values; }),
|
||||
yGroupMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
})),
|
||||
yStackMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y0 + d.y;
|
||||
})),
|
||||
yStackMax = d3.max(data.rows.map(function(data) {
|
||||
return d3.max(data.columns, function(col) {
|
||||
return d3.max(stack(col.layers), function(layer) {
|
||||
return d3.max(layer.values, function(d) {
|
||||
return d.y0 + d.y;
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
})),
|
||||
/* **************************************************** */
|
||||
})),
|
||||
/* **************************************************** */
|
||||
|
||||
/* *************** D3 parameters ********************* */
|
||||
xScale = d3.scale.ordinal().domain(keys).rangeRoundBands([0, width], 0.1),
|
||||
yScale = d3.scale.linear().range([height, 0]).nice(),
|
||||
xAxis = d3.svg.axis().scale(xScale).ticks(6).tickSize(3, 0).tickPadding(6).orient('bottom'),
|
||||
yAxis = d3.svg.axis().scale(yScale).ticks(6).tickSize(-(width), 0).tickPadding(4).orient('left'),
|
||||
color = d3.scale.linear().domain([0, m - 1]).range(args.color) ||
|
||||
d3.scale.linear().domain([0, m - 1]).range(['#e24700', '#f9e593']),
|
||||
toolTip = k4.tooltip().attr('class', 'k4-tip').html(function(d) {
|
||||
if (d.y < 1) { return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y.toFixed(2) * 100 + '%</span>'; }
|
||||
return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y + '</span>';
|
||||
}).offset([-12, 0]),
|
||||
svg, g, layer;
|
||||
/* ******************************************************** */
|
||||
/* *************** D3 parameters ********************* */
|
||||
xScale = d3.scale.ordinal().domain(keys).rangeRoundBands([0, width], 0.1),
|
||||
yScale = d3.scale.linear().range([height, 0]).nice(),
|
||||
xAxis = d3.svg.axis().scale(xScale).tickSize(3, 0).tickPadding(6).tickValues(xScale.domain().filter(function(d, i) { return (i % 5); })).orient('bottom'),
|
||||
yAxis = d3.svg.axis().scale(yScale).ticks(6).tickSize(-(width), 0).tickPadding(4).orient('left'),
|
||||
color = d3.scale.linear().domain([0, m - 1]).range(['#e24700', '#f9e593']),
|
||||
/*
|
||||
toolTip = !displayToolTip ? "undefined" : tooltip().attr('class', 'k4-tip').html(function(d) {
|
||||
if (d.y < 1) { return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y.toFixed(2) * 100 + '%</span>'; }
|
||||
return '<span>x: ' + d.x + '</span><br><span>y: ' + d.y + '</span>';
|
||||
}).offset([-12, 0]);
|
||||
*/
|
||||
/* ******************************************************** */
|
||||
|
||||
chart.render = function(data) {
|
||||
// Removing items off the element
|
||||
d3.select(elem).selectAll('*').remove();
|
||||
|
||||
// append svg(s)
|
||||
svg = getSvg(elem, data);
|
||||
// append svg(s)
|
||||
svg = getSvg(elem, data);
|
||||
svg.attr('width', outerWidth/n).attr('height', outerHeight);
|
||||
|
||||
// render each chart
|
||||
g = svg.append('g')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||
.each(function(d) {
|
||||
// render each chart
|
||||
g = svg.append('g')
|
||||
.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')')
|
||||
.each(function(d) {
|
||||
var g = d3.select(this);
|
||||
|
||||
var yMax = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y;
|
||||
});
|
||||
});
|
||||
|
||||
var yStack = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y0 + e.y;
|
||||
});
|
||||
});
|
||||
|
||||
// Change y/xScale domain based on stacktype
|
||||
if (stacktype === 'expand') { yScale.domain([0, 1]); }
|
||||
else if (stacktype === 'zero') {
|
||||
if (yGroup) {
|
||||
yScale.domain([0, yStackMax]).nice();
|
||||
} else {
|
||||
yScale.domain([0, yStack]).nice();
|
||||
}
|
||||
}
|
||||
else if (stacktype === 'group') {
|
||||
if (yGroup) {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yGroupMax]).nice();
|
||||
} else {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yMax]).nice();
|
||||
}
|
||||
}
|
||||
|
||||
// background rect
|
||||
g.append('g')
|
||||
.append('rect')
|
||||
.attr('class', 'bkgd')
|
||||
.style('fill', '#fff')
|
||||
.style('opacity', 0.35)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
|
||||
// x axis
|
||||
g.append('g')
|
||||
.attr('class', 'x axis')
|
||||
.attr('transform', 'translate(0,' + height + ')')
|
||||
.style('stroke-width', 0.5)
|
||||
.call(xAxis);
|
||||
|
||||
// y axis
|
||||
g.append('g')
|
||||
.attr('class', 'y axis')
|
||||
.style('stroke-width', 0.5)
|
||||
.call(yAxis);
|
||||
|
||||
// layer of bars
|
||||
layer = g.selectAll('.layer')
|
||||
.data(function(d) { return stack(d.layers); })
|
||||
.enter().append('g')
|
||||
.attr('class', 'layer')
|
||||
.style('fill', function(d, i) { return color(i); });
|
||||
|
||||
//Enter
|
||||
// bars for stack, expand, group
|
||||
layer.selectAll('rect')
|
||||
.data(function(d) { return d.values; })
|
||||
.enter().append('rect');
|
||||
|
||||
// Update
|
||||
if (stacktype === 'group') {
|
||||
layer.selectAll('rect')
|
||||
.attr('x', function(d, i, j) { return xScale(d.x) + xScale.rangeBand() / m * j; })
|
||||
.attr('width', xScale.rangeBand() / m)
|
||||
.attr('y', function(d) { return yScale(d.y); })
|
||||
.attr('height', function(d) { return height - yScale(d.y); })
|
||||
//.on('mouseover', toolTip.show)
|
||||
//.on('mouseout', toolTip.hide);
|
||||
} else {
|
||||
layer.selectAll('rect')
|
||||
.attr('width', xScale.rangeBand())
|
||||
.attr('x', function(d) { return xScale(d.x); })
|
||||
.attr('y', function(d) { return yScale(d.y0 + d.y); })
|
||||
.attr('height', function(d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
|
||||
//.on('mouseover', toolTip.show)
|
||||
//.on('mouseout', toolTip.hide);
|
||||
}
|
||||
|
||||
//Exit
|
||||
layer.selectAll('rect').data(function(d) { return d.values; }).exit().remove();
|
||||
|
||||
});
|
||||
|
||||
// Window resize
|
||||
d3.select(window).on('resize', resize);
|
||||
|
||||
// k4 tooltip function
|
||||
//if (displayToolTip) { g.call(toolTip); }
|
||||
|
||||
return svg;
|
||||
};
|
||||
|
||||
// append layout divs to elem and bind layout data
|
||||
function getSvg(elem, data) {
|
||||
var rows, cols, svg;
|
||||
|
||||
rows = d3.select(elem).selectAll('div')
|
||||
.data(data.rows)
|
||||
.enter().append('div')
|
||||
.attr('class', function(d, i) { return 'row r' + i; })
|
||||
.style('display', 'block');
|
||||
|
||||
cols = rows.selectAll('div')
|
||||
.data(function(d) { return d.columns; })
|
||||
.enter().append('div')
|
||||
.attr('class', function(d,i){ return 'col c' + i; })
|
||||
.style('display', 'inline-block');
|
||||
|
||||
svg = cols.append('svg');
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
function resize() {
|
||||
/* Update graph using new width and height */
|
||||
var elemWidth = parseInt(d3.select(elem.parentNode).style('width'), 10),
|
||||
elemHeight = d3.select(elem).attr('height'), //.80 * window.innerHeight, //parseInt(d3.select(elem.parentNode).style('height'), 10),
|
||||
outerWidth = elemWidth / n,
|
||||
outerHeight = elemHeight / numRows,
|
||||
width = outerWidth - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom;
|
||||
|
||||
d3.select('.row r').style('width', elemWidth).style('height', outerHeight);
|
||||
d3.select('.col c').style ('width', outerWidth).style('height', outerHeight);
|
||||
svg.attr('width', outerWidth).attr('height', outerHeight);
|
||||
|
||||
g.each(function(d) {
|
||||
var g = d3.select(this);
|
||||
|
||||
var yMax = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y;
|
||||
});
|
||||
});
|
||||
console.log(yMax);
|
||||
console.log(yGroupMax);
|
||||
|
||||
var yStack = d3.max(d.layers, function(d) {
|
||||
return d3.max(d.values, function(e) {
|
||||
return e.y0 + e.y;
|
||||
});
|
||||
});
|
||||
var yMax = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y; }); });
|
||||
var yStack = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y0 + e.y; }); });
|
||||
|
||||
// Change y/xScale domain based on stacktype
|
||||
if (stacktype === 'expand') { yScale.domain([0, 1]); }
|
||||
|
||||
if (stacktype === 'group' && yGroup) {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yGroupMax]);
|
||||
} else {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yMax]);
|
||||
else if (stacktype === 'zero') {
|
||||
if (yGroup) {
|
||||
yScale.domain([0, yStackMax]).nice();
|
||||
} else {
|
||||
yScale.domain([0, yStack]).nice();
|
||||
}
|
||||
}
|
||||
else if (stacktype === 'group') {
|
||||
if (yGroup) {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yGroupMax]).nice();
|
||||
} else {
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
yScale.domain([0, yMax]).nice();
|
||||
}
|
||||
}
|
||||
|
||||
if (stacktype === 'zero' && yGroup) {
|
||||
yScale.domain([0, yStackMax]);
|
||||
/* Update the range of the scale with new width/height */
|
||||
xScale.rangeRoundBands([0, width], 0.1);
|
||||
yScale.range([height, 0]).nice();
|
||||
xAxis.tickValues(xScale.domain().filter(function(d, i) { return (i % Math.min(width/80, 5)); }));
|
||||
//xAxis.ticks(Math.max(width/50, 2));
|
||||
yAxis.ticks(Math.max(height/20, 2)).tickSize(-(width), 0);
|
||||
|
||||
if (width < 300 && height < 80) {
|
||||
g.select('.x.axis').style('display', 'none');
|
||||
} else {
|
||||
yScale.domain([0, yStack]);
|
||||
g.select('.x.axis').style('display', 'initial');
|
||||
g.select('.y.axis').style('display', 'initial');
|
||||
}
|
||||
|
||||
// background rect
|
||||
g.append('g')
|
||||
.append('rect')
|
||||
.attr('class', 'bkgd')
|
||||
.style('fill', '#fff')
|
||||
.style('opacity', 0.35)
|
||||
.attr('width', width)
|
||||
.attr('height', height);
|
||||
g.attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');
|
||||
g.selectAll('.bkgd').attr('width', width).attr('height', height);
|
||||
|
||||
// x axis
|
||||
g.append('g')
|
||||
.attr('class', 'x axis')
|
||||
/* Update the axis with the new scale */
|
||||
g.select('.x.axis')
|
||||
.attr('transform', 'translate(0,' + height + ')')
|
||||
.style('stroke-width', 0.5)
|
||||
.call(xAxis);
|
||||
|
||||
// y axis
|
||||
g.append('g')
|
||||
.attr('class', 'y axis')
|
||||
.style('stroke-width', 0.5)
|
||||
g.select('.y.axis')
|
||||
.call(yAxis);
|
||||
|
||||
// layer of bars
|
||||
layer = g.selectAll('.layer')
|
||||
.data(function(d) { return stack(d.layers); })
|
||||
.enter().append('g')
|
||||
.attr('class', 'layer')
|
||||
.style('fill', function(d, i) { return color(i); });
|
||||
|
||||
//Enter
|
||||
// bars for stack, expand, group
|
||||
layer.selectAll('rect')
|
||||
.data(function(d) { return d.values; })
|
||||
.enter().append('rect');
|
||||
|
||||
// Update
|
||||
/* Force D3 to recalculate and update the line */
|
||||
if (stacktype === 'group') {
|
||||
layer.selectAll('rect')
|
||||
.attr('x', function(d, i, j) { return xScale(d.x) + xScale.rangeBand() / m * j; })
|
||||
g.selectAll('.layer').selectAll('rect')
|
||||
.attr( 'x', function (d, i, j) { return xScale(d.x) + xScale.rangeBand() / m * j; })
|
||||
.attr('width', xScale.rangeBand() / m)
|
||||
.attr('y', function(d) { return yScale(d.y); })
|
||||
.attr('height', function(d) { return height - yScale(d.y); })
|
||||
.on('mouseover', toolTip.show)
|
||||
.on('mouseout', toolTip.hide);
|
||||
.attr( 'y', function (d) { return yScale(d.y); })
|
||||
.attr( 'height', function (d) { return height - yScale(d.y); });
|
||||
} else {
|
||||
layer.selectAll('rect')
|
||||
g.selectAll('.layer').selectAll('rect')
|
||||
.attr('width', xScale.rangeBand())
|
||||
.attr('x', function(d) { return xScale(d.x); })
|
||||
.attr('y', function(d) { return yScale(d.y0 + d.y); })
|
||||
.attr('height', function(d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
|
||||
.on('mouseover', toolTip.show)
|
||||
.on('mouseout', toolTip.hide);
|
||||
.attr('y', function(d) { return yScale(d.y0 + d.y); });
|
||||
}
|
||||
|
||||
//Exit
|
||||
layer.selectAll('rect').data(function(d) { return d.values; }).exit().remove();
|
||||
});
|
||||
}
|
||||
|
||||
// Window resize
|
||||
d3.select(window).on('resize', resize);
|
||||
chart.margin = function() {
|
||||
if (!args.margin) { return margin; }
|
||||
margin.top = typeof args.margin.top !== 'undefined' ? args.margin.top : margin.top;
|
||||
margin.right = typeof args.margin.right !== 'undefined' ? args.margin.right : margin.right;
|
||||
margin.bottom = typeof args.margin.bottom !== 'undefined' ? args.margin.bottom : margin.bottom;
|
||||
margin.left = typeof args.margin.left !== 'undefined' ? args.margin.left : margin.left;
|
||||
return margin;
|
||||
};
|
||||
|
||||
// k4 tooltip function
|
||||
g.call(toolTip);
|
||||
chart.type = function(_) {
|
||||
if (!arguments.length) { return stacktype; }
|
||||
stacktype = _;
|
||||
return chart;
|
||||
};
|
||||
|
||||
return svg;
|
||||
/*
|
||||
chart.tooltip = function(_) {
|
||||
if (!arguments.length) { return tooltip; }
|
||||
tooltip = _;
|
||||
return chart;
|
||||
}
|
||||
*/
|
||||
|
||||
chart.width = function() {
|
||||
if (!args.width) { return width; }
|
||||
width = args.width;
|
||||
return width;
|
||||
};
|
||||
|
||||
chart.height = function() {
|
||||
if (!args.height) { return height; }
|
||||
height = args.height;
|
||||
return height;
|
||||
};
|
||||
|
||||
chart.color = function() {
|
||||
if (!args.color) { return color; }
|
||||
color = args.color;
|
||||
return color;
|
||||
};
|
||||
|
||||
return chart;
|
||||
};
|
||||
|
||||
// append layout divs to elem and bind layout data
|
||||
function getSvg(elem, data) {
|
||||
var rows, cols, svg;
|
||||
|
||||
rows = d3.select(elem).selectAll('div')
|
||||
.data(data.rows)
|
||||
.enter().append('div')
|
||||
.attr('class', function(d, i) { return 'row r' + i; });
|
||||
|
||||
cols = rows.selectAll('div')
|
||||
.data(function(d) { return d.columns; })
|
||||
.enter().append('div')
|
||||
.attr('class', function(d,i){ return 'col c' + i; });
|
||||
|
||||
svg = cols.append('svg')
|
||||
.attr("width", outerWidth/n)
|
||||
.attr("height", outerHeight);
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
function resize() {
|
||||
/* Update graph using new width and height */
|
||||
var elemWidth = parseInt(d3.select(elem).style("width"), 10),
|
||||
elemHeight = parseInt(d3.select(elem).style("padding-bottom"), 10),
|
||||
outerWidth = elemWidth / n,
|
||||
outerHeight = elemHeight / numRows,
|
||||
width = outerWidth - margin.left - margin.right,
|
||||
height = outerHeight - margin.top - margin.bottom;
|
||||
|
||||
d3.select(".row r").style("width", elemWidth).style("height", outerHeight);
|
||||
d3.select(".col c").style ("width", outerWidth).style("height", outerHeight);
|
||||
svg.attr("width", outerWidth).attr("height", outerHeight);
|
||||
|
||||
g.each(function(d) {
|
||||
var g = d3.select(this);
|
||||
|
||||
var yMax = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y; }); });
|
||||
var yStack = d3.max(d.layers, function(d) { return d3.max(d.values, function(e) { return e.y0 + e.y; }); });
|
||||
|
||||
// Change y/xScale domain based on stacktype
|
||||
// Change y/xScale domain based on stacktype
|
||||
if (stacktype === 'expand') { yScale.domain([0, 1]); }
|
||||
|
||||
if (stacktype === 'group' && yGroup) {
|
||||
yScale.domain([0, yGroupMax]);
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
} else {
|
||||
yScale.domain([0, yMax]);
|
||||
xScale.rangeRoundBands([0, width], 0.2);
|
||||
}
|
||||
|
||||
if (stacktype === 'zero' && yGroup) {
|
||||
yScale.domain([0, yStackMax]);
|
||||
} else {
|
||||
yScale.domain([0, yStack]);
|
||||
}
|
||||
|
||||
/* Update the range of the scale with new width/height */
|
||||
if (stacktype === "group") { xScale.rangeRoundBands([0, width], 0.4); }
|
||||
else { xScale.rangeRoundBands([0, width], 0.1); }
|
||||
yScale.range([height, 0]).nice();
|
||||
xAxis.ticks(Math.max(width/50, 2));
|
||||
yAxis.ticks(Math.max(height/20, 2)).tickSize(-(width), 0);
|
||||
|
||||
if (width < 300 && height < 80) {
|
||||
g.select('.x.axis').style('display', 'none');
|
||||
} else {
|
||||
g.select('.x.axis').style('display', 'initial');
|
||||
g.select('.y.axis').style('display', 'initial');
|
||||
}
|
||||
|
||||
g.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
g.selectAll(".bkgd").attr("width", width).attr("height", height);
|
||||
|
||||
/* Update the axis with the new scale */
|
||||
g.select('.x.axis')
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis);
|
||||
|
||||
g.select('.y.axis')
|
||||
.call(yAxis);
|
||||
|
||||
/* Force D3 to recalculate and update the line */
|
||||
if (stacktype === "group") {
|
||||
layer.selectAll("rect")
|
||||
.attr( "x", function (d, i, j) { return xScale(d.x) + xScale.rangeBand() / n * j; })
|
||||
.attr("width", xScale.rangeBand() / n)
|
||||
.attr( "y", function (d) { return yScale(d.y); })
|
||||
.attr( "height", function (d) { return height - yScale(d.y); });
|
||||
}
|
||||
|
||||
g.selectAll('rect')
|
||||
.attr("width", xScale.rangeBand())
|
||||
.attr("x", function(d) { return xScale(d.x); })
|
||||
.attr("height", function(d) { return yScale(d.y0) - yScale(d.y0 + d.y); })
|
||||
.attr("y", function(d) { return yScale(d.y0 + d.y); });
|
||||
});
|
||||
}
|
||||
|
||||
chart.margin = function() {
|
||||
if (!args.margin) { return margin; }
|
||||
margin.top = typeof args.margin.top !== 'undefined' ? args.margin.top : margin.top;
|
||||
margin.right = typeof args.margin.right !== 'undefined' ? args.margin.right : margin.right;
|
||||
margin.bottom = typeof args.margin.bottom !== 'undefined' ? args.margin.bottom : margin.bottom;
|
||||
margin.left = typeof args.margin.left !== 'undefined' ? args.margin.left : margin.left;
|
||||
return margin;
|
||||
};
|
||||
|
||||
chart.width = function() {
|
||||
if (!args.width) { return width; }
|
||||
width = args.width;
|
||||
return width;
|
||||
};
|
||||
|
||||
chart.height = function() {
|
||||
if (!args.height) { return height; }
|
||||
height = args.height;
|
||||
return height;
|
||||
};
|
||||
|
||||
chart.color = function() {
|
||||
if (!args.color) { return color; }
|
||||
color = args.color;
|
||||
return color;
|
||||
};
|
||||
|
||||
return chart;
|
||||
};
|
||||
});
|
||||
|
|
13
src/bower_components/K4D3/src/start.js
vendored
13
src/bower_components/K4D3/src/start.js
vendored
|
@ -1,13 +0,0 @@
|
|||
(function(root, factory) {
|
||||
'use strict';
|
||||
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define(factory);
|
||||
} else if (typeof module === 'object' && module.exports) {
|
||||
module.exports = factory();
|
||||
} else {
|
||||
root.k4 = factory();
|
||||
}
|
||||
}(this, function() {
|
||||
var k4 = { version: '0.0.0' };
|
||||
|
533
src/bower_components/K4D3/src/tooltip.js
vendored
533
src/bower_components/K4D3/src/tooltip.js
vendored
|
@ -1,278 +1,285 @@
|
|||
k4.tooltip = function() {
|
||||
'use strict';
|
||||
define(function(require) {
|
||||
"use strict";
|
||||
|
||||
// Based on Justin Palmer's d3.tip() function
|
||||
var d3 = require('d3');
|
||||
|
||||
var direction = d3_tip_direction,
|
||||
offset = d3_tip_offset,
|
||||
html = d3_tip_html,
|
||||
node = initNode(),
|
||||
svg = null,
|
||||
point = null,
|
||||
target = null;
|
||||
return function() {
|
||||
'use strict';
|
||||
|
||||
function tip(vis) {
|
||||
svg = getSVGNode(vis);
|
||||
point = svg.createSVGPoint();
|
||||
document.body.appendChild(node);
|
||||
}
|
||||
// Based on Justin Palmer's d3.tip() function
|
||||
|
||||
// Public - show the tooltip on the screen
|
||||
//
|
||||
// Returns a tip
|
||||
tip.show = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
if(args[args.length - 1] instanceof SVGElement) { target = args.pop(); }
|
||||
var direction = d3_tip_direction,
|
||||
offset = d3_tip_offset,
|
||||
html = d3_tip_html,
|
||||
node = initNode(),
|
||||
svg = null,
|
||||
point = null,
|
||||
target = null;
|
||||
|
||||
var content = html.apply(this, args),
|
||||
poffset = offset.apply(this, args),
|
||||
dir = direction.apply(this, args),
|
||||
nodel = d3.select(node),
|
||||
i = directions.length,
|
||||
coords;
|
||||
function tip(vis) {
|
||||
svg = getSVGNode(vis);
|
||||
point = svg.createSVGPoint();
|
||||
document.body.appendChild(node);
|
||||
}
|
||||
|
||||
nodel.html(content)
|
||||
.style({ opacity: 1, 'pointer-events': 'all' });
|
||||
// Public - show the tooltip on the screen
|
||||
//
|
||||
// Returns a tip
|
||||
tip.show = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
if(args[args.length - 1] instanceof SVGElement) { target = args.pop(); }
|
||||
|
||||
while(i--) nodel.classed(directions[i], false);
|
||||
coords = direction_callbacks.get(dir).apply(this);
|
||||
nodel.classed(dir, true).style({
|
||||
top: (coords.top + poffset[0]) + 'px',
|
||||
left: (coords.left + poffset[1]) + 'px'
|
||||
});
|
||||
var content = html.apply(this, args),
|
||||
poffset = offset.apply(this, args),
|
||||
dir = direction.apply(this, args),
|
||||
nodel = d3.select(node),
|
||||
i = directions.length,
|
||||
coords;
|
||||
|
||||
return tip;
|
||||
};
|
||||
nodel.html(content)
|
||||
.style({ opacity: 1, 'pointer-events': 'all' });
|
||||
|
||||
// Public - hide the tooltip
|
||||
//
|
||||
// Returns a tip
|
||||
tip.hide = function() {
|
||||
var nodel = d3.select(node);
|
||||
nodel.style({ opacity: 0, 'pointer-events': 'none' });
|
||||
return tip;
|
||||
};
|
||||
while(i--) nodel.classed(directions[i], false);
|
||||
coords = direction_callbacks.get(dir).apply(this);
|
||||
nodel.classed(dir, true).style({
|
||||
top: (coords.top + poffset[0]) + 'px',
|
||||
left: (coords.left + poffset[1]) + 'px'
|
||||
});
|
||||
|
||||
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
|
||||
//
|
||||
// n - name of the attribute
|
||||
// v - value of the attribute
|
||||
//
|
||||
// Returns tip or attribute value
|
||||
tip.attr = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).attr(n);
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.attr.apply(d3.select(node), args);
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public - hide the tooltip
|
||||
//
|
||||
// Returns a tip
|
||||
tip.hide = function() {
|
||||
var nodel = d3.select(node);
|
||||
nodel.style({ opacity: 0, 'pointer-events': 'none' });
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Proxy attr calls to the d3 tip container. Sets or gets attribute value.
|
||||
//
|
||||
// n - name of the attribute
|
||||
// v - value of the attribute
|
||||
//
|
||||
// Returns tip or attribute value
|
||||
tip.attr = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).attr(n);
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.attr.apply(d3.select(node), args);
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
|
||||
//
|
||||
// n - name of the property
|
||||
// v - value of the property
|
||||
//
|
||||
// Returns tip or style property value
|
||||
tip.style = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).style(n)
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.style.apply(d3.select(node), args);
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Set or get the direction of the tooltip
|
||||
//
|
||||
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
|
||||
// sw(southwest), ne(northeast) or se(southeast)
|
||||
//
|
||||
// Returns tip or direction
|
||||
tip.direction = function(v) {
|
||||
if (!arguments.length) { return direction; }
|
||||
direction = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Sets or gets the offset of the tip
|
||||
//
|
||||
// v - Array of [x, y] offset
|
||||
//
|
||||
// Returns offset or
|
||||
tip.offset = function(v) {
|
||||
if (!arguments.length) { return offset; }
|
||||
offset = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: sets or gets the html value of the tooltip
|
||||
//
|
||||
// v - String value of the tip
|
||||
//
|
||||
// Returns html value or tip
|
||||
tip.html = function(v) {
|
||||
if (!arguments.length) { return html; }
|
||||
html = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
function d3_tip_direction() { return 'n'; }
|
||||
function d3_tip_offset() { return [0, 0]; }
|
||||
function d3_tip_html() { return ' '; }
|
||||
|
||||
var direction_callbacks = d3.map({
|
||||
n: direction_n,
|
||||
s: direction_s,
|
||||
e: direction_e,
|
||||
w: direction_w,
|
||||
nw: direction_nw,
|
||||
ne: direction_ne,
|
||||
sw: direction_sw,
|
||||
se: direction_se
|
||||
}),
|
||||
|
||||
directions = direction_callbacks.keys();
|
||||
|
||||
function direction_n() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.n.y - node.offsetHeight,
|
||||
left: bbox.n.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_s() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.s.y,
|
||||
left: bbox.s.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_e() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.e.y - node.offsetHeight / 2,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_w() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.w.y - node.offsetHeight / 2,
|
||||
left: bbox.w.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_nw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.nw.y - node.offsetHeight,
|
||||
left: bbox.nw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_ne() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.ne.y - node.offsetHeight,
|
||||
left: bbox.ne.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_sw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.sw.y,
|
||||
left: bbox.sw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_se() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.se.y,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function initNode() {
|
||||
var node = d3.select(document.createElement('div'));
|
||||
node.style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
opacity: 0,
|
||||
'pointer-events': 'none',
|
||||
'box-sizing': 'border-box'
|
||||
});
|
||||
|
||||
return node.node();
|
||||
}
|
||||
|
||||
function getSVGNode(el) {
|
||||
el = el.node();
|
||||
if(el.tagName.toLowerCase() === 'svg') { return el; }
|
||||
|
||||
return el.ownerSVGElement
|
||||
}
|
||||
|
||||
// Private - gets the screen coordinates of a shape
|
||||
//
|
||||
// Given a shape on the screen, will return an SVGPoint for the directions
|
||||
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
|
||||
// sw(southwest).
|
||||
//
|
||||
// +-+-+
|
||||
// | |
|
||||
// + +
|
||||
// | |
|
||||
// +-+-+
|
||||
//
|
||||
// Returns an Object {n, s, e, w, nw, sw, ne, se}
|
||||
function getScreenBBox() {
|
||||
var targetel = target || d3.event.target,
|
||||
bbox = {},
|
||||
matrix = targetel.getScreenCTM(),
|
||||
tbbox = targetel.getBBox(),
|
||||
width = tbbox.width,
|
||||
height = tbbox.height,
|
||||
x = tbbox.x,
|
||||
y = tbbox.y,
|
||||
scrollEl = document.documentElement ? document.documentElement : document.body,
|
||||
scrollTop = scrollEl.scrollTop,
|
||||
scrollLeft = scrollEl.scrollLeft;
|
||||
|
||||
|
||||
point.x = x + scrollLeft;
|
||||
point.y = y + scrollTop;
|
||||
bbox.nw = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.ne = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.se = point.matrixTransform(matrix);
|
||||
point.x -= width;
|
||||
bbox.sw = point.matrixTransform(matrix);
|
||||
point.y -= height / 2;
|
||||
bbox.w = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.e = point.matrixTransform(matrix);
|
||||
point.x -= width / 2;
|
||||
point.y -= height / 2;
|
||||
bbox.n = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.s = point.matrixTransform(matrix);
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Proxy style calls to the d3 tip container. Sets or gets a style value.
|
||||
//
|
||||
// n - name of the property
|
||||
// v - value of the property
|
||||
//
|
||||
// Returns tip or style property value
|
||||
tip.style = function(n, v) {
|
||||
if (arguments.length < 2 && typeof n === 'string') {
|
||||
return d3.select(node).style(n)
|
||||
} else {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
d3.selection.prototype.style.apply(d3.select(node), args);
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Set or get the direction of the tooltip
|
||||
//
|
||||
// v - One of n(north), s(south), e(east), or w(west), nw(northwest),
|
||||
// sw(southwest), ne(northeast) or se(southeast)
|
||||
//
|
||||
// Returns tip or direction
|
||||
tip.direction = function(v) {
|
||||
if (!arguments.length) { return direction; }
|
||||
direction = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: Sets or gets the offset of the tip
|
||||
//
|
||||
// v - Array of [x, y] offset
|
||||
//
|
||||
// Returns offset or
|
||||
tip.offset = function(v) {
|
||||
if (!arguments.length) { return offset; }
|
||||
offset = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
// Public: sets or gets the html value of the tooltip
|
||||
//
|
||||
// v - String value of the tip
|
||||
//
|
||||
// Returns html value or tip
|
||||
tip.html = function(v) {
|
||||
if (!arguments.length) { return html; }
|
||||
html = v === null ? v : d3.functor(v);
|
||||
|
||||
return tip;
|
||||
};
|
||||
|
||||
function d3_tip_direction() { return 'n'; }
|
||||
function d3_tip_offset() { return [0, 0]; }
|
||||
function d3_tip_html() { return ' '; }
|
||||
|
||||
var direction_callbacks = d3.map({
|
||||
n: direction_n,
|
||||
s: direction_s,
|
||||
e: direction_e,
|
||||
w: direction_w,
|
||||
nw: direction_nw,
|
||||
ne: direction_ne,
|
||||
sw: direction_sw,
|
||||
se: direction_se
|
||||
}),
|
||||
|
||||
directions = direction_callbacks.keys();
|
||||
|
||||
function direction_n() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.n.y - node.offsetHeight,
|
||||
left: bbox.n.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_s() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.s.y,
|
||||
left: bbox.s.x - node.offsetWidth / 2
|
||||
};
|
||||
}
|
||||
|
||||
function direction_e() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.e.y - node.offsetHeight / 2,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_w() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.w.y - node.offsetHeight / 2,
|
||||
left: bbox.w.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_nw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.nw.y - node.offsetHeight,
|
||||
left: bbox.nw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_ne() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.ne.y - node.offsetHeight,
|
||||
left: bbox.ne.x
|
||||
};
|
||||
}
|
||||
|
||||
function direction_sw() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.sw.y,
|
||||
left: bbox.sw.x - node.offsetWidth
|
||||
};
|
||||
}
|
||||
|
||||
function direction_se() {
|
||||
var bbox = getScreenBBox();
|
||||
return {
|
||||
top: bbox.se.y,
|
||||
left: bbox.e.x
|
||||
};
|
||||
}
|
||||
|
||||
function initNode() {
|
||||
var node = d3.select(document.createElement('div'));
|
||||
node.style({
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
opacity: 0,
|
||||
'pointer-events': 'none',
|
||||
'box-sizing': 'border-box'
|
||||
});
|
||||
|
||||
return node.node();
|
||||
}
|
||||
|
||||
function getSVGNode(el) {
|
||||
el = el.node();
|
||||
if(el.tagName.toLowerCase() === 'svg') { return el; }
|
||||
|
||||
return el.ownerSVGElement
|
||||
}
|
||||
|
||||
// Private - gets the screen coordinates of a shape
|
||||
//
|
||||
// Given a shape on the screen, will return an SVGPoint for the directions
|
||||
// n(north), s(south), e(east), w(west), ne(northeast), se(southeast), nw(northwest),
|
||||
// sw(southwest).
|
||||
//
|
||||
// +-+-+
|
||||
// | |
|
||||
// + +
|
||||
// | |
|
||||
// +-+-+
|
||||
//
|
||||
// Returns an Object {n, s, e, w, nw, sw, ne, se}
|
||||
function getScreenBBox() {
|
||||
var targetel = target || d3.event.target,
|
||||
bbox = {},
|
||||
matrix = targetel.getScreenCTM(),
|
||||
tbbox = targetel.getBBox(),
|
||||
width = tbbox.width,
|
||||
height = tbbox.height,
|
||||
x = tbbox.x,
|
||||
y = tbbox.y,
|
||||
scrollEl = document.documentElement ? document.documentElement : document.body,
|
||||
scrollTop = scrollEl.scrollTop,
|
||||
scrollLeft = scrollEl.scrollLeft;
|
||||
|
||||
|
||||
point.x = x + scrollLeft;
|
||||
point.y = y + scrollTop;
|
||||
bbox.nw = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.ne = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.se = point.matrixTransform(matrix);
|
||||
point.x -= width;
|
||||
bbox.sw = point.matrixTransform(matrix);
|
||||
point.y -= height / 2;
|
||||
bbox.w = point.matrixTransform(matrix);
|
||||
point.x += width;
|
||||
bbox.e = point.matrixTransform(matrix);
|
||||
point.x -= width / 2;
|
||||
point.y -= height / 2;
|
||||
bbox.n = point.matrixTransform(matrix);
|
||||
point.y += height;
|
||||
bbox.s = point.matrixTransform(matrix);
|
||||
|
||||
return bbox;
|
||||
}
|
||||
|
||||
return tip;
|
||||
};
|
||||
});
|
||||
|
|
11
src/bower_components/K4D3/test/BasicSpec.js
vendored
Normal file
11
src/bower_components/K4D3/test/BasicSpec.js
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
describe('Simple Tests:', function() {
|
||||
it("b is true because its true man", function() {
|
||||
var b = true;
|
||||
expect(b).toBe(true);
|
||||
});
|
||||
|
||||
it('e is not a number', function() {
|
||||
var e = 1;
|
||||
expect(e).toBe(1);
|
||||
});
|
||||
});
|
46
src/bower_components/K4D3/test/HeatmapSpec.js
vendored
Normal file
46
src/bower_components/K4D3/test/HeatmapSpec.js
vendored
Normal file
|
@ -0,0 +1,46 @@
|
|||
describe('Heatmap Chart Test Cases', function() {
|
||||
'use strict';
|
||||
|
||||
var div, chart, cols = 50, rows = 24, data = [];
|
||||
for (var x = 1; x < cols+1; x++) {
|
||||
for (var y = 1; y < rows+1; y++) {
|
||||
data.push({ x: x, y: y, z: Math.random() });
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function() {
|
||||
div = d3.select('body').append('div').attr('id', 'heatmap');
|
||||
|
||||
chart = k4.heatmap();
|
||||
div.datum(data).call(chart);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
// Tests
|
||||
it('should generate svg', function() {
|
||||
expect(d3.select('svg')[0].length).not.toBe(0);
|
||||
});
|
||||
|
||||
it('should set default svg height and width', function() {
|
||||
expect(div.select('svg').attr('width')).toBe('500');
|
||||
expect(div.select('svg').attr('height')).toBe('500');
|
||||
});
|
||||
|
||||
it('should allow changing svg height and width', function() {
|
||||
chart.width(760).height(400);
|
||||
div.datum(data).call(chart);
|
||||
expect(div.select('svg').attr('width')).toBe('760');
|
||||
expect(div.select('svg').attr('height')).toBe('400');
|
||||
});
|
||||
|
||||
it('should have random data selection with z value >= 0 && <= 1', function() {
|
||||
var n = Math.floor(Math.random()*data.length);
|
||||
expect(n).toBeGreaterThan(0);
|
||||
expect(data[n].z).not.toBeGreaterThan(1);
|
||||
expect(data[n].z).not.toBeLessThan(0);
|
||||
});
|
||||
|
||||
});
|
176
src/bower_components/K4D3/test/unit/unitSpec.js
vendored
Normal file
176
src/bower_components/K4D3/test/unit/unitSpec.js
vendored
Normal file
|
@ -0,0 +1,176 @@
|
|||
describe('Unit tests', function() {
|
||||
'use strict';
|
||||
|
||||
var chart,
|
||||
data,
|
||||
div,
|
||||
formatDate;
|
||||
|
||||
// Tests
|
||||
describe('Area Chart Test Cases', function() {
|
||||
beforeEach(function() {
|
||||
formatDate = d3.time.format("%b %Y").parse;
|
||||
data = [
|
||||
{x: "Jan 2013", y: 256},
|
||||
{x: "Feb 2013", y: 770},
|
||||
{x: "May 2013", y: 159},
|
||||
{x: "Oct 2013", y: 106}
|
||||
];
|
||||
|
||||
div = d3.select('body').append('div').attr('id', 'chart');
|
||||
|
||||
chart = k4.area()
|
||||
.interpolate("cardinal")
|
||||
.x(function(d) { return formatDate(d.x); })
|
||||
.y(function(d) { return d.y; });
|
||||
|
||||
div.datum(data).call(chart);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
it('should generate svg', function() {
|
||||
expect(d3.select('svg')[0][0]).not.toBe('undefined');
|
||||
});
|
||||
|
||||
it('should set default svg height and width', function() {
|
||||
expect(div.select('svg').attr('width')).toBe('960');
|
||||
expect(div.select('svg').attr('height')).toBe('500');
|
||||
});
|
||||
|
||||
it('should allow changing svg height and width', function() {
|
||||
chart.width(1160).height(450);
|
||||
div.datum(data).call(chart);
|
||||
|
||||
expect(div.select('svg').attr('width')).toBe('1160');
|
||||
expect(div.select('svg').attr('height')).toBe('450');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Pie Chart Test Cases', function() {
|
||||
beforeEach(function() {
|
||||
data = [
|
||||
{label: "DEN", value: 256},
|
||||
{label: "SEA", value: 770},
|
||||
{label: "SF", value: 159},
|
||||
{label: "NE", value: 106}
|
||||
];
|
||||
|
||||
div = d3.select('body').append('div').attr('id', 'chart');
|
||||
|
||||
chart = k4.pie()
|
||||
.label(function(d) { return d.label; })
|
||||
.value(function(d) { return d.value; });
|
||||
|
||||
div.datum(data).call(chart);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
// Tests
|
||||
it('should generate svg', function() {
|
||||
expect(d3.select('svg')[0][0]).not.toBe('undefined');
|
||||
});
|
||||
|
||||
it('should set default svg height and width', function() {
|
||||
expect(div.select('svg').attr('width')).toBe('500');
|
||||
expect(div.select('svg').attr('height')).toBe('500');
|
||||
});
|
||||
|
||||
it('should allow changing svg height and width', function() {
|
||||
chart.width(1160).height(450);
|
||||
div.datum(data).call(chart);
|
||||
|
||||
expect(div.select('svg').attr('width')).toBe('1160');
|
||||
expect(div.select('svg').attr('height')).toBe('450');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Line Chart Test Cases', function() {
|
||||
beforeEach(function() {
|
||||
formatDate = d3.time.format("%b %Y").parse;
|
||||
data = [
|
||||
{x: "Jan 2013", y: 256},
|
||||
{x: "Feb 2013", y: 770},
|
||||
{x: "May 2013", y: 159},
|
||||
{x: "Oct 2013", y: 106}
|
||||
];
|
||||
|
||||
div = d3.select('body').append('div').attr('id', 'chart');
|
||||
|
||||
chart = k4.line()
|
||||
.interpolate("cardinal")
|
||||
.x(function(d) { return formatDate(d.x); })
|
||||
.y(function(d) { return d.y; });
|
||||
|
||||
div.datum(data).call(chart);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
it('should generate svg', function() {
|
||||
expect(d3.select('svg')[0][0]).not.toBe('undefined');
|
||||
});
|
||||
|
||||
it('should set default svg height and width', function() {
|
||||
expect(div.select('svg').attr('width')).toBe('960');
|
||||
expect(div.select('svg').attr('height')).toBe('500');
|
||||
});
|
||||
|
||||
it('should allow changing svg height and width', function() {
|
||||
chart.width(1160).height(450);
|
||||
div.datum(data).call(chart);
|
||||
|
||||
expect(div.select('svg').attr('width')).toBe('1160');
|
||||
expect(div.select('svg').attr('height')).toBe('450');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Sparkline Chart Test Cases', function() {
|
||||
beforeEach(function() {
|
||||
formatDate = d3.time.format("%b %Y").parse;
|
||||
data = [
|
||||
{x: "Jan 2013", y: 256},
|
||||
{x: "Feb 2013", y: 770},
|
||||
{x: "May 2013", y: 159},
|
||||
{x: "Oct 2013", y: 106}
|
||||
];
|
||||
|
||||
div = d3.select('body').append('div').attr('id', 'chart');
|
||||
|
||||
chart = k4.sparkline()
|
||||
.interpolate("cardinal")
|
||||
.x(function(d) { return formatDate(d.x); })
|
||||
.y(function(d) { return d.y; });
|
||||
|
||||
div.datum(data).call(chart);
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
div.remove();
|
||||
});
|
||||
|
||||
it('should generate svg', function() {
|
||||
expect(d3.select('svg')[0][0]).not.toBe('undefined');
|
||||
});
|
||||
|
||||
it('should set default svg height and width', function() {
|
||||
expect(div.select('svg').attr('width')).toBe('760');
|
||||
expect(div.select('svg').attr('height')).toBe('120');
|
||||
});
|
||||
|
||||
it('should allow changing svg height and width', function() {
|
||||
chart.width(1160).height(450);
|
||||
div.datum(data).call(chart);
|
||||
|
||||
expect(div.select('svg').attr('width')).toBe('1160');
|
||||
expect(div.select('svg').attr('height')).toBe('450');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,7 +7,10 @@
|
|||
<meta name="viewport" content="width=device-width">
|
||||
<title>Kibana 4</title>
|
||||
<!-- load the root require context -->
|
||||
<script src="bower_components/d3/d3.js"></script>
|
||||
|
||||
<script src="bower_components/requirejs/require.js"></script>
|
||||
|
||||
<script src="kibana/require.config.js"></script>
|
||||
<script>require(['kibana'], function () {});</script>
|
||||
<link rel="stylesheet" href="kibana/styles/main.css" >
|
||||
|
|
|
@ -45,10 +45,7 @@ define(function (require) {
|
|||
min_cols: 12,
|
||||
max_cols: 12,
|
||||
resize: {
|
||||
enabled: true,
|
||||
stop: function (event, ui, widget) {
|
||||
console.log(widget.height(), widget.width());
|
||||
}
|
||||
enabled: true
|
||||
},
|
||||
serialize_params: function (el, wgd) {
|
||||
return {
|
||||
|
|
|
@ -69,16 +69,16 @@
|
|||
clear: both;
|
||||
}
|
||||
body.application-dashboard {
|
||||
background-color: #1e6d74;
|
||||
background-color: #18bc9c;
|
||||
}
|
||||
div.application div.dashboard-container {
|
||||
width: 100%;
|
||||
background-color: #1e6d74;
|
||||
background-color: #18bc9c;
|
||||
}
|
||||
[dashboard-grid].gridster {
|
||||
list-style-type: none;
|
||||
display: block;
|
||||
background-color: #1e6d74;
|
||||
background-color: #18bc9c;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
[dashboard-grid].gridster .preview-holder {
|
||||
|
@ -88,7 +88,7 @@ div.application div.dashboard-container {
|
|||
[dashboard-grid].gridster li.gs-w {
|
||||
background: #fff;
|
||||
padding: 5px;
|
||||
color: #1e6d74;
|
||||
color: #18bc9c;
|
||||
font-weight: bold;
|
||||
font-size: 20px;
|
||||
padding: 10px;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
@import (reference) "../../../../bower_components/bootstrap/less/bootstrap.less";
|
||||
@import (reference) "../../../../bower_components/bootstrap/less/theme.less";
|
||||
@import (reference) "../../../styles/_bootstrap.less";
|
||||
@import (reference) "../../../styles/theme/_theme.less";
|
||||
|
||||
@dashboard-background: #1E6D74;
|
||||
@dashboard-background: #18bc9c;
|
||||
|
||||
body.application-dashboard {
|
||||
background-color: @dashboard-background;
|
||||
|
|
|
@ -7,6 +7,7 @@ define(function (require) {
|
|||
var app = require('modules').get('app/discover');
|
||||
|
||||
require('services/state');
|
||||
require('directives/fixed_scroll');
|
||||
|
||||
require('routes')
|
||||
.when('/discover/:id?', {
|
||||
|
@ -95,13 +96,27 @@ define(function (require) {
|
|||
|
||||
search.onResults().then(function onResults(resp) {
|
||||
if (!$scope.fields) getFields();
|
||||
|
||||
$scope.rows = resp.hits.hits;
|
||||
$scope.chart = {rows: [{columns: [{
|
||||
label: 'Events over time',
|
||||
xAxisLabel: 'DateTime',
|
||||
yAxisLabel: 'Hits',
|
||||
layers: [
|
||||
{
|
||||
key: 'somekey',
|
||||
values: _.map(resp.aggregations.events.buckets, function (bucket) {
|
||||
return { y: bucket.doc_count, x: bucket.key_as_string };
|
||||
})
|
||||
}
|
||||
]
|
||||
}]}]};
|
||||
|
||||
return search.onResults(onResults);
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', _.bindKey(search, 'cancelPending'));
|
||||
|
||||
|
||||
$scope.getSort = function () {
|
||||
return $scope.state.sort;
|
||||
};
|
||||
|
@ -153,6 +168,15 @@ define(function (require) {
|
|||
query_string: {
|
||||
query: $scope.state.query
|
||||
}
|
||||
})
|
||||
.aggs({
|
||||
events: {
|
||||
date_histogram: {
|
||||
field: '@timestamp',
|
||||
interval: '12h',
|
||||
format: 'yyyy-MM-dd'
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -267,7 +291,6 @@ define(function (require) {
|
|||
};
|
||||
|
||||
function refreshColumns() {
|
||||
|
||||
// Get all displayed field names;
|
||||
var fields = _.pluck(_.filter($scope.fields, function (field) {
|
||||
return field.display;
|
||||
|
|
17
src/kibana/apps/discover/directives/discover_field.js
Normal file
17
src/kibana/apps/discover/directives/discover_field.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
define(function (require) {
|
||||
var app = require('modules').get('app/discover');
|
||||
var html = require('text!../partials/discover_field.html');
|
||||
var _ = require('lodash');
|
||||
|
||||
require('directives/css_truncate');
|
||||
require('directives/field_name');
|
||||
|
||||
|
||||
app.directive('discoverField', function () {
|
||||
return {
|
||||
restrict: 'E',
|
||||
template: html,
|
||||
replace: true
|
||||
};
|
||||
});
|
||||
});
|
|
@ -1,9 +1,13 @@
|
|||
define(function (require) {
|
||||
var app = require('modules').get('app/discover');
|
||||
var html = require('text!./partials/field_chooser.html');
|
||||
var html = require('text!../partials/field_chooser.html');
|
||||
var _ = require('lodash');
|
||||
|
||||
require('directives/css_truncate');
|
||||
require('directives/field_name');
|
||||
require('./discover_field');
|
||||
|
||||
|
||||
|
||||
app.directive('discFieldChooser', function () {
|
||||
return {
|
||||
|
@ -43,23 +47,6 @@ define(function (require) {
|
|||
$scope.filterFunc(field.name, value, operation);
|
||||
};
|
||||
|
||||
$scope.typeIcon = function (fieldType) {
|
||||
switch (fieldType)
|
||||
{
|
||||
case 'source':
|
||||
return 'fa-file-text-o';
|
||||
case 'string':
|
||||
return 'fa-sort-alpha-asc';
|
||||
case 'number':
|
||||
return 'fa-sort-numeric-asc';
|
||||
case 'date':
|
||||
return 'fa-clock-o';
|
||||
case 'ip':
|
||||
return 'fa-laptop';
|
||||
default:
|
||||
}
|
||||
};
|
||||
|
||||
var getFieldValues = function (data, field) {
|
||||
return _.map(data, function (row) {
|
||||
var val;
|
|
@ -14,16 +14,19 @@ define(function (require) {
|
|||
link: function ($scope, elem) {
|
||||
|
||||
var init = function () {
|
||||
/*
|
||||
// This elem should already have a height/width
|
||||
var myChart = new k4.Chart(elem, {type: 'timechart', doSomething: true, draggable: false});
|
||||
var myChart = new k4.Chart(elem[0], {
|
||||
type: 'histogram',
|
||||
stacktype: 'zero',
|
||||
yGroup: true,
|
||||
color: ['#81dfe2', '#0762b7']
|
||||
});
|
||||
|
||||
myChart.on('hover', function (elem, event) {
|
||||
})
|
||||
*/
|
||||
|
||||
|
||||
//myChart.render($scope.data);
|
||||
$scope.$watch('data', function (data) {
|
||||
if (!_.isUndefined(data)) {
|
||||
myChart.render(data);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
// Start the directive
|
|
@ -9,16 +9,17 @@
|
|||
<form class="navbar-form" ng-submit="fetch()">
|
||||
<div class="form-group" style="display:inline;">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon"><span class="fa fa-search"></span></span>
|
||||
<input placeholder="Search..." type="text" class="form-control" ng-model="state.query">
|
||||
<span class="input-group-addon" ng-click="fetch()"><span class="fa fa-search"></span></span>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</nav>
|
||||
<config config-template="configTemplate" config-object="opts" config-close="configClose" config-submit="fetch"></config>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-2 discovery-field-container">
|
||||
<div class="col-md-2 discover-field-container">
|
||||
<disc-field-chooser
|
||||
fields="fields"
|
||||
toggle="toggleField"
|
||||
|
@ -28,15 +29,20 @@
|
|||
</disc-field-chooser>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<discover-timechart></discover-timechart>
|
||||
<kbn-table style="overflow-x:auto" class="table table-condensed"
|
||||
rows="rows"
|
||||
columns="state.columns"
|
||||
refresh="fetch"
|
||||
max-length="opts.maxSummaryLength"
|
||||
get-sort="getSort"
|
||||
set-sort="setSort">
|
||||
</kbn-table>
|
||||
<discover-timechart data="chart" height="150"></discover-timechart>
|
||||
<div class="discover-table"
|
||||
fixed-scroll='table'
|
||||
fixed-scroll-trigger="state.columns">
|
||||
|
||||
<kbn-table class="table table-condensed"
|
||||
rows="rows"
|
||||
columns="state.columns"
|
||||
refresh="fetch"
|
||||
max-length="opts.maxSummaryLength"
|
||||
get-sort="getSort"
|
||||
set-sort="setSort">
|
||||
</kbn-table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
define(function (require, module, exports) {
|
||||
require('directives/table');
|
||||
require('./field_chooser');
|
||||
require('./saved_searches/service');
|
||||
require('./timechart');
|
||||
require('./directives/timechart');
|
||||
require('./directives/field_chooser');
|
||||
require('./controllers/discover');
|
||||
});
|
37
src/kibana/apps/discover/partials/discover_field.html
Normal file
37
src/kibana/apps/discover/partials/discover_field.html
Normal file
|
@ -0,0 +1,37 @@
|
|||
|
||||
<li class="discover-field-item">
|
||||
<div ng-click="details(field)" class="discover-field-name">
|
||||
<span field-name="field.name" field-type="field.type"></span>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="discover-field-details" ng-if="field.details">
|
||||
|
||||
<a ng-click="toggle(field.name)" class="pull-right btn btn-default btn-xs discover-field-toggle">
|
||||
{{field.display ? 'Hide' : 'Show'}}
|
||||
</a>
|
||||
|
||||
<span bo-if="!field.details.error">Present in {{field.details.exists}}/{{field.details.total}} records</span>
|
||||
|
||||
|
||||
|
||||
<div class="clearfix"></div>
|
||||
|
||||
<div bo-if="field.details.error" class="discover-field-details-error">{{field.details.error}}</div>
|
||||
|
||||
<div bo-if="!field.details.error">
|
||||
<div ng-repeat="bucket in field.details.buckets" class="discover-field-details-item">
|
||||
<div>
|
||||
<i class="fa fa-search-minus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '-')"></i>
|
||||
<i class="fa fa-search-plus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '+')"></i>
|
||||
<div css-truncate css-truncate-expandable="true" class="discover-field-details-value">
|
||||
{{bucket.value}}
|
||||
</div>
|
||||
</div>
|
||||
<progressbar value="bucket.percent" max="100" animate="false"><span>{{bucket.percent}}%</span></progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</li>
|
|
@ -1,63 +1,17 @@
|
|||
<div class="discover-field-list">
|
||||
<h5>Selected</h5>
|
||||
<div class="discover-field-list-header">
|
||||
<h5>Selected</h5>
|
||||
</div>
|
||||
<ul bindonce class="list-unstyled">
|
||||
<li ng-repeat="field in fields|filter:{display:true}" class="discover-field-item">
|
||||
<a ng-click="toggle(field.name)" class="discover-field-add">
|
||||
<i class="fa fa-minus-circle"></i>
|
||||
</a>
|
||||
|
||||
<a ng-click="details(field)" class="discover-field-name"><i ng-click="clicked()" class="fa" bo-class="typeIcon(field.type)"></i> <span bo-text="field.name"></span></a>
|
||||
|
||||
|
||||
<div class="discover-field-details" ng-if="field.details">
|
||||
<div bo-if="field.details.error">{{field.details.error}}</div>
|
||||
|
||||
<div bo-if="!field.details.error">
|
||||
<div ng-repeat="bucket in field.details.buckets" class="discover-field-details-item">
|
||||
<div>
|
||||
<i class="fa fa-search-minus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '-')"></i>
|
||||
<i class="fa fa-search-plus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '+')"></i>
|
||||
<div css-truncate css-truncate-expandable="true" class="discover-field-details-value">
|
||||
{{bucket.value}}
|
||||
</div>
|
||||
</div>
|
||||
<progressbar value="bucket.percent" max="100" animate="false"><span>{{bucket.percent}}%</span></progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</li>
|
||||
<discover-field field="field" ng-repeat="field in fields|filter:{display:true}">
|
||||
</discover-field>
|
||||
</ul>
|
||||
|
||||
<h5>Available</h5>
|
||||
<div class="discover-field-list-header">
|
||||
<h5>Available</h5>
|
||||
</div>
|
||||
<ul bindonce class="list-unstyled">
|
||||
<li ng-repeat="field in fields|filter:{display:!true}" class="discover-field-item">
|
||||
<a ng-click="toggle(field.name)" class="discover-field-add">
|
||||
<i class="fa fa-plus-circle"></i>
|
||||
</a>
|
||||
|
||||
<a ng-click="details(field)" class="discover-field-name"><i ng-click="clicked()" class="fa" bo-class="typeIcon(field.type)"></i> <span bo-text="field.name"></span></a>
|
||||
|
||||
|
||||
<div class="discover-field-details" ng-if="field.details">
|
||||
<div bo-if="field.details.error">{{field.details.error}}</div>
|
||||
|
||||
<div bo-if="!field.details.error">
|
||||
<div ng-repeat="bucket in field.details.buckets" class="discover-field-details-item">
|
||||
<div>
|
||||
<i class="fa fa-search-minus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '-')"></i>
|
||||
<i class="fa fa-search-plus pull-right discover-field-details-filter"
|
||||
ng-click="filter(field, bucket.value, '+')"></i>
|
||||
<div css-truncate css-truncate-expandable="true" class="discover-field-details-value">
|
||||
{{bucket.value}}
|
||||
</div>
|
||||
</div>
|
||||
<progressbar value="bucket.percent" max="100" animate="false"><span>{{bucket.percent}}%</span></progressbar>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
</li>
|
||||
<discover-field field="field" ng-repeat="field in fields|filter:{display:false}">
|
||||
</discover-field>
|
||||
</ul>
|
||||
</div>
|
|
@ -68,23 +68,50 @@
|
|||
.modal-footer:after {
|
||||
clear: both;
|
||||
}
|
||||
.discover-field-list .discover-field-item .discover-field-add {
|
||||
visibility: hidden;
|
||||
.application-discover {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.discover-field-list .discover-field-item:hover .discover-field-add {
|
||||
visibility: visible;
|
||||
.discover-table {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
margin-top: 10px;
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
.discover-field-list .discover-field-name:hover {
|
||||
text-decoration: none;
|
||||
margin-left: 0;
|
||||
.discover-field-container {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
background-color: #f5f5f5;
|
||||
border-right: 1px solid #e3e3e3;
|
||||
border-bottom: 1px solid #e3e3e3;
|
||||
}
|
||||
.discover-field-list .discover-field-list-header {
|
||||
padding-left: 10px;
|
||||
color: #777777;
|
||||
}
|
||||
.discover-field-list .discover-field-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 11px;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
}
|
||||
.discover-field-list .discover-field-name {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.discover-field-list .discover-field-name:hover,
|
||||
.discover-field-list .discover-field-name:hover .text-muted {
|
||||
background-color: #428bca;
|
||||
color: #ffffff;
|
||||
}
|
||||
.discover-field-list .discover-field-details {
|
||||
font-size: 12px;
|
||||
margin-left: 15px;
|
||||
padding: 5px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dddddd;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
padding: 5px 10px;
|
||||
background-color: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
.discover-field-list .discover-field-details .discover-field-details-error {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.discover-field-list .discover-field-details .discover-field-details-item {
|
||||
margin-top: 5px;
|
||||
|
|
|
@ -1,27 +1,61 @@
|
|||
@import (reference) "../../../../bower_components/bootstrap/less/bootstrap.less";
|
||||
@import (reference) "../../../../bower_components/bootstrap/less/theme.less";
|
||||
@import (reference) "../../../styles/_bootstrap.less";
|
||||
@import (reference) "../../../styles/theme/_theme.less";
|
||||
@import (reference) "../../../styles/_variables.less";
|
||||
|
||||
.application-discover {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.discover-table {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
margin-top: 10px;
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
|
||||
.discover-field-container {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
background-color: @well-bg;
|
||||
border-right: 1px solid @well-border;
|
||||
border-bottom: 1px solid @well-border;
|
||||
}
|
||||
|
||||
.discover-field-list {
|
||||
.discover-field-item .discover-field-add {
|
||||
visibility:hidden;
|
||||
|
||||
.discover-field-list-header {
|
||||
padding-left: 10px;
|
||||
color: @navbar-default-color;
|
||||
}
|
||||
|
||||
.discover-field-item:hover .discover-field-add {
|
||||
visibility:visible;
|
||||
|
||||
.discover-field-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: @font-size-smaller;
|
||||
border-top: 1px solid @well-border;
|
||||
}
|
||||
|
||||
.discover-field-name:hover {
|
||||
text-decoration: none;
|
||||
margin-left: 0;
|
||||
.discover-field-name {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
|
||||
.discover-field-name:hover, .discover-field-name:hover .text-muted {
|
||||
background-color: @component-active-bg;
|
||||
color: @component-active-color;
|
||||
}
|
||||
|
||||
.discover-field-details {
|
||||
font-size: @font-size-small;
|
||||
margin-left: 15px;
|
||||
padding: 5px;
|
||||
background-color: @well-bg;
|
||||
border-radius: @border-radius-base;
|
||||
border: 1px solid @table-border-color;
|
||||
border-top: 1px solid @well-border;
|
||||
padding: 5px 10px;
|
||||
background-color: @body-bg;
|
||||
color: @text-color;
|
||||
|
||||
.discover-field-details-error {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.discover-field-details-item {
|
||||
margin-top: 5px;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
@import (reference) "../../../../bower_components/bootstrap/less/bootstrap.less";
|
||||
@import (reference) "../../../styles/_bootstrap.less";
|
||||
@import (reference) "../../../styles/theme/_theme.less";
|
||||
|
||||
.vis-config-panel {
|
||||
padding: 0;
|
||||
|
|
39
src/kibana/directives/field_name.js
Normal file
39
src/kibana/directives/field_name.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
define(function (require) {
|
||||
var module = require('modules').get('kibana/directives');
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
|
||||
module.directive('fieldName', function ($compile) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
fieldName: '=',
|
||||
fieldType: '='
|
||||
},
|
||||
link: function ($scope, $elem, attrs) {
|
||||
|
||||
var typeIcon = function (fieldType) {
|
||||
switch (fieldType)
|
||||
{
|
||||
case 'source':
|
||||
return $('<i class="fa fa-file-text-o"></i> ');
|
||||
case 'string':
|
||||
return $('<i><strong>t</strong></i> ');
|
||||
case 'number':
|
||||
return $('<i><strong>#</strong></i> ');
|
||||
case 'date':
|
||||
return $('<i class="fa fa-clock-o"></i> ');
|
||||
case 'ip':
|
||||
return $('<i class="fa fa-laptop"></i> ');
|
||||
default:
|
||||
return $('<i><strong>?</strong></i> ');
|
||||
}
|
||||
};
|
||||
|
||||
var icon = typeIcon($scope.fieldType).addClass('text-muted').css({'margin-right': '5px'});
|
||||
|
||||
$elem.text($scope.fieldName).prepend(icon);
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
110
src/kibana/directives/fixed_scroll.js
Normal file
110
src/kibana/directives/fixed_scroll.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
// Creates a fake scrollbar at the bottom of an element. Useful for infinite scrolling components
|
||||
define(function (require) {
|
||||
var module = require('modules').get('kibana/directives');
|
||||
var $ = require('jquery');
|
||||
var _ = require('lodash');
|
||||
|
||||
module.directive('fixedScroll', function ($timeout) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
fixedScrollTrigger: '=fixedScrollTrigger',
|
||||
anchor: '@fixedScroll',
|
||||
},
|
||||
link: function ($scope, $elem, attrs) {
|
||||
|
||||
var options = {
|
||||
contentElement: _.isUndefined($scope.anchor) ? undefined : $elem.find($scope.anchor),
|
||||
fixedScrollMarkup: '<div class="fixedScroll-container" ' +
|
||||
'style="height: 20px;"><div class="fixedScroll-scroll" style="height: 20px;"></div></div>',
|
||||
fixedScrollInnerSelector: '.fixedScroll-scroll'
|
||||
};
|
||||
|
||||
var innerElem;
|
||||
// Set the inner element that gives context to the scroll
|
||||
if (options.contentElement !== undefined && $elem.find(options.contentElement).length !== 0) {
|
||||
innerElem = $elem.find(options.contentElement);
|
||||
} else {
|
||||
innerElem = $elem.find('>:first-child');
|
||||
}
|
||||
|
||||
var fixedScroll = $($(options.fixedScrollMarkup));
|
||||
fixedScroll.css({position: 'fixed', bottom: 0});
|
||||
|
||||
|
||||
var addScroll = function ($elem, options) {
|
||||
|
||||
// If content isn't wide enough to scroll, abort
|
||||
if ($elem.get(0).scrollWidth <= $elem.width()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// add container for fake scrollbar
|
||||
$elem.after(fixedScroll);
|
||||
|
||||
// bind fixed scroll to real scroll
|
||||
fixedScroll.bind('scroll.fixedScroll', function () {
|
||||
$elem.scrollLeft(fixedScroll.scrollLeft());
|
||||
});
|
||||
|
||||
// and bind real scroll to fixed scroll
|
||||
var scrollHandler = function () {
|
||||
fixedScroll.scrollLeft($elem.scrollLeft());
|
||||
};
|
||||
$elem.bind('scroll.fixedScroll', scrollHandler);
|
||||
|
||||
fixedScroll.css({'overflow-x': 'auto', 'overflow-y': 'hidden'});
|
||||
$elem.css({'overflow-x': 'auto', 'overflow-y': 'hidden'});
|
||||
|
||||
// Check the width until it stops changing
|
||||
var setWidth = function (innerElemWidth) {
|
||||
$timeout(function () {
|
||||
if (innerElemWidth !== innerElem.outerWidth()) {
|
||||
setWidth(innerElem.outerWidth());
|
||||
} else {
|
||||
$(options.fixedScrollInnerSelector, fixedScroll).width(innerElem.outerWidth());
|
||||
fixedScroll.width($elem.width());
|
||||
}
|
||||
}, 500);
|
||||
};
|
||||
|
||||
setWidth(innerElem.outerWidth());
|
||||
|
||||
};
|
||||
|
||||
addScroll($elem, options);
|
||||
|
||||
var recompute = function () {
|
||||
$elem.unbind('scroll.fixedScroll');
|
||||
$elem.prev('div.fixedScroll-container').remove();
|
||||
addScroll($elem, options);
|
||||
};
|
||||
|
||||
// Create a watchable for the content element
|
||||
$scope.innerElemWidth = function () {
|
||||
return innerElem.outerWidth();
|
||||
};
|
||||
|
||||
// Watch window size
|
||||
$(window).resize(recompute);
|
||||
|
||||
// Watch the trigger if there is one
|
||||
$scope.$watch('trigger', function () {
|
||||
recompute();
|
||||
});
|
||||
|
||||
// And watch the element width
|
||||
$scope.$watch('innerElemWidth()', function (width) {
|
||||
recompute();
|
||||
});
|
||||
|
||||
// Clean up listeners
|
||||
$scope.$on('$destroy', function () {
|
||||
$elem.unbind('scroll.fixedScroll');
|
||||
fixedScroll.unbind('scroll.fixedScroll');
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
});
|
||||
});
|
|
@ -28,10 +28,20 @@ define(function (require) {
|
|||
if (column === sort[0]) {
|
||||
return ['fa', sort[1] === 'asc' ? 'fa-sort-up' : 'fa-sort-down'];
|
||||
} else {
|
||||
return ['fa', 'fa-sort'];
|
||||
return ['fa', 'fa-sort', 'table-header-sortchange'];
|
||||
}
|
||||
};
|
||||
|
||||
$scope.moveLeft = function (column) {
|
||||
var index = _.indexOf($scope.columns, column);
|
||||
_.move($scope.columns, index, --index);
|
||||
};
|
||||
|
||||
$scope.moveRight = function (column) {
|
||||
var index = _.indexOf($scope.columns, column);
|
||||
_.move($scope.columns, index, ++index);
|
||||
};
|
||||
|
||||
$scope.sort = function (column) {
|
||||
var sort = $scope.getSort();
|
||||
console.log('dir', sort);
|
||||
|
@ -72,7 +82,8 @@ define(function (require) {
|
|||
refresh: '=',
|
||||
getSort: '=',
|
||||
setSort: '=',
|
||||
maxLength: '=?'
|
||||
maxLength: '=?',
|
||||
mapping: '=?'
|
||||
},
|
||||
link: function ($scope, element, attrs) {
|
||||
// track a list of id's that are currently open, so that
|
||||
|
@ -96,7 +107,7 @@ define(function (require) {
|
|||
|
||||
// rerender when either is changed
|
||||
$scope.$watch('rows', render);
|
||||
$scope.$watch('columns', render);
|
||||
$scope.$watchCollection('columns', render);
|
||||
$scope.$watch('maxLength', render);
|
||||
|
||||
// the body of the table
|
||||
|
@ -104,6 +115,7 @@ define(function (require) {
|
|||
|
||||
// itterate the columns and rows, rebuild the table's html
|
||||
function render() {
|
||||
|
||||
$body.empty();
|
||||
if (!$scope.rows || $scope.rows.length === 0) return;
|
||||
if (!$scope.columns || $scope.columns.length === 0) return;
|
||||
|
@ -252,6 +264,7 @@ define(function (require) {
|
|||
table.appendChild(tbody);
|
||||
|
||||
// itterate each row and append it to the tbody
|
||||
// TODO: This doesn't work since _source is not flattened
|
||||
_(row._source)
|
||||
.keys()
|
||||
.concat(topLevelDetails)
|
||||
|
|
|
@ -1 +1,7 @@
|
|||
<th ng-repeat="name in columns">{{name}} <i ng-click="sort(name)" ng-class="headerClass(name)"></i></th>
|
||||
<th ng-repeat="name in columns">
|
||||
<span ng-click="sort(name)">{{name}} <i ng-class="headerClass(name)"></i> </span>
|
||||
<span class="table-header-move">
|
||||
<i ng-click="moveLeft(name)" class="fa fa-angle-double-left" ng-show="!$first"></i>
|
||||
<i ng-click="moveRight(name)" class="fa fa-angle-double-right" ng-show="!$last"></i>
|
||||
</span>
|
||||
</th>
|
|
@ -1,5 +1,6 @@
|
|||
define(function (require) {
|
||||
var _ = require('lodash');
|
||||
require('utils/rison');
|
||||
|
||||
require('modules')
|
||||
.get('kibana/services')
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
@bs-less-dir: "../../bower_components/bootstrap/less";
|
||||
|
||||
// Core variables and mixins
|
||||
@import "@{bs-less-dir}/variables.less";
|
||||
@import "theme/_variables.less";
|
||||
@import "theme/_theme.less";
|
||||
|
||||
// Mixins
|
||||
@import "@{bs-less-dir}/mixins.less";
|
||||
|
||||
// Reset
|
||||
|
@ -49,6 +52,3 @@
|
|||
// Utility classes
|
||||
@import "@{bs-less-dir}/utilities.less";
|
||||
@import "@{bs-less-dir}/responsive-utilities.less";
|
||||
|
||||
// automatically include the theme file
|
||||
@import "@{bs-less-dir}/theme.less";
|
1
src/kibana/styles/_variables.less
Normal file
1
src/kibana/styles/_variables.less
Normal file
|
@ -0,0 +1 @@
|
|||
@font-size-smaller: ceil((@font-size-base * 0.75));
|
|
@ -6499,346 +6499,6 @@ button.close {
|
|||
display: none !important;
|
||||
}
|
||||
}
|
||||
.btn-default,
|
||||
.btn-primary,
|
||||
.btn-success,
|
||||
.btn-info,
|
||||
.btn-warning,
|
||||
.btn-danger {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-primary:active,
|
||||
.btn-success:active,
|
||||
.btn-info:active,
|
||||
.btn-warning:active,
|
||||
.btn-danger:active,
|
||||
.btn-default.active,
|
||||
.btn-primary.active,
|
||||
.btn-success.active,
|
||||
.btn-info.active,
|
||||
.btn-warning.active,
|
||||
.btn-danger.active {
|
||||
-webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
.btn:active,
|
||||
.btn.active {
|
||||
background-image: none;
|
||||
}
|
||||
.btn-default {
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #e0e0e0 100%);
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #e0e0e0 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#ffe0e0e0', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #dbdbdb;
|
||||
text-shadow: 0 1px 0 #fff;
|
||||
border-color: #ccc;
|
||||
}
|
||||
.btn-default:hover,
|
||||
.btn-default:focus {
|
||||
background-color: #e0e0e0;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-default:active,
|
||||
.btn-default.active {
|
||||
background-color: #e0e0e0;
|
||||
border-color: #dbdbdb;
|
||||
}
|
||||
.btn-primary {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #2d6ca2 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #2d6ca2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff2d6ca2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
.btn-primary:hover,
|
||||
.btn-primary:focus {
|
||||
background-color: #2d6ca2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-primary:active,
|
||||
.btn-primary.active {
|
||||
background-color: #2d6ca2;
|
||||
border-color: #2b669a;
|
||||
}
|
||||
.btn-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #419641 100%);
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #419641 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff419641', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-success:hover,
|
||||
.btn-success:focus {
|
||||
background-color: #419641;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-success:active,
|
||||
.btn-success.active {
|
||||
background-color: #419641;
|
||||
border-color: #3e8f3e;
|
||||
}
|
||||
.btn-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #2aabd2 100%);
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #2aabd2 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff2aabd2', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-info:hover,
|
||||
.btn-info:focus {
|
||||
background-color: #2aabd2;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-info:active,
|
||||
.btn-info.active {
|
||||
background-color: #2aabd2;
|
||||
border-color: #28a4c9;
|
||||
}
|
||||
.btn-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #eb9316 100%);
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #eb9316 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffeb9316', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-warning:hover,
|
||||
.btn-warning:focus {
|
||||
background-color: #eb9316;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-warning:active,
|
||||
.btn-warning.active {
|
||||
background-color: #eb9316;
|
||||
border-color: #e38d13;
|
||||
}
|
||||
.btn-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c12e2a 100%);
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c12e2a 100%);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc12e2a', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
background-repeat: repeat-x;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.btn-danger:hover,
|
||||
.btn-danger:focus {
|
||||
background-color: #c12e2a;
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
.btn-danger:active,
|
||||
.btn-danger.active {
|
||||
background-color: #c12e2a;
|
||||
border-color: #b92c28;
|
||||
}
|
||||
.thumbnail,
|
||||
.img-thumbnail {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.dropdown-menu > li > a:hover,
|
||||
.dropdown-menu > li > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
background-color: #e8e8e8;
|
||||
}
|
||||
.dropdown-menu > .active > a,
|
||||
.dropdown-menu > .active > a:hover,
|
||||
.dropdown-menu > .active > a:focus {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
|
||||
background-color: #357ebd;
|
||||
}
|
||||
.navbar-default {
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-default .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.navbar-brand,
|
||||
.navbar-nav > li > a {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.25);
|
||||
}
|
||||
.navbar-inverse {
|
||||
background-image: -webkit-linear-gradient(top, #3c3c3c 0%, #222222 100%);
|
||||
background-image: linear-gradient(to bottom, #3c3c3c 0%, #222222 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff3c3c3c', endColorstr='#ff222222', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
}
|
||||
.navbar-inverse .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #222222 0%, #282828 100%);
|
||||
background-image: linear-gradient(to bottom, #222222 0%, #282828 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff222222', endColorstr='#ff282828', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-inverse .navbar-brand,
|
||||
.navbar-inverse .navbar-nav > li > a {
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
.navbar-static-top,
|
||||
.navbar-fixed-top,
|
||||
.navbar-fixed-bottom {
|
||||
border-radius: 0;
|
||||
}
|
||||
.alert {
|
||||
text-shadow: 0 1px 0 rgba(255, 255, 255, 0.2);
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.alert-success {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #c8e5bc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffc8e5bc', GradientType=0);
|
||||
border-color: #b2dba1;
|
||||
}
|
||||
.alert-info {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #b9def0 100%);
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #b9def0 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffb9def0', GradientType=0);
|
||||
border-color: #9acfea;
|
||||
}
|
||||
.alert-warning {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #f8efc0 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fff8efc0', GradientType=0);
|
||||
border-color: #f5e79e;
|
||||
}
|
||||
.alert-danger {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #e7c3c3 100%);
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #e7c3c3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffe7c3c3', GradientType=0);
|
||||
border-color: #dca7a7;
|
||||
}
|
||||
.progress {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f5f5f5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff5f5f5', GradientType=0);
|
||||
}
|
||||
.progress-bar {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3071a9 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #3071a9 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3071a9', GradientType=0);
|
||||
}
|
||||
.progress-bar-success {
|
||||
background-image: -webkit-linear-gradient(top, #5cb85c 0%, #449d44 100%);
|
||||
background-image: linear-gradient(to bottom, #5cb85c 0%, #449d44 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5cb85c', endColorstr='#ff449d44', GradientType=0);
|
||||
}
|
||||
.progress-bar-info {
|
||||
background-image: -webkit-linear-gradient(top, #5bc0de 0%, #31b0d5 100%);
|
||||
background-image: linear-gradient(to bottom, #5bc0de 0%, #31b0d5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff5bc0de', endColorstr='#ff31b0d5', GradientType=0);
|
||||
}
|
||||
.progress-bar-warning {
|
||||
background-image: -webkit-linear-gradient(top, #f0ad4e 0%, #ec971f 100%);
|
||||
background-image: linear-gradient(to bottom, #f0ad4e 0%, #ec971f 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff0ad4e', endColorstr='#ffec971f', GradientType=0);
|
||||
}
|
||||
.progress-bar-danger {
|
||||
background-image: -webkit-linear-gradient(top, #d9534f 0%, #c9302c 100%);
|
||||
background-image: linear-gradient(to bottom, #d9534f 0%, #c9302c 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9534f', endColorstr='#ffc9302c', GradientType=0);
|
||||
}
|
||||
.list-group {
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
.list-group-item.active,
|
||||
.list-group-item.active:hover,
|
||||
.list-group-item.active:focus {
|
||||
text-shadow: 0 -1px 0 #3071a9;
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #3278b3 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #3278b3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff3278b3', GradientType=0);
|
||||
border-color: #3278b3;
|
||||
}
|
||||
.panel {
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
.panel-default > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-image: linear-gradient(to bottom, #f5f5f5 0%, #e8e8e8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff5f5f5', endColorstr='#ffe8e8e8', GradientType=0);
|
||||
}
|
||||
.panel-primary > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #428bca 0%, #357ebd 100%);
|
||||
background-image: linear-gradient(to bottom, #428bca 0%, #357ebd 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff428bca', endColorstr='#ff357ebd', GradientType=0);
|
||||
}
|
||||
.panel-success > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-image: linear-gradient(to bottom, #dff0d8 0%, #d0e9c6 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffdff0d8', endColorstr='#ffd0e9c6', GradientType=0);
|
||||
}
|
||||
.panel-info > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-image: linear-gradient(to bottom, #d9edf7 0%, #c4e3f3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffd9edf7', endColorstr='#ffc4e3f3', GradientType=0);
|
||||
}
|
||||
.panel-warning > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-image: linear-gradient(to bottom, #fcf8e3 0%, #faf2cc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fffcf8e3', endColorstr='#fffaf2cc', GradientType=0);
|
||||
}
|
||||
.panel-danger > .panel-heading {
|
||||
background-image: -webkit-linear-gradient(top, #f2dede 0%, #ebcccc 100%);
|
||||
background-image: linear-gradient(to bottom, #f2dede 0%, #ebcccc 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fff2dede', endColorstr='#ffebcccc', GradientType=0);
|
||||
}
|
||||
.well {
|
||||
background-image: -webkit-linear-gradient(top, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-image: linear-gradient(to bottom, #e8e8e8 0%, #f5f5f5 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe8e8e8', endColorstr='#fff5f5f5', GradientType=0);
|
||||
border-color: #dcdcdc;
|
||||
-webkit-box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.05), 0 1px 0 rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
body {
|
||||
margin: 0px;
|
||||
}
|
||||
|
@ -6854,6 +6514,10 @@ body {
|
|||
position: relative;
|
||||
z-index: 0;
|
||||
}
|
||||
.top-fixed {
|
||||
position: fixed;
|
||||
bottom: 0px;
|
||||
}
|
||||
notifications {
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -6877,17 +6541,8 @@ notifications {
|
|||
margin-bottom: 0px!important;
|
||||
background-color: #f8f8f8;
|
||||
border-color: #e7e7e7;
|
||||
background-image: -webkit-linear-gradient(top, #ffffff 0%, #f8f8f8 100%);
|
||||
background-image: linear-gradient(to bottom, #ffffff 0%, #f8f8f8 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffffff', endColorstr='#fff8f8f8', GradientType=0);
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
|
||||
border-radius: 4px;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.15), 0 1px 5px rgba(0, 0, 0, 0.075);
|
||||
z-index: 1000;
|
||||
border-width: 0 0 1px;
|
||||
border-radius: 0;
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.config {
|
||||
|
@ -6973,14 +6628,6 @@ notifications {
|
|||
.config .navbar-link:hover {
|
||||
color: #333333;
|
||||
}
|
||||
.config .navbar-nav > .active > a {
|
||||
background-image: -webkit-linear-gradient(top, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-image: linear-gradient(to bottom, #ebebeb 0%, #f3f3f3 100%);
|
||||
background-repeat: repeat-x;
|
||||
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffebebeb', endColorstr='#fff3f3f3', GradientType=0);
|
||||
-webkit-box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 3px 9px rgba(0, 0, 0, 0.075);
|
||||
}
|
||||
@media (min-width: 768px) {
|
||||
.config {
|
||||
border-radius: 0;
|
||||
|
@ -7047,23 +6694,50 @@ kbn-table tr.even td {
|
|||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
}
|
||||
.discover-field-list .discover-field-item .discover-field-add {
|
||||
visibility: hidden;
|
||||
.application-discover {
|
||||
overflow-x: hidden;
|
||||
}
|
||||
.discover-field-list .discover-field-item:hover .discover-field-add {
|
||||
visibility: visible;
|
||||
.discover-table {
|
||||
overflow-y: auto;
|
||||
overflow-x: auto;
|
||||
margin-top: 10px;
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
}
|
||||
.discover-field-list .discover-field-name:hover {
|
||||
text-decoration: none;
|
||||
margin-left: 0;
|
||||
.discover-field-container {
|
||||
padding-left: 0px !important;
|
||||
padding-right: 0px !important;
|
||||
background-color: #f5f5f5;
|
||||
border-right: 1px solid #e3e3e3;
|
||||
border-bottom: 1px solid #e3e3e3;
|
||||
}
|
||||
.discover-field-list .discover-field-list-header {
|
||||
padding-left: 10px;
|
||||
color: #777777;
|
||||
}
|
||||
.discover-field-list .discover-field-item {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
font-size: 11px;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
}
|
||||
.discover-field-list .discover-field-name {
|
||||
padding: 5px 10px;
|
||||
}
|
||||
.discover-field-list .discover-field-name:hover,
|
||||
.discover-field-list .discover-field-name:hover .text-muted {
|
||||
background-color: #428bca;
|
||||
color: #ffffff;
|
||||
}
|
||||
.discover-field-list .discover-field-details {
|
||||
font-size: 12px;
|
||||
margin-left: 15px;
|
||||
padding: 5px;
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #dddddd;
|
||||
border-top: 1px solid #e3e3e3;
|
||||
padding: 5px 10px;
|
||||
background-color: #ffffff;
|
||||
color: #333333;
|
||||
}
|
||||
.discover-field-list .discover-field-details .discover-field-details-error {
|
||||
margin-top: 5px;
|
||||
}
|
||||
.discover-field-list .discover-field-details .discover-field-details-item {
|
||||
margin-top: 5px;
|
||||
|
@ -7138,3 +6812,21 @@ fieldset[disabled] .kbn-timepicker .btn-info.active {
|
|||
color: #5bc0de;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
kbn-table {
|
||||
font-size: 11px;
|
||||
}
|
||||
kbn-table th {
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
}
|
||||
kbn-table th .table-header-move,
|
||||
kbn-table th .table-header-sortchange {
|
||||
visibility: hidden;
|
||||
}
|
||||
kbn-table th .fa {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
kbn-table th:hover .table-header-move,
|
||||
kbn-table th:hover .table-header-sortchange {
|
||||
visibility: visible;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
.top-fixed {
|
||||
position:fixed;
|
||||
bottom:0px;
|
||||
}
|
||||
|
||||
notifications {
|
||||
z-index: 1;
|
||||
}
|
||||
|
@ -91,4 +96,31 @@ notifications {
|
|||
.kbn-timepicker .btn-info {
|
||||
.button-variant(@btn-info-color; @btn-info-bg; @btn-info-border);
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
//== Table
|
||||
|
||||
kbn-table {
|
||||
font-size: @font-size-smaller;
|
||||
|
||||
th {
|
||||
white-space: nowrap;
|
||||
padding-right: 10px;
|
||||
|
||||
.table-header-move, .table-header-sortchange {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.fa {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
th:hover {
|
||||
.table-header-move, .table-header-sortchange {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
0
src/kibana/styles/theme/_theme.less
Normal file
0
src/kibana/styles/theme/_theme.less
Normal file
830
src/kibana/styles/theme/_variables.less
Normal file
830
src/kibana/styles/theme/_variables.less
Normal file
|
@ -0,0 +1,830 @@
|
|||
//
|
||||
// Variables
|
||||
// --------------------------------------------------
|
||||
|
||||
|
||||
//== Colors
|
||||
//
|
||||
//## Gray and brand colors for use across Bootstrap.
|
||||
|
||||
@gray-darker: lighten(#000, 13.5%); // #222
|
||||
@gray-dark: lighten(#000, 20%); // #333
|
||||
@gray: lighten(#000, 33.5%); // #555
|
||||
@gray-light: lighten(#000, 60%); // #999
|
||||
@gray-lighter: lighten(#000, 93.5%); // #eee
|
||||
|
||||
@brand-primary: #428bca;
|
||||
@brand-success: #5cb85c;
|
||||
@brand-info: #5bc0de;
|
||||
@brand-warning: #f0ad4e;
|
||||
@brand-danger: #d9534f;
|
||||
|
||||
|
||||
//== Scaffolding
|
||||
//
|
||||
// ## Settings for some of the most global styles.
|
||||
|
||||
//** Background color for `<body>`.
|
||||
@body-bg: #fff;
|
||||
//** Global text color on `<body>`.
|
||||
@text-color: @gray-dark;
|
||||
|
||||
//** Global textual link color.
|
||||
@link-color: @brand-primary;
|
||||
//** Link hover color set via `darken()` function.
|
||||
@link-hover-color: darken(@link-color, 15%);
|
||||
|
||||
|
||||
//== Typography
|
||||
//
|
||||
//## Font, line-height, and color for body text, headings, and more.
|
||||
|
||||
@font-family-sans-serif: "Helvetica Neue", Helvetica, Arial, sans-serif;
|
||||
@font-family-serif: Georgia, "Times New Roman", Times, serif;
|
||||
//** Default monospace fonts for `<code>`, `<kbd>`, and `<pre>`.
|
||||
@font-family-monospace: Menlo, Monaco, Consolas, "Courier New", monospace;
|
||||
@font-family-base: @font-family-sans-serif;
|
||||
|
||||
@font-size-base: 14px;
|
||||
@font-size-large: ceil((@font-size-base * 1.25)); // ~18px
|
||||
@font-size-small: ceil((@font-size-base * 0.85)); // ~12px
|
||||
|
||||
@font-size-h1: floor((@font-size-base * 2.6)); // ~36px
|
||||
@font-size-h2: floor((@font-size-base * 2.15)); // ~30px
|
||||
@font-size-h3: ceil((@font-size-base * 1.7)); // ~24px
|
||||
@font-size-h4: ceil((@font-size-base * 1.25)); // ~18px
|
||||
@font-size-h5: @font-size-base;
|
||||
@font-size-h6: ceil((@font-size-base * 0.85)); // ~12px
|
||||
|
||||
//** Unit-less `line-height` for use in components like buttons.
|
||||
@line-height-base: 1.428571429; // 20/14
|
||||
//** Computed "line-height" (`font-size` * `line-height`) for use with `margin`, `padding`, etc.
|
||||
@line-height-computed: floor((@font-size-base * @line-height-base)); // ~20px
|
||||
|
||||
//** By default, this inherits from the `<body>`.
|
||||
@headings-font-family: inherit;
|
||||
@headings-font-weight: 500;
|
||||
@headings-line-height: 1.1;
|
||||
@headings-color: inherit;
|
||||
|
||||
|
||||
//-- Iconography
|
||||
//
|
||||
//## Specify custom locations of the include Glyphicons icon font. Useful for those including Bootstrap via Bower.
|
||||
|
||||
@icon-font-path: "../fonts/";
|
||||
@icon-font-name: "glyphicons-halflings-regular";
|
||||
@icon-font-svg-id: "glyphicons_halflingsregular";
|
||||
|
||||
//== Components
|
||||
//
|
||||
//## Define common padding and border radius sizes and more. Values based on 14px text and 1.428 line-height (~20px to start).
|
||||
|
||||
@padding-base-vertical: 6px;
|
||||
@padding-base-horizontal: 12px;
|
||||
|
||||
@padding-large-vertical: 10px;
|
||||
@padding-large-horizontal: 16px;
|
||||
|
||||
@padding-small-vertical: 5px;
|
||||
@padding-small-horizontal: 10px;
|
||||
|
||||
@padding-xs-vertical: 1px;
|
||||
@padding-xs-horizontal: 5px;
|
||||
|
||||
@line-height-large: 1.33;
|
||||
@line-height-small: 1.5;
|
||||
|
||||
@border-radius-base: 4px;
|
||||
@border-radius-large: 6px;
|
||||
@border-radius-small: 3px;
|
||||
|
||||
//** Global color for active items (e.g., navs or dropdowns).
|
||||
@component-active-color: #fff;
|
||||
//** Global background color for active items (e.g., navs or dropdowns).
|
||||
@component-active-bg: @brand-primary;
|
||||
|
||||
//** Width of the `border` for generating carets that indicator dropdowns.
|
||||
@caret-width-base: 4px;
|
||||
//** Carets increase slightly in size for larger components.
|
||||
@caret-width-large: 5px;
|
||||
|
||||
|
||||
//== Tables
|
||||
//
|
||||
//## Customizes the `.table` component with basic values, each used across all table variations.
|
||||
|
||||
//** Padding for `<th>`s and `<td>`s.
|
||||
@table-cell-padding: 8px;
|
||||
//** Padding for cells in `.table-condensed`.
|
||||
@table-condensed-cell-padding: 5px;
|
||||
|
||||
//** Default background color used for all tables.
|
||||
@table-bg: transparent;
|
||||
//** Background color used for `.table-striped`.
|
||||
@table-bg-accent: #f9f9f9;
|
||||
//** Background color used for `.table-hover`.
|
||||
@table-bg-hover: #f5f5f5;
|
||||
@table-bg-active: @table-bg-hover;
|
||||
|
||||
//** Border color for table and cell borders.
|
||||
@table-border-color: #ddd;
|
||||
|
||||
|
||||
//== Buttons
|
||||
//
|
||||
//## For each of Bootstrap's buttons, define text, background and border color.
|
||||
|
||||
@btn-font-weight: normal;
|
||||
|
||||
@btn-default-color: #333;
|
||||
@btn-default-bg: #fff;
|
||||
@btn-default-border: #ccc;
|
||||
|
||||
@btn-primary-color: #fff;
|
||||
@btn-primary-bg: @brand-primary;
|
||||
@btn-primary-border: darken(@btn-primary-bg, 5%);
|
||||
|
||||
@btn-success-color: #fff;
|
||||
@btn-success-bg: @brand-success;
|
||||
@btn-success-border: darken(@btn-success-bg, 5%);
|
||||
|
||||
@btn-info-color: #fff;
|
||||
@btn-info-bg: @brand-info;
|
||||
@btn-info-border: darken(@btn-info-bg, 5%);
|
||||
|
||||
@btn-warning-color: #fff;
|
||||
@btn-warning-bg: @brand-warning;
|
||||
@btn-warning-border: darken(@btn-warning-bg, 5%);
|
||||
|
||||
@btn-danger-color: #fff;
|
||||
@btn-danger-bg: @brand-danger;
|
||||
@btn-danger-border: darken(@btn-danger-bg, 5%);
|
||||
|
||||
@btn-link-disabled-color: @gray-light;
|
||||
|
||||
|
||||
//== Forms
|
||||
//
|
||||
//##
|
||||
|
||||
//** `<input>` background color
|
||||
@input-bg: #fff;
|
||||
//** `<input disabled>` background color
|
||||
@input-bg-disabled: @gray-lighter;
|
||||
|
||||
//** Text color for `<input>`s
|
||||
@input-color: @gray;
|
||||
//** `<input>` border color
|
||||
@input-border: #ccc;
|
||||
//** `<input>` border radius
|
||||
@input-border-radius: @border-radius-base;
|
||||
//** Border color for inputs on focus
|
||||
@input-border-focus: #66afe9;
|
||||
|
||||
//** Placeholder text color
|
||||
@input-color-placeholder: @gray-light;
|
||||
|
||||
//** Default `.form-control` height
|
||||
@input-height-base: (@line-height-computed + (@padding-base-vertical * 2) + 2);
|
||||
//** Large `.form-control` height
|
||||
@input-height-large: (ceil(@font-size-large * @line-height-large) + (@padding-large-vertical * 2) + 2);
|
||||
//** Small `.form-control` height
|
||||
@input-height-small: (floor(@font-size-small * @line-height-small) + (@padding-small-vertical * 2) + 2);
|
||||
|
||||
@legend-color: @gray-dark;
|
||||
@legend-border-color: #e5e5e5;
|
||||
|
||||
//** Background color for textual input addons
|
||||
@input-group-addon-bg: @gray-lighter;
|
||||
//** Border color for textual input addons
|
||||
@input-group-addon-border-color: @input-border;
|
||||
|
||||
|
||||
//== Dropdowns
|
||||
//
|
||||
//## Dropdown menu container and contents.
|
||||
|
||||
//** Background for the dropdown menu.
|
||||
@dropdown-bg: #fff;
|
||||
//** Dropdown menu `border-color`.
|
||||
@dropdown-border: rgba(0,0,0,.15);
|
||||
//** Dropdown menu `border-color` **for IE8**.
|
||||
@dropdown-fallback-border: #ccc;
|
||||
//** Divider color for between dropdown items.
|
||||
@dropdown-divider-bg: #e5e5e5;
|
||||
|
||||
//** Dropdown link text color.
|
||||
@dropdown-link-color: @gray-dark;
|
||||
//** Hover color for dropdown links.
|
||||
@dropdown-link-hover-color: darken(@gray-dark, 5%);
|
||||
//** Hover background for dropdown links.
|
||||
@dropdown-link-hover-bg: #f5f5f5;
|
||||
|
||||
//** Active dropdown menu item text color.
|
||||
@dropdown-link-active-color: @component-active-color;
|
||||
//** Active dropdown menu item background color.
|
||||
@dropdown-link-active-bg: @component-active-bg;
|
||||
|
||||
//** Disabled dropdown menu item background color.
|
||||
@dropdown-link-disabled-color: @gray-light;
|
||||
|
||||
//** Text color for headers within dropdown menus.
|
||||
@dropdown-header-color: @gray-light;
|
||||
|
||||
// Note: Deprecated @dropdown-caret-color as of v3.1.0
|
||||
@dropdown-caret-color: #000;
|
||||
|
||||
|
||||
//-- Z-index master list
|
||||
//
|
||||
// Warning: Avoid customizing these values. They're used for a bird's eye view
|
||||
// of components dependent on the z-axis and are designed to all work together.
|
||||
//
|
||||
// Note: These variables are not generated into the Customizer.
|
||||
|
||||
@zindex-navbar: 1000;
|
||||
@zindex-dropdown: 1000;
|
||||
@zindex-popover: 1010;
|
||||
@zindex-tooltip: 1030;
|
||||
@zindex-navbar-fixed: 1030;
|
||||
@zindex-modal-background: 1040;
|
||||
@zindex-modal: 1050;
|
||||
|
||||
|
||||
//== Media queries breakpoints
|
||||
//
|
||||
//## Define the breakpoints at which your layout will change, adapting to different screen sizes.
|
||||
|
||||
// Extra small screen / phone
|
||||
// Note: Deprecated @screen-xs and @screen-phone as of v3.0.1
|
||||
@screen-xs: 480px;
|
||||
@screen-xs-min: @screen-xs;
|
||||
@screen-phone: @screen-xs-min;
|
||||
|
||||
// Small screen / tablet
|
||||
// Note: Deprecated @screen-sm and @screen-tablet as of v3.0.1
|
||||
@screen-sm: 768px;
|
||||
@screen-sm-min: @screen-sm;
|
||||
@screen-tablet: @screen-sm-min;
|
||||
|
||||
// Medium screen / desktop
|
||||
// Note: Deprecated @screen-md and @screen-desktop as of v3.0.1
|
||||
@screen-md: 992px;
|
||||
@screen-md-min: @screen-md;
|
||||
@screen-desktop: @screen-md-min;
|
||||
|
||||
// Large screen / wide desktop
|
||||
// Note: Deprecated @screen-lg and @screen-lg-desktop as of v3.0.1
|
||||
@screen-lg: 1200px;
|
||||
@screen-lg-min: @screen-lg;
|
||||
@screen-lg-desktop: @screen-lg-min;
|
||||
|
||||
// So media queries don't overlap when required, provide a maximum
|
||||
@screen-xs-max: (@screen-sm-min - 1);
|
||||
@screen-sm-max: (@screen-md-min - 1);
|
||||
@screen-md-max: (@screen-lg-min - 1);
|
||||
|
||||
|
||||
//== Grid system
|
||||
//
|
||||
//## Define your custom responsive grid.
|
||||
|
||||
//** Number of columns in the grid.
|
||||
@grid-columns: 12;
|
||||
//** Padding between columns. Gets divided in half for the left and right.
|
||||
@grid-gutter-width: 30px;
|
||||
// Navbar collapse
|
||||
//** Point at which the navbar becomes uncollapsed.
|
||||
@grid-float-breakpoint: @screen-sm-min;
|
||||
//** Point at which the navbar begins collapsing.
|
||||
@grid-float-breakpoint-max: (@grid-float-breakpoint - 1);
|
||||
|
||||
|
||||
//== Container sizes
|
||||
//
|
||||
//## Define the maximum width of `.container` for different screen sizes.
|
||||
|
||||
// Small screen / tablet
|
||||
@container-tablet: ((720px + @grid-gutter-width));
|
||||
//** For `@screen-sm-min` and up.
|
||||
@container-sm: @container-tablet;
|
||||
|
||||
// Medium screen / desktop
|
||||
@container-desktop: ((940px + @grid-gutter-width));
|
||||
//** For `@screen-md-min` and up.
|
||||
@container-md: @container-desktop;
|
||||
|
||||
// Large screen / wide desktop
|
||||
@container-large-desktop: ((1140px + @grid-gutter-width));
|
||||
//** For `@screen-lg-min` and up.
|
||||
@container-lg: @container-large-desktop;
|
||||
|
||||
|
||||
//== Navbar
|
||||
//
|
||||
//##
|
||||
|
||||
// Basics of a navbar
|
||||
@navbar-height: 50px;
|
||||
@navbar-margin-bottom: @line-height-computed;
|
||||
@navbar-border-radius: @border-radius-base;
|
||||
@navbar-padding-horizontal: floor((@grid-gutter-width / 2));
|
||||
@navbar-padding-vertical: ((@navbar-height - @line-height-computed) / 2);
|
||||
@navbar-collapse-max-height: 340px;
|
||||
|
||||
@navbar-default-color: #777;
|
||||
@navbar-default-bg: #f8f8f8;
|
||||
@navbar-default-border: darken(@navbar-default-bg, 6.5%);
|
||||
|
||||
// Navbar links
|
||||
@navbar-default-link-color: #777;
|
||||
@navbar-default-link-hover-color: #333;
|
||||
@navbar-default-link-hover-bg: transparent;
|
||||
@navbar-default-link-active-color: #555;
|
||||
@navbar-default-link-active-bg: darken(@navbar-default-bg, 6.5%);
|
||||
@navbar-default-link-disabled-color: #ccc;
|
||||
@navbar-default-link-disabled-bg: transparent;
|
||||
|
||||
// Navbar brand label
|
||||
@navbar-default-brand-color: @navbar-default-link-color;
|
||||
@navbar-default-brand-hover-color: darken(@navbar-default-brand-color, 10%);
|
||||
@navbar-default-brand-hover-bg: transparent;
|
||||
|
||||
// Navbar toggle
|
||||
@navbar-default-toggle-hover-bg: #ddd;
|
||||
@navbar-default-toggle-icon-bar-bg: #888;
|
||||
@navbar-default-toggle-border-color: #ddd;
|
||||
|
||||
|
||||
// Inverted navbar
|
||||
// Reset inverted navbar basics
|
||||
@navbar-inverse-color: @gray-light;
|
||||
@navbar-inverse-bg: #222;
|
||||
@navbar-inverse-border: darken(@navbar-inverse-bg, 10%);
|
||||
|
||||
// Inverted navbar links
|
||||
@navbar-inverse-link-color: @gray-light;
|
||||
@navbar-inverse-link-hover-color: #fff;
|
||||
@navbar-inverse-link-hover-bg: transparent;
|
||||
@navbar-inverse-link-active-color: @navbar-inverse-link-hover-color;
|
||||
@navbar-inverse-link-active-bg: darken(@navbar-inverse-bg, 10%);
|
||||
@navbar-inverse-link-disabled-color: #444;
|
||||
@navbar-inverse-link-disabled-bg: transparent;
|
||||
|
||||
// Inverted navbar brand label
|
||||
@navbar-inverse-brand-color: @navbar-inverse-link-color;
|
||||
@navbar-inverse-brand-hover-color: #fff;
|
||||
@navbar-inverse-brand-hover-bg: transparent;
|
||||
|
||||
// Inverted navbar toggle
|
||||
@navbar-inverse-toggle-hover-bg: #333;
|
||||
@navbar-inverse-toggle-icon-bar-bg: #fff;
|
||||
@navbar-inverse-toggle-border-color: #333;
|
||||
|
||||
|
||||
//== Navs
|
||||
//
|
||||
//##
|
||||
|
||||
//=== Shared nav styles
|
||||
@nav-link-padding: 10px 15px;
|
||||
@nav-link-hover-bg: @gray-lighter;
|
||||
|
||||
@nav-disabled-link-color: @gray-light;
|
||||
@nav-disabled-link-hover-color: @gray-light;
|
||||
|
||||
@nav-open-link-hover-color: #fff;
|
||||
|
||||
//== Tabs
|
||||
@nav-tabs-border-color: #ddd;
|
||||
|
||||
@nav-tabs-link-hover-border-color: @gray-lighter;
|
||||
|
||||
@nav-tabs-active-link-hover-bg: @body-bg;
|
||||
@nav-tabs-active-link-hover-color: @gray;
|
||||
@nav-tabs-active-link-hover-border-color: #ddd;
|
||||
|
||||
@nav-tabs-justified-link-border-color: #ddd;
|
||||
@nav-tabs-justified-active-link-border-color: @body-bg;
|
||||
|
||||
//== Pills
|
||||
@nav-pills-border-radius: @border-radius-base;
|
||||
@nav-pills-active-link-hover-bg: @component-active-bg;
|
||||
@nav-pills-active-link-hover-color: @component-active-color;
|
||||
|
||||
|
||||
//== Pagination
|
||||
//
|
||||
//##
|
||||
|
||||
@pagination-color: @link-color;
|
||||
@pagination-bg: #fff;
|
||||
@pagination-border: #ddd;
|
||||
|
||||
@pagination-hover-color: @link-hover-color;
|
||||
@pagination-hover-bg: @gray-lighter;
|
||||
@pagination-hover-border: #ddd;
|
||||
|
||||
@pagination-active-color: #fff;
|
||||
@pagination-active-bg: @brand-primary;
|
||||
@pagination-active-border: @brand-primary;
|
||||
|
||||
@pagination-disabled-color: @gray-light;
|
||||
@pagination-disabled-bg: #fff;
|
||||
@pagination-disabled-border: #ddd;
|
||||
|
||||
|
||||
//== Pager
|
||||
//
|
||||
//##
|
||||
|
||||
@pager-bg: @pagination-bg;
|
||||
@pager-border: @pagination-border;
|
||||
@pager-border-radius: 15px;
|
||||
|
||||
@pager-hover-bg: @pagination-hover-bg;
|
||||
|
||||
@pager-active-bg: @pagination-active-bg;
|
||||
@pager-active-color: @pagination-active-color;
|
||||
|
||||
@pager-disabled-color: @pagination-disabled-color;
|
||||
|
||||
|
||||
//== Jumbotron
|
||||
//
|
||||
//##
|
||||
|
||||
@jumbotron-padding: 30px;
|
||||
@jumbotron-color: inherit;
|
||||
@jumbotron-bg: @gray-lighter;
|
||||
@jumbotron-heading-color: inherit;
|
||||
@jumbotron-font-size: ceil((@font-size-base * 1.5));
|
||||
|
||||
|
||||
//== Form states and alerts
|
||||
//
|
||||
//## Define colors for form feedback states and, by default, alerts.
|
||||
|
||||
@state-success-text: #3c763d;
|
||||
@state-success-bg: #dff0d8;
|
||||
@state-success-border: darken(spin(@state-success-bg, -10), 5%);
|
||||
|
||||
@state-info-text: #31708f;
|
||||
@state-info-bg: #d9edf7;
|
||||
@state-info-border: darken(spin(@state-info-bg, -10), 7%);
|
||||
|
||||
@state-warning-text: #8a6d3b;
|
||||
@state-warning-bg: #fcf8e3;
|
||||
@state-warning-border: darken(spin(@state-warning-bg, -10), 5%);
|
||||
|
||||
@state-danger-text: #a94442;
|
||||
@state-danger-bg: #f2dede;
|
||||
@state-danger-border: darken(spin(@state-danger-bg, -10), 5%);
|
||||
|
||||
|
||||
//== Tooltips
|
||||
//
|
||||
//##
|
||||
|
||||
//** Tooltip max width
|
||||
@tooltip-max-width: 200px;
|
||||
//** Tooltip text color
|
||||
@tooltip-color: #fff;
|
||||
//** Tooltip background color
|
||||
@tooltip-bg: #000;
|
||||
@tooltip-opacity: .9;
|
||||
|
||||
//** Tooltip arrow width
|
||||
@tooltip-arrow-width: 5px;
|
||||
//** Tooltip arrow color
|
||||
@tooltip-arrow-color: @tooltip-bg;
|
||||
|
||||
|
||||
//== Popovers
|
||||
//
|
||||
//##
|
||||
|
||||
//** Popover body background color
|
||||
@popover-bg: #fff;
|
||||
//** Popover maximum width
|
||||
@popover-max-width: 276px;
|
||||
//** Popover border color
|
||||
@popover-border-color: rgba(0,0,0,.2);
|
||||
//** Popover fallback border color
|
||||
@popover-fallback-border-color: #ccc;
|
||||
|
||||
//** Popover title background color
|
||||
@popover-title-bg: darken(@popover-bg, 3%);
|
||||
|
||||
//** Popover arrow width
|
||||
@popover-arrow-width: 10px;
|
||||
//** Popover arrow color
|
||||
@popover-arrow-color: #fff;
|
||||
|
||||
//** Popover outer arrow width
|
||||
@popover-arrow-outer-width: (@popover-arrow-width + 1);
|
||||
//** Popover outer arrow color
|
||||
@popover-arrow-outer-color: fadein(@popover-border-color, 5%);
|
||||
//** Popover outer arrow fallback color
|
||||
@popover-arrow-outer-fallback-color: darken(@popover-fallback-border-color, 20%);
|
||||
|
||||
|
||||
//== Labels
|
||||
//
|
||||
//##
|
||||
|
||||
//** Default label background color
|
||||
@label-default-bg: @gray-light;
|
||||
//** Primary label background color
|
||||
@label-primary-bg: @brand-primary;
|
||||
//** Success label background color
|
||||
@label-success-bg: @brand-success;
|
||||
//** Info label background color
|
||||
@label-info-bg: @brand-info;
|
||||
//** Warning label background color
|
||||
@label-warning-bg: @brand-warning;
|
||||
//** Danger label background color
|
||||
@label-danger-bg: @brand-danger;
|
||||
|
||||
//** Default label text color
|
||||
@label-color: #fff;
|
||||
//** Default text color of a linked label
|
||||
@label-link-hover-color: #fff;
|
||||
|
||||
|
||||
//== Modals
|
||||
//
|
||||
//##
|
||||
|
||||
//** Padding applied to the modal body
|
||||
@modal-inner-padding: 20px;
|
||||
|
||||
//** Padding applied to the modal title
|
||||
@modal-title-padding: 15px;
|
||||
//** Modal title line-height
|
||||
@modal-title-line-height: @line-height-base;
|
||||
|
||||
//** Background color of modal content area
|
||||
@modal-content-bg: #fff;
|
||||
//** Modal content border color
|
||||
@modal-content-border-color: rgba(0,0,0,.2);
|
||||
//** Modal content border color **for IE8**
|
||||
@modal-content-fallback-border-color: #999;
|
||||
|
||||
//** Modal backdrop background color
|
||||
@modal-backdrop-bg: #000;
|
||||
//** Modal backdrop opacity
|
||||
@modal-backdrop-opacity: .5;
|
||||
//** Modal header border color
|
||||
@modal-header-border-color: #e5e5e5;
|
||||
//** Modal footer border color
|
||||
@modal-footer-border-color: @modal-header-border-color;
|
||||
|
||||
@modal-lg: 900px;
|
||||
@modal-md: 600px;
|
||||
@modal-sm: 300px;
|
||||
|
||||
|
||||
//== Alerts
|
||||
//
|
||||
//## Define alert colors, border radius, and padding.
|
||||
|
||||
@alert-padding: 15px;
|
||||
@alert-border-radius: @border-radius-base;
|
||||
@alert-link-font-weight: bold;
|
||||
|
||||
@alert-success-bg: @state-success-bg;
|
||||
@alert-success-text: @state-success-text;
|
||||
@alert-success-border: @state-success-border;
|
||||
|
||||
@alert-info-bg: @state-info-bg;
|
||||
@alert-info-text: @state-info-text;
|
||||
@alert-info-border: @state-info-border;
|
||||
|
||||
@alert-warning-bg: @state-warning-bg;
|
||||
@alert-warning-text: @state-warning-text;
|
||||
@alert-warning-border: @state-warning-border;
|
||||
|
||||
@alert-danger-bg: @state-danger-bg;
|
||||
@alert-danger-text: @state-danger-text;
|
||||
@alert-danger-border: @state-danger-border;
|
||||
|
||||
|
||||
//== Progress bars
|
||||
//
|
||||
//##
|
||||
|
||||
//** Background color of the whole progress component
|
||||
@progress-bg: #f5f5f5;
|
||||
//** Progress bar text color
|
||||
@progress-bar-color: #fff;
|
||||
|
||||
//** Default progress bar color
|
||||
@progress-bar-bg: @brand-primary;
|
||||
//** Success progress bar color
|
||||
@progress-bar-success-bg: @brand-success;
|
||||
//** Warning progress bar color
|
||||
@progress-bar-warning-bg: @brand-warning;
|
||||
//** Danger progress bar color
|
||||
@progress-bar-danger-bg: @brand-danger;
|
||||
//** Info progress bar color
|
||||
@progress-bar-info-bg: @brand-info;
|
||||
|
||||
|
||||
//== List group
|
||||
//
|
||||
//##
|
||||
|
||||
//** Background color on `.list-group-item`
|
||||
@list-group-bg: #fff;
|
||||
//** `.list-group-item` border color
|
||||
@list-group-border: #ddd;
|
||||
//** List group border radius
|
||||
@list-group-border-radius: @border-radius-base;
|
||||
|
||||
//** Background color of single list elements on hover
|
||||
@list-group-hover-bg: #f5f5f5;
|
||||
//** Text color of active list elements
|
||||
@list-group-active-color: @component-active-color;
|
||||
//** Background color of active list elements
|
||||
@list-group-active-bg: @component-active-bg;
|
||||
//** Border color of active list elements
|
||||
@list-group-active-border: @list-group-active-bg;
|
||||
@list-group-active-text-color: lighten(@list-group-active-bg, 40%);
|
||||
|
||||
@list-group-link-color: #555;
|
||||
@list-group-link-heading-color: #333;
|
||||
|
||||
|
||||
//== Panels
|
||||
//
|
||||
//##
|
||||
|
||||
@panel-bg: #fff;
|
||||
@panel-body-padding: 15px;
|
||||
@panel-border-radius: @border-radius-base;
|
||||
|
||||
//** Border color for elements within panels
|
||||
@panel-inner-border: #ddd;
|
||||
@panel-footer-bg: #f5f5f5;
|
||||
|
||||
@panel-default-text: @gray-dark;
|
||||
@panel-default-border: #ddd;
|
||||
@panel-default-heading-bg: #f5f5f5;
|
||||
|
||||
@panel-primary-text: #fff;
|
||||
@panel-primary-border: @brand-primary;
|
||||
@panel-primary-heading-bg: @brand-primary;
|
||||
|
||||
@panel-success-text: @state-success-text;
|
||||
@panel-success-border: @state-success-border;
|
||||
@panel-success-heading-bg: @state-success-bg;
|
||||
|
||||
@panel-info-text: @state-info-text;
|
||||
@panel-info-border: @state-info-border;
|
||||
@panel-info-heading-bg: @state-info-bg;
|
||||
|
||||
@panel-warning-text: @state-warning-text;
|
||||
@panel-warning-border: @state-warning-border;
|
||||
@panel-warning-heading-bg: @state-warning-bg;
|
||||
|
||||
@panel-danger-text: @state-danger-text;
|
||||
@panel-danger-border: @state-danger-border;
|
||||
@panel-danger-heading-bg: @state-danger-bg;
|
||||
|
||||
|
||||
//== Thumbnails
|
||||
//
|
||||
//##
|
||||
|
||||
//** Padding around the thumbnail image
|
||||
@thumbnail-padding: 4px;
|
||||
//** Thumbnail background color
|
||||
@thumbnail-bg: @body-bg;
|
||||
//** Thumbnail border color
|
||||
@thumbnail-border: #ddd;
|
||||
//** Thumbnail border radius
|
||||
@thumbnail-border-radius: @border-radius-base;
|
||||
|
||||
//** Custom text color for thumbnail captions
|
||||
@thumbnail-caption-color: @text-color;
|
||||
//** Padding around the thumbnail caption
|
||||
@thumbnail-caption-padding: 9px;
|
||||
|
||||
|
||||
//== Wells
|
||||
//
|
||||
//##
|
||||
|
||||
@well-bg: #f5f5f5;
|
||||
@well-border: darken(@well-bg, 7%);
|
||||
|
||||
|
||||
//== Badges
|
||||
//
|
||||
//##
|
||||
|
||||
@badge-color: #fff;
|
||||
//** Linked badge text color on hover
|
||||
@badge-link-hover-color: #fff;
|
||||
@badge-bg: @gray-light;
|
||||
|
||||
//** Badge text color in active nav link
|
||||
@badge-active-color: @link-color;
|
||||
//** Badge background color in active nav link
|
||||
@badge-active-bg: #fff;
|
||||
|
||||
@badge-font-weight: bold;
|
||||
@badge-line-height: 1;
|
||||
@badge-border-radius: 10px;
|
||||
|
||||
|
||||
//== Breadcrumbs
|
||||
//
|
||||
//##
|
||||
|
||||
@breadcrumb-padding-vertical: 8px;
|
||||
@breadcrumb-padding-horizontal: 15px;
|
||||
//** Breadcrumb background color
|
||||
@breadcrumb-bg: #f5f5f5;
|
||||
//** Breadcrumb text color
|
||||
@breadcrumb-color: #ccc;
|
||||
//** Text color of current page in the breadcrumb
|
||||
@breadcrumb-active-color: @gray-light;
|
||||
//** Textual separator for between breadcrumb elements
|
||||
@breadcrumb-separator: "/";
|
||||
|
||||
|
||||
//== Carousel
|
||||
//
|
||||
//##
|
||||
|
||||
@carousel-text-shadow: 0 1px 2px rgba(0,0,0,.6);
|
||||
|
||||
@carousel-control-color: #fff;
|
||||
@carousel-control-width: 15%;
|
||||
@carousel-control-opacity: .5;
|
||||
@carousel-control-font-size: 20px;
|
||||
|
||||
@carousel-indicator-active-bg: #fff;
|
||||
@carousel-indicator-border-color: #fff;
|
||||
|
||||
@carousel-caption-color: #fff;
|
||||
|
||||
|
||||
//== Close
|
||||
//
|
||||
//##
|
||||
|
||||
@close-font-weight: bold;
|
||||
@close-color: #000;
|
||||
@close-text-shadow: 0 1px 0 #fff;
|
||||
|
||||
|
||||
//== Code
|
||||
//
|
||||
//##
|
||||
|
||||
@code-color: #c7254e;
|
||||
@code-bg: #f9f2f4;
|
||||
|
||||
@kbd-color: #fff;
|
||||
@kbd-bg: #333;
|
||||
|
||||
@pre-bg: #f5f5f5;
|
||||
@pre-color: @gray-dark;
|
||||
@pre-border-color: #ccc;
|
||||
@pre-scrollable-max-height: 340px;
|
||||
|
||||
|
||||
//== Type
|
||||
//
|
||||
//##
|
||||
|
||||
//** Text muted color
|
||||
@text-muted: @gray-light;
|
||||
//** Abbreviations and acronyms border color
|
||||
@abbr-border-color: @gray-light;
|
||||
//** Headings small color
|
||||
@headings-small-color: @gray-light;
|
||||
//** Blockquote small color
|
||||
@blockquote-small-color: @gray-light;
|
||||
//** Blockquote font size
|
||||
@blockquote-font-size: (@font-size-base * 1.25);
|
||||
//** Blockquote border color
|
||||
@blockquote-border-color: @gray-lighter;
|
||||
//** Page header border color
|
||||
@page-header-border-color: @gray-lighter;
|
||||
|
||||
|
||||
//== Miscellaneous
|
||||
//
|
||||
//##
|
||||
|
||||
//** Horizontal line color.
|
||||
@hr-border: @gray-lighter;
|
||||
|
||||
//** Horizontal offset for forms and lists.
|
||||
@component-offset-horizontal: 180px;
|
||||
|
|
@ -49,6 +49,9 @@
|
|||
require([
|
||||
'sinon/sinon',
|
||||
'specs/apps/dashboard/index',
|
||||
'specs/apps/dashboard/directives/panel',
|
||||
'specs/apps/dashboard/directives/grid',
|
||||
'specs/services/state',
|
||||
'specs/courier/index'
|
||||
], function (sinon) {
|
||||
|
||||
|
|
145
test/unit/specs/apps/dashboard/directives/grid.js
Normal file
145
test/unit/specs/apps/dashboard/directives/grid.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
define(function (require) {
|
||||
var angular = require('angular');
|
||||
var mocks = require('angular-mocks');
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
|
||||
// Load the kibana app dependencies.
|
||||
require('angular-route');
|
||||
|
||||
// Load the code for the directive
|
||||
require('apps/dashboard/directives/panel');
|
||||
|
||||
describe('Gridster', function () {
|
||||
var $scope, $elem, compile;
|
||||
|
||||
beforeEach(function () {
|
||||
module('app/dashboard');
|
||||
|
||||
// Create the scope
|
||||
inject(function ($rootScope, $compile) {
|
||||
|
||||
// So we can use this in other sections
|
||||
compile = $compile;
|
||||
|
||||
$scope = $rootScope;
|
||||
|
||||
$elem = angular.element(
|
||||
'<ul dashboard-grid="" ' +
|
||||
' grid="dashboard.panels" ' +
|
||||
' control="gridControl" ' +
|
||||
' class="ng-isolate-scope gridster" ' +
|
||||
' style="position: relative; width: 1207px; height: 220px;">' +
|
||||
'</ul>'
|
||||
);
|
||||
|
||||
// The element must be attached to the DOM for gridster to work.
|
||||
$elem.hide();
|
||||
$elem.appendTo(document.body);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$elem.remove();
|
||||
});
|
||||
|
||||
describe('without parameters', function () {
|
||||
beforeEach(function () {
|
||||
compile($elem)($scope);
|
||||
$scope.$digest();
|
||||
});
|
||||
|
||||
it('should return without attaching anything', function (done) {
|
||||
var panels = $elem.find('li.gs-w');
|
||||
expect(panels.length).to.be(0);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('with parameters', function () {
|
||||
var grid;
|
||||
|
||||
beforeEach(function () {
|
||||
$scope.gridControl = {};
|
||||
$scope.dashboard = {
|
||||
panels: [{
|
||||
col: 1,
|
||||
row: 1,
|
||||
size_x: 3,
|
||||
size_y: 2,
|
||||
params: {
|
||||
type: 'vis1'
|
||||
}
|
||||
}, {
|
||||
col: 4,
|
||||
row: 1,
|
||||
size_x: 3,
|
||||
size_y: 2,
|
||||
params: {
|
||||
type: 'vis2'
|
||||
}
|
||||
}]
|
||||
};
|
||||
|
||||
compile($elem)($scope);
|
||||
$scope.$digest();
|
||||
|
||||
grid = $scope.gridControl.serializeGrid;
|
||||
});
|
||||
|
||||
it('should have 2 panels', function (done) {
|
||||
var panels = $elem.find('li.gs-w');
|
||||
expect(panels.length).to.be(2);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should remove panels when remove is clicked', function (done) {
|
||||
expect(grid().length).to.be(2);
|
||||
|
||||
// Click close button
|
||||
$elem.find('li.gs-w:first i.remove').trigger('click');
|
||||
expect(grid().length).to.be(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should have a control.clearGrid that removes all widgets', function (done) {
|
||||
expect(grid().length).to.be(2);
|
||||
$scope.gridControl.clearGrid();
|
||||
expect(grid().length).to.be(0);
|
||||
done();
|
||||
});
|
||||
|
||||
it('has an addWidget that adds a widget', function (done) {
|
||||
expect(grid().length).to.be(2);
|
||||
$scope.gridControl.addWidget({});
|
||||
expect(grid().length).to.be(3);
|
||||
done();
|
||||
});
|
||||
|
||||
it('has an unserializeGrid that creates a grid from an object', function (done) {
|
||||
expect(grid().length).to.be(2);
|
||||
$scope.gridControl.clearGrid();
|
||||
expect(grid().length).to.be(0);
|
||||
$scope.gridControl.unserializeGrid({
|
||||
panels: [{
|
||||
col: 1,
|
||||
row: 1,
|
||||
size_x: 3,
|
||||
size_y: 2,
|
||||
params: {
|
||||
type: 'vis1'
|
||||
}
|
||||
}]
|
||||
});
|
||||
expect(grid().length).to.be(1);
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
51
test/unit/specs/apps/dashboard/directives/panel.js
Normal file
51
test/unit/specs/apps/dashboard/directives/panel.js
Normal file
|
@ -0,0 +1,51 @@
|
|||
define(function (require) {
|
||||
var angular = require('angular');
|
||||
var mocks = require('angular-mocks');
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
|
||||
// Load the kibana app dependencies.
|
||||
require('angular-route');
|
||||
|
||||
// Load the code for the directive
|
||||
require('apps/dashboard/directives/panel');
|
||||
|
||||
describe('Dashboard panels', function () {
|
||||
var $scope, $elem;
|
||||
|
||||
beforeEach(function () {
|
||||
module('app/dashboard');
|
||||
|
||||
// Create the scope
|
||||
inject(function ($rootScope, $compile) {
|
||||
|
||||
$scope = $rootScope;
|
||||
|
||||
var params = {
|
||||
type: 'new'
|
||||
};
|
||||
|
||||
$elem = angular.element(
|
||||
'<dashboard-panel params=\'' + JSON.stringify(params) + '\'></dashboard-panel>'
|
||||
);
|
||||
|
||||
$compile($elem)($scope);
|
||||
$scope.$digest();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
it('should have a close button', function (done) {
|
||||
var closeIcon = $elem.find('i.remove');
|
||||
expect(closeIcon.length).to.be(1);
|
||||
done();
|
||||
});
|
||||
|
||||
it('should have the name of the panel', function (done) {
|
||||
expect($elem.text()).to.be('new');
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
|
@ -2,6 +2,8 @@ define(function (require) {
|
|||
var mocks = require('angular-mocks');
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
var sinon = require('test_utils/auto_release_sinon');
|
||||
|
||||
|
||||
// Load the kibana app dependencies.
|
||||
require('angular-route');
|
||||
|
@ -10,23 +12,30 @@ define(function (require) {
|
|||
require('apps/dashboard/index');
|
||||
|
||||
describe('Dashboard app', function () {
|
||||
var $scope;
|
||||
var $scope,
|
||||
location;
|
||||
|
||||
beforeEach(function () {
|
||||
module('app/dashboard');
|
||||
|
||||
// Create the scope
|
||||
inject(function ($rootScope, $controller) {
|
||||
inject(function ($rootScope, $controller, $location) {
|
||||
$scope = $rootScope.$new();
|
||||
var dashCtrl = $controller('dashboard', {
|
||||
$scope: $scope
|
||||
});
|
||||
|
||||
location = $location;
|
||||
|
||||
// $scope is now available in tests
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
$scope.$destroy();
|
||||
});
|
||||
|
||||
it('should attach $routeParams to scope', function (done) {
|
||||
expect($scope.routeParams).to.be.a(Object);
|
||||
done();
|
||||
|
@ -39,6 +48,56 @@ define(function (require) {
|
|||
done();
|
||||
});
|
||||
|
||||
|
||||
describe('saving', function () {
|
||||
beforeEach(function () {
|
||||
sinon.stub($scope, 'save', function () {});
|
||||
});
|
||||
it('should open the save dialog with openSave()', function (done) {
|
||||
expect($scope.configTemplate).to.be(undefined);
|
||||
$scope.openSave();
|
||||
expect($scope.configTemplate).to.be.a('string');
|
||||
done();
|
||||
});
|
||||
it('should unset the dialog when called again', function (done) {
|
||||
$scope.openSave();
|
||||
$scope.openSave();
|
||||
expect($scope.configTemplate).to.be(undefined);
|
||||
done();
|
||||
});
|
||||
it('should save the dashboard when submitted', function (done) {
|
||||
$scope.openSave();
|
||||
$scope.configSubmit();
|
||||
expect($scope.save.called).to.be(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
describe('loading', function () {
|
||||
beforeEach(function () {
|
||||
$scope.gridControl = {
|
||||
clearGrid: function () {},
|
||||
unserializeGrid: function () {},
|
||||
};
|
||||
_.each($scope.gridControl, function (value, key) {
|
||||
sinon.spy($scope.gridControl, key);
|
||||
});
|
||||
});
|
||||
|
||||
it('should attach the schema to the dashboard object', function (done) {
|
||||
$scope.load({foo: 'bar'});
|
||||
expect($scope.dashboard.foo).to.be('bar');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should clear the grid before loading a new one', function (done) {
|
||||
$scope.load({foo: 'bar'});
|
||||
expect($scope.gridControl.clearGrid.called).to.be(true);
|
||||
expect($scope.gridControl.unserializeGrid.called).to.be(true);
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
52
test/unit/specs/services/state.js
Normal file
52
test/unit/specs/services/state.js
Normal file
|
@ -0,0 +1,52 @@
|
|||
define(function (require) {
|
||||
var angular = require('angular');
|
||||
var mocks = require('angular-mocks');
|
||||
var _ = require('lodash');
|
||||
var $ = require('jquery');
|
||||
|
||||
// Load the kibana app dependencies.
|
||||
require('angular-route');
|
||||
|
||||
// Load the code for the directive
|
||||
require('services/state');
|
||||
|
||||
describe('State service', function () {
|
||||
var state, location;
|
||||
|
||||
beforeEach(function () {
|
||||
module('kibana/services');
|
||||
|
||||
// Create the scope
|
||||
inject(function (_state_, $location) {
|
||||
|
||||
state = _state_;
|
||||
location = $location;
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
afterEach(function () {
|
||||
location.search({});
|
||||
});
|
||||
|
||||
it('should have no state by default', function (done) {
|
||||
expect(state.get()).to.eql({});
|
||||
done();
|
||||
});
|
||||
|
||||
it('should have a set(Object) that writes state to the search string', function (done) {
|
||||
state.set({foo: 'bar'});
|
||||
expect(location.search()._r).to.be('(foo:bar)');
|
||||
done();
|
||||
});
|
||||
|
||||
it('should have a get() that deserializes rison from the search string', function (done) {
|
||||
location.search({_r: '(foo:bar)'});
|
||||
expect(state.get()).to.eql({foo: 'bar'});
|
||||
done();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue